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 }