1 29 30 package com.caucho.jaxb.skeleton; 31 32 import com.caucho.jaxb.JAXBContextImpl; 33 import com.caucho.jaxb.JAXBUtil; 34 import com.caucho.util.L10N; 35 36 import javax.xml.bind.JAXBException; 37 import javax.xml.bind.Marshaller; 38 import javax.xml.bind.Unmarshaller; 39 import javax.xml.bind.annotation.*; 40 41 import javax.xml.namespace.QName ; 42 43 import javax.xml.stream.XMLStreamException; 44 import javax.xml.stream.XMLStreamReader; 45 import javax.xml.stream.XMLStreamWriter; 46 47 import java.beans.BeanInfo ; 48 import java.beans.Introspector ; 49 import java.beans.PropertyDescriptor ; 50 51 import java.io.IOException ; 52 53 import java.lang.reflect.AccessibleObject ; 54 import java.lang.reflect.Constructor ; 55 import java.lang.reflect.Field ; 56 import java.lang.reflect.InvocationTargetException ; 57 import java.lang.reflect.Method ; 58 import java.lang.reflect.Modifier ; 59 60 import java.util.Collection ; 61 import java.util.HashMap ; 62 import java.util.List ; 63 import java.util.Set ; 64 import java.util.logging.Logger ; 65 66 public class ClassSkeleton<C> extends Skeleton { 67 public static final String XML_SCHEMA_NS = "http://www.w3.org/2001/XMLSchema"; 68 public static final String XML_SCHEMA_PREFIX = "xsd"; 69 70 private static final L10N L = new L10N(ClassSkeleton.class); 71 private static final Logger log = Logger.getLogger(Skeleton.class.getName()); 72 73 private static final Class [] NO_PARAMS = new Class [0]; 74 private static final Object [] NO_ARGS = new Object [0]; 75 76 private Class <C> _class; 77 78 private Method _beforeUnmarshal; 79 private Method _afterUnmarshal; 80 private Method _beforeMarshal; 81 private Method _afterMarshal; 82 83 private QName _elementName; 84 85 private Constructor _constructor; 86 87 91 private Accessor _value; 92 93 public Class <C> getType() 94 { 95 return _class; 96 } 97 98 public String toString() 99 { 100 return "ClassSkeleton[" + _class + "]"; 101 } 102 103 public ClassSkeleton(JAXBContextImpl context, Class <C> c) 104 throws JAXBException 105 { 106 super(context); 107 108 try { 109 _class = c; 110 111 try { 112 _beforeUnmarshal = 113 c.getMethod("beforeUnmarshal", Unmarshaller.class, Object .class); 114 } catch (NoSuchMethodException _) { 115 } 117 118 try { 119 _afterUnmarshal = 120 c.getMethod("afterUnmarshal", Unmarshaller.class, Object .class); 121 } catch (NoSuchMethodException _) { 122 } 124 125 try { 126 _beforeMarshal = 127 c.getMethod("beforeMarshal", Marshaller.class, Object .class); 128 } catch (NoSuchMethodException _) { 129 } 131 132 try { 133 _afterMarshal = 134 c.getMethod("afterMarshal", Marshaller.class, Object .class); 135 } catch (NoSuchMethodException _) { 136 } 138 139 140 if (List .class.isAssignableFrom(_class)) { 141 } 143 if (Set .class.isAssignableFrom(_class)) { 144 } 146 if (HashMap .class.isAssignableFrom(_class)) { 147 } 149 150 152 try { 154 _constructor = c.getConstructor(NO_PARAMS); 155 _constructor.setAccessible(true); 156 } 157 catch (Exception e1) { 158 try { 159 _constructor = c.getDeclaredConstructor(NO_PARAMS); 160 _constructor.setAccessible(true); 161 } 162 catch (Exception e2) { 163 throw new JAXBException(L.l("Zero-arg constructor not found for class {0}", c.getName()), e2); 164 } 165 } 166 167 _typeName = new QName (JAXBUtil.getXmlSchemaDatatype(_class)); 168 169 if (c.isAnnotationPresent(XmlRootElement.class)) { 170 XmlRootElement xre = c.getAnnotation(XmlRootElement.class); 171 172 String localName = null; 173 174 if ("##default".equals(xre.name())) 175 localName = JAXBUtil.identifierToXmlName(_class); 176 else 177 localName = xre.name(); 178 179 if ("##default".equals(xre.namespace())) 180 _elementName = new QName (localName); 181 else 182 _elementName = new QName (xre.namespace(), localName); 183 184 _typeName = _elementName; 185 186 _context.addRootElement(this); 187 } 188 189 XmlAccessorType accessorType = c.getAnnotation(XmlAccessorType.class); 190 XmlAccessType accessType = (accessorType == null ? 191 XmlAccessType.PUBLIC_MEMBER : 192 accessorType.value()); 193 194 if (accessType != XmlAccessType.FIELD) { 195 BeanInfo beanInfo = Introspector.getBeanInfo(c); 197 198 for (PropertyDescriptor property : beanInfo.getPropertyDescriptors()) { 199 if ("class".equals(property.getName())) 202 continue; 203 204 Method get = property.getReadMethod(); 205 Method set = property.getWriteMethod(); 206 207 if (property.getPropertyType() == null) { 208 continue; 209 } 210 211 if (get != null && get.isAnnotationPresent(XmlTransient.class)) 212 continue; 213 if (set != null && set.isAnnotationPresent(XmlTransient.class)) 214 continue; 215 216 addAccessor(new GetterSetterAccessor(property, _context)); 217 } 218 } 219 220 if (accessType != XmlAccessType.PROPERTY) { 221 Field [] fields = c.getDeclaredFields(); 222 AccessibleObject.setAccessible(fields, true); 223 224 for (Field f : fields) { 225 if (Modifier.isStatic(f.getModifiers())) 226 continue; 227 if (f.isAnnotationPresent(XmlTransient.class)) 228 continue; 229 231 if (accessType == XmlAccessType.PUBLIC_MEMBER 232 && ! Modifier.isPublic(f.getModifiers())) 233 continue; 234 235 237 addAccessor(new FieldAccessor(f, _context)); 238 } 239 } 240 } 241 catch (Exception e) { 242 throw new JAXBException(e); 243 } 244 } 245 246 private void addAccessor(Accessor a) 247 throws JAXBException 248 { 249 if (a.getAnnotation(XmlValue.class) != null) { 250 if (_value != null) 251 throw new JAXBException(L.l("Cannot have two @XmlValue annotated fields or properties")); 252 253 if (! a.isXmlPrimitiveType() && 254 ! Collection .class.isAssignableFrom(a.getType())) 255 throw new JAXBException(L.l("XmlValue must be either a collection or a simple type")); 256 257 _value = a; 258 } 259 else if (a.getAnnotation(XmlAttribute.class) != null) 260 _attributeAccessors.put(a.getName(), a); 261 else { 262 if (_value != null) 263 throw new JAXBException(L.l("Cannot have both @XmlValue and elements in a JAXB element")); 264 265 _elementAccessors.put(a.getName(), a); 266 } 267 268 277 278 279 if (! a.isXmlPrimitiveType()) { 280 _context.createSkeleton(a.getType()); 281 } 282 } 283 284 public C newInstance() 285 throws JAXBException 286 { 287 try { 288 XmlType xmlType = getXmlType(); 289 290 if (xmlType != null) { 291 Class factoryClass = xmlType.factoryClass(); 292 293 if (xmlType.factoryClass() == XmlType.DEFAULT.class) 294 factoryClass = _class; 295 296 if (! "".equals(xmlType.factoryMethod())) { 297 Method m = factoryClass.getMethod(xmlType.factoryMethod(), NO_PARAMS); 298 299 if (! Modifier.isStatic(m.getModifiers())) 300 throw new JAXBException(L.l("Factory method not static")); 301 302 return (C) m.invoke(null); 303 } 304 } 305 306 Constructor con = _class.getConstructor(NO_PARAMS); 307 308 return (C)con.newInstance(NO_ARGS); 309 } 310 catch (Exception e) { 311 throw new JAXBException(e); 312 } 313 } 314 315 public XmlType getXmlType() 316 { 317 return (XmlType)_class.getAnnotation(XmlType.class); 318 } 319 320 public Object read(Unmarshaller u, XMLStreamReader in) 321 throws IOException , XMLStreamException, JAXBException 322 { 323 try { 325 C ret = (C) _constructor.newInstance(); 326 in.next(); 327 328 if (_beforeUnmarshal != null) 329 _beforeUnmarshal.invoke(ret, null, null); 330 if (u.getListener() != null) 331 u.getListener().beforeUnmarshal(ret, null); 332 333 while (in.getEventType() == in.START_ELEMENT) { 334 Accessor a = getAccessor(in.getName()); 335 Object val = a.read(u, in); 336 a.set(ret, val); 337 } 338 339 if (_afterUnmarshal != null) 340 _afterUnmarshal.invoke(ret, null, null); 341 if (u.getListener() != null) 342 u.getListener().afterUnmarshal(ret, null); 343 344 return ret; 345 } 346 catch (InstantiationException e) { 347 throw new JAXBException(e); 348 } 349 catch (InvocationTargetException e) { 350 throw new JAXBException(e); 351 } 352 catch (IllegalAccessException e) { 353 throw new JAXBException(e); 354 } 355 } 356 357 public void write(Marshaller m, XMLStreamWriter out, 358 Object obj, QName fieldName) 359 throws IOException , XMLStreamException, JAXBException 360 { 361 try { 362 if (_beforeMarshal != null) 363 _beforeMarshal.invoke(obj, null, null); 364 365 if (m.getListener() != null) 366 m.getListener().beforeMarshal(obj); 367 368 QName tagName = _elementName; 370 if (tagName == null) 371 tagName = fieldName; 372 373 if (tagName.getNamespaceURI() == null || 374 tagName.getNamespaceURI().equals("")) 375 out.writeStartElement(tagName.getLocalPart()); 376 else 377 out.writeStartElement(tagName.getNamespaceURI(), 378 tagName.getLocalPart()); 379 380 for (Accessor a : _elementAccessors.values()) 381 a.write(m, out, a.get(obj)); 382 383 out.writeEndElement(); 384 385 if (_afterMarshal != null) 386 _afterMarshal.invoke(obj, null, null); 387 if (m.getListener() != null) 388 m.getListener().afterMarshal(obj); 389 } 390 catch (InvocationTargetException e) { 391 throw new JAXBException(e); 392 } 393 catch (IllegalAccessException e) { 394 throw new JAXBException(e); 395 } 396 } 397 398 public QName getElementName() 399 { 400 return _elementName; 401 432 } 433 434 public void generateSchema(XMLStreamWriter out) 435 throws JAXBException, XMLStreamException 436 { 437 if (_elementName != null) { 438 439 if ("".equals(_typeName.getLocalPart())) 440 out.writeStartElement(XML_SCHEMA_PREFIX, "element", XML_SCHEMA_NS); 441 else { 442 out.writeEmptyElement(XML_SCHEMA_PREFIX, "element", XML_SCHEMA_NS); 443 out.writeAttribute("type", _typeName.getLocalPart()); 444 } 445 446 out.writeAttribute("name", _elementName.getLocalPart()); 447 } 448 449 generateSchemaType(out); 450 451 if (_elementName != null && "".equals(_typeName.getLocalPart())) 452 out.writeEndElement(); } 454 455 public void generateSchemaType(XMLStreamWriter out) 456 throws JAXBException, XMLStreamException 457 { 458 if (_value != null) { 459 out.writeStartElement(XML_SCHEMA_PREFIX, "simpleType", XML_SCHEMA_NS); 460 461 if (! "".equals(_typeName.getLocalPart())) 462 out.writeAttribute("name", _typeName.getLocalPart()); 463 464 out.writeEmptyElement(XML_SCHEMA_PREFIX, "restriction", XML_SCHEMA_NS); 465 out.writeAttribute("base", _value.getSchemaType()); 466 467 for (Accessor accessor : _attributeAccessors.values()) 468 accessor.generateSchema(out); 469 470 out.writeEndElement(); } 472 else { 473 out.writeStartElement(XML_SCHEMA_PREFIX, "complexType", XML_SCHEMA_NS); 474 475 if (! "".equals(_typeName.getLocalPart())) 476 out.writeAttribute("name", _typeName.getLocalPart()); 477 478 out.writeStartElement(XML_SCHEMA_PREFIX, "sequence", XML_SCHEMA_NS); 479 480 for (Accessor accessor : _elementAccessors.values()) 481 accessor.generateSchema(out); 482 483 out.writeEndElement(); 485 for (Accessor accessor : _attributeAccessors.values()) 486 accessor.generateSchema(out); 487 488 out.writeEndElement(); } 490 } 491 } 492 | Popular Tags |