Skip to content

Commit

Permalink
Merge pull request #93 from karldmoore/master
Browse files Browse the repository at this point in the history
Builder and Delegate changes
  • Loading branch information
notnoop committed Mar 24, 2013
2 parents fb6e85f + c916cc7 commit 6ea2403
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 43 deletions.
17 changes: 1 addition & 16 deletions src/main/java/com/notnoop/apns/ApnsDelegate.java
Expand Up @@ -70,20 +70,5 @@ public interface ApnsDelegate {
/**
* A NOOP delegate that does nothing!
*/
public final static ApnsDelegate EMPTY = new ApnsDelegate() {
public void messageSent(ApnsNotification message, boolean resent) {
}

public void messageSendFailed(ApnsNotification message, Throwable e) {
}

public void connectionClosed(DeliveryError e, int messageIdentifier) {
}

public void cacheLengthExceeded(int newCacheLength) {
}

public void notificationsResent(int resendCount) {
}
};
public final static ApnsDelegate EMPTY = new ApnsDelegateAdapter();
}
22 changes: 22 additions & 0 deletions src/main/java/com/notnoop/apns/ApnsDelegateAdapter.java
@@ -0,0 +1,22 @@
package com.notnoop.apns;

/**
* A NOOP delegate that does nothing!
*/
public class ApnsDelegateAdapter implements ApnsDelegate {

public void messageSent(ApnsNotification message, boolean resent) {
}

public void messageSendFailed(ApnsNotification message, Throwable e) {
}

public void connectionClosed(DeliveryError e, int messageIdentifier) {
}

public void cacheLengthExceeded(int newCacheLength) {
}

public void notificationsResent(int resendCount) {
}
}
39 changes: 34 additions & 5 deletions src/main/java/com/notnoop/apns/ApnsServiceBuilder.java
Expand Up @@ -37,6 +37,7 @@
import java.net.Proxy;
import java.net.Socket;

import java.security.KeyStore;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
Expand Down Expand Up @@ -162,16 +163,44 @@ public ApnsServiceBuilder withCert(String fileName, String password)
*/
public ApnsServiceBuilder withCert(InputStream stream, String password)
throws InvalidSSLConfig {
if (password == null || password.length() == 0) {
throw new IllegalArgumentException("Passwords must be specified." +
"Oracle Java SDK does not support passwordless p12 certificates");
}

assertPasswordNotEmpty(password);
return withSSLContext(
newSSLContext(stream, password,
KEYSTORE_TYPE, KEY_ALGORITHM));
}

/**
* Specify the certificate used to connect to Apple APNS
* servers. This relies on a keystore (*.p12)
* containing the certificate, along with the given password.
*
* This library does not support password-less p12 certificates, due to a
* Oracle Java library <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6415637">
* Bug 6415637</a>. There are three workarounds: use a password-protected
* certificate, use a different boot Java SDK implementation, or constract
* the `SSLContext` yourself! Needless to say, the password-protected
* certificate is most recommended option.
*
* @param stream the keystore
* @param password the password of the keystore
* @return this
* @throws InvalidSSLConfig if stream is invalid Keystore
* or the password is invalid
*/
public ApnsServiceBuilder withCert(KeyStore keyStore, String password)
throws InvalidSSLConfig {
assertPasswordNotEmpty(password);
return withSSLContext(
newSSLContext(keyStore, password, KEY_ALGORITHM));
}

private void assertPasswordNotEmpty(String password) {
if (password == null || password.length() == 0) {
throw new IllegalArgumentException("Passwords must be specified." +
"Oracle Java SDK does not support passwordless p12 certificates");
}
}

/**
* Specify the SSLContext that should be used to initiate the
* connection to Apple Server.
Expand Down
52 changes: 30 additions & 22 deletions src/main/java/com/notnoop/apns/internal/Utilities.java
Expand Up @@ -79,28 +79,36 @@ public static SSLSocketFactory newSSLSocketFactory(final InputStream cert, final
}

public static SSLContext newSSLContext(final InputStream cert, final String password,
final String ksType, final String ksAlgorithm) throws InvalidSSLConfig {
try {
final KeyStore ks = KeyStore.getInstance(ksType);
ks.load(cert, password.toCharArray());

// Get a KeyManager and initialize it
final KeyManagerFactory kmf = KeyManagerFactory.getInstance(ksAlgorithm);
kmf.init(ks, password.toCharArray());

// Get a TrustManagerFactory with the DEFAULT KEYSTORE, so we have all
// the certificates in cacerts trusted
final TrustManagerFactory tmf = TrustManagerFactory.getInstance(ksAlgorithm);
tmf.init((KeyStore)null);

// Get the SSLContext to help create SSLSocketFactory
final SSLContext sslc = SSLContext.getInstance("TLS");
sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
return sslc;
} catch (final Exception e) {
throw new InvalidSSLConfig(e);
}
}
final String ksType, final String ksAlgorithm) throws InvalidSSLConfig {
try {
final KeyStore ks = KeyStore.getInstance(ksType);
ks.load(cert, password.toCharArray());
return newSSLContext(ks, password, ksAlgorithm);
} catch (final Exception e) {
throw new InvalidSSLConfig(e);
}
}

public static SSLContext newSSLContext(final KeyStore ks, final String password,
final String ksAlgorithm) throws InvalidSSLConfig {
try {
// Get a KeyManager and initialize it
final KeyManagerFactory kmf = KeyManagerFactory.getInstance(ksAlgorithm);
kmf.init(ks, password.toCharArray());

// Get a TrustManagerFactory with the DEFAULT KEYSTORE, so we have all
// the certificates in cacerts trusted
final TrustManagerFactory tmf = TrustManagerFactory.getInstance(ksAlgorithm);
tmf.init((KeyStore)null);

// Get the SSLContext to help create SSLSocketFactory
final SSLContext sslc = SSLContext.getInstance("TLS");
sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
return sslc;
} catch (final Exception e) {
throw new InvalidSSLConfig(e);
}
}

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

0 comments on commit 6ea2403

Please sign in to comment.