├── .github └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.txt ├── NOTICE ├── README.md ├── pom.xml ├── release.sh └── src ├── .gitkeep ├── main └── java │ ├── com │ └── amazon │ │ └── dtasdk │ │ ├── base │ │ ├── InstantAccessOperationValue.java │ │ ├── InstantAccessRequest.java │ │ ├── InstantAccessResponse.java │ │ ├── SubscriptionPeriodValue.java │ │ ├── SubscriptionReasonValue.java │ │ ├── SubscriptionRequest.java │ │ ├── SubscriptionResponse.java │ │ └── SubscriptionResponseValue.java │ │ ├── serializer │ │ ├── JacksonSerializer.java │ │ └── SerializationException.java │ │ ├── signature │ │ ├── AuthenticationHeader.java │ │ ├── AuthenticationHeaderParser.java │ │ ├── Credential.java │ │ ├── CredentialNotFoundException.java │ │ ├── CredentialStore.java │ │ ├── Request.java │ │ ├── Signer.java │ │ └── SigningException.java │ │ ├── utils │ │ ├── BinaryUtils.java │ │ ├── Clock.java │ │ └── HttpUtils.java │ │ ├── v2 │ │ ├── serialization │ │ │ └── messages │ │ │ │ ├── FulfillPurchaseRequest.java │ │ │ │ ├── FulfillPurchaseResponse.java │ │ │ │ ├── FulfillPurchaseResponseValue.java │ │ │ │ ├── GetUserIdSerializableRequest.java │ │ │ │ ├── GetUserIdSerializableResponse.java │ │ │ │ ├── GetUserIdSerializableResponseValue.java │ │ │ │ ├── RevokePurchaseRequest.java │ │ │ │ ├── RevokePurchaseResponse.java │ │ │ │ ├── RevokePurchaseResponseValue.java │ │ │ │ ├── SubscriptionActivateRequest.java │ │ │ │ └── SubscriptionDeactivateRequest.java │ │ └── servlets │ │ │ ├── AccountLinkingServlet.java │ │ │ ├── InstantAccessServlet.java │ │ │ └── PurchaseServlet.java │ │ └── v3 │ │ ├── serialization │ │ └── messages │ │ │ ├── FulfillPurchaseRequest.java │ │ │ ├── FulfillPurchaseResponse.java │ │ │ ├── GetUserIdSerializableRequest.java │ │ │ ├── GetUserIdSerializableResponse.java │ │ │ ├── RevokePurchaseRequest.java │ │ │ ├── RevokePurchaseResponse.java │ │ │ ├── SubscriptionActivateRequest.java │ │ │ ├── SubscriptionActivateResponse.java │ │ │ ├── SubscriptionDeactivateRequest.java │ │ │ ├── SubscriptionDeactivateResponse.java │ │ │ ├── SubscriptionGetRequest.java │ │ │ ├── SubscriptionGetResponse.java │ │ │ ├── SubscriptionUpdateRequest.java │ │ │ └── SubscriptionUpdateResponse.java │ │ └── servlets │ │ ├── AccountLinkingServlet.java │ │ ├── InstantAccessServlet.java │ │ └── PurchaseServlet.java │ └── examples │ └── servlet │ ├── AccountLinkingServletImpl.java │ └── PurchaseServletImpl.java └── test └── java └── com └── amazon └── dtasdk ├── connection ├── SignatureVerificationTest.java └── TestServer.java ├── serializer ├── JacksonSerializerTest.java └── TestJson.java ├── signature ├── AuthenticationHeaderParserTest.java ├── CredentialStoreTest.java ├── RequestTest.java └── SignerTest.java ├── utils └── ClockTest.java ├── v2 ├── serialization │ └── messages │ │ ├── InstantAccessRequestTest.java │ │ └── InstantAccessResponseTest.java └── servlets │ ├── AccountLinkingServletTest.java │ ├── InstantAccessServletTest.java │ └── PurchaseServletTest.java └── v3 ├── messages ├── InstantAccessRequestTest.java └── InstantAccessResponseTest.java └── servlets ├── AccountLinkingServletTest.java ├── InstantAccessServletTest.java └── PurchaseServletTest.java /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | *Issue #, if available:* 2 | 3 | *Description of changes:* 4 | 5 | 6 | By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.iml 3 | target 4 | build 5 | .classpath 6 | eclipse-bin 7 | .project 8 | .settings 9 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check [existing open](https://github.com/amzn/amazon-instant-access-sdk-java/issues), or [recently closed](https://github.com/amzn/amazon-instant-access-sdk-java/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *master* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels ((enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/amzn/amazon-instant-access-sdk-java/labels/help%20wanted) issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](https://github.com/amzn/amazon-instant-access-sdk-java/blob/master/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | 61 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. 62 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Amazon Instance Access SDK for Java 2 | Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.amazon.dtg 8 | dta-sdk-java 9 | 2.1 10 | 11 | 12 | 13 | commons-logging 14 | commons-logging 15 | 1.1.1 16 | 17 | 18 | commons-codec 19 | commons-codec 20 | 1.3 21 | 22 | 23 | commons-lang 24 | commons-lang 25 | 2.6 26 | 27 | 28 | commons-io 29 | commons-io 30 | 2.7 31 | 32 | 33 | javax.servlet 34 | javax.servlet-api 35 | 3.0.1 36 | provided 37 | 38 | 39 | com.fasterxml.jackson.core 40 | jackson-databind 41 | 2.12.7.1 42 | 43 | 44 | 45 | 46 | 47 | junit 48 | junit 49 | 4.13.1 50 | true 51 | test 52 | 53 | 54 | org.easymock 55 | easymock 56 | 3.1 57 | test 58 | 59 | 60 | org.eclipse.jetty 61 | jetty-server 62 | 9.4.41.v20210516 63 | test 64 | 65 | 66 | commons-httpclient 67 | commons-httpclient 68 | 3.1 69 | test 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | org.apache.maven.plugins 78 | maven-compiler-plugin 79 | 80 | 1.8 81 | 1.8 82 | UTF-8 83 | 84 | 85 | 86 | 87 | 88 | 89 | org.apache.maven.plugins 90 | maven-surefire-plugin 91 | 2.4 92 | 93 | 94 | org.apache.maven.surefire 95 | surefire-junit4 96 | 2.4 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /release.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | zip -r build/DTAv2SDKJava.zip src pom.xml LICENSE.txt -------------------------------------------------------------------------------- /src/.gitkeep: -------------------------------------------------------------------------------- 1 | Feel free to delete this file as soon as actual Java code is added to this 2 | directory. 3 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/base/InstantAccessOperationValue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.base; 16 | 17 | import com.fasterxml.jackson.annotation.JsonCreator; 18 | import com.fasterxml.jackson.annotation.JsonValue; 19 | 20 | /** 21 | * Contains all the operations supported by Amazon Instant Access 22 | */ 23 | public enum InstantAccessOperationValue { 24 | PURCHASE("Purchase"), 25 | REVOKE("Revoke"), 26 | GETUSERID("GetUserId"), 27 | SUBSCRIPTIONGET("SubscriptionGet"), 28 | SUBSCRIPTIONACTIVATE("SubscriptionActivate"), 29 | SUBSCRIPTIONDEACTIVATE("SubscriptionDeactivate"), 30 | SUBSCRIPTIONUPDATE("SubscriptionUpdate"); 31 | 32 | private String apiName; 33 | 34 | /** 35 | * @param apiName 36 | * The string representation of the operation according to the API 37 | */ 38 | InstantAccessOperationValue(String apiName) { 39 | this.apiName = apiName; 40 | } 41 | 42 | @JsonValue 43 | public String toJson() { 44 | return apiName; 45 | } 46 | 47 | @JsonCreator 48 | public static InstantAccessOperationValue fromJson(String text) { 49 | // ignore the case when deserializing 50 | return valueOf(text.toUpperCase()); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/base/InstantAccessRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.base; 16 | 17 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 18 | import com.fasterxml.jackson.databind.annotation.JsonSerialize; 19 | import org.apache.commons.lang.builder.ToStringBuilder; 20 | import org.apache.commons.lang.builder.ToStringStyle; 21 | 22 | @JsonIgnoreProperties(ignoreUnknown = true) 23 | @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) 24 | public class InstantAccessRequest { 25 | protected InstantAccessOperationValue operation; 26 | 27 | public InstantAccessOperationValue getOperation() { 28 | return operation; 29 | } 30 | 31 | public InstantAccessRequest setOperation(InstantAccessOperationValue operation) { 32 | this.operation = operation; 33 | return this; 34 | } 35 | 36 | @Override 37 | public int hashCode() { 38 | final int prime = 31; 39 | int result = 1; 40 | result = prime * result + ((operation == null) ? 0 : operation.hashCode()); 41 | return result; 42 | } 43 | 44 | @Override 45 | public boolean equals(Object obj) { 46 | if (this == obj) { 47 | return true; 48 | } 49 | if (obj == null) { 50 | return false; 51 | } 52 | if (getClass() != obj.getClass()) { 53 | return false; 54 | } 55 | InstantAccessRequest other = (InstantAccessRequest) obj; 56 | if (operation == null) { 57 | if (other.operation != null) { 58 | return false; 59 | } 60 | } else if (!operation.equals(other.operation)) { 61 | return false; 62 | } 63 | return true; 64 | } 65 | 66 | @Override 67 | public String toString() { 68 | return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("operation", operation).toString(); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/base/InstantAccessResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.base; 16 | 17 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 18 | import com.fasterxml.jackson.databind.annotation.JsonSerialize; 19 | import org.apache.commons.lang.builder.ToStringBuilder; 20 | import org.apache.commons.lang.builder.ToStringStyle; 21 | 22 | import java.io.Serializable; 23 | 24 | @JsonIgnoreProperties(ignoreUnknown = true) 25 | @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) 26 | public abstract class InstantAccessResponse { 27 | protected R response; 28 | 29 | public R getResponse() { 30 | return response; 31 | } 32 | 33 | public void setResponse(R response) { 34 | this.response = response; 35 | } 36 | 37 | @Override 38 | public int hashCode() { 39 | final int prime = 31; 40 | int result = 1; 41 | result = prime * result + ((response == null) ? 0 : response.hashCode()); 42 | return result; 43 | } 44 | 45 | @Override 46 | public boolean equals(Object obj) { 47 | if (this == obj) { 48 | return true; 49 | } 50 | if (obj == null) { 51 | return false; 52 | } 53 | if (getClass() != obj.getClass()) { 54 | return false; 55 | } 56 | InstantAccessResponse other = (InstantAccessResponse) obj; 57 | if (response == null) { 58 | if (other.response != null) { 59 | return false; 60 | } 61 | } else if (!response.equals(other.response)) { 62 | return false; 63 | } 64 | return true; 65 | } 66 | 67 | @Override 68 | public String toString() { 69 | return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("response", response).toString(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/base/SubscriptionPeriodValue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.base; 16 | 17 | import com.fasterxml.jackson.annotation.JsonCreator; 18 | 19 | /** 20 | * Possible periods that could be included in a subscription action 21 | */ 22 | public enum SubscriptionPeriodValue { 23 | FREE_TRIAL, 24 | GRACE_PERIOD, 25 | NOT_STARTED, 26 | REGULAR; 27 | 28 | @JsonCreator 29 | public static SubscriptionPeriodValue fromJson(String text) { 30 | // ignore the case when deserializing 31 | return valueOf(text.toUpperCase()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/base/SubscriptionReasonValue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.base; 16 | 17 | import com.fasterxml.jackson.annotation.JsonCreator; 18 | 19 | /** 20 | * Possible reasons for a subscription action 21 | */ 22 | public enum SubscriptionReasonValue { 23 | NOT_RENEWED, 24 | USER_REQUEST, 25 | CUSTOMER_SERVICE_REQUEST, 26 | PAYMENT_PROBLEM, 27 | TESTING, 28 | UNABLE_TO_FULFILL, 29 | REASSIGN; 30 | 31 | @JsonCreator 32 | public static SubscriptionReasonValue fromJson(String text) { 33 | // ignore the case when deserializing 34 | return valueOf(text.toUpperCase()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/base/SubscriptionRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.base; 16 | 17 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 18 | 19 | @JsonIgnoreProperties(ignoreUnknown = true) 20 | public class SubscriptionRequest extends InstantAccessRequest { 21 | 22 | protected String subscriptionId; 23 | 24 | protected String productId; 25 | 26 | protected String userId; 27 | 28 | public String getSubscriptionId() { 29 | return subscriptionId; 30 | } 31 | 32 | public SubscriptionRequest setSubscriptionId(String subscriptionId) { 33 | this.subscriptionId = subscriptionId; 34 | return this; 35 | } 36 | 37 | public String getProductId() { 38 | return productId; 39 | } 40 | 41 | public SubscriptionRequest setProductId(String productId) { 42 | this.productId = productId; 43 | return this; 44 | } 45 | 46 | public String getUserId() { 47 | return userId; 48 | } 49 | 50 | public SubscriptionRequest setUserId(String userId) { 51 | this.userId = userId; 52 | return this; 53 | } 54 | 55 | @Override 56 | public boolean equals(Object o) { 57 | if (this == o) return true; 58 | if (o == null || getClass() != o.getClass()) return false; 59 | if (!super.equals(o)) return false; 60 | 61 | final SubscriptionRequest that = (SubscriptionRequest) o; 62 | 63 | if (subscriptionId != null ? !subscriptionId.equals(that.subscriptionId) : that.subscriptionId != null) 64 | return false; 65 | 66 | return true; 67 | } 68 | 69 | @Override 70 | public int hashCode() { 71 | int result = super.hashCode(); 72 | result = 31 * result + (subscriptionId != null ? subscriptionId.hashCode() : 0); 73 | return result; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/base/SubscriptionResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.base; 16 | 17 | /** 18 | * Serializable SubscriptionResponse object 19 | */ 20 | public class SubscriptionResponse extends InstantAccessResponse { 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/base/SubscriptionResponseValue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.base; 16 | 17 | import com.fasterxml.jackson.annotation.JsonCreator; 18 | 19 | /** 20 | * Possible response values for inclusion in a SubscriptionResponse 21 | */ 22 | public enum SubscriptionResponseValue { 23 | OK, 24 | FAIL_USER_NOT_ELIGIBLE, 25 | FAIL_USER_INVALID, 26 | FAIL_INVALID_SUBSCRIPTION, 27 | FAIL_OTHER; 28 | 29 | @JsonCreator 30 | public static SubscriptionResponseValue fromJson(String text) { 31 | // ignore the case when deserializing 32 | return valueOf(text.toUpperCase()); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/serializer/JacksonSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.serializer; 16 | 17 | import java.io.StringWriter; 18 | 19 | import com.fasterxml.jackson.databind.ObjectMapper; 20 | import org.apache.commons.logging.Log; 21 | import org.apache.commons.logging.LogFactory; 22 | 23 | public class JacksonSerializer { 24 | private static final Log log = LogFactory.getLog(JacksonSerializer.class); 25 | 26 | private ObjectMapper objectMapper; 27 | 28 | public JacksonSerializer() { 29 | objectMapper = new ObjectMapper(); 30 | } 31 | 32 | public String encode(T serialObject) throws SerializationException { 33 | log.info(String.format("Serializing object [%s]", serialObject)); 34 | 35 | StringWriter writer = new StringWriter(); 36 | 37 | try { 38 | objectMapper.writeValue(writer, serialObject); 39 | } catch (Exception e) { 40 | String error = "Unable to serialize object to string"; 41 | log.error(error, e); 42 | throw new SerializationException(error, e); 43 | } 44 | 45 | return writer.toString(); 46 | } 47 | 48 | public T decode(String jsonString, Class pojoClass) throws SerializationException { 49 | try { 50 | return objectMapper.readValue(jsonString, pojoClass); 51 | } catch (Exception e) { 52 | String error = "Unable to deserialize string into object"; 53 | log.error(error, e); 54 | throw new SerializationException(error, e); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/serializer/SerializationException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.serializer; 16 | 17 | public class SerializationException extends Exception { 18 | private static final long serialVersionUID = -3095196341869438153L; 19 | 20 | public SerializationException(String message) { 21 | super(message); 22 | } 23 | 24 | public SerializationException(Throwable cause) { 25 | super(cause); 26 | } 27 | 28 | public SerializationException(String message, Throwable cause) { 29 | super(message, cause); 30 | } 31 | } -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/signature/AuthenticationHeader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.signature; 16 | 17 | /** 18 | * Bean class representing the authentication header, which looks like 19 | * 20 | *
21 |  * Authentication: ALGORITHM Credential=CREDENTIAL, SignedHeaders=SIGNED_HEADERS, Signature=SIGNATURE
22 |  * 
23 | * 24 | * Where: 25 | * ALGORITHM := The signing algorithm used for the credential, ex. DTAv1-SHA-256 26 | * CREDENTIAL := KEYID/DATE. 27 | * SIGNED_HEADERS := lower cased header names sorted by byte order joined with semicolons. 28 | * SIGNATURE := The signature calculated by the signing algorithm. 29 | * KEYID := The public id for the sceret key used to calculate the signature. 30 | * DATE := The date the message was signed in YYMMDD format. This is used to generate the daily key. 31 | */ 32 | public class AuthenticationHeader { 33 | private String algorithm; 34 | private String credential; 35 | private String signedHeaders; 36 | private String signature; 37 | 38 | public void setAlgorithm(String algorithm) { 39 | this.algorithm = algorithm; 40 | } 41 | 42 | public void setCredential(String credential) { 43 | this.credential = credential; 44 | } 45 | 46 | public void setSignedHeaders(String signedHeaders) { 47 | this.signedHeaders = signedHeaders; 48 | } 49 | 50 | public void setSignature(String signature) { 51 | this.signature = signature; 52 | } 53 | 54 | public String getAlgorithm() { 55 | return algorithm; 56 | } 57 | 58 | public String getCredential() { 59 | return credential; 60 | } 61 | 62 | public String getSignedHeaders() { 63 | return signedHeaders; 64 | } 65 | 66 | public String getSignature() { 67 | return signature; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/signature/AuthenticationHeaderParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.signature; 16 | 17 | import java.util.regex.Matcher; 18 | import java.util.regex.Pattern; 19 | 20 | /** 21 | * Parses an AuthenticationHeader from a header value string. 22 | * 23 | * Pattern: ALGORITHM SignedHeaders=x;y;z, Credential=XXX, Signature=BIGSHA 24 | * Example: DTA1-HMAC-SHA256 SignedHeaders=aaa;content-type;x-amz-date;zzz, Credential=KEYID/20110909, 25 | * Signature=87729cb3475859a18b5d9cead0bba82f0f56a85c2a13bed3bc229c6c35e06628 26 | */ 27 | public class AuthenticationHeaderParser { 28 | private static final Pattern pattern = Pattern 29 | .compile("(\\S+) SignedHeaders=(\\S+), Credential=(\\S+), Signature=([\\S&&[^,]]+)"); 30 | 31 | public AuthenticationHeader parse(String headerString) { 32 | Matcher match = pattern.matcher(headerString); 33 | AuthenticationHeader header = new AuthenticationHeader(); 34 | 35 | if (!match.find()) { 36 | return null; 37 | } 38 | 39 | header.setAlgorithm(match.group(1)); 40 | header.setSignedHeaders(match.group(2)); 41 | header.setCredential(match.group(3)); 42 | header.setSignature(match.group(4)); 43 | 44 | return header; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/signature/Credential.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.signature; 16 | 17 | /** 18 | * Bean class representing a signing credential 19 | */ 20 | public class Credential { 21 | private String secretKey; 22 | private String publicKey; 23 | 24 | public Credential(String secretkey, String publicKey) { 25 | this.secretKey = secretkey; 26 | this.publicKey = publicKey; 27 | } 28 | 29 | public String getSecretKey() { 30 | return secretKey; 31 | } 32 | 33 | public String getPublicKey() { 34 | return publicKey; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/signature/CredentialNotFoundException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.signature; 16 | 17 | public class CredentialNotFoundException extends Exception { 18 | public CredentialNotFoundException(String message) { 19 | super(message); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/signature/CredentialStore.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.signature; 16 | 17 | import java.io.File; 18 | import java.io.FileInputStream; 19 | import java.io.IOException; 20 | import java.io.InputStream; 21 | import java.io.StringWriter; 22 | import java.nio.charset.Charset; 23 | import java.util.Collection; 24 | import java.util.HashMap; 25 | 26 | import org.apache.commons.io.IOUtils; 27 | import org.apache.commons.lang.StringUtils; 28 | import org.apache.commons.logging.Log; 29 | import org.apache.commons.logging.LogFactory; 30 | 31 | /** 32 | * Class that is used to manage multiple credentials. 33 | * 34 | * The {@link CredentialStore#load()} method can be called to load keys from a {@link File}, a {@link InputStream} or a 35 | * {@link String}. 36 | * 37 | * Each line of the file/stream/string must contain a secret key and a public key separated by an empty space, for 38 | * example: 39 | * 40 | * 69b2048d-8bf8-4c1c-b49d-e6114897a9a5 dce53190-1f70-4206-ad28-0e1ab3683161 41 | * 42 | * Credentials, then, can be accessed by the public key using {@link CredentialStore#get(String)} 43 | * 44 | */ 45 | public class CredentialStore { 46 | private static final Log log = LogFactory.getLog(CredentialStore.class); 47 | 48 | private HashMap store; 49 | 50 | public CredentialStore() { 51 | store = new HashMap(); 52 | } 53 | 54 | /** 55 | * Gets the credential for a given public key. 56 | * 57 | * @param publicKey 58 | * the public key 59 | * @return the credential 60 | * 61 | * @throws CredentialNotFoundException 62 | */ 63 | public Credential get(String publicKey) throws CredentialNotFoundException { 64 | if (!store.containsKey(publicKey)) { 65 | String message = "Credential not found for public key: " + publicKey; 66 | log.error(message); 67 | throw new CredentialNotFoundException(message); 68 | } 69 | 70 | return store.get(publicKey); 71 | } 72 | 73 | /** 74 | * Gets the credentials stored in this store. 75 | * 76 | * @return a {@link Collection} with all the credentials 77 | */ 78 | public Collection getAll() { 79 | return store.values(); 80 | } 81 | 82 | /** 83 | * Adds the new credential to the store. If the store already contains the public key the credential is replaced. 84 | * 85 | * @param credential 86 | * the credential object to be added 87 | */ 88 | public void add(Credential credential) { 89 | store.put(credential.getPublicKey(), credential); 90 | } 91 | 92 | /** 93 | * Removes the credential from the store. 94 | * 95 | * @param publicKey 96 | * the public key of the credential to be removed 97 | */ 98 | public void remove(String publicKey) { 99 | store.remove(publicKey); 100 | } 101 | 102 | /** 103 | * Loads keys from a file and populates the store. 104 | * 105 | * Each line of the file must contain a secret key and a public key separated by an empty space. 106 | * 107 | * @param file 108 | * the file object that contains the keys 109 | * @throws IOException 110 | */ 111 | public void load(File file) throws IOException { 112 | if (file == null || !file.exists()) { 113 | String message = "Invalid keys file object"; 114 | log.error(message); 115 | throw new IllegalArgumentException(message); 116 | } 117 | 118 | load(new FileInputStream(file)); 119 | } 120 | 121 | /** 122 | * Loads keys from a input stream and populates the store. 123 | * 124 | * Each line of the file must contain a secret key and a public key separated by an empty space. 125 | * 126 | * @param stream 127 | * the stream object that contains the keys 128 | * @throws IOException 129 | */ 130 | public void load(InputStream stream) throws IOException { 131 | if (stream == null) { 132 | String message = "Invalid keys input stream"; 133 | log.error(message); 134 | throw new IllegalArgumentException(message); 135 | } 136 | 137 | StringWriter writer = new StringWriter(); 138 | IOUtils.copy(stream, writer, Charset.defaultCharset()); 139 | String contents = writer.toString(); 140 | 141 | load(contents); 142 | } 143 | 144 | /** 145 | * Loads keys from a string and populates the store. 146 | * 147 | * Each line of the file must contain a secret key and a public key separated by an empty space. 148 | * 149 | * @param contents 150 | * the string object that contains the keys 151 | * @throws IOException 152 | */ 153 | public void load(String contents) { 154 | if (StringUtils.isEmpty(contents)) { 155 | String message = "Invalid keys"; 156 | log.error(message); 157 | throw new IllegalArgumentException(message); 158 | } 159 | 160 | String[] lines = contents.split("\\n"); 161 | 162 | for (int i = 0; i < lines.length; ++i) { 163 | String line = lines[i]; 164 | 165 | // Ignore blank lines in between credentials 166 | if (StringUtils.isEmpty(line)) { 167 | continue; 168 | } 169 | 170 | // credentials should be separate by an empty space 171 | String[] keys = line.split("\\s+"); 172 | 173 | // Invalid format 174 | if (keys.length < 2) { 175 | String message = String.format("Invalid credentials format found on line %d", i); 176 | log.error(message); 177 | throw new IllegalArgumentException(message); 178 | } 179 | 180 | String secretKey = keys[0]; 181 | String publicKey = keys[1]; 182 | 183 | store.put(publicKey, new Credential(secretKey, publicKey)); 184 | } 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/signature/Request.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.signature; 16 | 17 | import java.io.IOException; 18 | import java.net.MalformedURLException; 19 | import java.net.URISyntaxException; 20 | import java.net.URL; 21 | import java.util.Enumeration; 22 | import java.util.Map; 23 | import java.util.Set; 24 | import java.util.TreeMap; 25 | 26 | import javax.servlet.http.HttpServletRequest; 27 | 28 | import org.apache.commons.io.IOUtils; 29 | import org.apache.commons.lang.StringUtils; 30 | 31 | /** 32 | * Represents an HTTP request. This is used to for both signing and verifying a request to be signed. 33 | */ 34 | public class Request { 35 | public static final String CONTENT_TYPE_HEADER = "Content-Type"; 36 | public static final String DEFAULT_USER_AGENT = "Mozilla/5.0 (compatible; Amazon Instant Access/1.0"; 37 | private String url; 38 | private Method method; 39 | private String body; 40 | private Map headers = new TreeMap(String.CASE_INSENSITIVE_ORDER); 41 | private String userAgent; 42 | 43 | /** 44 | * Creates a Request from an HttpServletRequest. Useful for verifying the signature of a request. 45 | * 46 | * NOTE: This consumes the body of the request which can cause issues when you try and read it again. 47 | * 48 | * @param httpServletRequest 49 | * the HttpServletRequest to copy 50 | * @throws IOException 51 | * on invalid url or body copying 52 | */ 53 | public Request(HttpServletRequest httpServletRequest) throws IOException { 54 | url = getFullURL(httpServletRequest); 55 | method = Method.valueOf(httpServletRequest.getMethod()); 56 | 57 | Enumeration headerNames = httpServletRequest.getHeaderNames(); 58 | while (headerNames.hasMoreElements()) { 59 | String name = headerNames.nextElement(); 60 | headers.put(name, httpServletRequest.getHeader(name)); 61 | } 62 | headers.put(CONTENT_TYPE_HEADER, httpServletRequest.getContentType()); 63 | body = IOUtils.toString(httpServletRequest.getInputStream()); 64 | } 65 | 66 | public Request(String url, Method method, String contentType) { 67 | validateUrl(url); 68 | this.url = url; 69 | this.method = method; 70 | this.headers.put(CONTENT_TYPE_HEADER, contentType); 71 | this.userAgent = DEFAULT_USER_AGENT; 72 | } 73 | 74 | public String getUserAgent() { 75 | return userAgent; 76 | } 77 | 78 | public void setUserAgent(String userAgent) { 79 | this.userAgent = userAgent; 80 | } 81 | 82 | /** 83 | * An enumeration of HTTP methods supported 84 | */ 85 | public enum Method { 86 | POST, 87 | GET 88 | } 89 | 90 | /** 91 | * @return the full url of the request 92 | */ 93 | public String getUrl() { 94 | return url; 95 | } 96 | 97 | public void setBody(String body) { 98 | this.body = body; 99 | } 100 | 101 | public String getBody() { 102 | return body; 103 | } 104 | 105 | public String getHeader(String headerName) { 106 | return headers.get(headerName); 107 | } 108 | 109 | public void setHeader(String name, String value) { 110 | headers.put(name, value); 111 | } 112 | 113 | public void removeHeader(String headerName) { 114 | headers.remove(headerName); 115 | } 116 | 117 | public Method getMethod() { 118 | return method; 119 | } 120 | 121 | public Set getHeaderNames() { 122 | return headers.keySet(); 123 | } 124 | 125 | private void validateUrl(String inputUrl) { 126 | if (inputUrl == null) { 127 | throw new IllegalArgumentException("inputUrl cannot be null"); 128 | } 129 | try { 130 | new URL(inputUrl).toURI(); 131 | } catch (MalformedURLException e) { 132 | throw new IllegalArgumentException("inputUrl does not resolve to a valid URL", e); 133 | } catch (URISyntaxException e) { 134 | throw new IllegalArgumentException("inputUrl does not resolve to a valid URI", e); 135 | } 136 | } 137 | 138 | private String getFullURL(HttpServletRequest request) { 139 | StringBuffer requestURL = request.getRequestURL(); 140 | String queryString = request.getQueryString(); 141 | 142 | if (StringUtils.isEmpty(queryString)) { 143 | return requestURL.toString(); 144 | } else { 145 | return requestURL.append('?').append(queryString).toString(); 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/signature/SigningException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.signature; 16 | 17 | public class SigningException extends Exception { 18 | public SigningException(Exception e) { 19 | super(e); 20 | } 21 | 22 | public SigningException(String message) { 23 | super(message); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/utils/BinaryUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.utils; 16 | 17 | import org.apache.commons.codec.binary.Base64; 18 | import org.apache.commons.logging.Log; 19 | import org.apache.commons.logging.LogFactory; 20 | 21 | import java.io.UnsupportedEncodingException; 22 | import java.util.Locale; 23 | 24 | // Complete https://tt.amazon.com/0026066375 before open release WHOLE CLASS 25 | /** 26 | * Utilities for encoding and decoding binary data to and from different forms. 27 | */ 28 | public class BinaryUtils { 29 | 30 | /** Default encoding when extracting binary data from a String */ 31 | private static final String DEFAULT_ENCODING = "UTF-8"; 32 | 33 | private static final Log log = LogFactory.getLog(BinaryUtils.class); 34 | 35 | /** 36 | * Converts byte data to a Hex-encoded string. 37 | * 38 | * @param data 39 | * data to hex encode. 40 | * 41 | * @return hex-encoded string. 42 | */ 43 | public static String toHex(byte[] data) { 44 | StringBuilder sb = new StringBuilder(data.length * 2); 45 | for (int i = 0; i < data.length; i++) { 46 | String hex = Integer.toHexString(data[i]); 47 | if (hex.length() == 1) { 48 | // Append leading zero. 49 | sb.append("0"); 50 | } else if (hex.length() == 8) { 51 | // Remove ff prefix from negative numbers. 52 | hex = hex.substring(6); 53 | } 54 | sb.append(hex); 55 | } 56 | return sb.toString().toLowerCase(Locale.getDefault()); 57 | } 58 | 59 | /** 60 | * Converts a Hex-encoded data string to the original byte data. 61 | * 62 | * @param hexData 63 | * hex-encoded data to decode. 64 | * @return decoded data from the hex string. 65 | */ 66 | public static byte[] fromHex(String hexData) { 67 | byte[] result = new byte[(hexData.length() + 1) / 2]; 68 | String hexNumber = null; 69 | int stringOffset = 0; 70 | int byteOffset = 0; 71 | while (stringOffset < hexData.length()) { 72 | hexNumber = hexData.substring(stringOffset, stringOffset + 2); 73 | stringOffset += 2; 74 | result[byteOffset++] = (byte) Integer.parseInt(hexNumber, 16); 75 | } 76 | return result; 77 | } 78 | 79 | /** 80 | * Converts byte data to a Base64-encoded string. 81 | * 82 | * @param data 83 | * data to Base64 encode. 84 | * @return encoded Base64 string. 85 | */ 86 | public static String toBase64(byte[] data) { 87 | byte[] b64 = Base64.encodeBase64(data); 88 | return new String(b64); 89 | } 90 | 91 | /** 92 | * Converts a Base64-encoded string to the original byte data. 93 | * 94 | * @param b64Data 95 | * a Base64-encoded string to decode. 96 | * 97 | * @return bytes decoded from a Base64 string. 98 | */ 99 | public static byte[] fromBase64(String b64Data) { 100 | byte[] decoded; 101 | try { 102 | decoded = Base64.decodeBase64(b64Data.getBytes(DEFAULT_ENCODING)); 103 | } catch (UnsupportedEncodingException uee) { 104 | // Shouldn't happen if the string is truly Base64 encoded. 105 | log.warn("Tried to Base64-decode a String with the wrong encoding: ", uee); 106 | decoded = Base64.decodeBase64(b64Data.getBytes()); 107 | } 108 | return decoded; 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/utils/Clock.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.utils; 16 | 17 | import java.util.Date; 18 | 19 | /** 20 | * Wrapper class for current time, mainly used for testing. 21 | */ 22 | public class Clock { 23 | public Date now() { 24 | return new Date(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/utils/HttpUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.utils; 16 | 17 | import java.io.UnsupportedEncodingException; 18 | import java.net.URI; 19 | import java.net.URLEncoder; 20 | import java.util.regex.Matcher; 21 | import java.util.regex.Pattern; 22 | 23 | public class HttpUtils { 24 | private static final String DEFAULT_ENCODING = "UTF-8"; 25 | 26 | /** 27 | * Regex which matches any of the sequences that we need to fix up after URLEncoder.encode(). 28 | */ 29 | private static final Pattern ENCODED_CHARACTERS_PATTERN; 30 | static { 31 | StringBuilder pattern = new StringBuilder(); 32 | 33 | pattern.append(Pattern.quote("+")).append("|").append(Pattern.quote("*")).append("|") 34 | .append(Pattern.quote("%7E")).append("|").append(Pattern.quote("%2F")); 35 | 36 | ENCODED_CHARACTERS_PATTERN = Pattern.compile(pattern.toString()); 37 | } 38 | 39 | /** 40 | * Encode a string for use in the path of a URL; uses URLEncoder.encode, (which encodes a string for use in the 41 | * query portion of a URL), then applies some postfilters to fix things up per the RFC. Can optionally handle 42 | * strings which are meant to encode a path (ie include '/'es which should NOT be escaped). 43 | * 44 | * @param value 45 | * the value to encode 46 | * @param path 47 | * true if the value is intended to represent a path 48 | * @return the encoded value 49 | */ 50 | public static String urlEncode(String value, boolean path) { 51 | if (value == null) { 52 | return ""; 53 | } 54 | 55 | try { 56 | String encoded = URLEncoder.encode(value, DEFAULT_ENCODING); 57 | 58 | Matcher matcher = ENCODED_CHARACTERS_PATTERN.matcher(encoded); 59 | StringBuffer buffer = new StringBuffer(encoded.length()); 60 | 61 | while (matcher.find()) { 62 | String replacement = matcher.group(0); 63 | 64 | if ("+".equals(replacement)) { 65 | replacement = "%20"; 66 | } else if ("*".equals(replacement)) { 67 | replacement = "%2A"; 68 | } else if ("%7E".equals(replacement)) { 69 | replacement = "~"; 70 | } else if (path && "%2F".equals(replacement)) { 71 | replacement = "/"; 72 | } 73 | 74 | matcher.appendReplacement(buffer, replacement); 75 | } 76 | 77 | matcher.appendTail(buffer); 78 | return buffer.toString(); 79 | 80 | } catch (UnsupportedEncodingException ex) { 81 | throw new RuntimeException(ex); 82 | } 83 | } 84 | 85 | /** 86 | * Returns true if the specified URI is using a non-standard port (i.e. any port other than 80 for HTTP URIs or any 87 | * port other than 443 for HTTPS URIs). 88 | * 89 | * @param uri 90 | * 91 | * @return True if the specified URI is using a non-standard port, otherwise false. 92 | */ 93 | public static boolean isUsingNonDefaultPort(URI uri) { 94 | String scheme = uri.getScheme().toLowerCase(); 95 | int port = uri.getPort(); 96 | 97 | if (port <= 0) { 98 | return false; 99 | } 100 | if (scheme.equals("http") && port == 80) { 101 | return false; 102 | } 103 | if (scheme.equals("https") && port == 443) { 104 | return false; 105 | } 106 | 107 | return true; 108 | } 109 | 110 | /** 111 | * Append the given path to the given baseUri. By default, all slash characters in path will not be url-encoded. 112 | */ 113 | public static String appendUri(String baseUri, String path) { 114 | return appendUri(baseUri, path, false); 115 | } 116 | 117 | /** 118 | * Append the given path to the given baseUri. 119 | * 120 | *

121 | * This method will encode the given path but not the given baseUri. 122 | *

123 | * 124 | * @param baseUri 125 | * The URI to append to (required, may be relative) 126 | * @param path 127 | * The path to append (may be null or empty) 128 | * @param escapeDoubleSlash 129 | * Whether double-slash in the path should be escaped to "/%2F" 130 | * @return The baseUri with the (encoded) path appended 131 | */ 132 | public static String appendUri(String baseUri, String path, boolean escapeDoubleSlash) { 133 | String resultUri = baseUri; 134 | if (path != null && path.length() > 0) { 135 | if (path.startsWith("/")) { 136 | // trim the trailing slash in baseUri, since the path already starts with a slash 137 | if (resultUri.endsWith("/")) { 138 | resultUri = resultUri.substring(0, resultUri.length() - 1); 139 | } 140 | } else if (!resultUri.endsWith("/")) { 141 | resultUri += "/"; 142 | } 143 | String encodedPath = HttpUtils.urlEncode(path, true); 144 | if (escapeDoubleSlash) { 145 | encodedPath = encodedPath.replace("//", "/%2F"); 146 | } 147 | resultUri += encodedPath; 148 | } else if (!resultUri.endsWith("/")) { 149 | resultUri += "/"; 150 | } 151 | 152 | return resultUri; 153 | } 154 | 155 | } 156 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v2/serialization/messages/FulfillPurchaseRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v2.serialization.messages; 16 | 17 | import com.amazon.dtasdk.base.InstantAccessOperationValue; 18 | import com.amazon.dtasdk.base.InstantAccessRequest; 19 | import org.apache.commons.lang.builder.ToStringBuilder; 20 | import org.apache.commons.lang.builder.ToStringStyle; 21 | 22 | /** 23 | * Serializable FulfillPurchaseRequest object to pass to developer used to fulfill a purchase 24 | */ 25 | 26 | public class FulfillPurchaseRequest extends InstantAccessRequest { 27 | private String purchaseToken; 28 | private String userId; 29 | private String productId; 30 | private String reason; 31 | 32 | @Override 33 | public FulfillPurchaseRequest setOperation(InstantAccessOperationValue operation) { 34 | this.operation = operation; 35 | return this; 36 | } 37 | 38 | public String getPurchaseToken() { 39 | return purchaseToken; 40 | } 41 | 42 | public FulfillPurchaseRequest setPurchaseToken(String purchaseToken) { 43 | this.purchaseToken = purchaseToken; 44 | return this; 45 | } 46 | 47 | public String getUserId() { 48 | return userId; 49 | } 50 | 51 | public FulfillPurchaseRequest setUserId(String userId) { 52 | this.userId = userId; 53 | return this; 54 | } 55 | 56 | public String getProductId() { 57 | return productId; 58 | } 59 | 60 | public FulfillPurchaseRequest setProductId(String productId) { 61 | this.productId = productId; 62 | return this; 63 | } 64 | 65 | public String getReason() { 66 | return reason; 67 | } 68 | 69 | public FulfillPurchaseRequest setReason(String reason) { 70 | this.reason = reason; 71 | return this; 72 | } 73 | 74 | @Override 75 | public int hashCode() { 76 | final int prime = 31; 77 | int result = 1; 78 | result = prime * result + ((purchaseToken == null) ? 0 : purchaseToken.hashCode()); 79 | result = prime * result + ((operation == null) ? 0 : operation.hashCode()); 80 | result = prime * result + ((userId == null) ? 0 : userId.hashCode()); 81 | result = prime * result + ((productId == null) ? 0 : productId.hashCode()); 82 | result = prime * result + ((reason == null) ? 0 : reason.hashCode()); 83 | return result; 84 | } 85 | 86 | @Override 87 | public boolean equals(Object obj) { 88 | if (this == obj) { 89 | return true; 90 | } 91 | if (obj == null) { 92 | return false; 93 | } 94 | if (getClass() != obj.getClass()) { 95 | return false; 96 | } 97 | final FulfillPurchaseRequest other = (FulfillPurchaseRequest) obj; 98 | if (purchaseToken == null) { 99 | if (other.purchaseToken != null) { 100 | return false; 101 | } 102 | } else if (!purchaseToken.equals(other.purchaseToken)) { 103 | return false; 104 | } 105 | 106 | if (operation == null) { 107 | if (other.operation != null) { 108 | return false; 109 | } 110 | } else if (!operation.equals(other.operation)) { 111 | return false; 112 | } 113 | 114 | if (userId == null) { 115 | if (other.userId != null) { 116 | return false; 117 | } 118 | } else if (!userId.equals(other.userId)) { 119 | return false; 120 | } 121 | 122 | if (productId == null) { 123 | if (other.productId != null) { 124 | return false; 125 | } 126 | } else if (!productId.equals(other.productId)) { 127 | return false; 128 | } 129 | 130 | if (reason == null) { 131 | if (other.reason != null) { 132 | return false; 133 | } 134 | } else if (!reason.equals(other.reason)) { 135 | return false; 136 | } 137 | return true; 138 | } 139 | 140 | @Override 141 | public String toString() { 142 | return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("operation", operation) 143 | .append("reason", reason).append("productId", productId).append("userId", userId) 144 | .append("purchaseToken", purchaseToken).toString(); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v2/serialization/messages/FulfillPurchaseResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v2.serialization.messages; 16 | 17 | import com.amazon.dtasdk.base.InstantAccessResponse; 18 | 19 | /** 20 | * Serilizable response from vendor used to fulfill a purchase 21 | */ 22 | 23 | public class FulfillPurchaseResponse extends InstantAccessResponse { 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v2/serialization/messages/FulfillPurchaseResponseValue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v2.serialization.messages; 16 | 17 | import com.fasterxml.jackson.annotation.JsonCreator; 18 | 19 | public enum FulfillPurchaseResponseValue { 20 | OK, 21 | FAIL_USER_NOT_ELIGIBLE, 22 | FAIL_USER_INVALID, 23 | FAIL_OTHER; 24 | 25 | @JsonCreator 26 | public static FulfillPurchaseResponseValue fromJson(String text) { 27 | // ignore the case when deserializing 28 | return valueOf(text.toUpperCase()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v2/serialization/messages/GetUserIdSerializableRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v2.serialization.messages; 16 | 17 | import com.amazon.dtasdk.base.InstantAccessOperationValue; 18 | import com.amazon.dtasdk.base.InstantAccessRequest; 19 | import org.apache.commons.lang.builder.ToStringBuilder; 20 | import org.apache.commons.lang.builder.ToStringStyle; 21 | 22 | /** 23 | * Serializable GetUserId object to pass to developer 24 | */ 25 | public class GetUserIdSerializableRequest extends InstantAccessRequest { 26 | private String infoField1; 27 | private String infoField2; 28 | private String infoField3; 29 | 30 | @Override 31 | public GetUserIdSerializableRequest setOperation(InstantAccessOperationValue operation) { 32 | this.operation = operation; 33 | return this; 34 | } 35 | 36 | public String getInfoField1() { 37 | return infoField1; 38 | } 39 | 40 | public void setInfoField1(String infoField1) { 41 | this.infoField1 = infoField1; 42 | } 43 | 44 | public String getInfoField2() { 45 | return infoField2; 46 | } 47 | 48 | public void setInfoField2(String infoField2) { 49 | this.infoField2 = infoField2; 50 | } 51 | 52 | public String getInfoField3() { 53 | return infoField3; 54 | } 55 | 56 | public void setInfoField3(String infoField3) { 57 | this.infoField3 = infoField3; 58 | } 59 | 60 | @Override 61 | public int hashCode() { 62 | final int prime = 31; 63 | int result = 1; 64 | result = prime * result + ((operation == null) ? 0 : operation.hashCode()); 65 | result = prime * result + ((infoField1 == null) ? 0 : infoField1.hashCode()); 66 | result = prime * result + ((infoField2 == null) ? 0 : infoField2.hashCode()); 67 | result = prime * result + ((infoField3 == null) ? 0 : infoField3.hashCode()); 68 | return result; 69 | } 70 | 71 | @Override 72 | public boolean equals(Object obj) { 73 | if (this == obj) { 74 | return true; 75 | } 76 | if (obj == null) { 77 | return false; 78 | } 79 | if (getClass() != obj.getClass()) { 80 | return false; 81 | } 82 | final GetUserIdSerializableRequest other = (GetUserIdSerializableRequest) obj; 83 | if (operation == null) { 84 | if (other.operation != null) { 85 | return false; 86 | } 87 | } else if (!operation.equals(other.operation)) { 88 | return false; 89 | } 90 | if (infoField1 == null) { 91 | if (other.infoField1 != null) { 92 | return false; 93 | } 94 | } else if (!infoField1.equals(other.infoField1)) { 95 | return false; 96 | } 97 | 98 | if (infoField2 == null) { 99 | if (other.infoField2 != null) { 100 | return false; 101 | } 102 | } else if (!infoField2.equals(other.infoField2)) { 103 | return false; 104 | } 105 | 106 | if (infoField3 == null) { 107 | if (other.infoField3 != null) { 108 | return false; 109 | } 110 | } else if (!infoField3.equals(other.infoField3)) { 111 | return false; 112 | } 113 | return true; 114 | } 115 | 116 | @Override 117 | public String toString() { 118 | return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("operation", operation) 119 | .append("infoField1", infoField1).append("infoField2", infoField2).append("infoField3", infoField3) 120 | .toString(); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v2/serialization/messages/GetUserIdSerializableResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v2.serialization.messages; 16 | 17 | import com.amazon.dtasdk.base.InstantAccessResponse; 18 | import org.apache.commons.lang.builder.ToStringBuilder; 19 | import org.apache.commons.lang.builder.ToStringStyle; 20 | 21 | public class GetUserIdSerializableResponse extends InstantAccessResponse { 22 | private String userId; 23 | 24 | public String getUserId() { 25 | return userId; 26 | } 27 | 28 | public void setUserId(String userId) { 29 | this.userId = userId; 30 | } 31 | 32 | @Override 33 | public int hashCode() { 34 | final int prime = 31; 35 | int result = 1; 36 | result = prime * result + ((userId == null) ? 0 : userId.hashCode()); 37 | result = prime * result + ((response == null) ? 0 : response.hashCode()); 38 | return result; 39 | } 40 | 41 | @Override 42 | public boolean equals(Object obj) { 43 | if (this == obj) { 44 | return true; 45 | } 46 | if (obj == null) { 47 | return false; 48 | } 49 | if (getClass() != obj.getClass()) { 50 | return false; 51 | } 52 | final GetUserIdSerializableResponse other = (GetUserIdSerializableResponse) obj; 53 | if (userId == null) { 54 | if (other.userId != null) { 55 | return false; 56 | } 57 | } else if (!userId.equals(other.userId)) { 58 | return false; 59 | } 60 | 61 | if (response == null) { 62 | if (other.response != null) { 63 | return false; 64 | } 65 | } else if (!response.equals(other.response)) { 66 | return false; 67 | } 68 | return true; 69 | } 70 | 71 | @Override 72 | public String toString() { 73 | return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("userId", userId) 74 | .append("response", response).toString(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v2/serialization/messages/GetUserIdSerializableResponseValue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v2.serialization.messages; 16 | 17 | import com.fasterxml.jackson.annotation.JsonCreator; 18 | 19 | public enum GetUserIdSerializableResponseValue { 20 | OK, 21 | FAIL_ACCOUNT_INVALID; 22 | 23 | @JsonCreator 24 | public static GetUserIdSerializableResponseValue fromJson(String text) { 25 | // ignore the case when deserializing 26 | return valueOf(text.toUpperCase()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v2/serialization/messages/RevokePurchaseRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v2.serialization.messages; 16 | 17 | import com.amazon.dtasdk.base.InstantAccessOperationValue; 18 | import com.amazon.dtasdk.base.InstantAccessRequest; 19 | import org.apache.commons.lang.builder.ToStringBuilder; 20 | import org.apache.commons.lang.builder.ToStringStyle; 21 | 22 | /** 23 | * Serializable FulfillPurchaseRequest object to pass to developer used to revoke a purchase 24 | */ 25 | public class RevokePurchaseRequest extends InstantAccessRequest { 26 | private String purchaseToken; 27 | private String userId; 28 | private String productId; 29 | private String reason; 30 | 31 | @Override 32 | public RevokePurchaseRequest setOperation(InstantAccessOperationValue operation) { 33 | this.operation = operation; 34 | return this; 35 | } 36 | 37 | public String getPurchaseToken() { 38 | return purchaseToken; 39 | } 40 | 41 | public RevokePurchaseRequest setPurchaseToken(String purchaseToken) { 42 | this.purchaseToken = purchaseToken; 43 | return this; 44 | } 45 | 46 | public String getUserId() { 47 | return userId; 48 | } 49 | 50 | public RevokePurchaseRequest setUserId(String userId) { 51 | this.userId = userId; 52 | return this; 53 | } 54 | 55 | public String getProductId() { 56 | return productId; 57 | } 58 | 59 | public RevokePurchaseRequest setProductId(String productId) { 60 | this.productId = productId; 61 | return this; 62 | } 63 | 64 | public String getReason() { 65 | return reason; 66 | } 67 | 68 | public RevokePurchaseRequest setReason(String reason) { 69 | this.reason = reason; 70 | return this; 71 | } 72 | 73 | @Override 74 | public int hashCode() { 75 | final int prime = 31; 76 | int result = 1; 77 | result = prime * result + ((operation == null) ? 0 : operation.hashCode()); 78 | result = prime * result + ((productId == null) ? 0 : productId.hashCode()); 79 | result = prime * result + ((purchaseToken == null) ? 0 : purchaseToken.hashCode()); 80 | result = prime * result + ((reason == null) ? 0 : reason.hashCode()); 81 | result = prime * result + ((userId == null) ? 0 : userId.hashCode()); 82 | return result; 83 | } 84 | 85 | @Override 86 | public boolean equals(Object obj) { 87 | if (this == obj) { 88 | return true; 89 | } 90 | if (obj == null) { 91 | return false; 92 | } 93 | if (getClass() != obj.getClass()) { 94 | return false; 95 | } 96 | RevokePurchaseRequest other = (RevokePurchaseRequest) obj; 97 | if (operation == null) { 98 | if (other.operation != null) { 99 | return false; 100 | } 101 | } else if (!operation.equals(other.operation)) { 102 | return false; 103 | } 104 | if (productId == null) { 105 | if (other.productId != null) { 106 | return false; 107 | } 108 | } else if (!productId.equals(other.productId)) { 109 | return false; 110 | } 111 | if (purchaseToken == null) { 112 | if (other.purchaseToken != null) { 113 | return false; 114 | } 115 | } else if (!purchaseToken.equals(other.purchaseToken)) { 116 | return false; 117 | } 118 | if (reason == null) { 119 | if (other.reason != null) { 120 | return false; 121 | } 122 | } else if (!reason.equals(other.reason)) { 123 | return false; 124 | } 125 | if (userId == null) { 126 | if (other.userId != null) { 127 | return false; 128 | } 129 | } else if (!userId.equals(other.userId)) { 130 | return false; 131 | } 132 | return true; 133 | } 134 | 135 | @Override 136 | public String toString() { 137 | return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("operation", operation) 138 | .append("reason", reason).append("productId", productId).append("userId", userId) 139 | .append("purchaseToken", purchaseToken).toString(); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v2/serialization/messages/RevokePurchaseResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v2.serialization.messages; 16 | 17 | import com.amazon.dtasdk.base.InstantAccessResponse; 18 | 19 | /** 20 | * Serilizable response from vendor used to revoke a purchase 21 | */ 22 | public class RevokePurchaseResponse extends InstantAccessResponse { 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v2/serialization/messages/RevokePurchaseResponseValue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v2.serialization.messages; 16 | 17 | import com.fasterxml.jackson.annotation.JsonCreator; 18 | 19 | public enum RevokePurchaseResponseValue { 20 | OK, 21 | FAIL_USER_INVALID, 22 | FAIL_INVALID_PURCHASE_TOKEN, 23 | FAIL_OTHER; 24 | 25 | @JsonCreator 26 | public static RevokePurchaseResponseValue fromJson(String text) { 27 | // ignore the case when deserializing 28 | return valueOf(text.toUpperCase()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v2/serialization/messages/SubscriptionActivateRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v2.serialization.messages; 16 | 17 | import com.amazon.dtasdk.base.InstantAccessOperationValue; 18 | import com.amazon.dtasdk.base.SubscriptionRequest; 19 | import com.fasterxml.jackson.databind.annotation.JsonSerialize; 20 | import org.apache.commons.lang.builder.ToStringBuilder; 21 | import org.apache.commons.lang.builder.ToStringStyle; 22 | 23 | /** 24 | * A request to activate a subscription for a specified user and product 25 | * This activate request is on the deprecation path, please do not use it. 26 | */ 27 | @Deprecated 28 | @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) 29 | public class SubscriptionActivateRequest extends SubscriptionRequest { 30 | 31 | protected String productId; 32 | protected String userId; 33 | protected Integer numberOfSubscriptionsInGroup; 34 | protected String subscriptionGroupId; 35 | 36 | @Override 37 | public SubscriptionActivateRequest setOperation(InstantAccessOperationValue operationValue) { 38 | this.operation = operationValue; 39 | return this; 40 | } 41 | 42 | public String getProductId() { 43 | return productId; 44 | } 45 | 46 | public SubscriptionActivateRequest setProductId(String productId) { 47 | this.productId = productId; 48 | return this; 49 | } 50 | 51 | @Override 52 | public SubscriptionActivateRequest setSubscriptionId(String subscriptionId) { 53 | this.subscriptionId = subscriptionId; 54 | return this; 55 | } 56 | 57 | public String getUserId() { 58 | return userId; 59 | } 60 | 61 | public SubscriptionActivateRequest setUserId(String userId) { 62 | this.userId = userId; 63 | return this; 64 | } 65 | 66 | public Integer getNumberOfSubscriptionsInGroup() { 67 | return numberOfSubscriptionsInGroup; 68 | } 69 | 70 | public SubscriptionActivateRequest setNumberOfSubscriptionsInGroup(Integer numberOfSubscriptionsInGroup) { 71 | this.numberOfSubscriptionsInGroup = numberOfSubscriptionsInGroup; 72 | return this; 73 | } 74 | 75 | public String getSubscriptionGroupId() { 76 | return subscriptionGroupId; 77 | } 78 | 79 | public SubscriptionActivateRequest setSubscriptionGroupId(String subscriptionGroupId) { 80 | this.subscriptionGroupId = subscriptionGroupId; 81 | return this; 82 | } 83 | 84 | @Override 85 | public boolean equals(Object o) { 86 | if (this == o) return true; 87 | if (!(o instanceof SubscriptionActivateRequest)) return false; 88 | if (!super.equals(o)) return false; 89 | 90 | final SubscriptionActivateRequest that = (SubscriptionActivateRequest) o; 91 | 92 | if (productId != null ? !productId.equals(that.productId) : that.productId != null) return false; 93 | if (userId != null ? !userId.equals(that.userId) : that.userId != null) return false; 94 | if (numberOfSubscriptionsInGroup != null ? !numberOfSubscriptionsInGroup.equals(that.numberOfSubscriptionsInGroup) : that.numberOfSubscriptionsInGroup != null) 95 | return false; 96 | if (subscriptionGroupId != null ? !subscriptionGroupId.equals(that.subscriptionGroupId) : that.subscriptionGroupId != null) 97 | return false; 98 | 99 | return true; 100 | } 101 | 102 | @Override 103 | public int hashCode() { 104 | int result = super.hashCode(); 105 | result = 31 * result + (productId != null ? productId.hashCode() : 0); 106 | result = 31 * result + (userId != null ? userId.hashCode() : 0); 107 | result = 31 * result + (numberOfSubscriptionsInGroup != null ? numberOfSubscriptionsInGroup.hashCode() : 0); 108 | result = 31 * result + (subscriptionGroupId != null ? subscriptionGroupId.hashCode() : 0); 109 | return result; 110 | } 111 | 112 | @Override 113 | public String toString() { 114 | return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) 115 | .append("operation", operation) 116 | .append("subscriptionId", subscriptionId) 117 | .append("productId", productId) 118 | .append("userId", userId) 119 | .append("numberOfSubscriptionsInGroup", numberOfSubscriptionsInGroup) 120 | .append("subscriptionGroupId", subscriptionGroupId) 121 | .toString(); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v2/serialization/messages/SubscriptionDeactivateRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v2.serialization.messages; 16 | 17 | import com.amazon.dtasdk.base.InstantAccessOperationValue; 18 | import com.amazon.dtasdk.base.SubscriptionPeriodValue; 19 | import com.amazon.dtasdk.base.SubscriptionReasonValue; 20 | import com.amazon.dtasdk.base.SubscriptionRequest; 21 | import com.fasterxml.jackson.databind.annotation.JsonSerialize; 22 | import org.apache.commons.lang.builder.ToStringBuilder; 23 | import org.apache.commons.lang.builder.ToStringStyle; 24 | 25 | /** 26 | * A request to deactivate a subscription. 27 | * Includes the reason for deactivation and the period in which it was deactivated. 28 | * This deactivate request is on the deprecation path, please do not use it. 29 | */ 30 | @Deprecated 31 | @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) 32 | public class SubscriptionDeactivateRequest extends SubscriptionRequest { 33 | 34 | protected SubscriptionReasonValue reason; 35 | protected SubscriptionPeriodValue period; 36 | 37 | @Override 38 | public SubscriptionDeactivateRequest setOperation(InstantAccessOperationValue operationValue) { 39 | this.operation = operationValue; 40 | return this; 41 | } 42 | 43 | public SubscriptionReasonValue getReason() { 44 | return reason; 45 | } 46 | 47 | public SubscriptionDeactivateRequest setReason(SubscriptionReasonValue reason) { 48 | this.reason = reason; 49 | return this; 50 | } 51 | 52 | public SubscriptionPeriodValue getPeriod() { 53 | return period; 54 | } 55 | 56 | public SubscriptionDeactivateRequest setPeriod(SubscriptionPeriodValue period) { 57 | this.period = period; 58 | return this; 59 | } 60 | 61 | @Override 62 | public SubscriptionDeactivateRequest setSubscriptionId(String subscriptionId) { 63 | this.subscriptionId = subscriptionId; 64 | return this; 65 | } 66 | 67 | @Override 68 | public boolean equals(Object o) { 69 | if (this == o) return true; 70 | if (o == null || getClass() != o.getClass()) return false; 71 | if (!super.equals(o)) return false; 72 | 73 | final SubscriptionDeactivateRequest that = (SubscriptionDeactivateRequest) o; 74 | 75 | if (period != that.period) return false; 76 | if (reason != that.reason) return false; 77 | 78 | return true; 79 | } 80 | 81 | @Override 82 | public int hashCode() { 83 | int result = super.hashCode(); 84 | result = 31 * result + (reason != null ? reason.hashCode() : 0); 85 | result = 31 * result + (period != null ? period.hashCode() : 0); 86 | return result; 87 | } 88 | 89 | @Override 90 | public String toString() { 91 | return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) 92 | .append("operation", operation) 93 | .append("subscriptionId", subscriptionId) 94 | .append("reason", reason) 95 | .append("period", period) 96 | .toString(); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v2/servlets/AccountLinkingServlet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v2.servlets; 16 | 17 | import com.amazon.dtasdk.v2.serialization.messages.GetUserIdSerializableRequest; 18 | import com.amazon.dtasdk.v2.serialization.messages.GetUserIdSerializableResponse; 19 | import com.amazon.dtasdk.base.InstantAccessOperationValue; 20 | import com.amazon.dtasdk.base.InstantAccessResponse; 21 | import com.amazon.dtasdk.serializer.SerializationException; 22 | 23 | /** 24 | *

25 | * This abstract servlet can be extended to implement the V2 Account Linking section of Instant Access API. 26 | *

27 | * 28 | *

29 | * When extending this servlet, you must implement the abstract method {@link #getUserId(GetUserIdSerializableRequest)}, 30 | * it is the method for returning a user id based on the parameters in order to link accounts. 31 | *

32 | * 33 | *

34 | * You must also implement the abstract method {@link #getCredentialStore()}. This method must provide a valid credential 35 | * store that will be used to verify the message authenticity. 36 | *

37 | * 38 | */ 39 | public abstract class AccountLinkingServlet extends InstantAccessServlet { 40 | 41 | /** 42 | * Process the request and returns the user id 43 | * 44 | * @param request 45 | * the request relative to the get user id operation 46 | * 47 | * @return a GetUserIdSerializableResponse object 48 | */ 49 | public abstract GetUserIdSerializableResponse getUserId(GetUserIdSerializableRequest request); 50 | 51 | @Override 52 | public InstantAccessResponse processOperation(InstantAccessOperationValue operation, String requestBody) 53 | throws SerializationException { 54 | 55 | GetUserIdSerializableResponse iaResponse; 56 | 57 | // process the request according to the operation 58 | switch (operation) { 59 | case GETUSERID: 60 | iaResponse = getUserId(serializer.decode(requestBody, GetUserIdSerializableRequest.class)); 61 | break; 62 | default: 63 | throw new IllegalArgumentException(String.format("Operation[%s] not supported by %s", operation.name(), 64 | this.getClass().getName())); 65 | } 66 | 67 | return iaResponse; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v2/servlets/InstantAccessServlet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v2.servlets; 16 | 17 | import com.amazon.dtasdk.base.InstantAccessRequest; 18 | import com.amazon.dtasdk.serializer.JacksonSerializer; 19 | import com.amazon.dtasdk.serializer.SerializationException; 20 | import com.amazon.dtasdk.signature.CredentialStore; 21 | import com.amazon.dtasdk.signature.Request; 22 | import com.amazon.dtasdk.signature.Signer; 23 | import com.amazon.dtasdk.signature.SigningException; 24 | import com.amazon.dtasdk.base.InstantAccessOperationValue; 25 | import com.amazon.dtasdk.base.InstantAccessResponse; 26 | import org.apache.commons.logging.Log; 27 | import org.apache.commons.logging.LogFactory; 28 | 29 | import javax.servlet.http.HttpServlet; 30 | import javax.servlet.http.HttpServletRequest; 31 | import javax.servlet.http.HttpServletResponse; 32 | import java.io.IOException; 33 | import java.nio.charset.Charset; 34 | 35 | /** 36 | *

37 | * This abstract servlet is extended by the {@link PurchaseServlet} and {@link AccountLinkingServlet} in order to 38 | * implement the Instant Access API. This class should not be used, use the aforementioned classes instead. 39 | *

40 | * 41 | */ 42 | public abstract class InstantAccessServlet extends HttpServlet { 43 | private static final Log log = LogFactory.getLog(InstantAccessServlet.class); 44 | private static final Charset CHARSET = Charset.forName("UTF-8"); 45 | 46 | private final Signer signer = new Signer(); 47 | 48 | protected final JacksonSerializer serializer = new JacksonSerializer(); 49 | 50 | /** 51 | * Returns the credential store 52 | * 53 | * @return a CredentialStore object with all the credentials 54 | */ 55 | public abstract CredentialStore getCredentialStore(); 56 | 57 | /** 58 | * Processes the request based on the operation 59 | * 60 | * @param operation 61 | * The operation being called 62 | * @param requestBody 63 | * The content of the message 64 | * @return a generic InstantAccessResponse containing the result of the operation 65 | * 66 | * @throws SerializationException 67 | * @throws IllegalArgumentException 68 | */ 69 | public abstract InstantAccessResponse processOperation(InstantAccessOperationValue operation, String requestBody) 70 | throws SerializationException; 71 | 72 | @Override 73 | public void doPost(HttpServletRequest request, HttpServletResponse response) { 74 | try { 75 | Request req = new Request(request); 76 | 77 | if (!signer.verify(req, getCredentialStore())) { 78 | throw new SigningException("Request validation failed."); 79 | } 80 | 81 | String requestBody = req.getBody(); 82 | 83 | // deserialize the content to a InstantAccessRequest object so we can check which operation is going 84 | // to be called 85 | InstantAccessRequest iaRequest = serializer.decode(requestBody, InstantAccessRequest.class); 86 | 87 | // process the request according to the operation 88 | InstantAccessResponse iaResponse = processOperation(iaRequest.getOperation(), requestBody); 89 | 90 | response.setStatus(HttpServletResponse.SC_OK); 91 | response.getOutputStream().write(serializer.encode(iaResponse).getBytes(CHARSET)); 92 | } catch (IOException e) { 93 | log.error("Unable to read the request.", e); 94 | response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); 95 | } catch (SigningException e) { 96 | log.error("Unable to verify the request against the credential store.", e); 97 | response.setStatus(HttpServletResponse.SC_FORBIDDEN); 98 | } catch (SerializationException e) { 99 | log.error("Serialization error.", e); 100 | response.setStatus(HttpServletResponse.SC_BAD_REQUEST); 101 | } catch (Exception e) { 102 | log.error("Unable to process the request.", e); 103 | response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v2/servlets/PurchaseServlet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v2.servlets; 16 | 17 | import com.amazon.dtasdk.base.InstantAccessOperationValue; 18 | import com.amazon.dtasdk.base.InstantAccessResponse; 19 | import com.amazon.dtasdk.base.SubscriptionResponse; 20 | import com.amazon.dtasdk.v2.serialization.messages.FulfillPurchaseRequest; 21 | import com.amazon.dtasdk.v2.serialization.messages.FulfillPurchaseResponse; 22 | import com.amazon.dtasdk.v2.serialization.messages.RevokePurchaseRequest; 23 | import com.amazon.dtasdk.v2.serialization.messages.RevokePurchaseResponse; 24 | import com.amazon.dtasdk.v2.serialization.messages.SubscriptionActivateRequest; 25 | import com.amazon.dtasdk.v2.serialization.messages.SubscriptionDeactivateRequest; 26 | import com.amazon.dtasdk.serializer.SerializationException; 27 | 28 | /** 29 | *

30 | * This abstract servlet can be extended to implement the V2 Purchase/Subscription section of Instant Access API. 31 | *

32 | * 33 | *

34 | * When extending this servlet, you must implement the abstract methods relative to the four operations present in the 35 | * API. {@link #fulfillPurchase(FulfillPurchaseRequest)} is the method responsible for fulfilling a purchase, {@link 36 | * #revokePurchase(RevokePurchaseRequest)} is the method responsible for revoking a purchase, {@link 37 | * #processSubscriptionActivate(SubscriptionActivateRequest)} is the method responsible for activating a subscription and 38 | * {@link #processSubscriptionDeactivate(SubscriptionDeactivateRequest)} is the method responsible for deactivating a 39 | * subscription 40 | *

41 | * 42 | *

43 | * You must also implement the abstract method {@link #getCredentialStore()}. This method must provide a valid credential 44 | * store that will be used to verify the message authenticity. 45 | *

46 | * 47 | */ 48 | public abstract class PurchaseServlet extends InstantAccessServlet { 49 | 50 | /** 51 | * Process the fulfill purchase request and return the response to whether or not the request succeeded. 52 | * 53 | * @param request 54 | * the request relative to the fulfill purchase 55 | * 56 | * @return a FulfillPurchaseResponse object 57 | */ 58 | public abstract FulfillPurchaseResponse fulfillPurchase(FulfillPurchaseRequest request); 59 | 60 | /** 61 | * Process the revoke purchase request and return the response to whether or not the request succeeded. 62 | * 63 | * @param request 64 | * the request relative to the revoke purchase 65 | * 66 | * @return a RevokePurchaseResponse object 67 | */ 68 | public abstract RevokePurchaseResponse revokePurchase(RevokePurchaseRequest request); 69 | 70 | /** 71 | * Process a subscription activation based on the request and returns the response to whether or not the request 72 | * succeeded. 73 | * 74 | * @param request 75 | * the request object with information about the subscription 76 | * 77 | * @return a SubscriptionResponse object 78 | */ 79 | public abstract SubscriptionResponse processSubscriptionActivate(SubscriptionActivateRequest request); 80 | 81 | /** 82 | * Process a subscription deactivation based on the request and returns the response to whether or not the request 83 | * succeeded. 84 | * 85 | * @param request 86 | * the request object with information about the subscription 87 | * 88 | * @return a SubscriptionResponse object 89 | */ 90 | public abstract SubscriptionResponse processSubscriptionDeactivate(SubscriptionDeactivateRequest request); 91 | 92 | @Override 93 | public InstantAccessResponse processOperation(InstantAccessOperationValue operation, String requestBody) 94 | throws SerializationException { 95 | 96 | InstantAccessResponse iaResponse; 97 | 98 | // process the request according to the operation 99 | switch (operation) { 100 | case PURCHASE: 101 | iaResponse = fulfillPurchase(serializer.decode(requestBody, FulfillPurchaseRequest.class)); 102 | break; 103 | case REVOKE: 104 | iaResponse = revokePurchase(serializer.decode(requestBody, RevokePurchaseRequest.class)); 105 | break; 106 | case SUBSCRIPTIONACTIVATE: 107 | iaResponse = processSubscriptionActivate(serializer.decode(requestBody, 108 | SubscriptionActivateRequest.class)); 109 | break; 110 | case SUBSCRIPTIONDEACTIVATE: 111 | iaResponse = processSubscriptionDeactivate(serializer.decode(requestBody, 112 | SubscriptionDeactivateRequest.class)); 113 | break; 114 | default: 115 | throw new IllegalArgumentException(String.format("Operation[%s] not supported by %s", operation.name(), 116 | this.getClass().getName())); 117 | } 118 | 119 | return iaResponse; 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v3/serialization/messages/FulfillPurchaseRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v3.serialization.messages; 16 | 17 | /** 18 | * Serializable FulfillPurchaseRequest object to pass to developer used to fulfill a purchase 19 | */ 20 | public class FulfillPurchaseRequest extends com.amazon.dtasdk.v2.serialization.messages.FulfillPurchaseRequest { 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v3/serialization/messages/FulfillPurchaseResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v3.serialization.messages; 16 | 17 | /** 18 | * Serilizable response from vendor used to fulfill a purchase 19 | */ 20 | public class FulfillPurchaseResponse extends com.amazon.dtasdk.v2.serialization.messages.FulfillPurchaseResponse { 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v3/serialization/messages/GetUserIdSerializableRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v3.serialization.messages; 16 | 17 | /** 18 | * Serializable GetUserId object to pass to developer 19 | */ 20 | public class GetUserIdSerializableRequest extends com.amazon.dtasdk.v2.serialization.messages.GetUserIdSerializableRequest { 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v3/serialization/messages/GetUserIdSerializableResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v3.serialization.messages; 16 | 17 | public class GetUserIdSerializableResponse extends com.amazon.dtasdk.v2.serialization.messages.GetUserIdSerializableResponse { 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v3/serialization/messages/RevokePurchaseRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v3.serialization.messages; 16 | 17 | /** 18 | * Serializable FulfillPurchaseRequest object to pass to developer used to revoke a purchase 19 | */ 20 | public class RevokePurchaseRequest extends com.amazon.dtasdk.v2.serialization.messages.RevokePurchaseRequest { 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v3/serialization/messages/RevokePurchaseResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v3.serialization.messages; 16 | 17 | /** 18 | * Serilizable response from vendor used to revoke a purchase 19 | */ 20 | public class RevokePurchaseResponse extends com.amazon.dtasdk.v2.serialization.messages.RevokePurchaseResponse { 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v3/serialization/messages/SubscriptionActivateRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v3.serialization.messages; 16 | 17 | import com.amazon.dtasdk.base.InstantAccessOperationValue; 18 | import com.amazon.dtasdk.base.SubscriptionRequest; 19 | import com.fasterxml.jackson.databind.annotation.JsonSerialize; 20 | import org.apache.commons.lang.builder.ToStringBuilder; 21 | import org.apache.commons.lang.builder.ToStringStyle; 22 | 23 | /** 24 | * A request to activate a subscription for a specified user and product 25 | */ 26 | @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) 27 | public class SubscriptionActivateRequest extends SubscriptionRequest { 28 | 29 | private Integer numberOfLicenses; 30 | 31 | @Override 32 | public SubscriptionActivateRequest setOperation(InstantAccessOperationValue operationValue) { 33 | this.operation = operationValue; 34 | return this; 35 | } 36 | 37 | public String getProductId() { 38 | return productId; 39 | } 40 | 41 | @Override 42 | public SubscriptionActivateRequest setSubscriptionId(String subscriptionId) { 43 | this.subscriptionId = subscriptionId; 44 | return this; 45 | } 46 | 47 | public Integer getNumberOfLicenses() { 48 | return numberOfLicenses; 49 | } 50 | 51 | public SubscriptionActivateRequest setNumberOfLicenses(Integer numberOfLicenses) { 52 | this.numberOfLicenses = numberOfLicenses; 53 | return this; 54 | } 55 | 56 | public SubscriptionActivateRequest setProductId(String productId) { 57 | this.productId = productId; 58 | return this; 59 | } 60 | 61 | public String getUserId() { 62 | return userId; 63 | } 64 | 65 | public SubscriptionActivateRequest setUserId(String userId) { 66 | this.userId = userId; 67 | return this; 68 | } 69 | 70 | @Override 71 | public boolean equals(Object o) { 72 | if (this == o) return true; 73 | if (!(o instanceof SubscriptionActivateRequest)) return false; 74 | if (!super.equals(o)) return false; 75 | 76 | final SubscriptionActivateRequest that = (SubscriptionActivateRequest) o; 77 | 78 | if (productId != null ? !productId.equals(that.productId) : that.productId != null) return false; 79 | if (userId != null ? !userId.equals(that.userId) : that.userId != null) return false; 80 | if (numberOfLicenses != null ? !numberOfLicenses.equals(that.numberOfLicenses) : that.numberOfLicenses != null) 81 | return false; 82 | 83 | return true; 84 | } 85 | 86 | @Override 87 | public int hashCode() { 88 | int result = super.hashCode(); 89 | result = 31 * result + (productId != null ? productId.hashCode() : 0); 90 | result = 31 * result + (userId != null ? userId.hashCode() : 0); 91 | result = 31 * result + (numberOfLicenses != null ? numberOfLicenses.hashCode() : 0); 92 | return result; 93 | } 94 | 95 | @Override 96 | public String toString() { 97 | return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) 98 | .append("operation", operation) 99 | .append("subscriptionId", subscriptionId) 100 | .append("productId", productId) 101 | .append("userId", userId) 102 | .append("numberOfLicenses", numberOfLicenses) 103 | .toString(); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v3/serialization/messages/SubscriptionActivateResponse.java: -------------------------------------------------------------------------------- 1 | package com.amazon.dtasdk.v3.serialization.messages; 2 | 3 | 4 | import com.amazon.dtasdk.base.SubscriptionResponse; 5 | import org.apache.commons.lang.builder.ToStringBuilder; 6 | import org.apache.commons.lang.builder.ToStringStyle; 7 | 8 | public class SubscriptionActivateResponse extends SubscriptionResponse { 9 | private Integer numberOfUnusedLicenses; 10 | private Integer numberOfUsedLicenses; 11 | private String managementURL; 12 | 13 | public Integer getNumberOfUnusedLicenses() { 14 | return numberOfUnusedLicenses; 15 | } 16 | 17 | public void setNumberOfUnusedLicenses(Integer numberOfUnusedLicenses) { 18 | this.numberOfUnusedLicenses = numberOfUnusedLicenses; 19 | } 20 | 21 | public Integer getNumberOfUsedLicenses() { 22 | return numberOfUsedLicenses; 23 | } 24 | 25 | public void setNumberOfUsedLicenses(Integer numberOfUsedLicenses) { 26 | this.numberOfUsedLicenses = numberOfUsedLicenses; 27 | } 28 | 29 | public String getManagementURL() { 30 | return managementURL; 31 | } 32 | 33 | public void setManagementURL(String managementUrl) { 34 | this.managementURL = managementUrl; 35 | } 36 | 37 | @Override 38 | public int hashCode() { 39 | final int prime = 31; 40 | int result = 1; 41 | result = prime * result + ((numberOfUnusedLicenses == null) ? 0 : numberOfUnusedLicenses.hashCode()); 42 | result = prime * result + ((numberOfUsedLicenses == null) ? 0 : numberOfUsedLicenses.hashCode()); 43 | result = prime * result + ((managementURL == null) ? 0 : managementURL.hashCode()); 44 | result = prime * result + ((response == null) ? 0 : response.hashCode()); 45 | return result; 46 | } 47 | 48 | @Override 49 | public boolean equals(Object obj) { 50 | if (this == obj) { 51 | return true; 52 | } 53 | if (obj == null) { 54 | return false; 55 | } 56 | if (getClass() != obj.getClass()) { 57 | return false; 58 | } 59 | final SubscriptionActivateResponse other = (SubscriptionActivateResponse) obj; 60 | if (numberOfUnusedLicenses == null) { 61 | if (other.numberOfUnusedLicenses != null) { 62 | return false; 63 | } 64 | } else if (!numberOfUnusedLicenses.equals(other.numberOfUnusedLicenses)) { 65 | return false; 66 | } 67 | 68 | if (numberOfUsedLicenses == null) { 69 | if (other.numberOfUsedLicenses != null) { 70 | return false; 71 | } 72 | } else if (!numberOfUsedLicenses.equals(other.numberOfUsedLicenses)) { 73 | return false; 74 | } 75 | 76 | if (managementURL == null) { 77 | if (other.managementURL != null) { 78 | return false; 79 | } 80 | } else if (!managementURL.equals(other.managementURL)) { 81 | return false; 82 | } 83 | 84 | if (response == null) { 85 | if (other.response != null) { 86 | return false; 87 | } 88 | } else if (!response.equals(other.response)) { 89 | return false; 90 | } 91 | return true; 92 | } 93 | 94 | @Override 95 | public String toString() { 96 | return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) 97 | .append("numberOfUnusedLicenses", numberOfUnusedLicenses) 98 | .append("numberOfUsedLicenses", numberOfUsedLicenses) 99 | .append("managementURL", managementURL) 100 | .append("response", response).toString(); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v3/serialization/messages/SubscriptionDeactivateRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v3.serialization.messages; 16 | 17 | import com.amazon.dtasdk.base.InstantAccessOperationValue; 18 | import com.amazon.dtasdk.base.SubscriptionPeriodValue; 19 | import com.amazon.dtasdk.base.SubscriptionReasonValue; 20 | import com.amazon.dtasdk.base.SubscriptionRequest; 21 | import com.fasterxml.jackson.databind.annotation.JsonSerialize; 22 | import org.apache.commons.lang.builder.ToStringBuilder; 23 | import org.apache.commons.lang.builder.ToStringStyle; 24 | 25 | /** 26 | * A request to deactivate a subscription. 27 | * Includes the reason for deactivation and the period in which it was deactivated. 28 | */ 29 | @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) 30 | public class SubscriptionDeactivateRequest extends SubscriptionRequest { 31 | 32 | protected SubscriptionReasonValue reason; 33 | protected SubscriptionPeriodValue period; 34 | 35 | @Override 36 | public SubscriptionDeactivateRequest setOperation(InstantAccessOperationValue operationValue) { 37 | this.operation = operationValue; 38 | return this; 39 | } 40 | 41 | public SubscriptionReasonValue getReason() { 42 | return reason; 43 | } 44 | 45 | public SubscriptionDeactivateRequest setReason(SubscriptionReasonValue reason) { 46 | this.reason = reason; 47 | return this; 48 | } 49 | 50 | public SubscriptionPeriodValue getPeriod() { 51 | return period; 52 | } 53 | 54 | public SubscriptionDeactivateRequest setPeriod(SubscriptionPeriodValue period) { 55 | this.period = period; 56 | return this; 57 | } 58 | 59 | @Override 60 | public SubscriptionDeactivateRequest setSubscriptionId(String subscriptionId) { 61 | this.subscriptionId = subscriptionId; 62 | return this; 63 | } 64 | 65 | @Override 66 | public boolean equals(Object o) { 67 | if (this == o) return true; 68 | if (o == null || getClass() != o.getClass()) return false; 69 | if (!super.equals(o)) return false; 70 | 71 | final SubscriptionDeactivateRequest that = (SubscriptionDeactivateRequest) o; 72 | 73 | if (period != that.period) return false; 74 | if (reason != that.reason) return false; 75 | 76 | return true; 77 | } 78 | 79 | @Override 80 | public int hashCode() { 81 | int result = super.hashCode(); 82 | result = 31 * result + (reason != null ? reason.hashCode() : 0); 83 | result = 31 * result + (period != null ? period.hashCode() : 0); 84 | return result; 85 | } 86 | 87 | @Override 88 | public String toString() { 89 | return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) 90 | .append("operation", operation) 91 | .append("subscriptionId", subscriptionId) 92 | .append("reason", reason) 93 | .append("period", period) 94 | .toString(); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v3/serialization/messages/SubscriptionDeactivateResponse.java: -------------------------------------------------------------------------------- 1 | package com.amazon.dtasdk.v3.serialization.messages; 2 | 3 | import com.amazon.dtasdk.base.SubscriptionResponse; 4 | 5 | public class SubscriptionDeactivateResponse extends SubscriptionResponse { 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v3/serialization/messages/SubscriptionGetRequest.java: -------------------------------------------------------------------------------- 1 | package com.amazon.dtasdk.v3.serialization.messages; 2 | 3 | import com.amazon.dtasdk.base.SubscriptionRequest; 4 | 5 | public class SubscriptionGetRequest extends SubscriptionRequest { 6 | public SubscriptionGetRequest setProductId(String productId) { 7 | this.productId = productId; 8 | return this; 9 | } 10 | 11 | public SubscriptionGetRequest setUserId(String userId) { 12 | this.userId = userId; 13 | return this; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v3/serialization/messages/SubscriptionGetResponse.java: -------------------------------------------------------------------------------- 1 | package com.amazon.dtasdk.v3.serialization.messages; 2 | 3 | import com.amazon.dtasdk.base.SubscriptionResponse; 4 | import org.apache.commons.lang.builder.ToStringBuilder; 5 | import org.apache.commons.lang.builder.ToStringStyle; 6 | 7 | public class SubscriptionGetResponse extends SubscriptionResponse { 8 | private Integer numberOfUnusedLicenses; 9 | private Integer numberOfUsedLicenses; 10 | private String managementURL; 11 | 12 | public Integer getNumberOfUnusedLicenses() { 13 | return numberOfUnusedLicenses; 14 | } 15 | 16 | public void setNumberOfUnusedLicenses(Integer numberOfUnusedLicenses) { 17 | this.numberOfUnusedLicenses = numberOfUnusedLicenses; 18 | } 19 | 20 | public Integer getNumberOfUsedLicenses() { 21 | return numberOfUsedLicenses; 22 | } 23 | 24 | public void setNumberOfUsedLicenses(Integer numberOfUsedLicenses) { 25 | this.numberOfUsedLicenses = numberOfUsedLicenses; 26 | } 27 | 28 | public String getManagementURL() { 29 | return managementURL; 30 | } 31 | 32 | public void setManagementURL(String managementUrl) { 33 | this.managementURL = managementUrl; 34 | } 35 | 36 | @Override 37 | public int hashCode() { 38 | final int prime = 31; 39 | int result = 1; 40 | result = prime * result + ((numberOfUnusedLicenses == null) ? 0 : numberOfUnusedLicenses.hashCode()); 41 | result = prime * result + ((numberOfUsedLicenses == null) ? 0 : numberOfUsedLicenses.hashCode()); 42 | result = prime * result + ((managementURL == null) ? 0 : managementURL.hashCode()); 43 | result = prime * result + ((response == null) ? 0 : response.hashCode()); 44 | return result; 45 | } 46 | 47 | @Override 48 | public boolean equals(Object obj) { 49 | if (this == obj) { 50 | return true; 51 | } 52 | if (obj == null) { 53 | return false; 54 | } 55 | if (getClass() != obj.getClass()) { 56 | return false; 57 | } 58 | final SubscriptionGetResponse other = (SubscriptionGetResponse) obj; 59 | if (numberOfUnusedLicenses == null) { 60 | if (other.numberOfUnusedLicenses != null) { 61 | return false; 62 | } 63 | } else if (!numberOfUnusedLicenses.equals(other.numberOfUnusedLicenses)) { 64 | return false; 65 | } 66 | 67 | if (numberOfUsedLicenses == null) { 68 | if (other.numberOfUsedLicenses != null) { 69 | return false; 70 | } 71 | } else if (!numberOfUsedLicenses.equals(other.numberOfUsedLicenses)) { 72 | return false; 73 | } 74 | 75 | if (managementURL == null) { 76 | if (other.managementURL != null) { 77 | return false; 78 | } 79 | } else if (!managementURL.equals(other.managementURL)) { 80 | return false; 81 | } 82 | 83 | if (response == null) { 84 | if (other.response != null) { 85 | return false; 86 | } 87 | } else if (!response.equals(other.response)) { 88 | return false; 89 | } 90 | return true; 91 | } 92 | 93 | @Override 94 | public String toString() { 95 | return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) 96 | .append("numberOfUnusedLicenses", numberOfUnusedLicenses) 97 | .append("numberOfUsedLicenses", numberOfUsedLicenses) 98 | .append("managementURL", managementURL) 99 | .append("response", response).toString(); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v3/serialization/messages/SubscriptionUpdateRequest.java: -------------------------------------------------------------------------------- 1 | package com.amazon.dtasdk.v3.serialization.messages; 2 | 3 | import com.amazon.dtasdk.base.InstantAccessOperationValue; 4 | import com.amazon.dtasdk.base.SubscriptionRequest; 5 | import org.apache.commons.lang.builder.ToStringBuilder; 6 | import org.apache.commons.lang.builder.ToStringStyle; 7 | 8 | public class SubscriptionUpdateRequest extends SubscriptionRequest { 9 | 10 | private Integer numberOfLicenses; 11 | private Boolean removeAllUnassignedLicenses; 12 | 13 | @Override 14 | public SubscriptionUpdateRequest setOperation(InstantAccessOperationValue operationValue) { 15 | this.operation = operationValue; 16 | return this; 17 | } 18 | 19 | public String getProductId() { 20 | return productId; 21 | } 22 | 23 | @Override 24 | public SubscriptionUpdateRequest setSubscriptionId(String subscriptionId) { 25 | this.subscriptionId = subscriptionId; 26 | return this; 27 | } 28 | 29 | public Integer getNumberOfLicenses() { 30 | return numberOfLicenses; 31 | } 32 | 33 | public SubscriptionUpdateRequest setNumberOfLicenses(Integer numberOfLicenses) { 34 | this.numberOfLicenses = numberOfLicenses; 35 | return this; 36 | } 37 | 38 | public Boolean getRemoveAllUnassignedLicenses() { 39 | return removeAllUnassignedLicenses; 40 | } 41 | 42 | public SubscriptionUpdateRequest setRemoveAllUnassignedLicenses(Boolean removeAllUnassignedLicenses) { 43 | this.removeAllUnassignedLicenses = removeAllUnassignedLicenses; 44 | return this; 45 | } 46 | 47 | public SubscriptionUpdateRequest setProductId(String productId) { 48 | this.productId = productId; 49 | return this; 50 | } 51 | 52 | public String getUserId() { 53 | return userId; 54 | } 55 | 56 | public SubscriptionUpdateRequest setUserId(String userId) { 57 | this.userId = userId; 58 | return this; 59 | } 60 | 61 | @Override 62 | public boolean equals(Object o) { 63 | if (this == o) return true; 64 | if (!(o instanceof SubscriptionUpdateRequest)) return false; 65 | if (!super.equals(o)) return false; 66 | 67 | final SubscriptionUpdateRequest that = (SubscriptionUpdateRequest) o; 68 | 69 | if (productId != null ? !productId.equals(that.productId) : that.productId != null) 70 | return false; 71 | if (userId != null ? !userId.equals(that.userId) : that.userId != null) 72 | return false; 73 | if (numberOfLicenses != null ? !numberOfLicenses.equals(that.numberOfLicenses) : that.numberOfLicenses != null) 74 | return false; 75 | if (removeAllUnassignedLicenses != null ? 76 | !removeAllUnassignedLicenses.equals(that.removeAllUnassignedLicenses) : 77 | that.removeAllUnassignedLicenses != null) 78 | return false; 79 | return true; 80 | } 81 | 82 | @Override 83 | public int hashCode() { 84 | int result = super.hashCode(); 85 | result = 31 * result + (productId != null ? productId.hashCode() : 0); 86 | result = 31 * result + (userId != null ? userId.hashCode() : 0); 87 | result = 31 * result + (numberOfLicenses != null ? numberOfLicenses.hashCode() : 0); 88 | result = 31 * result + (removeAllUnassignedLicenses != null ? removeAllUnassignedLicenses.hashCode() : 0); 89 | return result; 90 | } 91 | 92 | @Override 93 | public String toString() { 94 | return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) 95 | .append("operation", operation) 96 | .append("subscriptionId", subscriptionId) 97 | .append("productId", productId) 98 | .append("userId", userId) 99 | .append("numberOfLicenses", numberOfLicenses) 100 | .append("removeAllUnassignedLicenses", removeAllUnassignedLicenses) 101 | .toString(); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v3/serialization/messages/SubscriptionUpdateResponse.java: -------------------------------------------------------------------------------- 1 | package com.amazon.dtasdk.v3.serialization.messages; 2 | 3 | import com.amazon.dtasdk.base.SubscriptionResponse; 4 | import org.apache.commons.lang.builder.ToStringBuilder; 5 | import org.apache.commons.lang.builder.ToStringStyle; 6 | 7 | public class SubscriptionUpdateResponse extends SubscriptionResponse { 8 | private Integer numberOfUnusedLicenses; 9 | private Integer numberOfUsedLicenses; 10 | private String managementURL; 11 | 12 | public Integer getNumberOfUnusedLicenses() { 13 | return numberOfUnusedLicenses; 14 | } 15 | 16 | public void setNumberOfUnusedLicenses(Integer numberOfUnusedLicenses) { 17 | this.numberOfUnusedLicenses = numberOfUnusedLicenses; 18 | } 19 | 20 | public Integer getNumberOfUsedLicenses() { 21 | return numberOfUsedLicenses; 22 | } 23 | 24 | public void setNumberOfUsedLicenses(Integer numberOfUsedLicenses) { 25 | this.numberOfUsedLicenses = numberOfUsedLicenses; 26 | } 27 | 28 | public String getManagementURL() { 29 | return managementURL; 30 | } 31 | 32 | public void setManagementURL(String managementUrl) { 33 | this.managementURL = managementUrl; 34 | } 35 | 36 | @Override 37 | public int hashCode() { 38 | final int prime = 31; 39 | int result = 1; 40 | result = prime * result + ((numberOfUnusedLicenses == null) ? 0 : numberOfUnusedLicenses.hashCode()); 41 | result = prime * result + ((numberOfUsedLicenses == null) ? 0 : numberOfUsedLicenses.hashCode()); 42 | result = prime * result + ((managementURL == null) ? 0 : managementURL.hashCode()); 43 | result = prime * result + ((response == null) ? 0 : response.hashCode()); 44 | return result; 45 | } 46 | 47 | @Override 48 | public boolean equals(Object obj) { 49 | if (this == obj) { 50 | return true; 51 | } 52 | if (obj == null) { 53 | return false; 54 | } 55 | if (getClass() != obj.getClass()) { 56 | return false; 57 | } 58 | final SubscriptionUpdateResponse other = (SubscriptionUpdateResponse) obj; 59 | if (numberOfUnusedLicenses == null) { 60 | if (other.numberOfUnusedLicenses != null) { 61 | return false; 62 | } 63 | } else if (!numberOfUnusedLicenses.equals(other.numberOfUnusedLicenses)) { 64 | return false; 65 | } 66 | 67 | if (numberOfUsedLicenses == null) { 68 | if (other.numberOfUsedLicenses != null) { 69 | return false; 70 | } 71 | } else if (!numberOfUsedLicenses.equals(other.numberOfUsedLicenses)) { 72 | return false; 73 | } 74 | 75 | if (managementURL == null) { 76 | if (other.managementURL != null) { 77 | return false; 78 | } 79 | } else if (!managementURL.equals(other.managementURL)) { 80 | return false; 81 | } 82 | 83 | if (response == null) { 84 | if (other.response != null) { 85 | return false; 86 | } 87 | } else if (!response.equals(other.response)) { 88 | return false; 89 | } 90 | return true; 91 | } 92 | 93 | @Override 94 | public String toString() { 95 | return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) 96 | .append("numberOfUnusedLicenses", numberOfUnusedLicenses) 97 | .append("numberOfUsedLicenses", numberOfUsedLicenses) 98 | .append("managementURL", managementURL) 99 | .append("response", response).toString(); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v3/servlets/AccountLinkingServlet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v3.servlets; 16 | 17 | import com.amazon.dtasdk.v3.serialization.messages.GetUserIdSerializableRequest; 18 | import com.amazon.dtasdk.v3.serialization.messages.GetUserIdSerializableResponse; 19 | import com.amazon.dtasdk.base.InstantAccessOperationValue; 20 | import com.amazon.dtasdk.base.InstantAccessResponse; 21 | import com.amazon.dtasdk.serializer.SerializationException; 22 | 23 | /** 24 | *

25 | * This abstract servlet can be extended to implement the V3 Account Linking section of Instant Access API. 26 | *

27 | * 28 | *

29 | * When extending this servlet, you must implement the abstract method {@link #getUserId( GetUserIdSerializableRequest )}, 30 | * it is the method for returning a user id based on the parameters in order to link accounts. 31 | *

32 | * 33 | *

34 | * You must also implement the abstract method {@link #getCredentialStore()}. This method must provide a valid credential 35 | * store that will be used to verify the message authenticity. 36 | *

37 | * 38 | */ 39 | public abstract class AccountLinkingServlet extends InstantAccessServlet { 40 | 41 | /** 42 | * Process the request and returns the user id 43 | * 44 | * @param request 45 | * the request relative to the get user id operation 46 | * 47 | * @return a GetUserIdSerializableResponse object 48 | */ 49 | public abstract GetUserIdSerializableResponse getUserId(GetUserIdSerializableRequest request); 50 | 51 | @Override 52 | public InstantAccessResponse processOperation(InstantAccessOperationValue operation, String requestBody) 53 | throws SerializationException { 54 | 55 | GetUserIdSerializableResponse iaResponse; 56 | 57 | // process the request according to the operation 58 | switch (operation) { 59 | case GETUSERID: 60 | iaResponse = getUserId(serializer.decode(requestBody, GetUserIdSerializableRequest.class)); 61 | break; 62 | default: 63 | throw new IllegalArgumentException(String.format("Operation[%s] not supported by v3 %s", operation.name(), 64 | this.getClass().getName())); 65 | } 66 | 67 | return iaResponse; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v3/servlets/InstantAccessServlet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v3.servlets; 16 | 17 | import com.amazon.dtasdk.base.InstantAccessOperationValue; 18 | import com.amazon.dtasdk.base.InstantAccessRequest; 19 | import com.amazon.dtasdk.base.InstantAccessResponse; 20 | import com.amazon.dtasdk.serializer.JacksonSerializer; 21 | import com.amazon.dtasdk.serializer.SerializationException; 22 | import com.amazon.dtasdk.signature.CredentialStore; 23 | import com.amazon.dtasdk.signature.Request; 24 | import com.amazon.dtasdk.signature.Signer; 25 | import com.amazon.dtasdk.signature.SigningException; 26 | import org.apache.commons.logging.Log; 27 | import org.apache.commons.logging.LogFactory; 28 | 29 | import javax.servlet.http.HttpServlet; 30 | import javax.servlet.http.HttpServletRequest; 31 | import javax.servlet.http.HttpServletResponse; 32 | import java.io.IOException; 33 | import java.nio.charset.Charset; 34 | 35 | /** 36 | *

37 | * This abstract servlet is extended by the {@link PurchaseServlet} and {@link AccountLinkingServlet} in order to 38 | * implement the Instant Access API. This class should not be used, use the aforementioned classes instead. 39 | *

40 | * 41 | */ 42 | public abstract class InstantAccessServlet extends HttpServlet { 43 | private static final Log log = LogFactory.getLog(InstantAccessServlet.class); 44 | private static final Charset CHARSET = Charset.forName("UTF-8"); 45 | 46 | private final Signer signer = new Signer(); 47 | 48 | protected final JacksonSerializer serializer = new JacksonSerializer(); 49 | 50 | /** 51 | * Returns the credential store 52 | * 53 | * @return a CredentialStore object with all the credentials 54 | */ 55 | public abstract CredentialStore getCredentialStore(); 56 | 57 | /** 58 | * Processes the request based on the operation 59 | * 60 | * @param operation 61 | * The operation being called 62 | * @param requestBody 63 | * The content of the message 64 | * @return a generic InstantAccessResponse containing the result of the operation 65 | * 66 | * @throws SerializationException 67 | * @throws IllegalArgumentException 68 | */ 69 | public abstract InstantAccessResponse processOperation(InstantAccessOperationValue operation, String requestBody) 70 | throws SerializationException; 71 | 72 | @Override 73 | public void doPost(HttpServletRequest request, HttpServletResponse response) { 74 | try { 75 | Request req = new Request(request); 76 | 77 | if (!signer.verify(req, getCredentialStore())) { 78 | throw new SigningException("Request validation failed."); 79 | } 80 | 81 | String requestBody = req.getBody(); 82 | 83 | // deserialize the content to a InstantAccessRequest object so we can check which operation is going 84 | // to be called 85 | InstantAccessRequest iaRequest = serializer.decode(requestBody, InstantAccessRequest.class); 86 | 87 | // process the request according to the operation 88 | InstantAccessResponse iaResponse = processOperation(iaRequest.getOperation(), requestBody); 89 | 90 | response.setStatus(HttpServletResponse.SC_OK); 91 | response.getOutputStream().write(serializer.encode(iaResponse).getBytes(CHARSET)); 92 | } catch (IOException e) { 93 | log.error("Unable to read the v3 request.", e); 94 | response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); 95 | } catch (SigningException e) { 96 | log.error("Unable to verify the v3 request against the credential store.", e); 97 | response.setStatus(HttpServletResponse.SC_FORBIDDEN); 98 | } catch (SerializationException e) { 99 | log.error("v3 Serialization error.", e); 100 | response.setStatus(HttpServletResponse.SC_BAD_REQUEST); 101 | } catch (Exception e) { 102 | log.error("Unable to process the v3 request.", e); 103 | response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/com/amazon/dtasdk/v3/servlets/PurchaseServlet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v3.servlets; 16 | 17 | import com.amazon.dtasdk.base.InstantAccessOperationValue; 18 | import com.amazon.dtasdk.base.InstantAccessResponse; 19 | import com.amazon.dtasdk.base.SubscriptionResponse; 20 | import com.amazon.dtasdk.serializer.SerializationException; 21 | import com.amazon.dtasdk.v3.serialization.messages.*; 22 | 23 | /** 24 | *

25 | * This abstract servlet can be extended to implement the V3 Purchase/Subscription section of Instant Access API. 26 | *

27 | *

28 | *

29 | * When extending this servlet, you must implement the abstract methods relative to the four operations present in the 30 | * API. {@link #fulfillPurchase( FulfillPurchaseRequest )} is the method responsible for fulfilling a purchase, {@link 31 | * #revokePurchase( RevokePurchaseRequest )} is the method responsible for revoking a purchase, {@link 32 | * #processSubscriptionActivate( SubscriptionActivateRequest )} is the method responsible for activating a subscription, 33 | * {@link #processSubscriptionDeactivate( SubscriptionDeactivateRequest )} is the method responsible for deactivating a 34 | * subscription, {@link #processSubscriptionUpdate( SubscriptionUpdateRequest )} is the method responsible for updating a 35 | * subscription and {@link #processSubscriptionGet( SubscriptionGetRequest )} is the method responsible for getting a 36 | * subscription 37 | *

38 | *

39 | *

40 | * You must also implement the abstract method {@link #getCredentialStore()}. This method must provide a valid credential 41 | * store that will be used to verify the message authenticity. 42 | *

43 | */ 44 | public abstract class PurchaseServlet extends InstantAccessServlet { 45 | 46 | /** 47 | * Process the fulfill purchase request and return the response to whether or not the request succeeded. 48 | * 49 | * @param request the request relative to the fulfill purchase 50 | * @return a FulfillPurchaseResponse object 51 | */ 52 | public abstract FulfillPurchaseResponse fulfillPurchase(FulfillPurchaseRequest request); 53 | 54 | /** 55 | * Process the revoke purchase request and return the response to whether or not the request succeeded. 56 | * 57 | * @param request the request relative to the revoke purchase 58 | * @return a RevokePurchaseResponse object 59 | */ 60 | public abstract RevokePurchaseResponse revokePurchase(RevokePurchaseRequest request); 61 | 62 | /** 63 | * Process a subscription activation based on the request and returns the response to whether or not the request 64 | * succeeded. 65 | * 66 | * @param request the request object with information about the subscription 67 | * @return a SubscriptionResponse object 68 | */ 69 | public abstract SubscriptionResponse processSubscriptionActivate(SubscriptionActivateRequest request); 70 | 71 | /** 72 | * Process a subscription deactivation based on the request and returns the response to whether or not the request 73 | * succeeded. 74 | * 75 | * @param request the request object with information about the subscription 76 | * @return a SubscriptionResponse object 77 | */ 78 | public abstract SubscriptionResponse processSubscriptionDeactivate(SubscriptionDeactivateRequest request); 79 | 80 | 81 | /** 82 | * Process a subscription get based on the request and returns the response to whether or not the request 83 | * succeeded. 84 | * 85 | * @param request the request object with information about the subscription 86 | * @return a SubscriptionGetResponse object 87 | */ 88 | public abstract SubscriptionGetResponse processSubscriptionGet(SubscriptionGetRequest request); 89 | 90 | /** 91 | * Process a subscription update based on the request and returns the response to whether or not the request 92 | * succeeded. 93 | * 94 | * @param request the request object with information about the subscription 95 | * @return a SubscriptionResponse object 96 | */ 97 | public abstract SubscriptionResponse processSubscriptionUpdate(SubscriptionUpdateRequest request); 98 | 99 | @Override 100 | public InstantAccessResponse processOperation(InstantAccessOperationValue operation, String requestBody) 101 | throws SerializationException { 102 | 103 | InstantAccessResponse iaResponse; 104 | 105 | // process the request according to the operation 106 | switch (operation) { 107 | case PURCHASE: 108 | iaResponse = fulfillPurchase(serializer.decode(requestBody, FulfillPurchaseRequest.class)); 109 | break; 110 | case REVOKE: 111 | iaResponse = revokePurchase(serializer.decode(requestBody, RevokePurchaseRequest.class)); 112 | break; 113 | case SUBSCRIPTIONGET: 114 | iaResponse = processSubscriptionGet(serializer.decode(requestBody, SubscriptionGetRequest.class)); 115 | break; 116 | case SUBSCRIPTIONACTIVATE: 117 | iaResponse = processSubscriptionActivate(serializer.decode(requestBody, 118 | SubscriptionActivateRequest.class)); 119 | break; 120 | case SUBSCRIPTIONDEACTIVATE: 121 | iaResponse = processSubscriptionDeactivate(serializer.decode(requestBody, 122 | SubscriptionDeactivateRequest.class)); 123 | break; 124 | case SUBSCRIPTIONUPDATE: 125 | iaResponse = processSubscriptionUpdate(serializer.decode(requestBody, SubscriptionUpdateRequest.class)); 126 | break; 127 | default: 128 | throw new IllegalArgumentException(String.format("Operation[%s] not supported by v3 %s", operation.name(), 129 | this.getClass().getName())); 130 | } 131 | 132 | return iaResponse; 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/main/java/examples/servlet/AccountLinkingServletImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package examples.servlet; 17 | 18 | import com.amazon.dtasdk.signature.CredentialStore; 19 | import com.amazon.dtasdk.v2.serialization.messages.GetUserIdSerializableResponseValue; 20 | import com.amazon.dtasdk.v3.serialization.messages.GetUserIdSerializableRequest; 21 | import com.amazon.dtasdk.v3.serialization.messages.GetUserIdSerializableResponse; 22 | import com.amazon.dtasdk.v3.servlets.AccountLinkingServlet; 23 | import org.apache.commons.logging.Log; 24 | import org.apache.commons.logging.LogFactory; 25 | 26 | /** 27 | * Servlet class that listens to the account linking requests 28 | */ 29 | public class AccountLinkingServletImpl extends AccountLinkingServlet { 30 | 31 | private static final Log log = LogFactory.getLog(AccountLinkingServletImpl.class); 32 | 33 | @Override 34 | public CredentialStore getCredentialStore() { 35 | CredentialStore store = new CredentialStore(); 36 | 37 | /** 38 | * Add your public and private keys to the CredentialStore 39 | */ 40 | 41 | return store; 42 | } 43 | 44 | @Override 45 | public GetUserIdSerializableResponse getUserId(GetUserIdSerializableRequest request) { 46 | log.info(String.format("Started getUserId with request[%s]", request)); 47 | 48 | GetUserIdSerializableResponse response = new GetUserIdSerializableResponse(); 49 | 50 | try { 51 | /** 52 | * Retrieve userId and set it in the response object 53 | * response.setUserId(service.getUserId(request)); 54 | */ 55 | 56 | response.setResponse(GetUserIdSerializableResponseValue.OK); 57 | } catch (Exception e) { 58 | log.error(String.format("Error while processing getUserId[%s]", request), e); 59 | response.setResponse(GetUserIdSerializableResponseValue.FAIL_ACCOUNT_INVALID); 60 | } 61 | 62 | log.info(String.format("Finished getUserId with response[%s]", response)); 63 | 64 | return response; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/examples/servlet/PurchaseServletImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package examples.servlet; 17 | 18 | import com.amazon.dtasdk.base.SubscriptionResponse; 19 | import com.amazon.dtasdk.base.SubscriptionResponseValue; 20 | import com.amazon.dtasdk.signature.CredentialStore; 21 | import com.amazon.dtasdk.v2.serialization.messages.FulfillPurchaseResponseValue; 22 | import com.amazon.dtasdk.v2.serialization.messages.RevokePurchaseResponseValue; 23 | import com.amazon.dtasdk.v3.serialization.messages.FulfillPurchaseRequest; 24 | import com.amazon.dtasdk.v3.serialization.messages.FulfillPurchaseResponse; 25 | import com.amazon.dtasdk.v3.serialization.messages.RevokePurchaseRequest; 26 | import com.amazon.dtasdk.v3.serialization.messages.RevokePurchaseResponse; 27 | import com.amazon.dtasdk.v3.serialization.messages.SubscriptionActivateRequest; 28 | import com.amazon.dtasdk.v3.serialization.messages.SubscriptionDeactivateRequest; 29 | import com.amazon.dtasdk.v3.serialization.messages.SubscriptionGetRequest; 30 | import com.amazon.dtasdk.v3.serialization.messages.SubscriptionGetResponse; 31 | import com.amazon.dtasdk.v3.serialization.messages.SubscriptionUpdateRequest; 32 | import com.amazon.dtasdk.v3.servlets.PurchaseServlet; 33 | import org.apache.commons.logging.Log; 34 | import org.apache.commons.logging.LogFactory; 35 | 36 | 37 | /** 38 | * Servlet class that listens to the purchases/subscriptions requests 39 | */ 40 | public class PurchaseServletImpl extends PurchaseServlet { 41 | private static final Log log = LogFactory.getLog(PurchaseServletImpl.class); 42 | 43 | @Override 44 | public CredentialStore getCredentialStore() { 45 | CredentialStore store = new CredentialStore(); 46 | 47 | /** 48 | * Add your public and private keys to the CredentialStore 49 | */ 50 | 51 | return store; 52 | } 53 | 54 | @Override 55 | public FulfillPurchaseResponse fulfillPurchase(FulfillPurchaseRequest request) { 56 | log.info(String.format("Started fulfillPurchase with request[%s]", request)); 57 | 58 | FulfillPurchaseResponse response = new FulfillPurchaseResponse(); 59 | 60 | try { 61 | /** 62 | * Add logic to fulfill a purchase 63 | */ 64 | response.setResponse(FulfillPurchaseResponseValue.OK); 65 | } catch (Exception e) { 66 | log.error(String.format("Error while processing fulfillPurchase[%s]", request), e); 67 | response.setResponse(FulfillPurchaseResponseValue.FAIL_OTHER); 68 | } 69 | 70 | log.info(String.format("Finished fulfillPurchase with response[%s]", response)); 71 | 72 | return response; 73 | } 74 | 75 | @Override 76 | public RevokePurchaseResponse revokePurchase(RevokePurchaseRequest request) { 77 | log.info(String.format("Started revokePurchase with request[%s]", request)); 78 | 79 | RevokePurchaseResponse response = new RevokePurchaseResponse(); 80 | 81 | try { 82 | /** 83 | * Add logic to revoke a purchase 84 | */ 85 | response.setResponse(RevokePurchaseResponseValue.OK); 86 | } catch (Exception e) { 87 | log.error(String.format("Error while processing revokePurchase[%s]", request), e); 88 | response.setResponse(RevokePurchaseResponseValue.FAIL_OTHER); 89 | } 90 | 91 | log.info(String.format("Finished revokePurchase with response[%s]", response)); 92 | 93 | return response; 94 | } 95 | 96 | @Override 97 | public SubscriptionResponse processSubscriptionActivate(SubscriptionActivateRequest request) { 98 | log.info(String.format("Started processSubscriptionActivate with request[%s]", request)); 99 | 100 | SubscriptionResponse response = new SubscriptionResponse(); 101 | 102 | try { 103 | /** 104 | * Add logic to activate a subscription 105 | */ 106 | response.setResponse(SubscriptionResponseValue.OK); 107 | } catch (Exception e) { 108 | log.error(String.format("Error while processing processSubscriptionActivate[%s]", request), e); 109 | response.setResponse(SubscriptionResponseValue.FAIL_OTHER); 110 | } 111 | 112 | log.info(String.format("Finished processSubscriptionActivate with response[%s]", response)); 113 | 114 | return response; 115 | } 116 | 117 | @Override 118 | public SubscriptionResponse processSubscriptionDeactivate(SubscriptionDeactivateRequest request) { 119 | log.info(String.format("Started processSubscriptionDeactivate with request[%s]", request)); 120 | 121 | SubscriptionResponse response = new SubscriptionResponse(); 122 | 123 | try { 124 | /** 125 | * Add logic to deactivate a subscription 126 | */ 127 | response.setResponse(SubscriptionResponseValue.OK); 128 | } catch (Exception e) { 129 | log.error(String.format("Error while processing processSubscriptionDeactivate[%s]", request), e); 130 | response.setResponse(SubscriptionResponseValue.FAIL_OTHER); 131 | } 132 | 133 | log.info(String.format("Finished processSubscriptionDeactivate with response[%s]", response)); 134 | 135 | return response; 136 | } 137 | 138 | @Override 139 | public SubscriptionGetResponse processSubscriptionGet(SubscriptionGetRequest request) { 140 | log.info(String.format("Started processSubscriptionGet with request[%s]", request)); 141 | 142 | SubscriptionGetResponse response = new SubscriptionGetResponse(); 143 | 144 | try { 145 | /** 146 | * Add logic to get a subscription 147 | */ 148 | response.setResponse(SubscriptionResponseValue.OK); 149 | } catch (Exception e) { 150 | log.error(String.format("Error while processing processSubscriptionGet[%s]", request), e); 151 | response.setResponse(SubscriptionResponseValue.FAIL_OTHER); 152 | } 153 | 154 | log.info(String.format("Finished processSubscriptionGet with response[%s]", response)); 155 | 156 | return response; 157 | } 158 | 159 | @Override 160 | public SubscriptionResponse processSubscriptionUpdate(SubscriptionUpdateRequest request) { 161 | log.info(String.format("Started processSubscriptionUpdate with request[%s]", request)); 162 | 163 | SubscriptionResponse response = new SubscriptionResponse(); 164 | 165 | try { 166 | /** 167 | * Add logic to update a subscription 168 | */ 169 | response.setResponse(SubscriptionResponseValue.OK); 170 | } catch (Exception e) { 171 | log.error(String.format("Error while processing processSubscriptionUpdate[%s]", request), e); 172 | response.setResponse(SubscriptionResponseValue.FAIL_OTHER); 173 | } 174 | 175 | log.info(String.format("Finished processSubscriptionUpdate with response[%s]", response)); 176 | 177 | return response; 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /src/test/java/com/amazon/dtasdk/connection/SignatureVerificationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.connection; 16 | 17 | import com.amazon.dtasdk.signature.Credential; 18 | import com.amazon.dtasdk.signature.Request; 19 | import com.amazon.dtasdk.signature.Signer; 20 | import com.amazon.dtasdk.signature.SigningException; 21 | import org.apache.commons.httpclient.HttpClient; 22 | import org.apache.commons.httpclient.HttpMethod; 23 | import org.apache.commons.httpclient.methods.GetMethod; 24 | import org.apache.commons.httpclient.methods.PostMethod; 25 | import org.eclipse.jetty.server.handler.AbstractHandler; 26 | import org.junit.AfterClass; 27 | import org.junit.Before; 28 | import org.junit.BeforeClass; 29 | import org.junit.Test; 30 | 31 | import javax.servlet.ServletException; 32 | import javax.servlet.http.HttpServletRequest; 33 | import javax.servlet.http.HttpServletResponse; 34 | import java.io.IOException; 35 | import java.security.KeyManagementException; 36 | import java.security.NoSuchAlgorithmException; 37 | 38 | import static org.junit.Assert.assertEquals; 39 | 40 | @Deprecated 41 | public class SignatureVerificationTest { 42 | 43 | private static MockHandler handler; 44 | private static TestServer server; 45 | private static HttpClient httpClient; 46 | private HttpClient client; 47 | private Signer signer; 48 | 49 | static class MockHandler extends AbstractHandler { 50 | 51 | private Credential credential; 52 | private Signer signer = new Signer(); 53 | private Exception exception; 54 | 55 | @Override 56 | public void handle(String s, org.eclipse.jetty.server.Request jettyRequest, 57 | HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException, 58 | ServletException { 59 | Request request = new Request(httpServletRequest); 60 | 61 | try { 62 | if (!signer.verify(request, this.credential)) { 63 | httpServletResponse.setStatus(403); 64 | jettyRequest.setHandled(true); 65 | return; 66 | } 67 | } catch (SigningException e) { 68 | this.exception = e; 69 | throw new IOException(e); 70 | } 71 | 72 | httpServletResponse.setStatus(200); 73 | httpServletResponse.getWriter().write("success"); 74 | jettyRequest.setHandled(true); 75 | } 76 | 77 | public void setCredential(Credential credential) { 78 | this.credential = credential; 79 | } 80 | 81 | public void clear() { 82 | exception = null; 83 | } 84 | 85 | public Exception getException() { 86 | return exception; 87 | } 88 | } 89 | 90 | @BeforeClass 91 | public static void startServer() throws Exception { 92 | handler = new MockHandler(); 93 | server = new TestServer(handler).start(); 94 | } 95 | 96 | @AfterClass 97 | public static void stopServer() throws Exception { 98 | server.stop(); 99 | } 100 | 101 | private String serverUrl() { 102 | return "http://localhost:" + server.getPort(); 103 | } 104 | 105 | private void setDefaultHeaders(Request request) { 106 | request.setHeader("x-amz-request-id", "0A49CE4060975EAC"); 107 | request.setHeader("x-amz-customer-id", "ABCDCUSTID"); 108 | request.setHeader("x-amz-dta-version", "1"); 109 | } 110 | 111 | private void copyHeaders(Request request, HttpMethod method) { 112 | for (String headerName : request.getHeaderNames()) { 113 | method.setRequestHeader(headerName, request.getHeader(headerName)); 114 | } 115 | } 116 | 117 | @Before 118 | public void before() throws KeyManagementException, NoSuchAlgorithmException { 119 | client = new HttpClient(); 120 | signer = new Signer(); 121 | } 122 | 123 | @Test 124 | public void roundTripServer_withBareUrl() throws Exception { 125 | Credential credential = new Credential("SECRETKEY", "KEYID"); 126 | handler.setCredential(credential); 127 | 128 | Request request = new Request(serverUrl(), Request.Method.GET, ""); 129 | setDefaultHeaders(request); 130 | signer.sign(request, credential); 131 | 132 | HttpMethod method = new GetMethod(request.getUrl()); 133 | copyHeaders(request, method); 134 | 135 | assertEquals(200, client.executeMethod(method)); 136 | } 137 | 138 | @Test 139 | public void roundTrip_withPath() throws Exception { 140 | Credential credential = new Credential("SECRETKEY", "KEYID"); 141 | handler.setCredential(credential); 142 | 143 | Request request = new Request(serverUrl() + "/path/to/servlet", Request.Method.POST, ""); 144 | setDefaultHeaders(request); 145 | request.setBody("{\"json\": \"value\"}"); 146 | signer.sign(request, credential); 147 | 148 | PostMethod method = new PostMethod(request.getUrl()); 149 | copyHeaders(request, method); 150 | method.setRequestBody(request.getBody()); 151 | 152 | assertEquals(200, client.executeMethod(method)); 153 | } 154 | 155 | @Test 156 | public void roundTrip_NoAuth() throws Exception { 157 | Credential credential = new Credential("SECRETKEY", "KEYID"); 158 | handler.setCredential(credential); 159 | 160 | PostMethod method = new PostMethod(serverUrl() + "/path/to/servlet"); 161 | method.setRequestBody("{\"json\": \"value\"}"); 162 | 163 | assertEquals(403, client.executeMethod(method)); 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /src/test/java/com/amazon/dtasdk/connection/TestServer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.connection; 16 | 17 | import org.eclipse.jetty.server.Server; 18 | import org.eclipse.jetty.server.handler.AbstractHandler; 19 | import org.junit.Ignore; 20 | 21 | /** 22 | * This is a wrapper for unit tests that brings up a real Jetty HTTP server with a handler. 23 | */ 24 | @Deprecated 25 | @Ignore 26 | public class TestServer { 27 | private final Server server; 28 | private final int port; 29 | 30 | public TestServer(AbstractHandler handler) { 31 | port = 58901 + (int) (Math.random() * 6000); 32 | server = new Server(port); 33 | server.setHandler(handler); 34 | } 35 | 36 | public int getPort() { 37 | return port; 38 | } 39 | 40 | public TestServer start() throws Exception { 41 | server.start(); 42 | return this; 43 | } 44 | 45 | public void stop() throws Exception { 46 | server.stop(); 47 | server.join(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/com/amazon/dtasdk/serializer/JacksonSerializerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.serializer; 16 | 17 | import com.amazon.dtasdk.serializer.TestJson.Name; 18 | import com.fasterxml.jackson.databind.JsonNode; 19 | import com.fasterxml.jackson.databind.ObjectMapper; 20 | import junit.framework.Assert; 21 | import org.junit.Test; 22 | 23 | import java.util.LinkedList; 24 | import java.util.List; 25 | 26 | public class JacksonSerializerTest { 27 | private static final String jsonString = "{\"value\":\"theValue\"," 28 | + "\"names\":[{\"first\":\"Joe\",\"last\":\"Sixpack\"}," + "{\"first\":\"Bill\",\"last\":\"Fourpack\"}]}"; 29 | 30 | private static final JacksonSerializer serializer = new JacksonSerializer(); 31 | 32 | @Test 33 | public void testDecode() throws Exception { 34 | TestJson dtgObject = serializer.decode(jsonString, TestJson.class); 35 | 36 | Assert.assertEquals(TestJson.class, dtgObject.getClass()); 37 | TestJson testJson = dtgObject; 38 | Assert.assertEquals("Joe", testJson.getNames().get(0).getFirst()); 39 | Assert.assertEquals("Sixpack", testJson.getNames().get(0).getLast()); 40 | Assert.assertEquals("Bill", testJson.getNames().get(1).getFirst()); 41 | Assert.assertEquals("Fourpack", testJson.getNames().get(1).getLast()); 42 | Assert.assertEquals("theValue", testJson.getValue()); 43 | } 44 | 45 | @Test 46 | public void testEncode() throws Exception { 47 | String encodedJson = encodeObject(getTestObject()); 48 | 49 | ObjectMapper mapper = new ObjectMapper(); 50 | JsonNode expected = mapper.readTree(jsonString); 51 | JsonNode actual = mapper.readTree(encodedJson); 52 | 53 | Assert.assertEquals(expected, actual); 54 | } 55 | 56 | private TestJson getTestObject() throws Exception { 57 | TestJson testJson = new TestJson(); 58 | Name name = new Name(); 59 | name.setFirst("Joe"); 60 | name.setLast("Sixpack"); 61 | 62 | Name name2 = new Name(); 63 | name2.setFirst("Bill"); 64 | name2.setLast("Fourpack"); 65 | 66 | List names = new LinkedList(); 67 | names.add(name); 68 | names.add(name2); 69 | 70 | testJson.setNames(names); 71 | testJson.setValue("theValue"); 72 | 73 | return testJson; 74 | } 75 | 76 | private String encodeObject(TestJson testJson) throws SerializationException { 77 | return serializer.encode(testJson); 78 | } 79 | 80 | @Test 81 | public void testEncodeAndDecode() throws Exception { 82 | TestJson testObject = getTestObject(); 83 | String json = encodeObject(testObject); 84 | 85 | Object decoded = serializer.decode(json, TestJson.class); 86 | Assert.assertEquals(testObject, decoded); 87 | } 88 | 89 | @Test(expected = SerializationException.class) 90 | public void badJsonDecodeTest() throws Exception { 91 | String badJson = "{fjan"; 92 | 93 | serializer.decode(badJson, TestJson.class); 94 | } 95 | 96 | @Test(expected = SerializationException.class) 97 | public void testNonExistentClass() throws Exception { 98 | String badJson = "{\"Value\":\"theValue\"," 99 | + "\"Names\":[{\"First\":\"Joe\",\"Last\":\"Sixpack\"},{\"First\":\"Bill\",\"Last\":\"Fourpack\"}]," 100 | + "\"Type\":\"NonExistent\"}"; 101 | 102 | serializer.decode(badJson, TestJson.class); 103 | } 104 | 105 | @Test(expected = SerializationException.class) 106 | public void testJsonDoesntMapToClass() throws Exception { 107 | String badJson = "{\"Names\":[{\"First\":\"Joe\",\"Last\":\"Sixpack\"},{\"First\":\"Bill\",\"Last\":\"Fourpack\"}]," 108 | + "\"Type\":\"NonExistent\"}"; 109 | 110 | serializer.decode(badJson, TestJson.class); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/test/java/com/amazon/dtasdk/serializer/TestJson.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.serializer; 16 | 17 | import java.util.List; 18 | 19 | import com.fasterxml.jackson.annotation.JsonIgnore; 20 | import org.junit.Ignore; 21 | 22 | @Ignore 23 | public class TestJson { 24 | private String testValue = "unset"; 25 | 26 | public static class Name { 27 | private String first, last; 28 | 29 | public String getFirst() { 30 | return first; 31 | } 32 | 33 | public String getLast() { 34 | return last; 35 | } 36 | 37 | public void setFirst(String first) { 38 | this.first = first; 39 | } 40 | 41 | public void setLast(String last) { 42 | this.last = last; 43 | } 44 | 45 | @Override 46 | public int hashCode() { 47 | final int prime = 31; 48 | int result = 1; 49 | result = prime * result + ((first == null) ? 0 : first.hashCode()); 50 | result = prime * result + ((last == null) ? 0 : last.hashCode()); 51 | return result; 52 | } 53 | 54 | @Override 55 | public boolean equals(Object obj) { 56 | if (this == obj) { 57 | return true; 58 | } 59 | if (obj == null) { 60 | return false; 61 | } 62 | if (getClass() != obj.getClass()) { 63 | return false; 64 | } 65 | Name other = (Name) obj; 66 | if (first == null) { 67 | if (other.first != null) { 68 | return false; 69 | } 70 | } else if (!first.equals(other.first)) { 71 | return false; 72 | } 73 | if (last == null) { 74 | if (other.last != null) { 75 | return false; 76 | } 77 | } else if (!last.equals(other.last)) { 78 | return false; 79 | } 80 | return true; 81 | } 82 | } 83 | 84 | private List names; 85 | private String value; 86 | 87 | public List getNames() { 88 | return names; 89 | } 90 | 91 | public void setNames(List names) { 92 | this.names = names; 93 | } 94 | 95 | public String getValue() { 96 | return value; 97 | } 98 | 99 | public void setValue(String value) { 100 | this.value = value; 101 | } 102 | 103 | @JsonIgnore 104 | public void setTestValue(String testValue) { 105 | this.testValue = testValue; 106 | } 107 | 108 | @JsonIgnore 109 | public String getTestValue() { 110 | return testValue; 111 | } 112 | 113 | @Override 114 | public int hashCode() { 115 | final int prime = 31; 116 | int result = 1; 117 | result = prime * result + ((names == null) ? 0 : names.hashCode()); 118 | result = prime * result + ((testValue == null) ? 0 : testValue.hashCode()); 119 | result = prime * result + ((value == null) ? 0 : value.hashCode()); 120 | return result; 121 | } 122 | 123 | @Override 124 | public boolean equals(Object obj) { 125 | if (this == obj) { 126 | return true; 127 | } 128 | if (obj == null) { 129 | return false; 130 | } 131 | if (getClass() != obj.getClass()) { 132 | return false; 133 | } 134 | TestJson other = (TestJson) obj; 135 | if (names == null) { 136 | if (other.names != null) { 137 | return false; 138 | } 139 | } else if (names.size() != other.names.size()) { 140 | return false; 141 | } else { 142 | for (int i = 0; i < names.size(); i++) { 143 | if (!names.get(i).equals(other.names.get(i))) { 144 | return false; 145 | } 146 | } 147 | } 148 | if (testValue == null) { 149 | if (other.testValue != null) { 150 | return false; 151 | } 152 | } else if (!testValue.equals(other.testValue)) { 153 | return false; 154 | } 155 | if (value == null) { 156 | if (other.value != null) { 157 | return false; 158 | } 159 | } else if (!value.equals(other.value)) { 160 | return false; 161 | } 162 | return true; 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /src/test/java/com/amazon/dtasdk/signature/AuthenticationHeaderParserTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.signature; 16 | 17 | import static org.junit.Assert.assertEquals; 18 | import static org.junit.Assert.assertNull; 19 | 20 | import org.junit.Test; 21 | 22 | public class AuthenticationHeaderParserTest { 23 | @Test 24 | public void singleHeaderAuthentication() { 25 | String value = "DTA1-HMAC-SHA256 " + "SignedHeaders=aaa;content-type;x-amz-date;zzz, " 26 | + "Credential=KEYID/20110909, " 27 | + "Signature=87729cb3475859a18b5d9cead0bba82f0f56a85c2a13bed3bc229c6c35e06628"; 28 | 29 | AuthenticationHeader result = new AuthenticationHeaderParser().parse(value); 30 | 31 | assertEquals("DTA1-HMAC-SHA256", result.getAlgorithm()); 32 | assertEquals("KEYID/20110909", result.getCredential()); 33 | assertEquals("aaa;content-type;x-amz-date;zzz", result.getSignedHeaders()); 34 | assertEquals("87729cb3475859a18b5d9cead0bba82f0f56a85c2a13bed3bc229c6c35e06628", result.getSignature()); 35 | } 36 | 37 | @Test 38 | public void singleHeaderAuthentication2() { 39 | String value = "DTA1-HMAC-SHA256 " 40 | + "SignedHeaders=content-type;x-amz-date;x-amz-dta-version;x-amz-request-id, " 41 | + "Credential=367caa91-cde5-48f2-91fe-bb95f546e9f0/20131207, " 42 | + "Signature=6fe5d5bbf4acda9b0f47f66db3ad8f23a33117ee52b45ae69983bec0b50550fe"; 43 | 44 | AuthenticationHeader result = new AuthenticationHeaderParser().parse(value); 45 | 46 | assertEquals("DTA1-HMAC-SHA256", result.getAlgorithm()); 47 | assertEquals("367caa91-cde5-48f2-91fe-bb95f546e9f0/20131207", result.getCredential()); 48 | assertEquals("content-type;x-amz-date;x-amz-dta-version;x-amz-request-id", result.getSignedHeaders()); 49 | assertEquals("6fe5d5bbf4acda9b0f47f66db3ad8f23a33117ee52b45ae69983bec0b50550fe", result.getSignature()); 50 | } 51 | 52 | @Test 53 | public void invalidHeader() { 54 | assertNull(new AuthenticationHeaderParser().parse("DAT")); 55 | } 56 | 57 | @Test 58 | public void futureCompatibilityForMultipleHeaders() { 59 | String value = "DTA1-HMAC-SHA256 " + "SignedHeaders=aaa;content-type;x-amz-date;zzz, " 60 | + "Credential=KEYID/20110909, " 61 | + "Signature=87729cb3475859a18b5d9cead0bba82f0f56a85c2a13bed3bc229c6c35e06628, " 62 | + "Credential=KEYID2/20110909, " 63 | + "Signature=OTHERSIGNATUREalskdjfasldkjf234lkj234lkjalkj234lkj324lkj2345lkj2"; 64 | 65 | AuthenticationHeader result = new AuthenticationHeaderParser().parse(value); 66 | 67 | assertEquals("DTA1-HMAC-SHA256", result.getAlgorithm()); 68 | assertEquals("KEYID/20110909", result.getCredential()); 69 | assertEquals("aaa;content-type;x-amz-date;zzz", result.getSignedHeaders()); 70 | assertEquals("87729cb3475859a18b5d9cead0bba82f0f56a85c2a13bed3bc229c6c35e06628", result.getSignature()); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/test/java/com/amazon/dtasdk/signature/CredentialStoreTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.signature; 16 | 17 | import java.io.File; 18 | import java.io.FileInputStream; 19 | import java.io.FileWriter; 20 | import java.io.IOException; 21 | import java.io.StringWriter; 22 | import java.nio.charset.Charset; 23 | 24 | import junit.framework.Assert; 25 | 26 | import org.apache.commons.io.IOUtils; 27 | import org.junit.BeforeClass; 28 | import org.junit.Test; 29 | 30 | /** 31 | * CredentialStore test class 32 | */ 33 | public class CredentialStoreTest { 34 | 35 | private static File VALID_FILE; 36 | private static File INVALID_FILE; 37 | 38 | private static final String[] KEYS = { "69b2048d-8bf8-4c1c-b49d-e6114897a9a5", 39 | "dce53190-1f70-4206-ad28-0e1ab3683161", "f0a2586d-24ea-432f-a833-2da18f15ebd4", 40 | "eb3ce251-ef76-48ee-abb0-5886b1a3dfa0", "7568ccc2-9881-4468-ad73-025d16f0662e", 41 | "5de206ab-3a06-4354-a9a4-bfd6efee8027" }; 42 | 43 | private static final String INVALID_KEY = "871dbe31-3b46-4ca5-b9a2-8ad78eac4a4f"; 44 | 45 | @BeforeClass 46 | public static void setUp() throws IOException { 47 | VALID_FILE = File.createTempFile("store", "csv"); 48 | FileWriter writer = new FileWriter(VALID_FILE); 49 | 50 | writer.write(String.format("%s %s\n", KEYS[0], KEYS[1])); 51 | // Intentionally check if blank lines are supported 52 | writer.write(String.format("%s %s\n\n", KEYS[2], KEYS[3])); 53 | writer.write(String.format("%s %s\n", KEYS[4], KEYS[5])); 54 | writer.write("\n"); 55 | 56 | writer.close(); 57 | 58 | INVALID_FILE = File.createTempFile("store", "csv"); 59 | writer = new FileWriter(INVALID_FILE); 60 | 61 | writer.write(String.format("%s%s\n", KEYS[0], KEYS[1])); 62 | writer.write(String.format("%s %s\n", KEYS[2], KEYS[3])); 63 | writer.write(String.format("%s %s\n", KEYS[4], KEYS[5])); 64 | writer.write("\n"); 65 | 66 | writer.close(); 67 | } 68 | 69 | @Test 70 | public void testLoadFromFile() throws IOException, CredentialNotFoundException { 71 | CredentialStore store = new CredentialStore(); 72 | store.load(VALID_FILE); 73 | 74 | assertCorrectCredentials(store); 75 | } 76 | 77 | @Test 78 | public void testLoadFromInputStream() throws IOException, CredentialNotFoundException { 79 | CredentialStore store = new CredentialStore(); 80 | store.load(new FileInputStream(VALID_FILE)); 81 | 82 | assertCorrectCredentials(store); 83 | } 84 | 85 | @Test 86 | public void testLoadFromString() throws IOException, CredentialNotFoundException { 87 | CredentialStore store = new CredentialStore(); 88 | 89 | StringWriter writer = new StringWriter(); 90 | IOUtils.copy(new FileInputStream(VALID_FILE), writer, Charset.defaultCharset()); 91 | String contents = writer.toString(); 92 | 93 | store.load(contents); 94 | 95 | assertCorrectCredentials(store); 96 | } 97 | 98 | private void assertCorrectCredentials(CredentialStore store) throws CredentialNotFoundException { 99 | Assert.assertEquals(KEYS[0], store.get(KEYS[1]).getSecretKey()); 100 | Assert.assertEquals(KEYS[1], store.get(KEYS[1]).getPublicKey()); 101 | 102 | Assert.assertEquals(KEYS[2], store.get(KEYS[3]).getSecretKey()); 103 | Assert.assertEquals(KEYS[3], store.get(KEYS[3]).getPublicKey()); 104 | 105 | Assert.assertEquals(KEYS[4], store.get(KEYS[5]).getSecretKey()); 106 | Assert.assertEquals(KEYS[5], store.get(KEYS[5]).getPublicKey()); 107 | } 108 | 109 | @Test(expected = CredentialNotFoundException.class) 110 | public void testGetInvalidCredential() throws IOException, CredentialNotFoundException { 111 | CredentialStore store = new CredentialStore(); 112 | store.load(new FileInputStream(VALID_FILE)); 113 | 114 | store.get(INVALID_KEY); 115 | } 116 | 117 | @Test(expected = IllegalArgumentException.class) 118 | public void testInvalidFile() throws IOException, CredentialNotFoundException { 119 | CredentialStore store = new CredentialStore(); 120 | store.load(INVALID_FILE); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/test/java/com/amazon/dtasdk/signature/RequestTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.signature; 16 | 17 | import static org.junit.Assert.assertEquals; 18 | 19 | import java.io.ByteArrayInputStream; 20 | import java.io.IOException; 21 | import java.util.Arrays; 22 | import java.util.Collections; 23 | import java.util.HashMap; 24 | import java.util.HashSet; 25 | import java.util.Map; 26 | import java.util.Map.Entry; 27 | 28 | import javax.servlet.ServletInputStream; 29 | import javax.servlet.http.HttpServletRequest; 30 | 31 | import org.easymock.EasyMock; 32 | import org.junit.Test; 33 | 34 | public class RequestTest { 35 | 36 | @Test(expected = IllegalArgumentException.class) 37 | public void ctor_BlankUrl() throws Exception { 38 | new Request("", Request.Method.GET, ""); 39 | } 40 | 41 | @Test(expected = IllegalArgumentException.class) 42 | public void ctor_MalformedURL() throws Exception { 43 | new Request("blork", Request.Method.GET, ""); 44 | } 45 | 46 | @Test(expected = IllegalArgumentException.class) 47 | public void ctor_MalformedURI() throws Exception { 48 | new Request("http://amazon.com/?s=^IXIC", Request.Method.GET, ""); 49 | } 50 | 51 | @Test(expected = IllegalArgumentException.class) 52 | public void ctor_NullUrl() throws Exception { 53 | new Request(null, Request.Method.GET, ""); 54 | } 55 | 56 | @Test 57 | public void defaultValues() { 58 | Request request = new Request("http://amazon.com", Request.Method.GET, "content/type"); 59 | assertEquals("content/type", request.getHeader(Request.CONTENT_TYPE_HEADER)); 60 | assertEquals(new HashSet(Arrays.asList(Request.CONTENT_TYPE_HEADER)), request.getHeaderNames()); 61 | assertEquals(Request.DEFAULT_USER_AGENT, request.getUserAgent()); 62 | } 63 | 64 | @Test 65 | public void getSetHeader() { 66 | Request request = new Request("http://amazon.com", Request.Method.GET, "content/type"); 67 | request.setHeader("key", "value"); 68 | assertEquals("value", request.getHeader("key")); 69 | } 70 | 71 | @Test 72 | public void getHeaderNames() { 73 | Request request = new Request("http://amazon.com", Request.Method.GET, "content/type"); 74 | request.setHeader("key", "value"); 75 | request.setHeader("key2", "value"); 76 | assertEquals(new HashSet(Arrays.asList("key", "key2", Request.CONTENT_TYPE_HEADER)), request.getHeaderNames()); 77 | } 78 | 79 | @Test 80 | public void headersInsenstive() { 81 | Request request = new Request("http://amazon.com", Request.Method.GET, "content/type"); 82 | request.setHeader("KeyName", "values"); 83 | 84 | assertEquals("values", request.getHeader("Keyname")); 85 | assertEquals("values", request.getHeader("keyName")); 86 | assertEquals("values", request.getHeader("keyname")); 87 | } 88 | 89 | @Test 90 | public void fromHttpServletRequest() throws IOException { 91 | HttpServletRequest hsr = EasyMock.createMock(HttpServletRequest.class); 92 | 93 | Map headers = new HashMap(); 94 | headers.put("header1", "header1"); 95 | headers.put("header2", "header2"); 96 | 97 | EasyMock.expect(hsr.getHeaderNames()).andReturn(Collections.enumeration(headers.keySet())); 98 | 99 | for (Entry e : headers.entrySet()) { 100 | EasyMock.expect(hsr.getHeader(e.getKey())).andReturn(e.getValue()); 101 | } 102 | 103 | EasyMock.expect(hsr.getMethod()).andReturn("GET"); 104 | EasyMock.expect(hsr.getContentType()).andReturn("content-type"); 105 | EasyMock.expect(hsr.getRequestURL()).andReturn(new StringBuffer("http://amazon.com:80/servlet/path")); 106 | EasyMock.expect(hsr.getQueryString()).andReturn(""); 107 | 108 | EasyMock.expect(hsr.getInputStream()).andReturn(new ServletInputStream() { 109 | private final ByteArrayInputStream stream = new ByteArrayInputStream("body".getBytes()); 110 | 111 | @Override 112 | public int read() throws IOException { 113 | return stream.read(); 114 | } 115 | }); 116 | 117 | EasyMock.replay(hsr); 118 | 119 | Request request = new Request(hsr); 120 | 121 | assertEquals("header1", request.getHeader("header1")); 122 | assertEquals("header2", request.getHeader("header2")); 123 | assertEquals("content-type", request.getHeader(Request.CONTENT_TYPE_HEADER)); 124 | assertEquals(Request.Method.GET, request.getMethod()); 125 | assertEquals("http://amazon.com:80/servlet/path", request.getUrl()); 126 | assertEquals("body", request.getBody()); 127 | 128 | EasyMock.verify(hsr); 129 | } 130 | 131 | @Test 132 | public void fromHttpServletRequest_withQueryParams() throws IOException { 133 | HttpServletRequest hsr = EasyMock.createMock(HttpServletRequest.class); 134 | 135 | Map headers = new HashMap(); 136 | headers.put("header1", "header1"); 137 | headers.put("header2", "header2"); 138 | 139 | EasyMock.expect(hsr.getHeaderNames()).andReturn(Collections.enumeration(headers.keySet())); 140 | 141 | for (Entry e : headers.entrySet()) { 142 | EasyMock.expect(hsr.getHeader(e.getKey())).andReturn(e.getValue()); 143 | } 144 | 145 | EasyMock.expect(hsr.getMethod()).andReturn("GET"); 146 | EasyMock.expect(hsr.getContentType()).andReturn("content-type"); 147 | EasyMock.expect(hsr.getRequestURL()).andReturn(new StringBuffer("http://amazon.com:8888/servlet")); 148 | EasyMock.expect(hsr.getQueryString()).andReturn("param=value¶m2=value2").anyTimes(); 149 | 150 | EasyMock.expect(hsr.getInputStream()).andReturn(new ServletInputStream() { 151 | private final ByteArrayInputStream stream = new ByteArrayInputStream("body".getBytes()); 152 | 153 | @Override 154 | public int read() throws IOException { 155 | return stream.read(); 156 | } 157 | }); 158 | 159 | EasyMock.replay(hsr); 160 | 161 | Request request = new Request(hsr); 162 | 163 | assertEquals("header1", request.getHeader("header1")); 164 | assertEquals("header2", request.getHeader("header2")); 165 | assertEquals("content-type", request.getHeader(Request.CONTENT_TYPE_HEADER)); 166 | assertEquals(Request.Method.GET, request.getMethod()); 167 | assertEquals("http://amazon.com:8888/servlet?param=value¶m2=value2", request.getUrl()); 168 | assertEquals("body", request.getBody()); 169 | 170 | EasyMock.verify(hsr); 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /src/test/java/com/amazon/dtasdk/utils/ClockTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.utils; 16 | 17 | import static org.junit.Assert.assertEquals; 18 | import static org.junit.Assert.assertNotSame; 19 | 20 | import java.util.Date; 21 | 22 | import org.junit.Test; 23 | 24 | public class ClockTest { 25 | @Test 26 | public void clockReturnsDate() { 27 | assertEquals(Date.class, new Clock().now().getClass()); 28 | } 29 | 30 | @Test 31 | public void consecutiveDatesNotEqual() { 32 | Clock clock = new Clock(); 33 | assertNotSame(clock.now(), clock.now()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/com/amazon/dtasdk/v2/serialization/messages/InstantAccessRequestTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v2.serialization.messages; 16 | 17 | import com.amazon.dtasdk.base.InstantAccessOperationValue; 18 | import com.amazon.dtasdk.serializer.JacksonSerializer; 19 | import com.amazon.dtasdk.serializer.SerializationException; 20 | import org.junit.Test; 21 | 22 | import static org.junit.Assert.assertEquals; 23 | 24 | @Deprecated 25 | public class InstantAccessRequestTest { 26 | private JacksonSerializer serializer = new JacksonSerializer(); 27 | 28 | @Test 29 | public void testSerialize() throws SerializationException { 30 | GetUserIdSerializableRequest request = new GetUserIdSerializableRequest(); 31 | request.setOperation(InstantAccessOperationValue.GETUSERID); 32 | request.setInfoField1("nobody@amazon.com"); 33 | request.setInfoField2("AMZN"); 34 | 35 | String requestString = serializer.encode(request); 36 | 37 | assertEquals("{\"operation\":\"GetUserId\",\"infoField1\":\"nobody@amazon.com\",\"infoField2\":\"AMZN\"}", 38 | requestString); 39 | } 40 | 41 | @Test 42 | public void testDeserialize() throws SerializationException { 43 | String str = "{\"operation\" : \"GetUserId\", \"infoField1\" : \"nobody@amazon.com\",\"infoField2\" : \"AMZN\"}"; 44 | GetUserIdSerializableRequest request = serializer.decode(str, GetUserIdSerializableRequest.class); 45 | 46 | assertEquals(InstantAccessOperationValue.GETUSERID, request.getOperation()); 47 | assertEquals("nobody@amazon.com", request.getInfoField1()); 48 | assertEquals("AMZN", request.getInfoField2()); 49 | } 50 | 51 | @Test 52 | public void testDeserializeExtraFields() throws SerializationException { 53 | String str = "{\"operation\" : \"GetUserId\", \"infoField1\" : \"nobody@amazon.com\",\"infoField2\" : \"AMZN\", \"newField\":\"newValue\"}"; 54 | GetUserIdSerializableRequest request = serializer.decode(str, GetUserIdSerializableRequest.class); 55 | 56 | assertEquals(InstantAccessOperationValue.GETUSERID, request.getOperation()); 57 | assertEquals("nobody@amazon.com", request.getInfoField1()); 58 | assertEquals("AMZN", request.getInfoField2()); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/test/java/com/amazon/dtasdk/v2/serialization/messages/InstantAccessResponseTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v2.serialization.messages; 16 | 17 | import com.amazon.dtasdk.serializer.JacksonSerializer; 18 | import com.amazon.dtasdk.serializer.SerializationException; 19 | import org.junit.Test; 20 | 21 | import static org.junit.Assert.assertEquals; 22 | 23 | @Deprecated 24 | public class InstantAccessResponseTest { 25 | private JacksonSerializer serializer = new JacksonSerializer(); 26 | 27 | @Test 28 | public void testSerialize() throws SerializationException { 29 | GetUserIdSerializableResponse response = new GetUserIdSerializableResponse(); 30 | response.setResponse(GetUserIdSerializableResponseValue.OK); 31 | response.setUserId("190248"); 32 | 33 | String responseString = serializer.encode(response); 34 | 35 | assertEquals("{\"response\":\"OK\",\"userId\":\"190248\"}", responseString); 36 | } 37 | 38 | @Test 39 | public void testDeserialize() throws SerializationException { 40 | String str = "{\"response\":\"OK\",\"userId\":\"190248\"}"; 41 | GetUserIdSerializableResponse response = serializer.decode(str, GetUserIdSerializableResponse.class); 42 | 43 | assertEquals(GetUserIdSerializableResponseValue.OK, response.getResponse()); 44 | assertEquals("190248", response.getUserId()); 45 | } 46 | 47 | @Test 48 | public void testDeserializeExtraFields() throws SerializationException { 49 | String str = "{\"response\":\"OK\",\"userId\":\"190248\",\"newField\":\"newValue\"}"; 50 | GetUserIdSerializableResponse response = serializer.decode(str, GetUserIdSerializableResponse.class); 51 | 52 | assertEquals(GetUserIdSerializableResponseValue.OK, response.getResponse()); 53 | assertEquals("190248", response.getUserId()); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/test/java/com/amazon/dtasdk/v2/servlets/AccountLinkingServletTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v2.servlets; 16 | 17 | import com.amazon.dtasdk.signature.Credential; 18 | import com.amazon.dtasdk.signature.CredentialStore; 19 | import com.amazon.dtasdk.signature.SigningException; 20 | import com.amazon.dtasdk.v2.serialization.messages.GetUserIdSerializableRequest; 21 | import com.amazon.dtasdk.v2.serialization.messages.GetUserIdSerializableResponse; 22 | import com.amazon.dtasdk.v2.serialization.messages.GetUserIdSerializableResponseValue; 23 | import junit.framework.Assert; 24 | import org.easymock.EasyMock; 25 | import org.junit.Test; 26 | 27 | import javax.servlet.ServletOutputStream; 28 | import javax.servlet.http.HttpServletRequest; 29 | import javax.servlet.http.HttpServletResponse; 30 | import java.io.ByteArrayOutputStream; 31 | import java.io.IOException; 32 | 33 | /** 34 | * Test class for InstantAccessServlet. 35 | */ 36 | @Deprecated 37 | public class AccountLinkingServletTest extends InstantAccessServletTest { 38 | 39 | private static final GetUserIdSerializableResponseValue GETUSERID_RESPONSE = GetUserIdSerializableResponseValue.FAIL_ACCOUNT_INVALID; 40 | 41 | private class AccountLinkingServletImpl extends AccountLinkingServlet { 42 | 43 | private final CredentialStore store; 44 | 45 | public AccountLinkingServletImpl(CredentialStore store) { 46 | this.store = store; 47 | } 48 | 49 | @Override 50 | public CredentialStore getCredentialStore() { 51 | return store; 52 | } 53 | 54 | @Override 55 | public GetUserIdSerializableResponse getUserId(GetUserIdSerializableRequest request) { 56 | GetUserIdSerializableResponse response = new GetUserIdSerializableResponse(); 57 | response.setResponse(GETUSERID_RESPONSE); 58 | response.setUserId("1234"); 59 | 60 | return response; 61 | } 62 | } 63 | 64 | @Test 65 | public void testGetUserId() throws SigningException, IOException { 66 | HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); 67 | HttpServletResponse response = EasyMock.createMock(HttpServletResponse.class); 68 | 69 | CredentialStore store = new CredentialStore(); 70 | Credential credential = new Credential("SECRETKEY", "KEYID"); 71 | store.add(credential); 72 | 73 | AccountLinkingServletImpl servlet = new AccountLinkingServletImpl(store); 74 | 75 | // @formatter:off 76 | String bodyContent = "{" + 77 | "\"operation\": \"GetUserId\"," + 78 | "\"infoField1\": \"nobody@amazon.com\"," + 79 | "\"infoField2\": \"amazon\"" + 80 | "}"; 81 | // @formatter:on 82 | 83 | mockRequest(request, bodyContent, credential); 84 | 85 | final ByteArrayOutputStream output = new ByteArrayOutputStream(); 86 | EasyMock.expect(response.getOutputStream()).andReturn(new ServletOutputStream() { 87 | @Override 88 | public void write(int b) throws IOException { 89 | output.write(b); 90 | } 91 | }); 92 | 93 | response.setStatus(HttpServletResponse.SC_OK); 94 | 95 | EasyMock.replay(request, response); 96 | 97 | servlet.doPost(request, response); 98 | 99 | EasyMock.verify(request, response); 100 | 101 | Assert.assertEquals("{\"response\":\"" + GETUSERID_RESPONSE + "\",\"userId\":\"1234\"}", output.toString()); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/test/java/com/amazon/dtasdk/v3/messages/InstantAccessRequestTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v3.messages; 16 | 17 | import com.amazon.dtasdk.serializer.JacksonSerializer; 18 | import com.amazon.dtasdk.serializer.SerializationException; 19 | import com.amazon.dtasdk.v3.serialization.messages.GetUserIdSerializableRequest; 20 | import com.amazon.dtasdk.base.InstantAccessOperationValue; 21 | import org.junit.Test; 22 | 23 | import static org.junit.Assert.assertEquals; 24 | 25 | public class InstantAccessRequestTest { 26 | private JacksonSerializer serializer = new JacksonSerializer(); 27 | 28 | @Test 29 | public void testSerialize() throws SerializationException { 30 | GetUserIdSerializableRequest request = new GetUserIdSerializableRequest(); 31 | request.setOperation(InstantAccessOperationValue.GETUSERID); 32 | request.setInfoField1("nobody@amazon.com"); 33 | request.setInfoField2("AMZN"); 34 | 35 | String requestString = serializer.encode(request); 36 | 37 | assertEquals("{\"operation\":\"GetUserId\",\"infoField1\":\"nobody@amazon.com\",\"infoField2\":\"AMZN\"}", 38 | requestString); 39 | } 40 | 41 | @Test 42 | public void testDeserialize() throws SerializationException { 43 | String str = "{\"operation\" : \"GetUserId\", \"infoField1\" : \"nobody@amazon.com\",\"infoField2\" : \"AMZN\"}"; 44 | GetUserIdSerializableRequest request = serializer.decode(str, GetUserIdSerializableRequest.class); 45 | 46 | assertEquals(InstantAccessOperationValue.GETUSERID, request.getOperation()); 47 | assertEquals("nobody@amazon.com", request.getInfoField1()); 48 | assertEquals("AMZN", request.getInfoField2()); 49 | } 50 | 51 | @Test 52 | public void testDeserializeExtraFields() throws SerializationException { 53 | String str = "{\"operation\" : \"GetUserId\", \"infoField1\" : \"nobody@amazon.com\",\"infoField2\" : \"AMZN\", \"newField\":\"newValue\"}"; 54 | GetUserIdSerializableRequest request = serializer.decode(str, GetUserIdSerializableRequest.class); 55 | 56 | assertEquals(InstantAccessOperationValue.GETUSERID, request.getOperation()); 57 | assertEquals("nobody@amazon.com", request.getInfoField1()); 58 | assertEquals("AMZN", request.getInfoField2()); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/test/java/com/amazon/dtasdk/v3/messages/InstantAccessResponseTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v3.messages; 16 | 17 | import com.amazon.dtasdk.base.SubscriptionResponseValue; 18 | import com.amazon.dtasdk.serializer.JacksonSerializer; 19 | import com.amazon.dtasdk.serializer.SerializationException; 20 | import com.amazon.dtasdk.v2.serialization.messages.GetUserIdSerializableResponseValue; 21 | import com.amazon.dtasdk.v3.serialization.messages.GetUserIdSerializableResponse; 22 | import com.amazon.dtasdk.v3.serialization.messages.SubscriptionGetResponse; 23 | import org.junit.Test; 24 | 25 | import static org.junit.Assert.assertEquals; 26 | 27 | public class InstantAccessResponseTest { 28 | private JacksonSerializer serializer = new JacksonSerializer(); 29 | 30 | @Test 31 | public void testSerialize() throws SerializationException { 32 | GetUserIdSerializableResponse response = new GetUserIdSerializableResponse(); 33 | response.setResponse(GetUserIdSerializableResponseValue.OK); 34 | response.setUserId("190248"); 35 | 36 | String responseString = serializer.encode(response); 37 | 38 | assertEquals("{\"response\":\"OK\",\"userId\":\"190248\"}", responseString); 39 | } 40 | 41 | @Test 42 | public void testDeserialize() throws SerializationException { 43 | String str = "{\"response\":\"OK\",\"userId\":\"190248\"}"; 44 | GetUserIdSerializableResponse response = serializer.decode(str, GetUserIdSerializableResponse.class); 45 | 46 | assertEquals(GetUserIdSerializableResponseValue.OK, response.getResponse()); 47 | assertEquals("190248", response.getUserId()); 48 | } 49 | 50 | @Test 51 | public void testDeserializeExtraFields() throws SerializationException { 52 | String str = "{\"response\":\"OK\",\"userId\":\"190248\",\"newField\":\"newValue\"}"; 53 | GetUserIdSerializableResponse response = serializer.decode(str, GetUserIdSerializableResponse.class); 54 | 55 | assertEquals(GetUserIdSerializableResponseValue.OK, response.getResponse()); 56 | assertEquals("190248", response.getUserId()); 57 | } 58 | 59 | @Test 60 | public void testDeserializeSubscriptionGetResponse() throws SerializationException { 61 | String str = "{\"response\":\"OK\", \"numberOfUnusedLicenses\": 5, \"numberOfUsedLicenses\": 10, \"managementURL\": \"dummyUrl\"}"; 62 | SubscriptionGetResponse response = serializer.decode(str, SubscriptionGetResponse.class); 63 | 64 | assertEquals(SubscriptionResponseValue.OK, response.getResponse()); 65 | assertEquals(Integer.valueOf(5), response.getNumberOfUnusedLicenses()); 66 | assertEquals(Integer.valueOf(10), response.getNumberOfUsedLicenses()); 67 | assertEquals("dummyUrl", response.getManagementURL()); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/test/java/com/amazon/dtasdk/v3/servlets/AccountLinkingServletTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v3.servlets; 16 | 17 | import com.amazon.dtasdk.signature.Credential; 18 | import com.amazon.dtasdk.signature.CredentialStore; 19 | import com.amazon.dtasdk.signature.SigningException; 20 | import com.amazon.dtasdk.v2.serialization.messages.GetUserIdSerializableRequest; 21 | import com.amazon.dtasdk.v2.serialization.messages.GetUserIdSerializableResponse; 22 | import com.amazon.dtasdk.v2.serialization.messages.GetUserIdSerializableResponseValue; 23 | import com.amazon.dtasdk.v2.servlets.AccountLinkingServlet; 24 | import junit.framework.Assert; 25 | import org.easymock.EasyMock; 26 | import org.junit.Test; 27 | 28 | import javax.servlet.ServletOutputStream; 29 | import javax.servlet.http.HttpServletRequest; 30 | import javax.servlet.http.HttpServletResponse; 31 | import java.io.ByteArrayOutputStream; 32 | import java.io.IOException; 33 | 34 | /** 35 | * Test class for InstantAccessServlet. 36 | */ 37 | 38 | public class AccountLinkingServletTest extends InstantAccessServletTest { 39 | 40 | private static final GetUserIdSerializableResponseValue GETUSERID_RESPONSE = GetUserIdSerializableResponseValue.FAIL_ACCOUNT_INVALID; 41 | 42 | private class AccountLinkingServletImpl extends AccountLinkingServlet { 43 | 44 | private final CredentialStore store; 45 | 46 | public AccountLinkingServletImpl(CredentialStore store) { 47 | this.store = store; 48 | } 49 | 50 | @Override 51 | public CredentialStore getCredentialStore() { 52 | return store; 53 | } 54 | 55 | @Override 56 | public GetUserIdSerializableResponse getUserId(GetUserIdSerializableRequest request) { 57 | GetUserIdSerializableResponse response = new GetUserIdSerializableResponse(); 58 | response.setResponse(GETUSERID_RESPONSE); 59 | response.setUserId("1234"); 60 | 61 | return response; 62 | } 63 | } 64 | 65 | @Test 66 | public void testGetUserId() throws SigningException, IOException { 67 | HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); 68 | HttpServletResponse response = EasyMock.createMock(HttpServletResponse.class); 69 | 70 | CredentialStore store = new CredentialStore(); 71 | Credential credential = new Credential("SECRETKEY", "KEYID"); 72 | store.add(credential); 73 | 74 | AccountLinkingServletImpl servlet = new AccountLinkingServletImpl(store); 75 | 76 | // @formatter:off 77 | String bodyContent = "{" + 78 | "\"operation\": \"GetUserId\"," + 79 | "\"infoField1\": \"nobody@amazon.com\"," + 80 | "\"infoField2\": \"amazon\"" + 81 | "}"; 82 | // @formatter:on 83 | 84 | mockRequest(request, bodyContent, credential); 85 | 86 | final ByteArrayOutputStream output = new ByteArrayOutputStream(); 87 | EasyMock.expect(response.getOutputStream()).andReturn(new ServletOutputStream() { 88 | @Override 89 | public void write(int b) throws IOException { 90 | output.write(b); 91 | } 92 | }); 93 | 94 | response.setStatus(HttpServletResponse.SC_OK); 95 | 96 | EasyMock.replay(request, response); 97 | 98 | servlet.doPost(request, response); 99 | 100 | EasyMock.verify(request, response); 101 | 102 | Assert.assertEquals("{\"response\":\"" + GETUSERID_RESPONSE + "\",\"userId\":\"1234\"}", output.toString()); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/test/java/com/amazon/dtasdk/v3/servlets/InstantAccessServletTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | package com.amazon.dtasdk.v3.servlets; 16 | 17 | import com.amazon.dtasdk.serializer.SerializationException; 18 | import com.amazon.dtasdk.signature.*; 19 | import com.amazon.dtasdk.signature.Request.Method; 20 | import com.amazon.dtasdk.base.InstantAccessOperationValue; 21 | import com.amazon.dtasdk.base.InstantAccessResponse; 22 | import junit.framework.Assert; 23 | import org.easymock.EasyMock; 24 | import org.junit.Test; 25 | 26 | import javax.servlet.ServletInputStream; 27 | import javax.servlet.ServletOutputStream; 28 | import javax.servlet.http.HttpServletRequest; 29 | import javax.servlet.http.HttpServletResponse; 30 | import java.io.ByteArrayInputStream; 31 | import java.io.ByteArrayOutputStream; 32 | import java.io.IOException; 33 | import java.util.Vector; 34 | 35 | /** 36 | * Test class for InstantAccessServlet. 37 | */ 38 | 39 | public class InstantAccessServletTest { 40 | 41 | private static final String RESPONSE = "OK"; 42 | 43 | private class InstantAccessServletImpl extends InstantAccessServlet { 44 | 45 | private final CredentialStore store; 46 | 47 | public InstantAccessServletImpl(CredentialStore store) { 48 | this.store = store; 49 | } 50 | 51 | @Override 52 | public CredentialStore getCredentialStore() { 53 | return store; 54 | } 55 | 56 | @Override 57 | public InstantAccessResponse processOperation(InstantAccessOperationValue instantAccessOperationValue, 58 | String requestBody) throws SerializationException { 59 | return new InstantAccessResponse() { 60 | { 61 | setResponse(RESPONSE); 62 | } 63 | }; 64 | } 65 | } 66 | 67 | @Test 68 | public void testDoPost() throws SigningException, IOException { 69 | HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); 70 | HttpServletResponse response = EasyMock.createMock(HttpServletResponse.class); 71 | 72 | CredentialStore store = new CredentialStore(); 73 | Credential credential = new Credential("SECRETKEY", "KEYID"); 74 | store.add(credential); 75 | 76 | InstantAccessServlet servlet = new InstantAccessServletImpl(store); 77 | 78 | // @formatter:off 79 | String bodyContent = "{" + 80 | "\"operation\": \"GetUserId\"," + 81 | "\"infoField1\": \"nobody@amazon.com\"," + 82 | "\"infoField2\": \"amazon\"" + 83 | "}"; 84 | // @formatter:on 85 | 86 | mockRequest(request, bodyContent, credential); 87 | 88 | final ByteArrayOutputStream output = new ByteArrayOutputStream(); 89 | EasyMock.expect(response.getOutputStream()).andReturn(new ServletOutputStream() { 90 | @Override 91 | public void write(int b) throws IOException { 92 | output.write(b); 93 | } 94 | }); 95 | 96 | response.setStatus(HttpServletResponse.SC_OK); 97 | 98 | EasyMock.replay(request, response); 99 | 100 | servlet.doPost(request, response); 101 | 102 | EasyMock.verify(request, response); 103 | 104 | Assert.assertEquals("{\"response\":\"" + RESPONSE + "\"}", output.toString()); 105 | } 106 | 107 | @Test 108 | public void testDoPostIOException() throws SigningException, IOException { 109 | HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); 110 | HttpServletResponse response = EasyMock.createMock(HttpServletResponse.class); 111 | 112 | CredentialStore store = new CredentialStore(); 113 | Credential credential = new Credential("SECRETKEY", "KEYID"); 114 | store.add(credential); 115 | 116 | InstantAccessServlet servlet = new InstantAccessServletImpl(store); 117 | 118 | // @formatter:off 119 | String bodyContent = "{" + 120 | "\"operation\": \"GetUserId\"," + 121 | "\"infoField1\": \"nobody@amazon.com\"," + 122 | "\"infoField2\": \"amazon\"" + 123 | "}"; 124 | // @formatter:on 125 | 126 | mockRequest(request, bodyContent, credential); 127 | 128 | new ByteArrayOutputStream(); 129 | EasyMock.expect(response.getOutputStream()).andReturn(new ServletOutputStream() { 130 | @Override 131 | public void write(int b) throws IOException { 132 | throw new IOException(""); 133 | } 134 | }); 135 | 136 | // Response first set to OK and then should be finally set to ISE after exception 137 | response.setStatus(HttpServletResponse.SC_OK); 138 | response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); 139 | 140 | EasyMock.replay(request, response); 141 | 142 | servlet.doPost(request, response); 143 | 144 | EasyMock.verify(request, response); 145 | } 146 | 147 | @Test 148 | public void testDoPostSerializationException() throws SigningException, IOException { 149 | HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); 150 | HttpServletResponse response = EasyMock.createMock(HttpServletResponse.class); 151 | 152 | CredentialStore store = new CredentialStore(); 153 | Credential credential = new Credential("SECRETKEY", "KEYID"); 154 | store.add(credential); 155 | 156 | InstantAccessServlet servlet = new InstantAccessServletImpl(store); 157 | 158 | // @formatter:off 159 | String bodyContent = // missing opening bracket 160 | "\"operation\": \"GetUserId\"," + 161 | "\"infoField1\": \"nobody@amazon.com\"," + 162 | "\"infoField2\": \"amazon\"" + 163 | "}"; 164 | // @formatter:on 165 | 166 | mockRequest(request, bodyContent, credential); 167 | 168 | response.setStatus(HttpServletResponse.SC_BAD_REQUEST); 169 | 170 | EasyMock.replay(request, response); 171 | 172 | servlet.doPost(request, response); 173 | 174 | EasyMock.verify(request, response); 175 | } 176 | 177 | @Test 178 | public void testDoPostEmptyCredentialStore() throws SigningException, IOException { 179 | HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); 180 | HttpServletResponse response = EasyMock.createMock(HttpServletResponse.class); 181 | 182 | Credential credential = new Credential("SECRETKEY", "KEYID"); 183 | 184 | InstantAccessServlet servlet = new InstantAccessServletImpl(new CredentialStore()); 185 | 186 | // @formatter:off 187 | String bodyContent = "{}"; 188 | // @formatter:on 189 | 190 | mockRequest(request, bodyContent, credential); 191 | 192 | response.setStatus(HttpServletResponse.SC_FORBIDDEN); 193 | 194 | EasyMock.replay(request, response); 195 | 196 | servlet.doPost(request, response); 197 | 198 | EasyMock.verify(request, response); 199 | } 200 | 201 | protected void mockRequest(HttpServletRequest request, final String bodyContent, Credential credential) 202 | throws IOException, SigningException { 203 | Signer signer = new Signer(); 204 | final Request req = new Request("https://amazon.com:8443/", Method.POST, "application/json"); 205 | req.setBody(bodyContent); 206 | 207 | signer.sign(req, credential); 208 | 209 | EasyMock.expect(request.getRequestURL()).andReturn(new StringBuffer("https://amazon.com:8443/")); 210 | EasyMock.expect(request.getQueryString()).andReturn(null); 211 | EasyMock.expect(request.getMethod()).andReturn("POST").anyTimes(); 212 | EasyMock.expect(request.getContentType()).andReturn("application/json"); 213 | EasyMock.expect(request.getInputStream()).andReturn(new ServletInputStream() { 214 | private final ByteArrayInputStream stream = new ByteArrayInputStream(bodyContent.getBytes()); 215 | 216 | @Override 217 | public int read() throws IOException { 218 | return stream.read(); 219 | } 220 | }); 221 | 222 | EasyMock.expect(request.getHeaderNames()).andReturn((new Vector() { 223 | { 224 | for (String n : req.getHeaderNames()) { 225 | add(n); 226 | } 227 | } 228 | }).elements()); 229 | 230 | for (String n : req.getHeaderNames()) { 231 | EasyMock.expect(request.getHeader(n)).andReturn(req.getHeader(n)).anyTimes(); 232 | } 233 | } 234 | } 235 | --------------------------------------------------------------------------------