├── .gitignore
├── .travis.yml
├── LICENSE
├── LICENSE.txt
├── README.md
├── pom.xml
└── src
├── main
└── java
│ └── cn
│ └── teaey
│ └── apns4j
│ ├── Apns4j.java
│ ├── ApnsException.java
│ ├── ApnsHelper.java
│ ├── keystore
│ ├── InvalidKeyStoreException.java
│ ├── InvalidKeyStoreFormatException.java
│ ├── InvalidKeyStorePasswordException.java
│ ├── InvalidKeyStoreTypeException.java
│ ├── KeyStoreGetter.java
│ └── KeyStoreType.java
│ ├── network
│ ├── ApnsChannel.java
│ ├── ApnsChannelFactory.java
│ ├── ApnsGateway.java
│ ├── Channel.java
│ ├── SecuritySocketFactory.java
│ └── async
│ │ ├── ApnsFuture.java
│ │ ├── ApnsService.java
│ │ ├── AsyncServiceShutdownException.java
│ │ └── PayloadSender.java
│ └── protocol
│ ├── ApnsPayload.java
│ ├── ErrorResp.java
│ ├── InvalidDeviceTokenException.java
│ ├── InvalidErrorResponse.java
│ ├── JsonParser.java
│ ├── ListMap.java
│ ├── Payload.java
│ └── Protocal.java
└── test
└── java
└── cn
└── teaey
└── apns4j
├── ActionButtonTest.java
├── AlertTest.java
├── BadgeTest.java
├── MainTest.java
└── TestConts.java
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 |
3 | # Package Files #
4 | *.jar
5 | *.war
6 | *.ear
7 | .idea
8 | .idea/**
9 | *.iml
10 | *.jar
11 | target
12 | target/**
13 | *.ipr
14 | *.iws
15 | *.p12
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction, and
10 | distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by the copyright
13 | owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all other entities
16 | that control, are controlled by, or are under common control with that entity.
17 | For the purposes of this definition, "control" means (i) the power, direct or
18 | indirect, to cause the direction or management of such entity, whether by
19 | contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
20 | outstanding shares, or (iii) beneficial ownership of such entity.
21 |
22 | "You" (or "Your") shall mean an individual or Legal Entity exercising
23 | permissions granted by this License.
24 |
25 | "Source" form shall mean the preferred form for making modifications, including
26 | but not limited to software source code, documentation source, and configuration
27 | files.
28 |
29 | "Object" form shall mean any form resulting from mechanical transformation or
30 | translation of a Source form, including but not limited to compiled object code,
31 | generated documentation, and conversions to other media types.
32 |
33 | "Work" shall mean the work of authorship, whether in Source or Object form, made
34 | available under the License, as indicated by a copyright notice that is included
35 | in or attached to the work (an example is provided in the Appendix below).
36 |
37 | "Derivative Works" shall mean any work, whether in Source or Object form, that
38 | is based on (or derived from) the Work and for which the editorial revisions,
39 | annotations, elaborations, or other modifications represent, as a whole, an
40 | original work of authorship. For the purposes of this License, Derivative Works
41 | shall not include works that remain separable from, or merely link (or bind by
42 | name) to the interfaces of, the Work and Derivative Works thereof.
43 |
44 | "Contribution" shall mean any work of authorship, including the original version
45 | of the Work and any modifications or additions to that Work or Derivative Works
46 | thereof, that is intentionally submitted to Licensor for inclusion in the Work
47 | by the copyright owner or by an individual or Legal Entity authorized to submit
48 | on behalf of the copyright owner. For the purposes of this definition,
49 | "submitted" means any form of electronic, verbal, or written communication sent
50 | to the Licensor or its representatives, including but not limited to
51 | communication on electronic mailing lists, source code control systems, and
52 | issue tracking systems that are managed by, or on behalf of, the Licensor for
53 | the purpose of discussing and improving the Work, but excluding communication
54 | that is conspicuously marked or otherwise designated in writing by the copyright
55 | owner as "Not a Contribution."
56 |
57 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf
58 | of whom a Contribution has been received by Licensor and subsequently
59 | incorporated within the Work.
60 |
61 | 2. Grant of Copyright License.
62 |
63 | Subject to the terms and conditions of this License, each Contributor hereby
64 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
65 | irrevocable copyright license to reproduce, prepare Derivative Works of,
66 | publicly display, publicly perform, sublicense, and distribute the Work and such
67 | Derivative Works in Source or Object form.
68 |
69 | 3. Grant of Patent License.
70 |
71 | Subject to the terms and conditions of this License, each Contributor hereby
72 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
73 | irrevocable (except as stated in this section) patent license to make, have
74 | made, use, offer to sell, sell, import, and otherwise transfer the Work, where
75 | such license applies only to those patent claims licensable by such Contributor
76 | that are necessarily infringed by their Contribution(s) alone or by combination
77 | of their Contribution(s) with the Work to which such Contribution(s) was
78 | submitted. If You institute patent litigation against any entity (including a
79 | cross-claim or counterclaim in a lawsuit) alleging that the Work or a
80 | Contribution incorporated within the Work constitutes direct or contributory
81 | patent infringement, then any patent licenses granted to You under this License
82 | for that Work shall terminate as of the date such litigation is filed.
83 |
84 | 4. Redistribution.
85 |
86 | You may reproduce and distribute copies of the Work or Derivative Works thereof
87 | in any medium, with or without modifications, and in Source or Object form,
88 | provided that You meet the following conditions:
89 |
90 | You must give any other recipients of the Work or Derivative Works a copy of
91 | this License; and
92 | You must cause any modified files to carry prominent notices stating that You
93 | changed the files; and
94 | You must retain, in the Source form of any Derivative Works that You distribute,
95 | all copyright, patent, trademark, and attribution notices from the Source form
96 | of the Work, excluding those notices that do not pertain to any part of the
97 | Derivative Works; and
98 | If the Work includes a "NOTICE" text file as part of its distribution, then any
99 | Derivative Works that You distribute must include a readable copy of the
100 | attribution notices contained within such NOTICE file, excluding those notices
101 | that do not pertain to any part of the Derivative Works, in at least one of the
102 | following places: within a NOTICE text file distributed as part of the
103 | Derivative Works; within the Source form or documentation, if provided along
104 | with the Derivative Works; or, within a display generated by the Derivative
105 | Works, if and wherever such third-party notices normally appear. The contents of
106 | the NOTICE file are for informational purposes only and do not modify the
107 | License. You may add Your own attribution notices within Derivative Works that
108 | You distribute, alongside or as an addendum to the NOTICE text from the Work,
109 | provided that such additional attribution notices cannot be construed as
110 | modifying the License.
111 | You may add Your own copyright statement to Your modifications and may provide
112 | additional or different license terms and conditions for use, reproduction, or
113 | distribution of Your modifications, or for any such Derivative Works as a whole,
114 | provided Your use, reproduction, and distribution of the Work otherwise complies
115 | with the conditions stated in this License.
116 |
117 | 5. Submission of Contributions.
118 |
119 | Unless You explicitly state otherwise, any Contribution intentionally submitted
120 | for inclusion in the Work by You to the Licensor shall be under the terms and
121 | conditions of this License, without any additional terms or conditions.
122 | Notwithstanding the above, nothing herein shall supersede or modify the terms of
123 | any separate license agreement you may have executed with Licensor regarding
124 | such Contributions.
125 |
126 | 6. Trademarks.
127 |
128 | This License does not grant permission to use the trade names, trademarks,
129 | service marks, or product names of the Licensor, except as required for
130 | reasonable and customary use in describing the origin of the Work and
131 | reproducing the content of the NOTICE file.
132 |
133 | 7. Disclaimer of Warranty.
134 |
135 | Unless required by applicable law or agreed to in writing, Licensor provides the
136 | Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
137 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
138 | including, without limitation, any warranties or conditions of TITLE,
139 | NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
140 | solely responsible for determining the appropriateness of using or
141 | redistributing the Work and assume any risks associated with Your exercise of
142 | permissions under this License.
143 |
144 | 8. Limitation of Liability.
145 |
146 | In no event and under no legal theory, whether in tort (including negligence),
147 | contract, or otherwise, unless required by applicable law (such as deliberate
148 | and grossly negligent acts) or agreed to in writing, shall any Contributor be
149 | liable to You for damages, including any direct, indirect, special, incidental,
150 | or consequential damages of any character arising as a result of this License or
151 | out of the use or inability to use the Work (including but not limited to
152 | damages for loss of goodwill, work stoppage, computer failure or malfunction, or
153 | any and all other commercial damages or losses), even if such Contributor has
154 | been advised of the possibility of such damages.
155 |
156 | 9. Accepting Warranty or Additional Liability.
157 |
158 | While redistributing the Work or Derivative Works thereof, You may choose to
159 | offer, and charge a fee for, acceptance of support, warranty, indemnity, or
160 | other liability obligations and/or rights consistent with this License. However,
161 | in accepting such obligations, You may act only on Your own behalf and on Your
162 | sole responsibility, not on behalf of any other Contributor, and only if You
163 | agree to indemnify, defend, and hold each Contributor harmless for any liability
164 | incurred by, or claims asserted against, such Contributor by reason of your
165 | accepting any such warranty or additional liability.
166 |
167 | END OF TERMS AND CONDITIONS
168 |
169 | APPENDIX: How to apply the Apache License to your work
170 |
171 | To apply the Apache License to your work, attach the following boilerplate
172 | notice, with the fields enclosed by brackets "[]" replaced with your own
173 | identifying information. (Don't include the brackets!) The text should be
174 | enclosed in the appropriate comment syntax for the file format. We also
175 | recommend that a file or class name and description of purpose be included on
176 | the same "printed page" as the copyright notice for easier identification within
177 | third-party archives.
178 |
179 | Copyright [yyyy] [name of copyright owner]
180 |
181 | Licensed under the Apache License, Version 2.0 (the "License");
182 | you may not use this file except in compliance with the License.
183 | You may obtain a copy of the License at
184 |
185 | http://www.apache.org/licenses/LICENSE-2.0
186 |
187 | Unless required by applicable law or agreed to in writing, software
188 | distributed under the License is distributed on an "AS IS" BASIS,
189 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
190 | See the License for the specific language governing permissions and
191 | limitations under the License.
192 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Apns4j
2 |
3 | [](https://www.apache.org/licenses/LICENSE-2.0.html)
4 | [](https://travis-ci.org/teaey/apns4j)
5 |
6 | ### Quick start
7 |
8 | ```
9 |
newNotifyPayload.
38 | * 39 | * @return a {@link ApnsPayload} object. 40 | */ 41 | public static final ApnsPayload newPayload() { 42 | return new ApnsPayload(); 43 | } 44 | 45 | public static final ApnsChannelFactoryBuilder newChannelFactoryBuilder() { 46 | return new ApnsChannelFactoryBuilder(); 47 | } 48 | 49 | public static final class ApnsChannelFactoryBuilder { 50 | private Object keyStoreMeta; 51 | private String keyStorePwd; 52 | private ApnsGateway apnsGateway = ApnsGateway.DEVELOPMENT; 53 | private KeyStoreType keyStoreType = KeyStoreType.PKCS12; 54 | 55 | public ApnsChannelFactoryBuilder keyStoreMeta(Object keyStoreMeta) { 56 | ApnsHelper.checkNullThrowException(keyStoreMeta, "keyStoreMeta"); 57 | this.keyStoreMeta = keyStoreMeta; 58 | return this; 59 | } 60 | 61 | public ApnsChannelFactoryBuilder keyStorePwd(String keyStorePwd) { 62 | ApnsHelper.checkNullThrowException(keyStorePwd, "keyStorePwd"); 63 | this.keyStorePwd = keyStorePwd; 64 | return this; 65 | } 66 | 67 | public ApnsChannelFactoryBuilder apnsGateway(ApnsGateway apnsGateway) { 68 | ApnsHelper.checkNullThrowException(apnsGateway, "apnsGateway"); 69 | this.apnsGateway = apnsGateway; 70 | return this; 71 | } 72 | 73 | public ApnsChannelFactoryBuilder keyStoreType(KeyStoreType keyStoreType) { 74 | ApnsHelper.checkNullThrowException(keyStoreType, "keyStoreType"); 75 | this.keyStoreType = keyStoreType; 76 | return this; 77 | } 78 | 79 | public ApnsChannelFactory build() { 80 | KeyStoreGetter keyStoreGetter = null; 81 | if (keyStoreMeta instanceof String) { 82 | keyStoreGetter = new KeyStoreGetter((String) this.keyStoreMeta, this.keyStorePwd, this.keyStoreType); 83 | } else if (keyStoreMeta instanceof File) { 84 | keyStoreGetter = new KeyStoreGetter((File) this.keyStoreMeta, this.keyStorePwd, this.keyStoreType); 85 | } else if (keyStoreMeta instanceof InputStream) { 86 | keyStoreGetter = new KeyStoreGetter((InputStream) this.keyStoreMeta, this.keyStorePwd, this.keyStoreType); 87 | } 88 | if (null == keyStoreGetter) { 89 | throw new IllegalArgumentException(keyStoreMeta.getClass().getName()); 90 | } 91 | SecuritySocketFactory securitySocketFactory = new SecuritySocketFactory(this.apnsGateway.host(), this.apnsGateway.port(), keyStoreGetter.keyStore(), keyStoreGetter.keyStorePwd()); 92 | return new ApnsChannelFactory(securitySocketFactory); 93 | } 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/cn/teaey/apns4j/ApnsException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * * Copyright 2015 The Apns4j Project 4 | * * 5 | * * The Netty Project licenses this file to you under the Apache License, 6 | * * version 2.0 (the "License"); you may not use this file except in compliance 7 | * * with the License. You may obtain a copy of the License at: 8 | * * 9 | * * http://www.apache.org/licenses/LICENSE-2.0 10 | * * 11 | * * Unless required by applicable law or agreed to in writing, software 12 | * * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | * * License for the specific language governing permissions and limitations 15 | * * under the License. 16 | * 17 | */ 18 | 19 | package cn.teaey.apns4j; 20 | 21 | /** 22 | * @author xiaofei.wxf 23 | */ 24 | public class ApnsException extends RuntimeException { 25 | public ApnsException() { 26 | } 27 | 28 | public ApnsException(String message) { 29 | super(message); 30 | } 31 | 32 | public ApnsException(String message, Throwable cause) { 33 | super(message, cause); 34 | } 35 | 36 | public ApnsException(Throwable cause) { 37 | super(cause); 38 | } 39 | 40 | public ApnsException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 41 | super(message, cause, enableSuppression, writableStackTrace); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/cn/teaey/apns4j/ApnsHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * * Copyright 2015 The Apns4j Project 4 | * * 5 | * * The Netty Project licenses this file to you under the Apache License, 6 | * * version 2.0 (the "License"); you may not use this file except in compliance 7 | * * with the License. You may obtain a copy of the License at: 8 | * * 9 | * * http://www.apache.org/licenses/LICENSE-2.0 10 | * * 11 | * * Unless required by applicable law or agreed to in writing, software 12 | * * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | * * License for the specific language governing permissions and limitations 15 | * * under the License. 16 | * 17 | */ 18 | 19 | package cn.teaey.apns4j; 20 | 21 | import cn.teaey.apns4j.protocol.InvalidDeviceTokenException; 22 | import cn.teaey.apns4j.protocol.Protocal; 23 | 24 | import java.nio.ByteBuffer; 25 | import java.util.concurrent.atomic.AtomicInteger; 26 | 27 | /** 28 | * @author teaey 29 | * @since 1.0.0 30 | */ 31 | public class ApnsHelper { 32 | private static final int HEADER_LENGTH = 45; 33 | 34 | public static final AtomicInteger IDENTIFIER = new AtomicInteger(0); 35 | 36 | /** 37 | *toRequestBytes.
38 | * 39 | * @param deviceTokenBytes an array of byte. 40 | * @param payloadJsonString a {@link String} object. 41 | * @param identifier a int. 42 | * @param expiry a int. 43 | * @return an array of byte. 44 | */ 45 | public static final byte[] toRequestBytes(byte[] deviceTokenBytes, String payloadJsonString, int identifier, int expiry) { 46 | byte[] payloadBytes = payloadJsonString.getBytes(Protocal.DEF_CHARSET); 47 | ByteBuffer buffer = ByteBuffer.allocate(HEADER_LENGTH + payloadBytes.length); 48 | buffer.put((byte) 1); 49 | buffer.putInt(identifier); 50 | buffer.putInt(expiry); 51 | buffer.putShort((short) 32); 52 | buffer.put(deviceTokenBytes); 53 | buffer.putShort((short) payloadBytes.length); 54 | buffer.put(payloadBytes); 55 | return buffer.array(); 56 | } 57 | 58 | /** 59 | *toHexString.
60 | * 61 | * @param bytes an array of byte. 62 | * @return a {@link String} object. 63 | */ 64 | public static final String toHexString(byte[] bytes) { 65 | StringBuilder ret = new StringBuilder(64); 66 | for (byte each : bytes) { 67 | String hexStr = Integer.toHexString(each >= 0 ? each : (256 + each)); 68 | if (hexStr.length() == 1) { 69 | ret.append("0"); 70 | } 71 | ret.append(hexStr); 72 | } 73 | return ret.toString(); 74 | } 75 | 76 | /** 77 | *toByteArray.
78 | * 79 | * @param deviceToken a {@link String} object. 80 | * @return an array of byte. 81 | */ 82 | public static final byte[] toByteArray(String deviceToken) { 83 | byte[] deviceTokenAsBytes = new byte[deviceToken.length() / 2]; 84 | deviceToken = deviceToken.toUpperCase(); 85 | int j = 0; 86 | try { 87 | for (int i = 0; i < deviceToken.length(); i += 2) { 88 | String t = deviceToken.substring(i, i + 2); 89 | deviceTokenAsBytes[j++] = (byte) Integer.parseInt(t, 16); 90 | } 91 | } catch (NumberFormatException e) { 92 | throw new InvalidDeviceTokenException(e.getMessage()); 93 | } 94 | return deviceTokenAsBytes; 95 | } 96 | 97 | /** 98 | *checkDeviceToken.
99 | * 100 | * @param deviceToken a {@link Object} object. 101 | */ 102 | public static final void checkDeviceToken(Object deviceToken) { 103 | if (deviceToken instanceof String && ((String) deviceToken).length() != 64) { 104 | throw new InvalidDeviceTokenException("device token string must [64] length not [" + ((String) deviceToken).length() + "]"); 105 | } 106 | if (deviceToken instanceof byte[] && ((byte[]) deviceToken).length != 32) { 107 | throw new InvalidDeviceTokenException("device token bytes must [32] length not [" + ((byte[]) deviceToken).length + "]"); 108 | } 109 | } 110 | 111 | public static final void checkNullThrowException(Object target, String name) { 112 | if (null == target) { 113 | throw new NullPointerException(name == null ? "" : name); 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/cn/teaey/apns4j/keystore/InvalidKeyStoreException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * * Copyright 2015 The Apns4j Project 4 | * * 5 | * * The Netty Project licenses this file to you under the Apache License, 6 | * * version 2.0 (the "License"); you may not use this file except in compliance 7 | * * with the License. You may obtain a copy of the License at: 8 | * * 9 | * * http://www.apache.org/licenses/LICENSE-2.0 10 | * * 11 | * * Unless required by applicable law or agreed to in writing, software 12 | * * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | * * License for the specific language governing permissions and limitations 15 | * * under the License. 16 | * 17 | */ 18 | 19 | package cn.teaey.apns4j.keystore; 20 | 21 | /** 22 | * @author teaey 23 | * @since 1.0.0 24 | */ 25 | public class InvalidKeyStoreException extends Exception { 26 | /** 27 | *Constructor for InvalidKeyStoreException.
28 | * 29 | * @param message a {@link String} object. 30 | */ 31 | public InvalidKeyStoreException(String message) { 32 | super(message); 33 | } 34 | 35 | /** 36 | *Constructor for InvalidKeyStoreException.
37 | * 38 | * @param message a {@link String} object. 39 | * @param cause a {@link Exception} object. 40 | */ 41 | public InvalidKeyStoreException(String message, Exception cause) { 42 | super(message, cause); 43 | } 44 | 45 | /** 46 | *Constructor for InvalidKeyStoreException.
47 | * 48 | * @param cause a {@link Exception} object. 49 | */ 50 | public InvalidKeyStoreException(Exception cause) { 51 | super(cause); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/cn/teaey/apns4j/keystore/InvalidKeyStoreFormatException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * * Copyright 2015 The Apns4j Project 4 | * * 5 | * * The Netty Project licenses this file to you under the Apache License, 6 | * * version 2.0 (the "License"); you may not use this file except in compliance 7 | * * with the License. You may obtain a copy of the License at: 8 | * * 9 | * * http://www.apache.org/licenses/LICENSE-2.0 10 | * * 11 | * * Unless required by applicable law or agreed to in writing, software 12 | * * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | * * License for the specific language governing permissions and limitations 15 | * * under the License. 16 | * 17 | */ 18 | 19 | package cn.teaey.apns4j.keystore; 20 | 21 | /** 22 | * @author teaey 23 | * @since 1.0.0 24 | */ 25 | public class InvalidKeyStoreFormatException extends InvalidKeyStoreException { 26 | /** 27 | *Constructor for InvalidKeyStoreFormatException.
28 | * 29 | * @param message a {@link String} object. 30 | */ 31 | public InvalidKeyStoreFormatException(String message) { 32 | super(message); 33 | } 34 | 35 | /** 36 | *Constructor for InvalidKeyStoreFormatException.
37 | * 38 | * @param message a {@link String} object. 39 | * @param cause a {@link Exception} object. 40 | */ 41 | public InvalidKeyStoreFormatException(String message, Exception cause) { 42 | super(message, cause); 43 | } 44 | 45 | /** 46 | *Constructor for InvalidKeyStoreFormatException.
47 | * 48 | * @param cause a {@link Exception} object. 49 | */ 50 | public InvalidKeyStoreFormatException(Exception cause) { 51 | super(cause); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/cn/teaey/apns4j/keystore/InvalidKeyStorePasswordException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * * Copyright 2015 The Apns4j Project 4 | * * 5 | * * The Netty Project licenses this file to you under the Apache License, 6 | * * version 2.0 (the "License"); you may not use this file except in compliance 7 | * * with the License. You may obtain a copy of the License at: 8 | * * 9 | * * http://www.apache.org/licenses/LICENSE-2.0 10 | * * 11 | * * Unless required by applicable law or agreed to in writing, software 12 | * * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | * * License for the specific language governing permissions and limitations 15 | * * under the License. 16 | * 17 | */ 18 | 19 | package cn.teaey.apns4j.keystore; 20 | 21 | /** 22 | * @author teaey 23 | * @since 1.0.0 24 | */ 25 | public class InvalidKeyStorePasswordException extends InvalidKeyStoreException { 26 | /** 27 | *Constructor for InvalidKeyStorePasswordException.
28 | * 29 | * @param msg a {@link String} object. 30 | * @param e a {@link Exception} object. 31 | */ 32 | public InvalidKeyStorePasswordException(String msg, Exception e) { 33 | super(msg, e); 34 | } 35 | 36 | /** 37 | *Constructor for InvalidKeyStorePasswordException.
38 | * 39 | * @param e a {@link Exception} object. 40 | */ 41 | public InvalidKeyStorePasswordException(Exception e) { 42 | super(e); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/cn/teaey/apns4j/keystore/InvalidKeyStoreTypeException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * * Copyright 2015 The Apns4j Project 4 | * * 5 | * * The Netty Project licenses this file to you under the Apache License, 6 | * * version 2.0 (the "License"); you may not use this file except in compliance 7 | * * with the License. You may obtain a copy of the License at: 8 | * * 9 | * * http://www.apache.org/licenses/LICENSE-2.0 10 | * * 11 | * * Unless required by applicable law or agreed to in writing, software 12 | * * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | * * License for the specific language governing permissions and limitations 15 | * * under the License. 16 | * 17 | */ 18 | 19 | package cn.teaey.apns4j.keystore; 20 | 21 | /** 22 | * @author teaey 23 | * @since 1.0.0 24 | */ 25 | public class InvalidKeyStoreTypeException extends InvalidKeyStoreException { 26 | /** 27 | *Constructor for InvalidKeyStoreTypeException.
28 | * 29 | * @param msg a {@link String} object. 30 | * @param e a {@link Exception} object. 31 | */ 32 | public InvalidKeyStoreTypeException(String msg, Exception e) { 33 | super(msg, e); 34 | } 35 | 36 | /** 37 | *Constructor for InvalidKeyStoreTypeException.
38 | * 39 | * @param e a {@link Exception} object. 40 | */ 41 | public InvalidKeyStoreTypeException(Exception e) { 42 | super(e); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/cn/teaey/apns4j/keystore/KeyStoreGetter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * * Copyright 2015 The Apns4j Project 4 | * * 5 | * * The Netty Project licenses this file to you under the Apache License, 6 | * * version 2.0 (the "License"); you may not use this file except in compliance 7 | * * with the License. You may obtain a copy of the License at: 8 | * * 9 | * * http://www.apache.org/licenses/LICENSE-2.0 10 | * * 11 | * * Unless required by applicable law or agreed to in writing, software 12 | * * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | * * License for the specific language governing permissions and limitations 15 | * * under the License. 16 | * 17 | */ 18 | 19 | package cn.teaey.apns4j.keystore; 20 | 21 | import cn.teaey.apns4j.ApnsException; 22 | import cn.teaey.apns4j.ApnsHelper; 23 | 24 | import javax.crypto.BadPaddingException; 25 | import java.io.*; 26 | import java.security.KeyStore; 27 | import java.security.KeyStoreException; 28 | import java.security.NoSuchAlgorithmException; 29 | import java.security.NoSuchProviderException; 30 | import java.security.cert.CertificateException; 31 | 32 | /** 33 | * @author teaey(xiaofei.wxf) 34 | * @since 1.0.3 35 | */ 36 | public class KeyStoreGetter { 37 | private final InputStream keyStoreInputStream; 38 | private final String keyStorePwd; 39 | private final KeyStoreType keyStoreType; 40 | 41 | public KeyStoreGetter(InputStream keyStoreInputStream, String keyStorePwd, KeyStoreType keyStoreType) { 42 | ApnsHelper.checkNullThrowException(keyStoreInputStream, "keyStoreInputStream"); 43 | ApnsHelper.checkNullThrowException(keyStoreType, "keyStoreType"); 44 | this.keyStoreInputStream = keyStoreInputStream; 45 | this.keyStorePwd = keyStorePwd; 46 | this.keyStoreType = keyStoreType; 47 | } 48 | 49 | public KeyStoreGetter(File keyStoreFile, String keyStorePwd, KeyStoreType keyStoreType) { 50 | ApnsHelper.checkNullThrowException(keyStoreFile, "keyStoreFile"); 51 | ApnsHelper.checkNullThrowException(keyStoreType, "keyStoreType"); 52 | try { 53 | this.keyStoreInputStream = new FileInputStream(keyStoreFile); 54 | } catch (FileNotFoundException e) { 55 | throw new ApnsException(e); 56 | } 57 | this.keyStorePwd = keyStorePwd; 58 | this.keyStoreType = keyStoreType; 59 | } 60 | 61 | public KeyStoreGetter(String keyStoreFilePath, String keyStorePwd, KeyStoreType keyStoreType) { 62 | ApnsHelper.checkNullThrowException(keyStoreFilePath, "keyStoreFilePath"); 63 | ApnsHelper.checkNullThrowException(keyStoreType, "keyStoreType"); 64 | try { 65 | this.keyStoreInputStream = new FileInputStream(keyStoreFilePath); 66 | } catch (FileNotFoundException e) { 67 | throw new ApnsException(e); 68 | } 69 | this.keyStorePwd = keyStorePwd; 70 | this.keyStoreType = keyStoreType; 71 | } 72 | 73 | public KeyStoreGetter(InputStream keyStoreInputStream, String keyStorePwd) { 74 | ApnsHelper.checkNullThrowException(keyStoreInputStream, "keyStoreInputStream"); 75 | this.keyStoreInputStream = keyStoreInputStream; 76 | this.keyStorePwd = keyStorePwd; 77 | this.keyStoreType = KeyStoreType.PKCS12; 78 | } 79 | 80 | public KeyStoreGetter(File keyStoreFile, String keyStorePwd) { 81 | ApnsHelper.checkNullThrowException(keyStoreFile, "keyStoreFile"); 82 | try { 83 | this.keyStoreInputStream = new FileInputStream(keyStoreFile); 84 | } catch (FileNotFoundException e) { 85 | throw new ApnsException(e); 86 | } 87 | this.keyStorePwd = keyStorePwd; 88 | this.keyStoreType = KeyStoreType.PKCS12; 89 | } 90 | 91 | public KeyStoreGetter(String keyStoreFilePath, String keyStorePwd) { 92 | ApnsHelper.checkNullThrowException(keyStoreFilePath, "keyStoreFilePath"); 93 | try { 94 | this.keyStoreInputStream = new FileInputStream(keyStoreFilePath); 95 | } catch (FileNotFoundException e) { 96 | throw new ApnsException(e); 97 | } 98 | this.keyStorePwd = keyStorePwd; 99 | this.keyStoreType = KeyStoreType.PKCS12; 100 | } 101 | 102 | public KeyStore keyStore() { 103 | try { 104 | KeyStore keyStore = KeyStore.getInstance(this.keyStoreType.name()); 105 | keyStore.load(this.keyStoreInputStream, null == keyStorePwd ? new char[0] : keyStorePwd.toCharArray()); 106 | return keyStore; 107 | } catch (KeyStoreException e) { 108 | if (e.getCause() instanceof NoSuchAlgorithmException || e.getCause() instanceof NoSuchProviderException) { 109 | throw new ApnsException(new InvalidKeyStoreTypeException("(" + this.keyStoreType + ")", e)); 110 | } else { 111 | throw new ApnsException(new InvalidKeyStoreTypeException(e)); 112 | } 113 | } catch (CertificateException e) { 114 | throw new ApnsException(new InvalidKeyStoreFormatException("cant load keystore", e)); 115 | } catch (NoSuchAlgorithmException e) { 116 | throw new ApnsException(new InvalidKeyStoreFormatException("cant load keystore", e)); 117 | } catch (IOException e) { 118 | if (e.getCause() instanceof BadPaddingException) { 119 | throw new ApnsException(new InvalidKeyStorePasswordException("(" + this.keyStorePwd + ")", e)); 120 | } else { 121 | throw new ApnsException(new InvalidKeyStoreFormatException(e)); 122 | } 123 | } 124 | } 125 | 126 | 127 | public String keyStorePwd() { 128 | return this.keyStorePwd; 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/main/java/cn/teaey/apns4j/keystore/KeyStoreType.java: -------------------------------------------------------------------------------- 1 | package cn.teaey.apns4j.keystore; 2 | 3 | /** 4 | * @author teaey(xiaofei.wxf) 5 | * @since 1.0.3 6 | */ 7 | public enum KeyStoreType { 8 | PKCS12, 9 | JKS 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/cn/teaey/apns4j/network/ApnsChannel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * * Copyright 2015 The Apns4j Project 4 | * * 5 | * * The Netty Project licenses this file to you under the Apache License, 6 | * * version 2.0 (the "License"); you may not use this file except in compliance 7 | * * with the License. You may obtain a copy of the License at: 8 | * * 9 | * * http://www.apache.org/licenses/LICENSE-2.0 10 | * * 11 | * * Unless required by applicable law or agreed to in writing, software 12 | * * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | * * License for the specific language governing permissions and limitations 15 | * * under the License. 16 | * 17 | */ 18 | 19 | package cn.teaey.apns4j.network; 20 | 21 | import cn.teaey.apns4j.ApnsException; 22 | import cn.teaey.apns4j.ApnsHelper; 23 | import cn.teaey.apns4j.network.async.ApnsFuture; 24 | import cn.teaey.apns4j.network.async.PayloadSender; 25 | import cn.teaey.apns4j.protocol.ApnsPayload; 26 | import cn.teaey.apns4j.protocol.ErrorResp; 27 | 28 | import javax.net.ssl.SSLSocket; 29 | import java.io.IOException; 30 | import java.io.InputStream; 31 | import java.io.OutputStream; 32 | import java.util.LinkedHashMap; 33 | import java.util.Map; 34 | import java.util.concurrent.atomic.AtomicBoolean; 35 | import java.util.concurrent.atomic.AtomicInteger; 36 | 37 | /** 38 | * @author teaey(xiaofei.wxf) 39 | * @since 1.0.3 40 | */ 41 | public class ApnsChannel implements Channel, PayloadSenderflush.
107 | * 108 | * @throws java.io.IOException if any. 109 | */ 110 | private void flush() throws IOException { 111 | checkClosed(); 112 | out().flush(); 113 | } 114 | 115 | public ApnsFuture send(byte[] deviceTokenBytes, ApnsPayload apnsPayload, int tryTimes, boolean resent) { 116 | checkClosed(); 117 | if (tryTimes < 1) { 118 | tryTimes = 1; 119 | } 120 | int payloadId = ApnsHelper.IDENTIFIER.incrementAndGet(); 121 | ApnsHelper.checkDeviceToken(deviceTokenBytes); 122 | String jsonString = apnsPayload.toJsonString(); 123 | byte[] binaryData = ApnsHelper.toRequestBytes(deviceTokenBytes, jsonString, payloadId, apnsPayload.getExpiry()); 124 | for (int i = 1; i <= tryTimes; i++) { 125 | try { 126 | socket(); 127 | out().write(binaryData); 128 | flush(); 129 | //log.debug("Success send payload : {} to device : {} try : {}", new Object[]{jsonString, deviceTokenBytes, i}); 130 | break; 131 | } catch (IOException e) { 132 | try { 133 | _close(); 134 | } catch (IOException e1) { 135 | } 136 | //log.error("Failed send payload : {} to device : {} try : {}", new Object[]{jsonString, deviceTokenBytes, e}); 137 | if (i == tryTimes) 138 | throw new ApnsException(e); 139 | } 140 | } 141 | if(!resent) { 142 | payloadCache.put(payloadId, new CacheWapper(payloadId, deviceTokenBytes, apnsPayload)); 143 | } 144 | return null; 145 | } 146 | 147 | /** 148 | * Send a payload with a devicetoken bytes(32 bytes) 149 | * 150 | * @param deviceTokenBytes an array of byte. 151 | * @param apnsPayload a {@link ApnsPayload} object. 152 | */ 153 | public ApnsFuture send(byte[] deviceTokenBytes, ApnsPayload apnsPayload) { 154 | checkClosed(); 155 | return this.send(deviceTokenBytes, apnsPayload, tryTimes, false); 156 | } 157 | 158 | /** 159 | * Send a payload with a devicetoken string(length 64) 160 | * 161 | * @param deviceTokenString a {@link String} object. 162 | * @param apnsPayload a {@link ApnsPayload} object. 163 | * @param tryTimes retry times 164 | * @return feture 165 | */ 166 | public ApnsFuture send(String deviceTokenString, ApnsPayload apnsPayload, int tryTimes) { 167 | checkClosed(); 168 | return send(ApnsHelper.toByteArray(deviceTokenString), apnsPayload, tryTimes, false); 169 | } 170 | 171 | /** 172 | * Send a payload with a devicetoken string(length 64) 173 | * 174 | * @param deviceTokenString a {@link String} object. 175 | * @param apnsPayload a {@link ApnsPayload} object. 176 | */ 177 | public ApnsFuture send(String deviceTokenString, ApnsPayload apnsPayload) { 178 | checkClosed(); 179 | return this.send(ApnsHelper.toByteArray(deviceTokenString), apnsPayload); 180 | } 181 | 182 | /** 183 | *recvErrorResp.
184 | * 185 | * @return a {@link ErrorResp} object. 186 | */ 187 | public ErrorResp recvErrorResp() { 188 | checkClosed(); 189 | try { 190 | if (null == in()) { 191 | return null; 192 | } 193 | byte[] data = new byte[6]; 194 | recv(data); 195 | _close(); 196 | return new ErrorResp(data); 197 | } catch (ApnsException e) { 198 | throw e; 199 | } catch (IOException e) { 200 | throw new ApnsException(e); 201 | } 202 | } 203 | 204 | private void _close() throws IOException { 205 | if (null != socket) { 206 | try { 207 | socket.close(); 208 | } finally { 209 | in = null; 210 | out = null; 211 | socket = null; 212 | } 213 | } 214 | } 215 | 216 | private void _detectSocket() { 217 | Thread t = new Thread(new Runnable() { 218 | @Override 219 | public void run() { 220 | while(!ApnsChannel.this.closed.get()) { 221 | try { 222 | ErrorResp errorResp = recvErrorResp(); 223 | if(null == errorResp) { 224 | Thread.sleep(1000); 225 | continue; 226 | } 227 | LRUCacheclose.
248 | */ 249 | @Override 250 | public void close() { 251 | try { 252 | if (this.closed.compareAndSet(false, true)) { 253 | _close(); 254 | } 255 | } catch (IOException e) { 256 | throw new ApnsException(e); 257 | } 258 | } 259 | 260 | private void checkClosed() { 261 | if (closed.get()) { 262 | throw new IllegalStateException("Channel closed, get a new channel from channel factory"); 263 | } 264 | } 265 | 266 | /** 267 | * {@inheritDoc} 268 | */ 269 | @Override 270 | public void send(byte[] data) { 271 | checkClosed(); 272 | try { 273 | out().write(data); 274 | } catch (IOException e) { 275 | try { 276 | _close(); 277 | } catch (IOException e1) { 278 | } 279 | throw new ApnsException(e); 280 | } 281 | } 282 | 283 | /** 284 | * {@inheritDoc} 285 | */ 286 | @Override 287 | public int recv(byte[] data) { 288 | checkClosed(); 289 | try { 290 | return in().read(data); 291 | } catch (IOException e) { 292 | try { 293 | _close(); 294 | } catch (IOException e1) { 295 | } 296 | throw new ApnsException(e); 297 | } 298 | } 299 | 300 | /** 301 | *socket.
302 | * @throws IOException 303 | */ 304 | protected void socket() throws IOException { 305 | checkClosed(); 306 | if (null != socket && null != in && null != out && !socket.isClosed()) { 307 | return; 308 | } else { 309 | _close(); 310 | this.socket = socketFactory.createSocket(); 311 | this.in = socket.getInputStream(); 312 | this.out = socket.getOutputStream(); 313 | } 314 | } 315 | 316 | /** 317 | *out.
318 | * 319 | * @return a {@link java.io.OutputStream} object. 320 | */ 321 | protected OutputStream out() { 322 | return this.out; 323 | } 324 | 325 | /** 326 | *in.
327 | * 328 | * @return a {@link java.io.InputStream} object. 329 | */ 330 | protected InputStream in() { 331 | return this.in; 332 | } 333 | 334 | /** 335 | *Getter for the field id
.
data.length
bytes from the specified byte array
30 | * to this connection
31 | *
32 | * @param data an array of byte.
33 | */
34 | void send(byte[] data);
35 |
36 | /**
37 | * Reads some number of bytes from the connection and stores them into
38 | * the buffer array data
. The number of bytes actually read is
39 | * returned as an integer.
40 | *
41 | * @param data an array of byte.
42 | * @return a int.
43 | */
44 | int recv(byte[] data);
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/cn/teaey/apns4j/network/SecuritySocketFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * * Copyright 2015 The Apns4j Project
4 | * *
5 | * * The Netty Project licenses this file to you under the Apache License,
6 | * * version 2.0 (the "License"); you may not use this file except in compliance
7 | * * with the License. You may obtain a copy of the License at:
8 | * *
9 | * * http://www.apache.org/licenses/LICENSE-2.0
10 | * *
11 | * * Unless required by applicable law or agreed to in writing, software
12 | * * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 | * * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 | * * License for the specific language governing permissions and limitations
15 | * * under the License.
16 | *
17 | */
18 |
19 | package cn.teaey.apns4j.network;
20 |
21 | import cn.teaey.apns4j.ApnsException;
22 | import cn.teaey.apns4j.keystore.InvalidKeyStoreException;
23 |
24 | import javax.net.ssl.*;
25 | import java.io.IOException;
26 | import java.security.KeyStore;
27 | import java.security.Security;
28 | import java.security.cert.CertificateException;
29 | import java.security.cert.X509Certificate;
30 |
31 | //import org.bouncycastle.jce.provider.BouncyCastleProvider;
32 |
33 | /**
34 | * @author teaey
35 | * @since 1.0.0
36 | */
37 | public final class SecuritySocketFactory {
38 | /* The algorithm used by KeyManagerFactory */
39 | private static final String ALGORITHM = ((Security.getProperty("ssl.KeyManagerFactory.algorithm") == null) ? "sunx509" : Security.getProperty("ssl.KeyManagerFactory.algorithm"));
40 | /* The protocol used to create the SSLSocket */
41 | private static final String PROTOCOL = "TLS";
42 | // static
43 | // {
44 | // Security.addProvider(new BouncyCastleProvider());
45 | // }
46 | private final String host;
47 | private final int port;
48 | private final KeyStore keyStore;
49 | private final String keyStorePwd;
50 | private final SSLSocketFactory sslSocketFactory;
51 | private final TrustManager[] trustManagers = new TrustManager[]{new ServerTrustingTrustManager()};
52 |
53 | public SecuritySocketFactory(String host, int port, KeyStore keyStore, String keyStorePwd) {
54 | if (host == null) {
55 | throw new NullPointerException("host");
56 | }
57 | if (keyStore == null) {
58 | throw new NullPointerException("keystore");
59 | }
60 | if (keyStorePwd == null) {
61 | throw new NullPointerException("keyStorePwd");
62 | }
63 | this.host = host;
64 | this.port = port;
65 | this.keyStore = keyStore;
66 | this.keyStorePwd = keyStorePwd;
67 | this.sslSocketFactory = createSSLSocketFactoryWithTrustManagers(trustManagers);
68 | }
69 |
70 | public String getHost() {
71 | return host;
72 | }
73 |
74 | public int getPort() {
75 | return port;
76 | }
77 |
78 | public KeyStore getKeyStore() {
79 | return keyStore;
80 | }
81 |
82 | public String getKeyStorePwd() {
83 | return keyStorePwd;
84 | }
85 |
86 | public SSLSocketFactory getSslSocketFactory() {
87 | return sslSocketFactory;
88 | }
89 |
90 | public TrustManager[] getTrustManagers() {
91 | return trustManagers;
92 | }
93 |
94 | /**
95 | * createSSLSocketFactoryWithTrustManagers.
96 | * 97 | * @param trustManagers an array of {@link javax.net.ssl.TrustManager} objects. 98 | * @return a {@link javax.net.ssl.SSLSocketFactory} object. 99 | */ 100 | protected SSLSocketFactory createSSLSocketFactoryWithTrustManagers(TrustManager[] trustManagers) { 101 | // Get a KeyManager and initialize it 102 | try { 103 | KeyManagerFactory kmf = KeyManagerFactory.getInstance(ALGORITHM); 104 | kmf.init(keyStore, keyStorePwd.toCharArray()); 105 | // Get the SSLContext to help create SSLSocketFactory 106 | SSLContext sslc = SSLContext.getInstance(PROTOCOL); 107 | sslc.init(kmf.getKeyManagers(), trustManagers, null); 108 | return sslc.getSocketFactory(); 109 | } catch (Exception e) { 110 | throw new ApnsException(new InvalidKeyStoreException(e)); 111 | } 112 | } 113 | 114 | /** 115 | * Create a SSLSocket which will be used to send data to Apple 116 | * 117 | * @return the SSLSocket 118 | */ 119 | public SSLSocket createSocket() throws IOException { 120 | return (SSLSocket) sslSocketFactory.createSocket(host, port); 121 | } 122 | 123 | private class ServerTrustingTrustManager implements X509TrustManager { 124 | public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { 125 | throw new CertificateException("not trusted"); 126 | } 127 | 128 | public void checkServerTrusted(X509Certificate[] chain, String authType) { 129 | // trust all servers 130 | } 131 | 132 | public X509Certificate[] getAcceptedIssuers() { 133 | return null; 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/main/java/cn/teaey/apns4j/network/async/ApnsFuture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * * Copyright 2015 The Apns4j Project 4 | * * 5 | * * The Netty Project licenses this file to you under the Apache License, 6 | * * version 2.0 (the "License"); you may not use this file except in compliance 7 | * * with the License. You may obtain a copy of the License at: 8 | * * 9 | * * http://www.apache.org/licenses/LICENSE-2.0 10 | * * 11 | * * Unless required by applicable law or agreed to in writing, software 12 | * * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | * * License for the specific language governing permissions and limitations 15 | * * under the License. 16 | * 17 | */ 18 | 19 | package cn.teaey.apns4j.network.async; 20 | 21 | import cn.teaey.apns4j.protocol.ApnsPayload; 22 | 23 | import java.util.concurrent.ExecutionException; 24 | import java.util.concurrent.Future; 25 | import java.util.concurrent.TimeUnit; 26 | import java.util.concurrent.TimeoutException; 27 | 28 | /** 29 | * @author xiaofei.wxf 30 | */ 31 | public class ApnsFuture implements Future { 32 | private final Future future; 33 | private final byte[] deviceToken; 34 | private final ApnsPayload payload; 35 | 36 | public ApnsFuture(Future future, byte[] deviceToken, ApnsPayload payload) { 37 | this.future = future; 38 | this.deviceToken = deviceToken; 39 | this.payload = payload; 40 | } 41 | 42 | @Override 43 | public boolean cancel(boolean mayInterruptIfRunning) { 44 | return future.cancel(mayInterruptIfRunning); 45 | } 46 | 47 | @Override 48 | public boolean isCancelled() { 49 | return future.isCancelled(); 50 | } 51 | 52 | @Override 53 | public boolean isDone() { 54 | return future.isDone(); 55 | } 56 | 57 | @Override 58 | public Object get() throws InterruptedException, ExecutionException { 59 | return future.get(); 60 | } 61 | 62 | @Override 63 | public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { 64 | return future.get(timeout, unit); 65 | } 66 | 67 | public byte[] getDeviceToken() { 68 | return deviceToken; 69 | } 70 | 71 | public ApnsPayload getPayload() { 72 | return payload; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/cn/teaey/apns4j/network/async/ApnsService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * * Copyright 2015 The Apns4j Project 4 | * * 5 | * * The Netty Project licenses this file to you under the Apache License, 6 | * * version 2.0 (the "License"); you may not use this file except in compliance 7 | * * with the License. You may obtain a copy of the License at: 8 | * * 9 | * * http://www.apache.org/licenses/LICENSE-2.0 10 | * * 11 | * * Unless required by applicable law or agreed to in writing, software 12 | * * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | * * License for the specific language governing permissions and limitations 15 | * * under the License. 16 | * 17 | */ 18 | 19 | package cn.teaey.apns4j.network.async; 20 | 21 | import cn.teaey.apns4j.ApnsException; 22 | import cn.teaey.apns4j.ApnsHelper; 23 | import cn.teaey.apns4j.network.ApnsChannelFactory; 24 | import cn.teaey.apns4j.protocol.ApnsPayload; 25 | 26 | import java.util.concurrent.*; 27 | import java.util.concurrent.atomic.AtomicBoolean; 28 | 29 | /** 30 | * @author teaey 31 | * @since 1.0.0 32 | */ 33 | public class ApnsService implements PayloadSendershutdown.
69 | */ 70 | public void shutdown() { 71 | if (START.compareAndSet(true, false)) { 72 | executorService.shutdown(); 73 | } 74 | } 75 | 76 | public void shutdownNow() { 77 | if (START.compareAndSet(true, false)) { 78 | executorService.shutdownNow(); 79 | } 80 | } 81 | 82 | public void shutdown(long timeout, TimeUnit timeUnit) { 83 | if (START.compareAndSet(true, false)) { 84 | try { 85 | executorService.shutdown(); 86 | executorService.awaitTermination(timeout, timeUnit); 87 | } catch (InterruptedException e) { 88 | throw new ApnsException(e); 89 | } 90 | } 91 | } 92 | 93 | //private static final Logger log = LoggerFactory.getLogger(APNSAsynService.class); 94 | class APNSAsynTask implements Callable