001: /*
002: * $Id: ClientWrapper.java 11351 2008-03-13 18:40:41Z dandiep $
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.api.MuleEvent;
014: import org.mule.api.config.MuleProperties;
015: import org.mule.api.endpoint.EndpointURI;
016: import org.mule.api.endpoint.ImmutableEndpoint;
017: import org.mule.api.lifecycle.CreateException;
018: import org.mule.api.transport.DispatchException;
019: import org.mule.transport.cxf.i18n.CxfMessages;
020: import org.mule.transport.cxf.support.MuleHeadersInInterceptor;
021: import org.mule.transport.cxf.support.MuleHeadersOutInterceptor;
022: import org.mule.transport.cxf.support.MuleProtocolHeadersOutInterceptor;
023: import org.mule.transport.soap.i18n.SoapMessages;
024:
025: import java.io.IOException;
026: import java.lang.reflect.Constructor;
027: import java.lang.reflect.Method;
028: import java.net.URL;
029: import java.util.List;
030:
031: import javax.xml.namespace.QName;
032: import javax.xml.ws.BindingProvider;
033: import javax.xml.ws.Service;
034: import javax.xml.ws.WebEndpoint;
035: import javax.xml.ws.WebServiceClient;
036:
037: import org.apache.cxf.Bus;
038: import org.apache.cxf.common.classloader.ClassLoaderUtils;
039: import org.apache.cxf.endpoint.Client;
040: import org.apache.cxf.endpoint.ClientImpl;
041: import org.apache.cxf.endpoint.Endpoint;
042: import org.apache.cxf.feature.AbstractFeature;
043: import org.apache.cxf.frontend.ClientProxy;
044: import org.apache.cxf.frontend.MethodDispatcher;
045: import org.apache.cxf.interceptor.Interceptor;
046: import org.apache.cxf.resource.ResourceManager;
047: import org.apache.cxf.resource.URIResolver;
048: import org.apache.cxf.service.model.BindingOperationInfo;
049: import org.apache.cxf.service.model.EndpointInfo;
050: import org.apache.cxf.transport.ChainInitiationObserver;
051: import org.apache.cxf.transport.Destination;
052: import org.apache.cxf.transport.DestinationFactory;
053: import org.apache.cxf.transport.DestinationFactoryManager;
054: import org.apache.cxf.transport.MessageObserver;
055:
056: public class ClientWrapper {
057:
058: protected ImmutableEndpoint endpoint;
059: protected Bus bus;
060: protected Client client;
061: protected String defaultMethodName;
062:
063: // If we have a proxy we're going to invoke it directly
064: // Since the JAX-WS proxy does extra special things for us.
065: protected BindingProvider proxy;
066: protected Method defaultMethod;
067:
068: public Client getClient() {
069: return client;
070: }
071:
072: public BindingProvider getProxy() {
073: return proxy;
074: }
075:
076: @SuppressWarnings("unchecked")
077: public void initialize() throws Exception, IOException {
078: String clientClass = (String) endpoint
079: .getProperty(CxfConstants.CLIENT_CLASS);
080: if (clientClass != null) {
081: createClientFromClass(bus, clientClass);
082: } else {
083: createClientFromLocalServer(bus);
084: }
085:
086: addInterceptors(client.getInInterceptors(),
087: (List<Interceptor>) endpoint
088: .getProperty(CxfConstants.IN_INTERCEPTORS));
089: addInterceptors(
090: client.getInFaultInterceptors(),
091: (List<Interceptor>) endpoint
092: .getProperty(CxfConstants.IN_FAULT_INTERCEPTORS));
093: addInterceptors(client.getOutInterceptors(),
094: (List<Interceptor>) endpoint
095: .getProperty(CxfConstants.OUT_INTERCEPTORS));
096: addInterceptors(
097: client.getOutFaultInterceptors(),
098: (List<Interceptor>) endpoint
099: .getProperty(CxfConstants.OUT_FAULT_INTERCEPTORS));
100:
101: List<AbstractFeature> features = (List<AbstractFeature>) endpoint
102: .getProperty(CxfConstants.OUT_FAULT_INTERCEPTORS);
103:
104: if (features != null) {
105: for (AbstractFeature f : features) {
106: f.initialize(client, bus);
107: }
108: }
109:
110: addMuleInterceptors();
111: }
112:
113: @SuppressWarnings("unchecked")
114: private void addInterceptors(List<Interceptor> col,
115: List<Interceptor> supplied) {
116: if (supplied != null) {
117: col.addAll(supplied);
118: }
119: }
120:
121: protected Method findMethod(Class<?> clientCls) throws Exception {
122: if (defaultMethod == null) {
123: String op = (String) endpoint.getProperties().get(
124: CxfConstants.OPERATION);
125: if (op == null) {
126: op = (String) endpoint.getProperties().get(
127: CxfConstants.OPERATION);
128: }
129:
130: if (op != null) {
131: return getMethodFromOperation(op);
132: }
133: }
134:
135: return null;
136: }
137:
138: protected BindingOperationInfo getOperation(String opName)
139: throws Exception {
140: // Normally its not this hard to invoke the CXF Client, but we're
141: // sending along some exchange properties, so we need to use a more advanced
142: // method
143: Endpoint ep = client.getEndpoint();
144: QName q = new QName(
145: ep.getService().getName().getNamespaceURI(), opName);
146: BindingOperationInfo bop = ep.getBinding().getBindingInfo()
147: .getOperation(q);
148: if (bop == null) {
149: throw new Exception("No such operation: " + defaultMethod);
150: }
151:
152: if (bop.isUnwrappedCapable()) {
153: bop = bop.getUnwrappedOperation();
154: }
155: return bop;
156: }
157:
158: private Method getMethodFromOperation(String op) throws Exception {
159: BindingOperationInfo bop = getOperation(op);
160: MethodDispatcher md = (MethodDispatcher) client.getEndpoint()
161: .getService().get(MethodDispatcher.class.getName());
162: return md.getMethod(bop);
163: }
164:
165: protected void createClientFromClass(Bus bus, String clientClassName)
166: throws Exception {
167: // TODO: Specify WSDL
168: String wsdlLocation = (String) endpoint
169: .getProperty(CxfConstants.WSDL_LOCATION);
170: Class<?> clientCls = ClassLoaderUtils.loadClass(
171: clientClassName, getClass());
172:
173: Service s = null;
174: if (wsdlLocation != null) {
175: Constructor<?> cons = clientCls.getConstructor(URL.class,
176: QName.class);
177: ResourceManager rr = bus
178: .getExtension(ResourceManager.class);
179: URL url = rr.resolveResource(wsdlLocation, URL.class);
180:
181: if (url == null) {
182: URIResolver res = new URIResolver(wsdlLocation);
183:
184: if (!res.isResolved()) {
185: throw new CreateException(CxfMessages
186: .wsdlNotFound(wsdlLocation), this );
187: }
188: url = res.getURL();
189: }
190:
191: WebServiceClient clientAnn = clientCls
192: .getAnnotation(WebServiceClient.class);
193: QName svcName = new QName(clientAnn.targetNamespace(),
194: clientAnn.name());
195:
196: s = (Service) cons.newInstance(url, svcName);
197: } else {
198: s = (Service) clientCls.newInstance();
199: }
200: String port = (String) endpoint
201: .getProperty(CxfConstants.CLIENT_PORT);
202:
203: if (port == null) {
204: throw new CreateException(CxfMessages.mustSpecifyPort(),
205: this );
206: }
207:
208: proxy = null;
209: if (port != null) {
210: for (Method m : clientCls.getMethods()) {
211: WebEndpoint we = m.getAnnotation(WebEndpoint.class);
212:
213: if (we != null && we.name().equals(port)) {
214: proxy = (BindingProvider) m
215: .invoke(s, new Object[0]);
216: break;
217: }
218: }
219: }
220:
221: if (proxy == null) {
222: throw new CreateException(CxfMessages.portNotFound(port),
223: this );
224: }
225:
226: EndpointURI uri = endpoint.getEndpointURI();
227: if (uri.getUser() != null) {
228: proxy.getRequestContext().put(
229: BindingProvider.USERNAME_PROPERTY, uri.getUser());
230: }
231:
232: if (uri.getPassword() != null) {
233: proxy.getRequestContext().put(
234: BindingProvider.PASSWORD_PROPERTY,
235: uri.getPassword());
236: }
237:
238: proxy.getRequestContext().put(
239: BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
240: uri.getAddress());
241:
242: client = ClientProxy.getClient(proxy);
243:
244: defaultMethod = findMethod(clientCls);
245: defaultMethodName = getDefaultMethodName();
246: }
247:
248: private String getDefaultMethodName() {
249: EndpointURI endpointUri = endpoint.getEndpointURI();
250: String m = (String) endpointUri.getParams().get(
251: MuleProperties.MULE_METHOD_PROPERTY);
252:
253: if (m == null) {
254: m = (String) endpoint.getProperties().get(
255: MuleProperties.MULE_METHOD_PROPERTY);
256: }
257:
258: return m;
259: }
260:
261: protected void createClientFromLocalServer(final Bus bus)
262: throws Exception, IOException {
263: String uri = endpoint.getEndpointURI().toString();
264: int idx = uri.indexOf('?');
265: if (idx != -1) {
266: uri = uri.substring(0, idx);
267: }
268:
269: EndpointInfo ei = new EndpointInfo();
270: ei.setAddress(uri);
271:
272: DestinationFactoryManager dfm = bus
273: .getExtension(DestinationFactoryManager.class);
274: DestinationFactory df = dfm.getDestinationFactoryForUri(uri);
275: if (df == null) {
276: throw new Exception(
277: "Could not find a destination factory for uri "
278: + uri);
279: }
280:
281: Destination dest = df.getDestination(ei);
282: MessageObserver mo = dest.getMessageObserver();
283: if (mo instanceof ChainInitiationObserver) {
284: ChainInitiationObserver cMo = (ChainInitiationObserver) mo;
285: Endpoint cxfEP = cMo.getEndpoint();
286:
287: client = new ClientImpl(bus, cxfEP);
288: } else {
289: throw new Exception(
290: "Could not create client! No Server was found directly on the endpoint: "
291: + uri);
292: }
293: }
294:
295: protected void addMuleInterceptors() {
296: client.getInInterceptors().add(new MuleHeadersInInterceptor());
297: client.getInFaultInterceptors().add(
298: new MuleHeadersInInterceptor());
299: client.getOutInterceptors()
300: .add(new MuleHeadersOutInterceptor());
301: client.getOutFaultInterceptors().add(
302: new MuleHeadersOutInterceptor());
303: client.getOutInterceptors().add(
304: new MuleProtocolHeadersOutInterceptor());
305: client.getOutFaultInterceptors().add(
306: new MuleProtocolHeadersOutInterceptor());
307: }
308:
309: protected String getMethodOrOperationName(MuleEvent event)
310: throws DispatchException {
311: // @TODO: Which of these *really* matter?
312: String method = (String) event.getMessage().getProperty(
313: MuleProperties.MULE_METHOD_PROPERTY);
314:
315: if (method == null) {
316: method = (String) event.getMessage().getProperty(
317: CxfConstants.OPERATION);
318: }
319:
320: if (method == null) {
321: method = defaultMethodName;
322: }
323:
324: if (method == null) {
325: throw new DispatchException(SoapMessages
326: .cannotInvokeCallWithoutOperation(), event
327: .getMessage(), event.getEndpoint());
328: }
329:
330: return method;
331: }
332:
333: public void setEndpoint(ImmutableEndpoint endpoint) {
334: this .endpoint = endpoint;
335: }
336:
337: public void setBus(Bus bus) {
338: this .bus = bus;
339: }
340:
341: public boolean isProxy() {
342: return proxy != null;
343: }
344:
345: public BindingOperationInfo getOperation(MuleEvent event)
346: throws Exception {
347: String opName = getMethodOrOperationName(event);
348:
349: if (opName == null) {
350: opName = defaultMethodName;
351: }
352:
353: return getOperation(opName);
354: }
355:
356: public Method getMethod(MuleEvent event) throws Exception {
357: Method method = defaultMethod;
358: if (method == null) {
359: String opName = (String) event.getMessage().getProperty(
360: CxfConstants.OPERATION);
361: if (opName != null) {
362: method = getMethodFromOperation(opName);
363: }
364:
365: if (method == null) {
366: opName = (String) endpoint
367: .getProperty(CxfConstants.OPERATION);
368: if (opName != null) {
369: method = getMethodFromOperation(opName);
370: }
371: }
372:
373: if (method == null) {
374: opName = defaultMethodName;
375: if (opName != null) {
376: method = getMethodFromOperation(opName);
377: }
378: }
379: }
380:
381: if (method == null) {
382: throw new DispatchException(CxfMessages
383: .noOperationWasFoundOrSpecified(), event
384: .getMessage(), endpoint);
385: }
386: return method;
387: }
388: }
|