1
10
11 package com.sun.xml.bind.v2.runtime;
12
13 import java.io.IOException;
14 import java.lang.ref.WeakReference;
15 import java.lang.reflect.Field;
16 import java.lang.reflect.Method;
17 import java.lang.reflect.Type;
18 import java.util.Arrays;
19 import java.util.Collection;
20 import java.util.Collections;
21 import java.util.Comparator;
22 import java.util.HashMap;
23 import java.util.HashSet;
24 import java.util.LinkedHashMap;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Map.Entry;
28 import java.util.Set;
29 import java.util.TreeSet;
30 import javax.xml.bind.Binder;
31 import javax.xml.bind.JAXBContext;
32 import javax.xml.bind.JAXBElement;
33 import javax.xml.bind.JAXBException;
34 import javax.xml.bind.JAXBIntrospector;
35 import javax.xml.bind.Marshaller;
36 import javax.xml.bind.SchemaOutputResolver;
37 import javax.xml.bind.Unmarshaller;
38 import javax.xml.bind.Validator;
39 import javax.xml.bind.annotation.XmlAttachmentRef;
40 import javax.xml.bind.annotation.XmlList;
41 import javax.xml.bind.annotation.XmlNs;
42 import javax.xml.bind.annotation.XmlSchema;
43 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
44 import javax.xml.namespace.QName;
45 import javax.xml.parsers.DocumentBuilder;
46 import javax.xml.parsers.DocumentBuilderFactory;
47 import javax.xml.parsers.FactoryConfigurationError;
48 import javax.xml.parsers.ParserConfigurationException;
49 import javax.xml.transform.Result;
50 import javax.xml.transform.Transformer;
51 import javax.xml.transform.TransformerConfigurationException;
52 import javax.xml.transform.TransformerFactory;
53 import javax.xml.transform.sax.SAXTransformerFactory;
54 import javax.xml.transform.sax.TransformerHandler;
55
56 import com.sun.istack.NotNull;
57 import com.sun.istack.Pool;
58 import com.sun.xml.bind.v2.WellKnownNamespace;
59 import com.sun.xml.bind.api.AccessorException;
60 import com.sun.xml.bind.api.Bridge;
61 import com.sun.xml.bind.api.BridgeContext;
62 import com.sun.xml.bind.api.CompositeStructure;
63 import com.sun.xml.bind.api.ErrorListener;
64 import com.sun.xml.bind.api.JAXBRIContext;
65 import com.sun.xml.bind.api.RawAccessor;
66 import com.sun.xml.bind.api.TypeReference;
67 import com.sun.xml.bind.unmarshaller.DOMScanner;
68 import com.sun.xml.bind.util.Which;
69 import com.sun.xml.bind.v2.model.annotation.RuntimeAnnotationReader;
70 import com.sun.xml.bind.v2.model.annotation.RuntimeInlineAnnotationReader;
71 import com.sun.xml.bind.v2.model.core.Adapter;
72 import com.sun.xml.bind.v2.model.core.NonElement;
73 import com.sun.xml.bind.v2.model.core.Ref;
74 import com.sun.xml.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl;
75 import com.sun.xml.bind.v2.model.impl.RuntimeModelBuilder;
76 import com.sun.xml.bind.v2.model.nav.Navigator;
77 import com.sun.xml.bind.v2.model.runtime.RuntimeArrayInfo;
78 import com.sun.xml.bind.v2.model.runtime.RuntimeBuiltinLeafInfo;
79 import com.sun.xml.bind.v2.model.runtime.RuntimeClassInfo;
80 import com.sun.xml.bind.v2.model.runtime.RuntimeElementInfo;
81 import com.sun.xml.bind.v2.model.runtime.RuntimeEnumLeafInfo;
82 import com.sun.xml.bind.v2.model.runtime.RuntimeLeafInfo;
83 import com.sun.xml.bind.v2.model.runtime.RuntimeTypeInfo;
84 import com.sun.xml.bind.v2.model.runtime.RuntimeTypeInfoSet;
85 import com.sun.xml.bind.v2.runtime.output.Encoded;
86 import com.sun.xml.bind.v2.runtime.property.AttributeProperty;
87 import com.sun.xml.bind.v2.runtime.property.Property;
88 import com.sun.xml.bind.v2.runtime.reflect.Accessor;
89 import com.sun.xml.bind.v2.runtime.unmarshaller.Loader;
90 import com.sun.xml.bind.v2.runtime.unmarshaller.TagName;
91 import com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl;
92 import com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext;
93 import com.sun.xml.bind.v2.schemagen.XmlSchemaGenerator;
94 import com.sun.xml.bind.v2.util.EditDistance;
95 import com.sun.xml.bind.v2.util.QNameMap;
96 import com.sun.xml.bind.v2.util.XmlFactory;
97 import com.sun.xml.txw2.output.ResultFactory;
98
99 import org.w3c.dom.Document;
100 import org.w3c.dom.Element;
101 import org.w3c.dom.Node;
102 import org.xml.sax.SAXException;
103 import org.xml.sax.SAXParseException;
104
105
109 public final class JAXBContextImpl extends JAXBRIContext {
110
111
114 private final Map<TypeReference,Bridge> bridges = new LinkedHashMap<TypeReference,Bridge>();
115
116
120 private static DocumentBuilder db;
121
122 private final QNameMap<JaxBeanInfo> rootMap = new QNameMap<JaxBeanInfo>();
123 private final HashMap<QName,JaxBeanInfo> typeMap = new HashMap<QName,JaxBeanInfo>();
124
125
128 private final Map<Class,JaxBeanInfo> beanInfoMap = new LinkedHashMap<Class,JaxBeanInfo>();
129
130
139 protected Map<RuntimeTypeInfo,JaxBeanInfo> beanInfos = new LinkedHashMap<RuntimeTypeInfo, JaxBeanInfo>();
140
141 private final Map<Class,Map<QName,ElementBeanInfoImpl>> elements = new LinkedHashMap<Class, Map<QName, ElementBeanInfoImpl>>();
142
143
146 public final Pool<Marshaller> marshallerPool = new Pool.Impl<Marshaller>() {
147 protected @NotNull Marshaller create() {
148 return createMarshaller();
149 }
150 };
151
152 public final Pool<Unmarshaller> unmarshallerPool = new Pool.Impl<Unmarshaller>() {
153 protected @NotNull Unmarshaller create() {
154 return createUnmarshaller();
155 }
156 };
157
158
162 public NameBuilder nameBuilder = new NameBuilder();
163
164
168 public final NameList nameList;
169
170
174 private final String defaultNsUri;
175 private final Class[] classes;
176
177
180 protected final boolean c14nSupport;
181
182
185 public final boolean xmlAccessorFactorySupport;
186
187
190 public final boolean allNillable;
191
192
195 public final boolean retainPropertyInfo;
196
197
200 public final boolean supressAccessorWarnings;
201
202
205 public final boolean improvedXsiTypeHandling;
206
207
210 public final boolean disableSecurityProcessing;
211
212 private WeakReference<RuntimeTypeInfoSet> typeInfoSetCache;
213
214 private @NotNull RuntimeAnnotationReader annotationReader;
215
216 private boolean hasSwaRef;
217 private final @NotNull Map<Class,Class> subclassReplacements;
218
219
225 public final boolean fastBoot;
226
227 private Set<XmlNs> xmlNsSet = null;
228
229
237 public Boolean backupWithParentNamespace = null;
238
239
245 public final int maxErrorsCount;
246
247
252 public Set<XmlNs> getXmlNsSet() {
253 return xmlNsSet;
254 }
255
256 private JAXBContextImpl(JAXBContextBuilder builder) throws JAXBException {
257
258 this.defaultNsUri = builder.defaultNsUri;
259 this.retainPropertyInfo = builder.retainPropertyInfo;
260 this.annotationReader = builder.annotationReader;
261 this.subclassReplacements = builder.subclassReplacements;
262 this.c14nSupport = builder.c14nSupport;
263 this.classes = builder.classes;
264 this.xmlAccessorFactorySupport = builder.xmlAccessorFactorySupport;
265 this.allNillable = builder.allNillable;
266 this.supressAccessorWarnings = builder.supressAccessorWarnings;
267 this.improvedXsiTypeHandling = builder.improvedXsiTypeHandling;
268 this.disableSecurityProcessing = builder.disableSecurityProcessing;
269 this.backupWithParentNamespace = builder.backupWithParentNamespace;
270 this.maxErrorsCount = builder.maxErrorsCount;
271
272 Collection<TypeReference> typeRefs = builder.typeRefs;
273
274 boolean fastB;
275 try {
276 fastB = Boolean.getBoolean(JAXBContextImpl.class.getName()+".fastBoot");
277 } catch (SecurityException e) {
278 fastB = false;
279 }
280 this.fastBoot = fastB;
281
282 RuntimeTypeInfoSet typeSet = getTypeInfoSet();
283
284
285 elements.put(null,new LinkedHashMap<QName, ElementBeanInfoImpl>());
286
287
288 for( RuntimeBuiltinLeafInfo leaf : RuntimeBuiltinLeafInfoImpl.builtinBeanInfos ) {
289 LeafBeanInfoImpl<?> bi = new LeafBeanInfoImpl(this,leaf);
290 beanInfoMap.put(leaf.getClazz(),bi);
291 for( QName t : bi.getTypeNames() )
292 typeMap.put(t,bi);
293 }
294
295 for (RuntimeEnumLeafInfo e : typeSet.enums().values()) {
296 JaxBeanInfo<?> bi = getOrCreate(e);
297 for (QName qn : bi.getTypeNames())
298 typeMap.put( qn, bi );
299 if(e.isElement())
300 rootMap.put( e.getElementName(), bi );
301 }
302
303 for (RuntimeArrayInfo a : typeSet.arrays().values()) {
304 JaxBeanInfo<?> ai = getOrCreate(a);
305 for (QName qn : ai.getTypeNames())
306 typeMap.put( qn, ai );
307 }
308
309 for( Entry<Class, ? extends RuntimeClassInfo> e : typeSet.beans().entrySet() ) {
310 ClassBeanInfoImpl<?> bi = getOrCreate(e.getValue());
311
312 XmlSchema xs = this.annotationReader.getPackageAnnotation(XmlSchema.class, e.getKey(), null);
313 if(xs != null) {
314 if(xs.xmlns() != null && xs.xmlns().length > 0) {
315 if(xmlNsSet == null)
316 xmlNsSet = new HashSet<XmlNs>();
317 xmlNsSet.addAll(Arrays.asList(xs.xmlns()));
318 }
319 }
320
321 if(bi.isElement())
322 rootMap.put( e.getValue().getElementName(), bi );
323
324 for (QName qn : bi.getTypeNames())
325 typeMap.put( qn, bi );
326 }
327
328
329 for( RuntimeElementInfo n : typeSet.getAllElements() ) {
330 ElementBeanInfoImpl bi = getOrCreate(n);
331 if(n.getScope()==null)
332 rootMap.put(n.getElementName(),bi);
333
334 RuntimeClassInfo scope = n.getScope();
335 Class scopeClazz = scope==null?null:scope.getClazz();
336 Map<QName,ElementBeanInfoImpl> m = elements.get(scopeClazz);
337 if(m==null) {
338 m = new LinkedHashMap<QName, ElementBeanInfoImpl>();
339 elements.put(scopeClazz,m);
340 }
341 m.put(n.getElementName(),bi);
342 }
343
344
345 beanInfoMap.put(JAXBElement.class,new ElementBeanInfoImpl(this));
346
347 beanInfoMap.put(CompositeStructure.class,new CompositeStructureBeanInfo(this));
348
349 getOrCreate(typeSet.getAnyTypeInfo());
350
351
352 for (JaxBeanInfo bi : beanInfos.values())
353 bi.link(this);
354
355
356 for( Map.Entry<Class,Class> e : RuntimeUtil.primitiveToBox.entrySet() )
357 beanInfoMap.put( e.getKey(), beanInfoMap.get(e.getValue()) );
358
359
360 Navigator<Type, Class, Field, Method> nav = typeSet.getNavigator();
361
362 for (TypeReference tr : typeRefs) {
363 XmlJavaTypeAdapter xjta = tr.get(XmlJavaTypeAdapter.class);
364 Adapter<Type,Class> a=null;
365 XmlList xl = tr.get(XmlList.class);
366
367
368 Class erasedType = (Class) nav.erasure(tr.type);
369
370 if(xjta!=null) {
371 a = new Adapter<Type,Class>(xjta.value(),nav);
372 }
373 if(tr.get(XmlAttachmentRef.class)!=null) {
374 a = new Adapter<Type,Class>(SwaRefAdapter.class,nav);
375 hasSwaRef = true;
376 }
377
378 if(a!=null) {
379 erasedType = (Class) nav.erasure(a.defaultType);
380 }
381
382 Name name = nameBuilder.createElementName(tr.tagName);
383
384 InternalBridge bridge;
385 if(xl==null)
386 bridge = new BridgeImpl(this, name,getBeanInfo(erasedType,true),tr);
387 else
388 bridge = new BridgeImpl(this, name,new ValueListBeanInfoImpl(this,erasedType),tr);
389
390 if(a!=null)
391 bridge = new BridgeAdapter(bridge,a.adapterType);
392
393 bridges.put(tr,bridge);
394 }
395
396 this.nameList = nameBuilder.conclude();
397
398 for (JaxBeanInfo bi : beanInfos.values())
399 bi.wrapUp();
400
401
402 nameBuilder = null;
403 beanInfos = null;
404 }
405
406
409 public boolean hasSwaRef() {
410 return hasSwaRef;
411 }
412
413 public RuntimeTypeInfoSet getRuntimeTypeInfoSet() {
414 try {
415 return getTypeInfoSet();
416 } catch (IllegalAnnotationsException e) {
417
418 throw new AssertionError(e);
419 }
420 }
421
422
425 public RuntimeTypeInfoSet getTypeInfoSet() throws IllegalAnnotationsException {
426
427
428 if(typeInfoSetCache!=null) {
429 RuntimeTypeInfoSet r = typeInfoSetCache.get();
430 if(r!=null)
431 return r;
432 }
433
434 final RuntimeModelBuilder builder = new RuntimeModelBuilder(this,annotationReader,subclassReplacements,defaultNsUri);
435
436 IllegalAnnotationsException.Builder errorHandler = new IllegalAnnotationsException.Builder();
437 builder.setErrorHandler(errorHandler);
438
439 for( Class c : classes ) {
440 if(c==CompositeStructure.class)
441
442
443 continue;
444 builder.getTypeInfo(new Ref<Type,Class>(c));
445 }
446
447 this.hasSwaRef |= builder.hasSwaRef;
448 RuntimeTypeInfoSet r = builder.link();
449
450 errorHandler.check();
451 assert r!=null : "if no error was reported, the link must be a success";
452
453 typeInfoSetCache = new WeakReference<RuntimeTypeInfoSet>(r);
454
455 return r;
456 }
457
458
459 public ElementBeanInfoImpl getElement(Class scope, QName name) {
460 Map<QName,ElementBeanInfoImpl> m = elements.get(scope);
461 if(m!=null) {
462 ElementBeanInfoImpl bi = m.get(name);
463 if(bi!=null)
464 return bi;
465 }
466 m = elements.get(null);
467 return m.get(name);
468 }
469
470
471
472
473
474 private ElementBeanInfoImpl getOrCreate( RuntimeElementInfo rei ) {
475 JaxBeanInfo bi = beanInfos.get(rei);
476 if(bi!=null) return (ElementBeanInfoImpl)bi;
477
478
479 return new ElementBeanInfoImpl(this, rei);
480 }
481
482 protected JaxBeanInfo getOrCreate( RuntimeEnumLeafInfo eli ) {
483 JaxBeanInfo bi = beanInfos.get(eli);
484 if(bi!=null) return bi;
485 bi = new LeafBeanInfoImpl(this,eli);
486 beanInfoMap.put(bi.jaxbType,bi);
487 return bi;
488 }
489
490 protected ClassBeanInfoImpl getOrCreate( RuntimeClassInfo ci ) {
491 ClassBeanInfoImpl bi = (ClassBeanInfoImpl)beanInfos.get(ci);
492 if(bi!=null) return bi;
493 bi = new ClassBeanInfoImpl(this,ci);
494 beanInfoMap.put(bi.jaxbType,bi);
495 return bi;
496 }
497
498 protected JaxBeanInfo getOrCreate( RuntimeArrayInfo ai ) {
499 JaxBeanInfo abi = beanInfos.get(ai);
500 if(abi!=null) return abi;
501
502 abi = new ArrayBeanInfoImpl(this,ai);
503
504 beanInfoMap.put(ai.getType(),abi);
505 return abi;
506 }
507
508 public JaxBeanInfo getOrCreate(RuntimeTypeInfo e) {
509 if(e instanceof RuntimeElementInfo)
510 return getOrCreate((RuntimeElementInfo)e);
511 if(e instanceof RuntimeClassInfo)
512 return getOrCreate((RuntimeClassInfo)e);
513 if(e instanceof RuntimeLeafInfo) {
514 JaxBeanInfo bi = beanInfos.get(e);
515 assert bi!=null;
516 return bi;
517 }
518 if(e instanceof RuntimeArrayInfo)
519 return getOrCreate((RuntimeArrayInfo)e);
520 if(e.getType()==Object.class) {
521
522 JaxBeanInfo bi = beanInfoMap.get(Object.class);
523 if(bi==null) {
524 bi = new AnyTypeBeanInfo(this,e);
525 beanInfoMap.put(Object.class,bi);
526 }
527 return bi;
528 }
529
530 throw new IllegalArgumentException();
531 }
532
533
543 public final JaxBeanInfo getBeanInfo(Object o) {
544
545 for( Class c=o.getClass(); c!=Object.class; c=c.getSuperclass()) {
546 JaxBeanInfo bi = beanInfoMap.get(c);
547 if(bi!=null) return bi;
548 }
549 if(o instanceof Element)
550 return beanInfoMap.get(Object.class);
551 for( Class c : o.getClass().getInterfaces()) {
552 JaxBeanInfo bi = beanInfoMap.get(c);
553 if(bi!=null) return bi;
554 }
555 return null;
556 }
557
558
566 public final JaxBeanInfo getBeanInfo(Object o,boolean fatal) throws JAXBException {
567 JaxBeanInfo bi = getBeanInfo(o);
568 if(bi!=null) return bi;
569 if(fatal) {
570 if(o instanceof Document)
571 throw new JAXBException(Messages.ELEMENT_NEEDED_BUT_FOUND_DOCUMENT.format(o.getClass()));
572 throw new JAXBException(Messages.UNKNOWN_CLASS.format(o.getClass()));
573 }
574 return null;
575 }
576
577
587 public final <T> JaxBeanInfo<T> getBeanInfo(Class<T> clazz) {
588 return (JaxBeanInfo<T>)beanInfoMap.get(clazz);
589 }
590
591
599 public final <T> JaxBeanInfo<T> getBeanInfo(Class<T> clazz,boolean fatal) throws JAXBException {
600 JaxBeanInfo<T> bi = getBeanInfo(clazz);
601 if(bi!=null) return bi;
602 if(fatal)
603 throw new JAXBException(clazz.getName()+" is not known to this context");
604 return null;
605 }
606
607
614 public final Loader selectRootLoader( UnmarshallingContext.State state, TagName tag ) {
615 JaxBeanInfo beanInfo = rootMap.get(tag.uri,tag.local);
616 if(beanInfo==null)
617 return null;
618
619 return beanInfo.getLoader(this,true);
620 }
621
622
630 public JaxBeanInfo getGlobalType(QName name) {
631 return typeMap.get(name);
632 }
633
634
641 public String getNearestTypeName(QName name) {
642 String[] all = new String[typeMap.size()];
643 int i=0;
644 for (QName qn : typeMap.keySet()) {
645 if(qn.getLocalPart().equals(name.getLocalPart()))
646 return qn.toString();
647 all[i++] = qn.toString();
648 }
649
650 String nearest = EditDistance.findNearest(name.toString(), all);
651
652 if(EditDistance.editDistance(nearest,name.toString())>10)
653 return null;
654
655 return nearest;
656 }
657
658
662 public Set<QName> getValidRootNames() {
663 Set<QName> r = new TreeSet<QName>(QNAME_COMPARATOR);
664 for (QNameMap.Entry e : rootMap.entrySet()) {
665 r.add(e.createQName());
666 }
667 return r;
668 }
669
670
673 private Encoded[] utf8nameTable;
674
675 public synchronized Encoded[] getUTF8NameTable() {
676 if(utf8nameTable==null) {
677 Encoded[] x = new Encoded[nameList.localNames.length];
678 for( int i=0; i<x.length; i++ ) {
679 Encoded e = new Encoded(nameList.localNames[i]);
680 e.compact();
681 x[i] = e;
682 }
683 utf8nameTable = x;
684 }
685 return utf8nameTable;
686 }
687
688 public int getNumberOfLocalNames() {
689 return nameList.localNames.length;
690 }
691
692 public int getNumberOfElementNames() {
693 return nameList.numberOfElementNames;
694 }
695
696 public int getNumberOfAttributeNames() {
697 return nameList.numberOfAttributeNames;
698 }
699
700
703 static Transformer createTransformer(boolean disableSecureProcessing) {
704 try {
705 SAXTransformerFactory tf = (SAXTransformerFactory)XmlFactory.createTransformerFactory(disableSecureProcessing);
706 return tf.newTransformer();
707 } catch (TransformerConfigurationException e) {
708 throw new Error(e);
709 }
710 }
711
712
715 public static TransformerHandler createTransformerHandler(boolean disableSecureProcessing) {
716 try {
717 SAXTransformerFactory tf = (SAXTransformerFactory)XmlFactory.createTransformerFactory(disableSecureProcessing);
718 return tf.newTransformerHandler();
719 } catch (TransformerConfigurationException e) {
720 throw new Error(e);
721 }
722 }
723
724
727 static Document createDom(boolean disableSecurityProcessing) {
728 synchronized(JAXBContextImpl.class) {
729 if(db==null) {
730 try {
731 DocumentBuilderFactory dbf = XmlFactory.createDocumentBuilderFactory(disableSecurityProcessing);
732 db = dbf.newDocumentBuilder();
733 } catch (ParserConfigurationException e) {
734
735 throw new FactoryConfigurationError(e);
736 }
737 }
738 return db.newDocument();
739 }
740 }
741
742 public MarshallerImpl createMarshaller() {
743 return new MarshallerImpl(this,null);
744 }
745
746 public UnmarshallerImpl createUnmarshaller() {
747 return new UnmarshallerImpl(this,null);
748 }
749
750 public Validator createValidator() {
751 throw new UnsupportedOperationException(Messages.NOT_IMPLEMENTED_IN_2_0.format());
752 }
753
754 @Override
755 public JAXBIntrospector createJAXBIntrospector() {
756 return new JAXBIntrospector() {
757 public boolean isElement(Object object) {
758 return getElementName(object)!=null;
759 }
760
761 public QName getElementName(Object jaxbElement) {
762 try {
763 return JAXBContextImpl.this.getElementName(jaxbElement);
764 } catch (JAXBException e) {
765 return null;
766 }
767 }
768 };
769 }
770
771 private NonElement<Type,Class> getXmlType(RuntimeTypeInfoSet tis, TypeReference tr) {
772 if(tr==null)
773 throw new IllegalArgumentException();
774
775 XmlJavaTypeAdapter xjta = tr.get(XmlJavaTypeAdapter.class);
776 XmlList xl = tr.get(XmlList.class);
777
778 Ref<Type,Class> ref = new Ref<Type,Class>(annotationReader, tis.getNavigator(), tr.type, xjta, xl );
779
780 return tis.getTypeInfo(ref);
781 }
782
783 @Override
784 public void generateEpisode(Result output) {
785 if(output==null)
786 throw new IllegalArgumentException();
787 createSchemaGenerator().writeEpisodeFile(ResultFactory.createSerializer(output));
788 }
789
790 @Override
791 @SuppressWarnings("ThrowableInitCause")
792 public void generateSchema(SchemaOutputResolver outputResolver) throws IOException {
793 if(outputResolver==null)
794 throw new IOException(Messages.NULL_OUTPUT_RESOLVER.format());
795
796 final SAXParseException[] e = new SAXParseException[1];
797 final SAXParseException[] w = new SAXParseException[1];
798
799 createSchemaGenerator().write(outputResolver, new ErrorListener() {
800 public void error(SAXParseException exception) {
801 e[0] = exception;
802 }
803
804 public void fatalError(SAXParseException exception) {
805 e[0] = exception;
806 }
807
808 public void warning(SAXParseException exception) {
809 w[0] = exception;
810 }
811
812 public void info(SAXParseException exception) {}
813 });
814
815 if (e[0]!=null) {
816 IOException x = new IOException(Messages.FAILED_TO_GENERATE_SCHEMA.format());
817 x.initCause(e[0]);
818 throw x;
819 }
820 if (w[0]!=null) {
821 IOException x = new IOException(Messages.ERROR_PROCESSING_SCHEMA.format());
822 x.initCause(w[0]);
823 throw x;
824 }
825 }
826
827 private XmlSchemaGenerator<Type,Class,Field,Method> createSchemaGenerator() {
828 RuntimeTypeInfoSet tis;
829 try {
830 tis = getTypeInfoSet();
831 } catch (IllegalAnnotationsException e) {
832
833 throw new AssertionError(e);
834 }
835
836 XmlSchemaGenerator<Type,Class,Field,Method> xsdgen =
837 new XmlSchemaGenerator<Type,Class,Field,Method>(tis.getNavigator(),tis);
838
839
840
841
842 Set<QName> rootTagNames = new HashSet<QName>();
843 for (RuntimeElementInfo ei : tis.getAllElements()) {
844 rootTagNames.add(ei.getElementName());
845 }
846 for (RuntimeClassInfo ci : tis.beans().values()) {
847 if(ci.isElement())
848 rootTagNames.add(ci.asElement().getElementName());
849 }
850
851 for (TypeReference tr : bridges.keySet()) {
852 if(rootTagNames.contains(tr.tagName))
853 continue;
854
855 if(tr.type==void.class || tr.type==Void.class) {
856 xsdgen.add(tr.tagName,false,null);
857 } else
858 if(tr.type==CompositeStructure.class) {
859
860 } else {
861 NonElement<Type,Class> typeInfo = getXmlType(tis,tr);
862 xsdgen.add(tr.tagName, !tis.getNavigator().isPrimitive(tr.type),typeInfo);
863 }
864 }
865 return xsdgen;
866 }
867
868 public QName getTypeName(TypeReference tr) {
869 try {
870 NonElement<Type,Class> xt = getXmlType(getTypeInfoSet(),tr);
871 if(xt==null) throw new IllegalArgumentException();
872 return xt.getTypeName();
873 } catch (IllegalAnnotationsException e) {
874
875 throw new AssertionError(e);
876 }
877 }
878
879 @Override
880 public <T> Binder<T> createBinder(Class<T> domType) {
881 if(domType==Node.class)
882 return (Binder<T>)createBinder();
883 else
884 return super.createBinder(domType);
885 }
886
887 @Override
888 public Binder<Node> createBinder() {
889 return new BinderImpl<Node>(this,new DOMScanner());
890 }
891
892 public QName getElementName(Object o) throws JAXBException {
893 JaxBeanInfo bi = getBeanInfo(o,true);
894 if(!bi.isElement())
895 return null;
896 return new QName(bi.getElementNamespaceURI(o),bi.getElementLocalName(o));
897 }
898
899 public QName getElementName(Class o) throws JAXBException {
900 JaxBeanInfo bi = getBeanInfo(o,true);
901 if(!bi.isElement())
902 return null;
903 return new QName(bi.getElementNamespaceURI(o),bi.getElementLocalName(o));
904 }
905
906 public Bridge createBridge(TypeReference ref) {
907 return bridges.get(ref);
908 }
909
910 public @NotNull BridgeContext createBridgeContext() {
911 return new BridgeContextImpl(this);
912 }
913
914 public RawAccessor getElementPropertyAccessor(Class wrapperBean, String nsUri, String localName) throws JAXBException {
915 JaxBeanInfo bi = getBeanInfo(wrapperBean,true);
916 if(!(bi instanceof ClassBeanInfoImpl))
917 throw new JAXBException(wrapperBean+" is not a bean");
918
919 for( ClassBeanInfoImpl cb = (ClassBeanInfoImpl) bi; cb!=null; cb=cb.superClazz) {
920 for (Property p : cb.properties) {
921 final Accessor acc = p.getElementPropertyAccessor(nsUri,localName);
922 if(acc!=null)
923 return new RawAccessor() {
924
925
926
927
928
929 public Object get(Object bean) throws AccessorException {
930 return acc.getUnadapted(bean);
931 }
932
933 public void set(Object bean, Object value) throws AccessorException {
934 acc.setUnadapted(bean,value);
935 }
936 };
937 }
938 }
939 throw new JAXBException(new QName(nsUri,localName)+" is not a valid property on "+wrapperBean);
940 }
941
942 public List<String> getKnownNamespaceURIs() {
943 return Arrays.asList(nameList.namespaceURIs);
944 }
945
946 public String getBuildId() {
947 Package pkg = getClass().getPackage();
948 if(pkg==null) return null;
949 return pkg.getImplementationVersion();
950 }
951
952 @Override
953 public String toString() {
954 StringBuilder buf = new StringBuilder(Which.which(getClass()) + " Build-Id: " + getBuildId());
955 buf.append("\nClasses known to this context:\n");
956
957 Set<String> names = new TreeSet<String>();
958
959 for (Class key : beanInfoMap.keySet())
960 names.add(key.getName());
961
962 for(String name: names)
963 buf.append(" ").append(name).append('\n');
964
965 return buf.toString();
966 }
967
968
972 public String getXMIMEContentType( Object o ) {
973 JaxBeanInfo bi = getBeanInfo(o);
974 if(!(bi instanceof ClassBeanInfoImpl))
975 return null;
976
977 ClassBeanInfoImpl cb = (ClassBeanInfoImpl) bi;
978 for (Property p : cb.properties) {
979 if (p instanceof AttributeProperty) {
980 AttributeProperty ap = (AttributeProperty) p;
981 if(ap.attName.equals(WellKnownNamespace.XML_MIME_URI,"contentType"))
982 try {
983 return (String)ap.xacc.print(o);
984 } catch (AccessorException e) {
985 return null;
986 } catch (SAXException e) {
987 return null;
988 } catch (ClassCastException e) {
989 return null;
990 }
991 }
992 }
993 return null;
994 }
995
996
999 public JAXBContextImpl createAugmented(Class<?> clazz) throws JAXBException {
1000 Class[] newList = new Class[classes.length+1];
1001 System.arraycopy(classes,0,newList,0,classes.length);
1002 newList[classes.length] = clazz;
1003
1004 JAXBContextBuilder builder = new JAXBContextBuilder(this);
1005 builder.setClasses(newList);
1006 return builder.build();
1007 }
1008
1009 private static final Comparator<QName> QNAME_COMPARATOR = new Comparator<QName>() {
1010 public int compare(QName lhs, QName rhs) {
1011 int r = lhs.getLocalPart().compareTo(rhs.getLocalPart());
1012 if(r!=0) return r;
1013
1014 return lhs.getNamespaceURI().compareTo(rhs.getNamespaceURI());
1015 }
1016 };
1017
1018 public static class JAXBContextBuilder {
1019
1020 private boolean retainPropertyInfo = false;
1021 private boolean supressAccessorWarnings = false;
1022 private String defaultNsUri = "";
1023 private @NotNull RuntimeAnnotationReader annotationReader = new RuntimeInlineAnnotationReader();
1024 private @NotNull Map<Class,Class> subclassReplacements = Collections.emptyMap();
1025 private boolean c14nSupport = false;
1026 private Class[] classes;
1027 private Collection<TypeReference> typeRefs;
1028 private boolean xmlAccessorFactorySupport = false;
1029 private boolean allNillable;
1030 private boolean improvedXsiTypeHandling = true;
1031 private boolean disableSecurityProcessing = true;
1032 private Boolean backupWithParentNamespace = null;
1033 private int maxErrorsCount;
1034
1035 public JAXBContextBuilder() {};
1036
1037 public JAXBContextBuilder(JAXBContextImpl baseImpl) {
1038 this.supressAccessorWarnings = baseImpl.supressAccessorWarnings;
1039 this.retainPropertyInfo = baseImpl.retainPropertyInfo;
1040 this.defaultNsUri = baseImpl.defaultNsUri;
1041 this.annotationReader = baseImpl.annotationReader;
1042 this.subclassReplacements = baseImpl.subclassReplacements;
1043 this.c14nSupport = baseImpl.c14nSupport;
1044 this.classes = baseImpl.classes;
1045 this.typeRefs = baseImpl.bridges.keySet();
1046 this.xmlAccessorFactorySupport = baseImpl.xmlAccessorFactorySupport;
1047 this.allNillable = baseImpl.allNillable;
1048 this.disableSecurityProcessing = baseImpl.disableSecurityProcessing;
1049 this.backupWithParentNamespace = baseImpl.backupWithParentNamespace;
1050 this.maxErrorsCount = baseImpl.maxErrorsCount;
1051 }
1052
1053 public JAXBContextBuilder setRetainPropertyInfo(boolean val) {
1054 this.retainPropertyInfo = val;
1055 return this;
1056 }
1057
1058 public JAXBContextBuilder setSupressAccessorWarnings(boolean val) {
1059 this.supressAccessorWarnings = val;
1060 return this;
1061 }
1062
1063 public JAXBContextBuilder setC14NSupport(boolean val) {
1064 this.c14nSupport = val;
1065 return this;
1066 }
1067
1068 public JAXBContextBuilder setXmlAccessorFactorySupport(boolean val) {
1069 this.xmlAccessorFactorySupport = val;
1070 return this;
1071 }
1072
1073 public JAXBContextBuilder setDefaultNsUri(String val) {
1074 this.defaultNsUri = val;
1075 return this;
1076 }
1077
1078 public JAXBContextBuilder setAllNillable(boolean val) {
1079 this.allNillable = val;
1080 return this;
1081 }
1082
1083 public JAXBContextBuilder setClasses(Class[] val) {
1084 this.classes = val;
1085 return this;
1086 }
1087
1088 public JAXBContextBuilder setAnnotationReader(RuntimeAnnotationReader val) {
1089 this.annotationReader = val;
1090 return this;
1091 }
1092
1093 public JAXBContextBuilder setSubclassReplacements(Map<Class,Class> val) {
1094 this.subclassReplacements = val;
1095 return this;
1096 }
1097
1098 public JAXBContextBuilder setTypeRefs(Collection<TypeReference> val) {
1099 this.typeRefs = val;
1100 return this;
1101 }
1102
1103 public JAXBContextBuilder setImprovedXsiTypeHandling(boolean val) {
1104 this.improvedXsiTypeHandling = val;
1105 return this;
1106 }
1107
1108 public JAXBContextBuilder setDisableSecurityProcessing(boolean val) {
1109 this.disableSecurityProcessing = val;
1110 return this;
1111 }
1112
1113 public JAXBContextBuilder setBackupWithParentNamespace(Boolean backupWithParentNamespace) {
1114 this.backupWithParentNamespace = backupWithParentNamespace;
1115 return this;
1116 }
1117
1118 public JAXBContextBuilder setMaxErrorsCount(int maxErrorsCount) {
1119 this.maxErrorsCount = maxErrorsCount;
1120 return this;
1121 }
1122
1123 public JAXBContextImpl build() throws JAXBException {
1124
1125
1126 if (this.defaultNsUri == null) {
1127 this.defaultNsUri = "";
1128 }
1129
1130 if (this.subclassReplacements == null) {
1131 this.subclassReplacements = Collections.emptyMap();
1132 }
1133
1134 if (this.annotationReader == null) {
1135 this.annotationReader = new RuntimeInlineAnnotationReader();
1136 }
1137
1138 if (this.typeRefs == null) {
1139 this.typeRefs = Collections.<TypeReference>emptyList();
1140 }
1141
1142 return new JAXBContextImpl(this);
1143 }
1144
1145 }
1146
1147 }
1148