classskeleton.java

来自「RESIN 3.2 最新源码」· Java 代码 · 共 1,047 行 · 第 1/2 页

JAVA
1,047
字号
/* * Copyright (c) 1998-2007 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT.  See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * *   Free Software Foundation, Inc. *   59 Temple Place, Suite 330 *   Boston, MA 02111-1307  USA * * @author Emil Ong, Adam Megacz */package com.caucho.jaxb.skeleton;import org.w3c.dom.Node;import static javax.xml.XMLConstants.*;import javax.xml.bind.JAXBException;import javax.xml.bind.Marshaller;import javax.xml.bind.Unmarshaller;import javax.xml.bind.UnmarshalException;import javax.xml.bind.annotation.*;import javax.xml.namespace.QName;import javax.xml.stream.Location;import javax.xml.stream.XMLStreamException;import javax.xml.stream.XMLStreamReader;import javax.xml.stream.XMLStreamWriter;import java.io.IOException;import java.lang.reflect.AccessibleObject;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.lang.reflect.Modifier;import java.util.ArrayList;import java.util.Collection;import java.util.Collections;import java.util.Comparator;import java.util.HashMap;import java.util.HashSet;import java.util.Set;import java.util.TreeSet;import java.util.logging.Level;import java.util.logging.Logger;import com.caucho.jaxb.BinderImpl;import com.caucho.jaxb.JAXBContextImpl;import com.caucho.jaxb.JAXBUtil;import com.caucho.jaxb.NodeIterator;import com.caucho.jaxb.annotation.XmlLocation;import com.caucho.jaxb.accessor.Accessor;import com.caucho.jaxb.accessor.FieldAccessor;import com.caucho.jaxb.accessor.GetterSetterAccessor;import com.caucho.jaxb.mapping.AnyAttributeMapping;import com.caucho.jaxb.mapping.AttributeMapping;import com.caucho.jaxb.mapping.AnyElementMapping;import com.caucho.jaxb.mapping.ElementMapping;import com.caucho.jaxb.mapping.ElementRefMapping;import com.caucho.jaxb.mapping.ElementsMapping;import com.caucho.jaxb.mapping.Namer;import com.caucho.jaxb.mapping.XmlMapping;import com.caucho.jaxb.mapping.XmlValueMapping;import com.caucho.util.L10N;import com.caucho.xml.stream.StaxUtil;public class ClassSkeleton<C> {  public static final String XML_SCHEMA_NS = "http://www.w3.org/2001/XMLSchema";  public static final String XML_SCHEMA_PREFIX = "xsd";  private static final L10N L = new L10N(ClassSkeleton.class);  private static final Logger log =     Logger.getLogger(ClassSkeleton.class.getName());  private static final Class[] NO_PARAMS = new Class[0];  private static final Object[] NO_ARGS = new Object[0];  protected JAXBContextImpl _context;  protected QName _elementName;  private Class<C> _class;  private ClassSkeleton _parent;  private Package _package;  private Method _createMethod;  private Object _factory;  private QName _typeName;  private HashMap<QName,XmlMapping> _attributeQNameToMappingMap    = new HashMap<QName,XmlMapping>();  private HashMap<QName,XmlMapping> _elementQNameToMappingMap    = new HashMap<QName,XmlMapping>();  private ArrayList<XmlMapping> _attributeMappings    = new ArrayList<XmlMapping>();  private ArrayList<XmlMapping> _elementMappings    = new ArrayList<XmlMapping>();  private AnyElementMapping _anyElementMapping;  private AnyAttributeMapping _anyAttributeMapping;  private Method _beforeUnmarshal;  private Method _afterUnmarshal;  private Method _beforeMarshal;  private Method _afterMarshal;  private Constructor _constructor;  /** Special hook to allow injecting the location where an instance was      unmarshalled from. */  private Accessor _locationAccessor;  /**   * The value @XmlValue.   *    **/  protected XmlValueMapping _value;  public Class<C> getType()  {    return _class;  }  public String toString()  {    return "ClassSkeleton[" + _class + "]";  }  protected ClassSkeleton(JAXBContextImpl context)  {    _context = context;  }  public ClassSkeleton(JAXBContextImpl context, Class<C> c)  {    this(context);    _class = c;  }  public void init()     throws JAXBException  {    try {      _package = _class.getPackage();      // check for special before and after methods      try {        _beforeUnmarshal =          _class.getMethod("beforeUnmarshal", Unmarshaller.class, Object.class);      } catch (NoSuchMethodException _) {        // deliberate      }      try {        _afterUnmarshal =          _class.getMethod("afterUnmarshal", Unmarshaller.class, Object.class);      } catch (NoSuchMethodException _) {        // deliberate      }      try {        _beforeMarshal = _class.getMethod("beforeMarshal", Marshaller.class);      } catch (NoSuchMethodException _) {        // deliberate      }      try {        _afterMarshal = _class.getMethod("afterMarshal", Marshaller.class);      } catch (NoSuchMethodException _) {        // deliberate      }      if (Set.class.isAssignableFrom(_class)) {        // XXX:      }            // XXX: @XmlJavaTypeAdapter            // Find the zero-parameter constructor      try {        _constructor = _class.getConstructor(NO_PARAMS);        _constructor.setAccessible(true);      }      catch (Exception e1) {        try {          _constructor = _class.getDeclaredConstructor(NO_PARAMS);          _constructor.setAccessible(true);        }        catch (Exception e2) {          throw new JAXBException(L.l("{0}: Zero-arg constructor not found",                                       _class.getName()), e2);        }      }      _typeName = JAXBUtil.getXmlSchemaDatatype(_class, _context);      // Special case: when name="", this is an "anonymous" type, bound      // exclusively to a particular element name      if (! "".equals(_typeName.getLocalPart()))        _context.addXmlType(_typeName, this);      // Check for the complete name of the element...      String namespace = _context.getTargetNamespace();      // look at package defaults first...      XmlSchema schema = (XmlSchema) _package.getAnnotation(XmlSchema.class);      if (schema != null && ! "".equals(schema.namespace()))        namespace = schema.namespace();            // then look at class specific overrides.      XmlRootElement xre = _class.getAnnotation(XmlRootElement.class);      if (xre != null) {         String localName = null;                if ("##default".equals(xre.name()))          localName = JAXBUtil.identifierToXmlName(_class);        else          localName = xre.name();        if (! "##default".equals(xre.namespace()))          namespace = xre.namespace();        if (namespace == null)          _elementName = new QName(localName);        else          _elementName = new QName(namespace, localName);        _context.addRootElement(this);      }      // order the elements, if specified            XmlAccessOrder accessOrder = XmlAccessOrder.UNDEFINED;      XmlAccessorOrder packageOrder =         _package.getAnnotation(XmlAccessorOrder.class);      XmlAccessorOrder classOrder =         _class.getAnnotation(XmlAccessorOrder.class);      if (packageOrder != null)        accessOrder = packageOrder.value();      if (classOrder != null)        accessOrder = classOrder.value();      // try property orders too           XmlType xmlType = (XmlType) _class.getAnnotation(XmlType.class);      HashMap<String,Integer> orderMap = null;      if (xmlType != null &&          (xmlType.propOrder().length != 1 ||           ! "".equals(xmlType.propOrder()[0]))) {        // non-default propOrder        orderMap = new HashMap<String,Integer>();        for (int i = 0; i < xmlType.propOrder().length; i++)          orderMap.put(xmlType.propOrder()[i], i);      }      // Collect the fields/properties of the class      if (orderMap != null) {        for (int i = 0; i < orderMap.size(); i++)          _elementMappings.add(null);      }      XmlAccessorType accessorType =         _class.getAnnotation(XmlAccessorType.class);      XmlAccessType accessType = (accessorType == null ?                                   XmlAccessType.PUBLIC_MEMBER :                                  accessorType.value());      if (accessType != XmlAccessType.FIELD) {        // getter/setter        TreeSet<Method> methodSet = new TreeSet<Method>(methodComparator);        Method[] declared = _class.getDeclaredMethods();        for (Method m : declared)          methodSet.add(m);        Method[] methods = new Method[methodSet.size()];        methodSet.toArray(methods);        AccessibleObject.setAccessible(methods, true);        while (methodSet.size() > 0) {          Method m = methodSet.first();          methodSet.remove(m);          String name = null;          Method get = null;          Method set = null;          if (m.getName().startsWith("get")) {            get = m;            if (Void.TYPE.equals(get.getReturnType()))              continue;            name = get.getName().substring(3); // 3 == "get".length());            Class cl = get.getDeclaringClass();            try {              set = cl.getDeclaredMethod("set" + name, get.getReturnType());            }            catch (NoSuchMethodException e) {              continue;            }            if (! methodSet.remove(set))              continue;          }           else if (m.getName().startsWith("set")) {            set = m;            Class[] parameterTypes = set.getParameterTypes();            if (parameterTypes.length != 1)              continue;            name = set.getName().substring(3); // 3 == "set".length());            Class cl = set.getDeclaringClass();            try {              get = cl.getDeclaredMethod("get" + name);            }            catch (NoSuchMethodException e) {              continue;            }            if (! parameterTypes[0].equals(get.getReturnType()))              continue;            if (! methodSet.remove(get))              continue;          }          else            continue;          name = Character.toLowerCase(name.charAt(0)) + name.substring(1);          // JAXB specifies that a "class" property must be specified as "clazz"          // because of Object.getClass()          if ("class".equals(name))            continue;          // XXX special cases for Throwable specified in JAX-WS          // Should it be in the general JAXB?          if (Throwable.class.isAssignableFrom(_class) &&               ("stackTrace".equals(name) ||               "cause".equals(name) ||               "localizedMessage".equals(name)))            continue;          // XXX PUBLIC_MEMBER          if (accessType == XmlAccessType.NONE &&              ! JAXBUtil.isJAXBAnnotated(get) &&              ! JAXBUtil.isJAXBAnnotated(set))            continue;          // jaxb/0456          if (Modifier.isStatic(get.getModifiers()) &&              JAXBUtil.isJAXBAnnotated(get))            throw new JAXBException(L.l("JAXB annotations cannot be applied to static methods: {0}", get));          // jaxb/0457          if (Modifier.isStatic(set.getModifiers()) &&              JAXBUtil.isJAXBAnnotated(set))            throw new JAXBException(L.l("JAXB annotations cannot be applied to static methods: {0}", set));          // jaxb/0374          if (Modifier.isStatic(set.getModifiers()) ||              Modifier.isStatic(get.getModifiers()))            continue;          if (get != null && get.isAnnotationPresent(XmlTransient.class))            continue;          if (set != null && set.isAnnotationPresent(XmlTransient.class))            continue;          get.setAccessible(true);          set.setAccessible(true);          Accessor a = new GetterSetterAccessor(name, get, set);           if (orderMap != null) {            Integer i = orderMap.remove(name);            if (i != null)              a.setOrder(i.intValue());            // XXX else throw something?          }          processAccessor(a);        }      }      if (accessType != XmlAccessType.PROPERTY) {        // XXX Don't overwrite property accessors        HashSet<Field> fieldSet = new HashSet<Field>();        Field[] declared = _class.getDeclaredFields();        for (Field f : declared)          fieldSet.add(f);        Field[] fields = new Field[fieldSet.size()];        fieldSet.toArray(fields);        AccessibleObject.setAccessible(fields, true);        for (Field f : fields) {          if (f.isAnnotationPresent(XmlLocation.class))           {            if (! f.getType().equals(Location.class))              throw new JAXBException(L.l("Fields annotated by @Location must have type javax.xml.stream.Location"));            _locationAccessor = new FieldAccessor(f);          }          // special case: jaxb/0250          // fields which are static are skipped _unless_ they are also          // both final and attributes          if (Modifier.isStatic(f.getModifiers()) &&              ! (Modifier.isFinal(f.getModifiers()) &&                 f.isAnnotationPresent(XmlAttribute.class)))            continue;          if (f.isAnnotationPresent(XmlTransient.class))            continue;          // jaxb/0176: transient modifier ignored          if (accessType == XmlAccessType.PUBLIC_MEMBER &&               ! Modifier.isPublic(f.getModifiers()) &&              ! JAXBUtil.isJAXBAnnotated(f))            continue;          if (accessType == XmlAccessType.NONE && ! JAXBUtil.isJAXBAnnotated(f))            continue;          Accessor a = new FieldAccessor(f);          if (orderMap != null) {            Integer i = orderMap.remove(f.getName());            if (i != null)              a.setOrder(i.intValue());            // XXX else throw something?          }          processAccessor(a);        }      }      // do ordering if necessary      if (orderMap == null && accessOrder == XmlAccessOrder.ALPHABETICAL)        Collections.sort(_elementMappings, XmlMapping.nameComparator);    }    catch (JAXBException e) {      throw e;    }    catch (Exception e) {      throw new JAXBException(L.l("{0}: Initialization error",                                   _class.getName()), e);    }    if (! Object.class.equals(_class.getSuperclass()))      _parent = _context.getSkeleton(_class.getSuperclass());  }  /**   * Handles any processing that needs to happen after all ClassSkeletons   * have been created and all classes have been discovered.   **/  public void postProcess()    throws JAXBException  {    if (log.isLoggable(Level.FINEST))      log.finest("JAXB: " + _class.getName() + " has children: ");    for (int i = 0; i < _elementMappings.size(); i++)      _elementMappings.get(i).putQNames(_elementQNameToMappingMap);  }  /**   * Create an XmlMapping for this accessor and insert it in the correct   * mapping or field.   **/  private void processAccessor(Accessor accessor)    throws JAXBException

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?