1 package org.objectweb.celtix.bus.jaxws; 2 3 import java.io.StringWriter ; 4 import java.lang.reflect.Array ; 5 import java.lang.reflect.GenericArrayType ; 6 import java.lang.reflect.Method ; 7 import java.lang.reflect.ParameterizedType ; 8 import java.lang.reflect.Type ; 9 import java.util.HashSet ; 10 import java.util.Map ; 11 import java.util.Set ; 12 import java.util.concurrent.ConcurrentHashMap ; 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 ; 26 import javax.xml.validation.Schema ; 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 ; 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 43 public final class JAXBEncoderDecoder { 44 45 static Map <Class , JAXBContext> contextMap = new ConcurrentHashMap <Class , JAXBContext>(); 46 47 private JAXBEncoderDecoder() { 48 } 49 50 public static JAXBContext createJAXBContextForClass(Class cls) throws JAXBException { 51 JAXBContext context = contextMap.get(cls); 52 if (context == null) { 53 Set <Class > classes = new HashSet <Class >(); 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 [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 getValidClass(Class 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 .class || cls == String .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 [0]) == null) { 84 cls = null; 85 } 86 } catch (NoSuchMethodException ex) { 87 cls = null; 88 } 89 } 90 return cls; 91 } 92 private static void addClass(Class cls, Set <Class > classes) { 93 if (cls.isArray()) { 94 classes.add(cls); 95 return; 96 102 } 103 cls = getValidClass(cls); 104 if (null != cls) { 105 if (cls.isEnum()) { 106 classes.add(cls); 108 } 109 String 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 ex) { 116 classes.add(cls); 118 } 119 } 120 } 121 private static void addType(Type cls, Set <Class > classes) { 122 if (cls instanceof Class ) { 123 addClass((Class )cls, classes); 124 } else if (cls instanceof ParameterizedType ) { 125 for (Type t2 : ((ParameterizedType )cls).getActualTypeArguments()) { 126 addType(t2, classes); 127 } 128 } else if (cls instanceof GenericArrayType ) { 129 GenericArrayType gt = (GenericArrayType )cls; 130 addType(gt.getGenericComponentType(), classes); 131 } 132 } 133 134 private static void getClassesForContext(Class <?> theClass, Set <Class > classes, ClassLoader loader) { 136 Method methods[] = theClass.getMethods(); 137 for (Method meth : methods) { 138 WebMethod webMethod = meth.getAnnotation(WebMethod.class); 140 if (webMethod == null) { 141 continue; 142 } 143 144 for (Type 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 cls : meth.getParameterTypes()) { 153 addClass(cls, classes); 154 } 155 156 for (Class <?> cls : meth.getExceptionTypes()) { 157 try { 159 Method fim = cls.getMethod("getFaultInfo", new Class [0]); 160 addClass(fim.getReturnType(), classes); 161 } catch (NoSuchMethodException ex) { 162 } 164 } 165 try { 166 RequestWrapper reqWrapper = meth.getAnnotation(RequestWrapper.class); 168 if (reqWrapper != null) { 169 Class cls = Class.forName(reqWrapper.className(), false, 170 loader); 171 addClass(cls, classes); 172 } 173 ResponseWrapper respWrapper = meth.getAnnotation(ResponseWrapper.class); 175 if (respWrapper != null) { 176 Class cls = Class.forName(respWrapper.className(), 177 false, 178 loader); 179 addClass(cls, classes); 180 } 181 } catch (ClassNotFoundException ex) { 182 } 184 } 185 186 for (Class 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 schema, 195 Object elValue, QName elNname, Node destNode) { 196 197 try { 198 if (context == null) { 199 context = JAXBContext.newInstance(elValue.getClass()); 200 } 201 Object 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 packageName = elValue.getClass().getPackage().getName(); 208 Class <?> objectFactory = Class.forName(packageName + ".ObjectFactory", false, 209 elValue.getClass().getClassLoader()); 210 211 Method methods[] = objectFactory.getDeclaredMethods(); 212 for (Method 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 elementType = new QName (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 [] {QName .class, Class .class, Object .class}) 228 .newInstance(elNname, mObj.getClass(), mObj); 229 } 230 u.setSchema(schema); 231 u.marshal(mObj, destNode); 232 } catch (MarshalException me) { 233 String message = "Marshalling error "; 236 if (me.getCause() != null) { 237 message += me.getCause(); 238 } 239 throw new ProtocolException(message, me); 240 } catch (Exception ex) { 241 throw new ProtocolException("Marshalling Error", ex); 242 } 243 } 244 245 public static Object unmarshall(JAXBContext context, Schema schema, 246 Node srcNode, QName elName, Class <?> clazz) { 247 Object 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 String message = "Unmarshalling error "; 267 if (ue.getCause() != null) { 268 message += ue.getCause(); 269 } 270 throw new ProtocolException(message, ue); 271 } catch (Exception ex) { 272 throw new ProtocolException("Unmarshalling error", ex); 273 } 274 return obj; 275 } 276 277 private static boolean isSame(QName messageQName, QName 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 unmarshall(JAXBContext context, Schema schema, Node srcNode, QName elName) { 288 Object 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 String message = "Unmarshalling error "; 305 if (ue.getCause() != null) { 306 message += ue.getCause(); 307 } 308 throw new ProtocolException(message, ue); 309 310 } catch (Exception ex) { 311 throw new ProtocolException("Unmarshalling error", ex); 312 } 313 return obj; 314 } 315 316 public static Class getClassFromType(Type t) { 317 if (t instanceof Class ) { 318 return (Class )t; 319 } else if (t instanceof GenericArrayType ) { 320 GenericArrayType g = (GenericArrayType )t; 321 return Array.newInstance(getClassFromType(g.getGenericComponentType()), 0).getClass(); 322 } else if (t instanceof ParameterizedType ) { 323 ParameterizedType p = (ParameterizedType )t; 324 return getClassFromType(p.getRawType()); 325 } 326 assert false; 329 throw new IllegalArgumentException ("Cannot get Class object from unknown Type"); 330 } 331 332 public static String toString(Object obj) throws JAXBException { 333 String name = obj.getClass().getPackage().getName(); 334 JAXBContext context = JAXBContext.newInstance(name); 335 JAXBElement<Object > el = new JAXBElement<Object >(new QName ("test"), Object .class, obj); 336 Marshaller m = context.createMarshaller(); 337 StringWriter writer = new StringWriter (); 338 m.marshal(el, writer); 339 340 return writer.toString(); 341 } 342 } 343 | Popular Tags |