1
2
3
4
5
6
7
8
9 package it.imolinfo.jbi4corba.jbi.cxf;
10
11 import it.imolinfo.jbi4corba.Logger;
12 import it.imolinfo.jbi4corba.LoggerFactory;
13 import it.imolinfo.jbi4corba.jbi.Messages;
14
15 import java.lang.reflect.Array;
16 import java.lang.reflect.Constructor;
17 import java.lang.reflect.Field;
18 import java.lang.reflect.GenericArrayType;
19 import java.lang.reflect.Method;
20 import java.lang.reflect.ParameterizedType;
21 import java.lang.reflect.Type;
22 import java.util.ArrayList;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.StringTokenizer;
27
28 import javax.xml.bind.JAXBContext;
29 import javax.xml.bind.JAXBElement;
30 import javax.xml.bind.Unmarshaller;
31 import javax.xml.bind.annotation.XmlAccessorType;
32 import javax.xml.namespace.QName;
33 import javax.xml.stream.XMLStreamConstants;
34 import javax.xml.stream.XMLStreamException;
35 import javax.xml.stream.XMLStreamReader;
36 import javax.xml.xpath.XPathConstants;
37
38 import org.apache.cxf.common.util.StringUtils;
39 import org.apache.cxf.databinding.DataBinding;
40 import org.apache.cxf.databinding.DataReader;
41 import org.apache.cxf.helpers.CastUtils;
42 import org.apache.cxf.helpers.DOMUtils;
43 import org.apache.cxf.helpers.XPathUtils;
44 import org.apache.cxf.interceptor.Fault;
45 import org.apache.cxf.jaxb.JAXBDataBinding;
46 import org.apache.cxf.message.Message;
47 import org.apache.cxf.phase.AbstractPhaseInterceptor;
48 import org.apache.cxf.phase.Phase;
49 import org.apache.cxf.service.Service;
50 import org.apache.cxf.service.model.BindingOperationInfo;
51 import org.apache.cxf.service.model.FaultInfo;
52 import org.apache.cxf.service.model.MessagePartInfo;
53 import org.apache.cxf.staxutils.StaxUtils;
54 import org.w3c.dom.Element;
55 import org.w3c.dom.Node;
56
57
58
59
60
61
62
63 @SuppressWarnings("unchecked")
64 public class Jbi4CorbaConsumerExceptionInterceptor extends
65 AbstractPhaseInterceptor<Message> {
66
67
68
69
70 private static final transient Logger LOG = LoggerFactory
71 .getLogger(Jbi4CorbaConsumerExceptionInterceptor.class);
72
73
74 @SuppressWarnings("unused")
75 private static final Messages MESSAGES =
76 Messages.getMessages(Jbi4CorbaConsumerExceptionInterceptor.class);
77
78 public Jbi4CorbaConsumerExceptionInterceptor() {
79 super(Phase.UNMARSHAL);
80 }
81
82 public Jbi4CorbaConsumerExceptionInterceptor(String phase) {
83 super(phase);
84 }
85
86 public void handleMessage(Message msg) {
87 Fault fault = (Fault) msg.getContent(Exception.class);
88
89 if (fault.getDetail() != null) {
90 processFaultDetail(fault, msg);
91 setStackTrace(fault, msg);
92 }
93 }
94
95 protected void processFaultDetail(Fault fault, Message msg) {
96 Element exDetail = (Element) DOMUtils.getChild(fault.getDetail(),
97 Node.ELEMENT_NODE);
98 if (exDetail == null) {
99 return;
100 }
101 QName qname = new QName(exDetail.getNamespaceURI(), exDetail
102 .getLocalName());
103 FaultInfo faultWanted = null;
104 MessagePartInfo part = null;
105 BindingOperationInfo boi = msg.getExchange().get(
106 BindingOperationInfo.class);
107 if (boi == null) {
108 return;
109 }
110 if (boi.isUnwrapped()) {
111 boi = boi.getWrappedOperation();
112 }
113 for (FaultInfo faultInfo : boi.getOperationInfo().getFaults()) {
114 for (MessagePartInfo mpi : faultInfo.getMessageParts()) {
115 if (qname.equals(mpi.getConcreteName())) {
116 faultWanted = faultInfo;
117 part = mpi;
118 break;
119 }
120 }
121 if (faultWanted != null) {
122 break;
123 }
124 }
125 if (faultWanted == null) {
126
127
128 for (FaultInfo faultInfo : boi.getOperationInfo().getFaults()) {
129 for (MessagePartInfo mpi : faultInfo.getMessageParts()) {
130 if (qname.getLocalPart().equals(
131 mpi.getConcreteName().getLocalPart())) {
132 faultWanted = faultInfo;
133 part = mpi;
134 break;
135 }
136 }
137 if (faultWanted != null) {
138 break;
139 }
140 }
141 }
142 if (faultWanted == null) {
143 return;
144 }
145 Service s = msg.getExchange().get(Service.class);
146 DataBinding dataBinding = s.getDataBinding();
147
148 Object e = null;
149 if (isDOMSupported(dataBinding)) {
150 DataReader<Node> reader = dataBinding.createReader(Node.class);
151 reader.setProperty(DataReader.FAULT, fault);
152 JAXBContext context = ((JAXBDataBinding) dataBinding).getContext();
153 try {
154 Unmarshaller unmarshaller = context.createUnmarshaller();
155 e = unmarshallException(unmarshaller, exDetail, part);
156
157 } catch (Exception ex) {
158 if (ex instanceof javax.xml.bind.UnmarshalException) {
159 javax.xml.bind.UnmarshalException unmarshalEx = (javax.xml.bind.UnmarshalException) ex;
160 throw new Fault(unmarshalEx);
161 } else {
162 throw new Fault(ex);
163 }
164 }
165 }
166
167 LOG.debug("Returned object of class:" + e.getClass().getName());
168 if (!(e instanceof Exception)) {
169
170 try {
171 Class<?> exClass = faultWanted.getProperty(Class.class
172 .getName(), Class.class);
173 LOG.debug("ExClass exClass:" + exClass.getName());
174 if (e == null) {
175 Constructor constructor = exClass
176 .getConstructor(new Class[] { String.class });
177 e = constructor.newInstance(new Object[] { fault
178 .getMessage() });
179 } else {
180 Constructor constructor = getConstructor(exClass, e);
181 e = constructor.newInstance(new Object[] {
182 fault.getMessage(), e });
183 LOG.debug("After newInstance");
184 }
185 msg.setContent(Exception.class, e);
186 } catch (Throwable e1) {
187 e1.printStackTrace();
188 String errmsg = MESSAGES.getString("CRB000901_Exception_while_creating_exception");
189 LOG.debug(errmsg, e1.getMessage());
190 }
191 } else if (e != null) {
192 if (fault.getMessage() != null) {
193 Field f;
194 try {
195 f = Throwable.class.getDeclaredField("detailMessage");
196 f.setAccessible(true);
197 f.set(e, fault.getMessage());
198 } catch (Exception e1) {
199 String errmsg = MESSAGES.getString("CRB000902_Exception_in_fault_processing");
200 LOG.debug(errmsg, e1.getMessage());
201 }
202 }
203 msg.setContent(Exception.class, e);
204 }
205 }
206
207 private Constructor getConstructor(Class<?> faultClass, Object e)
208 throws NoSuchMethodException {
209 Class<?> beanClass = e.getClass();
210 Constructor cons[] = faultClass.getConstructors();
211 for (Constructor c : cons) {
212 if (c.getParameterTypes().length == 2
213 && String.class.equals(c.getParameterTypes()[0])
214 && c.getParameterTypes()[1].isInstance(e)) {
215 LOG.debug("Found constructor: " + c);
216 LOG.debug("The second parameter type is: " + c.getParameterTypes()[1]);
217 return c;
218 }
219 }
220 try {
221 LOG.debug("Found constructor directly");
222 return faultClass.getConstructor(new Class[] { String.class,
223 beanClass });
224 } catch (NoSuchMethodException ex) {
225 ex.printStackTrace();
226 Class<?> cls = getPrimitiveClass(beanClass);
227 if (cls != null) {
228 LOG.debug("Uses the primitive class: " + cls);
229 return faultClass.getConstructor(new Class[] { String.class,
230 cls });
231 } else {
232 throw ex;
233 }
234 }
235
236 }
237
238 private boolean isDOMSupported(DataBinding db) {
239 boolean supportsDOM = false;
240 for (Class c : db.getSupportedReaderFormats()) {
241 if (c.equals(Node.class)) {
242 supportsDOM = true;
243 }
244 }
245 return supportsDOM;
246 }
247
248 private void setStackTrace(Fault fault, Message msg) {
249 Map<String, String> ns = new HashMap<String, String>();
250 XPathUtils xu = new XPathUtils(ns);
251 String ss = (String) xu.getValue("/" + Fault.STACKTRACE + "/text()",
252 fault.getDetail(), XPathConstants.STRING);
253 List<StackTraceElement> stackTraceList = new ArrayList<StackTraceElement>();
254 if (!StringUtils.isEmpty(ss)) {
255 StringTokenizer st = new StringTokenizer(ss, "\n");
256 while (st.hasMoreTokens()) {
257 String oneLine = st.nextToken();
258 StringTokenizer stInner = new StringTokenizer(oneLine, "!");
259 StackTraceElement ste = new StackTraceElement(stInner
260 .nextToken(), stInner.nextToken(), stInner.nextToken(),
261 Integer.parseInt(stInner.nextToken()));
262 stackTraceList.add(ste);
263 }
264 if (stackTraceList.size() > 0) {
265 StackTraceElement[] stackTraceElement = new StackTraceElement[stackTraceList
266 .size()];
267 Exception e = msg.getContent(Exception.class);
268 e.setStackTrace(stackTraceList.toArray(stackTraceElement));
269 }
270 }
271
272 }
273
274 private Class<?> getPrimitiveClass(Class<?> cls) {
275 if (cls.isPrimitive()) {
276 return cls;
277 }
278 try {
279 Field field = cls.getField("TYPE");
280 Object obj = (Object) cls;
281 Object type = field.get(obj);
282 if (type instanceof Class) {
283 return (Class) type;
284 }
285 } catch (Exception e) {
286 String errmsg = MESSAGES.getString("CRB000902_Exception_in_fault_processing");
287 LOG.error(errmsg, e.getMessage());
288 }
289 return null;
290 }
291
292
293
294
295
296
297
298
299 public static Object unmarshallException(Unmarshaller u, Object source,
300 MessagePartInfo part) {
301 XMLStreamReader reader = null;
302 Object obj = null;
303 try {
304 if (source instanceof XMLStreamReader) {
305 reader = (XMLStreamReader) source;
306 } else if (source instanceof Element) {
307 reader = StaxUtils.createXMLStreamReader((Element) source);
308 try {
309
310 reader.nextTag();
311 } catch (XMLStreamException e) {
312 String errmsg = MESSAGES.getString("CRB000903_Exception_in_exception_unmarshalling");
313 LOG.error(errmsg, e.getMessage());
314 }
315 } else {
316 String errmsg = MESSAGES.getString("CRB000904_Wrong_source_type_in_Exception_unmarshalling");
317 LOG.error(errmsg);
318 }
319
320 QName qn = part.getElementQName();
321 if (!qn.equals(reader.getName())) {
322 String errmsg = MESSAGES.getString("CRB000905_Element_name_mismatch_in_Exception_unmarshalling");
323 LOG.error(errmsg);
324 }
325
326 Class<?> cls = part.getTypeClass();
327
328 try {
329 Constructor cons = cls.getConstructor();
330 obj = cons.newInstance();
331 } catch (NoSuchMethodException nse) {
332 Constructor cons = cls
333 .getConstructor(new Class[] { String.class });
334 obj = cons.newInstance(new Object[1]);
335 }
336
337 XmlAccessorType accessorType = cls
338 .getAnnotation(XmlAccessorType.class);
339 if (accessorType == null && cls.getPackage() != null) {
340 accessorType = cls.getPackage().getAnnotation(
341 XmlAccessorType.class);
342 }
343
344
345 reader.nextTag();
346 while (reader.getEventType() == XMLStreamReader.START_ELEMENT) {
347 QName q = reader.getName();
348
349 String s = Character.toUpperCase(q.getLocalPart().charAt(0))
350 + q.getLocalPart().substring(1);
351 Method m = null;
352 try {
353 m = cls.getMethod("get" + s);
354 } catch (NoSuchMethodException mex) {
355 m = cls.getMethod("is" + s);
356 }
357 Type type = m.getGenericReturnType();
358 Method m2 = cls.getMethod("set" + s, m.getReturnType());
359 if (isArray(type)) {
360 Class<?> compType = getArrayComponentType(type);
361 List<Object> ret = unmarshallArray(u, reader, q, compType,
362 createList(type));
363 Object o = ret;
364 if (!isList(type)) {
365 if (compType.isPrimitive()) {
366 o = java.lang.reflect.Array.newInstance(compType,
367 ret.size());
368 for (int x = 0; x < ret.size(); x++) {
369 Array.set(o, x, ret.get(x));
370 }
371 } else {
372 o = ret.toArray((Object[]) Array.newInstance(
373 compType, ret.size()));
374 }
375 }
376
377 m2.invoke(obj, o);
378 } else {
379 Object o = getElementValue(u.unmarshal(reader, m
380 .getReturnType()));
381 m2.invoke(obj, o);
382 }
383 }
384 } catch (Exception ex) {
385 ex.printStackTrace();
386 }
387 return obj;
388
389 }
390
391 static boolean isArray(Type cls) {
392 if (cls instanceof Class) {
393 return ((Class) cls).isArray();
394 } else if (cls instanceof ParameterizedType) {
395 return true;
396 } else if (cls instanceof GenericArrayType) {
397 return true;
398 }
399 return false;
400 }
401
402 static Class<?> getArrayComponentType(Type cls) {
403 if (cls instanceof Class) {
404 if (((Class) cls).isArray()) {
405 return ((Class) cls).getComponentType();
406 } else {
407 return (Class) cls;
408 }
409 } else if (cls instanceof ParameterizedType) {
410 for (Type t2 : ((ParameterizedType) cls).getActualTypeArguments()) {
411 return getArrayComponentType(t2);
412 }
413 } else if (cls instanceof GenericArrayType) {
414 GenericArrayType gt = (GenericArrayType) cls;
415 Class ct = (Class) gt.getGenericComponentType();
416 return Array.newInstance(ct, 0).getClass();
417 }
418 return null;
419 }
420
421 private static List<Object> createList(Type genericType) {
422 if (genericType instanceof ParameterizedType) {
423 Type tp2 = ((ParameterizedType) genericType).getRawType();
424 if (tp2 instanceof Class) {
425 Class<?> cls = (Class) tp2;
426 if (!cls.isInterface()
427 && List.class.isAssignableFrom((Class<?>) cls)) {
428 try {
429 return CastUtils.cast((List) cls.newInstance());
430 } catch (Exception e) {
431
432 String errmsg = MESSAGES.getString("CRB000906_Exception_in_list_exception_unmarshalling");
433 LOG.warn(errmsg, e.getMessage());
434 }
435 }
436 }
437 }
438 return new ArrayList<Object>();
439 }
440
441 public static List<Object> unmarshallArray(Unmarshaller u, Object source,
442 QName elName, Class<?> clazz, List<Object> ret) throws Exception {
443 try {
444 XMLStreamReader reader = null;
445 if (source instanceof XMLStreamReader) {
446 reader = (XMLStreamReader) source;
447 } else if (source instanceof Element) {
448 reader = StaxUtils.createXMLStreamReader((Element) source);
449 } else {
450
451 String errmsg = MESSAGES.getString("CRB000907_Should_be_XMLStreamReader_or_Element");
452 LOG.error(errmsg);
453 }
454 while (reader.getName().equals(elName)) {
455 Object obj = u.unmarshal(reader, clazz);
456 if (obj instanceof JAXBElement) {
457 obj = ((JAXBElement) obj).getValue();
458 }
459 ret.add(obj);
460 while (reader.getEventType() != XMLStreamConstants.START_ELEMENT
461 && reader.getEventType() != XMLStreamConstants.END_ELEMENT) {
462 reader.nextTag();
463 }
464 }
465 return ret;
466 } catch (Fault ex) {
467 ex.fillInStackTrace();
468 throw ex;
469 } catch (Exception ex) {
470 if (ex instanceof javax.xml.bind.UnmarshalException) {
471 javax.xml.bind.UnmarshalException unmarshalEx = (javax.xml.bind.UnmarshalException) ex;
472 throw new Fault(unmarshalEx);
473
474 } else {
475 throw new Fault(ex);
476 }
477 }
478 }
479
480 private static boolean isList(Type cls) {
481 if (cls instanceof ParameterizedType) {
482 return true;
483 }
484 return false;
485 }
486
487 public static Object getElementValue(Object obj) {
488 if (null == obj) {
489 return null;
490 }
491
492 if (obj instanceof JAXBElement) {
493 return ((JAXBElement<?>) obj).getValue();
494 }
495 return obj;
496 }
497
498 }