--- old/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/reflect/Lister.java 2018-01-30 20:34:14.000000000 -0500 +++ /dev/null 2018-01-30 20:34:14.000000000 -0500 @@ -1,494 +0,0 @@ -/* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code 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. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.xml.internal.bind.v2.runtime.reflect; - -import java.lang.ref.WeakReference; -import java.lang.reflect.Array; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.WeakHashMap; -import java.util.LinkedList; -import java.util.HashSet; -import java.util.TreeSet; -import java.util.Stack; -import java.util.concurrent.Callable; - -import javax.xml.bind.JAXBException; - -import com.sun.istack.internal.SAXException2; -import com.sun.xml.internal.bind.api.AccessorException; -import com.sun.xml.internal.bind.v2.ClassFactory; -import com.sun.xml.internal.bind.v2.TODO; -import com.sun.xml.internal.bind.v2.model.core.Adapter; -import com.sun.xml.internal.bind.v2.model.core.ID; -import com.sun.xml.internal.bind.v2.runtime.XMLSerializer; -import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Patcher; -import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext; -import com.sun.xml.internal.bind.v2.runtime.unmarshaller.LocatorEx; - -import org.xml.sax.SAXException; - -/** - * Used to list individual values of a multi-value property, and - * to pack individual values into a multi-value property. - * - * @author Kohsuke Kawaguchi (kk@kohsuke.org) - */ -public abstract class Lister { - - protected Lister() {} - - /** - * Iterates values of a multi-value property. - * - * @param context - * This parameter is used to support ID/IDREF handling. - */ - public abstract ListIterator iterator(PropT multiValueProp, XMLSerializer context); - - /** - * Setting values to a multi-value property starts by creating - * a transient object called "pack" from the current field. - */ - public abstract PackT startPacking(BeanT bean, Accessor acc) throws AccessorException; - - /** - * Once the {@link #startPacking} is called, you can - * add values to the pack by using this method. - */ - public abstract void addToPack( PackT pack, ItemT newValue ) throws AccessorException; - - /** - * Finally, call this method to - * wraps up the {@code pack}. This method may update the field of - * the given bean. - */ - public abstract void endPacking( PackT pack, BeanT bean, Accessor acc ) throws AccessorException; - - /** - * Clears the values of the property. - */ - public abstract void reset(BeanT o,Accessor acc) throws AccessorException; - - - /** - * Gets a reference to the appropriate {@link Lister} object - * if the field is a multi-value field. Otherwise null. - * - * @param fieldType - * the type of the field that stores the collection - * @param idness - * ID-ness of the property. - * @param adapter - * adapter to be used for individual items. can be null. - */ - public static - Lister create(Type fieldType,ID idness, Adapter adapter) { - - Class rawType = (Class) Utils.REFLECTION_NAVIGATOR.erasure(fieldType); - Class itemType; - - Lister l; - if( rawType.isArray() ) { - itemType = rawType.getComponentType(); - l = getArrayLister(itemType); - } else - if( Collection.class.isAssignableFrom(rawType) ) { - Type bt = Utils.REFLECTION_NAVIGATOR.getBaseClass(fieldType,Collection.class); - if(bt instanceof ParameterizedType) - itemType = (Class) Utils.REFLECTION_NAVIGATOR.erasure(((ParameterizedType)bt).getActualTypeArguments()[0]); - else - itemType = Object.class; - l = new CollectionLister(getImplClass(rawType)); - } else - return null; - - if(idness==ID.IDREF) - l = new IDREFS(l,itemType); - - if(adapter!=null) - l = new AdaptedLister(l,adapter.adapterType); - - return l; - } - - private static Class getImplClass(Class fieldType) { - return ClassFactory.inferImplClass(fieldType,COLLECTION_IMPL_CLASSES); - } - - /** - * Cache instances of {@link ArrayLister}s. - */ - private static final Map> arrayListerCache = - Collections.synchronizedMap(new WeakHashMap>()); - - /** - * Creates a lister for array type. - */ - private static Lister getArrayLister( Class componentType ) { - Lister l=null; - if(componentType.isPrimitive()) - l = primitiveArrayListers.get(componentType); - else { - WeakReference wr = arrayListerCache.get(componentType); - if(wr!=null) - l = wr.get(); - if(l==null) { - l = new ArrayLister(componentType); - arrayListerCache.put(componentType,new WeakReference(l)); - } - } - assert l!=null; - return l; - } - - /** - * {@link Lister} for an array. - * - *

- * Array packing is slower, but we expect this to be used less frequently than - * the {@link CollectionLister}. - */ - private static final class ArrayLister extends Lister> { - - private final Class itemType; - - public ArrayLister(Class itemType) { - this.itemType = itemType; - } - - public ListIterator iterator(final ItemT[] objects, XMLSerializer context) { - return new ListIterator() { - int idx=0; - public boolean hasNext() { - return idx acc) { - return new Pack(itemType); - } - - public void addToPack(Pack objects, ItemT o) { - objects.add(o); - } - - public void endPacking( Pack pack, BeanT bean, Accessor acc ) throws AccessorException { - acc.set(bean,pack.build()); - } - - public void reset(BeanT o,Accessor acc) throws AccessorException { - acc.set(o,(ItemT[])Array.newInstance(itemType,0)); - } - - } - - public static final class Pack extends ArrayList { - private final Class itemType; - - public Pack(Class itemType) { - this.itemType = itemType; - } - - public ItemT[] build() { - return super.toArray( (ItemT[])Array.newInstance(itemType,size()) ); - } - } - - /** - * Listers for the primitive type arrays, keyed by their primitive Class object. - */ - /*package*/ static final Map primitiveArrayListers = new HashMap(); - - static { - // register primitive array listers - PrimitiveArrayListerBoolean.register(); - PrimitiveArrayListerByte.register(); - PrimitiveArrayListerCharacter.register(); - PrimitiveArrayListerDouble.register(); - PrimitiveArrayListerFloat.register(); - PrimitiveArrayListerInteger.register(); - PrimitiveArrayListerLong.register(); - PrimitiveArrayListerShort.register(); - } - - /** - * {@link Lister} for a collection - */ - public static final class CollectionLister extends Lister { - - /** - * Sometimes we need to create a new instance of a collection. - * This is such an implementation class. - */ - private final Class implClass; - - public CollectionLister(Class implClass) { - this.implClass = implClass; - } - - public ListIterator iterator(T collection, XMLSerializer context) { - final Iterator itr = collection.iterator(); - return new ListIterator() { - public boolean hasNext() { - return itr.hasNext(); - } - public Object next() { - return itr.next(); - } - }; - } - - public T startPacking(BeanT bean, Accessor acc) throws AccessorException { - T collection = acc.get(bean); - if(collection==null) { - collection = ClassFactory.create(implClass); - if(!acc.isAdapted()) - acc.set(bean,collection); - } - collection.clear(); - return collection; - } - - public void addToPack(T collection, Object o) { - collection.add(o); - } - - public void endPacking( T collection, BeanT bean, Accessor acc ) throws AccessorException { - // this needs to be done in the endPacking, because - // sometimes the accessor uses an adapter, and the adapter needs to see - // the whole thing. - - // but always doing so causes a problem when this collection property - // is getter-only - - // invoke set when possible (see Issue 488) - try { - if (acc.isAdapted()) { - acc.set(bean,collection); - } - } catch (AccessorException ae) { - if(acc.isAdapted()) throw ae; - } - } - - public void reset(BeanT bean, Accessor acc) throws AccessorException { - T collection = acc.get(bean); - if(collection == null) { - return; - } - collection.clear(); - } - } - - /** - * {@link Lister} for IDREFS. - */ - private static final class IDREFS extends Lister.Pack> { - private final Lister core; - /** - * Expected type to which IDREF resolves to. - */ - private final Class itemType; - - public IDREFS(Lister core, Class itemType) { - this.core = core; - this.itemType = itemType; - } - - public ListIterator iterator(PropT prop, XMLSerializer context) { - final ListIterator i = core.iterator(prop,context); - - return new IDREFSIterator(i, context); - } - - public Pack startPacking(BeanT bean, Accessor acc) { - return new Pack(bean,acc); - } - - public void addToPack(Pack pack, String item) { - pack.add(item); - } - - public void endPacking(Pack pack, BeanT bean, Accessor acc) { - } - - public void reset(BeanT bean, Accessor acc) throws AccessorException { - core.reset(bean,acc); - } - - /** - * PackT for this lister. - */ - private class Pack implements Patcher { - private final BeanT bean; - private final List idrefs = new ArrayList(); - private final UnmarshallingContext context; - private final Accessor acc; - private final LocatorEx location; - - public Pack(BeanT bean, Accessor acc) { - this.bean = bean; - this.acc = acc; - this.context = UnmarshallingContext.getInstance(); - this.location = new LocatorEx.Snapshot(context.getLocator()); - context.addPatcher(this); - } - - public void add(String item) { - idrefs.add(item); - } - - /** - * Resolves IDREFS and fill in the actual array. - */ - public void run() throws SAXException { - try { - Object pack = core.startPacking(bean,acc); - - for( String id : idrefs ) { - Callable callable = context.getObjectFromId(id,itemType); - Object t; - - try { - t = (callable!=null) ? callable.call() : null; - } catch (SAXException e) { - throw e; - } catch (Exception e) { - throw new SAXException2(e); - } - - if(t==null) { - context.errorUnresolvedIDREF(bean,id,location); - } else { - TODO.prototype(); // TODO: check if the type of t is proper. - core.addToPack(pack,t); - } - } - - core.endPacking(pack,bean,acc); - } catch (AccessorException e) { - context.handleError(e); - } - } - } - } - - /** - * {@link Iterator} for IDREFS lister. - * - *

- * Only in ArrayElementProperty we need to get the actual - * referenced object. This is a kind of ugly way to make that work. - */ - public static final class IDREFSIterator implements ListIterator { - private final ListIterator i; - private final XMLSerializer context; - private Object last; - - private IDREFSIterator(ListIterator i, XMLSerializer context) { - this.i = i; - this.context = context; - } - - public boolean hasNext() { - return i.hasNext(); - } - - /** - * Returns the last referenced object (not just its ID) - */ - public Object last() { - return last; - } - - public String next() throws SAXException, JAXBException { - last = i.next(); - String id = context.grammar.getBeanInfo(last,true).getId(last,context); - if(id==null) { - context.errorMissingId(last); - } - return id; - } - } - - /** - * Gets the special {@link Lister} used to recover from an error. - */ - @SuppressWarnings("unchecked") - public static Lister getErrorInstance() { - return ERROR; - } - - public static final Lister ERROR = new Lister() { - public ListIterator iterator(Object o, XMLSerializer context) { - return EMPTY_ITERATOR; - } - - public Object startPacking(Object o, Accessor accessor) { - return null; - } - - public void addToPack(Object o, Object o1) { - } - - public void endPacking(Object o, Object o1, Accessor accessor) { - } - - public void reset(Object o, Accessor accessor) { - } - }; - - private static final ListIterator EMPTY_ITERATOR = new ListIterator() { - public boolean hasNext() { - return false; - } - - public Object next() { - throw new IllegalStateException(); - } - }; - - private static final Class[] COLLECTION_IMPL_CLASSES = new Class[] { - ArrayList.class, - LinkedList.class, - HashSet.class, - TreeSet.class, - Stack.class - }; -}