1 /**
2 * Copyright 2011 The Kuali Foundation Licensed under the
3 * Educational Community License, Version 2.0 (the "License"); you may
4 * not use this file except in compliance with the License. You may
5 * obtain a copy of the License at
6 *
7 * http://www.osedu.org/licenses/ECL-2.0
8 *
9 * Unless required by applicable law or agreed to in writing,
10 * software distributed under the License is distributed on an "AS IS"
11 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12 * or implied. See the License for the specific language governing
13 * permissions and limitations under 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 Feedback Service.
31 * This Factory is used by <code>DeviceFeedbackMonitor</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.feedback.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.feedback.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.3.0
46 */
47 public class iOSFeedbackConnectionFactory implements PoolableObjectFactory<SSLSocket>{
48
49 /** APN host name */
50 @Value("${push.apple.feedback.host}")
51 private String host = null;
52
53 /** APN Host port */
54 @Value("${push.apple.feedback.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 * (non-Javadoc)
69 * @see org.apache.commons.pool.PoolableObjectFactory#makeObject()
70 */
71 @Override
72 public SSLSocket makeObject() throws Exception {
73 SSLSocket socket = null;
74 KeyStore keyStore = KeyStore.getInstance("PKCS12");
75 keyStore.load(certPath.getInputStream(), certPassword.toCharArray());
76 KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("sunx509");
77 keyManagerFactory.init(keyStore, certPassword.toCharArray());
78 TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("sunx509");
79 trustManagerFactory.init(keyStore);
80 SSLContext sslCtx = SSLContext.getInstance("TLS");
81 sslCtx.init(keyManagerFactory.getKeyManagers(), null, null);
82 SSLSocketFactory sslSocketFactory = sslCtx.getSocketFactory();
83 socket = (SSLSocket)sslSocketFactory.createSocket(host, port);
84 socket.startHandshake();
85 return socket;
86 }
87
88 /*
89 * (non-Javadoc)
90 * @see org.apache.commons.pool.PoolableObjectFactory#destroyObject(java.lang.Object)
91 */
92 @Override
93 public void destroyObject(SSLSocket obj) throws Exception {
94 if (obj == null){
95 /* If an exception ocurred during the creation of an object
96 * we will receive an null object to destroy */
97 return;
98 }
99 try{
100 obj.close();
101 }
102 catch (Exception e) {
103 // Don't worry - just try and close
104 }
105 }
106
107 /*
108 * (non-Javadoc)
109 * @see org.apache.commons.pool.PoolableObjectFactory#validateObject(java.lang.Object)
110 */
111 @Override
112 public boolean validateObject(SSLSocket obj) {
113 if (obj == null){
114 return false; // null is obviously not valid
115 }
116 return obj.isConnected() && !obj.isClosed();
117 }
118
119 /*
120 * (non-Javadoc)
121 * @see org.apache.commons.pool.PoolableObjectFactory#activateObject(java.lang.Object)
122 */
123 @Override
124 public void activateObject(SSLSocket obj) throws Exception {
125 // Do nothing
126 }
127
128 /*
129 * (non-Javadoc)
130 * @see org.apache.commons.pool.PoolableObjectFactory#passivateObject(java.lang.Object)
131 */
132 @Override
133 public void passivateObject(SSLSocket obj) throws Exception {
134 // Do nothing
135 }
136 }