001: /*
002: * $Id: CxfMessageDispatcher.java 11405 2008-03-18 00:13:00Z dirk.olmes $
003: * --------------------------------------------------------------------------------------
004: * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.com
005: *
006: * The software in this package is published under the terms of the CPAL v1.0
007: * license, a copy of which has been included with this distribution in the
008: * LICENSE.txt file.
009: */
010:
011: package org.mule.transport.cxf;
012:
013: import org.mule.DefaultMuleMessage;
014: import org.mule.api.MuleEvent;
015: import org.mule.api.MuleMessage;
016: import org.mule.api.config.MuleProperties;
017: import org.mule.api.endpoint.EndpointURI;
018: import org.mule.api.endpoint.OutboundEndpoint;
019: import org.mule.api.transformer.TransformerException;
020: import org.mule.transport.AbstractMessageDispatcher;
021: import org.mule.transport.soap.SoapConstants;
022: import org.mule.util.TemplateParser;
023:
024: import java.lang.reflect.Method;
025: import java.util.ArrayList;
026: import java.util.Arrays;
027: import java.util.HashMap;
028: import java.util.Iterator;
029: import java.util.List;
030: import java.util.Map;
031: import java.util.Set;
032: import java.util.regex.Pattern;
033:
034: import javax.activation.DataHandler;
035: import javax.xml.namespace.QName;
036: import javax.xml.ws.BindingProvider;
037:
038: import org.apache.cxf.endpoint.Client;
039: import org.apache.cxf.endpoint.ClientImpl;
040: import org.apache.cxf.service.model.BindingOperationInfo;
041:
042: /**
043: * The CxfMessageDispatcher is used for making Soap client requests to remote
044: * services.
045: */
046: public class CxfMessageDispatcher extends AbstractMessageDispatcher {
047:
048: private static final String URI_REGEX = "cxf:\\[(.+?)\\]:(.+?)/\\[(.+?)\\]:(.+?)";
049: Pattern URI_PATTERN = Pattern.compile(URI_REGEX);
050:
051: protected final CxfConnector connector;
052: protected ClientWrapper wrapper;
053: private final TemplateParser soapActionTemplateParser = TemplateParser
054: .createAntStyleParser();
055:
056: public CxfMessageDispatcher(OutboundEndpoint endpoint) {
057: super (endpoint);
058: this .connector = (CxfConnector) endpoint.getConnector();
059: }
060:
061: /*
062: We need a way to associate an endpoint with a specific CXF service and operation, and the most sensible way to
063: accomplish that is to overload URI syntax:
064:
065: cxf:[service_URI]:service_localname/[ep_URI]:ep_localname
066:
067: And the map method to operation
068: */
069: protected void doConnect() throws Exception {
070: wrapper = new ClientWrapper();
071: wrapper.setBus(connector.getCxfBus());
072: wrapper.setEndpoint(endpoint);
073: wrapper.initialize();
074: }
075:
076: protected void doDisconnect() throws Exception {
077: wrapper = null;
078: }
079:
080: protected void doDispose() {
081: // nothing to do
082: }
083:
084: protected Object[] getArgs(MuleEvent event)
085: throws TransformerException {
086: Object payload = event.transformMessage();
087: Object[] args;
088:
089: if (payload instanceof Object[]) {
090: args = (Object[]) payload;
091: } else {
092: args = new Object[] { payload };
093: }
094:
095: MuleMessage message = event.getMessage();
096: Set<?> attachmentNames = message.getAttachmentNames();
097: if (attachmentNames != null && !attachmentNames.isEmpty()) {
098: List<DataHandler> attachments = new ArrayList<DataHandler>();
099: for (Iterator<?> i = attachmentNames.iterator(); i
100: .hasNext();) {
101: attachments.add(message
102: .getAttachment((String) i.next()));
103: }
104: List<Object> temp = new ArrayList<Object>(Arrays
105: .asList(args));
106: temp.add(attachments.toArray(new DataHandler[0]));
107: args = temp.toArray();
108: }
109:
110: return args;
111: }
112:
113: protected MuleMessage doSend(MuleEvent event) throws Exception {
114: ((ClientImpl) wrapper.getClient()).setSynchronousTimeout(event
115: .getTimeout());
116: if (!wrapper.isProxy()) {
117: return doSendWithClient(event);
118: } else {
119: return doSendWithProxy(event);
120: }
121: }
122:
123: protected MuleMessage doSendWithProxy(MuleEvent event)
124: throws Exception {
125: Method method = wrapper.getMethod(event);
126:
127: Map<String, Object> props = new HashMap<String, Object>();
128: props.put(MuleProperties.MULE_EVENT_PROPERTY, event);
129:
130: // Set custom soap action if set on the event or endpoint
131: String soapAction = (String) event.getMessage().getProperty(
132: SoapConstants.SOAP_ACTION_PROPERTY);
133: if (soapAction != null) {
134: soapAction = parseSoapAction(soapAction, new QName(method
135: .getName()), event);
136: props
137: .put(
138: org.apache.cxf.binding.soap.SoapConstants.SOAP_ACTION,
139: soapAction);
140: }
141:
142: BindingProvider bp = wrapper.getProxy();
143: bp.getRequestContext().putAll(props);
144:
145: Object response = method.invoke(wrapper.getProxy(),
146: getArgs(event));
147:
148: // TODO: handle holders
149:
150: return buildResponseMessage(event, new Object[] { response });
151: }
152:
153: protected MuleMessage doSendWithClient(MuleEvent event)
154: throws Exception {
155: BindingOperationInfo bop = wrapper.getOperation(event);
156:
157: Map<String, Object> props = new HashMap<String, Object>();
158: props.put(MuleProperties.MULE_EVENT_PROPERTY, event);
159:
160: // Set custom soap action if set on the event or endpoint
161: String soapAction = (String) event.getMessage().getProperty(
162: SoapConstants.SOAP_ACTION_PROPERTY);
163: if (soapAction != null) {
164: soapAction = parseSoapAction(soapAction, bop.getName(),
165: event);
166: props
167: .put(
168: org.apache.cxf.binding.soap.SoapConstants.SOAP_ACTION,
169: soapAction);
170: event.getMessage().setProperty(
171: SoapConstants.SOAP_ACTION_PROPERTY, soapAction);
172: }
173:
174: Map<String, Object> ctx = new HashMap<String, Object>();
175: ctx.put(Client.REQUEST_CONTEXT, props);
176: ctx.put(Client.RESPONSE_CONTEXT, props);
177:
178: // Set Custom Headers on the client
179: Object[] arr = event.getMessage().getPropertyNames().toArray();
180: String head;
181:
182: for (int i = 0; i < arr.length; i++) {
183: head = (String) arr[i];
184: if ((head != null) && (!head.startsWith("MULE"))) {
185: props.put((String) arr[i], event.getMessage()
186: .getProperty((String) arr[i]));
187: }
188: }
189:
190: Object[] response = wrapper.getClient().invoke(bop,
191: getArgs(event), ctx);
192:
193: return buildResponseMessage(event, response);
194: }
195:
196: protected MuleMessage buildResponseMessage(MuleEvent event,
197: Object[] response) {
198: MuleMessage result = null;
199: if (response != null && response.length <= 1) {
200: if (response.length == 1) {
201: result = new DefaultMuleMessage(response[0], event
202: .getMessage());
203: }
204: } else {
205: result = new DefaultMuleMessage(response, event
206: .getMessage());
207: }
208:
209: return result;
210: }
211:
212: protected void doDispatch(MuleEvent event) throws Exception {
213: doSend(event);
214: }
215:
216: public String parseSoapAction(String soapAction, QName method,
217: MuleEvent event) {
218: EndpointURI endpointURI = event.getEndpoint().getEndpointURI();
219: Map<String, String> properties = new HashMap<String, String>();
220: MuleMessage msg = event.getMessage();
221: for (Iterator<?> iterator = msg.getPropertyNames().iterator(); iterator
222: .hasNext();) {
223: String propertyKey = (String) iterator.next();
224: properties.put(propertyKey, msg.getProperty(propertyKey)
225: .toString());
226: }
227: properties.put(MuleProperties.MULE_METHOD_PROPERTY, method
228: .getLocalPart());
229: properties.put("methodNamespace", method.getNamespaceURI());
230: properties.put("address", endpointURI.getAddress());
231: properties.put("scheme", endpointURI.getScheme());
232: properties.put("host", endpointURI.getHost());
233: properties.put("port", String.valueOf(endpointURI.getPort()));
234: properties.put("path", endpointURI.getPath());
235: properties.put("hostInfo", endpointURI.getScheme()
236: + "://"
237: + endpointURI.getHost()
238: + (endpointURI.getPort() > -1 ? ":"
239: + String.valueOf(endpointURI.getPort()) : ""));
240: if (event.getService() != null) {
241: properties.put("serviceName", event.getService().getName());
242: }
243:
244: soapAction = soapActionTemplateParser.parse(properties,
245: soapAction);
246:
247: if (logger.isDebugEnabled()) {
248: logger.debug("SoapAction for this call is: " + soapAction);
249: }
250:
251: return soapAction;
252: }
253: }
|