src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/JAXBContextImpl.java

Wed, 27 Apr 2016 01:27:09 +0800

author
aoqi
date
Wed, 27 Apr 2016 01:27:09 +0800
changeset 0
373ffda63c9a
child 637
9c07ef4934dd
permissions
-rw-r--r--

Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/jaxws/
changeset: 657:d47a47f961ee
tag: jdk8u25-b17

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation. Oracle designates this
aoqi@0 8 * particular file as subject to the "Classpath" exception as provided
aoqi@0 9 * by Oracle in the LICENSE file that accompanied this code.
aoqi@0 10 *
aoqi@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 14 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 15 * accompanied this code).
aoqi@0 16 *
aoqi@0 17 * You should have received a copy of the GNU General Public License version
aoqi@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 20 *
aoqi@0 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 22 * or visit www.oracle.com if you need additional information or have any
aoqi@0 23 * questions.
aoqi@0 24 */
aoqi@0 25
aoqi@0 26 package com.sun.xml.internal.bind.v2.runtime;
aoqi@0 27
aoqi@0 28 import java.io.IOException;
aoqi@0 29 import java.lang.ref.WeakReference;
aoqi@0 30 import java.lang.reflect.Field;
aoqi@0 31 import java.lang.reflect.Method;
aoqi@0 32 import java.lang.reflect.Type;
aoqi@0 33 import java.util.Arrays;
aoqi@0 34 import java.util.Collection;
aoqi@0 35 import java.util.Collections;
aoqi@0 36 import java.util.Comparator;
aoqi@0 37 import java.util.HashMap;
aoqi@0 38 import java.util.HashSet;
aoqi@0 39 import java.util.LinkedHashMap;
aoqi@0 40 import java.util.List;
aoqi@0 41 import java.util.Map;
aoqi@0 42 import java.util.Map.Entry;
aoqi@0 43 import java.util.Set;
aoqi@0 44 import java.util.TreeSet;
aoqi@0 45 import javax.xml.bind.Binder;
aoqi@0 46 import javax.xml.bind.JAXBContext;
aoqi@0 47 import javax.xml.bind.JAXBElement;
aoqi@0 48 import javax.xml.bind.JAXBException;
aoqi@0 49 import javax.xml.bind.JAXBIntrospector;
aoqi@0 50 import javax.xml.bind.Marshaller;
aoqi@0 51 import javax.xml.bind.SchemaOutputResolver;
aoqi@0 52 import javax.xml.bind.Unmarshaller;
aoqi@0 53 import javax.xml.bind.Validator;
aoqi@0 54 import javax.xml.bind.annotation.XmlAttachmentRef;
aoqi@0 55 import javax.xml.bind.annotation.XmlList;
aoqi@0 56 import javax.xml.bind.annotation.XmlNs;
aoqi@0 57 import javax.xml.bind.annotation.XmlSchema;
aoqi@0 58 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
aoqi@0 59 import javax.xml.namespace.QName;
aoqi@0 60 import javax.xml.parsers.DocumentBuilder;
aoqi@0 61 import javax.xml.parsers.DocumentBuilderFactory;
aoqi@0 62 import javax.xml.parsers.FactoryConfigurationError;
aoqi@0 63 import javax.xml.parsers.ParserConfigurationException;
aoqi@0 64 import javax.xml.transform.Result;
aoqi@0 65 import javax.xml.transform.Transformer;
aoqi@0 66 import javax.xml.transform.TransformerConfigurationException;
aoqi@0 67 import javax.xml.transform.TransformerFactory;
aoqi@0 68 import javax.xml.transform.sax.SAXTransformerFactory;
aoqi@0 69 import javax.xml.transform.sax.TransformerHandler;
aoqi@0 70
aoqi@0 71 import com.sun.istack.internal.NotNull;
aoqi@0 72 import com.sun.istack.internal.Pool;
aoqi@0 73 import com.sun.xml.internal.bind.v2.WellKnownNamespace;
aoqi@0 74 import com.sun.xml.internal.bind.api.AccessorException;
aoqi@0 75 import com.sun.xml.internal.bind.api.Bridge;
aoqi@0 76 import com.sun.xml.internal.bind.api.BridgeContext;
aoqi@0 77 import com.sun.xml.internal.bind.api.CompositeStructure;
aoqi@0 78 import com.sun.xml.internal.bind.api.ErrorListener;
aoqi@0 79 import com.sun.xml.internal.bind.api.JAXBRIContext;
aoqi@0 80 import com.sun.xml.internal.bind.api.RawAccessor;
aoqi@0 81 import com.sun.xml.internal.bind.api.TypeReference;
aoqi@0 82 import com.sun.xml.internal.bind.unmarshaller.DOMScanner;
aoqi@0 83 import com.sun.xml.internal.bind.util.Which;
aoqi@0 84 import com.sun.xml.internal.bind.v2.model.annotation.RuntimeAnnotationReader;
aoqi@0 85 import com.sun.xml.internal.bind.v2.model.annotation.RuntimeInlineAnnotationReader;
aoqi@0 86 import com.sun.xml.internal.bind.v2.model.core.Adapter;
aoqi@0 87 import com.sun.xml.internal.bind.v2.model.core.NonElement;
aoqi@0 88 import com.sun.xml.internal.bind.v2.model.core.Ref;
aoqi@0 89 import com.sun.xml.internal.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl;
aoqi@0 90 import com.sun.xml.internal.bind.v2.model.impl.RuntimeModelBuilder;
aoqi@0 91 import com.sun.xml.internal.bind.v2.model.nav.Navigator;
aoqi@0 92 import com.sun.xml.internal.bind.v2.model.runtime.RuntimeArrayInfo;
aoqi@0 93 import com.sun.xml.internal.bind.v2.model.runtime.RuntimeBuiltinLeafInfo;
aoqi@0 94 import com.sun.xml.internal.bind.v2.model.runtime.RuntimeClassInfo;
aoqi@0 95 import com.sun.xml.internal.bind.v2.model.runtime.RuntimeElementInfo;
aoqi@0 96 import com.sun.xml.internal.bind.v2.model.runtime.RuntimeEnumLeafInfo;
aoqi@0 97 import com.sun.xml.internal.bind.v2.model.runtime.RuntimeLeafInfo;
aoqi@0 98 import com.sun.xml.internal.bind.v2.model.runtime.RuntimeTypeInfo;
aoqi@0 99 import com.sun.xml.internal.bind.v2.model.runtime.RuntimeTypeInfoSet;
aoqi@0 100 import com.sun.xml.internal.bind.v2.runtime.output.Encoded;
aoqi@0 101 import com.sun.xml.internal.bind.v2.runtime.property.AttributeProperty;
aoqi@0 102 import com.sun.xml.internal.bind.v2.runtime.property.Property;
aoqi@0 103 import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor;
aoqi@0 104 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
aoqi@0 105 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.TagName;
aoqi@0 106 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl;
aoqi@0 107 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext;
aoqi@0 108 import com.sun.xml.internal.bind.v2.schemagen.XmlSchemaGenerator;
aoqi@0 109 import com.sun.xml.internal.bind.v2.util.EditDistance;
aoqi@0 110 import com.sun.xml.internal.bind.v2.util.QNameMap;
aoqi@0 111 import com.sun.xml.internal.bind.v2.util.XmlFactory;
aoqi@0 112 import com.sun.xml.internal.txw2.output.ResultFactory;
aoqi@0 113
aoqi@0 114 import org.w3c.dom.Document;
aoqi@0 115 import org.w3c.dom.Element;
aoqi@0 116 import org.w3c.dom.Node;
aoqi@0 117 import org.xml.sax.SAXException;
aoqi@0 118 import org.xml.sax.SAXParseException;
aoqi@0 119
aoqi@0 120 /**
aoqi@0 121 * This class provides the implementation of JAXBContext.
aoqi@0 122 *
aoqi@0 123 */
aoqi@0 124 public final class JAXBContextImpl extends JAXBRIContext {
aoqi@0 125
aoqi@0 126 /**
aoqi@0 127 * All the bridge classes.
aoqi@0 128 */
aoqi@0 129 private final Map<TypeReference,Bridge> bridges = new LinkedHashMap<TypeReference,Bridge>();
aoqi@0 130
aoqi@0 131 /**
aoqi@0 132 * Shared instance of {@link DocumentBuilder}.
aoqi@0 133 * Lock before use. Lazily created.
aoqi@0 134 */
aoqi@0 135 private static DocumentBuilder db;
aoqi@0 136
aoqi@0 137 private final QNameMap<JaxBeanInfo> rootMap = new QNameMap<JaxBeanInfo>();
aoqi@0 138 private final HashMap<QName,JaxBeanInfo> typeMap = new HashMap<QName,JaxBeanInfo>();
aoqi@0 139
aoqi@0 140 /**
aoqi@0 141 * Map from JAXB-bound {@link Class} to its {@link JaxBeanInfo}.
aoqi@0 142 */
aoqi@0 143 private final Map<Class,JaxBeanInfo> beanInfoMap = new LinkedHashMap<Class,JaxBeanInfo>();
aoqi@0 144
aoqi@0 145 /**
aoqi@0 146 * All created {@link JaxBeanInfo}s.
aoqi@0 147 * Updated from each {@link JaxBeanInfo}s constructors to avoid infinite recursion
aoqi@0 148 * for a cyclic reference.
aoqi@0 149 *
aoqi@0 150 * <p>
aoqi@0 151 * This map is only used while the {@link JAXBContextImpl} is built and set to null
aoqi@0 152 * to avoid keeping references too long.
aoqi@0 153 */
aoqi@0 154 protected Map<RuntimeTypeInfo,JaxBeanInfo> beanInfos = new LinkedHashMap<RuntimeTypeInfo, JaxBeanInfo>();
aoqi@0 155
aoqi@0 156 private final Map<Class/*scope*/,Map<QName,ElementBeanInfoImpl>> elements = new LinkedHashMap<Class, Map<QName, ElementBeanInfoImpl>>();
aoqi@0 157
aoqi@0 158 /**
aoqi@0 159 * Pool of {@link Marshaller}s.
aoqi@0 160 */
aoqi@0 161 public final Pool<Marshaller> marshallerPool = new Pool.Impl<Marshaller>() {
aoqi@0 162 protected @NotNull Marshaller create() {
aoqi@0 163 return createMarshaller();
aoqi@0 164 }
aoqi@0 165 };
aoqi@0 166
aoqi@0 167 public final Pool<Unmarshaller> unmarshallerPool = new Pool.Impl<Unmarshaller>() {
aoqi@0 168 protected @NotNull Unmarshaller create() {
aoqi@0 169 return createUnmarshaller();
aoqi@0 170 }
aoqi@0 171 };
aoqi@0 172
aoqi@0 173 /**
aoqi@0 174 * Used to assign indices to known names in this grammar.
aoqi@0 175 * Reset to null once the build phase is completed.
aoqi@0 176 */
aoqi@0 177 public NameBuilder nameBuilder = new NameBuilder();
aoqi@0 178
aoqi@0 179 /**
aoqi@0 180 * Keeps the list of known names.
aoqi@0 181 * This field is set once the build pahse is completed.
aoqi@0 182 */
aoqi@0 183 public final NameList nameList;
aoqi@0 184
aoqi@0 185 /**
aoqi@0 186 * Input to the JAXBContext.newInstance, so that we can recreate
aoqi@0 187 * {@link RuntimeTypeInfoSet} whenever we need.
aoqi@0 188 */
aoqi@0 189 private final String defaultNsUri;
aoqi@0 190 private final Class[] classes;
aoqi@0 191
aoqi@0 192 /**
aoqi@0 193 * true to reorder attributes lexicographically in preparation of the c14n support.
aoqi@0 194 */
aoqi@0 195 protected final boolean c14nSupport;
aoqi@0 196
aoqi@0 197 /**
aoqi@0 198 * Flag that user has provided a custom AccessorFactory for JAXB to use
aoqi@0 199 */
aoqi@0 200 public final boolean xmlAccessorFactorySupport;
aoqi@0 201
aoqi@0 202 /**
aoqi@0 203 * @see JAXBRIContext#TREAT_EVERYTHING_NILLABLE
aoqi@0 204 */
aoqi@0 205 public final boolean allNillable;
aoqi@0 206
aoqi@0 207 /**
aoqi@0 208 * Store properties, so that they can be recovered in the run (is here because of JSON encoding of Jersey).
aoqi@0 209 */
aoqi@0 210 public final boolean retainPropertyInfo;
aoqi@0 211
aoqi@0 212 /**
aoqi@0 213 * Suppress reflection accessor warnings.
aoqi@0 214 */
aoqi@0 215 public final boolean supressAccessorWarnings;
aoqi@0 216
aoqi@0 217 /**
aoqi@0 218 * Improved xsi type handling.
aoqi@0 219 */
aoqi@0 220 public final boolean improvedXsiTypeHandling;
aoqi@0 221
aoqi@0 222 /**
aoqi@0 223 * Disable security processing.
aoqi@0 224 */
aoqi@0 225 public final boolean disableSecurityProcessing;
aoqi@0 226
aoqi@0 227 private WeakReference<RuntimeTypeInfoSet> typeInfoSetCache;
aoqi@0 228
aoqi@0 229 private @NotNull RuntimeAnnotationReader annotationReader;
aoqi@0 230
aoqi@0 231 private /*almost final*/ boolean hasSwaRef;
aoqi@0 232 private final @NotNull Map<Class,Class> subclassReplacements;
aoqi@0 233
aoqi@0 234 /**
aoqi@0 235 * If true, we aim for faster {@link JAXBContext} instantiation performance,
aoqi@0 236 * instead of going after efficient sustained unmarshalling/marshalling performance.
aoqi@0 237 *
aoqi@0 238 * @since 2.0.4
aoqi@0 239 */
aoqi@0 240 public final boolean fastBoot;
aoqi@0 241
aoqi@0 242 private Set<XmlNs> xmlNsSet = null;
aoqi@0 243
aoqi@0 244 /**
aoqi@0 245 * Returns declared XmlNs annotations (from package-level annotation XmlSchema
aoqi@0 246 *
aoqi@0 247 * @return set of all present XmlNs annotations
aoqi@0 248 */
aoqi@0 249 public Set<XmlNs> getXmlNsSet() {
aoqi@0 250 return xmlNsSet;
aoqi@0 251 }
aoqi@0 252
aoqi@0 253 private JAXBContextImpl(JAXBContextBuilder builder) throws JAXBException {
aoqi@0 254
aoqi@0 255 this.defaultNsUri = builder.defaultNsUri;
aoqi@0 256 this.retainPropertyInfo = builder.retainPropertyInfo;
aoqi@0 257 this.annotationReader = builder.annotationReader;
aoqi@0 258 this.subclassReplacements = builder.subclassReplacements;
aoqi@0 259 this.c14nSupport = builder.c14nSupport;
aoqi@0 260 this.classes = builder.classes;
aoqi@0 261 this.xmlAccessorFactorySupport = builder.xmlAccessorFactorySupport;
aoqi@0 262 this.allNillable = builder.allNillable;
aoqi@0 263 this.supressAccessorWarnings = builder.supressAccessorWarnings;
aoqi@0 264 this.improvedXsiTypeHandling = builder.improvedXsiTypeHandling;
aoqi@0 265 this.disableSecurityProcessing = builder.disableSecurityProcessing;
aoqi@0 266
aoqi@0 267 Collection<TypeReference> typeRefs = builder.typeRefs;
aoqi@0 268
aoqi@0 269 boolean fastB;
aoqi@0 270 try {
aoqi@0 271 fastB = Boolean.getBoolean(JAXBContextImpl.class.getName()+".fastBoot");
aoqi@0 272 } catch (SecurityException e) {
aoqi@0 273 fastB = false;
aoqi@0 274 }
aoqi@0 275 this.fastBoot = fastB;
aoqi@0 276
aoqi@0 277 RuntimeTypeInfoSet typeSet = getTypeInfoSet();
aoqi@0 278
aoqi@0 279 // at least prepare the empty table so that we don't have to check for null later
aoqi@0 280 elements.put(null,new LinkedHashMap<QName, ElementBeanInfoImpl>());
aoqi@0 281
aoqi@0 282 // recognize leaf bean infos
aoqi@0 283 for( RuntimeBuiltinLeafInfo leaf : RuntimeBuiltinLeafInfoImpl.builtinBeanInfos ) {
aoqi@0 284 LeafBeanInfoImpl<?> bi = new LeafBeanInfoImpl(this,leaf);
aoqi@0 285 beanInfoMap.put(leaf.getClazz(),bi);
aoqi@0 286 for( QName t : bi.getTypeNames() )
aoqi@0 287 typeMap.put(t,bi);
aoqi@0 288 }
aoqi@0 289
aoqi@0 290 for (RuntimeEnumLeafInfo e : typeSet.enums().values()) {
aoqi@0 291 JaxBeanInfo<?> bi = getOrCreate(e);
aoqi@0 292 for (QName qn : bi.getTypeNames())
aoqi@0 293 typeMap.put( qn, bi );
aoqi@0 294 if(e.isElement())
aoqi@0 295 rootMap.put( e.getElementName(), bi );
aoqi@0 296 }
aoqi@0 297
aoqi@0 298 for (RuntimeArrayInfo a : typeSet.arrays().values()) {
aoqi@0 299 JaxBeanInfo<?> ai = getOrCreate(a);
aoqi@0 300 for (QName qn : ai.getTypeNames())
aoqi@0 301 typeMap.put( qn, ai );
aoqi@0 302 }
aoqi@0 303
aoqi@0 304 for( Entry<Class, ? extends RuntimeClassInfo> e : typeSet.beans().entrySet() ) {
aoqi@0 305 ClassBeanInfoImpl<?> bi = getOrCreate(e.getValue());
aoqi@0 306
aoqi@0 307 XmlSchema xs = this.annotationReader.getPackageAnnotation(XmlSchema.class, e.getKey(), null);
aoqi@0 308 if(xs != null) {
aoqi@0 309 if(xs.xmlns() != null && xs.xmlns().length > 0) {
aoqi@0 310 if(xmlNsSet == null)
aoqi@0 311 xmlNsSet = new HashSet<XmlNs>();
aoqi@0 312 xmlNsSet.addAll(Arrays.asList(xs.xmlns()));
aoqi@0 313 }
aoqi@0 314 }
aoqi@0 315
aoqi@0 316 if(bi.isElement())
aoqi@0 317 rootMap.put( e.getValue().getElementName(), bi );
aoqi@0 318
aoqi@0 319 for (QName qn : bi.getTypeNames())
aoqi@0 320 typeMap.put( qn, bi );
aoqi@0 321 }
aoqi@0 322
aoqi@0 323 // fill in element mappings
aoqi@0 324 for( RuntimeElementInfo n : typeSet.getAllElements() ) {
aoqi@0 325 ElementBeanInfoImpl bi = getOrCreate(n);
aoqi@0 326 if(n.getScope()==null)
aoqi@0 327 rootMap.put(n.getElementName(),bi);
aoqi@0 328
aoqi@0 329 RuntimeClassInfo scope = n.getScope();
aoqi@0 330 Class scopeClazz = scope==null?null:scope.getClazz();
aoqi@0 331 Map<QName,ElementBeanInfoImpl> m = elements.get(scopeClazz);
aoqi@0 332 if(m==null) {
aoqi@0 333 m = new LinkedHashMap<QName, ElementBeanInfoImpl>();
aoqi@0 334 elements.put(scopeClazz,m);
aoqi@0 335 }
aoqi@0 336 m.put(n.getElementName(),bi);
aoqi@0 337 }
aoqi@0 338
aoqi@0 339 // this one is so that we can handle plain JAXBElements.
aoqi@0 340 beanInfoMap.put(JAXBElement.class,new ElementBeanInfoImpl(this));
aoqi@0 341 // another special BeanInfoImpl just for marshalling
aoqi@0 342 beanInfoMap.put(CompositeStructure.class,new CompositeStructureBeanInfo(this));
aoqi@0 343
aoqi@0 344 getOrCreate(typeSet.getAnyTypeInfo());
aoqi@0 345
aoqi@0 346 // then link them all!
aoqi@0 347 for (JaxBeanInfo bi : beanInfos.values())
aoqi@0 348 bi.link(this);
aoqi@0 349
aoqi@0 350 // register primitives for boxed types just to make GrammarInfo fool-proof
aoqi@0 351 for( Map.Entry<Class,Class> e : RuntimeUtil.primitiveToBox.entrySet() )
aoqi@0 352 beanInfoMap.put( e.getKey(), beanInfoMap.get(e.getValue()) );
aoqi@0 353
aoqi@0 354 // build bridges
aoqi@0 355 Navigator<Type, Class, Field, Method> nav = typeSet.getNavigator();
aoqi@0 356
aoqi@0 357 for (TypeReference tr : typeRefs) {
aoqi@0 358 XmlJavaTypeAdapter xjta = tr.get(XmlJavaTypeAdapter.class);
aoqi@0 359 Adapter<Type,Class> a=null;
aoqi@0 360 XmlList xl = tr.get(XmlList.class);
aoqi@0 361
aoqi@0 362 // eventually compute the in-memory type
aoqi@0 363 Class erasedType = (Class) nav.erasure(tr.type);
aoqi@0 364
aoqi@0 365 if(xjta!=null) {
aoqi@0 366 a = new Adapter<Type,Class>(xjta.value(),nav);
aoqi@0 367 }
aoqi@0 368 if(tr.get(XmlAttachmentRef.class)!=null) {
aoqi@0 369 a = new Adapter<Type,Class>(SwaRefAdapter.class,nav);
aoqi@0 370 hasSwaRef = true;
aoqi@0 371 }
aoqi@0 372
aoqi@0 373 if(a!=null) {
aoqi@0 374 erasedType = (Class) nav.erasure(a.defaultType);
aoqi@0 375 }
aoqi@0 376
aoqi@0 377 Name name = nameBuilder.createElementName(tr.tagName);
aoqi@0 378
aoqi@0 379 InternalBridge bridge;
aoqi@0 380 if(xl==null)
aoqi@0 381 bridge = new BridgeImpl(this, name,getBeanInfo(erasedType,true),tr);
aoqi@0 382 else
aoqi@0 383 bridge = new BridgeImpl(this, name,new ValueListBeanInfoImpl(this,erasedType),tr);
aoqi@0 384
aoqi@0 385 if(a!=null)
aoqi@0 386 bridge = new BridgeAdapter(bridge,a.adapterType);
aoqi@0 387
aoqi@0 388 bridges.put(tr,bridge);
aoqi@0 389 }
aoqi@0 390
aoqi@0 391 this.nameList = nameBuilder.conclude();
aoqi@0 392
aoqi@0 393 for (JaxBeanInfo bi : beanInfos.values())
aoqi@0 394 bi.wrapUp();
aoqi@0 395
aoqi@0 396 // no use for them now
aoqi@0 397 nameBuilder = null;
aoqi@0 398 beanInfos = null;
aoqi@0 399 }
aoqi@0 400
aoqi@0 401 /**
aoqi@0 402 * True if this JAXBContext has {@link XmlAttachmentRef}.
aoqi@0 403 */
aoqi@0 404 public boolean hasSwaRef() {
aoqi@0 405 return hasSwaRef;
aoqi@0 406 }
aoqi@0 407
aoqi@0 408 public RuntimeTypeInfoSet getRuntimeTypeInfoSet() {
aoqi@0 409 try {
aoqi@0 410 return getTypeInfoSet();
aoqi@0 411 } catch (IllegalAnnotationsException e) {
aoqi@0 412 // impossible, once the model is constructred
aoqi@0 413 throw new AssertionError(e);
aoqi@0 414 }
aoqi@0 415 }
aoqi@0 416
aoqi@0 417 /**
aoqi@0 418 * Creates a {@link RuntimeTypeInfoSet}.
aoqi@0 419 */
aoqi@0 420 public RuntimeTypeInfoSet getTypeInfoSet() throws IllegalAnnotationsException {
aoqi@0 421
aoqi@0 422 // check cache
aoqi@0 423 if(typeInfoSetCache!=null) {
aoqi@0 424 RuntimeTypeInfoSet r = typeInfoSetCache.get();
aoqi@0 425 if(r!=null)
aoqi@0 426 return r;
aoqi@0 427 }
aoqi@0 428
aoqi@0 429 final RuntimeModelBuilder builder = new RuntimeModelBuilder(this,annotationReader,subclassReplacements,defaultNsUri);
aoqi@0 430
aoqi@0 431 IllegalAnnotationsException.Builder errorHandler = new IllegalAnnotationsException.Builder();
aoqi@0 432 builder.setErrorHandler(errorHandler);
aoqi@0 433
aoqi@0 434 for( Class c : classes ) {
aoqi@0 435 if(c==CompositeStructure.class)
aoqi@0 436 // CompositeStructure doesn't have TypeInfo, so skip it.
aoqi@0 437 // We'll add JaxBeanInfo for this later automatically
aoqi@0 438 continue;
aoqi@0 439 builder.getTypeInfo(new Ref<Type,Class>(c));
aoqi@0 440 }
aoqi@0 441
aoqi@0 442 this.hasSwaRef |= builder.hasSwaRef;
aoqi@0 443 RuntimeTypeInfoSet r = builder.link();
aoqi@0 444
aoqi@0 445 errorHandler.check();
aoqi@0 446 assert r!=null : "if no error was reported, the link must be a success";
aoqi@0 447
aoqi@0 448 typeInfoSetCache = new WeakReference<RuntimeTypeInfoSet>(r);
aoqi@0 449
aoqi@0 450 return r;
aoqi@0 451 }
aoqi@0 452
aoqi@0 453
aoqi@0 454 public ElementBeanInfoImpl getElement(Class scope, QName name) {
aoqi@0 455 Map<QName,ElementBeanInfoImpl> m = elements.get(scope);
aoqi@0 456 if(m!=null) {
aoqi@0 457 ElementBeanInfoImpl bi = m.get(name);
aoqi@0 458 if(bi!=null)
aoqi@0 459 return bi;
aoqi@0 460 }
aoqi@0 461 m = elements.get(null);
aoqi@0 462 return m.get(name);
aoqi@0 463 }
aoqi@0 464
aoqi@0 465
aoqi@0 466
aoqi@0 467
aoqi@0 468
aoqi@0 469 private ElementBeanInfoImpl getOrCreate( RuntimeElementInfo rei ) {
aoqi@0 470 JaxBeanInfo bi = beanInfos.get(rei);
aoqi@0 471 if(bi!=null) return (ElementBeanInfoImpl)bi;
aoqi@0 472
aoqi@0 473 // all elements share the same type, so we can't register them to beanInfoMap
aoqi@0 474 return new ElementBeanInfoImpl(this, rei);
aoqi@0 475 }
aoqi@0 476
aoqi@0 477 protected JaxBeanInfo getOrCreate( RuntimeEnumLeafInfo eli ) {
aoqi@0 478 JaxBeanInfo bi = beanInfos.get(eli);
aoqi@0 479 if(bi!=null) return bi;
aoqi@0 480 bi = new LeafBeanInfoImpl(this,eli);
aoqi@0 481 beanInfoMap.put(bi.jaxbType,bi);
aoqi@0 482 return bi;
aoqi@0 483 }
aoqi@0 484
aoqi@0 485 protected ClassBeanInfoImpl getOrCreate( RuntimeClassInfo ci ) {
aoqi@0 486 ClassBeanInfoImpl bi = (ClassBeanInfoImpl)beanInfos.get(ci);
aoqi@0 487 if(bi!=null) return bi;
aoqi@0 488 bi = new ClassBeanInfoImpl(this,ci);
aoqi@0 489 beanInfoMap.put(bi.jaxbType,bi);
aoqi@0 490 return bi;
aoqi@0 491 }
aoqi@0 492
aoqi@0 493 protected JaxBeanInfo getOrCreate( RuntimeArrayInfo ai ) {
aoqi@0 494 JaxBeanInfo abi = beanInfos.get(ai);
aoqi@0 495 if(abi!=null) return abi;
aoqi@0 496
aoqi@0 497 abi = new ArrayBeanInfoImpl(this,ai);
aoqi@0 498
aoqi@0 499 beanInfoMap.put(ai.getType(),abi);
aoqi@0 500 return abi;
aoqi@0 501 }
aoqi@0 502
aoqi@0 503 public JaxBeanInfo getOrCreate(RuntimeTypeInfo e) {
aoqi@0 504 if(e instanceof RuntimeElementInfo)
aoqi@0 505 return getOrCreate((RuntimeElementInfo)e);
aoqi@0 506 if(e instanceof RuntimeClassInfo)
aoqi@0 507 return getOrCreate((RuntimeClassInfo)e);
aoqi@0 508 if(e instanceof RuntimeLeafInfo) {
aoqi@0 509 JaxBeanInfo bi = beanInfos.get(e); // must have been created
aoqi@0 510 assert bi!=null;
aoqi@0 511 return bi;
aoqi@0 512 }
aoqi@0 513 if(e instanceof RuntimeArrayInfo)
aoqi@0 514 return getOrCreate((RuntimeArrayInfo)e);
aoqi@0 515 if(e.getType()==Object.class) {
aoqi@0 516 // anyType
aoqi@0 517 JaxBeanInfo bi = beanInfoMap.get(Object.class);
aoqi@0 518 if(bi==null) {
aoqi@0 519 bi = new AnyTypeBeanInfo(this,e);
aoqi@0 520 beanInfoMap.put(Object.class,bi);
aoqi@0 521 }
aoqi@0 522 return bi;
aoqi@0 523 }
aoqi@0 524
aoqi@0 525 throw new IllegalArgumentException();
aoqi@0 526 }
aoqi@0 527
aoqi@0 528 /**
aoqi@0 529 * Gets the {@link JaxBeanInfo} object that can handle
aoqi@0 530 * the given JAXB-bound object.
aoqi@0 531 *
aoqi@0 532 * <p>
aoqi@0 533 * This method traverses the base classes of the given object.
aoqi@0 534 *
aoqi@0 535 * @return null
aoqi@0 536 * if <tt>c</tt> isn't a JAXB-bound class and <tt>fatal==false</tt>.
aoqi@0 537 */
aoqi@0 538 public final JaxBeanInfo getBeanInfo(Object o) {
aoqi@0 539 // don't allow xs:anyType beanInfo to handle all the unbound objects
aoqi@0 540 for( Class c=o.getClass(); c!=Object.class; c=c.getSuperclass()) {
aoqi@0 541 JaxBeanInfo bi = beanInfoMap.get(c);
aoqi@0 542 if(bi!=null) return bi;
aoqi@0 543 }
aoqi@0 544 if(o instanceof Element)
aoqi@0 545 return beanInfoMap.get(Object.class); // return the BeanInfo for xs:anyType
aoqi@0 546 for( Class c : o.getClass().getInterfaces()) {
aoqi@0 547 JaxBeanInfo bi = beanInfoMap.get(c);
aoqi@0 548 if(bi!=null) return bi;
aoqi@0 549 }
aoqi@0 550 return null;
aoqi@0 551 }
aoqi@0 552
aoqi@0 553 /**
aoqi@0 554 * Gets the {@link JaxBeanInfo} object that can handle
aoqi@0 555 * the given JAXB-bound object.
aoqi@0 556 *
aoqi@0 557 * @param fatal
aoqi@0 558 * if true, the failure to look up will throw an exception.
aoqi@0 559 * Otherwise it will just return null.
aoqi@0 560 */
aoqi@0 561 public final JaxBeanInfo getBeanInfo(Object o,boolean fatal) throws JAXBException {
aoqi@0 562 JaxBeanInfo bi = getBeanInfo(o);
aoqi@0 563 if(bi!=null) return bi;
aoqi@0 564 if(fatal) {
aoqi@0 565 if(o instanceof Document)
aoqi@0 566 throw new JAXBException(Messages.ELEMENT_NEEDED_BUT_FOUND_DOCUMENT.format(o.getClass()));
aoqi@0 567 throw new JAXBException(Messages.UNKNOWN_CLASS.format(o.getClass()));
aoqi@0 568 }
aoqi@0 569 return null;
aoqi@0 570 }
aoqi@0 571
aoqi@0 572 /**
aoqi@0 573 * Gets the {@link JaxBeanInfo} object that can handle
aoqi@0 574 * the given JAXB-bound class.
aoqi@0 575 *
aoqi@0 576 * <p>
aoqi@0 577 * This method doesn't look for base classes.
aoqi@0 578 *
aoqi@0 579 * @return null
aoqi@0 580 * if <tt>c</tt> isn't a JAXB-bound class and <tt>fatal==false</tt>.
aoqi@0 581 */
aoqi@0 582 public final <T> JaxBeanInfo<T> getBeanInfo(Class<T> clazz) {
aoqi@0 583 return (JaxBeanInfo<T>)beanInfoMap.get(clazz);
aoqi@0 584 }
aoqi@0 585
aoqi@0 586 /**
aoqi@0 587 * Gets the {@link JaxBeanInfo} object that can handle
aoqi@0 588 * the given JAXB-bound class.
aoqi@0 589 *
aoqi@0 590 * @param fatal
aoqi@0 591 * if true, the failure to look up will throw an exception.
aoqi@0 592 * Otherwise it will just return null.
aoqi@0 593 */
aoqi@0 594 public final <T> JaxBeanInfo<T> getBeanInfo(Class<T> clazz,boolean fatal) throws JAXBException {
aoqi@0 595 JaxBeanInfo<T> bi = getBeanInfo(clazz);
aoqi@0 596 if(bi!=null) return bi;
aoqi@0 597 if(fatal)
aoqi@0 598 throw new JAXBException(clazz.getName()+" is not known to this context");
aoqi@0 599 return null;
aoqi@0 600 }
aoqi@0 601
aoqi@0 602 /**
aoqi@0 603 * Based on the tag name, determine what object to unmarshal,
aoqi@0 604 * and then set a new object and its loader to the current unmarshaller state.
aoqi@0 605 *
aoqi@0 606 * @return
aoqi@0 607 * null if the given name pair is not recognized.
aoqi@0 608 */
aoqi@0 609 public final Loader selectRootLoader( UnmarshallingContext.State state, TagName tag ) {
aoqi@0 610 JaxBeanInfo beanInfo = rootMap.get(tag.uri,tag.local);
aoqi@0 611 if(beanInfo==null)
aoqi@0 612 return null;
aoqi@0 613
aoqi@0 614 return beanInfo.getLoader(this,true);
aoqi@0 615 }
aoqi@0 616
aoqi@0 617 /**
aoqi@0 618 * Gets the {@link JaxBeanInfo} for the given named XML Schema type.
aoqi@0 619 *
aoqi@0 620 * @return
aoqi@0 621 * null if the type name is not recognized. For schema
aoqi@0 622 * languages other than XML Schema, this method always
aoqi@0 623 * returns null.
aoqi@0 624 */
aoqi@0 625 public JaxBeanInfo getGlobalType(QName name) {
aoqi@0 626 return typeMap.get(name);
aoqi@0 627 }
aoqi@0 628
aoqi@0 629 /**
aoqi@0 630 * Finds a type name that this context recognizes which is
aoqi@0 631 * "closest" to the given type name.
aoqi@0 632 *
aoqi@0 633 * <p>
aoqi@0 634 * This method is used for error recovery.
aoqi@0 635 */
aoqi@0 636 public String getNearestTypeName(QName name) {
aoqi@0 637 String[] all = new String[typeMap.size()];
aoqi@0 638 int i=0;
aoqi@0 639 for (QName qn : typeMap.keySet()) {
aoqi@0 640 if(qn.getLocalPart().equals(name.getLocalPart()))
aoqi@0 641 return qn.toString(); // probably a match, as people often gets confused about namespace.
aoqi@0 642 all[i++] = qn.toString();
aoqi@0 643 }
aoqi@0 644
aoqi@0 645 String nearest = EditDistance.findNearest(name.toString(), all);
aoqi@0 646
aoqi@0 647 if(EditDistance.editDistance(nearest,name.toString())>10)
aoqi@0 648 return null; // too far apart.
aoqi@0 649
aoqi@0 650 return nearest;
aoqi@0 651 }
aoqi@0 652
aoqi@0 653 /**
aoqi@0 654 * Returns the set of valid root tag names.
aoqi@0 655 * For diagnostic use.
aoqi@0 656 */
aoqi@0 657 public Set<QName> getValidRootNames() {
aoqi@0 658 Set<QName> r = new TreeSet<QName>(QNAME_COMPARATOR);
aoqi@0 659 for (QNameMap.Entry e : rootMap.entrySet()) {
aoqi@0 660 r.add(e.createQName());
aoqi@0 661 }
aoqi@0 662 return r;
aoqi@0 663 }
aoqi@0 664
aoqi@0 665 /**
aoqi@0 666 * Cache of UTF-8 encoded local names to improve the performance for the marshalling.
aoqi@0 667 */
aoqi@0 668 private Encoded[] utf8nameTable;
aoqi@0 669
aoqi@0 670 public synchronized Encoded[] getUTF8NameTable() {
aoqi@0 671 if(utf8nameTable==null) {
aoqi@0 672 Encoded[] x = new Encoded[nameList.localNames.length];
aoqi@0 673 for( int i=0; i<x.length; i++ ) {
aoqi@0 674 Encoded e = new Encoded(nameList.localNames[i]);
aoqi@0 675 e.compact();
aoqi@0 676 x[i] = e;
aoqi@0 677 }
aoqi@0 678 utf8nameTable = x;
aoqi@0 679 }
aoqi@0 680 return utf8nameTable;
aoqi@0 681 }
aoqi@0 682
aoqi@0 683 public int getNumberOfLocalNames() {
aoqi@0 684 return nameList.localNames.length;
aoqi@0 685 }
aoqi@0 686
aoqi@0 687 public int getNumberOfElementNames() {
aoqi@0 688 return nameList.numberOfElementNames;
aoqi@0 689 }
aoqi@0 690
aoqi@0 691 public int getNumberOfAttributeNames() {
aoqi@0 692 return nameList.numberOfAttributeNames;
aoqi@0 693 }
aoqi@0 694
aoqi@0 695 /**
aoqi@0 696 * Creates a new identity transformer.
aoqi@0 697 */
aoqi@0 698 static Transformer createTransformer(boolean disableSecureProcessing) {
aoqi@0 699 try {
aoqi@0 700 SAXTransformerFactory tf = (SAXTransformerFactory)XmlFactory.createTransformerFactory(disableSecureProcessing);
aoqi@0 701 return tf.newTransformer();
aoqi@0 702 } catch (TransformerConfigurationException e) {
aoqi@0 703 throw new Error(e); // impossible
aoqi@0 704 }
aoqi@0 705 }
aoqi@0 706
aoqi@0 707 /**
aoqi@0 708 * Creates a new identity transformer.
aoqi@0 709 */
aoqi@0 710 public static TransformerHandler createTransformerHandler(boolean disableSecureProcessing) {
aoqi@0 711 try {
aoqi@0 712 SAXTransformerFactory tf = (SAXTransformerFactory)XmlFactory.createTransformerFactory(disableSecureProcessing);
aoqi@0 713 return tf.newTransformerHandler();
aoqi@0 714 } catch (TransformerConfigurationException e) {
aoqi@0 715 throw new Error(e); // impossible
aoqi@0 716 }
aoqi@0 717 }
aoqi@0 718
aoqi@0 719 /**
aoqi@0 720 * Creates a new DOM document.
aoqi@0 721 */
aoqi@0 722 static Document createDom(boolean disableSecurityProcessing) {
aoqi@0 723 synchronized(JAXBContextImpl.class) {
aoqi@0 724 if(db==null) {
aoqi@0 725 try {
aoqi@0 726 DocumentBuilderFactory dbf = XmlFactory.createDocumentBuilderFactory(disableSecurityProcessing);
aoqi@0 727 db = dbf.newDocumentBuilder();
aoqi@0 728 } catch (ParserConfigurationException e) {
aoqi@0 729 // impossible
aoqi@0 730 throw new FactoryConfigurationError(e);
aoqi@0 731 }
aoqi@0 732 }
aoqi@0 733 return db.newDocument();
aoqi@0 734 }
aoqi@0 735 }
aoqi@0 736
aoqi@0 737 public MarshallerImpl createMarshaller() {
aoqi@0 738 return new MarshallerImpl(this,null);
aoqi@0 739 }
aoqi@0 740
aoqi@0 741 public UnmarshallerImpl createUnmarshaller() {
aoqi@0 742 return new UnmarshallerImpl(this,null);
aoqi@0 743 }
aoqi@0 744
aoqi@0 745 public Validator createValidator() {
aoqi@0 746 throw new UnsupportedOperationException(Messages.NOT_IMPLEMENTED_IN_2_0.format());
aoqi@0 747 }
aoqi@0 748
aoqi@0 749 @Override
aoqi@0 750 public JAXBIntrospector createJAXBIntrospector() {
aoqi@0 751 return new JAXBIntrospector() {
aoqi@0 752 public boolean isElement(Object object) {
aoqi@0 753 return getElementName(object)!=null;
aoqi@0 754 }
aoqi@0 755
aoqi@0 756 public QName getElementName(Object jaxbElement) {
aoqi@0 757 try {
aoqi@0 758 return JAXBContextImpl.this.getElementName(jaxbElement);
aoqi@0 759 } catch (JAXBException e) {
aoqi@0 760 return null;
aoqi@0 761 }
aoqi@0 762 }
aoqi@0 763 };
aoqi@0 764 }
aoqi@0 765
aoqi@0 766 private NonElement<Type,Class> getXmlType(RuntimeTypeInfoSet tis, TypeReference tr) {
aoqi@0 767 if(tr==null)
aoqi@0 768 throw new IllegalArgumentException();
aoqi@0 769
aoqi@0 770 XmlJavaTypeAdapter xjta = tr.get(XmlJavaTypeAdapter.class);
aoqi@0 771 XmlList xl = tr.get(XmlList.class);
aoqi@0 772
aoqi@0 773 Ref<Type,Class> ref = new Ref<Type,Class>(annotationReader, tis.getNavigator(), tr.type, xjta, xl );
aoqi@0 774
aoqi@0 775 return tis.getTypeInfo(ref);
aoqi@0 776 }
aoqi@0 777
aoqi@0 778 @Override
aoqi@0 779 public void generateEpisode(Result output) {
aoqi@0 780 if(output==null)
aoqi@0 781 throw new IllegalArgumentException();
aoqi@0 782 createSchemaGenerator().writeEpisodeFile(ResultFactory.createSerializer(output));
aoqi@0 783 }
aoqi@0 784
aoqi@0 785 @Override
aoqi@0 786 @SuppressWarnings("ThrowableInitCause")
aoqi@0 787 public void generateSchema(SchemaOutputResolver outputResolver) throws IOException {
aoqi@0 788 if(outputResolver==null)
aoqi@0 789 throw new IOException(Messages.NULL_OUTPUT_RESOLVER.format());
aoqi@0 790
aoqi@0 791 final SAXParseException[] e = new SAXParseException[1];
aoqi@0 792 final SAXParseException[] w = new SAXParseException[1];
aoqi@0 793
aoqi@0 794 createSchemaGenerator().write(outputResolver, new ErrorListener() {
aoqi@0 795 public void error(SAXParseException exception) {
aoqi@0 796 e[0] = exception;
aoqi@0 797 }
aoqi@0 798
aoqi@0 799 public void fatalError(SAXParseException exception) {
aoqi@0 800 e[0] = exception;
aoqi@0 801 }
aoqi@0 802
aoqi@0 803 public void warning(SAXParseException exception) {
aoqi@0 804 w[0] = exception;
aoqi@0 805 }
aoqi@0 806
aoqi@0 807 public void info(SAXParseException exception) {}
aoqi@0 808 });
aoqi@0 809
aoqi@0 810 if (e[0]!=null) {
aoqi@0 811 IOException x = new IOException(Messages.FAILED_TO_GENERATE_SCHEMA.format());
aoqi@0 812 x.initCause(e[0]);
aoqi@0 813 throw x;
aoqi@0 814 }
aoqi@0 815 if (w[0]!=null) {
aoqi@0 816 IOException x = new IOException(Messages.ERROR_PROCESSING_SCHEMA.format());
aoqi@0 817 x.initCause(w[0]);
aoqi@0 818 throw x;
aoqi@0 819 }
aoqi@0 820 }
aoqi@0 821
aoqi@0 822 private XmlSchemaGenerator<Type,Class,Field,Method> createSchemaGenerator() {
aoqi@0 823 RuntimeTypeInfoSet tis;
aoqi@0 824 try {
aoqi@0 825 tis = getTypeInfoSet();
aoqi@0 826 } catch (IllegalAnnotationsException e) {
aoqi@0 827 // this shouldn't happen because we've already
aoqi@0 828 throw new AssertionError(e);
aoqi@0 829 }
aoqi@0 830
aoqi@0 831 XmlSchemaGenerator<Type,Class,Field,Method> xsdgen =
aoqi@0 832 new XmlSchemaGenerator<Type,Class,Field,Method>(tis.getNavigator(),tis);
aoqi@0 833
aoqi@0 834 // JAX-RPC uses Bridge objects that collide with
aoqi@0 835 // @XmlRootElement.
aoqi@0 836 // we will avoid collision here
aoqi@0 837 Set<QName> rootTagNames = new HashSet<QName>();
aoqi@0 838 for (RuntimeElementInfo ei : tis.getAllElements()) {
aoqi@0 839 rootTagNames.add(ei.getElementName());
aoqi@0 840 }
aoqi@0 841 for (RuntimeClassInfo ci : tis.beans().values()) {
aoqi@0 842 if(ci.isElement())
aoqi@0 843 rootTagNames.add(ci.asElement().getElementName());
aoqi@0 844 }
aoqi@0 845
aoqi@0 846 for (TypeReference tr : bridges.keySet()) {
aoqi@0 847 if(rootTagNames.contains(tr.tagName))
aoqi@0 848 continue;
aoqi@0 849
aoqi@0 850 if(tr.type==void.class || tr.type==Void.class) {
aoqi@0 851 xsdgen.add(tr.tagName,false,null);
aoqi@0 852 } else
aoqi@0 853 if(tr.type==CompositeStructure.class) {
aoqi@0 854 // this is a special class we introduced for JAX-WS that we *don't* want in the schema
aoqi@0 855 } else {
aoqi@0 856 NonElement<Type,Class> typeInfo = getXmlType(tis,tr);
aoqi@0 857 xsdgen.add(tr.tagName, !tis.getNavigator().isPrimitive(tr.type),typeInfo);
aoqi@0 858 }
aoqi@0 859 }
aoqi@0 860 return xsdgen;
aoqi@0 861 }
aoqi@0 862
aoqi@0 863 public QName getTypeName(TypeReference tr) {
aoqi@0 864 try {
aoqi@0 865 NonElement<Type,Class> xt = getXmlType(getTypeInfoSet(),tr);
aoqi@0 866 if(xt==null) throw new IllegalArgumentException();
aoqi@0 867 return xt.getTypeName();
aoqi@0 868 } catch (IllegalAnnotationsException e) {
aoqi@0 869 // impossible given that JAXBRIContext has been successfully built in the first place
aoqi@0 870 throw new AssertionError(e);
aoqi@0 871 }
aoqi@0 872 }
aoqi@0 873
aoqi@0 874 @Override
aoqi@0 875 public <T> Binder<T> createBinder(Class<T> domType) {
aoqi@0 876 if(domType==Node.class)
aoqi@0 877 return (Binder<T>)createBinder();
aoqi@0 878 else
aoqi@0 879 return super.createBinder(domType);
aoqi@0 880 }
aoqi@0 881
aoqi@0 882 @Override
aoqi@0 883 public Binder<Node> createBinder() {
aoqi@0 884 return new BinderImpl<Node>(this,new DOMScanner());
aoqi@0 885 }
aoqi@0 886
aoqi@0 887 public QName getElementName(Object o) throws JAXBException {
aoqi@0 888 JaxBeanInfo bi = getBeanInfo(o,true);
aoqi@0 889 if(!bi.isElement())
aoqi@0 890 return null;
aoqi@0 891 return new QName(bi.getElementNamespaceURI(o),bi.getElementLocalName(o));
aoqi@0 892 }
aoqi@0 893
aoqi@0 894 public QName getElementName(Class o) throws JAXBException {
aoqi@0 895 JaxBeanInfo bi = getBeanInfo(o,true);
aoqi@0 896 if(!bi.isElement())
aoqi@0 897 return null;
aoqi@0 898 return new QName(bi.getElementNamespaceURI(o),bi.getElementLocalName(o));
aoqi@0 899 }
aoqi@0 900
aoqi@0 901 public Bridge createBridge(TypeReference ref) {
aoqi@0 902 return bridges.get(ref);
aoqi@0 903 }
aoqi@0 904
aoqi@0 905 public @NotNull BridgeContext createBridgeContext() {
aoqi@0 906 return new BridgeContextImpl(this);
aoqi@0 907 }
aoqi@0 908
aoqi@0 909 public RawAccessor getElementPropertyAccessor(Class wrapperBean, String nsUri, String localName) throws JAXBException {
aoqi@0 910 JaxBeanInfo bi = getBeanInfo(wrapperBean,true);
aoqi@0 911 if(!(bi instanceof ClassBeanInfoImpl))
aoqi@0 912 throw new JAXBException(wrapperBean+" is not a bean");
aoqi@0 913
aoqi@0 914 for( ClassBeanInfoImpl cb = (ClassBeanInfoImpl) bi; cb!=null; cb=cb.superClazz) {
aoqi@0 915 for (Property p : cb.properties) {
aoqi@0 916 final Accessor acc = p.getElementPropertyAccessor(nsUri,localName);
aoqi@0 917 if(acc!=null)
aoqi@0 918 return new RawAccessor() {
aoqi@0 919 // Accessor.set/get are designed for unmarshaller/marshaller, and hence
aoqi@0 920 // they go through an adapter behind the scene.
aoqi@0 921 // this isn't desirable for JAX-WS, which essentially uses this method
aoqi@0 922 // just as a reflection library. So use the "unadapted" version to
aoqi@0 923 // achieve the desired semantics
aoqi@0 924 public Object get(Object bean) throws AccessorException {
aoqi@0 925 return acc.getUnadapted(bean);
aoqi@0 926 }
aoqi@0 927
aoqi@0 928 public void set(Object bean, Object value) throws AccessorException {
aoqi@0 929 acc.setUnadapted(bean,value);
aoqi@0 930 }
aoqi@0 931 };
aoqi@0 932 }
aoqi@0 933 }
aoqi@0 934 throw new JAXBException(new QName(nsUri,localName)+" is not a valid property on "+wrapperBean);
aoqi@0 935 }
aoqi@0 936
aoqi@0 937 public List<String> getKnownNamespaceURIs() {
aoqi@0 938 return Arrays.asList(nameList.namespaceURIs);
aoqi@0 939 }
aoqi@0 940
aoqi@0 941 public String getBuildId() {
aoqi@0 942 Package pkg = getClass().getPackage();
aoqi@0 943 if(pkg==null) return null;
aoqi@0 944 return pkg.getImplementationVersion();
aoqi@0 945 }
aoqi@0 946
aoqi@0 947 @Override
aoqi@0 948 public String toString() {
aoqi@0 949 StringBuilder buf = new StringBuilder(Which.which(getClass()) + " Build-Id: " + getBuildId());
aoqi@0 950 buf.append("\nClasses known to this context:\n");
aoqi@0 951
aoqi@0 952 Set<String> names = new TreeSet<String>(); // sort them so that it's easy to read
aoqi@0 953
aoqi@0 954 for (Class key : beanInfoMap.keySet())
aoqi@0 955 names.add(key.getName());
aoqi@0 956
aoqi@0 957 for(String name: names)
aoqi@0 958 buf.append(" ").append(name).append('\n');
aoqi@0 959
aoqi@0 960 return buf.toString();
aoqi@0 961 }
aoqi@0 962
aoqi@0 963 /**
aoqi@0 964 * Gets the value of the xmime:contentType attribute on the given object, or null
aoqi@0 965 * if for some reason it couldn't be found, including any error.
aoqi@0 966 */
aoqi@0 967 public String getXMIMEContentType( Object o ) {
aoqi@0 968 JaxBeanInfo bi = getBeanInfo(o);
aoqi@0 969 if(!(bi instanceof ClassBeanInfoImpl))
aoqi@0 970 return null;
aoqi@0 971
aoqi@0 972 ClassBeanInfoImpl cb = (ClassBeanInfoImpl) bi;
aoqi@0 973 for (Property p : cb.properties) {
aoqi@0 974 if (p instanceof AttributeProperty) {
aoqi@0 975 AttributeProperty ap = (AttributeProperty) p;
aoqi@0 976 if(ap.attName.equals(WellKnownNamespace.XML_MIME_URI,"contentType"))
aoqi@0 977 try {
aoqi@0 978 return (String)ap.xacc.print(o);
aoqi@0 979 } catch (AccessorException e) {
aoqi@0 980 return null;
aoqi@0 981 } catch (SAXException e) {
aoqi@0 982 return null;
aoqi@0 983 } catch (ClassCastException e) {
aoqi@0 984 return null;
aoqi@0 985 }
aoqi@0 986 }
aoqi@0 987 }
aoqi@0 988 return null;
aoqi@0 989 }
aoqi@0 990
aoqi@0 991 /**
aoqi@0 992 * Creates a {@link JAXBContextImpl} that includes the specified additional classes.
aoqi@0 993 */
aoqi@0 994 public JAXBContextImpl createAugmented(Class<?> clazz) throws JAXBException {
aoqi@0 995 Class[] newList = new Class[classes.length+1];
aoqi@0 996 System.arraycopy(classes,0,newList,0,classes.length);
aoqi@0 997 newList[classes.length] = clazz;
aoqi@0 998
aoqi@0 999 JAXBContextBuilder builder = new JAXBContextBuilder(this);
aoqi@0 1000 builder.setClasses(newList);
aoqi@0 1001 return builder.build();
aoqi@0 1002 }
aoqi@0 1003
aoqi@0 1004 private static final Comparator<QName> QNAME_COMPARATOR = new Comparator<QName>() {
aoqi@0 1005 public int compare(QName lhs, QName rhs) {
aoqi@0 1006 int r = lhs.getLocalPart().compareTo(rhs.getLocalPart());
aoqi@0 1007 if(r!=0) return r;
aoqi@0 1008
aoqi@0 1009 return lhs.getNamespaceURI().compareTo(rhs.getNamespaceURI());
aoqi@0 1010 }
aoqi@0 1011 };
aoqi@0 1012
aoqi@0 1013 public static class JAXBContextBuilder {
aoqi@0 1014
aoqi@0 1015 private boolean retainPropertyInfo = false;
aoqi@0 1016 private boolean supressAccessorWarnings = false;
aoqi@0 1017 private String defaultNsUri = "";
aoqi@0 1018 private @NotNull RuntimeAnnotationReader annotationReader = new RuntimeInlineAnnotationReader();
aoqi@0 1019 private @NotNull Map<Class,Class> subclassReplacements = Collections.emptyMap();
aoqi@0 1020 private boolean c14nSupport = false;
aoqi@0 1021 private Class[] classes;
aoqi@0 1022 private Collection<TypeReference> typeRefs;
aoqi@0 1023 private boolean xmlAccessorFactorySupport = false;
aoqi@0 1024 private boolean allNillable;
aoqi@0 1025 private boolean improvedXsiTypeHandling = true;
aoqi@0 1026 private boolean disableSecurityProcessing = true;
aoqi@0 1027
aoqi@0 1028 public JAXBContextBuilder() {};
aoqi@0 1029
aoqi@0 1030 public JAXBContextBuilder(JAXBContextImpl baseImpl) {
aoqi@0 1031 this.supressAccessorWarnings = baseImpl.supressAccessorWarnings;
aoqi@0 1032 this.retainPropertyInfo = baseImpl.retainPropertyInfo;
aoqi@0 1033 this.defaultNsUri = baseImpl.defaultNsUri;
aoqi@0 1034 this.annotationReader = baseImpl.annotationReader;
aoqi@0 1035 this.subclassReplacements = baseImpl.subclassReplacements;
aoqi@0 1036 this.c14nSupport = baseImpl.c14nSupport;
aoqi@0 1037 this.classes = baseImpl.classes;
aoqi@0 1038 this.typeRefs = baseImpl.bridges.keySet();
aoqi@0 1039 this.xmlAccessorFactorySupport = baseImpl.xmlAccessorFactorySupport;
aoqi@0 1040 this.allNillable = baseImpl.allNillable;
aoqi@0 1041 this.disableSecurityProcessing = baseImpl.disableSecurityProcessing;
aoqi@0 1042 }
aoqi@0 1043
aoqi@0 1044 public JAXBContextBuilder setRetainPropertyInfo(boolean val) {
aoqi@0 1045 this.retainPropertyInfo = val;
aoqi@0 1046 return this;
aoqi@0 1047 }
aoqi@0 1048
aoqi@0 1049 public JAXBContextBuilder setSupressAccessorWarnings(boolean val) {
aoqi@0 1050 this.supressAccessorWarnings = val;
aoqi@0 1051 return this;
aoqi@0 1052 }
aoqi@0 1053
aoqi@0 1054 public JAXBContextBuilder setC14NSupport(boolean val) {
aoqi@0 1055 this.c14nSupport = val;
aoqi@0 1056 return this;
aoqi@0 1057 }
aoqi@0 1058
aoqi@0 1059 public JAXBContextBuilder setXmlAccessorFactorySupport(boolean val) {
aoqi@0 1060 this.xmlAccessorFactorySupport = val;
aoqi@0 1061 return this;
aoqi@0 1062 }
aoqi@0 1063
aoqi@0 1064 public JAXBContextBuilder setDefaultNsUri(String val) {
aoqi@0 1065 this.defaultNsUri = val;
aoqi@0 1066 return this;
aoqi@0 1067 }
aoqi@0 1068
aoqi@0 1069 public JAXBContextBuilder setAllNillable(boolean val) {
aoqi@0 1070 this.allNillable = val;
aoqi@0 1071 return this;
aoqi@0 1072 }
aoqi@0 1073
aoqi@0 1074 public JAXBContextBuilder setClasses(Class[] val) {
aoqi@0 1075 this.classes = val;
aoqi@0 1076 return this;
aoqi@0 1077 }
aoqi@0 1078
aoqi@0 1079 public JAXBContextBuilder setAnnotationReader(RuntimeAnnotationReader val) {
aoqi@0 1080 this.annotationReader = val;
aoqi@0 1081 return this;
aoqi@0 1082 }
aoqi@0 1083
aoqi@0 1084 public JAXBContextBuilder setSubclassReplacements(Map<Class,Class> val) {
aoqi@0 1085 this.subclassReplacements = val;
aoqi@0 1086 return this;
aoqi@0 1087 }
aoqi@0 1088
aoqi@0 1089 public JAXBContextBuilder setTypeRefs(Collection<TypeReference> val) {
aoqi@0 1090 this.typeRefs = val;
aoqi@0 1091 return this;
aoqi@0 1092 }
aoqi@0 1093
aoqi@0 1094 public JAXBContextBuilder setImprovedXsiTypeHandling(boolean val) {
aoqi@0 1095 this.improvedXsiTypeHandling = val;
aoqi@0 1096 return this;
aoqi@0 1097 }
aoqi@0 1098
aoqi@0 1099 public JAXBContextBuilder setDisableSecurityProcessing(boolean val) {
aoqi@0 1100 this.disableSecurityProcessing = val;
aoqi@0 1101 return this;
aoqi@0 1102 }
aoqi@0 1103
aoqi@0 1104 public JAXBContextImpl build() throws JAXBException {
aoqi@0 1105
aoqi@0 1106 // fool-proof
aoqi@0 1107 if (this.defaultNsUri == null) {
aoqi@0 1108 this.defaultNsUri = "";
aoqi@0 1109 }
aoqi@0 1110
aoqi@0 1111 if (this.subclassReplacements == null) {
aoqi@0 1112 this.subclassReplacements = Collections.emptyMap();
aoqi@0 1113 }
aoqi@0 1114
aoqi@0 1115 if (this.annotationReader == null) {
aoqi@0 1116 this.annotationReader = new RuntimeInlineAnnotationReader();
aoqi@0 1117 }
aoqi@0 1118
aoqi@0 1119 if (this.typeRefs == null) {
aoqi@0 1120 this.typeRefs = Collections.<TypeReference>emptyList();
aoqi@0 1121 }
aoqi@0 1122
aoqi@0 1123 return new JAXBContextImpl(this);
aoqi@0 1124 }
aoqi@0 1125
aoqi@0 1126 }
aoqi@0 1127
aoqi@0 1128 }

mercurial