KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > celtix > bus > jaxws > JAXBEncoderDecoder


1 package org.objectweb.celtix.bus.jaxws;
2
3 import java.io.StringWriter JavaDoc;
4 import java.lang.reflect.Array JavaDoc;
5 import java.lang.reflect.GenericArrayType JavaDoc;
6 import java.lang.reflect.Method JavaDoc;
7 import java.lang.reflect.ParameterizedType JavaDoc;
8 import java.lang.reflect.Type JavaDoc;
9 import java.util.HashSet JavaDoc;
10 import java.util.Map JavaDoc;
11 import java.util.Set JavaDoc;
12 import java.util.concurrent.ConcurrentHashMap JavaDoc;
13
14 import javax.jws.WebMethod;
15 import javax.xml.bind.JAXBContext;
16 import javax.xml.bind.JAXBElement;
17 import javax.xml.bind.JAXBException;
18 import javax.xml.bind.MarshalException;
19 import javax.xml.bind.Marshaller;
20 import javax.xml.bind.UnmarshalException;
21 import javax.xml.bind.Unmarshaller;
22
23 import javax.xml.bind.annotation.XmlElementDecl;
24 import javax.xml.bind.annotation.XmlRootElement;
25 import javax.xml.namespace.QName JavaDoc;
26 import javax.xml.validation.Schema JavaDoc;
27 import javax.xml.ws.Holder;
28 import javax.xml.ws.ProtocolException;
29 import javax.xml.ws.RequestWrapper;
30 import javax.xml.ws.ResponseWrapper;
31
32 import org.w3c.dom.Node JavaDoc;
33
34 import org.objectweb.celtix.common.util.StringUtils;
35 import org.objectweb.celtix.ws.addressing.wsdl.AttributedQNameType;
36 import org.objectweb.celtix.ws.addressing.wsdl.ObjectFactory;
37 import org.objectweb.celtix.ws.addressing.wsdl.ServiceNameType;
38
39 /**
40  * JAXBEncoderDecoder
41  * @author apaibir
42  */

