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

Fri, 14 Feb 2014 10:53:55 +0100

author
mkos
date
Fri, 14 Feb 2014 10:53:55 +0100
changeset 514
29a761eaff0d
parent 450
b0c2840e2513
child 515
6cd506508147
permissions
-rw-r--r--

8025030: Enhance stream handling
Summary: Avoiding caching data initialized via TCCL in static context; fix also reviewed by Iaroslav Savytskyi, Alexander Fomin
Reviewed-by: ahgross, mgrebac, skoivu

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

mercurial