001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.servicemix.components.http;
018:
019: import java.io.IOException;
020: import java.net.InetAddress;
021: import java.net.InetSocketAddress;
022: import java.net.Socket;
023: import java.net.SocketAddress;
024: import java.net.URI;
025: import java.net.URL;
026: import java.net.UnknownHostException;
027: import java.security.KeyStore;
028:
029: import javax.jbi.JBIException;
030: import javax.jbi.messaging.MessageExchange;
031: import javax.jbi.messaging.MessagingException;
032: import javax.jbi.messaging.NormalizedMessage;
033: import javax.net.ssl.KeyManagerFactory;
034: import javax.net.ssl.SSLContext;
035: import javax.net.ssl.SSLSocketFactory;
036: import javax.net.ssl.TrustManagerFactory;
037:
038: import org.apache.commons.httpclient.ConnectTimeoutException;
039: import org.apache.commons.httpclient.HostConfiguration;
040: import org.apache.commons.httpclient.HttpClient;
041: import org.apache.commons.httpclient.HttpHost;
042: import org.apache.commons.httpclient.HttpStatus;
043: import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
044: import org.apache.commons.httpclient.methods.PostMethod;
045: import org.apache.commons.httpclient.params.HttpConnectionParams;
046: import org.apache.commons.httpclient.protocol.Protocol;
047: import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
048: import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
049: import org.apache.servicemix.MessageExchangeListener;
050: import org.apache.servicemix.components.util.TransformComponentSupport;
051: import org.mortbay.resource.Resource;
052: import org.springframework.core.io.ClassPathResource;
053:
054: /**
055: * Performs HTTP client invocations on a remote HTTP site.
056: *
057: * @version $Revision: 373823 $
058: */
059: public class HttpsInvoker extends TransformComponentSupport implements
060: MessageExchangeListener {
061:
062: protected HttpClientMarshaler marshaler = new HttpClientMarshaler();
063: protected MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
064: protected HttpClient httpClient = new HttpClient(connectionManager);
065: protected HostConfiguration hostConfiguration = new HostConfiguration();
066: protected String url;
067: protected boolean defaultInOut = true;
068:
069: private String keyPassword;
070: private String keyStore;
071: private String keyStorePassword;
072: private String keyStoreType = "JKS"; // type of the key store
073: private String trustStore;
074: private String trustStorePassword;
075: private String trustStoreType = "JKS";
076: private String protocol = "TLS";
077: private String algorithm = "SunX509"; // cert algorithm
078:
079: private class CommonsHttpSSLSocketFactory implements
080: SecureProtocolSocketFactory {
081:
082: private SSLSocketFactory factory;
083:
084: public CommonsHttpSSLSocketFactory() throws Exception {
085: SSLContext context = SSLContext.getInstance(protocol);
086: KeyManagerFactory keyManagerFactory = KeyManagerFactory
087: .getInstance(algorithm);
088: if (keyStore == null) {
089: keyStore = System.getProperty("javax.net.ssl.keyStore");
090: if (keyStore == null) {
091: throw new IllegalArgumentException(
092: "keyStore or system property javax.net.ssl.keyStore must be set");
093: }
094: }
095: if (keyStore.startsWith("classpath:")) {
096: try {
097: String res = keyStore.substring(10);
098: URL url = new ClassPathResource(res).getURL();
099: keyStore = url.toString();
100: } catch (IOException e) {
101: throw new JBIException("Unable to find keyStore "
102: + keyStore, e);
103: }
104: }
105: if (keyStorePassword == null) {
106: keyStorePassword = System
107: .getProperty("javax.net.ssl.keyStorePassword");
108: if (keyStorePassword == null) {
109: throw new IllegalArgumentException(
110: "keyStorePassword or system property javax.net.ssl.keyStorePassword must be set");
111: }
112: }
113: if (trustStore == null) {
114: trustStore = System
115: .getProperty("javax.net.ssl.trustStore");
116: }
117: if (trustStore != null
118: && trustStore.startsWith("classpath:")) {
119: try {
120: String res = trustStore.substring(10);
121: URL url = new ClassPathResource(res).getURL();
122: trustStore = url.toString();
123: } catch (IOException e) {
124: throw new JBIException("Unable to find trustStore "
125: + trustStore, e);
126: }
127: }
128: if (trustStorePassword == null) {
129: trustStorePassword = System
130: .getProperty("javax.net.ssl.trustStorePassword");
131: if (keyStorePassword == null) {
132: throw new IllegalArgumentException(
133: "trustStorePassword or system property javax.net.ssl.trustStorePassword must be set");
134: }
135: }
136: KeyStore ks = KeyStore.getInstance(keyStoreType);
137: ks.load(Resource.newResource(keyStore).getInputStream(),
138: keyStorePassword.toCharArray());
139: keyManagerFactory.init(ks,
140: keyPassword != null ? keyPassword.toCharArray()
141: : keyStorePassword.toCharArray());
142: if (trustStore != null) {
143: KeyStore ts = KeyStore.getInstance(trustStoreType);
144: ts.load(Resource.newResource(trustStore)
145: .getInputStream(), trustStorePassword
146: .toCharArray());
147: TrustManagerFactory trustManagerFactory = TrustManagerFactory
148: .getInstance(algorithm);
149: trustManagerFactory.init(ts);
150: context.init(keyManagerFactory.getKeyManagers(),
151: trustManagerFactory.getTrustManagers(),
152: new java.security.SecureRandom());
153: } else {
154: context.init(keyManagerFactory.getKeyManagers(), null,
155: new java.security.SecureRandom());
156: }
157: factory = context.getSocketFactory();
158: }
159:
160: public Socket createSocket(Socket socket, String host,
161: int port, boolean autoClose) throws IOException,
162: UnknownHostException {
163: return factory.createSocket(socket, host, port, autoClose);
164: }
165:
166: public Socket createSocket(String host, int port,
167: InetAddress localAddress, int localPort)
168: throws IOException, UnknownHostException {
169: return factory.createSocket(host, port, localAddress,
170: localPort);
171: }
172:
173: public Socket createSocket(String host, int port,
174: InetAddress localAddress, int localPort,
175: HttpConnectionParams params) throws IOException,
176: UnknownHostException, ConnectTimeoutException {
177: if (params == null) {
178: throw new IllegalArgumentException(
179: "Parameters may not be null");
180: }
181: int timeout = params.getConnectionTimeout();
182: if (timeout == 0) {
183: return createSocket(host, port, localAddress, localPort);
184: } else {
185: Socket socket = factory.createSocket();
186: SocketAddress localaddr = new InetSocketAddress(
187: localAddress, localPort);
188: SocketAddress remoteaddr = new InetSocketAddress(host,
189: port);
190: socket.bind(localaddr);
191: socket.connect(remoteaddr, timeout);
192: return socket;
193: }
194: }
195:
196: public Socket createSocket(String host, int port)
197: throws IOException, UnknownHostException {
198: return factory.createSocket(host, port);
199: }
200:
201: }
202:
203: protected void init() throws JBIException {
204: super .init();
205: try {
206: URI uri = new URI(url);
207: ProtocolSocketFactory sf = new CommonsHttpSSLSocketFactory();
208: Protocol protocol = new Protocol("https", sf, 443);
209: HttpHost host = new HttpHost(uri.getHost(), uri.getPort(),
210: protocol);
211: hostConfiguration.setHost(host);
212: } catch (Exception e) {
213: throw new JBIException("Unable to initialize HttpsInvoker",
214: e);
215: }
216: }
217:
218: public void stop() throws JBIException {
219: super .stop();
220: connectionManager.shutdown();
221: }
222:
223: protected boolean transform(MessageExchange exchange,
224: NormalizedMessage in, NormalizedMessage out)
225: throws MessagingException {
226: String url;
227: // We need to relativize the method url to the host config
228: // so that the hostConfiguration is not overriden by the executeMethod call
229: try {
230: java.net.URI uri = new URI(this .url);
231: uri = uri
232: .relativize(new URI(hostConfiguration.getHostURL()));
233: url = uri.toString();
234: } catch (Exception e1) {
235: url = this .url;
236: }
237: PostMethod method = new PostMethod(url);
238: try {
239: marshaler.fromNMS(method, exchange, in);
240: if (method.getRequestHeader("Content-Type") == null) {
241: method.setRequestHeader("Content-Type",
242: "text/html; charset=UTF-8");
243: }
244: int response = httpClient.executeMethod(hostConfiguration,
245: method);
246:
247: if (response != HttpStatus.SC_OK
248: && response != HttpStatus.SC_ACCEPTED) {
249: throw new InvalidStatusResponseException(response);
250: }
251:
252: // now lets grab the output and set it on the out message
253: if (defaultInOut) {
254: marshaler.toNMS(out, method);
255: }
256: return defaultInOut;
257: } catch (Exception e) {
258: throw new MessagingException(
259: "Error executing http request", e);
260: } finally {
261: method.releaseConnection();
262: }
263: }
264:
265: public HttpClient getHttpClient() {
266: return httpClient;
267: }
268:
269: public void setHttpClient(HttpClient httpClient) {
270: this .httpClient = httpClient;
271: }
272:
273: public String getUrl() {
274: return url;
275: }
276:
277: public void setUrl(String url) {
278: this .url = url;
279: }
280:
281: public boolean isDefaultInOut() {
282: return defaultInOut;
283: }
284:
285: public void setDefaultInOut(boolean defaultInOut) {
286: this .defaultInOut = defaultInOut;
287: }
288:
289: public HttpClientMarshaler getMarshaler() {
290: return marshaler;
291: }
292:
293: public void setMarshaler(HttpClientMarshaler marshaler) {
294: this .marshaler = marshaler;
295: }
296:
297: /**
298: * @return Returns the algorithm.
299: */
300: public String getAlgorithm() {
301: return algorithm;
302: }
303:
304: /**
305: * @param algorithm The algorithm to set.
306: */
307: public void setAlgorithm(String algorithm) {
308: this .algorithm = algorithm;
309: }
310:
311: /**
312: * @return Returns the keyPassword.
313: */
314: public String getKeyPassword() {
315: return keyPassword;
316: }
317:
318: /**
319: * @param keyPassword The keyPassword to set.
320: */
321: public void setKeyPassword(String keyPassword) {
322: this .keyPassword = keyPassword;
323: }
324:
325: /**
326: * @return Returns the keyStore.
327: */
328: public String getKeyStore() {
329: return keyStore;
330: }
331:
332: /**
333: * @param keyStore The keyStore to set.
334: */
335: public void setKeyStore(String keyStore) {
336: this .keyStore = keyStore;
337: }
338:
339: /**
340: * @return Returns the keyStorePassword.
341: */
342: public String getKeyStorePassword() {
343: return keyStorePassword;
344: }
345:
346: /**
347: * @param keyStorePassword The keyStorePassword to set.
348: */
349: public void setKeyStorePassword(String keyStorePassword) {
350: this .keyStorePassword = keyStorePassword;
351: }
352:
353: /**
354: * @return Returns the keyStoreType.
355: */
356: public String getKeyStoreType() {
357: return keyStoreType;
358: }
359:
360: /**
361: * @param keyStoreType The keyStoreType to set.
362: */
363: public void setKeyStoreType(String keyStoreType) {
364: this .keyStoreType = keyStoreType;
365: }
366:
367: /**
368: * @return Returns the protocol.
369: */
370: public String getProtocol() {
371: return protocol;
372: }
373:
374: /**
375: * @param protocol The protocol to set.
376: */
377: public void setProtocol(String protocol) {
378: this .protocol = protocol;
379: }
380:
381: /**
382: * @return Returns the trustStore.
383: */
384: public String getTrustStore() {
385: return trustStore;
386: }
387:
388: /**
389: * @param trustStore The trustStore to set.
390: */
391: public void setTrustStore(String trustStore) {
392: this .trustStore = trustStore;
393: }
394:
395: /**
396: * @return Returns the trustStorePassword.
397: */
398: public String getTrustStorePassword() {
399: return trustStorePassword;
400: }
401:
402: /**
403: * @param trustStorePassword The trustStorePassword to set.
404: */
405: public void setTrustStorePassword(String trustStorePassword) {
406: this .trustStorePassword = trustStorePassword;
407: }
408:
409: /**
410: * @return Returns the trustStoreType.
411: */
412: public String getTrustStoreType() {
413: return trustStoreType;
414: }
415:
416: /**
417: * @param trustStoreType The trustStoreType to set.
418: */
419: public void setTrustStoreType(String trustStoreType) {
420: this.trustStoreType = trustStoreType;
421: }
422:
423: }
|