1 29 30 package com.caucho.jaxb; 31 32 import com.caucho.jaxb.skeleton.*; 33 import com.caucho.server.util.CauchoSystem; 34 import com.caucho.util.L10N; 35 36 import org.w3c.dom.Node ; 37 38 import javax.xml.bind.*; 39 import javax.xml.datatype.*; 40 import javax.xml.namespace.QName ; 41 import javax.xml.stream.XMLInputFactory; 42 import javax.xml.stream.XMLOutputFactory; 43 import javax.xml.stream.XMLStreamException; 44 import javax.xml.stream.XMLStreamReader; 45 import javax.xml.stream.XMLStreamWriter; 46 import javax.xml.transform.Result ; 47 import java.io.IOException ; 48 import java.io.InputStream ; 49 import java.io.InputStreamReader ; 50 import java.io.LineNumberReader ; 51 import java.lang.reflect.ParameterizedType ; 52 import java.lang.reflect.Type ; 53 import java.math.BigDecimal ; 54 import java.math.BigInteger ; 55 import java.util.*; 56 57 60 public class JAXBContextImpl extends JAXBContext { 61 private static final L10N L = new L10N(JAXBContextImpl.class); 62 63 private static final HashSet<Class > _specialClasses = new HashSet<Class >(); 64 65 static { 66 _specialClasses.add(Object .class); 67 _specialClasses.add(Class .class); 68 _specialClasses.add(String .class); 69 _specialClasses.add(Double .class); 70 _specialClasses.add(Float .class); 71 _specialClasses.add(Integer .class); 72 _specialClasses.add(Long .class); 73 _specialClasses.add(Boolean .class); 74 _specialClasses.add(Character .class); 75 _specialClasses.add(Short .class); 76 _specialClasses.add(Byte .class); 77 _specialClasses.add(BigDecimal .class); 78 _specialClasses.add(BigInteger .class); 79 _specialClasses.add(QName .class); 80 _specialClasses.add(Date.class); 81 _specialClasses.add(Calendar.class); 82 _specialClasses.add(XMLGregorianCalendar.class); 83 } 84 85 private String [] _packages; 86 private ClassLoader _classLoader; 87 private JAXBIntrospector _jaxbIntrospector; 88 89 private XMLInputFactory _staxInputFactory; 90 private XMLOutputFactory _staxOutputFactory; 91 92 private ArrayList<ObjectFactorySkeleton> _objectFactories 93 = new ArrayList<ObjectFactorySkeleton>(); 94 95 private HashMap<String ,Object > _properties 96 = new HashMap<String ,Object >(); 97 98 private LinkedHashMap<Class ,ClassSkeleton> _classSkeletons 99 = new LinkedHashMap<Class ,ClassSkeleton>(); 100 101 private HashMap<QName ,Skeleton> _roots 102 = new HashMap<QName ,Skeleton>(); 103 104 public JAXBContextImpl(String contextPath, 105 ClassLoader classLoader, 106 Map<String ,?> properties) 107 throws JAXBException 108 { 109 _jaxbIntrospector = new JAXBIntrospectorImpl(this); 110 _classLoader = classLoader; 111 112 StringTokenizer st = new StringTokenizer(contextPath, ":"); 113 114 do { 115 String packageName = st.nextToken(); 116 loadPackage(packageName); 117 } 118 while (st.hasMoreTokens()); 119 120 if (properties != null) 121 for(Map.Entry<String ,?> e : properties.entrySet()) 122 setProperty(e.getKey(), e.getValue()); 123 124 DatatypeConverter.setDatatypeConverter(new DatatypeConverterImpl()); 125 } 126 127 public static JAXBContext createContext(Class []classes, 128 Map<String ,?> properties) 129 throws JAXBException 130 { 131 return new JAXBContextImpl(classes, properties); 132 } 133 134 public JAXBContextImpl(Class [] classes, Map<String ,?> properties) 135 throws JAXBException 136 { 137 _jaxbIntrospector = new JAXBIntrospectorImpl(this); 138 _packages = new String [0]; 139 _classLoader = null; 140 141 for(Class c : classes) { 142 if (! c.isPrimitive() && 144 ! c.isArray() && 145 ! _specialClasses.contains(c)) 146 createSkeleton(c); 147 } 148 149 if (properties != null) { 150 for(Map.Entry<String ,?> e : properties.entrySet()) 151 setProperty(e.getKey(), e.getValue()); 152 } 153 154 DatatypeConverter.setDatatypeConverter(new DatatypeConverterImpl()); 155 } 156 157 public Marshaller createMarshaller() 158 throws JAXBException 159 { 160 return new MarshallerImpl(this); 161 } 162 163 public Unmarshaller createUnmarshaller() 164 throws JAXBException 165 { 166 return new UnmarshallerImpl(this); 167 } 168 169 public Validator createValidator() 170 throws JAXBException 171 { 172 throw new UnsupportedOperationException (); 173 } 174 175 XMLStreamReader getXMLStreamReader(InputStream is) 176 throws XMLStreamException 177 { 178 if (_staxInputFactory == null) 179 _staxInputFactory = XMLInputFactory.newInstance(); 180 181 return _staxInputFactory.createXMLStreamReader(is); 182 } 183 184 XMLInputFactory getXMLInputFactory() 185 { 186 if (_staxInputFactory == null) 187 _staxInputFactory = XMLInputFactory.newInstance(); 188 189 return _staxInputFactory; 190 } 191 192 XMLOutputFactory getXMLOutputFactory() 193 { 194 if (_staxOutputFactory == null) 195 _staxOutputFactory = XMLOutputFactory.newInstance(); 196 197 return _staxOutputFactory; 198 } 199 200 public String toString() { 201 StringBuilder sb = new StringBuilder (); 202 sb.append("JAXBContext["); 203 204 for (Class c : _classSkeletons.keySet()) 205 sb.append(c.getName() + ":"); 206 207 for (int i = 0; i < _packages.length; i++) { 208 String p = _packages[i]; 209 sb.append(p + (i < _packages.length - 1 ? ":" : "")); 210 } 211 212 sb.append("]"); 213 return sb.toString(); 214 } 215 216 private void setProperty(String key, Object val) 217 { 218 _properties.put(key, val); 219 } 220 221 public Binder<Node > createBinder() 222 { 223 throw new UnsupportedOperationException ("XML Infoset not supported"); 224 } 225 226 public <T> Binder<T> createBinder(Class <T> domType) 227 { 228 throw new UnsupportedOperationException ("XML Infoset not supported"); 229 } 230 231 public JAXBIntrospector createJAXBIntrospector() 232 { 233 return _jaxbIntrospector; 234 } 235 236 public void generateSchema(SchemaOutputResolver outputResolver) 237 throws IOException 238 { 239 Result result = outputResolver.createOutput("", "schema1.xsd"); 240 241 try { 242 XMLOutputFactory factory = getXMLOutputFactory(); 243 XMLStreamWriter out = factory.createXMLStreamWriter(result); 244 245 out.writeStartDocument("UTF-8", "1.0"); 246 247 generateSchemaWithoutHeader(out); 248 } 249 catch (Exception e) { 250 IOException ioException = new IOException (); 251 252 ioException.initCause(e); 253 254 throw ioException; 255 } 256 } 257 258 public void generateSchemaWithoutHeader(XMLStreamWriter out) 259 throws JAXBException, XMLStreamException 260 { 261 out.writeStartElement("xsd", "schema", "http://www.w3.org/2001/XMLSchema"); 262 out.writeAttribute("version", "1.0"); 263 264 for (Skeleton skeleton : _classSkeletons.values()) 265 skeleton.generateSchema(out); 266 267 out.writeEndElement(); } 269 270 public void createSkeleton(Class c) 271 throws JAXBException 272 { 273 if (_classSkeletons.containsKey(c)) 274 return; 275 276 if (c.isEnum() || c.isInterface()) 278 return; 279 280 _classSkeletons.put(c, null); 282 283 ClassSkeleton skeleton = new ClassSkeleton(this, c); 284 _classSkeletons.put(c, skeleton); 285 } 286 287 public Skeleton getSkeleton(Class c) 288 throws JAXBException 289 { 290 createSkeleton(c); 291 292 return _classSkeletons.get(c); 293 } 294 295 public ClassSkeleton findSkeletonForObject(Object obj) 296 throws JAXBException 297 { 298 Class cl = obj.getClass(); 299 300 while (! cl.equals(Object .class)) { 301 ClassSkeleton skeleton = _classSkeletons.get(cl); 302 303 if (skeleton != null) 304 return skeleton; 305 306 cl = cl.getSuperclass(); 307 } 308 309 throw new JAXBException(L.l("Class {0} unknown to this JAXBContext", cl)); 310 } 311 312 public Property createProperty(Type type) 313 throws JAXBException 314 { 315 if (type instanceof Class ) { 316 if (String .class.equals(type)) 317 return StringProperty.PROPERTY; 318 319 if (Double .class.equals(type)) 320 return DoubleProperty.OBJECT_PROPERTY; 321 322 if (Double.TYPE.equals(type)) 323 return DoubleProperty.PRIMITIVE_PROPERTY; 324 325 if (Float .class.equals(type)) 326 return FloatProperty.OBJECT_PROPERTY; 327 328 if (Float.TYPE.equals(type)) 329 return FloatProperty.PRIMITIVE_PROPERTY; 330 331 if (Integer .class.equals(type)) 332 return IntProperty.OBJECT_PROPERTY; 333 334 if (Integer.TYPE.equals(type)) 335 return IntProperty.PRIMITIVE_PROPERTY; 336 337 if (Long .class.equals(type)) 338 return LongProperty.OBJECT_PROPERTY; 339 340 if (Long.TYPE.equals(type)) 341 return LongProperty.PRIMITIVE_PROPERTY; 342 343 if (Boolean .class.equals(type)) 344 return BooleanProperty.OBJECT_PROPERTY; 345 346 if (Boolean.TYPE.equals(type)) 347 return BooleanProperty.PRIMITIVE_PROPERTY; 348 349 if (Character .class.equals(type)) 350 return CharacterProperty.OBJECT_PROPERTY; 351 352 if (Character.TYPE.equals(type)) 353 return CharacterProperty.PRIMITIVE_PROPERTY; 354 355 if (Short .class.equals(type)) 356 return ShortProperty.OBJECT_PROPERTY; 357 358 if (Short.TYPE.equals(type)) 359 return ShortProperty.PRIMITIVE_PROPERTY; 360 361 if (Byte .class.equals(type)) 362 return ByteProperty.OBJECT_PROPERTY; 363 364 if (Byte.TYPE.equals(type)) 365 return ByteProperty.PRIMITIVE_PROPERTY; 366 367 if (BigDecimal .class.equals(type)) 368 return BigDecimalProperty.PROPERTY; 369 370 if (BigInteger .class.equals(type)) 371 return BigIntegerProperty.PROPERTY; 372 373 if (QName .class.equals(type)) 374 return QNameProperty.PROPERTY; 375 376 if (Date.class.equals(type)) 377 return DateTimeProperty.PROPERTY; 378 379 if (Calendar.class.equals(type)) 380 return CalendarProperty.PROPERTY; 381 382 if (XMLGregorianCalendar.class.equals(type)) 383 return XMLGregorianCalendarProperty.PROPERTY; 384 385 if (byte[].class.equals(type)) 386 return ByteArrayProperty.PROPERTY; 387 388 Class cl = (Class ) type; 389 390 if (cl.isArray()) { 391 Property componentProperty = createProperty(cl.getComponentType()); 392 return ArrayProperty.createArrayProperty(componentProperty, 393 cl.getComponentType()); 394 } 395 396 if (cl.isEnum()) 397 return new EnumProperty(); 398 399 return new SkeletonProperty(getSkeleton(cl)); 400 } 401 else if (type instanceof ParameterizedType ) { 402 ParameterizedType ptype = (ParameterizedType ) type; 403 Type rawType = ptype.getRawType(); 404 405 if (rawType instanceof Class ) { 406 Class rawClass = (Class ) rawType; 407 408 if (Map.class.equals(rawClass)) 409 return new MapProperty(); 410 411 if (List.class.equals(rawClass)) { 412 Type [] args = ptype.getActualTypeArguments(); 413 414 if (args.length != 1) 415 throw new JAXBException(L.l("unexpected number of generic arguments for List<>: {0}", args.length)); 416 417 Property componentProperty = createProperty(args[0]); 418 return new ListProperty(componentProperty); 419 } 420 421 if (Collection.class.isAssignableFrom(rawClass)) 422 return new CollectionProperty(); 423 } 424 } 425 426 throw new JAXBException(L.l("Unrecognized type: {0}", type.toString())); 427 } 428 429 public void addRootElement(Skeleton s) 430 { 431 _roots.put(s.getTypeName(), s); 432 } 433 434 public Skeleton getRootElement(QName q) 435 { 436 return _roots.get(q); 437 } 438 439 private void loadPackage(String packageName) 440 throws JAXBException 441 { 442 boolean success = false; 443 444 try { 445 Class cl = CauchoSystem.loadClass(packageName + ".ObjectFactory"); 446 _objectFactories.add(new ObjectFactorySkeleton(cl)); 447 448 success = true; 449 } 450 catch (ClassNotFoundException e) { 451 } 453 454 try { 455 String resourceName = packageName.replace('.', '/') + "/jaxb.index"; 456 457 InputStream is = this.getClass().getResourceAsStream('/' + resourceName); 459 460 if (is == null) { 462 ClassLoader classLoader = 463 Thread.currentThread().getContextClassLoader(); 464 465 is = classLoader.getResourceAsStream(resourceName); 466 } 467 468 InputStreamReader isr = new InputStreamReader (is, "utf-8"); 469 LineNumberReader in = new LineNumberReader (isr); 470 471 for (String line = in.readLine(); 472 line != null; 473 line = in.readLine()) { 474 String [] parts = line.split("#", 2); 475 String className = parts[0].trim(); 476 477 if (! "".equals(className)) { 478 Class cl = CauchoSystem.loadClass(packageName + "." + className); 479 480 createSkeleton(cl); 481 } 482 } 483 484 success = true; 485 } 486 catch (Throwable t) { 487 if (! success) { 488 throw new JAXBException(L.l("Unable to open jaxb.index for package {0}", 489 packageName), t); 490 } 491 } 492 } 493 } 494 495 | Popular Tags |