1
2
3
4
5
6
7 package org.mule.component;
8
9 import org.mule.DefaultMuleEvent;
10 import org.mule.DefaultMuleMessage;
11 import org.mule.RequestContext;
12 import org.mule.api.MuleContext;
13 import org.mule.api.MuleEvent;
14 import org.mule.api.MuleMessage;
15 import org.mule.api.component.InterfaceBinding;
16 import org.mule.api.config.MuleProperties;
17 import org.mule.config.i18n.CoreMessages;
18 import org.mule.transport.NullPayload;
19 import org.mule.util.StringMessageUtils;
20
21 import java.lang.reflect.InvocationHandler;
22 import java.lang.reflect.Method;
23 import java.util.Map;
24
25 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29
30 public class BindingInvocationHandler implements InvocationHandler
31 {
32
33 public static final String DEFAULT_METHOD_NAME_TOKEN = "default";
34
35 protected static Log logger = LogFactory.getLog(BindingInvocationHandler.class);
36
37 protected Map<String, InterfaceBinding> routers = null;
38
39 protected MuleContext muleContext;
40
41 @SuppressWarnings("unchecked")
42 public BindingInvocationHandler(InterfaceBinding router)
43 {
44 routers = new ConcurrentHashMap();
45 addRouterForInterface(router);
46 }
47
48 public void addRouterForInterface(InterfaceBinding router)
49 {
50 if (router.getMethod() == null)
51 {
52 if (routers.size() == 0)
53 {
54 routers.put(DEFAULT_METHOD_NAME_TOKEN, router);
55 }
56 else
57 {
58 throw new IllegalArgumentException(CoreMessages.mustSetMethodNamesOnBinding().getMessage());
59 }
60 }
61 else
62 {
63 routers.put(router.getMethod(), router);
64 }
65 muleContext = router.getEndpoint().getMuleContext();
66 }
67
68 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
69 {
70 if (method.getName().equals("toString"))
71 {
72 return toString();
73 }
74
75 MuleMessage message = createMuleMessage(args);
76
77
78 message.setInvocationProperty(MuleProperties.MULE_METHOD_PROPERTY, method.getName());
79
80 InterfaceBinding router = routers.get(method.getName());
81 if (router == null)
82 {
83 router = routers.get(DEFAULT_METHOD_NAME_TOKEN);
84 }
85
86 if (router == null)
87 {
88 throw new IllegalArgumentException(CoreMessages.cannotFindBindingForMethod(method.getName()).toString());
89 }
90
91 MuleEvent currentEvent = RequestContext.getEvent();
92 MuleEvent replyEvent = router.process(new DefaultMuleEvent(message,currentEvent));
93
94 if (replyEvent != null && replyEvent.getMessage()!=null)
95 {
96 MuleMessage reply = replyEvent.getMessage();
97 if (reply.getExceptionPayload() != null)
98 {
99 throw findDeclaredMethodException(method, reply.getExceptionPayload().getException());
100 }
101 else
102 {
103 return determineReply(reply, method);
104 }
105 }
106 else
107 {
108 return null;
109 }
110 }
111
112 private MuleMessage createMuleMessage(Object[] args)
113 {
114 if (args == null)
115 {
116 return new DefaultMuleMessage(NullPayload.getInstance(), muleContext);
117 }
118 else if (args.length == 1)
119 {
120 return new DefaultMuleMessage(args[0], muleContext);
121 }
122 else
123 {
124 return new DefaultMuleMessage(args, muleContext);
125 }
126 }
127
128
129
130
131
132
133 private Throwable findDeclaredMethodException(Method method, Throwable throwable) throws Throwable
134 {
135 Throwable cause = throwable.getCause();
136 if (cause != null)
137 {
138
139
140 Class[] exceptions = method.getExceptionTypes();
141 for (int i = 0; i < exceptions.length; i++)
142 {
143 if (cause.getClass().equals(exceptions[i]))
144 {
145 return cause;
146 }
147 }
148 }
149
150 return throwable;
151 }
152
153 private Object determineReply(MuleMessage reply, Method bindingMethod)
154 {
155 if (MuleMessage.class.isAssignableFrom(bindingMethod.getReturnType()))
156 {
157 return reply;
158 }
159 else if (reply.getPayload() == NullPayload.getInstance() && !bindingMethod.getReturnType().isInstance(reply.getPayload()))
160 {
161 return null;
162 }
163 else
164 {
165 return reply.getPayload();
166 }
167 }
168
169 @Override
170 public String toString()
171 {
172 final StringBuffer sb = new StringBuffer();
173 sb.append("BindingInvocation");
174 sb.append("{routers='").append(StringMessageUtils.toString(routers));
175 sb.append('}');
176 return sb.toString();
177 }
178
179 }