src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/RuntimeClassInfoImpl.java

Thu, 12 Oct 2017 19:44:07 +0800

author
aoqi
date
Thu, 12 Oct 2017 19:44:07 +0800
changeset 760
e530533619ec
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 1997, 2010, 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.model.impl;
aoqi@0 27
aoqi@0 28 import java.io.IOException;
aoqi@0 29 import java.lang.annotation.Annotation;
aoqi@0 30 import java.lang.reflect.Field;
aoqi@0 31 import java.lang.reflect.Method;
aoqi@0 32 import java.lang.reflect.Modifier;
aoqi@0 33 import java.lang.reflect.Type;
aoqi@0 34 import java.util.List;
aoqi@0 35 import java.util.Map;
aoqi@0 36
aoqi@0 37 import javax.xml.bind.JAXBException;
aoqi@0 38 import javax.xml.namespace.QName;
aoqi@0 39 import javax.xml.stream.XMLStreamException;
aoqi@0 40
aoqi@0 41 import com.sun.istack.internal.NotNull;
aoqi@0 42 import com.sun.xml.internal.bind.AccessorFactory;
aoqi@0 43 import com.sun.xml.internal.bind.AccessorFactoryImpl;
aoqi@0 44 import com.sun.xml.internal.bind.InternalAccessorFactory;
aoqi@0 45 import com.sun.xml.internal.bind.XmlAccessorFactory;
aoqi@0 46 import com.sun.xml.internal.bind.annotation.XmlLocation;
aoqi@0 47 import com.sun.xml.internal.bind.api.AccessorException;
aoqi@0 48 import com.sun.xml.internal.bind.v2.ClassFactory;
aoqi@0 49 import com.sun.xml.internal.bind.v2.model.annotation.Locatable;
aoqi@0 50 import com.sun.xml.internal.bind.v2.model.core.PropertyKind;
aoqi@0 51 import com.sun.xml.internal.bind.v2.model.runtime.RuntimeClassInfo;
aoqi@0 52 import com.sun.xml.internal.bind.v2.model.runtime.RuntimeElement;
aoqi@0 53 import com.sun.xml.internal.bind.v2.model.runtime.RuntimePropertyInfo;
aoqi@0 54 import com.sun.xml.internal.bind.v2.model.runtime.RuntimeValuePropertyInfo;
aoqi@0 55 import com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationException;
aoqi@0 56 import com.sun.xml.internal.bind.v2.runtime.Location;
aoqi@0 57 import com.sun.xml.internal.bind.v2.runtime.Name;
aoqi@0 58 import com.sun.xml.internal.bind.v2.runtime.Transducer;
aoqi@0 59 import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
aoqi@0 60 import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
aoqi@0 61 import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor;
aoqi@0 62 import com.sun.xml.internal.bind.v2.runtime.reflect.TransducedAccessor;
aoqi@0 63 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext;
aoqi@0 64
aoqi@0 65 import org.xml.sax.Locator;
aoqi@0 66 import org.xml.sax.SAXException;
aoqi@0 67
aoqi@0 68 /**
aoqi@0 69 * @author Kohsuke Kawaguchi (kk@kohsuke.org)
aoqi@0 70 */
aoqi@0 71 class RuntimeClassInfoImpl extends ClassInfoImpl<Type,Class,Field,Method>
aoqi@0 72 implements RuntimeClassInfo, RuntimeElement {
aoqi@0 73
aoqi@0 74 /**
aoqi@0 75 * If this class has a property annotated with {@link XmlLocation},
aoqi@0 76 * this field will get the accessor for it.
aoqi@0 77 *
aoqi@0 78 * TODO: support method based XmlLocation
aoqi@0 79 */
aoqi@0 80 private Accessor<?,Locator> xmlLocationAccessor;
aoqi@0 81
aoqi@0 82 private AccessorFactory accessorFactory;
aoqi@0 83
aoqi@0 84 private boolean supressAccessorWarnings = false;
aoqi@0 85
aoqi@0 86 public RuntimeClassInfoImpl(RuntimeModelBuilder modelBuilder, Locatable upstream, Class clazz) {
aoqi@0 87 super(modelBuilder, upstream, clazz);
aoqi@0 88 accessorFactory = createAccessorFactory(clazz);
aoqi@0 89 }
aoqi@0 90
aoqi@0 91 protected AccessorFactory createAccessorFactory(Class clazz) {
aoqi@0 92 XmlAccessorFactory factoryAnn;
aoqi@0 93 AccessorFactory accFactory = null;
aoqi@0 94
aoqi@0 95 // user providing class to be used.
aoqi@0 96 JAXBContextImpl context = ((RuntimeModelBuilder) builder).context;
aoqi@0 97 if (context!=null) {
aoqi@0 98 this.supressAccessorWarnings = context.supressAccessorWarnings;
aoqi@0 99 if (context.xmlAccessorFactorySupport) {
aoqi@0 100 factoryAnn = findXmlAccessorFactoryAnnotation(clazz);
aoqi@0 101 if (factoryAnn != null) {
aoqi@0 102 try {
aoqi@0 103 accFactory = factoryAnn.value().newInstance();
aoqi@0 104 } catch (InstantiationException e) {
aoqi@0 105 builder.reportError(new IllegalAnnotationException(
aoqi@0 106 Messages.ACCESSORFACTORY_INSTANTIATION_EXCEPTION.format(
aoqi@0 107 factoryAnn.getClass().getName(), nav().getClassName(clazz)), this));
aoqi@0 108 } catch (IllegalAccessException e) {
aoqi@0 109 builder.reportError(new IllegalAnnotationException(
aoqi@0 110 Messages.ACCESSORFACTORY_ACCESS_EXCEPTION.format(
aoqi@0 111 factoryAnn.getClass().getName(), nav().getClassName(clazz)),this));
aoqi@0 112 }
aoqi@0 113 }
aoqi@0 114 }
aoqi@0 115 }
aoqi@0 116
aoqi@0 117
aoqi@0 118 // Fall back to local AccessorFactory when no
aoqi@0 119 // user not providing one or as error recovery.
aoqi@0 120 if (accFactory == null){
aoqi@0 121 accFactory = AccessorFactoryImpl.getInstance();
aoqi@0 122 }
aoqi@0 123 return accFactory;
aoqi@0 124 }
aoqi@0 125
aoqi@0 126 protected XmlAccessorFactory findXmlAccessorFactoryAnnotation(Class clazz) {
aoqi@0 127 XmlAccessorFactory factoryAnn = reader().getClassAnnotation(XmlAccessorFactory.class,clazz,this);
aoqi@0 128 if (factoryAnn == null) {
aoqi@0 129 factoryAnn = reader().getPackageAnnotation(XmlAccessorFactory.class,clazz,this);
aoqi@0 130 }
aoqi@0 131 return factoryAnn;
aoqi@0 132 }
aoqi@0 133
aoqi@0 134
aoqi@0 135 public Method getFactoryMethod(){
aoqi@0 136 return super.getFactoryMethod();
aoqi@0 137 }
aoqi@0 138
aoqi@0 139 public final RuntimeClassInfoImpl getBaseClass() {
aoqi@0 140 return (RuntimeClassInfoImpl)super.getBaseClass();
aoqi@0 141 }
aoqi@0 142
aoqi@0 143 @Override
aoqi@0 144 protected ReferencePropertyInfoImpl createReferenceProperty(PropertySeed<Type,Class,Field,Method> seed) {
aoqi@0 145 return new RuntimeReferencePropertyInfoImpl(this,seed);
aoqi@0 146 }
aoqi@0 147
aoqi@0 148 @Override
aoqi@0 149 protected AttributePropertyInfoImpl createAttributeProperty(PropertySeed<Type,Class,Field,Method> seed) {
aoqi@0 150 return new RuntimeAttributePropertyInfoImpl(this,seed);
aoqi@0 151 }
aoqi@0 152
aoqi@0 153 @Override
aoqi@0 154 protected ValuePropertyInfoImpl createValueProperty(PropertySeed<Type,Class,Field,Method> seed) {
aoqi@0 155 return new RuntimeValuePropertyInfoImpl(this,seed);
aoqi@0 156 }
aoqi@0 157
aoqi@0 158 @Override
aoqi@0 159 protected ElementPropertyInfoImpl createElementProperty(PropertySeed<Type,Class,Field,Method> seed) {
aoqi@0 160 return new RuntimeElementPropertyInfoImpl(this,seed);
aoqi@0 161 }
aoqi@0 162
aoqi@0 163 @Override
aoqi@0 164 protected MapPropertyInfoImpl createMapProperty(PropertySeed<Type,Class,Field,Method> seed) {
aoqi@0 165 return new RuntimeMapPropertyInfoImpl(this,seed);
aoqi@0 166 }
aoqi@0 167
aoqi@0 168
aoqi@0 169 @Override
aoqi@0 170 public List<? extends RuntimePropertyInfo> getProperties() {
aoqi@0 171 return (List<? extends RuntimePropertyInfo>)super.getProperties();
aoqi@0 172 }
aoqi@0 173
aoqi@0 174 @Override
aoqi@0 175 public RuntimePropertyInfo getProperty(String name) {
aoqi@0 176 return (RuntimePropertyInfo)super.getProperty(name);
aoqi@0 177 }
aoqi@0 178
aoqi@0 179
aoqi@0 180 public void link() {
aoqi@0 181 getTransducer(); // populate the transducer
aoqi@0 182 super.link();
aoqi@0 183 }
aoqi@0 184
aoqi@0 185 private Accessor<?,Map<QName,String>> attributeWildcardAccessor;
aoqi@0 186
aoqi@0 187 public <B> Accessor<B,Map<QName,String>> getAttributeWildcard() {
aoqi@0 188 for( RuntimeClassInfoImpl c=this; c!=null; c=c.getBaseClass() ) {
aoqi@0 189 if(c.attributeWildcard!=null) {
aoqi@0 190 if(c.attributeWildcardAccessor==null)
aoqi@0 191 c.attributeWildcardAccessor = c.createAttributeWildcardAccessor();
aoqi@0 192 return (Accessor<B,Map<QName,String>>)c.attributeWildcardAccessor;
aoqi@0 193 }
aoqi@0 194 }
aoqi@0 195 return null;
aoqi@0 196 }
aoqi@0 197
aoqi@0 198 private boolean computedTransducer = false;
aoqi@0 199 private Transducer xducer = null;
aoqi@0 200
aoqi@0 201 public Transducer getTransducer() {
aoqi@0 202 if(!computedTransducer) {
aoqi@0 203 computedTransducer = true;
aoqi@0 204 xducer = calcTransducer();
aoqi@0 205 }
aoqi@0 206 return xducer;
aoqi@0 207 }
aoqi@0 208
aoqi@0 209 /**
aoqi@0 210 * Creates a transducer if this class is bound to a text in XML.
aoqi@0 211 */
aoqi@0 212 private Transducer calcTransducer() {
aoqi@0 213 RuntimeValuePropertyInfo valuep=null;
aoqi@0 214 if(hasAttributeWildcard())
aoqi@0 215 return null; // has attribute wildcard. Can't be handled as a leaf
aoqi@0 216 for (RuntimeClassInfoImpl ci = this; ci != null; ci = ci.getBaseClass()) {
aoqi@0 217 for( RuntimePropertyInfo pi : ci.getProperties() )
aoqi@0 218 if(pi.kind()==PropertyKind.VALUE) {
aoqi@0 219 valuep = (RuntimeValuePropertyInfo)pi;
aoqi@0 220 } else {
aoqi@0 221 // this bean has something other than a value
aoqi@0 222 return null;
aoqi@0 223 }
aoqi@0 224 }
aoqi@0 225 if(valuep==null)
aoqi@0 226 return null;
aoqi@0 227 if( !valuep.getTarget().isSimpleType() )
aoqi@0 228 return null; // if there's an error, recover from it by returning null.
aoqi@0 229
aoqi@0 230 return new TransducerImpl(getClazz(),TransducedAccessor.get(
aoqi@0 231 ((RuntimeModelBuilder)builder).context,valuep));
aoqi@0 232 }
aoqi@0 233
aoqi@0 234 /**
aoqi@0 235 * Creates
aoqi@0 236 */
aoqi@0 237 private Accessor<?,Map<QName,String>> createAttributeWildcardAccessor() {
aoqi@0 238 assert attributeWildcard!=null;
aoqi@0 239 return ((RuntimePropertySeed)attributeWildcard).getAccessor();
aoqi@0 240 }
aoqi@0 241
aoqi@0 242 @Override
aoqi@0 243 protected RuntimePropertySeed createFieldSeed(Field field) {
aoqi@0 244 final boolean readOnly = Modifier.isStatic(field.getModifiers());
aoqi@0 245 Accessor acc;
aoqi@0 246 try {
aoqi@0 247 if (supressAccessorWarnings) {
aoqi@0 248 acc = ((InternalAccessorFactory)accessorFactory).createFieldAccessor(clazz, field, readOnly, supressAccessorWarnings);
aoqi@0 249 } else {
aoqi@0 250 acc = accessorFactory.createFieldAccessor(clazz, field, readOnly);
aoqi@0 251 }
aoqi@0 252 } catch(JAXBException e) {
aoqi@0 253 builder.reportError(new IllegalAnnotationException(
aoqi@0 254 Messages.CUSTOM_ACCESSORFACTORY_FIELD_ERROR.format(
aoqi@0 255 nav().getClassName(clazz), e.toString()), this ));
aoqi@0 256 acc = Accessor.getErrorInstance(); // error recovery
aoqi@0 257 }
aoqi@0 258 return new RuntimePropertySeed(super.createFieldSeed(field), acc );
aoqi@0 259 }
aoqi@0 260
aoqi@0 261 @Override
aoqi@0 262 public RuntimePropertySeed createAccessorSeed(Method getter, Method setter) {
aoqi@0 263 Accessor acc;
aoqi@0 264 try {
aoqi@0 265 acc = accessorFactory.createPropertyAccessor(clazz, getter, setter);
aoqi@0 266 } catch(JAXBException e) {
aoqi@0 267 builder.reportError(new IllegalAnnotationException(
aoqi@0 268 Messages.CUSTOM_ACCESSORFACTORY_PROPERTY_ERROR.format(
aoqi@0 269 nav().getClassName(clazz), e.toString()), this ));
aoqi@0 270 acc = Accessor.getErrorInstance(); // error recovery
aoqi@0 271 }
aoqi@0 272 return new RuntimePropertySeed( super.createAccessorSeed(getter,setter),
aoqi@0 273 acc );
aoqi@0 274 }
aoqi@0 275
aoqi@0 276 @Override
aoqi@0 277 protected void checkFieldXmlLocation(Field f) {
aoqi@0 278 if(reader().hasFieldAnnotation(XmlLocation.class,f))
aoqi@0 279 // TODO: check for XmlLocation signature
aoqi@0 280 // TODO: check a collision with the super class
aoqi@0 281 xmlLocationAccessor = new Accessor.FieldReflection<Object,Locator>(f);
aoqi@0 282 }
aoqi@0 283
aoqi@0 284 public Accessor<?,Locator> getLocatorField() {
aoqi@0 285 return xmlLocationAccessor;
aoqi@0 286 }
aoqi@0 287
aoqi@0 288 static final class RuntimePropertySeed implements PropertySeed<Type,Class,Field,Method> {
aoqi@0 289 /**
aoqi@0 290 * @see #getAccessor()
aoqi@0 291 */
aoqi@0 292 private final Accessor acc;
aoqi@0 293
aoqi@0 294 private final PropertySeed<Type,Class,Field,Method> core;
aoqi@0 295
aoqi@0 296 public RuntimePropertySeed(PropertySeed<Type,Class,Field,Method> core, Accessor acc) {
aoqi@0 297 this.core = core;
aoqi@0 298 this.acc = acc;
aoqi@0 299 }
aoqi@0 300
aoqi@0 301 public String getName() {
aoqi@0 302 return core.getName();
aoqi@0 303 }
aoqi@0 304
aoqi@0 305 public <A extends Annotation> A readAnnotation(Class<A> annotationType) {
aoqi@0 306 return core.readAnnotation(annotationType);
aoqi@0 307 }
aoqi@0 308
aoqi@0 309 public boolean hasAnnotation(Class<? extends Annotation> annotationType) {
aoqi@0 310 return core.hasAnnotation(annotationType);
aoqi@0 311 }
aoqi@0 312
aoqi@0 313 public Type getRawType() {
aoqi@0 314 return core.getRawType();
aoqi@0 315 }
aoqi@0 316
aoqi@0 317 public Location getLocation() {
aoqi@0 318 return core.getLocation();
aoqi@0 319 }
aoqi@0 320
aoqi@0 321 public Locatable getUpstream() {
aoqi@0 322 return core.getUpstream();
aoqi@0 323 }
aoqi@0 324
aoqi@0 325 public Accessor getAccessor() {
aoqi@0 326 return acc;
aoqi@0 327 }
aoqi@0 328 }
aoqi@0 329
aoqi@0 330
aoqi@0 331
aoqi@0 332 /**
aoqi@0 333 * {@link Transducer} implementation used when this class maps to PCDATA in XML.
aoqi@0 334 *
aoqi@0 335 * TODO: revisit the exception handling
aoqi@0 336 */
aoqi@0 337 private static final class TransducerImpl<BeanT> implements Transducer<BeanT> {
aoqi@0 338 private final TransducedAccessor<BeanT> xacc;
aoqi@0 339 private final Class<BeanT> ownerClass;
aoqi@0 340
aoqi@0 341 public TransducerImpl(Class<BeanT> ownerClass,TransducedAccessor<BeanT> xacc) {
aoqi@0 342 this.xacc = xacc;
aoqi@0 343 this.ownerClass = ownerClass;
aoqi@0 344 }
aoqi@0 345
aoqi@0 346 public boolean useNamespace() {
aoqi@0 347 return xacc.useNamespace();
aoqi@0 348 }
aoqi@0 349
aoqi@0 350 public boolean isDefault() {
aoqi@0 351 return false;
aoqi@0 352 }
aoqi@0 353
aoqi@0 354 public void declareNamespace(BeanT bean, XMLSerializer w) throws AccessorException {
aoqi@0 355 try {
aoqi@0 356 xacc.declareNamespace(bean,w);
aoqi@0 357 } catch (SAXException e) {
aoqi@0 358 throw new AccessorException(e);
aoqi@0 359 }
aoqi@0 360 }
aoqi@0 361
aoqi@0 362 public @NotNull CharSequence print(BeanT o) throws AccessorException {
aoqi@0 363 try {
aoqi@0 364 CharSequence value = xacc.print(o);
aoqi@0 365 if(value==null)
aoqi@0 366 throw new AccessorException(Messages.THERE_MUST_BE_VALUE_IN_XMLVALUE.format(o));
aoqi@0 367 return value;
aoqi@0 368 } catch (SAXException e) {
aoqi@0 369 throw new AccessorException(e);
aoqi@0 370 }
aoqi@0 371 }
aoqi@0 372
aoqi@0 373 public BeanT parse(CharSequence lexical) throws AccessorException, SAXException {
aoqi@0 374 UnmarshallingContext ctxt = UnmarshallingContext.getInstance();
aoqi@0 375 BeanT inst;
aoqi@0 376 if(ctxt!=null)
aoqi@0 377 inst = (BeanT)ctxt.createInstance(ownerClass);
aoqi@0 378 else
aoqi@0 379 // when this runs for parsing enum constants,
aoqi@0 380 // there's no UnmarshallingContext.
aoqi@0 381 inst = ClassFactory.create(ownerClass);
aoqi@0 382
aoqi@0 383 xacc.parse(inst,lexical);
aoqi@0 384 return inst;
aoqi@0 385 }
aoqi@0 386
aoqi@0 387 public void writeText(XMLSerializer w, BeanT o, String fieldName) throws IOException, SAXException, XMLStreamException, AccessorException {
aoqi@0 388 if(!xacc.hasValue(o))
aoqi@0 389 throw new AccessorException(Messages.THERE_MUST_BE_VALUE_IN_XMLVALUE.format(o));
aoqi@0 390 xacc.writeText(w,o,fieldName);
aoqi@0 391 }
aoqi@0 392
aoqi@0 393 public void writeLeafElement(XMLSerializer w, Name tagName, BeanT o, String fieldName) throws IOException, SAXException, XMLStreamException, AccessorException {
aoqi@0 394 if(!xacc.hasValue(o))
aoqi@0 395 throw new AccessorException(Messages.THERE_MUST_BE_VALUE_IN_XMLVALUE.format(o));
aoqi@0 396 xacc.writeLeafElement(w,tagName,o,fieldName);
aoqi@0 397 }
aoqi@0 398
aoqi@0 399 public QName getTypeName(BeanT instance) {
aoqi@0 400 return null;
aoqi@0 401 }
aoqi@0 402 }
aoqi@0 403 }

mercurial