001: /*
002: * $Id: MuleInvoker.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.MuleException;
015: import org.mule.api.MuleMessage;
016: import org.mule.api.config.MuleProperties;
017: import org.mule.api.endpoint.InboundEndpoint;
018: import org.mule.api.service.ServiceException;
019: import org.mule.transport.NullPayload;
020:
021: import java.lang.reflect.Method;
022: import java.lang.reflect.Proxy;
023:
024: import org.apache.cxf.frontend.MethodDispatcher;
025: import org.apache.cxf.interceptor.Fault;
026: import org.apache.cxf.message.Exchange;
027: import org.apache.cxf.message.FaultMode;
028: import org.apache.cxf.service.Service;
029: import org.apache.cxf.service.invoker.Invoker;
030: import org.apache.cxf.service.model.BindingOperationInfo;
031:
032: /**
033: * Invokes a Mule Service via a CXF binding.
034: */
035: public class MuleInvoker implements Invoker {
036: private final CxfMessageReceiver receiver;
037: private final boolean synchronous;
038: private Class<?> targetClass;
039:
040: public MuleInvoker(CxfMessageReceiver receiver,
041: Class<?> targetClass, boolean synchronous) {
042: this .receiver = receiver;
043: this .targetClass = targetClass;
044: this .synchronous = synchronous;
045: }
046:
047: public Object invoke(Exchange exchange, Object o) {
048: BindingOperationInfo bop = exchange
049: .get(BindingOperationInfo.class);
050: Service svc = exchange.get(Service.class);
051: MethodDispatcher md = (MethodDispatcher) svc
052: .get(MethodDispatcher.class.getName());
053: Method m = md.getMethod(bop);
054: if (targetClass != null) {
055: m = matchMethod(m, targetClass);
056: }
057:
058: MuleMessage message = null;
059: try {
060: CxfMessageAdapter messageAdapter = (CxfMessageAdapter) receiver
061: .getConnector().getMessageAdapter(
062: exchange.getInMessage());
063:
064: if (!receiver.isBridge()) {
065: messageAdapter.setProperty(
066: MuleProperties.MULE_METHOD_PROPERTY, m);
067: }
068:
069: DefaultMuleMessage muleReq = new DefaultMuleMessage(
070: messageAdapter);
071: String replyTo = (String) exchange.getInMessage().get(
072: MuleProperties.MULE_REPLY_TO_PROPERTY);
073: if (replyTo != null) {
074: muleReq.setReplyTo(replyTo);
075: }
076:
077: String corId = (String) exchange.getInMessage().get(
078: MuleProperties.MULE_CORRELATION_ID_PROPERTY);
079: if (corId != null) {
080: muleReq.setCorrelationId(corId);
081: }
082:
083: String corGroupSize = (String) exchange
084: .getInMessage()
085: .get(
086: MuleProperties.MULE_CORRELATION_GROUP_SIZE_PROPERTY);
087: if (corGroupSize != null) {
088: muleReq.setCorrelationGroupSize(Integer
089: .valueOf(corGroupSize));
090: }
091:
092: String corSeq = (String) exchange.getInMessage().get(
093: MuleProperties.MULE_CORRELATION_SEQUENCE_PROPERTY);
094: if (corSeq != null) {
095: muleReq.setCorrelationSequence(Integer.valueOf(corSeq));
096: }
097:
098: message = receiver.routeMessage(muleReq, synchronous);
099: } catch (MuleException e) {
100: throw new Fault(e);
101: }
102:
103: if (message != null) {
104: if (message.getExceptionPayload() != null) {
105: Throwable cause = message.getExceptionPayload()
106: .getException();
107: if (cause instanceof ServiceException) {
108: cause = cause.getCause();
109: }
110:
111: exchange.getInMessage().put(FaultMode.class,
112: FaultMode.UNCHECKED_APPLICATION_FAULT);
113: if (cause instanceof Fault) {
114: throw (Fault) cause;
115: }
116:
117: throw new Fault(cause);
118: } else if (message.getPayload() instanceof NullPayload) {
119: return null;
120: } else {
121: return new Object[] { message.getPayload() };
122: }
123: } else {
124: return null;
125: }
126: }
127:
128: public InboundEndpoint getEndpoint() {
129: return receiver.getEndpoint();
130: }
131:
132: /**
133: * Returns a Method that has the same declaring class as the class of
134: * targetObject to avoid the IllegalArgumentException when invoking the
135: * method on the target object. The methodToMatch will be returned if the
136: * targetObject doesn't have a similar method.
137: *
138: * @param methodToMatch The method to be used when finding a matching method
139: * in targetObject
140: * @param targetObject The object to search in for the method.
141: * @return The methodToMatch if no such method exist in the class of
142: * targetObject; otherwise, a method from the class of targetObject
143: * matching the matchToMethod method.
144: */
145: private static Method matchMethod(Method methodToMatch,
146: Class<?> targetClass) {
147: Class<?>[] interfaces = targetClass.getInterfaces();
148: for (int i = 0; i < interfaces.length; i++) {
149: Method m = getMostSpecificMethod(methodToMatch,
150: interfaces[i]);
151: if (!methodToMatch.equals(m)) {
152: return m;
153: }
154: }
155: return methodToMatch;
156: }
157:
158: /**
159: * Return whether the given object is a J2SE dynamic proxy.
160: *
161: * @param object the object to check
162: * @see java.lang.reflect.Proxy#isProxyClass
163: */
164: public static boolean isJdkDynamicProxy(Object object) {
165: return object != null && Proxy.isProxyClass(object.getClass());
166: }
167:
168: /**
169: * Given a method, which may come from an interface, and a targetClass used
170: * in the current AOP invocation, find the most specific method if there is
171: * one. E.g. the method may be IFoo.bar() and the target class may be
172: * DefaultFoo. In this case, the method may be DefaultFoo.bar(). This
173: * enables attributes on that method to be found.
174: *
175: * @param method method to be invoked, which may come from an interface
176: * @param targetClass target class for the curren invocation. May be
177: * <code>null</code> or may not even implement the method.
178: * @return the more specific method, or the original method if the
179: * targetClass doesn't specialize it or implement it or is null
180: */
181: public static Method getMostSpecificMethod(Method method,
182: Class<?> targetClass) {
183: if (method != null && targetClass != null) {
184: try {
185: method = targetClass.getMethod(method.getName(), method
186: .getParameterTypes());
187: } catch (NoSuchMethodException ex) {
188: // Perhaps the target class doesn't implement this method:
189: // that's fine, just use the original method
190: }
191: }
192: return method;
193: }
194: }
|