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

Tue, 06 Mar 2012 16:09:35 -0800

author
ohair
date
Tue, 06 Mar 2012 16:09:35 -0800
changeset 286
f50545b5e2f1
child 368
0989ad8c0860
permissions
-rw-r--r--

7150322: Stop using drop source bundles in jaxws
Reviewed-by: darcy, ohrstrom

     1 /*
     2  * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.xml.internal.bind.v2.runtime;
    28 import java.io.IOException;
    29 import java.lang.reflect.InvocationTargetException;
    30 import java.lang.reflect.Method;
    31 import java.lang.reflect.Modifier;
    32 import java.util.Collection;
    33 import java.util.Collections;
    34 import java.util.List;
    35 import java.util.Map;
    36 import java.util.logging.Level;
    37 import java.util.logging.Logger;
    39 import javax.xml.bind.ValidationEvent;
    40 import javax.xml.bind.annotation.XmlRootElement;
    41 import javax.xml.bind.helpers.ValidationEventImpl;
    42 import javax.xml.namespace.QName;
    43 import javax.xml.stream.XMLStreamException;
    45 import com.sun.istack.internal.FinalArrayList;
    46 import com.sun.xml.internal.bind.Util;
    47 import com.sun.xml.internal.bind.api.AccessorException;
    48 import com.sun.xml.internal.bind.v2.ClassFactory;
    49 import com.sun.xml.internal.bind.v2.WellKnownNamespace;
    50 import com.sun.xml.internal.bind.v2.model.core.ID;
    51 import com.sun.xml.internal.bind.v2.model.runtime.RuntimeClassInfo;
    52 import com.sun.xml.internal.bind.v2.model.runtime.RuntimePropertyInfo;
    53 import com.sun.xml.internal.bind.v2.runtime.property.AttributeProperty;
    54 import com.sun.xml.internal.bind.v2.runtime.property.Property;
    55 import com.sun.xml.internal.bind.v2.runtime.property.PropertyFactory;
    56 import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor;
    57 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
    58 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.StructureLoader;
    59 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext;
    60 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.XsiTypeLoader;
    62 import org.xml.sax.Locator;
    63 import org.xml.sax.SAXException;
    64 import org.xml.sax.helpers.LocatorImpl;
    66 /**
    67  * {@link JaxBeanInfo} implementation for j2s bean.
    68  *
    69  * @author Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
    70  */
    71 public final class ClassBeanInfoImpl<BeanT> extends JaxBeanInfo<BeanT> implements AttributeAccessor<BeanT> {
    73     /**
    74      * Properties of this bean class but not its ancestor classes.
    75      */
    76     public final Property<BeanT>[] properties;
    78     /**
    79      * Non-null if this bean has an ID property.
    80      */
    81     private Property<? super BeanT> idProperty;
    83     /**
    84      * Immutable configured loader for this class.
    85      *
    86      * <p>
    87      * Set from the link method, but considered final.
    88      */
    89     private Loader loader;
    90     private Loader loaderWithTypeSubst;
    92     /**
    93      * Set only until the link phase to avoid leaking memory.
    94      */
    95     private RuntimeClassInfo ci;
    97     private final Accessor<? super BeanT,Map<QName,String>> inheritedAttWildcard;
    98     private final Transducer<BeanT> xducer;
   100     /**
   101      * {@link ClassBeanInfoImpl} that represents the super class of {@link #jaxbType}.
   102      */
   103     public final ClassBeanInfoImpl<? super BeanT> superClazz;
   105     private final Accessor<? super BeanT,Locator> xmlLocatorField;
   107     private final Name tagName;
   109     private boolean retainPropertyInfo = false;
   111     /**
   112      * The {@link AttributeProperty}s for this type and all its ancestors.
   113      * If {@link JAXBContextImpl#c14nSupport} is true, this is sorted alphabetically.
   114      */
   115     private /*final*/ AttributeProperty<BeanT>[] attributeProperties;
   117     /**
   118      * {@link Property}s that need to receive {@link Property#serializeURIs(Object, XMLSerializer)} callback.
   119      */
   120     private /*final*/ Property<BeanT>[] uriProperties;
   122     private final Method factoryMethod;
   124     /*package*/ ClassBeanInfoImpl(JAXBContextImpl owner, RuntimeClassInfo ci) {
   125         super(owner,ci,ci.getClazz(),ci.getTypeName(),ci.isElement(),false,true);
   127         this.ci = ci;
   128         this.inheritedAttWildcard = ci.getAttributeWildcard();
   129         this.xducer = ci.getTransducer();
   130         this.factoryMethod = ci.getFactoryMethod();
   131         this.retainPropertyInfo = owner.retainPropertyInfo;
   133         // make the factory accessible
   134         if(factoryMethod!=null) {
   135             int classMod = factoryMethod.getDeclaringClass().getModifiers();
   137             if(!Modifier.isPublic(classMod) || !Modifier.isPublic(factoryMethod.getModifiers())) {
   138                 // attempt to make it work even if the constructor is not accessible
   139                 try {
   140                     factoryMethod.setAccessible(true);
   141                 } catch(SecurityException e) {
   142                     // but if we don't have a permission to do so, work gracefully.
   143                     logger.log(Level.FINE,"Unable to make the method of "+factoryMethod+" accessible",e);
   144                     throw e;
   145                 }
   146             }
   147         }
   150         if(ci.getBaseClass()==null)
   151             this.superClazz = null;
   152         else
   153             this.superClazz = owner.getOrCreate(ci.getBaseClass());
   155         if(superClazz!=null && superClazz.xmlLocatorField!=null)
   156             xmlLocatorField = superClazz.xmlLocatorField;
   157         else
   158             xmlLocatorField = ci.getLocatorField();
   160         // create property objects
   161         Collection<? extends RuntimePropertyInfo> ps = ci.getProperties();
   162         this.properties = new Property[ps.size()];
   163         int idx=0;
   164         boolean elementOnly = true;
   165         for( RuntimePropertyInfo info : ps ) {
   166             Property p = PropertyFactory.create(owner,info);
   167             if(info.id()==ID.ID)
   168                 idProperty = p;
   169             properties[idx++] = p;
   170             elementOnly &= info.elementOnlyContent();
   171             checkOverrideProperties(p);
   172         }
   173         // super class' idProperty might not be computed at this point,
   174         // so check that later
   176         hasElementOnlyContentModel( elementOnly );
   177         // again update this value later when we know that of the super class
   179         if(ci.isElement())
   180             tagName = owner.nameBuilder.createElementName(ci.getElementName());
   181         else
   182             tagName = null;
   184         setLifecycleFlags();
   185     }
   187     private void checkOverrideProperties(Property p) {
   188         ClassBeanInfoImpl bi = this;
   189         while ((bi = bi.superClazz) != null) {
   190             Property[] props = bi.properties;
   191             if (props == null) break;
   192             for (Property superProperty : props) {
   193                 if (superProperty == null) break;
   194                 String spName = superProperty.getFieldName();
   195                 if ((spName != null) && (spName.equals(p.getFieldName()))) {
   196                     superProperty.setHiddenByOverride(true);
   197                 }
   198             }
   199         }
   200     }
   202     @Override
   203     protected void link(JAXBContextImpl grammar) {
   204         if(uriProperties!=null)
   205             return; // avoid linking twice
   207         super.link(grammar);
   209         if(superClazz!=null)
   210             superClazz.link(grammar);
   212         getLoader(grammar,true);    // make sure to build the loader if we haven't done so.
   214         // propagate values from super class
   215         if(superClazz!=null) {
   216             if(idProperty==null)
   217                 idProperty = superClazz.idProperty;
   219             if(!superClazz.hasElementOnlyContentModel())
   220                 hasElementOnlyContentModel(false);
   221         }
   223         // create a list of attribute/URI handlers
   224         List<AttributeProperty> attProps = new FinalArrayList<AttributeProperty>();
   225         List<Property> uriProps = new FinalArrayList<Property>();
   226         for (ClassBeanInfoImpl bi = this; bi != null; bi = bi.superClazz) {
   227             for (int i = 0; i < bi.properties.length; i++) {
   228                 Property p = bi.properties[i];
   229                 if(p instanceof AttributeProperty)
   230                     attProps.add((AttributeProperty) p);
   231                 if(p.hasSerializeURIAction())
   232                     uriProps.add(p);
   233             }
   234         }
   235         if(grammar.c14nSupport)
   236             Collections.sort(attProps);
   238         if(attProps.isEmpty())
   239             attributeProperties = EMPTY_PROPERTIES;
   240         else
   241             attributeProperties = attProps.toArray(new AttributeProperty[attProps.size()]);
   243         if(uriProps.isEmpty())
   244             uriProperties = EMPTY_PROPERTIES;
   245         else
   246             uriProperties = uriProps.toArray(new Property[uriProps.size()]);
   247     }
   249     @Override
   250     public void wrapUp() {
   251         for (Property p : properties)
   252             p.wrapUp();
   253         ci = null;
   254         super.wrapUp();
   255     }
   257     public String getElementNamespaceURI(BeanT bean) {
   258         return tagName.nsUri;
   259     }
   261     public String getElementLocalName(BeanT bean) {
   262         return tagName.localName;
   263     }
   265     public BeanT createInstance(UnmarshallingContext context) throws IllegalAccessException, InvocationTargetException, InstantiationException, SAXException {
   267         BeanT bean = null;
   268         if (factoryMethod == null){
   269            bean = ClassFactory.create0(jaxbType);
   270         }else {
   271             Object o = ClassFactory.create(factoryMethod);
   272             if( jaxbType.isInstance(o) ){
   273                 bean = (BeanT)o;
   274             } else {
   275                 throw new InstantiationException("The factory method didn't return a correct object");
   276             }
   277         }
   279         if(xmlLocatorField!=null)
   280             // need to copy because Locator is mutable
   281             try {
   282                 xmlLocatorField.set(bean,new LocatorImpl(context.getLocator()));
   283             } catch (AccessorException e) {
   284                 context.handleError(e);
   285             }
   286         return bean;
   287     }
   289     public boolean reset(BeanT bean, UnmarshallingContext context) throws SAXException {
   290         try {
   291             if(superClazz!=null)
   292                 superClazz.reset(bean,context);
   293             for( Property<BeanT> p : properties )
   294                 p.reset(bean);
   295             return true;
   296         } catch (AccessorException e) {
   297             context.handleError(e);
   298             return false;
   299         }
   300     }
   302     public String getId(BeanT bean, XMLSerializer target) throws SAXException {
   303         if(idProperty!=null) {
   304             try {
   305                 return idProperty.getIdValue(bean);
   306             } catch (AccessorException e) {
   307                 target.reportError(null,e);
   308             }
   309         }
   310         return null;
   311     }
   313     public void serializeRoot(BeanT bean, XMLSerializer target) throws SAXException, IOException, XMLStreamException {
   314         if(tagName==null) {
   315             Class beanClass = bean.getClass();
   316             String message;
   317             if (beanClass.isAnnotationPresent(XmlRootElement.class)) {
   318                 message = Messages.UNABLE_TO_MARSHAL_UNBOUND_CLASS.format(beanClass.getName());
   319             } else {
   320                 message = Messages.UNABLE_TO_MARSHAL_NON_ELEMENT.format(beanClass.getName());
   321             }
   322             target.reportError(new ValidationEventImpl(ValidationEvent.ERROR,message,null, null));
   323         } else {
   324             target.startElement(tagName,bean);
   325             target.childAsSoleContent(bean,null);
   326             target.endElement();
   327             if (retainPropertyInfo) {
   328                 target.currentProperty.remove();
   329             }
   330         }
   331     }
   333     public void serializeBody(BeanT bean, XMLSerializer target) throws SAXException, IOException, XMLStreamException {
   334         if (superClazz != null) {
   335             superClazz.serializeBody(bean, target);
   336         }
   337         try {
   338             for (Property<BeanT> p : properties) {
   339                 if (retainPropertyInfo) {
   340                     target.currentProperty.set(p);
   341                 }
   342                 if (!(p.isHiddenByOverride() && !bean.getClass().equals(jaxbType))) {
   343                     p.serializeBody(bean, target, null);
   344                 }
   345             }
   346         } catch (AccessorException e) {
   347             target.reportError(null, e);
   348         }
   349     }
   351     public void serializeAttributes(BeanT bean, XMLSerializer target) throws SAXException, IOException, XMLStreamException {
   352         for( AttributeProperty<BeanT> p : attributeProperties )
   353             try {
   354                 if (retainPropertyInfo) {
   355                 final Property parentProperty = target.getCurrentProperty();
   356                 target.currentProperty.set(p);
   357                 p.serializeAttributes(bean,target);
   358                 target.currentProperty.set(parentProperty);
   359                 } else {
   360                     p.serializeAttributes(bean,target);
   361                 }
   362                 if (p.attName.equals(WellKnownNamespace.XML_SCHEMA_INSTANCE, "nil")) {
   363                     isNilIncluded = true;
   364                 }
   365             } catch (AccessorException e) {
   366                 target.reportError(null,e);
   367             }
   369         try {
   370             if(inheritedAttWildcard!=null) {
   371                 Map<QName,String> map = inheritedAttWildcard.get(bean);
   372                 target.attWildcardAsAttributes(map,null);
   373             }
   374         } catch (AccessorException e) {
   375             target.reportError(null,e);
   376         }
   377     }
   379     public void serializeURIs(BeanT bean, XMLSerializer target) throws SAXException {
   380         try {
   381             if (retainPropertyInfo) {
   382             final Property parentProperty = target.getCurrentProperty();
   383             for( Property<BeanT> p : uriProperties ) {
   384                 target.currentProperty.set(p);
   385                 p.serializeURIs(bean,target);
   386             }
   387             target.currentProperty.set(parentProperty);
   388             } else {
   389                 for( Property<BeanT> p : uriProperties ) {
   390                     p.serializeURIs(bean,target);
   391                 }
   392             }
   393             if(inheritedAttWildcard!=null) {
   394                 Map<QName,String> map = inheritedAttWildcard.get(bean);
   395                 target.attWildcardAsURIs(map,null);
   396             }
   397         } catch (AccessorException e) {
   398             target.reportError(null,e);
   399         }
   400     }
   402     public Loader getLoader(JAXBContextImpl context, boolean typeSubstitutionCapable) {
   403         if(loader==null) {
   404             // these variables have to be set before they are initialized,
   405             // because the initialization may build other loaders and they may refer to this.
   406             StructureLoader sl = new StructureLoader(this);
   407             loader = sl;
   408             if(ci.hasSubClasses())
   409                 loaderWithTypeSubst = new XsiTypeLoader(this);
   410             else
   411                 // optimization. we know there can be no @xsi:type
   412                 loaderWithTypeSubst = loader;
   415             sl.init(context,this,ci.getAttributeWildcard());
   416         }
   417         if(typeSubstitutionCapable)
   418             return loaderWithTypeSubst;
   419         else
   420             return loader;
   421     }
   423     public Transducer<BeanT> getTransducer() {
   424         return xducer;
   425     }
   427     private static final AttributeProperty[] EMPTY_PROPERTIES = new AttributeProperty[0];
   429     private static final Logger logger = Util.getClassLogger();
   431 }

mercurial