├── .github
├── ISSUE_TEMPLATE
│ ├── bug-report.yml
│ ├── config.yml
│ ├── documentation.yml
│ └── feature-request.yml
└── workflows
│ ├── ci.yml
│ ├── closed-issue-message.yml
│ ├── handle-stale-discussions.yml
│ └── stale_issue.yml
├── .gitignore
├── LICENSE.txt
├── NOTICE.txt
├── README.md
├── aws-iot-device-sdk-java-samples
├── pom.xml
├── samples-pom.xml
└── src
│ └── main
│ ├── java
│ └── com
│ │ └── amazonaws
│ │ └── services
│ │ └── iot
│ │ └── client
│ │ └── sample
│ │ ├── pubSub
│ │ ├── NonBlockingPublishListener.java
│ │ ├── PublishSubscribeSample.java
│ │ └── TestTopicListener.java
│ │ ├── sampleUtil
│ │ ├── CommandArguments.java
│ │ ├── PrivateKeyReader.java
│ │ └── SampleUtil.java
│ │ ├── shadow
│ │ ├── ConnectedWindow.java
│ │ └── ShadowSample.java
│ │ └── shadowEcho
│ │ ├── ShadowEchoSample.java
│ │ └── Thing.java
│ └── resources
│ └── com
│ └── amazonaws
│ └── services
│ └── iot
│ └── client
│ └── sample
│ └── sampleUtil
│ └── aws-iot-sdk-samples.properties
├── aws-iot-device-sdk-java
├── pom.xml
└── src
│ ├── main
│ └── java
│ │ └── com
│ │ └── amazonaws
│ │ └── services
│ │ └── iot
│ │ └── client
│ │ ├── AWSIotConfig.java
│ │ ├── AWSIotConnectionStatus.java
│ │ ├── AWSIotDevice.java
│ │ ├── AWSIotDeviceErrorCode.java
│ │ ├── AWSIotDeviceProperty.java
│ │ ├── AWSIotException.java
│ │ ├── AWSIotMessage.java
│ │ ├── AWSIotMqttClient.java
│ │ ├── AWSIotQos.java
│ │ ├── AWSIotTimeoutException.java
│ │ ├── AWSIotTopic.java
│ │ ├── auth
│ │ ├── Credentials.java
│ │ ├── CredentialsProvider.java
│ │ └── StaticCredentialsProvider.java
│ │ ├── core
│ │ ├── AbstractAwsIotClient.java
│ │ ├── AwsIotCompletion.java
│ │ ├── AwsIotConnection.java
│ │ ├── AwsIotConnectionCallback.java
│ │ ├── AwsIotConnectionType.java
│ │ ├── AwsIotMessageCallback.java
│ │ ├── AwsIotRetryableException.java
│ │ ├── AwsIotRuntimeException.java
│ │ ├── AwsIotTlsConnection.java
│ │ ├── AwsIotTopicCallback.java
│ │ └── AwsIotWebsocketConnection.java
│ │ ├── mqtt
│ │ ├── AwsIotMqttClientListener.java
│ │ ├── AwsIotMqttConnection.java
│ │ ├── AwsIotMqttConnectionListener.java
│ │ └── AwsIotMqttMessageListener.java
│ │ ├── shadow
│ │ ├── AbstractAwsIotDevice.java
│ │ ├── AwsIotDeviceCommand.java
│ │ ├── AwsIotDeviceCommandAckListener.java
│ │ ├── AwsIotDeviceCommandManager.java
│ │ ├── AwsIotDeviceDeltaListener.java
│ │ ├── AwsIotDeviceReportMessage.java
│ │ ├── AwsIotDeviceSyncMessage.java
│ │ ├── AwsIotJsonDeserializer.java
│ │ └── AwsIotJsonSerializer.java
│ │ └── util
│ │ ├── AwsIotTlsSocketFactory.java
│ │ └── AwsIotWebSocketUrlSigner.java
│ └── test
│ └── java
│ └── com
│ └── amazonaws
│ └── services
│ └── iot
│ └── client
│ ├── AWSIotDeviceErrorCodeTest.java
│ ├── AWSIotDeviceIntegrationTest.java
│ ├── AWSIotMessageTest.java
│ ├── AWSIotMqttClientIntegrationTest.java
│ ├── AWSIotMqttClientIntegrationUtil.java
│ ├── AWSIotQosTest.java
│ ├── CredentialUtil.java
│ ├── TestDevice.java
│ ├── TestDeviceNotifier.java
│ ├── TestTopic.java
│ ├── auth
│ ├── core
│ ├── AbstractAwsIotClientTest.java
│ ├── AwsIotCompletionTest.java
│ ├── AwsIotConnectionTest.java
│ └── AwsIotWebsocketConnectionTest.java
│ ├── mqtt
│ ├── AwsIotMqttClientListenerTest.java
│ ├── AwsIotMqttConnectionListenerTest.java
│ ├── AwsIotMqttConnectionTest.java
│ └── AwsIotMqttMessageListenerTest.java
│ ├── shadow
│ ├── AbstractAwsIotDeviceTest.java
│ ├── AwsIotDeviceCommandManagerTest.java
│ ├── AwsIotDeviceCommandTest.java
│ ├── AwsIotDeviceDeltaListenerTest.java
│ ├── AwsIotDeviceReportMessageTest.java
│ └── AwsIotDeviceSyncMessageTest.java
│ ├── system_props_mutualAuth.properties
│ ├── system_props_websocket.properties
│ └── util
│ ├── AwsIotTlsSocketFactoryTest.java
│ └── AwsIotWebSocketUrlSignerTest.java
├── codebuild
└── cd
│ ├── promote-release.yml
│ ├── test-version-exists.sh
│ └── test-version-exists.yml
└── pom.xml
/.github/ISSUE_TEMPLATE/bug-report.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: "🐛 Bug Report"
3 | description: Report a bug
4 | title: "(short issue description)"
5 | labels: [bug, needs-triage]
6 | assignees: []
7 | body:
8 | - type: textarea
9 | id: description
10 | attributes:
11 | label: Describe the bug
12 | description: What is the problem? A clear and concise description of the bug.
13 | validations:
14 | required: true
15 | - type: textarea
16 | id: expected
17 | attributes:
18 | label: Expected Behavior
19 | description: |
20 | What did you expect to happen?
21 | validations:
22 | required: true
23 | - type: textarea
24 | id: current
25 | attributes:
26 | label: Current Behavior
27 | description: |
28 | What actually happened?
29 |
30 | Please include full errors, uncaught exceptions, stack traces, and relevant logs.
31 | If service responses are relevant, please include wire logs.
32 | validations:
33 | required: true
34 | - type: textarea
35 | id: reproduction
36 | attributes:
37 | label: Reproduction Steps
38 | description: |
39 | Provide a self-contained, concise snippet of code that can be used to reproduce the issue.
40 | For more complex issues provide a repo with the smallest sample that reproduces the bug.
41 |
42 | Avoid including business logic or unrelated code, it makes diagnosis more difficult.
43 | The code sample should be an SSCCE. See http://sscce.org/ for details. In short, please provide a code sample that we can copy/paste, run and reproduce.
44 | validations:
45 | required: true
46 | - type: textarea
47 | id: solution
48 | attributes:
49 | label: Possible Solution
50 | description: |
51 | Suggest a fix/reason for the bug
52 | validations:
53 | required: false
54 | - type: textarea
55 | id: context
56 | attributes:
57 | label: Additional Information/Context
58 | description: |
59 | Anything else that might be relevant for troubleshooting this bug. Providing context helps us come up with a solution that is most useful in the real world.
60 | validations:
61 | required: false
62 | - type: input
63 | id: sdk-version
64 | attributes:
65 | label: SDK version used
66 | validations:
67 | required: true
68 | - type: input
69 | id: environment
70 | attributes:
71 | label: Environment details (OS name and version, etc.)
72 | validations:
73 | required: true
74 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | ---
2 | blank_issues_enabled: false
3 | contact_links:
4 | - name: 💬 General Question
5 | url: https://github.com/aws/aws-iot-device-sdk-java/discussions/categories/q-a
6 | about: Please ask and answer questions as a discussion thread
7 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/documentation.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: "📕 Documentation Issue"
3 | description: Report an issue in the API Reference documentation or Developer Guide
4 | title: "(short issue description)"
5 | labels: [documentation, needs-triage]
6 | assignees: []
7 | body:
8 | - type: textarea
9 | id: description
10 | attributes:
11 | label: Describe the issue
12 | description: A clear and concise description of the issue.
13 | validations:
14 | required: true
15 |
16 | - type: textarea
17 | id: links
18 | attributes:
19 | label: Links
20 | description: |
21 | Include links to affected documentation page(s).
22 | validations:
23 | required: true
24 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature-request.yml:
--------------------------------------------------------------------------------
1 | ---
2 | ---
3 | name: 🚀 Feature Request
4 | description: Suggest an idea for this project
5 | title: "(short issue description)"
6 | labels: [feature-request, needs-triage]
7 | assignees: []
8 | body:
9 | - type: textarea
10 | id: description
11 | attributes:
12 | label: Describe the feature
13 | description: A clear and concise description of the feature you are proposing.
14 | validations:
15 | required: true
16 | - type: textarea
17 | id: use-case
18 | attributes:
19 | label: Use Case
20 | description: |
21 | Why do you need this feature? For example: "I'm always frustrated when..."
22 | validations:
23 | required: true
24 | - type: textarea
25 | id: solution
26 | attributes:
27 | label: Proposed Solution
28 | description: |
29 | Suggest how to implement the addition or change. Please include prototype/workaround/sketch/reference implementation.
30 | validations:
31 | required: false
32 | - type: textarea
33 | id: other
34 | attributes:
35 | label: Other Information
36 | description: |
37 | Any alternative solutions or features you considered, a more detailed explanation, stack traces, related issues, links for context, etc.
38 | validations:
39 | required: false
40 | - type: checkboxes
41 | id: ack
42 | attributes:
43 | label: Acknowledgements
44 | options:
45 | - label: I may be able to implement this feature request
46 | required: false
47 | - label: This feature might incur a breaking change
48 | required: false
49 | - type: input
50 | id: sdk-version
51 | attributes:
52 | label: SDK version used
53 | validations:
54 | required: true
55 | - type: input
56 | id: environment
57 | attributes:
58 | label: Environment details (OS name and version, etc.)
59 | validations:
60 | required: true
61 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches:
6 | - '*'
7 | - '!main'
8 |
9 | env:
10 | BUILDER_VERSION: v0.9.14
11 | BUILDER_SOURCE: releases
12 | BUILDER_HOST: https://d19elf31gohf1l.cloudfront.net
13 | PACKAGE_NAME: aws-iot-device-sdk-java
14 | RUN: ${{ github.run_id }}-${{ github.run_number }}
15 | AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
16 | AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
17 | AWS_DEFAULT_REGION: us-east-1
18 |
19 | jobs:
20 | java-compat:
21 | runs-on: ubuntu-20.04
22 | strategy:
23 | fail-fast: false
24 | matrix:
25 | version:
26 | - 8
27 | - 11
28 | - 17
29 | steps:
30 | - name: Checkout Sources
31 | uses: actions/checkout@v2
32 | - name: Setup Java
33 | uses: actions/setup-java@v2
34 | with:
35 | distribution: temurin
36 | java-version: ${{ matrix.version }}
37 | cache: maven
38 | - name: Build ${{ env.PACKAGE_NAME }} + consumers
39 | run: |
40 | java -version
41 | mvn -B test
42 |
--------------------------------------------------------------------------------
/.github/workflows/closed-issue-message.yml:
--------------------------------------------------------------------------------
1 | name: Closed Issue Message
2 | on:
3 | issues:
4 | types: [closed]
5 | jobs:
6 | auto_comment:
7 | runs-on: ubuntu-latest
8 | permissions:
9 | issues: write
10 | steps:
11 | - uses: aws-actions/closed-issue-message@v1
12 | with:
13 | # These inputs are both required
14 | repo-token: "${{ secrets.GITHUB_TOKEN }}"
15 | message: |
16 | This issue is now closed. Comments on closed issues are hard for our team to see.
17 | If you need more assistance, please open a new issue that references this one.
18 |
--------------------------------------------------------------------------------
/.github/workflows/handle-stale-discussions.yml:
--------------------------------------------------------------------------------
1 | name: HandleStaleDiscussions
2 | on:
3 | schedule:
4 | - cron: '0 */4 * * *'
5 | discussion_comment:
6 | types: [created]
7 |
8 | jobs:
9 | handle-stale-discussions:
10 | name: Handle stale discussions
11 | runs-on: ubuntu-latest
12 | permissions:
13 | discussions: write
14 | steps:
15 | - name: Stale discussions action
16 | uses: aws-github-ops/handle-stale-discussions@v1
17 | env:
18 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
19 |
--------------------------------------------------------------------------------
/.github/workflows/stale_issue.yml:
--------------------------------------------------------------------------------
1 | name: "Close stale issues"
2 |
3 | # Controls when the action will run.
4 | on:
5 | schedule:
6 | - cron: "0 0 * * *"
7 |
8 | jobs:
9 | cleanup:
10 | runs-on: ubuntu-latest
11 | name: Stale issue job
12 | permissions:
13 | issues: write
14 | pull-requests: write
15 | steps:
16 | - uses: aws-actions/stale-issue-cleanup@v3
17 | with:
18 | # Setting messages to an empty string will cause the automation to skip
19 | # that category
20 | ancient-issue-message: Greetings! Sorry to say but this is a very old issue that is probably not getting as much attention as it deserves. We encourage you to try V2 and if you find that this is still a problem, please feel free to open a new issue there.
21 | stale-issue-message: Greetings! It looks like this issue hasn’t been active in longer than a week. Because it has been longer than a week since the last update on this, and in the absence of more information, we will be closing this issue soon. If you find that this is still a problem, please feel free to provide a comment or add an upvote to prevent automatic closure, or if the issue is already closed, please feel free to open a new one, also please try V2 as this might be solved there too.
22 | stale-pr-message: Greetings! It looks like this PR hasn’t been active in longer than a week, add a comment or an upvote to prevent automatic closure, or if the issue is already closed, please feel free to open a new one.
23 |
24 | # These labels are required
25 | stale-issue-label: closing-soon
26 | exempt-issue-label: automation-exempt
27 | stale-pr-label: closing-soon
28 | exempt-pr-label: pr/needs-review
29 | response-requested-label: response-requested
30 |
31 | # Don't set closed-for-staleness label to skip closing very old issues
32 | # regardless of label
33 | closed-for-staleness-label: closed-for-staleness
34 |
35 | # Issue timing
36 | days-before-stale: 10
37 | days-before-close: 4
38 | days-before-ancient: 36500
39 |
40 | # If you don't want to mark a issue as being ancient based on a
41 | # threshold of "upvotes", you can set this here. An "upvote" is
42 | # the total number of +1, heart, hooray, and rocket reactions
43 | # on an issue.
44 | minimum-upvotes-to-exempt: 1
45 |
46 | repo-token: ${{ secrets.GITHUB_TOKEN }}
47 | loglevel: DEBUG
48 | # Set dry-run to true to not perform label or close actions.
49 | dry-run: false
50 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | *.iml
3 | aws-iot-device-sdk-java-samples/target/
4 | aws-iot-device-sdk-java/target/
--------------------------------------------------------------------------------
/NOTICE.txt:
--------------------------------------------------------------------------------
1 | AWS IoT Device SDK for Java
2 | Copyright 2010-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 |
4 | This product includes software developed by
5 | Amazon Technologies, Inc (http://www.amazon.com/).
6 |
7 | **********************
8 | THIRD PARTY COMPONENTS
9 | **********************
10 | This software includes third party software subject to the following copyrights:
11 | - PKCS#1 and PKCS#8 PEM encoded private key parsing and utility functions from oauth.googlecode.com - Copyright 1998-2010 AOL Inc.
12 |
13 | The licenses for these third party components are included in LICENSE.txt
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java-samples/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 | com.amazonaws
5 | aws-iot-device-sdk-java-pom
6 | 0.0.1-dev
7 |
8 | aws-iot-device-sdk-java-samples
9 |
10 |
11 | com.amazonaws
12 | aws-iot-device-sdk-java
13 | 0.0.1-dev
14 |
15 |
16 | commons-codec
17 | commons-codec
18 | 1.12
19 |
20 |
21 |
22 |
23 |
24 | org.apache.maven.plugins
25 | maven-compiler-plugin
26 | 3.5.1
27 |
28 |
29 | com/amazonaws/services/iot/client/sample/odin/*.java
30 |
31 |
32 |
33 |
34 | org.apache.maven.plugins
35 | maven-source-plugin
36 | 3.0.0
37 |
38 |
39 | attach-sources
40 |
41 | jar-no-fork
42 |
43 |
44 |
45 |
46 |
47 | org.apache.maven.plugins
48 | maven-javadoc-plugin
49 | 2.10.3
50 |
51 | 8
52 | *.odin.*
53 |
54 |
55 |
56 | attach-javadocs
57 |
58 | jar
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java-samples/samples-pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 | com.amazonaws
4 | aws-iot-device-sdk-java-samples
5 | 0.0.1-dev
6 |
7 |
8 | org.apache.maven.plugins
9 | maven-compiler-plugin
10 | 3.5.1
11 |
12 |
13 | com.amazonaws
14 | aws-iot-device-sdk-java
15 | 0.0.1-dev
16 |
17 |
18 | com.fasterxml.jackson.core
19 | jackson-core
20 | 2.13.4
21 |
22 |
23 | com.fasterxml.jackson.core
24 | jackson-databind
25 | 2.13.4.2
26 |
27 |
28 |
29 |
30 |
31 | org.apache.maven.plugins
32 | maven-compiler-plugin
33 |
34 | 1.7
35 | 1.7
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java-samples/src/main/java/com/amazonaws/services/iot/client/sample/pubSub/NonBlockingPublishListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.sample.pubSub;
17 |
18 | import com.amazonaws.services.iot.client.AWSIotMessage;
19 | import com.amazonaws.services.iot.client.AWSIotQos;
20 |
21 | /**
22 | * This class extends {@link AWSIotMessage} to provide customized handlers for
23 | * non-blocking message publishing.
24 | */
25 | public class NonBlockingPublishListener extends AWSIotMessage {
26 |
27 | public NonBlockingPublishListener(String topic, AWSIotQos qos, String payload) {
28 | super(topic, qos, payload);
29 | }
30 |
31 | @Override
32 | public void onSuccess() {
33 | System.out.println(System.currentTimeMillis() + ": >>> " + getStringPayload());
34 | }
35 |
36 | @Override
37 | public void onFailure() {
38 | System.out.println(System.currentTimeMillis() + ": publish failed for " + getStringPayload());
39 | }
40 |
41 | @Override
42 | public void onTimeout() {
43 | System.out.println(System.currentTimeMillis() + ": publish timeout for " + getStringPayload());
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java-samples/src/main/java/com/amazonaws/services/iot/client/sample/pubSub/PublishSubscribeSample.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.sample.pubSub;
17 |
18 | import com.amazonaws.services.iot.client.AWSIotMqttClient;
19 | import com.amazonaws.services.iot.client.AWSIotException;
20 | import com.amazonaws.services.iot.client.AWSIotMessage;
21 | import com.amazonaws.services.iot.client.AWSIotQos;
22 | import com.amazonaws.services.iot.client.AWSIotTimeoutException;
23 | import com.amazonaws.services.iot.client.AWSIotTopic;
24 | import com.amazonaws.services.iot.client.sample.sampleUtil.CommandArguments;
25 | import com.amazonaws.services.iot.client.sample.sampleUtil.SampleUtil;
26 | import com.amazonaws.services.iot.client.sample.sampleUtil.SampleUtil.KeyStorePasswordPair;
27 |
28 | /**
29 | * This is an example that uses {@link AWSIotMqttClient} to subscribe to a topic and
30 | * publish messages to it. Both blocking and non-blocking publishing are
31 | * demonstrated in this example.
32 | */
33 | public class PublishSubscribeSample {
34 |
35 | private static final String TestTopic = "sdk/test/java";
36 | private static final AWSIotQos TestTopicQos = AWSIotQos.QOS0;
37 |
38 | private static AWSIotMqttClient awsIotClient;
39 |
40 | public static void setClient(AWSIotMqttClient client) {
41 | awsIotClient = client;
42 | }
43 |
44 | public static class BlockingPublisher implements Runnable {
45 | private final AWSIotMqttClient awsIotClient;
46 |
47 | public BlockingPublisher(AWSIotMqttClient awsIotClient) {
48 | this.awsIotClient = awsIotClient;
49 | }
50 |
51 | @Override
52 | public void run() {
53 | long counter = 1;
54 |
55 | while (true) {
56 | String payload = "hello from blocking publisher - " + (counter++);
57 | try {
58 | awsIotClient.publish(TestTopic, payload);
59 | } catch (AWSIotException e) {
60 | System.out.println(System.currentTimeMillis() + ": publish failed for " + payload);
61 | }
62 | System.out.println(System.currentTimeMillis() + ": >>> " + payload);
63 |
64 | try {
65 | Thread.sleep(1000);
66 | } catch (InterruptedException e) {
67 | System.out.println(System.currentTimeMillis() + ": BlockingPublisher was interrupted");
68 | return;
69 | }
70 | }
71 | }
72 | }
73 |
74 | public static class NonBlockingPublisher implements Runnable {
75 | private final AWSIotMqttClient awsIotClient;
76 |
77 | public NonBlockingPublisher(AWSIotMqttClient awsIotClient) {
78 | this.awsIotClient = awsIotClient;
79 | }
80 |
81 | @Override
82 | public void run() {
83 | long counter = 1;
84 |
85 | while (true) {
86 | String payload = "hello from non-blocking publisher - " + (counter++);
87 | AWSIotMessage message = new NonBlockingPublishListener(TestTopic, TestTopicQos, payload);
88 | try {
89 | awsIotClient.publish(message);
90 | } catch (AWSIotException e) {
91 | System.out.println(System.currentTimeMillis() + ": publish failed for " + payload);
92 | }
93 |
94 | try {
95 | Thread.sleep(1000);
96 | } catch (InterruptedException e) {
97 | System.out.println(System.currentTimeMillis() + ": NonBlockingPublisher was interrupted");
98 | return;
99 | }
100 | }
101 | }
102 | }
103 |
104 | private static void initClient(CommandArguments arguments) {
105 | String clientEndpoint = arguments.getNotNull("clientEndpoint", SampleUtil.getConfig("clientEndpoint"));
106 | String clientId = arguments.getNotNull("clientId", SampleUtil.getConfig("clientId"));
107 |
108 | String certificateFile = arguments.get("certificateFile", SampleUtil.getConfig("certificateFile"));
109 | String privateKeyFile = arguments.get("privateKeyFile", SampleUtil.getConfig("privateKeyFile"));
110 | if (awsIotClient == null && certificateFile != null && privateKeyFile != null) {
111 | String algorithm = arguments.get("keyAlgorithm", SampleUtil.getConfig("keyAlgorithm"));
112 |
113 | KeyStorePasswordPair pair = SampleUtil.getKeyStorePasswordPair(certificateFile, privateKeyFile, algorithm);
114 |
115 | awsIotClient = new AWSIotMqttClient(clientEndpoint, clientId, pair.keyStore, pair.keyPassword);
116 | }
117 |
118 | if (awsIotClient == null) {
119 | String awsAccessKeyId = arguments.get("awsAccessKeyId", SampleUtil.getConfig("awsAccessKeyId"));
120 | String awsSecretAccessKey = arguments.get("awsSecretAccessKey", SampleUtil.getConfig("awsSecretAccessKey"));
121 | String sessionToken = arguments.get("sessionToken", SampleUtil.getConfig("sessionToken"));
122 |
123 | if (awsAccessKeyId != null && awsSecretAccessKey != null) {
124 | awsIotClient = new AWSIotMqttClient(clientEndpoint, clientId, awsAccessKeyId, awsSecretAccessKey,
125 | sessionToken);
126 | }
127 | }
128 |
129 | if (awsIotClient == null) {
130 | throw new IllegalArgumentException("Failed to construct client due to missing certificate or credentials.");
131 | }
132 | }
133 |
134 | public static void main(String args[]) throws InterruptedException, AWSIotException, AWSIotTimeoutException {
135 | CommandArguments arguments = CommandArguments.parse(args);
136 | initClient(arguments);
137 |
138 | awsIotClient.connect();
139 |
140 | AWSIotTopic topic = new TestTopicListener(TestTopic, TestTopicQos);
141 | awsIotClient.subscribe(topic, true);
142 |
143 | Thread blockingPublishThread = new Thread(new BlockingPublisher(awsIotClient));
144 | Thread nonBlockingPublishThread = new Thread(new NonBlockingPublisher(awsIotClient));
145 |
146 | blockingPublishThread.start();
147 | nonBlockingPublishThread.start();
148 |
149 | blockingPublishThread.join();
150 | nonBlockingPublishThread.join();
151 | }
152 |
153 | }
154 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java-samples/src/main/java/com/amazonaws/services/iot/client/sample/pubSub/TestTopicListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.sample.pubSub;
17 |
18 | import com.amazonaws.services.iot.client.AWSIotMessage;
19 | import com.amazonaws.services.iot.client.AWSIotQos;
20 | import com.amazonaws.services.iot.client.AWSIotTopic;
21 |
22 | /**
23 | * This class extends {@link AWSIotTopic} to receive messages from a subscribed
24 | * topic.
25 | */
26 | public class TestTopicListener extends AWSIotTopic {
27 |
28 | public TestTopicListener(String topic, AWSIotQos qos) {
29 | super(topic, qos);
30 | }
31 |
32 | @Override
33 | public void onMessage(AWSIotMessage message) {
34 | System.out.println(System.currentTimeMillis() + ": <<< " + message.getStringPayload());
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java-samples/src/main/java/com/amazonaws/services/iot/client/sample/sampleUtil/CommandArguments.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.sample.sampleUtil;
17 |
18 | import java.util.HashMap;
19 | import java.util.Map;
20 |
21 | public class CommandArguments {
22 |
23 | private final Map arguments = new HashMap();
24 |
25 | private CommandArguments(String[] args) {
26 | String name = null;
27 |
28 | for (int i = 0; i < args.length; i++) {
29 | String arg = args[i].trim();
30 | if (name == null) {
31 | if (arg.startsWith("-")) {
32 | name = arg.replaceFirst("^-+", "");
33 | if (name.length() < 1) {
34 | name = null;
35 | }
36 | }
37 | continue;
38 | }
39 |
40 | if (arg.startsWith("-")) {
41 | arguments.put(name.toLowerCase(), null);
42 |
43 | name = arg.replaceFirst("^-+", "");
44 | if (name.length() < 1) {
45 | name = null;
46 | }
47 | } else {
48 | arguments.put(name.toLowerCase(), arg);
49 | name = null;
50 | }
51 | }
52 |
53 | if (name != null) {
54 | arguments.put(name.toLowerCase(), null);
55 | }
56 | }
57 |
58 | public static CommandArguments parse(String[] args) {
59 | return new CommandArguments(args);
60 | }
61 |
62 | public String get(String name) {
63 | return arguments.get(name.toLowerCase());
64 | }
65 |
66 | public String get(String name, String defaultValue) {
67 | String value = arguments.get(name.toLowerCase());
68 | if (value == null) {
69 | value = defaultValue;
70 | }
71 | return value;
72 | }
73 |
74 | public String getNotNull(String name) {
75 | String value = get(name);
76 | if (value == null) {
77 | throw new RuntimeException("Missing required argument for " + name);
78 | }
79 | return value;
80 | }
81 |
82 | public String getNotNull(String name, String defaultValue) {
83 | String value = get(name, defaultValue);
84 | if (value == null) {
85 | throw new RuntimeException("Missing required argument for " + name);
86 | }
87 | return value;
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java-samples/src/main/java/com/amazonaws/services/iot/client/sample/sampleUtil/SampleUtil.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.sample.sampleUtil;
17 |
18 | import java.io.BufferedInputStream;
19 | import java.io.DataInputStream;
20 | import java.io.File;
21 | import java.io.FileInputStream;
22 | import java.io.IOException;
23 | import java.io.InputStream;
24 | import java.math.BigInteger;
25 | import java.net.URL;
26 | import java.security.GeneralSecurityException;
27 | import java.security.KeyStore;
28 | import java.security.KeyStoreException;
29 | import java.security.NoSuchAlgorithmException;
30 | import java.security.PrivateKey;
31 | import java.security.SecureRandom;
32 | import java.security.cert.Certificate;
33 | import java.security.cert.CertificateException;
34 | import java.security.cert.CertificateFactory;
35 | import java.util.List;
36 | import java.util.Properties;
37 |
38 | /**
39 | * This is a helper class to facilitate reading of the configurations and
40 | * certificate from the resource files.
41 | */
42 | public class SampleUtil {
43 | private static final String PropertyFile = "aws-iot-sdk-samples.properties";
44 |
45 | public static class KeyStorePasswordPair {
46 | public KeyStore keyStore;
47 | public String keyPassword;
48 |
49 | public KeyStorePasswordPair(KeyStore keyStore, String keyPassword) {
50 | this.keyStore = keyStore;
51 | this.keyPassword = keyPassword;
52 | }
53 | }
54 |
55 | public static String getConfig(String name) {
56 | Properties prop = new Properties();
57 | URL resource = SampleUtil.class.getResource(PropertyFile);
58 | if (resource == null) {
59 | return null;
60 | }
61 | try (InputStream stream = resource.openStream()) {
62 | prop.load(stream);
63 | } catch (IOException e) {
64 | return null;
65 | }
66 | String value = prop.getProperty(name);
67 | if (value == null || value.trim().length() == 0) {
68 | return null;
69 | } else {
70 | return value;
71 | }
72 | }
73 |
74 | public static KeyStorePasswordPair getKeyStorePasswordPair(final String certificateFile, final String privateKeyFile) {
75 | return getKeyStorePasswordPair(certificateFile, privateKeyFile, null);
76 | }
77 |
78 | public static KeyStorePasswordPair getKeyStorePasswordPair(final String certificateFile, final String privateKeyFile,
79 | String keyAlgorithm) {
80 | if (certificateFile == null || privateKeyFile == null) {
81 | System.out.println("Certificate or private key file missing");
82 | return null;
83 | }
84 | System.out.println("Cert file:" +certificateFile + " Private key: "+ privateKeyFile);
85 |
86 | final PrivateKey privateKey = loadPrivateKeyFromFile(privateKeyFile, keyAlgorithm);
87 |
88 | final List certChain = loadCertificatesFromFile(certificateFile);
89 |
90 | if (certChain == null || privateKey == null) return null;
91 |
92 | return getKeyStorePasswordPair(certChain, privateKey);
93 | }
94 |
95 | public static KeyStorePasswordPair getKeyStorePasswordPair(final List certificates, final PrivateKey privateKey) {
96 | KeyStore keyStore;
97 | String keyPassword;
98 | try {
99 | keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
100 | keyStore.load(null);
101 |
102 | // randomly generated key password for the key in the KeyStore
103 | keyPassword = new BigInteger(128, new SecureRandom()).toString(32);
104 |
105 | Certificate[] certChain = new Certificate[certificates.size()];
106 | certChain = certificates.toArray(certChain);
107 | keyStore.setKeyEntry("alias", privateKey, keyPassword.toCharArray(), certChain);
108 | } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) {
109 | System.out.println("Failed to create key store");
110 | return null;
111 | }
112 |
113 | return new KeyStorePasswordPair(keyStore, keyPassword);
114 | }
115 |
116 | private static List loadCertificatesFromFile(final String filename) {
117 | File file = new File(filename);
118 | if (!file.exists()) {
119 | System.out.println("Certificate file: " + filename + " is not found.");
120 | return null;
121 | }
122 |
123 | try (BufferedInputStream stream = new BufferedInputStream(new FileInputStream(file))) {
124 | final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
125 | return (List) certFactory.generateCertificates(stream);
126 | } catch (IOException | CertificateException e) {
127 | System.out.println("Failed to load certificate file " + filename);
128 | }
129 | return null;
130 | }
131 |
132 | private static PrivateKey loadPrivateKeyFromFile(final String filename, final String algorithm) {
133 | PrivateKey privateKey = null;
134 |
135 | File file = new File(filename);
136 | if (!file.exists()) {
137 | System.out.println("Private key file not found: " + filename);
138 | return null;
139 | }
140 | try (DataInputStream stream = new DataInputStream(new FileInputStream(file))) {
141 | privateKey = PrivateKeyReader.getPrivateKey(stream, algorithm);
142 | } catch (IOException | GeneralSecurityException e) {
143 | System.out.println("Failed to load private key from file " + filename);
144 | }
145 |
146 | return privateKey;
147 | }
148 |
149 | }
150 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java-samples/src/main/java/com/amazonaws/services/iot/client/sample/shadow/ConnectedWindow.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.sample.shadow;
17 |
18 | import java.util.Random;
19 |
20 | import com.amazonaws.services.iot.client.AWSIotDevice;
21 | import com.amazonaws.services.iot.client.AWSIotDeviceProperty;
22 |
23 | /**
24 | * This class encapsulates an actual device. It extends {@link AWSIotDevice} to
25 | * define properties that are to be kept in sync with the AWS IoT shadow.
26 | */
27 | public class ConnectedWindow extends AWSIotDevice {
28 |
29 | public ConnectedWindow(String thingName) {
30 | super(thingName);
31 | }
32 |
33 | @AWSIotDeviceProperty
34 | private boolean windowOpen;
35 |
36 | @AWSIotDeviceProperty
37 | private float roomTemperature;
38 |
39 | public boolean getWindowOpen() {
40 | // 1. read the window state from the window actuator
41 | boolean reportedState = this.windowOpen;
42 | System.out.println(
43 | System.currentTimeMillis() + " >>> reported window state: " + (reportedState ? "open" : "closed"));
44 |
45 | // 2. return the current window state
46 | return reportedState;
47 | }
48 |
49 | public void setWindowOpen(boolean desiredState) {
50 | // 1. update the window actuator with the desired state
51 | this.windowOpen = desiredState;
52 |
53 | System.out.println(
54 | System.currentTimeMillis() + " <<< desired window state to " + (desiredState ? "open" : "closed"));
55 | }
56 |
57 | public float getRoomTemperature() {
58 | // 1. Read the actual room temperature from the thermostat
59 | Random rand = new Random();
60 | float minTemperature = 20.0f;
61 | float maxTemperature = 85.0f;
62 | float reportedTemperature = rand.nextFloat() * (maxTemperature - minTemperature) + minTemperature;
63 |
64 | // 2. (optionally) update the local copy
65 | this.roomTemperature = reportedTemperature;
66 |
67 | // 3. return the current room temperature
68 | System.out.println(System.currentTimeMillis() + " >>> reported room temperature: " + reportedTemperature);
69 | return this.roomTemperature;
70 | }
71 |
72 | public void setRoomTemperature(float desiredTemperature) {
73 | // no-op as room temperature is a read-only property. It's not required
74 | // to have this setter.
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java-samples/src/main/java/com/amazonaws/services/iot/client/sample/shadow/ShadowSample.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.sample.shadow;
17 |
18 | import com.amazonaws.services.iot.client.AWSIotConnectionStatus;
19 | import com.amazonaws.services.iot.client.AWSIotDevice;
20 | import com.amazonaws.services.iot.client.AWSIotException;
21 | import com.amazonaws.services.iot.client.AWSIotMessage;
22 | import com.amazonaws.services.iot.client.AWSIotMqttClient;
23 | import com.amazonaws.services.iot.client.AWSIotQos;
24 | import com.amazonaws.services.iot.client.sample.sampleUtil.CommandArguments;
25 | import com.amazonaws.services.iot.client.sample.sampleUtil.SampleUtil;
26 | import com.amazonaws.services.iot.client.sample.sampleUtil.SampleUtil.KeyStorePasswordPair;
27 |
28 | /**
29 | * This example demonstrates how to use {@link AWSIotMqttClient} and a derived
30 | * {@link AWSIotDevice} to keep the device connected with its shadow in the
31 | * cloud. This is the recommended way of accessing a shadow and keeping it
32 | * synchronized with the device. The only thing the application needs to provide
33 | * in the derived class is the annotated device properties and their
34 | * corresponding getter and setter methods.
35 | */
36 | public class ShadowSample {
37 |
38 | private static AWSIotMqttClient awsIotClient;
39 |
40 | public static void setClient(AWSIotMqttClient client) {
41 | awsIotClient = client;
42 | }
43 |
44 | private static void initClient(CommandArguments arguments) {
45 | String clientEndpoint = arguments.getNotNull("clientEndpoint", SampleUtil.getConfig("clientEndpoint"));
46 | String clientId = arguments.getNotNull("clientId", SampleUtil.getConfig("clientId"));
47 |
48 | String certificateFile = arguments.get("certificateFile", SampleUtil.getConfig("certificateFile"));
49 | String privateKeyFile = arguments.get("privateKeyFile", SampleUtil.getConfig("privateKeyFile"));
50 | if (awsIotClient == null && certificateFile != null && privateKeyFile != null) {
51 | String algorithm = arguments.get("keyAlgorithm", SampleUtil.getConfig("keyAlgorithm"));
52 | KeyStorePasswordPair pair = SampleUtil.getKeyStorePasswordPair(certificateFile, privateKeyFile, algorithm);
53 |
54 | awsIotClient = new AWSIotMqttClient(clientEndpoint, clientId, pair.keyStore, pair.keyPassword);
55 | }
56 |
57 | if (awsIotClient == null) {
58 | String awsAccessKeyId = arguments.get("awsAccessKeyId", SampleUtil.getConfig("awsAccessKeyId"));
59 | String awsSecretAccessKey = arguments.get("awsSecretAccessKey", SampleUtil.getConfig("awsSecretAccessKey"));
60 | String sessionToken = arguments.get("sessionToken", SampleUtil.getConfig("sessionToken"));
61 |
62 | if (awsAccessKeyId != null && awsSecretAccessKey != null) {
63 | awsIotClient = new AWSIotMqttClient(clientEndpoint, clientId, awsAccessKeyId, awsSecretAccessKey,
64 | sessionToken);
65 | }
66 | }
67 |
68 | if (awsIotClient == null) {
69 | throw new IllegalArgumentException("Failed to construct client due to missing certificate or credentials.");
70 | }
71 | }
72 |
73 | public static void main(String args[]) throws InterruptedException, AWSIotException {
74 | CommandArguments arguments = CommandArguments.parse(args);
75 | initClient(arguments);
76 |
77 | awsIotClient.setWillMessage(new AWSIotMessage("client/disconnect", AWSIotQos.QOS0, awsIotClient.getClientId()));
78 |
79 | String thingName = arguments.getNotNull("thingName", SampleUtil.getConfig("thingName"));
80 | ConnectedWindow connectedWindow = new ConnectedWindow(thingName);
81 |
82 | awsIotClient.attach(connectedWindow);
83 | awsIotClient.connect();
84 |
85 | // Delete existing document if any
86 | connectedWindow.delete();
87 |
88 | AWSIotConnectionStatus status = AWSIotConnectionStatus.DISCONNECTED;
89 | while (true) {
90 | AWSIotConnectionStatus newStatus = awsIotClient.getConnectionStatus();
91 | if (!status.equals(newStatus)) {
92 | System.out.println(System.currentTimeMillis() + " Connection status changed to " + newStatus);
93 | status = newStatus;
94 | }
95 |
96 | Thread.sleep(1000);
97 | }
98 | }
99 |
100 | }
101 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java-samples/src/main/java/com/amazonaws/services/iot/client/sample/shadowEcho/ShadowEchoSample.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.sample.shadowEcho;
17 |
18 | import java.io.IOException;
19 |
20 | import com.amazonaws.services.iot.client.AWSIotMqttClient;
21 | import com.amazonaws.services.iot.client.AWSIotDevice;
22 | import com.amazonaws.services.iot.client.AWSIotException;
23 | import com.amazonaws.services.iot.client.AWSIotTimeoutException;
24 | import com.amazonaws.services.iot.client.sample.sampleUtil.CommandArguments;
25 | import com.amazonaws.services.iot.client.sample.sampleUtil.SampleUtil;
26 | import com.amazonaws.services.iot.client.sample.sampleUtil.SampleUtil.KeyStorePasswordPair;
27 | import com.fasterxml.jackson.databind.DeserializationFeature;
28 | import com.fasterxml.jackson.databind.ObjectMapper;
29 |
30 | /**
31 | * This example demonstrates how to use {@link AWSIotDevice} to directly access
32 | * the shadow document.
33 | */
34 | public class ShadowEchoSample {
35 |
36 | private static AWSIotMqttClient awsIotClient;
37 |
38 | public static void setClient(AWSIotMqttClient client) {
39 | awsIotClient = client;
40 | }
41 |
42 | private static void initClient(CommandArguments arguments) {
43 | String clientEndpoint = arguments.getNotNull("clientEndpoint", SampleUtil.getConfig("clientEndpoint"));
44 | String clientId = arguments.getNotNull("clientId", SampleUtil.getConfig("clientId"));
45 |
46 | String certificateFile = arguments.get("certificateFile", SampleUtil.getConfig("certificateFile"));
47 | String privateKeyFile = arguments.get("privateKeyFile", SampleUtil.getConfig("privateKeyFile"));
48 | if (awsIotClient == null && certificateFile != null && privateKeyFile != null) {
49 | String algorithm = arguments.get("keyAlgorithm", SampleUtil.getConfig("keyAlgorithm"));
50 | KeyStorePasswordPair pair = SampleUtil.getKeyStorePasswordPair(certificateFile, privateKeyFile, algorithm);
51 |
52 | awsIotClient = new AWSIotMqttClient(clientEndpoint, clientId, pair.keyStore, pair.keyPassword);
53 | }
54 |
55 | if (awsIotClient == null) {
56 | String awsAccessKeyId = arguments.get("awsAccessKeyId", SampleUtil.getConfig("awsAccessKeyId"));
57 | String awsSecretAccessKey = arguments.get("awsSecretAccessKey", SampleUtil.getConfig("awsSecretAccessKey"));
58 | String sessionToken = arguments.get("sessionToken", SampleUtil.getConfig("sessionToken"));
59 |
60 | if (awsAccessKeyId != null && awsSecretAccessKey != null) {
61 | awsIotClient = new AWSIotMqttClient(clientEndpoint, clientId, awsAccessKeyId, awsSecretAccessKey,
62 | sessionToken);
63 | }
64 | }
65 |
66 | if (awsIotClient == null) {
67 | throw new IllegalArgumentException("Failed to construct client due to missing certificate or credentials.");
68 | }
69 | }
70 |
71 | public static void main(String args[]) throws IOException, AWSIotException, AWSIotTimeoutException,
72 | InterruptedException {
73 | CommandArguments arguments = CommandArguments.parse(args);
74 | initClient(arguments);
75 |
76 | String thingName = arguments.getNotNull("thingName", SampleUtil.getConfig("thingName"));
77 | AWSIotDevice device = new AWSIotDevice(thingName);
78 |
79 | awsIotClient.attach(device);
80 | awsIotClient.connect();
81 |
82 | // Delete existing document if any
83 | device.delete();
84 |
85 | ObjectMapper objectMapper = new ObjectMapper();
86 | objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
87 |
88 | Thing thing = new Thing();
89 |
90 | while (true) {
91 | long desired = thing.state.desired.counter;
92 | thing.state.reported.counter = desired;
93 | thing.state.desired.counter = desired + 1;
94 |
95 | String jsonState = objectMapper.writeValueAsString(thing);
96 |
97 | try {
98 | // Send updated document to the shadow
99 | device.update(jsonState);
100 | System.out.println(System.currentTimeMillis() + ": >>> " + jsonState);
101 | } catch (AWSIotException e) {
102 | System.out.println(System.currentTimeMillis() + ": update failed for " + jsonState);
103 | continue;
104 | }
105 |
106 | try {
107 | // Retrieve updated document from the shadow
108 | String shadowState = device.get();
109 | System.out.println(System.currentTimeMillis() + ": <<< " + shadowState);
110 |
111 | thing = objectMapper.readValue(shadowState, Thing.class);
112 | } catch (AWSIotException e) {
113 | System.out.println(System.currentTimeMillis() + ": get failed for " + jsonState);
114 | continue;
115 | }
116 |
117 | Thread.sleep(1000);
118 | }
119 |
120 | }
121 |
122 | }
123 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java-samples/src/main/java/com/amazonaws/services/iot/client/sample/shadowEcho/Thing.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.sample.shadowEcho;
17 |
18 | /**
19 | * This POJO class defines a simple document for communicating with the AWS IoT
20 | * thing. It only contains one property ({@code counter}).
21 | */
22 | public class Thing {
23 |
24 | public State state = new State();
25 |
26 | public static class State {
27 | public Document reported = new Document();
28 | public Document desired = new Document();
29 | }
30 |
31 | public static class Document {
32 | public long counter = 1;
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java-samples/src/main/resources/com/amazonaws/services/iot/client/sample/sampleUtil/aws-iot-sdk-samples.properties:
--------------------------------------------------------------------------------
1 | # Client endpoint, e.g. .iot.us-east-1.amazonaws.com
2 | clientEndpoint=
3 |
4 | # Client ID, unique client ID per connection
5 | clientId=
6 |
7 | # Client certificate file
8 | certificateFile=
9 |
10 | # Client private key file
11 | privateKeyFile=
12 |
13 | # Thing name
14 | thingName=
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 | com.amazonaws
5 | aws-iot-device-sdk-java-pom
6 | 0.0.1-dev
7 |
8 | aws-iot-device-sdk-java
9 |
10 |
11 | org.mockito
12 | mockito-core
13 | 2.25.0
14 | test
15 |
16 |
17 | junit
18 | junit
19 | 4.13.1
20 | test
21 |
22 |
23 | org.projectlombok
24 | lombok
25 | 1.18.24
26 | provided
27 |
28 |
29 | com.fasterxml.jackson.core
30 | jackson-core
31 | 2.13.4
32 |
33 |
34 | com.fasterxml.jackson.core
35 | jackson-databind
36 | 2.13.4.2
37 |
38 |
39 | org.eclipse.paho
40 | org.eclipse.paho.client.mqttv3
41 | [1.2.4]
42 |
43 |
44 | com.amazonaws
45 | aws-java-sdk-secretsmanager
46 | 1.12.315
47 |
48 |
49 |
50 | target/generated-sources/delombok
51 |
52 |
53 | org.apache.maven.plugins
54 | maven-compiler-plugin
55 | 3.5.1
56 |
57 |
58 | org.projectlombok
59 | lombok-maven-plugin
60 | 1.18.20.0
61 |
62 |
63 | generate-sources
64 |
65 | delombok
66 |
67 |
68 | false
69 | src/main/java
70 |
71 |
72 |
73 |
74 |
75 | org.apache.maven.plugins
76 | maven-source-plugin
77 | 3.0.0
78 |
79 |
80 | attach-sources
81 |
82 | jar-no-fork
83 |
84 |
85 |
86 |
87 |
88 | org.apache.maven.plugins
89 | maven-javadoc-plugin
90 | 2.10.3
91 |
92 | 8
93 | target/generated-sources/delombok
94 |
95 |
96 |
97 | attach-javadocs
98 |
99 | jar
100 |
101 |
102 |
103 |
104 |
105 | maven-surefire-plugin
106 | 2.22.2
107 |
108 |
109 | main-run
110 |
111 | test
112 |
113 |
114 | src/test/java/com/amazonaws/services/iot/client/system_props_mutualAuth.properties
115 |
116 |
117 |
118 | default-test
119 |
120 | test
121 |
122 |
123 | src/test/java/com/amazonaws/services/iot/client/system_props_websocket.properties
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 | org.codehaus.mojo
134 | findbugs-maven-plugin
135 | 3.0.5
136 |
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/AWSIotConfig.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client;
17 |
18 | /**
19 | * The class provides default values for the library. All the values defined
20 | * here can be overridden at runtime through setter functions in
21 | * {@link AWSIotMqttClient} and {@link AWSIotDevice}.
22 | */
23 | public class AWSIotConfig {
24 |
25 | /**
26 | * The default value for number of client threads. See also
27 | * {@link AWSIotMqttClient#getNumOfClientThreads()}.
28 | */
29 | public static final int NUM_OF_CLIENT_THREADS = 1;
30 |
31 | /**
32 | * The default value for client connection timeout (milliseconds). See also
33 | * {@link AWSIotMqttClient#getConnectionTimeout()}.
34 | */
35 | public static final int CONNECTION_TIMEOUT = 30000;
36 |
37 | /**
38 | * The default value for service acknowledge timeout (milliseconds). See
39 | * also {@link AWSIotMqttClient#getServerAckTimeout()}.
40 | */
41 | public static final int SERVER_ACK_TIMEOUT = 3000;
42 |
43 | /**
44 | * The default value for client keep-alive interval (milliseconds). See also
45 | * {@link AWSIotMqttClient#getKeepAliveInterval()}.
46 | */
47 | public static final int KEEP_ALIVE_INTERVAL = 600000;
48 |
49 | /**
50 | * The default value for maximum connection retry times. See also
51 | * {@link AWSIotMqttClient#getMaxConnectionRetries()}.
52 | */
53 | public static final int MAX_CONNECTION_RETRIES = 5;
54 |
55 | /**
56 | * The default value for connection base retry delay (milliseconds). See
57 | * also {@link AWSIotMqttClient#getBaseRetryDelay()}.
58 | */
59 | public static final int CONNECTION_BASE_RETRY_DELAY = 3000;
60 |
61 | /**
62 | * The default value for connection maximum retry delay (milliseconds). See
63 | * also {@link AWSIotMqttClient#getMaxRetryDelay()}.
64 | */
65 | public static final int CONNECTION_MAX_RETRY_DELAY = 30000;
66 |
67 | /**
68 | * The default value for clean session connections.
69 | * See also {@link AWSIotMqttClient#isCleanSession()}.
70 | */
71 | public static final boolean CLEAN_SESSION = true;
72 |
73 | /**
74 | * The default value for maximum offline queue size. See also
75 | * {@link AWSIotMqttClient#getMaxOfflineQueueSize()}.
76 | */
77 | public static final int MAX_OFFLINE_QUEUE_SIZE = 64;
78 |
79 | /**
80 | * The default value for device reporting interval (milliseconds). See also
81 | * {@link AWSIotDevice#getReportInterval()}.
82 | */
83 | public static final int DEVICE_REPORT_INTERVAL = 3000;
84 |
85 | /**
86 | * The default value for enabling device update versioning. See also
87 | * {@link AWSIotDevice#isEnableVersioning()}.
88 | */
89 | public static final boolean DEVICE_ENABLE_VERSIONING = false;
90 |
91 | /**
92 | * The default value for device reporting QoS level. See also
93 | * {@link AWSIotDevice#getDeviceReportQos()}.
94 | */
95 | public static final int DEVICE_REPORT_QOS = 0;
96 |
97 | /**
98 | * The default value for the QoS level for subscribing to shadow updates.
99 | * See also {@link AWSIotDevice#getShadowUpdateQos()}.
100 | */
101 | public static final int DEVICE_SHADOW_UPDATE_QOS = 0;
102 |
103 | /**
104 | * The default value for the QoS level for publishing shadow methods. See
105 | * also {@link AWSIotDevice#getMethodQos()}.
106 | */
107 | public static final int DEVICE_METHOD_QOS = 0;
108 |
109 | /**
110 | * The default value for the QoS level for subscribing to shadow method
111 | * acknowledgement. See also {@link AWSIotDevice#getMethodAckQos()}.
112 | */
113 | public static final int DEVICE_METHOD_ACK_QOS = 0;
114 |
115 | }
116 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/AWSIotConnectionStatus.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client;
17 |
18 | /**
19 | * Connection status that can be retrieved through
20 | * {@link AWSIotMqttClient#getConnectionStatus()}.
21 | */
22 | public enum AWSIotConnectionStatus {
23 |
24 | /** Client successfully connected. */
25 | CONNECTED,
26 |
27 | /** Not connected. */
28 | DISCONNECTED,
29 |
30 | /** Automatically reconnecting after connection loss. */
31 | RECONNECTING
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/AWSIotDeviceErrorCode.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client;
17 |
18 | /**
19 | * These error codes are used by the server in acknowledgement message for the
20 | * shadow methods, namely Get, Update, and Delete.
21 | */
22 | public enum AWSIotDeviceErrorCode {
23 |
24 | /** The bad request. */
25 | BAD_REQUEST(400),
26 | /** The Unauthorized. */
27 | UNAUTHORIZED(401),
28 | /** The Forbidden. */
29 | FORBIDDEN(403),
30 | /** The Not found. */
31 | NOT_FOUND(404),
32 | /** The Conflict. */
33 | CONFLICT(409),
34 | /** The Payload too large. */
35 | PAYLOAD_TOO_LARGE(413),
36 | /** The Unsupported media type. */
37 | UNSUPPORTED_MEDIA_TYPE(415),
38 | /** The Too many requests. */
39 | TOO_MANY_REQUESTS(429),
40 | /** The Internal service failure. */
41 | INTERNAL_SERVICE_FAILURE(429);
42 |
43 | /** The error code. */
44 | private final long errorCode;
45 |
46 | /**
47 | * Instantiates a new device error code object.
48 | *
49 | * @param errorCode
50 | * the error code
51 | */
52 | private AWSIotDeviceErrorCode(final long errorCode) {
53 | this.errorCode = errorCode;
54 | }
55 |
56 | /**
57 | * Gets the error code value.
58 | *
59 | * @return the error code value
60 | */
61 | public long getValue() {
62 | return this.errorCode;
63 | }
64 |
65 | /**
66 | * Returns the Enum representation of the error code value
67 | *
68 | * @param code
69 | * the error code value
70 | * @return the Enum representation of the error code, or null if the error
71 | * code is unknown
72 | */
73 | public static AWSIotDeviceErrorCode valueOf(long code) {
74 | for (AWSIotDeviceErrorCode errorCode : AWSIotDeviceErrorCode.values()) {
75 | if (errorCode.errorCode == code) {
76 | return errorCode;
77 | }
78 | }
79 |
80 | return null;
81 | }
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/AWSIotDeviceProperty.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client;
17 |
18 | import java.lang.annotation.Retention;
19 | import java.lang.annotation.RetentionPolicy;
20 |
21 | /**
22 | * Annotation class that is used to annotate properties in {@link AWSIotDevice}.
23 | * Properties annotated must be accessible via corresponding getter and setter
24 | * methods.
25 | *
26 | * With optional values provided by this annotation class, properties can also
27 | * be configured to disable reporting to the shadow or not to accept updates
28 | * from the shadow. If {@link #enableReport()} is disabled, property getter
29 | * function is not required. Likewise, if {@link #allowUpdate()} is disabled for
30 | * a property, its setter method is not required.
31 | *
32 | */
33 | @Retention(RetentionPolicy.RUNTIME)
34 | public @interface AWSIotDeviceProperty {
35 |
36 | /**
37 | * An optional name can be provided to the annotated property, which will be
38 | * used for publishing to the shadow as well as receiving updates from the
39 | * shadow. If not provided, the actual property name will be used.
40 | *
41 | * @return the name of the property.
42 | */
43 | String name() default "";
44 |
45 | /**
46 | * Enable reporting the annotated property to the shadow. It's enabled by
47 | * default.
48 | *
49 | * @return true to enable reporting to the shadow, false otherwise.
50 | */
51 | boolean enableReport() default true;
52 |
53 | /**
54 | * Allow updates from the shadow. It's enabled by default.
55 | *
56 | * @return true to allow updates from the shadow, false otherwise.
57 | */
58 | boolean allowUpdate() default true;
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/AWSIotException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client;
17 |
18 | import lombok.Getter;
19 | import lombok.Setter;
20 |
21 | /**
22 | * This is a generic exception that can be thrown in most of the APIs, blocking
23 | * and non-blocking, by the library.
24 | */
25 | public class AWSIotException extends Exception {
26 |
27 | /** The Constant serialVersionUID. */
28 | private static final long serialVersionUID = 1L;
29 |
30 | /**
31 | * Error code for shadow methods. It's only applicable to exceptions thrown
32 | * by those shadow method APIs.
33 | *
34 | * @param errorCode the new error code for the shadow method exception
35 | * @return the error code of the shadow method exception
36 | */
37 | @Getter
38 | @Setter
39 | private AWSIotDeviceErrorCode errorCode;
40 |
41 | /**
42 | * Instantiates a new exception object.
43 | *
44 | * @param message
45 | * the error message
46 | */
47 | public AWSIotException(String message) {
48 | super(message);
49 | }
50 |
51 | /**
52 | * Instantiates a new exception object.
53 | *
54 | * @param errorCode
55 | * the error code
56 | * @param message
57 | * the error message
58 | */
59 | public AWSIotException(AWSIotDeviceErrorCode errorCode, String message) {
60 | super(message);
61 | this.errorCode = errorCode;
62 | }
63 |
64 | /**
65 | * Instantiates a new exception object.
66 | *
67 | * @param cause
68 | * the cause. A null value is permitted, and indicates that the
69 | * cause is nonexistent or unknown.
70 | */
71 | public AWSIotException(Throwable cause) {
72 | super(cause);
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/AWSIotMessage.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client;
17 |
18 | import java.io.UnsupportedEncodingException;
19 |
20 | import com.amazonaws.services.iot.client.core.AwsIotMessageCallback;
21 | import com.amazonaws.services.iot.client.core.AwsIotRuntimeException;
22 |
23 | import lombok.Getter;
24 | import lombok.Setter;
25 |
26 | /**
27 | * A common data structure that is used in a lot of non-blocking APIs in this
28 | * library.
29 | *
30 | * It provides common data elements, such as {@link #topic}, {@link #qos}, and
31 | * {@link #payload}, used by the APIs.
32 | *
33 | *
34 | * It also contains callback functions that can be overridden to provide
35 | * customized handlers. The callback functions are invoked when a non-blocking
36 | * API call has completed successfully, unsuccessfully, or timed out.
37 | * Applications wish to have customized callback functions must extend this
38 | * class or its child classes, such as {@link AWSIotTopic}.
39 | */
40 | public class AWSIotMessage implements AwsIotMessageCallback {
41 |
42 | /**
43 | * The topic the message is received from or published to.
44 | *
45 | * @param topic the new topic of the message
46 | * @return the current topic of the message
47 | */
48 | @Getter
49 | @Setter
50 | protected String topic;
51 |
52 | /**
53 | * The MQTT QoS level for the message.
54 | *
55 | * @param qos the new QoS level
56 | * @return the current QoS level
57 | */
58 | @Getter
59 | @Setter
60 | protected AWSIotQos qos;
61 |
62 | /**
63 | * The payload of the message.
64 | */
65 | protected byte[] payload;
66 |
67 | /**
68 | * Error code for shadow methods. It's only applicable to messages returned
69 | * by those shadow method APIs.
70 | *
71 | * @param errorCode the new error code for the shadow method
72 | * @return the current error code of the shadow method
73 | */
74 | @Getter
75 | @Setter
76 | protected AWSIotDeviceErrorCode errorCode;
77 |
78 | /**
79 | * Error message for shadow methods. It's only applicable to messages
80 | * returned by those shadow method APIs.
81 | *
82 | * @param errorMessage the new error message for the shadow method
83 | * @return the current error message of the shadow method
84 | */
85 | @Getter
86 | @Setter
87 | protected String errorMessage;
88 |
89 | /**
90 | * Instantiates a new message object.
91 | *
92 | * @param topic
93 | * the topic of the message
94 | * @param qos
95 | * the QoS level of the message
96 | */
97 | public AWSIotMessage(String topic, AWSIotQos qos) {
98 | this.topic = topic;
99 | this.qos = qos;
100 | }
101 |
102 | /**
103 | * Instantiates a new message object.
104 | *
105 | * @param topic
106 | * the topic of the message
107 | * @param qos
108 | * the QoS level of the message
109 | * @param payload
110 | * the payload of the message
111 | */
112 | public AWSIotMessage(String topic, AWSIotQos qos, byte[] payload) {
113 | this.topic = topic;
114 | this.qos = qos;
115 | setPayload(payload);
116 | }
117 |
118 | /**
119 | * Instantiates a new message object.
120 | *
121 | * @param topic
122 | * the topic of the message
123 | * @param qos
124 | * the QoS level of the message
125 | * @param payload
126 | * the payload of the message
127 | */
128 | public AWSIotMessage(String topic, AWSIotQos qos, String payload) {
129 | this.topic = topic;
130 | this.qos = qos;
131 | setStringPayload(payload);
132 | }
133 |
134 | /**
135 | * Gets the byte array payload.
136 | *
137 | * @return the byte array payload
138 | */
139 | public byte[] getPayload() {
140 | if (payload == null) {
141 | return null;
142 | }
143 |
144 | return payload.clone();
145 | }
146 |
147 | /**
148 | * Sets the byte array payload.
149 | *
150 | * @param payload
151 | * the new byte array payload
152 | */
153 | public void setPayload(byte[] payload) {
154 | if (payload == null) {
155 | this.payload = null;
156 | return;
157 | }
158 |
159 | this.payload = payload.clone();
160 | }
161 |
162 | /**
163 | * Gets the string payload.
164 | *
165 | * @return the string payload
166 | */
167 | public String getStringPayload() {
168 | if (payload == null) {
169 | return null;
170 | }
171 |
172 | String str;
173 | try {
174 | str = new String(payload, "UTF-8");
175 | } catch (UnsupportedEncodingException e) {
176 | throw new AwsIotRuntimeException(e);
177 | }
178 | return str;
179 | }
180 |
181 | /**
182 | * Sets the string payload.
183 | *
184 | * @param payload
185 | * the new string payload
186 | */
187 | public void setStringPayload(String payload) {
188 | if (payload == null) {
189 | this.payload = null;
190 | return;
191 | }
192 |
193 | try {
194 | this.payload = payload.getBytes("UTF-8");
195 | } catch (UnsupportedEncodingException e) {
196 | throw new AwsIotRuntimeException(e);
197 | }
198 | }
199 |
200 | /**
201 | * Callback function to be invoked a non-block API has completed
202 | * successfully.
203 | */
204 | @Override
205 | public void onSuccess() {
206 | // Default callback implementation is no-op
207 | }
208 |
209 | /**
210 | * Callback function to be invoked a non-block API has completed
211 | * unsuccessfully.
212 | */
213 | @Override
214 | public void onFailure() {
215 | // Default callback implementation is no-op
216 | }
217 |
218 | /**
219 | * Callback function to be invoked a non-block API has timed out.
220 | */
221 | @Override
222 | public void onTimeout() {
223 | // Default callback implementation is no-op
224 | }
225 |
226 | }
227 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/AWSIotQos.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client;
17 |
18 | /**
19 | * QoS definitions. The AWS IoT service supports QoS0 and QoS1 defined by the
20 | * MQTT protocol.
21 | */
22 | public enum AWSIotQos {
23 |
24 | /** The QoS0. */
25 | QOS0(0),
26 |
27 | /** The QoS1. */
28 | QOS1(1);
29 |
30 | /** The qos. */
31 | private final int qos;
32 |
33 | /**
34 | * Instantiates a QoS object.
35 | *
36 | * @param qos
37 | * the QoS level
38 | */
39 | private AWSIotQos(final int qos) {
40 | this.qos = qos;
41 | }
42 |
43 | /**
44 | * Gets the integer representation of the QoS
45 | *
46 | * @return the integer value of the QoS
47 | */
48 | public int getValue() {
49 | return this.qos;
50 | }
51 |
52 | /**
53 | * Gets the Enum representation of the QoS
54 | *
55 | * @param qos
56 | * the integer value of the QoS
57 | * @return the Enum value of the QoS
58 | */
59 | public static AWSIotQos valueOf(int qos) {
60 | if (qos == 0) {
61 | return QOS0;
62 | } else if (qos == 1) {
63 | return QOS1;
64 | } else {
65 | throw new IllegalArgumentException("QoS not supported");
66 | }
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/AWSIotTimeoutException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client;
17 |
18 | /**
19 | * This timeout exception can be thrown by the blocking APIs in this library
20 | * when expected time has elapsed.
21 | */
22 | public class AWSIotTimeoutException extends Exception {
23 |
24 | /** The Constant serialVersionUID. */
25 | private static final long serialVersionUID = 1L;
26 |
27 | /**
28 | * Instantiates a new exception object.
29 | *
30 | * @param message
31 | * the error message
32 | */
33 | public AWSIotTimeoutException(String message) {
34 | super(message);
35 | }
36 |
37 | /**
38 | * Instantiates a new exception object.
39 | *
40 | * @param cause
41 | * the cause. A null value is permitted, and indicates that the
42 | * cause is nonexistent or unknown.
43 | */
44 | public AWSIotTimeoutException(Throwable cause) {
45 | super(cause);
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/AWSIotTopic.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client;
17 |
18 | import com.amazonaws.services.iot.client.core.AwsIotTopicCallback;
19 |
20 | /**
21 | * This class is used for subscribing to a topic in the subscription APIs, such
22 | * as {@link AWSIotMqttClient#subscribe(AWSIotTopic topic)}.
23 | *
24 | * In contains a callback function, {@link #onMessage}, that is invoked when a
25 | * subscribed message has arrived. In most cases, applications are expected to
26 | * override the default {@link #onMessage} method in order to access the message
27 | * payload.
28 | *
29 | *
30 | * This class extends {@link AWSIotMessage}, therefore callback functions in
31 | * {@link AWSIotMessage} can also be overridden if the application wishes to be
32 | * invoked for the outcomes of the subscription API. For more details, please
33 | * refer to {@link AWSIotMessage}.
34 | *
35 | */
36 | public class AWSIotTopic extends AWSIotMessage implements AwsIotTopicCallback {
37 |
38 | /**
39 | * Instantiates a new topic object.
40 | *
41 | * @param topic
42 | * the topic to be subscribed to
43 | */
44 | public AWSIotTopic(String topic) {
45 | super(topic, AWSIotQos.QOS0);
46 | }
47 |
48 | /**
49 | * Instantiates a new topic object.
50 | *
51 | * @param topic
52 | * the topic to be subscribed to
53 | * @param qos
54 | * the MQTT QoS level for the subscription
55 | */
56 | public AWSIotTopic(String topic, AWSIotQos qos) {
57 | super(topic, qos);
58 | }
59 |
60 | /**
61 | * Callback function to be invoked upon the arrival of a subscribed message.
62 | *
63 | * @param message
64 | * the message received
65 | */
66 | @Override
67 | public void onMessage(AWSIotMessage message) {
68 | // Default callback implementation is no-op
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/auth/Credentials.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 | * SPDX-License-Identifier: Apache-2.0.
4 | */
5 |
6 | package com.amazonaws.services.iot.client.auth;
7 |
8 | /**
9 | * A class representing a set of AWS credentials.
10 | */
11 | public class Credentials {
12 |
13 | private String accessKeyId;
14 | private String secretAccessKey;
15 | private String sessionToken;
16 |
17 | public Credentials(String accessKeyId, String secretAccessKey) {
18 | this(accessKeyId, secretAccessKey, null);
19 | }
20 |
21 | public Credentials(String accessKeyId, String secretAccessKey, String sessionToken) {
22 | this.accessKeyId = accessKeyId.trim();
23 | this.secretAccessKey = secretAccessKey;
24 | this.sessionToken = sessionToken;
25 | }
26 |
27 | public String getAccessKeyId() { return accessKeyId; }
28 | public String getSecretAccessKey() { return secretAccessKey; }
29 | public String getSessionToken() { return sessionToken; }
30 | }
31 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/auth/CredentialsProvider.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 | * SPDX-License-Identifier: Apache-2.0.
4 | */
5 |
6 | package com.amazonaws.services.iot.client.auth;
7 |
8 | public interface CredentialsProvider {
9 |
10 | Credentials getCredentials();
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/auth/StaticCredentialsProvider.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 | * SPDX-License-Identifier: Apache-2.0.
4 | */
5 |
6 | package com.amazonaws.services.iot.client.auth;
7 |
8 | public class StaticCredentialsProvider implements CredentialsProvider {
9 |
10 | private Credentials credentials;
11 |
12 | public StaticCredentialsProvider(Credentials credentials) {
13 | this.credentials = credentials;
14 | }
15 |
16 | public Credentials getCredentials() {
17 | return credentials;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/core/AwsIotConnectionCallback.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.core;
17 |
18 | /**
19 | * This interface class defines functions called under different connection
20 | * events.
21 | */
22 | public interface AwsIotConnectionCallback {
23 |
24 | /**
25 | * On connection success.
26 | */
27 | void onConnectionSuccess();
28 |
29 | /**
30 | * On connection failure.
31 | */
32 | void onConnectionFailure();
33 |
34 | /**
35 | * On connection closed.
36 | */
37 | void onConnectionClosed();
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/core/AwsIotConnectionType.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.core;
17 |
18 | /**
19 | * Connection types supported by this library.
20 | */
21 | public enum AwsIotConnectionType {
22 |
23 | /** The mqtt over tls. */
24 | MQTT_OVER_TLS,
25 |
26 | /** The mqtt over websocket. */
27 | MQTT_OVER_WEBSOCKET
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/core/AwsIotMessageCallback.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.core;
17 |
18 | /**
19 | * This interface class defines functions called under different message related
20 | * events.
21 | */
22 | public interface AwsIotMessageCallback {
23 |
24 | /**
25 | * On success.
26 | */
27 | void onSuccess();
28 |
29 | /**
30 | * On failure.
31 | */
32 | void onFailure();
33 |
34 | /**
35 | * On timeout.
36 | */
37 | void onTimeout();
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/core/AwsIotRetryableException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.core;
17 |
18 | /**
19 | * This exception class is used internally in the library to track retryable
20 | * events.
21 | */
22 | public class AwsIotRetryableException extends Exception {
23 |
24 | private static final long serialVersionUID = 1L;
25 |
26 | public AwsIotRetryableException(String message) {
27 | super(message);
28 | }
29 |
30 | public AwsIotRetryableException(Throwable e) {
31 | super(e);
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/core/AwsIotRuntimeException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.core;
17 |
18 | /**
19 | * This exception class is used internally in the library for runtime errors.
20 | */
21 | public class AwsIotRuntimeException extends RuntimeException {
22 |
23 | private static final long serialVersionUID = 1L;
24 |
25 | public AwsIotRuntimeException(Throwable e) {
26 | super(e);
27 | }
28 |
29 | public AwsIotRuntimeException(String message) {
30 | super(message);
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/core/AwsIotTlsConnection.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.core;
17 |
18 | import java.security.KeyStore;
19 | import javax.net.SocketFactory;
20 | import javax.net.ssl.SSLSocketFactory;
21 |
22 | import com.amazonaws.services.iot.client.AWSIotException;
23 | import com.amazonaws.services.iot.client.mqtt.AwsIotMqttConnection;
24 | import com.amazonaws.services.iot.client.util.AwsIotTlsSocketFactory;
25 |
26 | /**
27 | * This is a thin layer on top of {@link AwsIotMqttConnection} that provides a
28 | * TLS v1.2 based communication channel to the MQTT implementation.
29 | */
30 | public class AwsIotTlsConnection extends AwsIotMqttConnection {
31 |
32 | public AwsIotTlsConnection(AbstractAwsIotClient client, KeyStore keyStore, String keyPassword)
33 | throws AWSIotException {
34 | super(client, new AwsIotTlsSocketFactory(keyStore, keyPassword), "ssl://" + client.getClientEndpoint() + ":" + client.getPort());
35 | }
36 |
37 | public AwsIotTlsConnection(AbstractAwsIotClient client, SSLSocketFactory socketFactory) throws AWSIotException {
38 | super(client, new AwsIotTlsSocketFactory(socketFactory), "ssl://" + client.getClientEndpoint() + ":" + client.getPort());
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/core/AwsIotTopicCallback.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.core;
17 |
18 | import com.amazonaws.services.iot.client.AWSIotMessage;
19 |
20 | /**
21 | * This interface class defines the function called when subscribed message has
22 | * arrived.
23 | */
24 | public interface AwsIotTopicCallback {
25 |
26 | void onMessage(AWSIotMessage message);
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/core/AwsIotWebsocketConnection.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.core;
17 |
18 | import java.util.HashSet;
19 | import java.util.Set;
20 |
21 | import com.amazonaws.services.iot.client.auth.CredentialsProvider;
22 | import com.amazonaws.services.iot.client.AWSIotException;
23 | import com.amazonaws.services.iot.client.mqtt.AwsIotMqttConnection;
24 | import com.amazonaws.services.iot.client.util.AwsIotWebSocketUrlSigner;
25 |
26 | /**
27 | * This is a thin layer on top of {@link AwsIotMqttConnection} that provides a
28 | * WebSocket based communication channel to the MQTT implementation.
29 | */
30 | public class AwsIotWebsocketConnection extends AwsIotMqttConnection {
31 |
32 | private AwsIotWebSocketUrlSigner urlSigner;
33 |
34 | public AwsIotWebsocketConnection(AbstractAwsIotClient client, String awsAccessKeyId, String awsSecretAccessKey)
35 | throws AWSIotException {
36 | this(client, awsAccessKeyId, awsSecretAccessKey, null);
37 | }
38 |
39 | public AwsIotWebsocketConnection(AbstractAwsIotClient client, String awsAccessKeyId, String awsSecretAccessKey,
40 | String sessionToken, String region) throws AWSIotException {
41 | super(client, null, "wss://" + client.getClientEndpoint() + ":443");
42 |
43 | // Port number must be included in the endpoint for signing otherwise
44 | // the signature verification will fail. This is because the Paho client
45 | // library always includes port number in the host line of the
46 | // HTTP request header, e.g "Host: data.iot.us-east-1.amazonaws.com:443".
47 | urlSigner = new AwsIotWebSocketUrlSigner(client.getClientEndpoint() + ":443", region);
48 | urlSigner.updateCredentials(awsAccessKeyId, awsSecretAccessKey, sessionToken);
49 | }
50 |
51 | public AwsIotWebsocketConnection(AbstractAwsIotClient client, String awsAccessKeyId, String awsSecretAccessKey,
52 | String sessionToken) throws AWSIotException {
53 | //setting the region blank to ensure it's determined from the client Endpoint
54 | this(client, awsAccessKeyId, awsSecretAccessKey, sessionToken, "");
55 | }
56 |
57 | public AwsIotWebsocketConnection(AbstractAwsIotClient client, CredentialsProvider provider, String region) throws AWSIotException {
58 | super(client, null, "wss://" + client.getClientEndpoint() + ":443");
59 |
60 | // Port number must be included in the endpoint for signing otherwise
61 | // the signature verification will fail. This is because the Paho client
62 | // library always includes port number in the host line of the
63 | // HTTP request header, e.g "Host: data.iot.us-east-1.amazonaws.com:443".
64 | urlSigner = new AwsIotWebSocketUrlSigner(client.getClientEndpoint() + ":443", provider, region);
65 | }
66 |
67 | @Override
68 | public void updateCredentials(String awsAccessKeyId, String awsSecretAccessKey, String sessionToken) {
69 | urlSigner.updateCredentials(awsAccessKeyId, awsSecretAccessKey, sessionToken);
70 | }
71 |
72 | @Override
73 | public Set getServerUris() {
74 | Set uris = new HashSet<>();
75 | try {
76 | uris.add(urlSigner.getSignedUrl(null));
77 | } catch (AWSIotException e) {
78 | throw new AwsIotRuntimeException(e);
79 | }
80 |
81 | return uris;
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/mqtt/AwsIotMqttClientListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.mqtt;
17 |
18 | import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
19 | import org.eclipse.paho.client.mqttv3.MqttCallback;
20 | import org.eclipse.paho.client.mqttv3.MqttMessage;
21 |
22 | import com.amazonaws.services.iot.client.AWSIotMessage;
23 | import com.amazonaws.services.iot.client.AWSIotQos;
24 | import com.amazonaws.services.iot.client.core.AbstractAwsIotClient;
25 |
26 | /**
27 | * This class implements listener functions for client related events from the
28 | * Paho MQTT library.
29 | */
30 | public class AwsIotMqttClientListener implements MqttCallback {
31 |
32 | private AbstractAwsIotClient client;
33 |
34 | public AwsIotMqttClientListener(AbstractAwsIotClient client) {
35 | this.client = client;
36 | }
37 |
38 | @Override
39 | public void connectionLost(Throwable arg0) {
40 | client.scheduleTask(new Runnable() {
41 | @Override
42 | public void run() {
43 | client.getConnection().onConnectionFailure();
44 | }
45 | });
46 | }
47 |
48 | @Override
49 | public void deliveryComplete(IMqttDeliveryToken arg0) {
50 | // Callback is not used
51 | }
52 |
53 | @Override
54 | public void messageArrived(String topic, MqttMessage arg1) throws Exception {
55 | AWSIotMessage message = new AWSIotMessage(topic, AWSIotQos.valueOf(arg1.getQos()), arg1.getPayload());
56 | client.dispatch(message);
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/mqtt/AwsIotMqttConnection.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.mqtt;
17 |
18 | import java.util.HashSet;
19 | import java.util.Set;
20 |
21 | import javax.net.SocketFactory;
22 |
23 | import org.eclipse.paho.client.mqttv3.MqttAsyncClient;
24 | import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
25 | import org.eclipse.paho.client.mqttv3.MqttException;
26 | import org.eclipse.paho.client.mqttv3.MqttMessage;
27 | import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
28 |
29 | import com.amazonaws.services.iot.client.AWSIotException;
30 | import com.amazonaws.services.iot.client.AWSIotMessage;
31 | import com.amazonaws.services.iot.client.core.AbstractAwsIotClient;
32 | import com.amazonaws.services.iot.client.core.AwsIotConnection;
33 | import com.amazonaws.services.iot.client.core.AwsIotMessageCallback;
34 | import com.amazonaws.services.iot.client.core.AwsIotRetryableException;
35 |
36 | import lombok.Getter;
37 | import lombok.Setter;
38 |
39 | /**
40 | * This class extends {@link AwsIotConnection} to provide the basic MQTT pub/sub
41 | * functionalities using the Paho MQTT library.
42 | */
43 | @Getter
44 | @Setter
45 | public class AwsIotMqttConnection extends AwsIotConnection {
46 |
47 | // Release Script will replace the version string on release. Refer to codebuild/cd/promote-release.yml
48 | private static final String USERNAME_METRIC_STRING = "?SDK=Java&Version=0.0.1-dev";
49 | private final SocketFactory socketFactory;
50 |
51 | private MqttAsyncClient mqttClient;
52 | private AwsIotMqttMessageListener messageListener;
53 | private AwsIotMqttClientListener clientListener;
54 |
55 | public AwsIotMqttConnection(AbstractAwsIotClient client, SocketFactory socketFactory, String serverUri)
56 | throws AWSIotException {
57 | super(client);
58 |
59 | this.socketFactory = socketFactory;
60 |
61 | messageListener = new AwsIotMqttMessageListener(client);
62 | clientListener = new AwsIotMqttClientListener(client);
63 |
64 | try {
65 | mqttClient = new MqttAsyncClient(serverUri, client.getClientId(), new MemoryPersistence());
66 | mqttClient.setCallback(clientListener);
67 | } catch (MqttException e) {
68 | throw new AWSIotException(e);
69 | }
70 | }
71 |
72 | AwsIotMqttConnection(AbstractAwsIotClient client, MqttAsyncClient mqttClient) throws AWSIotException {
73 | super(client);
74 | this.mqttClient = mqttClient;
75 | this.socketFactory = null;
76 | }
77 |
78 | public void openConnection(AwsIotMessageCallback callback) throws AWSIotException {
79 | try {
80 | AwsIotMqttConnectionListener connectionListener = new AwsIotMqttConnectionListener(client, true, callback);
81 | MqttConnectOptions options = buildMqttConnectOptions(client, socketFactory);
82 | mqttClient.connect(options, null, connectionListener);
83 | } catch (MqttException e) {
84 | throw new AWSIotException(e);
85 | }
86 | }
87 |
88 | public void closeConnection(AwsIotMessageCallback callback) throws AWSIotException {
89 | try {
90 | AwsIotMqttConnectionListener connectionListener = new AwsIotMqttConnectionListener(client, false, callback);
91 | mqttClient.disconnect(0, null, connectionListener);
92 | } catch (MqttException e) {
93 | throw new AWSIotException(e);
94 | }
95 | }
96 |
97 | @Override
98 | public void publishMessage(AWSIotMessage message) throws AWSIotException, AwsIotRetryableException {
99 | String topic = message.getTopic();
100 | MqttMessage mqttMessage = new MqttMessage(message.getPayload());
101 | mqttMessage.setQos(message.getQos().getValue());
102 |
103 | try {
104 | mqttClient.publish(topic, mqttMessage, message, messageListener);
105 | } catch (MqttException e) {
106 | if (e.getReasonCode() == MqttException.REASON_CODE_CLIENT_NOT_CONNECTED) {
107 | throw new AwsIotRetryableException(e);
108 | } else {
109 | throw new AWSIotException(e);
110 | }
111 | }
112 | }
113 |
114 | @Override
115 | public void subscribeTopic(AWSIotMessage message) throws AWSIotException, AwsIotRetryableException {
116 | try {
117 | mqttClient.subscribe(message.getTopic(), message.getQos().getValue(), message, messageListener);
118 | } catch (MqttException e) {
119 | if (e.getReasonCode() == MqttException.REASON_CODE_CLIENT_NOT_CONNECTED) {
120 | throw new AwsIotRetryableException(e);
121 | } else {
122 | throw new AWSIotException(e);
123 | }
124 | }
125 | }
126 |
127 | @Override
128 | public void unsubscribeTopic(AWSIotMessage message) throws AWSIotException, AwsIotRetryableException {
129 | try {
130 | mqttClient.unsubscribe(message.getTopic(), message, messageListener);
131 | } catch (MqttException e) {
132 | if (e.getReasonCode() == MqttException.REASON_CODE_CLIENT_NOT_CONNECTED) {
133 | throw new AwsIotRetryableException(e);
134 | } else {
135 | throw new AWSIotException(e);
136 | }
137 | }
138 | }
139 |
140 | public Set getServerUris() {
141 | return new HashSet<>();
142 | }
143 |
144 | private MqttConnectOptions buildMqttConnectOptions(AbstractAwsIotClient client, SocketFactory socketFactory) {
145 | MqttConnectOptions options = new MqttConnectOptions();
146 |
147 | options.setSocketFactory(socketFactory);
148 | options.setCleanSession(client.isCleanSession());
149 | options.setConnectionTimeout(client.getConnectionTimeout() / 1000);
150 | options.setKeepAliveInterval(client.getKeepAliveInterval() / 1000);
151 | if(client.isClientEnableMetrics()) {
152 | options.setUserName(USERNAME_METRIC_STRING);
153 | }
154 |
155 | Set serverUris = getServerUris();
156 | if (serverUris != null && !serverUris.isEmpty()) {
157 | String[] uriArray = new String[serverUris.size()];
158 | serverUris.toArray(uriArray);
159 | options.setServerURIs(uriArray);
160 | }
161 |
162 | if (client.getWillMessage() != null) {
163 | AWSIotMessage message = client.getWillMessage();
164 |
165 | options.setWill(message.getTopic(), message.getPayload(), message.getQos().getValue(), false);
166 | }
167 |
168 | return options;
169 | }
170 |
171 | }
172 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/mqtt/AwsIotMqttConnectionListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.mqtt;
17 |
18 | import java.util.logging.Level;
19 | import java.util.logging.Logger;
20 |
21 | import org.eclipse.paho.client.mqttv3.IMqttActionListener;
22 | import org.eclipse.paho.client.mqttv3.IMqttToken;
23 |
24 | import com.amazonaws.services.iot.client.core.AbstractAwsIotClient;
25 | import com.amazonaws.services.iot.client.core.AwsIotMessageCallback;
26 |
27 | /**
28 | * This class implements listener functions for the connection events from the
29 | * Paho MQTT library.
30 | */
31 | public class AwsIotMqttConnectionListener implements IMqttActionListener {
32 |
33 | private static final Logger LOGGER = Logger.getLogger(AwsIotMqttConnectionListener.class.getName());
34 |
35 | private final AbstractAwsIotClient client;
36 | private final boolean isConnect;
37 | private final AwsIotMessageCallback userCallback;
38 |
39 | public AwsIotMqttConnectionListener(AbstractAwsIotClient client, boolean isConnect,
40 | AwsIotMessageCallback userCallback) {
41 | this.client = client;
42 | this.isConnect = isConnect;
43 | this.userCallback = userCallback;
44 | }
45 |
46 | @Override
47 | public void onSuccess(IMqttToken arg0) {
48 | client.scheduleTask(new Runnable() {
49 | @Override
50 | public void run() {
51 | if (isConnect) {
52 | client.getConnection().onConnectionSuccess();
53 | } else {
54 | client.getConnection().onConnectionClosed();
55 | }
56 | if (userCallback != null) {
57 | userCallback.onSuccess();
58 | }
59 | }
60 | });
61 | }
62 |
63 | @Override
64 | public void onFailure(IMqttToken arg0, Throwable arg1) {
65 | LOGGER.log(Level.WARNING, (isConnect ? "Connect" : "Disconnect") + " request failure", arg1);
66 |
67 | client.scheduleTask(new Runnable() {
68 | @Override
69 | public void run() {
70 | if (isConnect) {
71 | client.getConnection().onConnectionFailure();
72 | } else {
73 | client.getConnection().onConnectionClosed();
74 | }
75 | if (userCallback != null) {
76 | userCallback.onFailure();
77 | }
78 | }
79 | });
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/mqtt/AwsIotMqttMessageListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.mqtt;
17 |
18 | import java.util.logging.Logger;
19 |
20 | import org.eclipse.paho.client.mqttv3.IMqttActionListener;
21 | import org.eclipse.paho.client.mqttv3.IMqttToken;
22 | import org.eclipse.paho.client.mqttv3.internal.wire.MqttSuback;
23 |
24 | import com.amazonaws.services.iot.client.AWSIotMessage;
25 | import com.amazonaws.services.iot.client.core.AbstractAwsIotClient;
26 |
27 | /**
28 | * This class implements listener functions for the message events from the Paho
29 | * MQTT library.
30 | */
31 | public class AwsIotMqttMessageListener implements IMqttActionListener {
32 |
33 | private static final Logger LOGGER = Logger.getLogger(AwsIotMqttMessageListener.class.getName());
34 |
35 | private static final int SUB_ACK_RETURN_CODE_FAILURE = 0x80;
36 |
37 | private AbstractAwsIotClient client;
38 |
39 | public AwsIotMqttMessageListener(AbstractAwsIotClient client) {
40 | this.client = client;
41 | }
42 |
43 | @Override
44 | public void onSuccess(IMqttToken token) {
45 | final AWSIotMessage message = (AWSIotMessage) token.getUserContext();
46 | if (message == null) {
47 | return;
48 | }
49 |
50 | boolean forceFailure = false;
51 | if (token.getResponse() instanceof MqttSuback) {
52 | MqttSuback subAck = (MqttSuback) token.getResponse();
53 | int qos[] = subAck.getGrantedQos();
54 | for (int i = 0; i < qos.length; i++) {
55 | if (qos[i] == SUB_ACK_RETURN_CODE_FAILURE) {
56 | LOGGER.warning("Request failed: likely due to too many subscriptions or policy violations");
57 | forceFailure = true;
58 | break;
59 | }
60 | }
61 | }
62 |
63 | final boolean isSuccess = !forceFailure;
64 | client.scheduleTask(new Runnable() {
65 | @Override
66 | public void run() {
67 | if (isSuccess) {
68 | message.onSuccess();
69 | } else {
70 | message.onFailure();
71 | }
72 | }
73 | });
74 | }
75 |
76 | @Override
77 | public void onFailure(IMqttToken token, Throwable cause) {
78 | final AWSIotMessage message = (AWSIotMessage) token.getUserContext();
79 | if (message == null) {
80 | LOGGER.warning("Request failed: " + token.getException());
81 | return;
82 | }
83 |
84 | LOGGER.warning("Request failed for topic " + message.getTopic() + ": " + token.getException());
85 | client.scheduleTask(new Runnable() {
86 | @Override
87 | public void run() {
88 | message.onFailure();
89 | }
90 | });
91 | }
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/shadow/AwsIotDeviceCommand.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.shadow;
17 |
18 | import java.util.logging.Logger;
19 |
20 | import com.amazonaws.services.iot.client.AWSIotException;
21 | import com.amazonaws.services.iot.client.AWSIotMessage;
22 | import com.amazonaws.services.iot.client.AWSIotTimeoutException;
23 | import com.amazonaws.services.iot.client.core.AwsIotCompletion;
24 | import com.amazonaws.services.iot.client.shadow.AwsIotDeviceCommandManager.Command;
25 |
26 | import lombok.AccessLevel;
27 | import lombok.Getter;
28 | import lombok.Setter;
29 |
30 | /**
31 | * This is a helper class that can be used to manage the execution result of a
32 | * shadow command, i.e. get, update, and delete. It makes sure that the command
33 | * is not published until the subscription requests for the acknowledgment
34 | * topics, namely accepted and rejected, have completed successfully.
35 | *
36 | * @see com.amazonaws.services.iot.client.core.AwsIotCompletion
37 | */
38 | @Getter
39 | @Setter
40 | public class AwsIotDeviceCommand extends AwsIotCompletion {
41 |
42 | private static final Logger LOGGER = Logger.getLogger(AwsIotDeviceCommand.class.getName());
43 |
44 | private final AwsIotDeviceCommandManager commandManager;
45 | private final Command command;
46 | private final String commandId;
47 |
48 | private AWSIotMessage response;
49 |
50 | @Setter(AccessLevel.NONE)
51 | private Boolean requestSent;
52 |
53 | public AwsIotDeviceCommand(AwsIotDeviceCommandManager commandManager, Command command, String commandId,
54 | AWSIotMessage request, long commandTimeout, boolean isAsync) {
55 | super(request, commandTimeout, isAsync);
56 | this.commandManager = commandManager;
57 | this.command = command;
58 | this.commandId = commandId;
59 | this.requestSent = false;
60 | }
61 |
62 | public void put(AbstractAwsIotDevice device) throws AWSIotException {
63 | if (device.isCommandReady(command)) {
64 | _put(device);
65 | } else {
66 | LOGGER.info("Request is pending: " + command.name() + "/" + commandId);
67 | }
68 | }
69 |
70 | public String get(AbstractAwsIotDevice device) throws AWSIotException, AWSIotTimeoutException {
71 | super.get(device.getClient());
72 | return (response != null) ? response.getStringPayload() : null;
73 | }
74 |
75 | public boolean onReady(AbstractAwsIotDevice device) {
76 | try {
77 | LOGGER.info("Request is resumed: " + command.name() + "/" + commandId);
78 | _put(device);
79 | return true;
80 | } catch (AWSIotException e) {
81 | return false;
82 | }
83 | }
84 |
85 | @Override
86 | public void onSuccess() {
87 | // first callback is for the command ack, which we ignore
88 | if (response == null) {
89 | return;
90 | } else {
91 | request.setPayload(response.getPayload());
92 | }
93 |
94 | super.onSuccess();
95 | }
96 |
97 | @Override
98 | public void onFailure() {
99 | super.onFailure();
100 | }
101 |
102 | @Override
103 | public void onTimeout() {
104 | commandManager.onCommandTimeout(this);
105 | super.onTimeout();
106 | }
107 |
108 | private void _put(AbstractAwsIotDevice device) throws AWSIotException {
109 | synchronized (this) {
110 | if (requestSent) {
111 | LOGGER.warning("Request was already sent: " + command.name() + "/" + commandId);
112 | return;
113 | } else {
114 | requestSent = true;
115 | }
116 | }
117 |
118 | device.getClient().publish(this, timeout);
119 | }
120 |
121 | }
122 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/shadow/AwsIotDeviceCommandAckListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.shadow;
17 |
18 | import java.util.logging.Logger;
19 |
20 | import com.amazonaws.services.iot.client.AWSIotMessage;
21 | import com.amazonaws.services.iot.client.AWSIotQos;
22 | import com.amazonaws.services.iot.client.AWSIotTopic;
23 |
24 | /**
25 | * This class extends {@link AWSIotTopic} to provide customized callback
26 | * functions for the subscription requests of the shadow commands.
27 | */
28 | public class AwsIotDeviceCommandAckListener extends AWSIotTopic {
29 |
30 | private static final Logger LOGGER = Logger.getLogger(AwsIotDeviceCommandAckListener.class.getName());
31 |
32 | private final AbstractAwsIotDevice device;
33 |
34 | public AwsIotDeviceCommandAckListener(String topic, AWSIotQos qos, AbstractAwsIotDevice device) {
35 | super(topic, qos);
36 | this.device = device;
37 | }
38 |
39 | @Override
40 | public void onMessage(AWSIotMessage message) {
41 | device.onCommandAck(message);
42 | }
43 |
44 | @Override
45 | public void onSuccess() {
46 | device.onSubscriptionAck(topic, true);
47 | }
48 |
49 | @Override
50 | public void onFailure() {
51 | LOGGER.warning("Failed to subscribe to device topic " + topic);
52 | device.onSubscriptionAck(topic, false);
53 | }
54 |
55 | @Override
56 | public void onTimeout() {
57 | LOGGER.warning("Timeout when subscribing to device topic " + topic);
58 | device.onSubscriptionAck(topic, false);
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/shadow/AwsIotDeviceDeltaListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.shadow;
17 |
18 | import java.io.IOException;
19 | import java.util.logging.Logger;
20 |
21 | import com.amazonaws.services.iot.client.AWSIotMessage;
22 | import com.amazonaws.services.iot.client.AWSIotQos;
23 | import com.amazonaws.services.iot.client.AWSIotTopic;
24 | import com.fasterxml.jackson.databind.JsonNode;
25 |
26 | /**
27 | * This class extends {@link AWSIotTopic} to provide a callback function for
28 | * receiving the shadow delta updates.
29 | */
30 | public class AwsIotDeviceDeltaListener extends AWSIotTopic {
31 |
32 | private static final Logger LOGGER = Logger.getLogger(AwsIotDeviceDeltaListener.class.getName());
33 |
34 | private final AbstractAwsIotDevice device;
35 |
36 | public AwsIotDeviceDeltaListener(String topic, AWSIotQos qos, AbstractAwsIotDevice device) {
37 | super(topic, qos);
38 | this.device = device;
39 | }
40 |
41 | @Override
42 | public void onMessage(AWSIotMessage message) {
43 | String payload = message.getStringPayload();
44 | if (payload == null) {
45 | LOGGER.warning("Received empty delta for device " + device.getThingName());
46 | return;
47 | }
48 |
49 | JsonNode rootNode;
50 | try {
51 | rootNode = device.getJsonObjectMapper().readTree(payload);
52 | if (!rootNode.isObject()) {
53 | throw new IOException();
54 | }
55 | } catch (IOException e) {
56 | LOGGER.warning("Received invalid delta for device " + device.getThingName());
57 | return;
58 | }
59 |
60 | if (device.enableVersioning) {
61 | JsonNode node = rootNode.get("version");
62 | if (node == null) {
63 | LOGGER.warning("Missing version field in delta for device " + device.getThingName());
64 | return;
65 | }
66 |
67 | long receivedVersion = node.longValue();
68 | long localVersion = device.getLocalVersion().get();
69 | if (receivedVersion < localVersion) {
70 | LOGGER.warning("An old version of delta received for " + device.getThingName() + ", local "
71 | + localVersion + ", received " + receivedVersion);
72 | return;
73 | }
74 |
75 | device.getLocalVersion().set(receivedVersion);
76 | LOGGER.info("Local version number updated to " + receivedVersion);
77 | }
78 |
79 | JsonNode node = rootNode.get("state");
80 | if (node == null) {
81 | LOGGER.warning("Missing state field in delta for device " + device.getThingName());
82 | return;
83 | }
84 | device.onShadowUpdate(node.toString());
85 | }
86 |
87 | @Override
88 | public void onSuccess() {
89 | }
90 |
91 | @Override
92 | public void onFailure() {
93 | LOGGER.warning("Failed to subscribe to device topic " + topic);
94 | }
95 |
96 | @Override
97 | public void onTimeout() {
98 | LOGGER.warning("Timeout when subscribing to device topic " + topic);
99 | }
100 |
101 | }
102 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/shadow/AwsIotDeviceReportMessage.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.shadow;
17 |
18 | import java.util.logging.Logger;
19 |
20 | import com.amazonaws.services.iot.client.AWSIotDeviceErrorCode;
21 | import com.amazonaws.services.iot.client.AWSIotMessage;
22 | import com.amazonaws.services.iot.client.AWSIotQos;
23 |
24 | public class AwsIotDeviceReportMessage extends AWSIotMessage {
25 |
26 | private static final Logger LOGGER = Logger.getLogger(AwsIotDeviceReportMessage.class.getName());
27 |
28 | private final AbstractAwsIotDevice device;
29 | private final long reportVersion;
30 |
31 | public AwsIotDeviceReportMessage(String topic, AWSIotQos qos, long reportVersion, String jsonState,
32 | AbstractAwsIotDevice device) {
33 | super(topic, qos, jsonState);
34 | this.device = device;
35 | this.reportVersion = reportVersion;
36 | }
37 |
38 | @Override
39 | public void onSuccess() {
40 | // increment local version only if it hasn't be updated
41 | device.getLocalVersion().compareAndSet(reportVersion, reportVersion + 1);
42 | }
43 |
44 | @Override
45 | public void onFailure() {
46 | if (AWSIotDeviceErrorCode.CONFLICT.equals(errorCode)) {
47 | LOGGER.warning("Device version conflict, restart version synchronization");
48 | device.startVersionSync();
49 | } else {
50 | LOGGER.warning("Failed to publish device report: " + errorMessage);
51 | }
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/shadow/AwsIotDeviceSyncMessage.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.shadow;
17 |
18 | import java.io.IOException;
19 | import java.util.logging.Logger;
20 |
21 | import com.amazonaws.services.iot.client.AWSIotDeviceErrorCode;
22 | import com.amazonaws.services.iot.client.AWSIotMessage;
23 | import com.amazonaws.services.iot.client.AWSIotQos;
24 |
25 | public class AwsIotDeviceSyncMessage extends AWSIotMessage {
26 |
27 | private static final Logger LOGGER = Logger.getLogger(AwsIotDeviceSyncMessage.class.getName());
28 |
29 | private final AbstractAwsIotDevice device;
30 |
31 | public AwsIotDeviceSyncMessage(String topic, AWSIotQos qos, AbstractAwsIotDevice device) {
32 | super(topic, qos);
33 | this.device = device;
34 | }
35 |
36 | @Override
37 | public void onSuccess() {
38 | if (payload != null) {
39 | try {
40 | long version = AwsIotJsonDeserializer.deserializeVersion(device, getStringPayload());
41 | if (version > 0) {
42 | LOGGER.info("Received shadow version number: " + version);
43 |
44 | boolean updated = device.getLocalVersion().compareAndSet(-1, version);
45 | if (!updated) {
46 | LOGGER.warning(
47 | "Local version not updated likely because newer version recieved from shadow update");
48 | }
49 | }
50 | } catch (IOException e) {
51 | LOGGER.warning("Device update error: " + e.getMessage());
52 | }
53 | }
54 | }
55 |
56 | @Override
57 | public void onFailure() {
58 | if (AWSIotDeviceErrorCode.NOT_FOUND.equals(errorCode)) {
59 | LOGGER.info("No shadow document found, reset local version to 0");
60 | device.getLocalVersion().set(0);
61 | } else {
62 | LOGGER.warning("Failed to get shadow version: " + errorMessage);
63 | }
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/shadow/AwsIotJsonDeserializer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.shadow;
17 |
18 | import java.io.IOException;
19 | import java.lang.reflect.Field;
20 | import java.lang.reflect.InvocationTargetException;
21 | import java.lang.reflect.Method;
22 | import java.util.Iterator;
23 |
24 | import com.fasterxml.jackson.databind.JsonNode;
25 | import com.fasterxml.jackson.databind.ObjectMapper;
26 |
27 | /**
28 | * This is a customized JSON deserializer for deserializing the delta update
29 | * document from the shadow.
30 | */
31 | public class AwsIotJsonDeserializer {
32 |
33 | public static void deserialize(AbstractAwsIotDevice device, String jsonState) throws IOException {
34 | ObjectMapper jsonObjectMapper = device.getJsonObjectMapper();
35 |
36 | JsonNode node = jsonObjectMapper.readTree(jsonState);
37 | if (node == null) {
38 | throw new IOException("Invalid delta update received for " + device.getThingName());
39 | }
40 |
41 | for (Iterator it = node.fieldNames(); it.hasNext();) {
42 | String property = it.next();
43 | Field field = device.getUpdatableProperties().get(property);
44 | JsonNode fieldNode = node.get(property);
45 | if (field == null || fieldNode == null) {
46 | continue;
47 | }
48 |
49 | updateDeviceProperty(jsonObjectMapper, fieldNode, device, field);
50 | }
51 | }
52 |
53 | public static long deserializeVersion(AbstractAwsIotDevice device, String jsonState) throws IOException {
54 | ObjectMapper jsonObjectMapper = device.getJsonObjectMapper();
55 |
56 | JsonNode node = jsonObjectMapper.readTree(jsonState);
57 | if (node == null) {
58 | throw new IOException("Invalid shadow document received for " + device.getThingName());
59 | }
60 |
61 | JsonNode versionNode = node.get("version");
62 | if (versionNode == null) {
63 | throw new IOException("Missing version field from shadow document for " + device.getThingName());
64 | }
65 |
66 | return versionNode.asLong();
67 | }
68 |
69 | private static void updateDeviceProperty(ObjectMapper jsonObjectMapper, JsonNode node, AbstractAwsIotDevice device,
70 | Field field) throws IOException {
71 | Object value = jsonObjectMapper.treeToValue(node, field.getType());
72 | invokeSetterMethod(device, field.getName(), field.getType(), value);
73 | }
74 |
75 | private static void invokeSetterMethod(Object target, String name, Class> type, Object value) throws IOException {
76 | String setter = "set" + Character.toUpperCase(name.charAt(0)) + name.substring(1);
77 |
78 | Method method;
79 | try {
80 | method = target.getClass().getMethod(setter, type);
81 | } catch (NoSuchMethodException | SecurityException e) {
82 | throw new IllegalArgumentException(e);
83 | }
84 |
85 | try {
86 | method.invoke(target, value);
87 | } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
88 | throw new IOException(e);
89 | }
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/shadow/AwsIotJsonSerializer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.shadow;
17 |
18 | import java.io.IOException;
19 | import java.lang.reflect.Field;
20 | import java.lang.reflect.InvocationTargetException;
21 | import java.lang.reflect.Method;
22 |
23 | import com.fasterxml.jackson.core.JsonGenerator;
24 | import com.fasterxml.jackson.core.JsonProcessingException;
25 | import com.fasterxml.jackson.databind.JsonSerializer;
26 | import com.fasterxml.jackson.databind.SerializerProvider;
27 |
28 | /**
29 | * This is a customized JSON serializer for the Jackson databind module. It is
30 | * used for serializing the device properties to be reported to the shadow.
31 | */
32 | public class AwsIotJsonSerializer extends JsonSerializer {
33 |
34 | @Override
35 | public void serialize(AbstractAwsIotDevice device, JsonGenerator generator, SerializerProvider provider)
36 | throws IOException, JsonProcessingException {
37 | generator.writeStartObject();
38 |
39 | try {
40 | for (String property : device.getReportedProperties().keySet()) {
41 | Field field = device.getReportedProperties().get(property);
42 |
43 | Object value = invokeGetterMethod(device, field);
44 | generator.writeObjectField(property, value);
45 | }
46 | } catch (IllegalArgumentException e) {
47 | throw new IOException(e);
48 | }
49 |
50 | generator.writeEndObject();
51 | }
52 |
53 | private static Object invokeGetterMethod(Object target, Field field) throws IOException {
54 | String fieldName = Character.toUpperCase(field.getName().charAt(0)) + field.getName().substring(1);
55 | String getter = "get" + fieldName;
56 |
57 | Method method;
58 | try {
59 | method = target.getClass().getMethod(getter);
60 | } catch (NoSuchMethodException | SecurityException e) {
61 | if (e instanceof NoSuchMethodException && boolean.class.equals(field.getType())) {
62 | getter = "is" + fieldName;
63 | try {
64 | method = target.getClass().getMethod(getter);
65 | } catch (NoSuchMethodException | SecurityException ie) {
66 | throw new IllegalArgumentException(ie);
67 | }
68 | } else {
69 | throw new IllegalArgumentException(e);
70 | }
71 | }
72 |
73 | Object value;
74 | try {
75 | value = method.invoke(target);
76 | } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
77 | throw new IOException(e);
78 | }
79 | return value;
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/util/AwsIotTlsSocketFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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 com.amazonaws.services.iot.client.util;
17 |
18 | import java.io.IOException;
19 | import java.net.InetAddress;
20 | import java.net.Socket;
21 | import java.net.UnknownHostException;
22 | import java.security.KeyManagementException;
23 | import java.security.KeyStore;
24 |
25 | import java.security.KeyStoreException;
26 | import java.security.NoSuchAlgorithmException;
27 | import java.security.UnrecoverableKeyException;
28 |
29 | import javax.net.ssl.KeyManagerFactory;
30 | import javax.net.ssl.SSLContext;
31 | import javax.net.ssl.SSLParameters;
32 | import javax.net.ssl.SSLSocket;
33 | import javax.net.ssl.SSLSocketFactory;
34 |
35 | import com.amazonaws.services.iot.client.AWSIotException;
36 |
37 | /**
38 | * This class extends {@link SSLSocketFactory} to enforce TLS v1.2 to be used
39 | * for SSL sockets created by the library.
40 | */
41 | public class AwsIotTlsSocketFactory extends SSLSocketFactory {
42 | private static final String TLS_V_1_2 = "TLSv1.2";
43 |
44 | /**
45 | * SSL Socket Factory A SSL socket factory is created and passed into this
46 | * class which decorates it to enable TLS 1.2 when sockets are created.
47 | */
48 | private final SSLSocketFactory sslSocketFactory;
49 |
50 | public AwsIotTlsSocketFactory(KeyStore keyStore, String keyPassword) throws AWSIotException {
51 | try {
52 | SSLContext context = SSLContext.getInstance(TLS_V_1_2);
53 |
54 | KeyManagerFactory managerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
55 | managerFactory.init(keyStore, keyPassword.toCharArray());
56 | context.init(managerFactory.getKeyManagers(), null, null);
57 |
58 | sslSocketFactory = context.getSocketFactory();
59 | } catch (NoSuchAlgorithmException | KeyStoreException | UnrecoverableKeyException | KeyManagementException e) {
60 | throw new AWSIotException(e);
61 | }
62 | }
63 |
64 | public AwsIotTlsSocketFactory(SSLSocketFactory sslSocketFactory) {
65 | this.sslSocketFactory = sslSocketFactory;
66 | }
67 |
68 | @Override
69 | public String[] getDefaultCipherSuites() {
70 | return sslSocketFactory.getDefaultCipherSuites();
71 | }
72 |
73 | @Override
74 | public String[] getSupportedCipherSuites() {
75 | return sslSocketFactory.getSupportedCipherSuites();
76 | }
77 |
78 | @Override
79 | public Socket createSocket() throws IOException {
80 | return ensureTls(sslSocketFactory.createSocket());
81 | }
82 |
83 | @Override
84 | public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
85 | return ensureTls(sslSocketFactory.createSocket(s, host, port, autoClose));
86 | }
87 |
88 | @Override
89 | public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
90 | return ensureTls(sslSocketFactory.createSocket(host, port));
91 | }
92 |
93 | @Override
94 | public Socket createSocket(String host, int port, InetAddress localHost, int localPort)
95 | throws IOException, UnknownHostException {
96 | return ensureTls(sslSocketFactory.createSocket(host, port, localHost, localPort));
97 | }
98 |
99 | @Override
100 | public Socket createSocket(InetAddress host, int port) throws IOException {
101 | return ensureTls(sslSocketFactory.createSocket(host, port));
102 | }
103 |
104 | @Override
105 | public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort)
106 | throws IOException {
107 | return ensureTls(sslSocketFactory.createSocket(address, port, localAddress, localPort));
108 | }
109 |
110 | /**
111 | * Enable TLS 1.2 on any socket created by the underlying SSL Socket
112 | * Factory.
113 | *
114 | * @param socket
115 | * newly created socket which may not have TLS 1.2 enabled.
116 | * @return TLS 1.2 enabled socket.
117 | */
118 | private Socket ensureTls(Socket socket) {
119 | if (socket != null && (socket instanceof SSLSocket)) {
120 | ((SSLSocket) socket).setEnabledProtocols(new String[] { TLS_V_1_2 });
121 |
122 | // Ensure hostname is validated againt the CN in the certificate
123 | SSLParameters sslParams = new SSLParameters();
124 | sslParams.setEndpointIdentificationAlgorithm("HTTPS");
125 | ((SSLSocket) socket).setSSLParameters(sslParams);
126 | }
127 | return socket;
128 | }
129 |
130 | }
131 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/test/java/com/amazonaws/services/iot/client/AWSIotDeviceErrorCodeTest.java:
--------------------------------------------------------------------------------
1 | package com.amazonaws.services.iot.client;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import org.junit.Test;
6 |
7 | public class AWSIotDeviceErrorCodeTest {
8 |
9 | @Test
10 | public void testValueOf() {
11 | assertEquals(AWSIotDeviceErrorCode.BAD_REQUEST, AWSIotDeviceErrorCode.valueOf(400));
12 | }
13 |
14 | @Test
15 | public void testgetValue() {
16 | assertEquals(400, AWSIotDeviceErrorCode.BAD_REQUEST.getValue());
17 | }
18 |
19 | @Test
20 | public void testInvalidValue() {
21 | assertNull(AWSIotDeviceErrorCode.valueOf(10));
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/test/java/com/amazonaws/services/iot/client/AWSIotDeviceIntegrationTest.java:
--------------------------------------------------------------------------------
1 | package com.amazonaws.services.iot.client;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.io.UnsupportedEncodingException;
6 | import java.util.HashMap;
7 | import java.util.Map;
8 | import java.util.logging.Level;
9 | import java.util.logging.Logger;
10 |
11 | import org.junit.After;
12 | import org.junit.Before;
13 | import org.junit.BeforeClass;
14 | import org.junit.Test;
15 | import java.util.UUID;
16 |
17 | public class AWSIotDeviceIntegrationTest implements TestDeviceNotifier {
18 |
19 | private static final Logger LOGGER = Logger.getLogger(AWSIotDeviceIntegrationTest.class.getName());
20 | private static final String UPDATE_TOPIC = "$aws/things/?/shadow/update";
21 | // Added UID to distinguish concurrent running test
22 | private static final String THING_NAME = System.getProperty("thingName") + UUID.randomUUID().toString();
23 | private static final String STABILITY_TEST_ITERATIONS = System.getProperty("stabilityTestIterations");
24 |
25 | private AWSIotMqttClient client;
26 | private TestDevice device;
27 |
28 | @BeforeClass
29 | public static void init() {
30 | AWSIotMqttClientIntegrationUtil.enableConsoleLogging(LOGGER);
31 | }
32 |
33 | @Before
34 | public void setup() {
35 | client = AWSIotMqttClientIntegrationUtil.getClient();
36 | assertNotNull("Client not initialized likely due to required system properties not being provided", client);
37 | assertNotNull("thingName was not provided", THING_NAME);
38 | }
39 |
40 | @After
41 | public void cleanup() {
42 | try {
43 | if (client != null) {
44 | client.disconnect(500);
45 | client = null;
46 | }
47 | } catch (Exception e) {
48 | LOGGER.log(Level.WARNING, "disconnect failed with exception", e);
49 | }
50 | }
51 |
52 | @Test
53 | public void testDeviceReport() throws AWSIotException, InterruptedException, UnsupportedEncodingException {
54 | String serailNumber = "123-456-789";
55 | Float threshold = Float.valueOf(0f);
56 | Map sensors = new HashMap<>();
57 | sensors.put("sensor-0", Float.valueOf(0f));
58 | sensors.put("sensor-1", Float.valueOf(0f));
59 | sensors.put("sensor-2", Float.valueOf(0f));
60 |
61 | device = new TestDevice(THING_NAME, serailNumber, threshold, sensors);
62 | device.setReportInterval(1000);
63 | client.attach(device);
64 |
65 | client.connect();
66 |
67 | device.delete();
68 |
69 | String deltaTopic = UPDATE_TOPIC.replace("?", THING_NAME);
70 | TestTopic topic = new TestTopic(deltaTopic, null);
71 | client.subscribe(topic);
72 |
73 | Thread.sleep(2000);
74 |
75 | assertNotNull(topic.lastPayload);
76 | String update = new String(topic.lastPayload, "UTF-8");
77 | assertTrue(update.contains("\"threshold\":0.0"));
78 | assertTrue(update.contains("\"serialNumber\":\"123-456-789\""));
79 | assertTrue(update.contains("\"sensor-0\":0.0"));
80 | assertTrue(update.contains("\"sensor-1\":0.0"));
81 | assertTrue(update.contains("\"sensor-2\":0.0"));
82 | }
83 |
84 | @Test
85 | public void testDeviceUpdate() throws AWSIotException, InterruptedException, UnsupportedEncodingException {
86 | String serailNumber = "123-456-789";
87 | Float threshold = Float.valueOf(0f);
88 | Map sensors = new HashMap<>();
89 | sensors.put("sensor-0", Float.valueOf(0f));
90 | sensors.put("sensor-1", Float.valueOf(0f));
91 | sensors.put("sensor-2", Float.valueOf(0f));
92 |
93 | device = new TestDevice(THING_NAME, serailNumber, threshold, sensors);
94 | device.setReportInterval(1000);
95 | client.attach(device);
96 |
97 | client.connect();
98 |
99 | device.delete();
100 |
101 | Thread.sleep(1000);
102 |
103 | String desired = "{\"state\":{\"desired\":{\"threshold\":3.0}}}";
104 | device.update(desired);
105 |
106 | Thread.sleep(2000);
107 | assertEquals(Float.valueOf(3.0f), device.getThreshold());
108 | }
109 |
110 | @Test
111 | public void testDeviceReportAndUpdate() throws AWSIotException, InterruptedException, UnsupportedEncodingException {
112 | String serailNumber = "123-456-789";
113 | Float threshold = Float.valueOf(0f);
114 | Map sensors = new HashMap<>();
115 | sensors.put("sensor-0", Float.valueOf(0f));
116 | sensors.put("sensor-1", Float.valueOf(0f));
117 | sensors.put("sensor-2", Float.valueOf(0f));
118 |
119 | device = new TestDevice(THING_NAME, serailNumber, threshold, sensors);
120 | device.setReportInterval(1000);
121 | device.addNotifier(this);
122 | device.startMonitoring();
123 |
124 | client.attach(device);
125 |
126 | client.connect();
127 |
128 | device.delete();
129 |
130 | String desired = "{\"state\":{\"desired\":{\"threshold\":-10.0}}}";
131 | device.update(desired);
132 |
133 | Thread.sleep(3000);
134 | device.stopMonitoring();
135 |
136 | assertEquals(Float.valueOf(-10f), device.getSensorValue("sensor-0"));
137 | assertEquals(Float.valueOf(-10f), device.getSensorValue("sensor-1"));
138 | assertEquals(Float.valueOf(-10f), device.getSensorValue("sensor-2"));
139 |
140 | String state = device.get();
141 | assertTrue(state.contains("\"sensor-0\":-10.0"));
142 | assertTrue(state.contains("\"sensor-1\":-10.0"));
143 | assertTrue(state.contains("\"sensor-2\":-10.0"));
144 | }
145 |
146 | @Test
147 | public void testDeviceStability() throws AWSIotException, InterruptedException, UnsupportedEncodingException {
148 | String serailNumber = "123-456-789";
149 | Float threshold = Float.valueOf(0f);
150 | Map sensors = new HashMap<>();
151 | sensors.put("sensor-0", Float.valueOf(0f));
152 | sensors.put("sensor-1", Float.valueOf(0f));
153 | sensors.put("sensor-2", Float.valueOf(0f));
154 |
155 | device = new TestDevice(THING_NAME, serailNumber, threshold, sensors);
156 | device.setReportInterval(1000);
157 | device.addNotifier(this);
158 | device.startMonitoring();
159 |
160 | client.attach(device);
161 |
162 | AWSIotMessage willMessage = new AWSIotMessage("test/disconnect", AWSIotQos.QOS0, client.getClientId());
163 | client.setWillMessage(willMessage);
164 | client.connect();
165 |
166 | device.delete();
167 |
168 | Float value = Float.valueOf(0.0f);
169 | long testIterations = STABILITY_TEST_ITERATIONS == null ? 10 : Long.parseLong(STABILITY_TEST_ITERATIONS);
170 | while (testIterations-- > 0) {
171 | value -= 10.0f;
172 | device.update("{\"state\":{\"desired\":{\"threshold\":" + value.toString() + "}}}");
173 | Thread.sleep(3000);
174 | }
175 |
176 | String state = device.get();
177 | assertTrue(state.contains("\"sensor-0\":" + value));
178 | assertTrue(state.contains("\"sensor-1\":" + value));
179 | assertTrue(state.contains("\"sensor-2\":" + value));
180 | }
181 |
182 | @Override
183 | public void reportAlarm(String sensorName, Float sensorValue, Float threshold) {
184 | device.setSensorValue(sensorName, sensorValue - 1.0f);
185 | }
186 |
187 | }
188 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/test/java/com/amazonaws/services/iot/client/AWSIotMessageTest.java:
--------------------------------------------------------------------------------
1 | package com.amazonaws.services.iot.client;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.util.Arrays;
6 |
7 | import org.junit.Test;
8 |
9 | public class AWSIotMessageTest {
10 |
11 | @Test
12 | public void testRawPayload() {
13 | byte[] testBytes = "test string".getBytes();
14 |
15 | AWSIotMessage message = new AWSIotMessage("topic", AWSIotQos.QOS0);
16 |
17 | message.setPayload(testBytes);
18 |
19 | assertTrue(Arrays.equals(testBytes, message.getPayload()));
20 | }
21 |
22 | @Test
23 | public void testBytesToStringPayload() {
24 | byte[] testBytes = "test string".getBytes();
25 |
26 | AWSIotMessage message = new AWSIotMessage("topic", AWSIotQos.QOS0);
27 |
28 | message.setPayload(testBytes);
29 |
30 | assertEquals("test string", message.getStringPayload());
31 | }
32 |
33 | @Test
34 | public void testStringSerialization() {
35 | String testString = "test string";
36 |
37 | AWSIotMessage message = new AWSIotMessage("topic", AWSIotQos.QOS0);
38 |
39 | message.setStringPayload(testString);
40 |
41 | assertEquals(testString, message.getStringPayload());
42 | }
43 |
44 | @Test
45 | public void testMultiByteStringSerialization() {
46 | byte[] chineseLetterInUtf8 = { (byte) 0xE7, (byte) 0x9A, (byte) 0x84 };
47 |
48 | AWSIotMessage message = new AWSIotMessage("topic", AWSIotQos.QOS0, chineseLetterInUtf8);
49 |
50 | assertEquals("的", message.getStringPayload());
51 | }
52 |
53 | @Test
54 | public void testMultiByteStringDeserialization() {
55 | byte[] chineseLetterInUtf8 = { (byte) 0xE7, (byte) 0x9A, (byte) 0x84 };
56 |
57 | AWSIotMessage message = new AWSIotMessage("topic", AWSIotQos.QOS0, "的");
58 |
59 | assertTrue(Arrays.equals(chineseLetterInUtf8, message.getPayload()));
60 | }
61 |
62 | @Test
63 | public void testInvalidMultiByteString() {
64 | byte[] chineseLetterInUtf8 = { (byte) 0xE7, (byte) 0x9A };
65 |
66 | AWSIotMessage message = new AWSIotMessage("topic", AWSIotQos.QOS0, chineseLetterInUtf8);
67 |
68 | assertEquals("�", message.getStringPayload());
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/test/java/com/amazonaws/services/iot/client/AWSIotMqttClientIntegrationUtil.java:
--------------------------------------------------------------------------------
1 | package com.amazonaws.services.iot.client;
2 |
3 | import static org.junit.Assert.assertNotNull;
4 | import static org.junit.Assert.fail;
5 |
6 | import java.io.FileInputStream;
7 | import java.security.KeyStore;
8 | import java.util.logging.ConsoleHandler;
9 | import java.util.logging.Handler;
10 | import java.util.logging.Level;
11 | import java.util.logging.Logger;
12 |
13 | import com.amazonaws.services.iot.client.CredentialUtil;
14 |
15 | public class AWSIotMqttClientIntegrationUtil {
16 |
17 | private static final String CLIENT_ENDPOINT = System.getProperty("clientEndpoint");
18 | private static final String CLIENT_ID = System.getProperty("clientId");
19 |
20 | private static final String AUTH_MODE = System.getProperty("authMode");
21 |
22 | private static final Boolean IS_WEBSOCKET = Boolean.parseBoolean(System.getProperty("isWebSocket"));
23 | private static final String PUBLIC_MATERIAL = System.getProperty("publicMaterial");
24 | private static final String PRIVATE_MATERIAL = System.getProperty("privateMaterial");
25 | private static final String KEYSTORE_FILE = System.getProperty("keystoreFile");
26 | private static final String KEYSTORE_PASSWORD = System.getProperty("keystorePassword");
27 | private static final String KEY_PASSWORD = System.getProperty("keyPassword");
28 |
29 | private static final String LOG_LEVEL = System.getProperty("logLevel");
30 |
31 | public static void enableConsoleLogging(Logger logger) {
32 | Level level = Level.FINE;
33 |
34 | if (LOG_LEVEL != null) {
35 | level = Level.parse(LOG_LEVEL);
36 | }
37 |
38 | Handler consoleHandler = new ConsoleHandler();
39 | consoleHandler.setLevel(level);
40 |
41 | logger.addHandler(consoleHandler);
42 | logger.setUseParentHandlers(false);
43 | logger.setLevel(level);
44 | }
45 |
46 | public static AWSIotMqttClient getClient() {
47 | return getClient("");
48 | }
49 |
50 | public static AWSIotMqttClient getClient(String suffix) {
51 | assertNotNull("Client endpoint not provided", CLIENT_ENDPOINT);
52 | assertNotNull("Client ID not provided", CLIENT_ID);
53 |
54 | AWSIotMqttClient client = getClientFromAutoConfig(suffix);
55 | if (client == null) {
56 | client = getClientFromManualConfig(suffix);
57 | }
58 |
59 | return client;
60 | }
61 |
62 | private static AWSIotMqttClient getClientFromAutoConfig(final String suffix) {
63 | AWSIotMqttClient client = null;
64 |
65 | if (AUTH_MODE != null) {
66 | switch (AUTH_MODE) {
67 | case AuthMode.CERT_AUTH: // CredentialUtil handles cert from odin to generate client as well. : )
68 | case AuthMode.WSS_SIGV4_AUTH:
69 | client = CredentialUtil.newClient(CLIENT_ENDPOINT, CLIENT_ID + suffix, PUBLIC_MATERIAL, PRIVATE_MATERIAL, IS_WEBSOCKET);
70 | break;
71 | default:
72 | throw new UnsupportedOperationException("No such auth mode supported: " + AUTH_MODE);
73 | }
74 | }
75 |
76 | return client;
77 | }
78 |
79 | private static AWSIotMqttClient getClientFromManualConfig(final String suffix) {
80 | AWSIotMqttClient client = null;
81 |
82 | if (KEYSTORE_FILE != null && KEYSTORE_PASSWORD != null) {
83 | try {
84 | KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
85 | keyStore.load(new FileInputStream(KEYSTORE_FILE), KEYSTORE_PASSWORD.toCharArray());
86 |
87 | client = new AWSIotMqttClient(CLIENT_ENDPOINT, CLIENT_ID + suffix, keyStore, KEY_PASSWORD);
88 | } catch (Exception e) {
89 | fail("Failed to load keystore file for the integration tests");
90 | }
91 | } else if (PUBLIC_MATERIAL != null && PRIVATE_MATERIAL != null) {
92 | client = CredentialUtil.newClient(CLIENT_ENDPOINT, CLIENT_ID + suffix, PUBLIC_MATERIAL, PRIVATE_MATERIAL, IS_WEBSOCKET);
93 | }
94 |
95 | return client;
96 | }
97 |
98 | private class AuthMode {
99 | private static final String CERT_AUTH = "CertificateMutualAuthentication";
100 | private static final String WSS_SIGV4_AUTH = "MqttOverWebSocketSigV4Signing";
101 | private static final String WSS_CUSTOM_AUTH = "MqttOverWebSocketCustomAuthZ"; // Reserved for custom authZ integ test
102 | }
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/test/java/com/amazonaws/services/iot/client/AWSIotQosTest.java:
--------------------------------------------------------------------------------
1 | package com.amazonaws.services.iot.client;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import org.junit.Test;
6 |
7 | public class AWSIotQosTest {
8 |
9 | @Test
10 | public void testValueOf0() {
11 | assertEquals(AWSIotQos.QOS0, AWSIotQos.valueOf(0));
12 | }
13 |
14 | @Test
15 | public void testValueOf1() {
16 | assertEquals(AWSIotQos.QOS1, AWSIotQos.valueOf(1));
17 | }
18 |
19 | @Test(expected = IllegalArgumentException.class)
20 | public void testValueOf2() {
21 | AWSIotQos.valueOf(2);
22 | }
23 |
24 | @Test
25 | public void testgetValueOf0() {
26 | assertEquals(0, AWSIotQos.QOS0.getValue());
27 | }
28 |
29 | @Test
30 | public void testgetValueOf1() {
31 | assertEquals(1, AWSIotQos.QOS1.getValue());
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/test/java/com/amazonaws/services/iot/client/TestDevice.java:
--------------------------------------------------------------------------------
1 | package com.amazonaws.services.iot.client;
2 |
3 | import java.util.ArrayList;
4 | import java.util.HashMap;
5 | import java.util.List;
6 | import java.util.Map;
7 | import java.util.Map.Entry;
8 | import java.util.logging.Logger;
9 |
10 | import com.amazonaws.services.iot.client.AWSIotDevice;
11 | import com.amazonaws.services.iot.client.AWSIotDeviceProperty;
12 |
13 | public class TestDevice extends AWSIotDevice {
14 |
15 | private static final Logger LOGGER = Logger.getLogger(AWSIotDeviceIntegrationTest.class.getName());
16 |
17 | @AWSIotDeviceProperty(allowUpdate = false)
18 | private String serialNumber;
19 |
20 | @AWSIotDeviceProperty
21 | private Float threshold;
22 |
23 | @AWSIotDeviceProperty
24 | private Map sensors;
25 |
26 | private final List notifiers = new ArrayList<>();
27 |
28 | private boolean enableMonitoring;
29 | private Thread monitoringThread;
30 |
31 | public TestDevice(String thingName, String serialNumber, Float threshold, Map sensors) {
32 | super(thingName);
33 | this.serialNumber = serialNumber;
34 | this.threshold = threshold;
35 | this.sensors = new HashMap<>(sensors);
36 | this.threshold = Float.valueOf(0f);
37 | }
38 |
39 | public String getSerialNumber() {
40 | return serialNumber;
41 | }
42 |
43 | public void setSerialNumber(String serialNumber) {
44 | this.serialNumber = serialNumber;
45 | }
46 |
47 | public Float getThreshold() {
48 | return threshold;
49 | }
50 |
51 | public void setThreshold(Float threshold) {
52 | this.threshold = threshold;
53 | }
54 |
55 | public Map getSensors() {
56 | return new HashMap(sensors);
57 | }
58 |
59 | public void setSensors(Map sensors) {
60 | this.sensors = new HashMap(sensors);
61 | }
62 |
63 | public Float getSensorValue(String sensorName) {
64 | return sensors.get(sensorName);
65 | }
66 |
67 | public void setSensorValue(String sensorName, Float sensorValue) {
68 | sensors.put(sensorName, sensorValue);
69 | }
70 |
71 | public Thread startMonitoring() {
72 | if (monitoringThread != null) {
73 | return monitoringThread;
74 | }
75 |
76 | enableMonitoring = true;
77 | monitoringThread = new Thread(new Runnable() {
78 | @Override
79 | public void run() {
80 | monitoringThread();
81 | }
82 | });
83 |
84 | monitoringThread.start();
85 | return monitoringThread;
86 | }
87 |
88 | public void stopMonitoring() {
89 | if (monitoringThread != null) {
90 | enableMonitoring = false;
91 | try {
92 | monitoringThread.join();
93 | } catch (InterruptedException e) {
94 | LOGGER.warning("joining monitoring thread got interrupted");
95 | }
96 | monitoringThread = null;
97 | }
98 | }
99 |
100 | public void addNotifier(TestDeviceNotifier notifier) {
101 | notifiers.add(notifier);
102 | }
103 |
104 | public void removeNotifier(TestDeviceNotifier notifier) {
105 | notifiers.remove(notifier);
106 | }
107 |
108 | private void monitoringThread() {
109 | while (enableMonitoring) {
110 | for (Entry entry : sensors.entrySet()) {
111 | if (entry.getValue().compareTo(threshold) > 0) {
112 | LOGGER.finer("sensor " + entry.getKey() + " exceeded threshould (" + threshold + "): "
113 | + entry.getValue());
114 |
115 | for (TestDeviceNotifier notifier : notifiers) {
116 | notifier.reportAlarm(entry.getKey(), entry.getValue(), threshold);
117 | }
118 | }
119 | }
120 |
121 | try {
122 | Thread.sleep(150);
123 | } catch (InterruptedException e) {
124 | LOGGER.warning("monitoring thread got interrupted");
125 | break;
126 | }
127 | }
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/test/java/com/amazonaws/services/iot/client/TestDeviceNotifier.java:
--------------------------------------------------------------------------------
1 | package com.amazonaws.services.iot.client;
2 |
3 | public interface TestDeviceNotifier {
4 |
5 | void reportAlarm(String sensorName, Float sensorValue, Float threshold);
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/test/java/com/amazonaws/services/iot/client/TestTopic.java:
--------------------------------------------------------------------------------
1 | package com.amazonaws.services.iot.client;
2 |
3 | import java.util.Arrays;
4 | import java.util.logging.Logger;
5 |
6 | public class TestTopic extends AWSIotTopic {
7 |
8 | private static final Logger LOGGER = Logger.getLogger(TestTopic.class.getName());
9 |
10 | public boolean isSuccess;
11 | public boolean isFailure;
12 | public boolean isTimeout;
13 | public long expectedMessageCount;
14 | public long unexpectedMessageCount;
15 | public byte[] lastPayload;
16 |
17 | public final byte[] expected;
18 |
19 | public TestTopic(String topic, byte[] expected) {
20 | super(topic);
21 | this.expected = expected;
22 | }
23 |
24 | @Override
25 | public void onMessage(AWSIotMessage message) {
26 | LOGGER.finer("message received for " + topic);
27 | lastPayload = message.getPayload();
28 | if (Arrays.equals(expected, lastPayload)) {
29 | expectedMessageCount++;
30 | } else {
31 | unexpectedMessageCount++;
32 | }
33 | }
34 |
35 | @Override
36 | public void onSuccess() {
37 | LOGGER.finer("request success for " + topic);
38 | isSuccess = true;
39 | }
40 |
41 | @Override
42 | public void onFailure() {
43 | LOGGER.finer("request failure for " + topic);
44 | isFailure = true;
45 | }
46 |
47 | @Override
48 | public void onTimeout() {
49 | LOGGER.finer("request timeout for " + topic);
50 | isTimeout = true;
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/test/java/com/amazonaws/services/iot/client/auth:
--------------------------------------------------------------------------------
1 | package com.amazonaws.services.iot.client.auth;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import com.amazonaws.auth.AWSCredentials;
6 | import com.amazonaws.auth.AWSCredentialsProvider;
7 | import com.amazonaws.auth.AWSSessionCredentials;
8 | import com.amazonaws.services.iot.client.auth.Credentials;
9 | import com.amazonaws.services.iot.client.auth.CredentialsProvider;
10 | import org.junit.Test;
11 |
12 | public class AwsCredentialsProviderAdapterTest {
13 |
14 | private static String ACCESS_KEY_ID = "TestAccessKeyId";
15 | private static String SECRET_ACCESS_KEY = "TestSecretAccessKey";
16 | private static String SESSION_TOKEN = "TestSessionToken";
17 |
18 | private class TestAWSCredentials implements AWSCredentials {
19 | private String accessKeyId;
20 | private String secretAccessKey;
21 |
22 | public TestAWSCredentials(String accessKeyId, String secretAccessKey) {
23 | this.accessKeyId = accessKeyId;
24 | this.secretAccessKey = secretAccessKey;
25 | }
26 |
27 | public String getAWSAccessKeyId() {
28 | return accessKeyId;
29 | }
30 |
31 | public String getAWSSecretKey() {
32 | return secretAccessKey;
33 | }
34 | }
35 |
36 | private class TestSessionAWSCredentials extends TestAWSCredentials implements AWSSessionCredentials {
37 | private String sessionToken;
38 |
39 | public TestSessionAWSCredentials(String accessKeyId, String secretAccessKey, String sessionToken) {
40 | super(accessKeyId, secretAccessKey);
41 | this.sessionToken = sessionToken;
42 | }
43 |
44 | public String getSessionToken() {
45 | return sessionToken;
46 | }
47 | }
48 |
49 | private class TestStaticAWSCredentialsProvider implements AWSCredentialsProvider {
50 |
51 | private AWSCredentials credentials;
52 |
53 | public TestStaticAWSCredentialsProvider(AWSCredentials credentials) {
54 | this.credentials = credentials;
55 | }
56 |
57 | public AWSCredentials getCredentials() {
58 | return credentials;
59 | }
60 |
61 | public void refresh() {}
62 | }
63 |
64 | private void testAdapter(String accessKeyId, String secretAccessKey, String sessionToken) {
65 | AWSCredentials innerCreds = null;
66 | if (sessionToken == null) {
67 | innerCreds = new TestAWSCredentials(accessKeyId, secretAccessKey);
68 | } else {
69 | innerCreds = new TestSessionAWSCredentials(accessKeyId, secretAccessKey, sessionToken);
70 | }
71 |
72 | AWSCredentialsProvider innerProvider = new TestStaticAWSCredentialsProvider(innerCreds);
73 | CredentialsProvider provider = new AwsCredentialsProviderAdapter(innerProvider);
74 |
75 | Credentials credentials = provider.getCredentials();
76 | assertEquals(accessKeyId, credentials.getAccessKeyId());
77 | assertEquals(secretAccessKey, credentials.getSecretAccessKey());
78 | assertEquals(sessionToken, credentials.getSessionToken());
79 | }
80 |
81 | @Test
82 | public void testAdapterFetchCredentials() {
83 | testAdapter(ACCESS_KEY_ID, SECRET_ACCESS_KEY, null);
84 | }
85 |
86 | @Test
87 | public void testAdapterFetchSessionCredentials() {
88 | testAdapter(ACCESS_KEY_ID, SECRET_ACCESS_KEY, SESSION_TOKEN);
89 | }
90 |
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/test/java/com/amazonaws/services/iot/client/core/AwsIotCompletionTest.java:
--------------------------------------------------------------------------------
1 | package com.amazonaws.services.iot.client.core;
2 |
3 | import java.util.concurrent.Executors;
4 | import java.util.concurrent.Future;
5 | import java.util.concurrent.ScheduledExecutorService;
6 | import java.util.concurrent.TimeUnit;
7 |
8 | import org.junit.Before;
9 | import org.junit.Test;
10 | import org.junit.runner.RunWith;
11 | import org.mockito.Mock;
12 | import org.mockito.invocation.InvocationOnMock;
13 |
14 | import static org.junit.Assert.*;
15 | import static org.mockito.Mockito.*;
16 |
17 | import org.mockito.runners.MockitoJUnitRunner;
18 | import org.mockito.stubbing.Answer;
19 |
20 | import com.amazonaws.services.iot.client.AWSIotException;
21 | import com.amazonaws.services.iot.client.AWSIotMessage;
22 | import com.amazonaws.services.iot.client.AWSIotQos;
23 | import com.amazonaws.services.iot.client.AWSIotTimeoutException;
24 | import com.amazonaws.services.iot.client.core.AbstractAwsIotClient;
25 | import com.amazonaws.services.iot.client.core.AwsIotCompletion;
26 |
27 | @RunWith(MockitoJUnitRunner.class)
28 | public class AwsIotCompletionTest {
29 |
30 | private static final String TEST_TOPIC = "test/topic";
31 | private static final AWSIotQos TEST_QOS = AWSIotQos.QOS0;
32 |
33 | private final ScheduledExecutorService executionService = Executors.newScheduledThreadPool(2);
34 |
35 | @Mock
36 | private AbstractAwsIotClient client;
37 |
38 | @Before
39 | public void setup() {
40 | doAnswer(new Answer>() {
41 | @Override
42 | public Future> answer(InvocationOnMock invocation) throws Throwable {
43 | Runnable runnable = (Runnable) invocation.getArguments()[0];
44 | long timeout = (long) invocation.getArguments()[1];
45 | return scheduleTimeoutTask(runnable, timeout);
46 | }
47 | }).when(client).scheduleTimeoutTask(any(Runnable.class), anyLong());
48 | }
49 |
50 | @Test
51 | public void testSyncWithoutTimeoutSuccess() throws AWSIotException, AWSIotTimeoutException {
52 | AwsIotCompletion completion = new AwsIotCompletion(TEST_TOPIC, TEST_QOS, 0);
53 |
54 | // schedule a delayed task to simulate the callback
55 | scheduleTimeoutTask(completion, "success", 100);
56 |
57 | completion.get(client);
58 | }
59 |
60 | @Test(expected = AWSIotException.class)
61 | public void testSyncWithoutTimeoutFailure() throws AWSIotException, AWSIotTimeoutException {
62 | AwsIotCompletion completion = new AwsIotCompletion(TEST_TOPIC, TEST_QOS, 0);
63 |
64 | // schedule a delayed task to simulate the callback
65 | scheduleTimeoutTask(completion, "failure", 100);
66 |
67 | completion.get(client);
68 | }
69 |
70 | @Test
71 | public void testSyncWithTimeoutSuccess() throws AWSIotException, AWSIotTimeoutException {
72 | AwsIotCompletion completion = new AwsIotCompletion(TEST_TOPIC, TEST_QOS, 100);
73 |
74 | // schedule a delayed task to simulate the callback
75 | scheduleTimeoutTask(completion, "success", 50);
76 |
77 | completion.get(client);
78 |
79 | assertTrue(completion.timeoutTask.isCancelled());
80 | }
81 |
82 | @Test(expected = AWSIotException.class)
83 | public void testSyncWithTimeoutFailure() throws AWSIotException, AWSIotTimeoutException {
84 | AwsIotCompletion completion = new AwsIotCompletion(TEST_TOPIC, TEST_QOS, (String) null, 100);
85 |
86 | // schedule a delayed task to simulate the callback
87 | scheduleTimeoutTask(completion, "failure", 50);
88 |
89 | try {
90 | completion.get(client);
91 | } finally {
92 | assertTrue(completion.timeoutTask.isCancelled());
93 | }
94 | }
95 |
96 | @Test(expected = AWSIotTimeoutException.class)
97 | public void testSyncWithTimeoutTimeout() throws AWSIotException, AWSIotTimeoutException {
98 | AwsIotCompletion completion = new AwsIotCompletion(TEST_TOPIC, TEST_QOS, (byte[]) null, 100);
99 |
100 | try {
101 | completion.get(client);
102 | } finally {
103 | assertTrue(completion.timeoutTask.isCancelled());
104 | }
105 | }
106 |
107 | @Test
108 | public void testAsyncWithoutTimeoutSuccess() throws AWSIotException, AWSIotTimeoutException, InterruptedException {
109 | TestMessage request = new TestMessage(TEST_TOPIC, TEST_QOS);
110 | AwsIotCompletion completion = new AwsIotCompletion(request, 0, true);
111 |
112 | // schedule a delayed task to simulate the callback
113 | scheduleTimeoutTask(completion, "success", 100);
114 |
115 | completion.get(client);
116 |
117 | synchronized (request) {
118 | while (!request.isSuccess && !request.isFailure && !request.isTimeout) {
119 | request.wait(150);
120 | break;
121 | }
122 | }
123 |
124 | assertTrue(request.isSuccess);
125 | assertFalse(request.isFailure);
126 | assertFalse(request.isTimeout);
127 | }
128 |
129 | @Test
130 | public void testAsyncWithoutTimeoutFailure() throws AWSIotException, AWSIotTimeoutException, InterruptedException {
131 | TestMessage request = new TestMessage(TEST_TOPIC, TEST_QOS);
132 | AwsIotCompletion completion = new AwsIotCompletion(request, 0, true);
133 |
134 | // schedule a delayed task to simulate the callback
135 | scheduleTimeoutTask(completion, "failure", 100);
136 |
137 | completion.get(client);
138 |
139 | synchronized (request) {
140 | while (!request.isSuccess && !request.isFailure && !request.isTimeout) {
141 | request.wait(200);
142 | break;
143 | }
144 | }
145 |
146 | assertTrue(request.isFailure);
147 | assertFalse(request.isSuccess);
148 | assertFalse(request.isTimeout);
149 | }
150 |
151 | @Test
152 | public void testAsyncWithTimeoutSuccess() throws AWSIotException, AWSIotTimeoutException, InterruptedException {
153 | TestMessage request = new TestMessage(TEST_TOPIC, TEST_QOS);
154 | AwsIotCompletion completion = new AwsIotCompletion(request, 100, true);
155 |
156 | // schedule a delayed task to simulate the callback
157 | scheduleTimeoutTask(completion, "success", 50);
158 |
159 | completion.get(client);
160 |
161 | synchronized (request) {
162 | while (!request.isSuccess && !request.isFailure && !request.isTimeout) {
163 | request.wait(200);
164 | break;
165 | }
166 | }
167 |
168 | assertTrue(request.isSuccess);
169 | assertFalse(request.isFailure);
170 | assertFalse(request.isTimeout);
171 | assertTrue(completion.timeoutTask.isCancelled());
172 | }
173 |
174 | @Test
175 | public void testAsyncWithTimeoutFailure() throws AWSIotException, AWSIotTimeoutException, InterruptedException {
176 | TestMessage request = new TestMessage(TEST_TOPIC, TEST_QOS);
177 | AwsIotCompletion completion = new AwsIotCompletion(request, 100, true);
178 |
179 | // schedule a delayed task to simulate the callback
180 | scheduleTimeoutTask(completion, "failure", 50);
181 |
182 | completion.get(client);
183 |
184 | synchronized (request) {
185 | while (!request.isSuccess && !request.isFailure && !request.isTimeout) {
186 | request.wait(200);
187 | break;
188 | }
189 | }
190 |
191 | assertTrue(request.isFailure);
192 | assertFalse(request.isSuccess);
193 | assertFalse(request.isTimeout);
194 | assertTrue(completion.timeoutTask.isCancelled());
195 | }
196 |
197 | @Test
198 | public void testAsyncWithTimeoutTimeout() throws AWSIotException, AWSIotTimeoutException, InterruptedException {
199 | TestMessage request = new TestMessage(TEST_TOPIC, TEST_QOS);
200 | AwsIotCompletion completion = new AwsIotCompletion(request, 100, true);
201 |
202 | completion.get(client);
203 |
204 | synchronized (request) {
205 | while (!request.isSuccess && !request.isFailure && !request.isTimeout) {
206 | request.wait(200);
207 | break;
208 | }
209 | }
210 |
211 | assertTrue(request.isTimeout);
212 | assertFalse(request.isSuccess);
213 | assertFalse(request.isFailure);
214 | assertTrue(completion.timeoutTask.isCancelled());
215 | }
216 |
217 | class TestMessage extends AWSIotMessage {
218 | public boolean isSuccess;
219 | public boolean isFailure;
220 | public boolean isTimeout;
221 |
222 | public TestMessage(String topic, AWSIotQos qos) {
223 | super(topic, qos);
224 | }
225 |
226 | @Override
227 | public void onSuccess() {
228 | synchronized (this) {
229 | isSuccess = true;
230 | notify();
231 | }
232 | }
233 |
234 | @Override
235 | public void onFailure() {
236 | synchronized (this) {
237 | isFailure = true;
238 | notify();
239 | }
240 | }
241 |
242 | @Override
243 | public void onTimeout() {
244 | synchronized (this) {
245 | isTimeout = true;
246 | notify();
247 | }
248 | }
249 | }
250 |
251 | private Future> scheduleTimeoutTask(Runnable runnable, long timeout) {
252 | return executionService.schedule(runnable, timeout, TimeUnit.MILLISECONDS);
253 | }
254 |
255 | private Future> scheduleTimeoutTask(final AwsIotCompletion completion, final String whichCallback, long timeout) {
256 | return executionService.schedule(new Runnable() {
257 | @Override
258 | public void run() {
259 | if (whichCallback.equals("success")) {
260 | completion.onSuccess();
261 | } else if (whichCallback.equals("failure")) {
262 | completion.onFailure();
263 | } else if (whichCallback.equals("timeout")) {
264 | completion.onTimeout();
265 | }
266 | }
267 | }, timeout, TimeUnit.MILLISECONDS);
268 | }
269 |
270 | }
271 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/test/java/com/amazonaws/services/iot/client/core/AwsIotWebsocketConnectionTest.java:
--------------------------------------------------------------------------------
1 | package com.amazonaws.services.iot.client.core;
2 |
3 | import static org.junit.Assert.*;
4 | import static org.mockito.Mockito.when;
5 |
6 | import java.util.Set;
7 |
8 | import org.junit.Before;
9 | import org.junit.Test;
10 | import org.junit.runner.RunWith;
11 | import org.mockito.Mock;
12 | import org.mockito.runners.MockitoJUnitRunner;
13 |
14 | import com.amazonaws.services.iot.client.AWSIotException;
15 |
16 | @RunWith(MockitoJUnitRunner.class)
17 | public class AwsIotWebsocketConnectionTest {
18 |
19 | private final String ClientId = "test";
20 | private final String EndPoint = "iot.us-east-1.AMAZONAWS.COM";
21 | private final String AccessKeyId = "123";
22 | private final String SecretAccessKey = "456";
23 | private final String NewAccessKeyId = "new123";
24 |
25 | @Mock
26 | private AbstractAwsIotClient client;
27 |
28 | private AwsIotWebsocketConnection connection;
29 |
30 | @Before
31 | public void setup() throws AWSIotException {
32 | when(client.getClientEndpoint()).thenReturn(EndPoint);
33 | when(client.getClientId()).thenReturn(ClientId);
34 |
35 | connection = new AwsIotWebsocketConnection(client, AccessKeyId, SecretAccessKey);
36 | }
37 |
38 | @Test
39 | public void testGetServerUris() throws AWSIotException {
40 | Set uris = connection.getServerUris();
41 |
42 | assertEquals(1, uris.size());
43 | }
44 |
45 | @Test
46 | public void testUpdateCredentails() throws AWSIotException {
47 | Set uris1 = connection.getServerUris();
48 |
49 | connection.updateCredentials(NewAccessKeyId, SecretAccessKey, null);
50 | Set uris2 = connection.getServerUris();
51 |
52 | assertEquals(1, uris1.size());
53 | assertEquals(1, uris2.size());
54 | assertTrue(!uris1.equals(uris2));
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/test/java/com/amazonaws/services/iot/client/mqtt/AwsIotMqttClientListenerTest.java:
--------------------------------------------------------------------------------
1 | package com.amazonaws.services.iot.client.mqtt;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertTrue;
5 | import static org.mockito.Matchers.any;
6 | import static org.mockito.Mockito.doAnswer;
7 | import static org.mockito.Mockito.doNothing;
8 | import static org.mockito.Mockito.times;
9 | import static org.mockito.Mockito.verify;
10 | import static org.mockito.Mockito.when;
11 |
12 | import java.util.Arrays;
13 | import java.util.concurrent.Future;
14 |
15 | import org.eclipse.paho.client.mqttv3.MqttMessage;
16 | import org.junit.Before;
17 | import org.junit.Test;
18 | import org.junit.runner.RunWith;
19 | import org.mockito.ArgumentCaptor;
20 | import org.mockito.Mock;
21 | import org.mockito.invocation.InvocationOnMock;
22 | import org.mockito.runners.MockitoJUnitRunner;
23 | import org.mockito.stubbing.Answer;
24 |
25 | import com.amazonaws.services.iot.client.AWSIotMessage;
26 | import com.amazonaws.services.iot.client.AWSIotQos;
27 | import com.amazonaws.services.iot.client.core.AbstractAwsIotClient;
28 |
29 | @RunWith(MockitoJUnitRunner.class)
30 | public class AwsIotMqttClientListenerTest {
31 |
32 | private static final String TEST_TOPIC = "test/topic";
33 | private static final byte[] TEST_PAYLOAD = "test payload".getBytes();
34 |
35 | @Mock
36 | private AbstractAwsIotClient client;
37 | @Mock
38 | private AwsIotMqttConnection connection;
39 |
40 | @Before
41 | public void setup() {
42 | doAnswer(new Answer>() {
43 | @Override
44 | public Future> answer(InvocationOnMock invocation) throws Throwable {
45 | Runnable runnable = (Runnable) invocation.getArguments()[0];
46 | runnable.run();
47 | return null;
48 | }
49 | }).when(client).scheduleTask(any(Runnable.class));
50 |
51 | when(client.getConnection()).thenReturn(connection);
52 | }
53 |
54 | @Test
55 | public void testConnectionLost() {
56 | AwsIotMqttClientListener listener = new AwsIotMqttClientListener(client);
57 |
58 | listener.connectionLost(null);
59 |
60 | verify(connection, times(1)).onConnectionFailure();
61 | }
62 |
63 | @Test
64 | public void testOnMessageArrived() throws Exception {
65 | AwsIotMqttClientListener listener = new AwsIotMqttClientListener(client);
66 |
67 | MqttMessage mqttMessage = new MqttMessage();
68 | mqttMessage.setQos(0);
69 | mqttMessage.setPayload(TEST_PAYLOAD);
70 |
71 | ArgumentCaptor messageCaptor = ArgumentCaptor.forClass(AWSIotMessage.class);
72 | doNothing().when(client).dispatch(messageCaptor.capture());
73 |
74 | listener.messageArrived(TEST_TOPIC, mqttMessage);
75 |
76 | verify(client, times(1)).dispatch(any(AWSIotMessage.class));
77 | assertTrue(Arrays.equals(TEST_PAYLOAD, messageCaptor.getValue().getPayload()));
78 | assertEquals(AWSIotQos.QOS0, messageCaptor.getValue().getQos());
79 | }
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/test/java/com/amazonaws/services/iot/client/mqtt/AwsIotMqttConnectionListenerTest.java:
--------------------------------------------------------------------------------
1 | package com.amazonaws.services.iot.client.mqtt;
2 |
3 | import static org.mockito.Matchers.any;
4 | import static org.mockito.Mockito.doAnswer;
5 | import static org.mockito.Mockito.times;
6 | import static org.mockito.Mockito.verify;
7 | import static org.mockito.Mockito.when;
8 |
9 | import java.util.concurrent.Future;
10 |
11 | import org.junit.Before;
12 | import org.junit.Test;
13 | import org.junit.runner.RunWith;
14 | import org.mockito.Mock;
15 | import org.mockito.invocation.InvocationOnMock;
16 | import org.mockito.runners.MockitoJUnitRunner;
17 | import org.mockito.stubbing.Answer;
18 |
19 | import com.amazonaws.services.iot.client.core.AbstractAwsIotClient;
20 | import com.amazonaws.services.iot.client.core.AwsIotMessageCallback;
21 |
22 | @RunWith(MockitoJUnitRunner.class)
23 | public class AwsIotMqttConnectionListenerTest {
24 |
25 | @Mock
26 | private AbstractAwsIotClient client;
27 | @Mock
28 | private AwsIotMqttConnection connection;
29 | @Mock
30 | AwsIotMessageCallback userCallback;
31 |
32 | @Before
33 | public void setup() {
34 | doAnswer(new Answer>() {
35 | @Override
36 | public Future> answer(InvocationOnMock invocation) throws Throwable {
37 | Runnable runnable = (Runnable) invocation.getArguments()[0];
38 | runnable.run();
39 | return null;
40 | }
41 | }).when(client).scheduleTask(any(Runnable.class));
42 |
43 | when(client.getConnection()).thenReturn(connection);
44 | }
45 |
46 | @Test
47 | public void testOnConnectSuccess() {
48 | AwsIotMqttConnectionListener listener = new AwsIotMqttConnectionListener(client, true, userCallback);
49 |
50 | listener.onSuccess(null);
51 |
52 | verify(connection, times(1)).onConnectionSuccess();
53 | verify(userCallback, times(1)).onSuccess();
54 | }
55 |
56 | @Test
57 | public void testOnConnectFailure() {
58 | AwsIotMqttConnectionListener listener = new AwsIotMqttConnectionListener(client, true, userCallback);
59 |
60 | listener.onFailure(null, null);
61 |
62 | verify(connection, times(1)).onConnectionFailure();
63 | verify(userCallback, times(1)).onFailure();
64 | }
65 |
66 | @Test
67 | public void testOnDisconnectSuccess() {
68 | AwsIotMqttConnectionListener listener = new AwsIotMqttConnectionListener(client, false, userCallback);
69 |
70 | listener.onSuccess(null);
71 |
72 | verify(connection, times(1)).onConnectionClosed();
73 | verify(userCallback, times(1)).onSuccess();
74 | }
75 |
76 | @Test
77 | public void testOnDisconnectFailure() {
78 | AwsIotMqttConnectionListener listener = new AwsIotMqttConnectionListener(client, false, userCallback);
79 |
80 | listener.onFailure(null, null);
81 |
82 | verify(connection, times(1)).onConnectionClosed();
83 | verify(userCallback, times(1)).onFailure();
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/test/java/com/amazonaws/services/iot/client/mqtt/AwsIotMqttMessageListenerTest.java:
--------------------------------------------------------------------------------
1 | package com.amazonaws.services.iot.client.mqtt;
2 |
3 | import static org.mockito.Matchers.any;
4 | import static org.mockito.Mockito.doAnswer;
5 | import static org.mockito.Mockito.times;
6 | import static org.mockito.Mockito.verify;
7 | import static org.mockito.Mockito.when;
8 |
9 | import java.util.concurrent.Future;
10 |
11 | import org.eclipse.paho.client.mqttv3.MqttToken;
12 | import org.eclipse.paho.client.mqttv3.internal.wire.MqttSuback;
13 | import org.junit.Before;
14 | import org.junit.Test;
15 | import org.junit.runner.RunWith;
16 | import org.mockito.Mock;
17 | import org.mockito.invocation.InvocationOnMock;
18 | import org.mockito.runners.MockitoJUnitRunner;
19 | import org.mockito.stubbing.Answer;
20 |
21 | import com.amazonaws.services.iot.client.AWSIotMessage;
22 | import com.amazonaws.services.iot.client.core.AbstractAwsIotClient;
23 |
24 | @RunWith(MockitoJUnitRunner.class)
25 | public class AwsIotMqttMessageListenerTest {
26 |
27 | @Mock
28 | private AbstractAwsIotClient client;
29 | @Mock
30 | private AWSIotMessage message;
31 | @Mock
32 | private MqttToken token;
33 | @Mock
34 | private MqttSuback subAck;
35 |
36 | @Before
37 | public void setup() {
38 | doAnswer(new Answer>() {
39 | @Override
40 | public Future> answer(InvocationOnMock invocation) throws Throwable {
41 | Runnable runnable = (Runnable) invocation.getArguments()[0];
42 | runnable.run();
43 | return null;
44 | }
45 | }).when(client).scheduleTask(any(Runnable.class));
46 |
47 | when(token.getUserContext()).thenReturn(message);
48 | }
49 |
50 | @Test
51 | public void testOnSuccess() {
52 | AwsIotMqttMessageListener listener = new AwsIotMqttMessageListener(client);
53 | listener.onSuccess(token);
54 |
55 | verify(message, times(1)).onSuccess();
56 | }
57 |
58 | @Test
59 | public void testOnSuccessWithSubAckAccepted() {
60 | AwsIotMqttMessageListener listener = new AwsIotMqttMessageListener(client);
61 |
62 | when(token.getResponse()).thenReturn(subAck);
63 | when(subAck.getGrantedQos()).thenReturn(new int[] { 1 });
64 |
65 | listener.onSuccess(token);
66 |
67 | verify(message, times(1)).onSuccess();
68 | }
69 |
70 | @Test
71 | public void testOnSuccessWithSubAckRejected() {
72 | AwsIotMqttMessageListener listener = new AwsIotMqttMessageListener(client);
73 |
74 | when(token.getResponse()).thenReturn(subAck);
75 | when(subAck.getGrantedQos()).thenReturn(new int[] { 128 });
76 |
77 | listener.onSuccess(token);
78 |
79 | verify(message, times(1)).onFailure();
80 | }
81 |
82 | @Test
83 | public void testOnFailure() {
84 | AwsIotMqttMessageListener listener = new AwsIotMqttMessageListener(client);
85 | listener.onFailure(token, null);
86 |
87 | verify(message, times(1)).onFailure();
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/test/java/com/amazonaws/services/iot/client/shadow/AwsIotDeviceCommandTest.java:
--------------------------------------------------------------------------------
1 | package com.amazonaws.services.iot.client.shadow;
2 |
3 | import static org.junit.Assert.*;
4 | import static org.mockito.Mockito.*;
5 |
6 | import org.junit.Before;
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 | import org.mockito.Mock;
10 | import org.mockito.runners.MockitoJUnitRunner;
11 |
12 | import com.amazonaws.services.iot.client.AWSIotException;
13 | import com.amazonaws.services.iot.client.AWSIotMessage;
14 | import com.amazonaws.services.iot.client.AWSIotQos;
15 | import com.amazonaws.services.iot.client.AWSIotTimeoutException;
16 | import com.amazonaws.services.iot.client.core.AbstractAwsIotClient;
17 | import com.amazonaws.services.iot.client.shadow.AwsIotDeviceCommandManager.Command;
18 |
19 | @RunWith(MockitoJUnitRunner.class)
20 | public class AwsIotDeviceCommandTest {
21 |
22 | @Mock
23 | private AwsIotDeviceCommandManager commandManager;
24 | @Mock
25 | private AbstractAwsIotClient client;
26 | @Mock
27 | private AbstractAwsIotDevice device;
28 | @Mock
29 | private AWSIotMessage request;
30 |
31 | private AWSIotMessage response;
32 |
33 | @Before
34 | public void setup() {
35 | when(device.getClient()).thenReturn(client);
36 |
37 | response = new AWSIotMessage("test/topic", AWSIotQos.QOS0, "response payload");
38 | }
39 |
40 | @Test
41 | public void testPutWhenDeviceReady() throws AWSIotException {
42 | AwsIotDeviceCommand command = new AwsIotDeviceCommand(commandManager, Command.GET, "1", request, 0, true);
43 |
44 | when(device.isCommandReady(Command.GET)).thenReturn(true);
45 |
46 | command.put(device);
47 |
48 | verify(client, times(1)).publish(command, 0);
49 | }
50 |
51 | @Test
52 | public void testPutWhenDeviceNotReady() throws AWSIotException {
53 | AwsIotDeviceCommand command = new AwsIotDeviceCommand(commandManager, Command.GET, "1", request, 0, true);
54 |
55 | when(device.isCommandReady(Command.GET)).thenReturn(false);
56 |
57 | command.put(device);
58 |
59 | verify(client, times(0)).publish(command, 0);
60 | }
61 |
62 | @Test
63 | public void testGetWithPayload() throws AWSIotException, AWSIotTimeoutException {
64 | AwsIotDeviceCommand command = new AwsIotDeviceCommand(commandManager, Command.GET, "1", request, 0, true);
65 | command.setResponse(response);
66 | command.onSuccess();
67 |
68 | String payload = command.get(device);
69 |
70 | assertEquals("response payload", payload);
71 | }
72 |
73 | @Test
74 | public void testGetWithoutPayload() throws AWSIotException, AWSIotTimeoutException {
75 | AwsIotDeviceCommand command = new AwsIotDeviceCommand(commandManager, Command.GET, "1", request, 0, true);
76 | command.onSuccess();
77 |
78 | String payload = command.get(device);
79 |
80 | assertEquals(null, payload);
81 | verify(request, times(0)).onSuccess();
82 | }
83 |
84 | @Test
85 | public void testGetFailure() throws AWSIotException, AWSIotTimeoutException {
86 | AwsIotDeviceCommand command = new AwsIotDeviceCommand(commandManager, Command.GET, "1", request, 0, true);
87 | command.onFailure();
88 |
89 | command.get(device);
90 |
91 | verify(request, times(1)).onFailure();
92 | }
93 |
94 | @Test
95 | public void testGetTimeout() throws AWSIotException, AWSIotTimeoutException {
96 | AwsIotDeviceCommand command = new AwsIotDeviceCommand(commandManager, Command.GET, "1", request, 0, true);
97 | command.onTimeout();
98 |
99 | command.get(device);
100 |
101 | verify(request, times(1)).onTimeout();
102 | }
103 |
104 | @Test(expected = AWSIotException.class)
105 | public void testGetFailureSync() throws AWSIotException, AWSIotTimeoutException {
106 | AwsIotDeviceCommand command = new AwsIotDeviceCommand(commandManager, Command.GET, "1", request, 0, false);
107 | command.onFailure();
108 |
109 | command.get(device);
110 | }
111 |
112 | @Test(expected = AWSIotTimeoutException.class)
113 | public void testGetTimeoutSync() throws AWSIotException, AWSIotTimeoutException {
114 | AwsIotDeviceCommand command = new AwsIotDeviceCommand(commandManager, Command.GET, "1", request, 0, false);
115 | command.onTimeout();
116 |
117 | try {
118 | command.get(device);
119 | } finally{
120 | verify(commandManager, times(1)).onCommandTimeout(command);
121 | }
122 | }
123 |
124 | }
125 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/test/java/com/amazonaws/services/iot/client/shadow/AwsIotDeviceDeltaListenerTest.java:
--------------------------------------------------------------------------------
1 | package com.amazonaws.services.iot.client.shadow;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.mockito.Matchers.anyString;
5 | import static org.mockito.Mockito.never;
6 | import static org.mockito.Mockito.times;
7 | import static org.mockito.Mockito.verify;
8 | import static org.mockito.Mockito.when;
9 |
10 | import java.io.IOException;
11 | import java.util.concurrent.atomic.AtomicLong;
12 |
13 | import org.junit.Before;
14 | import org.junit.Test;
15 | import org.junit.runner.RunWith;
16 | import org.mockito.Mock;
17 | import org.mockito.runners.MockitoJUnitRunner;
18 |
19 | import com.amazonaws.services.iot.client.AWSIotMessage;
20 | import com.amazonaws.services.iot.client.AWSIotQos;
21 | import com.fasterxml.jackson.core.JsonProcessingException;
22 | import com.fasterxml.jackson.databind.ObjectMapper;
23 |
24 | @RunWith(MockitoJUnitRunner.class)
25 | public class AwsIotDeviceDeltaListenerTest {
26 |
27 | private static final String TEST_SHADOW = "shadow";
28 | private static final String TEST_TOPIC = "test/topic";
29 | private static final AWSIotQos TEST_QOS = AWSIotQos.QOS0;
30 |
31 | @Mock
32 | private AbstractAwsIotDevice device;
33 |
34 | private ObjectMapper objectMapper;
35 |
36 | @Before
37 | public void setup() {
38 | objectMapper = new ObjectMapper();
39 | device.enableVersioning = false;
40 | when(device.getThingName()).thenReturn(TEST_SHADOW);
41 | }
42 |
43 | @Test
44 | public void testNullPayload() {
45 | AWSIotMessage message = new AWSIotMessage(TEST_TOPIC, TEST_QOS);
46 |
47 | AwsIotDeviceDeltaListener listener = new AwsIotDeviceDeltaListener(TEST_TOPIC, TEST_QOS, device);
48 | listener.onMessage(message);
49 |
50 | verify(device, never()).getJsonObjectMapper();
51 | }
52 |
53 | @Test
54 | public void testReadTreeNonObject() throws JsonProcessingException, IOException {
55 | when(device.getJsonObjectMapper()).thenReturn(objectMapper);
56 |
57 | AWSIotMessage message = new AWSIotMessage(TEST_TOPIC, TEST_QOS, "123");
58 |
59 | AwsIotDeviceDeltaListener listener = new AwsIotDeviceDeltaListener(TEST_TOPIC, TEST_QOS, device);
60 | listener.onMessage(message);
61 |
62 | verify(device, times(1)).getJsonObjectMapper();
63 | verify(device, never()).onShadowUpdate(anyString());
64 | }
65 |
66 | @Test
67 | public void testReadTreeMissingState() throws JsonProcessingException, IOException {
68 | when(device.getJsonObjectMapper()).thenReturn(objectMapper);
69 |
70 | AWSIotMessage message = new AWSIotMessage(TEST_TOPIC, TEST_QOS, "{}");
71 |
72 | AwsIotDeviceDeltaListener listener = new AwsIotDeviceDeltaListener(TEST_TOPIC, TEST_QOS, device);
73 | listener.onMessage(message);
74 |
75 | verify(device, times(1)).getJsonObjectMapper();
76 | verify(device, never()).onShadowUpdate(anyString());
77 | }
78 |
79 | @Test
80 | public void testOnShadowUpdate() throws JsonProcessingException, IOException {
81 | when(device.getJsonObjectMapper()).thenReturn(objectMapper);
82 |
83 | AWSIotMessage message = new AWSIotMessage(TEST_TOPIC, TEST_QOS, "{\"state\":{}}");
84 |
85 | AwsIotDeviceDeltaListener listener = new AwsIotDeviceDeltaListener(TEST_TOPIC, TEST_QOS, device);
86 | listener.onMessage(message);
87 |
88 | verify(device, times(1)).getJsonObjectMapper();
89 | verify(device, times(1)).onShadowUpdate(anyString());
90 | }
91 |
92 | @Test
93 | public void testVersioningEnabledMissingVersion() throws JsonProcessingException, IOException {
94 | when(device.getJsonObjectMapper()).thenReturn(objectMapper);
95 | device.enableVersioning = true;
96 |
97 | AWSIotMessage message = new AWSIotMessage(TEST_TOPIC, TEST_QOS, "{\"state\":{}}");
98 |
99 | AwsIotDeviceDeltaListener listener = new AwsIotDeviceDeltaListener(TEST_TOPIC, TEST_QOS, device);
100 | listener.onMessage(message);
101 |
102 | verify(device, times(1)).getJsonObjectMapper();
103 | verify(device, never()).getLocalVersion();
104 | }
105 |
106 | @Test
107 | public void testVersioningEnabledReceivedOldVersion() throws JsonProcessingException, IOException {
108 | when(device.getJsonObjectMapper()).thenReturn(objectMapper);
109 | when(device.getLocalVersion()).thenReturn(new AtomicLong(2));
110 | device.enableVersioning = true;
111 |
112 | AWSIotMessage message = new AWSIotMessage(TEST_TOPIC, TEST_QOS, "{\"version\":1, \"state\":{}}");
113 |
114 | AwsIotDeviceDeltaListener listener = new AwsIotDeviceDeltaListener(TEST_TOPIC, TEST_QOS, device);
115 | listener.onMessage(message);
116 |
117 | verify(device, times(1)).getJsonObjectMapper();
118 | verify(device, never()).onShadowUpdate(anyString());
119 | }
120 |
121 | @Test
122 | public void testVersioningEnabledReceivedNewerVersion() throws JsonProcessingException, IOException {
123 | AtomicLong localVersion = new AtomicLong(2);
124 | when(device.getJsonObjectMapper()).thenReturn(objectMapper);
125 | when(device.getLocalVersion()).thenReturn(localVersion);
126 | device.enableVersioning = true;
127 |
128 | AWSIotMessage message = new AWSIotMessage(TEST_TOPIC, TEST_QOS, "{\"version\":3, \"state\":{}}");
129 |
130 | AwsIotDeviceDeltaListener listener = new AwsIotDeviceDeltaListener(TEST_TOPIC, TEST_QOS, device);
131 | listener.onMessage(message);
132 |
133 | assertEquals(3, localVersion.get());
134 | verify(device, times(1)).getJsonObjectMapper();
135 | verify(device, times(1)).onShadowUpdate(anyString());
136 | }
137 |
138 | }
139 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/test/java/com/amazonaws/services/iot/client/shadow/AwsIotDeviceReportMessageTest.java:
--------------------------------------------------------------------------------
1 | package com.amazonaws.services.iot.client.shadow;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.mockito.Mockito.never;
5 | import static org.mockito.Mockito.times;
6 | import static org.mockito.Mockito.verify;
7 | import static org.mockito.Mockito.when;
8 |
9 | import java.util.concurrent.atomic.AtomicLong;
10 |
11 | import org.junit.Test;
12 | import org.junit.runner.RunWith;
13 | import org.mockito.Mock;
14 | import org.mockito.runners.MockitoJUnitRunner;
15 |
16 | import com.amazonaws.services.iot.client.AWSIotDeviceErrorCode;
17 | import com.amazonaws.services.iot.client.AWSIotQos;
18 |
19 | @RunWith(MockitoJUnitRunner.class)
20 | public class AwsIotDeviceReportMessageTest {
21 |
22 | private static final String TEST_TOPIC = "test/topic";
23 | private static final AWSIotQos TEST_QOS = AWSIotQos.QOS0;
24 |
25 | @Mock
26 | private AbstractAwsIotDevice device;
27 |
28 | @Test
29 | public void testOnSuccessLocalVersionUnchanged() {
30 | AtomicLong localVersion = new AtomicLong(2);
31 | when(device.getLocalVersion()).thenReturn(localVersion);
32 |
33 | long reportVersion = 2;
34 | AwsIotDeviceReportMessage message = new AwsIotDeviceReportMessage(TEST_TOPIC, TEST_QOS, reportVersion, "",
35 | device);
36 | message.onSuccess();
37 |
38 | assertEquals(3, localVersion.get());
39 | }
40 |
41 | @Test
42 | public void testOnSuccessLocalVersionChanged() {
43 | AtomicLong localVersion = new AtomicLong(4);
44 | when(device.getLocalVersion()).thenReturn(localVersion);
45 |
46 | long reportVersion = 2;
47 | AwsIotDeviceReportMessage message = new AwsIotDeviceReportMessage(TEST_TOPIC, TEST_QOS, reportVersion, "",
48 | device);
49 | message.onSuccess();
50 |
51 | assertEquals(4, localVersion.get());
52 | }
53 |
54 | @Test
55 | public void testOnFailureVersionConflict() {
56 | AwsIotDeviceReportMessage message = new AwsIotDeviceReportMessage(TEST_TOPIC, TEST_QOS, 1, "", device);
57 | message.setErrorCode(AWSIotDeviceErrorCode.CONFLICT);
58 |
59 | message.onFailure();
60 |
61 | verify(device, times(1)).startVersionSync();
62 | }
63 |
64 | @Test
65 | public void testOnFailureNonVersionConflict() {
66 | AwsIotDeviceReportMessage message = new AwsIotDeviceReportMessage(TEST_TOPIC, TEST_QOS, 1, "", device);
67 | message.setErrorCode(AWSIotDeviceErrorCode.NOT_FOUND);
68 |
69 | message.onFailure();
70 |
71 | verify(device, never()).startVersionSync();
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/test/java/com/amazonaws/services/iot/client/shadow/AwsIotDeviceSyncMessageTest.java:
--------------------------------------------------------------------------------
1 | package com.amazonaws.services.iot.client.shadow;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.mockito.Mockito.never;
5 | import static org.mockito.Mockito.verify;
6 | import static org.mockito.Mockito.when;
7 | import static org.mockito.Mockito.lenient;
8 |
9 | import java.util.concurrent.atomic.AtomicLong;
10 |
11 | import org.junit.Before;
12 | import org.junit.Test;
13 | import org.junit.runner.RunWith;
14 | import org.mockito.Mock;
15 | import org.mockito.runners.MockitoJUnitRunner;
16 |
17 | import com.amazonaws.services.iot.client.AWSIotDeviceErrorCode;
18 | import com.amazonaws.services.iot.client.AWSIotQos;
19 | import com.fasterxml.jackson.databind.ObjectMapper;
20 |
21 | @RunWith(MockitoJUnitRunner.class)
22 | public class AwsIotDeviceSyncMessageTest {
23 |
24 | private static final String TEST_TOPIC = "test/topic";
25 | private static final AWSIotQos TEST_QOS = AWSIotQos.QOS0;
26 |
27 | @Mock
28 | private AbstractAwsIotDevice device;
29 |
30 | private ObjectMapper objectMapper;
31 |
32 | @Before
33 | public void setup() {
34 | objectMapper = new ObjectMapper();
35 | when(device.getJsonObjectMapper()).thenReturn(objectMapper);
36 |
37 | }
38 |
39 | @Test
40 | public void testOnSuccessInvalidPayload() {
41 | AwsIotDeviceSyncMessage message = new AwsIotDeviceSyncMessage(TEST_TOPIC, TEST_QOS, device);
42 | message.setStringPayload("123");
43 |
44 | message.onSuccess();
45 | verify(device, never()).getLocalVersion();
46 | }
47 |
48 | @Test
49 | public void testOnSuccessVersionAlreadyUpdated() {
50 | AtomicLong localVersion = new AtomicLong(2);
51 | when(device.getLocalVersion()).thenReturn(localVersion);
52 |
53 | AwsIotDeviceSyncMessage message = new AwsIotDeviceSyncMessage(TEST_TOPIC, TEST_QOS, device);
54 | message.setStringPayload("{\"version\":1}");
55 |
56 | message.onSuccess();
57 |
58 | assertEquals(2, localVersion.get());
59 | }
60 |
61 | @Test
62 | public void testOnSuccessVersionNotUpdated() {
63 | AtomicLong localVersion = new AtomicLong(-1);
64 | when(device.getLocalVersion()).thenReturn(localVersion);
65 |
66 | AwsIotDeviceSyncMessage message = new AwsIotDeviceSyncMessage(TEST_TOPIC, TEST_QOS, device);
67 | message.setStringPayload("{\"version\":1}");
68 |
69 | message.onSuccess();
70 |
71 | assertEquals(1, localVersion.get());
72 | }
73 |
74 | @Test
75 | public void testOnFailureDeviceNotFound() {
76 | AtomicLong localVersion = new AtomicLong(-1);
77 | when(device.getLocalVersion()).thenReturn(localVersion);
78 |
79 | AwsIotDeviceSyncMessage message = new AwsIotDeviceSyncMessage(TEST_TOPIC, TEST_QOS, device);
80 | message.setErrorCode(AWSIotDeviceErrorCode.NOT_FOUND);
81 |
82 | message.onFailure();
83 |
84 | assertEquals(0, localVersion.get());
85 | }
86 |
87 | @Test
88 | public void testOnFailureOtherError() {
89 | AtomicLong localVersion = new AtomicLong(-1);
90 | lenient().when(device.getLocalVersion()).thenReturn(localVersion);
91 |
92 | AwsIotDeviceSyncMessage message = new AwsIotDeviceSyncMessage(TEST_TOPIC, TEST_QOS, device);
93 | message.setErrorCode(AWSIotDeviceErrorCode.INTERNAL_SERVICE_FAILURE);
94 |
95 | message.onFailure();
96 |
97 | assertEquals(-1, localVersion.get());
98 | }
99 |
100 | }
101 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/test/java/com/amazonaws/services/iot/client/system_props_mutualAuth.properties:
--------------------------------------------------------------------------------
1 | clientEndpoint=ajje7lpljulm4-ats.iot.us-east-1.amazonaws.com
2 | clientId=DefaultClientId
3 | thingName=DefaultThingName
4 | privateMaterial=arn:aws:secretsmanager:us-east-1:123124136734:secret:V1IotSdkIntegrationTestPrivateKey-vNUQU8
5 | publicMaterial=arn:aws:secretsmanager:us-east-1:123124136734:secret:V1IotSdkIntegrationTestCertificate-vTRwjE
6 | isWebSocket=false
7 | authMode=CertificateMutualAuthentication
8 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/test/java/com/amazonaws/services/iot/client/system_props_websocket.properties:
--------------------------------------------------------------------------------
1 | clientEndpoint=ajje7lpljulm4-ats.iot.us-east-1.amazonaws.com
2 | clientId=DefaultClientId
3 | thingName=DefaultThingName
4 | privateMaterial=arn:aws:secretsmanager:us-east-1:123124136734:secret:V1IotSdkIntegrationTestWebsocketSecretAccessKey-MKTSaV
5 | publicMaterial=arn:aws:secretsmanager:us-east-1:123124136734:secret:V1IotSdkIntegrationTestWebsocketAccessKeyId-1YdB9z
6 | isWebSocket=true
7 | authMode=MqttOverWebSocketSigV4Signing
8 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/test/java/com/amazonaws/services/iot/client/util/AwsIotTlsSocketFactoryTest.java:
--------------------------------------------------------------------------------
1 | package com.amazonaws.services.iot.client.util;
2 |
3 | import static org.mockito.Matchers.any;
4 | import static org.mockito.Matchers.anyBoolean;
5 | import static org.mockito.Matchers.anyInt;
6 | import static org.mockito.Matchers.anyString;
7 | import static org.mockito.Matchers.nullable;
8 | import static org.mockito.Mockito.times;
9 | import static org.mockito.Mockito.verify;
10 | import static org.mockito.Mockito.when;
11 |
12 | import java.io.IOException;
13 | import java.net.InetAddress;
14 | import java.net.Socket;
15 | import java.net.UnknownHostException;
16 |
17 | import javax.net.ssl.SSLSocket;
18 | import javax.net.ssl.SSLSocketFactory;
19 |
20 | import org.junit.Before;
21 | import org.junit.Test;
22 | import org.junit.runner.RunWith;
23 | import org.mockito.Mock;
24 | import org.mockito.runners.MockitoJUnitRunner;
25 |
26 | @RunWith(MockitoJUnitRunner.class)
27 | public class AwsIotTlsSocketFactoryTest {
28 |
29 | @Mock
30 | private SSLSocketFactory sslSocketFactory;
31 | @Mock
32 | private SSLSocket socket;
33 |
34 | private AwsIotTlsSocketFactory tlsSocketFactory;
35 |
36 | @Before
37 | public void setup() {
38 | tlsSocketFactory = new AwsIotTlsSocketFactory(sslSocketFactory);
39 | }
40 |
41 | @Test
42 | public void getDefaultCipherSuites() {
43 | tlsSocketFactory.getDefaultCipherSuites();
44 |
45 | verify(sslSocketFactory, times(1)).getDefaultCipherSuites();
46 | }
47 |
48 | @Test
49 | public void getSupportedCipherSuites() {
50 | tlsSocketFactory.getSupportedCipherSuites();
51 |
52 | verify(sslSocketFactory, times(1)).getSupportedCipherSuites();
53 | }
54 |
55 | @Test
56 | public void testCreateSocket() throws IOException {
57 | when(sslSocketFactory.createSocket()).thenReturn(socket);
58 |
59 | tlsSocketFactory.createSocket();
60 |
61 | verify(socket, times(1)).setEnabledProtocols(new String[] { "TLSv1.2" });
62 | }
63 |
64 | @Test
65 | public void testCreateSocketWithSocket() throws IOException {
66 | when(sslSocketFactory.createSocket(nullable(Socket.class), anyString(), anyInt(), anyBoolean())).thenReturn(socket);
67 |
68 | tlsSocketFactory.createSocket(nullable(Socket.class), anyString(), anyInt(), anyBoolean());
69 |
70 | verify(socket, times(1)).setEnabledProtocols(new String[] { "TLSv1.2" });
71 | }
72 |
73 | @Test
74 | public void testCreateSocketWithHost() throws IOException, UnknownHostException {
75 | when(sslSocketFactory.createSocket(anyString(), anyInt())).thenReturn(socket);
76 |
77 | tlsSocketFactory.createSocket(anyString(), anyInt());
78 |
79 | verify(socket, times(1)).setEnabledProtocols(new String[] { "TLSv1.2" });
80 | }
81 |
82 | @Test
83 | public void testCreateSocketWithInetAddress() throws IOException, UnknownHostException {
84 | when(sslSocketFactory.createSocket(anyString(), anyInt(), nullable(InetAddress.class), anyInt())).thenReturn(socket);
85 |
86 | tlsSocketFactory.createSocket(anyString(), anyInt(), nullable(InetAddress.class), anyInt());
87 |
88 | verify(socket, times(1)).setEnabledProtocols(new String[] { "TLSv1.2" });
89 | }
90 |
91 | @Test
92 | public void testCreateSocketWithInetAddressAndPort() throws IOException {
93 | when(sslSocketFactory.createSocket(nullable(InetAddress.class), anyInt())).thenReturn(socket);
94 |
95 | tlsSocketFactory.createSocket(nullable(InetAddress.class), anyInt());
96 |
97 | verify(socket, times(1)).setEnabledProtocols(new String[] { "TLSv1.2" });
98 | }
99 |
100 | @Test
101 | public void testCreateSocketWithInetAddressAndLocalInetAddress() throws IOException {
102 | when(sslSocketFactory.createSocket(nullable(InetAddress.class), anyInt(), nullable(InetAddress.class), anyInt()))
103 | .thenReturn(socket);
104 |
105 | tlsSocketFactory.createSocket(nullable(InetAddress.class), anyInt(), nullable(InetAddress.class), anyInt());
106 |
107 | verify(socket, times(1)).setEnabledProtocols(new String[] { "TLSv1.2" });
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/aws-iot-device-sdk-java/src/test/java/com/amazonaws/services/iot/client/util/AwsIotWebSocketUrlSignerTest.java:
--------------------------------------------------------------------------------
1 | package com.amazonaws.services.iot.client.util;
2 |
3 | import com.amazonaws.services.iot.client.AWSIotException;
4 | import org.junit.Test;
5 | import org.junit.runner.RunWith;
6 | import org.mockito.runners.MockitoJUnitRunner;
7 |
8 | import java.util.Date;
9 |
10 | import static org.junit.Assert.assertEquals;
11 |
12 | @RunWith(MockitoJUnitRunner.class)
13 | public class AwsIotWebSocketUrlSignerTest {
14 |
15 | private final String PrefixedEndPoint = "hostname.iot.us-east-1.AMAZONAWS.COM:443";
16 | private final String EndPoint = "iot.us-east-1.AMAZONAWS.COM";
17 | private final String AccessKeyId = "123";
18 | private final String SecretAccessKey = "456";
19 | private final String SessionToken = "abc";
20 | private final Date SigningDate = new Date(1451606400000l);
21 | private final String PrefixedEndPointSigned = "wss://hostname.iot.us-east-1.amazonaws.com:443/mqtt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=123%2F20160101%2Fus-east-1%2Fiotdata%2Faws4_request&X-Amz-Date=20160101T000000Z&X-Amz-SignedHeaders=host&X-Amz-Signature=08b80c7273fa6c9d8bd815081c80e60818f2bf974213993a1cd4463a5785b1ce";
22 | private final String EndPointSigned = "wss://iot.us-east-1.amazonaws.com/mqtt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=123%2F20160101%2Fus-east-1%2Fiotdata%2Faws4_request&X-Amz-Date=20160101T000000Z&X-Amz-SignedHeaders=host&X-Amz-Signature=b50019dd3ec2d316a6a7938f363f6c792b5f58c04e1e6535d6ae277bf8cf3304";
23 |
24 | @Test
25 | public void testSigningPrefixEndpoint() throws AWSIotException {
26 | AwsIotWebSocketUrlSigner urlSigner = new AwsIotWebSocketUrlSigner(PrefixedEndPoint, AccessKeyId,
27 | SecretAccessKey, null);
28 |
29 | String url = urlSigner.getSignedUrl(SigningDate);
30 |
31 | assertEquals(PrefixedEndPointSigned, url);
32 | }
33 |
34 | @Test
35 | public void testSigningRegularEndpoint() throws AWSIotException {
36 | AwsIotWebSocketUrlSigner urlSigner = new AwsIotWebSocketUrlSigner(EndPoint, AccessKeyId, SecretAccessKey, null);
37 |
38 | String url = urlSigner.getSignedUrl(SigningDate);
39 |
40 | assertEquals(EndPointSigned, url);
41 | }
42 |
43 | @Test
44 | public void testSigningWithSessionToken() throws AWSIotException {
45 | AwsIotWebSocketUrlSigner urlSigner = new AwsIotWebSocketUrlSigner(EndPoint, AccessKeyId, SecretAccessKey,
46 | SessionToken);
47 |
48 | String url = urlSigner.getSignedUrl(SigningDate);
49 |
50 | assertEquals(EndPointSigned + "&X-Amz-Security-Token=" + SessionToken, url);
51 | }
52 |
53 | @Test(expected = IllegalArgumentException.class)
54 | public void testSigningWithInvalidEndpoint() throws AWSIotException {
55 | AwsIotWebSocketUrlSigner urlSigner = new AwsIotWebSocketUrlSigner("hostname.iot.us-east-1.AMAZON.COM",
56 | AccessKeyId, SecretAccessKey, SessionToken);
57 | urlSigner.getSignedUrl(SigningDate);
58 | }
59 |
60 | @Test(expected = IllegalArgumentException.class)
61 | public void testSigningWithCredentials() throws AWSIotException {
62 | AwsIotWebSocketUrlSigner urlSigner = new AwsIotWebSocketUrlSigner(EndPoint, null, null, SessionToken);
63 | urlSigner.getSignedUrl(SigningDate);
64 | }
65 |
66 | @Test(expected = IllegalArgumentException.class)
67 | public void testNullRegionWithCreds() {
68 | AwsIotWebSocketUrlSigner urlSigner = new AwsIotWebSocketUrlSigner(EndPoint, null, null, SessionToken, null);
69 | }
70 |
71 | @Test(expected = IllegalArgumentException.class)
72 | public void testNullRegion() {
73 | AwsIotWebSocketUrlSigner urlSigner = new AwsIotWebSocketUrlSigner(EndPoint, null);
74 | }
75 |
76 | public void testRegionDerivedFromEndpointWithCreds() {
77 | AwsIotWebSocketUrlSigner urlSigner = new AwsIotWebSocketUrlSigner(EndPoint, null, null, SessionToken);
78 | assertEquals("us-east-1", urlSigner.getRegion());
79 | }
80 |
81 | public void testRegionDerivedFromEndpoint() {
82 | AwsIotWebSocketUrlSigner urlSigner = new AwsIotWebSocketUrlSigner(EndPoint);
83 | assertEquals("us-east-1", urlSigner.getRegion());
84 | }
85 |
86 | public void testRegionSetFromTheConstructorWithCreds() {
87 | AwsIotWebSocketUrlSigner urlSigner = new AwsIotWebSocketUrlSigner(EndPoint, null, null, SessionToken, "us" +
88 | "-east-2");
89 | assertEquals("us-east-2", urlSigner.getRegion());
90 | }
91 |
92 | public void testRegionSetFromTheConstructor() {
93 | AwsIotWebSocketUrlSigner urlSigner = new AwsIotWebSocketUrlSigner(EndPoint, "us-east-2");
94 | assertEquals("us-east-2", urlSigner.getRegion());
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/codebuild/cd/promote-release.yml:
--------------------------------------------------------------------------------
1 | version: 0.2
2 | #this buildspec assumes the ubuntu 16.04:x64 image
3 | # This job is responsible for artifacting the JAR which will have all of the other shared libs stuffed
4 | # into it once all platforms are built and artifacted
5 | phases:
6 | install:
7 | commands:
8 | - sudo add-apt-repository ppa:openjdk-r/ppa
9 | - sudo apt-get update -y
10 | - sudo apt-get install openjdk-8-jdk-headless maven -y -f
11 | - sudo apt-get install jq -y
12 | # need latest awscli for secretsmanager
13 | - sudo pip3 install awscli --upgrade
14 |
15 | pre_build:
16 | commands:
17 | - cd $CODEBUILD_SRC_DIR/aws-iot-device-sdk-java
18 | - export PKG_VERSION=$(git describe --tags | cut -f2 -dv)
19 | - echo PKG_VERSION=$PKG_VERSION
20 | # Set version to PKG_VERSION
21 | - sed -i 's/0.0.1-dev/'"$PKG_VERSION"'/g' pom.xml
22 | - sed -i 's/0.0.1-dev/'"$PKG_VERSION"'/g' aws-iot-device-sdk-java/pom.xml
23 | - sed -i 's/0.0.1-dev/'"$PKG_VERSION"'/g' aws-iot-device-sdk-java-samples/pom.xml
24 | - sed -i 's/0.0.1-dev/'"$PKG_VERSION"'/g' aws-iot-device-sdk-java/src/main/java/com/amazonaws/services/iot/client/mqtt/AwsIotMqttConnection.java
25 | # Get java v1 gpg files
26 | - aws s3 cp --recursive s3://code-sharing-aws-crt/gpg-java-v1/ maven-gpg
27 | # manully copy the maven-gpg in subfolder, since codeBuild does not set localRepository correctly
28 | - cp -r maven-gpg aws-iot-device-sdk-java/maven-gpg
29 | - cp -r maven-gpg aws-iot-device-sdk-java-samples/maven-gpg
30 | # install settings.xml to ~/.m2/settings.xml
31 | - mkdir -p $HOME/.m2
32 | - aws s3 cp s3://code-sharing-aws-crt/iot-sdk-java-v1.settings.xml $HOME/.m2/settings.xml
33 | - aws --query "SecretString" secretsmanager get-secret-value --secret-id Sonatype/JIRA/token/V1 > sonatype_secret
34 | - jq fromjson sonatype_secret > sonatype_json
35 | - export ST_PASSWORD=$(jq -r '.password' sonatype_json)
36 | - export ESCAPED_PASSWORD=$(printf '%s\n' "$ST_PASSWORD" | sed 's:[\\/&]:\\&:g')
37 | - export ST_USERNAME=$(jq -r '.username' sonatype_json)
38 | - aws --query "SecretString" secretsmanager get-secret-value --secret-id gpg/IoT/JAVA/V1 > gpg_secret
39 | - jq fromjson gpg_secret > gpg_json
40 | - export GPG_PRINCIPAL=$(jq -r '.username' gpg_json)
41 | - export GPG_CREDENTIAL=$(jq -r '.password' gpg_json)
42 | # Use the password from secret manager to update the settings
43 | - sed -i 's/sonatype_Principal/'"$ST_USERNAME"'/g' $HOME/.m2/settings.xml
44 | - sed -i 's/sonatype_Credential/'"$ESCAPED_PASSWORD"'/g' $HOME/.m2/settings.xml
45 | - sed -i 's/gpg_Principal/'"$GPG_PRINCIPAL"'/g' $HOME/.m2/settings.xml
46 | - sed -i 's/gpg_Credential/'"$GPG_CREDENTIAL"'/g' $HOME/.m2/settings.xml
47 |
48 |
49 | build:
50 | commands:
51 | - cd $CODEBUILD_SRC_DIR/aws-iot-device-sdk-java
52 | # Trigger the release of the last staged package in the staging repository
53 | - mvn -s $HOME/.m2/settings.xml clean package -Dmaven.test.skip=true
54 | - mvn -s $HOME/.m2/settings.xml clean deploy -P publishing -e -X
55 | - mvn -s $HOME/.m2/settings.xml nexus-staging:release -e -X
56 |
57 | cache:
58 | paths:
59 | - "/root/.m2/**/*"
60 |
--------------------------------------------------------------------------------
/codebuild/cd/test-version-exists.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -e
3 | set -x
4 | # force a failure if there's no tag
5 | git describe --tags
6 | # now get the tag
7 | CURRENT_TAG=$(git describe --tags | cut -f2 -dv)
8 | # convert v0.2.12-2-g50254a9 to 0.2.12
9 | CURRENT_TAG_VERSION=$(git describe --tags | cut -f1 -d'-' | cut -f2 -dv)
10 | # if there's a hash on the tag, then this is not a release tagged commit
11 | if [ "$CURRENT_TAG" != "$CURRENT_TAG_VERSION" ]; then
12 | echo "Current tag version is not a release tag, cut a new release if you want to publish."
13 | exit 1
14 | fi
15 |
16 | PUBLISHED_TAG_VERSION=$(curl -s "https://repo.maven.apache.org/maven2/com/amazonaws/aws-iot-device-sdk-java/maven-metadata.xml" | grep "" | cut -f2 -d ">" | cut -f1 -d "<")
17 | if [ "$PUBLISHED_TAG_VERSION" == "$CURRENT_TAG_VERSION" ]; then
18 | echo "$CURRENT_TAG_VERSION is already in Sonatype, cut a new tag if you want to upload another version."
19 | exit 1
20 | fi
21 |
22 | echo "$CURRENT_TAG_VERSION currently does not exist in Sonatype, allowing pipeline to continue."
23 | exit 0
24 |
--------------------------------------------------------------------------------
/codebuild/cd/test-version-exists.yml:
--------------------------------------------------------------------------------
1 | version: 0.2
2 | #this build spec assumes the ubuntu 16.04:x64 image
3 | #this build run simply verifies we haven't published something at this tag yet.
4 | #if we have we fail the build and stop the pipeline, if we haven't we allow the pipeline to run.
5 | phases:
6 | build:
7 | commands:
8 | - cd $CODEBUILD_SRC_DIR/aws-iot-device-sdk-java
9 | - bash ./codebuild/cd/test-version-exists.sh
10 |
11 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 | com.amazonaws
4 | aws-iot-device-sdk-java-pom
5 | 0.0.1-dev
6 | pom
7 | AWS IoT Device SDK for Java
8 | The AWS IoT Device SDK for Java provides Java APIs for devices to connect to AWS IoT service using the MQTT protocol. The SDK also provides support for AWS IoT specific features, such as Thing Shadow and Thing Shadow abstraction.
9 | https://aws.amazon.com/iot/sdk
10 |
11 |
12 | Apache License, Version 2.0
13 | https://aws.amazon.com/apache2.0
14 | repo
15 |
16 |
17 |
18 |
19 | amazonwebservices
20 | Amazon Web Services
21 | https://aws.amazon.com
22 |
23 | developer
24 |
25 |
26 |
27 |
28 | https://github.com/aws/aws-iot-device-sdk-java.git
29 |
30 |
31 | aws-iot-device-sdk-java
32 | aws-iot-device-sdk-java-samples
33 |
34 |
35 | UTF-8
36 |
37 |
38 |
39 | ossrh
40 | https://aws.oss.sonatype.org/content/repositories/snapshots
41 |
42 |
43 |
44 |
45 |
46 | org.sonatype.plugins
47 | nexus-staging-maven-plugin
48 | 1.6.8
49 | true
50 |
51 | ossrh
52 | https://aws.oss.sonatype.org/
53 | false
54 |
55 |
56 |
57 | org.apache.maven.plugins
58 | maven-compiler-plugin
59 | 3.5.1
60 |
61 | 1.7
62 | 1.7
63 | 1.7
64 |
65 |
66 |
67 | org.apache.maven.plugins
68 | maven-gpg-plugin
69 | 1.6
70 |
71 |
72 | sign-artifacts
73 | verify
74 |
75 | sign
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
--------------------------------------------------------------------------------