View Javadoc

1   package net.sf.crispy;
2   
3   import java.io.ByteArrayOutputStream;
4   import java.io.IOException;
5   import java.io.OutputStream;
6   import java.io.PrintStream;
7   import java.io.Serializable;
8   import java.lang.reflect.Constructor;
9   import java.util.ArrayList;
10  import java.util.List;
11  import java.util.Map;
12  
13  import net.sf.crispy.impl.ServiceManager;
14  import net.sf.crispy.util.Converter;
15  import net.sf.crispy.util.Util;
16  
17  /**
18   * Wraped the server side thrown exception. Transport to the client.
19   * Unwraped the exception and thrown the exception on the client side.
20   * 
21   * @author Linke
22   * @since 1.1.0
23   *
24   */
25  public final class ExceptionWrapper implements Serializable {
26  
27  	private static final long serialVersionUID = -2137246018098063392L;
28  	
29  	private byte stackTraceByteArray[] = null;
30  	private String message = "no message available";
31  	private String exceptionClassName = "no exception class name";
32  	private List stackTraceElementWrapperList = new ArrayList(0);
33  	
34  	private Object exceptionPlaceHolder = null;
35  	private boolean withExceptionSerializer = false;
36  	
37  	public ExceptionWrapper() {}
38  	
39  	public ExceptionWrapper(Throwable pvThrowable) {
40  		this(pvThrowable, false);
41  	}
42  	public ExceptionWrapper(Throwable pvThrowable, boolean pvWithExceptionSerializer) {
43  		setMessage(pvThrowable.getMessage());
44  		setExceptionClassName(pvThrowable.getClass().getName());
45  		stackTrace2ByteArray(pvThrowable);
46  		copyStackTraceElement(pvThrowable.getStackTrace());
47  		withExceptionSerializer = pvWithExceptionSerializer;
48  		
49  		if (getWithExceptionSerializer() == true) {
50  			createPlaceHolder(pvThrowable);
51  		}
52  	}
53  	
54  	private void createPlaceHolder(Throwable pvThrowable) {
55  		try {
56  			Converter lvConverter = new Converter();
57  			lvConverter.setWithSimpleKeyMapper(true);
58  			exceptionPlaceHolder = lvConverter.makeSimple(pvThrowable);
59  			// StackTrace can't unmarshall
60  			((Map) exceptionPlaceHolder).remove("stackTrace");
61  		} catch (Exception e) {
62  			if (ServiceManager.DEBUG_MODE_ON) {
63  				e.printStackTrace();
64  			}
65  		}				
66  	}
67  
68  	public boolean getWithExceptionSerializer() { return withExceptionSerializer; }
69  
70  	public void setExceptionPlaceHolder(Object pvPlaceHolder) { exceptionPlaceHolder = pvPlaceHolder; }
71  	public Object getExceptionPlaceHolder() { return exceptionPlaceHolder; }
72  	
73  	public void setMessage(String pvMessage) { message = pvMessage; }
74  	public String getMessage() { return message; }
75  	
76  	public void setExceptionClassName(String pvExceptionClassName) { exceptionClassName = pvExceptionClassName; }
77  	public String getExceptionClassName() { return exceptionClassName; }
78  	
79  	public void setStackTraceByteArray(byte b[]) { stackTraceByteArray = b; }
80  	public byte[] getStackTraceByteArray() { return stackTraceByteArray; }
81  	
82  	public List getStackTraceElementWrapperList() { return stackTraceElementWrapperList; }
83  	public void setStackTraceElementWrapperList(List pvStackTraceElementWrapperList) {stackTraceElementWrapperList = pvStackTraceElementWrapperList;}
84  	
85  	public void copyStackTraceElement(StackTraceElement[] pvStackTraceElements) {
86  		int lvArraySize = pvStackTraceElements.length;
87  		stackTraceElementWrapperList = new ArrayList(lvArraySize);
88  		for (int i=0; i<lvArraySize; i++) {
89  			stackTraceElementWrapperList.add(new StackTraceElementWrapper(pvStackTraceElements[i]));
90  		}
91  	}
92  	
93  	public void stackTrace2ByteArray(Throwable pvThrowable) {
94  		ByteArrayOutputStream out = new ByteArrayOutputStream();
95  		PrintStream lvPrintStream = new PrintStream(out);
96  		pvThrowable.printStackTrace(lvPrintStream);
97  		
98  		setStackTraceByteArray(out.toByteArray());
99  	}
100 	
101 	public void printStackTrace2() {
102 		int lvSize = stackTraceElementWrapperList.size();
103 		System.out.println(getExceptionClassName() + ": " + getMessage());
104 		for (int i=0; i<lvSize; i++) {
105 			System.out.println("  at " + stackTraceElementWrapperList.get(i));
106 		}
107 	}
108 	
109 	public void printStackTrace() {
110 		printStackTrace(System.out);
111 	}
112 	
113 	public void printStackTrace(OutputStream pvOutputStream) {
114 		ByteArrayOutputStream out = new ByteArrayOutputStream();
115 		try {
116 			out.write(getStackTraceByteArray());
117 			out.writeTo(pvOutputStream);
118 			out.flush();
119 			out.close();
120 		} catch (IOException e) {
121 			if (ServiceManager.DEBUG_MODE_ON) {
122 				e.printStackTrace();
123 			}
124 		}
125 		
126 	}
127 	
128 	public Exception newExceptionInstance() {
129 		
130 		Exception lvResult = null;
131 		try {
132 			Converter lvConverter = new Converter();
133 			lvConverter.setWithSimpleKeyMapper(true);
134 			lvResult = (Exception) lvConverter.makeComplex(getExceptionPlaceHolder());
135 		} catch (Exception e) {
136 			if (ServiceManager.DEBUG_MODE_ON) {
137 				e.printStackTrace();
138 			}
139 		}
140 		if (lvResult != null) {
141 			lvResult.initCause(new InvocationException(getMessage()));
142 			return lvResult;
143 		} else {
144 			return newExceptionInstanceIntern();
145 		}
146 	}
147 	
148 	private Exception newExceptionInstanceIntern() {
149 		Exception lvException = new InvocationException(this);
150 		try {
151 			Class c = Class.forName(this.getExceptionClassName());
152 			Constructor con[] = c.getConstructors();
153 			for (int i = 0; i < con.length; i++) {
154 				int lvParamSize = con[i].getParameterTypes().length;
155 				if ((lvParamSize == 1) && (con[i].getParameterTypes()[0].equals(String.class))) {
156 					lvException = (Exception) con[i].newInstance(new Object [] { this.getMessage() });
157 					break;
158 				}
159 				else if (lvParamSize == 0) {
160 					lvException = (Exception) con[i].newInstance(null);
161 					break;
162 				} 
163 			}
164 		} catch (Exception e) {
165 			if (ServiceManager.DEBUG_MODE_ON) {
166 				e.printStackTrace();
167 			}
168 		}
169 		return lvException;
170 	}
171 	
172 	/**
173 	 * This method is used on the server side (from the invocation handler) to convert the
174 	 * <code>Exception</code> to the <code>ExceptionWrapper</code>.
175 	 * 
176 	 * @param pvResult Result of execution remote call (on the server side).
177 	 * @return The unchanged result object or if the result object is a Throwable,
178 	 * than is the return value a ExceptionWrapper from the Throwable.
179 	 */
180     public static Object isThrowableThanHandleThrowable(final Object pvResult) {
181     	if (pvResult instanceof Throwable) {
182     		Throwable lvThrowable = (Throwable) pvResult;
183 
184     		if (ServiceManager.DEBUG_MODE_ON == true) {
185     			lvThrowable.printStackTrace();
186     		}
187  
188     		Throwable t = Util.findDeepestThrowable(lvThrowable);
189     		return new ExceptionWrapper(t, true);
190     	} else {
191     		return pvResult;
192     	}
193     }
194     
195     /**
196      * This method is calling from the client side procy (Executor or Static-Proxy).
197      * It is converting from the <code>ExceptionWrapper</code> to the <code>Exception</code>.
198      * 
199      * @param pvResult Result of execution remote call (on the server side).
200      * @return The same result object (unchanged) 
201      * @throws Exception If the result is a map and in the map is a key: class and value 
202      * is equals ExceptionWrapper, than throw the server side created Exception.
203      */
204     public static Object isResultExceptionThanThrowIt (final Object pvResult) throws Exception {
205     	if (pvResult instanceof Map) {
206     		Map lvMap = (Map) pvResult;
207     		Object lvClassObj = lvMap.get("class");
208     		if ((lvClassObj != null) && lvClassObj.equals(ExceptionWrapper.class.getName())) {
209     			
210 //    			Map lvMapSimpleException = (Map) lvMap.get("simpleException");
211 //    			if (lvMapSimpleException != null) {
212 //    				lvMapSimpleException.remove("stackTrace");
213 //    			}
214     			
215     			Converter lvConverter = new Converter();
216     			lvConverter.setWithSimpleKeyMapper(true);
217     			Object o = lvConverter.makeComplex(lvMap);
218    				ExceptionWrapper lvExceptionWrapper = (ExceptionWrapper) o;
219    				throw lvExceptionWrapper.newExceptionInstance();
220     		}
221         }
222         else if (pvResult instanceof ExceptionWrapper) {
223    			ExceptionWrapper lvExceptionWrapper = (ExceptionWrapper) pvResult;
224    			throw lvExceptionWrapper.newExceptionInstance();        	
225         }
226         return pvResult;
227     }    
228 
229 }