View Javadoc

1   /**
2    * Copyright 2011-2013 The Kuali Foundation Licensed under the Educational
3    * Community License, Version 2.0 (the "License"); you may not use this file
4    * except in compliance with the License. You may obtain a copy of the License
5    * at
6    *
7    * http://www.osedu.org/licenses/ECL-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12   * License for the specific language governing permissions and limitations under
13   * the License.
14   */
15  package org.kuali.mobility.push.factory;
16  
17  import java.security.KeyStore;
18  
19  import javax.net.ssl.KeyManagerFactory;
20  import javax.net.ssl.SSLContext;
21  import javax.net.ssl.SSLSocket;
22  import javax.net.ssl.SSLSocketFactory;
23  import javax.net.ssl.TrustManagerFactory;
24  
25  import org.apache.commons.pool.PoolableObjectFactory;
26  import org.springframework.beans.factory.annotation.Value;
27  import org.springframework.core.io.Resource;
28  
29  /**
30   * Factory that creates a pool of connection to the Apple Push Notifications Service (APNS)
31   * This Factory is use by the <code>iOSSendService</code> and is injected using spring configuration.
32   * 
33   * The configuration for this factory is injected via spring.
34   * 
35    * Available spring properties are:<br>
36   * <table style="border-collapse:collapse; border: 1px solid;" border="1" cellpadding="3px">
37   * 	<tr><th>Property</th><th>Purpose</th></tr>
38   *  <tr><td><code>push.apple.host</code></td><td>APNS host name</td></tr>
39   * 	<tr><td><code>push.apple.key.file</code></td><td>Path to the certificate for APNS</td></tr>
40   * 	<tr><td><code>push.apple.key.passphrase</code></td><td>Password for the certificate</td></tr>
41   * 	<tr><td><code>push.apple.port</code></td><td>Port connect to on the APNS</td></tr>
42   * </table>
43   * 
44   * @author Kuali Mobility Team (mobility.dev@kuali.org)
45   * @since 2.2.0
46   */
47  public class iOSConnectionFactory implements PoolableObjectFactory<SSLSocket> {
48  
49  	/** APN host name */
50  	@Value("${push.apple.host}")
51  	private String host = null;
52  
53  	/** APN host port */
54  	@Value("${push.apple.port}")
55  	private int port;
56  	
57  	/** Path to the cert for APN */
58  	@Value("${push.apple.key.file}")
59  	private Resource certPath;
60  
61  	/** Password for the APN certificate */
62  	@Value("${push.apple.key.passphrase}")
63  	private String certPassword;
64  
65  
66  
67  
68  	/*
69  	 * (non-Javadoc)
70  	 * @see org.apache.commons.pool.PoolableObjectFactory#makeObject()
71  	 */
72  	@Override
73  	public SSLSocket makeObject() throws Exception {
74  		SSLSocket socket = null;
75  		KeyStore keyStore = KeyStore.getInstance("PKCS12");
76  		keyStore.load(certPath.getInputStream(), certPassword.toCharArray());
77  		KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("sunx509");
78  		keyManagerFactory.init(keyStore, certPassword.toCharArray());
79  		TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("sunx509");
80  		trustManagerFactory.init(keyStore);
81  		SSLContext sslCtx = SSLContext.getInstance("TLS");
82  		sslCtx.init(keyManagerFactory.getKeyManagers(), null, null);
83  		SSLSocketFactory sslSocketFactory = sslCtx.getSocketFactory();
84  		socket = (SSLSocket)sslSocketFactory.createSocket(host, port);
85  		socket.startHandshake();
86  		return socket;
87  	}
88  
89  	/*
90  	 * (non-Javadoc)
91  	 * @see org.apache.commons.pool.PoolableObjectFactory#destroyObject(java.lang.Object)
92  	 */
93  	@Override
94  	public void destroyObject(SSLSocket obj) throws Exception {
95  		if (obj == null){
96  			/* If an exception ocurred during the creation of an object
97  			 * we will receive an null object to destroy */
98  			return;
99  		}
100 		try{
101 			obj.close();
102 		}
103 		catch (Exception e) {
104 			// Don't worry - just try and close
105 		}
106 	}
107 
108 	/*
109 	 * (non-Javadoc)
110 	 * @see org.apache.commons.pool.PoolableObjectFactory#validateObject(java.lang.Object)
111 	 */
112 	@Override
113 	public boolean validateObject(SSLSocket obj) {
114 		if (obj == null){
115 			return false; // null is obviously not valid
116 		}
117 		return obj.isConnected() && !obj.isClosed();
118 	}
119 
120 	/*
121 	 * (non-Javadoc)
122 	 * @see org.apache.commons.pool.PoolableObjectFactory#activateObject(java.lang.Object)
123 	 */
124 	@Override
125 	public void activateObject(SSLSocket obj) throws Exception {
126 		// Do nothing
127 	}
128 
129 	/*
130 	 * (non-Javadoc)
131 	 * @see org.apache.commons.pool.PoolableObjectFactory#passivateObject(java.lang.Object)
132 	 */
133 	@Override
134 	public void passivateObject(SSLSocket obj) throws Exception {
135 		// Do nothing
136 	}
137 }