Skip to content

Commit 6ea2403

Browse files
committed
Merge pull request #93 from karldmoore/master
Builder and Delegate changes
2 parents fb6e85f + c916cc7 commit 6ea2403

File tree

4 files changed

+87
-43
lines changed

4 files changed

+87
-43
lines changed

src/main/java/com/notnoop/apns/ApnsDelegate.java

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -70,20 +70,5 @@ public interface ApnsDelegate {
7070
/**
7171
* A NOOP delegate that does nothing!
7272
*/
73-
public final static ApnsDelegate EMPTY = new ApnsDelegate() {
74-
public void messageSent(ApnsNotification message, boolean resent) {
75-
}
76-
77-
public void messageSendFailed(ApnsNotification message, Throwable e) {
78-
}
79-
80-
public void connectionClosed(DeliveryError e, int messageIdentifier) {
81-
}
82-
83-
public void cacheLengthExceeded(int newCacheLength) {
84-
}
85-
86-
public void notificationsResent(int resendCount) {
87-
}
88-
};
73+
public final static ApnsDelegate EMPTY = new ApnsDelegateAdapter();
8974
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.notnoop.apns;
2+
3+
/**
4+
* A NOOP delegate that does nothing!
5+
*/
6+
public class ApnsDelegateAdapter implements ApnsDelegate {
7+
8+
public void messageSent(ApnsNotification message, boolean resent) {
9+
}
10+
11+
public void messageSendFailed(ApnsNotification message, Throwable e) {
12+
}
13+
14+
public void connectionClosed(DeliveryError e, int messageIdentifier) {
15+
}
16+
17+
public void cacheLengthExceeded(int newCacheLength) {
18+
}
19+
20+
public void notificationsResent(int resendCount) {
21+
}
22+
}

src/main/java/com/notnoop/apns/ApnsServiceBuilder.java

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import java.net.Proxy;
3838
import java.net.Socket;
3939

40+
import java.security.KeyStore;
4041
import java.util.concurrent.ExecutorService;
4142
import java.util.concurrent.Executors;
4243
import java.util.concurrent.ThreadFactory;
@@ -162,16 +163,44 @@ public ApnsServiceBuilder withCert(String fileName, String password)
162163
*/
163164
public ApnsServiceBuilder withCert(InputStream stream, String password)
164165
throws InvalidSSLConfig {
165-
if (password == null || password.length() == 0) {
166-
throw new IllegalArgumentException("Passwords must be specified." +
167-
"Oracle Java SDK does not support passwordless p12 certificates");
168-
}
169-
166+
assertPasswordNotEmpty(password);
170167
return withSSLContext(
171168
newSSLContext(stream, password,
172169
KEYSTORE_TYPE, KEY_ALGORITHM));
173170
}
174171

172+
/**
173+
* Specify the certificate used to connect to Apple APNS
174+
* servers. This relies on a keystore (*.p12)
175+
* containing the certificate, along with the given password.
176+
*
177+
* This library does not support password-less p12 certificates, due to a
178+
* Oracle Java library <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6415637">
179+
* Bug 6415637</a>. There are three workarounds: use a password-protected
180+
* certificate, use a different boot Java SDK implementation, or constract
181+
* the `SSLContext` yourself! Needless to say, the password-protected
182+
* certificate is most recommended option.
183+
*
184+
* @param stream the keystore
185+
* @param password the password of the keystore
186+
* @return this
187+
* @throws InvalidSSLConfig if stream is invalid Keystore
188+
* or the password is invalid
189+
*/
190+
public ApnsServiceBuilder withCert(KeyStore keyStore, String password)
191+
throws InvalidSSLConfig {
192+
assertPasswordNotEmpty(password);
193+
return withSSLContext(
194+
newSSLContext(keyStore, password, KEY_ALGORITHM));
195+
}
196+
197+
private void assertPasswordNotEmpty(String password) {
198+
if (password == null || password.length() == 0) {
199+
throw new IllegalArgumentException("Passwords must be specified." +
200+
"Oracle Java SDK does not support passwordless p12 certificates");
201+
}
202+
}
203+
175204
/**
176205
* Specify the SSLContext that should be used to initiate the
177206
* connection to Apple Server.

src/main/java/com/notnoop/apns/internal/Utilities.java

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -79,28 +79,36 @@ public static SSLSocketFactory newSSLSocketFactory(final InputStream cert, final
7979
}
8080

8181
public static SSLContext newSSLContext(final InputStream cert, final String password,
82-
final String ksType, final String ksAlgorithm) throws InvalidSSLConfig {
83-
try {
84-
final KeyStore ks = KeyStore.getInstance(ksType);
85-
ks.load(cert, password.toCharArray());
86-
87-
// Get a KeyManager and initialize it
88-
final KeyManagerFactory kmf = KeyManagerFactory.getInstance(ksAlgorithm);
89-
kmf.init(ks, password.toCharArray());
90-
91-
// Get a TrustManagerFactory with the DEFAULT KEYSTORE, so we have all
92-
// the certificates in cacerts trusted
93-
final TrustManagerFactory tmf = TrustManagerFactory.getInstance(ksAlgorithm);
94-
tmf.init((KeyStore)null);
95-
96-
// Get the SSLContext to help create SSLSocketFactory
97-
final SSLContext sslc = SSLContext.getInstance("TLS");
98-
sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
99-
return sslc;
100-
} catch (final Exception e) {
101-
throw new InvalidSSLConfig(e);
102-
}
103-
}
82+
final String ksType, final String ksAlgorithm) throws InvalidSSLConfig {
83+
try {
84+
final KeyStore ks = KeyStore.getInstance(ksType);
85+
ks.load(cert, password.toCharArray());
86+
return newSSLContext(ks, password, ksAlgorithm);
87+
} catch (final Exception e) {
88+
throw new InvalidSSLConfig(e);
89+
}
90+
}
91+
92+
public static SSLContext newSSLContext(final KeyStore ks, final String password,
93+
final String ksAlgorithm) throws InvalidSSLConfig {
94+
try {
95+
// Get a KeyManager and initialize it
96+
final KeyManagerFactory kmf = KeyManagerFactory.getInstance(ksAlgorithm);
97+
kmf.init(ks, password.toCharArray());
98+
99+
// Get a TrustManagerFactory with the DEFAULT KEYSTORE, so we have all
100+
// the certificates in cacerts trusted
101+
final TrustManagerFactory tmf = TrustManagerFactory.getInstance(ksAlgorithm);
102+
tmf.init((KeyStore)null);
103+
104+
// Get the SSLContext to help create SSLSocketFactory
105+
final SSLContext sslc = SSLContext.getInstance("TLS");
106+
sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
107+
return sslc;
108+
} catch (final Exception e) {
109+
throw new InvalidSSLConfig(e);
110+
}
111+
}
104112

105113
private static final Pattern pattern = Pattern.compile("[ -]");
106114
public static byte[] decodeHex(final String deviceToken) {

0 commit comments

Comments
 (0)