├── .gitignore ├── .reuse └── dep5 ├── LICENSE ├── LICENSES └── Apache-2.0.txt ├── NOTICE.txt ├── README.md ├── pom.xml └── src ├── main └── java │ └── com │ └── sap │ └── cloud │ └── rest │ └── api │ └── client │ ├── RequestBuilder.java │ ├── RestApiClient.java │ ├── auth │ ├── Authentication.java │ ├── AuthenticationType.java │ ├── basic │ │ ├── BasicAuthentication.java │ │ └── BasicHttpClientProvider.java │ ├── cert │ │ ├── ClientCertAuthentication.java │ │ ├── KeystoreConfig.java │ │ ├── KeystoreConfigBuilder.java │ │ └── SSLHttpClientProvider.java │ ├── none │ │ ├── NoAuthHttpClientProvider.java │ │ └── NoAuthentication.java │ └── oauth │ │ ├── AccessTokenProvider.java │ │ ├── AccessTokenProviderFactory.java │ │ ├── AccessTokenResponseDto.java │ │ ├── ClientCredentialsAccessTokenProvider.java │ │ ├── OAuthAuthentication.java │ │ ├── OAuthHeaderProviderRequestInterceptor.java │ │ ├── OAuthHttpClientProvider.java │ │ ├── OAuthServerConfig.java │ │ └── OAuthServerConfigBuilder.java │ ├── config │ ├── AbstractRestApiClientConfigBuilder.java │ ├── RestApiClientConfig.java │ └── RestApiClientConfigBuilder.java │ ├── exceptions │ ├── ConnectionException.java │ ├── RequestBuilderException.java │ ├── ResponseException.java │ ├── RestApiClientException.java │ └── UnauthorizedException.java │ ├── handler │ ├── DefaultResponseHandler.java │ ├── DefaultStatusCodeHandler.java │ └── StatusCodeHandler.java │ ├── http │ ├── HttpClientCreationException.java │ ├── HttpClientProvider.java │ ├── HttpClientProviderFactory.java │ └── Proxy.java │ ├── model │ ├── HttpExchangeContext.java │ ├── Request.java │ ├── Response.java │ └── multipart │ │ ├── EntityPart.java │ │ └── MultipartEntity.java │ └── utils │ ├── JacksonJsonResponseHandler.java │ ├── PropertiesResponseHandler.java │ └── ValidateArgument.java └── test ├── java └── com │ └── sap │ └── cloud │ └── rest │ └── api │ └── client │ ├── RequestBuilderTest.java │ ├── RestApiClientTest.java │ ├── auth │ ├── basic │ │ ├── BasicAuthenticationTest.java │ │ └── BasicHttpClientProviderTest.java │ ├── cert │ │ ├── ClientCertAuthenticationTest.java │ │ ├── KeystoreConfigBuilderTest.java │ │ └── SSLHttpClientProviderTest.java │ ├── none │ │ └── NoAuthHttpClientProviderTest.java │ └── oauth │ │ ├── AccessTokenProviderFactoryTest.java │ │ ├── AccessTokenResponseDtoTest.java │ │ ├── ClientCredentialsAccessTokenProviderTest.java │ │ ├── OAuthAuthenticationTest.java │ │ ├── OAuthHeaderProviderRequestInterceptorTest.java │ │ ├── OAuthHttpClientProviderTest.java │ │ ├── OAuthServerConfigBuilderTest.java │ │ └── OAuthServerConfigTest.java │ ├── config │ ├── RestApiClientConfigBuilderTest.java │ └── RestApiClientConfigTest.java │ ├── exceptions │ ├── ConnectionExceptionTest.java │ └── ResponseExceptionTest.java │ ├── handler │ ├── DefaultResponseHandlerTest.java │ └── DefaultStatusCodeHandlerTest.java │ ├── http │ ├── HttpClientProviderFactoryTest.java │ └── ProxyTest.java │ ├── model │ ├── HttpExchangeContextTest.java │ ├── RequestTest.java │ ├── ResponseTest.java │ └── multipart │ │ ├── EntityPartTest.java │ │ └── MultipartEntityTest.java │ └── utils │ ├── JacksonJsonResponseHandlerTest.java │ ├── PropertiesResponseHandlerTest.java │ ├── ValidateArgumentTest.java │ └── test │ ├── HttpClientProviderUtils.java │ ├── MockResponseUtil.java │ └── RequestMatcher.java └── resources └── test-keystore.jks /.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | /target/ 3 | .classpath 4 | .project 5 | .settings/ 6 | *DS_Store 7 | .DS_Store 8 | .idea/ 9 | *.iml 10 | -------------------------------------------------------------------------------- /.reuse/dep5: -------------------------------------------------------------------------------- 1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: cloud-rest-api-client 3 | Upstream-Contact: Dimitar Giormov 4 | Source: https://github.com/SAP/cloud-rest-api-client 5 | Disclaimer: The code in this project may include calls to APIs (“API Calls”) of 6 | SAP or third-party products or services developed outside of this project 7 | (“External Products”). 8 | “APIs” means application programming interfaces, as well as their respective 9 | specifications and implementing code that allows software to communicate with 10 | other software. 11 | API Calls to External Products are not licensed under the open source license 12 | that governs this project. The use of such API Calls and related External 13 | Products are subject to applicable additional agreements with the relevant 14 | provider of the External Products. In no event shall the open source license 15 | that governs this project grant any rights in or to any External Products,or 16 | alter, expand or supersede any terms of the applicable additional agreements. 17 | If you have a valid license agreement with SAP for the use of a particular SAP 18 | External Product, then you may make use of any API Calls included in this 19 | project’s code for that SAP External Product, subject to the terms of such 20 | license agreement. If you do not have a valid license agreement for the use of 21 | a particular SAP External Product, then you may only make use of any API Calls 22 | in this project for that SAP External Product for your internal, non-productive 23 | and non-commercial test and evaluation of such API Calls. Nothing herein grants 24 | you any rights to use or access any SAP External Product, or provide any third 25 | parties the right to use of access any SAP External Product, through API Calls. 26 | 27 | Files: * 28 | Copyright: 2017-2020 SAP SE or an SAP affiliate company and cloud-rest-api-client 29 | License: Apache-2.0 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2017-2020 SAP SE or an SAP affiliate company and cloud-rest-api-client contributors 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSES/Apache-2.0.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. 10 | 11 | "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. 12 | 13 | "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 14 | 15 | "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. 16 | 17 | "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. 18 | 19 | "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. 20 | 21 | "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). 22 | 23 | "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. 24 | 25 | "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." 26 | 27 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 28 | 29 | 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 30 | 31 | 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 32 | 33 | 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: 34 | 35 | (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and 36 | 37 | (b) You must cause any modified files to carry prominent notices stating that You changed the files; and 38 | 39 | (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and 40 | 41 | (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. 42 | 43 | You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 44 | 45 | 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 46 | 47 | 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 48 | 49 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 50 | 51 | 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 52 | 53 | 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. 54 | 55 | END OF TERMS AND CONDITIONS 56 | 57 | APPENDIX: How to apply the Apache License to your work. 58 | 59 | To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. 60 | 61 | Copyright [yyyy] [name of copyright owner] 62 | 63 | Licensed under the Apache License, Version 2.0 (the "License"); 64 | you may not use this file except in compliance with the License. 65 | You may obtain a copy of the License at 66 | 67 | http://www.apache.org/licenses/LICENSE-2.0 68 | 69 | Unless required by applicable law or agreed to in writing, software 70 | distributed under the License is distributed on an "AS IS" BASIS, 71 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 72 | See the License for the specific language governing permissions and 73 | limitations under the License. 74 | -------------------------------------------------------------------------------- /NOTICE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 SAP SE or an SAP affiliate company. All rights reserved. 2 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.sap.cloud.client 5 | rest-api-client 6 | 1.1.7-SNAPSHOT 7 | jar 8 | SAP Cloud Platform REST API Client 9 | Java HTTP client library for HTTP handling, when building clients for RESTful APIs. 10 | https://github.com/SAP/cloud-rest-api-client 11 | 12 | 13 | UTF-8 14 | UTF-8 15 | 1.4.1 16 | 4.5.13 17 | 2.12.7.1 18 | 3.7 19 | 1.8 20 | 4.13.1 21 | 1.9.5 22 | 2.4.7 23 | true 24 | 25 | 1.6 26 | 2.8.2 27 | 1.6.7 28 | 2.5.3 29 | 1.9.5 30 | 3.0.1 31 | 1.9.5 32 | 33 | 34 | 35 | SAP SE 36 | http://www.sap.com 37 | 38 | 39 | 40 | 41 | The Apache Software License, Version 2.0 42 | http://www.apache.org/licenses/LICENSE-2.0.txt 43 | repo 44 | 45 | 46 | 47 | 48 | 49 | Chavdar Baikov 50 | chavdar.baikov@sap.com 51 | SAP SE 52 | https://www.sap.com 53 | 54 | 55 | 56 | 57 | scm:git:git://github.com/SAP/cloud-rest-api-client.git 58 | scm:git:git@github.com/SAP/cloud-rest-api-client.git 59 | https://github.com/SAP/cloud-rest-api-client 60 | HEAD 61 | 62 | 63 | 64 | 65 | ossrh 66 | https://oss.sonatype.org/content/repositories/snapshots 67 | 68 | 69 | ossrh 70 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 71 | 72 | 73 | 74 | 75 | Github 76 | https://github.com/SAP/cloud-rest-api-client/issues 77 | 78 | 79 | 80 | 81 | 82 | 83 | org.apache.httpcomponents 84 | httpclient 85 | ${http.client.version} 86 | 87 | 88 | org.apache.httpcomponents 89 | httpmime 90 | ${http.client.version} 91 | 92 | 93 | 94 | 95 | 96 | org.apache.commons 97 | commons-lang3 98 | ${apache.commons.lang.version} 99 | 100 | 101 | 102 | 103 | 104 | com.fasterxml.jackson.core 105 | jackson-databind 106 | ${jackson.version} 107 | 108 | 109 | 110 | 111 | 112 | junit 113 | junit 114 | ${junit.version} 115 | test 116 | 117 | 118 | nl.jqno.equalsverifier 119 | equalsverifier 120 | ${equalsverifier.version} 121 | test 122 | 123 | 124 | org.mockito 125 | mockito-all 126 | ${mockito.version} 127 | test 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | org.apache.maven.plugins 137 | maven-compiler-plugin 138 | 139 | ${java.version} 140 | ${java.version} 141 | 142 | 143 | 144 | org.apache.maven.plugins 145 | maven-surefire-plugin 146 | 147 | ${skip.tests} 148 | 149 | 150 | 151 | org.apache.maven.plugins 152 | maven-failsafe-plugin 153 | 154 | ${skip.tests} 155 | 156 | 157 | 158 | org.apache.maven.plugins 159 | maven-enforcer-plugin 160 | ${maven.enforcer.version} 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | dependency-convergence 169 | install 170 | 171 | enforce 172 | 173 | 174 | 175 | 176 | 177 | true 178 | 179 | 180 | 181 | 182 | 183 | org.apache.maven.plugins 184 | maven-source-plugin 185 | ${version.maven-source-plugin} 186 | 187 | 188 | attach-sources 189 | 190 | jar 191 | 192 | 193 | 194 | 195 | 196 | maven-deploy-plugin 197 | ${version.maven-deploy-plugin} 198 | 199 | 200 | default-deploy 201 | deploy 202 | 203 | deploy 204 | 205 | 206 | 207 | 208 | 209 | org.sonatype.plugins 210 | nexus-staging-maven-plugin 211 | ${version.nexus-staging-maven-plugin} 212 | true 213 | 214 | ossrh 215 | https://oss.sonatype.org/ 216 | true 217 | 218 | 219 | 220 | org.apache.maven.plugins 221 | maven-release-plugin 222 | ${version.maven-release-plugin} 223 | 224 | true 225 | false 226 | forked-path 227 | -Dgpg.passphrase=${gpg.passphrase} 228 | 229 | 230 | 231 | org.apache.maven.scm 232 | maven-scm-provider-gitexe 233 | ${version.maven-scm-provider-gitexe} 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | unit-tests 242 | 243 | false 244 | 245 | 246 | 247 | 248 | org.apache.maven.plugins 249 | maven-surefire-plugin 250 | 251 | false 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | release-sign-artifacts 260 | 261 | 262 | performRelease 263 | true 264 | 265 | 266 | 267 | 268 | 269 | org.apache.maven.plugins 270 | maven-gpg-plugin 271 | ${version.maven-gpg-plugin} 272 | 273 | 274 | sign-artifacts 275 | verify 276 | 277 | sign 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/RequestBuilder.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client; 2 | 3 | import static com.sap.cloud.rest.api.client.utils.ValidateArgument.isNotEmptyOrNull; 4 | import static com.sap.cloud.rest.api.client.utils.ValidateArgument.isNotNull; 5 | import static java.text.MessageFormat.format; 6 | 7 | import java.io.ByteArrayInputStream; 8 | import java.io.ByteArrayOutputStream; 9 | import java.io.IOException; 10 | import java.io.UnsupportedEncodingException; 11 | import java.net.URI; 12 | import java.net.URISyntaxException; 13 | import java.net.URLDecoder; 14 | import java.nio.charset.StandardCharsets; 15 | import java.util.ArrayList; 16 | import java.util.Arrays; 17 | import java.util.List; 18 | import java.util.Properties; 19 | 20 | import org.apache.http.Header; 21 | import org.apache.http.NameValuePair; 22 | import org.apache.http.client.entity.EntityBuilder; 23 | import org.apache.http.client.utils.URIBuilder; 24 | import org.apache.http.entity.ContentType; 25 | import org.apache.http.entity.mime.MultipartEntityBuilder; 26 | import org.apache.http.entity.mime.content.InputStreamBody; 27 | import org.apache.http.message.BasicNameValuePair; 28 | 29 | import com.fasterxml.jackson.core.JsonProcessingException; 30 | import com.fasterxml.jackson.databind.ObjectMapper; 31 | import com.sap.cloud.rest.api.client.exceptions.RequestBuilderException; 32 | import com.sap.cloud.rest.api.client.model.Request; 33 | import com.sap.cloud.rest.api.client.model.multipart.EntityPart; 34 | import com.sap.cloud.rest.api.client.model.multipart.MultipartEntity; 35 | 36 | /** 37 | * A builder for {@link Request}s. Initialize using the static methods to create 38 | * a builder for a specific HTTP method. 39 | * 40 | * Supports JSON deserialization for POST, PUT and PATCH requests, using Jackson 41 | * library. To use it pass the type of the object you want to deserialize as a 42 | * {@link Class} object when initializing the builder and then pass an object of 43 | * type {@link T} to the entity method.
44 | * 45 | * Supports multipart requests. To build a multipart {@link Request}, add entity 46 | * parts using the multipartEntity method and build the request with the 47 | * buildMultipart method. 48 | * 49 | * @param 50 | * the type of the {@link Request} that will be build. If no 51 | * {@link Class} object is provided during initialization, T defaults 52 | * to type {@link String}. If multipart, the {@link Request} will be 53 | * of type {@link MultipartEntity} with this generic type. 54 | */ 55 | public class RequestBuilder { 56 | 57 | static final String FAILED_TO_BUILD_REQUEST_OBJECT_MSG = "Failed to build request object. "; 58 | static final String FAILED_TO_PARSE_ENTITY_TO_JSON_MSG = "Failed to parse entity [{0}] to json."; 59 | static final String FAILED_TO_SET_URI_X_MSG = "Failed to set URI. Provided URI [{0}] is invalid."; 60 | 61 | static final String ADDING_QUERY_PARAMS_FAILED_MSG = "Adding query parameters failed."; 62 | static final String URI_IS_NOT_SET_MSG = "URI is not set."; 63 | 64 | static final String ENTITY_DISPLAY_NAME = "Entity"; 65 | static final String NAME_DISPLAY_NAME = "Name"; 66 | 67 | private org.apache.http.client.methods.RequestBuilder requestBuilder; 68 | private MultipartEntityBuilder multipartEntityBuilder; 69 | private EntityBuilder entityBuilder; 70 | 71 | private List parameters; 72 | private ObjectMapper objectMapper; 73 | private List> multipartEntities; 74 | private T entity; 75 | 76 | public static RequestBuilder postRequest(Class clazz) { 77 | return new RequestBuilder(org.apache.http.client.methods.RequestBuilder.post()); 78 | } 79 | 80 | public static RequestBuilder putRequest(Class clazz) { 81 | return new RequestBuilder(org.apache.http.client.methods.RequestBuilder.put()); 82 | } 83 | 84 | public static RequestBuilder patchRequest(Class clazz) { 85 | return new RequestBuilder(org.apache.http.client.methods.RequestBuilder.patch()); 86 | } 87 | 88 | public static RequestBuilder patchRequest() { 89 | return new RequestBuilder<>(org.apache.http.client.methods.RequestBuilder.patch()); 90 | } 91 | 92 | public static RequestBuilder getRequest() { 93 | return new RequestBuilder<>(org.apache.http.client.methods.RequestBuilder.get()); 94 | } 95 | 96 | public static RequestBuilder postRequest() { 97 | return new RequestBuilder<>(org.apache.http.client.methods.RequestBuilder.post()); 98 | } 99 | 100 | public static RequestBuilder putRequest() { 101 | return new RequestBuilder<>(org.apache.http.client.methods.RequestBuilder.put()); 102 | } 103 | 104 | public static RequestBuilder deleteRequest() { 105 | return new RequestBuilder<>(org.apache.http.client.methods.RequestBuilder.delete()); 106 | } 107 | 108 | private RequestBuilder(org.apache.http.client.methods.RequestBuilder requestBuilder) { 109 | this.requestBuilder = requestBuilder; 110 | this.entityBuilder = EntityBuilder.create().setContentType(ContentType.APPLICATION_JSON); 111 | this.multipartEntityBuilder = MultipartEntityBuilder.create(); 112 | 113 | this.parameters = new ArrayList<>(); 114 | this.objectMapper = new ObjectMapper(); 115 | this.multipartEntities = new ArrayList<>(); 116 | this.entity = null; 117 | } 118 | 119 | public RequestBuilder uri(String uri) { 120 | try { 121 | requestBuilder.setUri(uri); 122 | } catch (IllegalArgumentException e) { 123 | throw new RequestBuilderException(format(FAILED_TO_SET_URI_X_MSG, uri), e); 124 | } 125 | return this; 126 | } 127 | 128 | public RequestBuilder uri(URI uri) { 129 | return uri(uri.toString()); 130 | } 131 | 132 | public RequestBuilder addHeader(String name, String value) { 133 | requestBuilder.addHeader(name, value); 134 | return this; 135 | } 136 | 137 | public RequestBuilder addHeader(Header header) { 138 | requestBuilder.addHeader(header); 139 | return this; 140 | } 141 | 142 | public RequestBuilder addHeaders(List
headers) { 143 | for (Header header : headers) { 144 | requestBuilder.addHeader(header); 145 | } 146 | return this; 147 | } 148 | 149 | public RequestBuilder addHeaders(Header[] headers) { 150 | return addHeaders(Arrays.asList(headers)); 151 | } 152 | 153 | public RequestBuilder addParameter(String param, String value) { 154 | parameters.add(new BasicNameValuePair(param, value)); 155 | return this; 156 | } 157 | 158 | public RequestBuilder addParameters(List nvps) { 159 | parameters.addAll(nvps); 160 | return this; 161 | } 162 | 163 | /** 164 | * Sets an entity as request body. If the entity is not of type 165 | * {@link String} it is deserialized using Jackson. 166 | * 167 | * @param entity the request entity 168 | * @return request builder 169 | * @throws RequestBuilderException 170 | * if Jackson fails to parse the provided entity 171 | */ 172 | public RequestBuilder entity(T entity) { 173 | isNotNull(ENTITY_DISPLAY_NAME, entity); 174 | 175 | if (entity instanceof String) { 176 | entityBuilder.setText((String) entity); 177 | this.entity = entity; 178 | return this; 179 | } 180 | try { 181 | entityBuilder.setText(objectMapper.writeValueAsString(entity)); 182 | this.entity = entity; 183 | return this; 184 | } catch (JsonProcessingException e) { 185 | throw new RequestBuilderException(format(FAILED_TO_PARSE_ENTITY_TO_JSON_MSG, entity), e); 186 | } 187 | } 188 | 189 | /** 190 | * Adds an entity part to the request builder in case a multipart request is 191 | * to be created. The {@link Request} object is to be build with the 192 | * buildMultipart() method instead of the normal build() method in order to 193 | * use multipart entities that are set. 194 | * 195 | * @param name the name of the entity part 196 | * @param entity an entity representing the part 197 | * @throws RequestBuilderException 198 | * if Jackson fails to parse the provided entity 199 | * @return RequestBuilder instance. 200 | */ 201 | public RequestBuilder multipartEntity(String name, T entity) { 202 | isNotEmptyOrNull(NAME_DISPLAY_NAME, name); 203 | isNotNull(ENTITY_DISPLAY_NAME, entity); 204 | 205 | if (entity instanceof String) { 206 | multipartEntityBuilder.addTextBody(name, (String) entity); 207 | } else { 208 | try { 209 | String jsonObj = objectMapper.writeValueAsString(entity); 210 | Properties props = objectMapper.readValue(jsonObj, Properties.class); 211 | 212 | ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 213 | props.store(outputStream, null); 214 | ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()); 215 | 216 | multipartEntityBuilder.addPart(name, new InputStreamBody(inputStream, name)); 217 | } catch (IOException e) { 218 | throw new RequestBuilderException(format(FAILED_TO_PARSE_ENTITY_TO_JSON_MSG, entity), e); 219 | } 220 | } 221 | 222 | this.multipartEntities.add(new EntityPart<>(name, entity)); 223 | return this; 224 | } 225 | 226 | /** 227 | * Builds a {@link Request} with generic type {@link T} with the provided 228 | * URI and optionally an request entity, any headers and any query 229 | * parameters if set. 230 | * 231 | * @throws RequestBuilderException 232 | * in case of a problem while building the request 233 | * @return Request instance. 234 | */ 235 | public Request build() { 236 | if (requestBuilder.getUri() == null) { 237 | throw new RequestBuilderException(FAILED_TO_BUILD_REQUEST_OBJECT_MSG + URI_IS_NOT_SET_MSG); 238 | } 239 | if (!parameters.isEmpty()) { 240 | this.uri(getUriWithParametersSet()); 241 | } 242 | if (entity != null) { 243 | requestBuilder.setEntity(entityBuilder.build()); 244 | } 245 | 246 | return new Request<>(requestBuilder.build(), entity); 247 | } 248 | 249 | /** 250 | * Builds a multipart {@link Request} of type {@link MultipartEntity} with 251 | * generic type {@link T} with the provided URI and optionally any request 252 | * entity parts, any headers and any query parameters if set. 253 | * 254 | * @throws RequestBuilderException 255 | * in case of a problem while building the request 256 | * @return Returns multipart request. 257 | */ 258 | public Request> buildMultipart() { 259 | if (requestBuilder.getUri() == null) { 260 | throw new RequestBuilderException(FAILED_TO_BUILD_REQUEST_OBJECT_MSG + URI_IS_NOT_SET_MSG); 261 | } 262 | if (!parameters.isEmpty()) { 263 | this.uri(getUriWithParametersSet()); 264 | } 265 | if (!multipartEntities.isEmpty()) { 266 | requestBuilder.setEntity(multipartEntityBuilder.build()); 267 | } 268 | 269 | return new Request<>(requestBuilder.build(), new MultipartEntity<>(multipartEntities)); 270 | } 271 | 272 | protected String getUriWithParametersSet() { 273 | try { 274 | URI uri = requestBuilder.getUri(); 275 | return URLDecoder.decode(new URIBuilder(uri) 276 | .setParameters(parameters) 277 | .build().toString(), StandardCharsets.UTF_8.name()); 278 | } catch (URISyntaxException | UnsupportedEncodingException e) { 279 | throw new RequestBuilderException(FAILED_TO_BUILD_REQUEST_OBJECT_MSG + ADDING_QUERY_PARAMS_FAILED_MSG, e); 280 | } 281 | } 282 | } 283 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/auth/Authentication.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth; 2 | 3 | import com.sap.cloud.rest.api.client.config.RestApiClientConfig; 4 | 5 | /** 6 | * An interface that represents an authentication used by 7 | * {@link RestApiClientConfig} 8 | * 9 | */ 10 | public interface Authentication { 11 | 12 | /** 13 | * @return Returns the {@link AuthenticationType} value. 14 | */ 15 | AuthenticationType getAuthenticationType(); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/auth/AuthenticationType.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth; 2 | 3 | /** 4 | * An enumerable that represents the supported authentication types 5 | */ 6 | public enum AuthenticationType { 7 | /** 8 | * HTTP Basic Authentication. 9 | */ 10 | BASIC, 11 | /** 12 | * Client Certificate Authentication. 13 | */ 14 | CLIENT_CERT, 15 | /** 16 | * OAuth Client Credentials flow. 17 | */ 18 | OAUTH, 19 | /** 20 | * No authentication. 21 | */ 22 | NO_AUTH 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/auth/basic/BasicAuthentication.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.basic; 2 | 3 | import static com.sap.cloud.rest.api.client.utils.ValidateArgument.isNotEmptyOrNull; 4 | 5 | import java.util.Arrays; 6 | 7 | import com.sap.cloud.rest.api.client.auth.Authentication; 8 | import com.sap.cloud.rest.api.client.auth.AuthenticationType; 9 | import com.sap.cloud.rest.api.client.config.RestApiClientConfig;; 10 | 11 | /** 12 | * A class that represents basic authentication for {@link RestApiClientConfig}. 13 | */ 14 | public class BasicAuthentication implements Authentication { 15 | 16 | private static final String USERNAME_DISPLAY_NAME = "Username"; 17 | private static final String PASSWORD_DISPLAY_NAME = "Password"; 18 | 19 | private final String username; 20 | private final char[] password; 21 | 22 | public BasicAuthentication(String username, char[] password) { 23 | isNotEmptyOrNull(USERNAME_DISPLAY_NAME, username); 24 | isNotEmptyOrNull(PASSWORD_DISPLAY_NAME, password); 25 | 26 | this.username = username; 27 | this.password = password; 28 | } 29 | 30 | public String getUsername() { 31 | return username; 32 | } 33 | 34 | public char[] getPassword() { 35 | return Arrays.copyOf(password, password.length); 36 | } 37 | 38 | @Override 39 | public AuthenticationType getAuthenticationType() { 40 | return AuthenticationType.BASIC; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/auth/basic/BasicHttpClientProvider.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.basic; 2 | 3 | import org.apache.http.auth.AuthScope; 4 | import org.apache.http.auth.UsernamePasswordCredentials; 5 | import org.apache.http.client.CredentialsProvider; 6 | import org.apache.http.client.HttpClient; 7 | import org.apache.http.conn.routing.HttpRoutePlanner; 8 | import org.apache.http.impl.client.BasicCredentialsProvider; 9 | import org.apache.http.impl.client.HttpClientBuilder; 10 | 11 | import com.sap.cloud.rest.api.client.http.HttpClientCreationException; 12 | import com.sap.cloud.rest.api.client.http.HttpClientProvider; 13 | 14 | public class BasicHttpClientProvider extends HttpClientProvider { 15 | 16 | private final String username; 17 | private final char[] password; 18 | 19 | public BasicHttpClientProvider(BasicAuthentication authentication) { 20 | this.username = authentication.getUsername(); 21 | this.password = authentication.getPassword(); 22 | } 23 | 24 | @Override 25 | public HttpClient createHttpClient(HttpRoutePlanner routePlanner) throws HttpClientCreationException { 26 | CredentialsProvider provider = new BasicCredentialsProvider(); 27 | UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(username, String.valueOf(password)); 28 | provider.setCredentials(AuthScope.ANY, credentials); 29 | 30 | return HttpClientBuilder.create() 31 | .useSystemProperties() 32 | .setRoutePlanner(routePlanner) 33 | .setDefaultCredentialsProvider(provider) 34 | .build(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/auth/cert/ClientCertAuthentication.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.cert; 2 | 3 | import static com.sap.cloud.rest.api.client.utils.ValidateArgument.isNotNull; 4 | 5 | import com.sap.cloud.rest.api.client.auth.Authentication; 6 | import com.sap.cloud.rest.api.client.auth.AuthenticationType; 7 | import com.sap.cloud.rest.api.client.config.RestApiClientConfig; 8 | 9 | /** 10 | * A class that represents client cert authentication for 11 | * {@link RestApiClientConfig}. 12 | */ 13 | public class ClientCertAuthentication implements Authentication { 14 | 15 | private static final String KEYSTORE_CONFIG_DISPLAY_NAME = "Keystore configuration"; 16 | 17 | private final KeystoreConfig keystoreConfig; 18 | 19 | /** 20 | * Creates ClientCestAuthentication using specified keystore. 21 | * @param keystoreConfig Keystore configuration. 22 | */ 23 | public ClientCertAuthentication(KeystoreConfig keystoreConfig) { 24 | isNotNull(KEYSTORE_CONFIG_DISPLAY_NAME, keystoreConfig); 25 | 26 | this.keystoreConfig = keystoreConfig; 27 | } 28 | 29 | /** 30 | * @return Returns the {@link KeystoreConfig} 31 | */ 32 | public KeystoreConfig getKeystoreConfig() { 33 | return keystoreConfig; 34 | } 35 | 36 | @Override 37 | public AuthenticationType getAuthenticationType() { 38 | return AuthenticationType.CLIENT_CERT; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/auth/cert/KeystoreConfig.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.cert; 2 | 3 | import static com.sap.cloud.rest.api.client.utils.ValidateArgument.isNotEmptyOrNull; 4 | import static com.sap.cloud.rest.api.client.utils.ValidateArgument.isNotNull; 5 | 6 | import java.security.KeyStore; 7 | import java.util.Arrays; 8 | 9 | /** 10 | * This class represents a configuration object used to configure the key store. 11 | * 12 | */ 13 | public class KeystoreConfig { 14 | 15 | private static final String KEY_ALIAS_DISPLAY_NAME = "Key store alias"; 16 | private static final String KEYSTORE_PASSWORD_DISPLAY_NAME = "Key store password"; 17 | private static final String KEYSTORE_DISPLAY_NAME = "Key store"; 18 | 19 | private final KeyStore keystore; 20 | private final char[] keystorePassword; 21 | private final String keyAlias; 22 | 23 | /** 24 | * Creates new {@link KeystoreConfig} instance with specific password and alias. 25 | * @param keystore Keystore 26 | * @param keystorePassword Keystore password 27 | * @param keyAlias Keystore alias 28 | */ 29 | public KeystoreConfig(KeyStore keystore, char[] keystorePassword, String keyAlias) { 30 | isNotNull(KEYSTORE_DISPLAY_NAME, keystore); 31 | isNotEmptyOrNull(KEYSTORE_PASSWORD_DISPLAY_NAME, keystorePassword); 32 | isNotEmptyOrNull(KEY_ALIAS_DISPLAY_NAME, keyAlias); 33 | 34 | this.keystore = keystore; 35 | this.keystorePassword = keystorePassword; 36 | this.keyAlias = keyAlias; 37 | } 38 | 39 | /** 40 | * @return Returns the keystore. 41 | */ 42 | public KeyStore getKeystore() { 43 | return keystore; 44 | } 45 | 46 | /** 47 | * @return Returns the keystore password. 48 | */ 49 | public char[] getKeystorePassword() { 50 | return Arrays.copyOf(keystorePassword, keystorePassword.length); 51 | } 52 | 53 | /** 54 | * @return Returns the keystore alias. 55 | */ 56 | public String getKeyAlias() { 57 | return keyAlias; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/auth/cert/KeystoreConfigBuilder.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.cert; 2 | 3 | import java.security.KeyStore; 4 | 5 | /** 6 | * A builder for @{link {@link KeystoreConfig}. 7 | */ 8 | public class KeystoreConfigBuilder { 9 | 10 | private KeyStore keystore; 11 | private char[] keystorePassword; 12 | private String keyAlias; 13 | 14 | /** 15 | * Attaches a key store to the builder. 16 | * @param keystore key store 17 | * @return Returns {@link KeystoreConfigBuilder} 18 | */ 19 | public KeystoreConfigBuilder keystore(KeyStore keystore) { 20 | this.keystore = keystore; 21 | return this; 22 | } 23 | 24 | /** 25 | * Attaches a key store password to the builder. 26 | * @param keystorePassword key store password 27 | * @return Returns {@link KeystoreConfigBuilder} 28 | */ 29 | public KeystoreConfigBuilder keystorePassword(char[] keystorePassword) { 30 | this.keystorePassword = keystorePassword; 31 | return this; 32 | } 33 | 34 | /** 35 | * Attaches a key store alias to the builder. 36 | * @param keyAlias key store alias 37 | * @return Returns {@link KeystoreConfigBuilder} 38 | */ 39 | public KeystoreConfigBuilder keyAlias(String keyAlias) { 40 | this.keyAlias = keyAlias; 41 | return this; 42 | } 43 | 44 | /** 45 | * Builds a {@link KeystoreConfig} with the provided key store, password and 46 | * alias. 47 | * @return Returns {@link KeystoreConfig} 48 | */ 49 | public KeystoreConfig build() { 50 | return new KeystoreConfig(keystore, keystorePassword, keyAlias); 51 | } 52 | 53 | /** 54 | * Returns an instance of {@link KeystoreConfigBuilder}. 55 | * @return Returns {@link KeystoreConfigBuilder} 56 | */ 57 | public static KeystoreConfigBuilder getBuilder() { 58 | return new KeystoreConfigBuilder(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/auth/cert/SSLHttpClientProvider.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.cert; 2 | 3 | import java.net.Socket; 4 | import java.security.GeneralSecurityException; 5 | import java.security.KeyManagementException; 6 | import java.security.KeyStore; 7 | import java.security.KeyStoreException; 8 | import java.security.NoSuchAlgorithmException; 9 | import java.security.UnrecoverableKeyException; 10 | import java.util.Map; 11 | 12 | import javax.net.ssl.SSLContext; 13 | 14 | import org.apache.http.client.HttpClient; 15 | import org.apache.http.client.config.RequestConfig; 16 | import org.apache.http.conn.routing.HttpRoutePlanner; 17 | import org.apache.http.impl.client.HttpClients; 18 | import org.apache.http.ssl.PrivateKeyDetails; 19 | import org.apache.http.ssl.PrivateKeyStrategy; 20 | import org.apache.http.ssl.SSLContexts; 21 | 22 | import com.sap.cloud.rest.api.client.http.HttpClientCreationException; 23 | import com.sap.cloud.rest.api.client.http.HttpClientProvider; 24 | 25 | /** 26 | * Creates HTTP Client with Mutual TLS authentication. 27 | */ 28 | public class SSLHttpClientProvider extends HttpClientProvider { 29 | 30 | private static final String SSL_CONTEXT_ERROR_MESSAGE = "Could not create SSLContext"; 31 | 32 | private static final int DEFAULT_TIMEOUT_MILLIS = 30000; 33 | 34 | private KeystoreConfig keystoreConfig; 35 | private int timeoutInMillis; 36 | 37 | /** 38 | * Constructor using Client Certificate Authentication configuration. 39 | * @param authentication Client Certificate Authentication configuration. 40 | */ 41 | public SSLHttpClientProvider(ClientCertAuthentication authentication) { 42 | this(authentication, DEFAULT_TIMEOUT_MILLIS); 43 | } 44 | 45 | /** 46 | * Constructor using Client Certificate Authentication configuration. 47 | * @param authentication authentication Client Certificate Authentication configuration. 48 | * @param timeoutInMillis Client timeout in milliseconds. 49 | */ 50 | public SSLHttpClientProvider(ClientCertAuthentication authentication, int timeoutInMillis) { 51 | this.keystoreConfig = authentication.getKeystoreConfig(); 52 | this.timeoutInMillis = timeoutInMillis; 53 | } 54 | 55 | @Override 56 | public HttpClient createHttpClient(HttpRoutePlanner routePlanner) throws HttpClientCreationException { 57 | try { 58 | return HttpClients.custom() 59 | .useSystemProperties() 60 | .setRoutePlanner(routePlanner) 61 | .setDefaultRequestConfig(createRequestConfig()) 62 | .setSSLContext(createSSLContext()) 63 | .build(); 64 | } catch (GeneralSecurityException e) { 65 | throw new HttpClientCreationException(SSL_CONTEXT_ERROR_MESSAGE, e); 66 | } 67 | } 68 | 69 | private SSLContext createSSLContext() throws KeyManagementException, UnrecoverableKeyException, 70 | NoSuchAlgorithmException, KeyStoreException { 71 | KeyStore keystore = keystoreConfig.getKeystore(); 72 | 73 | return SSLContexts.custom() 74 | .loadKeyMaterial(keystore, keystoreConfig.getKeystorePassword(), privateKeyStrategy()) 75 | .build(); 76 | } 77 | 78 | private PrivateKeyStrategy privateKeyStrategy() { 79 | return (Map aliases, Socket socket) -> keystoreConfig.getKeyAlias(); 80 | } 81 | 82 | private RequestConfig createRequestConfig() { 83 | return RequestConfig.custom() 84 | .setConnectTimeout(timeoutInMillis) 85 | .setConnectionRequestTimeout(timeoutInMillis) 86 | .setSocketTimeout(timeoutInMillis) 87 | .build(); 88 | } 89 | } -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/auth/none/NoAuthHttpClientProvider.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.none; 2 | 3 | import org.apache.http.client.HttpClient; 4 | import org.apache.http.conn.routing.HttpRoutePlanner; 5 | import org.apache.http.impl.client.HttpClients; 6 | 7 | import com.sap.cloud.rest.api.client.http.HttpClientCreationException; 8 | import com.sap.cloud.rest.api.client.http.HttpClientProvider; 9 | 10 | public class NoAuthHttpClientProvider extends HttpClientProvider { 11 | 12 | @Override 13 | public HttpClient createHttpClient(HttpRoutePlanner routePlanner) throws HttpClientCreationException { 14 | return HttpClients.custom() 15 | .useSystemProperties() 16 | .setRoutePlanner(routePlanner) 17 | .build(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/auth/none/NoAuthentication.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.none; 2 | 3 | import com.sap.cloud.rest.api.client.auth.Authentication; 4 | import com.sap.cloud.rest.api.client.auth.AuthenticationType; 5 | import com.sap.cloud.rest.api.client.config.RestApiClientConfig; 6 | 7 | /** 8 | * A class that represents no authentication for {@link RestApiClientConfig}. 9 | */ 10 | public class NoAuthentication implements Authentication { 11 | 12 | @Override 13 | public AuthenticationType getAuthenticationType() { 14 | return AuthenticationType.NO_AUTH; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/auth/oauth/AccessTokenProvider.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.oauth; 2 | 3 | public interface AccessTokenProvider { 4 | 5 | String retrieveAccessToken(); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/auth/oauth/AccessTokenProviderFactory.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.oauth; 2 | 3 | import static java.text.MessageFormat.format; 4 | 5 | import com.sap.cloud.rest.api.client.auth.Authentication; 6 | import com.sap.cloud.rest.api.client.auth.AuthenticationType; 7 | import com.sap.cloud.rest.api.client.config.RestApiClientConfig; 8 | import com.sap.cloud.rest.api.client.config.RestApiClientConfigBuilder; 9 | import com.sap.cloud.rest.api.client.http.HttpClientProvider; 10 | 11 | public class AccessTokenProviderFactory { 12 | 13 | static final String NON_OAUTH_AUTHENTICATION_MSG = "The provided configuration is required to have an OAuth authentication and it has [{0}] authentication type instead."; 14 | 15 | public static ClientCredentialsAccessTokenProvider createClientCredentialsAccessTokenProvider( 16 | RestApiClientConfig config) { 17 | OAuthAuthentication oAuthAuthentication = extractOAuthAuthentication(config); 18 | OAuthServerConfig oAuthServerConfig = oAuthAuthentication.getOAuthServerConfig(); 19 | 20 | RestApiClientConfig restApiClientConfig = RestApiClientConfigBuilder.getBuilder() 21 | .host(oAuthServerConfig.getOAuthServerHost()) 22 | .basicAuthentication(oAuthServerConfig.getClientID(), oAuthServerConfig.getClientSecret()) 23 | .proxy(config.getRoutePlanner()) 24 | .build(); 25 | 26 | return new ClientCredentialsAccessTokenProvider(restApiClientConfig, getApiPath(oAuthAuthentication)); 27 | } 28 | 29 | public static ClientCredentialsAccessTokenProvider createClientCredentialsAccessTokenProvider( 30 | RestApiClientConfig config, HttpClientProvider httpClientProvider) { 31 | OAuthAuthentication oAuthAuthentication = extractOAuthAuthentication(config); 32 | OAuthServerConfig oAuthServerConfig = oAuthAuthentication.getOAuthServerConfig(); 33 | 34 | RestApiClientConfig restApiClientConfig = RestApiClientConfigBuilder.getBuilder() 35 | .host(oAuthServerConfig.getOAuthServerHost()) 36 | .basicAuthentication(oAuthServerConfig.getClientID(), oAuthServerConfig.getClientSecret()) 37 | .proxy(config.getRoutePlanner()) 38 | .build(); 39 | 40 | return new ClientCredentialsAccessTokenProvider(restApiClientConfig, httpClientProvider, 41 | getApiPath(oAuthAuthentication)); 42 | } 43 | 44 | private static OAuthAuthentication extractOAuthAuthentication(RestApiClientConfig config) { 45 | Authentication authentication = config.getAuthentication(); 46 | AuthenticationType authenticationType = authentication.getAuthenticationType(); 47 | if (authenticationType != AuthenticationType.OAUTH) { 48 | throw new IllegalArgumentException(format(NON_OAUTH_AUTHENTICATION_MSG, authenticationType)); 49 | } 50 | return (OAuthAuthentication) config.getAuthentication(); 51 | } 52 | 53 | private static String getApiPath(OAuthAuthentication oauthAuthentication) { 54 | return oauthAuthentication.getOAuthServerConfig().getoAuthServerApiPath(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/auth/oauth/AccessTokenResponseDto.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.oauth; 2 | 3 | import java.util.Objects; 4 | 5 | import com.fasterxml.jackson.annotation.JsonCreator; 6 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 7 | import com.fasterxml.jackson.annotation.JsonProperty; 8 | 9 | @JsonIgnoreProperties(ignoreUnknown = true) 10 | public final class AccessTokenResponseDto { 11 | 12 | private static final String ACCESS_TOKEN_JSON_PROPERTY = "access_token"; 13 | 14 | private final String accessToken; 15 | 16 | @JsonCreator 17 | public AccessTokenResponseDto( 18 | @JsonProperty(value = ACCESS_TOKEN_JSON_PROPERTY, required = true) final String accessToken) { 19 | this.accessToken = accessToken; 20 | } 21 | 22 | @JsonProperty(value = ACCESS_TOKEN_JSON_PROPERTY) 23 | public String getAccessToken() { 24 | return accessToken; 25 | } 26 | 27 | @Override 28 | public boolean equals(Object o) { 29 | if (this == o) return true; 30 | if (o == null || getClass() != o.getClass()) return false; 31 | AccessTokenResponseDto jwtToken = (AccessTokenResponseDto) o; 32 | return Objects.equals(accessToken, jwtToken.accessToken); 33 | } 34 | 35 | @Override 36 | public int hashCode() { 37 | return Objects.hash(accessToken); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/auth/oauth/ClientCredentialsAccessTokenProvider.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.oauth; 2 | 3 | import com.sap.cloud.rest.api.client.RequestBuilder; 4 | import com.sap.cloud.rest.api.client.RestApiClient; 5 | import com.sap.cloud.rest.api.client.config.RestApiClientConfig; 6 | import com.sap.cloud.rest.api.client.http.HttpClientProvider; 7 | import com.sap.cloud.rest.api.client.model.Request; 8 | import com.sap.cloud.rest.api.client.utils.JacksonJsonResponseHandler; 9 | 10 | public class ClientCredentialsAccessTokenProvider extends RestApiClient implements AccessTokenProvider { 11 | 12 | private static final String RESPONSE_TYPE = "response_type"; 13 | private static final String TOKEN = "token"; 14 | 15 | private static final String GRANT_TYPE = "grant_type"; 16 | private static final String CLIENT_CREDENTIALS = "client_credentials"; 17 | 18 | private String apiPath; 19 | 20 | public ClientCredentialsAccessTokenProvider(RestApiClientConfig restApiClientConfig, String apiPath) { 21 | super(restApiClientConfig); 22 | 23 | this.apiPath = apiPath; 24 | } 25 | 26 | public ClientCredentialsAccessTokenProvider(RestApiClientConfig restApiClientConfig, 27 | HttpClientProvider httpClientProvider, String apiPath) { 28 | super(restApiClientConfig, httpClientProvider); 29 | 30 | this.apiPath = apiPath; 31 | } 32 | 33 | @Override 34 | public String retrieveAccessToken() { 35 | Request retrieveAccessTokenRequest = getAccessTokenRequestBuilder().build(); 36 | 37 | AccessTokenResponseDto accessTokenResponse = execute(retrieveAccessTokenRequest, 38 | new JacksonJsonResponseHandler<>(AccessTokenResponseDto.class)).getEntity(); 39 | return accessTokenResponse.getAccessToken(); 40 | } 41 | 42 | public RequestBuilder getAccessTokenRequestBuilder() { 43 | return RequestBuilder 44 | .postRequest() 45 | .uri(buildRequestUri()) 46 | .addParameter(GRANT_TYPE, CLIENT_CREDENTIALS) 47 | .addParameter(RESPONSE_TYPE, TOKEN); 48 | } 49 | 50 | @Override 51 | protected String getApiPath() { 52 | return apiPath; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/auth/oauth/OAuthAuthentication.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.oauth; 2 | 3 | import static com.sap.cloud.rest.api.client.utils.ValidateArgument.isNotNull; 4 | 5 | import com.sap.cloud.rest.api.client.auth.Authentication; 6 | import com.sap.cloud.rest.api.client.auth.AuthenticationType; 7 | import com.sap.cloud.rest.api.client.config.RestApiClientConfig; 8 | 9 | /** 10 | * A class that represents OAuth authentication for {@link RestApiClientConfig}. 11 | * Requires {@link OAuthServerConfig}. 12 | */ 13 | public class OAuthAuthentication implements Authentication { 14 | 15 | private static final String OAUTH_SERVER_CONFIG_DISPLAY_NAME = "OAuth Server Config"; 16 | 17 | private final OAuthServerConfig oauthConfig; 18 | 19 | public OAuthAuthentication(OAuthServerConfig config) { 20 | isNotNull(OAUTH_SERVER_CONFIG_DISPLAY_NAME, config); 21 | 22 | this.oauthConfig = config; 23 | } 24 | 25 | @Override 26 | public AuthenticationType getAuthenticationType() { 27 | return AuthenticationType.OAUTH; 28 | } 29 | 30 | public OAuthServerConfig getOAuthServerConfig() { 31 | return this.oauthConfig; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/auth/oauth/OAuthHeaderProviderRequestInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.oauth; 2 | 3 | import org.apache.http.HttpRequest; 4 | import org.apache.http.HttpRequestInterceptor; 5 | import org.apache.http.protocol.HttpContext; 6 | 7 | /** 8 | * HTTP request interceptor called during the Rest API Client execution in case 9 | * of OAuth authentication. It retrieves the access token and adds it as a 10 | * Bearer header to the request. The header key is provided in the constructor. 11 | * 12 | */ 13 | public class OAuthHeaderProviderRequestInterceptor implements HttpRequestInterceptor { 14 | 15 | private static final String BEARER_HEADER_PREFIX = "Bearer "; 16 | 17 | private final AccessTokenProvider accessTokenProvider; 18 | private final String oAuthHeaderKey; 19 | 20 | public OAuthHeaderProviderRequestInterceptor(AccessTokenProvider accessTokenProvider, String oAuthHeaderKey) { 21 | this.accessTokenProvider = accessTokenProvider; 22 | this.oAuthHeaderKey = oAuthHeaderKey; 23 | } 24 | 25 | @Override 26 | public void process(final HttpRequest request, final HttpContext context) { 27 | request.addHeader(oAuthHeaderKey, BEARER_HEADER_PREFIX + accessTokenProvider.retrieveAccessToken()); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/auth/oauth/OAuthHttpClientProvider.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.oauth; 2 | 3 | import org.apache.http.HttpHeaders; 4 | import org.apache.http.client.HttpClient; 5 | import org.apache.http.conn.routing.HttpRoutePlanner; 6 | import org.apache.http.impl.client.HttpClientBuilder; 7 | 8 | import com.sap.cloud.rest.api.client.http.HttpClientCreationException; 9 | import com.sap.cloud.rest.api.client.http.HttpClientProvider; 10 | 11 | public class OAuthHttpClientProvider extends HttpClientProvider { 12 | 13 | private final AccessTokenProvider accessTokenProvider; 14 | private final String oAuthHeaderKey; 15 | 16 | public OAuthHttpClientProvider(AccessTokenProvider accessTokenProvider) { 17 | this(accessTokenProvider, HttpHeaders.AUTHORIZATION); 18 | } 19 | 20 | public OAuthHttpClientProvider(AccessTokenProvider accessTokenProvider, String oAuthHeaderKey) { 21 | this.accessTokenProvider = accessTokenProvider; 22 | this.oAuthHeaderKey = oAuthHeaderKey; 23 | } 24 | 25 | @Override 26 | public HttpClient createHttpClient(HttpRoutePlanner routePlanner) throws HttpClientCreationException { 27 | return HttpClientBuilder.create() 28 | .useSystemProperties() 29 | .setRoutePlanner(routePlanner) 30 | .addInterceptorLast(new OAuthHeaderProviderRequestInterceptor(accessTokenProvider, oAuthHeaderKey)) 31 | .build(); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/auth/oauth/OAuthServerConfig.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.oauth; 2 | 3 | import static com.sap.cloud.rest.api.client.utils.ValidateArgument.isNotEmptyOrNull; 4 | import static com.sap.cloud.rest.api.client.utils.ValidateArgument.isNotNull; 5 | import static com.sap.cloud.rest.api.client.utils.ValidateArgument.isValidUrl; 6 | 7 | import org.apache.http.HttpHeaders; 8 | 9 | /** 10 | * This class represents a configuration object used to configure an 11 | * {@link AccessTokenProvider}. 12 | * 13 | */ 14 | public class OAuthServerConfig { 15 | 16 | static final String CLIENT_SECRET_DISPLAY_NAME = "Client secret"; 17 | static final String CLIENT_ID_DISPLAY_NAME = "Client ID"; 18 | static final String OAUTH_SERVER_HOST_DISPLAY_NAME = "OAuth server host"; 19 | static final String OAUTH_SERVER_API_PATH_DISPLAY_NAME = "OAuth server API path"; 20 | static final String OAUTH_HEADER_KEY_DISPLAY_NAME = "OAuth server host"; 21 | 22 | static final String DEFAULT_OAUTH_SERVER_API_PATH = "/oauth/token"; 23 | static final String DEFAULT_OAUTH_HEADER_KEY = HttpHeaders.AUTHORIZATION; 24 | 25 | private final String oAuthServerHost; 26 | private final String oAuthServerApiPath; 27 | private final String oAuthHeaderKey; 28 | private final String clientID; 29 | private final char[] clientSecret; 30 | 31 | /** 32 | * This constructor allows omitting the API path and header key. In this 33 | * case, /oauth/token is used for API path and Authorization 34 | * for header key as the default values. 35 | * @param oAuthServerHost OAuth server host. 36 | * @param clientID Client ID. 37 | * @param clientSecret Client secret. 38 | */ 39 | public OAuthServerConfig(final String oAuthServerHost, final String clientID, final char[] clientSecret) { 40 | this(oAuthServerHost, DEFAULT_OAUTH_SERVER_API_PATH, clientID, clientSecret); 41 | } 42 | 43 | /** 44 | * This constructor allows omitting the header key. In this case, 45 | * Authorization is used for header key as the default value. 46 | * @param oAuthServerHost OAuth server host. 47 | * @param oAuthServerApiPath API Path 48 | * @param clientID Client ID. 49 | * @param clientSecret Client secret. 50 | */ 51 | public OAuthServerConfig(final String oAuthServerHost, final String oAuthServerApiPath, final String clientID, 52 | final char[] clientSecret) { 53 | this(oAuthServerHost, oAuthServerApiPath, clientID, clientSecret, DEFAULT_OAUTH_HEADER_KEY); 54 | } 55 | 56 | /** 57 | * This constructor allows omitting the API path. In this case, 58 | * /oauth/token is used the API path as the default value. 59 | * @param oAuthServerHost OAuth server host. 60 | * @param clientID Client ID. 61 | * @param clientSecret Client secret. 62 | * @param oAuthHeaderKey OAuth Header key. 63 | */ 64 | public OAuthServerConfig(final String oAuthServerHost, final String clientID, final char[] clientSecret, 65 | final String oAuthHeaderKey) { 66 | this(oAuthServerHost, DEFAULT_OAUTH_SERVER_API_PATH, clientID, clientSecret, oAuthHeaderKey); 67 | } 68 | 69 | /** 70 | * Fill OAuth server configuration constructor. 71 | * @param oAuthServerHost OAuth server host. 72 | * @param oAuthServerApiPath API Path 73 | * @param clientID Client ID. 74 | * @param clientSecret Client secret. 75 | * @param oAuthHeaderKey OAuth Header key. 76 | */ 77 | public OAuthServerConfig(final String oAuthServerHost, final String oAuthServerApiPath, final String clientID, 78 | final char[] clientSecret, final String oAuthHeaderKey) { 79 | isNotEmptyOrNull(OAUTH_SERVER_HOST_DISPLAY_NAME, oAuthServerHost); 80 | isNotNull(OAUTH_SERVER_API_PATH_DISPLAY_NAME, oAuthServerApiPath); 81 | isNotEmptyOrNull(OAUTH_HEADER_KEY_DISPLAY_NAME, oAuthHeaderKey); 82 | isNotEmptyOrNull(CLIENT_ID_DISPLAY_NAME, clientID); 83 | isNotNull(CLIENT_SECRET_DISPLAY_NAME, clientSecret); 84 | isValidUrl(OAUTH_SERVER_HOST_DISPLAY_NAME, oAuthServerHost); 85 | 86 | this.oAuthServerHost = oAuthServerHost; 87 | this.oAuthServerApiPath = oAuthServerApiPath; 88 | this.oAuthHeaderKey = oAuthHeaderKey; 89 | this.clientID = clientID; 90 | this.clientSecret = clientSecret; 91 | } 92 | 93 | public String getOAuthServerHost() { 94 | return oAuthServerHost; 95 | } 96 | 97 | public String getoAuthServerApiPath() { 98 | return oAuthServerApiPath; 99 | } 100 | 101 | public String getClientID() { 102 | return clientID; 103 | } 104 | 105 | public char[] getClientSecret() { 106 | return clientSecret.clone(); 107 | } 108 | 109 | public String getoAuthHeaderKey() { 110 | return oAuthHeaderKey; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/auth/oauth/OAuthServerConfigBuilder.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.oauth; 2 | 3 | import java.net.URL; 4 | 5 | /** 6 | * A builder for @{link OAuthServerConfig}. 7 | */ 8 | public class OAuthServerConfigBuilder { 9 | 10 | private String oAuthServerHost; 11 | private String oAuthServerApiPath; 12 | private String oAuthHeaderKey; 13 | private String clientID; 14 | private char[] clientSecret; 15 | 16 | /** 17 | * Attaches an OAuth Server Host to the builder. 18 | * @param oAuthServerHost OAuth Server host. 19 | * @return {@link OAuthServerConfigBuilder} instance. 20 | */ 21 | public OAuthServerConfigBuilder oAuthServerHost(final URL oAuthServerHost) { 22 | final String protocol = oAuthServerHost.getProtocol(); 23 | final String host = oAuthServerHost.getHost(); 24 | final int port = oAuthServerHost.getPort(); 25 | 26 | this.oAuthServerHost = protocol + "://" + host; 27 | if (port > 0) { 28 | this.oAuthServerHost += ":" + port; 29 | } 30 | return this; 31 | } 32 | 33 | /** 34 | * Attaches an OAuth Server Host to the builder. 35 | * @param oAuthServerHost OAuth Server host. 36 | * @return {@link OAuthServerConfigBuilder} instance. 37 | */ 38 | public OAuthServerConfigBuilder oAuthServerHost(final String oAuthServerHost) { 39 | this.oAuthServerHost = oAuthServerHost; 40 | return this; 41 | } 42 | 43 | /** 44 | * Attaches an OAuth Server API path to the builder. 45 | * @param oAuthServerApiPath OAuth Server API path 46 | * @return {@link OAuthServerConfigBuilder} instance. 47 | */ 48 | public OAuthServerConfigBuilder oAuthServerApiPath(final String oAuthServerApiPath) { 49 | this.oAuthServerApiPath = oAuthServerApiPath; 50 | return this; 51 | } 52 | 53 | /** 54 | * Attaches a client ID to the builder. 55 | * @param clientID client ID 56 | * @return {@link OAuthServerConfigBuilder} instance. 57 | */ 58 | public OAuthServerConfigBuilder clientID(final String clientID) { 59 | this.clientID = clientID; 60 | return this; 61 | } 62 | 63 | /** 64 | * Attaches a client secret to the builder. 65 | * @param clientSecret a client secret 66 | * @return {@link OAuthServerConfigBuilder} instance. 67 | */ 68 | public OAuthServerConfigBuilder clientSecret(final char[] clientSecret) { 69 | this.clientSecret = clientSecret; 70 | return this; 71 | } 72 | 73 | /** 74 | * Attaches a custom OAuth header to the builder 75 | * @param oAuthHeaderKey custom OAuth header. 76 | * @return {@link OAuthServerConfigBuilder} instance. 77 | */ 78 | public OAuthServerConfigBuilder oAuthHeaderKey(String oAuthHeaderKey) { 79 | this.oAuthHeaderKey = oAuthHeaderKey; 80 | return this; 81 | } 82 | 83 | /** 84 | * Builds a {@link OAuthServerConfig} with the provided OAuth Server Host, 85 | * OAuth Server API Path, client ID and client secret and OAuth Header key. 86 | * If API path or OAuth Header key are not provided, the default ones from 87 | * {@link OAuthServerConfig} are used. 88 | * @return {@link OAuthServerConfig} instance. 89 | */ 90 | public OAuthServerConfig build() { 91 | if (oAuthServerApiPath != null && oAuthHeaderKey != null) { 92 | return new OAuthServerConfig(oAuthServerHost, oAuthServerApiPath, clientID, clientSecret, oAuthHeaderKey); 93 | } 94 | if (oAuthServerApiPath != null) { 95 | return new OAuthServerConfig(oAuthServerHost, oAuthServerApiPath, clientID, clientSecret); 96 | } 97 | if (oAuthHeaderKey != null) { 98 | return new OAuthServerConfig(oAuthServerHost, clientID, clientSecret, oAuthHeaderKey); 99 | } 100 | return new OAuthServerConfig(oAuthServerHost, clientID, clientSecret); 101 | } 102 | 103 | /** 104 | * @return Returns an instance of {@link OAuthServerConfigBuilder}. 105 | */ 106 | public static OAuthServerConfigBuilder getBuilder() { 107 | return new OAuthServerConfigBuilder(); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/config/AbstractRestApiClientConfigBuilder.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.config; 2 | 3 | import java.net.URL; 4 | 5 | import org.apache.http.HttpHost; 6 | import org.apache.http.conn.routing.HttpRoutePlanner; 7 | import org.apache.http.impl.conn.DefaultProxyRoutePlanner; 8 | 9 | import com.sap.cloud.rest.api.client.auth.Authentication; 10 | import com.sap.cloud.rest.api.client.auth.basic.BasicAuthentication; 11 | import com.sap.cloud.rest.api.client.auth.cert.ClientCertAuthentication; 12 | import com.sap.cloud.rest.api.client.auth.cert.KeystoreConfig; 13 | import com.sap.cloud.rest.api.client.auth.none.NoAuthentication; 14 | import com.sap.cloud.rest.api.client.auth.oauth.OAuthAuthentication; 15 | import com.sap.cloud.rest.api.client.auth.oauth.OAuthServerConfig; 16 | import com.sap.cloud.rest.api.client.http.Proxy; 17 | 18 | /** 19 | * A builder for {@link RestApiClientConfig}. 20 | */ 21 | public abstract class AbstractRestApiClientConfigBuilder, Configuration extends RestApiClientConfig> { 22 | 23 | protected String host; 24 | protected Authentication authentication; 25 | protected HttpRoutePlanner routePlanner; 26 | 27 | /** 28 | * Attaches the host for the configuration to the builder. 29 | * 30 | * @param hostUrl 31 | * the host that will be used by the client 32 | * @return Builder instance. 33 | */ 34 | public Builder host(URL hostUrl) { 35 | final String protocol = hostUrl.getProtocol(); 36 | final String host = hostUrl.getHost(); 37 | final int port = hostUrl.getPort(); 38 | 39 | String hostString = protocol + "://" + host; 40 | if (port > 0) { 41 | hostString += ":" + port; 42 | } 43 | 44 | return host(hostString); 45 | } 46 | 47 | /** 48 | * Attaches the host for the configuration to the builder. 49 | * 50 | * @param host 51 | * the host that will be used by the client 52 | * @return Builder instance. 53 | */ 54 | public Builder host(String host) { 55 | this.host = host; 56 | return self(); 57 | } 58 | 59 | /** 60 | * Attaches the provided authentication to the builder. 61 | * @param authentication authentication configuration. 62 | * @return Builder instance. 63 | */ 64 | public Builder authentication(Authentication authentication) { 65 | this.authentication = authentication; 66 | return self(); 67 | } 68 | 69 | /** 70 | * Attaches a {@link BasicAuthentication} as the authentication type for the 71 | * configuration to the builder. 72 | * 73 | * @param username 74 | * the username used to create the Authorization header 75 | * @param password 76 | * the password used to create the Authorization header 77 | * @return Builder instance. 78 | */ 79 | public Builder basicAuthentication(String username, char[] password) { 80 | return authentication(new BasicAuthentication(username, password)); 81 | } 82 | 83 | /** 84 | * Attaches an {@link OAuthAuthentication} as the authentication type for 85 | * the configuration to the builder. 86 | * 87 | * @param oAuthServerConfig 88 | * the {@link OAuthServerConfig} needed for creation of 89 | * {@link OAuthAuthentication} 90 | * @return Builder instance. 91 | */ 92 | public Builder oAuthAuthentication(OAuthServerConfig oAuthServerConfig) { 93 | return authentication(new OAuthAuthentication(oAuthServerConfig)); 94 | } 95 | 96 | /** 97 | * Attaches a {@link ClientCertAuthentication} as the authentication type 98 | * for the configuration to the builder. 99 | * 100 | * @param keystoreConfig 101 | * the key store configuration used to the set the SSL context 102 | * @return Builder instance. 103 | */ 104 | public Builder clientCertAuthentication(KeystoreConfig keystoreConfig) { 105 | return authentication(new ClientCertAuthentication(keystoreConfig)); 106 | } 107 | 108 | /** 109 | * Attaches {@link NoAuthentication} as the authentication type for the 110 | * configuration to the builder. 111 | * @return Builder instance. 112 | */ 113 | public Builder noAuthentication() { 114 | return authentication(new NoAuthentication()); 115 | } 116 | 117 | /** 118 | * Attaches a proxy route planner, with an {@link HttpHost} created using 119 | * the provided {@link Proxy}, to the builder. 120 | * @param proxy Proxy 121 | * @return Builder instance. 122 | */ 123 | public Builder proxy(Proxy proxy) { 124 | if (proxy != null) { 125 | HttpHost httpHost = new HttpHost(proxy.getProxyHost(), proxy.getProxyPort(), 126 | proxy.getProxyScheme()); 127 | this.routePlanner = new DefaultProxyRoutePlanner(httpHost); 128 | } 129 | return self(); 130 | } 131 | 132 | /** 133 | * Attaches a proxy route planner using the provided 134 | * {@link HttpRoutePlanner}, to the builder. 135 | * @param routePlanner Route planner 136 | * @return Builder instance. 137 | */ 138 | public Builder proxy(HttpRoutePlanner routePlanner) { 139 | this.routePlanner = routePlanner; 140 | return self(); 141 | } 142 | 143 | /** 144 | * Override to return an instance of {@link Configuration} with the attached 145 | * to the builder host, authentication and any subclass properties. 146 | * @return Configuration instance. 147 | */ 148 | public abstract Configuration build(); 149 | 150 | /** 151 | * Override to return the instance of the subclass {@link Builder}. 152 | * @return Builder instance. 153 | */ 154 | protected abstract Builder self(); 155 | } 156 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/config/RestApiClientConfig.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.config; 2 | 3 | import static com.sap.cloud.rest.api.client.utils.ValidateArgument.isNotEmptyOrNull; 4 | import static com.sap.cloud.rest.api.client.utils.ValidateArgument.isNotNull; 5 | 6 | import org.apache.http.conn.routing.HttpRoutePlanner; 7 | import org.apache.http.impl.conn.DefaultRoutePlanner; 8 | import org.apache.http.impl.conn.DefaultSchemePortResolver; 9 | 10 | import com.sap.cloud.rest.api.client.RestApiClient; 11 | import com.sap.cloud.rest.api.client.auth.Authentication; 12 | import com.sap.cloud.rest.api.client.auth.none.NoAuthentication; 13 | 14 | /** 15 | * This class represents a configuration object used to configure the 16 | * {@link RestApiClient}. 17 | * 18 | */ 19 | public class RestApiClientConfig { 20 | 21 | static final String HOST_DISPLAY_NAME = "Host"; 22 | static final String AUTHENTICATION_DISPLAY_NAME = "Authentication"; 23 | static final String ROUTE_PLANNER_DISPLAY_NAME = "Route Planner"; 24 | 25 | private final String host; 26 | private final Authentication authentication; 27 | private final HttpRoutePlanner routePlanner; 28 | 29 | /** 30 | * Creates a {@link RestApiClientConfig} instance with the given host, 31 | * {@link NoAuthentication} for authentication and default route planner. 32 | * @param host Endpoint host. 33 | */ 34 | public RestApiClientConfig(String host) { 35 | this(host, new NoAuthentication()); 36 | } 37 | 38 | /** 39 | * Creates a {@link RestApiClientConfig} instance with the given host and 40 | * route planner and {@link NoAuthentication} for authentication. 41 | * @param host Endpoint host. 42 | * @param routePlanner Route planner. 43 | */ 44 | public RestApiClientConfig(String host, HttpRoutePlanner routePlanner) { 45 | this(host, new NoAuthentication(), routePlanner); 46 | } 47 | 48 | /** 49 | * Creates a {@link RestApiClientConfig} instance with the given host and 50 | * authentication and the default route planner. 51 | * @param host Endpoint host. 52 | * @param authentication Authentication configuration. 53 | */ 54 | public RestApiClientConfig(String host, Authentication authentication) { 55 | this(host, authentication, new DefaultRoutePlanner(DefaultSchemePortResolver.INSTANCE)); 56 | } 57 | 58 | /** 59 | * Creates a {@link RestApiClientConfig} instance with the given host, 60 | * authentication and route planner. 61 | * @param host Endpoint host. 62 | * @param authentication Authentication configuration. 63 | * @param routePlanner Route planner. 64 | */ 65 | public RestApiClientConfig(String host, Authentication authentication, HttpRoutePlanner routePlanner) { 66 | isNotEmptyOrNull(HOST_DISPLAY_NAME, host); 67 | isNotNull(AUTHENTICATION_DISPLAY_NAME, authentication); 68 | isNotNull(ROUTE_PLANNER_DISPLAY_NAME, routePlanner); 69 | 70 | this.host = host; 71 | this.authentication = authentication; 72 | this.routePlanner = routePlanner; 73 | } 74 | 75 | /** 76 | * @return Returns endpoint host. 77 | */ 78 | public String getHost() { 79 | return host; 80 | } 81 | 82 | /** 83 | * @return Returns authentication configuration. 84 | */ 85 | public Authentication getAuthentication() { 86 | return authentication; 87 | } 88 | 89 | /** 90 | * @return Returns configured route planner. 91 | */ 92 | public HttpRoutePlanner getRoutePlanner() { 93 | return routePlanner; 94 | } 95 | } -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/config/RestApiClientConfigBuilder.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.config; 2 | 3 | /** 4 | * Builder for {@link RestApiClientConfig} instance. 5 | */ 6 | public class RestApiClientConfigBuilder 7 | extends AbstractRestApiClientConfigBuilder { 8 | 9 | @Override 10 | public RestApiClientConfig build() { 11 | if (authentication != null && routePlanner != null) { 12 | return new RestApiClientConfig(host, authentication, routePlanner); 13 | } 14 | if (authentication != null) { 15 | return new RestApiClientConfig(host, authentication); 16 | } 17 | if (routePlanner != null) { 18 | return new RestApiClientConfig(host, routePlanner); 19 | } 20 | return new RestApiClientConfig(host); 21 | } 22 | 23 | @Override 24 | public RestApiClientConfigBuilder self() { 25 | return this; 26 | } 27 | 28 | /** 29 | * @return Returns an instance of {@link RestApiClientConfigBuilder} 30 | */ 31 | public static RestApiClientConfigBuilder getBuilder() { 32 | return new RestApiClientConfigBuilder(); 33 | } 34 | } -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/exceptions/ConnectionException.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.exceptions; 2 | 3 | import java.io.IOException; 4 | 5 | import com.sap.cloud.rest.api.client.model.Request; 6 | 7 | /** 8 | * This exception is a wrapper for IO related exceptions. 9 | * 10 | * It contains the request made before the exception occurred. 11 | * 12 | */ 13 | public class ConnectionException extends RestApiClientException { 14 | 15 | private static final long serialVersionUID = 1L; 16 | 17 | private final transient Request request; 18 | 19 | public ConnectionException(String message, IOException cause, Request request) { 20 | super(message, cause); 21 | 22 | this.request = request; 23 | } 24 | 25 | public Request getRequest() { 26 | return request; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/exceptions/RequestBuilderException.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.exceptions; 2 | 3 | import com.sap.cloud.rest.api.client.RequestBuilder; 4 | import com.sap.cloud.rest.api.client.model.Request; 5 | 6 | /** 7 | * This exception represents an error, occurred while building a {@link Request} 8 | * object using the {@link RequestBuilder}. 9 | * 10 | */ 11 | public class RequestBuilderException extends RestApiClientException { 12 | 13 | private static final long serialVersionUID = 1L; 14 | 15 | /** 16 | * @param message Exception message. 17 | */ 18 | public RequestBuilderException(String message) { 19 | super(message); 20 | } 21 | 22 | /** 23 | * @param message Exception message. 24 | * @param cause Exception cause. 25 | */ 26 | public RequestBuilderException(String message, Throwable cause) { 27 | super(message, cause); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/exceptions/ResponseException.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.exceptions; 2 | 3 | import com.sap.cloud.rest.api.client.model.HttpExchangeContext; 4 | import com.sap.cloud.rest.api.client.model.Request; 5 | import com.sap.cloud.rest.api.client.model.Response; 6 | 7 | /** 8 | * This exception represents that an error response code has been received from 9 | * the remote service. 10 | * 11 | * It contains the context of the HTTP exchange. 12 | */ 13 | public class ResponseException extends RestApiClientException { 14 | 15 | private static final long serialVersionUID = 1L; 16 | 17 | private final HttpExchangeContext context; 18 | 19 | public ResponseException(String message, HttpExchangeContext context) { 20 | super(message); 21 | 22 | this.context = context; 23 | } 24 | 25 | public ResponseException(String message, HttpExchangeContext context, Throwable cause) { 26 | super(message, cause); 27 | 28 | this.context = context; 29 | } 30 | 31 | public Request getRequest() { 32 | return context.getRequest(); 33 | } 34 | 35 | public Response getResponse() { 36 | return context.getResponse(); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/exceptions/RestApiClientException.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.exceptions; 2 | 3 | /** 4 | * This exception is a base class for all other exceptions thrown by the client. 5 | */ 6 | public class RestApiClientException extends RuntimeException { 7 | 8 | private static final long serialVersionUID = 1L; 9 | 10 | public RestApiClientException(String message) { 11 | super(message); 12 | } 13 | 14 | public RestApiClientException(String message, Throwable cause) { 15 | super(message, cause); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/exceptions/UnauthorizedException.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.exceptions; 2 | 3 | import com.sap.cloud.rest.api.client.model.HttpExchangeContext; 4 | 5 | /** 6 | * This exception represents an HTTP status code 401 Unauthorized. 7 | * 8 | */ 9 | public class UnauthorizedException extends ResponseException { 10 | 11 | private static final long serialVersionUID = 1L; 12 | 13 | public UnauthorizedException(String message, HttpExchangeContext context) { 14 | super(message, context); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/handler/DefaultResponseHandler.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.handler; 2 | 3 | import java.io.IOException; 4 | import java.nio.charset.StandardCharsets; 5 | 6 | import org.apache.http.HttpEntity; 7 | import org.apache.http.HttpResponse; 8 | import org.apache.http.client.ResponseHandler; 9 | import org.apache.http.util.EntityUtils; 10 | 11 | import com.sap.cloud.rest.api.client.exceptions.ConnectionException; 12 | 13 | /** 14 | * This implementation of {@link ResponseHandler} parses the entity of the 15 | * received {link {@link HttpResponse} as a String. Returns an empty String if 16 | * the response entity is null. 17 | * 18 | */ 19 | public class DefaultResponseHandler implements ResponseHandler { 20 | 21 | @Override 22 | public String handleResponse(final HttpResponse httpResponse) 23 | throws ConnectionException, IOException { 24 | HttpEntity responseEntity = httpResponse.getEntity(); 25 | return responseEntity == null ? "" : EntityUtils.toString(responseEntity, StandardCharsets.UTF_8); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/handler/DefaultStatusCodeHandler.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.handler; 2 | 3 | import static java.text.MessageFormat.format; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | import org.apache.http.HttpStatus; 9 | 10 | import com.sap.cloud.rest.api.client.exceptions.ResponseException; 11 | import com.sap.cloud.rest.api.client.exceptions.UnauthorizedException; 12 | import com.sap.cloud.rest.api.client.model.HttpExchangeContext; 13 | 14 | /** 15 | * This implementation of {@link StatusCodeHandler} has predefined handler for 16 | * 401 Unauthorized status code and a default one that is used when there is no 17 | * handler for a given status code. 18 | * 19 | * The default handler throws {@link ResponseException}. 20 | * 21 | */ 22 | public class DefaultStatusCodeHandler implements StatusCodeHandler { 23 | 24 | static final String UNAUTHORIZED_MSG = "The user is not authorized for the current operation. Context: [{0}]"; 25 | static final String HTTP_RESPOSNE_EXCEPTION_MSG = "An error HTTP response code was received from server. Context: [{0}]"; 26 | 27 | private final Map handlers = new HashMap<>(); 28 | 29 | protected DefaultStatusCodeHandler() { 30 | //prevent initialization from constructor 31 | } 32 | 33 | public DefaultStatusCodeHandler addHandler(int statusCode, ContextHandler handler) { 34 | handlers.put(statusCode, handler); 35 | return this; 36 | } 37 | 38 | public static DefaultStatusCodeHandler create() { 39 | return new DefaultStatusCodeHandler().addHandler(HttpStatus.SC_UNAUTHORIZED, defaultUnauthorizedHandler()); 40 | } 41 | 42 | protected static ContextHandler defaultUnauthorizedHandler() { 43 | return context -> { 44 | throw new UnauthorizedException(format(UNAUTHORIZED_MSG, context), context); 45 | }; 46 | } 47 | 48 | public void handleStatusCode(int statusCode, HttpExchangeContext context) throws ResponseException { 49 | handlers.getOrDefault(statusCode, defaultContextHandler()).handle(context); 50 | } 51 | 52 | protected ContextHandler defaultContextHandler() { 53 | return context -> { 54 | defaultStatusCodeHandling(context); 55 | }; 56 | } 57 | 58 | protected void defaultStatusCodeHandling(HttpExchangeContext context) { 59 | if (context.getResponse().getStatusCode() >= 300) { 60 | throw new ResponseException(format(HTTP_RESPOSNE_EXCEPTION_MSG, context), context); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/handler/StatusCodeHandler.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.handler; 2 | 3 | import com.sap.cloud.rest.api.client.exceptions.ResponseException; 4 | import com.sap.cloud.rest.api.client.model.HttpExchangeContext; 5 | 6 | /** 7 | * This class is a container for context handlers. It chooses which handler to 8 | * execute based on the given status code. 9 | */ 10 | public interface StatusCodeHandler { 11 | 12 | /** 13 | * Adds a handler for the given status code. 14 | * 15 | * @param statusCode 16 | * the status code, for which the handler should be used. 17 | * @param handler 18 | * the handler to be used for the given status code. 19 | * @return the same class instance 20 | */ 21 | StatusCodeHandler addHandler(int statusCode, ContextHandler handler); 22 | 23 | /** 24 | * Executes the context handler corresponding to the given status code. 25 | * 26 | * @param statusCode 27 | * the status code that should be handled. 28 | * @param context 29 | * HTTP context, for which the status code was returned. 30 | */ 31 | void handleStatusCode(int statusCode, HttpExchangeContext context) throws ResponseException; 32 | 33 | /** 34 | * Represents a function that is executed by the {@link StatusCodeHandler} 35 | * for the corresponding status code. 36 | * 37 | */ 38 | @FunctionalInterface 39 | static interface ContextHandler { 40 | 41 | void handle(HttpExchangeContext context) throws ResponseException; 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/http/HttpClientCreationException.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.http; 2 | 3 | public class HttpClientCreationException extends RuntimeException { 4 | 5 | private static final long serialVersionUID = 1L; 6 | 7 | public HttpClientCreationException(String message, Throwable cause) { 8 | super(message, cause); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/http/HttpClientProvider.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.http; 2 | 3 | import org.apache.http.client.HttpClient; 4 | import org.apache.http.conn.routing.HttpRoutePlanner; 5 | import org.apache.http.impl.conn.DefaultRoutePlanner; 6 | import org.apache.http.impl.conn.DefaultSchemePortResolver; 7 | 8 | public abstract class HttpClientProvider { 9 | 10 | public HttpClient createHttpClient() throws HttpClientCreationException { 11 | return createHttpClient(new DefaultRoutePlanner(DefaultSchemePortResolver.INSTANCE)); 12 | } 13 | 14 | public abstract HttpClient createHttpClient(HttpRoutePlanner proxyRouteHandler) throws HttpClientCreationException; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/http/HttpClientProviderFactory.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.http; 2 | 3 | import static com.sap.cloud.rest.api.client.auth.oauth.AccessTokenProviderFactory.createClientCredentialsAccessTokenProvider; 4 | 5 | import com.sap.cloud.rest.api.client.auth.Authentication; 6 | import com.sap.cloud.rest.api.client.auth.basic.BasicAuthentication; 7 | import com.sap.cloud.rest.api.client.auth.basic.BasicHttpClientProvider; 8 | import com.sap.cloud.rest.api.client.auth.cert.ClientCertAuthentication; 9 | import com.sap.cloud.rest.api.client.auth.cert.SSLHttpClientProvider; 10 | import com.sap.cloud.rest.api.client.auth.none.NoAuthHttpClientProvider; 11 | import com.sap.cloud.rest.api.client.auth.oauth.OAuthAuthentication; 12 | import com.sap.cloud.rest.api.client.auth.oauth.OAuthHttpClientProvider; 13 | import com.sap.cloud.rest.api.client.config.RestApiClientConfig; 14 | 15 | public class HttpClientProviderFactory { 16 | 17 | public static HttpClientProvider createHttpClientProvider(RestApiClientConfig config) { 18 | Authentication authentication = config.getAuthentication(); 19 | switch (authentication.getAuthenticationType()) { 20 | case BASIC: 21 | return new BasicHttpClientProvider((BasicAuthentication) authentication); 22 | case CLIENT_CERT: 23 | return new SSLHttpClientProvider((ClientCertAuthentication) authentication); 24 | case OAUTH: 25 | OAuthAuthentication oAuthAuthentication = (OAuthAuthentication) authentication; 26 | return new OAuthHttpClientProvider( 27 | createClientCredentialsAccessTokenProvider(config), 28 | oAuthAuthentication.getOAuthServerConfig().getoAuthHeaderKey()); 29 | case NO_AUTH: 30 | default: 31 | return new NoAuthHttpClientProvider(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/http/Proxy.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.http; 2 | 3 | import org.apache.commons.lang3.builder.ToStringBuilder; 4 | import org.apache.commons.lang3.builder.ToStringStyle; 5 | 6 | /** 7 | * Represents a proxy. Consists of proxy host, proxy port and proxy scheme. The 8 | * default proxy scheme is "http". 9 | */ 10 | public class Proxy { 11 | 12 | private static final String DEFAULT_PROXY_SCHEME = "http"; 13 | 14 | private final String proxyScheme; 15 | private final String proxyHost; 16 | private final int proxyPort; 17 | 18 | /** 19 | * Public constructor. 20 | * @param proxyHost Proxy host. 21 | * @param proxyPort Proxy port. 22 | * @param proxyScheme Proxy http scheme. 23 | */ 24 | public Proxy(final String proxyHost, final int proxyPort, String proxyScheme) { 25 | this.proxyScheme = proxyScheme; 26 | this.proxyHost = proxyHost; 27 | this.proxyPort = proxyPort; 28 | } 29 | 30 | /** 31 | * A constructor using the default proxy scheme. 32 | * @param proxyHost Proxy host. 33 | * @param proxyPort Proxy port. 34 | */ 35 | public Proxy(final String proxyHost, final int proxyPort) { 36 | this(proxyHost, proxyPort, DEFAULT_PROXY_SCHEME); 37 | } 38 | 39 | public String getProxyScheme() { 40 | return proxyScheme; 41 | } 42 | 43 | public String getProxyHost() { 44 | return proxyHost; 45 | } 46 | 47 | public int getProxyPort() { 48 | return proxyPort; 49 | } 50 | 51 | public String toString() { 52 | return new ToStringBuilder(Proxy.class.getName(), ToStringStyle.JSON_STYLE) 53 | .append("proxyScheme", proxyScheme) 54 | .append("proxyHost", proxyHost) 55 | .append("proxyPort", proxyPort) 56 | .toString(); 57 | } 58 | 59 | @Override 60 | public int hashCode() { 61 | final int prime = 31; 62 | int result = 1; 63 | result = prime * result + ((proxyHost == null) ? 0 : proxyHost.hashCode()); 64 | result = prime * result + proxyPort; 65 | result = prime * result + ((proxyScheme == null) ? 0 : proxyScheme.hashCode()); 66 | return result; 67 | } 68 | 69 | @Override 70 | public boolean equals(Object obj) { 71 | if (this == obj) return true; 72 | if (obj == null) return false; 73 | if (getClass() != obj.getClass()) return false; 74 | Proxy other = (Proxy) obj; 75 | if (proxyHost == null) { 76 | if (other.proxyHost != null) return false; 77 | } else if (!proxyHost.equals(other.proxyHost)) return false; 78 | if (proxyPort != other.proxyPort) return false; 79 | if (proxyScheme == null) { 80 | if (other.proxyScheme != null) return false; 81 | } else if (!proxyScheme.equals(other.proxyScheme)) return false; 82 | return true; 83 | } 84 | } -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/model/HttpExchangeContext.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.model; 2 | 3 | import static com.sap.cloud.rest.api.client.utils.ValidateArgument.isNotNull; 4 | 5 | import org.apache.commons.lang3.builder.ToStringBuilder; 6 | import org.apache.commons.lang3.builder.ToStringStyle; 7 | 8 | /** 9 | * Represents the context in which the exception was thrown, e.g the request 10 | * that was made and the response received. 11 | * 12 | */ 13 | public class HttpExchangeContext { 14 | 15 | static final String REQUEST_DISPLAY_NAME = "Request"; 16 | static final String RESPONSE_DISPLAY_NAME = "Response"; 17 | 18 | private final Request request; 19 | private final Response response; 20 | 21 | public HttpExchangeContext(final Request request, final Response response) { 22 | isNotNull(REQUEST_DISPLAY_NAME, request); 23 | isNotNull(RESPONSE_DISPLAY_NAME, response); 24 | 25 | this.request = request; 26 | this.response = response; 27 | } 28 | 29 | public Request getRequest() { 30 | return request; 31 | } 32 | 33 | public Response getResponse() { 34 | return response; 35 | } 36 | 37 | public String toString() { 38 | return new ToStringBuilder(HttpExchangeContext.class.getName(), ToStringStyle.JSON_STYLE) 39 | .append("request", request) 40 | .append("response", response) 41 | .toString(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/model/Request.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.model; 2 | 3 | import static com.sap.cloud.rest.api.client.utils.ValidateArgument.isNotNull; 4 | import static org.apache.http.HttpHeaders.AUTHORIZATION; 5 | import static org.apache.http.HttpHeaders.PROXY_AUTHENTICATE; 6 | import static org.apache.http.HttpHeaders.PROXY_AUTHORIZATION; 7 | 8 | import java.util.ArrayList; 9 | import java.util.Arrays; 10 | import java.util.List; 11 | import java.util.stream.Collectors; 12 | 13 | import org.apache.commons.lang3.builder.ToStringBuilder; 14 | import org.apache.commons.lang3.builder.ToStringStyle; 15 | import org.apache.http.Header; 16 | import org.apache.http.client.methods.HttpUriRequest; 17 | import org.apache.http.message.BasicHeader; 18 | 19 | /** 20 | * Represents an HTTP request. Contains the {@link HttpUriRequest} and the 21 | * request body. 22 | */ 23 | public class Request { 24 | 25 | static final String MASKED_VALUE = "********"; 26 | 27 | private static final List AUTHORIZATION_HEADERS_LIST = Arrays.asList( 28 | AUTHORIZATION, PROXY_AUTHENTICATE, PROXY_AUTHORIZATION); 29 | 30 | private static final String HTTP_URI_REQUEST_DISPLAY_NAME = "Http request"; 31 | 32 | private final HttpUriRequest httpUriRequest; 33 | 34 | private final T entity; 35 | 36 | public Request(HttpUriRequest httpUriRequest) { 37 | this(httpUriRequest, null); 38 | } 39 | 40 | public Request(HttpUriRequest httpUriRequest, T body) { 41 | isNotNull(HTTP_URI_REQUEST_DISPLAY_NAME, httpUriRequest); 42 | 43 | this.httpUriRequest = httpUriRequest; 44 | this.entity = body; 45 | } 46 | 47 | public HttpUriRequest getHttpRequest() { 48 | return httpUriRequest; 49 | } 50 | 51 | public Header[] getHeaders() { 52 | return httpUriRequest.getAllHeaders(); 53 | } 54 | 55 | public T getEntity() { 56 | return entity; 57 | } 58 | 59 | /** 60 | * Returns a String representation of the {@link Request}. Hides the 61 | * Authorization header if existent. 62 | */ 63 | public String toString() { 64 | return new ToStringBuilder(Request.class.getName(), ToStringStyle.JSON_STYLE) 65 | .append("httpRequest", httpUriRequest) 66 | .append("requestHeaders", Arrays.toString(sanitizeSensitiveHeaders(getHeaders()))) 67 | .append("requestEntity", entity) 68 | .toString(); 69 | } 70 | 71 | private Header[] sanitizeSensitiveHeaders(Header[] headers) { 72 | List
headerList = new ArrayList<>(Arrays.asList(headers)) 73 | .stream() 74 | .map(this::sanitizeHeader) 75 | .collect(Collectors.toList()); 76 | 77 | return headerList.toArray(new Header[headerList.size()]); 78 | } 79 | 80 | private Header sanitizeHeader(Header header) { 81 | if (isAuthorizationHeader(header)) { 82 | return new BasicHeader(header.getName(), MASKED_VALUE); 83 | } 84 | return header; 85 | } 86 | 87 | private boolean isAuthorizationHeader(Header header) { 88 | String headerName = header.getName(); 89 | if (AUTHORIZATION_HEADERS_LIST.contains(headerName)) { 90 | return true; 91 | } 92 | return false; 93 | } 94 | } -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/model/Response.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.model; 2 | 3 | import static com.sap.cloud.rest.api.client.utils.ValidateArgument.isNotNull; 4 | 5 | import org.apache.commons.lang3.builder.ToStringBuilder; 6 | import org.apache.commons.lang3.builder.ToStringStyle; 7 | import org.apache.http.Header; 8 | import org.apache.http.HttpResponse; 9 | 10 | /** 11 | * Represents an HTTP response. Holds the {@link HttpResponse} and the response 12 | * entity. 13 | * 14 | * @param 15 | * the type of the response entity 16 | */ 17 | public class Response { 18 | 19 | private static final String HTTP_RESPONSE_DISPLAY_NAME = "Http response"; 20 | 21 | private final HttpResponse httpResponse; 22 | 23 | private final T entity; 24 | 25 | public Response(HttpResponse httpResponse, T responseEntity) { 26 | isNotNull(HTTP_RESPONSE_DISPLAY_NAME, httpResponse); 27 | 28 | this.httpResponse = httpResponse; 29 | this.entity = responseEntity; 30 | } 31 | 32 | public HttpResponse getHttpResponse() { 33 | return httpResponse; 34 | } 35 | 36 | public int getStatusCode() { 37 | return httpResponse.getStatusLine().getStatusCode(); 38 | } 39 | 40 | public Header[] getHeaders() { 41 | return httpResponse.getAllHeaders(); 42 | } 43 | 44 | public T getEntity() { 45 | return entity; 46 | } 47 | 48 | public String toString() { 49 | return new ToStringBuilder(Response.class.getName(), ToStringStyle.JSON_STYLE) 50 | .append("httpResponse", httpResponse) 51 | .append("responseEntity", entity) 52 | .toString(); 53 | } 54 | } -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/model/multipart/EntityPart.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.model.multipart; 2 | 3 | import org.apache.commons.lang3.builder.ToStringBuilder; 4 | import org.apache.commons.lang3.builder.ToStringStyle; 5 | 6 | /** 7 | * Represents an entity part in a multipart entity. Consist of an entity of type 8 | * {@link T} and name. 9 | * 10 | * @param 11 | * the type of the entity 12 | */ 13 | public class EntityPart { 14 | 15 | private final String name; 16 | 17 | private final T entity; 18 | 19 | public EntityPart(String name, T entity) { 20 | this.name = name; 21 | this.entity = entity; 22 | } 23 | 24 | public String getName() { 25 | return name; 26 | } 27 | 28 | public T getEntity() { 29 | return entity; 30 | } 31 | 32 | public String toString() { 33 | return new ToStringBuilder(EntityPart.class.getName(), ToStringStyle.JSON_STYLE) 34 | .append("name", name) 35 | .append("entity", entity) 36 | .toString(); 37 | } 38 | 39 | @Override 40 | public int hashCode() { 41 | final int prime = 31; 42 | int result = 1; 43 | result = prime * result + ((entity == null) ? 0 : entity.hashCode()); 44 | result = prime * result + ((name == null) ? 0 : name.hashCode()); 45 | return result; 46 | } 47 | 48 | @Override 49 | public boolean equals(Object obj) { 50 | if (this == obj) return true; 51 | if (obj == null) return false; 52 | if (getClass() != obj.getClass()) return false; 53 | EntityPart other = (EntityPart) obj; 54 | if (entity == null) { 55 | if (other.entity != null) return false; 56 | } else if (!entity.equals(other.entity)) return false; 57 | if (name == null) { 58 | if (other.name != null) return false; 59 | } else if (!name.equals(other.name)) return false; 60 | return true; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/model/multipart/MultipartEntity.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.model.multipart; 2 | 3 | import java.util.List; 4 | import java.util.stream.Collectors; 5 | 6 | import org.apache.commons.lang3.builder.ToStringBuilder; 7 | import org.apache.commons.lang3.builder.ToStringStyle; 8 | 9 | /** 10 | * Represents a multipart entity. It consists of a list of {@link EntityPart}s. 11 | * 12 | * @param 13 | * the type of the entity parts 14 | */ 15 | public class MultipartEntity { 16 | 17 | private final List> multipartEntity; 18 | 19 | public MultipartEntity(List> parts) { 20 | this.multipartEntity = parts; 21 | } 22 | 23 | public List> getParts() { 24 | return multipartEntity; 25 | } 26 | 27 | public List> getPartsByName(String name) { 28 | return multipartEntity.stream() 29 | .filter(x -> x.getName().equals(name)) 30 | .collect(Collectors.toList()); 31 | } 32 | 33 | public String toString() { 34 | return new ToStringBuilder(MultipartEntity.class.getName(), ToStringStyle.JSON_STYLE) 35 | .append("multipartEntity", multipartEntity) 36 | .toString(); 37 | } 38 | 39 | @Override 40 | public int hashCode() { 41 | final int prime = 31; 42 | int result = 1; 43 | result = prime * result + ((multipartEntity == null) ? 0 : multipartEntity.hashCode()); 44 | return result; 45 | } 46 | 47 | @Override 48 | public boolean equals(Object obj) { 49 | if (this == obj) return true; 50 | if (obj == null) return false; 51 | if (getClass() != obj.getClass()) return false; 52 | MultipartEntity other = (MultipartEntity) obj; 53 | if (multipartEntity == null) { 54 | if (other.multipartEntity != null) return false; 55 | } else if (!multipartEntity.equals(other.multipartEntity)) return false; 56 | return true; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/utils/JacksonJsonResponseHandler.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.utils; 2 | 3 | import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES; 4 | 5 | import java.io.IOException; 6 | 7 | import org.apache.http.HttpResponse; 8 | import org.apache.http.client.ResponseHandler; 9 | 10 | import com.fasterxml.jackson.core.type.TypeReference; 11 | import com.fasterxml.jackson.databind.ObjectMapper; 12 | import com.sap.cloud.rest.api.client.handler.DefaultResponseHandler; 13 | 14 | /** 15 | * This implementation of {@link ResponseHandler} expects that the received HTTP 16 | * response body is in JSON format. 17 | * 18 | * The received JSON is parsed using the Jackson library and returned as an 19 | * object of type T. 20 | * 21 | * @param 22 | * type of the object, the JSON needs to be parsed to. 23 | */ 24 | public class JacksonJsonResponseHandler implements ResponseHandler { 25 | 26 | private Class clazz; 27 | private TypeReference type; 28 | 29 | private ObjectMapper objectMapper = new ObjectMapper().configure(FAIL_ON_UNKNOWN_PROPERTIES, false); 30 | 31 | public JacksonJsonResponseHandler(Class clazz) { 32 | this.clazz = clazz; 33 | } 34 | 35 | public JacksonJsonResponseHandler(TypeReference type) { 36 | this.type = type; 37 | } 38 | 39 | @Override 40 | public T handleResponse(HttpResponse response) throws IOException { 41 | ResponseHandler handler = new DefaultResponseHandler(); 42 | String body = handler.handleResponse(response); 43 | 44 | if (type != null) { 45 | return body.isEmpty() ? null : objectMapper.readValue(body, type); 46 | } 47 | return body.isEmpty() ? null : objectMapper.readValue(body, clazz); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/utils/PropertiesResponseHandler.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.utils; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.IOException; 5 | import java.nio.charset.StandardCharsets; 6 | import java.util.Properties; 7 | 8 | import org.apache.http.HttpResponse; 9 | import org.apache.http.client.ResponseHandler; 10 | 11 | import com.fasterxml.jackson.core.JsonProcessingException; 12 | import com.fasterxml.jackson.databind.ObjectMapper; 13 | import com.sap.cloud.rest.api.client.handler.DefaultResponseHandler; 14 | 15 | /** 16 | * This implementation of {@link ResponseHandler} expects that the received HTTP 17 | * response body is in {@link Properties} format. 18 | * 19 | * The received body is stored in {@link Properties} object and serialized to 20 | * JSON format. After that the JSON is parsed using the Jackson library and 21 | * returned as an object of type T. 22 | * 23 | * @param 24 | * type of the object, the {@link Properties} needs to be parsed to. 25 | */ 26 | public class PropertiesResponseHandler implements ResponseHandler { 27 | 28 | private Class clazz; 29 | 30 | private ObjectMapper objectMapper = new ObjectMapper(); 31 | 32 | public PropertiesResponseHandler(Class clazz) { 33 | this.clazz = clazz; 34 | } 35 | 36 | @Override 37 | public T handleResponse(HttpResponse response) throws IOException { 38 | ResponseHandler handler = new DefaultResponseHandler(); 39 | String body = handler.handleResponse(response); 40 | 41 | return body.isEmpty() ? null : objectMapper.readValue(convertPropertiesToJson(body), clazz); 42 | } 43 | 44 | private String convertPropertiesToJson(String body) throws IOException, JsonProcessingException { 45 | Properties props = new Properties(); 46 | 47 | try (ByteArrayInputStream inputStream = new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8))) { 48 | props.load(inputStream); 49 | } 50 | 51 | return objectMapper.writeValueAsString(props); 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /src/main/java/com/sap/cloud/rest/api/client/utils/ValidateArgument.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.utils; 2 | 3 | import java.net.MalformedURLException; 4 | import java.net.URISyntaxException; 5 | import java.net.URL; 6 | 7 | /** 8 | * Utility class for argument validations. 9 | * 10 | */ 11 | public class ValidateArgument { 12 | 13 | public static final String CANNOT_BE_NULL_MSG = " cannot be null."; 14 | public static final String CANNOT_BE_BLANK_MSG = " cannot be blank."; 15 | public static final String NOT_VALID_URL_MSG = " is not a vlaid URL."; 16 | 17 | /** 18 | * Validates that the strings are not null or empty. 19 | * 20 | * If a string is not valid - throws IllegalArgumentException. 21 | * 22 | * @param messagePrefix 23 | * a display message for the tested strings. 24 | * @param strings 25 | * the strings that will be validated. 26 | */ 27 | public static void isNotEmptyOrNull(String messagePrefix, String... strings) { 28 | for (String string : strings) { 29 | if (ValidateArgument.isEmpty(string)) { 30 | throw new IllegalArgumentException(messagePrefix + CANNOT_BE_BLANK_MSG); 31 | } 32 | } 33 | } 34 | 35 | private static boolean isEmpty(String string) { 36 | return string == null || string.trim().isEmpty(); 37 | } 38 | 39 | /** 40 | * Validates that the char array is not null or empty. 41 | * 42 | * If the char array is not valid - throws IllegalArgumentException. 43 | * 44 | * @param messagePrefix 45 | * a display message for the tested array. 46 | * @param charArray 47 | * the char array that will be validated. 48 | */ 49 | public static void isNotEmptyOrNull(String messagePrefix, char[] charArray) { 50 | if (charArray == null || charArray.length < 1) { 51 | throw new IllegalArgumentException(messagePrefix + CANNOT_BE_BLANK_MSG); 52 | } 53 | } 54 | 55 | /** 56 | * Validates that the objects are not null. 57 | * 58 | * If an object is null - throws IllegalArgumentException. 59 | * 60 | * @param messagePrefix 61 | * a display message for the tested objects. 62 | * @param objects 63 | * the objects that will be validated. 64 | */ 65 | public static void isNotNull(String messagePrefix, Object... objects) { 66 | for (Object object : objects) { 67 | if (object == null) { 68 | throw new IllegalArgumentException(messagePrefix + CANNOT_BE_NULL_MSG); 69 | } 70 | } 71 | } 72 | 73 | /** 74 | * Validates that the object is a correct URL 75 | * 76 | * If an object is incorrect URL - throws IllegalArgumentException. 77 | * 78 | * @param messagePrefix 79 | * - a display message for the URL 80 | * @param url 81 | * - the URL that will be validated. 82 | */ 83 | public static void isValidUrl(String messagePrefix, String url) { 84 | try { 85 | new URL(url).toURI(); 86 | } catch (MalformedURLException | URISyntaxException e) { 87 | throw new IllegalArgumentException(messagePrefix + NOT_VALID_URL_MSG, e); 88 | } 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/auth/basic/BasicAuthenticationTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.basic; 2 | 3 | import org.junit.Test; 4 | 5 | import com.sap.cloud.rest.api.client.auth.AuthenticationType; 6 | import com.sap.cloud.rest.api.client.auth.basic.BasicAuthentication; 7 | 8 | import static org.junit.Assert.assertArrayEquals; 9 | import static org.junit.Assert.assertEquals; 10 | 11 | public class BasicAuthenticationTest { 12 | 13 | private static final String USERNAME = "username"; 14 | private static final char[] PASSWORD = "password".toCharArray(); 15 | 16 | @Test 17 | public void validBasicAuthenticationTest() { 18 | BasicAuthentication authentication = new BasicAuthentication(USERNAME, PASSWORD); 19 | 20 | assertEquals(USERNAME, authentication.getUsername()); 21 | assertArrayEquals(PASSWORD, authentication.getPassword()); 22 | assertEquals(AuthenticationType.BASIC, authentication.getAuthenticationType()); 23 | } 24 | 25 | @Test(expected = IllegalArgumentException.class) 26 | public void nullUsernameBasicAuthenticationTest() { 27 | new BasicAuthentication(null, PASSWORD); 28 | } 29 | 30 | @Test(expected = IllegalArgumentException.class) 31 | public void nullPasswordBasicAuthenticationTest() { 32 | new BasicAuthentication(USERNAME, null); 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/auth/basic/BasicHttpClientProviderTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.basic; 2 | 3 | import static com.sap.cloud.rest.api.client.utils.test.HttpClientProviderUtils.getHttpClientProviderForAuthentication; 4 | import static org.junit.Assert.assertNotNull; 5 | import static org.junit.Assert.assertTrue; 6 | 7 | import org.apache.http.client.HttpClient; 8 | import org.junit.Test; 9 | 10 | import com.sap.cloud.rest.api.client.auth.Authentication; 11 | import com.sap.cloud.rest.api.client.auth.basic.BasicAuthentication; 12 | import com.sap.cloud.rest.api.client.auth.basic.BasicHttpClientProvider; 13 | import com.sap.cloud.rest.api.client.http.HttpClientCreationException; 14 | import com.sap.cloud.rest.api.client.http.HttpClientProvider; 15 | 16 | public class BasicHttpClientProviderTest { 17 | 18 | private static final String USERNAME = "username"; 19 | private static final char[] PASSWORD = "password".toCharArray(); 20 | 21 | @Test 22 | public void createHttpClient() throws HttpClientCreationException { 23 | Authentication authentication = new BasicAuthentication(USERNAME, PASSWORD); 24 | 25 | HttpClientProvider httpClientProvider = getHttpClientProviderForAuthentication(authentication); 26 | 27 | assertTrue(httpClientProvider instanceof BasicHttpClientProvider); 28 | 29 | HttpClient httpClient = httpClientProvider.createHttpClient(); 30 | assertNotNull(httpClient); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/auth/cert/ClientCertAuthenticationTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.cert; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.mockito.Mockito.mock; 5 | 6 | import java.security.KeyStore; 7 | 8 | import org.junit.Test; 9 | 10 | import com.sap.cloud.rest.api.client.auth.AuthenticationType; 11 | import com.sap.cloud.rest.api.client.auth.cert.ClientCertAuthentication; 12 | import com.sap.cloud.rest.api.client.auth.cert.KeystoreConfig; 13 | import com.sap.cloud.rest.api.client.auth.cert.KeystoreConfigBuilder; 14 | 15 | public class ClientCertAuthenticationTest { 16 | 17 | private static final KeyStore KEYSTORE = mock(KeyStore.class); 18 | private static final char[] PASSWORD = "password".toCharArray(); 19 | private static final String ALIAS = "alias"; 20 | 21 | private static final KeystoreConfig KEYSTORE_CONFIG = KeystoreConfigBuilder.getBuilder() 22 | .keystore(KEYSTORE) 23 | .keystorePassword(PASSWORD) 24 | .keyAlias(ALIAS) 25 | .build(); 26 | 27 | @Test 28 | public void validClientCertAuthenticationTest() { 29 | ClientCertAuthentication authentication = new ClientCertAuthentication(KEYSTORE_CONFIG); 30 | 31 | assertEquals(KEYSTORE_CONFIG, authentication.getKeystoreConfig()); 32 | assertEquals(AuthenticationType.CLIENT_CERT, authentication.getAuthenticationType()); 33 | } 34 | 35 | @Test(expected = IllegalArgumentException.class) 36 | public void nullKeystoreConfigClientCertAuthenticationTest() { 37 | new ClientCertAuthentication(null); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/auth/cert/KeystoreConfigBuilderTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.cert; 2 | 3 | import static org.junit.Assert.assertArrayEquals; 4 | import static org.junit.Assert.assertEquals; 5 | import static org.junit.Assert.assertTrue; 6 | import static org.mockito.Mockito.mock; 7 | 8 | import java.security.KeyStore; 9 | 10 | import org.junit.Rule; 11 | import org.junit.Test; 12 | import org.junit.rules.ExpectedException; 13 | 14 | import com.sap.cloud.rest.api.client.auth.cert.KeystoreConfig; 15 | import com.sap.cloud.rest.api.client.auth.cert.KeystoreConfigBuilder; 16 | 17 | public class KeystoreConfigBuilderTest { 18 | 19 | @Rule 20 | public ExpectedException expected = ExpectedException.none(); 21 | 22 | private static final KeyStore TEST_KEYSTORE = mock(KeyStore.class); 23 | private static final char[] TEST_PASSWORD = "example-password".toCharArray(); 24 | private static final String TEST_ALIAS = "exampleAlias"; 25 | 26 | @Test 27 | public void testWithValidCanBuild() { 28 | KeystoreConfig config = KeystoreConfigBuilder.getBuilder() 29 | .keystore(TEST_KEYSTORE) 30 | .keystorePassword(TEST_PASSWORD) 31 | .keyAlias(TEST_ALIAS) 32 | .build(); 33 | 34 | assertEquals(config.getKeystore(), TEST_KEYSTORE); 35 | assertArrayEquals(config.getKeystorePassword(), TEST_PASSWORD); 36 | assertEquals(config.getKeyAlias(), TEST_ALIAS); 37 | } 38 | 39 | @Test 40 | public void testThrowsExceptionOnMissingKeystore() { 41 | expected.expect(IllegalArgumentException.class); 42 | expected.expectMessage("Key store cannot be null."); 43 | 44 | KeystoreConfigBuilder.getBuilder() 45 | .keystorePassword(TEST_PASSWORD) 46 | .keyAlias(TEST_ALIAS) 47 | .build(); 48 | } 49 | 50 | @Test 51 | public void testThrowsExceptionOnMissingPassword() { 52 | expected.expect(IllegalArgumentException.class); 53 | expected.expectMessage("Key store password cannot be blank."); 54 | 55 | KeystoreConfigBuilder.getBuilder() 56 | .keystore(TEST_KEYSTORE) 57 | .keyAlias(TEST_ALIAS) 58 | .build(); 59 | } 60 | 61 | @Test 62 | public void testThrowsExceptionOnMissingAlias() { 63 | expected.expect(IllegalArgumentException.class); 64 | expected.expectMessage("Key store alias cannot be blank."); 65 | 66 | KeystoreConfigBuilder.getBuilder() 67 | .keystore(TEST_KEYSTORE) 68 | .keystorePassword(TEST_PASSWORD) 69 | .build(); 70 | } 71 | 72 | @Test 73 | public void getKeystoreConfigBuilderTest() { 74 | assertTrue(KeystoreConfigBuilder.getBuilder() instanceof KeystoreConfigBuilder); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/auth/cert/SSLHttpClientProviderTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.cert; 2 | 3 | import static com.sap.cloud.rest.api.client.utils.test.HttpClientProviderUtils.getHttpClientProviderForAuthentication; 4 | import static org.junit.Assert.assertNotNull; 5 | import static org.junit.Assert.assertTrue; 6 | 7 | import java.io.FileInputStream; 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | import java.security.GeneralSecurityException; 11 | import java.security.KeyStore; 12 | import java.security.KeyStoreException; 13 | import java.security.NoSuchAlgorithmException; 14 | import java.security.cert.CertificateException; 15 | 16 | import org.apache.http.client.HttpClient; 17 | import org.junit.BeforeClass; 18 | import org.junit.Test; 19 | 20 | import com.sap.cloud.rest.api.client.auth.cert.ClientCertAuthentication; 21 | import com.sap.cloud.rest.api.client.auth.cert.KeystoreConfigBuilder; 22 | import com.sap.cloud.rest.api.client.auth.cert.SSLHttpClientProvider; 23 | import com.sap.cloud.rest.api.client.http.HttpClientCreationException; 24 | import com.sap.cloud.rest.api.client.http.HttpClientProvider; 25 | 26 | public class SSLHttpClientProviderTest { 27 | 28 | private static final String KEY_ALIAS = "testAlias"; 29 | private static char[] KEYSTORE_PASSWORD = "test1234".toCharArray(); 30 | private static final String KEYSTORE_TYPE = "JKS"; 31 | private static KeyStore keystore; 32 | 33 | @BeforeClass 34 | public static void setup() throws GeneralSecurityException, IOException { 35 | String path = Thread 36 | .currentThread() 37 | .getContextClassLoader() 38 | .getResource("test-keystore.jks") 39 | .getPath(); 40 | 41 | keystore = loadKeystore(path); 42 | } 43 | 44 | @Test 45 | public void createHttpClient_notNull() throws HttpClientCreationException { 46 | ClientCertAuthentication authentication = new ClientCertAuthentication(KeystoreConfigBuilder.getBuilder() 47 | .keystore(keystore) 48 | .keystorePassword(KEYSTORE_PASSWORD) 49 | .keyAlias(KEY_ALIAS) 50 | .build()); 51 | 52 | HttpClientProvider httpClientProvider = getHttpClientProviderForAuthentication(authentication); 53 | 54 | assertTrue(httpClientProvider instanceof SSLHttpClientProvider); 55 | 56 | HttpClient httpClient = httpClientProvider.createHttpClient(); 57 | assertNotNull(httpClient); 58 | } 59 | 60 | @Test(expected = HttpClientCreationException.class) 61 | public void createHttpClientWrongKeystorePassword_throwsException() throws HttpClientCreationException { 62 | ClientCertAuthentication authentication = new ClientCertAuthentication(KeystoreConfigBuilder.getBuilder() 63 | .keystore(keystore) 64 | .keystorePassword("wrong-password".toCharArray()) 65 | .keyAlias(KEY_ALIAS) 66 | .build()); 67 | 68 | HttpClientProvider httpClientProvider = getHttpClientProviderForAuthentication(authentication); 69 | 70 | httpClientProvider.createHttpClient(); 71 | } 72 | 73 | private static KeyStore loadKeystore(String path) 74 | throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException { 75 | KeyStore keystore = KeyStore.getInstance(KEYSTORE_TYPE); 76 | InputStream keystoreInputStream = new FileInputStream(path); 77 | 78 | keystore.load(keystoreInputStream, KEYSTORE_PASSWORD); 79 | 80 | return keystore; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/auth/none/NoAuthHttpClientProviderTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.none; 2 | 3 | import static com.sap.cloud.rest.api.client.utils.test.HttpClientProviderUtils.getHttpClientProviderForAuthentication; 4 | import static org.junit.Assert.assertNotNull; 5 | import static org.junit.Assert.assertTrue; 6 | 7 | import org.apache.http.client.HttpClient; 8 | import org.junit.Test; 9 | 10 | import com.sap.cloud.rest.api.client.auth.none.NoAuthHttpClientProvider; 11 | import com.sap.cloud.rest.api.client.auth.none.NoAuthentication; 12 | import com.sap.cloud.rest.api.client.http.HttpClientCreationException; 13 | import com.sap.cloud.rest.api.client.http.HttpClientProvider; 14 | 15 | public class NoAuthHttpClientProviderTest { 16 | 17 | @Test 18 | public void createHttpClient() throws HttpClientCreationException { 19 | HttpClientProvider httpClientProvider = getHttpClientProviderForAuthentication(new NoAuthentication()); 20 | 21 | assertTrue(httpClientProvider instanceof NoAuthHttpClientProvider); 22 | 23 | HttpClient httpClient = httpClientProvider.createHttpClient(); 24 | assertNotNull(httpClient); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/auth/oauth/AccessTokenProviderFactoryTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.oauth; 2 | 3 | import static com.sap.cloud.rest.api.client.auth.oauth.AccessTokenProviderFactory.NON_OAUTH_AUTHENTICATION_MSG; 4 | import static com.sap.cloud.rest.api.client.auth.oauth.AccessTokenProviderFactory.createClientCredentialsAccessTokenProvider; 5 | import static java.text.MessageFormat.format; 6 | import static org.junit.Assert.assertEquals; 7 | import static org.junit.Assert.assertNotNull; 8 | 9 | import org.junit.Before; 10 | import org.junit.Rule; 11 | import org.junit.Test; 12 | import org.junit.rules.ExpectedException; 13 | import org.mockito.Mockito; 14 | 15 | import com.sap.cloud.rest.api.client.auth.AuthenticationType; 16 | import com.sap.cloud.rest.api.client.auth.oauth.AccessTokenProviderFactory; 17 | import com.sap.cloud.rest.api.client.auth.oauth.ClientCredentialsAccessTokenProvider; 18 | import com.sap.cloud.rest.api.client.auth.oauth.OAuthServerConfig; 19 | import com.sap.cloud.rest.api.client.auth.oauth.OAuthServerConfigBuilder; 20 | import com.sap.cloud.rest.api.client.config.RestApiClientConfig; 21 | import com.sap.cloud.rest.api.client.config.RestApiClientConfigBuilder; 22 | import com.sap.cloud.rest.api.client.http.HttpClientProvider; 23 | 24 | public class AccessTokenProviderFactoryTest { 25 | 26 | private static final String TEST_HOST = "https://example.com"; 27 | private static final String TEST_API_PATH = "/oauth/token"; 28 | private static final String TEST_CLIENT_ID = "testClientID"; 29 | private static final char[] TEST_CLIENT_SECRET = "testClientSecret".toCharArray(); 30 | 31 | private RestApiClientConfig oAuthRestApiClientConfig; 32 | private RestApiClientConfig invalidRestApiClientConfig; 33 | private HttpClientProvider httpClientProviderMock; 34 | 35 | @Rule 36 | public ExpectedException expected = ExpectedException.none(); 37 | 38 | @Before 39 | public void init() { 40 | OAuthServerConfig oAuthServerConfig = OAuthServerConfigBuilder.getBuilder() 41 | .oAuthServerHost(TEST_HOST) 42 | .oAuthServerApiPath(TEST_API_PATH) 43 | .clientID(TEST_CLIENT_ID) 44 | .clientSecret(TEST_CLIENT_SECRET) 45 | .build(); 46 | 47 | oAuthRestApiClientConfig = RestApiClientConfigBuilder.getBuilder() 48 | .oAuthAuthentication(oAuthServerConfig) 49 | .host(TEST_HOST) 50 | .build(); 51 | 52 | invalidRestApiClientConfig = RestApiClientConfigBuilder.getBuilder() 53 | .host(TEST_HOST) 54 | .build(); 55 | 56 | httpClientProviderMock = Mockito.mock(HttpClientProvider.class); 57 | new AccessTokenProviderFactory(); 58 | } 59 | 60 | @Test 61 | public void testCreateClientCredentialsAccessTokenProvider() { 62 | ClientCredentialsAccessTokenProvider createClientCredentialsAccessTokenProvider = AccessTokenProviderFactory 63 | .createClientCredentialsAccessTokenProvider(oAuthRestApiClientConfig); 64 | 65 | assertNotNull(createClientCredentialsAccessTokenProvider); 66 | assertEquals(TEST_API_PATH, createClientCredentialsAccessTokenProvider.getApiPath()); 67 | } 68 | 69 | @Test 70 | public void testCreateClientCredentialsAccessTokenProvider_withCustomHttpClientProvider() { 71 | ClientCredentialsAccessTokenProvider createClientCredentialsAccessTokenProvider = AccessTokenProviderFactory 72 | .createClientCredentialsAccessTokenProvider(oAuthRestApiClientConfig, 73 | httpClientProviderMock); 74 | 75 | assertNotNull(createClientCredentialsAccessTokenProvider); 76 | assertEquals(TEST_API_PATH, createClientCredentialsAccessTokenProvider.getApiPath()); 77 | } 78 | 79 | @Test 80 | public void testCreateClientCredentialsAccessTokenProvider_withNonOAuthAuthentication() { 81 | expected.expect(IllegalArgumentException.class); 82 | expected.expectMessage(format(NON_OAUTH_AUTHENTICATION_MSG, AuthenticationType.NO_AUTH)); 83 | 84 | createClientCredentialsAccessTokenProvider(invalidRestApiClientConfig); 85 | } 86 | 87 | @Test 88 | public void testCreateClientCredentialsAccessTokenProvider_withCustomHttpClientProviderAndNonOAuthAuthentication() { 89 | expected.expect(IllegalArgumentException.class); 90 | expected.expectMessage(format(NON_OAUTH_AUTHENTICATION_MSG, AuthenticationType.NO_AUTH)); 91 | 92 | createClientCredentialsAccessTokenProvider(invalidRestApiClientConfig, httpClientProviderMock); 93 | 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/auth/oauth/AccessTokenResponseDtoTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.oauth; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import org.junit.Test; 6 | 7 | import com.fasterxml.jackson.core.JsonProcessingException; 8 | import com.fasterxml.jackson.databind.ObjectMapper; 9 | import com.sap.cloud.rest.api.client.auth.oauth.AccessTokenResponseDto; 10 | 11 | import nl.jqno.equalsverifier.EqualsVerifier; 12 | 13 | public class AccessTokenResponseDtoTest { 14 | 15 | private static final String ACCESS_TOKEN = "dummyAccessToken"; 16 | private static final String ACCESS_TOKEN_RESPONSE_JSON = "{\"access_token\":\"" + ACCESS_TOKEN + "\"}"; 17 | private static final AccessTokenResponseDto ACCESS_TOKEN_RESPONSE_DTO = new AccessTokenResponseDto(ACCESS_TOKEN); 18 | private static final ObjectMapper objectMapper = new ObjectMapper(); 19 | 20 | @Test 21 | public void getAccessTokenTest() { 22 | assertEquals(ACCESS_TOKEN, ACCESS_TOKEN_RESPONSE_DTO.getAccessToken()); 23 | } 24 | 25 | @Test 26 | public void serializeAccessTokenDtoTest() throws JsonProcessingException { 27 | String serialized = objectMapper.writeValueAsString(ACCESS_TOKEN_RESPONSE_DTO); 28 | assertEquals(ACCESS_TOKEN_RESPONSE_JSON, serialized); 29 | } 30 | 31 | @Test 32 | public void deserializeAccessTokenResponseDtoTest() throws Exception { 33 | AccessTokenResponseDto accessTokenResponse = objectMapper.readValue(ACCESS_TOKEN_RESPONSE_JSON, 34 | AccessTokenResponseDto.class); 35 | assertEquals(ACCESS_TOKEN, accessTokenResponse.getAccessToken()); 36 | } 37 | 38 | @Test 39 | public void equalsTest() { 40 | EqualsVerifier.forClass(AccessTokenResponseDto.class).verify(); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/auth/oauth/ClientCredentialsAccessTokenProviderTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.oauth; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.mockito.Matchers.any; 5 | import static org.mockito.Matchers.argThat; 6 | import static org.mockito.Mockito.verify; 7 | import static org.mockito.Mockito.when; 8 | 9 | import java.io.IOException; 10 | 11 | import org.apache.http.HttpResponse; 12 | import org.apache.http.StatusLine; 13 | import org.apache.http.client.ClientProtocolException; 14 | import org.apache.http.client.HttpClient; 15 | import org.apache.http.client.entity.EntityBuilder; 16 | import org.junit.Before; 17 | import org.junit.Test; 18 | import org.mockito.Mockito; 19 | 20 | import com.fasterxml.jackson.core.JsonProcessingException; 21 | import com.fasterxml.jackson.databind.ObjectMapper; 22 | import com.sap.cloud.rest.api.client.auth.oauth.AccessTokenResponseDto; 23 | import com.sap.cloud.rest.api.client.auth.oauth.ClientCredentialsAccessTokenProvider; 24 | import com.sap.cloud.rest.api.client.config.RestApiClientConfig; 25 | import com.sap.cloud.rest.api.client.config.RestApiClientConfigBuilder; 26 | import com.sap.cloud.rest.api.client.http.HttpClientProvider; 27 | import com.sap.cloud.rest.api.client.utils.test.RequestMatcher; 28 | 29 | public class ClientCredentialsAccessTokenProviderTest { 30 | 31 | private static final String TEST_HOST = "https://example.com"; 32 | private static final String TEST_API_PATH = "/oauth/token"; 33 | private static final String TEST_ACCESS_TOKEN_STRING = "dummyAccessToken"; 34 | private static final String QUERY_PARAMS_AND_VALUES = "?grant_type=client_credentials&response_type=token"; 35 | 36 | private static final AccessTokenResponseDto TEST_ACCESS_TOKEN_RESPONSE_DTO = new AccessTokenResponseDto(TEST_ACCESS_TOKEN_STRING); 37 | 38 | private HttpClient httpClientMock; 39 | private HttpClientProvider httpClientProviderMock; 40 | private RestApiClientConfig restApiClientConfig; 41 | private ObjectMapper objectMapper = new ObjectMapper(); 42 | private HttpResponse mockedResponse; 43 | private ClientCredentialsAccessTokenProvider clientCredentialsAccessTokenProvider; 44 | 45 | @Before 46 | public void before() throws ClientProtocolException, IOException { 47 | setUpRestApiClientConfig(); 48 | setupMockedHttpClient(); 49 | clientCredentialsAccessTokenProvider = new ClientCredentialsAccessTokenProvider(restApiClientConfig, 50 | httpClientProviderMock, TEST_API_PATH); 51 | } 52 | 53 | @Test 54 | public void testAccessTokenReceived() throws Exception { 55 | String accessToken = clientCredentialsAccessTokenProvider.retrieveAccessToken(); 56 | 57 | assertEquals(TEST_ACCESS_TOKEN_STRING, accessToken); 58 | } 59 | 60 | @Test 61 | public void testAccessTokenRequestUrl() throws Exception { 62 | clientCredentialsAccessTokenProvider.retrieveAccessToken(); 63 | 64 | verify(httpClientMock).execute(argThat(new RequestMatcher("POST", 65 | TEST_HOST + TEST_API_PATH + QUERY_PARAMS_AND_VALUES))); 66 | } 67 | 68 | private void setupMockedHttpClient() throws JsonProcessingException, IOException, ClientProtocolException { 69 | httpClientProviderMock = Mockito.mock(HttpClientProvider.class); 70 | httpClientMock = Mockito.mock(HttpClient.class); 71 | 72 | setupMockedResponse(200, objectMapper.writeValueAsString(TEST_ACCESS_TOKEN_RESPONSE_DTO)); 73 | when(httpClientMock.execute(any())).thenReturn(mockedResponse); 74 | when(httpClientProviderMock.createHttpClient(any())).thenReturn(httpClientMock); 75 | } 76 | 77 | private void setUpRestApiClientConfig() { 78 | restApiClientConfig = RestApiClientConfigBuilder.getBuilder() 79 | .host(TEST_HOST) 80 | .noAuthentication() 81 | .build(); 82 | } 83 | 84 | private void setupMockedResponse(int statusCode, String responseText) { 85 | mockedResponse = Mockito.mock(HttpResponse.class); 86 | StatusLine mockedStatusLine = Mockito.mock(StatusLine.class); 87 | when(mockedResponse.getStatusLine()).thenReturn(mockedStatusLine); 88 | when(mockedStatusLine.getStatusCode()).thenReturn(statusCode); 89 | when(mockedResponse.getEntity()).thenReturn(EntityBuilder.create().setText(responseText).build()); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/auth/oauth/OAuthAuthenticationTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.oauth; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import org.junit.Test; 6 | 7 | import com.sap.cloud.rest.api.client.auth.AuthenticationType; 8 | import com.sap.cloud.rest.api.client.auth.oauth.OAuthAuthentication; 9 | import com.sap.cloud.rest.api.client.auth.oauth.OAuthServerConfig; 10 | import com.sap.cloud.rest.api.client.auth.oauth.OAuthServerConfigBuilder; 11 | 12 | public class OAuthAuthenticationTest { 13 | 14 | private static final char[] TEST_CLIENT_SECRET = "testClientSecret".toCharArray(); 15 | private static final String TEST_CLIENT_ID = "testClientID"; 16 | private static final String TEST_OAUTH_SERVER_URL = "https://testOauthServerURL"; 17 | 18 | private static final OAuthServerConfig OAUTH_SERVER_CONFIG = OAuthServerConfigBuilder.getBuilder() 19 | .oAuthServerHost(TEST_OAUTH_SERVER_URL) 20 | .clientID(TEST_CLIENT_ID) 21 | .clientSecret(TEST_CLIENT_SECRET) 22 | .build(); 23 | 24 | @Test 25 | public void testValidOAuthAuthentication() { 26 | OAuthAuthentication authentication = new OAuthAuthentication(OAUTH_SERVER_CONFIG); 27 | 28 | assertEquals(OAUTH_SERVER_CONFIG, authentication.getOAuthServerConfig()); 29 | assertEquals(AuthenticationType.OAUTH, authentication.getAuthenticationType()); 30 | } 31 | 32 | @Test(expected = IllegalArgumentException.class) 33 | public void nullOAuthAuthenticationTest() { 34 | new OAuthAuthentication(null); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/auth/oauth/OAuthHeaderProviderRequestInterceptorTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.oauth; 2 | 3 | import static org.mockito.Mockito.verify; 4 | import static org.mockito.Mockito.when; 5 | 6 | import org.apache.http.HttpHeaders; 7 | import org.apache.http.HttpRequest; 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | import org.mockito.Mock; 11 | import org.mockito.runners.MockitoJUnitRunner; 12 | 13 | import com.sap.cloud.rest.api.client.auth.oauth.AccessTokenProvider; 14 | import com.sap.cloud.rest.api.client.auth.oauth.OAuthHeaderProviderRequestInterceptor; 15 | 16 | @RunWith(MockitoJUnitRunner.class) 17 | public class OAuthHeaderProviderRequestInterceptorTest { 18 | 19 | private static final String OAUTH_HEADER_KEY = HttpHeaders.AUTHORIZATION; 20 | private static final String TEST_ACCESS_TOKEN = "dummyAccessToken"; 21 | private static final String EXPECTED_AUTH_HEADER_VALUE = "Bearer " + TEST_ACCESS_TOKEN; 22 | 23 | @Mock 24 | private HttpRequest httpRequestMock; 25 | @Mock 26 | private AccessTokenProvider accessTokenProviderMock; 27 | 28 | @Test 29 | public void testAuthHeaderAdded() { 30 | when(accessTokenProviderMock.retrieveAccessToken()).thenReturn(TEST_ACCESS_TOKEN); 31 | OAuthHeaderProviderRequestInterceptor оаuthHeaderProviderRequestInterceptor = new OAuthHeaderProviderRequestInterceptor( 32 | accessTokenProviderMock, OAUTH_HEADER_KEY); 33 | 34 | оаuthHeaderProviderRequestInterceptor.process(httpRequestMock, null); 35 | 36 | verify(httpRequestMock).addHeader(OAUTH_HEADER_KEY, EXPECTED_AUTH_HEADER_VALUE); 37 | 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/auth/oauth/OAuthHttpClientProviderTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.oauth; 2 | 3 | import static org.junit.Assert.assertNotNull; 4 | import static org.junit.Assert.assertTrue; 5 | 6 | import org.apache.http.client.HttpClient; 7 | import org.junit.Test; 8 | 9 | import com.sap.cloud.rest.api.client.auth.Authentication; 10 | import com.sap.cloud.rest.api.client.auth.oauth.OAuthAuthentication; 11 | import com.sap.cloud.rest.api.client.auth.oauth.OAuthHttpClientProvider; 12 | import com.sap.cloud.rest.api.client.auth.oauth.OAuthServerConfig; 13 | import com.sap.cloud.rest.api.client.http.HttpClientCreationException; 14 | import com.sap.cloud.rest.api.client.http.HttpClientProvider; 15 | import com.sap.cloud.rest.api.client.utils.test.HttpClientProviderUtils; 16 | 17 | public class OAuthHttpClientProviderTest { 18 | 19 | private static final char[] TEST_CLIENT_SECRET = "testClientSecret".toCharArray(); 20 | private static final String TEST_CLIENT_ID = "testClientID"; 21 | private static final String TEST_OAUTH_SERVER_URL = "https://testOauthServerURL"; 22 | 23 | @Test 24 | public void createHttpClient() throws HttpClientCreationException { 25 | OAuthServerConfig oAuthServerConfig = new OAuthServerConfig(TEST_OAUTH_SERVER_URL, TEST_CLIENT_ID, 26 | TEST_CLIENT_SECRET); 27 | Authentication authentication = new OAuthAuthentication(oAuthServerConfig); 28 | 29 | HttpClientProvider httpClientProvider = HttpClientProviderUtils 30 | .getHttpClientProviderForAuthentication(authentication); 31 | 32 | assertTrue(httpClientProvider instanceof OAuthHttpClientProvider); 33 | 34 | HttpClient httpClient = httpClientProvider.createHttpClient(); 35 | assertNotNull(httpClient); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/auth/oauth/OAuthServerConfigBuilderTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.oauth; 2 | 3 | import static com.sap.cloud.rest.api.client.auth.oauth.OAuthServerConfig.DEFAULT_OAUTH_HEADER_KEY; 4 | import static com.sap.cloud.rest.api.client.auth.oauth.OAuthServerConfig.DEFAULT_OAUTH_SERVER_API_PATH; 5 | import static org.junit.Assert.assertArrayEquals; 6 | import static org.junit.Assert.assertEquals; 7 | 8 | import java.net.URL; 9 | 10 | import org.apache.http.HttpHeaders; 11 | import org.junit.Test; 12 | 13 | import com.sap.cloud.rest.api.client.auth.oauth.OAuthServerConfig; 14 | import com.sap.cloud.rest.api.client.auth.oauth.OAuthServerConfigBuilder; 15 | 16 | public class OAuthServerConfigBuilderTest { 17 | 18 | private static final String TEST_OAUTH_SERVER_HOST = "https://testOauthServerHost"; 19 | private static final String TEST_OAUTH_SERVER_HOST_WITH_PORT = "https://testOauthServerHost:666"; 20 | private static final String TEST_OAUTH_SERVER_API_PATH = "/test/api"; 21 | private static final char[] TEST_CLIENT_SECRET = "testClientSecret".toCharArray(); 22 | private static final String TEST_CLIENT_ID = "testClientID"; 23 | private static final String TEST_OAUTH_HEADER_KEY = HttpHeaders.PROXY_AUTHORIZATION; 24 | 25 | @Test 26 | public void testBuildWithValidData() { 27 | OAuthServerConfig config = OAuthServerConfigBuilder.getBuilder() 28 | .oAuthServerHost(TEST_OAUTH_SERVER_HOST) 29 | .clientSecret(TEST_CLIENT_SECRET) 30 | .clientID(TEST_CLIENT_ID) 31 | .build(); 32 | 33 | assertEquals(TEST_OAUTH_SERVER_HOST, config.getOAuthServerHost()); 34 | assertEquals(DEFAULT_OAUTH_SERVER_API_PATH, config.getoAuthServerApiPath()); 35 | assertEquals(DEFAULT_OAUTH_HEADER_KEY, config.getoAuthHeaderKey()); 36 | assertEquals(TEST_CLIENT_ID, config.getClientID()); 37 | assertArrayEquals(TEST_CLIENT_SECRET, config.getClientSecret()); 38 | } 39 | 40 | @Test 41 | public void testBuildWithValidDataProvidedApiPath() { 42 | OAuthServerConfig config = OAuthServerConfigBuilder.getBuilder() 43 | .oAuthServerHost(TEST_OAUTH_SERVER_HOST) 44 | .oAuthServerApiPath(TEST_OAUTH_SERVER_API_PATH) 45 | .clientSecret(TEST_CLIENT_SECRET) 46 | .clientID(TEST_CLIENT_ID) 47 | .build(); 48 | 49 | assertEquals(TEST_OAUTH_SERVER_HOST, config.getOAuthServerHost()); 50 | assertEquals(TEST_OAUTH_SERVER_API_PATH, config.getoAuthServerApiPath()); 51 | assertEquals(DEFAULT_OAUTH_HEADER_KEY, config.getoAuthHeaderKey()); 52 | assertEquals(TEST_CLIENT_ID, config.getClientID()); 53 | assertArrayEquals(TEST_CLIENT_SECRET, config.getClientSecret()); 54 | } 55 | 56 | @Test 57 | public void testBuildWithValidDataProvidedHeaderKey() { 58 | OAuthServerConfig config = OAuthServerConfigBuilder.getBuilder() 59 | .oAuthServerHost(TEST_OAUTH_SERVER_HOST) 60 | .oAuthHeaderKey(TEST_OAUTH_HEADER_KEY) 61 | .clientSecret(TEST_CLIENT_SECRET) 62 | .clientID(TEST_CLIENT_ID) 63 | .build(); 64 | 65 | assertEquals(TEST_OAUTH_SERVER_HOST, config.getOAuthServerHost()); 66 | assertEquals(DEFAULT_OAUTH_SERVER_API_PATH, config.getoAuthServerApiPath()); 67 | assertEquals(TEST_OAUTH_HEADER_KEY, config.getoAuthHeaderKey()); 68 | assertEquals(TEST_CLIENT_ID, config.getClientID()); 69 | assertArrayEquals(TEST_CLIENT_SECRET, config.getClientSecret()); 70 | } 71 | 72 | @Test 73 | public void testBuildWithValidDataProvidedApiPathAndHeaderKey() { 74 | OAuthServerConfig config = OAuthServerConfigBuilder.getBuilder() 75 | .oAuthServerHost(TEST_OAUTH_SERVER_HOST) 76 | .oAuthServerApiPath(TEST_OAUTH_SERVER_API_PATH) 77 | .oAuthHeaderKey(TEST_OAUTH_HEADER_KEY) 78 | .clientSecret(TEST_CLIENT_SECRET) 79 | .clientID(TEST_CLIENT_ID) 80 | .build(); 81 | 82 | assertEquals(TEST_OAUTH_SERVER_HOST, config.getOAuthServerHost()); 83 | assertEquals(TEST_OAUTH_SERVER_API_PATH, config.getoAuthServerApiPath()); 84 | assertEquals(TEST_OAUTH_HEADER_KEY, config.getoAuthHeaderKey()); 85 | assertEquals(TEST_CLIENT_ID, config.getClientID()); 86 | assertArrayEquals(TEST_CLIENT_SECRET, config.getClientSecret()); 87 | } 88 | 89 | @Test 90 | public void testHostFromUrlWithoutPort() throws Exception { 91 | final OAuthServerConfig config = OAuthServerConfigBuilder.getBuilder() 92 | .oAuthServerHost(new URL(TEST_OAUTH_SERVER_HOST)) 93 | .clientID(TEST_CLIENT_ID) 94 | .clientSecret(TEST_CLIENT_SECRET) 95 | .build(); 96 | 97 | assertEquals(TEST_OAUTH_SERVER_HOST, config.getOAuthServerHost()); 98 | } 99 | 100 | @Test 101 | public void testHostFromUrlWithPort() throws Exception { 102 | final OAuthServerConfig config = OAuthServerConfigBuilder.getBuilder() 103 | .oAuthServerHost(new URL(TEST_OAUTH_SERVER_HOST_WITH_PORT)) 104 | .clientID(TEST_CLIENT_ID) 105 | .clientSecret(TEST_CLIENT_SECRET) 106 | .build(); 107 | 108 | assertEquals(TEST_OAUTH_SERVER_HOST_WITH_PORT, config.getOAuthServerHost()); 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/auth/oauth/OAuthServerConfigTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.auth.oauth; 2 | 3 | import static com.sap.cloud.rest.api.client.auth.oauth.OAuthServerConfig.CLIENT_ID_DISPLAY_NAME; 4 | import static com.sap.cloud.rest.api.client.auth.oauth.OAuthServerConfig.CLIENT_SECRET_DISPLAY_NAME; 5 | import static com.sap.cloud.rest.api.client.auth.oauth.OAuthServerConfig.DEFAULT_OAUTH_HEADER_KEY; 6 | import static com.sap.cloud.rest.api.client.auth.oauth.OAuthServerConfig.DEFAULT_OAUTH_SERVER_API_PATH; 7 | import static com.sap.cloud.rest.api.client.auth.oauth.OAuthServerConfig.OAUTH_HEADER_KEY_DISPLAY_NAME; 8 | import static com.sap.cloud.rest.api.client.auth.oauth.OAuthServerConfig.OAUTH_SERVER_API_PATH_DISPLAY_NAME; 9 | import static com.sap.cloud.rest.api.client.auth.oauth.OAuthServerConfig.OAUTH_SERVER_HOST_DISPLAY_NAME; 10 | import static com.sap.cloud.rest.api.client.utils.ValidateArgument.CANNOT_BE_BLANK_MSG; 11 | import static com.sap.cloud.rest.api.client.utils.ValidateArgument.CANNOT_BE_NULL_MSG; 12 | import static com.sap.cloud.rest.api.client.utils.ValidateArgument.NOT_VALID_URL_MSG; 13 | import static org.junit.Assert.assertArrayEquals; 14 | import static org.junit.Assert.assertEquals; 15 | 16 | import org.apache.http.HttpHeaders; 17 | import org.junit.Rule; 18 | import org.junit.Test; 19 | import org.junit.rules.ExpectedException; 20 | 21 | import com.sap.cloud.rest.api.client.auth.oauth.OAuthServerConfig; 22 | 23 | public class OAuthServerConfigTest { 24 | 25 | private static final String TEST_OAUTH_SERVER_HOST = "https://testOauthServerHost"; 26 | private static final String TEST_OAUTH_SERVER_API_PATH = "/test/api"; 27 | private static final char[] TEST_CLIENT_SECRET = "testClientSecret".toCharArray(); 28 | private static final String TEST_CLIENT_ID = "testClientID"; 29 | private static final String TEST_OAUTH_HEADER_KEY = HttpHeaders.PROXY_AUTHORIZATION; 30 | 31 | private static final String TEST_INCORRECT_OAUTH_SERVER_HOST = "incorrect host"; 32 | 33 | @Rule 34 | public ExpectedException expected = ExpectedException.none(); 35 | 36 | @Test 37 | public void testCreateConfigWithValidData() { 38 | OAuthServerConfig config = new OAuthServerConfig(TEST_OAUTH_SERVER_HOST, TEST_CLIENT_ID, TEST_CLIENT_SECRET); 39 | 40 | assertEquals(TEST_OAUTH_SERVER_HOST, config.getOAuthServerHost()); 41 | assertEquals(DEFAULT_OAUTH_SERVER_API_PATH, config.getoAuthServerApiPath()); 42 | assertEquals(DEFAULT_OAUTH_HEADER_KEY, config.getoAuthHeaderKey()); 43 | assertEquals(TEST_CLIENT_ID, config.getClientID()); 44 | assertArrayEquals(TEST_CLIENT_SECRET, config.getClientSecret()); 45 | } 46 | 47 | @Test 48 | public void testCreateConfigWithValidDataProvidedApiPath() { 49 | OAuthServerConfig config = new OAuthServerConfig(TEST_OAUTH_SERVER_HOST, TEST_OAUTH_SERVER_API_PATH, 50 | TEST_CLIENT_ID, TEST_CLIENT_SECRET); 51 | 52 | assertEquals(TEST_OAUTH_SERVER_HOST, config.getOAuthServerHost()); 53 | assertEquals(TEST_OAUTH_SERVER_API_PATH, config.getoAuthServerApiPath()); 54 | assertEquals(DEFAULT_OAUTH_HEADER_KEY, config.getoAuthHeaderKey()); 55 | assertEquals(TEST_CLIENT_ID, config.getClientID()); 56 | assertArrayEquals(TEST_CLIENT_SECRET, config.getClientSecret()); 57 | } 58 | 59 | @Test 60 | public void testCreateConfigWithValidDataProvidedHeaderKey() { 61 | OAuthServerConfig config = new OAuthServerConfig(TEST_OAUTH_SERVER_HOST, 62 | TEST_CLIENT_ID, TEST_CLIENT_SECRET, TEST_OAUTH_HEADER_KEY); 63 | 64 | assertEquals(TEST_OAUTH_SERVER_HOST, config.getOAuthServerHost()); 65 | assertEquals(DEFAULT_OAUTH_SERVER_API_PATH, config.getoAuthServerApiPath()); 66 | assertEquals(TEST_OAUTH_HEADER_KEY, config.getoAuthHeaderKey()); 67 | assertEquals(TEST_CLIENT_ID, config.getClientID()); 68 | assertArrayEquals(TEST_CLIENT_SECRET, config.getClientSecret()); 69 | } 70 | 71 | @Test 72 | public void testCreateConfigWithValidDataProvidedApiPathAndHeaderKey() { 73 | OAuthServerConfig config = new OAuthServerConfig(TEST_OAUTH_SERVER_HOST, TEST_OAUTH_SERVER_API_PATH, 74 | TEST_CLIENT_ID, TEST_CLIENT_SECRET, TEST_OAUTH_HEADER_KEY); 75 | 76 | assertEquals(TEST_OAUTH_SERVER_HOST, config.getOAuthServerHost()); 77 | assertEquals(TEST_OAUTH_SERVER_API_PATH, config.getoAuthServerApiPath()); 78 | assertEquals(TEST_OAUTH_HEADER_KEY, config.getoAuthHeaderKey()); 79 | assertEquals(TEST_CLIENT_ID, config.getClientID()); 80 | assertArrayEquals(TEST_CLIENT_SECRET, config.getClientSecret()); 81 | } 82 | 83 | @Test 84 | public void testCreateConfigWithNullOAuthServerHost() { 85 | expected.expect(IllegalArgumentException.class); 86 | expected.expectMessage(OAUTH_SERVER_HOST_DISPLAY_NAME + CANNOT_BE_BLANK_MSG); 87 | 88 | new OAuthServerConfig(null, TEST_OAUTH_SERVER_API_PATH, 89 | TEST_CLIENT_ID, TEST_CLIENT_SECRET, TEST_OAUTH_HEADER_KEY); 90 | } 91 | 92 | @Test 93 | public void testCreateConfigWithBlankOAuthServerHost() { 94 | expected.expect(IllegalArgumentException.class); 95 | expected.expectMessage(OAUTH_SERVER_HOST_DISPLAY_NAME + CANNOT_BE_BLANK_MSG); 96 | 97 | new OAuthServerConfig("", TEST_OAUTH_SERVER_API_PATH, 98 | TEST_CLIENT_ID, TEST_CLIENT_SECRET, TEST_OAUTH_HEADER_KEY); 99 | } 100 | 101 | @Test 102 | public void testCreateConfigWithIncorrectOAuthServerHost() { 103 | expected.expect(IllegalArgumentException.class); 104 | expected.expectMessage(OAUTH_SERVER_HOST_DISPLAY_NAME + NOT_VALID_URL_MSG); 105 | 106 | new OAuthServerConfig(TEST_INCORRECT_OAUTH_SERVER_HOST, TEST_OAUTH_SERVER_API_PATH, 107 | TEST_CLIENT_ID, TEST_CLIENT_SECRET, TEST_OAUTH_HEADER_KEY); 108 | } 109 | 110 | @Test 111 | public void testCreateConfigWithNullOAuthServerApiPath() { 112 | expected.expect(IllegalArgumentException.class); 113 | expected.expectMessage(OAUTH_SERVER_API_PATH_DISPLAY_NAME + CANNOT_BE_NULL_MSG); 114 | 115 | new OAuthServerConfig(TEST_OAUTH_SERVER_HOST, null, 116 | TEST_CLIENT_ID, TEST_CLIENT_SECRET, TEST_OAUTH_HEADER_KEY); 117 | } 118 | 119 | @Test 120 | public void testCreateConfigWithNullClientSecret() { 121 | expected.expect(IllegalArgumentException.class); 122 | expected.expectMessage(CLIENT_SECRET_DISPLAY_NAME + CANNOT_BE_NULL_MSG); 123 | 124 | new OAuthServerConfig(TEST_OAUTH_SERVER_HOST, TEST_OAUTH_SERVER_API_PATH, 125 | TEST_CLIENT_ID, null, TEST_OAUTH_HEADER_KEY); 126 | } 127 | 128 | @Test 129 | public void testCreateConfigWithNullClientId() { 130 | expected.expect(IllegalArgumentException.class); 131 | expected.expectMessage(CLIENT_ID_DISPLAY_NAME + CANNOT_BE_BLANK_MSG); 132 | 133 | new OAuthServerConfig(TEST_OAUTH_SERVER_HOST, TEST_OAUTH_SERVER_API_PATH, 134 | null, TEST_CLIENT_SECRET, TEST_OAUTH_HEADER_KEY); 135 | } 136 | 137 | @Test 138 | public void testCreateConfigWithEmptyClientId() { 139 | expected.expect(IllegalArgumentException.class); 140 | expected.expectMessage(CLIENT_ID_DISPLAY_NAME + CANNOT_BE_BLANK_MSG); 141 | 142 | new OAuthServerConfig(TEST_OAUTH_SERVER_HOST, TEST_OAUTH_SERVER_API_PATH, 143 | "", TEST_CLIENT_SECRET, TEST_OAUTH_HEADER_KEY); 144 | } 145 | 146 | @Test 147 | public void testCreateConfigWithNullOAuthHeaderKey() { 148 | expected.expect(IllegalArgumentException.class); 149 | expected.expectMessage(OAUTH_HEADER_KEY_DISPLAY_NAME + CANNOT_BE_BLANK_MSG); 150 | 151 | new OAuthServerConfig(TEST_OAUTH_SERVER_HOST, TEST_OAUTH_SERVER_API_PATH, 152 | TEST_CLIENT_ID, TEST_CLIENT_SECRET, null); 153 | } 154 | 155 | @Test 156 | public void testCreateConfigWithEmptyOAuthHeaderKey() { 157 | expected.expect(IllegalArgumentException.class); 158 | expected.expectMessage(OAUTH_HEADER_KEY_DISPLAY_NAME + CANNOT_BE_BLANK_MSG); 159 | 160 | new OAuthServerConfig(TEST_OAUTH_SERVER_HOST, TEST_OAUTH_SERVER_API_PATH, 161 | TEST_CLIENT_ID, TEST_CLIENT_SECRET, ""); 162 | } 163 | 164 | } 165 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/config/RestApiClientConfigBuilderTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.config; 2 | 3 | import static org.junit.Assert.assertArrayEquals; 4 | import static org.junit.Assert.assertEquals; 5 | import static org.junit.Assert.assertTrue; 6 | import static org.mockito.Mockito.mock; 7 | 8 | import java.net.URL; 9 | import java.security.KeyStore; 10 | 11 | import org.apache.http.HttpHost; 12 | import org.apache.http.client.methods.RequestBuilder; 13 | import org.apache.http.conn.routing.HttpRoute; 14 | import org.apache.http.conn.routing.HttpRoutePlanner; 15 | import org.apache.http.impl.conn.DefaultProxyRoutePlanner; 16 | import org.apache.http.impl.conn.DefaultRoutePlanner; 17 | import org.apache.http.protocol.BasicHttpContext; 18 | import org.junit.Test; 19 | 20 | import com.sap.cloud.rest.api.client.auth.AuthenticationType; 21 | import com.sap.cloud.rest.api.client.auth.basic.BasicAuthentication; 22 | import com.sap.cloud.rest.api.client.auth.cert.ClientCertAuthentication; 23 | import com.sap.cloud.rest.api.client.auth.cert.KeystoreConfig; 24 | import com.sap.cloud.rest.api.client.auth.cert.KeystoreConfigBuilder; 25 | import com.sap.cloud.rest.api.client.auth.none.NoAuthentication; 26 | import com.sap.cloud.rest.api.client.auth.oauth.OAuthAuthentication; 27 | import com.sap.cloud.rest.api.client.auth.oauth.OAuthServerConfig; 28 | import com.sap.cloud.rest.api.client.config.RestApiClientConfig; 29 | import com.sap.cloud.rest.api.client.config.RestApiClientConfigBuilder; 30 | import com.sap.cloud.rest.api.client.http.Proxy; 31 | 32 | public class RestApiClientConfigBuilderTest { 33 | 34 | private static final char[] TEST_CLIENT_SECRET = "testClientSecret".toCharArray(); 35 | private static final String TEST_CLIENT_ID = "testClientID"; 36 | private static final String TEST_OAUTH_SERVER_URL = "https://testOauthServerURL"; 37 | private static final String TEST_HOSTNAME = "www.example.com"; 38 | private static final String TEST_HOST = "https://" + TEST_HOSTNAME; 39 | private static final String TEST_HOST_WITH_PORT = "https://www.example.com:69"; 40 | private static final String TEST_USER = "example_user"; 41 | private static final KeyStore TEST_KEYSTORE = mock(KeyStore.class); 42 | private static final char[] TEST_PASSWORD = "example-password".toCharArray(); 43 | private static final String TEST_ALIAS = "exampleAlias"; 44 | private static final KeystoreConfig TEST_KEYSTORE_CONFIG = KeystoreConfigBuilder.getBuilder() 45 | .keystore(TEST_KEYSTORE) 46 | .keystorePassword(TEST_PASSWORD) 47 | .keyAlias(TEST_ALIAS) 48 | .build(); 49 | 50 | private static final String PROXY_HOST = "proxy.int"; 51 | private static final int PROXY_PORT = 8888; 52 | private static final Proxy PROXY_CREDENTIALS = new Proxy(PROXY_HOST, PROXY_PORT); 53 | private static final HttpHost PROXY_HTTP_HOST = new HttpHost(PROXY_HOST, PROXY_PORT, 54 | PROXY_CREDENTIALS.getProxyScheme()); 55 | 56 | @Test 57 | public void buildWithHostOnlyTest() { 58 | RestApiClientConfig config = RestApiClientConfigBuilder.getBuilder() 59 | .host(TEST_HOST) 60 | .build(); 61 | 62 | assertEquals(config.getHost(), TEST_HOST); 63 | 64 | // Assert default authentication is used 65 | NoAuthentication authentication = (NoAuthentication) config.getAuthentication(); 66 | assertEquals(AuthenticationType.NO_AUTH, authentication.getAuthenticationType()); 67 | } 68 | 69 | @Test 70 | public void buildWithAuthenticationTest() { 71 | RestApiClientConfig config = RestApiClientConfigBuilder.getBuilder() 72 | .host(TEST_HOST) 73 | .authentication(new BasicAuthentication(TEST_USER, TEST_PASSWORD)) 74 | .build(); 75 | 76 | BasicAuthentication authentication = (BasicAuthentication) config.getAuthentication(); 77 | assertEquals(TEST_USER, authentication.getUsername()); 78 | assertArrayEquals(TEST_PASSWORD, authentication.getPassword()); 79 | assertEquals(AuthenticationType.BASIC, authentication.getAuthenticationType()); 80 | } 81 | 82 | @Test 83 | public void buildWithBasicAuthTest() { 84 | RestApiClientConfig config = RestApiClientConfigBuilder.getBuilder() 85 | .host(TEST_HOST) 86 | .basicAuthentication(TEST_USER, TEST_PASSWORD) 87 | .build(); 88 | 89 | BasicAuthentication authentication = (BasicAuthentication) config.getAuthentication(); 90 | assertEquals(TEST_USER, authentication.getUsername()); 91 | assertArrayEquals(TEST_PASSWORD, authentication.getPassword()); 92 | assertEquals(AuthenticationType.BASIC, authentication.getAuthenticationType()); 93 | } 94 | 95 | @Test 96 | public void buildWithClientCertAuthTest() { 97 | RestApiClientConfig config = RestApiClientConfigBuilder.getBuilder() 98 | .host(TEST_HOST) 99 | .clientCertAuthentication(TEST_KEYSTORE_CONFIG) 100 | .build(); 101 | 102 | ClientCertAuthentication authentication = (ClientCertAuthentication) config.getAuthentication(); 103 | assertEquals(TEST_KEYSTORE_CONFIG, authentication.getKeystoreConfig()); 104 | assertEquals(AuthenticationType.CLIENT_CERT, authentication.getAuthenticationType()); 105 | } 106 | 107 | @Test 108 | public void buildWithOAuthTest() { 109 | OAuthServerConfig oAuthServerConfig = new OAuthServerConfig(TEST_OAUTH_SERVER_URL, TEST_CLIENT_ID, 110 | TEST_CLIENT_SECRET); 111 | RestApiClientConfig config = RestApiClientConfigBuilder.getBuilder() 112 | .host(TEST_HOST) 113 | .oAuthAuthentication(oAuthServerConfig) 114 | .build(); 115 | 116 | OAuthAuthentication authentication = (OAuthAuthentication) config.getAuthentication(); 117 | assertEquals(TEST_OAUTH_SERVER_URL, authentication.getOAuthServerConfig().getOAuthServerHost()); 118 | assertEquals(TEST_CLIENT_ID, authentication.getOAuthServerConfig().getClientID()); 119 | assertArrayEquals(TEST_CLIENT_SECRET, authentication.getOAuthServerConfig().getClientSecret()); 120 | assertEquals(AuthenticationType.OAUTH, authentication.getAuthenticationType()); 121 | } 122 | 123 | @Test 124 | public void buildWithNoAuthTest() { 125 | RestApiClientConfig config = RestApiClientConfigBuilder.getBuilder() 126 | .host(TEST_HOST) 127 | .noAuthentication() 128 | .build(); 129 | 130 | NoAuthentication authentication = (NoAuthentication) config.getAuthentication(); 131 | assertEquals(AuthenticationType.NO_AUTH, authentication.getAuthenticationType()); 132 | } 133 | 134 | @Test 135 | public void buildWithProxyTest() throws Exception { 136 | RestApiClientConfig config = RestApiClientConfigBuilder.getBuilder() 137 | .host(TEST_HOST) 138 | .proxy(PROXY_CREDENTIALS) 139 | .build(); 140 | 141 | HttpRoute route = config.getRoutePlanner() 142 | .determineRoute(new HttpHost(TEST_HOSTNAME), RequestBuilder.get().build(), new BasicHttpContext()); 143 | 144 | assertEquals(2, route.getHopCount()); 145 | assertEquals(PROXY_HTTP_HOST, route.getHopTarget(0)); 146 | assertEquals(PROXY_HTTP_HOST, route.getProxyHost()); 147 | } 148 | 149 | @Test 150 | public void buildWithNullProxyTest() throws Exception { 151 | Proxy nullProxy = null; 152 | RestApiClientConfig config = RestApiClientConfigBuilder.getBuilder() 153 | .host(TEST_HOST) 154 | .proxy(nullProxy) 155 | .build(); 156 | 157 | assertTrue(config.getRoutePlanner() instanceof DefaultRoutePlanner); 158 | } 159 | 160 | @Test 161 | public void buildWithRoutePlannerTest() throws Exception { 162 | HttpRoutePlanner routePlanner = new DefaultProxyRoutePlanner(PROXY_HTTP_HOST); 163 | 164 | RestApiClientConfig config = RestApiClientConfigBuilder.getBuilder() 165 | .host(TEST_HOST) 166 | .proxy(routePlanner) 167 | .build(); 168 | 169 | HttpRoute route = config.getRoutePlanner() 170 | .determineRoute(new HttpHost(TEST_HOSTNAME), RequestBuilder.get().build(), new BasicHttpContext()); 171 | 172 | assertEquals(2, route.getHopCount()); 173 | assertEquals(PROXY_HTTP_HOST, route.getHopTarget(0)); 174 | assertEquals(PROXY_HTTP_HOST, route.getProxyHost()); 175 | } 176 | 177 | @Test 178 | public void buildWithNullRoutePlannerTest() throws Exception { 179 | HttpRoutePlanner nullRoutePlanner = null; 180 | RestApiClientConfig config = RestApiClientConfigBuilder.getBuilder() 181 | .host(TEST_HOST) 182 | .proxy(nullRoutePlanner) 183 | .build(); 184 | 185 | assertTrue(config.getRoutePlanner() instanceof DefaultRoutePlanner); 186 | } 187 | 188 | @Test 189 | public void buildWithProxyAndAuthenticationTest() throws Exception { 190 | RestApiClientConfig config = RestApiClientConfigBuilder.getBuilder() 191 | .host(TEST_HOST) 192 | .authentication(new BasicAuthentication(TEST_USER, TEST_PASSWORD)) 193 | .proxy(PROXY_CREDENTIALS) 194 | .build(); 195 | 196 | BasicAuthentication authentication = (BasicAuthentication) config.getAuthentication(); 197 | assertEquals(TEST_USER, authentication.getUsername()); 198 | assertArrayEquals(TEST_PASSWORD, authentication.getPassword()); 199 | assertEquals(AuthenticationType.BASIC, authentication.getAuthenticationType()); 200 | 201 | HttpRoute route = config.getRoutePlanner() 202 | .determineRoute(new HttpHost(TEST_HOSTNAME), RequestBuilder.get().build(), new BasicHttpContext()); 203 | 204 | assertEquals(2, route.getHopCount()); 205 | assertEquals(PROXY_HTTP_HOST, route.getHopTarget(0)); 206 | assertEquals(PROXY_HTTP_HOST, route.getProxyHost()); 207 | } 208 | 209 | @Test 210 | public void buildWithHostFromUrlTest() throws Exception { 211 | final RestApiClientConfig config = RestApiClientConfigBuilder.getBuilder() 212 | .noAuthentication() 213 | .host(new URL(TEST_HOST)) 214 | .build(); 215 | 216 | assertEquals(TEST_HOST, config.getHost()); 217 | } 218 | 219 | @Test 220 | public void buildWithHostWithPortFromUrlTest() throws Exception { 221 | final RestApiClientConfig config = RestApiClientConfigBuilder.getBuilder() 222 | .noAuthentication() 223 | .host(new URL(TEST_HOST_WITH_PORT)) 224 | .build(); 225 | 226 | assertEquals(TEST_HOST_WITH_PORT, config.getHost()); 227 | } 228 | 229 | @Test 230 | public void getRestApiClientBuilderTest() { 231 | assertTrue(RestApiClientConfigBuilder.getBuilder() instanceof RestApiClientConfigBuilder); 232 | } 233 | } 234 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/config/RestApiClientConfigTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.config; 2 | 3 | import static com.sap.cloud.rest.api.client.config.RestApiClientConfig.AUTHENTICATION_DISPLAY_NAME; 4 | import static com.sap.cloud.rest.api.client.config.RestApiClientConfig.HOST_DISPLAY_NAME; 5 | import static com.sap.cloud.rest.api.client.config.RestApiClientConfig.ROUTE_PLANNER_DISPLAY_NAME; 6 | import static com.sap.cloud.rest.api.client.utils.ValidateArgument.CANNOT_BE_BLANK_MSG; 7 | import static com.sap.cloud.rest.api.client.utils.ValidateArgument.CANNOT_BE_NULL_MSG; 8 | import static org.junit.Assert.assertEquals; 9 | import static org.junit.Assert.assertTrue; 10 | import static org.mockito.Mockito.mock; 11 | 12 | import org.apache.http.conn.routing.HttpRoutePlanner; 13 | import org.apache.http.impl.conn.DefaultRoutePlanner; 14 | import org.junit.Rule; 15 | import org.junit.Test; 16 | import org.junit.rules.ExpectedException; 17 | 18 | import com.sap.cloud.rest.api.client.auth.Authentication; 19 | import com.sap.cloud.rest.api.client.auth.none.NoAuthentication; 20 | import com.sap.cloud.rest.api.client.config.RestApiClientConfig; 21 | 22 | public class RestApiClientConfigTest { 23 | 24 | @Rule 25 | public ExpectedException expected = ExpectedException.none(); 26 | 27 | private static final String TEST_HOST = "https://example.com"; 28 | private static final Authentication AUTHENTICATION = mock(Authentication.class); 29 | private static final HttpRoutePlanner ROUTE_PLANNER = mock(HttpRoutePlanner.class); 30 | 31 | @Test 32 | public void createRestApiClientConfigTest() { 33 | RestApiClientConfig config = new RestApiClientConfig(TEST_HOST, AUTHENTICATION, ROUTE_PLANNER); 34 | 35 | assertEquals(TEST_HOST, config.getHost()); 36 | assertEquals(AUTHENTICATION, config.getAuthentication()); 37 | assertEquals(ROUTE_PLANNER, config.getRoutePlanner()); 38 | } 39 | 40 | @Test 41 | public void createRestApiClientConfigWithDefaultRoutePlannerTest() { 42 | RestApiClientConfig config = new RestApiClientConfig(TEST_HOST, AUTHENTICATION); 43 | 44 | assertEquals(TEST_HOST, config.getHost()); 45 | assertEquals(AUTHENTICATION, config.getAuthentication()); 46 | assertTrue(config.getRoutePlanner() instanceof DefaultRoutePlanner); 47 | } 48 | 49 | @Test 50 | public void createRestApiClientConfigWithDefaultAuthenticationTest() { 51 | RestApiClientConfig config = new RestApiClientConfig(TEST_HOST, ROUTE_PLANNER); 52 | 53 | assertEquals(TEST_HOST, config.getHost()); 54 | assertTrue(config.getAuthentication() instanceof NoAuthentication); 55 | assertEquals(ROUTE_PLANNER, config.getRoutePlanner()); 56 | } 57 | 58 | @Test 59 | public void createRestApiClientConfigWithDefaultAuthenticationAndRoutePlannerTest() { 60 | RestApiClientConfig config = new RestApiClientConfig(TEST_HOST); 61 | 62 | assertEquals(TEST_HOST, config.getHost()); 63 | assertTrue(config.getAuthentication() instanceof NoAuthentication); 64 | assertTrue(config.getRoutePlanner() instanceof DefaultRoutePlanner); 65 | } 66 | 67 | @Test 68 | public void createRestApiClientConfigNullHostTest() { 69 | expected.expect(IllegalArgumentException.class); 70 | expected.expectMessage(HOST_DISPLAY_NAME + CANNOT_BE_BLANK_MSG); 71 | 72 | new RestApiClientConfig(null, AUTHENTICATION); 73 | } 74 | 75 | @Test 76 | public void createRestApiClientConfigEmptyHostTest() { 77 | expected.expect(IllegalArgumentException.class); 78 | expected.expectMessage(HOST_DISPLAY_NAME + CANNOT_BE_BLANK_MSG); 79 | 80 | new RestApiClientConfig(null, AUTHENTICATION); 81 | } 82 | 83 | @Test 84 | public void createRestApiClientConfigNullAuthenticationTest() { 85 | expected.expect(IllegalArgumentException.class); 86 | expected.expectMessage(AUTHENTICATION_DISPLAY_NAME + CANNOT_BE_NULL_MSG); 87 | 88 | Authentication authentication = null; 89 | new RestApiClientConfig(TEST_HOST, authentication); 90 | } 91 | 92 | @Test 93 | public void createRestApiClientConfigNullRoutePlannerTest() { 94 | expected.expect(IllegalArgumentException.class); 95 | expected.expectMessage(ROUTE_PLANNER_DISPLAY_NAME + CANNOT_BE_NULL_MSG); 96 | 97 | HttpRoutePlanner httpRoutePlanner = null; 98 | new RestApiClientConfig(TEST_HOST, httpRoutePlanner); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/exceptions/ConnectionExceptionTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.exceptions; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import java.io.IOException; 6 | 7 | import org.apache.http.client.methods.RequestBuilder; 8 | import org.junit.Test; 9 | 10 | import com.sap.cloud.rest.api.client.exceptions.ConnectionException; 11 | import com.sap.cloud.rest.api.client.model.Request; 12 | 13 | public class ConnectionExceptionTest { 14 | 15 | private static final String TEST_MESSAGE = "test_message"; 16 | private static final IOException TEST_CAUSE = new IOException(); 17 | private static final Request TEST_REQUEST = new Request<>(RequestBuilder.get().build()); 18 | 19 | @Test 20 | public void testGetRequest() { 21 | ConnectionException ex = new ConnectionException(TEST_MESSAGE, TEST_CAUSE, TEST_REQUEST); 22 | 23 | assertEquals(TEST_REQUEST, ex.getRequest()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/exceptions/ResponseExceptionTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.exceptions; 2 | 3 | import static com.sap.cloud.rest.api.client.utils.test.MockResponseUtil.makeMockedResponseWithStatusCode; 4 | import static org.junit.Assert.assertArrayEquals; 5 | import static org.junit.Assert.assertEquals; 6 | import static org.mockito.Mockito.doReturn; 7 | 8 | import java.io.IOException; 9 | 10 | import org.apache.http.Header; 11 | import org.apache.http.HttpResponse; 12 | import org.apache.http.client.methods.RequestBuilder; 13 | import org.junit.Before; 14 | import org.junit.Test; 15 | 16 | import com.sap.cloud.rest.api.client.exceptions.ResponseException; 17 | import com.sap.cloud.rest.api.client.model.HttpExchangeContext; 18 | import com.sap.cloud.rest.api.client.model.Request; 19 | import com.sap.cloud.rest.api.client.model.Response; 20 | 21 | public class ResponseExceptionTest { 22 | 23 | private static final int TEST_STATUS_CODE = 500; 24 | private static final String TEST_RESPONSE_BODY = "test_response_body"; 25 | private static final String TEST_MESSAGE = "test_message"; 26 | private static final Header[] TEST_RESPONSE_HEADERS = new Header[] {}; 27 | private static final Throwable TEST_CAUSE = new IOException(); 28 | 29 | private static final Request TEST_REQUEST = new Request<>(RequestBuilder.get().build()); 30 | private static final HttpResponse TEST_HTTP_RESPONSE = makeMockedResponseWithStatusCode(TEST_STATUS_CODE); 31 | private static final Response TEST_RESPONSE = new Response<>(TEST_HTTP_RESPONSE, TEST_RESPONSE_BODY); 32 | private static final HttpExchangeContext TEST_CONTEXT = new HttpExchangeContext(TEST_REQUEST, TEST_RESPONSE); 33 | 34 | @Before 35 | public void setup() { 36 | doReturn(TEST_RESPONSE_HEADERS).when(TEST_HTTP_RESPONSE).getAllHeaders(); 37 | } 38 | 39 | @Test 40 | public void testGetRequest() { 41 | ResponseException ex = new ResponseException(TEST_MESSAGE, TEST_CONTEXT); 42 | 43 | assertEquals(TEST_REQUEST, ex.getRequest()); 44 | } 45 | 46 | @Test 47 | public void testGetStatusCode() { 48 | ResponseException ex = new ResponseException(TEST_MESSAGE, TEST_CONTEXT); 49 | 50 | assertEquals(TEST_STATUS_CODE, ex.getResponse().getStatusCode()); 51 | } 52 | 53 | @Test 54 | public void testGetResponseBody() { 55 | ResponseException ex = new ResponseException(TEST_MESSAGE, TEST_CONTEXT); 56 | 57 | assertEquals(TEST_RESPONSE_BODY, ex.getResponse().getEntity()); 58 | } 59 | 60 | @Test 61 | public void testGetResponseHeaders() { 62 | ResponseException ex = new ResponseException(TEST_MESSAGE, TEST_CONTEXT); 63 | 64 | assertArrayEquals(TEST_RESPONSE_HEADERS, ex.getResponse().getHeaders()); 65 | } 66 | 67 | @Test 68 | public void testGetCause() { 69 | ResponseException ex = new ResponseException(TEST_MESSAGE, TEST_CONTEXT, TEST_CAUSE); 70 | 71 | assertEquals(TEST_CAUSE, ex.getCause()); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/handler/DefaultResponseHandlerTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.handler; 2 | 3 | import static com.sap.cloud.rest.api.client.utils.test.MockResponseUtil.makeMockedResponseWithEntity; 4 | import static org.junit.Assert.assertEquals; 5 | import static org.mockito.Mockito.doReturn; 6 | import static org.mockito.Mockito.mock; 7 | 8 | import java.io.IOException; 9 | 10 | import org.apache.http.HttpResponse; 11 | import org.junit.Test; 12 | 13 | import com.sap.cloud.rest.api.client.exceptions.ConnectionException; 14 | import com.sap.cloud.rest.api.client.handler.DefaultResponseHandler; 15 | 16 | public class DefaultResponseHandlerTest { 17 | 18 | private DefaultResponseHandler responseHandler = new DefaultResponseHandler(); 19 | 20 | @Test 21 | public void testHandleResponse() throws ConnectionException, IOException { 22 | String expectedResponse = "responseBody"; 23 | HttpResponse httpResponse = makeMockedResponseWithEntity(expectedResponse); 24 | 25 | String actualResponse = responseHandler.handleResponse(httpResponse); 26 | assertEquals(expectedResponse, actualResponse); 27 | } 28 | 29 | @Test 30 | public void testHandleResponseWithNullEntity() throws ConnectionException, IOException { 31 | HttpResponse httpResponse = mock(HttpResponse.class); 32 | doReturn(null).when(httpResponse).getEntity(); 33 | 34 | String actualResponse = responseHandler.handleResponse(httpResponse); 35 | assertEquals("", actualResponse); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/handler/DefaultStatusCodeHandlerTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.handler; 2 | 3 | import static com.sap.cloud.rest.api.client.handler.DefaultStatusCodeHandler.HTTP_RESPOSNE_EXCEPTION_MSG; 4 | import static com.sap.cloud.rest.api.client.handler.DefaultStatusCodeHandler.UNAUTHORIZED_MSG; 5 | import static java.text.MessageFormat.format; 6 | import static org.mockito.Mockito.doReturn; 7 | import static org.mockito.Mockito.mock; 8 | 9 | import org.apache.http.HttpResponse; 10 | import org.apache.http.StatusLine; 11 | import org.apache.http.client.methods.RequestBuilder; 12 | import org.junit.Rule; 13 | import org.junit.Test; 14 | import org.junit.rules.ExpectedException; 15 | 16 | import com.sap.cloud.rest.api.client.exceptions.ResponseException; 17 | import com.sap.cloud.rest.api.client.exceptions.UnauthorizedException; 18 | import com.sap.cloud.rest.api.client.handler.DefaultStatusCodeHandler; 19 | import com.sap.cloud.rest.api.client.handler.StatusCodeHandler; 20 | import com.sap.cloud.rest.api.client.model.HttpExchangeContext; 21 | import com.sap.cloud.rest.api.client.model.Request; 22 | import com.sap.cloud.rest.api.client.model.Response; 23 | import com.sap.cloud.rest.api.client.utils.test.MockResponseUtil; 24 | 25 | public class DefaultStatusCodeHandlerTest { 26 | 27 | private static final int TEST_SUCCESS_CODE = 200; 28 | private static final int TEST_ERROR_CODE = 500; 29 | private static final String TEST_RESPONSE_BODY = "responseBody"; 30 | private static final Request TEST_REQUEST = new Request<>(RequestBuilder.get().build()); 31 | 32 | private HttpResponse httpResponse = MockResponseUtil.makeMockedResponseWithStatusCode(TEST_SUCCESS_CODE); 33 | private Response response = new Response(httpResponse, TEST_RESPONSE_BODY); 34 | private HttpExchangeContext context = new HttpExchangeContext(TEST_REQUEST, response); 35 | private StatusCodeHandler handler = DefaultStatusCodeHandler.create(); 36 | 37 | @Rule 38 | public ExpectedException expected = ExpectedException.none(); 39 | 40 | @Test 41 | public void testDefaultHandler() { 42 | handler.handleStatusCode(TEST_SUCCESS_CODE, context); 43 | } 44 | 45 | @Test 46 | public void testDefaultHandlerErrorResponseCode() throws ResponseException { 47 | expected.expect(ResponseException.class); 48 | expected.expectMessage(format(HTTP_RESPOSNE_EXCEPTION_MSG, context)); 49 | 50 | StatusLine statusLine = mock(StatusLine.class); 51 | doReturn(TEST_ERROR_CODE).when(statusLine).getStatusCode(); 52 | doReturn(statusLine).when(httpResponse).getStatusLine(); 53 | 54 | handler.handleStatusCode(TEST_ERROR_CODE, context); 55 | } 56 | 57 | @Test 58 | public void testUnauthorizedHandler() throws ResponseException { 59 | expected.expect(UnauthorizedException.class); 60 | expected.expectMessage(format(UNAUTHORIZED_MSG, context)); 61 | 62 | handler.handleStatusCode(401, context); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/http/HttpClientProviderFactoryTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.http; 2 | 3 | import static com.sap.cloud.rest.api.client.utils.test.HttpClientProviderUtils.getHttpClientProviderForAuthentication; 4 | import static org.junit.Assert.assertTrue; 5 | import static org.mockito.Mockito.mock; 6 | 7 | import org.junit.Test; 8 | 9 | import com.sap.cloud.rest.api.client.auth.Authentication; 10 | import com.sap.cloud.rest.api.client.auth.basic.BasicAuthentication; 11 | import com.sap.cloud.rest.api.client.auth.basic.BasicHttpClientProvider; 12 | import com.sap.cloud.rest.api.client.auth.cert.ClientCertAuthentication; 13 | import com.sap.cloud.rest.api.client.auth.cert.KeystoreConfig; 14 | import com.sap.cloud.rest.api.client.auth.cert.SSLHttpClientProvider; 15 | import com.sap.cloud.rest.api.client.auth.none.NoAuthHttpClientProvider; 16 | import com.sap.cloud.rest.api.client.auth.none.NoAuthentication; 17 | import com.sap.cloud.rest.api.client.auth.oauth.OAuthAuthentication; 18 | import com.sap.cloud.rest.api.client.auth.oauth.OAuthHttpClientProvider; 19 | import com.sap.cloud.rest.api.client.auth.oauth.OAuthServerConfig; 20 | import com.sap.cloud.rest.api.client.http.HttpClientProvider; 21 | 22 | public class HttpClientProviderFactoryTest { 23 | 24 | @Test 25 | public void createBasicHttpClientProviderTest() { 26 | Authentication authentication = new BasicAuthentication("username", "password".toCharArray()); 27 | HttpClientProvider basicHttpClientProvider = getHttpClientProviderForAuthentication(authentication); 28 | assertTrue(basicHttpClientProvider instanceof BasicHttpClientProvider); 29 | } 30 | 31 | @Test 32 | public void createClientCertHttpClientProviderTest() { 33 | Authentication authentication = new ClientCertAuthentication(mock(KeystoreConfig.class)); 34 | HttpClientProvider clientCertHttpClientProvider = getHttpClientProviderForAuthentication(authentication); 35 | assertTrue(clientCertHttpClientProvider instanceof SSLHttpClientProvider); 36 | } 37 | 38 | @Test 39 | public void createOauthHttpClientProviderTest() { 40 | OAuthServerConfig oAuthServerConfig = new OAuthServerConfig("http://test", "dummyClientID", 41 | "dummyClientSecret".toCharArray()); 42 | Authentication authentication = new OAuthAuthentication(oAuthServerConfig); 43 | HttpClientProvider oauthHttpClientProvider = getHttpClientProviderForAuthentication(authentication); 44 | assertTrue(oauthHttpClientProvider instanceof OAuthHttpClientProvider); 45 | } 46 | 47 | @Test 48 | public void createNoAuthHttpClientProviderTest() { 49 | Authentication authentication = new NoAuthentication(); 50 | HttpClientProvider noAuthHttpClientProvider = getHttpClientProviderForAuthentication(authentication); 51 | ; 52 | assertTrue(noAuthHttpClientProvider instanceof NoAuthHttpClientProvider); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/http/ProxyTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.http; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import org.junit.Test; 6 | 7 | import com.sap.cloud.rest.api.client.http.Proxy; 8 | 9 | import nl.jqno.equalsverifier.EqualsVerifier; 10 | 11 | public class ProxyTest { 12 | 13 | private static final String DEFAUL_PROXY_SCHEME = "http"; 14 | private static final String PROXY_SCHEME = "https"; 15 | private static final String PROXY_HOST = "proxy.int"; 16 | private static final int PROXY_PORT = 8888; 17 | 18 | @Test 19 | public void createProxyConfigurationTest() { 20 | Proxy proxyConfiguration = new Proxy(PROXY_HOST, PROXY_PORT, PROXY_SCHEME); 21 | 22 | assertEquals(PROXY_HOST, proxyConfiguration.getProxyHost()); 23 | assertEquals(PROXY_PORT, proxyConfiguration.getProxyPort()); 24 | assertEquals(PROXY_SCHEME, proxyConfiguration.getProxyScheme()); 25 | } 26 | 27 | @Test 28 | public void createProxyConfigurationWithDefaultSchemeTest() { 29 | Proxy proxyConfiguration = new Proxy(PROXY_HOST, PROXY_PORT); 30 | 31 | assertEquals(PROXY_HOST, proxyConfiguration.getProxyHost()); 32 | assertEquals(PROXY_PORT, proxyConfiguration.getProxyPort()); 33 | assertEquals(DEFAUL_PROXY_SCHEME, proxyConfiguration.getProxyScheme()); 34 | } 35 | 36 | @Test 37 | public void toStringTest() { 38 | Proxy proxyConfiguration = new Proxy(PROXY_HOST, PROXY_PORT, PROXY_SCHEME); 39 | 40 | String expectedString = "{\"proxyScheme\":\"" + PROXY_SCHEME 41 | + "\",\"proxyHost\":\"" + PROXY_HOST 42 | + "\",\"proxyPort\":" + PROXY_PORT + "}"; 43 | assertEquals(expectedString, proxyConfiguration.toString()); 44 | } 45 | 46 | @Test 47 | public void equalsTest() { 48 | EqualsVerifier.forClass(Proxy.class).usingGetClass().verify(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/model/HttpExchangeContextTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.model; 2 | 3 | import static com.sap.cloud.rest.api.client.model.HttpExchangeContext.REQUEST_DISPLAY_NAME; 4 | import static com.sap.cloud.rest.api.client.model.HttpExchangeContext.RESPONSE_DISPLAY_NAME; 5 | import static com.sap.cloud.rest.api.client.utils.ValidateArgument.CANNOT_BE_NULL_MSG; 6 | import static org.junit.Assert.assertEquals; 7 | import static org.mockito.Mockito.mock; 8 | 9 | import org.apache.http.HttpResponse; 10 | import org.apache.http.client.methods.RequestBuilder; 11 | import org.junit.Rule; 12 | import org.junit.Test; 13 | import org.junit.rules.ExpectedException; 14 | 15 | import com.sap.cloud.rest.api.client.model.HttpExchangeContext; 16 | import com.sap.cloud.rest.api.client.model.Request; 17 | import com.sap.cloud.rest.api.client.model.Response; 18 | 19 | public class HttpExchangeContextTest { 20 | 21 | private static final Request TEST_REQUEST = new Request<>(RequestBuilder.get().build()); 22 | private static final String TEST_RESPONSE_BODY = "test_response_body"; 23 | private static final HttpResponse TEST_HTTP_RESPONSE = mock(HttpResponse.class); 24 | private static final Response TEST_RESPONSE = new Response<>(TEST_HTTP_RESPONSE, TEST_RESPONSE_BODY); 25 | private static final HttpExchangeContext TEST_CONTEXT = new HttpExchangeContext(TEST_REQUEST, TEST_RESPONSE); 26 | 27 | @Rule 28 | public ExpectedException expected = ExpectedException.none(); 29 | 30 | @Test 31 | public void testGetRequest() { 32 | assertEquals(TEST_REQUEST, TEST_CONTEXT.getRequest()); 33 | } 34 | 35 | @Test 36 | public void testGetResponse() { 37 | assertEquals(TEST_RESPONSE, TEST_CONTEXT.getResponse()); 38 | } 39 | 40 | @Test 41 | public void testCreateHttpExchangeContextWithNullRequest() { 42 | expected.expect(IllegalArgumentException.class); 43 | expected.expectMessage(REQUEST_DISPLAY_NAME + CANNOT_BE_NULL_MSG); 44 | 45 | new HttpExchangeContext(null, TEST_RESPONSE); 46 | } 47 | 48 | @Test 49 | public void testCreateHttpExchangeContextWithNullResponse() { 50 | expected.expect(IllegalArgumentException.class); 51 | expected.expectMessage(RESPONSE_DISPLAY_NAME + CANNOT_BE_NULL_MSG); 52 | 53 | new HttpExchangeContext(TEST_REQUEST, null); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/model/RequestTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.model; 2 | 3 | import static com.sap.cloud.rest.api.client.model.Request.MASKED_VALUE; 4 | import static org.junit.Assert.assertEquals; 5 | 6 | import org.apache.http.HttpHeaders; 7 | import org.apache.http.client.methods.HttpUriRequest; 8 | import org.apache.http.client.methods.RequestBuilder; 9 | import org.junit.Test; 10 | 11 | import com.sap.cloud.rest.api.client.model.Request; 12 | 13 | public class RequestTest { 14 | 15 | @Test(expected = IllegalArgumentException.class) 16 | public void testCreateRequestWithNullInnerRequestShouldThrow() { 17 | new Request(null); 18 | } 19 | 20 | @Test 21 | public void testGetHttpRequest() { 22 | HttpUriRequest innerRequest = RequestBuilder.get().build(); 23 | Request request = new Request(innerRequest); 24 | 25 | assertEquals(request.getHttpRequest(), innerRequest); 26 | } 27 | 28 | @Test 29 | public void testGetBody() { 30 | HttpUriRequest innerRequest = RequestBuilder.get().build(); 31 | String body = "test_body"; 32 | Request request = new Request(innerRequest, body); 33 | 34 | assertEquals(request.getEntity(), body); 35 | } 36 | 37 | @Test 38 | public void testToStringContatinsHttpUriRequestAndHeadersAndBody() { 39 | HttpUriRequest httpUriRequest = RequestBuilder.get().addHeader("header", "value").build(); 40 | String body = "test_body"; 41 | Request request = new Request(httpUriRequest, body); 42 | 43 | String expectedString = "{\"httpRequest\":\"GET / HTTP/1.1\",\"requestHeaders\":\"[header: value]\",\"requestEntity\":\"test_body\"}"; 44 | assertEquals(request.toString(), expectedString); 45 | } 46 | 47 | @Test 48 | public void testToStringSanitizesAuthorizationHeader() { 49 | HttpUriRequest httpUriRequest = RequestBuilder.get() 50 | .addHeader("header", "value") 51 | .addHeader(HttpHeaders.AUTHORIZATION, "credentials") 52 | .addHeader(HttpHeaders.PROXY_AUTHENTICATE, "credentials") 53 | .addHeader(HttpHeaders.PROXY_AUTHORIZATION, "credentials") 54 | .build(); 55 | String body = "test_body"; 56 | Request request = new Request(httpUriRequest, body); 57 | 58 | String expectedString = "{\"httpRequest\":\"GET / HTTP/1.1\",\"requestHeaders\":\"[header: value, " 59 | + HttpHeaders.AUTHORIZATION + ": " + MASKED_VALUE + ", " 60 | + HttpHeaders.PROXY_AUTHENTICATE + ": " + MASKED_VALUE + ", " 61 | + HttpHeaders.PROXY_AUTHORIZATION + ": " + MASKED_VALUE 62 | + "]\",\"requestEntity\":\"test_body\"}"; 63 | assertEquals(request.toString(), expectedString); 64 | 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/model/ResponseTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.model; 2 | 3 | import static com.sap.cloud.rest.api.client.utils.test.MockResponseUtil.makeMockedResponseWithStatusCode; 4 | import static org.junit.Assert.assertArrayEquals; 5 | import static org.junit.Assert.assertEquals; 6 | import static org.junit.Assert.assertTrue; 7 | import static org.mockito.Mockito.doReturn; 8 | 9 | import org.apache.http.Header; 10 | import org.apache.http.HttpResponse; 11 | import org.apache.http.message.BasicHeader; 12 | import org.junit.Before; 13 | import org.junit.Test; 14 | 15 | import com.sap.cloud.rest.api.client.model.Response; 16 | 17 | public class ResponseTest { 18 | 19 | private static final int TEST_STATUS_CODE = 500; 20 | private static final Header[] TEST_RESPONSE_HEADERS = new Header[] {}; 21 | 22 | private static final HttpResponse TEST_HTTP_RESPONSE = makeMockedResponseWithStatusCode(TEST_STATUS_CODE); 23 | 24 | @Before 25 | public void setup() { 26 | doReturn(TEST_RESPONSE_HEADERS).when(TEST_HTTP_RESPONSE).getAllHeaders(); 27 | } 28 | 29 | @Test(expected = IllegalArgumentException.class) 30 | public void testCreateResponseWithNullHttpResponseShouldThrow() { 31 | new Response(null, new TestEntity()); 32 | } 33 | 34 | @Test 35 | public void testResponseEntityIsNullShouldNotThrow() { 36 | new Response(TEST_HTTP_RESPONSE, null); 37 | } 38 | 39 | @Test 40 | public void testGetHttpResponse() { 41 | Response response = new Response<>(TEST_HTTP_RESPONSE, null); 42 | 43 | assertEquals(response.getHttpResponse(), TEST_HTTP_RESPONSE); 44 | } 45 | 46 | @Test 47 | public void testGetStatusCode() { 48 | Response response = new Response(TEST_HTTP_RESPONSE, new TestEntity()); 49 | 50 | assertEquals(TEST_STATUS_CODE, response.getStatusCode()); 51 | } 52 | 53 | @Test 54 | public void testGetEntity() { 55 | TestEntity entity = new TestEntity(); 56 | 57 | Response response = new Response<>(TEST_HTTP_RESPONSE, entity); 58 | 59 | assertEquals(response.getEntity(), entity); 60 | } 61 | 62 | @Test 63 | public void testGetHeaders() { 64 | Response response = new Response(TEST_HTTP_RESPONSE, new TestEntity()); 65 | 66 | assertArrayEquals(TEST_RESPONSE_HEADERS, response.getHeaders()); 67 | } 68 | 69 | @Test 70 | public void testToStringContatinsHttpResponseAndEntity() { 71 | doReturn(new Header[] { new BasicHeader("header", "value") }).when(TEST_HTTP_RESPONSE).getAllHeaders(); 72 | TestEntity entity = new TestEntity(); 73 | 74 | Response response = new Response<>(TEST_HTTP_RESPONSE, entity); 75 | 76 | String httpResponseAsString = TEST_HTTP_RESPONSE.toString(); 77 | String entityAsString = entity.toString(); 78 | String toStringResult = response.toString(); 79 | 80 | assertTrue(toStringResult.contains(httpResponseAsString)); 81 | assertTrue(toStringResult.contains(entityAsString)); 82 | } 83 | 84 | private static class TestEntity { 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/model/multipart/EntityPartTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.model.multipart; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import org.junit.Test; 6 | 7 | import com.sap.cloud.rest.api.client.model.multipart.EntityPart; 8 | 9 | import nl.jqno.equalsverifier.EqualsVerifier; 10 | 11 | public class EntityPartTest { 12 | 13 | private static final String TEST_NAME = "test_name"; 14 | private static final String TEST_ENTITY = "test_entity"; 15 | 16 | @Test 17 | public void testCreateEntityPart() { 18 | EntityPart entityPart = new EntityPart(TEST_NAME, TEST_ENTITY); 19 | 20 | assertEquals(TEST_NAME, entityPart.getName()); 21 | assertEquals(TEST_ENTITY, entityPart.getEntity()); 22 | } 23 | 24 | @Test 25 | public void testEntityPartToString() { 26 | EntityPart entityPart = new EntityPart(TEST_NAME, TEST_ENTITY); 27 | 28 | assertEquals("{\"name\":\"" + TEST_NAME + "\",\"entity\":\"" + TEST_ENTITY + "\"}", entityPart.toString()); 29 | } 30 | 31 | @Test 32 | public void testEqualsAndHashcode() { 33 | EqualsVerifier.forClass(EntityPart.class).usingGetClass().verify(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/model/multipart/MultipartEntityTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.model.multipart; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.assertTrue; 5 | 6 | import java.util.ArrayList; 7 | 8 | import org.junit.Test; 9 | 10 | import com.sap.cloud.rest.api.client.model.multipart.EntityPart; 11 | import com.sap.cloud.rest.api.client.model.multipart.MultipartEntity; 12 | 13 | import nl.jqno.equalsverifier.EqualsVerifier; 14 | 15 | public class MultipartEntityTest { 16 | 17 | private static final String TEST_NAME = "test_name"; 18 | private static final String TEST_ENTITY = "test_entity"; 19 | 20 | private static final EntityPart ENTITY_PART = new EntityPart(TEST_NAME, TEST_ENTITY); 21 | 22 | @Test 23 | public void testCreateMultipartEntity() { 24 | ArrayList> parts = new ArrayList<>(); 25 | parts.add(new EntityPart(TEST_NAME, TEST_ENTITY)); 26 | MultipartEntity multipartEntity = new MultipartEntity<>(parts); 27 | 28 | assertEquals(1, multipartEntity.getParts().size()); 29 | assertEquals(ENTITY_PART, multipartEntity.getPartsByName(TEST_NAME).get(0)); 30 | } 31 | 32 | @Test 33 | public void testCreateMultipartEntityEmptyList() { 34 | MultipartEntity multipartEntity = new MultipartEntity<>(new ArrayList<>()); 35 | 36 | assertTrue(multipartEntity.getParts().isEmpty()); 37 | } 38 | 39 | @Test 40 | public void testMultipartEntityToString() { 41 | ArrayList> parts = new ArrayList<>(); 42 | parts.add(new EntityPart(TEST_NAME, TEST_ENTITY)); 43 | MultipartEntity multipartEntity = new MultipartEntity<>(parts); 44 | 45 | assertEquals("{\"multipartEntity\":[{\"name\":\"" + TEST_NAME + "\",\"entity\":\"" + TEST_ENTITY + "\"}]}", 46 | multipartEntity.toString()); 47 | } 48 | 49 | @Test 50 | public void testEqualsAndHashcode() { 51 | EqualsVerifier.forClass(MultipartEntity.class).usingGetClass().verify(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/utils/JacksonJsonResponseHandlerTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.utils; 2 | 3 | import com.fasterxml.jackson.core.JsonParseException; 4 | import com.fasterxml.jackson.core.type.TypeReference; 5 | import com.sap.cloud.rest.api.client.utils.JacksonJsonResponseHandler; 6 | 7 | import org.apache.http.HttpResponse; 8 | import org.junit.Test; 9 | 10 | import java.util.List; 11 | 12 | import static com.sap.cloud.rest.api.client.utils.test.MockResponseUtil.makeMockedResponseWithStatusAndEntity; 13 | import static com.sap.cloud.rest.api.client.utils.test.MockResponseUtil.makeMockedResponseWithStatusCode; 14 | import static org.junit.Assert.assertEquals; 15 | import static org.junit.Assert.assertNull; 16 | 17 | public class JacksonJsonResponseHandlerTest { 18 | 19 | @Test 20 | public void testWithValidJsonShouldParseToObject() throws Exception { 21 | HttpResponse mockResponse = makeMockedResponseWithStatusAndEntity(200, 22 | "{ \"field\": \"value\"}"); 23 | 24 | JacksonJsonResponseHandler responseHandler = new JacksonJsonResponseHandler<>(TestClass.class); 25 | TestClass resultEntity = responseHandler.handleResponse(mockResponse); 26 | 27 | assertEquals("value", resultEntity.field); 28 | } 29 | 30 | @Test 31 | public void testWithValidJsonUsingTypeReferenceShouldParseToObject() throws Exception { 32 | HttpResponse mockResponse = makeMockedResponseWithStatusAndEntity(200, 33 | "[{ \"field\": \"value\"}]"); 34 | 35 | JacksonJsonResponseHandler> responseHandler = 36 | new JacksonJsonResponseHandler<>(new TypeReference>() { 37 | }); 38 | List resultActual = responseHandler.handleResponse(mockResponse); 39 | assertEquals(1, resultActual.size()); 40 | assertEquals("value", resultActual.get(0).field); 41 | } 42 | 43 | @Test 44 | public void testWithEmptyBodyShouldReturnNull() throws Exception { 45 | HttpResponse mockResponse = makeMockedResponseWithStatusCode(200); 46 | 47 | JacksonJsonResponseHandler responseHandler = new JacksonJsonResponseHandler<>(TestClass.class); 48 | TestClass resultEntity = responseHandler.handleResponse(mockResponse); 49 | 50 | assertNull(resultEntity); 51 | } 52 | 53 | @Test 54 | public void testWithEmptyBodyUsingTypeReferenceShouldReturnNull() throws Exception { 55 | HttpResponse mockResponse = makeMockedResponseWithStatusCode(200); 56 | 57 | JacksonJsonResponseHandler> responseHandler = new JacksonJsonResponseHandler<>(new TypeReference>() { 58 | }); 59 | List resultActual = responseHandler.handleResponse(mockResponse); 60 | 61 | assertNull(resultActual); 62 | } 63 | 64 | @Test(expected = JsonParseException.class) 65 | public void testWithInvalidJsonShouldThrowJsonParseException() throws Exception { 66 | HttpResponse mockResponse = makeMockedResponseWithStatusAndEntity(200, "field=value"); 67 | 68 | JacksonJsonResponseHandler responseHandler = new JacksonJsonResponseHandler<>(TestClass.class); 69 | responseHandler.handleResponse(mockResponse); 70 | } 71 | 72 | @Test(expected = JsonParseException.class) 73 | public void testWithInvalidJsonUsingTypeReferenceShouldThrowJsonParseException() throws Exception { 74 | HttpResponse mockResponse = makeMockedResponseWithStatusAndEntity(200, "[field=value]"); 75 | 76 | JacksonJsonResponseHandler> responseHandler = new JacksonJsonResponseHandler<>(new TypeReference>() { 77 | }); 78 | responseHandler.handleResponse(mockResponse); 79 | } 80 | 81 | private static class TestClass { 82 | 83 | public String field; 84 | } 85 | 86 | } -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/utils/PropertiesResponseHandlerTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.utils; 2 | 3 | import static com.sap.cloud.rest.api.client.utils.test.MockResponseUtil.makeMockedResponseWithStatusAndEntity; 4 | import static com.sap.cloud.rest.api.client.utils.test.MockResponseUtil.makeMockedResponseWithStatusCode; 5 | import static org.junit.Assert.assertEquals; 6 | import static org.junit.Assert.assertNull; 7 | 8 | import org.apache.http.HttpResponse; 9 | import org.junit.Test; 10 | 11 | import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException; 12 | import com.sap.cloud.rest.api.client.utils.PropertiesResponseHandler; 13 | 14 | public class PropertiesResponseHandlerTest { 15 | 16 | @Test 17 | public void testWithValidPropertiesShouldParseToObject() throws Exception { 18 | HttpResponse mockResponse = makeMockedResponseWithStatusAndEntity(200, 19 | "field=value"); 20 | 21 | PropertiesResponseHandler responseHandler = new PropertiesResponseHandler<>(TestClass.class); 22 | TestClass resultEntity = responseHandler.handleResponse(mockResponse); 23 | 24 | assertEquals("value", resultEntity.field); 25 | } 26 | 27 | @Test 28 | public void testWithEmptyBodyShouldReturnNull() throws Exception { 29 | HttpResponse mockResponse = makeMockedResponseWithStatusCode(200); 30 | 31 | PropertiesResponseHandler responseHandler = new PropertiesResponseHandler<>(TestClass.class); 32 | TestClass resultEntity = responseHandler.handleResponse(mockResponse); 33 | 34 | assertNull(resultEntity); 35 | } 36 | 37 | @Test(expected = UnrecognizedPropertyException.class) 38 | public void testWithJsonBodyShouldThrowUnrecognizedPropertyException() throws Exception { 39 | HttpResponse mockResponse = makeMockedResponseWithStatusAndEntity(200, "{ \"field\": \"value\"}"); 40 | 41 | PropertiesResponseHandler responseHandler = new PropertiesResponseHandler<>(TestClass.class); 42 | responseHandler.handleResponse(mockResponse); 43 | } 44 | 45 | private static class TestClass { 46 | 47 | public String field; 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/utils/ValidateArgumentTest.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.utils; 2 | 3 | import static com.sap.cloud.rest.api.client.utils.ValidateArgument.isNotEmptyOrNull; 4 | import static com.sap.cloud.rest.api.client.utils.ValidateArgument.isNotNull; 5 | import static com.sap.cloud.rest.api.client.utils.ValidateArgument.isValidUrl; 6 | 7 | import org.junit.Rule; 8 | import org.junit.Test; 9 | import org.junit.rules.ExpectedException; 10 | 11 | import com.sap.cloud.rest.api.client.utils.ValidateArgument; 12 | 13 | public class ValidateArgumentTest { 14 | 15 | private static final String OBJECT_ARGUMENT = "Object"; 16 | 17 | private static final String CHAR_ARRAY_ARGUMENT = "Char array"; 18 | 19 | private static final String STRING_ARGUMENT = "String"; 20 | 21 | private static final String URL_MSG_PREFIX = "Host URL"; 22 | 23 | private static final String TEST_CORRECT_URL = "https://example.com"; 24 | 25 | private static final String TEST_INCORRECT_URL = "wrong URL"; 26 | 27 | @Rule 28 | public ExpectedException expected = ExpectedException.none(); 29 | 30 | @Test 31 | public void isNotEmptyOrNullValidStringTest() { 32 | isNotEmptyOrNull(STRING_ARGUMENT, "string"); 33 | } 34 | 35 | @Test 36 | public void isNotEmptyOrNullEmptyStringTest() { 37 | expected.expect(IllegalArgumentException.class); 38 | expected.expectMessage(STRING_ARGUMENT + ValidateArgument.CANNOT_BE_BLANK_MSG); 39 | 40 | isNotEmptyOrNull(STRING_ARGUMENT, ""); 41 | } 42 | 43 | @Test 44 | public void isNotEmptyOrNullNullStringTest() { 45 | expected.expect(IllegalArgumentException.class); 46 | expected.expectMessage(STRING_ARGUMENT + ValidateArgument.CANNOT_BE_BLANK_MSG); 47 | 48 | String str = null; 49 | isNotEmptyOrNull(STRING_ARGUMENT, str); 50 | } 51 | 52 | @Test 53 | public void isNotEmptyOrNullValidCharArrayTest() { 54 | isNotEmptyOrNull(CHAR_ARRAY_ARGUMENT, "string".toCharArray()); 55 | } 56 | 57 | @Test 58 | public void isNotEmptyOrNullEmptyCharArrayTest() { 59 | expected.expect(IllegalArgumentException.class); 60 | expected.expectMessage(CHAR_ARRAY_ARGUMENT + ValidateArgument.CANNOT_BE_BLANK_MSG); 61 | 62 | isNotEmptyOrNull(CHAR_ARRAY_ARGUMENT, "".toCharArray()); 63 | } 64 | 65 | @Test 66 | public void isNotEmptyOrNullNullCharArrayTest() { 67 | expected.expect(IllegalArgumentException.class); 68 | expected.expectMessage(CHAR_ARRAY_ARGUMENT + ValidateArgument.CANNOT_BE_BLANK_MSG); 69 | 70 | char[] charArray = null; 71 | isNotEmptyOrNull(CHAR_ARRAY_ARGUMENT, charArray); 72 | } 73 | 74 | @Test 75 | public void isNotNullValidObjectTest() { 76 | Object object = new Object(); 77 | isNotNull(OBJECT_ARGUMENT, object); 78 | } 79 | 80 | @Test 81 | public void isNotNullNullObjectTest() { 82 | expected.expect(IllegalArgumentException.class); 83 | expected.expectMessage(OBJECT_ARGUMENT + ValidateArgument.CANNOT_BE_NULL_MSG); 84 | 85 | Object object = null; 86 | isNotNull(OBJECT_ARGUMENT, object); 87 | } 88 | 89 | @Test 90 | public void testCorrectUrl() { 91 | isValidUrl(URL_MSG_PREFIX, TEST_CORRECT_URL); 92 | } 93 | 94 | @Test 95 | public void testIncorrectUrl() { 96 | expected.expect(IllegalArgumentException.class); 97 | expected.expectMessage(URL_MSG_PREFIX + ValidateArgument.NOT_VALID_URL_MSG); 98 | 99 | isValidUrl(URL_MSG_PREFIX, TEST_INCORRECT_URL); 100 | 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/utils/test/HttpClientProviderUtils.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.utils.test; 2 | 3 | import com.sap.cloud.rest.api.client.auth.Authentication; 4 | import com.sap.cloud.rest.api.client.config.RestApiClientConfig; 5 | import com.sap.cloud.rest.api.client.http.HttpClientProvider; 6 | import com.sap.cloud.rest.api.client.http.HttpClientProviderFactory; 7 | 8 | public class HttpClientProviderUtils { 9 | 10 | private static final String TEST_HOST = "http://test.com"; 11 | 12 | public static HttpClientProvider getHttpClientProviderForAuthentication(Authentication authentication) { 13 | RestApiClientConfig config = new RestApiClientConfig(TEST_HOST, authentication); 14 | HttpClientProvider basicHttpClientProvider = HttpClientProviderFactory.createHttpClientProvider(config); 15 | return basicHttpClientProvider; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/utils/test/MockResponseUtil.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.utils.test; 2 | 3 | import static org.mockito.Mockito.when; 4 | 5 | import org.apache.http.HttpResponse; 6 | import org.apache.http.StatusLine; 7 | import org.apache.http.client.entity.EntityBuilder; 8 | import org.mockito.Mockito; 9 | 10 | public class MockResponseUtil { 11 | 12 | public static HttpResponse makeMockedResponseWithStatusAndEntity(int statusCode, String responseText) { 13 | HttpResponse mockedResponse = makeMockedResponseWithStatusCode(statusCode); 14 | 15 | when(mockedResponse.getEntity()).thenReturn( 16 | EntityBuilder.create() 17 | .setText(responseText) 18 | .build()); 19 | 20 | return mockedResponse; 21 | } 22 | 23 | public static HttpResponse makeMockedResponseWithStatusCode(int statusCode) { 24 | HttpResponse mockedResponse = Mockito.mock(HttpResponse.class); 25 | 26 | StatusLine mockedStatusLine = Mockito.mock(StatusLine.class); 27 | when(mockedResponse.getStatusLine()).thenReturn(mockedStatusLine); 28 | when(mockedStatusLine.getStatusCode()).thenReturn(statusCode); 29 | 30 | return mockedResponse; 31 | } 32 | 33 | public static HttpResponse makeMockedResponseWithEntity(String responseText) { 34 | HttpResponse mockedResponse = Mockito.mock(HttpResponse.class); 35 | 36 | when(mockedResponse.getEntity()).thenReturn( 37 | EntityBuilder.create() 38 | .setText(responseText) 39 | .build()); 40 | 41 | return mockedResponse; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/com/sap/cloud/rest/api/client/utils/test/RequestMatcher.java: -------------------------------------------------------------------------------- 1 | package com.sap.cloud.rest.api.client.utils.test; 2 | 3 | import org.apache.http.client.methods.HttpUriRequest; 4 | import org.mockito.ArgumentMatcher; 5 | 6 | /** 7 | * Custom matcher that accepts an {@link HttpUriRequest} argument with the given 8 | * url. 9 | * 10 | */ 11 | public class RequestMatcher extends ArgumentMatcher { 12 | 13 | private String url; 14 | private String method; 15 | 16 | public RequestMatcher(String method, String url) { 17 | this.method = method; 18 | this.url = url; 19 | } 20 | 21 | @Override 22 | public boolean matches(Object argument) { 23 | HttpUriRequest request = (HttpUriRequest) argument; 24 | 25 | return method.equals(request.getMethod()) && url.equals(request.getURI().toString()); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/test/resources/test-keystore.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP-archive/cloud-rest-api-client/638cc488d6befe0f26f803662741283c8405df5a/src/test/resources/test-keystore.jks --------------------------------------------------------------------------------