KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mx4j > tools > remote > soap > ClientExceptionCatcher


1 /*
2  * Copyright (C) The MX4J Contributors.
3  * All rights reserved.
4  *
5  * This software is distributed under the terms of the MX4J License version 1.0.
6  * See the terms of the MX4J License in the documentation provided with this software.
7  */

8
9 package mx4j.tools.remote.soap;
10
11 import java.io.IOException JavaDoc;
12 import java.lang.reflect.Constructor JavaDoc;
13 import java.lang.reflect.InvocationHandler JavaDoc;
14 import java.lang.reflect.InvocationTargetException JavaDoc;
15 import java.lang.reflect.Method JavaDoc;
16 import java.lang.reflect.Proxy JavaDoc;
17 import javax.management.MBeanException JavaDoc;
18 import javax.management.RuntimeMBeanException JavaDoc;
19
20 import mx4j.log.Log;
21 import mx4j.log.Logger;
22 import mx4j.tools.remote.http.HTTPConnection;
23 import org.apache.axis.AxisFault;
24
25 /**
26  * Handles exceptions thrown on server-side by rethrowing them on client side.
27  * Axis, as of version 1.1, is not able to do this transparently, so we have to
28  * manually do it here, by parsing the class name and message that are encoded
29  * by Axis in the response.
30  *
31  * @version $Revision: 1.5 $
32  */

33 class ClientExceptionCatcher implements InvocationHandler JavaDoc
34 {
35    public static HTTPConnection newInstance(HTTPConnection target)
36    {
37       ClientExceptionCatcher handler = new ClientExceptionCatcher(target);
38       return (HTTPConnection)Proxy.newProxyInstance(handler.getClass().getClassLoader(), new Class JavaDoc[]{HTTPConnection.class}, handler);
39    }
40
41    private final HTTPConnection target;
42
43    private ClientExceptionCatcher(HTTPConnection target)
44    {
45       this.target = target;
46    }
47
48    public Object JavaDoc invoke(Object JavaDoc proxy, Method JavaDoc method, Object JavaDoc[] args) throws Throwable JavaDoc
49    {
50       try
51       {
52          try
53          {
54             return method.invoke(target, args);
55          }
56          catch (InvocationTargetException JavaDoc x)
57          {
58             throw x.getTargetException();
59          }
60       }
61       catch (Throwable JavaDoc x)
62       {
63          throw handleException(x, method.getExceptionTypes());
64       }
65    }
66
67    private Throwable JavaDoc handleException(Throwable JavaDoc x, Class JavaDoc[] declared)
68    {
69       if (x instanceof Error JavaDoc) return x;
70       if (x instanceof AxisFault) x = extractThrowable((AxisFault)x);
71       if (isDeclaredOrRuntime(x, declared)) return x;
72       return new IOException JavaDoc(x.toString());
73    }
74
75    private Throwable JavaDoc extractThrowable(AxisFault fault)
76    {
77       String JavaDoc name = fault.getFaultString();
78       if (name == null) return fault;
79
80       // FaultStrings in Axis 1.1 are obtained with Throwable.toString(),
81
// which is <exception class>: <message>.
82
// Here we parse the string to re-create the exception
83
int colon = name.indexOf(':');
84       String JavaDoc className = colon < 0 ? name : name.substring(0, colon).trim();
85       String JavaDoc message = colon < 0 ? null : name.substring(colon + 1).trim();
86
87       Class JavaDoc cls = null;
88       try
89       {
90          // Try to load the class: mostly these are JMX exceptions or java.* exceptions
91
// so we can use this class' classloader
92
cls = getClass().getClassLoader().loadClass(className);
93       }
94       catch (ClassNotFoundException JavaDoc x)
95       {
96          Logger logger = getLogger();
97          if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Cannot load Throwable class " + className, x);
98       }
99
100       if (cls == null) return fault;
101
102       Object JavaDoc exception = null;
103       if (message != null)
104       {
105          try
106          {
107             // Try to find the suitable constructor
108
Constructor JavaDoc ctor = cls.getConstructor(new Class JavaDoc[]{String JavaDoc.class});
109             exception = ctor.newInstance(new Object JavaDoc[]{message});
110          }
111          catch (Throwable JavaDoc x)
112          {
113             Logger logger = getLogger();
114             if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Cannot find constructor " + className + "(String message)", x);
115          }
116       }
117
118       if (exception == null)
119       {
120          try
121          {
122             exception = cls.newInstance();
123          }
124          catch (Throwable JavaDoc x)
125          {
126             Logger logger = getLogger();
127             if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Cannot find constructor " + className + "()", x);
128          }
129       }
130
131       // Handle JMX exceptions with special case constructors
132
if (MBeanException JavaDoc.class.getName().equals(className))
133       {
134          exception = new MBeanException JavaDoc(null, message);
135       }
136       else if (RuntimeMBeanException JavaDoc.class.getName().equals(className))
137       {
138          exception = new RuntimeMBeanException JavaDoc(null, message);
139       }
140
141       if (!(exception instanceof Throwable JavaDoc))
142       {
143          Logger logger = getLogger();
144          if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Could not recreate exception thrown on server side: " + className);
145          return fault;
146       }
147
148       return (Throwable JavaDoc)exception;
149    }
150
151    private boolean isDeclaredOrRuntime(Throwable JavaDoc x, Class JavaDoc[] declared)
152    {
153       if (x instanceof RuntimeException JavaDoc) return true;
154
155       for (int i = 0; i < declared.length; ++i)
156       {
157          Class JavaDoc exception = declared[i];
158          if (exception.isInstance(x)) return true;
159       }
160       return false;
161    }
162
163    private Logger getLogger()
164    {
165       return Log.getLogger(getClass().getName());
166    }
167 }
168
Popular Tags