43 public final class JAXBEncoderDecoder {
44     
45     static Map JavaDoc<Class JavaDoc, JAXBContext> contextMap = new ConcurrentHashMap JavaDoc<Class JavaDoc, JAXBContext>();
46     
47     private JAXBEncoderDecoder() {
48     }
49     
50     public static JAXBContext createJAXBContextForClass(Class JavaDoc cls) throws JAXBException {
51         JAXBContext context = contextMap.get(cls);
52         if (context == null) {
53             Set JavaDoc<Class JavaDoc> classes = new HashSet JavaDoc<Class JavaDoc>();
54             getClassesForContext(cls, classes, cls.getClassLoader());
55             classes.add(AttributedQNameType.class);
56             classes.add(ServiceNameType.class);
57             classes.add(ObjectFactory.class);
58             try {
59                 context = JAXBContext.newInstance(classes.toArray(new Class JavaDoc[classes.size()]));
60                 contextMap.put(cls, context);
61             } catch (JAXBException ex) {
62                 throw ex;
63             }
64         }
65         return context;
66     }
67     
68     private static Class JavaDoc getValidClass(Class JavaDoc cls) {
69         if (cls.isEnum()) {
70             return cls;
71         }
72         if (cls.isArray()) {
73             return getValidClass(cls.getComponentType());
74         }
75
76         if (cls == Holder.class || cls == Object JavaDoc.class || cls == String JavaDoc.class) {
77             cls = null;
78         } else if (cls.isPrimitive() || cls.isInterface() || cls.isAnnotation()) {
79             cls = null;
80         }
81         if (cls != null) {
82             try {
83                 if (cls.getConstructor(new Class JavaDoc[0]) == null) {
84                     cls = null;
85                 }
86             } catch (NoSuchMethodException JavaDoc ex) {
87                 cls = null;
88             }
89         }
90         return cls;
91     }
92     private static void addClass(Class JavaDoc cls, Set JavaDoc<Class JavaDoc> classes) {
93         if (cls.isArray()) {
94             classes.add(cls);
95             return;
96             /*
97             Class c2 = getValidClass(cls);
98             if (c2 != null) {
99                 classes.add(cls);
100                 return;
101             }*/

102         }
103         cls = getValidClass(cls);
104         if (null != cls) {
105             if (cls.isEnum()) {
106                 // The object factory stuff doesn't work for enums
107
classes.add(cls);
108             }
109             String JavaDoc name = cls.getPackage().getName() + ".ObjectFactory";
110             try {
111                 cls = Class.forName(name, false, cls.getClassLoader());
112                 if (cls != null) {
113                     classes.add(cls);
114                 }
115             } catch (ClassNotFoundException JavaDoc ex) {
116                 //cannot add factory, just add the class
117
classes.add(cls);
118             }
119         }
120     }
121     private static void addType(Type JavaDoc cls, Set JavaDoc<Class JavaDoc> classes) {
122         if (cls instanceof Class JavaDoc) {
123             addClass((Class JavaDoc)cls, classes);
124         } else if (cls instanceof ParameterizedType JavaDoc) {
125             for (Type JavaDoc t2 : ((ParameterizedType JavaDoc)cls).getActualTypeArguments()) {
126                 addType(t2, classes);
127             }
128         } else if (cls instanceof GenericArrayType JavaDoc) {
129             GenericArrayType JavaDoc gt = (GenericArrayType JavaDoc)cls;
130             addType(gt.getGenericComponentType(), classes);
131         }
132     }
133     
134     //collect ALL the classes that are accessed by the class
135
private static void getClassesForContext(Class JavaDoc<?> theClass, Set JavaDoc<Class JavaDoc> classes, ClassLoader JavaDoc loader) {
136         Method JavaDoc methods[] = theClass.getMethods();
137         for (Method JavaDoc meth : methods) {
138             //only methods marked as WebMethods are interesting to us
139
WebMethod webMethod = meth.getAnnotation(WebMethod.class);
140             if (webMethod == null) {
141                 continue;
142             }
143             
144             for (Type JavaDoc t : meth.getGenericParameterTypes()) {
145                 addType(t, classes);
146             }
147             addType(meth.getGenericReturnType(), classes);
148             
149             if (meth.getReturnType().isArray()) {
150                 addClass(meth.getReturnType(), classes);
151             }
152             for (Class JavaDoc cls : meth.getParameterTypes()) {
153                 addClass(cls, classes);
154             }
155             
156             for (Class JavaDoc<?> cls : meth.getExceptionTypes()) {
157                 //addClass(cls, classes);
158
try {
159                     Method JavaDoc fim = cls.getMethod("getFaultInfo", new Class JavaDoc[0]);
160                     addClass(fim.getReturnType(), classes);
161                 } catch (NoSuchMethodException JavaDoc ex) {
162                     //ignore - not a valid JAXB fault thing
163
}
164             }
165             try {
166                 //Get the RequestWrapper
167
RequestWrapper reqWrapper = meth.getAnnotation(RequestWrapper.class);
168                 if (reqWrapper != null) {
169                     Class JavaDoc cls = Class.forName(reqWrapper.className(), false,
170                                         loader);
171                     addClass(cls, classes);
172                 }
173                 //Get the RequestWrapper
174
ResponseWrapper respWrapper = meth.getAnnotation(ResponseWrapper.class);
175                 if (respWrapper != null) {
176                     Class JavaDoc cls = Class.forName(respWrapper.className(),
177                                               false,
178                                               loader);
179                     addClass(cls, classes);
180                 }
181             } catch (ClassNotFoundException JavaDoc ex) {
182                 //ignore
183
}
184         }
185
186         for (Class JavaDoc intf : theClass.getInterfaces()) {
187             getClassesForContext(intf, classes, loader);
188         }
189         if (theClass.getSuperclass() != null) {
190             getClassesForContext(theClass.getSuperclass(), classes, loader);
191         }
192     }
193     
194     public static void marshall(JAXBContext context, Schema JavaDoc schema,
195                                 Object JavaDoc elValue, QName JavaDoc elNname, Node JavaDoc destNode) {
196         
197         try {
198             if (context == null) {
199                 context = JAXBContext.newInstance(elValue.getClass());
200             }
201             Object JavaDoc mObj = elValue;
202             Marshaller u = context.createMarshaller();
203             u.setProperty(Marshaller.JAXB_ENCODING , "UTF-8");
204             u.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
205
206             if (elValue.getClass().isAnnotationPresent(XmlRootElement.class)) {
207                 String JavaDoc packageName = elValue.getClass().getPackage().getName();
208                 Class JavaDoc<?> objectFactory = Class.forName(packageName + ".ObjectFactory", false,
209                                                        elValue.getClass().getClassLoader());
210
211                 Method JavaDoc methods[] = objectFactory.getDeclaredMethods();
212                 for (Method JavaDoc method : methods) {
213                     if (method.getParameterTypes().length == 1
214                         && method.getParameterTypes()[0].equals(elValue.getClass())) {
215
216                         XmlElementDecl elementDecl = method.getAnnotation(XmlElementDecl.class);
217                         if (null != elementDecl) {
218                             QName JavaDoc elementType = new QName JavaDoc(elementDecl.namespace(), elementDecl.name());
219                             if (elementType.equals(elNname)) {
220                                 mObj = method.invoke(objectFactory.newInstance(),
221                                                     elValue);
222                             }
223                         }
224                     }
225                 }
226             } else {
227                 mObj = JAXBElement.class.getConstructor(new Class JavaDoc[] {QName JavaDoc.class, Class JavaDoc.class, Object JavaDoc.class})
228                     .newInstance(elNname, mObj.getClass(), mObj);
229             }
230             u.setSchema(schema);
231             u.marshal(mObj, destNode);
232         } catch (MarshalException me) {
233             // It's helpful to include the cause in the case of
234
// schema validation exceptions.
235
String JavaDoc message = "Marshalling error ";
236             if (me.getCause() != null) {
237                 message += me.getCause();
238             }
239             throw new ProtocolException(message, me);
240         } catch (Exception JavaDoc ex) {
241             throw new ProtocolException("Marshalling Error", ex);
242         }
243     }
244     
245     public static Object JavaDoc unmarshall(JAXBContext context, Schema JavaDoc schema,
246                                     Node JavaDoc srcNode, QName JavaDoc elName, Class JavaDoc<?> clazz) {
247         Object JavaDoc obj = null;
248         try {
249             if (context == null) {
250                 context = JAXBContext.newInstance(clazz);
251             }
252             Unmarshaller u = context.createUnmarshaller();
253             u.setSchema(schema);
254
255             obj = (clazz != null) ? u.unmarshal(srcNode, clazz) : u.unmarshal(srcNode);
256             
257             if (obj instanceof JAXBElement<?>) {
258                 JAXBElement<?> el = (JAXBElement<?>)obj;
259                 if (isSame(el.getName(), elName)) {
260                     obj = el.getValue();
261                 }
262             }
263         } catch (UnmarshalException ue) {
264             // It's helpful to include the cause in the case of
265
// schema validation exceptions.
266
String JavaDoc message = "Unmarshalling error ";
267             if (ue.getCause() != null) {
268                 message += ue.getCause();
269             }
270             throw new ProtocolException(message, ue);
271         } catch (Exception JavaDoc ex) {
272             throw new ProtocolException("Unmarshalling error", ex);
273         }
274         return obj;
275     }
276
277     private static boolean isSame(QName JavaDoc messageQName, QName JavaDoc methodQName) {
278         boolean same = false;
279         if (StringUtils.isEmpty(messageQName.getNamespaceURI())) {
280             same = messageQName.getLocalPart().equals(methodQName.getLocalPart());
281         } else {
282             same = messageQName.equals(methodQName);
283         }
284         return same;
285     }
286
287     public static Object JavaDoc unmarshall(JAXBContext context, Schema JavaDoc schema, Node JavaDoc srcNode, QName JavaDoc elName) {
288         Object JavaDoc obj = null;
289         try {
290             Unmarshaller u = context.createUnmarshaller();
291             u.setSchema(schema);
292
293             obj = u.unmarshal(srcNode);
294             
295             if (obj instanceof JAXBElement<?>) {
296                 JAXBElement<?> el = (JAXBElement<?>)obj;
297                 if (el.getName().equals(elName)) {
298                     obj = el.getValue();
299                 }
300             }
301         } catch (UnmarshalException ue) {
302             // It's helpful to include the cause in the case of
303
// schema validation exceptions.
304
String JavaDoc message = "Unmarshalling error ";
305             if (ue.getCause() != null) {
306                 message += ue.getCause();
307             }
308             throw new ProtocolException(message, ue);
309             
310         } catch (Exception JavaDoc ex) {
311             throw new ProtocolException("Unmarshalling error", ex);
312         }
313         return obj;
314     }
315     
316     public static Class JavaDoc getClassFromType(Type JavaDoc t) {
317         if (t instanceof Class JavaDoc) {
318             return (Class JavaDoc)t;
319         } else if (t instanceof GenericArrayType JavaDoc) {
320             GenericArrayType JavaDoc g = (GenericArrayType JavaDoc)t;
321             return Array.newInstance(getClassFromType(g.getGenericComponentType()), 0).getClass();
322         } else if (t instanceof ParameterizedType JavaDoc) {
323             ParameterizedType JavaDoc p = (ParameterizedType JavaDoc)t;
324             return getClassFromType(p.getRawType());
325         }
326         //TypeVariable and WildCardType are not handled as it is unlikely such Types will
327
// JAXB Code Generated.
328
assert false;
329         throw new IllegalArgumentException JavaDoc("Cannot get Class object from unknown Type");
330     }
331     
332     public static String JavaDoc toString(Object JavaDoc obj) throws JAXBException {
333         String JavaDoc name = obj.getClass().getPackage().getName();
334         JAXBContext context = JAXBContext.newInstance(name);
335         JAXBElement<Object JavaDoc> el = new JAXBElement<Object JavaDoc>(new QName JavaDoc("test"), Object JavaDoc.class, obj);
336         Marshaller m = context.createMarshaller();
337         StringWriter JavaDoc writer = new StringWriter JavaDoc();
338         m.marshal(el, writer);
339
340         return writer.toString();
341     }
342 }
343
Popular Tags