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: SoapProviderProcessor.java 12068 2008-02-22 15:07:09Z mpreston $
023: */
024: package com.bostechcorp.cbesb.runtime.component.http.processors;
025:
026: import java.net.ConnectException;
027: import java.util.Iterator;
028: import java.util.List;
029: import java.util.Vector;
030:
031: import javax.jbi.messaging.MessageExchange;
032: import javax.jbi.messaging.MessagingException;
033: import javax.jbi.messaging.NormalizedMessage;
034: import javax.jbi.messaging.RobustInOnly;
035: import javax.wsdl.Binding;
036: import javax.wsdl.BindingOperation;
037: import javax.wsdl.Definition;
038: import javax.wsdl.Port;
039: import javax.wsdl.Service;
040: import javax.wsdl.extensions.ExtensibilityElement;
041: import javax.wsdl.extensions.soap.SOAPOperation;
042: import javax.wsdl.extensions.soap12.SOAP12Operation;
043: import javax.xml.namespace.QName;
044:
045: import org.apache.axiom.om.OMAbstractFactory;
046: import org.apache.axiom.soap.SOAPEnvelope;
047: import org.apache.axiom.soap.SOAPFactory;
048: import org.apache.axis2.AxisFault;
049: import org.apache.axis2.Constants;
050: import org.apache.axis2.addressing.EndpointReference;
051: import org.apache.axis2.client.OperationClient;
052: import org.apache.axis2.client.Options;
053: import org.apache.axis2.client.ServiceClient;
054: import org.apache.axis2.context.ConfigurationContext;
055: import org.apache.axis2.context.ConfigurationContextFactory;
056: import org.apache.axis2.context.MessageContext;
057: import org.apache.axis2.context.ServiceContext;
058: import org.apache.axis2.context.ServiceGroupContext;
059: import org.apache.axis2.description.AxisOperation;
060: import org.apache.axis2.description.AxisService;
061: import org.apache.axis2.description.AxisServiceGroup;
062: import org.apache.axis2.description.OutInAxisOperation;
063: import org.apache.axis2.description.OutOnlyAxisOperation;
064: import org.apache.axis2.transport.http.CommonsHTTPTransportSender;
065: import org.apache.axis2.transport.http.HTTPConstants;
066: import org.apache.axis2.transport.http.HttpTransportProperties.Authenticator;
067: import org.apache.axis2.transport.http.HttpTransportProperties.ProxyProperties;
068: import org.apache.axis2.util.threadpool.ThreadPool;
069: import org.apache.axis2.wsdl.WSDLConstants;
070: import org.apache.commons.httpclient.HttpClient;
071: import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
072: import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
073: import org.apache.commons.httpclient.protocol.Protocol;
074: import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
075:
076: import com.bostechcorp.cbesb.common.constant.MetadataConstants;
077: import com.bostechcorp.cbesb.common.runtime.DataContentException;
078: import com.bostechcorp.cbesb.common.runtime.ResourcesConnectionException;
079: import com.bostechcorp.cbesb.runtime.ccsl.jbi.messaging.CbProviderProcessor;
080: import com.bostechcorp.cbesb.runtime.ccsl.lib.ISoapProviderMarshaller;
081: import com.bostechcorp.cbesb.runtime.component.http.HttpEndpoint;
082: import com.bostechcorp.cbesb.runtime.component.http.client.AuthSSLProtocolSocketFactory;
083:
084: public class SoapProviderProcessor extends CbProviderProcessor {
085:
086: protected static final int DEFAULT_TIMEOUT = 30000; //30 seconds
087: protected static final String SOAP_11_ENVELOPE_NS = "http://schemas.xmlsoap.org/soap/envelope/";
088: protected static final String SOAP_12_ENVELOPE_NS = "http://www.w3.org/2003/05/soap-envelope";
089:
090: protected static final QName IN_ONLY_OPERATION = new QName(
091: "http://cbesb.bostechcorp.com/wsdl/http/1.0",
092: "InOnlyOperation");
093: protected static final QName IN_OUT_OPERATION = new QName(
094: "http://cbesb.bostechcorp.com/wsdl/http/1.0",
095: "InOutOperation");
096:
097: protected HttpEndpoint endpoint;
098:
099: protected ConfigurationContext configContext;
100: protected AxisService axisService;
101: protected ServiceContext serviceContext;
102: protected ServiceClient serviceClient;
103: protected ISoapProviderMarshaller marshaller;
104: private AuthSSLProtocolSocketFactory sslProtocolSocketFactory;
105: private Protocol httpsProtocol;
106:
107: /**
108: * @param endpoint
109: */
110: public SoapProviderProcessor(HttpEndpoint endpoint) {
111: super (endpoint);
112: this .endpoint = endpoint;
113:
114: sslProtocolSocketFactory = new AuthSSLProtocolSocketFactory(
115: endpoint);
116: httpsProtocol = new Protocol("https",
117: (ProtocolSocketFactory) sslProtocolSocketFactory, 443);
118:
119: initializeAxis();
120:
121: marshaller = endpoint.getSoapProviderMarshaller();
122: }
123:
124: protected void initializeAxis() {
125: try {
126: MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
127: HttpConnectionManagerParams connectionManagerParams = new HttpConnectionManagerParams();
128: connectionManagerParams.setDefaultMaxConnectionsPerHost(10);
129: connectionManagerParams.setTcpNoDelay(true);
130: connectionManagerParams.setStaleCheckingEnabled(true);
131: connectionManagerParams.setLinger(0);
132: connectionManagerParams.setSoTimeout(endpoint.getTimeout());
133: connectionManager.setParams(connectionManagerParams);
134: HttpClient httpClient = new HttpClient(connectionManager);
135:
136: QName scvName = endpoint.getService();
137: AxisServiceGroup axisServiceGroup = new AxisServiceGroup();
138:
139: configContext = ConfigurationContextFactory
140: .createBasicConfigurationContext("META-INF/Axis2.xml");
141:
142: configContext.setThreadPool(new ThreadPool(1, 100));
143: configContext.setProperty(HTTPConstants.REUSE_HTTP_CLIENT,
144: Boolean.TRUE);
145: configContext.setProperty(HTTPConstants.CACHED_HTTP_CLIENT,
146: httpClient);
147:
148: axisService = new AxisService(scvName.toString());
149: axisServiceGroup.addService(axisService);
150: AxisOperation inOnlyOper = new OutOnlyAxisOperation(
151: IN_ONLY_OPERATION);
152: AxisOperation inOutOper = new OutInAxisOperation(
153: IN_OUT_OPERATION);
154: axisService.addOperation(inOnlyOper);
155: axisService.addOperation(inOutOper);
156: ServiceGroupContext sgc = configContext
157: .createServiceGroupContext(axisServiceGroup);
158: serviceContext = sgc.getServiceContext(axisService);
159: } catch (Exception e) {
160: logger.error("Unable to create Axis ServiceClient.", e);
161: }
162: }
163:
164: protected SOAPFactory getSoapFactory(Options options) {
165: if (options.getSoapVersionURI().equals(SOAP_12_ENVELOPE_NS)) {
166: return OMAbstractFactory.getSOAP12Factory();
167: } else {
168: return OMAbstractFactory.getSOAP11Factory();
169: }
170: }
171:
172: /* (non-Javadoc)
173: * @see com.bostechcorp.cbesb.runtime.ccsl.jbi.messaging.CbProviderProcessor#processInMessage(javax.xml.namespace.QName, javax.xml.namespace.QName, javax.jbi.messaging.NormalizedMessage, javax.jbi.messaging.MessageExchange)
174: */
175: @Override
176: protected void processInMessage(QName service, QName operation,
177: NormalizedMessage in, MessageExchange exchange)
178: throws Exception {
179:
180: Options options = createOptions(exchange);
181:
182: SOAPFactory soapFactory = getSoapFactory(options);
183:
184: try {
185: AxisOperation axisOperation = axisService
186: .getOperation(IN_ONLY_OPERATION);
187: OperationClient opClient = axisOperation.createClient(
188: serviceContext, options);
189:
190: MessageContext soapMsgContext = new MessageContext();
191: soapMsgContext.setServiceContext(serviceContext);
192: SOAPEnvelope envelope = soapFactory.getDefaultEnvelope();
193: soapMsgContext.setEnvelope(envelope);
194: opClient.addMessageContext(soapMsgContext);
195:
196: marshaller.NormalizedMessageToSoap(in, soapMsgContext,
197: exchange, soapFactory, endpoint.isUsingMTOM(),
198: endpoint.isUsingSwA());
199:
200: opClient.execute(true);
201:
202: CommonsHTTPTransportSender sender = (CommonsHTTPTransportSender) soapMsgContext
203: .getTransportOut().getSender();
204: sender.cleanup(soapMsgContext);
205:
206: } catch (AxisFault e) {
207: if (exchange instanceof RobustInOnly) {
208: if (e.getCause() instanceof ConnectException) {
209: ResourcesConnectionException connExc = new ResourcesConnectionException(
210: "Unable to connect to Web Service - "
211: + e.getMessage(), e);
212: connExc
213: .setRemedy("Check that web service is up and the URL is correct.");
214: endpoint.createRecoverableFault(connExc, exchange);
215: } else {
216: DataContentException dce = new DataContentException(
217: "AxisFault occurred while invoking web service - "
218: + e.getMessage(), e);
219: endpoint.createFault(dce, exchange);
220: }
221: } else {
222: logger.error(
223: "AxisFault occurred while invoking web service - "
224: + e.getMessage(), e);
225: }
226: } catch (MessagingException e) {
227: if (exchange instanceof RobustInOnly) {
228: DataContentException dce = new DataContentException(
229: "Messaging Exception occurred while invoking web service - "
230: + e.getMessage(), e);
231: endpoint.createFault(dce, exchange);
232: } else {
233: logger.error(
234: "Messaging Exception occurred while invoking web service - "
235: + e.getMessage(), e);
236: }
237: }
238:
239: }
240:
241: /* (non-Javadoc)
242: * @see com.bostechcorp.cbesb.runtime.ccsl.jbi.messaging.CbProviderProcessor#processInOutMessage(javax.xml.namespace.QName, javax.xml.namespace.QName, javax.jbi.messaging.NormalizedMessage, javax.jbi.messaging.NormalizedMessage, boolean, javax.jbi.messaging.MessageExchange)
243: */
244: @Override
245: protected boolean processInOutMessage(QName service,
246: QName operation, NormalizedMessage in,
247: NormalizedMessage out, boolean optionalOut,
248: MessageExchange exchange) throws Exception {
249:
250: boolean useOutMessage = true;
251: Options options = createOptions(exchange);
252:
253: SOAPFactory soapFactory = getSoapFactory(options);
254: MessageContext soapMsgContext = new MessageContext();
255:
256: try {
257:
258: AxisOperation axisOperation = axisService
259: .getOperation(IN_OUT_OPERATION);
260: OperationClient opClient = axisOperation.createClient(
261: serviceContext, options);
262:
263: soapMsgContext.setServiceContext(serviceContext);
264: SOAPEnvelope envelope = soapFactory.getDefaultEnvelope();
265: soapMsgContext.setEnvelope(envelope);
266:
267: opClient.addMessageContext(soapMsgContext);
268:
269: marshaller.NormalizedMessageToSoap(in, soapMsgContext,
270: exchange, soapFactory, endpoint.isUsingMTOM(),
271: endpoint.isUsingSwA());
272:
273: opClient.execute(true);
274:
275: MessageContext response = opClient
276: .getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
277: response.getEnvelope().build();
278:
279: marshaller.SoapToNormalizedMessage(response, out, exchange,
280: endpoint.getSvcDescHandler(), endpoint
281: .isUsingMTOM(), endpoint.isUsingSwA());
282:
283: } catch (AxisFault e) {
284: if (e.getCause() instanceof ConnectException) {
285: ResourcesConnectionException connExc = new ResourcesConnectionException(
286: "Unable to connect to Web Service - "
287: + e.getMessage(), e);
288: connExc
289: .setRemedy("Check that web service is up and the URL is correct.");
290: endpoint.createRecoverableFault(connExc, exchange);
291: } else {
292: DataContentException dce = new DataContentException(
293: "AxisFault occurred while invoking web service - "
294: + e.getMessage(), e);
295: endpoint.createFault(dce, exchange);
296: }
297: useOutMessage = false;
298: } catch (MessagingException e) {
299: DataContentException dce = new DataContentException(
300: "Messaging Exception occurred while invoking web service - "
301: + e.getMessage(), e);
302: endpoint.createFault(dce, exchange);
303: useOutMessage = false;
304: } catch (Exception e) {
305: logger.error(
306: "Exception occurred while invoking web service - "
307: + e.getMessage(), e);
308: endpoint.createFault(e, exchange);
309: useOutMessage = false;
310: } finally {
311: CommonsHTTPTransportSender sender = (CommonsHTTPTransportSender) soapMsgContext
312: .getTransportOut().getSender();
313: sender.cleanup(soapMsgContext);
314: }
315:
316: return useOutMessage;
317: }
318:
319: protected Options createOptions(MessageExchange exchange) {
320: Options options = new Options();
321:
322: //Get Address
323: String address = (String) exchange
324: .getProperty(MetadataConstants.HTTP_PROVIDER_ADDRESS);
325: if (address == null) {
326: address = endpoint.getLocationURI();
327: }
328: options.setTo(new EndpointReference(address));
329:
330: //Get SoapAction
331: String soapAction = (String) exchange
332: .getProperty(MetadataConstants.HTTP_PROVIDER_SOAPACTION);
333: if (soapAction != null) {
334: logger.debug("SoapAction found in metadata: " + soapAction);
335: options.setAction(soapAction);
336: } else {
337: QName operation = exchange.getOperation();
338: if (operation != null) {
339: soapAction = getSoapActionForOperation(operation);
340: logger.debug("Operation found in exchange: "
341: + operation + " soapAction: " + soapAction);
342: } else {
343: String opStr = (String) exchange
344: .getProperty(MetadataConstants.HTTP_PROVIDER_OPERATION);
345: if (opStr != null) {
346: soapAction = getSoapActionForOperation(opStr);
347: logger.debug("Operation found in metadata: "
348: + opStr + " soapAction: " + soapAction);
349: } else if (endpoint.getTargetOperation() != null) {
350: soapAction = getSoapActionForOperation(endpoint
351: .getTargetOperation());
352: logger.debug("Using default Operation: "
353: + endpoint.getTargetOperation()
354: + " soapAction: " + soapAction);
355: }
356: }
357: if (soapAction != null) {
358: if (soapAction.equals("")) {
359: soapAction = "\"\"";
360: }
361: options.setAction(soapAction);
362: }
363: }
364:
365: //Get Timeout
366: if (endpoint.getTimeout() == -1) {
367: options.setTimeOutInMilliSeconds(endpoint.getTimeout());
368: options.setProperty(HTTPConstants.SO_TIMEOUT, endpoint
369: .getTimeout());
370: options.setProperty(HTTPConstants.CONNECTION_TIMEOUT,
371: endpoint.getTimeout());
372: } else {
373: //Use default timeout
374: options.setTimeOutInMilliSeconds(DEFAULT_TIMEOUT);
375: options.setProperty(HTTPConstants.SO_TIMEOUT,
376: DEFAULT_TIMEOUT);
377: options.setProperty(HTTPConstants.CONNECTION_TIMEOUT,
378: DEFAULT_TIMEOUT);
379: }
380:
381: //Setup HTTP client options
382: options.setProperty(HTTPConstants.CHUNKED, Boolean.FALSE);
383: options.setProperty(HTTPConstants.REUSE_HTTP_CLIENT,
384: Boolean.TRUE);
385:
386: // Causes attempted read from unavailable stream error
387: // options.setProperty(HTTPConstants.AUTO_RELEASE_CONNECTION,
388: // Boolean.TRUE);
389:
390: //Get Soap Version
391: //Get Soap Version based on operation in wsdl
392: String operation = null;
393: QName operationQN = exchange.getOperation();
394: if (operationQN != null) {
395: operation = operationQN.getLocalPart();
396: } else {
397: String opStr = (String) exchange
398: .getProperty(MetadataConstants.HTTP_PROVIDER_OPERATION);
399: if (opStr != null) {
400: operation = opStr;
401: } else if (endpoint.getTargetOperation() != null) {
402: operation = endpoint.getTargetOperation();
403: }
404: }
405: options
406: .setSoapVersionURI(getSoapVersionUriForOperation(operation));
407:
408: //Get SSL
409: if (address.startsWith("https")) {
410: options.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER,
411: httpsProtocol);
412: options.setTransportInProtocol(Constants.TRANSPORT_HTTPS);
413: } else {
414: options.setTransportInProtocol(Constants.TRANSPORT_HTTP);
415:
416: }
417:
418: //Get Basic Auth Settings
419: if (endpoint.getAuthMode() != null
420: && endpoint.getAuthMode().equalsIgnoreCase("Basic")) {
421: Authenticator authenticator = new Authenticator();
422: Vector<String> authSchemes = new Vector<String>();
423: authSchemes.add(Authenticator.BASIC);
424: // authSchemes.add(Authenticator.DIGEST);
425: // authSchemes.add(Authenticator.NTLM);
426: authenticator.setAuthSchemes(authSchemes);
427: authenticator.setPreemptiveAuthentication(true);
428: authenticator.setUsername(endpoint.getAuthUser());
429: authenticator.setPassword(endpoint.getAuthPassword());
430: options.setProperty(HTTPConstants.AUTHENTICATE,
431: authenticator);
432: }
433:
434: //Get Proxy Settings
435: if (endpoint.getProxyHost() != null
436: && endpoint.getProxyPort() != null) {
437: ProxyProperties proxyProperties = new ProxyProperties();
438: proxyProperties.setProxyName(endpoint.getProxyHost());
439: proxyProperties.setProxyPort(Integer.parseInt(endpoint
440: .getProxyPort()));
441: if (endpoint.getProxyUser() != null) {
442: proxyProperties.setUserName(endpoint.getProxyUser());
443: }
444: if (endpoint.getProxyPassword() != null) {
445: proxyProperties
446: .setPassWord(endpoint.getProxyPassword());
447: }
448: options.setProperty(HTTPConstants.PROXY, proxyProperties);
449: }
450:
451: if (endpoint.isUsingMTOM()) {
452: configContext.setProperty(
453: Constants.Configuration.ENABLE_MTOM,
454: Constants.VALUE_TRUE);
455: configContext.setProperty(
456: Constants.Configuration.ENABLE_SWA,
457: Constants.VALUE_FALSE);
458: } else if (endpoint.isUsingSwA()) {
459: configContext.setProperty(
460: Constants.Configuration.ENABLE_MTOM,
461: Constants.VALUE_FALSE);
462: configContext.setProperty(
463: Constants.Configuration.ENABLE_SWA,
464: Constants.VALUE_TRUE);
465: } else {
466: configContext.setProperty(
467: Constants.Configuration.ENABLE_MTOM,
468: Constants.VALUE_FALSE);
469: configContext.setProperty(
470: Constants.Configuration.ENABLE_SWA,
471: Constants.VALUE_FALSE);
472: }
473:
474: return options;
475: }
476:
477: protected String getSoapActionForOperation(QName operation) {
478: return getSoapActionForOperation(operation.getLocalPart());
479: }
480:
481: protected String getSoapActionForOperation(String operation) {
482: Definition def = endpoint.getWsdlResourceAsDefinition();
483: String targetNS = def.getTargetNamespace();
484: QName targetService = new QName(targetNS, endpoint
485: .getTargetService());
486: Service svc = def.getService(targetService);
487: if (svc != null) {
488: Port port = svc.getPort(endpoint.getTargetPort());
489: if (port != null) {
490: Binding binding = port.getBinding();
491: List bindingOps = binding.getBindingOperations();
492: for (Iterator iter = bindingOps.iterator(); iter
493: .hasNext();) {
494: BindingOperation bindingOp = (BindingOperation) iter
495: .next();
496: if (bindingOp.getName().equals(operation)) {
497: List extElements = bindingOp
498: .getExtensibilityElements();
499: for (Iterator iter2 = extElements.iterator(); iter2
500: .hasNext();) {
501: ExtensibilityElement extElem = (ExtensibilityElement) iter2
502: .next();
503: if (extElem instanceof SOAPOperation) {
504: SOAPOperation soapOp = (SOAPOperation) extElem;
505: logger.debug("Found SoapAction: "
506: + soapOp.getSoapActionURI());
507: return soapOp.getSoapActionURI();
508: } else if (extElem instanceof SOAP12Operation) {
509: SOAP12Operation soapOp = (SOAP12Operation) extElem;
510: logger.debug("Found SoapAction: "
511: + soapOp.getSoapActionURI());
512: return soapOp.getSoapActionURI();
513: }
514: }
515: }
516: }
517: logger.debug("Did not find '" + operation
518: + "' operation in binding");
519: } else {
520: logger.debug("Did not find '"
521: + endpoint.getTargetPort()
522: + "' port in service");
523: }
524: } else {
525: logger.debug("Did not find '" + targetService
526: + "' service in definition");
527: }
528:
529: return null;
530: }
531:
532: private String getSoapVersionUriForOperation(String operation) {
533: Definition def = endpoint.getWsdlResourceAsDefinition();
534: String targetNS = def.getTargetNamespace();
535: QName targetService = new QName(targetNS, endpoint
536: .getTargetService());
537: Service svc = def.getService(targetService);
538: if (svc != null) {
539: Port port = svc.getPort(endpoint.getTargetPort());
540: if (port != null) {
541: Binding binding = port.getBinding();
542: List bindingOps = binding.getBindingOperations();
543: for (Iterator iter = bindingOps.iterator(); iter
544: .hasNext();) {
545: BindingOperation bindingOp = (BindingOperation) iter
546: .next();
547: if (bindingOp.getName().equals(operation)) {
548: List extElements = bindingOp
549: .getExtensibilityElements();
550: for (Iterator iter2 = extElements.iterator(); iter2
551: .hasNext();) {
552: ExtensibilityElement extElem = (ExtensibilityElement) iter2
553: .next();
554: if (extElem instanceof SOAPOperation) {
555: logger.debug("Using SOAP 1.1");
556: return SOAP_11_ENVELOPE_NS;
557: } else if (extElem instanceof SOAP12Operation) {
558: logger.debug("Using SOAP 1.2");
559: return SOAP_12_ENVELOPE_NS;
560: }
561: }
562: }
563: }
564: logger.debug("Did not find '" + operation
565: + "' operation in binding");
566: } else {
567: logger.debug("Did not find '"
568: + endpoint.getTargetPort()
569: + "' port in service");
570: }
571: } else {
572: logger.debug("Did not find '" + targetService
573: + "' service in definition");
574: }
575:
576: return SOAP_11_ENVELOPE_NS;
577: }
578: }
|