1 package org.codehaus.xfire.client;
2
3 import java.lang.reflect.InvocationHandler;
4 import java.lang.reflect.Method;
5 import java.lang.reflect.Proxy;
6 import java.util.Arrays;
7
8 import org.apache.commons.logging.Log;
9 import org.apache.commons.logging.LogFactory;
10 import org.codehaus.xfire.XFireException;
11 import org.codehaus.xfire.service.OperationInfo;
12
13 /***
14 * Proxy implementation for XFire SOAP clients. Applications will generally use <code>XFireProxyFactory</code> to
15 * create proxy clients.
16 *
17 * @author <a href="mailto:poutsma@mac.com">Arjen Poutsma</a>
18 * @see XFireProxyFactory#create
19 */
20 public class XFireProxy
21 implements InvocationHandler
22 {
23 private static final Log log = LogFactory.getLog(XFireProxy.class);
24 private Client client;
25
26 XFireProxy(Client client)
27 {
28 this.client = client;
29 }
30
31 /***
32 * Handles the object invocation.
33 *
34 * @param proxy the proxy object to invoke
35 * @param method the method to call
36 * @param args the arguments to the proxy object
37 */
38 public Object invoke(Object proxy, Method method, Object[] args)
39 throws Throwable
40 {
41 String methodName = method.getName();
42 Class[] parameterTypes = method.getParameterTypes();
43 if (log.isDebugEnabled())
44 {
45 log.debug("Method [" + methodName + "] " + ((args == null) ? "" : Arrays.asList(args).toString()));
46 }
47
48 Object result = handleCanonicalMethods(methodName, parameterTypes, args);
49
50 if (result == null)
51 {
52 result = handleRequest(methodName, args);
53 }
54 if (log.isDebugEnabled())
55 {
56 log.debug("Result [" + String.valueOf(result) + "]");
57 }
58 return result;
59 }
60
61 private Object handleRequest(String methodName, Object[] args)
62 throws XFireException
63 {
64 OperationInfo op = client.getService().getServiceInfo().getOperation(methodName);
65
66 Object[] response = (Object[]) client.invoke(op, args);
67
68 if (response.length > 0)
69 return response[0];
70 else
71 return null;
72 }
73
74 /***
75 * Handles canonical method calls such as <code>equals</code>, <code>hashCode</code>, and <code>toString</code>.
76 *
77 * @param methodName the method name.
78 * @param params the parameter types.
79 * @param args the arguments
80 * @return the result, if <code>methodName</code> is a canonical method; or <code>null</code> if not.
81 */
82 private Object handleCanonicalMethods(String methodName, Class[] params, Object[] args)
83 {
84 if (methodName.equals("equals") &&
85 params.length == 1
86 && params[0].equals(Object.class))
87 {
88 Object other = args[0];
89 if (other == null ||
90 !Proxy.isProxyClass(other.getClass()) ||
91 !(Proxy.getInvocationHandler(other) instanceof XFireProxy))
92 {
93 return Boolean.FALSE;
94 }
95
96 XFireProxy otherClient = (XFireProxy) Proxy.getInvocationHandler(other);
97
98 return new Boolean(otherClient == this);
99 }
100 else if (methodName.equals("hashCode") && params.length == 0)
101 {
102 return new Integer(hashCode());
103 }
104 else if (methodName.equals("toString") && params.length == 0)
105 {
106 return "XFireProxy[" + client.getUrl() + "]";
107 }
108 return null;
109 }
110 }
111