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: HttpProviderProcessor.java 12068 2008-02-22 15:07:09Z mpreston $
023: */
024: package com.bostechcorp.cbesb.runtime.component.http.processors;
025:
026: import java.io.ByteArrayInputStream;
027: import java.io.ByteArrayOutputStream;
028: import java.io.InputStream;
029: import java.net.ConnectException;
030: import java.net.URL;
031: import java.util.Iterator;
032:
033: import javax.jbi.messaging.MessageExchange;
034: import javax.jbi.messaging.MessagingException;
035: import javax.jbi.messaging.NormalizedMessage;
036: import javax.jbi.messaging.RobustInOnly;
037: import javax.xml.namespace.QName;
038: import javax.xml.parsers.DocumentBuilder;
039: import javax.xml.parsers.DocumentBuilderFactory;
040: import javax.xml.transform.Source;
041: import javax.xml.transform.Transformer;
042: import javax.xml.transform.TransformerFactory;
043: import javax.xml.transform.dom.DOMSource;
044: import javax.xml.transform.stream.StreamResult;
045:
046: import org.apache.commons.httpclient.ConnectTimeoutException;
047: import org.apache.commons.httpclient.Header;
048: import org.apache.commons.httpclient.HostConfiguration;
049: import org.apache.commons.httpclient.HttpClient;
050: import org.apache.commons.httpclient.HttpMethod;
051: import org.apache.commons.httpclient.HttpStatus;
052: import org.apache.commons.httpclient.auth.CredentialsProvider;
053: import org.apache.commons.httpclient.methods.GetMethod;
054: import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
055: import org.apache.commons.httpclient.methods.PostMethod;
056: import org.apache.commons.httpclient.methods.PutMethod;
057: import org.apache.commons.httpclient.protocol.Protocol;
058: import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
059: import org.w3c.dom.Document;
060:
061: import com.bostechcorp.cbesb.common.runtime.CbesbException;
062: import com.bostechcorp.cbesb.common.runtime.DataContentException;
063: import com.bostechcorp.cbesb.common.runtime.ResourcesConnectionException;
064: import com.bostechcorp.cbesb.runtime.ccsl.jbi.messaging.CbProviderProcessor;
065: import com.bostechcorp.cbesb.runtime.ccsl.lib.IHttpHeader;
066: import com.bostechcorp.cbesb.runtime.ccsl.lib.IHttpProviderMarshaller;
067: import com.bostechcorp.cbesb.runtime.ccsl.lib.IHttpRequest;
068: import com.bostechcorp.cbesb.runtime.ccsl.lib.IHttpResponse;
069: import com.bostechcorp.cbesb.runtime.ccsl.nmhandler.ByteArraySource;
070: import com.bostechcorp.cbesb.runtime.ccsl.nmhandler.StringSource;
071: import com.bostechcorp.cbesb.runtime.component.http.HttpEndpoint;
072: import com.bostechcorp.cbesb.runtime.component.http.client.AuthSSLProtocolSocketFactory;
073: import com.bostechcorp.cbesb.runtime.component.http.client.HttpClientCredentialsProvider;
074: import com.bostechcorp.cbesb.runtime.component.http.client.HttpRequestImpl;
075: import com.bostechcorp.cbesb.runtime.component.http.client.HttpResponseImpl;
076:
077: public class HttpProviderProcessor extends CbProviderProcessor {
078:
079: private HttpEndpoint endpoint;
080: private HttpClientCredentialsProvider httpCredentialsProvider;
081: private AuthSSLProtocolSocketFactory sslProtocolSocketFactory;
082: private Protocol httpsProtocol;
083: private IHttpProviderMarshaller marshaller;
084:
085: protected static final String PROTOCOL_HTTP = "http";
086: protected static final String PROTOCOL_HTTPS = "https";
087:
088: /**
089: * @param endpoint
090: */
091: public HttpProviderProcessor(HttpEndpoint endpoint) {
092: super (endpoint);
093: this .endpoint = endpoint;
094: marshaller = endpoint.getHttpProviderMarshaller();
095:
096: httpCredentialsProvider = new HttpClientCredentialsProvider();
097: if (endpoint.getAuthMode() != null) {
098: httpCredentialsProvider.setUsernamePassword(endpoint
099: .getAuthUser(), endpoint.getAuthPassword());
100: }
101:
102: sslProtocolSocketFactory = new AuthSSLProtocolSocketFactory(
103: endpoint);
104: httpsProtocol = new Protocol("https",
105: (ProtocolSocketFactory) sslProtocolSocketFactory, 443);
106:
107: }
108:
109: /*
110: * (non-Javadoc)
111: *
112: * @see com.bostechcorp.cbesb.runtime.ccsl.jbi.messaging.CbProviderProcessor#processInMessage(javax.xml.namespace.QName,
113: * javax.xml.namespace.QName, javax.jbi.messaging.NormalizedMessage,
114: * javax.jbi.messaging.MessageExchange)
115: */
116: @Override
117: protected void processInMessage(QName service, QName operation,
118: NormalizedMessage in, MessageExchange exchange)
119: throws Exception {
120: IHttpRequest request;
121: try {
122: request = createRequest(in, exchange);
123: } catch (MessagingException e) {
124: String msg = "Exception converting NormalizedMessage into Http Request - "
125: + e.getMessage();
126: if (exchange instanceof RobustInOnly) {
127: DataContentException dce = new DataContentException(
128: msg, e);
129: dce
130: .setRemedy("Check that the message content is valid.");
131: endpoint.createFault(dce, exchange);
132: } else {
133: logger.error(msg, e);
134: }
135: return;
136: }
137:
138: try {
139: IHttpResponse response = executeRequest(request);
140: if (response.getStatusCode() != 200) {
141: String msg = "Http call returned error code: "
142: + response.getStatusCode() + " - "
143: + response.getStatusDescription();
144: DataContentException dce = new DataContentException(msg);
145: throw dce;
146: }
147: } catch (CbesbException e) {
148: if (exchange instanceof RobustInOnly) {
149: endpoint.createFault(e, exchange);
150: } else {
151: logger.error(e.getMessage(), e);
152: }
153: }
154:
155: }
156:
157: /*
158: * (non-Javadoc)
159: *
160: * @see com.bostechcorp.cbesb.runtime.ccsl.jbi.messaging.CbProviderProcessor#processInOutMessage(javax.xml.namespace.QName,
161: * javax.xml.namespace.QName, javax.jbi.messaging.NormalizedMessage,
162: * javax.jbi.messaging.NormalizedMessage, boolean,
163: * javax.jbi.messaging.MessageExchange)
164: */
165: @Override
166: protected boolean processInOutMessage(QName service,
167: QName operation, NormalizedMessage in,
168: NormalizedMessage out, boolean optionalOut,
169: MessageExchange exchange) throws Exception {
170: IHttpRequest request;
171: try {
172: request = createRequest(in, exchange);
173: } catch (MessagingException e) {
174: String msg = "Exception converting NormalizedMessage into Http Request - "
175: + e.getMessage();
176: DataContentException dce = new DataContentException(msg, e);
177: dce.setRemedy("Check that the message content is valid.");
178: endpoint.createFault(dce, exchange);
179:
180: return false;
181: }
182:
183: try {
184: IHttpResponse response = executeRequest(request);
185: if (response.getStatusCode() != 200) {
186: String msg = "Http call returned error code: "
187: + response.getStatusCode() + " - "
188: + response.getStatusDescription();
189: DataContentException dce = new DataContentException(msg);
190: throw dce;
191: }
192:
193: marshaller.HttpResponseToNormalizedMessage(response, out,
194: exchange, endpoint.getSvcDescHandler());
195:
196: return true;
197:
198: } catch (CbesbException e) {
199: endpoint.createFault(e, exchange);
200: return false;
201:
202: } catch (MessagingException e) {
203: String msg = "Exception converting Http Response into NormalizedMessage - "
204: + e.getMessage();
205: DataContentException dce = new DataContentException(msg, e);
206: endpoint.createFault(dce, exchange);
207:
208: return false;
209: }
210: }
211:
212: protected IHttpRequest createRequest(NormalizedMessage in,
213: MessageExchange exchange) throws MessagingException {
214: IHttpRequest request = new HttpRequestImpl();
215: request.setURL(endpoint.getLocationURI());
216: marshaller
217: .NormalizedMessageToHttpRequest(in, request, exchange);
218: return request;
219: }
220:
221: protected IHttpResponse executeRequest(IHttpRequest request)
222: throws CbesbException {
223: IHttpResponse response = new HttpResponseImpl();
224: HttpMethod httpMethod = null;
225: HostConfiguration hostConfig;
226: try {
227: hostConfig = getHostConfiguration(request);
228: if (request.getMethod() == IHttpRequest.METHOD_GET) {
229: httpMethod = createGetMethod(request);
230: } else if (request.getMethod() == IHttpRequest.METHOD_POST) {
231: httpMethod = createPostMethod(request);
232: } else {
233: httpMethod = createPutMethod(request);
234: }
235: } catch (Exception e) {
236: String msg = "Exception creating HTTP request - "
237: + e.getMessage();
238: DataContentException dce = new DataContentException(msg, e);
239: throw dce;
240: }
241:
242: try {
243: HttpClient httpClient = new HttpClient();
244: if (endpoint.getTimeout() > 0) {
245: httpClient.getHttpConnectionManager().getParams()
246: .setSoTimeout(endpoint.getTimeout());
247: }
248:
249: httpClient.getParams().setParameter(
250: CredentialsProvider.PROVIDER,
251: httpCredentialsProvider);
252:
253: httpMethod.setDoAuthentication(true);
254:
255: if (endpoint.getProxyHost() != null
256: && endpoint.getProxyPort() != null) {
257: httpClient.getHostConfiguration().setProxy(
258: endpoint.getProxyHost(),
259: Integer.parseInt(endpoint.getProxyPort()));
260: if (endpoint.getProxyUser() != null) {
261: httpCredentialsProvider.setProxyUsernamePassword(
262: endpoint.getProxyUser(), endpoint
263: .getProxyPassword());
264: }
265: }
266:
267: httpClient.setHostConfiguration(hostConfig);
268: int statusCode = httpClient.executeMethod(httpMethod);
269: response.setStatusCode(statusCode);
270: response.setStatusDescription(HttpStatus
271: .getStatusText(statusCode));
272:
273: Header[] headers = httpMethod.getResponseHeaders();
274: String contentType = null;
275: for (int i = 0; i < headers.length; i++) {
276: response.createHeader(headers[i].getName(), headers[i]
277: .getValue());
278: if (headers[i].getName().startsWith("Content-Type")) {
279: contentType = headers[i].getValue();
280: }
281: }
282: if (contentType.startsWith("text/xml")) {
283: DocumentBuilderFactory dbf = DocumentBuilderFactory
284: .newInstance();
285: dbf.setNamespaceAware(true);
286: DocumentBuilder db = dbf.newDocumentBuilder();
287: Document doc = db.parse(httpMethod
288: .getResponseBodyAsStream());
289: response.setBody(new DOMSource(doc));
290:
291: } else if (contentType.startsWith("text")) {
292: response.setBody(new StringSource(httpMethod
293: .getResponseBodyAsString()));
294:
295: } else {
296: response.setBody(new ByteArraySource(httpMethod
297: .getResponseBody()));
298: }
299:
300: } catch (ConnectTimeoutException e) {
301: String msg = "Exception executing HTTP request - "
302: + e.getMessage();
303: ResourcesConnectionException rce = new ResourcesConnectionException(
304: msg, e);
305: rce
306: .setRemedy("Provide a larger timeout interval and verify that the server is operating correctly.");
307: throw rce;
308:
309: } catch (ConnectException e) {
310: String msg = "Exception executing HTTP request - "
311: + e.getMessage();
312: ResourcesConnectionException rce = new ResourcesConnectionException(
313: msg, e);
314: rce
315: .setRemedy("Verify the URL is correct and that the server is up.");
316: throw rce;
317:
318: } catch (Exception e) {
319: String msg = "Exception executing HTTP request - "
320: + e.getMessage();
321: DataContentException dce = new DataContentException(msg, e);
322: throw dce;
323:
324: } finally {
325: httpMethod.releaseConnection();
326: }
327:
328: return response;
329: }
330:
331: protected HostConfiguration getHostConfiguration(
332: IHttpRequest request) throws Exception {
333: HostConfiguration config = new HostConfiguration();
334:
335: URL url = new URL(request.getURL());
336: int port = url.getPort();
337: String protocol = url.getProtocol();
338: if (port == -1) {
339: if (PROTOCOL_HTTP.equals(protocol)) {
340: port = 80;
341: } else if (PROTOCOL_HTTPS.equals(protocol)) {
342: port = 443;
343: }
344: }
345: if (PROTOCOL_HTTPS.equals(protocol)) {
346: config.setHost(url.getHost(), port, httpsProtocol);
347: } else {
348: config.setHost(url.getHost(), port, protocol);
349: }
350:
351: return config;
352: }
353:
354: protected PostMethod createPostMethod(IHttpRequest request)
355: throws Exception {
356: URL url = new URL(request.getURL());
357: PostMethod method = new PostMethod(url.getPath());
358: setHeaders(method, request);
359: Source src = request.getBody();
360: method.setRequestEntity(new InputStreamRequestEntity(
361: SourceToInputStream(src)));
362:
363: return method;
364: }
365:
366: protected PutMethod createPutMethod(IHttpRequest request)
367: throws Exception {
368: URL url = new URL(request.getURL());
369: PutMethod method = new PutMethod(url.getPath());
370: setHeaders(method, request);
371: method.setRequestEntity(new InputStreamRequestEntity(
372: SourceToInputStream(request.getBody())));
373: return method;
374: }
375:
376: protected GetMethod createGetMethod(IHttpRequest request)
377: throws Exception {
378: URL url = new URL(request.getURL());
379: GetMethod method = new GetMethod(url.getPath());
380: setHeaders(method, request);
381: return method;
382: }
383:
384: protected void setHeaders(HttpMethod method, IHttpRequest request) {
385: Iterator iter = request.getHeaders().iterator();
386: boolean setContentType = false;
387:
388: while (iter.hasNext()) {
389: IHttpHeader header = (IHttpHeader) iter.next();
390: method
391: .addRequestHeader(header.getName(), header
392: .getValue());
393: if ("Content-Type".equals(header.getName())) {
394: setContentType = true;
395: }
396: }
397: if (!setContentType) {
398: Source body = request.getBody();
399: if (body != null
400: && request.getMethod() != IHttpRequest.METHOD_GET) {
401: method.addRequestHeader("Content-Type",
402: getContentTypeFromSource(body));
403: }
404: }
405: }
406:
407: protected String getContentTypeFromSource(Source source) {
408: if (source instanceof StringSource) {
409: return "text/plain";
410: } else if (source instanceof ByteArraySource) {
411: return "application/octet-stream";
412: } else {
413: return "text/xml";
414: }
415:
416: }
417:
418: protected InputStream SourceToInputStream(Source source)
419: throws Exception {
420: if (source instanceof StringSource) {
421: return ((StringSource) source).getInputStream();
422:
423: } else if (source instanceof ByteArraySource) {
424: return ((ByteArraySource) source).getInputStream();
425:
426: } else {
427: ByteArrayOutputStream baos = new ByteArrayOutputStream();
428: StreamResult streamResult = new StreamResult(baos);
429: TransformerFactory factory = TransformerFactory
430: .newInstance();
431: Transformer transformer = factory.newTransformer();
432: transformer.setOutputProperty("encoding", "utf-8");
433: transformer.transform(source, streamResult);
434: return new ByteArrayInputStream(baos.toByteArray());
435: }
436: }
437:
438: }
|