001: /*
002: * ChainBuilder ESB
003: * Visual Enterprise Integration
004: *
005: * Copyright (C) 2007 Bostech Corporation
006: *
007: * This program is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License as published by the
009: * Free Software Foundation; either version 2 of the License, or (at your option)
010: * any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
014: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
015: * for more details.
016: *
017: * You should have received a copy of the GNU General Public License along with
018: * this program; if not, write to the Free Software Foundation, Inc.,
019: * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: *
021: *
022: * $Id: TcpipSocketManager.java 11804 2008-02-01 05:26:28Z lzheng $
023: */
024: package com.bostechcorp.cbesb.runtime.component.tcpip;
025:
026: import java.io.FileInputStream;
027: import java.net.InetAddress;
028: import java.net.InetSocketAddress;
029: import java.net.ServerSocket;
030: import java.net.Socket;
031: import java.security.KeyStore;
032:
033: import javax.jbi.JBIException;
034: import javax.net.ssl.KeyManager;
035: import javax.net.ssl.KeyManagerFactory;
036: import javax.net.ssl.SSLContext;
037: import javax.net.ssl.SSLServerSocket;
038: import javax.net.ssl.SSLServerSocketFactory;
039: import javax.net.ssl.SSLSocket;
040: import javax.net.ssl.SSLSocketFactory;
041: import javax.net.ssl.TrustManager;
042: import javax.net.ssl.TrustManagerFactory;
043: import javax.net.ssl.X509TrustManager;
044:
045: import org.apache.commons.logging.Log;
046: import org.apache.commons.logging.LogFactory;
047:
048: import com.bostechcorp.cbesb.common.util.ErrorUtil;
049: import com.bostechcorp.cbesb.common.util.EsbPathHelper;
050: import com.bostechcorp.cbesb.runtime.component.tcpip.wsdl.TcpipConfig;
051:
052: /*
053: * This class performs the job of connecting with remote systems. In server mode
054: * it starts a server socket and waits for client connections. In client mode
055: * it attempts to connect to the remote system.
056: * In either case, it will retry in the event of failures.
057: * When a connection is established, a new TcpipSocket thread is started to handle
058: * it and is registered with the endpoint. When the maximum connection
059: * limit is reached this thread ends.
060: */
061: public class TcpipSocketManager extends Thread {
062: protected final transient Log logger = LogFactory
063: .getLog(getClass());
064: private TcpipEndpoint endpoint;
065: private IManager manager;
066: private int maxSockets;
067: private boolean isRunning = true;
068:
069: public static TcpipSocketManager getInstance(TcpipEndpoint ep)
070: throws JBIException {
071: TcpipSocketManager mgr = new TcpipSocketManager(ep);
072: mgr.start();
073: return mgr;
074: }
075:
076: // force stop the manager
077: public void forceStop() {
078: try {
079: manager.stop();
080: isRunning = false;
081: } catch (Exception e) {
082: ErrorUtil.printError("Exception in forceStop(): ", e);
083: }
084: }
085:
086: public int getMaxSockets() {
087: return maxSockets;
088: }
089:
090: protected TcpipSocketManager(TcpipEndpoint ep) throws JBIException {
091: endpoint = ep;
092: TcpipConfig config = endpoint.getConfig();
093:
094: try {
095: if (config.connectionMode == TcpipConfig.CONNECTION_MODE_CLIENT) {
096: maxSockets = 1;
097: manager = new ClientManager(config);
098: } else {
099: maxSockets = config.getMaxClients();
100: manager = new ServerManager(config);
101: }
102: } catch (Exception e) {
103: ErrorUtil.printError("can't create socket manager ", e);
104: throw new JBIException(e);
105: }
106: }
107:
108: /*
109: * IManager abstracts the client and server connection logic into a common interface
110: */
111: private interface IManager {
112: void stop() throws Exception;
113:
114: TcpipSocket getSocket() throws Exception;
115: }
116:
117: private class ServerManager implements IManager {
118: InetAddress localBindAddress;
119: int listenPort;
120: ServerSocket listener;
121:
122: public ServerManager(TcpipConfig config) throws Exception {
123: // basic socket configuration
124: if (config.getLocalBindHost() != null)
125: localBindAddress = InetAddress.getByName(config
126: .getLocalBindHost());
127: listenPort = config.getListenPort();
128: }
129:
130: public void stop() throws Exception {
131: isRunning = false;
132: listener.close();
133: listener = null;
134: }
135:
136: public TcpipSocket getSocket() throws Exception {
137: TcpipSocket result = null;
138: // start listening
139: if (listener == null) {
140: try {
141: if (endpoint.getConfig().isUseSsl()) {
142: // SSL Server
143: SSLContext ctx = getSslContext();
144: SSLServerSocketFactory ssocketFactory = ctx
145: .getServerSocketFactory();
146: SSLServerSocket ssocket = null;
147: if (localBindAddress == null)
148: ssocket = (SSLServerSocket) ssocketFactory
149: .createServerSocket(listenPort);
150: else
151: ssocket = (SSLServerSocket) ssocketFactory
152: .createServerSocket(listenPort, 0,
153: localBindAddress);
154: if (endpoint.getConfig().isAllowAnonymous())
155: ssocket.setEnabledCipherSuites(ssocket
156: .getSupportedCipherSuites());
157: ssocket.setNeedClientAuth(endpoint.getConfig()
158: .isAuthenticateClient());
159: listener = ssocket;
160: } else {
161: // normal server
162: logger.debug("localBindAddress "
163: + localBindAddress);
164: if (localBindAddress == null)
165: listener = new ServerSocket(listenPort);
166: else
167: listener = new ServerSocket(listenPort, 0,
168: localBindAddress);
169: }
170: } catch (Exception sse) {
171: String listenAddress = "";
172: if (localBindAddress != null)
173: listenAddress = listenAddress
174: .concat(localBindAddress + ":");
175: listenAddress = listenAddress.concat(""
176: + listenPort);
177: ErrorUtil.printError(
178: "ServerSocket Exception listening on", sse);
179: throw sse;
180: }
181: }
182: //accept a connection
183: if (listener != null) {
184: // get a client
185: Socket client = listener.accept();
186: logger.debug("accepting a client "
187: + client.getInetAddress() + ":"
188: + client.getPort());
189: result = TcpipSocket.getInstance(endpoint, client);
190: }
191: return result;
192: }
193: }
194:
195: private class ClientManager implements IManager {
196: InetAddress localBindAddress;
197: InetAddress remoteHost;
198: int port;
199: Socket connectedClient;
200: SSLSocketFactory sslSocketFactory;
201:
202: public ClientManager(TcpipConfig config) throws Exception {
203: // basic socket configuration
204: if (config.getLocalBindHost() != null)
205: localBindAddress = InetAddress.getByName(config
206: .getLocalBindHost());
207: remoteHost = InetAddress.getByName(config.getHost());
208: port = config.getPort();
209: // SSL configuration
210: if (endpoint.getConfig().isUseSsl()) {
211: // SSL Client
212: SSLContext ctx = getSslContext();
213: sslSocketFactory = ctx.getSocketFactory();
214: }
215: }
216:
217: public void stop() throws Exception {
218: isRunning = false;
219: }
220:
221: public TcpipSocket getSocket() throws Exception {
222: TcpipSocket result = null;
223: if (sslSocketFactory != null) {
224: SSLSocket sock = (SSLSocket) sslSocketFactory
225: .createSocket();
226: if (endpoint.getConfig().isAllowAnonymous())
227: sock.setEnabledCipherSuites(sock
228: .getSupportedCipherSuites());
229: InetSocketAddress sockAddr = new InetSocketAddress(
230: remoteHost, port);
231: if (localBindAddress == null)
232: sock.connect(sockAddr);
233: else {
234: InetSocketAddress bindAddr = new InetSocketAddress(
235: localBindAddress, 0);
236: sock.bind(bindAddr);
237: sock.connect(sockAddr);
238: }
239: sock.setSoTimeout(10000);
240: sock.startHandshake();
241: connectedClient = sock;
242: } else {
243: if (localBindAddress == null)
244: connectedClient = new Socket(remoteHost, port);
245: else
246: connectedClient = new Socket(remoteHost, port,
247: localBindAddress, 0);
248: }
249: result = TcpipSocket.getInstance(endpoint, connectedClient);
250: return result;
251: }
252: }
253:
254: /*
255: * Thread main method
256: */
257: public void run() {
258: while (isRunning) {
259: TcpipSocket newSocket = null;
260: try {
261: newSocket = manager.getSocket();
262: } catch (Exception e) {
263: logger.error("Exception getting a socket \n"
264: + endpoint.getService()
265: + endpoint.getEndpoint() + "\n" + e);
266: if (isRunning) {
267: logger.error("retry in 10 seconds");
268: try {
269: sleep(10000);
270: } catch (InterruptedException ie) {
271: ErrorUtil.printError("Exception in run(): ", e);
272: }
273: }
274: }
275: if (newSocket != null) {
276: endpoint.addSocket(newSocket);
277: if (endpoint.getSocketCount() >= maxSockets) {
278: try {
279: manager.stop();
280: } catch (Exception e) {
281: ErrorUtil.printError(
282: "error stopping the manager", e);
283: logger.debug("error stopping the manager" + e,
284: e);
285: }
286: break;
287: }
288: }
289: }
290: endpoint.clearSocketManager();
291: }
292:
293: private SSLContext getSslContext() {
294: SSLContext ctx = null;
295: try {
296: ctx = SSLContext.getInstance(endpoint.getConfig()
297: .getSslProtocol());
298: // get the private key
299: KeyManager[] km = null;
300: if (endpoint.getConfig().isUsePrivateKey()) {
301: KeyStore ks = KeyStore.getInstance("JKS");
302: KeyManagerFactory kmf = KeyManagerFactory
303: .getInstance("SunX509");
304: String keyStorePath = EsbPathHelper
305: .getFullPathForDef(endpoint.getConfig()
306: .getKeyStoreFile());
307: char[] keyStorePassword = endpoint.getConfig()
308: .getKeyStorePassword().toCharArray();
309: FileInputStream kstr = new FileInputStream(keyStorePath);
310: ks.load(kstr, keyStorePassword);
311: kmf.init(ks, keyStorePassword);
312: km = kmf.getKeyManagers();
313: }
314: // get the trust store
315: TrustManager[] tm = null;
316: if ((endpoint.getConfig().isAuthenticateServer() || endpoint
317: .getConfig().isAuthenticateClient())) {
318: if (!endpoint.getConfig().isUseDefaultTrustStore()) {
319: TrustManagerFactory tmf = TrustManagerFactory
320: .getInstance("SunX509");
321: KeyStore ks = KeyStore.getInstance("JKS");
322: String trustStorePath = EsbPathHelper
323: .getFullPathForDef(endpoint.getConfig()
324: .getTrustStoreFile());
325: FileInputStream tstr = new FileInputStream(
326: trustStorePath);
327: ks.load(tstr, null);
328: tmf.init(ks);
329: tm = tmf.getTrustManagers();
330: }
331: } else {
332: // trust anyone for unauthenticated
333: TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
334:
335: public java.security.cert.X509Certificate[] getAcceptedIssuers() {
336: return null;
337: }
338:
339: public void checkClientTrusted(
340: java.security.cert.X509Certificate[] certs,
341: String authType) {
342: //No need to implement.
343: }
344:
345: public void checkServerTrusted(
346: java.security.cert.X509Certificate[] certs,
347: String authType) {
348: //No need to implement.
349: }
350: } };
351: tm = trustAllCerts;
352: }
353: // initialize the SSLContext
354: ctx.init(km, tm, null);
355: } catch (Exception e) {
356: ErrorUtil.printError("error getting SSL context ", e);
357: endpoint
358: .setState("Error", "error getting SSL context " + e);
359: ctx = null;
360: }
361: return ctx;
362: }
363: }
|