├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── pull_request_template.md └── workflows │ ├── build-and-test.yaml │ └── codeql.yaml ├── .gitignore ├── .mvn └── wrapper │ └── maven-wrapper.properties ├── CHANGELOG.md ├── CONTRIBUTING.md ├── README.md ├── assemblies └── sonatype-bundle.xml ├── config ├── scim2-parent-checkstyle.xml ├── scim2-parent-gpl.sourceheader ├── scim2-parent-ubid.sourceheader └── scim2-parent-unit-checkstyle.xml ├── mvnw ├── mvnw.cmd ├── pom.xml ├── resource ├── 3RD_PARTY_LICENSES.txt ├── LICENSE-GPLv2.txt ├── LICENSE-LGPLv2.1.txt ├── LICENSE-UnboundID-SCIM2.txt └── LICENSE.txt ├── scim2-assembly ├── assemblies │ └── zip.xml └── pom.xml ├── scim2-sdk-client ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── unboundid │ │ │ └── scim2 │ │ │ └── client │ │ │ ├── ScimInterface.java │ │ │ ├── ScimService.java │ │ │ ├── ScimServiceException.java │ │ │ ├── SearchResultHandler.java │ │ │ ├── package-info.java │ │ │ └── requests │ │ │ ├── CreateRequestBuilder.java │ │ │ ├── DeleteRequestBuilder.java │ │ │ ├── ListResponseBuilder.java │ │ │ ├── ModifyRequestBuilder.java │ │ │ ├── ReplaceRequestBuilder.java │ │ │ ├── RequestBuilder.java │ │ │ ├── ResourceReturningRequestBuilder.java │ │ │ ├── RetrieveRequestBuilder.java │ │ │ ├── SearchRequestBuilder.java │ │ │ └── package-info.java │ └── javadoc │ │ └── overview.html │ └── test │ └── java │ └── com │ └── unboundid │ └── scim2 │ └── client │ ├── ClientNullabilityAnnotationTest.java │ └── RequestBuilderTest.java ├── scim2-sdk-common ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── unboundid │ │ │ └── scim2 │ │ │ └── common │ │ │ ├── BaseScimResource.java │ │ │ ├── GenericScimResource.java │ │ │ ├── Path.java │ │ │ ├── ScimResource.java │ │ │ ├── annotations │ │ │ ├── Attribute.java │ │ │ ├── NotNull.java │ │ │ ├── Nullable.java │ │ │ ├── Schema.java │ │ │ └── package-info.java │ │ │ ├── exceptions │ │ │ ├── BadRequestException.java │ │ │ ├── ForbiddenException.java │ │ │ ├── MethodNotAllowedException.java │ │ │ ├── NotImplementedException.java │ │ │ ├── NotModifiedException.java │ │ │ ├── PreconditionFailedException.java │ │ │ ├── ResourceConflictException.java │ │ │ ├── ResourceNotFoundException.java │ │ │ ├── ScimException.java │ │ │ ├── ServerErrorException.java │ │ │ ├── UnauthorizedException.java │ │ │ └── package-info.java │ │ │ ├── filters │ │ │ ├── AndFilter.java │ │ │ ├── CombiningFilter.java │ │ │ ├── ComparisonFilter.java │ │ │ ├── ComplexValueFilter.java │ │ │ ├── ContainsFilter.java │ │ │ ├── EndsWithFilter.java │ │ │ ├── EqualFilter.java │ │ │ ├── Filter.java │ │ │ ├── FilterType.java │ │ │ ├── FilterVisitor.java │ │ │ ├── GreaterThanFilter.java │ │ │ ├── GreaterThanOrEqualFilter.java │ │ │ ├── LessThanFilter.java │ │ │ ├── LessThanOrEqualFilter.java │ │ │ ├── NotEqualFilter.java │ │ │ ├── NotFilter.java │ │ │ ├── OrFilter.java │ │ │ ├── PresentFilter.java │ │ │ ├── StartsWithFilter.java │ │ │ └── package-info.java │ │ │ ├── messages │ │ │ ├── ErrorResponse.java │ │ │ ├── ListResponse.java │ │ │ ├── PatchOpType.java │ │ │ ├── PatchOperation.java │ │ │ ├── PatchRequest.java │ │ │ ├── SearchRequest.java │ │ │ ├── SortOrder.java │ │ │ └── package-info.java │ │ │ ├── package-info.java │ │ │ ├── types │ │ │ ├── Address.java │ │ │ ├── AttributeDefinition.java │ │ │ ├── AuthenticationScheme.java │ │ │ ├── BulkConfig.java │ │ │ ├── ChangePasswordConfig.java │ │ │ ├── ETagConfig.java │ │ │ ├── Email.java │ │ │ ├── EnterpriseUserExtension.java │ │ │ ├── Entitlement.java │ │ │ ├── FilterConfig.java │ │ │ ├── Group.java │ │ │ ├── GroupResource.java │ │ │ ├── InstantMessagingAddress.java │ │ │ ├── JsonReference.java │ │ │ ├── Manager.java │ │ │ ├── Member.java │ │ │ ├── Meta.java │ │ │ ├── Name.java │ │ │ ├── PatchConfig.java │ │ │ ├── PhoneNumber.java │ │ │ ├── Photo.java │ │ │ ├── ResourceTypeResource.java │ │ │ ├── Role.java │ │ │ ├── SchemaResource.java │ │ │ ├── ServiceProviderConfigResource.java │ │ │ ├── SortConfig.java │ │ │ ├── UserResource.java │ │ │ ├── X509Certificate.java │ │ │ └── package-info.java │ │ │ └── utils │ │ │ ├── ApiConstants.java │ │ │ ├── CalendarDeserializer.java │ │ │ ├── CalendarSerializer.java │ │ │ ├── CaseIgnoreMap.java │ │ │ ├── CaseIgnoreObjectNode.java │ │ │ ├── DateDeserializer.java │ │ │ ├── DateSerializer.java │ │ │ ├── DateTimeUtils.java │ │ │ ├── Debug.java │ │ │ ├── DebugType.java │ │ │ ├── FilterEvaluator.java │ │ │ ├── GenericScimObjectDeserializer.java │ │ │ ├── GenericScimObjectSerializer.java │ │ │ ├── JsonDiff.java │ │ │ ├── JsonRefBeanSerializer.java │ │ │ ├── JsonUtils.java │ │ │ ├── MapperFactory.java │ │ │ ├── Parser.java │ │ │ ├── ParserOptions.java │ │ │ ├── SchemaUtils.java │ │ │ ├── ScimFilterJsonParser.java │ │ │ ├── ScimJsonFactory.java │ │ │ ├── ScimJsonNodeFactory.java │ │ │ ├── StaticUtils.java │ │ │ ├── StatusDeserializer.java │ │ │ ├── StatusSerializer.java │ │ │ └── package-info.java │ ├── javadoc │ │ └── overview.html │ └── stubs │ │ └── com │ │ └── unboundid │ │ └── scim2 │ │ └── common │ │ └── utils │ │ └── Version.java.stub │ └── test │ └── java │ └── com │ └── unboundid │ └── scim2 │ └── common │ ├── AddOperationValueFilterTestCase.java │ ├── BaseScimResourceTest.java │ ├── DiffTestCase.java │ ├── ErrorResponseTest.java │ ├── ExtensionsTest.java │ ├── FilterEvaluatorTestCase.java │ ├── FilterParsingTestCase.java │ ├── GenericScimResourceObjectTest.java │ ├── GroupResourceTestCase.java │ ├── JsonUtilsTestCase.java │ ├── ListResponseTestCase.java │ ├── MapperFactoryTest.java │ ├── MetaTest.java │ ├── NonStandardRemoveOperationTest.java │ ├── NullabilityAnnotationTest.java │ ├── ParserOptionsTestCase.java │ ├── PatchOpTestCase.java │ ├── PatchRequestTest.java │ ├── PathParsingTestCase.java │ ├── ScimMultiValuedObject.java │ ├── SearchRequestTestCase.java │ ├── StaticUtilsTest.java │ ├── UserResourceTestCase.java │ ├── UserResourceVarargsTestCase.java │ ├── exceptions │ └── ScimExceptionTest.java │ ├── schema │ ├── SchemaGenerationTest.java │ ├── SchemaResourceTestCase.java │ └── testobjects │ │ ├── TestObject1.java │ │ ├── TestObject2.java │ │ ├── TestObject3.java │ │ ├── TestObject3_a.java │ │ ├── TestObject3_b.java │ │ ├── TestObject3_c.java │ │ └── TestObject3_d.java │ └── types │ └── AuthenticationSchemeTest.java ├── scim2-sdk-server ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── unboundid │ │ │ └── scim2 │ │ │ └── server │ │ │ ├── ListResponseStreamingOutput.java │ │ │ ├── ListResponseWriter.java │ │ │ ├── PATCH.java │ │ │ ├── annotations │ │ │ ├── ResourceType.java │ │ │ └── package-info.java │ │ │ ├── package-info.java │ │ │ ├── providers │ │ │ ├── AuthenticatedSubjectAliasFilter.java │ │ │ ├── DefaultContentTypeFilter.java │ │ │ ├── DotSearchFilter.java │ │ │ ├── JsonProcessingExceptionMapper.java │ │ │ ├── RuntimeExceptionMapper.java │ │ │ ├── ScimExceptionMapper.java │ │ │ └── package-info.java │ │ │ ├── resources │ │ │ ├── AbstractServiceProviderConfigEndpoint.java │ │ │ ├── ResourceTypesEndpoint.java │ │ │ ├── SchemasEndpoint.java │ │ │ └── package-info.java │ │ │ └── utils │ │ │ ├── ResourceComparator.java │ │ │ ├── ResourceDiff.java │ │ │ ├── ResourcePreparer.java │ │ │ ├── ResourceTrimmer.java │ │ │ ├── ResourceTypeDefinition.java │ │ │ ├── SchemaAwareFilterEvaluator.java │ │ │ ├── SchemaCheckFilterVisitor.java │ │ │ ├── SchemaChecker.java │ │ │ ├── ScimResourceTrimmer.java │ │ │ ├── ServerUtils.java │ │ │ ├── SimpleSearchResults.java │ │ │ └── package-info.java │ └── javadoc │ │ └── overview.html │ └── test │ └── java │ └── com │ └── unboundid │ └── scim2 │ └── server │ ├── CustomContentEndpoint.java │ ├── ETagTestCase.java │ ├── ETagTestEndpoint.java │ ├── EndpointTestCase.java │ ├── TestAuthenticatedSubjectAliasFilter.java │ ├── TestRequestFilter.java │ ├── TestResourceEndpoint.java │ ├── TestServiceProviderConfigEndpoint.java │ ├── TestSingletonResourceEndpoint.java │ └── utils │ ├── EncodeTemplateNamesTestCase.java │ ├── ResourcePreparerTestCase.java │ ├── SchemaAwareFilterEvaluatorTestCase.java │ ├── SchemaCheckerTestCase.java │ └── ServerNullabilityAnnotationTest.java └── scim2-ubid-extensions ├── README.md ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── unboundid │ │ └── scim2 │ │ └── extension │ │ └── messages │ │ ├── consent │ │ ├── Consent.java │ │ ├── ConsentHistory.java │ │ ├── OAuth2Client.java │ │ ├── Scope.java │ │ └── package-info.java │ │ ├── contactvalidation │ │ ├── EmailValidationRequest.java │ │ ├── TelephonyValidationRequest.java │ │ └── package-info.java │ │ ├── externalidentity │ │ ├── ExternalIdentity.java │ │ ├── Provider.java │ │ └── package-info.java │ │ ├── pwdmgmt │ │ ├── AccountState.java │ │ ├── AccountUsabilityIssue.java │ │ ├── PasswordQualityRequirementResponse.java │ │ ├── PasswordRequirementResult.java │ │ ├── PasswordUpdateErr.java │ │ ├── PasswordUpdateRequest.java │ │ ├── RetiredPassword.java │ │ ├── TOTPSecretRegistrationRequest.java │ │ └── package-info.java │ │ └── sessionmgmt │ │ ├── Session.java │ │ └── package-info.java └── javadoc │ └── overview.html └── test └── java └── com └── unboundid └── scim2 └── extension └── messages ├── UBIDExtensionsNullabilityAnnotationTest.java ├── consent ├── ConsentHistoryTest.java ├── ConsentTest.java ├── OAuth2ClientTest.java └── ScopeTest.java ├── externalidentity ├── ExternalIdentityTest.java └── ProviderTest.java ├── pwdmgmt ├── AccountStateTest.java └── PasswordQualityRequirementResponseTest.java └── sessionmgmt └── SessionTest.java /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior, including a code example, if applicable. 15 | 16 | **Expected behavior** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Additional context** 20 | Add any other context about the problem here. For example: 21 | - Java version: [e.g. Java 8] 22 | - SCIM 2 SDK version: [e.g. 2.3.7, master branch] 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of the problem that would be solved by this feature. 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | _Please be aware that Ping Identity does not accept third-party contributions at this time! Please see our [contribution guidelines](https://github.com/pingidentity/scim2/blob/master/CONTRIBUTING.md)._ 2 | 3 | What does this implement/fix? Explain your changes. 4 | --------------------------------------------------- 5 | … 6 | 7 | Does this close any currently open issues? 8 | ------------------------------------------ 9 | … 10 | -------------------------------------------------------------------------------- /.github/workflows/build-and-test.yaml: -------------------------------------------------------------------------------- 1 | name: Build Status 2 | 3 | on: 4 | push: 5 | # Run tests on any push to the main branch. 6 | branches: [ "master", "main", "ubid-test" ] 7 | pull_request: 8 | branches: [ "master", "main" ] 9 | 10 | jobs: 11 | build: 12 | name: mvn package 13 | runs-on: ubuntu-latest 14 | 15 | # Compile and build with supported LTS releases of Java. 16 | strategy: 17 | matrix: 18 | java-version: [ 17, 21, 25 ] 19 | # Run tests with each Java version sequentially. 20 | max-parallel: 1 21 | steps: 22 | - run: | 23 | echo "This job was triggered by the '${{ github.event_name }}' event." 24 | - uses: actions/checkout@v4 25 | - name: Install JDK ${{ matrix.java-version }} 26 | uses: actions/setup-java@v5 27 | with: 28 | java-version: ${{ matrix.java-version }} 29 | distribution: 'temurin' 30 | cache: maven 31 | 32 | - name: Build 33 | run: | 34 | ./mvnw clean package 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # IntelliJ IDEA files 2 | .idea/ 3 | *.iml 4 | 5 | # Build artifacts are placed in this folder. 6 | target/ 7 | 8 | # Ignore MacOS metadata. 9 | .DS_Store 10 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | wrapperVersion=3.3.2 18 | distributionType=only-script 19 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.10/apache-maven-3.9.10-bin.zip 20 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to the SCIM 2 SDK 2 | 3 | Thanks for taking the time to contribute! 4 | 5 | ## How can I contribute? 6 | 7 | ### Reporting bugs 8 | 9 | #### Before submitting a bug report 10 | 11 | It can be helpful to review the documentation and examples, including the [Javadocs](https://javadoc.io/doc/com.unboundid.product.scim2/scim2-parent/) and the [wiki](https://github.com/pingidentity/scim2/wiki). It's also a good idea to search the [issue tracker](https://github.com/pingidentity/scim2/issues) to see if your issue or one similar to it has already been reported. 12 | 13 | #### How do I submit a bug report? 14 | 15 | Bugs are tracked as [GitHub Issues](https://guides.github.com/features/issues/). You can report a bug by submitting an issue in the project's [issue tracker](https://github.com/pingidentity/scim2/issues). To help the maintainers understand and reproduce the problem, please try to provide information such as the following: 16 | 17 | * A clear and descriptive title. 18 | * A description of what happened and a description of what you expected to happen. 19 | * An example with the exact steps needed to reproduce the problem. If relevant, example HTTP requests and responses are helpful. 20 | 21 | Please understand that bug reports are reviewed and prioritized internally, and we may not be able to address all bug reports or provide an estimated time for resolution. 22 | 23 | ### Suggesting enhancements 24 | 25 | As with bugs, enhancement requests are tracked as [GitHub Issues](https://guides.github.com/features/issues/). You can suggest an enhancement by submitting an issue in the project's [issue tracker](https://github.com/pingidentity/scim2/issues). 26 | 27 | Please understand that enhancement requests are reviewed and prioritized internally, and we may not be able to address all requests or provide an estimated time for resolution. 28 | 29 | ### Contributing code changes 30 | 31 | Ping Identity does not accept third-party code submissions, such as pull requests. 32 | -------------------------------------------------------------------------------- /assemblies/sonatype-bundle.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 22 | sonatype-bundle 23 | false 24 | 25 | jar 26 | 27 | 28 | 29 | / 30 | ${project.build.directory} 31 | 32 | ${project.build.finalName}.pom 33 | ${project.build.finalName}.jar 34 | ${project.artifactId}-${project.version}-sources.jar 35 | ${project.artifactId}-${project.version}-javadoc.jar 36 | 37 | 38 | 39 | / 40 | ${project.build.directory} 41 | 42 | ${project.build.finalName}.pom.asc 43 | ${project.build.finalName}.jar.asc 44 | ${project.artifactId}-${project.version}-sources.jar.asc 45 | ${project.artifactId}-${project.version}-javadoc.jar.asc 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /config/scim2-parent-gpl.sourceheader: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (\d\d\d\d-)?(\d\d\d\d) Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License \(GPLv2 only\) 6 | * or the terms of the GNU Lesser General Public License \(LGPLv2.1 only\) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | -------------------------------------------------------------------------------- /config/scim2-parent-ubid.sourceheader: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (\d\d\d\d-)?(\d\d\d\d) Ping Identity Corporation 3 | * All Rights Reserved. 4 | */ 5 | -------------------------------------------------------------------------------- /resource/LICENSE.txt: -------------------------------------------------------------------------------- 1 | UnboundID SCIM2 SDK 2 | Copyright 2011-2025 Ping Identity Corporation 3 | 4 | The UnboundID SCIM2 SDK is available under three licenses: 5 | the GNU General Public License version 2 (GPLv2), the GNU Lesser 6 | General Public License version 2.1 (LGPLv2.1), and a free-right-to-use license 7 | created by Ping Identity Corporation. 8 | 9 | See the LICENSE-GPLv2.txt file for the GNU General Public License version 2. 10 | 11 | See the LICENSE-LGPLv2.1.txt file for the GNU Lesser General Public License 12 | version 2.1. 13 | 14 | See the LICENSE-UnboundID-SCIM2.txt file for the UnboundID SCIM 2.0 CLIENT 15 | SDK Free Use License. 16 | -------------------------------------------------------------------------------- /scim2-assembly/assemblies/zip.xml: -------------------------------------------------------------------------------- 1 | 17 | 21 | scim2-sdk 22 | 23 | zip 24 | 25 | 26 | 27 | licenses 28 | ${main.basedir}/resource 29 | 755 30 | 644 31 | 32 | 33 | docs 34 | ${main.basedir}/target/javadoc 35 | 755 36 | 644 37 | 38 | 39 | 40 | 41 | sources 42 | ${main.basedir}/scim2-sdk-client/target/scim2-sdk-client-${project.version}-sources.jar 43 | 644 44 | 45 | 46 | sources 47 | ${main.basedir}/scim2-sdk-common/target/scim2-sdk-common-${project.version}-sources.jar 48 | 644 49 | 50 | 51 | sources 52 | ${main.basedir}/scim2-sdk-server/target/scim2-sdk-server-${project.version}-sources.jar 53 | 644 54 | 55 | 56 | sources 57 | ${main.basedir}/scim2-ubid-extensions/target/scim2-ubid-extensions-${project.version}-sources.jar 58 | 644 59 | 60 | 61 | . 62 | ${main.basedir}/CHANGELOG.md 63 | 644 64 | 65 | 66 | . 67 | ${main.basedir}/README.md 68 | 644 69 | 70 | 71 | 72 | 73 | lib 74 | false 75 | 755 76 | 644 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /scim2-assembly/pom.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 4.0.0 19 | 20 | com.unboundid.product.scim2 21 | scim2-parent 22 | 5.0.0-SNAPSHOT 23 | ../pom.xml 24 | 25 | scim2-assembly 26 | pom 27 | UnboundID SCIM2 Assembly 28 | 29 | 30 | ${project.parent.basedir} 31 | 32 | 33 | 34 | 35 | UnboundID 36 | 37 | 38 | 39 | maven-assembly-plugin 40 | 41 | 42 | create-zip-archive 43 | package 44 | 45 | single 46 | 47 | 48 | scim2-sdk-${project.version} 49 | 50 | ${project.basedir}/assemblies/zip.xml 51 | 52 | false 53 | false 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | org.apache.maven.plugins 66 | maven-checkstyle-plugin 67 | 68 | true 69 | 70 | 71 | 72 | 73 | 74 | 75 | com.unboundid.product.scim2 76 | scim2-sdk-server 77 | 78 | 79 | com.unboundid.product.scim2 80 | scim2-ubid-extensions 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /scim2-sdk-client/src/main/java/com/unboundid/scim2/client/ScimServiceException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.client; 19 | 20 | import com.unboundid.scim2.common.annotations.Nullable; 21 | import com.unboundid.scim2.common.exceptions.ScimException; 22 | 23 | /** 24 | * This exception is thrown when problems occur in the {@link ScimService}. This 25 | * class allows a client application to differentiate between errors that 26 | * arise on the client side from errors that come from the server. 27 | */ 28 | public class ScimServiceException extends ScimException 29 | { 30 | /** 31 | * Create a new ScimServiceException from the provided information. 32 | * 33 | * @param statusCode The HTTP status code for this exception. 34 | * @param errorMessage The error message for this SCIM exception. 35 | * @param cause The cause (which is saved for later retrieval by the 36 | * {@link #getCause()} method). A {@code null} value 37 | * is permitted, and indicates that the cause is 38 | * nonexistent or unknown. 39 | */ 40 | 41 | public ScimServiceException(final int statusCode, 42 | @Nullable final String errorMessage, 43 | @Nullable final Throwable cause) 44 | { 45 | super(statusCode, null, errorMessage, cause); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /scim2-sdk-client/src/main/java/com/unboundid/scim2/client/SearchResultHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.client; 19 | 20 | import com.fasterxml.jackson.databind.node.ObjectNode; 21 | import com.unboundid.scim2.common.annotations.NotNull; 22 | 23 | /** 24 | * An interface for handling the search result response. Methods will be called 25 | * in the order they are received. 26 | */ 27 | public interface SearchResultHandler 28 | { 29 | /** 30 | * Handle the startIndex in the search response. 31 | * 32 | * @param startIndex The startIndex. 33 | */ 34 | void startIndex(final int startIndex); 35 | 36 | /** 37 | * Handle the itemsPerPage in the search response. 38 | * 39 | * @param itemsPerPage The itemsPerPage. 40 | */ 41 | void itemsPerPage(final int itemsPerPage); 42 | 43 | /** 44 | * Handle the totalResults in the search response. 45 | * 46 | * @param totalResults The totalResults. 47 | */ 48 | void totalResults(final int totalResults); 49 | 50 | /** 51 | * Handle a search result resource. 52 | * 53 | * @param scimResource A search result resource. 54 | * @return {@code true} to continue processing the search result response or 55 | * {@code false} to immediate stop further processing of the response. 56 | */ 57 | boolean resource(@NotNull final T scimResource); 58 | 59 | /** 60 | * Handle a schema extension in the search response. 61 | * 62 | * @param urn The URN of the extension schema. 63 | * @param extensionObjectNode The ObjectNode representing the extension 64 | * schema. 65 | */ 66 | void extension(@NotNull final String urn, 67 | @NotNull final ObjectNode extensionObjectNode); 68 | } 69 | -------------------------------------------------------------------------------- /scim2-sdk-client/src/main/java/com/unboundid/scim2/client/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /** 19 | * Client classes for accessing SCIM 2 resources. SCIM 2 clients are typically 20 | * built around the {@link com.unboundid.scim2.client.ScimService} class, 21 | * which provides methods for accessing a SCIM 2 service provider's resources, 22 | * configuration, schemas, and resource types. Requests for resources may 23 | * designate the type of the return value by specifying a 24 | * {@link com.unboundid.scim2.common.GenericScimResource} or a POJO derived 25 | * from {@link com.unboundid.scim2.common.BaseScimResource}. 26 | * 27 | * @see com.unboundid.scim2.common.GenericScimResource 28 | * @see com.unboundid.scim2.common.BaseScimResource 29 | */ 30 | 31 | package com.unboundid.scim2.client; 32 | -------------------------------------------------------------------------------- /scim2-sdk-client/src/main/java/com/unboundid/scim2/client/requests/CreateRequestBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.client.requests; 19 | 20 | import com.unboundid.scim2.common.ScimResource; 21 | import com.unboundid.scim2.common.annotations.NotNull; 22 | import com.unboundid.scim2.common.exceptions.ScimException; 23 | 24 | import jakarta.ws.rs.ProcessingException; 25 | import jakarta.ws.rs.client.Entity; 26 | import jakarta.ws.rs.client.WebTarget; 27 | import jakarta.ws.rs.core.Response; 28 | 29 | import static jakarta.ws.rs.core.Response.Status.Family.SUCCESSFUL; 30 | 31 | /** 32 | * A builder for SCIM create requests. 33 | */ 34 | public class CreateRequestBuilder 35 | extends ResourceReturningRequestBuilder> 36 | { 37 | @NotNull 38 | private final T resource; 39 | 40 | /** 41 | * Create a new SCIM create request builder that will POST the given resource 42 | * to the given web target. 43 | * 44 | * @param target The WebTarget to POST to. 45 | * @param resource The SCIM resource to POST. 46 | */ 47 | public CreateRequestBuilder(@NotNull final WebTarget target, 48 | @NotNull final T resource) 49 | { 50 | super(target); 51 | this.resource = resource; 52 | } 53 | 54 | /** 55 | * Invoke the SCIM create request. 56 | * 57 | * @return The successfully create SCIM resource. 58 | * @throws ScimException If an error occurred. 59 | */ 60 | @NotNull 61 | @SuppressWarnings("unchecked") 62 | public T invoke() throws ScimException 63 | { 64 | return (T) invoke(resource.getClass()); 65 | } 66 | 67 | /** 68 | * Invoke the SCIM create request. 69 | * 70 | * @param The type of object to return. 71 | * @param cls The Java class object used to determine the type to return. 72 | * @return The successfully modified SCIM resource. 73 | * @throws ProcessingException If a JAX-RS runtime exception occurred. 74 | * @throws ScimException If the SCIM service provider responded with an error. 75 | */ 76 | @NotNull 77 | public C invoke(@NotNull final Class cls) throws ScimException 78 | { 79 | var entity = Entity.entity(generify(resource), getContentType()); 80 | try (Response response = buildRequest().post(entity)) 81 | { 82 | if (response.getStatusInfo().getFamily() == SUCCESSFUL) 83 | { 84 | return response.readEntity(cls); 85 | } 86 | else 87 | { 88 | throw toScimException(response); 89 | } 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /scim2-sdk-client/src/main/java/com/unboundid/scim2/client/requests/DeleteRequestBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.client.requests; 19 | 20 | import com.unboundid.scim2.common.annotations.NotNull; 21 | import com.unboundid.scim2.common.annotations.Nullable; 22 | import com.unboundid.scim2.common.exceptions.ScimException; 23 | 24 | import jakarta.ws.rs.ProcessingException; 25 | import jakarta.ws.rs.client.Invocation; 26 | import jakarta.ws.rs.client.WebTarget; 27 | import jakarta.ws.rs.core.HttpHeaders; 28 | import jakarta.ws.rs.core.Response; 29 | 30 | import static jakarta.ws.rs.core.Response.Status.Family.SUCCESSFUL; 31 | 32 | /** 33 | * A builder for SCIM delete requests. 34 | */ 35 | public class DeleteRequestBuilder extends RequestBuilder 36 | { 37 | @Nullable 38 | private String version; 39 | 40 | /** 41 | * Create a new DeleteRequestBuilder. 42 | * 43 | * @param target The WebTarget to DELETE. 44 | */ 45 | public DeleteRequestBuilder(@NotNull final WebTarget target) 46 | { 47 | super(target); 48 | } 49 | 50 | /** 51 | * Delete the resource only if the resource has not been modified since the 52 | * provided version. 53 | * 54 | * @param version The version of the resource to compare. 55 | * @return This builder. 56 | */ 57 | @NotNull 58 | public DeleteRequestBuilder ifMatch(@Nullable final String version) 59 | { 60 | this.version = version; 61 | return this; 62 | } 63 | 64 | /** 65 | * {@inheritDoc} 66 | */ 67 | @Override 68 | @NotNull 69 | protected Invocation.Builder buildRequest() 70 | { 71 | Invocation.Builder request = super.buildRequest(); 72 | if (version != null) 73 | { 74 | request.header(HttpHeaders.IF_MATCH, version); 75 | } 76 | return request; 77 | } 78 | 79 | /** 80 | * Invoke the SCIM delete request. 81 | * 82 | * @throws ProcessingException If a JAX-RS runtime exception occurred. 83 | * @throws ScimException If the SCIM service provider responded with an error. 84 | */ 85 | public void invoke() throws ScimException 86 | { 87 | try (Response response = buildRequest().delete()) 88 | { 89 | if (response.getStatusInfo().getFamily() != SUCCESSFUL) 90 | { 91 | throw toScimException(response); 92 | } 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /scim2-sdk-client/src/main/java/com/unboundid/scim2/client/requests/ListResponseBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.client.requests; 19 | 20 | import com.fasterxml.jackson.databind.node.ObjectNode; 21 | import com.unboundid.scim2.client.SearchResultHandler; 22 | import com.unboundid.scim2.common.annotations.NotNull; 23 | import com.unboundid.scim2.common.annotations.Nullable; 24 | import com.unboundid.scim2.common.messages.ListResponse; 25 | 26 | import java.util.LinkedList; 27 | import java.util.List; 28 | import java.util.Optional; 29 | 30 | /** 31 | * A builder for {@link ListResponse} that is also a SearchResultHandler 32 | * implementation. 33 | */ 34 | public class ListResponseBuilder 35 | implements SearchResultHandler 36 | { 37 | @Nullable 38 | private Integer totalResults; 39 | 40 | @NotNull 41 | private final List resources = new LinkedList<>(); 42 | 43 | @Nullable 44 | private Integer startIndex; 45 | 46 | @Nullable 47 | private Integer itemsPerPage; 48 | 49 | /** 50 | * {@inheritDoc} 51 | */ 52 | public void startIndex(final int startIndex) 53 | { 54 | this.startIndex = startIndex; 55 | } 56 | 57 | /** 58 | * {@inheritDoc} 59 | */ 60 | public void itemsPerPage(final int itemsPerPage) 61 | { 62 | this.itemsPerPage = itemsPerPage; 63 | } 64 | 65 | /** 66 | * {@inheritDoc} 67 | */ 68 | public void totalResults(final int totalResults) 69 | { 70 | this.totalResults = totalResults; 71 | } 72 | 73 | /** 74 | * {@inheritDoc} 75 | */ 76 | public boolean resource(@NotNull final T scimResource) 77 | { 78 | this.resources.add(scimResource); 79 | return true; 80 | } 81 | 82 | /** 83 | * {@inheritDoc} 84 | *

85 | * This method currently does not perform any action and should not be used. 86 | */ 87 | public void extension(@NotNull final String urn, 88 | @NotNull final ObjectNode extensionObjectNode) 89 | { 90 | // TODO: do nothing for now 91 | } 92 | 93 | /** 94 | * Builds a {@link ListResponse} based on the values supplied to the builder. 95 | * 96 | * @return A generated ListResponse. 97 | */ 98 | @NotNull 99 | public ListResponse build() 100 | { 101 | return new ListResponse<>( 102 | Optional.ofNullable(totalResults).orElse(resources.size()), 103 | resources, 104 | startIndex, 105 | itemsPerPage 106 | ); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /scim2-sdk-client/src/main/java/com/unboundid/scim2/client/requests/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /** 19 | * Classes for building SCIM 2 requests. These classes are typically accessed 20 | * through a {@link com.unboundid.scim2.client.ScimService} instance. 21 | * 22 | * @see com.unboundid.scim2.client.ScimService 23 | */ 24 | 25 | package com.unboundid.scim2.client.requests; 26 | -------------------------------------------------------------------------------- /scim2-sdk-client/src/main/javadoc/overview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | UnboundID SCIM 2 SDK Client 5 | 6 | 7 | 8 |

This package contains client classes for building SCIM 2 requests and for 9 | accessing resources from SCIM 2 service providers.

10 | 11 |

The most important of these is the 12 | {@link com.unboundid.scim2.client.ScimService} class, which is the 13 | main entry point for the SCIM 2 client API. This class provides methods for 14 | accessing a SCIM 2 service provider's resources, configuration, schemas, 15 | and resource types.

16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /scim2-sdk-client/src/test/java/com/unboundid/scim2/client/RequestBuilderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.client; 19 | 20 | import com.unboundid.scim2.client.requests.CreateRequestBuilder; 21 | import com.unboundid.scim2.client.requests.DeleteRequestBuilder; 22 | import com.unboundid.scim2.client.requests.ReplaceRequestBuilder; 23 | import com.unboundid.scim2.client.requests.SearchRequestBuilder; 24 | import com.unboundid.scim2.common.ScimResource; 25 | import com.unboundid.scim2.common.types.UserResource; 26 | import jakarta.ws.rs.client.WebTarget; 27 | import org.testng.annotations.Test; 28 | 29 | import static org.assertj.core.api.Assertions.assertThat; 30 | 31 | 32 | public class RequestBuilderTest 33 | { 34 | /** 35 | * Ensures that builder classes are not {@code final} and can be extended. 36 | */ 37 | @Test 38 | public void testExtendable() 39 | { 40 | final WebTarget target = null; 41 | final UserResource resource = new UserResource(); 42 | 43 | // Test CreateRequestBuilder. 44 | class CustomCreate 45 | extends CreateRequestBuilder 46 | { 47 | public String otherField; 48 | 49 | public CustomCreate(WebTarget target, T resource) 50 | { 51 | super(target, resource); 52 | } 53 | } 54 | var createInstance = new CustomCreate<>(target, resource); 55 | createInstance.otherField = "present"; 56 | assertThat(createInstance.otherField).isEqualTo("present"); 57 | 58 | // Test ReplaceRequestBuilder. 59 | class CustomReplace 60 | extends ReplaceRequestBuilder 61 | { 62 | public String otherField; 63 | 64 | public CustomReplace(WebTarget target, T resource) 65 | { 66 | super(target, resource); 67 | } 68 | } 69 | var replaceInstance = new CustomReplace<>(target, resource); 70 | replaceInstance.otherField = "present"; 71 | assertThat(replaceInstance.otherField).isEqualTo("present"); 72 | 73 | // Test DeleteRequestBuilder. 74 | class CustomDelete extends DeleteRequestBuilder 75 | { 76 | public String otherField; 77 | 78 | public CustomDelete(WebTarget target) 79 | { 80 | super(target); 81 | } 82 | } 83 | var deleteInstance = new CustomDelete(target); 84 | deleteInstance.otherField = "present"; 85 | assertThat(deleteInstance.otherField).isEqualTo("present"); 86 | 87 | // Test SearchRequestBuilder. 88 | class CustomSearch extends SearchRequestBuilder 89 | { 90 | public String otherField; 91 | 92 | public CustomSearch(WebTarget target) 93 | { 94 | super(target); 95 | } 96 | } 97 | var searchInstance = new CustomSearch(target); 98 | searchInstance.otherField = "present"; 99 | assertThat(searchInstance.otherField).isEqualTo("present"); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/annotations/NotNull.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | /* 18 | * Copyright 2023-2025 Ping Identity Corporation 19 | * 20 | * Licensed under the Apache License, Version 2.0 (the "License"); 21 | * you may not use this file except in compliance with the License. 22 | * You may obtain a copy of the License at 23 | * 24 | * http://www.apache.org/licenses/LICENSE-2.0 25 | * 26 | * Unless required by applicable law or agreed to in writing, software 27 | * distributed under the License is distributed on an "AS IS" BASIS, 28 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 29 | * See the License for the specific language governing permissions and 30 | * limitations under the License. 31 | */ 32 | 33 | package com.unboundid.scim2.common.annotations; 34 | 35 | 36 | 37 | import java.lang.annotation.Documented; 38 | import java.lang.annotation.ElementType; 39 | import java.lang.annotation.Retention; 40 | import java.lang.annotation.RetentionPolicy; 41 | import java.lang.annotation.Target; 42 | 43 | 44 | 45 | /** 46 | * This annotation type is used to indicate that the associated field, local 47 | * variable, method or constructor parameter, or method return value is not 48 | * allowed to be {@code null}. This annotation type is not strictly enforced by 49 | * the compiler, but development environments may be configured to warn or 50 | * reject attempts to use {@code null} values where non-{@code null} values are 51 | * expected. 52 | *

53 | * This annotation type will appear in the generated Javadoc documentation for 54 | * classes and interfaces that include it. 55 | *

56 | * This annotation class is based on a similar one from the UnboundID LDAP SDK. 57 | * 58 | * @see Nullable 59 | */ 60 | @Documented 61 | @Retention(RetentionPolicy.RUNTIME) 62 | @Target({ ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.PARAMETER, 63 | ElementType.METHOD }) 64 | public @interface NotNull 65 | { 66 | } 67 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/annotations/Nullable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | /* 18 | * Copyright 2023-2025 Ping Identity Corporation 19 | * 20 | * Licensed under the Apache License, Version 2.0 (the "License"); 21 | * you may not use this file except in compliance with the License. 22 | * You may obtain a copy of the License at 23 | * 24 | * http://www.apache.org/licenses/LICENSE-2.0 25 | * 26 | * Unless required by applicable law or agreed to in writing, software 27 | * distributed under the License is distributed on an "AS IS" BASIS, 28 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 29 | * See the License for the specific language governing permissions and 30 | * limitations under the License. 31 | */ 32 | 33 | package com.unboundid.scim2.common.annotations; 34 | 35 | 36 | 37 | import java.lang.annotation.Documented; 38 | import java.lang.annotation.ElementType; 39 | import java.lang.annotation.Retention; 40 | import java.lang.annotation.RetentionPolicy; 41 | import java.lang.annotation.Target; 42 | 43 | 44 | 45 | /** 46 | * This annotation type is used to indicate that the associated field, local 47 | * variable, method or constructor parameter, or method return value is allowed 48 | * to be {@code null}, and that code using nullable elements should be prepared 49 | * to encounter {@code null} values. 50 | *

51 | * This annotation type will appear in the generated Javadoc documentation for 52 | * classes and interfaces that include it. 53 | *

54 | * This annotation class is based on a similar one from the UnboundID LDAP SDK. 55 | * 56 | * @see NotNull 57 | */ 58 | @Documented 59 | @Retention(RetentionPolicy.RUNTIME) 60 | @Target({ ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.PARAMETER, 61 | ElementType.METHOD }) 62 | public @interface Nullable 63 | { 64 | } 65 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/annotations/Schema.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common.annotations; 19 | 20 | import java.lang.annotation.ElementType; 21 | import java.lang.annotation.Retention; 22 | import java.lang.annotation.RetentionPolicy; 23 | import java.lang.annotation.Target; 24 | 25 | /** 26 | * Class level annotation indicating the schema of a SCIM object. 27 | */ 28 | @Target(value = ElementType.TYPE) 29 | @Retention(value = RetentionPolicy.RUNTIME) 30 | public @interface Schema 31 | { 32 | /** 33 | * The id for the object. This is the complete URN. 34 | * 35 | * @return The object's id as a URN. 36 | */ 37 | @NotNull String id() default "urn:pingidentity:scim:api:messages:2.0"; 38 | 39 | /** 40 | * The description for the object. 41 | * 42 | * @return The object's description. 43 | */ 44 | @NotNull String description(); 45 | 46 | /** 47 | * The human-readable name for the object. 48 | * 49 | * @return The object's human-readable name. 50 | */ 51 | @NotNull String name(); 52 | } 53 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/annotations/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /** 19 | * Annotation classes to use when describing SCIM 2 resource types and 20 | * attributes. 21 | */ 22 | 23 | package com.unboundid.scim2.common.annotations; 24 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/exceptions/MethodNotAllowedException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common.exceptions; 19 | 20 | import com.unboundid.scim2.common.annotations.NotNull; 21 | import com.unboundid.scim2.common.annotations.Nullable; 22 | import com.unboundid.scim2.common.messages.ErrorResponse; 23 | 24 | /** 25 | * This class represents a SCIM exception pertaining to the 26 | * {@code HTTP 405 METHOD NOT ALLOWED} error response code. This exception type 27 | * should be thrown when a client sends a request to a valid endpoint, but 28 | * provides an unsupported REST method (e.g., {@code GET}, {@code POST}). 29 | *

30 | * The following is an example of a MethodNotAllowedException as seen by a SCIM 31 | * client. 32 | *
33 |  *   {
34 |  *     "schemas": [ "urn:ietf:params:scim:api:messages:2.0:Error" ],
35 |  *     "status": "405",
36 |  *     "detail": "The /.search endpoint only supports POST requests."
37 |  *   }
38 |  * 
39 | * 40 | * The MethodNotAllowedException in the above example can be created with the 41 | * following Java code: 42 | *
43 |  *   throw new MethodNotAllowedException(
44 |  *           "The /.search endpoint only supports POST requests.");
45 |  * 
46 | * 47 | * This exception type generally does not have a {@code scimType} value. 48 | */ 49 | public class MethodNotAllowedException extends ScimException 50 | { 51 | private static final int METHOD_NOT_ALLOWED_CODE = 405; 52 | 53 | 54 | /** 55 | * Create a new {@code MethodNotAllowedException} from the provided 56 | * information. 57 | * 58 | * @param errorMessage The error message for this SCIM exception. 59 | */ 60 | public MethodNotAllowedException(@Nullable final String errorMessage) 61 | { 62 | super(METHOD_NOT_ALLOWED_CODE, errorMessage); 63 | } 64 | 65 | 66 | /** 67 | * Create a new {@code MethodNotAllowedException} from the provided 68 | * information. 69 | * 70 | * @param scimError The SCIM error response. 71 | * @param cause The cause (which is saved for later retrieval by the 72 | * {@link #getCause()} method). A {@code null} value 73 | * is permitted, and indicates that the cause is 74 | * nonexistent or unknown. 75 | */ 76 | public MethodNotAllowedException(@NotNull final ErrorResponse scimError, 77 | @Nullable final Throwable cause) 78 | { 79 | super(scimError, cause); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/exceptions/ServerErrorException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common.exceptions; 19 | 20 | import com.unboundid.scim2.common.annotations.NotNull; 21 | import com.unboundid.scim2.common.annotations.Nullable; 22 | import com.unboundid.scim2.common.messages.ErrorResponse; 23 | 24 | /** 25 | * This class represents a SCIM exception pertaining to the 26 | * {@code HTTP 500 INTERNAL SERVER ERROR} error response code. This exception 27 | * type should be thrown when a SCIM service provider encounters an unexpected 28 | * error. 29 | *

30 | * The following is an example of a ServerErrorException seen by a SCIM client. 31 | *
32 |  *   {
33 |  *     "schemas": [ "urn:ietf:params:scim:api:messages:2.0:Error" ],
34 |  *     "status": "500",
35 |  *     "detail": "An unexpected error occurred."
36 |  *   }
37 |  * 
38 | * 39 | * The ServerErrorException in the above example can be created with the 40 | * following Java code: 41 | *
42 |  *   throw new ServerErrorException("An unexpected error occurred.");
43 |  * 
44 | * 45 | * This exception type generally does not have a {@code scimType} value. 46 | */ 47 | public class ServerErrorException extends ScimException 48 | { 49 | /** 50 | * Create a new {@code ServerErrorException} from the provided information. 51 | * 52 | * @param errorMessage The error message for this SCIM exception. 53 | */ 54 | public ServerErrorException(@Nullable final String errorMessage) 55 | { 56 | super(500, null, errorMessage); 57 | } 58 | 59 | /** 60 | * Create a new {@code ServerErrorException} from the provided information. 61 | * 62 | * @param errorMessage The error message for this SCIM exception. 63 | * @param scimType The SCIM detailed error keyword. 64 | * @param cause The cause (which is saved for later retrieval by the 65 | * {@link #getCause()} method). A {@code null} value 66 | * is permitted, and indicates that the cause is 67 | * nonexistent or unknown. 68 | */ 69 | public ServerErrorException(@Nullable final String errorMessage, 70 | @Nullable final String scimType, 71 | @Nullable final Throwable cause) 72 | { 73 | super(500, scimType, errorMessage, cause); 74 | } 75 | 76 | /** 77 | * Create a new {@code ServerErrorException} from the provided information. 78 | * 79 | * @param scimError The SCIM error response. 80 | * @param cause The cause (which is saved for later retrieval by the 81 | * {@link #getCause()} method). A {@code null} value 82 | * is permitted, and indicates that the cause is 83 | * nonexistent or unknown. 84 | */ 85 | public ServerErrorException(@NotNull final ErrorResponse scimError, 86 | @Nullable final Throwable cause) 87 | { 88 | super(scimError, cause); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/exceptions/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /** 19 | * Exception classes representing SCIM 2 service provider responses. 20 | */ 21 | 22 | package com.unboundid.scim2.common.exceptions; 23 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/filters/CombiningFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common.filters; 19 | 20 | import com.unboundid.scim2.common.annotations.NotNull; 21 | 22 | import java.util.Collections; 23 | import java.util.List; 24 | 25 | /** 26 | * This class is the superclass of filter types that contains two filters. There 27 | * are two types of combining filters: 28 | *
    29 | *
  • {@link AndFilter} 30 | *
  • {@link OrFilter} 31 | *
32 | *

33 | * 34 | * "Combining" filters contain subordinate filters, which are also referred to 35 | * as "filter components". To obtain the filter components that comprise a 36 | * combining filter, use the {@link #getCombinedFilters()} method. 37 | *

38 | * 39 | * For more information, see the class-level documentation of the subclasses of 40 | * CombiningFilter. 41 | */ 42 | public abstract class CombiningFilter extends Filter 43 | { 44 | @NotNull 45 | private final List filterComponents; 46 | 47 | /** 48 | * Create a new logical combining filter. 49 | * 50 | * @param filterComponents The filter components to combine. 51 | */ 52 | CombiningFilter(@NotNull final List filterComponents) 53 | { 54 | this.filterComponents = Collections.unmodifiableList(filterComponents); 55 | } 56 | 57 | /** 58 | * {@inheritDoc} 59 | */ 60 | @Override 61 | public boolean isCombiningFilter() 62 | { 63 | return true; 64 | } 65 | 66 | /** 67 | * {@inheritDoc} 68 | */ 69 | @Override 70 | @NotNull 71 | public List getCombinedFilters() 72 | { 73 | return filterComponents; 74 | } 75 | 76 | /** 77 | * Append the string representation of the filter to the provided buffer. 78 | * 79 | * @param builder The buffer to which the string representation of the 80 | * filter is to be appended. 81 | */ 82 | public void toString(@NotNull final StringBuilder builder) 83 | { 84 | builder.append('('); 85 | 86 | for (int i = 0; i < filterComponents.size(); i++) 87 | { 88 | if (i != 0) 89 | { 90 | builder.append(' '); 91 | builder.append(getFilterType().getStringValue()); 92 | builder.append(' '); 93 | } 94 | 95 | builder.append(filterComponents.get(i)); 96 | } 97 | 98 | builder.append(')'); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/filters/ComparisonFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common.filters; 19 | 20 | import com.fasterxml.jackson.databind.node.ValueNode; 21 | import com.unboundid.scim2.common.Path; 22 | import com.unboundid.scim2.common.annotations.NotNull; 23 | import com.unboundid.scim2.common.annotations.Nullable; 24 | import com.unboundid.scim2.common.utils.JsonUtils; 25 | 26 | /** 27 | * This superclass represents filter types that are used to compare attribute 28 | * values of SCIM resources. 29 | *

30 | * 31 | * For example, an {@link EqualFilter} is a comparison filter. A filter such as 32 | * {@code preferredLanguage eq "en-US"} is used to perform a comparison between 33 | * the filter value, {@code "en-US"}, and the value of a SCIM resource's 34 | * {@code preferredLanguage} attribute. 35 | *

36 | * 37 | * To determine whether a filter is a comparison filter, use the 38 | * {@link Filter#isComparisonFilter()} method. 39 | */ 40 | public abstract class ComparisonFilter extends Filter 41 | { 42 | @NotNull 43 | private final Path filterAttribute; 44 | 45 | @NotNull 46 | private final ValueNode filterValue; 47 | 48 | /** 49 | * Create a new attribute comparison filter. 50 | * 51 | * @param filterAttribute The path to the attribute to compare. 52 | * @param filterValue The comparison value. 53 | */ 54 | ComparisonFilter(@NotNull final Path filterAttribute, 55 | @Nullable final ValueNode filterValue) 56 | { 57 | this.filterAttribute = filterAttribute; 58 | if (filterValue == null) 59 | { 60 | this.filterValue = JsonUtils.getJsonNodeFactory().nullNode(); 61 | } 62 | else 63 | { 64 | this.filterValue = filterValue; 65 | } 66 | } 67 | 68 | /** 69 | * {@inheritDoc} 70 | */ 71 | @Override 72 | @Nullable 73 | public Path getAttributePath() 74 | { 75 | return filterAttribute; 76 | } 77 | 78 | /** 79 | * {@inheritDoc} 80 | */ 81 | @Override 82 | @Nullable 83 | public ValueNode getComparisonValue() 84 | { 85 | return filterValue; 86 | } 87 | 88 | /** 89 | * {@inheritDoc} 90 | */ 91 | @Override 92 | public boolean isComparisonFilter() 93 | { 94 | return true; 95 | } 96 | 97 | /** 98 | * Append the string representation of the filter to the provided buffer. 99 | * 100 | * @param builder The buffer to which the string representation of the 101 | * filter is to be appended. 102 | */ 103 | public void toString(@NotNull final StringBuilder builder) 104 | { 105 | builder.append(filterAttribute); 106 | builder.append(' '); 107 | builder.append(getFilterType().getStringValue()); 108 | builder.append(' '); 109 | builder.append(filterValue.toString()); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/filters/FilterType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common.filters; 19 | 20 | 21 | import com.unboundid.scim2.common.annotations.NotNull; 22 | 23 | /** 24 | * This enumeration defines the set of possible filter types that may 25 | * be used for SCIM query filters. 26 | */ 27 | public enum FilterType 28 | { 29 | /** 30 | * The filter type for {@code and} filters. 31 | */ 32 | AND("and"), 33 | 34 | 35 | /** 36 | * The filter type for {@code or} filters. 37 | */ 38 | OR("or"), 39 | 40 | 41 | /** 42 | * The filter type for {@code not} filters. 43 | */ 44 | NOT("not"), 45 | 46 | 47 | /** 48 | * The filter type for complex attribute value filters. 49 | */ 50 | COMPLEX_VALUE("complex"), 51 | 52 | 53 | /** 54 | * The filter type for {@code equal} filters. 55 | */ 56 | EQUAL("eq"), 57 | 58 | 59 | /** 60 | * The filter type for {@code not equal} filters. 61 | */ 62 | NOT_EQUAL("ne"), 63 | 64 | 65 | /** 66 | * The filter type for {@code contains} filters. 67 | */ 68 | CONTAINS("co"), 69 | 70 | 71 | /** 72 | * The filter type for {@code starts with} filters. 73 | */ 74 | STARTS_WITH("sw"), 75 | 76 | 77 | /** 78 | * The filter type for {@code starts ends} filters. 79 | */ 80 | ENDS_WITH("ew"), 81 | 82 | 83 | /** 84 | * The filter type for {@code present} filters. 85 | */ 86 | PRESENT("pr"), 87 | 88 | 89 | /** 90 | * The filter type for {@code greater than} filters. 91 | */ 92 | GREATER_THAN("gt"), 93 | 94 | 95 | /** 96 | * The filter type for {@code greater or equal} filters. 97 | */ 98 | GREATER_OR_EQUAL("ge"), 99 | 100 | 101 | /** 102 | * The filter type for {@code less than} filters. 103 | */ 104 | LESS_THAN("lt"), 105 | 106 | 107 | /** 108 | * The filter type for {@code less or equal} filters. 109 | */ 110 | LESS_OR_EQUAL("le"); 111 | 112 | 113 | /** 114 | * The lower case string value for this filter type. 115 | */ 116 | @NotNull 117 | private String stringValue; 118 | 119 | 120 | /** 121 | * Creates a new filter type with the provided string value. 122 | * 123 | * @param stringValue The lower case string value for this filter type. 124 | */ 125 | FilterType(@NotNull final String stringValue) 126 | { 127 | this.stringValue = stringValue; 128 | } 129 | 130 | 131 | /** 132 | * Retrieves the lower case string value for this filter type. 133 | * 134 | * @return The lower case string value for this filter type. 135 | */ 136 | @NotNull 137 | public String getStringValue() 138 | { 139 | return stringValue; 140 | } 141 | 142 | 143 | /** 144 | * Retrieves a string representation of this filter type. 145 | * 146 | * @return A string representation of this filter type. 147 | */ 148 | @NotNull 149 | public String toString() 150 | { 151 | return getStringValue(); 152 | } 153 | } 154 | 155 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/filters/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /** 19 | * Classes used to build SCIM 2 query filters. 20 | */ 21 | 22 | package com.unboundid.scim2.common.filters; 23 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/messages/PatchOpType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common.messages; 19 | 20 | 21 | import com.unboundid.scim2.common.annotations.NotNull; 22 | 23 | /** 24 | * This enumeration defines the set of possible operation types that may 25 | * be used for SCIM 2 patch operations. 26 | */ 27 | public enum PatchOpType 28 | { 29 | /** 30 | * The add operation type. 31 | */ 32 | ADD("add"), 33 | 34 | 35 | /** 36 | * The replace operation type. 37 | */ 38 | REPLACE("replace"), 39 | 40 | 41 | /** 42 | * The remove operation type. 43 | */ 44 | REMOVE("remove"); 45 | 46 | 47 | /** 48 | * The lower case string value for this operation type. 49 | */ 50 | @NotNull 51 | private String stringValue; 52 | 53 | 54 | /** 55 | * Creates a new operation type with the provided string value. 56 | * 57 | * @param stringValue The lower case string value for this operation type. 58 | */ 59 | PatchOpType(@NotNull final String stringValue) 60 | { 61 | this.stringValue = stringValue; 62 | } 63 | 64 | 65 | /** 66 | * Retrieves the lower case string value for this operation type. 67 | * 68 | * @return The lower case string value for this operation type. 69 | */ 70 | @NotNull 71 | public String getStringValue() 72 | { 73 | return stringValue; 74 | } 75 | 76 | 77 | /** 78 | * Retrieves a string representation of this operation type. 79 | * 80 | * @return A string representation of this operation type. 81 | */ 82 | @NotNull 83 | public String toString() 84 | { 85 | return getStringValue(); 86 | } 87 | } 88 | 89 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/messages/SortOrder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common.messages; 19 | 20 | import com.fasterxml.jackson.annotation.JsonCreator; 21 | import com.fasterxml.jackson.annotation.JsonValue; 22 | import com.unboundid.scim2.common.annotations.NotNull; 23 | import com.unboundid.scim2.common.exceptions.BadRequestException; 24 | 25 | /** 26 | * The order in which the sortBy parameter is applied. 27 | */ 28 | public enum SortOrder 29 | { 30 | /** 31 | * The ascending sort order. 32 | */ 33 | ASCENDING("ascending"), 34 | 35 | 36 | /** 37 | * The descending sort order. 38 | */ 39 | DESCENDING("descending"); 40 | 41 | 42 | /** 43 | * The lower case string value for this sort order. 44 | */ 45 | @NotNull 46 | private String name; 47 | 48 | 49 | /** 50 | * SortOrder enum private constructor. 51 | * 52 | * @param name the name of the sort order. 53 | */ 54 | SortOrder(@NotNull final String name) 55 | { 56 | this.name = name; 57 | } 58 | 59 | /** 60 | * Gets the name of the sort order. 61 | * 62 | * @return the name of the sort order. 63 | */ 64 | @NotNull 65 | @JsonValue 66 | public String getName() 67 | { 68 | return name; 69 | } 70 | 71 | /** 72 | * Finds the sort order by name. 73 | * 74 | * @param name the name of the mutability constraint. 75 | * @return the enum value for the given name. 76 | * @throws BadRequestException if the name of the sort order is invalid. 77 | */ 78 | @NotNull 79 | @JsonCreator 80 | public static SortOrder fromName(@NotNull final String name) 81 | throws BadRequestException 82 | { 83 | for (SortOrder sortOrder : SortOrder.values()) 84 | { 85 | if (sortOrder.getName().equals(name)) 86 | { 87 | return sortOrder; 88 | } 89 | } 90 | 91 | throw BadRequestException.invalidSyntax( 92 | "Unknown sort order value " + name); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/messages/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /** 19 | * Classes representing core SCIM 2 messages, such as error responses, query 20 | * responses, and PATCH requests. 21 | */ 22 | 23 | package com.unboundid.scim2.common.messages; 24 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /** 19 | * Common SCIM 2 classes, including base classes for representing SCIM 2 20 | * resources. 21 | */ 22 | 23 | package com.unboundid.scim2.common; 24 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/types/ChangePasswordConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common.types; 19 | 20 | import com.fasterxml.jackson.annotation.JsonCreator; 21 | import com.fasterxml.jackson.annotation.JsonProperty; 22 | import com.unboundid.scim2.common.annotations.Attribute; 23 | import com.unboundid.scim2.common.annotations.Nullable; 24 | 25 | /** 26 | * A complex type that specifies Change Password configuration options. 27 | */ 28 | public class ChangePasswordConfig 29 | { 30 | @Attribute(description = "Boolean value specifying whether the " + 31 | "operation is supported.", 32 | mutability = AttributeDefinition.Mutability.READ_ONLY, 33 | isRequired = true) 34 | private final boolean supported; 35 | 36 | /** 37 | * Create a new complex type that specifies Change Password configuration 38 | * options. 39 | * 40 | * @param supported Boolean value specifying whether the operation is 41 | * supported. 42 | */ 43 | @JsonCreator 44 | public ChangePasswordConfig( 45 | @JsonProperty(value = "supported", required = true) 46 | final boolean supported) 47 | { 48 | this.supported = supported; 49 | } 50 | 51 | /** 52 | * Retrieves the boolean value specifying whether the operation is 53 | * supported. 54 | * 55 | * @return {@code true} if the operation is supported or {@code false} 56 | * otherwise. 57 | */ 58 | public boolean isSupported() 59 | { 60 | return supported; 61 | } 62 | 63 | /** 64 | * Indicates whether the provided object is equal to this Change Password 65 | * configuration. 66 | * 67 | * @param o The object to compare. 68 | * @return {@code true} if the provided object is equal to this Change 69 | * Password configuration, or {@code false} if not. 70 | */ 71 | @Override 72 | public boolean equals(@Nullable final Object o) 73 | { 74 | if (this == o) 75 | { 76 | return true; 77 | } 78 | if (o == null || getClass() != o.getClass()) 79 | { 80 | return false; 81 | } 82 | 83 | ChangePasswordConfig that = (ChangePasswordConfig) o; 84 | return supported == that.supported; 85 | } 86 | 87 | /** 88 | * Retrieves a hash code for this Change Password configuration. 89 | * 90 | * @return A hash code for this Change Password configuration. 91 | */ 92 | @Override 93 | public int hashCode() 94 | { 95 | return (supported ? 1 : 0); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/types/PatchConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common.types; 19 | 20 | import com.fasterxml.jackson.annotation.JsonCreator; 21 | import com.fasterxml.jackson.annotation.JsonProperty; 22 | import com.unboundid.scim2.common.annotations.Attribute; 23 | import com.unboundid.scim2.common.annotations.Nullable; 24 | 25 | /** 26 | * A complex type that specifies PATCH configuration options. 27 | */ 28 | public class PatchConfig 29 | { 30 | @Attribute(description = "Boolean value specifying whether the " + 31 | "operation is supported.", 32 | mutability = AttributeDefinition.Mutability.READ_ONLY, 33 | isRequired = true) 34 | private final boolean supported; 35 | 36 | /** 37 | * Create a new complex type that specifies PATCH configuration options. 38 | * 39 | * @param supported Boolean value specifying whether the operation is 40 | * supported. 41 | */ 42 | @JsonCreator 43 | public PatchConfig(@JsonProperty(value = "supported", required = true) 44 | final boolean supported) 45 | { 46 | this.supported = supported; 47 | } 48 | 49 | /** 50 | * Retrieves the boolean value specifying whether the operation is 51 | * supported. 52 | * 53 | * @return {@code true} if the operation is supported or {@code false} 54 | * otherwise. 55 | */ 56 | public boolean isSupported() 57 | { 58 | return supported; 59 | } 60 | 61 | /** 62 | * Indicates whether the provided object is equal to this PATCH configuration. 63 | * 64 | * @param o The object to compare. 65 | * @return {@code true} if the provided object is equal to this PATCH 66 | * configuration, or {@code false} if not. 67 | */ 68 | @Override 69 | public boolean equals(@Nullable final Object o) 70 | { 71 | if (this == o) 72 | { 73 | return true; 74 | } 75 | if (o == null || getClass() != o.getClass()) 76 | { 77 | return false; 78 | } 79 | 80 | PatchConfig that = (PatchConfig) o; 81 | return supported == that.supported; 82 | } 83 | 84 | /** 85 | * Retrieves a hash code for this PATCH configuration. 86 | * 87 | * @return A hash code for this PATCH configuration. 88 | */ 89 | @Override 90 | public int hashCode() 91 | { 92 | return (supported ? 1 : 0); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/types/SortConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common.types; 19 | 20 | import com.fasterxml.jackson.annotation.JsonCreator; 21 | import com.fasterxml.jackson.annotation.JsonProperty; 22 | import com.unboundid.scim2.common.annotations.Attribute; 23 | import com.unboundid.scim2.common.annotations.Nullable; 24 | 25 | /** 26 | * A complex type that specifies Sort configuration options. 27 | */ 28 | public class SortConfig 29 | { 30 | @Attribute(description = "Boolean value specifying whether the " + 31 | "operation is supported.", 32 | mutability = AttributeDefinition.Mutability.READ_ONLY, 33 | isRequired = true) 34 | private final boolean supported; 35 | 36 | /** 37 | * Create a new complex type that specifies Sort configuration options. 38 | * 39 | * @param supported Boolean value specifying whether the operation is 40 | * supported 41 | */ 42 | @JsonCreator 43 | public SortConfig(@JsonProperty(value = "supported", required = true) 44 | final boolean supported) 45 | { 46 | this.supported = supported; 47 | } 48 | 49 | /** 50 | * Retrieves the boolean value specifying whether the operation is 51 | * supported. 52 | * 53 | * @return {@code true} if the operation is supported or {@code false} 54 | * otherwise. 55 | */ 56 | public boolean isSupported() 57 | { 58 | return supported; 59 | } 60 | 61 | /** 62 | * Indicates whether the provided object is equal to this sort configuration. 63 | * 64 | * @param o The object to compare. 65 | * @return {@code true} if the provided object is equal to this sort 66 | * configuration, or {@code false} if not. 67 | */ 68 | @Override 69 | public boolean equals(@Nullable final Object o) 70 | { 71 | if (this == o) 72 | { 73 | return true; 74 | } 75 | if (o == null || getClass() != o.getClass()) 76 | { 77 | return false; 78 | } 79 | 80 | SortConfig that = (SortConfig) o; 81 | return supported == that.supported; 82 | } 83 | 84 | /** 85 | * Retrieves a hash code for this sort configuration. 86 | * 87 | * @return A hash code for this sort configuration. 88 | */ 89 | @Override 90 | public int hashCode() 91 | { 92 | return (supported ? 1 : 0); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/types/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /** 19 | * Classes representing core SCIM 2 types. 20 | */ 21 | 22 | package com.unboundid.scim2.common.types; 23 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/utils/CalendarDeserializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | package com.unboundid.scim2.common.utils; 18 | 19 | import com.fasterxml.jackson.core.JsonParser; 20 | import com.fasterxml.jackson.core.JsonProcessingException; 21 | import com.fasterxml.jackson.databind.DeserializationContext; 22 | import com.fasterxml.jackson.databind.JsonDeserializer; 23 | import com.fasterxml.jackson.databind.exc.InvalidFormatException; 24 | import com.unboundid.scim2.common.annotations.NotNull; 25 | import com.unboundid.scim2.common.annotations.Nullable; 26 | 27 | import java.io.IOException; 28 | import java.util.Calendar; 29 | 30 | /** 31 | * Deserializes SCIM 2 DateTime values to {@link Calendar} objects. 32 | */ 33 | public class CalendarDeserializer extends JsonDeserializer 34 | { 35 | /** 36 | * {@inheritDoc} 37 | */ 38 | @Override 39 | @NotNull 40 | public Calendar deserialize(@NotNull final JsonParser jp, 41 | @Nullable final DeserializationContext ctxt) 42 | throws IOException, JsonProcessingException 43 | { 44 | String dateStr = jp.getText(); 45 | try 46 | { 47 | return DateTimeUtils.parse(dateStr); 48 | } 49 | catch (IllegalArgumentException e) 50 | { 51 | throw new InvalidFormatException(jp, "unable to deserialize value", 52 | dateStr, Calendar.class); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/utils/CalendarSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | package com.unboundid.scim2.common.utils; 18 | 19 | import com.fasterxml.jackson.core.JsonGenerator; 20 | import com.fasterxml.jackson.databind.JsonSerializer; 21 | import com.fasterxml.jackson.databind.SerializerProvider; 22 | import com.unboundid.scim2.common.annotations.NotNull; 23 | import com.unboundid.scim2.common.annotations.Nullable; 24 | 25 | import java.io.IOException; 26 | import java.util.Calendar; 27 | 28 | /** 29 | * Serializes a {@link Calendar} object to a SCIM 2 DateTime string. 30 | */ 31 | public class CalendarSerializer extends JsonSerializer 32 | { 33 | /** 34 | * {@inheritDoc} 35 | */ 36 | @Override 37 | public void serialize(@NotNull final Calendar value, 38 | @NotNull final JsonGenerator jgen, 39 | @Nullable final SerializerProvider serializers) 40 | throws IOException 41 | { 42 | jgen.writeString(DateTimeUtils.format(value)); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/utils/DateDeserializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | package com.unboundid.scim2.common.utils; 18 | 19 | import com.fasterxml.jackson.core.JsonParser; 20 | import com.fasterxml.jackson.core.JsonProcessingException; 21 | import com.fasterxml.jackson.databind.DeserializationContext; 22 | import com.fasterxml.jackson.databind.JsonDeserializer; 23 | import com.fasterxml.jackson.databind.exc.InvalidFormatException; 24 | import com.unboundid.scim2.common.annotations.NotNull; 25 | import com.unboundid.scim2.common.annotations.Nullable; 26 | 27 | import java.io.IOException; 28 | import java.util.Date; 29 | 30 | /** 31 | * Deserializes SCIM 2 DateTime values to {@link Date} objects. 32 | */ 33 | public class DateDeserializer extends JsonDeserializer 34 | { 35 | /** 36 | * {@inheritDoc} 37 | */ 38 | @Override 39 | @NotNull 40 | public Date deserialize(@NotNull final JsonParser jp, 41 | @Nullable final DeserializationContext ctxt) 42 | throws IOException, JsonProcessingException 43 | { 44 | String dateStr = jp.getText(); 45 | try 46 | { 47 | return DateTimeUtils.parse(dateStr).getTime(); 48 | } 49 | catch (IllegalArgumentException e) 50 | { 51 | throw new InvalidFormatException(jp, "unable to deserialize value", 52 | dateStr, Date.class); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/utils/DateSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | package com.unboundid.scim2.common.utils; 18 | 19 | import com.fasterxml.jackson.core.JsonGenerator; 20 | import com.fasterxml.jackson.databind.JsonSerializer; 21 | import com.fasterxml.jackson.databind.SerializerProvider; 22 | import com.unboundid.scim2.common.annotations.NotNull; 23 | import com.unboundid.scim2.common.annotations.Nullable; 24 | 25 | import java.io.IOException; 26 | import java.util.Date; 27 | 28 | /** 29 | * Serializes a {@link Date} object to a SCIM 2 DateTime string. 30 | */ 31 | public class DateSerializer extends JsonSerializer 32 | { 33 | /** 34 | * {@inheritDoc} 35 | */ 36 | @Override 37 | public void serialize(@NotNull final Date value, 38 | @NotNull final JsonGenerator jgen, 39 | @Nullable final SerializerProvider serializers) 40 | throws IOException 41 | { 42 | jgen.writeString(DateTimeUtils.format(value)); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/utils/DateTimeUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | package com.unboundid.scim2.common.utils; 18 | 19 | import com.unboundid.scim2.common.annotations.NotNull; 20 | import jakarta.xml.bind.DatatypeConverter; 21 | import java.util.Calendar; 22 | import java.util.Date; 23 | import java.util.TimeZone; 24 | 25 | /** 26 | * Utility methods for handling SCIM 2 DateTime values. The SCIM 2 DateTime 27 | * type is defined as a valid xsd:dateTime in RFC 7643, section 2.3.5. 28 | */ 29 | public final class DateTimeUtils 30 | { 31 | @NotNull 32 | private static final TimeZone DEFAULT_TIME_ZONE = TimeZone.getTimeZone("UTC"); 33 | 34 | /** 35 | * Formats a {@link Date} value as a SCIM 2 DateTime string. 36 | * 37 | * @param date A Date value. 38 | * @return The value as a SCIM 2 DateTime string. 39 | */ 40 | @NotNull 41 | public static String format(@NotNull final Date date) 42 | { 43 | return format(date, DEFAULT_TIME_ZONE); 44 | } 45 | 46 | /** 47 | * Formats a {@link Date} value as a SCIM 2 DateTime string. 48 | * 49 | * @param date A Date value. 50 | * @param timeZone The time zone. 51 | * @return The value as a SCIM 2 DateTime string. 52 | */ 53 | @NotNull 54 | public static String format(@NotNull final Date date, 55 | @NotNull final TimeZone timeZone) 56 | { 57 | Calendar calendar = Calendar.getInstance(timeZone); 58 | calendar.setTime(date); 59 | return format(calendar); 60 | } 61 | 62 | /** 63 | * Formats a {@link Calendar} value as a SCIM 2 DateTime string. 64 | * 65 | * @param calendar A Calendar value. 66 | * @return The value as a SCIM 2 DateTime string. 67 | */ 68 | @NotNull 69 | public static String format(@NotNull final Calendar calendar) 70 | { 71 | return DatatypeConverter.printDateTime(calendar); 72 | } 73 | 74 | /** 75 | * Converts a SCIM 2 DateTime string to a {@link Calendar}. 76 | * 77 | * @param dateStr A SCIM 2 DateTime string. 78 | * @return The DateTime string as a Calendar value. 79 | * @throws IllegalArgumentException if the string cannot be parsed as an 80 | * xsd:dateTime value. 81 | */ 82 | @NotNull 83 | public static Calendar parse(@NotNull final String dateStr) 84 | throws IllegalArgumentException 85 | { 86 | return DatatypeConverter.parseDateTime(dateStr); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/utils/GenericScimObjectDeserializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common.utils; 19 | 20 | import com.fasterxml.jackson.core.JsonParser; 21 | import com.fasterxml.jackson.databind.DeserializationContext; 22 | import com.fasterxml.jackson.databind.JsonDeserializer; 23 | import com.fasterxml.jackson.databind.node.ObjectNode; 24 | import com.unboundid.scim2.common.GenericScimResource; 25 | import com.unboundid.scim2.common.annotations.NotNull; 26 | import com.unboundid.scim2.common.annotations.Nullable; 27 | 28 | import java.io.IOException; 29 | 30 | /** 31 | * Deserializer for {@link GenericScimResource}. 32 | */ 33 | public class GenericScimObjectDeserializer 34 | extends JsonDeserializer 35 | { 36 | /** 37 | * {@inheritDoc} 38 | */ 39 | @Override 40 | @NotNull 41 | public GenericScimResource deserialize(@NotNull final JsonParser jp, 42 | @Nullable final DeserializationContext ctxt) 43 | throws IOException 44 | { 45 | ObjectNode objectNode = JsonUtils.getObjectReader().readTree(jp); 46 | return new GenericScimResource(objectNode); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/utils/GenericScimObjectSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common.utils; 19 | 20 | import com.fasterxml.jackson.core.JsonGenerator; 21 | import com.fasterxml.jackson.databind.JsonSerializer; 22 | import com.fasterxml.jackson.databind.SerializerProvider; 23 | import com.unboundid.scim2.common.GenericScimResource; 24 | import com.unboundid.scim2.common.annotations.NotNull; 25 | import com.unboundid.scim2.common.annotations.Nullable; 26 | 27 | import java.io.IOException; 28 | 29 | /** 30 | * Serializer for {@link GenericScimResource}. 31 | */ 32 | public class GenericScimObjectSerializer 33 | extends JsonSerializer 34 | { 35 | /** 36 | * {@inheritDoc} 37 | */ 38 | @Override 39 | public void serialize(@NotNull final GenericScimResource value, 40 | @NotNull final JsonGenerator jgen, 41 | @Nullable final SerializerProvider provider) 42 | throws IOException 43 | { 44 | JsonUtils.getObjectWriter().writeValue(jgen, value.getObjectNode()); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/utils/JsonRefBeanSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common.utils; 19 | 20 | import com.fasterxml.jackson.core.JsonGenerator; 21 | import com.fasterxml.jackson.databind.JsonSerializer; 22 | import com.fasterxml.jackson.databind.SerializerProvider; 23 | import com.unboundid.scim2.common.annotations.NotNull; 24 | import com.unboundid.scim2.common.types.JsonReference; 25 | 26 | import java.beans.IntrospectionException; 27 | import java.beans.PropertyDescriptor; 28 | import java.io.IOException; 29 | import java.lang.reflect.Field; 30 | import java.util.Collection; 31 | 32 | /** 33 | * Serializes classes that are beans, but the underlying structure holding 34 | * the attribute values is a JsonReference object. This will preserve those 35 | * values, so that if a value was explicitly set to null, we will know that, 36 | * but if not, we will know it was never set. During serialization, we will 37 | * serialize explicit {@code null} values, but not uninitialized values. 38 | */ 39 | public class JsonRefBeanSerializer extends JsonSerializer 40 | { 41 | /** 42 | * {@inheritDoc} 43 | */ 44 | @Override 45 | public void serialize(@NotNull final Object value, 46 | @NotNull final JsonGenerator gen, 47 | @NotNull final SerializerProvider serializers) 48 | throws IOException 49 | { 50 | Class clazz = value.getClass(); 51 | try 52 | { 53 | gen.writeStartObject(); 54 | Collection propertyDescriptors = 55 | SchemaUtils.getPropertyDescriptors(clazz); 56 | for (PropertyDescriptor propertyDescriptor : propertyDescriptors) 57 | { 58 | Field field = SchemaUtils.findField( 59 | clazz, propertyDescriptor.getName()); 60 | if (field == null) 61 | { 62 | continue; 63 | } 64 | field.setAccessible(true); 65 | Object obj = field.get(value); 66 | if (obj instanceof JsonReference reference) 67 | { 68 | if (reference.isSet()) 69 | { 70 | gen.writeFieldName(field.getName()); 71 | serializers.defaultSerializeValue(reference.getObj(), gen); 72 | } 73 | } 74 | } 75 | gen.writeEndObject(); 76 | } 77 | catch (IntrospectionException | IllegalAccessException e) 78 | { 79 | // This is not expected to occur. 80 | Debug.debugException(e); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/utils/ParserOptions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common.utils; 19 | 20 | import com.unboundid.scim2.common.annotations.NotNull; 21 | 22 | import java.util.Collections; 23 | import java.util.HashSet; 24 | import java.util.Set; 25 | 26 | /** 27 | * Configuration class for nonstandard parser options. 28 | *

29 | * NOTE: SCIM server implementations are not guaranteed to support a given 30 | * option. 31 | */ 32 | public class ParserOptions 33 | { 34 | @NotNull 35 | private Set extendedAttributeNameCharacters = new HashSet<>(); 36 | 37 | 38 | /** 39 | * Add characters (e.g., semicolons) to the set of extended naming characters 40 | * currently allowed within attribute names. 41 | * 42 | * @param extendedChars The extended characters to be added. 43 | * 44 | * @return The updated {@code ParserOptions}. 45 | */ 46 | @NotNull 47 | public ParserOptions addExtendedAttributeNameCharacters( 48 | @NotNull final Character... extendedChars) 49 | { 50 | Collections.addAll(this.extendedAttributeNameCharacters, extendedChars); 51 | return this; 52 | } 53 | 54 | /** 55 | * Clear the set of extended naming characters currently allowed within 56 | * attribute names, so that only standard attribute naming characters are 57 | * allowed. 58 | * 59 | * @return The updated {@code ParserOptions}. 60 | */ 61 | @NotNull 62 | public ParserOptions clearExtendedAttributeNameCharacters() 63 | { 64 | this.extendedAttributeNameCharacters.clear(); 65 | return this; 66 | } 67 | 68 | /** 69 | * Get the set of extended naming characters currently allowed within 70 | * attribute names. 71 | * 72 | * @return The extended set. By default this will be empty, indicating that 73 | * only standard attribute naming characters are allowed. 74 | */ 75 | @NotNull 76 | public Set getExtendedAttributeNameCharacters() 77 | { 78 | return Collections.unmodifiableSet(extendedAttributeNameCharacters); 79 | } 80 | 81 | /** 82 | * Indicate whether a given character is in the set of extended naming 83 | * characters currently allowed within attribute names. 84 | * 85 | * @param c The desired character. 86 | * @return {@code true} if the character is in the extended set. 87 | */ 88 | public boolean isExtendedAttributeNameCharacter(final char c) 89 | { 90 | return extendedAttributeNameCharacters.contains(c); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/utils/ScimFilterJsonParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | 19 | package com.unboundid.scim2.common.utils; 20 | 21 | import com.fasterxml.jackson.core.ObjectCodec; 22 | import com.fasterxml.jackson.core.io.IOContext; 23 | import com.fasterxml.jackson.core.json.JsonReadContext; 24 | import com.fasterxml.jackson.core.json.ReaderBasedJsonParser; 25 | import com.fasterxml.jackson.core.sym.CharsToNameCanonicalizer; 26 | import com.unboundid.scim2.common.annotations.NotNull; 27 | import com.unboundid.scim2.common.annotations.Nullable; 28 | 29 | import java.io.Reader; 30 | 31 | /** 32 | * A parser that can be used for parsing JSON objects contained 33 | * within a SCIM filter specification. 34 | */ 35 | public class ScimFilterJsonParser extends ReaderBasedJsonParser 36 | { 37 | /** 38 | * Constructor. 39 | * 40 | * @param ctxt see superclass 41 | * @param features see superclass 42 | * @param r see superclass 43 | * @param codec see superclass 44 | * @param st see superclass 45 | */ 46 | public ScimFilterJsonParser( 47 | @NotNull final IOContext ctxt, 48 | final int features, 49 | @Nullable final Reader r, 50 | @Nullable final ObjectCodec codec, 51 | @NotNull final CharsToNameCanonicalizer st) 52 | { 53 | super(ctxt, features, r, codec, st); 54 | // By default, the JSON read context is set to JsonStreamContext.TYPE_ROOT, 55 | // which will require whitespace after any unquoted token (e.g., a number). 56 | // We don't want this restriction when parsing a SCIM filter, so set the 57 | // context type to -1, which is effectively "none". 58 | this._parsingContext = new JsonReadContext(null, 0, null, -1, 1, 0); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/utils/ScimJsonFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | 19 | package com.unboundid.scim2.common.utils; 20 | 21 | import com.fasterxml.jackson.core.ErrorReportConfiguration; 22 | import com.fasterxml.jackson.core.JsonFactory; 23 | import com.fasterxml.jackson.core.JsonParser; 24 | import com.fasterxml.jackson.core.ObjectCodec; 25 | import com.fasterxml.jackson.core.io.ContentReference; 26 | import com.fasterxml.jackson.core.io.IOContext; 27 | import com.unboundid.scim2.common.annotations.NotNull; 28 | import com.unboundid.scim2.common.annotations.Nullable; 29 | 30 | import java.io.IOException; 31 | import java.io.Reader; 32 | 33 | 34 | /** 35 | * Custom JsonFactory implementation for SCIM. 36 | */ 37 | public class ScimJsonFactory extends JsonFactory 38 | { 39 | /** 40 | * Creates a new SCIM-compatible JsonFactory instance. 41 | */ 42 | public ScimJsonFactory() 43 | { 44 | super(); 45 | } 46 | 47 | /** 48 | * A constructor used when copying an existing SCIM JsonFactory instance. 49 | * 50 | * @param sourceFactory The original ScimJsonFactory. 51 | * @param codec The codec that defines the way that objects should 52 | * be serialized and deserialized. This may be 53 | * {@code null}. 54 | */ 55 | protected ScimJsonFactory(@NotNull final ScimJsonFactory sourceFactory, 56 | @Nullable final ObjectCodec codec) 57 | { 58 | super(sourceFactory, codec); 59 | } 60 | 61 | /** 62 | * Create a parser that can be used for parsing JSON objects contained 63 | * within a SCIM filter specification. 64 | * 65 | * @param r Reader to use for reading JSON content to parse 66 | * @return ScimFilterJsonParser object 67 | * @throws IOException on parse error 68 | */ 69 | @NotNull 70 | JsonParser createScimFilterParser(@NotNull final Reader r) 71 | throws IOException 72 | { 73 | ContentReference reference = ContentReference.construct(true, r, 74 | ErrorReportConfiguration.defaults()); 75 | IOContext ctxt = _createContext(reference, false); 76 | return new ScimFilterJsonParser(ctxt, _parserFeatures, r, _objectCodec, 77 | _rootCharSymbols.makeChild()); 78 | } 79 | 80 | /** 81 | * Provides another instance of this factory object. 82 | * 83 | * @return A new ScimJsonFactory instance. 84 | */ 85 | @Override 86 | @NotNull 87 | public ScimJsonFactory copy() 88 | { 89 | return new ScimJsonFactory(this, _objectCodec); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/utils/ScimJsonNodeFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common.utils; 19 | 20 | import com.fasterxml.jackson.databind.node.JsonNodeFactory; 21 | import com.fasterxml.jackson.databind.node.ObjectNode; 22 | import com.unboundid.scim2.common.annotations.NotNull; 23 | 24 | /** 25 | * This class represents a Jackson {@link JsonNodeFactory} implementation that 26 | * treats JSON attribute names as case-insensitive. 27 | */ 28 | public class ScimJsonNodeFactory extends JsonNodeFactory 29 | { 30 | /** 31 | * {@inheritDoc} 32 | */ 33 | @Override 34 | @NotNull 35 | public ObjectNode objectNode() 36 | { 37 | return new CaseIgnoreObjectNode(this); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/utils/StatusDeserializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common.utils; 19 | 20 | import com.fasterxml.jackson.core.JsonParser; 21 | import com.fasterxml.jackson.core.JsonProcessingException; 22 | import com.fasterxml.jackson.databind.DeserializationContext; 23 | import com.fasterxml.jackson.databind.JsonDeserializer; 24 | import com.unboundid.scim2.common.annotations.NotNull; 25 | import com.unboundid.scim2.common.annotations.Nullable; 26 | 27 | import java.io.IOException; 28 | 29 | /** 30 | * Deserializes the status field of 31 | * {@link com.unboundid.scim2.common.messages.ErrorResponse} to an Integer. 32 | */ 33 | public class StatusDeserializer extends JsonDeserializer 34 | { 35 | /** 36 | * {@inheritDoc} 37 | */ 38 | @Override 39 | @NotNull 40 | public Integer deserialize(@NotNull final JsonParser jp, 41 | @Nullable final DeserializationContext ctxt) 42 | throws IOException, JsonProcessingException 43 | { 44 | return jp.readValueAs(Integer.class); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/utils/StatusSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common.utils; 19 | 20 | import com.fasterxml.jackson.core.JsonGenerator; 21 | import com.fasterxml.jackson.core.JsonProcessingException; 22 | import com.fasterxml.jackson.databind.JsonSerializer; 23 | import com.fasterxml.jackson.databind.SerializerProvider; 24 | import com.unboundid.scim2.common.annotations.NotNull; 25 | import com.unboundid.scim2.common.annotations.Nullable; 26 | 27 | import java.io.IOException; 28 | 29 | /** 30 | * Serializes {@link com.unboundid.scim2.common.messages.ErrorResponse}'s 31 | * status field to a String. 32 | */ 33 | public class StatusSerializer extends JsonSerializer 34 | { 35 | /** 36 | * {@inheritDoc} 37 | */ 38 | @Override 39 | public void serialize(@Nullable final Integer value, 40 | @NotNull final JsonGenerator jgen, 41 | @Nullable final SerializerProvider serializers) 42 | throws IOException, JsonProcessingException 43 | { 44 | jgen.writeString(String.valueOf(value)); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/java/com/unboundid/scim2/common/utils/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /** 19 | * Utility classes, including classes for working with JSON objects. 20 | */ 21 | 22 | package com.unboundid.scim2.common.utils; 23 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/main/javadoc/overview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | UnboundID SCIM 2 SDK Common 5 | 6 | 7 | 8 |

This package contains shared classes that may be used by both SCIM 2 clients 9 | and SCIM 2 service providers. These include:

10 | 11 |
    12 |
  • The {@link com.unboundid.scim2.common.BaseScimResource} class, from 13 | which model classes representing SCIM resource types can be 14 | derived.
  • 15 |
  • The {@link com.unboundid.scim2.common.GenericScimResource} class, which 16 | provides a general-purpose interface for accessing attributes of any 17 | SCIM resource.
  • 18 |
  • The {@link com.unboundid.scim2.common.Path} class, which is used to 19 | specify the targets of SCIM PATCH operations or to specify attributes 20 | to retrieve or modify when manipulating resources through the 21 | {@link com.unboundid.scim2.common.GenericScimResource} class.
  • 22 |
  • The {@link com.unboundid.scim2.common.filters.Filter} class and related 23 | classes, used to build SCIM 2 query filters.
  • 24 |
  • Classes representing SCIM 2 messages, including error responses, search 25 | responses, and PATCH operations.
  • 26 |
  • Exception classes representing HTTP responses from SCIM 2 service 27 | providers.
  • 28 |
29 | 30 | 31 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/test/java/com/unboundid/scim2/common/MetaTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common; 19 | 20 | import com.unboundid.scim2.common.types.Meta; 21 | import org.testng.annotations.Test; 22 | 23 | import java.net.URI; 24 | import java.util.Calendar; 25 | import java.util.TimeZone; 26 | 27 | import static org.assertj.core.api.Assertions.assertThat; 28 | 29 | 30 | /** 31 | * Tests for the {@link Meta} class. 32 | */ 33 | public class MetaTest 34 | { 35 | /** 36 | * Tests that a Meta object can be created with the builder pattern. 37 | */ 38 | @Test 39 | public void testBuilderPattern() throws Exception 40 | { 41 | final Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); 42 | calendar.set(1970, Calendar.JANUARY, 1, 11, 0); 43 | 44 | // The class-level Javadoc of the Meta class contains an example JSON. 45 | // These values are based on the ones from that example. 46 | Meta meta = new Meta() 47 | .setResourceType("User") 48 | .setCreated(calendar) 49 | .setLastModified(calendar) 50 | .setLocation(new URI("https://example.com/v2/Users/fa1afe1")) 51 | .setVersion("W/\"e180ee84f0671b1\""); 52 | 53 | assertThat(meta.getResourceType()).isEqualTo("User"); 54 | assertThat(meta.getCreated()).isEqualTo(calendar); 55 | assertThat(meta.getLastModified()).isEqualTo(calendar); 56 | assertThat(meta.getLocation()).isNotNull(); 57 | assertThat(meta.getLocation().toString()) 58 | .isEqualTo("https://example.com/v2/Users/fa1afe1"); 59 | assertThat(meta.getVersion()).isEqualTo("W/\"e180ee84f0671b1\""); 60 | } 61 | 62 | /** 63 | * Ensures that it is possible to extend the Meta class. 64 | */ 65 | @Test 66 | public void testExtendable() 67 | { 68 | // Define a new subclass. 69 | class CustomMeta extends Meta 70 | { 71 | public String customField; 72 | } 73 | 74 | // Fields defined on the subclass and parent class should be accessible. 75 | CustomMeta object = new CustomMeta(); 76 | object.setResourceType("Custom"); 77 | object.customField = "present"; 78 | 79 | // Ensure the values were set properly. 80 | assertThat(object.getResourceType()).isEqualTo("Custom"); 81 | assertThat(object.customField).isEqualTo("present"); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/test/java/com/unboundid/scim2/common/ParserOptionsTestCase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common; 19 | 20 | import static org.testng.Assert.assertEquals; 21 | import static org.testng.Assert.assertFalse; 22 | import static org.testng.Assert.assertTrue; 23 | import static org.testng.Assert.fail; 24 | 25 | import org.testng.annotations.Test; 26 | 27 | import com.unboundid.scim2.common.exceptions.BadRequestException; 28 | import com.unboundid.scim2.common.filters.Filter; 29 | import com.unboundid.scim2.common.utils.Parser; 30 | 31 | 32 | /** 33 | * Test coverage for using {@code ParserOptions} with {@code Parser}. 34 | */ 35 | public class ParserOptionsTestCase 36 | { 37 | 38 | /** 39 | * Tests {@code ParserOptions} with an extended attribute name character. 40 | * 41 | * @throws Exception If the test fails. 42 | */ 43 | @Test 44 | public void testAllowSemicolons() 45 | throws Exception 46 | { 47 | String attributeWithSemicolon = "attribute;x-tag"; 48 | String filterString = attributeWithSemicolon + " eq 123"; 49 | 50 | // Verify filter is rejected by default 51 | assertFalse( 52 | Parser.getOptions().getExtendedAttributeNameCharacters().contains(';')); 53 | try 54 | { 55 | Parser.parseFilter(filterString); 56 | fail("Parser should have rejected '" + filterString + "'"); 57 | } 58 | catch (BadRequestException ex) 59 | { 60 | assertTrue( 61 | ex.getMessage().startsWith("Unexpected character ';' at position 9")); 62 | } 63 | 64 | // Verify filter is permitted after we specify the option. 65 | Parser.getOptions().addExtendedAttributeNameCharacters(';'); 66 | assertTrue( 67 | Parser.getOptions().getExtendedAttributeNameCharacters().contains(';')); 68 | 69 | Filter filter = Parser.parseFilter(filterString); 70 | assertEquals(filter.getAttributePath().toString(), attributeWithSemicolon); 71 | assertEquals(filter.getFilterType().toString(), "eq"); 72 | assertEquals(filter.getComparisonValue().toString(), "123"); 73 | 74 | // Verify attribute is rejected after we remove the option. 75 | Parser.getOptions().clearExtendedAttributeNameCharacters(); 76 | assertFalse( 77 | Parser.getOptions().getExtendedAttributeNameCharacters().contains(';')); 78 | try 79 | { 80 | Parser.parseFilter(filterString); 81 | fail("Parser should have rejected '" + filterString + "'"); 82 | } 83 | catch (BadRequestException ex) 84 | { 85 | assertTrue( 86 | ex.getMessage().startsWith("Unexpected character ';' at position 9")); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/test/java/com/unboundid/scim2/common/PatchRequestTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common; 19 | 20 | import com.fasterxml.jackson.databind.node.TextNode; 21 | import com.unboundid.scim2.common.messages.PatchOperation; 22 | import com.unboundid.scim2.common.messages.PatchRequest; 23 | import org.testng.annotations.Test; 24 | 25 | import java.util.Arrays; 26 | import java.util.Collections; 27 | 28 | import static org.testng.Assert.assertEquals; 29 | import static org.testng.Assert.assertThrows; 30 | 31 | public class PatchRequestTest 32 | { 33 | /** 34 | * Test the {@link PatchRequest} constructors. 35 | * 36 | * @throws Exception If an unexpected error occurs. 37 | */ 38 | @Test 39 | public void testConstructors() throws Exception 40 | { 41 | PatchRequest listRequest = new PatchRequest(Collections.singletonList( 42 | PatchOperation.add("nickName", TextNode.valueOf("G")) 43 | )); 44 | PatchRequest argsRequest = new PatchRequest( 45 | PatchOperation.add("nickName", TextNode.valueOf("G")) 46 | ); 47 | assertEquals(listRequest, argsRequest); 48 | 49 | listRequest = new PatchRequest(Arrays.asList( 50 | PatchOperation.add("displayName", TextNode.valueOf("myName")), 51 | PatchOperation.replace("displayName", TextNode.valueOf("yourName")) 52 | )); 53 | argsRequest = new PatchRequest( 54 | PatchOperation.add("displayName", TextNode.valueOf("myName")), 55 | PatchOperation.replace("displayName", TextNode.valueOf("yourName")) 56 | ); 57 | assertEquals(listRequest, argsRequest); 58 | 59 | // Providing a null operations list should not be permitted. 60 | assertThrows(NullPointerException.class, () -> new PatchRequest(null)); 61 | 62 | // The first parameter of the method should not accept null. 63 | assertThrows(NullPointerException.class, 64 | () -> new PatchRequest(null, PatchOperation.remove("invalid"))); 65 | 66 | // Null arguments in the varargs method should be ignored. 67 | PatchRequest singleOperation = new PatchRequest( 68 | PatchOperation.remove("password"), null, null 69 | ); 70 | assertEquals(singleOperation.getOperations().size(), 1); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/test/java/com/unboundid/scim2/common/schema/testobjects/TestObject1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common.schema.testobjects; 19 | 20 | import com.unboundid.scim2.common.annotations.Schema; 21 | 22 | @Schema(id="urn:id:junit", 23 | description = "description:TestObject1", name = "name:TestObject1") 24 | public class TestObject1 25 | { 26 | 27 | } 28 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/test/java/com/unboundid/scim2/common/schema/testobjects/TestObject3_a.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common.schema.testobjects; 19 | 20 | import com.unboundid.scim2.common.annotations.Attribute; 21 | import com.unboundid.scim2.common.BaseScimResource; 22 | 23 | /** 24 | * Class used by unit tests. 25 | */ 26 | public class TestObject3_a extends BaseScimResource 27 | { 28 | @Attribute(description = "description:stringField_3a") 29 | private String stringField_3a; 30 | 31 | /** 32 | * Getter for attribute in test class. 33 | * @return attribute value. 34 | */ 35 | public String getStringField_3a() 36 | { 37 | return stringField_3a; 38 | } 39 | 40 | /** 41 | * Setter for attribute in test class. 42 | * @param stringField_3a attribute value. 43 | */ 44 | public void setStringField_3a(String stringField_3a) 45 | { 46 | this.stringField_3a = stringField_3a; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/test/java/com/unboundid/scim2/common/schema/testobjects/TestObject3_b.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common.schema.testobjects; 19 | 20 | import com.unboundid.scim2.common.ScimMultiValuedObject; 21 | 22 | /** 23 | * Class used by unit tests. 24 | */ 25 | public class TestObject3_b extends ScimMultiValuedObject 26 | { 27 | } 28 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/test/java/com/unboundid/scim2/common/schema/testobjects/TestObject3_c.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common.schema.testobjects; 19 | 20 | import com.unboundid.scim2.common.ScimMultiValuedObject; 21 | 22 | /** 23 | * Class used by unit tests. 24 | */ 25 | public class TestObject3_c extends ScimMultiValuedObject 26 | { 27 | } 28 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/test/java/com/unboundid/scim2/common/schema/testobjects/TestObject3_d.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common.schema.testobjects; 19 | 20 | /** 21 | * Class used by unit tests. 22 | */ 23 | public class TestObject3_d 24 | { 25 | } 26 | -------------------------------------------------------------------------------- /scim2-sdk-common/src/test/java/com/unboundid/scim2/common/types/AuthenticationSchemeTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.common.types; 19 | 20 | import com.unboundid.scim2.common.utils.JsonUtils; 21 | import org.testng.Assert; 22 | import org.testng.annotations.Test; 23 | 24 | /** 25 | * Tests serialization and deserialization of AuthenticationScheme objects. 26 | */ 27 | @Test 28 | public class AuthenticationSchemeTest 29 | { 30 | private static final String AS_NAME = "name"; 31 | private static final String AS_DESC = "description"; 32 | private static final String AS_SPEC_URI = "http://localhost/specUri"; 33 | private static final String AS_DOC_URI = "http://localhost/documentationUri"; 34 | private static final String AS_TYPE = "type"; 35 | private static final String AS_PRIMARY = "true"; 36 | 37 | /** 38 | * Test the normal serialization case. 39 | * @throws Exception if an error occurs. 40 | */ 41 | @Test 42 | public void testSerializationAndDeserialization() throws Exception 43 | { 44 | String authSchemeString = "{\n" + 45 | " \"name\" : \"" + AS_NAME + "\",\n" + 46 | " \"description\" : \"" + AS_DESC + "\",\n" + 47 | " \"specUri\" : \"" + AS_SPEC_URI + "\",\n" + 48 | " \"documentationUri\" : \"" + AS_DOC_URI + "\",\n" + 49 | " \"type\" : \"" + AS_TYPE + "\",\n" + 50 | " \"primary\" : " + AS_PRIMARY + "\n" + 51 | " }"; 52 | 53 | AuthenticationScheme as = JsonUtils.getObjectReader().forType( 54 | AuthenticationScheme.class).readValue(authSchemeString); 55 | Assert.assertEquals(as.getName(), AS_NAME); 56 | Assert.assertEquals(as.getDescription(), AS_DESC); 57 | Assert.assertEquals(as.getSpecUri().toString(), AS_SPEC_URI); 58 | Assert.assertEquals(as.getDocumentationUri().toString(), AS_DOC_URI); 59 | Assert.assertEquals(as.getType(), AS_TYPE); 60 | Assert.assertEquals(as.isPrimary(), true); 61 | 62 | String serializedString = 63 | JsonUtils.getObjectWriter().writeValueAsString(as); 64 | AuthenticationScheme deserializedScheme = JsonUtils.getObjectReader(). 65 | forType(AuthenticationScheme.class).readValue(serializedString); 66 | Assert.assertEquals(as, deserializedScheme); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /scim2-sdk-server/src/main/java/com/unboundid/scim2/server/ListResponseStreamingOutput.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.server; 19 | 20 | import com.unboundid.scim2.common.ScimResource; 21 | 22 | import com.unboundid.scim2.common.annotations.NotNull; 23 | import jakarta.ws.rs.core.StreamingOutput; 24 | import java.io.IOException; 25 | import java.io.OutputStream; 26 | 27 | /** 28 | * Interface for streaming list/query results using the ListResponse container. 29 | */ 30 | public abstract class ListResponseStreamingOutput 31 | implements StreamingOutput 32 | { 33 | /** 34 | * Start streaming the contents of the list response. The list response will 35 | * be considered complete upon return; 36 | * 37 | * @param os The list response output stream used to stream back elements of 38 | * the list response. 39 | * @throws IOException if an error occurs while writing. 40 | */ 41 | public abstract void write(@NotNull ListResponseWriter os) 42 | throws IOException; 43 | 44 | 45 | /** 46 | * {@inheritDoc} 47 | */ 48 | public final void write(@NotNull final OutputStream os) 49 | throws IOException 50 | { 51 | ListResponseWriter handler = new ListResponseWriter<>(os); 52 | handler.startResponse(); 53 | write(handler); 54 | handler.endResponse(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /scim2-sdk-server/src/main/java/com/unboundid/scim2/server/PATCH.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.server; 19 | 20 | import jakarta.ws.rs.HttpMethod; 21 | import java.lang.annotation.ElementType; 22 | import java.lang.annotation.Retention; 23 | import java.lang.annotation.RetentionPolicy; 24 | import java.lang.annotation.Target; 25 | 26 | /** 27 | * Indicates that the annotated method responds to HTTP PATCH requests. 28 | */ 29 | @Target({ElementType.METHOD}) 30 | @Retention(RetentionPolicy.RUNTIME) 31 | @HttpMethod("PATCH") 32 | public @interface PATCH 33 | { 34 | } 35 | 36 | -------------------------------------------------------------------------------- /scim2-sdk-server/src/main/java/com/unboundid/scim2/server/annotations/ResourceType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.server.annotations; 19 | 20 | import com.unboundid.scim2.common.annotations.NotNull; 21 | 22 | import java.lang.annotation.ElementType; 23 | import java.lang.annotation.Retention; 24 | import java.lang.annotation.RetentionPolicy; 25 | import java.lang.annotation.Target; 26 | 27 | /** 28 | * Annotation for SCIM resource classes. 29 | */ 30 | @Target(value = ElementType.TYPE) 31 | @Retention(value = RetentionPolicy.RUNTIME) 32 | public @interface ResourceType 33 | { 34 | /** 35 | * The description for the object. 36 | * 37 | * @return The object's description. 38 | */ 39 | @NotNull 40 | String description(); 41 | 42 | /** 43 | * The name for the object. This is a human-readable name. 44 | * 45 | * @return The object's human-readable name. 46 | */ 47 | @NotNull 48 | String name(); 49 | 50 | /** 51 | * The primary/base resource class. 52 | * 53 | * @return The primary/base resource class. 54 | */ 55 | @NotNull 56 | Class schema(); 57 | 58 | /** 59 | * The required schema extension resource classes. 60 | * 61 | * @return The required schema extension resource classes. 62 | */ 63 | @NotNull 64 | Class[] requiredSchemaExtensions() default {}; 65 | 66 | /** 67 | * The optional schema extension resource classes. 68 | * 69 | * @return The optional schema extension resource classes. 70 | */ 71 | @NotNull 72 | Class[] optionalSchemaExtensions() default {}; 73 | 74 | /** 75 | * Whether this resource type and its associated schemas should be 76 | * discoverable using the SCIM 2 standard {@code /ResourceTypes} and 77 | * {@code /Schemas} endpoints. 78 | * 79 | * @return A flag indicating the discoverability of this resource type and 80 | * its associated schemas. 81 | */ 82 | boolean discoverable() default true; 83 | } 84 | -------------------------------------------------------------------------------- /scim2-sdk-server/src/main/java/com/unboundid/scim2/server/annotations/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /** 19 | * Annotation classes used by SCIM 2 service providers. 20 | */ 21 | 22 | package com.unboundid.scim2.server.annotations; 23 | -------------------------------------------------------------------------------- /scim2-sdk-server/src/main/java/com/unboundid/scim2/server/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /** 19 | * SCIM 2 service provider classes. 20 | */ 21 | 22 | package com.unboundid.scim2.server; 23 | -------------------------------------------------------------------------------- /scim2-sdk-server/src/main/java/com/unboundid/scim2/server/providers/DefaultContentTypeFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.server.providers; 19 | 20 | import com.unboundid.scim2.common.annotations.NotNull; 21 | import jakarta.annotation.Priority; 22 | import jakarta.ws.rs.HttpMethod; 23 | import jakarta.ws.rs.Priorities; 24 | import jakarta.ws.rs.container.ContainerRequestContext; 25 | import jakarta.ws.rs.container.ContainerRequestFilter; 26 | import jakarta.ws.rs.container.PreMatching; 27 | import jakarta.ws.rs.core.HttpHeaders; 28 | import jakarta.ws.rs.ext.Provider; 29 | import java.io.IOException; 30 | import java.util.Collections; 31 | 32 | import static com.unboundid.scim2.common.utils.ApiConstants.MEDIA_TYPE_SCIM; 33 | 34 | /** 35 | * A ContainerRequestFilter implementation to set the content type header of 36 | * POST, PUT, and PATCH requests to "application/scim+json" if the header is 37 | * missing. 38 | */ 39 | @Provider 40 | @PreMatching 41 | @Priority(Priorities.HEADER_DECORATOR) 42 | public class DefaultContentTypeFilter implements ContainerRequestFilter 43 | { 44 | /** 45 | * {@inheritDoc} 46 | */ 47 | public void filter(@NotNull final ContainerRequestContext requestContext) 48 | throws IOException 49 | { 50 | if ((requestContext.getMethod().equals(HttpMethod.POST) || 51 | requestContext.getMethod().equals(HttpMethod.PUT) || 52 | requestContext.getMethod().equals(HttpMethod.PATCH)) && 53 | requestContext.getMediaType() == null) 54 | { 55 | requestContext.getHeaders().put(HttpHeaders.CONTENT_TYPE, 56 | Collections.singletonList(MEDIA_TYPE_SCIM)); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /scim2-sdk-server/src/main/java/com/unboundid/scim2/server/providers/JsonProcessingExceptionMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.server.providers; 19 | 20 | import com.fasterxml.jackson.core.JsonParseException; 21 | import com.fasterxml.jackson.core.JsonProcessingException; 22 | import com.fasterxml.jackson.databind.JsonMappingException; 23 | import com.unboundid.scim2.common.annotations.NotNull; 24 | import com.unboundid.scim2.common.exceptions.BadRequestException; 25 | import com.unboundid.scim2.common.exceptions.ScimException; 26 | import com.unboundid.scim2.common.exceptions.ServerErrorException; 27 | import com.unboundid.scim2.common.messages.ErrorResponse; 28 | import com.unboundid.scim2.server.utils.ServerUtils; 29 | 30 | import jakarta.ws.rs.core.Context; 31 | import jakarta.ws.rs.core.HttpHeaders; 32 | import jakarta.ws.rs.core.Request; 33 | import jakarta.ws.rs.core.Response; 34 | import jakarta.ws.rs.ext.ExceptionMapper; 35 | import jakarta.ws.rs.ext.Provider; 36 | 37 | /** 38 | * A JAX-RS ExceptionMapper for to convert Jackson JsonProcessingException to 39 | * SCIM ErrorResponses. 40 | */ 41 | @Provider 42 | public class JsonProcessingExceptionMapper implements 43 | ExceptionMapper 44 | { 45 | @NotNull 46 | @Context 47 | private Request request; 48 | 49 | @NotNull 50 | @Context 51 | private HttpHeaders headers; 52 | 53 | /** 54 | * {@inheritDoc} 55 | */ 56 | @NotNull 57 | public Response toResponse(@NotNull final JsonProcessingException exception) 58 | { 59 | ErrorResponse errorResponse; 60 | if ((exception instanceof JsonParseException) || 61 | (exception instanceof JsonMappingException)) 62 | { 63 | StringBuilder builder = new StringBuilder(); 64 | builder.append("Unable to parse request: "); 65 | builder.append(exception.getOriginalMessage()); 66 | if (exception.getLocation() != null) 67 | { 68 | builder.append(" at line: "); 69 | builder.append(exception.getLocation().getLineNr()); 70 | builder.append(", column: "); 71 | builder.append(exception.getLocation().getColumnNr()); 72 | } 73 | errorResponse = 74 | BadRequestException.invalidSyntax(builder.toString()).getScimError(); 75 | } 76 | else 77 | { 78 | if (exception.getCause() != null && 79 | exception.getCause() instanceof ScimException scimException) 80 | { 81 | errorResponse = scimException.getScimError(); 82 | } 83 | else 84 | { 85 | errorResponse = 86 | new ServerErrorException(exception.getMessage()).getScimError(); 87 | } 88 | } 89 | 90 | return ServerUtils.setAcceptableType( 91 | Response.status(errorResponse.getStatus()).entity(errorResponse), 92 | headers.getAcceptableMediaTypes()).build(); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /scim2-sdk-server/src/main/java/com/unboundid/scim2/server/providers/RuntimeExceptionMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.server.providers; 19 | 20 | import com.unboundid.scim2.common.annotations.NotNull; 21 | import com.unboundid.scim2.common.exceptions.BadRequestException; 22 | import com.unboundid.scim2.common.messages.ErrorResponse; 23 | import com.unboundid.scim2.server.utils.ServerUtils; 24 | 25 | import jakarta.ws.rs.WebApplicationException; 26 | import jakarta.ws.rs.core.Context; 27 | import jakarta.ws.rs.core.HttpHeaders; 28 | import jakarta.ws.rs.core.NoContentException; 29 | import jakarta.ws.rs.core.Request; 30 | import jakarta.ws.rs.core.Response; 31 | import jakarta.ws.rs.ext.ExceptionMapper; 32 | import jakarta.ws.rs.ext.Provider; 33 | 34 | /** 35 | * A JAX-RS ExceptionMapper for to convert standard WebApplicationExceptions to 36 | * SCIM ErrorResponses. 37 | */ 38 | @Provider 39 | public class RuntimeExceptionMapper implements 40 | ExceptionMapper 41 | { 42 | @NotNull 43 | @Context 44 | private Request request; 45 | 46 | @NotNull 47 | @Context 48 | private HttpHeaders headers; 49 | 50 | /** 51 | * {@inheritDoc} 52 | */ 53 | @NotNull 54 | public Response toResponse(@NotNull final RuntimeException exception) 55 | { 56 | ErrorResponse errorResponse; 57 | 58 | if (exception instanceof WebApplicationException) 59 | { 60 | if (exception.getCause() != null && exception.getCause() 61 | instanceof NoContentException) 62 | { 63 | errorResponse = new ErrorResponse(400); 64 | errorResponse.setScimType(BadRequestException.INVALID_SYNTAX); 65 | errorResponse.setDetail("No content provided. A valid SCIM object " + 66 | "represented as a json document is required"); 67 | } 68 | else 69 | { 70 | errorResponse = new ErrorResponse( 71 | ((WebApplicationException) exception).getResponse().getStatus()); 72 | errorResponse.setDetail(exception.getMessage()); 73 | } 74 | } 75 | else 76 | { 77 | errorResponse = new ErrorResponse(500); 78 | errorResponse.setDetail(exception.toString()); 79 | } 80 | 81 | return ServerUtils.setAcceptableType( 82 | Response.status(errorResponse.getStatus()).entity(errorResponse), 83 | headers.getAcceptableMediaTypes()).build(); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /scim2-sdk-server/src/main/java/com/unboundid/scim2/server/providers/ScimExceptionMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.server.providers; 19 | 20 | import com.unboundid.scim2.common.annotations.NotNull; 21 | import com.unboundid.scim2.common.exceptions.ScimException; 22 | import com.unboundid.scim2.server.utils.ServerUtils; 23 | 24 | import jakarta.ws.rs.core.Context; 25 | import jakarta.ws.rs.core.HttpHeaders; 26 | import jakarta.ws.rs.core.Response; 27 | import jakarta.ws.rs.ext.ExceptionMapper; 28 | import jakarta.ws.rs.ext.Provider; 29 | 30 | /** 31 | * A JAX-RS ExceptionMapper for ScimExceptions. 32 | */ 33 | @Provider 34 | public class ScimExceptionMapper implements ExceptionMapper 35 | { 36 | @NotNull 37 | @Context 38 | private HttpHeaders headers; 39 | 40 | /** 41 | * {@inheritDoc} 42 | */ 43 | @NotNull 44 | public Response toResponse(@NotNull final ScimException throwable) 45 | { 46 | return ServerUtils.setAcceptableType( 47 | Response.status(throwable.getScimError().getStatus()). 48 | entity(throwable.getScimError()), 49 | headers.getAcceptableMediaTypes()).build(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /scim2-sdk-server/src/main/java/com/unboundid/scim2/server/providers/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /** 19 | * Request filters and exception mappers used by SCIM 2 service providers. 20 | */ 21 | 22 | package com.unboundid.scim2.server.providers; 23 | -------------------------------------------------------------------------------- /scim2-sdk-server/src/main/java/com/unboundid/scim2/server/resources/AbstractServiceProviderConfigEndpoint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.server.resources; 19 | 20 | import com.unboundid.scim2.common.GenericScimResource; 21 | import com.unboundid.scim2.common.annotations.NotNull; 22 | import com.unboundid.scim2.common.types.ServiceProviderConfigResource; 23 | import com.unboundid.scim2.common.exceptions.ScimException; 24 | import com.unboundid.scim2.server.annotations.ResourceType; 25 | import com.unboundid.scim2.server.utils.ResourcePreparer; 26 | import com.unboundid.scim2.server.utils.ResourceTypeDefinition; 27 | 28 | import jakarta.ws.rs.GET; 29 | import jakarta.ws.rs.Path; 30 | import jakarta.ws.rs.Produces; 31 | import jakarta.ws.rs.core.Context; 32 | import jakarta.ws.rs.core.MediaType; 33 | import jakarta.ws.rs.core.UriInfo; 34 | 35 | import static com.unboundid.scim2.common.utils.ApiConstants.MEDIA_TYPE_SCIM; 36 | 37 | /** 38 | * An abstract JAX-RS resource class for servicing the Service Provider Config 39 | * endpoint. 40 | */ 41 | @ResourceType( 42 | description = "SCIM 2.0 Service Provider Config", 43 | name = "ServiceProviderConfig", 44 | schema = ServiceProviderConfigResource.class, 45 | discoverable = false) 46 | @Path("ServiceProviderConfig") 47 | public abstract class AbstractServiceProviderConfigEndpoint 48 | { 49 | @NotNull 50 | private static final ResourceTypeDefinition RESOURCE_TYPE_DEFINITION = 51 | ResourceTypeDefinition.fromJaxRsResource( 52 | AbstractServiceProviderConfigEndpoint.class); 53 | 54 | /** 55 | * Service request to retrieve the Service Provider Config. 56 | * 57 | * @param uriInfo UriInfo of the request. 58 | * @return The Service Provider Config. 59 | * @throws ScimException if an error occurs. 60 | */ 61 | @GET 62 | @Produces({MEDIA_TYPE_SCIM, MediaType.APPLICATION_JSON}) 63 | @NotNull 64 | public GenericScimResource get(@NotNull @Context final UriInfo uriInfo) 65 | throws ScimException 66 | { 67 | ServiceProviderConfigResource serviceProviderConfig = 68 | getServiceProviderConfig(); 69 | ResourcePreparer resourcePreparer = 70 | new ResourcePreparer<>(RESOURCE_TYPE_DEFINITION, uriInfo); 71 | GenericScimResource resource = 72 | serviceProviderConfig.asGenericScimResource(); 73 | resourcePreparer.setResourceTypeAndLocation(resource); 74 | return resource; 75 | } 76 | 77 | /** 78 | * Retrieve the current service provider config. 79 | * 80 | * @return The current service provider config. 81 | * @throws ScimException if an error occurs. 82 | */ 83 | @NotNull 84 | public abstract ServiceProviderConfigResource getServiceProviderConfig() 85 | throws ScimException; 86 | } 87 | -------------------------------------------------------------------------------- /scim2-sdk-server/src/main/java/com/unboundid/scim2/server/resources/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /** 19 | * Classes representing SCIM 2 service provider endpoints. 20 | */ 21 | 22 | package com.unboundid.scim2.server.resources; 23 | -------------------------------------------------------------------------------- /scim2-sdk-server/src/main/java/com/unboundid/scim2/server/utils/ResourceDiff.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | 19 | package com.unboundid.scim2.server.utils; 20 | 21 | import com.fasterxml.jackson.databind.JsonNode; 22 | import com.unboundid.scim2.common.Path; 23 | import com.unboundid.scim2.common.annotations.NotNull; 24 | import com.unboundid.scim2.common.utils.JsonDiff; 25 | import com.unboundid.scim2.common.utils.JsonUtils; 26 | 27 | /** 28 | * This class can be used to calculate the diffs between two SCIM 29 | * resources for the purpose of building a set of patch operations. 30 | * The comparison takes into account the SCIM schema of the resources 31 | * to be compared. 32 | */ 33 | public class ResourceDiff extends JsonDiff 34 | { 35 | @NotNull 36 | private final ResourceTypeDefinition resourceTypeDefinition; 37 | 38 | /** 39 | * Construct a ResourceDiff instance. 40 | * 41 | * @param resourceTypeDefinition the ResourceTypeDefinition of the 42 | * resources to be compared. 43 | */ 44 | public ResourceDiff( 45 | @NotNull final ResourceTypeDefinition resourceTypeDefinition) 46 | { 47 | super(); 48 | this.resourceTypeDefinition = resourceTypeDefinition; 49 | } 50 | 51 | /** 52 | * {@inheritDoc} 53 | */ 54 | @Override 55 | protected int compareTo(@NotNull final Path path, 56 | @NotNull final JsonNode sourceNode, 57 | @NotNull final JsonNode targetNode) 58 | { 59 | return JsonUtils.compareTo(sourceNode, targetNode, 60 | resourceTypeDefinition.getAttributeDefinition(path)); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /scim2-sdk-server/src/main/java/com/unboundid/scim2/server/utils/SchemaAwareFilterEvaluator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.server.utils; 19 | 20 | import com.unboundid.scim2.common.Path; 21 | import com.unboundid.scim2.common.annotations.NotNull; 22 | import com.unboundid.scim2.common.annotations.Nullable; 23 | import com.unboundid.scim2.common.types.AttributeDefinition; 24 | import com.unboundid.scim2.common.utils.FilterEvaluator; 25 | 26 | /** 27 | * A schema aware filter evaluator that respects case sensitivity. 28 | */ 29 | public class SchemaAwareFilterEvaluator extends FilterEvaluator 30 | { 31 | @NotNull 32 | private final ResourceTypeDefinition resourceType; 33 | 34 | /** 35 | * Create a new schema aware filter evaluator. 36 | * 37 | * @param resourceType The resource type definition. 38 | */ 39 | public SchemaAwareFilterEvaluator( 40 | @NotNull final ResourceTypeDefinition resourceType) 41 | { 42 | this.resourceType = resourceType; 43 | } 44 | 45 | /** 46 | * {@inheritDoc} 47 | */ 48 | @Override 49 | @Nullable 50 | protected AttributeDefinition getAttributeDefinition(@NotNull final Path path) 51 | { 52 | return resourceType.getAttributeDefinition(path); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /scim2-sdk-server/src/main/java/com/unboundid/scim2/server/utils/ServerUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.server.utils; 19 | 20 | import com.unboundid.scim2.common.annotations.NotNull; 21 | import jakarta.ws.rs.core.MediaType; 22 | import jakarta.ws.rs.core.Response; 23 | 24 | import java.util.List; 25 | 26 | import static com.unboundid.scim2.common.utils.ApiConstants.MEDIA_TYPE_SCIM; 27 | 28 | /** 29 | * Utility methods for server side use. 30 | */ 31 | public class ServerUtils 32 | { 33 | /** 34 | * The SCIM media type. 35 | */ 36 | @NotNull 37 | public static final MediaType MEDIA_TYPE_SCIM_TYPE = 38 | MediaType.valueOf(MEDIA_TYPE_SCIM); 39 | 40 | /** 41 | * Sets the appropriate response content type while taking the accept header 42 | * into account. 43 | * 44 | * @param response The response builder. 45 | * @param acceptableTypes The list of acceptable types from 46 | * Request.getAcceptableMediaTypes. 47 | * @return The response builder. 48 | */ 49 | @NotNull 50 | public static Response.ResponseBuilder setAcceptableType( 51 | @NotNull final Response.ResponseBuilder response, 52 | @NotNull final List acceptableTypes) 53 | { 54 | MediaType responseType = null; 55 | for (MediaType mediaType : acceptableTypes) 56 | { 57 | if (mediaType.isCompatible(MEDIA_TYPE_SCIM_TYPE)) 58 | { 59 | responseType = MEDIA_TYPE_SCIM_TYPE; 60 | break; 61 | } 62 | else if (mediaType.isCompatible(MediaType.APPLICATION_JSON_TYPE)) 63 | { 64 | responseType = MediaType.APPLICATION_JSON_TYPE; 65 | break; 66 | } 67 | } 68 | response.type(responseType == null ? MEDIA_TYPE_SCIM_TYPE : responseType); 69 | 70 | return response; 71 | } 72 | 73 | /** 74 | * Encodes a string with template parameters name present, specifically the 75 | * characters '{' and '}' will be percent-encoded. 76 | * 77 | * @param s the string with zero or more template parameter names 78 | * @return the string with encoded template parameter names. 79 | */ 80 | @NotNull 81 | public static String encodeTemplateNames(@NotNull final String s) 82 | { 83 | String s1 = s; 84 | int i = s1.indexOf('{'); 85 | if (i != -1) 86 | { 87 | s1 = s1.replace("{", "%7B"); 88 | } 89 | i = s1.indexOf('}'); 90 | if (i != -1) 91 | { 92 | s1 = s1.replace("}", "%7D"); 93 | } 94 | 95 | return s1; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /scim2-sdk-server/src/main/java/com/unboundid/scim2/server/utils/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /** 19 | * SCIM 2 service provider utility classes, including classes that enforce 20 | * schema, classes for manipulating search results, and classes for processing 21 | * resources. 22 | */ 23 | 24 | package com.unboundid.scim2.server.utils; 25 | -------------------------------------------------------------------------------- /scim2-sdk-server/src/main/javadoc/overview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | UnboundID SCIM 2 SDK Server 5 | 6 | 7 | 8 |

This package contains classes used to implement SCIM 2 service providers.

9 | 10 | 11 | -------------------------------------------------------------------------------- /scim2-sdk-server/src/test/java/com/unboundid/scim2/server/CustomContentEndpoint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.server; 19 | 20 | import com.unboundid.scim2.common.messages.PatchRequest; 21 | import com.unboundid.scim2.common.types.Meta; 22 | import com.unboundid.scim2.common.types.UserResource; 23 | import com.unboundid.scim2.server.annotations.ResourceType; 24 | 25 | import jakarta.ws.rs.Consumes; 26 | import jakarta.ws.rs.GET; 27 | import jakarta.ws.rs.POST; 28 | import jakarta.ws.rs.PUT; 29 | import jakarta.ws.rs.Path; 30 | import jakarta.ws.rs.PathParam; 31 | import jakarta.ws.rs.Produces; 32 | import jakarta.ws.rs.core.MediaType; 33 | import java.net.URI; 34 | import java.net.URISyntaxException; 35 | 36 | /** 37 | * A per resource life cycle Resource Endpoint implementation. 38 | */ 39 | @ResourceType( 40 | description = "Custom User Account", 41 | name = "Custom User", 42 | schema = UserResource.class) 43 | @Path("/CustomContent") 44 | public class CustomContentEndpoint 45 | { 46 | /** 47 | * Test case endpoint method for testing custom media types. 48 | * 49 | * @param userResource user resource. 50 | * 51 | * @return user resource with a location set 52 | * @throws URISyntaxException error condition 53 | */ 54 | @Produces(MediaType.APPLICATION_JSON) 55 | @Consumes(MediaType.APPLICATION_JSON) 56 | @POST 57 | public UserResource postResource(UserResource userResource) throws URISyntaxException 58 | { 59 | userResource.setMeta(new Meta()); 60 | userResource.getMeta().setLocation(new URI("CustomContent")); 61 | return userResource; 62 | } 63 | 64 | 65 | /** 66 | * Test case endpoint method for testing custom media types. 67 | * 68 | * @param userResource user resource. 69 | * 70 | * @return user resource with a location set 71 | */ 72 | @Produces(MediaType.APPLICATION_JSON) 73 | @Consumes(MediaType.APPLICATION_JSON) 74 | @PUT 75 | public UserResource putResource(UserResource userResource) 76 | { 77 | return userResource; 78 | } 79 | 80 | /** 81 | * Test case endpoint method for testing custom media types. 82 | * 83 | * @param patchRequest user resource. 84 | */ 85 | @Consumes(MediaType.APPLICATION_JSON) 86 | @PATCH 87 | public void patchResource(PatchRequest patchRequest) 88 | { 89 | } 90 | 91 | 92 | /** 93 | * Test case endpoint method for testing custom media types. 94 | * 95 | * @param id string id, not used. 96 | * @return a byte array 97 | */ 98 | @Path("{id}") 99 | @Produces(MediaType.APPLICATION_OCTET_STREAM) 100 | @GET 101 | public byte[] getTextResource(@PathParam("id") String id) 102 | { 103 | return ("TextPlainReturn:" + id).getBytes(); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /scim2-sdk-server/src/test/java/com/unboundid/scim2/server/TestAuthenticatedSubjectAliasFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.server; 19 | 20 | import com.unboundid.scim2.common.annotations.NotNull; 21 | import com.unboundid.scim2.server.providers.AuthenticatedSubjectAliasFilter; 22 | 23 | import jakarta.ws.rs.container.PreMatching; 24 | import jakarta.ws.rs.core.SecurityContext; 25 | import jakarta.ws.rs.ext.Provider; 26 | 27 | /** 28 | * A test filter that just returns a static authenticated subject. 29 | */ 30 | @Provider 31 | @PreMatching 32 | public class TestAuthenticatedSubjectAliasFilter 33 | extends AuthenticatedSubjectAliasFilter 34 | { 35 | @Override 36 | @NotNull 37 | protected String getAuthenticatedSubjectPath( 38 | final SecurityContext securityContext) 39 | { 40 | return "Users/123"; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /scim2-sdk-server/src/test/java/com/unboundid/scim2/server/TestServiceProviderConfigEndpoint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.server; 19 | 20 | import com.unboundid.scim2.common.annotations.NotNull; 21 | import com.unboundid.scim2.common.types.AuthenticationScheme; 22 | import com.unboundid.scim2.common.types.BulkConfig; 23 | import com.unboundid.scim2.common.types.ChangePasswordConfig; 24 | import com.unboundid.scim2.common.types.ETagConfig; 25 | import com.unboundid.scim2.common.types.FilterConfig; 26 | import com.unboundid.scim2.common.types.PatchConfig; 27 | import com.unboundid.scim2.common.types.ServiceProviderConfigResource; 28 | import com.unboundid.scim2.common.exceptions.ScimException; 29 | import com.unboundid.scim2.common.types.SortConfig; 30 | import com.unboundid.scim2.server.resources. 31 | AbstractServiceProviderConfigEndpoint; 32 | 33 | import java.util.Collections; 34 | 35 | /** 36 | * A test Service Provider Config endpoint implementation that just serves up 37 | * a canned config. 38 | */ 39 | public class TestServiceProviderConfigEndpoint 40 | extends AbstractServiceProviderConfigEndpoint 41 | { 42 | /** 43 | * {@inheritDoc} 44 | */ 45 | @Override 46 | @NotNull 47 | public ServiceProviderConfigResource getServiceProviderConfig() 48 | throws ScimException 49 | { 50 | return create(); 51 | } 52 | 53 | /** 54 | * Create a test config resource. 55 | * 56 | * @return The created resource. 57 | */ 58 | public static ServiceProviderConfigResource create() 59 | { 60 | return new ServiceProviderConfigResource("https://doc", 61 | new PatchConfig(true), 62 | new BulkConfig(true, 100, 1000), 63 | new FilterConfig(true, 200), 64 | new ChangePasswordConfig(true), 65 | new SortConfig(true), 66 | new ETagConfig(false), 67 | Collections.singletonList( 68 | new AuthenticationScheme( 69 | "Basic", "HTTP BASIC", null, null, "httpbasic", true))); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /scim2-sdk-server/src/test/java/com/unboundid/scim2/server/utils/EncodeTemplateNamesTestCase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.server.utils; 19 | 20 | import org.testng.annotations.DataProvider; 21 | import org.testng.annotations.Test; 22 | 23 | import static org.testng.Assert.assertEquals; 24 | 25 | /** 26 | * Test coverage for ServerUtils.EncodeTemplateNames. 27 | */ 28 | public class EncodeTemplateNamesTestCase 29 | { 30 | /** 31 | * Retrieves a set of strings to test encodeTemplateNames. 32 | * 33 | * @return A set of input strings with expected output. 34 | */ 35 | @DataProvider(name = "testEncodeTemplateNamesStrings") 36 | public Object[][] getTestEncodeTemplateNames() 37 | { 38 | return new Object[][] 39 | { 40 | new Object[] { "cn eq \"{xx}\"", "cn eq \"%7Bxx%7D\"" }, 41 | new Object[] { "{a}{b}", "%7Ba%7D%7Bb%7D" }, 42 | new Object[] { "%7B%7D", "%7B%7D" }, 43 | new Object[] { "{{a}}", "%7B%7Ba%7D%7D" }, 44 | new Object[] { "}}}}{{{{", "%7D%7D%7D%7D%7B%7B%7B%7B" }, 45 | new Object[] { "{", "%7B" }, 46 | new Object[] { "}", "%7D" }, 47 | new Object[] { "", "" }, 48 | }; 49 | } 50 | 51 | /** 52 | * Test the encodeTemplateNames method. 53 | * 54 | * @param input The string to evaluate. 55 | * @param output The expected result. 56 | */ 57 | @Test(dataProvider = "testEncodeTemplateNamesStrings") 58 | public void testFilter(String input, String output) 59 | { 60 | final String actualOutput = ServerUtils.encodeTemplateNames(input); 61 | assertEquals(actualOutput, output); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /scim2-ubid-extensions/README.md: -------------------------------------------------------------------------------- 1 | # SCIM 2 SDK UnboundID Extensions 2 | This component contains model classes representing UnboundID-proprietary extensions to the [SCIM](http://www.simplecloud.info) standard. This component is considered **experimental** and its contents are subject to change. 3 | 4 | ## About the SCIM 2 SDK 5 | 6 | The UnboundID SCIM 2 SDK for Java provides a powerful and flexible set of APIs for interacting with SCIM service providers and resources. Use it to build applications and servers that interoperate with SCIM servers such as the [UnboundID Data Broker](https://www.unboundid.com/data-broker). 7 | 8 | Please refer to the [SCIM 2 SDK README](https://github.com/pingidentity/scim2) for license and support information. 9 | -------------------------------------------------------------------------------- /scim2-ubid-extensions/src/main/java/com/unboundid/scim2/extension/messages/consent/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /** 19 | * Classes representing UnboundID SCIM 2 extensions for OAuth 2 consent. 20 | */ 21 | 22 | package com.unboundid.scim2.extension.messages.consent; 23 | -------------------------------------------------------------------------------- /scim2-ubid-extensions/src/main/java/com/unboundid/scim2/extension/messages/contactvalidation/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /** 19 | * Classes representing UnboundID SCIM 2 extensions for contact mechanism 20 | * verification. 21 | */ 22 | 23 | package com.unboundid.scim2.extension.messages.contactvalidation; 24 | -------------------------------------------------------------------------------- /scim2-ubid-extensions/src/main/java/com/unboundid/scim2/extension/messages/externalidentity/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /** 19 | * Classes representing UnboundID SCIM 2 extensions for external identity 20 | * provider data. 21 | */ 22 | 23 | package com.unboundid.scim2.extension.messages.externalidentity; 24 | -------------------------------------------------------------------------------- /scim2-ubid-extensions/src/main/java/com/unboundid/scim2/extension/messages/pwdmgmt/AccountUsabilityIssue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.extension.messages.pwdmgmt; 19 | 20 | import com.fasterxml.jackson.annotation.JsonCreator; 21 | import com.fasterxml.jackson.annotation.JsonProperty; 22 | import com.unboundid.scim2.common.annotations.Nullable; 23 | 24 | import java.util.Objects; 25 | 26 | /** 27 | * Model class for an account usability issues. 28 | */ 29 | public class AccountUsabilityIssue 30 | { 31 | @Nullable 32 | private final String name; 33 | 34 | @Nullable 35 | private final String message; 36 | 37 | /** 38 | * Create a new account usability issue instance. 39 | * 40 | * @param name The name for this account usability issue. 41 | * @param message The human-readable message that provides specific details 42 | * about this account usability issue. 43 | */ 44 | @JsonCreator 45 | public AccountUsabilityIssue( 46 | @Nullable @JsonProperty(value = "name") final String name, 47 | @Nullable @JsonProperty(value = "message") final String message) 48 | { 49 | this.name = name; 50 | this.message = message; 51 | } 52 | 53 | /** 54 | * Retrieves the name for this account usability issue. 55 | * 56 | * @return The name for this account usability issue. 57 | */ 58 | @Nullable 59 | public String getName() 60 | { 61 | return name; 62 | } 63 | 64 | /** 65 | * Retrieves a human-readable message that provides specific details about 66 | * this account usability issue. 67 | * 68 | * @return A human-readable message that provides specific details about this 69 | * account usability issue, or {@code null} if no message is 70 | * available. 71 | */ 72 | @Nullable 73 | public String getMessage() 74 | { 75 | return message; 76 | } 77 | 78 | /** 79 | * Indicates whether the provided object is equal to this account usability 80 | * issue. 81 | * 82 | * @param o The object to compare. 83 | * @return {@code true} if the provided object is equal to this account 84 | * usability issue, or {@code false} if not. 85 | */ 86 | @Override 87 | public boolean equals(@Nullable final Object o) 88 | { 89 | if (this == o) 90 | { 91 | return true; 92 | } 93 | if (o == null || getClass() != o.getClass()) 94 | { 95 | return false; 96 | } 97 | 98 | AccountUsabilityIssue that = (AccountUsabilityIssue) o; 99 | if (!Objects.equals(name, that.name)) 100 | { 101 | return false; 102 | } 103 | return Objects.equals(message, that.message); 104 | } 105 | 106 | /** 107 | * Retrieves a hash code for this account usability issue. 108 | * 109 | * @return A hash code for this account usability issue. 110 | */ 111 | @Override 112 | public int hashCode() 113 | { 114 | return Objects.hash(name, message); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /scim2-ubid-extensions/src/main/java/com/unboundid/scim2/extension/messages/pwdmgmt/PasswordUpdateErr.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.extension.messages.pwdmgmt; 19 | 20 | import com.unboundid.scim2.common.annotations.NotNull; 21 | import com.unboundid.scim2.common.annotations.Schema; 22 | import com.unboundid.scim2.common.annotations.Attribute; 23 | 24 | import java.util.ArrayList; 25 | import java.util.List; 26 | 27 | /** 28 | * This class represents the errors that occurred while updating a password. 29 | */ 30 | @Schema(id="urn:pingidentity:scim:api:messages:2.0:PasswordUpdateError", 31 | description = "This class represents the errors that occurred while " + 32 | "updating a password.", 33 | name = "PasswordUpdateError") 34 | public class PasswordUpdateErr 35 | { 36 | @NotNull 37 | @Attribute( 38 | description = "A list of errors that occurred while attempting" 39 | + " to change the password.", 40 | multiValueClass = PasswordRequirementResult.class) 41 | private List passwordRequirements = 42 | new ArrayList<>(); 43 | 44 | 45 | /** 46 | * Gets the password requirements returned from the attempted password change. 47 | * 48 | * @return the password requirements returned from the attempted 49 | * password change. 50 | */ 51 | @NotNull 52 | public List getPasswordRequirements() 53 | { 54 | return passwordRequirements; 55 | } 56 | 57 | /** 58 | * Sets the password requirements returned from the attempted password change. 59 | * 60 | * @param passwordRequirementResults the password requirements returned from 61 | * the attempted password change. 62 | */ 63 | public void setPasswordRequirements( 64 | @NotNull final List passwordRequirementResults) 65 | { 66 | this.passwordRequirements = passwordRequirementResults; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /scim2-ubid-extensions/src/main/java/com/unboundid/scim2/extension/messages/pwdmgmt/RetiredPassword.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.extension.messages.pwdmgmt; 19 | 20 | import com.unboundid.scim2.common.annotations.Nullable; 21 | import com.unboundid.scim2.common.types.AttributeDefinition; 22 | import com.unboundid.scim2.common.annotations.Attribute; 23 | 24 | import java.util.Date; 25 | import java.util.Objects; 26 | 27 | /** 28 | * This class represents information about retired passwords. 29 | */ 30 | public class RetiredPassword 31 | { 32 | @Nullable 33 | @Attribute(description = "The time that the password was retired", 34 | mutability = AttributeDefinition.Mutability.READ_WRITE) 35 | private Date passwordRetiredTime; 36 | 37 | @Nullable 38 | @Attribute(description = "The expiration time of the password.", 39 | mutability = AttributeDefinition.Mutability.READ_WRITE) 40 | private Date passwordExpirationTime; 41 | 42 | /** 43 | * Gets the retired password expiration time. 44 | * 45 | * @return the retired password expiration. 46 | */ 47 | @Nullable 48 | public Date getPasswordExpirationTime() 49 | { 50 | return passwordExpirationTime; 51 | } 52 | 53 | /** 54 | * Sets the retired password expiration time. 55 | * 56 | * @param passwordExpirationTime the retired password expiration. 57 | */ 58 | public void setPasswordExpirationTime( 59 | @Nullable final Date passwordExpirationTime) 60 | { 61 | this.passwordExpirationTime = passwordExpirationTime; 62 | } 63 | 64 | /** 65 | * Gets the retired time. 66 | * 67 | * @return the retired time. 68 | */ 69 | @Nullable 70 | public Date getPasswordRetiredTime() 71 | { 72 | return passwordRetiredTime; 73 | } 74 | 75 | /** 76 | * Sets the retired time. 77 | * 78 | * @param passwordRetiredTime the retired time. 79 | */ 80 | public void setPasswordRetiredTime(@Nullable final Date passwordRetiredTime) 81 | { 82 | this.passwordRetiredTime = passwordRetiredTime; 83 | } 84 | 85 | /** 86 | * Indicates whether the provided object is equal to this retired password. 87 | * 88 | * @param o The object to compare. 89 | * @return {@code true} if the provided object is equal to this retired 90 | * password, or {@code false} if not. 91 | */ 92 | @Override 93 | public boolean equals(@Nullable final Object o) 94 | { 95 | if (this == o) 96 | { 97 | return true; 98 | } 99 | 100 | if (o == null || getClass() != o.getClass()) 101 | { 102 | return false; 103 | } 104 | 105 | RetiredPassword that = (RetiredPassword) o; 106 | if (!Objects.equals(passwordRetiredTime, that.passwordRetiredTime)) 107 | { 108 | return false; 109 | } 110 | return Objects.equals(passwordExpirationTime, that.passwordExpirationTime); 111 | } 112 | 113 | /** 114 | * Retrieves a hash code for this retired password. 115 | * 116 | * @return A hash code for this retired password. 117 | */ 118 | @Override 119 | public int hashCode() 120 | { 121 | return Objects.hash(passwordRetiredTime, passwordExpirationTime); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /scim2-ubid-extensions/src/main/java/com/unboundid/scim2/extension/messages/pwdmgmt/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /** 19 | * Classes representing UnboundID SCIM 2 extensions for account and password 20 | * management resources. 21 | */ 22 | 23 | package com.unboundid.scim2.extension.messages.pwdmgmt; 24 | -------------------------------------------------------------------------------- /scim2-ubid-extensions/src/main/java/com/unboundid/scim2/extension/messages/sessionmgmt/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | /** 19 | * Classes representing UnboundID SCIM 2 extensions for user sessions. 20 | */ 21 | 22 | package com.unboundid.scim2.extension.messages.sessionmgmt; 23 | -------------------------------------------------------------------------------- /scim2-ubid-extensions/src/main/javadoc/overview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | UnboundID SCIM 2 SDK UnboundID Extensions 5 | 6 | 7 | 8 |

This package contains model classes representing UnboundID-specific SCIM 2 9 | resources. These include classes representing user sessions, multifactor 10 | authentication preferences, account and password states, consent records, 11 | consent history, and external identity provider data.

12 | 13 | 14 | -------------------------------------------------------------------------------- /scim2-ubid-extensions/src/test/java/com/unboundid/scim2/extension/messages/consent/ConsentHistoryTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.extension.messages.consent; 19 | 20 | import com.unboundid.scim2.common.utils.JsonUtils; 21 | import org.testng.Assert; 22 | import org.testng.annotations.Test; 23 | 24 | 25 | @Test 26 | public class ConsentHistoryTest 27 | { 28 | /** 29 | * Tests serialization of ConsentHistory objects. 30 | * 31 | * @throws Exception if an error occurs. 32 | */ 33 | @Test 34 | public void testSerialization() throws Exception 35 | { 36 | String consentHistoryString = 37 | """ 38 | { 39 | "client":{ 40 | "name":"appName", 41 | "description":"appDesc", 42 | "iconUrl":"http://localhost:12345/app", 43 | "emailAddress":"email@address.com" 44 | }, 45 | "scopes":[ 46 | { 47 | "name":"name1", 48 | "description":"description1", 49 | "consent":"granted" 50 | }, 51 | { 52 | "name":"name2", 53 | "description":"description2", 54 | "consent":"denied" 55 | }, 56 | { 57 | "name":"name3", 58 | "description":"description3", 59 | "consent":"revoked" 60 | } 61 | ], 62 | "meta":{ 63 | "lastModified":"2015-07-04T00:00:00.000Z" 64 | }, 65 | "id":"ConsentHistoryId" 66 | }"""; 67 | 68 | ConsentHistory consentHistory = JsonUtils.getObjectReader().forType( 69 | ConsentHistory.class).readValue(consentHistoryString); 70 | String serializedConsentHistory = JsonUtils.getObjectWriter(). 71 | writeValueAsString(consentHistory); 72 | ConsentHistory deserializedConsentHistory = JsonUtils.getObjectReader(). 73 | forType(ConsentHistory.class).readValue(serializedConsentHistory); 74 | Assert.assertEquals(consentHistory, deserializedConsentHistory); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /scim2-ubid-extensions/src/test/java/com/unboundid/scim2/extension/messages/consent/ConsentTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.extension.messages.consent; 19 | 20 | import com.unboundid.scim2.common.utils.JsonUtils; 21 | import org.testng.Assert; 22 | import org.testng.annotations.Test; 23 | 24 | @Test 25 | public class ConsentTest 26 | { 27 | /** 28 | * Tests serialization of Consent objects. 29 | * 30 | * @throws Exception if an error occurs. 31 | */ 32 | @Test 33 | public void testSerialization() throws Exception 34 | { 35 | String consentString = 36 | """ 37 | { 38 | "client":{ 39 | "name":"appName", 40 | "description":"appDesc", 41 | "iconUrl":"http://localhost:12345/app", 42 | "emailAddress":"email@address.com" 43 | }, 44 | "scopes":[ 45 | { 46 | "name":"name1", 47 | "description":"description1", 48 | "consent":"granted" 49 | }, 50 | { 51 | "name":"name2", 52 | "description":"description2", 53 | "consent":"denied" 54 | }, 55 | { 56 | "name":"name3", 57 | "description":"description3", 58 | "consent":"revoked" 59 | } 60 | ], 61 | "meta":{ 62 | "lastModified":"2015-07-06T04:03:02.000Z" 63 | }, 64 | "id":"ConsentId" 65 | }"""; 66 | 67 | Consent consent = JsonUtils.getObjectReader().forType(Consent.class). 68 | readValue(consentString); 69 | String serializedConsent = 70 | JsonUtils.getObjectWriter().writeValueAsString(consent); 71 | Consent deserializedConsent = JsonUtils.getObjectReader(). 72 | forType(Consent.class).readValue(serializedConsent); 73 | Assert.assertEquals(consent, deserializedConsent); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /scim2-ubid-extensions/src/test/java/com/unboundid/scim2/extension/messages/consent/OAuth2ClientTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.extension.messages.consent; 19 | 20 | import com.fasterxml.jackson.databind.node.ObjectNode; 21 | import com.unboundid.scim2.common.utils.JsonUtils; 22 | import org.testng.Assert; 23 | import org.testng.annotations.Test; 24 | 25 | @Test 26 | public class OAuth2ClientTest 27 | { 28 | /** 29 | * Tests serialization of Client objects. 30 | * 31 | * @throws Exception if an error occurs. 32 | */ 33 | @Test 34 | public void testSerialization() throws Exception 35 | { 36 | String name = "testName"; 37 | String description = "testDescription"; 38 | String url = "https://localhost:12345/test/app/url"; 39 | String iconUrl = "https://localhost:12345/test/icon/url"; 40 | String emailAddress = "unit@test.com"; 41 | 42 | ObjectNode objectNode = JsonUtils.getJsonNodeFactory().objectNode(); 43 | objectNode.put("name", name); 44 | objectNode.put("description", description); 45 | objectNode.put("iconUrl", iconUrl); 46 | objectNode.put("url", url); 47 | objectNode.put("emailAddress", emailAddress); 48 | 49 | OAuth2Client app1 = JsonUtils.getObjectReader().forType(OAuth2Client.class). 50 | readValue(objectNode.toString()); 51 | Assert.assertEquals(app1.getName(), name); 52 | Assert.assertEquals(app1.getDescription(), description); 53 | Assert.assertEquals(app1.getIconUrl(), iconUrl); 54 | Assert.assertEquals(app1.getEmailAddress(), emailAddress); 55 | 56 | OAuth2Client app2 = 57 | JsonUtils.getObjectReader().forType(OAuth2Client.class).readValue( 58 | JsonUtils.getObjectWriter().writeValueAsString(app1)); 59 | Assert.assertEquals(app1, app2); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /scim2-ubid-extensions/src/test/java/com/unboundid/scim2/extension/messages/consent/ScopeTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.extension.messages.consent; 19 | 20 | import com.fasterxml.jackson.databind.node.ObjectNode; 21 | import com.unboundid.scim2.common.utils.JsonUtils; 22 | import org.testng.Assert; 23 | import org.testng.annotations.Test; 24 | 25 | @Test 26 | public class ScopeTest 27 | { 28 | /** 29 | * Tests serialization of Scope objects. 30 | * 31 | * @throws Exception if an error occurs. 32 | */ 33 | @Test 34 | public void testSerialization() throws Exception 35 | { 36 | String name = "testName"; 37 | String description = "testDescription"; 38 | String consent = Scope.CONSENT_GRANTED; 39 | 40 | ObjectNode objectNode = JsonUtils.getJsonNodeFactory().objectNode(); 41 | objectNode.put("name", name); 42 | objectNode.put("description", description); 43 | objectNode.put("consent", consent); 44 | 45 | Scope scope1 = JsonUtils.getObjectReader().forType(Scope.class).readValue( 46 | objectNode.toString()); 47 | Assert.assertEquals(name, scope1.getName()); 48 | Assert.assertEquals(description, scope1.getDescription()); 49 | Assert.assertEquals(consent, scope1.getConsent()); 50 | 51 | Scope scope2 = 52 | JsonUtils.getObjectReader().forType(Scope.class).readValue( 53 | JsonUtils.getObjectWriter().writeValueAsString(scope1)); 54 | Assert.assertEquals(scope1, scope2); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /scim2-ubid-extensions/src/test/java/com/unboundid/scim2/extension/messages/externalidentity/ExternalIdentityTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.extension.messages.externalidentity; 19 | 20 | import com.unboundid.scim2.common.utils.JsonUtils; 21 | import org.testng.Assert; 22 | import org.testng.annotations.Test; 23 | 24 | 25 | @Test 26 | public class ExternalIdentityTest 27 | { 28 | /** 29 | * Tests serialization of ExternalIdentity objects. 30 | * 31 | * @throws Exception if an error occurs. 32 | */ 33 | @Test 34 | public void testSerialization() throws Exception 35 | { 36 | String externalIdString = """ 37 | { 38 | "provider":{ 39 | "name":"testName", 40 | "description":"testDescription", 41 | "iconUrl":"http://localhost:3020/test/url", 42 | "type":"testType" 43 | }, 44 | "providerUserId":"testUserId", 45 | "accessToken":"testAccessToken", 46 | "refreshToken":"testRefreshToken", 47 | "callbackUrl":"testCallbackUrl", 48 | "callbackParameters": 49 | { 50 | "testParamOne":"testValueOne", 51 | "testParamTwo":"testValueTwo", 52 | "testParamThree":"testValueThree" 53 | }, 54 | "meta":{ 55 | "created":"2015-07-04T00:00:00.000Z", 56 | "lastModified":"2015-07-06T04:03:02.000Z" 57 | } 58 | }"""; 59 | 60 | ExternalIdentity externalId = JsonUtils.getObjectReader(). 61 | forType(ExternalIdentity.class).readValue(externalIdString); 62 | String serializedExternalId = JsonUtils.getObjectWriter(). 63 | writeValueAsString(externalId); 64 | ExternalIdentity deserializedObject = JsonUtils.getObjectReader(). 65 | forType(ExternalIdentity.class).readValue(serializedExternalId); 66 | Assert.assertEquals(externalId, deserializedObject); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /scim2-ubid-extensions/src/test/java/com/unboundid/scim2/extension/messages/externalidentity/ProviderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.extension.messages.externalidentity; 19 | 20 | import com.fasterxml.jackson.databind.node.ObjectNode; 21 | import com.unboundid.scim2.common.utils.JsonUtils; 22 | import org.testng.Assert; 23 | import org.testng.annotations.Test; 24 | 25 | @Test 26 | public class ProviderTest 27 | { 28 | /** 29 | * Tests serialization of Provider objects. 30 | * 31 | * @throws Exception if an error occurs. 32 | */ 33 | @Test 34 | public void testSerialization() throws Exception 35 | { 36 | String name = "testName"; 37 | String description = "testDescription"; 38 | String iconUrl = "https://localhost:12345/test/url"; 39 | String type = "testType"; 40 | String samlResponseBinding = "artifact"; 41 | 42 | ObjectNode objectNode = JsonUtils.getJsonNodeFactory().objectNode(); 43 | objectNode.put("name", name); 44 | objectNode.put("description", description); 45 | objectNode.put("iconUrl", iconUrl); 46 | objectNode.put("type", type); 47 | objectNode.put("samlResponseBinding", samlResponseBinding); 48 | 49 | Provider provider1 = JsonUtils.getObjectReader().forType(Provider.class). 50 | readValue(objectNode.toString()); 51 | Assert.assertEquals(provider1.getName(), name); 52 | Assert.assertEquals(provider1.getDescription(), description); 53 | Assert.assertEquals(provider1.getType(), type); 54 | Assert.assertEquals(provider1.getIconUrl(), iconUrl); 55 | Assert.assertEquals(provider1.getSamlResponseBinding(), 56 | samlResponseBinding); 57 | 58 | Provider provider2 = 59 | JsonUtils.getObjectReader().forType(Provider.class).readValue( 60 | JsonUtils.getObjectWriter().writeValueAsString(provider1)); 61 | Assert.assertEquals(provider1, provider2); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /scim2-ubid-extensions/src/test/java/com/unboundid/scim2/extension/messages/pwdmgmt/PasswordQualityRequirementResponseTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.extension.messages.pwdmgmt; 19 | 20 | import com.unboundid.scim2.common.utils.JsonUtils; 21 | import org.testng.Assert; 22 | import org.testng.annotations.Test; 23 | 24 | @Test 25 | public class PasswordQualityRequirementResponseTest 26 | { 27 | /** 28 | * Tests serialization of Provider objects. 29 | * 30 | * @throws Exception if an error occurs. 31 | */ 32 | @Test 33 | public void testSerialization() throws Exception 34 | { 35 | String pqrString = """ 36 | { 37 | "currentPasswordRequired":true, 38 | "mustChangePassword":true, 39 | "secondsUntilPasswordExpiration":12, 40 | "passwordRequirements": 41 | [ 42 | { 43 | "type":"Type One", 44 | "requirementSatisfied":true, 45 | "description":"Description One", 46 | "additionalInfo":"Additional Info One" 47 | }, 48 | { 49 | "type":"Type Two", 50 | "requirementSatisfied":true, 51 | "description":"Description Two", 52 | "additionalInfo":"Additional Info Two" 53 | } 54 | ] 55 | }"""; 56 | 57 | PasswordQualityRequirementResponse pqrResponse = 58 | JsonUtils.getObjectReader().forType( 59 | PasswordQualityRequirementResponse.class).readValue(pqrString); 60 | String serializedPqrResponse = JsonUtils.getObjectWriter(). 61 | writeValueAsString(pqrResponse); 62 | PasswordQualityRequirementResponse deserializedPqrResponse = 63 | JsonUtils.getObjectReader().forType( 64 | PasswordQualityRequirementResponse.class). 65 | readValue(serializedPqrResponse); 66 | Assert.assertEquals(pqrResponse, deserializedPqrResponse); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /scim2-ubid-extensions/src/test/java/com/unboundid/scim2/extension/messages/sessionmgmt/SessionTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 Ping Identity Corporation 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License (GPLv2 only) 6 | * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 7 | * as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, see . 16 | */ 17 | 18 | package com.unboundid.scim2.extension.messages.sessionmgmt; 19 | 20 | import com.unboundid.scim2.common.utils.JsonUtils; 21 | import org.testng.Assert; 22 | import org.testng.annotations.Test; 23 | 24 | /** 25 | * Tests Session objects. 26 | */ 27 | public class SessionTest 28 | { 29 | /** 30 | * Test serialization to and from JSON. 31 | * 32 | * @throws Exception if an error occurs. 33 | */ 34 | @Test 35 | public void testSerialization() throws Exception 36 | { 37 | String sessionString = """ 38 | { 39 | "lastLoginMethods":[ "Method One", "Method Two", "Method Three" ], 40 | "lastSecondFactorMethods":[ "SF Method One", "SF Method Two" ], 41 | "lastLogin":"2015-07-06T04:03:02.000Z", 42 | "lastSecondFactor":"2015-07-07T04:03:02.000Z", 43 | "ipAddress":"192.168.10.34", 44 | "userAgentString":"User Agent String", 45 | "clients":[ 46 | { 47 | "name":"Client 1", 48 | "description":"Description 1", 49 | "url":"http://localhost:8080/myUrl1", 50 | "iconUrl":"http://localhost:8080/myUrl1/icon.png", 51 | "emailAddress":"someone1@somewhere.com", 52 | "lastAuthorization":"2015-07-08T04:03:02.000Z" 53 | }, 54 | { 55 | "name":"Client 2", 56 | "description":"Description 2", 57 | "url":"http://localhost:8080/myUrl2", 58 | "iconUrl":"http://localhost:8080/myUrl2/icon.png", 59 | "emailAddress":"someone2@somewhere.com", 60 | "lastAuthorization":"2015-07-09T04:03:02.000Z" 61 | }, 62 | { 63 | "name":"Client 3", 64 | "description":"Description 3", 65 | "url":"http://localhost:8080/myUrl3", 66 | "iconUrl":"http://localhost:8080/myUrl3/icon.png", 67 | "emailAddress":"someone3@somewhere.com", 68 | "lastAuthorization":"2015-07-10T04:03:02.000Z" 69 | } 70 | ] 71 | }"""; 72 | 73 | Session session = JsonUtils.getObjectReader().forType(Session.class). 74 | readValue(sessionString); 75 | String serializedSession = 76 | JsonUtils.getObjectWriter().writeValueAsString(session); 77 | Session deserializedSession = JsonUtils.getObjectReader(). 78 | forType(Session.class).readValue(serializedSession); 79 | Assert.assertEquals(session, deserializedSession); 80 | } 81 | } 82 | --------------------------------------------------------------------------------