Merging in new classes emul
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 28 Jan 2013 18:14:14 +0100
branchemul
changeset 6033d10a6d55653
parent 602 e74abd436d60
parent 601 5198affdb915
child 604 3fcc279c921b
Merging in new classes
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/emul/compact/src/main/java/java/beans/ChangeListenerMap.java	Mon Jan 28 18:14:14 2013 +0100
     1.3 @@ -0,0 +1,247 @@
     1.4 +/*
     1.5 + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.  Oracle designates this
    1.11 + * particular file as subject to the "Classpath" exception as provided
    1.12 + * by Oracle in the LICENSE file that accompanied this code.
    1.13 + *
    1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 + * version 2 for more details (a copy is included in the LICENSE file that
    1.18 + * accompanied this code).
    1.19 + *
    1.20 + * You should have received a copy of the GNU General Public License version
    1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 + *
    1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.25 + * or visit www.oracle.com if you need additional information or have any
    1.26 + * questions.
    1.27 + */
    1.28 +package java.beans;
    1.29 +
    1.30 +import java.util.ArrayList;
    1.31 +import java.util.Collections;
    1.32 +import java.util.EventListener;
    1.33 +import java.util.EventListenerProxy;
    1.34 +import java.util.HashMap;
    1.35 +import java.util.List;
    1.36 +import java.util.Map;
    1.37 +import java.util.Map.Entry;
    1.38 +import java.util.Set;
    1.39 +
    1.40 +/**
    1.41 + * This is an abstract class that provides base functionality
    1.42 + * for the {@link PropertyChangeSupport PropertyChangeSupport} class
    1.43 + * and the {@link VetoableChangeSupport VetoableChangeSupport} class.
    1.44 + *
    1.45 + * @see PropertyChangeListenerMap
    1.46 + * @see VetoableChangeListenerMap
    1.47 + *
    1.48 + * @author Sergey A. Malenkov
    1.49 + */
    1.50 +abstract class ChangeListenerMap<L extends EventListener> {
    1.51 +    private Map<String, L[]> map;
    1.52 +
    1.53 +    /**
    1.54 +     * Creates an array of listeners.
    1.55 +     * This method can be optimized by using
    1.56 +     * the same instance of the empty array
    1.57 +     * when {@code length} is equal to {@code 0}.
    1.58 +     *
    1.59 +     * @param length  the array length
    1.60 +     * @return        an array with specified length
    1.61 +     */
    1.62 +    protected abstract L[] newArray(int length);
    1.63 +
    1.64 +    /**
    1.65 +     * Creates a proxy listener for the specified property.
    1.66 +     *
    1.67 +     * @param name      the name of the property to listen on
    1.68 +     * @param listener  the listener to process events
    1.69 +     * @return          a proxy listener
    1.70 +     */
    1.71 +    protected abstract L newProxy(String name, L listener);
    1.72 +
    1.73 +    /**
    1.74 +     * Adds a listener to the list of listeners for the specified property.
    1.75 +     * This listener is called as many times as it was added.
    1.76 +     *
    1.77 +     * @param name      the name of the property to listen on
    1.78 +     * @param listener  the listener to process events
    1.79 +     */
    1.80 +    public final synchronized void add(String name, L listener) {
    1.81 +        if (this.map == null) {
    1.82 +            this.map = new HashMap<String, L[]>();
    1.83 +        }
    1.84 +        L[] array = this.map.get(name);
    1.85 +        int size = (array != null)
    1.86 +                ? array.length
    1.87 +                : 0;
    1.88 +
    1.89 +        L[] clone = newArray(size + 1);
    1.90 +        clone[size] = listener;
    1.91 +        if (array != null) {
    1.92 +            System.arraycopy(array, 0, clone, 0, size);
    1.93 +        }
    1.94 +        this.map.put(name, clone);
    1.95 +    }
    1.96 +
    1.97 +    /**
    1.98 +     * Removes a listener from the list of listeners for the specified property.
    1.99 +     * If the listener was added more than once to the same event source,
   1.100 +     * this listener will be notified one less time after being removed.
   1.101 +     *
   1.102 +     * @param name      the name of the property to listen on
   1.103 +     * @param listener  the listener to process events
   1.104 +     */
   1.105 +    public final synchronized void remove(String name, L listener) {
   1.106 +        if (this.map != null) {
   1.107 +            L[] array = this.map.get(name);
   1.108 +            if (array != null) {
   1.109 +                for (int i = 0; i < array.length; i++) {
   1.110 +                    if (listener.equals(array[i])) {
   1.111 +                        int size = array.length - 1;
   1.112 +                        if (size > 0) {
   1.113 +                            L[] clone = newArray(size);
   1.114 +                            System.arraycopy(array, 0, clone, 0, i);
   1.115 +                            System.arraycopy(array, i + 1, clone, i, size - i);
   1.116 +                            this.map.put(name, clone);
   1.117 +                        }
   1.118 +                        else {
   1.119 +                            this.map.remove(name);
   1.120 +                            if (this.map.isEmpty()) {
   1.121 +                                this.map = null;
   1.122 +                            }
   1.123 +                        }
   1.124 +                        break;
   1.125 +                    }
   1.126 +                }
   1.127 +            }
   1.128 +        }
   1.129 +    }
   1.130 +
   1.131 +    /**
   1.132 +     * Returns the list of listeners for the specified property.
   1.133 +     *
   1.134 +     * @param name  the name of the property
   1.135 +     * @return      the corresponding list of listeners
   1.136 +     */
   1.137 +    public final synchronized L[] get(String name) {
   1.138 +        return (this.map != null)
   1.139 +                ? this.map.get(name)
   1.140 +                : null;
   1.141 +    }
   1.142 +
   1.143 +    /**
   1.144 +     * Sets new list of listeners for the specified property.
   1.145 +     *
   1.146 +     * @param name       the name of the property
   1.147 +     * @param listeners  new list of listeners
   1.148 +     */
   1.149 +    public final void set(String name, L[] listeners) {
   1.150 +        if (listeners != null) {
   1.151 +            if (this.map == null) {
   1.152 +                this.map = new HashMap<String, L[]>();
   1.153 +            }
   1.154 +            this.map.put(name, listeners);
   1.155 +        }
   1.156 +        else if (this.map != null) {
   1.157 +            this.map.remove(name);
   1.158 +            if (this.map.isEmpty()) {
   1.159 +                this.map = null;
   1.160 +            }
   1.161 +        }
   1.162 +    }
   1.163 +
   1.164 +    /**
   1.165 +     * Returns all listeners in the map.
   1.166 +     *
   1.167 +     * @return an array of all listeners
   1.168 +     */
   1.169 +    public final synchronized L[] getListeners() {
   1.170 +        if (this.map == null) {
   1.171 +            return newArray(0);
   1.172 +        }
   1.173 +        List<L> list = new ArrayList<L>();
   1.174 +
   1.175 +        L[] listeners = this.map.get(null);
   1.176 +        if (listeners != null) {
   1.177 +            for (L listener : listeners) {
   1.178 +                list.add(listener);
   1.179 +            }
   1.180 +        }
   1.181 +        for (Entry<String, L[]> entry : this.map.entrySet()) {
   1.182 +            String name = entry.getKey();
   1.183 +            if (name != null) {
   1.184 +                for (L listener : entry.getValue()) {
   1.185 +                    list.add(newProxy(name, listener));
   1.186 +                }
   1.187 +            }
   1.188 +        }
   1.189 +        return list.toArray(newArray(list.size()));
   1.190 +    }
   1.191 +
   1.192 +    /**
   1.193 +     * Returns listeners that have been associated with the named property.
   1.194 +     *
   1.195 +     * @param name  the name of the property
   1.196 +     * @return an array of listeners for the named property
   1.197 +     */
   1.198 +    public final L[] getListeners(String name) {
   1.199 +        if (name != null) {
   1.200 +            L[] listeners = get(name);
   1.201 +            if (listeners != null) {
   1.202 +                return listeners.clone();
   1.203 +            }
   1.204 +        }
   1.205 +        return newArray(0);
   1.206 +    }
   1.207 +
   1.208 +    /**
   1.209 +     * Indicates whether the map contains
   1.210 +     * at least one listener to be notified.
   1.211 +     *
   1.212 +     * @param name  the name of the property
   1.213 +     * @return      {@code true} if at least one listener exists or
   1.214 +     *              {@code false} otherwise
   1.215 +     */
   1.216 +    public final synchronized boolean hasListeners(String name) {
   1.217 +        if (this.map == null) {
   1.218 +            return false;
   1.219 +        }
   1.220 +        L[] array = this.map.get(null);
   1.221 +        return (array != null) || ((name != null) && (null != this.map.get(name)));
   1.222 +    }
   1.223 +
   1.224 +    /**
   1.225 +     * Returns a set of entries from the map.
   1.226 +     * Each entry is a pair consisted of the property name
   1.227 +     * and the corresponding list of listeners.
   1.228 +     *
   1.229 +     * @return a set of entries from the map
   1.230 +     */
   1.231 +    public final Set<Entry<String, L[]>> getEntries() {
   1.232 +        return (this.map != null)
   1.233 +                ? this.map.entrySet()
   1.234 +                : Collections.<Entry<String, L[]>>emptySet();
   1.235 +    }
   1.236 +
   1.237 +    /**
   1.238 +     * Extracts a real listener from the proxy listener.
   1.239 +     * It is necessary because default proxy class is not serializable.
   1.240 +     *
   1.241 +     * @return a real listener
   1.242 +     */
   1.243 +    public final L extract(L listener) {
   1.244 +        while (listener instanceof EventListenerProxy) {
   1.245 +            EventListenerProxy<L> proxy = (EventListenerProxy<L>) listener;
   1.246 +            listener = proxy.getListener();
   1.247 +        }
   1.248 +        return listener;
   1.249 +    }
   1.250 +}
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/emul/compact/src/main/java/java/beans/IndexedPropertyChangeEvent.java	Mon Jan 28 18:14:14 2013 +0100
     2.3 @@ -0,0 +1,78 @@
     2.4 +/*
     2.5 + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
     2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.7 + *
     2.8 + * This code is free software; you can redistribute it and/or modify it
     2.9 + * under the terms of the GNU General Public License version 2 only, as
    2.10 + * published by the Free Software Foundation.  Oracle designates this
    2.11 + * particular file as subject to the "Classpath" exception as provided
    2.12 + * by Oracle in the LICENSE file that accompanied this code.
    2.13 + *
    2.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    2.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    2.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    2.17 + * version 2 for more details (a copy is included in the LICENSE file that
    2.18 + * accompanied this code).
    2.19 + *
    2.20 + * You should have received a copy of the GNU General Public License version
    2.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    2.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    2.23 + *
    2.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    2.25 + * or visit www.oracle.com if you need additional information or have any
    2.26 + * questions.
    2.27 + */
    2.28 +package java.beans;
    2.29 +
    2.30 +/**
    2.31 + * An "IndexedPropertyChange" event gets delivered whenever a component that
    2.32 + * conforms to the JavaBeans&trade; specification (a "bean") changes a bound
    2.33 + * indexed property. This class is an extension of <code>PropertyChangeEvent</code>
    2.34 + * but contains the index of the property that has changed.
    2.35 + * <P>
    2.36 + * Null values may be provided for the old and the new values if their
    2.37 + * true values are not known.
    2.38 + * <P>
    2.39 + * An event source may send a null object as the name to indicate that an
    2.40 + * arbitrary set of if its properties have changed.  In this case the
    2.41 + * old and new values should also be null.
    2.42 + *
    2.43 + * @since 1.5
    2.44 + * @author Mark Davidson
    2.45 + */
    2.46 +public class IndexedPropertyChangeEvent extends PropertyChangeEvent {
    2.47 +    private static final long serialVersionUID = -320227448495806870L;
    2.48 +
    2.49 +    private int index;
    2.50 +
    2.51 +    /**
    2.52 +     * Constructs a new <code>IndexedPropertyChangeEvent</code> object.
    2.53 +     *
    2.54 +     * @param source  The bean that fired the event.
    2.55 +     * @param propertyName  The programmatic name of the property that
    2.56 +     *             was changed.
    2.57 +     * @param oldValue      The old value of the property.
    2.58 +     * @param newValue      The new value of the property.
    2.59 +     * @param index index of the property element that was changed.
    2.60 +     */
    2.61 +    public IndexedPropertyChangeEvent(Object source, String propertyName,
    2.62 +                                      Object oldValue, Object newValue,
    2.63 +                                      int index) {
    2.64 +        super (source, propertyName, oldValue, newValue);
    2.65 +        this.index = index;
    2.66 +    }
    2.67 +
    2.68 +    /**
    2.69 +     * Gets the index of the property that was changed.
    2.70 +     *
    2.71 +     * @return The index specifying the property element that was
    2.72 +     *         changed.
    2.73 +     */
    2.74 +    public int getIndex() {
    2.75 +        return index;
    2.76 +    }
    2.77 +
    2.78 +    void appendTo(StringBuilder sb) {
    2.79 +        sb.append("; index=").append(getIndex());
    2.80 +    }
    2.81 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/emul/compact/src/main/java/java/beans/PropertyChangeEvent.java	Mon Jan 28 18:14:14 2013 +0100
     3.3 @@ -0,0 +1,164 @@
     3.4 +/*
     3.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
     3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.7 + *
     3.8 + * This code is free software; you can redistribute it and/or modify it
     3.9 + * under the terms of the GNU General Public License version 2 only, as
    3.10 + * published by the Free Software Foundation.  Oracle designates this
    3.11 + * particular file as subject to the "Classpath" exception as provided
    3.12 + * by Oracle in the LICENSE file that accompanied this code.
    3.13 + *
    3.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    3.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    3.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    3.17 + * version 2 for more details (a copy is included in the LICENSE file that
    3.18 + * accompanied this code).
    3.19 + *
    3.20 + * You should have received a copy of the GNU General Public License version
    3.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    3.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    3.23 + *
    3.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    3.25 + * or visit www.oracle.com if you need additional information or have any
    3.26 + * questions.
    3.27 + */
    3.28 +
    3.29 +package java.beans;
    3.30 +
    3.31 +/**
    3.32 + * A "PropertyChange" event gets delivered whenever a bean changes a "bound"
    3.33 + * or "constrained" property.  A PropertyChangeEvent object is sent as an
    3.34 + * argument to the PropertyChangeListener and VetoableChangeListener methods.
    3.35 + * <P>
    3.36 + * Normally PropertyChangeEvents are accompanied by the name and the old
    3.37 + * and new value of the changed property.  If the new value is a primitive
    3.38 + * type (such as int or boolean) it must be wrapped as the
    3.39 + * corresponding java.lang.* Object type (such as Integer or Boolean).
    3.40 + * <P>
    3.41 + * Null values may be provided for the old and the new values if their
    3.42 + * true values are not known.
    3.43 + * <P>
    3.44 + * An event source may send a null object as the name to indicate that an
    3.45 + * arbitrary set of if its properties have changed.  In this case the
    3.46 + * old and new values should also be null.
    3.47 + */
    3.48 +
    3.49 +public class PropertyChangeEvent extends java.util.EventObject {
    3.50 +    private static final long serialVersionUID = 7042693688939648123L;
    3.51 +
    3.52 +    /**
    3.53 +     * Constructs a new <code>PropertyChangeEvent</code>.
    3.54 +     *
    3.55 +     * @param source  The bean that fired the event.
    3.56 +     * @param propertyName  The programmatic name of the property
    3.57 +     *          that was changed.
    3.58 +     * @param oldValue  The old value of the property.
    3.59 +     * @param newValue  The new value of the property.
    3.60 +     */
    3.61 +    public PropertyChangeEvent(Object source, String propertyName,
    3.62 +                                     Object oldValue, Object newValue) {
    3.63 +        super(source);
    3.64 +        this.propertyName = propertyName;
    3.65 +        this.newValue = newValue;
    3.66 +        this.oldValue = oldValue;
    3.67 +    }
    3.68 +
    3.69 +    /**
    3.70 +     * Gets the programmatic name of the property that was changed.
    3.71 +     *
    3.72 +     * @return  The programmatic name of the property that was changed.
    3.73 +     *          May be null if multiple properties have changed.
    3.74 +     */
    3.75 +    public String getPropertyName() {
    3.76 +        return propertyName;
    3.77 +    }
    3.78 +
    3.79 +    /**
    3.80 +     * Gets the new value for the property, expressed as an Object.
    3.81 +     *
    3.82 +     * @return  The new value for the property, expressed as an Object.
    3.83 +     *          May be null if multiple properties have changed.
    3.84 +     */
    3.85 +    public Object getNewValue() {
    3.86 +        return newValue;
    3.87 +    }
    3.88 +
    3.89 +    /**
    3.90 +     * Gets the old value for the property, expressed as an Object.
    3.91 +     *
    3.92 +     * @return  The old value for the property, expressed as an Object.
    3.93 +     *          May be null if multiple properties have changed.
    3.94 +     */
    3.95 +    public Object getOldValue() {
    3.96 +        return oldValue;
    3.97 +    }
    3.98 +
    3.99 +    /**
   3.100 +     * Sets the propagationId object for the event.
   3.101 +     *
   3.102 +     * @param propagationId  The propagationId object for the event.
   3.103 +     */
   3.104 +    public void setPropagationId(Object propagationId) {
   3.105 +        this.propagationId = propagationId;
   3.106 +    }
   3.107 +
   3.108 +    /**
   3.109 +     * The "propagationId" field is reserved for future use.  In Beans 1.0
   3.110 +     * the sole requirement is that if a listener catches a PropertyChangeEvent
   3.111 +     * and then fires a PropertyChangeEvent of its own, then it should
   3.112 +     * make sure that it propagates the propagationId field from its
   3.113 +     * incoming event to its outgoing event.
   3.114 +     *
   3.115 +     * @return the propagationId object associated with a bound/constrained
   3.116 +     *          property update.
   3.117 +     */
   3.118 +    public Object getPropagationId() {
   3.119 +        return propagationId;
   3.120 +    }
   3.121 +
   3.122 +    /**
   3.123 +     * name of the property that changed.  May be null, if not known.
   3.124 +     * @serial
   3.125 +     */
   3.126 +    private String propertyName;
   3.127 +
   3.128 +    /**
   3.129 +     * New value for property.  May be null if not known.
   3.130 +     * @serial
   3.131 +     */
   3.132 +    private Object newValue;
   3.133 +
   3.134 +    /**
   3.135 +     * Previous value for property.  May be null if not known.
   3.136 +     * @serial
   3.137 +     */
   3.138 +    private Object oldValue;
   3.139 +
   3.140 +    /**
   3.141 +     * Propagation ID.  May be null.
   3.142 +     * @serial
   3.143 +     * @see #getPropagationId
   3.144 +     */
   3.145 +    private Object propagationId;
   3.146 +
   3.147 +    /**
   3.148 +     * Returns a string representation of the object.
   3.149 +     *
   3.150 +     * @return a string representation of the object
   3.151 +     *
   3.152 +     * @since 1.7
   3.153 +     */
   3.154 +    public String toString() {
   3.155 +        StringBuilder sb = new StringBuilder(getClass().getName());
   3.156 +        sb.append("[propertyName=").append(getPropertyName());
   3.157 +        appendTo(sb);
   3.158 +        sb.append("; oldValue=").append(getOldValue());
   3.159 +        sb.append("; newValue=").append(getNewValue());
   3.160 +        sb.append("; propagationId=").append(getPropagationId());
   3.161 +        sb.append("; source=").append(getSource());
   3.162 +        return sb.append("]").toString();
   3.163 +    }
   3.164 +
   3.165 +    void appendTo(StringBuilder sb) {
   3.166 +    }
   3.167 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/emul/compact/src/main/java/java/beans/PropertyChangeListener.java	Mon Jan 28 18:14:14 2013 +0100
     4.3 @@ -0,0 +1,44 @@
     4.4 +/*
     4.5 + * Copyright (c) 1996, Oracle and/or its affiliates. All rights reserved.
     4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4.7 + *
     4.8 + * This code is free software; you can redistribute it and/or modify it
     4.9 + * under the terms of the GNU General Public License version 2 only, as
    4.10 + * published by the Free Software Foundation.  Oracle designates this
    4.11 + * particular file as subject to the "Classpath" exception as provided
    4.12 + * by Oracle in the LICENSE file that accompanied this code.
    4.13 + *
    4.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    4.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    4.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    4.17 + * version 2 for more details (a copy is included in the LICENSE file that
    4.18 + * accompanied this code).
    4.19 + *
    4.20 + * You should have received a copy of the GNU General Public License version
    4.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    4.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    4.23 + *
    4.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    4.25 + * or visit www.oracle.com if you need additional information or have any
    4.26 + * questions.
    4.27 + */
    4.28 +
    4.29 +package java.beans;
    4.30 +
    4.31 +/**
    4.32 + * A "PropertyChange" event gets fired whenever a bean changes a "bound"
    4.33 + * property.  You can register a PropertyChangeListener with a source
    4.34 + * bean so as to be notified of any bound property updates.
    4.35 + */
    4.36 +
    4.37 +public interface PropertyChangeListener extends java.util.EventListener {
    4.38 +
    4.39 +    /**
    4.40 +     * This method gets called when a bound property is changed.
    4.41 +     * @param evt A PropertyChangeEvent object describing the event source
    4.42 +     *          and the property that has changed.
    4.43 +     */
    4.44 +
    4.45 +    void propertyChange(PropertyChangeEvent evt);
    4.46 +
    4.47 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/emul/compact/src/main/java/java/beans/PropertyChangeListenerProxy.java	Mon Jan 28 18:14:14 2013 +0100
     5.3 @@ -0,0 +1,81 @@
     5.4 +/*
     5.5 + * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
     5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     5.7 + *
     5.8 + * This code is free software; you can redistribute it and/or modify it
     5.9 + * under the terms of the GNU General Public License version 2 only, as
    5.10 + * published by the Free Software Foundation.  Oracle designates this
    5.11 + * particular file as subject to the "Classpath" exception as provided
    5.12 + * by Oracle in the LICENSE file that accompanied this code.
    5.13 + *
    5.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    5.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    5.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    5.17 + * version 2 for more details (a copy is included in the LICENSE file that
    5.18 + * accompanied this code).
    5.19 + *
    5.20 + * You should have received a copy of the GNU General Public License version
    5.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    5.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    5.23 + *
    5.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    5.25 + * or visit www.oracle.com if you need additional information or have any
    5.26 + * questions.
    5.27 + */
    5.28 +
    5.29 +package java.beans;
    5.30 +
    5.31 +import java.util.EventListenerProxy;
    5.32 +
    5.33 +/**
    5.34 + * A class which extends the {@code EventListenerProxy}
    5.35 + * specifically for adding a {@code PropertyChangeListener}
    5.36 + * with a "bound" property.
    5.37 + * Instances of this class can be added
    5.38 + * as {@code PropertyChangeListener}s to a bean
    5.39 + * which supports firing property change events.
    5.40 + * <p>
    5.41 + * If the object has a {@code getPropertyChangeListeners} method
    5.42 + * then the array returned could be a mixture of {@code PropertyChangeListener}
    5.43 + * and {@code PropertyChangeListenerProxy} objects.
    5.44 + *
    5.45 + * @see java.util.EventListenerProxy
    5.46 + * @see PropertyChangeSupport#getPropertyChangeListeners
    5.47 + * @since 1.4
    5.48 + */
    5.49 +public class PropertyChangeListenerProxy
    5.50 +        extends EventListenerProxy<PropertyChangeListener>
    5.51 +        implements PropertyChangeListener {
    5.52 +
    5.53 +    private final String propertyName;
    5.54 +
    5.55 +    /**
    5.56 +     * Constructor which binds the {@code PropertyChangeListener}
    5.57 +     * to a specific property.
    5.58 +     *
    5.59 +     * @param propertyName  the name of the property to listen on
    5.60 +     * @param listener      the listener object
    5.61 +     */
    5.62 +    public PropertyChangeListenerProxy(String propertyName, PropertyChangeListener listener) {
    5.63 +        super(listener);
    5.64 +        this.propertyName = propertyName;
    5.65 +    }
    5.66 +
    5.67 +    /**
    5.68 +     * Forwards the property change event to the listener delegate.
    5.69 +     *
    5.70 +     * @param event  the property change event
    5.71 +     */
    5.72 +    public void propertyChange(PropertyChangeEvent event) {
    5.73 +        getListener().propertyChange(event);
    5.74 +    }
    5.75 +
    5.76 +    /**
    5.77 +     * Returns the name of the named property associated with the listener.
    5.78 +     *
    5.79 +     * @return the name of the named property associated with the listener
    5.80 +     */
    5.81 +    public String getPropertyName() {
    5.82 +        return this.propertyName;
    5.83 +    }
    5.84 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/emul/compact/src/main/java/java/beans/PropertyChangeSupport.java	Mon Jan 28 18:14:14 2013 +0100
     6.3 @@ -0,0 +1,536 @@
     6.4 +/*
     6.5 + * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
     6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     6.7 + *
     6.8 + * This code is free software; you can redistribute it and/or modify it
     6.9 + * under the terms of the GNU General Public License version 2 only, as
    6.10 + * published by the Free Software Foundation.  Oracle designates this
    6.11 + * particular file as subject to the "Classpath" exception as provided
    6.12 + * by Oracle in the LICENSE file that accompanied this code.
    6.13 + *
    6.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    6.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    6.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    6.17 + * version 2 for more details (a copy is included in the LICENSE file that
    6.18 + * accompanied this code).
    6.19 + *
    6.20 + * You should have received a copy of the GNU General Public License version
    6.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    6.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    6.23 + *
    6.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    6.25 + * or visit www.oracle.com if you need additional information or have any
    6.26 + * questions.
    6.27 + */
    6.28 +package java.beans;
    6.29 +
    6.30 +import java.io.Serializable;
    6.31 +import java.io.ObjectStreamField;
    6.32 +import java.io.ObjectOutputStream;
    6.33 +import java.io.ObjectInputStream;
    6.34 +import java.io.IOException;
    6.35 +import java.util.Hashtable;
    6.36 +import java.util.Map.Entry;
    6.37 +
    6.38 +/**
    6.39 + * This is a utility class that can be used by beans that support bound
    6.40 + * properties.  It manages a list of listeners and dispatches
    6.41 + * {@link PropertyChangeEvent}s to them.  You can use an instance of this class
    6.42 + * as a member field of your bean and delegate these types of work to it.
    6.43 + * The {@link PropertyChangeListener} can be registered for all properties
    6.44 + * or for a property specified by name.
    6.45 + * <p>
    6.46 + * Here is an example of {@code PropertyChangeSupport} usage that follows
    6.47 + * the rules and recommendations laid out in the JavaBeans&trade; specification:
    6.48 + * <pre>
    6.49 + * public class MyBean {
    6.50 + *     private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
    6.51 + *
    6.52 + *     public void addPropertyChangeListener(PropertyChangeListener listener) {
    6.53 + *         this.pcs.addPropertyChangeListener(listener);
    6.54 + *     }
    6.55 + *
    6.56 + *     public void removePropertyChangeListener(PropertyChangeListener listener) {
    6.57 + *         this.pcs.removePropertyChangeListener(listener);
    6.58 + *     }
    6.59 + *
    6.60 + *     private String value;
    6.61 + *
    6.62 + *     public String getValue() {
    6.63 + *         return this.value;
    6.64 + *     }
    6.65 + *
    6.66 + *     public void setValue(String newValue) {
    6.67 + *         String oldValue = this.value;
    6.68 + *         this.value = newValue;
    6.69 + *         this.pcs.firePropertyChange("value", oldValue, newValue);
    6.70 + *     }
    6.71 + *
    6.72 + *     [...]
    6.73 + * }
    6.74 + * </pre>
    6.75 + * <p>
    6.76 + * A {@code PropertyChangeSupport} instance is thread-safe.
    6.77 + * <p>
    6.78 + * This class is serializable.  When it is serialized it will save
    6.79 + * (and restore) any listeners that are themselves serializable.  Any
    6.80 + * non-serializable listeners will be skipped during serialization.
    6.81 + *
    6.82 + * @see VetoableChangeSupport
    6.83 + */
    6.84 +public class PropertyChangeSupport implements Serializable {
    6.85 +    private PropertyChangeListenerMap map = new PropertyChangeListenerMap();
    6.86 +
    6.87 +    /**
    6.88 +     * Constructs a <code>PropertyChangeSupport</code> object.
    6.89 +     *
    6.90 +     * @param sourceBean  The bean to be given as the source for any events.
    6.91 +     */
    6.92 +    public PropertyChangeSupport(Object sourceBean) {
    6.93 +        if (sourceBean == null) {
    6.94 +            throw new NullPointerException();
    6.95 +        }
    6.96 +        source = sourceBean;
    6.97 +    }
    6.98 +
    6.99 +    /**
   6.100 +     * Add a PropertyChangeListener to the listener list.
   6.101 +     * The listener is registered for all properties.
   6.102 +     * The same listener object may be added more than once, and will be called
   6.103 +     * as many times as it is added.
   6.104 +     * If <code>listener</code> is null, no exception is thrown and no action
   6.105 +     * is taken.
   6.106 +     *
   6.107 +     * @param listener  The PropertyChangeListener to be added
   6.108 +     */
   6.109 +    public void addPropertyChangeListener(PropertyChangeListener listener) {
   6.110 +        if (listener == null) {
   6.111 +            return;
   6.112 +        }
   6.113 +        if (listener instanceof PropertyChangeListenerProxy) {
   6.114 +            PropertyChangeListenerProxy proxy =
   6.115 +                   (PropertyChangeListenerProxy)listener;
   6.116 +            // Call two argument add method.
   6.117 +            addPropertyChangeListener(proxy.getPropertyName(),
   6.118 +                                      proxy.getListener());
   6.119 +        } else {
   6.120 +            this.map.add(null, listener);
   6.121 +        }
   6.122 +    }
   6.123 +
   6.124 +    /**
   6.125 +     * Remove a PropertyChangeListener from the listener list.
   6.126 +     * This removes a PropertyChangeListener that was registered
   6.127 +     * for all properties.
   6.128 +     * If <code>listener</code> was added more than once to the same event
   6.129 +     * source, it will be notified one less time after being removed.
   6.130 +     * If <code>listener</code> is null, or was never added, no exception is
   6.131 +     * thrown and no action is taken.
   6.132 +     *
   6.133 +     * @param listener  The PropertyChangeListener to be removed
   6.134 +     */
   6.135 +    public void removePropertyChangeListener(PropertyChangeListener listener) {
   6.136 +        if (listener == null) {
   6.137 +            return;
   6.138 +        }
   6.139 +        if (listener instanceof PropertyChangeListenerProxy) {
   6.140 +            PropertyChangeListenerProxy proxy =
   6.141 +                    (PropertyChangeListenerProxy)listener;
   6.142 +            // Call two argument remove method.
   6.143 +            removePropertyChangeListener(proxy.getPropertyName(),
   6.144 +                                         proxy.getListener());
   6.145 +        } else {
   6.146 +            this.map.remove(null, listener);
   6.147 +        }
   6.148 +    }
   6.149 +
   6.150 +    /**
   6.151 +     * Returns an array of all the listeners that were added to the
   6.152 +     * PropertyChangeSupport object with addPropertyChangeListener().
   6.153 +     * <p>
   6.154 +     * If some listeners have been added with a named property, then
   6.155 +     * the returned array will be a mixture of PropertyChangeListeners
   6.156 +     * and <code>PropertyChangeListenerProxy</code>s. If the calling
   6.157 +     * method is interested in distinguishing the listeners then it must
   6.158 +     * test each element to see if it's a
   6.159 +     * <code>PropertyChangeListenerProxy</code>, perform the cast, and examine
   6.160 +     * the parameter.
   6.161 +     *
   6.162 +     * <pre>
   6.163 +     * PropertyChangeListener[] listeners = bean.getPropertyChangeListeners();
   6.164 +     * for (int i = 0; i < listeners.length; i++) {
   6.165 +     *   if (listeners[i] instanceof PropertyChangeListenerProxy) {
   6.166 +     *     PropertyChangeListenerProxy proxy =
   6.167 +     *                    (PropertyChangeListenerProxy)listeners[i];
   6.168 +     *     if (proxy.getPropertyName().equals("foo")) {
   6.169 +     *       // proxy is a PropertyChangeListener which was associated
   6.170 +     *       // with the property named "foo"
   6.171 +     *     }
   6.172 +     *   }
   6.173 +     * }
   6.174 +     *</pre>
   6.175 +     *
   6.176 +     * @see PropertyChangeListenerProxy
   6.177 +     * @return all of the <code>PropertyChangeListeners</code> added or an
   6.178 +     *         empty array if no listeners have been added
   6.179 +     * @since 1.4
   6.180 +     */
   6.181 +    public PropertyChangeListener[] getPropertyChangeListeners() {
   6.182 +        return this.map.getListeners();
   6.183 +    }
   6.184 +
   6.185 +    /**
   6.186 +     * Add a PropertyChangeListener for a specific property.  The listener
   6.187 +     * will be invoked only when a call on firePropertyChange names that
   6.188 +     * specific property.
   6.189 +     * The same listener object may be added more than once.  For each
   6.190 +     * property,  the listener will be invoked the number of times it was added
   6.191 +     * for that property.
   6.192 +     * If <code>propertyName</code> or <code>listener</code> is null, no
   6.193 +     * exception is thrown and no action is taken.
   6.194 +     *
   6.195 +     * @param propertyName  The name of the property to listen on.
   6.196 +     * @param listener  The PropertyChangeListener to be added
   6.197 +     */
   6.198 +    public void addPropertyChangeListener(
   6.199 +                String propertyName,
   6.200 +                PropertyChangeListener listener) {
   6.201 +        if (listener == null || propertyName == null) {
   6.202 +            return;
   6.203 +        }
   6.204 +        listener = this.map.extract(listener);
   6.205 +        if (listener != null) {
   6.206 +            this.map.add(propertyName, listener);
   6.207 +        }
   6.208 +    }
   6.209 +
   6.210 +    /**
   6.211 +     * Remove a PropertyChangeListener for a specific property.
   6.212 +     * If <code>listener</code> was added more than once to the same event
   6.213 +     * source for the specified property, it will be notified one less time
   6.214 +     * after being removed.
   6.215 +     * If <code>propertyName</code> is null,  no exception is thrown and no
   6.216 +     * action is taken.
   6.217 +     * If <code>listener</code> is null, or was never added for the specified
   6.218 +     * property, no exception is thrown and no action is taken.
   6.219 +     *
   6.220 +     * @param propertyName  The name of the property that was listened on.
   6.221 +     * @param listener  The PropertyChangeListener to be removed
   6.222 +     */
   6.223 +    public void removePropertyChangeListener(
   6.224 +                String propertyName,
   6.225 +                PropertyChangeListener listener) {
   6.226 +        if (listener == null || propertyName == null) {
   6.227 +            return;
   6.228 +        }
   6.229 +        listener = this.map.extract(listener);
   6.230 +        if (listener != null) {
   6.231 +            this.map.remove(propertyName, listener);
   6.232 +        }
   6.233 +    }
   6.234 +
   6.235 +    /**
   6.236 +     * Returns an array of all the listeners which have been associated
   6.237 +     * with the named property.
   6.238 +     *
   6.239 +     * @param propertyName  The name of the property being listened to
   6.240 +     * @return all of the <code>PropertyChangeListeners</code> associated with
   6.241 +     *         the named property.  If no such listeners have been added,
   6.242 +     *         or if <code>propertyName</code> is null, an empty array is
   6.243 +     *         returned.
   6.244 +     * @since 1.4
   6.245 +     */
   6.246 +    public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
   6.247 +        return this.map.getListeners(propertyName);
   6.248 +    }
   6.249 +
   6.250 +    /**
   6.251 +     * Reports a bound property update to listeners
   6.252 +     * that have been registered to track updates of
   6.253 +     * all properties or a property with the specified name.
   6.254 +     * <p>
   6.255 +     * No event is fired if old and new values are equal and non-null.
   6.256 +     * <p>
   6.257 +     * This is merely a convenience wrapper around the more general
   6.258 +     * {@link #firePropertyChange(PropertyChangeEvent)} method.
   6.259 +     *
   6.260 +     * @param propertyName  the programmatic name of the property that was changed
   6.261 +     * @param oldValue      the old value of the property
   6.262 +     * @param newValue      the new value of the property
   6.263 +     */
   6.264 +    public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
   6.265 +        if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
   6.266 +            firePropertyChange(new PropertyChangeEvent(this.source, propertyName, oldValue, newValue));
   6.267 +        }
   6.268 +    }
   6.269 +
   6.270 +    /**
   6.271 +     * Reports an integer bound property update to listeners
   6.272 +     * that have been registered to track updates of
   6.273 +     * all properties or a property with the specified name.
   6.274 +     * <p>
   6.275 +     * No event is fired if old and new values are equal.
   6.276 +     * <p>
   6.277 +     * This is merely a convenience wrapper around the more general
   6.278 +     * {@link #firePropertyChange(String, Object, Object)}  method.
   6.279 +     *
   6.280 +     * @param propertyName  the programmatic name of the property that was changed
   6.281 +     * @param oldValue      the old value of the property
   6.282 +     * @param newValue      the new value of the property
   6.283 +     */
   6.284 +    public void firePropertyChange(String propertyName, int oldValue, int newValue) {
   6.285 +        if (oldValue != newValue) {
   6.286 +            firePropertyChange(propertyName, Integer.valueOf(oldValue), Integer.valueOf(newValue));
   6.287 +        }
   6.288 +    }
   6.289 +
   6.290 +    /**
   6.291 +     * Reports a boolean bound property update to listeners
   6.292 +     * that have been registered to track updates of
   6.293 +     * all properties or a property with the specified name.
   6.294 +     * <p>
   6.295 +     * No event is fired if old and new values are equal.
   6.296 +     * <p>
   6.297 +     * This is merely a convenience wrapper around the more general
   6.298 +     * {@link #firePropertyChange(String, Object, Object)}  method.
   6.299 +     *
   6.300 +     * @param propertyName  the programmatic name of the property that was changed
   6.301 +     * @param oldValue      the old value of the property
   6.302 +     * @param newValue      the new value of the property
   6.303 +     */
   6.304 +    public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {
   6.305 +        if (oldValue != newValue) {
   6.306 +            firePropertyChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
   6.307 +        }
   6.308 +    }
   6.309 +
   6.310 +    /**
   6.311 +     * Fires a property change event to listeners
   6.312 +     * that have been registered to track updates of
   6.313 +     * all properties or a property with the specified name.
   6.314 +     * <p>
   6.315 +     * No event is fired if the given event's old and new values are equal and non-null.
   6.316 +     *
   6.317 +     * @param event  the {@code PropertyChangeEvent} to be fired
   6.318 +     */
   6.319 +    public void firePropertyChange(PropertyChangeEvent event) {
   6.320 +        Object oldValue = event.getOldValue();
   6.321 +        Object newValue = event.getNewValue();
   6.322 +        if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
   6.323 +            String name = event.getPropertyName();
   6.324 +
   6.325 +            PropertyChangeListener[] common = this.map.get(null);
   6.326 +            PropertyChangeListener[] named = (name != null)
   6.327 +                        ? this.map.get(name)
   6.328 +                        : null;
   6.329 +
   6.330 +            fire(common, event);
   6.331 +            fire(named, event);
   6.332 +        }
   6.333 +    }
   6.334 +
   6.335 +    private static void fire(PropertyChangeListener[] listeners, PropertyChangeEvent event) {
   6.336 +        if (listeners != null) {
   6.337 +            for (PropertyChangeListener listener : listeners) {
   6.338 +                listener.propertyChange(event);
   6.339 +            }
   6.340 +        }
   6.341 +    }
   6.342 +
   6.343 +    /**
   6.344 +     * Reports a bound indexed property update to listeners
   6.345 +     * that have been registered to track updates of
   6.346 +     * all properties or a property with the specified name.
   6.347 +     * <p>
   6.348 +     * No event is fired if old and new values are equal and non-null.
   6.349 +     * <p>
   6.350 +     * This is merely a convenience wrapper around the more general
   6.351 +     * {@link #firePropertyChange(PropertyChangeEvent)} method.
   6.352 +     *
   6.353 +     * @param propertyName  the programmatic name of the property that was changed
   6.354 +     * @param index         the index of the property element that was changed
   6.355 +     * @param oldValue      the old value of the property
   6.356 +     * @param newValue      the new value of the property
   6.357 +     * @since 1.5
   6.358 +     */
   6.359 +    public void fireIndexedPropertyChange(String propertyName, int index, Object oldValue, Object newValue) {
   6.360 +        if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
   6.361 +            firePropertyChange(new IndexedPropertyChangeEvent(source, propertyName, oldValue, newValue, index));
   6.362 +        }
   6.363 +    }
   6.364 +
   6.365 +    /**
   6.366 +     * Reports an integer bound indexed property update to listeners
   6.367 +     * that have been registered to track updates of
   6.368 +     * all properties or a property with the specified name.
   6.369 +     * <p>
   6.370 +     * No event is fired if old and new values are equal.
   6.371 +     * <p>
   6.372 +     * This is merely a convenience wrapper around the more general
   6.373 +     * {@link #fireIndexedPropertyChange(String, int, Object, Object)} method.
   6.374 +     *
   6.375 +     * @param propertyName  the programmatic name of the property that was changed
   6.376 +     * @param index         the index of the property element that was changed
   6.377 +     * @param oldValue      the old value of the property
   6.378 +     * @param newValue      the new value of the property
   6.379 +     * @since 1.5
   6.380 +     */
   6.381 +    public void fireIndexedPropertyChange(String propertyName, int index, int oldValue, int newValue) {
   6.382 +        if (oldValue != newValue) {
   6.383 +            fireIndexedPropertyChange(propertyName, index, Integer.valueOf(oldValue), Integer.valueOf(newValue));
   6.384 +        }
   6.385 +    }
   6.386 +
   6.387 +    /**
   6.388 +     * Reports a boolean bound indexed property update to listeners
   6.389 +     * that have been registered to track updates of
   6.390 +     * all properties or a property with the specified name.
   6.391 +     * <p>
   6.392 +     * No event is fired if old and new values are equal.
   6.393 +     * <p>
   6.394 +     * This is merely a convenience wrapper around the more general
   6.395 +     * {@link #fireIndexedPropertyChange(String, int, Object, Object)} method.
   6.396 +     *
   6.397 +     * @param propertyName  the programmatic name of the property that was changed
   6.398 +     * @param index         the index of the property element that was changed
   6.399 +     * @param oldValue      the old value of the property
   6.400 +     * @param newValue      the new value of the property
   6.401 +     * @since 1.5
   6.402 +     */
   6.403 +    public void fireIndexedPropertyChange(String propertyName, int index, boolean oldValue, boolean newValue) {
   6.404 +        if (oldValue != newValue) {
   6.405 +            fireIndexedPropertyChange(propertyName, index, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
   6.406 +        }
   6.407 +    }
   6.408 +
   6.409 +    /**
   6.410 +     * Check if there are any listeners for a specific property, including
   6.411 +     * those registered on all properties.  If <code>propertyName</code>
   6.412 +     * is null, only check for listeners registered on all properties.
   6.413 +     *
   6.414 +     * @param propertyName  the property name.
   6.415 +     * @return true if there are one or more listeners for the given property
   6.416 +     */
   6.417 +    public boolean hasListeners(String propertyName) {
   6.418 +        return this.map.hasListeners(propertyName);
   6.419 +    }
   6.420 +
   6.421 +    /**
   6.422 +     * @serialData Null terminated list of <code>PropertyChangeListeners</code>.
   6.423 +     * <p>
   6.424 +     * At serialization time we skip non-serializable listeners and
   6.425 +     * only serialize the serializable listeners.
   6.426 +     */
   6.427 +    private void writeObject(ObjectOutputStream s) throws IOException {
   6.428 +        Hashtable<String, PropertyChangeSupport> children = null;
   6.429 +        PropertyChangeListener[] listeners = null;
   6.430 +        synchronized (this.map) {
   6.431 +            for (Entry<String, PropertyChangeListener[]> entry : this.map.getEntries()) {
   6.432 +                String property = entry.getKey();
   6.433 +                if (property == null) {
   6.434 +                    listeners = entry.getValue();
   6.435 +                } else {
   6.436 +                    if (children == null) {
   6.437 +                        children = new Hashtable<String, PropertyChangeSupport>();
   6.438 +                    }
   6.439 +                    PropertyChangeSupport pcs = new PropertyChangeSupport(this.source);
   6.440 +                    pcs.map.set(null, entry.getValue());
   6.441 +                    children.put(property, pcs);
   6.442 +                }
   6.443 +            }
   6.444 +        }
   6.445 +        ObjectOutputStream.PutField fields = s.putFields();
   6.446 +        fields.put("children", children);
   6.447 +        fields.put("source", this.source);
   6.448 +        fields.put("propertyChangeSupportSerializedDataVersion", 2);
   6.449 +        s.writeFields();
   6.450 +
   6.451 +        if (listeners != null) {
   6.452 +            for (PropertyChangeListener l : listeners) {
   6.453 +                if (l instanceof Serializable) {
   6.454 +                    s.writeObject(l);
   6.455 +                }
   6.456 +            }
   6.457 +        }
   6.458 +        s.writeObject(null);
   6.459 +    }
   6.460 +
   6.461 +    private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
   6.462 +        this.map = new PropertyChangeListenerMap();
   6.463 +
   6.464 +        ObjectInputStream.GetField fields = s.readFields();
   6.465 +
   6.466 +        Hashtable<String, PropertyChangeSupport> children = (Hashtable<String, PropertyChangeSupport>) fields.get("children", null);
   6.467 +        this.source = fields.get("source", null);
   6.468 +        fields.get("propertyChangeSupportSerializedDataVersion", 2);
   6.469 +
   6.470 +        Object listenerOrNull;
   6.471 +        while (null != (listenerOrNull = s.readObject())) {
   6.472 +            this.map.add(null, (PropertyChangeListener)listenerOrNull);
   6.473 +        }
   6.474 +        if (children != null) {
   6.475 +            for (Entry<String, PropertyChangeSupport> entry : children.entrySet()) {
   6.476 +                for (PropertyChangeListener listener : entry.getValue().getPropertyChangeListeners()) {
   6.477 +                    this.map.add(entry.getKey(), listener);
   6.478 +                }
   6.479 +            }
   6.480 +        }
   6.481 +    }
   6.482 +
   6.483 +    /**
   6.484 +     * The object to be provided as the "source" for any generated events.
   6.485 +     */
   6.486 +    private Object source;
   6.487 +
   6.488 +    /**
   6.489 +     * @serialField children                                   Hashtable
   6.490 +     * @serialField source                                     Object
   6.491 +     * @serialField propertyChangeSupportSerializedDataVersion int
   6.492 +     */
   6.493 +    private static final ObjectStreamField[] serialPersistentFields = {
   6.494 +            new ObjectStreamField("children", Hashtable.class),
   6.495 +            new ObjectStreamField("source", Object.class),
   6.496 +            new ObjectStreamField("propertyChangeSupportSerializedDataVersion", Integer.TYPE)
   6.497 +    };
   6.498 +
   6.499 +    /**
   6.500 +     * Serialization version ID, so we're compatible with JDK 1.1
   6.501 +     */
   6.502 +    static final long serialVersionUID = 6401253773779951803L;
   6.503 +
   6.504 +    /**
   6.505 +     * This is a {@link ChangeListenerMap ChangeListenerMap} implementation
   6.506 +     * that works with {@link PropertyChangeListener PropertyChangeListener} objects.
   6.507 +     */
   6.508 +    private static final class PropertyChangeListenerMap extends ChangeListenerMap<PropertyChangeListener> {
   6.509 +        private static final PropertyChangeListener[] EMPTY = {};
   6.510 +
   6.511 +        /**
   6.512 +         * Creates an array of {@link PropertyChangeListener PropertyChangeListener} objects.
   6.513 +         * This method uses the same instance of the empty array
   6.514 +         * when {@code length} equals {@code 0}.
   6.515 +         *
   6.516 +         * @param length  the array length
   6.517 +         * @return        an array with specified length
   6.518 +         */
   6.519 +        @Override
   6.520 +        protected PropertyChangeListener[] newArray(int length) {
   6.521 +            return (0 < length)
   6.522 +                    ? new PropertyChangeListener[length]
   6.523 +                    : EMPTY;
   6.524 +        }
   6.525 +
   6.526 +        /**
   6.527 +         * Creates a {@link PropertyChangeListenerProxy PropertyChangeListenerProxy}
   6.528 +         * object for the specified property.
   6.529 +         *
   6.530 +         * @param name      the name of the property to listen on
   6.531 +         * @param listener  the listener to process events
   6.532 +         * @return          a {@code PropertyChangeListenerProxy} object
   6.533 +         */
   6.534 +        @Override
   6.535 +        protected PropertyChangeListener newProxy(String name, PropertyChangeListener listener) {
   6.536 +            return new PropertyChangeListenerProxy(name, listener);
   6.537 +        }
   6.538 +    }
   6.539 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/emul/compact/src/main/java/java/beans/PropertyVetoException.java	Mon Jan 28 18:14:14 2013 +0100
     7.3 @@ -0,0 +1,64 @@
     7.4 +/*
     7.5 + * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
     7.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     7.7 + *
     7.8 + * This code is free software; you can redistribute it and/or modify it
     7.9 + * under the terms of the GNU General Public License version 2 only, as
    7.10 + * published by the Free Software Foundation.  Oracle designates this
    7.11 + * particular file as subject to the "Classpath" exception as provided
    7.12 + * by Oracle in the LICENSE file that accompanied this code.
    7.13 + *
    7.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    7.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    7.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    7.17 + * version 2 for more details (a copy is included in the LICENSE file that
    7.18 + * accompanied this code).
    7.19 + *
    7.20 + * You should have received a copy of the GNU General Public License version
    7.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    7.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    7.23 + *
    7.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    7.25 + * or visit www.oracle.com if you need additional information or have any
    7.26 + * questions.
    7.27 + */
    7.28 +
    7.29 +package java.beans;
    7.30 +
    7.31 +
    7.32 +/**
    7.33 + * A PropertyVetoException is thrown when a proposed change to a
    7.34 + * property represents an unacceptable value.
    7.35 + */
    7.36 +
    7.37 +public
    7.38 +class PropertyVetoException extends Exception {
    7.39 +    private static final long serialVersionUID = 129596057694162164L;
    7.40 +
    7.41 +    /**
    7.42 +     * Constructs a <code>PropertyVetoException</code> with a
    7.43 +     * detailed message.
    7.44 +     *
    7.45 +     * @param mess Descriptive message
    7.46 +     * @param evt A PropertyChangeEvent describing the vetoed change.
    7.47 +     */
    7.48 +    public PropertyVetoException(String mess, PropertyChangeEvent evt) {
    7.49 +        super(mess);
    7.50 +        this.evt = evt;
    7.51 +    }
    7.52 +
    7.53 +     /**
    7.54 +     * Gets the vetoed <code>PropertyChangeEvent</code>.
    7.55 +     *
    7.56 +     * @return A PropertyChangeEvent describing the vetoed change.
    7.57 +     */
    7.58 +    public PropertyChangeEvent getPropertyChangeEvent() {
    7.59 +        return evt;
    7.60 +    }
    7.61 +
    7.62 +    /**
    7.63 +     * A PropertyChangeEvent describing the vetoed change.
    7.64 +     * @serial
    7.65 +     */
    7.66 +    private PropertyChangeEvent evt;
    7.67 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/emul/compact/src/main/java/java/beans/VetoableChangeListener.java	Mon Jan 28 18:14:14 2013 +0100
     8.3 @@ -0,0 +1,44 @@
     8.4 +/*
     8.5 + * Copyright (c) 1996, 1997, Oracle and/or its affiliates. All rights reserved.
     8.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     8.7 + *
     8.8 + * This code is free software; you can redistribute it and/or modify it
     8.9 + * under the terms of the GNU General Public License version 2 only, as
    8.10 + * published by the Free Software Foundation.  Oracle designates this
    8.11 + * particular file as subject to the "Classpath" exception as provided
    8.12 + * by Oracle in the LICENSE file that accompanied this code.
    8.13 + *
    8.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    8.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    8.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    8.17 + * version 2 for more details (a copy is included in the LICENSE file that
    8.18 + * accompanied this code).
    8.19 + *
    8.20 + * You should have received a copy of the GNU General Public License version
    8.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    8.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    8.23 + *
    8.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    8.25 + * or visit www.oracle.com if you need additional information or have any
    8.26 + * questions.
    8.27 + */
    8.28 +
    8.29 +package java.beans;
    8.30 +
    8.31 +/**
    8.32 + * A VetoableChange event gets fired whenever a bean changes a "constrained"
    8.33 + * property.  You can register a VetoableChangeListener with a source bean
    8.34 + * so as to be notified of any constrained property updates.
    8.35 + */
    8.36 +public interface VetoableChangeListener extends java.util.EventListener {
    8.37 +    /**
    8.38 +     * This method gets called when a constrained property is changed.
    8.39 +     *
    8.40 +     * @param     evt a <code>PropertyChangeEvent</code> object describing the
    8.41 +     *                event source and the property that has changed.
    8.42 +     * @exception PropertyVetoException if the recipient wishes the property
    8.43 +     *              change to be rolled back.
    8.44 +     */
    8.45 +    void vetoableChange(PropertyChangeEvent evt)
    8.46 +                                throws PropertyVetoException;
    8.47 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/emul/compact/src/main/java/java/beans/VetoableChangeListenerProxy.java	Mon Jan 28 18:14:14 2013 +0100
     9.3 @@ -0,0 +1,84 @@
     9.4 +/*
     9.5 + * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
     9.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     9.7 + *
     9.8 + * This code is free software; you can redistribute it and/or modify it
     9.9 + * under the terms of the GNU General Public License version 2 only, as
    9.10 + * published by the Free Software Foundation.  Oracle designates this
    9.11 + * particular file as subject to the "Classpath" exception as provided
    9.12 + * by Oracle in the LICENSE file that accompanied this code.
    9.13 + *
    9.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    9.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    9.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    9.17 + * version 2 for more details (a copy is included in the LICENSE file that
    9.18 + * accompanied this code).
    9.19 + *
    9.20 + * You should have received a copy of the GNU General Public License version
    9.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    9.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    9.23 + *
    9.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    9.25 + * or visit www.oracle.com if you need additional information or have any
    9.26 + * questions.
    9.27 + */
    9.28 +
    9.29 +package java.beans;
    9.30 +
    9.31 +import java.util.EventListenerProxy;
    9.32 +
    9.33 +/**
    9.34 + * A class which extends the {@code EventListenerProxy}
    9.35 + * specifically for adding a {@code VetoableChangeListener}
    9.36 + * with a "constrained" property.
    9.37 + * Instances of this class can be added
    9.38 + * as {@code VetoableChangeListener}s to a bean
    9.39 + * which supports firing vetoable change events.
    9.40 + * <p>
    9.41 + * If the object has a {@code getVetoableChangeListeners} method
    9.42 + * then the array returned could be a mixture of {@code VetoableChangeListener}
    9.43 + * and {@code VetoableChangeListenerProxy} objects.
    9.44 + *
    9.45 + * @see java.util.EventListenerProxy
    9.46 + * @see VetoableChangeSupport#getVetoableChangeListeners
    9.47 + * @since 1.4
    9.48 + */
    9.49 +public class VetoableChangeListenerProxy
    9.50 +        extends EventListenerProxy<VetoableChangeListener>
    9.51 +        implements VetoableChangeListener {
    9.52 +
    9.53 +    private final String propertyName;
    9.54 +
    9.55 +    /**
    9.56 +     * Constructor which binds the {@code VetoableChangeListener}
    9.57 +     * to a specific property.
    9.58 +     *
    9.59 +     * @param propertyName  the name of the property to listen on
    9.60 +     * @param listener      the listener object
    9.61 +     */
    9.62 +    public VetoableChangeListenerProxy(String propertyName, VetoableChangeListener listener) {
    9.63 +        super(listener);
    9.64 +        this.propertyName = propertyName;
    9.65 +    }
    9.66 +
    9.67 +    /**
    9.68 +    * Forwards the property change event to the listener delegate.
    9.69 +    *
    9.70 +    * @param event  the property change event
    9.71 +    *
    9.72 +    * @exception PropertyVetoException if the recipient wishes the property
    9.73 +    *                                  change to be rolled back
    9.74 +    */
    9.75 +    public void vetoableChange(PropertyChangeEvent event) throws PropertyVetoException{
    9.76 +        getListener().vetoableChange(event);
    9.77 +    }
    9.78 +
    9.79 +    /**
    9.80 +     * Returns the name of the named property associated with the listener.
    9.81 +     *
    9.82 +     * @return the name of the named property associated with the listener
    9.83 +     */
    9.84 +    public String getPropertyName() {
    9.85 +        return this.propertyName;
    9.86 +    }
    9.87 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/emul/compact/src/main/java/java/beans/VetoableChangeSupport.java	Mon Jan 28 18:14:14 2013 +0100
    10.3 @@ -0,0 +1,525 @@
    10.4 +/*
    10.5 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
    10.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    10.7 + *
    10.8 + * This code is free software; you can redistribute it and/or modify it
    10.9 + * under the terms of the GNU General Public License version 2 only, as
   10.10 + * published by the Free Software Foundation.  Oracle designates this
   10.11 + * particular file as subject to the "Classpath" exception as provided
   10.12 + * by Oracle in the LICENSE file that accompanied this code.
   10.13 + *
   10.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   10.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   10.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   10.17 + * version 2 for more details (a copy is included in the LICENSE file that
   10.18 + * accompanied this code).
   10.19 + *
   10.20 + * You should have received a copy of the GNU General Public License version
   10.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   10.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   10.23 + *
   10.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   10.25 + * or visit www.oracle.com if you need additional information or have any
   10.26 + * questions.
   10.27 + */
   10.28 +package java.beans;
   10.29 +
   10.30 +import java.io.Serializable;
   10.31 +import java.io.ObjectStreamField;
   10.32 +import java.io.ObjectOutputStream;
   10.33 +import java.io.ObjectInputStream;
   10.34 +import java.io.IOException;
   10.35 +import java.util.Hashtable;
   10.36 +import java.util.Map.Entry;
   10.37 +
   10.38 +/**
   10.39 + * This is a utility class that can be used by beans that support constrained
   10.40 + * properties.  It manages a list of listeners and dispatches
   10.41 + * {@link PropertyChangeEvent}s to them.  You can use an instance of this class
   10.42 + * as a member field of your bean and delegate these types of work to it.
   10.43 + * The {@link VetoableChangeListener} can be registered for all properties
   10.44 + * or for a property specified by name.
   10.45 + * <p>
   10.46 + * Here is an example of {@code VetoableChangeSupport} usage that follows
   10.47 + * the rules and recommendations laid out in the JavaBeans&trade; specification:
   10.48 + * <pre>
   10.49 + * public class MyBean {
   10.50 + *     private final VetoableChangeSupport vcs = new VetoableChangeSupport(this);
   10.51 + *
   10.52 + *     public void addVetoableChangeListener(VetoableChangeListener listener) {
   10.53 + *         this.vcs.addVetoableChangeListener(listener);
   10.54 + *     }
   10.55 + *
   10.56 + *     public void removeVetoableChangeListener(VetoableChangeListener listener) {
   10.57 + *         this.vcs.removeVetoableChangeListener(listener);
   10.58 + *     }
   10.59 + *
   10.60 + *     private String value;
   10.61 + *
   10.62 + *     public String getValue() {
   10.63 + *         return this.value;
   10.64 + *     }
   10.65 + *
   10.66 + *     public void setValue(String newValue) throws PropertyVetoException {
   10.67 + *         String oldValue = this.value;
   10.68 + *         this.vcs.fireVetoableChange("value", oldValue, newValue);
   10.69 + *         this.value = newValue;
   10.70 + *     }
   10.71 + *
   10.72 + *     [...]
   10.73 + * }
   10.74 + * </pre>
   10.75 + * <p>
   10.76 + * A {@code VetoableChangeSupport} instance is thread-safe.
   10.77 + * <p>
   10.78 + * This class is serializable.  When it is serialized it will save
   10.79 + * (and restore) any listeners that are themselves serializable.  Any
   10.80 + * non-serializable listeners will be skipped during serialization.
   10.81 + *
   10.82 + * @see PropertyChangeSupport
   10.83 + */
   10.84 +public class VetoableChangeSupport implements Serializable {
   10.85 +    private VetoableChangeListenerMap map = new VetoableChangeListenerMap();
   10.86 +
   10.87 +    /**
   10.88 +     * Constructs a <code>VetoableChangeSupport</code> object.
   10.89 +     *
   10.90 +     * @param sourceBean  The bean to be given as the source for any events.
   10.91 +     */
   10.92 +    public VetoableChangeSupport(Object sourceBean) {
   10.93 +        if (sourceBean == null) {
   10.94 +            throw new NullPointerException();
   10.95 +        }
   10.96 +        source = sourceBean;
   10.97 +    }
   10.98 +
   10.99 +    /**
  10.100 +     * Add a VetoableChangeListener to the listener list.
  10.101 +     * The listener is registered for all properties.
  10.102 +     * The same listener object may be added more than once, and will be called
  10.103 +     * as many times as it is added.
  10.104 +     * If <code>listener</code> is null, no exception is thrown and no action
  10.105 +     * is taken.
  10.106 +     *
  10.107 +     * @param listener  The VetoableChangeListener to be added
  10.108 +     */
  10.109 +    public void addVetoableChangeListener(VetoableChangeListener listener) {
  10.110 +        if (listener == null) {
  10.111 +            return;
  10.112 +        }
  10.113 +        if (listener instanceof VetoableChangeListenerProxy) {
  10.114 +            VetoableChangeListenerProxy proxy =
  10.115 +                    (VetoableChangeListenerProxy)listener;
  10.116 +            // Call two argument add method.
  10.117 +            addVetoableChangeListener(proxy.getPropertyName(),
  10.118 +                                      proxy.getListener());
  10.119 +        } else {
  10.120 +            this.map.add(null, listener);
  10.121 +        }
  10.122 +    }
  10.123 +
  10.124 +    /**
  10.125 +     * Remove a VetoableChangeListener from the listener list.
  10.126 +     * This removes a VetoableChangeListener that was registered
  10.127 +     * for all properties.
  10.128 +     * If <code>listener</code> was added more than once to the same event
  10.129 +     * source, it will be notified one less time after being removed.
  10.130 +     * If <code>listener</code> is null, or was never added, no exception is
  10.131 +     * thrown and no action is taken.
  10.132 +     *
  10.133 +     * @param listener  The VetoableChangeListener to be removed
  10.134 +     */
  10.135 +    public void removeVetoableChangeListener(VetoableChangeListener listener) {
  10.136 +        if (listener == null) {
  10.137 +            return;
  10.138 +        }
  10.139 +        if (listener instanceof VetoableChangeListenerProxy) {
  10.140 +            VetoableChangeListenerProxy proxy =
  10.141 +                    (VetoableChangeListenerProxy)listener;
  10.142 +            // Call two argument remove method.
  10.143 +            removeVetoableChangeListener(proxy.getPropertyName(),
  10.144 +                                         proxy.getListener());
  10.145 +        } else {
  10.146 +            this.map.remove(null, listener);
  10.147 +        }
  10.148 +    }
  10.149 +
  10.150 +    /**
  10.151 +     * Returns an array of all the listeners that were added to the
  10.152 +     * VetoableChangeSupport object with addVetoableChangeListener().
  10.153 +     * <p>
  10.154 +     * If some listeners have been added with a named property, then
  10.155 +     * the returned array will be a mixture of VetoableChangeListeners
  10.156 +     * and <code>VetoableChangeListenerProxy</code>s. If the calling
  10.157 +     * method is interested in distinguishing the listeners then it must
  10.158 +     * test each element to see if it's a
  10.159 +     * <code>VetoableChangeListenerProxy</code>, perform the cast, and examine
  10.160 +     * the parameter.
  10.161 +     *
  10.162 +     * <pre>
  10.163 +     * VetoableChangeListener[] listeners = bean.getVetoableChangeListeners();
  10.164 +     * for (int i = 0; i < listeners.length; i++) {
  10.165 +     *        if (listeners[i] instanceof VetoableChangeListenerProxy) {
  10.166 +     *     VetoableChangeListenerProxy proxy =
  10.167 +     *                    (VetoableChangeListenerProxy)listeners[i];
  10.168 +     *     if (proxy.getPropertyName().equals("foo")) {
  10.169 +     *       // proxy is a VetoableChangeListener which was associated
  10.170 +     *       // with the property named "foo"
  10.171 +     *     }
  10.172 +     *   }
  10.173 +     * }
  10.174 +     *</pre>
  10.175 +     *
  10.176 +     * @see VetoableChangeListenerProxy
  10.177 +     * @return all of the <code>VetoableChangeListeners</code> added or an
  10.178 +     *         empty array if no listeners have been added
  10.179 +     * @since 1.4
  10.180 +     */
  10.181 +    public VetoableChangeListener[] getVetoableChangeListeners(){
  10.182 +        return this.map.getListeners();
  10.183 +    }
  10.184 +
  10.185 +    /**
  10.186 +     * Add a VetoableChangeListener for a specific property.  The listener
  10.187 +     * will be invoked only when a call on fireVetoableChange names that
  10.188 +     * specific property.
  10.189 +     * The same listener object may be added more than once.  For each
  10.190 +     * property,  the listener will be invoked the number of times it was added
  10.191 +     * for that property.
  10.192 +     * If <code>propertyName</code> or <code>listener</code> is null, no
  10.193 +     * exception is thrown and no action is taken.
  10.194 +     *
  10.195 +     * @param propertyName  The name of the property to listen on.
  10.196 +     * @param listener  The VetoableChangeListener to be added
  10.197 +     */
  10.198 +    public void addVetoableChangeListener(
  10.199 +                                String propertyName,
  10.200 +                VetoableChangeListener listener) {
  10.201 +        if (listener == null || propertyName == null) {
  10.202 +            return;
  10.203 +        }
  10.204 +        listener = this.map.extract(listener);
  10.205 +        if (listener != null) {
  10.206 +            this.map.add(propertyName, listener);
  10.207 +        }
  10.208 +    }
  10.209 +
  10.210 +    /**
  10.211 +     * Remove a VetoableChangeListener for a specific property.
  10.212 +     * If <code>listener</code> was added more than once to the same event
  10.213 +     * source for the specified property, it will be notified one less time
  10.214 +     * after being removed.
  10.215 +     * If <code>propertyName</code> is null, no exception is thrown and no
  10.216 +     * action is taken.
  10.217 +     * If <code>listener</code> is null, or was never added for the specified
  10.218 +     * property, no exception is thrown and no action is taken.
  10.219 +     *
  10.220 +     * @param propertyName  The name of the property that was listened on.
  10.221 +     * @param listener  The VetoableChangeListener to be removed
  10.222 +     */
  10.223 +    public void removeVetoableChangeListener(
  10.224 +                                String propertyName,
  10.225 +                VetoableChangeListener listener) {
  10.226 +        if (listener == null || propertyName == null) {
  10.227 +            return;
  10.228 +        }
  10.229 +        listener = this.map.extract(listener);
  10.230 +        if (listener != null) {
  10.231 +            this.map.remove(propertyName, listener);
  10.232 +        }
  10.233 +    }
  10.234 +
  10.235 +    /**
  10.236 +     * Returns an array of all the listeners which have been associated
  10.237 +     * with the named property.
  10.238 +     *
  10.239 +     * @param propertyName  The name of the property being listened to
  10.240 +     * @return all the <code>VetoableChangeListeners</code> associated with
  10.241 +     *         the named property.  If no such listeners have been added,
  10.242 +     *         or if <code>propertyName</code> is null, an empty array is
  10.243 +     *         returned.
  10.244 +     * @since 1.4
  10.245 +     */
  10.246 +    public VetoableChangeListener[] getVetoableChangeListeners(String propertyName) {
  10.247 +        return this.map.getListeners(propertyName);
  10.248 +    }
  10.249 +
  10.250 +    /**
  10.251 +     * Reports a constrained property update to listeners
  10.252 +     * that have been registered to track updates of
  10.253 +     * all properties or a property with the specified name.
  10.254 +     * <p>
  10.255 +     * Any listener can throw a {@code PropertyVetoException} to veto the update.
  10.256 +     * If one of the listeners vetoes the update, this method passes
  10.257 +     * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
  10.258 +     * to all listeners that already confirmed this update
  10.259 +     * and throws the {@code PropertyVetoException} again.
  10.260 +     * <p>
  10.261 +     * No event is fired if old and new values are equal and non-null.
  10.262 +     * <p>
  10.263 +     * This is merely a convenience wrapper around the more general
  10.264 +     * {@link #fireVetoableChange(PropertyChangeEvent)} method.
  10.265 +     *
  10.266 +     * @param propertyName  the programmatic name of the property that is about to change
  10.267 +     * @param oldValue      the old value of the property
  10.268 +     * @param newValue      the new value of the property
  10.269 +     * @throws PropertyVetoException if one of listeners vetoes the property update
  10.270 +     */
  10.271 +    public void fireVetoableChange(String propertyName, Object oldValue, Object newValue)
  10.272 +            throws PropertyVetoException {
  10.273 +        if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
  10.274 +            fireVetoableChange(new PropertyChangeEvent(this.source, propertyName, oldValue, newValue));
  10.275 +        }
  10.276 +    }
  10.277 +
  10.278 +    /**
  10.279 +     * Reports an integer constrained property update to listeners
  10.280 +     * that have been registered to track updates of
  10.281 +     * all properties or a property with the specified name.
  10.282 +     * <p>
  10.283 +     * Any listener can throw a {@code PropertyVetoException} to veto the update.
  10.284 +     * If one of the listeners vetoes the update, this method passes
  10.285 +     * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
  10.286 +     * to all listeners that already confirmed this update
  10.287 +     * and throws the {@code PropertyVetoException} again.
  10.288 +     * <p>
  10.289 +     * No event is fired if old and new values are equal.
  10.290 +     * <p>
  10.291 +     * This is merely a convenience wrapper around the more general
  10.292 +     * {@link #fireVetoableChange(String, Object, Object)} method.
  10.293 +     *
  10.294 +     * @param propertyName  the programmatic name of the property that is about to change
  10.295 +     * @param oldValue      the old value of the property
  10.296 +     * @param newValue      the new value of the property
  10.297 +     * @throws PropertyVetoException if one of listeners vetoes the property update
  10.298 +     */
  10.299 +    public void fireVetoableChange(String propertyName, int oldValue, int newValue)
  10.300 +            throws PropertyVetoException {
  10.301 +        if (oldValue != newValue) {
  10.302 +            fireVetoableChange(propertyName, Integer.valueOf(oldValue), Integer.valueOf(newValue));
  10.303 +        }
  10.304 +    }
  10.305 +
  10.306 +    /**
  10.307 +     * Reports a boolean constrained property update to listeners
  10.308 +     * that have been registered to track updates of
  10.309 +     * all properties or a property with the specified name.
  10.310 +     * <p>
  10.311 +     * Any listener can throw a {@code PropertyVetoException} to veto the update.
  10.312 +     * If one of the listeners vetoes the update, this method passes
  10.313 +     * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
  10.314 +     * to all listeners that already confirmed this update
  10.315 +     * and throws the {@code PropertyVetoException} again.
  10.316 +     * <p>
  10.317 +     * No event is fired if old and new values are equal.
  10.318 +     * <p>
  10.319 +     * This is merely a convenience wrapper around the more general
  10.320 +     * {@link #fireVetoableChange(String, Object, Object)} method.
  10.321 +     *
  10.322 +     * @param propertyName  the programmatic name of the property that is about to change
  10.323 +     * @param oldValue      the old value of the property
  10.324 +     * @param newValue      the new value of the property
  10.325 +     * @throws PropertyVetoException if one of listeners vetoes the property update
  10.326 +     */
  10.327 +    public void fireVetoableChange(String propertyName, boolean oldValue, boolean newValue)
  10.328 +            throws PropertyVetoException {
  10.329 +        if (oldValue != newValue) {
  10.330 +            fireVetoableChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
  10.331 +        }
  10.332 +    }
  10.333 +
  10.334 +    /**
  10.335 +     * Fires a property change event to listeners
  10.336 +     * that have been registered to track updates of
  10.337 +     * all properties or a property with the specified name.
  10.338 +     * <p>
  10.339 +     * Any listener can throw a {@code PropertyVetoException} to veto the update.
  10.340 +     * If one of the listeners vetoes the update, this method passes
  10.341 +     * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
  10.342 +     * to all listeners that already confirmed this update
  10.343 +     * and throws the {@code PropertyVetoException} again.
  10.344 +     * <p>
  10.345 +     * No event is fired if the given event's old and new values are equal and non-null.
  10.346 +     *
  10.347 +     * @param event  the {@code PropertyChangeEvent} to be fired
  10.348 +     * @throws PropertyVetoException if one of listeners vetoes the property update
  10.349 +     */
  10.350 +    public void fireVetoableChange(PropertyChangeEvent event)
  10.351 +            throws PropertyVetoException {
  10.352 +        Object oldValue = event.getOldValue();
  10.353 +        Object newValue = event.getNewValue();
  10.354 +        if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
  10.355 +            String name = event.getPropertyName();
  10.356 +
  10.357 +            VetoableChangeListener[] common = this.map.get(null);
  10.358 +            VetoableChangeListener[] named = (name != null)
  10.359 +                        ? this.map.get(name)
  10.360 +                        : null;
  10.361 +
  10.362 +            VetoableChangeListener[] listeners;
  10.363 +            if (common == null) {
  10.364 +                listeners = named;
  10.365 +            }
  10.366 +            else if (named == null) {
  10.367 +                listeners = common;
  10.368 +            }
  10.369 +            else {
  10.370 +                listeners = new VetoableChangeListener[common.length + named.length];
  10.371 +                System.arraycopy(common, 0, listeners, 0, common.length);
  10.372 +                System.arraycopy(named, 0, listeners, common.length, named.length);
  10.373 +            }
  10.374 +            if (listeners != null) {
  10.375 +                int current = 0;
  10.376 +                try {
  10.377 +                    while (current < listeners.length) {
  10.378 +                        listeners[current].vetoableChange(event);
  10.379 +                        current++;
  10.380 +                    }
  10.381 +                }
  10.382 +                catch (PropertyVetoException veto) {
  10.383 +                    event = new PropertyChangeEvent(this.source, name, newValue, oldValue);
  10.384 +                    for (int i = 0; i < current; i++) {
  10.385 +                        try {
  10.386 +                            listeners[i].vetoableChange(event);
  10.387 +                        }
  10.388 +                        catch (PropertyVetoException exception) {
  10.389 +                            // ignore exceptions that occur during rolling back
  10.390 +                        }
  10.391 +                    }
  10.392 +                    throw veto; // rethrow the veto exception
  10.393 +                }
  10.394 +            }
  10.395 +        }
  10.396 +    }
  10.397 +
  10.398 +    /**
  10.399 +     * Check if there are any listeners for a specific property, including
  10.400 +     * those registered on all properties.  If <code>propertyName</code>
  10.401 +     * is null, only check for listeners registered on all properties.
  10.402 +     *
  10.403 +     * @param propertyName  the property name.
  10.404 +     * @return true if there are one or more listeners for the given property
  10.405 +     */
  10.406 +    public boolean hasListeners(String propertyName) {
  10.407 +        return this.map.hasListeners(propertyName);
  10.408 +    }
  10.409 +
  10.410 +    /**
  10.411 +     * @serialData Null terminated list of <code>VetoableChangeListeners</code>.
  10.412 +     * <p>
  10.413 +     * At serialization time we skip non-serializable listeners and
  10.414 +     * only serialize the serializable listeners.
  10.415 +     */
  10.416 +    private void writeObject(ObjectOutputStream s) throws IOException {
  10.417 +        Hashtable<String, VetoableChangeSupport> children = null;
  10.418 +        VetoableChangeListener[] listeners = null;
  10.419 +        synchronized (this.map) {
  10.420 +            for (Entry<String, VetoableChangeListener[]> entry : this.map.getEntries()) {
  10.421 +                String property = entry.getKey();
  10.422 +                if (property == null) {
  10.423 +                    listeners = entry.getValue();
  10.424 +                } else {
  10.425 +                    if (children == null) {
  10.426 +                        children = new Hashtable<String, VetoableChangeSupport>();
  10.427 +                    }
  10.428 +                    VetoableChangeSupport vcs = new VetoableChangeSupport(this.source);
  10.429 +                    vcs.map.set(null, entry.getValue());
  10.430 +                    children.put(property, vcs);
  10.431 +                }
  10.432 +            }
  10.433 +        }
  10.434 +        ObjectOutputStream.PutField fields = s.putFields();
  10.435 +        fields.put("children", children);
  10.436 +        fields.put("source", this.source);
  10.437 +        fields.put("vetoableChangeSupportSerializedDataVersion", 2);
  10.438 +        s.writeFields();
  10.439 +
  10.440 +        if (listeners != null) {
  10.441 +            for (VetoableChangeListener l : listeners) {
  10.442 +                if (l instanceof Serializable) {
  10.443 +                    s.writeObject(l);
  10.444 +                }
  10.445 +            }
  10.446 +        }
  10.447 +        s.writeObject(null);
  10.448 +    }
  10.449 +
  10.450 +    private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
  10.451 +        this.map = new VetoableChangeListenerMap();
  10.452 +
  10.453 +        ObjectInputStream.GetField fields = s.readFields();
  10.454 +
  10.455 +        Hashtable<String, VetoableChangeSupport> children = (Hashtable<String, VetoableChangeSupport>) fields.get("children", null);
  10.456 +        this.source = fields.get("source", null);
  10.457 +        fields.get("vetoableChangeSupportSerializedDataVersion", 2);
  10.458 +
  10.459 +        Object listenerOrNull;
  10.460 +        while (null != (listenerOrNull = s.readObject())) {
  10.461 +            this.map.add(null, (VetoableChangeListener)listenerOrNull);
  10.462 +        }
  10.463 +        if (children != null) {
  10.464 +            for (Entry<String, VetoableChangeSupport> entry : children.entrySet()) {
  10.465 +                for (VetoableChangeListener listener : entry.getValue().getVetoableChangeListeners()) {
  10.466 +                    this.map.add(entry.getKey(), listener);
  10.467 +                }
  10.468 +            }
  10.469 +        }
  10.470 +    }
  10.471 +
  10.472 +    /**
  10.473 +     * The object to be provided as the "source" for any generated events.
  10.474 +     */
  10.475 +    private Object source;
  10.476 +
  10.477 +    /**
  10.478 +     * @serialField children                                   Hashtable
  10.479 +     * @serialField source                                     Object
  10.480 +     * @serialField vetoableChangeSupportSerializedDataVersion int
  10.481 +     */
  10.482 +    private static final ObjectStreamField[] serialPersistentFields = {
  10.483 +            new ObjectStreamField("children", Hashtable.class),
  10.484 +            new ObjectStreamField("source", Object.class),
  10.485 +            new ObjectStreamField("vetoableChangeSupportSerializedDataVersion", Integer.TYPE)
  10.486 +    };
  10.487 +
  10.488 +    /**
  10.489 +     * Serialization version ID, so we're compatible with JDK 1.1
  10.490 +     */
  10.491 +    static final long serialVersionUID = -5090210921595982017L;
  10.492 +
  10.493 +    /**
  10.494 +     * This is a {@link ChangeListenerMap ChangeListenerMap} implementation
  10.495 +     * that works with {@link VetoableChangeListener VetoableChangeListener} objects.
  10.496 +     */
  10.497 +    private static final class VetoableChangeListenerMap extends ChangeListenerMap<VetoableChangeListener> {
  10.498 +        private static final VetoableChangeListener[] EMPTY = {};
  10.499 +
  10.500 +        /**
  10.501 +         * Creates an array of {@link VetoableChangeListener VetoableChangeListener} objects.
  10.502 +         * This method uses the same instance of the empty array
  10.503 +         * when {@code length} equals {@code 0}.
  10.504 +         *
  10.505 +         * @param length  the array length
  10.506 +         * @return        an array with specified length
  10.507 +         */
  10.508 +        @Override
  10.509 +        protected VetoableChangeListener[] newArray(int length) {
  10.510 +            return (0 < length)
  10.511 +                    ? new VetoableChangeListener[length]
  10.512 +                    : EMPTY;
  10.513 +        }
  10.514 +
  10.515 +        /**
  10.516 +         * Creates a {@link VetoableChangeListenerProxy VetoableChangeListenerProxy}
  10.517 +         * object for the specified property.
  10.518 +         *
  10.519 +         * @param name      the name of the property to listen on
  10.520 +         * @param listener  the listener to process events
  10.521 +         * @return          a {@code VetoableChangeListenerProxy} object
  10.522 +         */
  10.523 +        @Override
  10.524 +        protected VetoableChangeListener newProxy(String name, VetoableChangeListener listener) {
  10.525 +            return new VetoableChangeListenerProxy(name, listener);
  10.526 +        }
  10.527 +    }
  10.528 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/emul/compact/src/main/java/java/io/Bits.java	Mon Jan 28 18:14:14 2013 +0100
    11.3 @@ -0,0 +1,123 @@
    11.4 +/*
    11.5 + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
    11.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    11.7 + *
    11.8 + * This code is free software; you can redistribute it and/or modify it
    11.9 + * under the terms of the GNU General Public License version 2 only, as
   11.10 + * published by the Free Software Foundation.  Oracle designates this
   11.11 + * particular file as subject to the "Classpath" exception as provided
   11.12 + * by Oracle in the LICENSE file that accompanied this code.
   11.13 + *
   11.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   11.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   11.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   11.17 + * version 2 for more details (a copy is included in the LICENSE file that
   11.18 + * accompanied this code).
   11.19 + *
   11.20 + * You should have received a copy of the GNU General Public License version
   11.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   11.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   11.23 + *
   11.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   11.25 + * or visit www.oracle.com if you need additional information or have any
   11.26 + * questions.
   11.27 + */
   11.28 +
   11.29 +package java.io;
   11.30 +
   11.31 +/**
   11.32 + * Utility methods for packing/unpacking primitive values in/out of byte arrays
   11.33 + * using big-endian byte ordering.
   11.34 + */
   11.35 +class Bits {
   11.36 +
   11.37 +    /*
   11.38 +     * Methods for unpacking primitive values from byte arrays starting at
   11.39 +     * given offsets.
   11.40 +     */
   11.41 +
   11.42 +    static boolean getBoolean(byte[] b, int off) {
   11.43 +        return b[off] != 0;
   11.44 +    }
   11.45 +
   11.46 +    static char getChar(byte[] b, int off) {
   11.47 +        return (char) ((b[off + 1] & 0xFF) +
   11.48 +                       (b[off] << 8));
   11.49 +    }
   11.50 +
   11.51 +    static short getShort(byte[] b, int off) {
   11.52 +        return (short) ((b[off + 1] & 0xFF) +
   11.53 +                        (b[off] << 8));
   11.54 +    }
   11.55 +
   11.56 +    static int getInt(byte[] b, int off) {
   11.57 +        return ((b[off + 3] & 0xFF)      ) +
   11.58 +               ((b[off + 2] & 0xFF) <<  8) +
   11.59 +               ((b[off + 1] & 0xFF) << 16) +
   11.60 +               ((b[off    ]       ) << 24);
   11.61 +    }
   11.62 +
   11.63 +    static float getFloat(byte[] b, int off) {
   11.64 +        return Float.intBitsToFloat(getInt(b, off));
   11.65 +    }
   11.66 +
   11.67 +    static long getLong(byte[] b, int off) {
   11.68 +        return ((b[off + 7] & 0xFFL)      ) +
   11.69 +               ((b[off + 6] & 0xFFL) <<  8) +
   11.70 +               ((b[off + 5] & 0xFFL) << 16) +
   11.71 +               ((b[off + 4] & 0xFFL) << 24) +
   11.72 +               ((b[off + 3] & 0xFFL) << 32) +
   11.73 +               ((b[off + 2] & 0xFFL) << 40) +
   11.74 +               ((b[off + 1] & 0xFFL) << 48) +
   11.75 +               (((long) b[off])      << 56);
   11.76 +    }
   11.77 +
   11.78 +    static double getDouble(byte[] b, int off) {
   11.79 +        return Double.longBitsToDouble(getLong(b, off));
   11.80 +    }
   11.81 +
   11.82 +    /*
   11.83 +     * Methods for packing primitive values into byte arrays starting at given
   11.84 +     * offsets.
   11.85 +     */
   11.86 +
   11.87 +    static void putBoolean(byte[] b, int off, boolean val) {
   11.88 +        b[off] = (byte) (val ? 1 : 0);
   11.89 +    }
   11.90 +
   11.91 +    static void putChar(byte[] b, int off, char val) {
   11.92 +        b[off + 1] = (byte) (val      );
   11.93 +        b[off    ] = (byte) (val >>> 8);
   11.94 +    }
   11.95 +
   11.96 +    static void putShort(byte[] b, int off, short val) {
   11.97 +        b[off + 1] = (byte) (val      );
   11.98 +        b[off    ] = (byte) (val >>> 8);
   11.99 +    }
  11.100 +
  11.101 +    static void putInt(byte[] b, int off, int val) {
  11.102 +        b[off + 3] = (byte) (val       );
  11.103 +        b[off + 2] = (byte) (val >>>  8);
  11.104 +        b[off + 1] = (byte) (val >>> 16);
  11.105 +        b[off    ] = (byte) (val >>> 24);
  11.106 +    }
  11.107 +
  11.108 +    static void putFloat(byte[] b, int off, float val) {
  11.109 +        putInt(b, off,  Float.floatToIntBits(val));
  11.110 +    }
  11.111 +
  11.112 +    static void putLong(byte[] b, int off, long val) {
  11.113 +        b[off + 7] = (byte) (val       );
  11.114 +        b[off + 6] = (byte) (val >>>  8);
  11.115 +        b[off + 5] = (byte) (val >>> 16);
  11.116 +        b[off + 4] = (byte) (val >>> 24);
  11.117 +        b[off + 3] = (byte) (val >>> 32);
  11.118 +        b[off + 2] = (byte) (val >>> 40);
  11.119 +        b[off + 1] = (byte) (val >>> 48);
  11.120 +        b[off    ] = (byte) (val >>> 56);
  11.121 +    }
  11.122 +
  11.123 +    static void putDouble(byte[] b, int off, double val) {
  11.124 +        putLong(b, off, Double.doubleToLongBits(val));
  11.125 +    }
  11.126 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/emul/compact/src/main/java/java/io/DataOutput.java	Mon Jan 28 18:14:14 2013 +0100
    12.3 @@ -0,0 +1,354 @@
    12.4 +/*
    12.5 + * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved.
    12.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    12.7 + *
    12.8 + * This code is free software; you can redistribute it and/or modify it
    12.9 + * under the terms of the GNU General Public License version 2 only, as
   12.10 + * published by the Free Software Foundation.  Oracle designates this
   12.11 + * particular file as subject to the "Classpath" exception as provided
   12.12 + * by Oracle in the LICENSE file that accompanied this code.
   12.13 + *
   12.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   12.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   12.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   12.17 + * version 2 for more details (a copy is included in the LICENSE file that
   12.18 + * accompanied this code).
   12.19 + *
   12.20 + * You should have received a copy of the GNU General Public License version
   12.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   12.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   12.23 + *
   12.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   12.25 + * or visit www.oracle.com if you need additional information or have any
   12.26 + * questions.
   12.27 + */
   12.28 +
   12.29 +package java.io;
   12.30 +
   12.31 +/**
   12.32 + * The <code>DataOutput</code> interface provides
   12.33 + * for converting data from any of the Java
   12.34 + * primitive types to a series of bytes and
   12.35 + * writing these bytes to a binary stream.
   12.36 + * There is  also a facility for converting
   12.37 + * a <code>String</code> into
   12.38 + * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
   12.39 + * format and writing the resulting series
   12.40 + * of bytes.
   12.41 + * <p>
   12.42 + * For all the methods in this interface that
   12.43 + * write bytes, it is generally true that if
   12.44 + * a byte cannot be written for any reason,
   12.45 + * an <code>IOException</code> is thrown.
   12.46 + *
   12.47 + * @author  Frank Yellin
   12.48 + * @see     java.io.DataInput
   12.49 + * @see     java.io.DataOutputStream
   12.50 + * @since   JDK1.0
   12.51 + */
   12.52 +public
   12.53 +interface DataOutput {
   12.54 +    /**
   12.55 +     * Writes to the output stream the eight
   12.56 +     * low-order bits of the argument <code>b</code>.
   12.57 +     * The 24 high-order  bits of <code>b</code>
   12.58 +     * are ignored.
   12.59 +     *
   12.60 +     * @param      b   the byte to be written.
   12.61 +     * @throws     IOException  if an I/O error occurs.
   12.62 +     */
   12.63 +    void write(int b) throws IOException;
   12.64 +
   12.65 +    /**
   12.66 +     * Writes to the output stream all the bytes in array <code>b</code>.
   12.67 +     * If <code>b</code> is <code>null</code>,
   12.68 +     * a <code>NullPointerException</code> is thrown.
   12.69 +     * If <code>b.length</code> is zero, then
   12.70 +     * no bytes are written. Otherwise, the byte
   12.71 +     * <code>b[0]</code> is written first, then
   12.72 +     * <code>b[1]</code>, and so on; the last byte
   12.73 +     * written is <code>b[b.length-1]</code>.
   12.74 +     *
   12.75 +     * @param      b   the data.
   12.76 +     * @throws     IOException  if an I/O error occurs.
   12.77 +     */
   12.78 +    void write(byte b[]) throws IOException;
   12.79 +
   12.80 +    /**
   12.81 +     * Writes <code>len</code> bytes from array
   12.82 +     * <code>b</code>, in order,  to
   12.83 +     * the output stream.  If <code>b</code>
   12.84 +     * is <code>null</code>, a <code>NullPointerException</code>
   12.85 +     * is thrown.  If <code>off</code> is negative,
   12.86 +     * or <code>len</code> is negative, or <code>off+len</code>
   12.87 +     * is greater than the length of the array
   12.88 +     * <code>b</code>, then an <code>IndexOutOfBoundsException</code>
   12.89 +     * is thrown.  If <code>len</code> is zero,
   12.90 +     * then no bytes are written. Otherwise, the
   12.91 +     * byte <code>b[off]</code> is written first,
   12.92 +     * then <code>b[off+1]</code>, and so on; the
   12.93 +     * last byte written is <code>b[off+len-1]</code>.
   12.94 +     *
   12.95 +     * @param      b     the data.
   12.96 +     * @param      off   the start offset in the data.
   12.97 +     * @param      len   the number of bytes to write.
   12.98 +     * @throws     IOException  if an I/O error occurs.
   12.99 +     */
  12.100 +    void write(byte b[], int off, int len) throws IOException;
  12.101 +
  12.102 +    /**
  12.103 +     * Writes a <code>boolean</code> value to this output stream.
  12.104 +     * If the argument <code>v</code>
  12.105 +     * is <code>true</code>, the value <code>(byte)1</code>
  12.106 +     * is written; if <code>v</code> is <code>false</code>,
  12.107 +     * the  value <code>(byte)0</code> is written.
  12.108 +     * The byte written by this method may
  12.109 +     * be read by the <code>readBoolean</code>
  12.110 +     * method of interface <code>DataInput</code>,
  12.111 +     * which will then return a <code>boolean</code>
  12.112 +     * equal to <code>v</code>.
  12.113 +     *
  12.114 +     * @param      v   the boolean to be written.
  12.115 +     * @throws     IOException  if an I/O error occurs.
  12.116 +     */
  12.117 +    void writeBoolean(boolean v) throws IOException;
  12.118 +
  12.119 +    /**
  12.120 +     * Writes to the output stream the eight low-
  12.121 +     * order bits of the argument <code>v</code>.
  12.122 +     * The 24 high-order bits of <code>v</code>
  12.123 +     * are ignored. (This means  that <code>writeByte</code>
  12.124 +     * does exactly the same thing as <code>write</code>
  12.125 +     * for an integer argument.) The byte written
  12.126 +     * by this method may be read by the <code>readByte</code>
  12.127 +     * method of interface <code>DataInput</code>,
  12.128 +     * which will then return a <code>byte</code>
  12.129 +     * equal to <code>(byte)v</code>.
  12.130 +     *
  12.131 +     * @param      v   the byte value to be written.
  12.132 +     * @throws     IOException  if an I/O error occurs.
  12.133 +     */
  12.134 +    void writeByte(int v) throws IOException;
  12.135 +
  12.136 +    /**
  12.137 +     * Writes two bytes to the output
  12.138 +     * stream to represent the value of the argument.
  12.139 +     * The byte values to be written, in the  order
  12.140 +     * shown, are: <p>
  12.141 +     * <pre><code>
  12.142 +     * (byte)(0xff &amp; (v &gt;&gt; 8))
  12.143 +     * (byte)(0xff &amp; v)
  12.144 +     * </code> </pre> <p>
  12.145 +     * The bytes written by this method may be
  12.146 +     * read by the <code>readShort</code> method
  12.147 +     * of interface <code>DataInput</code> , which
  12.148 +     * will then return a <code>short</code> equal
  12.149 +     * to <code>(short)v</code>.
  12.150 +     *
  12.151 +     * @param      v   the <code>short</code> value to be written.
  12.152 +     * @throws     IOException  if an I/O error occurs.
  12.153 +     */
  12.154 +    void writeShort(int v) throws IOException;
  12.155 +
  12.156 +    /**
  12.157 +     * Writes a <code>char</code> value, which
  12.158 +     * is comprised of two bytes, to the
  12.159 +     * output stream.
  12.160 +     * The byte values to be written, in the  order
  12.161 +     * shown, are:
  12.162 +     * <p><pre><code>
  12.163 +     * (byte)(0xff &amp; (v &gt;&gt; 8))
  12.164 +     * (byte)(0xff &amp; v)
  12.165 +     * </code></pre><p>
  12.166 +     * The bytes written by this method may be
  12.167 +     * read by the <code>readChar</code> method
  12.168 +     * of interface <code>DataInput</code> , which
  12.169 +     * will then return a <code>char</code> equal
  12.170 +     * to <code>(char)v</code>.
  12.171 +     *
  12.172 +     * @param      v   the <code>char</code> value to be written.
  12.173 +     * @throws     IOException  if an I/O error occurs.
  12.174 +     */
  12.175 +    void writeChar(int v) throws IOException;
  12.176 +
  12.177 +    /**
  12.178 +     * Writes an <code>int</code> value, which is
  12.179 +     * comprised of four bytes, to the output stream.
  12.180 +     * The byte values to be written, in the  order
  12.181 +     * shown, are:
  12.182 +     * <p><pre><code>
  12.183 +     * (byte)(0xff &amp; (v &gt;&gt; 24))
  12.184 +     * (byte)(0xff &amp; (v &gt;&gt; 16))
  12.185 +     * (byte)(0xff &amp; (v &gt;&gt; &#32; &#32;8))
  12.186 +     * (byte)(0xff &amp; v)
  12.187 +     * </code></pre><p>
  12.188 +     * The bytes written by this method may be read
  12.189 +     * by the <code>readInt</code> method of interface
  12.190 +     * <code>DataInput</code> , which will then
  12.191 +     * return an <code>int</code> equal to <code>v</code>.
  12.192 +     *
  12.193 +     * @param      v   the <code>int</code> value to be written.
  12.194 +     * @throws     IOException  if an I/O error occurs.
  12.195 +     */
  12.196 +    void writeInt(int v) throws IOException;
  12.197 +
  12.198 +    /**
  12.199 +     * Writes a <code>long</code> value, which is
  12.200 +     * comprised of eight bytes, to the output stream.
  12.201 +     * The byte values to be written, in the  order
  12.202 +     * shown, are:
  12.203 +     * <p><pre><code>
  12.204 +     * (byte)(0xff &amp; (v &gt;&gt; 56))
  12.205 +     * (byte)(0xff &amp; (v &gt;&gt; 48))
  12.206 +     * (byte)(0xff &amp; (v &gt;&gt; 40))
  12.207 +     * (byte)(0xff &amp; (v &gt;&gt; 32))
  12.208 +     * (byte)(0xff &amp; (v &gt;&gt; 24))
  12.209 +     * (byte)(0xff &amp; (v &gt;&gt; 16))
  12.210 +     * (byte)(0xff &amp; (v &gt;&gt;  8))
  12.211 +     * (byte)(0xff &amp; v)
  12.212 +     * </code></pre><p>
  12.213 +     * The bytes written by this method may be
  12.214 +     * read by the <code>readLong</code> method
  12.215 +     * of interface <code>DataInput</code> , which
  12.216 +     * will then return a <code>long</code> equal
  12.217 +     * to <code>v</code>.
  12.218 +     *
  12.219 +     * @param      v   the <code>long</code> value to be written.
  12.220 +     * @throws     IOException  if an I/O error occurs.
  12.221 +     */
  12.222 +    void writeLong(long v) throws IOException;
  12.223 +
  12.224 +    /**
  12.225 +     * Writes a <code>float</code> value,
  12.226 +     * which is comprised of four bytes, to the output stream.
  12.227 +     * It does this as if it first converts this
  12.228 +     * <code>float</code> value to an <code>int</code>
  12.229 +     * in exactly the manner of the <code>Float.floatToIntBits</code>
  12.230 +     * method  and then writes the <code>int</code>
  12.231 +     * value in exactly the manner of the  <code>writeInt</code>
  12.232 +     * method.  The bytes written by this method
  12.233 +     * may be read by the <code>readFloat</code>
  12.234 +     * method of interface <code>DataInput</code>,
  12.235 +     * which will then return a <code>float</code>
  12.236 +     * equal to <code>v</code>.
  12.237 +     *
  12.238 +     * @param      v   the <code>float</code> value to be written.
  12.239 +     * @throws     IOException  if an I/O error occurs.
  12.240 +     */
  12.241 +    void writeFloat(float v) throws IOException;
  12.242 +
  12.243 +    /**
  12.244 +     * Writes a <code>double</code> value,
  12.245 +     * which is comprised of eight bytes, to the output stream.
  12.246 +     * It does this as if it first converts this
  12.247 +     * <code>double</code> value to a <code>long</code>
  12.248 +     * in exactly the manner of the <code>Double.doubleToLongBits</code>
  12.249 +     * method  and then writes the <code>long</code>
  12.250 +     * value in exactly the manner of the  <code>writeLong</code>
  12.251 +     * method. The bytes written by this method
  12.252 +     * may be read by the <code>readDouble</code>
  12.253 +     * method of interface <code>DataInput</code>,
  12.254 +     * which will then return a <code>double</code>
  12.255 +     * equal to <code>v</code>.
  12.256 +     *
  12.257 +     * @param      v   the <code>double</code> value to be written.
  12.258 +     * @throws     IOException  if an I/O error occurs.
  12.259 +     */
  12.260 +    void writeDouble(double v) throws IOException;
  12.261 +
  12.262 +    /**
  12.263 +     * Writes a string to the output stream.
  12.264 +     * For every character in the string
  12.265 +     * <code>s</code>,  taken in order, one byte
  12.266 +     * is written to the output stream.  If
  12.267 +     * <code>s</code> is <code>null</code>, a <code>NullPointerException</code>
  12.268 +     * is thrown.<p>  If <code>s.length</code>
  12.269 +     * is zero, then no bytes are written. Otherwise,
  12.270 +     * the character <code>s[0]</code> is written
  12.271 +     * first, then <code>s[1]</code>, and so on;
  12.272 +     * the last character written is <code>s[s.length-1]</code>.
  12.273 +     * For each character, one byte is written,
  12.274 +     * the low-order byte, in exactly the manner
  12.275 +     * of the <code>writeByte</code> method . The
  12.276 +     * high-order eight bits of each character
  12.277 +     * in the string are ignored.
  12.278 +     *
  12.279 +     * @param      s   the string of bytes to be written.
  12.280 +     * @throws     IOException  if an I/O error occurs.
  12.281 +     */
  12.282 +    void writeBytes(String s) throws IOException;
  12.283 +
  12.284 +    /**
  12.285 +     * Writes every character in the string <code>s</code>,
  12.286 +     * to the output stream, in order,
  12.287 +     * two bytes per character. If <code>s</code>
  12.288 +     * is <code>null</code>, a <code>NullPointerException</code>
  12.289 +     * is thrown.  If <code>s.length</code>
  12.290 +     * is zero, then no characters are written.
  12.291 +     * Otherwise, the character <code>s[0]</code>
  12.292 +     * is written first, then <code>s[1]</code>,
  12.293 +     * and so on; the last character written is
  12.294 +     * <code>s[s.length-1]</code>. For each character,
  12.295 +     * two bytes are actually written, high-order
  12.296 +     * byte first, in exactly the manner of the
  12.297 +     * <code>writeChar</code> method.
  12.298 +     *
  12.299 +     * @param      s   the string value to be written.
  12.300 +     * @throws     IOException  if an I/O error occurs.
  12.301 +     */
  12.302 +    void writeChars(String s) throws IOException;
  12.303 +
  12.304 +    /**
  12.305 +     * Writes two bytes of length information
  12.306 +     * to the output stream, followed
  12.307 +     * by the
  12.308 +     * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
  12.309 +     * representation
  12.310 +     * of  every character in the string <code>s</code>.
  12.311 +     * If <code>s</code> is <code>null</code>,
  12.312 +     * a <code>NullPointerException</code> is thrown.
  12.313 +     * Each character in the string <code>s</code>
  12.314 +     * is converted to a group of one, two, or
  12.315 +     * three bytes, depending on the value of the
  12.316 +     * character.<p>
  12.317 +     * If a character <code>c</code>
  12.318 +     * is in the range <code>&#92;u0001</code> through
  12.319 +     * <code>&#92;u007f</code>, it is represented
  12.320 +     * by one byte:<p>
  12.321 +     * <pre>(byte)c </pre>  <p>
  12.322 +     * If a character <code>c</code> is <code>&#92;u0000</code>
  12.323 +     * or is in the range <code>&#92;u0080</code>
  12.324 +     * through <code>&#92;u07ff</code>, then it is
  12.325 +     * represented by two bytes, to be written
  12.326 +     * in the order shown:<p> <pre><code>
  12.327 +     * (byte)(0xc0 | (0x1f &amp; (c &gt;&gt; 6)))
  12.328 +     * (byte)(0x80 | (0x3f &amp; c))
  12.329 +     *  </code></pre>  <p> If a character
  12.330 +     * <code>c</code> is in the range <code>&#92;u0800</code>
  12.331 +     * through <code>uffff</code>, then it is
  12.332 +     * represented by three bytes, to be written
  12.333 +     * in the order shown:<p> <pre><code>
  12.334 +     * (byte)(0xe0 | (0x0f &amp; (c &gt;&gt; 12)))
  12.335 +     * (byte)(0x80 | (0x3f &amp; (c &gt;&gt;  6)))
  12.336 +     * (byte)(0x80 | (0x3f &amp; c))
  12.337 +     *  </code></pre>  <p> First,
  12.338 +     * the total number of bytes needed to represent
  12.339 +     * all the characters of <code>s</code> is
  12.340 +     * calculated. If this number is larger than
  12.341 +     * <code>65535</code>, then a <code>UTFDataFormatException</code>
  12.342 +     * is thrown. Otherwise, this length is written
  12.343 +     * to the output stream in exactly the manner
  12.344 +     * of the <code>writeShort</code> method;
  12.345 +     * after this, the one-, two-, or three-byte
  12.346 +     * representation of each character in the
  12.347 +     * string <code>s</code> is written.<p>  The
  12.348 +     * bytes written by this method may be read
  12.349 +     * by the <code>readUTF</code> method of interface
  12.350 +     * <code>DataInput</code> , which will then
  12.351 +     * return a <code>String</code> equal to <code>s</code>.
  12.352 +     *
  12.353 +     * @param      s   the string value to be written.
  12.354 +     * @throws     IOException  if an I/O error occurs.
  12.355 +     */
  12.356 +    void writeUTF(String s) throws IOException;
  12.357 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/emul/compact/src/main/java/java/io/DataOutputStream.java	Mon Jan 28 18:14:14 2013 +0100
    13.3 @@ -0,0 +1,416 @@
    13.4 +/*
    13.5 + * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.
    13.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    13.7 + *
    13.8 + * This code is free software; you can redistribute it and/or modify it
    13.9 + * under the terms of the GNU General Public License version 2 only, as
   13.10 + * published by the Free Software Foundation.  Oracle designates this
   13.11 + * particular file as subject to the "Classpath" exception as provided
   13.12 + * by Oracle in the LICENSE file that accompanied this code.
   13.13 + *
   13.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   13.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   13.17 + * version 2 for more details (a copy is included in the LICENSE file that
   13.18 + * accompanied this code).
   13.19 + *
   13.20 + * You should have received a copy of the GNU General Public License version
   13.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   13.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   13.23 + *
   13.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   13.25 + * or visit www.oracle.com if you need additional information or have any
   13.26 + * questions.
   13.27 + */
   13.28 +
   13.29 +package java.io;
   13.30 +
   13.31 +/**
   13.32 + * A data output stream lets an application write primitive Java data
   13.33 + * types to an output stream in a portable way. An application can
   13.34 + * then use a data input stream to read the data back in.
   13.35 + *
   13.36 + * @author  unascribed
   13.37 + * @see     java.io.DataInputStream
   13.38 + * @since   JDK1.0
   13.39 + */
   13.40 +public
   13.41 +class DataOutputStream extends FilterOutputStream implements DataOutput {
   13.42 +    /**
   13.43 +     * The number of bytes written to the data output stream so far.
   13.44 +     * If this counter overflows, it will be wrapped to Integer.MAX_VALUE.
   13.45 +     */
   13.46 +    protected int written;
   13.47 +
   13.48 +    /**
   13.49 +     * bytearr is initialized on demand by writeUTF
   13.50 +     */
   13.51 +    private byte[] bytearr = null;
   13.52 +
   13.53 +    /**
   13.54 +     * Creates a new data output stream to write data to the specified
   13.55 +     * underlying output stream. The counter <code>written</code> is
   13.56 +     * set to zero.
   13.57 +     *
   13.58 +     * @param   out   the underlying output stream, to be saved for later
   13.59 +     *                use.
   13.60 +     * @see     java.io.FilterOutputStream#out
   13.61 +     */
   13.62 +    public DataOutputStream(OutputStream out) {
   13.63 +        super(out);
   13.64 +    }
   13.65 +
   13.66 +    /**
   13.67 +     * Increases the written counter by the specified value
   13.68 +     * until it reaches Integer.MAX_VALUE.
   13.69 +     */
   13.70 +    private void incCount(int value) {
   13.71 +        int temp = written + value;
   13.72 +        if (temp < 0) {
   13.73 +            temp = Integer.MAX_VALUE;
   13.74 +        }
   13.75 +        written = temp;
   13.76 +    }
   13.77 +
   13.78 +    /**
   13.79 +     * Writes the specified byte (the low eight bits of the argument
   13.80 +     * <code>b</code>) to the underlying output stream. If no exception
   13.81 +     * is thrown, the counter <code>written</code> is incremented by
   13.82 +     * <code>1</code>.
   13.83 +     * <p>
   13.84 +     * Implements the <code>write</code> method of <code>OutputStream</code>.
   13.85 +     *
   13.86 +     * @param      b   the <code>byte</code> to be written.
   13.87 +     * @exception  IOException  if an I/O error occurs.
   13.88 +     * @see        java.io.FilterOutputStream#out
   13.89 +     */
   13.90 +    public synchronized void write(int b) throws IOException {
   13.91 +        out.write(b);
   13.92 +        incCount(1);
   13.93 +    }
   13.94 +
   13.95 +    /**
   13.96 +     * Writes <code>len</code> bytes from the specified byte array
   13.97 +     * starting at offset <code>off</code> to the underlying output stream.
   13.98 +     * If no exception is thrown, the counter <code>written</code> is
   13.99 +     * incremented by <code>len</code>.
  13.100 +     *
  13.101 +     * @param      b     the data.
  13.102 +     * @param      off   the start offset in the data.
  13.103 +     * @param      len   the number of bytes to write.
  13.104 +     * @exception  IOException  if an I/O error occurs.
  13.105 +     * @see        java.io.FilterOutputStream#out
  13.106 +     */
  13.107 +    public synchronized void write(byte b[], int off, int len)
  13.108 +        throws IOException
  13.109 +    {
  13.110 +        out.write(b, off, len);
  13.111 +        incCount(len);
  13.112 +    }
  13.113 +
  13.114 +    /**
  13.115 +     * Flushes this data output stream. This forces any buffered output
  13.116 +     * bytes to be written out to the stream.
  13.117 +     * <p>
  13.118 +     * The <code>flush</code> method of <code>DataOutputStream</code>
  13.119 +     * calls the <code>flush</code> method of its underlying output stream.
  13.120 +     *
  13.121 +     * @exception  IOException  if an I/O error occurs.
  13.122 +     * @see        java.io.FilterOutputStream#out
  13.123 +     * @see        java.io.OutputStream#flush()
  13.124 +     */
  13.125 +    public void flush() throws IOException {
  13.126 +        out.flush();
  13.127 +    }
  13.128 +
  13.129 +    /**
  13.130 +     * Writes a <code>boolean</code> to the underlying output stream as
  13.131 +     * a 1-byte value. The value <code>true</code> is written out as the
  13.132 +     * value <code>(byte)1</code>; the value <code>false</code> is
  13.133 +     * written out as the value <code>(byte)0</code>. If no exception is
  13.134 +     * thrown, the counter <code>written</code> is incremented by
  13.135 +     * <code>1</code>.
  13.136 +     *
  13.137 +     * @param      v   a <code>boolean</code> value to be written.
  13.138 +     * @exception  IOException  if an I/O error occurs.
  13.139 +     * @see        java.io.FilterOutputStream#out
  13.140 +     */
  13.141 +    public final void writeBoolean(boolean v) throws IOException {
  13.142 +        out.write(v ? 1 : 0);
  13.143 +        incCount(1);
  13.144 +    }
  13.145 +
  13.146 +    /**
  13.147 +     * Writes out a <code>byte</code> to the underlying output stream as
  13.148 +     * a 1-byte value. If no exception is thrown, the counter
  13.149 +     * <code>written</code> is incremented by <code>1</code>.
  13.150 +     *
  13.151 +     * @param      v   a <code>byte</code> value to be written.
  13.152 +     * @exception  IOException  if an I/O error occurs.
  13.153 +     * @see        java.io.FilterOutputStream#out
  13.154 +     */
  13.155 +    public final void writeByte(int v) throws IOException {
  13.156 +        out.write(v);
  13.157 +        incCount(1);
  13.158 +    }
  13.159 +
  13.160 +    /**
  13.161 +     * Writes a <code>short</code> to the underlying output stream as two
  13.162 +     * bytes, high byte first. If no exception is thrown, the counter
  13.163 +     * <code>written</code> is incremented by <code>2</code>.
  13.164 +     *
  13.165 +     * @param      v   a <code>short</code> to be written.
  13.166 +     * @exception  IOException  if an I/O error occurs.
  13.167 +     * @see        java.io.FilterOutputStream#out
  13.168 +     */
  13.169 +    public final void writeShort(int v) throws IOException {
  13.170 +        out.write((v >>> 8) & 0xFF);
  13.171 +        out.write((v >>> 0) & 0xFF);
  13.172 +        incCount(2);
  13.173 +    }
  13.174 +
  13.175 +    /**
  13.176 +     * Writes a <code>char</code> to the underlying output stream as a
  13.177 +     * 2-byte value, high byte first. If no exception is thrown, the
  13.178 +     * counter <code>written</code> is incremented by <code>2</code>.
  13.179 +     *
  13.180 +     * @param      v   a <code>char</code> value to be written.
  13.181 +     * @exception  IOException  if an I/O error occurs.
  13.182 +     * @see        java.io.FilterOutputStream#out
  13.183 +     */
  13.184 +    public final void writeChar(int v) throws IOException {
  13.185 +        out.write((v >>> 8) & 0xFF);
  13.186 +        out.write((v >>> 0) & 0xFF);
  13.187 +        incCount(2);
  13.188 +    }
  13.189 +
  13.190 +    /**
  13.191 +     * Writes an <code>int</code> to the underlying output stream as four
  13.192 +     * bytes, high byte first. If no exception is thrown, the counter
  13.193 +     * <code>written</code> is incremented by <code>4</code>.
  13.194 +     *
  13.195 +     * @param      v   an <code>int</code> to be written.
  13.196 +     * @exception  IOException  if an I/O error occurs.
  13.197 +     * @see        java.io.FilterOutputStream#out
  13.198 +     */
  13.199 +    public final void writeInt(int v) throws IOException {
  13.200 +        out.write((v >>> 24) & 0xFF);
  13.201 +        out.write((v >>> 16) & 0xFF);
  13.202 +        out.write((v >>>  8) & 0xFF);
  13.203 +        out.write((v >>>  0) & 0xFF);
  13.204 +        incCount(4);
  13.205 +    }
  13.206 +
  13.207 +    private byte writeBuffer[] = new byte[8];
  13.208 +
  13.209 +    /**
  13.210 +     * Writes a <code>long</code> to the underlying output stream as eight
  13.211 +     * bytes, high byte first. In no exception is thrown, the counter
  13.212 +     * <code>written</code> is incremented by <code>8</code>.
  13.213 +     *
  13.214 +     * @param      v   a <code>long</code> to be written.
  13.215 +     * @exception  IOException  if an I/O error occurs.
  13.216 +     * @see        java.io.FilterOutputStream#out
  13.217 +     */
  13.218 +    public final void writeLong(long v) throws IOException {
  13.219 +        writeBuffer[0] = (byte)(v >>> 56);
  13.220 +        writeBuffer[1] = (byte)(v >>> 48);
  13.221 +        writeBuffer[2] = (byte)(v >>> 40);
  13.222 +        writeBuffer[3] = (byte)(v >>> 32);
  13.223 +        writeBuffer[4] = (byte)(v >>> 24);
  13.224 +        writeBuffer[5] = (byte)(v >>> 16);
  13.225 +        writeBuffer[6] = (byte)(v >>>  8);
  13.226 +        writeBuffer[7] = (byte)(v >>>  0);
  13.227 +        out.write(writeBuffer, 0, 8);
  13.228 +        incCount(8);
  13.229 +    }
  13.230 +
  13.231 +    /**
  13.232 +     * Converts the float argument to an <code>int</code> using the
  13.233 +     * <code>floatToIntBits</code> method in class <code>Float</code>,
  13.234 +     * and then writes that <code>int</code> value to the underlying
  13.235 +     * output stream as a 4-byte quantity, high byte first. If no
  13.236 +     * exception is thrown, the counter <code>written</code> is
  13.237 +     * incremented by <code>4</code>.
  13.238 +     *
  13.239 +     * @param      v   a <code>float</code> value to be written.
  13.240 +     * @exception  IOException  if an I/O error occurs.
  13.241 +     * @see        java.io.FilterOutputStream#out
  13.242 +     * @see        java.lang.Float#floatToIntBits(float)
  13.243 +     */
  13.244 +    public final void writeFloat(float v) throws IOException {
  13.245 +        writeInt(Float.floatToIntBits(v));
  13.246 +    }
  13.247 +
  13.248 +    /**
  13.249 +     * Converts the double argument to a <code>long</code> using the
  13.250 +     * <code>doubleToLongBits</code> method in class <code>Double</code>,
  13.251 +     * and then writes that <code>long</code> value to the underlying
  13.252 +     * output stream as an 8-byte quantity, high byte first. If no
  13.253 +     * exception is thrown, the counter <code>written</code> is
  13.254 +     * incremented by <code>8</code>.
  13.255 +     *
  13.256 +     * @param      v   a <code>double</code> value to be written.
  13.257 +     * @exception  IOException  if an I/O error occurs.
  13.258 +     * @see        java.io.FilterOutputStream#out
  13.259 +     * @see        java.lang.Double#doubleToLongBits(double)
  13.260 +     */
  13.261 +    public final void writeDouble(double v) throws IOException {
  13.262 +        writeLong(Double.doubleToLongBits(v));
  13.263 +    }
  13.264 +
  13.265 +    /**
  13.266 +     * Writes out the string to the underlying output stream as a
  13.267 +     * sequence of bytes. Each character in the string is written out, in
  13.268 +     * sequence, by discarding its high eight bits. If no exception is
  13.269 +     * thrown, the counter <code>written</code> is incremented by the
  13.270 +     * length of <code>s</code>.
  13.271 +     *
  13.272 +     * @param      s   a string of bytes to be written.
  13.273 +     * @exception  IOException  if an I/O error occurs.
  13.274 +     * @see        java.io.FilterOutputStream#out
  13.275 +     */
  13.276 +    public final void writeBytes(String s) throws IOException {
  13.277 +        int len = s.length();
  13.278 +        for (int i = 0 ; i < len ; i++) {
  13.279 +            out.write((byte)s.charAt(i));
  13.280 +        }
  13.281 +        incCount(len);
  13.282 +    }
  13.283 +
  13.284 +    /**
  13.285 +     * Writes a string to the underlying output stream as a sequence of
  13.286 +     * characters. Each character is written to the data output stream as
  13.287 +     * if by the <code>writeChar</code> method. If no exception is
  13.288 +     * thrown, the counter <code>written</code> is incremented by twice
  13.289 +     * the length of <code>s</code>.
  13.290 +     *
  13.291 +     * @param      s   a <code>String</code> value to be written.
  13.292 +     * @exception  IOException  if an I/O error occurs.
  13.293 +     * @see        java.io.DataOutputStream#writeChar(int)
  13.294 +     * @see        java.io.FilterOutputStream#out
  13.295 +     */
  13.296 +    public final void writeChars(String s) throws IOException {
  13.297 +        int len = s.length();
  13.298 +        for (int i = 0 ; i < len ; i++) {
  13.299 +            int v = s.charAt(i);
  13.300 +            out.write((v >>> 8) & 0xFF);
  13.301 +            out.write((v >>> 0) & 0xFF);
  13.302 +        }
  13.303 +        incCount(len * 2);
  13.304 +    }
  13.305 +
  13.306 +    /**
  13.307 +     * Writes a string to the underlying output stream using
  13.308 +     * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
  13.309 +     * encoding in a machine-independent manner.
  13.310 +     * <p>
  13.311 +     * First, two bytes are written to the output stream as if by the
  13.312 +     * <code>writeShort</code> method giving the number of bytes to
  13.313 +     * follow. This value is the number of bytes actually written out,
  13.314 +     * not the length of the string. Following the length, each character
  13.315 +     * of the string is output, in sequence, using the modified UTF-8 encoding
  13.316 +     * for the character. If no exception is thrown, the counter
  13.317 +     * <code>written</code> is incremented by the total number of
  13.318 +     * bytes written to the output stream. This will be at least two
  13.319 +     * plus the length of <code>str</code>, and at most two plus
  13.320 +     * thrice the length of <code>str</code>.
  13.321 +     *
  13.322 +     * @param      str   a string to be written.
  13.323 +     * @exception  IOException  if an I/O error occurs.
  13.324 +     */
  13.325 +    public final void writeUTF(String str) throws IOException {
  13.326 +        writeUTF(str, this);
  13.327 +    }
  13.328 +
  13.329 +    /**
  13.330 +     * Writes a string to the specified DataOutput using
  13.331 +     * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
  13.332 +     * encoding in a machine-independent manner.
  13.333 +     * <p>
  13.334 +     * First, two bytes are written to out as if by the <code>writeShort</code>
  13.335 +     * method giving the number of bytes to follow. This value is the number of
  13.336 +     * bytes actually written out, not the length of the string. Following the
  13.337 +     * length, each character of the string is output, in sequence, using the
  13.338 +     * modified UTF-8 encoding for the character. If no exception is thrown, the
  13.339 +     * counter <code>written</code> is incremented by the total number of
  13.340 +     * bytes written to the output stream. This will be at least two
  13.341 +     * plus the length of <code>str</code>, and at most two plus
  13.342 +     * thrice the length of <code>str</code>.
  13.343 +     *
  13.344 +     * @param      str   a string to be written.
  13.345 +     * @param      out   destination to write to
  13.346 +     * @return     The number of bytes written out.
  13.347 +     * @exception  IOException  if an I/O error occurs.
  13.348 +     */
  13.349 +    static int writeUTF(String str, DataOutput out) throws IOException {
  13.350 +        int strlen = str.length();
  13.351 +        int utflen = 0;
  13.352 +        int c, count = 0;
  13.353 +
  13.354 +        /* use charAt instead of copying String to char array */
  13.355 +        for (int i = 0; i < strlen; i++) {
  13.356 +            c = str.charAt(i);
  13.357 +            if ((c >= 0x0001) && (c <= 0x007F)) {
  13.358 +                utflen++;
  13.359 +            } else if (c > 0x07FF) {
  13.360 +                utflen += 3;
  13.361 +            } else {
  13.362 +                utflen += 2;
  13.363 +            }
  13.364 +        }
  13.365 +
  13.366 +        if (utflen > 65535)
  13.367 +            throw new UTFDataFormatException(
  13.368 +                "encoded string too long: " + utflen + " bytes");
  13.369 +
  13.370 +        byte[] bytearr = null;
  13.371 +        if (out instanceof DataOutputStream) {
  13.372 +            DataOutputStream dos = (DataOutputStream)out;
  13.373 +            if(dos.bytearr == null || (dos.bytearr.length < (utflen+2)))
  13.374 +                dos.bytearr = new byte[(utflen*2) + 2];
  13.375 +            bytearr = dos.bytearr;
  13.376 +        } else {
  13.377 +            bytearr = new byte[utflen+2];
  13.378 +        }
  13.379 +
  13.380 +        bytearr[count++] = (byte) ((utflen >>> 8) & 0xFF);
  13.381 +        bytearr[count++] = (byte) ((utflen >>> 0) & 0xFF);
  13.382 +
  13.383 +        int i=0;
  13.384 +        for (i=0; i<strlen; i++) {
  13.385 +           c = str.charAt(i);
  13.386 +           if (!((c >= 0x0001) && (c <= 0x007F))) break;
  13.387 +           bytearr[count++] = (byte) c;
  13.388 +        }
  13.389 +
  13.390 +        for (;i < strlen; i++){
  13.391 +            c = str.charAt(i);
  13.392 +            if ((c >= 0x0001) && (c <= 0x007F)) {
  13.393 +                bytearr[count++] = (byte) c;
  13.394 +
  13.395 +            } else if (c > 0x07FF) {
  13.396 +                bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
  13.397 +                bytearr[count++] = (byte) (0x80 | ((c >>  6) & 0x3F));
  13.398 +                bytearr[count++] = (byte) (0x80 | ((c >>  0) & 0x3F));
  13.399 +            } else {
  13.400 +                bytearr[count++] = (byte) (0xC0 | ((c >>  6) & 0x1F));
  13.401 +                bytearr[count++] = (byte) (0x80 | ((c >>  0) & 0x3F));
  13.402 +            }
  13.403 +        }
  13.404 +        out.write(bytearr, 0, utflen+2);
  13.405 +        return utflen + 2;
  13.406 +    }
  13.407 +
  13.408 +    /**
  13.409 +     * Returns the current value of the counter <code>written</code>,
  13.410 +     * the number of bytes written to this data output stream so far.
  13.411 +     * If the counter overflows, it will be wrapped to Integer.MAX_VALUE.
  13.412 +     *
  13.413 +     * @return  the value of the <code>written</code> field.
  13.414 +     * @see     java.io.DataOutputStream#written
  13.415 +     */
  13.416 +    public final int size() {
  13.417 +        return written;
  13.418 +    }
  13.419 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/emul/compact/src/main/java/java/io/Externalizable.java	Mon Jan 28 18:14:14 2013 +0100
    14.3 @@ -0,0 +1,97 @@
    14.4 +/*
    14.5 + * Copyright (c) 1996, 2004, Oracle and/or its affiliates. All rights reserved.
    14.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    14.7 + *
    14.8 + * This code is free software; you can redistribute it and/or modify it
    14.9 + * under the terms of the GNU General Public License version 2 only, as
   14.10 + * published by the Free Software Foundation.  Oracle designates this
   14.11 + * particular file as subject to the "Classpath" exception as provided
   14.12 + * by Oracle in the LICENSE file that accompanied this code.
   14.13 + *
   14.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   14.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   14.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14.17 + * version 2 for more details (a copy is included in the LICENSE file that
   14.18 + * accompanied this code).
   14.19 + *
   14.20 + * You should have received a copy of the GNU General Public License version
   14.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   14.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   14.23 + *
   14.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   14.25 + * or visit www.oracle.com if you need additional information or have any
   14.26 + * questions.
   14.27 + */
   14.28 +
   14.29 +package java.io;
   14.30 +
   14.31 +import java.io.ObjectOutput;
   14.32 +import java.io.ObjectInput;
   14.33 +
   14.34 +/**
   14.35 + * Only the identity of the class of an Externalizable instance is
   14.36 + * written in the serialization stream and it is the responsibility
   14.37 + * of the class to save and restore the contents of its instances.
   14.38 + *
   14.39 + * The writeExternal and readExternal methods of the Externalizable
   14.40 + * interface are implemented by a class to give the class complete
   14.41 + * control over the format and contents of the stream for an object
   14.42 + * and its supertypes. These methods must explicitly
   14.43 + * coordinate with the supertype to save its state. These methods supersede
   14.44 + * customized implementations of writeObject and readObject methods.<br>
   14.45 + *
   14.46 + * Object Serialization uses the Serializable and Externalizable
   14.47 + * interfaces.  Object persistence mechanisms can use them as well.  Each
   14.48 + * object to be stored is tested for the Externalizable interface. If
   14.49 + * the object supports Externalizable, the writeExternal method is called. If the
   14.50 + * object does not support Externalizable and does implement
   14.51 + * Serializable, the object is saved using
   14.52 + * ObjectOutputStream. <br> When an Externalizable object is
   14.53 + * reconstructed, an instance is created using the public no-arg
   14.54 + * constructor, then the readExternal method called.  Serializable
   14.55 + * objects are restored by reading them from an ObjectInputStream.<br>
   14.56 + *
   14.57 + * An Externalizable instance can designate a substitution object via
   14.58 + * the writeReplace and readResolve methods documented in the Serializable
   14.59 + * interface.<br>
   14.60 + *
   14.61 + * @author  unascribed
   14.62 + * @see java.io.ObjectOutputStream
   14.63 + * @see java.io.ObjectInputStream
   14.64 + * @see java.io.ObjectOutput
   14.65 + * @see java.io.ObjectInput
   14.66 + * @see java.io.Serializable
   14.67 + * @since   JDK1.1
   14.68 + */
   14.69 +public interface Externalizable extends java.io.Serializable {
   14.70 +    /**
   14.71 +     * The object implements the writeExternal method to save its contents
   14.72 +     * by calling the methods of DataOutput for its primitive values or
   14.73 +     * calling the writeObject method of ObjectOutput for objects, strings,
   14.74 +     * and arrays.
   14.75 +     *
   14.76 +     * @serialData Overriding methods should use this tag to describe
   14.77 +     *             the data layout of this Externalizable object.
   14.78 +     *             List the sequence of element types and, if possible,
   14.79 +     *             relate the element to a public/protected field and/or
   14.80 +     *             method of this Externalizable class.
   14.81 +     *
   14.82 +     * @param out the stream to write the object to
   14.83 +     * @exception IOException Includes any I/O exceptions that may occur
   14.84 +     */
   14.85 +    void writeExternal(ObjectOutput out) throws IOException;
   14.86 +
   14.87 +    /**
   14.88 +     * The object implements the readExternal method to restore its
   14.89 +     * contents by calling the methods of DataInput for primitive
   14.90 +     * types and readObject for objects, strings and arrays.  The
   14.91 +     * readExternal method must read the values in the same sequence
   14.92 +     * and with the same types as were written by writeExternal.
   14.93 +     *
   14.94 +     * @param in the stream to read data from in order to restore the object
   14.95 +     * @exception IOException if I/O errors occur
   14.96 +     * @exception ClassNotFoundException If the class for an object being
   14.97 +     *              restored cannot be found.
   14.98 +     */
   14.99 +    void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
  14.100 +}
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/emul/compact/src/main/java/java/io/FilterOutputStream.java	Mon Jan 28 18:14:14 2013 +0100
    15.3 @@ -0,0 +1,162 @@
    15.4 +/*
    15.5 + * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
    15.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    15.7 + *
    15.8 + * This code is free software; you can redistribute it and/or modify it
    15.9 + * under the terms of the GNU General Public License version 2 only, as
   15.10 + * published by the Free Software Foundation.  Oracle designates this
   15.11 + * particular file as subject to the "Classpath" exception as provided
   15.12 + * by Oracle in the LICENSE file that accompanied this code.
   15.13 + *
   15.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   15.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   15.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   15.17 + * version 2 for more details (a copy is included in the LICENSE file that
   15.18 + * accompanied this code).
   15.19 + *
   15.20 + * You should have received a copy of the GNU General Public License version
   15.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   15.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   15.23 + *
   15.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   15.25 + * or visit www.oracle.com if you need additional information or have any
   15.26 + * questions.
   15.27 + */
   15.28 +
   15.29 +package java.io;
   15.30 +
   15.31 +/**
   15.32 + * This class is the superclass of all classes that filter output
   15.33 + * streams. These streams sit on top of an already existing output
   15.34 + * stream (the <i>underlying</i> output stream) which it uses as its
   15.35 + * basic sink of data, but possibly transforming the data along the
   15.36 + * way or providing additional functionality.
   15.37 + * <p>
   15.38 + * The class <code>FilterOutputStream</code> itself simply overrides
   15.39 + * all methods of <code>OutputStream</code> with versions that pass
   15.40 + * all requests to the underlying output stream. Subclasses of
   15.41 + * <code>FilterOutputStream</code> may further override some of these
   15.42 + * methods as well as provide additional methods and fields.
   15.43 + *
   15.44 + * @author  Jonathan Payne
   15.45 + * @since   JDK1.0
   15.46 + */
   15.47 +public
   15.48 +class FilterOutputStream extends OutputStream {
   15.49 +    /**
   15.50 +     * The underlying output stream to be filtered.
   15.51 +     */
   15.52 +    protected OutputStream out;
   15.53 +
   15.54 +    /**
   15.55 +     * Creates an output stream filter built on top of the specified
   15.56 +     * underlying output stream.
   15.57 +     *
   15.58 +     * @param   out   the underlying output stream to be assigned to
   15.59 +     *                the field <tt>this.out</tt> for later use, or
   15.60 +     *                <code>null</code> if this instance is to be
   15.61 +     *                created without an underlying stream.
   15.62 +     */
   15.63 +    public FilterOutputStream(OutputStream out) {
   15.64 +        this.out = out;
   15.65 +    }
   15.66 +
   15.67 +    /**
   15.68 +     * Writes the specified <code>byte</code> to this output stream.
   15.69 +     * <p>
   15.70 +     * The <code>write</code> method of <code>FilterOutputStream</code>
   15.71 +     * calls the <code>write</code> method of its underlying output stream,
   15.72 +     * that is, it performs <tt>out.write(b)</tt>.
   15.73 +     * <p>
   15.74 +     * Implements the abstract <tt>write</tt> method of <tt>OutputStream</tt>.
   15.75 +     *
   15.76 +     * @param      b   the <code>byte</code>.
   15.77 +     * @exception  IOException  if an I/O error occurs.
   15.78 +     */
   15.79 +    public void write(int b) throws IOException {
   15.80 +        out.write(b);
   15.81 +    }
   15.82 +
   15.83 +    /**
   15.84 +     * Writes <code>b.length</code> bytes to this output stream.
   15.85 +     * <p>
   15.86 +     * The <code>write</code> method of <code>FilterOutputStream</code>
   15.87 +     * calls its <code>write</code> method of three arguments with the
   15.88 +     * arguments <code>b</code>, <code>0</code>, and
   15.89 +     * <code>b.length</code>.
   15.90 +     * <p>
   15.91 +     * Note that this method does not call the one-argument
   15.92 +     * <code>write</code> method of its underlying stream with the single
   15.93 +     * argument <code>b</code>.
   15.94 +     *
   15.95 +     * @param      b   the data to be written.
   15.96 +     * @exception  IOException  if an I/O error occurs.
   15.97 +     * @see        java.io.FilterOutputStream#write(byte[], int, int)
   15.98 +     */
   15.99 +    public void write(byte b[]) throws IOException {
  15.100 +        write(b, 0, b.length);
  15.101 +    }
  15.102 +
  15.103 +    /**
  15.104 +     * Writes <code>len</code> bytes from the specified
  15.105 +     * <code>byte</code> array starting at offset <code>off</code> to
  15.106 +     * this output stream.
  15.107 +     * <p>
  15.108 +     * The <code>write</code> method of <code>FilterOutputStream</code>
  15.109 +     * calls the <code>write</code> method of one argument on each
  15.110 +     * <code>byte</code> to output.
  15.111 +     * <p>
  15.112 +     * Note that this method does not call the <code>write</code> method
  15.113 +     * of its underlying input stream with the same arguments. Subclasses
  15.114 +     * of <code>FilterOutputStream</code> should provide a more efficient
  15.115 +     * implementation of this method.
  15.116 +     *
  15.117 +     * @param      b     the data.
  15.118 +     * @param      off   the start offset in the data.
  15.119 +     * @param      len   the number of bytes to write.
  15.120 +     * @exception  IOException  if an I/O error occurs.
  15.121 +     * @see        java.io.FilterOutputStream#write(int)
  15.122 +     */
  15.123 +    public void write(byte b[], int off, int len) throws IOException {
  15.124 +        if ((off | len | (b.length - (len + off)) | (off + len)) < 0)
  15.125 +            throw new IndexOutOfBoundsException();
  15.126 +
  15.127 +        for (int i = 0 ; i < len ; i++) {
  15.128 +            write(b[off + i]);
  15.129 +        }
  15.130 +    }
  15.131 +
  15.132 +    /**
  15.133 +     * Flushes this output stream and forces any buffered output bytes
  15.134 +     * to be written out to the stream.
  15.135 +     * <p>
  15.136 +     * The <code>flush</code> method of <code>FilterOutputStream</code>
  15.137 +     * calls the <code>flush</code> method of its underlying output stream.
  15.138 +     *
  15.139 +     * @exception  IOException  if an I/O error occurs.
  15.140 +     * @see        java.io.FilterOutputStream#out
  15.141 +     */
  15.142 +    public void flush() throws IOException {
  15.143 +        out.flush();
  15.144 +    }
  15.145 +
  15.146 +    /**
  15.147 +     * Closes this output stream and releases any system resources
  15.148 +     * associated with the stream.
  15.149 +     * <p>
  15.150 +     * The <code>close</code> method of <code>FilterOutputStream</code>
  15.151 +     * calls its <code>flush</code> method, and then calls the
  15.152 +     * <code>close</code> method of its underlying output stream.
  15.153 +     *
  15.154 +     * @exception  IOException  if an I/O error occurs.
  15.155 +     * @see        java.io.FilterOutputStream#flush()
  15.156 +     * @see        java.io.FilterOutputStream#out
  15.157 +     */
  15.158 +    public void close() throws IOException {
  15.159 +        try {
  15.160 +          flush();
  15.161 +        } catch (IOException ignored) {
  15.162 +        }
  15.163 +        out.close();
  15.164 +    }
  15.165 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/emul/compact/src/main/java/java/io/Flushable.java	Mon Jan 28 18:14:14 2013 +0100
    16.3 @@ -0,0 +1,47 @@
    16.4 +/*
    16.5 + * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
    16.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    16.7 + *
    16.8 + * This code is free software; you can redistribute it and/or modify it
    16.9 + * under the terms of the GNU General Public License version 2 only, as
   16.10 + * published by the Free Software Foundation.  Oracle designates this
   16.11 + * particular file as subject to the "Classpath" exception as provided
   16.12 + * by Oracle in the LICENSE file that accompanied this code.
   16.13 + *
   16.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   16.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   16.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   16.17 + * version 2 for more details (a copy is included in the LICENSE file that
   16.18 + * accompanied this code).
   16.19 + *
   16.20 + * You should have received a copy of the GNU General Public License version
   16.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   16.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   16.23 + *
   16.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   16.25 + * or visit www.oracle.com if you need additional information or have any
   16.26 + * questions.
   16.27 + */
   16.28 +
   16.29 +package java.io;
   16.30 +
   16.31 +import java.io.IOException;
   16.32 +
   16.33 +/**
   16.34 + * A <tt>Flushable</tt> is a destination of data that can be flushed.  The
   16.35 + * flush method is invoked to write any buffered output to the underlying
   16.36 + * stream.
   16.37 + *
   16.38 + * @since 1.5
   16.39 + */
   16.40 +
   16.41 +public interface Flushable {
   16.42 +
   16.43 +    /**
   16.44 +     * Flushes this stream by writing any buffered output to the underlying
   16.45 +     * stream.
   16.46 +     *
   16.47 +     * @throws IOException If an I/O error occurs
   16.48 +     */
   16.49 +    void flush() throws IOException;
   16.50 +}
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/emul/compact/src/main/java/java/io/InvalidClassException.java	Mon Jan 28 18:14:14 2013 +0100
    17.3 @@ -0,0 +1,81 @@
    17.4 +/*
    17.5 + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
    17.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    17.7 + *
    17.8 + * This code is free software; you can redistribute it and/or modify it
    17.9 + * under the terms of the GNU General Public License version 2 only, as
   17.10 + * published by the Free Software Foundation.  Oracle designates this
   17.11 + * particular file as subject to the "Classpath" exception as provided
   17.12 + * by Oracle in the LICENSE file that accompanied this code.
   17.13 + *
   17.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   17.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   17.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   17.17 + * version 2 for more details (a copy is included in the LICENSE file that
   17.18 + * accompanied this code).
   17.19 + *
   17.20 + * You should have received a copy of the GNU General Public License version
   17.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   17.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   17.23 + *
   17.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   17.25 + * or visit www.oracle.com if you need additional information or have any
   17.26 + * questions.
   17.27 + */
   17.28 +
   17.29 +package java.io;
   17.30 +
   17.31 +/**
   17.32 + * Thrown when the Serialization runtime detects one of the following
   17.33 + * problems with a Class.
   17.34 + * <UL>
   17.35 + * <LI> The serial version of the class does not match that of the class
   17.36 + *      descriptor read from the stream
   17.37 + * <LI> The class contains unknown datatypes
   17.38 + * <LI> The class does not have an accessible no-arg constructor
   17.39 + * </UL>
   17.40 + *
   17.41 + * @author  unascribed
   17.42 + * @since   JDK1.1
   17.43 + */
   17.44 +public class InvalidClassException extends ObjectStreamException {
   17.45 +
   17.46 +    private static final long serialVersionUID = -4333316296251054416L;
   17.47 +
   17.48 +    /**
   17.49 +     * Name of the invalid class.
   17.50 +     *
   17.51 +     * @serial Name of the invalid class.
   17.52 +     */
   17.53 +    public String classname;
   17.54 +
   17.55 +    /**
   17.56 +     * Report an InvalidClassException for the reason specified.
   17.57 +     *
   17.58 +     * @param reason  String describing the reason for the exception.
   17.59 +     */
   17.60 +    public InvalidClassException(String reason) {
   17.61 +        super(reason);
   17.62 +    }
   17.63 +
   17.64 +    /**
   17.65 +     * Constructs an InvalidClassException object.
   17.66 +     *
   17.67 +     * @param cname   a String naming the invalid class.
   17.68 +     * @param reason  a String describing the reason for the exception.
   17.69 +     */
   17.70 +    public InvalidClassException(String cname, String reason) {
   17.71 +        super(reason);
   17.72 +        classname = cname;
   17.73 +    }
   17.74 +
   17.75 +    /**
   17.76 +     * Produce the message and include the classname, if present.
   17.77 +     */
   17.78 +    public String getMessage() {
   17.79 +        if (classname == null)
   17.80 +            return super.getMessage();
   17.81 +        else
   17.82 +            return classname + "; " + super.getMessage();
   17.83 +    }
   17.84 +}
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/emul/compact/src/main/java/java/io/InvalidObjectException.java	Mon Jan 28 18:14:14 2013 +0100
    18.3 @@ -0,0 +1,51 @@
    18.4 +/*
    18.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
    18.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    18.7 + *
    18.8 + * This code is free software; you can redistribute it and/or modify it
    18.9 + * under the terms of the GNU General Public License version 2 only, as
   18.10 + * published by the Free Software Foundation.  Oracle designates this
   18.11 + * particular file as subject to the "Classpath" exception as provided
   18.12 + * by Oracle in the LICENSE file that accompanied this code.
   18.13 + *
   18.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   18.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   18.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   18.17 + * version 2 for more details (a copy is included in the LICENSE file that
   18.18 + * accompanied this code).
   18.19 + *
   18.20 + * You should have received a copy of the GNU General Public License version
   18.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   18.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   18.23 + *
   18.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   18.25 + * or visit www.oracle.com if you need additional information or have any
   18.26 + * questions.
   18.27 + */
   18.28 +
   18.29 +package java.io;
   18.30 +
   18.31 +/**
   18.32 + * Indicates that one or more deserialized objects failed validation
   18.33 + * tests.  The argument should provide the reason for the failure.
   18.34 + *
   18.35 + * @see ObjectInputValidation
   18.36 + * @since JDK1.1
   18.37 + *
   18.38 + * @author  unascribed
   18.39 + * @since   JDK1.1
   18.40 + */
   18.41 +public class InvalidObjectException extends ObjectStreamException {
   18.42 +
   18.43 +    private static final long serialVersionUID = 3233174318281839583L;
   18.44 +
   18.45 +    /**
   18.46 +     * Constructs an <code>InvalidObjectException</code>.
   18.47 +     * @param reason Detailed message explaining the reason for the failure.
   18.48 +     *
   18.49 +     * @see ObjectInputValidation
   18.50 +     */
   18.51 +    public  InvalidObjectException(String reason) {
   18.52 +        super(reason);
   18.53 +    }
   18.54 +}
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/emul/compact/src/main/java/java/io/NotActiveException.java	Mon Jan 28 18:14:14 2013 +0100
    19.3 @@ -0,0 +1,53 @@
    19.4 +/*
    19.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
    19.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    19.7 + *
    19.8 + * This code is free software; you can redistribute it and/or modify it
    19.9 + * under the terms of the GNU General Public License version 2 only, as
   19.10 + * published by the Free Software Foundation.  Oracle designates this
   19.11 + * particular file as subject to the "Classpath" exception as provided
   19.12 + * by Oracle in the LICENSE file that accompanied this code.
   19.13 + *
   19.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   19.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   19.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   19.17 + * version 2 for more details (a copy is included in the LICENSE file that
   19.18 + * accompanied this code).
   19.19 + *
   19.20 + * You should have received a copy of the GNU General Public License version
   19.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   19.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   19.23 + *
   19.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   19.25 + * or visit www.oracle.com if you need additional information or have any
   19.26 + * questions.
   19.27 + */
   19.28 +
   19.29 +package java.io;
   19.30 +
   19.31 +/**
   19.32 + * Thrown when serialization or deserialization is not active.
   19.33 + *
   19.34 + * @author  unascribed
   19.35 + * @since   JDK1.1
   19.36 + */
   19.37 +public class NotActiveException extends ObjectStreamException {
   19.38 +
   19.39 +    private static final long serialVersionUID = -3893467273049808895L;
   19.40 +
   19.41 +    /**
   19.42 +     * Constructor to create a new NotActiveException with the reason given.
   19.43 +     *
   19.44 +     * @param reason  a String describing the reason for the exception.
   19.45 +     */
   19.46 +    public NotActiveException(String reason) {
   19.47 +        super(reason);
   19.48 +    }
   19.49 +
   19.50 +    /**
   19.51 +     * Constructor to create a new NotActiveException without a reason.
   19.52 +     */
   19.53 +    public NotActiveException() {
   19.54 +        super();
   19.55 +    }
   19.56 +}
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/emul/compact/src/main/java/java/io/NotSerializableException.java	Mon Jan 28 18:14:14 2013 +0100
    20.3 @@ -0,0 +1,55 @@
    20.4 +/*
    20.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
    20.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    20.7 + *
    20.8 + * This code is free software; you can redistribute it and/or modify it
    20.9 + * under the terms of the GNU General Public License version 2 only, as
   20.10 + * published by the Free Software Foundation.  Oracle designates this
   20.11 + * particular file as subject to the "Classpath" exception as provided
   20.12 + * by Oracle in the LICENSE file that accompanied this code.
   20.13 + *
   20.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   20.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   20.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   20.17 + * version 2 for more details (a copy is included in the LICENSE file that
   20.18 + * accompanied this code).
   20.19 + *
   20.20 + * You should have received a copy of the GNU General Public License version
   20.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   20.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20.23 + *
   20.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   20.25 + * or visit www.oracle.com if you need additional information or have any
   20.26 + * questions.
   20.27 + */
   20.28 +
   20.29 +package java.io;
   20.30 +
   20.31 +/**
   20.32 + * Thrown when an instance is required to have a Serializable interface.
   20.33 + * The serialization runtime or the class of the instance can throw
   20.34 + * this exception. The argument should be the name of the class.
   20.35 + *
   20.36 + * @author  unascribed
   20.37 + * @since   JDK1.1
   20.38 + */
   20.39 +public class NotSerializableException extends ObjectStreamException {
   20.40 +
   20.41 +    private static final long serialVersionUID = 2906642554793891381L;
   20.42 +
   20.43 +    /**
   20.44 +     * Constructs a NotSerializableException object with message string.
   20.45 +     *
   20.46 +     * @param classname Class of the instance being serialized/deserialized.
   20.47 +     */
   20.48 +    public NotSerializableException(String classname) {
   20.49 +        super(classname);
   20.50 +    }
   20.51 +
   20.52 +    /**
   20.53 +     *  Constructs a NotSerializableException object.
   20.54 +     */
   20.55 +    public NotSerializableException() {
   20.56 +        super();
   20.57 +    }
   20.58 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/emul/compact/src/main/java/java/io/ObjectInput.java	Mon Jan 28 18:14:14 2013 +0100
    21.3 @@ -0,0 +1,107 @@
    21.4 +/*
    21.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
    21.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    21.7 + *
    21.8 + * This code is free software; you can redistribute it and/or modify it
    21.9 + * under the terms of the GNU General Public License version 2 only, as
   21.10 + * published by the Free Software Foundation.  Oracle designates this
   21.11 + * particular file as subject to the "Classpath" exception as provided
   21.12 + * by Oracle in the LICENSE file that accompanied this code.
   21.13 + *
   21.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   21.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   21.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   21.17 + * version 2 for more details (a copy is included in the LICENSE file that
   21.18 + * accompanied this code).
   21.19 + *
   21.20 + * You should have received a copy of the GNU General Public License version
   21.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   21.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   21.23 + *
   21.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   21.25 + * or visit www.oracle.com if you need additional information or have any
   21.26 + * questions.
   21.27 + */
   21.28 +
   21.29 +package java.io;
   21.30 +
   21.31 +/**
   21.32 + * ObjectInput extends the DataInput interface to include the reading of
   21.33 + * objects. DataInput includes methods for the input of primitive types,
   21.34 + * ObjectInput extends that interface to include objects, arrays, and Strings.
   21.35 + *
   21.36 + * @author  unascribed
   21.37 + * @see java.io.InputStream
   21.38 + * @see java.io.ObjectOutputStream
   21.39 + * @see java.io.ObjectInputStream
   21.40 + * @since   JDK1.1
   21.41 + */
   21.42 +public interface ObjectInput extends DataInput, AutoCloseable {
   21.43 +    /**
   21.44 +     * Read and return an object. The class that implements this interface
   21.45 +     * defines where the object is "read" from.
   21.46 +     *
   21.47 +     * @return the object read from the stream
   21.48 +     * @exception java.lang.ClassNotFoundException If the class of a serialized
   21.49 +     *      object cannot be found.
   21.50 +     * @exception IOException If any of the usual Input/Output
   21.51 +     * related exceptions occur.
   21.52 +     */
   21.53 +    public Object readObject()
   21.54 +        throws ClassNotFoundException, IOException;
   21.55 +
   21.56 +    /**
   21.57 +     * Reads a byte of data. This method will block if no input is
   21.58 +     * available.
   21.59 +     * @return  the byte read, or -1 if the end of the
   21.60 +     *          stream is reached.
   21.61 +     * @exception IOException If an I/O error has occurred.
   21.62 +     */
   21.63 +    public int read() throws IOException;
   21.64 +
   21.65 +    /**
   21.66 +     * Reads into an array of bytes.  This method will
   21.67 +     * block until some input is available.
   21.68 +     * @param b the buffer into which the data is read
   21.69 +     * @return  the actual number of bytes read, -1 is
   21.70 +     *          returned when the end of the stream is reached.
   21.71 +     * @exception IOException If an I/O error has occurred.
   21.72 +     */
   21.73 +    public int read(byte b[]) throws IOException;
   21.74 +
   21.75 +    /**
   21.76 +     * Reads into an array of bytes.  This method will
   21.77 +     * block until some input is available.
   21.78 +     * @param b the buffer into which the data is read
   21.79 +     * @param off the start offset of the data
   21.80 +     * @param len the maximum number of bytes read
   21.81 +     * @return  the actual number of bytes read, -1 is
   21.82 +     *          returned when the end of the stream is reached.
   21.83 +     * @exception IOException If an I/O error has occurred.
   21.84 +     */
   21.85 +    public int read(byte b[], int off, int len) throws IOException;
   21.86 +
   21.87 +    /**
   21.88 +     * Skips n bytes of input.
   21.89 +     * @param n the number of bytes to be skipped
   21.90 +     * @return  the actual number of bytes skipped.
   21.91 +     * @exception IOException If an I/O error has occurred.
   21.92 +     */
   21.93 +    public long skip(long n) throws IOException;
   21.94 +
   21.95 +    /**
   21.96 +     * Returns the number of bytes that can be read
   21.97 +     * without blocking.
   21.98 +     * @return the number of available bytes.
   21.99 +     * @exception IOException If an I/O error has occurred.
  21.100 +     */
  21.101 +    public int available() throws IOException;
  21.102 +
  21.103 +    /**
  21.104 +     * Closes the input stream. Must be called
  21.105 +     * to release any resources associated with
  21.106 +     * the stream.
  21.107 +     * @exception IOException If an I/O error has occurred.
  21.108 +     */
  21.109 +    public void close() throws IOException;
  21.110 +}
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/emul/compact/src/main/java/java/io/ObjectInputStream.java	Mon Jan 28 18:14:14 2013 +0100
    22.3 @@ -0,0 +1,3508 @@
    22.4 +/*
    22.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
    22.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    22.7 + *
    22.8 + * This code is free software; you can redistribute it and/or modify it
    22.9 + * under the terms of the GNU General Public License version 2 only, as
   22.10 + * published by the Free Software Foundation.  Oracle designates this
   22.11 + * particular file as subject to the "Classpath" exception as provided
   22.12 + * by Oracle in the LICENSE file that accompanied this code.
   22.13 + *
   22.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   22.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   22.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   22.17 + * version 2 for more details (a copy is included in the LICENSE file that
   22.18 + * accompanied this code).
   22.19 + *
   22.20 + * You should have received a copy of the GNU General Public License version
   22.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   22.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   22.23 + *
   22.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22.25 + * or visit www.oracle.com if you need additional information or have any
   22.26 + * questions.
   22.27 + */
   22.28 +
   22.29 +package java.io;
   22.30 +
   22.31 +import java.io.ObjectStreamClass.WeakClassKey;
   22.32 +import java.lang.ref.ReferenceQueue;
   22.33 +import java.lang.reflect.Array;
   22.34 +import java.lang.reflect.Modifier;
   22.35 +import java.lang.reflect.Proxy;
   22.36 +import java.security.AccessControlContext;
   22.37 +import java.security.AccessController;
   22.38 +import java.security.PrivilegedAction;
   22.39 +import java.security.PrivilegedActionException;
   22.40 +import java.security.PrivilegedExceptionAction;
   22.41 +import java.util.Arrays;
   22.42 +import java.util.HashMap;
   22.43 +import java.util.concurrent.ConcurrentHashMap;
   22.44 +import java.util.concurrent.ConcurrentMap;
   22.45 +import java.util.concurrent.atomic.AtomicBoolean;
   22.46 +import static java.io.ObjectStreamClass.processQueue;
   22.47 +
   22.48 +/**
   22.49 + * An ObjectInputStream deserializes primitive data and objects previously
   22.50 + * written using an ObjectOutputStream.
   22.51 + *
   22.52 + * <p>ObjectOutputStream and ObjectInputStream can provide an application with
   22.53 + * persistent storage for graphs of objects when used with a FileOutputStream
   22.54 + * and FileInputStream respectively.  ObjectInputStream is used to recover
   22.55 + * those objects previously serialized. Other uses include passing objects
   22.56 + * between hosts using a socket stream or for marshaling and unmarshaling
   22.57 + * arguments and parameters in a remote communication system.
   22.58 + *
   22.59 + * <p>ObjectInputStream ensures that the types of all objects in the graph
   22.60 + * created from the stream match the classes present in the Java Virtual
   22.61 + * Machine.  Classes are loaded as required using the standard mechanisms.
   22.62 + *
   22.63 + * <p>Only objects that support the java.io.Serializable or
   22.64 + * java.io.Externalizable interface can be read from streams.
   22.65 + *
   22.66 + * <p>The method <code>readObject</code> is used to read an object from the
   22.67 + * stream.  Java's safe casting should be used to get the desired type.  In
   22.68 + * Java, strings and arrays are objects and are treated as objects during
   22.69 + * serialization. When read they need to be cast to the expected type.
   22.70 + *
   22.71 + * <p>Primitive data types can be read from the stream using the appropriate
   22.72 + * method on DataInput.
   22.73 + *
   22.74 + * <p>The default deserialization mechanism for objects restores the contents
   22.75 + * of each field to the value and type it had when it was written.  Fields
   22.76 + * declared as transient or static are ignored by the deserialization process.
   22.77 + * References to other objects cause those objects to be read from the stream
   22.78 + * as necessary.  Graphs of objects are restored correctly using a reference
   22.79 + * sharing mechanism.  New objects are always allocated when deserializing,
   22.80 + * which prevents existing objects from being overwritten.
   22.81 + *
   22.82 + * <p>Reading an object is analogous to running the constructors of a new
   22.83 + * object.  Memory is allocated for the object and initialized to zero (NULL).
   22.84 + * No-arg constructors are invoked for the non-serializable classes and then
   22.85 + * the fields of the serializable classes are restored from the stream starting
   22.86 + * with the serializable class closest to java.lang.object and finishing with
   22.87 + * the object's most specific class.
   22.88 + *
   22.89 + * <p>For example to read from a stream as written by the example in
   22.90 + * ObjectOutputStream:
   22.91 + * <br>
   22.92 + * <pre>
   22.93 + *      FileInputStream fis = new FileInputStream("t.tmp");
   22.94 + *      ObjectInputStream ois = new ObjectInputStream(fis);
   22.95 + *
   22.96 + *      int i = ois.readInt();
   22.97 + *      String today = (String) ois.readObject();
   22.98 + *      Date date = (Date) ois.readObject();
   22.99 + *
  22.100 + *      ois.close();
  22.101 + * </pre>
  22.102 + *
  22.103 + * <p>Classes control how they are serialized by implementing either the
  22.104 + * java.io.Serializable or java.io.Externalizable interfaces.
  22.105 + *
  22.106 + * <p>Implementing the Serializable interface allows object serialization to
  22.107 + * save and restore the entire state of the object and it allows classes to
  22.108 + * evolve between the time the stream is written and the time it is read.  It
  22.109 + * automatically traverses references between objects, saving and restoring
  22.110 + * entire graphs.
  22.111 + *
  22.112 + * <p>Serializable classes that require special handling during the
  22.113 + * serialization and deserialization process should implement the following
  22.114 + * methods:<p>
  22.115 + *
  22.116 + * <pre>
  22.117 + * private void writeObject(java.io.ObjectOutputStream stream)
  22.118 + *     throws IOException;
  22.119 + * private void readObject(java.io.ObjectInputStream stream)
  22.120 + *     throws IOException, ClassNotFoundException;
  22.121 + * private void readObjectNoData()
  22.122 + *     throws ObjectStreamException;
  22.123 + * </pre>
  22.124 + *
  22.125 + * <p>The readObject method is responsible for reading and restoring the state
  22.126 + * of the object for its particular class using data written to the stream by
  22.127 + * the corresponding writeObject method.  The method does not need to concern
  22.128 + * itself with the state belonging to its superclasses or subclasses.  State is
  22.129 + * restored by reading data from the ObjectInputStream for the individual
  22.130 + * fields and making assignments to the appropriate fields of the object.
  22.131 + * Reading primitive data types is supported by DataInput.
  22.132 + *
  22.133 + * <p>Any attempt to read object data which exceeds the boundaries of the
  22.134 + * custom data written by the corresponding writeObject method will cause an
  22.135 + * OptionalDataException to be thrown with an eof field value of true.
  22.136 + * Non-object reads which exceed the end of the allotted data will reflect the
  22.137 + * end of data in the same way that they would indicate the end of the stream:
  22.138 + * bytewise reads will return -1 as the byte read or number of bytes read, and
  22.139 + * primitive reads will throw EOFExceptions.  If there is no corresponding
  22.140 + * writeObject method, then the end of default serialized data marks the end of
  22.141 + * the allotted data.
  22.142 + *
  22.143 + * <p>Primitive and object read calls issued from within a readExternal method
  22.144 + * behave in the same manner--if the stream is already positioned at the end of
  22.145 + * data written by the corresponding writeExternal method, object reads will
  22.146 + * throw OptionalDataExceptions with eof set to true, bytewise reads will
  22.147 + * return -1, and primitive reads will throw EOFExceptions.  Note that this
  22.148 + * behavior does not hold for streams written with the old
  22.149 + * <code>ObjectStreamConstants.PROTOCOL_VERSION_1</code> protocol, in which the
  22.150 + * end of data written by writeExternal methods is not demarcated, and hence
  22.151 + * cannot be detected.
  22.152 + *
  22.153 + * <p>The readObjectNoData method is responsible for initializing the state of
  22.154 + * the object for its particular class in the event that the serialization
  22.155 + * stream does not list the given class as a superclass of the object being
  22.156 + * deserialized.  This may occur in cases where the receiving party uses a
  22.157 + * different version of the deserialized instance's class than the sending
  22.158 + * party, and the receiver's version extends classes that are not extended by
  22.159 + * the sender's version.  This may also occur if the serialization stream has
  22.160 + * been tampered; hence, readObjectNoData is useful for initializing
  22.161 + * deserialized objects properly despite a "hostile" or incomplete source
  22.162 + * stream.
  22.163 + *
  22.164 + * <p>Serialization does not read or assign values to the fields of any object
  22.165 + * that does not implement the java.io.Serializable interface.  Subclasses of
  22.166 + * Objects that are not serializable can be serializable. In this case the
  22.167 + * non-serializable class must have a no-arg constructor to allow its fields to
  22.168 + * be initialized.  In this case it is the responsibility of the subclass to
  22.169 + * save and restore the state of the non-serializable class. It is frequently
  22.170 + * the case that the fields of that class are accessible (public, package, or
  22.171 + * protected) or that there are get and set methods that can be used to restore
  22.172 + * the state.
  22.173 + *
  22.174 + * <p>Any exception that occurs while deserializing an object will be caught by
  22.175 + * the ObjectInputStream and abort the reading process.
  22.176 + *
  22.177 + * <p>Implementing the Externalizable interface allows the object to assume
  22.178 + * complete control over the contents and format of the object's serialized
  22.179 + * form.  The methods of the Externalizable interface, writeExternal and
  22.180 + * readExternal, are called to save and restore the objects state.  When
  22.181 + * implemented by a class they can write and read their own state using all of
  22.182 + * the methods of ObjectOutput and ObjectInput.  It is the responsibility of
  22.183 + * the objects to handle any versioning that occurs.
  22.184 + *
  22.185 + * <p>Enum constants are deserialized differently than ordinary serializable or
  22.186 + * externalizable objects.  The serialized form of an enum constant consists
  22.187 + * solely of its name; field values of the constant are not transmitted.  To
  22.188 + * deserialize an enum constant, ObjectInputStream reads the constant name from
  22.189 + * the stream; the deserialized constant is then obtained by calling the static
  22.190 + * method <code>Enum.valueOf(Class, String)</code> with the enum constant's
  22.191 + * base type and the received constant name as arguments.  Like other
  22.192 + * serializable or externalizable objects, enum constants can function as the
  22.193 + * targets of back references appearing subsequently in the serialization
  22.194 + * stream.  The process by which enum constants are deserialized cannot be
  22.195 + * customized: any class-specific readObject, readObjectNoData, and readResolve
  22.196 + * methods defined by enum types are ignored during deserialization.
  22.197 + * Similarly, any serialPersistentFields or serialVersionUID field declarations
  22.198 + * are also ignored--all enum types have a fixed serialVersionUID of 0L.
  22.199 + *
  22.200 + * @author      Mike Warres
  22.201 + * @author      Roger Riggs
  22.202 + * @see java.io.DataInput
  22.203 + * @see java.io.ObjectOutputStream
  22.204 + * @see java.io.Serializable
  22.205 + * @see <a href="../../../platform/serialization/spec/input.html"> Object Serialization Specification, Section 3, Object Input Classes</a>
  22.206 + * @since   JDK1.1
  22.207 + */
  22.208 +public class ObjectInputStream
  22.209 +    extends InputStream implements ObjectInput, ObjectStreamConstants
  22.210 +{
  22.211 +    /** handle value representing null */
  22.212 +    private static final int NULL_HANDLE = -1;
  22.213 +
  22.214 +    /** marker for unshared objects in internal handle table */
  22.215 +    private static final Object unsharedMarker = new Object();
  22.216 +
  22.217 +    /** table mapping primitive type names to corresponding class objects */
  22.218 +    private static final HashMap<String, Class<?>> primClasses
  22.219 +        = new HashMap<>(8, 1.0F);
  22.220 +    static {
  22.221 +        primClasses.put("boolean", boolean.class);
  22.222 +        primClasses.put("byte", byte.class);
  22.223 +        primClasses.put("char", char.class);
  22.224 +        primClasses.put("short", short.class);
  22.225 +        primClasses.put("int", int.class);
  22.226 +        primClasses.put("long", long.class);
  22.227 +        primClasses.put("float", float.class);
  22.228 +        primClasses.put("double", double.class);
  22.229 +        primClasses.put("void", void.class);
  22.230 +    }
  22.231 +
  22.232 +    private static class Caches {
  22.233 +        /** cache of subclass security audit results */
  22.234 +        static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits =
  22.235 +            new ConcurrentHashMap<>();
  22.236 +
  22.237 +        /** queue for WeakReferences to audited subclasses */
  22.238 +        static final ReferenceQueue<Class<?>> subclassAuditsQueue =
  22.239 +            new ReferenceQueue<>();
  22.240 +    }
  22.241 +
  22.242 +    /** filter stream for handling block data conversion */
  22.243 +    private final BlockDataInputStream bin;
  22.244 +    /** validation callback list */
  22.245 +    private final ValidationList vlist;
  22.246 +    /** recursion depth */
  22.247 +    private int depth;
  22.248 +    /** whether stream is closed */
  22.249 +    private boolean closed;
  22.250 +
  22.251 +    /** wire handle -> obj/exception map */
  22.252 +    private final HandleTable handles;
  22.253 +    /** scratch field for passing handle values up/down call stack */
  22.254 +    private int passHandle = NULL_HANDLE;
  22.255 +    /** flag set when at end of field value block with no TC_ENDBLOCKDATA */
  22.256 +    private boolean defaultDataEnd = false;
  22.257 +
  22.258 +    /** buffer for reading primitive field values */
  22.259 +    private byte[] primVals;
  22.260 +
  22.261 +    /** if true, invoke readObjectOverride() instead of readObject() */
  22.262 +    private final boolean enableOverride;
  22.263 +    /** if true, invoke resolveObject() */
  22.264 +    private boolean enableResolve;
  22.265 +
  22.266 +    /**
  22.267 +     * Context during upcalls to class-defined readObject methods; holds
  22.268 +     * object currently being deserialized and descriptor for current class.
  22.269 +     * Null when not during readObject upcall.
  22.270 +     */
  22.271 +    private SerialCallbackContext curContext;
  22.272 +
  22.273 +    /**
  22.274 +     * Creates an ObjectInputStream that reads from the specified InputStream.
  22.275 +     * A serialization stream header is read from the stream and verified.
  22.276 +     * This constructor will block until the corresponding ObjectOutputStream
  22.277 +     * has written and flushed the header.
  22.278 +     *
  22.279 +     * <p>If a security manager is installed, this constructor will check for
  22.280 +     * the "enableSubclassImplementation" SerializablePermission when invoked
  22.281 +     * directly or indirectly by the constructor of a subclass which overrides
  22.282 +     * the ObjectInputStream.readFields or ObjectInputStream.readUnshared
  22.283 +     * methods.
  22.284 +     *
  22.285 +     * @param   in input stream to read from
  22.286 +     * @throws  StreamCorruptedException if the stream header is incorrect
  22.287 +     * @throws  IOException if an I/O error occurs while reading stream header
  22.288 +     * @throws  SecurityException if untrusted subclass illegally overrides
  22.289 +     *          security-sensitive methods
  22.290 +     * @throws  NullPointerException if <code>in</code> is <code>null</code>
  22.291 +     * @see     ObjectInputStream#ObjectInputStream()
  22.292 +     * @see     ObjectInputStream#readFields()
  22.293 +     * @see     ObjectOutputStream#ObjectOutputStream(OutputStream)
  22.294 +     */
  22.295 +    public ObjectInputStream(InputStream in) throws IOException {
  22.296 +        verifySubclass();
  22.297 +        bin = new BlockDataInputStream(in);
  22.298 +        handles = new HandleTable(10);
  22.299 +        vlist = new ValidationList();
  22.300 +        enableOverride = false;
  22.301 +        readStreamHeader();
  22.302 +        bin.setBlockDataMode(true);
  22.303 +    }
  22.304 +
  22.305 +    /**
  22.306 +     * Provide a way for subclasses that are completely reimplementing
  22.307 +     * ObjectInputStream to not have to allocate private data just used by this
  22.308 +     * implementation of ObjectInputStream.
  22.309 +     *
  22.310 +     * <p>If there is a security manager installed, this method first calls the
  22.311 +     * security manager's <code>checkPermission</code> method with the
  22.312 +     * <code>SerializablePermission("enableSubclassImplementation")</code>
  22.313 +     * permission to ensure it's ok to enable subclassing.
  22.314 +     *
  22.315 +     * @throws  SecurityException if a security manager exists and its
  22.316 +     *          <code>checkPermission</code> method denies enabling
  22.317 +     *          subclassing.
  22.318 +     * @see SecurityManager#checkPermission
  22.319 +     * @see java.io.SerializablePermission
  22.320 +     */
  22.321 +    protected ObjectInputStream() throws IOException, SecurityException {
  22.322 +        SecurityManager sm = System.getSecurityManager();
  22.323 +        if (sm != null) {
  22.324 +            sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
  22.325 +        }
  22.326 +        bin = null;
  22.327 +        handles = null;
  22.328 +        vlist = null;
  22.329 +        enableOverride = true;
  22.330 +    }
  22.331 +
  22.332 +    /**
  22.333 +     * Read an object from the ObjectInputStream.  The class of the object, the
  22.334 +     * signature of the class, and the values of the non-transient and
  22.335 +     * non-static fields of the class and all of its supertypes are read.
  22.336 +     * Default deserializing for a class can be overriden using the writeObject
  22.337 +     * and readObject methods.  Objects referenced by this object are read
  22.338 +     * transitively so that a complete equivalent graph of objects is
  22.339 +     * reconstructed by readObject.
  22.340 +     *
  22.341 +     * <p>The root object is completely restored when all of its fields and the
  22.342 +     * objects it references are completely restored.  At this point the object
  22.343 +     * validation callbacks are executed in order based on their registered
  22.344 +     * priorities. The callbacks are registered by objects (in the readObject
  22.345 +     * special methods) as they are individually restored.
  22.346 +     *
  22.347 +     * <p>Exceptions are thrown for problems with the InputStream and for
  22.348 +     * classes that should not be deserialized.  All exceptions are fatal to
  22.349 +     * the InputStream and leave it in an indeterminate state; it is up to the
  22.350 +     * caller to ignore or recover the stream state.
  22.351 +     *
  22.352 +     * @throws  ClassNotFoundException Class of a serialized object cannot be
  22.353 +     *          found.
  22.354 +     * @throws  InvalidClassException Something is wrong with a class used by
  22.355 +     *          serialization.
  22.356 +     * @throws  StreamCorruptedException Control information in the
  22.357 +     *          stream is inconsistent.
  22.358 +     * @throws  OptionalDataException Primitive data was found in the
  22.359 +     *          stream instead of objects.
  22.360 +     * @throws  IOException Any of the usual Input/Output related exceptions.
  22.361 +     */
  22.362 +    public final Object readObject()
  22.363 +        throws IOException, ClassNotFoundException
  22.364 +    {
  22.365 +        if (enableOverride) {
  22.366 +            return readObjectOverride();
  22.367 +        }
  22.368 +
  22.369 +        // if nested read, passHandle contains handle of enclosing object
  22.370 +        int outerHandle = passHandle;
  22.371 +        try {
  22.372 +            Object obj = readObject0(false);
  22.373 +            handles.markDependency(outerHandle, passHandle);
  22.374 +            ClassNotFoundException ex = handles.lookupException(passHandle);
  22.375 +            if (ex != null) {
  22.376 +                throw ex;
  22.377 +            }
  22.378 +            if (depth == 0) {
  22.379 +                vlist.doCallbacks();
  22.380 +            }
  22.381 +            return obj;
  22.382 +        } finally {
  22.383 +            passHandle = outerHandle;
  22.384 +            if (closed && depth == 0) {
  22.385 +                clear();
  22.386 +            }
  22.387 +        }
  22.388 +    }
  22.389 +
  22.390 +    /**
  22.391 +     * This method is called by trusted subclasses of ObjectOutputStream that
  22.392 +     * constructed ObjectOutputStream using the protected no-arg constructor.
  22.393 +     * The subclass is expected to provide an override method with the modifier
  22.394 +     * "final".
  22.395 +     *
  22.396 +     * @return  the Object read from the stream.
  22.397 +     * @throws  ClassNotFoundException Class definition of a serialized object
  22.398 +     *          cannot be found.
  22.399 +     * @throws  OptionalDataException Primitive data was found in the stream
  22.400 +     *          instead of objects.
  22.401 +     * @throws  IOException if I/O errors occurred while reading from the
  22.402 +     *          underlying stream
  22.403 +     * @see #ObjectInputStream()
  22.404 +     * @see #readObject()
  22.405 +     * @since 1.2
  22.406 +     */
  22.407 +    protected Object readObjectOverride()
  22.408 +        throws IOException, ClassNotFoundException
  22.409 +    {
  22.410 +        return null;
  22.411 +    }
  22.412 +
  22.413 +    /**
  22.414 +     * Reads an "unshared" object from the ObjectInputStream.  This method is
  22.415 +     * identical to readObject, except that it prevents subsequent calls to
  22.416 +     * readObject and readUnshared from returning additional references to the
  22.417 +     * deserialized instance obtained via this call.  Specifically:
  22.418 +     * <ul>
  22.419 +     *   <li>If readUnshared is called to deserialize a back-reference (the
  22.420 +     *       stream representation of an object which has been written
  22.421 +     *       previously to the stream), an ObjectStreamException will be
  22.422 +     *       thrown.
  22.423 +     *
  22.424 +     *   <li>If readUnshared returns successfully, then any subsequent attempts
  22.425 +     *       to deserialize back-references to the stream handle deserialized
  22.426 +     *       by readUnshared will cause an ObjectStreamException to be thrown.
  22.427 +     * </ul>
  22.428 +     * Deserializing an object via readUnshared invalidates the stream handle
  22.429 +     * associated with the returned object.  Note that this in itself does not
  22.430 +     * always guarantee that the reference returned by readUnshared is unique;
  22.431 +     * the deserialized object may define a readResolve method which returns an
  22.432 +     * object visible to other parties, or readUnshared may return a Class
  22.433 +     * object or enum constant obtainable elsewhere in the stream or through
  22.434 +     * external means. If the deserialized object defines a readResolve method
  22.435 +     * and the invocation of that method returns an array, then readUnshared
  22.436 +     * returns a shallow clone of that array; this guarantees that the returned
  22.437 +     * array object is unique and cannot be obtained a second time from an
  22.438 +     * invocation of readObject or readUnshared on the ObjectInputStream,
  22.439 +     * even if the underlying data stream has been manipulated.
  22.440 +     *
  22.441 +     * <p>ObjectInputStream subclasses which override this method can only be
  22.442 +     * constructed in security contexts possessing the
  22.443 +     * "enableSubclassImplementation" SerializablePermission; any attempt to
  22.444 +     * instantiate such a subclass without this permission will cause a
  22.445 +     * SecurityException to be thrown.
  22.446 +     *
  22.447 +     * @return  reference to deserialized object
  22.448 +     * @throws  ClassNotFoundException if class of an object to deserialize
  22.449 +     *          cannot be found
  22.450 +     * @throws  StreamCorruptedException if control information in the stream
  22.451 +     *          is inconsistent
  22.452 +     * @throws  ObjectStreamException if object to deserialize has already
  22.453 +     *          appeared in stream
  22.454 +     * @throws  OptionalDataException if primitive data is next in stream
  22.455 +     * @throws  IOException if an I/O error occurs during deserialization
  22.456 +     * @since   1.4
  22.457 +     */
  22.458 +    public Object readUnshared() throws IOException, ClassNotFoundException {
  22.459 +        // if nested read, passHandle contains handle of enclosing object
  22.460 +        int outerHandle = passHandle;
  22.461 +        try {
  22.462 +            Object obj = readObject0(true);
  22.463 +            handles.markDependency(outerHandle, passHandle);
  22.464 +            ClassNotFoundException ex = handles.lookupException(passHandle);
  22.465 +            if (ex != null) {
  22.466 +                throw ex;
  22.467 +            }
  22.468 +            if (depth == 0) {
  22.469 +                vlist.doCallbacks();
  22.470 +            }
  22.471 +            return obj;
  22.472 +        } finally {
  22.473 +            passHandle = outerHandle;
  22.474 +            if (closed && depth == 0) {
  22.475 +                clear();
  22.476 +            }
  22.477 +        }
  22.478 +    }
  22.479 +
  22.480 +    /**
  22.481 +     * Read the non-static and non-transient fields of the current class from
  22.482 +     * this stream.  This may only be called from the readObject method of the
  22.483 +     * class being deserialized. It will throw the NotActiveException if it is
  22.484 +     * called otherwise.
  22.485 +     *
  22.486 +     * @throws  ClassNotFoundException if the class of a serialized object
  22.487 +     *          could not be found.
  22.488 +     * @throws  IOException if an I/O error occurs.
  22.489 +     * @throws  NotActiveException if the stream is not currently reading
  22.490 +     *          objects.
  22.491 +     */
  22.492 +    public void defaultReadObject()
  22.493 +        throws IOException, ClassNotFoundException
  22.494 +    {
  22.495 +        if (curContext == null) {
  22.496 +            throw new NotActiveException("not in call to readObject");
  22.497 +        }
  22.498 +        Object curObj = curContext.getObj();
  22.499 +        ObjectStreamClass curDesc = curContext.getDesc();
  22.500 +        bin.setBlockDataMode(false);
  22.501 +        defaultReadFields(curObj, curDesc);
  22.502 +        bin.setBlockDataMode(true);
  22.503 +        if (!curDesc.hasWriteObjectData()) {
  22.504 +            /*
  22.505 +             * Fix for 4360508: since stream does not contain terminating
  22.506 +             * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
  22.507 +             * knows to simulate end-of-custom-data behavior.
  22.508 +             */
  22.509 +            defaultDataEnd = true;
  22.510 +        }
  22.511 +        ClassNotFoundException ex = handles.lookupException(passHandle);
  22.512 +        if (ex != null) {
  22.513 +            throw ex;
  22.514 +        }
  22.515 +    }
  22.516 +
  22.517 +    /**
  22.518 +     * Reads the persistent fields from the stream and makes them available by
  22.519 +     * name.
  22.520 +     *
  22.521 +     * @return  the <code>GetField</code> object representing the persistent
  22.522 +     *          fields of the object being deserialized
  22.523 +     * @throws  ClassNotFoundException if the class of a serialized object
  22.524 +     *          could not be found.
  22.525 +     * @throws  IOException if an I/O error occurs.
  22.526 +     * @throws  NotActiveException if the stream is not currently reading
  22.527 +     *          objects.
  22.528 +     * @since 1.2
  22.529 +     */
  22.530 +    public ObjectInputStream.GetField readFields()
  22.531 +        throws IOException, ClassNotFoundException
  22.532 +    {
  22.533 +        if (curContext == null) {
  22.534 +            throw new NotActiveException("not in call to readObject");
  22.535 +        }
  22.536 +        Object curObj = curContext.getObj();
  22.537 +        ObjectStreamClass curDesc = curContext.getDesc();
  22.538 +        bin.setBlockDataMode(false);
  22.539 +        GetFieldImpl getField = new GetFieldImpl(curDesc);
  22.540 +        getField.readFields();
  22.541 +        bin.setBlockDataMode(true);
  22.542 +        if (!curDesc.hasWriteObjectData()) {
  22.543 +            /*
  22.544 +             * Fix for 4360508: since stream does not contain terminating
  22.545 +             * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
  22.546 +             * knows to simulate end-of-custom-data behavior.
  22.547 +             */
  22.548 +            defaultDataEnd = true;
  22.549 +        }
  22.550 +
  22.551 +        return getField;
  22.552 +    }
  22.553 +
  22.554 +    /**
  22.555 +     * Register an object to be validated before the graph is returned.  While
  22.556 +     * similar to resolveObject these validations are called after the entire
  22.557 +     * graph has been reconstituted.  Typically, a readObject method will
  22.558 +     * register the object with the stream so that when all of the objects are
  22.559 +     * restored a final set of validations can be performed.
  22.560 +     *
  22.561 +     * @param   obj the object to receive the validation callback.
  22.562 +     * @param   prio controls the order of callbacks;zero is a good default.
  22.563 +     *          Use higher numbers to be called back earlier, lower numbers for
  22.564 +     *          later callbacks. Within a priority, callbacks are processed in
  22.565 +     *          no particular order.
  22.566 +     * @throws  NotActiveException The stream is not currently reading objects
  22.567 +     *          so it is invalid to register a callback.
  22.568 +     * @throws  InvalidObjectException The validation object is null.
  22.569 +     */
  22.570 +    public void registerValidation(ObjectInputValidation obj, int prio)
  22.571 +        throws NotActiveException, InvalidObjectException
  22.572 +    {
  22.573 +        if (depth == 0) {
  22.574 +            throw new NotActiveException("stream inactive");
  22.575 +        }
  22.576 +        vlist.register(obj, prio);
  22.577 +    }
  22.578 +
  22.579 +    /**
  22.580 +     * Load the local class equivalent of the specified stream class
  22.581 +     * description.  Subclasses may implement this method to allow classes to
  22.582 +     * be fetched from an alternate source.
  22.583 +     *
  22.584 +     * <p>The corresponding method in <code>ObjectOutputStream</code> is
  22.585 +     * <code>annotateClass</code>.  This method will be invoked only once for
  22.586 +     * each unique class in the stream.  This method can be implemented by
  22.587 +     * subclasses to use an alternate loading mechanism but must return a
  22.588 +     * <code>Class</code> object. Once returned, if the class is not an array
  22.589 +     * class, its serialVersionUID is compared to the serialVersionUID of the
  22.590 +     * serialized class, and if there is a mismatch, the deserialization fails
  22.591 +     * and an {@link InvalidClassException} is thrown.
  22.592 +     *
  22.593 +     * <p>The default implementation of this method in
  22.594 +     * <code>ObjectInputStream</code> returns the result of calling
  22.595 +     * <pre>
  22.596 +     *     Class.forName(desc.getName(), false, loader)
  22.597 +     * </pre>
  22.598 +     * where <code>loader</code> is determined as follows: if there is a
  22.599 +     * method on the current thread's stack whose declaring class was
  22.600 +     * defined by a user-defined class loader (and was not a generated to
  22.601 +     * implement reflective invocations), then <code>loader</code> is class
  22.602 +     * loader corresponding to the closest such method to the currently
  22.603 +     * executing frame; otherwise, <code>loader</code> is
  22.604 +     * <code>null</code>. If this call results in a
  22.605 +     * <code>ClassNotFoundException</code> and the name of the passed
  22.606 +     * <code>ObjectStreamClass</code> instance is the Java language keyword
  22.607 +     * for a primitive type or void, then the <code>Class</code> object
  22.608 +     * representing that primitive type or void will be returned
  22.609 +     * (e.g., an <code>ObjectStreamClass</code> with the name
  22.610 +     * <code>"int"</code> will be resolved to <code>Integer.TYPE</code>).
  22.611 +     * Otherwise, the <code>ClassNotFoundException</code> will be thrown to
  22.612 +     * the caller of this method.
  22.613 +     *
  22.614 +     * @param   desc an instance of class <code>ObjectStreamClass</code>
  22.615 +     * @return  a <code>Class</code> object corresponding to <code>desc</code>
  22.616 +     * @throws  IOException any of the usual Input/Output exceptions.
  22.617 +     * @throws  ClassNotFoundException if class of a serialized object cannot
  22.618 +     *          be found.
  22.619 +     */
  22.620 +    protected Class<?> resolveClass(ObjectStreamClass desc)
  22.621 +        throws IOException, ClassNotFoundException
  22.622 +    {
  22.623 +        String name = desc.getName();
  22.624 +        try {
  22.625 +            return Class.forName(name, false, latestUserDefinedLoader());
  22.626 +        } catch (ClassNotFoundException ex) {
  22.627 +            Class<?> cl = primClasses.get(name);
  22.628 +            if (cl != null) {
  22.629 +                return cl;
  22.630 +            } else {
  22.631 +                throw ex;
  22.632 +            }
  22.633 +        }
  22.634 +    }
  22.635 +
  22.636 +    /**
  22.637 +     * Returns a proxy class that implements the interfaces named in a proxy
  22.638 +     * class descriptor; subclasses may implement this method to read custom
  22.639 +     * data from the stream along with the descriptors for dynamic proxy
  22.640 +     * classes, allowing them to use an alternate loading mechanism for the
  22.641 +     * interfaces and the proxy class.
  22.642 +     *
  22.643 +     * <p>This method is called exactly once for each unique proxy class
  22.644 +     * descriptor in the stream.
  22.645 +     *
  22.646 +     * <p>The corresponding method in <code>ObjectOutputStream</code> is
  22.647 +     * <code>annotateProxyClass</code>.  For a given subclass of
  22.648 +     * <code>ObjectInputStream</code> that overrides this method, the
  22.649 +     * <code>annotateProxyClass</code> method in the corresponding subclass of
  22.650 +     * <code>ObjectOutputStream</code> must write any data or objects read by
  22.651 +     * this method.
  22.652 +     *
  22.653 +     * <p>The default implementation of this method in
  22.654 +     * <code>ObjectInputStream</code> returns the result of calling
  22.655 +     * <code>Proxy.getProxyClass</code> with the list of <code>Class</code>
  22.656 +     * objects for the interfaces that are named in the <code>interfaces</code>
  22.657 +     * parameter.  The <code>Class</code> object for each interface name
  22.658 +     * <code>i</code> is the value returned by calling
  22.659 +     * <pre>
  22.660 +     *     Class.forName(i, false, loader)
  22.661 +     * </pre>
  22.662 +     * where <code>loader</code> is that of the first non-<code>null</code>
  22.663 +     * class loader up the execution stack, or <code>null</code> if no
  22.664 +     * non-<code>null</code> class loaders are on the stack (the same class
  22.665 +     * loader choice used by the <code>resolveClass</code> method).  Unless any
  22.666 +     * of the resolved interfaces are non-public, this same value of
  22.667 +     * <code>loader</code> is also the class loader passed to
  22.668 +     * <code>Proxy.getProxyClass</code>; if non-public interfaces are present,
  22.669 +     * their class loader is passed instead (if more than one non-public
  22.670 +     * interface class loader is encountered, an
  22.671 +     * <code>IllegalAccessError</code> is thrown).
  22.672 +     * If <code>Proxy.getProxyClass</code> throws an
  22.673 +     * <code>IllegalArgumentException</code>, <code>resolveProxyClass</code>
  22.674 +     * will throw a <code>ClassNotFoundException</code> containing the
  22.675 +     * <code>IllegalArgumentException</code>.
  22.676 +     *
  22.677 +     * @param interfaces the list of interface names that were
  22.678 +     *                deserialized in the proxy class descriptor
  22.679 +     * @return  a proxy class for the specified interfaces
  22.680 +     * @throws        IOException any exception thrown by the underlying
  22.681 +     *                <code>InputStream</code>
  22.682 +     * @throws        ClassNotFoundException if the proxy class or any of the
  22.683 +     *                named interfaces could not be found
  22.684 +     * @see ObjectOutputStream#annotateProxyClass(Class)
  22.685 +     * @since 1.3
  22.686 +     */
  22.687 +    protected Class<?> resolveProxyClass(String[] interfaces)
  22.688 +        throws IOException, ClassNotFoundException
  22.689 +    {
  22.690 +        ClassLoader latestLoader = latestUserDefinedLoader();
  22.691 +        ClassLoader nonPublicLoader = null;
  22.692 +        boolean hasNonPublicInterface = false;
  22.693 +
  22.694 +        // define proxy in class loader of non-public interface(s), if any
  22.695 +        Class[] classObjs = new Class[interfaces.length];
  22.696 +        for (int i = 0; i < interfaces.length; i++) {
  22.697 +            Class cl = Class.forName(interfaces[i], false, latestLoader);
  22.698 +            if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
  22.699 +                if (hasNonPublicInterface) {
  22.700 +                    if (nonPublicLoader != cl.getClassLoader()) {
  22.701 +                        throw new IllegalAccessError(
  22.702 +                            "conflicting non-public interface class loaders");
  22.703 +                    }
  22.704 +                } else {
  22.705 +                    nonPublicLoader = cl.getClassLoader();
  22.706 +                    hasNonPublicInterface = true;
  22.707 +                }
  22.708 +            }
  22.709 +            classObjs[i] = cl;
  22.710 +        }
  22.711 +        try {
  22.712 +            return Proxy.getProxyClass(
  22.713 +                hasNonPublicInterface ? nonPublicLoader : latestLoader,
  22.714 +                classObjs);
  22.715 +        } catch (IllegalArgumentException e) {
  22.716 +            throw new ClassNotFoundException(null, e);
  22.717 +        }
  22.718 +    }
  22.719 +
  22.720 +    /**
  22.721 +     * This method will allow trusted subclasses of ObjectInputStream to
  22.722 +     * substitute one object for another during deserialization. Replacing
  22.723 +     * objects is disabled until enableResolveObject is called. The
  22.724 +     * enableResolveObject method checks that the stream requesting to resolve
  22.725 +     * object can be trusted. Every reference to serializable objects is passed
  22.726 +     * to resolveObject.  To insure that the private state of objects is not
  22.727 +     * unintentionally exposed only trusted streams may use resolveObject.
  22.728 +     *
  22.729 +     * <p>This method is called after an object has been read but before it is
  22.730 +     * returned from readObject.  The default resolveObject method just returns
  22.731 +     * the same object.
  22.732 +     *
  22.733 +     * <p>When a subclass is replacing objects it must insure that the
  22.734 +     * substituted object is compatible with every field where the reference
  22.735 +     * will be stored.  Objects whose type is not a subclass of the type of the
  22.736 +     * field or array element abort the serialization by raising an exception
  22.737 +     * and the object is not be stored.
  22.738 +     *
  22.739 +     * <p>This method is called only once when each object is first
  22.740 +     * encountered.  All subsequent references to the object will be redirected
  22.741 +     * to the new object.
  22.742 +     *
  22.743 +     * @param   obj object to be substituted
  22.744 +     * @return  the substituted object
  22.745 +     * @throws  IOException Any of the usual Input/Output exceptions.
  22.746 +     */
  22.747 +    protected Object resolveObject(Object obj) throws IOException {
  22.748 +        return obj;
  22.749 +    }
  22.750 +
  22.751 +    /**
  22.752 +     * Enable the stream to allow objects read from the stream to be replaced.
  22.753 +     * When enabled, the resolveObject method is called for every object being
  22.754 +     * deserialized.
  22.755 +     *
  22.756 +     * <p>If <i>enable</i> is true, and there is a security manager installed,
  22.757 +     * this method first calls the security manager's
  22.758 +     * <code>checkPermission</code> method with the
  22.759 +     * <code>SerializablePermission("enableSubstitution")</code> permission to
  22.760 +     * ensure it's ok to enable the stream to allow objects read from the
  22.761 +     * stream to be replaced.
  22.762 +     *
  22.763 +     * @param   enable true for enabling use of <code>resolveObject</code> for
  22.764 +     *          every object being deserialized
  22.765 +     * @return  the previous setting before this method was invoked
  22.766 +     * @throws  SecurityException if a security manager exists and its
  22.767 +     *          <code>checkPermission</code> method denies enabling the stream
  22.768 +     *          to allow objects read from the stream to be replaced.
  22.769 +     * @see SecurityManager#checkPermission
  22.770 +     * @see java.io.SerializablePermission
  22.771 +     */
  22.772 +    protected boolean enableResolveObject(boolean enable)
  22.773 +        throws SecurityException
  22.774 +    {
  22.775 +        if (enable == enableResolve) {
  22.776 +            return enable;
  22.777 +        }
  22.778 +        if (enable) {
  22.779 +            SecurityManager sm = System.getSecurityManager();
  22.780 +            if (sm != null) {
  22.781 +                sm.checkPermission(SUBSTITUTION_PERMISSION);
  22.782 +            }
  22.783 +        }
  22.784 +        enableResolve = enable;
  22.785 +        return !enableResolve;
  22.786 +    }
  22.787 +
  22.788 +    /**
  22.789 +     * The readStreamHeader method is provided to allow subclasses to read and
  22.790 +     * verify their own stream headers. It reads and verifies the magic number
  22.791 +     * and version number.
  22.792 +     *
  22.793 +     * @throws  IOException if there are I/O errors while reading from the
  22.794 +     *          underlying <code>InputStream</code>
  22.795 +     * @throws  StreamCorruptedException if control information in the stream
  22.796 +     *          is inconsistent
  22.797 +     */
  22.798 +    protected void readStreamHeader()
  22.799 +        throws IOException, StreamCorruptedException
  22.800 +    {
  22.801 +        short s0 = bin.readShort();
  22.802 +        short s1 = bin.readShort();
  22.803 +        if (s0 != STREAM_MAGIC || s1 != STREAM_VERSION) {
  22.804 +            throw new StreamCorruptedException(
  22.805 +                String.format("invalid stream header: %04X%04X", s0, s1));
  22.806 +        }
  22.807 +    }
  22.808 +
  22.809 +    /**
  22.810 +     * Read a class descriptor from the serialization stream.  This method is
  22.811 +     * called when the ObjectInputStream expects a class descriptor as the next
  22.812 +     * item in the serialization stream.  Subclasses of ObjectInputStream may
  22.813 +     * override this method to read in class descriptors that have been written
  22.814 +     * in non-standard formats (by subclasses of ObjectOutputStream which have
  22.815 +     * overridden the <code>writeClassDescriptor</code> method).  By default,
  22.816 +     * this method reads class descriptors according to the format defined in
  22.817 +     * the Object Serialization specification.
  22.818 +     *
  22.819 +     * @return  the class descriptor read
  22.820 +     * @throws  IOException If an I/O error has occurred.
  22.821 +     * @throws  ClassNotFoundException If the Class of a serialized object used
  22.822 +     *          in the class descriptor representation cannot be found
  22.823 +     * @see java.io.ObjectOutputStream#writeClassDescriptor(java.io.ObjectStreamClass)
  22.824 +     * @since 1.3
  22.825 +     */
  22.826 +    protected ObjectStreamClass readClassDescriptor()
  22.827 +        throws IOException, ClassNotFoundException
  22.828 +    {
  22.829 +        ObjectStreamClass desc = new ObjectStreamClass();
  22.830 +        desc.readNonProxy(this);
  22.831 +        return desc;
  22.832 +    }
  22.833 +
  22.834 +    /**
  22.835 +     * Reads a byte of data. This method will block if no input is available.
  22.836 +     *
  22.837 +     * @return  the byte read, or -1 if the end of the stream is reached.
  22.838 +     * @throws  IOException If an I/O error has occurred.
  22.839 +     */
  22.840 +    public int read() throws IOException {
  22.841 +        return bin.read();
  22.842 +    }
  22.843 +
  22.844 +    /**
  22.845 +     * Reads into an array of bytes.  This method will block until some input
  22.846 +     * is available. Consider using java.io.DataInputStream.readFully to read
  22.847 +     * exactly 'length' bytes.
  22.848 +     *
  22.849 +     * @param   buf the buffer into which the data is read
  22.850 +     * @param   off the start offset of the data
  22.851 +     * @param   len the maximum number of bytes read
  22.852 +     * @return  the actual number of bytes read, -1 is returned when the end of
  22.853 +     *          the stream is reached.
  22.854 +     * @throws  IOException If an I/O error has occurred.
  22.855 +     * @see java.io.DataInputStream#readFully(byte[],int,int)
  22.856 +     */
  22.857 +    public int read(byte[] buf, int off, int len) throws IOException {
  22.858 +        if (buf == null) {
  22.859 +            throw new NullPointerException();
  22.860 +        }
  22.861 +        int endoff = off + len;
  22.862 +        if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
  22.863 +            throw new IndexOutOfBoundsException();
  22.864 +        }
  22.865 +        return bin.read(buf, off, len, false);
  22.866 +    }
  22.867 +
  22.868 +    /**
  22.869 +     * Returns the number of bytes that can be read without blocking.
  22.870 +     *
  22.871 +     * @return  the number of available bytes.
  22.872 +     * @throws  IOException if there are I/O errors while reading from the
  22.873 +     *          underlying <code>InputStream</code>
  22.874 +     */
  22.875 +    public int available() throws IOException {
  22.876 +        return bin.available();
  22.877 +    }
  22.878 +
  22.879 +    /**
  22.880 +     * Closes the input stream. Must be called to release any resources
  22.881 +     * associated with the stream.
  22.882 +     *
  22.883 +     * @throws  IOException If an I/O error has occurred.
  22.884 +     */
  22.885 +    public void close() throws IOException {
  22.886 +        /*
  22.887 +         * Even if stream already closed, propagate redundant close to
  22.888 +         * underlying stream to stay consistent with previous implementations.
  22.889 +         */
  22.890 +        closed = true;
  22.891 +        if (depth == 0) {
  22.892 +            clear();
  22.893 +        }
  22.894 +        bin.close();
  22.895 +    }
  22.896 +
  22.897 +    /**
  22.898 +     * Reads in a boolean.
  22.899 +     *
  22.900 +     * @return  the boolean read.
  22.901 +     * @throws  EOFException If end of file is reached.
  22.902 +     * @throws  IOException If other I/O error has occurred.
  22.903 +     */
  22.904 +    public boolean readBoolean() throws IOException {
  22.905 +        return bin.readBoolean();
  22.906 +    }
  22.907 +
  22.908 +    /**
  22.909 +     * Reads an 8 bit byte.
  22.910 +     *
  22.911 +     * @return  the 8 bit byte read.
  22.912 +     * @throws  EOFException If end of file is reached.
  22.913 +     * @throws  IOException If other I/O error has occurred.
  22.914 +     */
  22.915 +    public byte readByte() throws IOException  {
  22.916 +        return bin.readByte();
  22.917 +    }
  22.918 +
  22.919 +    /**
  22.920 +     * Reads an unsigned 8 bit byte.
  22.921 +     *
  22.922 +     * @return  the 8 bit byte read.
  22.923 +     * @throws  EOFException If end of file is reached.
  22.924 +     * @throws  IOException If other I/O error has occurred.
  22.925 +     */
  22.926 +    public int readUnsignedByte()  throws IOException {
  22.927 +        return bin.readUnsignedByte();
  22.928 +    }
  22.929 +
  22.930 +    /**
  22.931 +     * Reads a 16 bit char.
  22.932 +     *
  22.933 +     * @return  the 16 bit char read.
  22.934 +     * @throws  EOFException If end of file is reached.
  22.935 +     * @throws  IOException If other I/O error has occurred.
  22.936 +     */
  22.937 +    public char readChar()  throws IOException {
  22.938 +        return bin.readChar();
  22.939 +    }
  22.940 +
  22.941 +    /**
  22.942 +     * Reads a 16 bit short.
  22.943 +     *
  22.944 +     * @return  the 16 bit short read.
  22.945 +     * @throws  EOFException If end of file is reached.
  22.946 +     * @throws  IOException If other I/O error has occurred.
  22.947 +     */
  22.948 +    public short readShort()  throws IOException {
  22.949 +        return bin.readShort();
  22.950 +    }
  22.951 +
  22.952 +    /**
  22.953 +     * Reads an unsigned 16 bit short.
  22.954 +     *
  22.955 +     * @return  the 16 bit short read.
  22.956 +     * @throws  EOFException If end of file is reached.
  22.957 +     * @throws  IOException If other I/O error has occurred.
  22.958 +     */
  22.959 +    public int readUnsignedShort() throws IOException {
  22.960 +        return bin.readUnsignedShort();
  22.961 +    }
  22.962 +
  22.963 +    /**
  22.964 +     * Reads a 32 bit int.
  22.965 +     *
  22.966 +     * @return  the 32 bit integer read.
  22.967 +     * @throws  EOFException If end of file is reached.
  22.968 +     * @throws  IOException If other I/O error has occurred.
  22.969 +     */
  22.970 +    public int readInt()  throws IOException {
  22.971 +        return bin.readInt();
  22.972 +    }
  22.973 +
  22.974 +    /**
  22.975 +     * Reads a 64 bit long.
  22.976 +     *
  22.977 +     * @return  the read 64 bit long.
  22.978 +     * @throws  EOFException If end of file is reached.
  22.979 +     * @throws  IOException If other I/O error has occurred.
  22.980 +     */
  22.981 +    public long readLong()  throws IOException {
  22.982 +        return bin.readLong();
  22.983 +    }
  22.984 +
  22.985 +    /**
  22.986 +     * Reads a 32 bit float.
  22.987 +     *
  22.988 +     * @return  the 32 bit float read.
  22.989 +     * @throws  EOFException If end of file is reached.
  22.990 +     * @throws  IOException If other I/O error has occurred.
  22.991 +     */
  22.992 +    public float readFloat() throws IOException {
  22.993 +        return bin.readFloat();
  22.994 +    }
  22.995 +
  22.996 +    /**
  22.997 +     * Reads a 64 bit double.
  22.998 +     *
  22.999 +     * @return  the 64 bit double read.
 22.1000 +     * @throws  EOFException If end of file is reached.
 22.1001 +     * @throws  IOException If other I/O error has occurred.
 22.1002 +     */
 22.1003 +    public double readDouble() throws IOException {
 22.1004 +        return bin.readDouble();
 22.1005 +    }
 22.1006 +
 22.1007 +    /**
 22.1008 +     * Reads bytes, blocking until all bytes are read.
 22.1009 +     *
 22.1010 +     * @param   buf the buffer into which the data is read
 22.1011 +     * @throws  EOFException If end of file is reached.
 22.1012 +     * @throws  IOException If other I/O error has occurred.
 22.1013 +     */
 22.1014 +    public void readFully(byte[] buf) throws IOException {
 22.1015 +        bin.readFully(buf, 0, buf.length, false);
 22.1016 +    }
 22.1017 +
 22.1018 +    /**
 22.1019 +     * Reads bytes, blocking until all bytes are read.
 22.1020 +     *
 22.1021 +     * @param   buf the buffer into which the data is read
 22.1022 +     * @param   off the start offset of the data
 22.1023 +     * @param   len the maximum number of bytes to read
 22.1024 +     * @throws  EOFException If end of file is reached.
 22.1025 +     * @throws  IOException If other I/O error has occurred.
 22.1026 +     */
 22.1027 +    public void readFully(byte[] buf, int off, int len) throws IOException {
 22.1028 +        int endoff = off + len;
 22.1029 +        if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
 22.1030 +            throw new IndexOutOfBoundsException();
 22.1031 +        }
 22.1032 +        bin.readFully(buf, off, len, false);
 22.1033 +    }
 22.1034 +
 22.1035 +    /**
 22.1036 +     * Skips bytes.
 22.1037 +     *
 22.1038 +     * @param   len the number of bytes to be skipped
 22.1039 +     * @return  the actual number of bytes skipped.
 22.1040 +     * @throws  IOException If an I/O error has occurred.
 22.1041 +     */
 22.1042 +    public int skipBytes(int len) throws IOException {
 22.1043 +        return bin.skipBytes(len);
 22.1044 +    }
 22.1045 +
 22.1046 +    /**
 22.1047 +     * Reads in a line that has been terminated by a \n, \r, \r\n or EOF.
 22.1048 +     *
 22.1049 +     * @return  a String copy of the line.
 22.1050 +     * @throws  IOException if there are I/O errors while reading from the
 22.1051 +     *          underlying <code>InputStream</code>
 22.1052 +     * @deprecated This method does not properly convert bytes to characters.
 22.1053 +     *          see DataInputStream for the details and alternatives.
 22.1054 +     */
 22.1055 +    @Deprecated
 22.1056 +    public String readLine() throws IOException {
 22.1057 +        return bin.readLine();
 22.1058 +    }
 22.1059 +
 22.1060 +    /**
 22.1061 +     * Reads a String in
 22.1062 +     * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
 22.1063 +     * format.
 22.1064 +     *
 22.1065 +     * @return  the String.
 22.1066 +     * @throws  IOException if there are I/O errors while reading from the
 22.1067 +     *          underlying <code>InputStream</code>
 22.1068 +     * @throws  UTFDataFormatException if read bytes do not represent a valid
 22.1069 +     *          modified UTF-8 encoding of a string
 22.1070 +     */
 22.1071 +    public String readUTF() throws IOException {
 22.1072 +        return bin.readUTF();
 22.1073 +    }
 22.1074 +
 22.1075 +    /**
 22.1076 +     * Provide access to the persistent fields read from the input stream.
 22.1077 +     */
 22.1078 +    public static abstract class GetField {
 22.1079 +
 22.1080 +        /**
 22.1081 +         * Get the ObjectStreamClass that describes the fields in the stream.
 22.1082 +         *
 22.1083 +         * @return  the descriptor class that describes the serializable fields
 22.1084 +         */
 22.1085 +        public abstract ObjectStreamClass getObjectStreamClass();
 22.1086 +
 22.1087 +        /**
 22.1088 +         * Return true if the named field is defaulted and has no value in this
 22.1089 +         * stream.
 22.1090 +         *
 22.1091 +         * @param  name the name of the field
 22.1092 +         * @return true, if and only if the named field is defaulted
 22.1093 +         * @throws IOException if there are I/O errors while reading from
 22.1094 +         *         the underlying <code>InputStream</code>
 22.1095 +         * @throws IllegalArgumentException if <code>name</code> does not
 22.1096 +         *         correspond to a serializable field
 22.1097 +         */
 22.1098 +        public abstract boolean defaulted(String name) throws IOException;
 22.1099 +
 22.1100 +        /**
 22.1101 +         * Get the value of the named boolean field from the persistent field.
 22.1102 +         *
 22.1103 +         * @param  name the name of the field
 22.1104 +         * @param  val the default value to use if <code>name</code> does not
 22.1105 +         *         have a value
 22.1106 +         * @return the value of the named <code>boolean</code> field
 22.1107 +         * @throws IOException if there are I/O errors while reading from the
 22.1108 +         *         underlying <code>InputStream</code>
 22.1109 +         * @throws IllegalArgumentException if type of <code>name</code> is
 22.1110 +         *         not serializable or if the field type is incorrect
 22.1111 +         */
 22.1112 +        public abstract boolean get(String name, boolean val)
 22.1113 +            throws IOException;
 22.1114 +
 22.1115 +        /**
 22.1116 +         * Get the value of the named byte field from the persistent field.
 22.1117 +         *
 22.1118 +         * @param  name the name of the field
 22.1119 +         * @param  val the default value to use if <code>name</code> does not
 22.1120 +         *         have a value
 22.1121 +         * @return the value of the named <code>byte</code> field
 22.1122 +         * @throws IOException if there are I/O errors while reading from the
 22.1123 +         *         underlying <code>InputStream</code>
 22.1124 +         * @throws IllegalArgumentException if type of <code>name</code> is
 22.1125 +         *         not serializable or if the field type is incorrect
 22.1126 +         */
 22.1127 +        public abstract byte get(String name, byte val) throws IOException;
 22.1128 +
 22.1129 +        /**
 22.1130 +         * Get the value of the named char field from the persistent field.
 22.1131 +         *
 22.1132 +         * @param  name the name of the field
 22.1133 +         * @param  val the default value to use if <code>name</code> does not
 22.1134 +         *         have a value
 22.1135 +         * @return the value of the named <code>char</code> field
 22.1136 +         * @throws IOException if there are I/O errors while reading from the
 22.1137 +         *         underlying <code>InputStream</code>
 22.1138 +         * @throws IllegalArgumentException if type of <code>name</code> is
 22.1139 +         *         not serializable or if the field type is incorrect
 22.1140 +         */
 22.1141 +        public abstract char get(String name, char val) throws IOException;
 22.1142 +
 22.1143 +        /**
 22.1144 +         * Get the value of the named short field from the persistent field.
 22.1145 +         *
 22.1146 +         * @param  name the name of the field
 22.1147 +         * @param  val the default value to use if <code>name</code> does not
 22.1148 +         *         have a value
 22.1149 +         * @return the value of the named <code>short</code> field
 22.1150 +         * @throws IOException if there are I/O errors while reading from the
 22.1151 +         *         underlying <code>InputStream</code>
 22.1152 +         * @throws IllegalArgumentException if type of <code>name</code> is
 22.1153 +         *         not serializable or if the field type is incorrect
 22.1154 +         */
 22.1155 +        public abstract short get(String name, short val) throws IOException;
 22.1156 +
 22.1157 +        /**
 22.1158 +         * Get the value of the named int field from the persistent field.
 22.1159 +         *
 22.1160 +         * @param  name the name of the field
 22.1161 +         * @param  val the default value to use if <code>name</code> does not
 22.1162 +         *         have a value
 22.1163 +         * @return the value of the named <code>int</code> field
 22.1164 +         * @throws IOException if there are I/O errors while reading from the
 22.1165 +         *         underlying <code>InputStream</code>
 22.1166 +         * @throws IllegalArgumentException if type of <code>name</code> is
 22.1167 +         *         not serializable or if the field type is incorrect
 22.1168 +         */
 22.1169 +        public abstract int get(String name, int val) throws IOException;
 22.1170 +
 22.1171 +        /**
 22.1172 +         * Get the value of the named long field from the persistent field.
 22.1173 +         *
 22.1174 +         * @param  name the name of the field
 22.1175 +         * @param  val the default value to use if <code>name</code> does not
 22.1176 +         *         have a value
 22.1177 +         * @return the value of the named <code>long</code> field
 22.1178 +         * @throws IOException if there are I/O errors while reading from the
 22.1179 +         *         underlying <code>InputStream</code>
 22.1180 +         * @throws IllegalArgumentException if type of <code>name</code> is
 22.1181 +         *         not serializable or if the field type is incorrect
 22.1182 +         */
 22.1183 +        public abstract long get(String name, long val) throws IOException;
 22.1184 +
 22.1185 +        /**
 22.1186 +         * Get the value of the named float field from the persistent field.
 22.1187 +         *
 22.1188 +         * @param  name the name of the field
 22.1189 +         * @param  val the default value to use if <code>name</code> does not
 22.1190 +         *         have a value
 22.1191 +         * @return the value of the named <code>float</code> field
 22.1192 +         * @throws IOException if there are I/O errors while reading from the
 22.1193 +         *         underlying <code>InputStream</code>
 22.1194 +         * @throws IllegalArgumentException if type of <code>name</code> is
 22.1195 +         *         not serializable or if the field type is incorrect
 22.1196 +         */
 22.1197 +        public abstract float get(String name, float val) throws IOException;
 22.1198 +
 22.1199 +        /**
 22.1200 +         * Get the value of the named double field from the persistent field.
 22.1201 +         *
 22.1202 +         * @param  name the name of the field
 22.1203 +         * @param  val the default value to use if <code>name</code> does not
 22.1204 +         *         have a value
 22.1205 +         * @return the value of the named <code>double</code> field
 22.1206 +         * @throws IOException if there are I/O errors while reading from the
 22.1207 +         *         underlying <code>InputStream</code>
 22.1208 +         * @throws IllegalArgumentException if type of <code>name</code> is
 22.1209 +         *         not serializable or if the field type is incorrect
 22.1210 +         */
 22.1211 +        public abstract double get(String name, double val) throws IOException;
 22.1212 +
 22.1213 +        /**
 22.1214 +         * Get the value of the named Object field from the persistent field.
 22.1215 +         *
 22.1216 +         * @param  name the name of the field
 22.1217 +         * @param  val the default value to use if <code>name</code> does not
 22.1218 +         *         have a value
 22.1219 +         * @return the value of the named <code>Object</code> field
 22.1220 +         * @throws IOException if there are I/O errors while reading from the
 22.1221 +         *         underlying <code>InputStream</code>
 22.1222 +         * @throws IllegalArgumentException if type of <code>name</code> is
 22.1223 +         *         not serializable or if the field type is incorrect
 22.1224 +         */
 22.1225 +        public abstract Object get(String name, Object val) throws IOException;
 22.1226 +    }
 22.1227 +
 22.1228 +    /**
 22.1229 +     * Verifies that this (possibly subclass) instance can be constructed
 22.1230 +     * without violating security constraints: the subclass must not override
 22.1231 +     * security-sensitive non-final methods, or else the
 22.1232 +     * "enableSubclassImplementation" SerializablePermission is checked.
 22.1233 +     */
 22.1234 +    private void verifySubclass() {
 22.1235 +        Class cl = getClass();
 22.1236 +        if (cl == ObjectInputStream.class) {
 22.1237 +            return;
 22.1238 +        }
 22.1239 +        SecurityManager sm = System.getSecurityManager();
 22.1240 +        if (sm == null) {
 22.1241 +            return;
 22.1242 +        }
 22.1243 +        processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
 22.1244 +        WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
 22.1245 +        Boolean result = Caches.subclassAudits.get(key);
 22.1246 +        if (result == null) {
 22.1247 +            result = Boolean.valueOf(auditSubclass(cl));
 22.1248 +            Caches.subclassAudits.putIfAbsent(key, result);
 22.1249 +        }
 22.1250 +        if (result.booleanValue()) {
 22.1251 +            return;
 22.1252 +        }
 22.1253 +        sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
 22.1254 +    }
 22.1255 +
 22.1256 +    /**
 22.1257 +     * Performs reflective checks on given subclass to verify that it doesn't
 22.1258 +     * override security-sensitive non-final methods.  Returns true if subclass
 22.1259 +     * is "safe", false otherwise.
 22.1260 +     */
 22.1261 +    private static boolean auditSubclass(final Class<?> subcl) {
 22.1262 +        Boolean result = AccessController.doPrivileged(
 22.1263 +            new PrivilegedAction<Boolean>() {
 22.1264 +                public Boolean run() {
 22.1265 +                    for (Class<?> cl = subcl;
 22.1266 +                         cl != ObjectInputStream.class;
 22.1267 +                         cl = cl.getSuperclass())
 22.1268 +                    {
 22.1269 +                        try {
 22.1270 +                            cl.getDeclaredMethod(
 22.1271 +                                "readUnshared", (Class[]) null);
 22.1272 +                            return Boolean.FALSE;
 22.1273 +                        } catch (NoSuchMethodException ex) {
 22.1274 +                        }
 22.1275 +                        try {
 22.1276 +                            cl.getDeclaredMethod("readFields", (Class[]) null);
 22.1277 +                            return Boolean.FALSE;
 22.1278 +                        } catch (NoSuchMethodException ex) {
 22.1279 +                        }
 22.1280 +                    }
 22.1281 +                    return Boolean.TRUE;
 22.1282 +                }
 22.1283 +            }
 22.1284 +        );
 22.1285 +        return result.booleanValue();
 22.1286 +    }
 22.1287 +
 22.1288 +    /**
 22.1289 +     * Clears internal data structures.
 22.1290 +     */
 22.1291 +    private void clear() {
 22.1292 +        handles.clear();
 22.1293 +        vlist.clear();
 22.1294 +    }
 22.1295 +
 22.1296 +    /**
 22.1297 +     * Underlying readObject implementation.
 22.1298 +     */
 22.1299 +    private Object readObject0(boolean unshared) throws IOException {
 22.1300 +        boolean oldMode = bin.getBlockDataMode();
 22.1301 +        if (oldMode) {
 22.1302 +            int remain = bin.currentBlockRemaining();
 22.1303 +            if (remain > 0) {
 22.1304 +                throw new OptionalDataException(remain);
 22.1305 +            } else if (defaultDataEnd) {
 22.1306 +                /*
 22.1307 +                 * Fix for 4360508: stream is currently at the end of a field
 22.1308 +                 * value block written via default serialization; since there
 22.1309 +                 * is no terminating TC_ENDBLOCKDATA tag, simulate
 22.1310 +                 * end-of-custom-data behavior explicitly.
 22.1311 +                 */
 22.1312 +                throw new OptionalDataException(true);
 22.1313 +            }
 22.1314 +            bin.setBlockDataMode(false);
 22.1315 +        }
 22.1316 +
 22.1317 +        byte tc;
 22.1318 +        while ((tc = bin.peekByte()) == TC_RESET) {
 22.1319 +            bin.readByte();
 22.1320 +            handleReset();
 22.1321 +        }
 22.1322 +
 22.1323 +        depth++;
 22.1324 +        try {
 22.1325 +            switch (tc) {
 22.1326 +                case TC_NULL:
 22.1327 +                    return readNull();
 22.1328 +
 22.1329 +                case TC_REFERENCE:
 22.1330 +                    return readHandle(unshared);
 22.1331 +
 22.1332 +                case TC_CLASS:
 22.1333 +                    return readClass(unshared);
 22.1334 +
 22.1335 +                case TC_CLASSDESC:
 22.1336 +                case TC_PROXYCLASSDESC:
 22.1337 +                    return readClassDesc(unshared);
 22.1338 +
 22.1339 +                case TC_STRING:
 22.1340 +                case TC_LONGSTRING:
 22.1341 +                    return checkResolve(readString(unshared));
 22.1342 +
 22.1343 +                case TC_ARRAY:
 22.1344 +                    return checkResolve(readArray(unshared));
 22.1345 +
 22.1346 +                case TC_ENUM:
 22.1347 +                    return checkResolve(readEnum(unshared));
 22.1348 +
 22.1349 +                case TC_OBJECT:
 22.1350 +                    return checkResolve(readOrdinaryObject(unshared));
 22.1351 +
 22.1352 +                case TC_EXCEPTION:
 22.1353 +                    IOException ex = readFatalException();
 22.1354 +                    throw new WriteAbortedException("writing aborted", ex);
 22.1355 +
 22.1356 +                case TC_BLOCKDATA:
 22.1357 +                case TC_BLOCKDATALONG:
 22.1358 +                    if (oldMode) {
 22.1359 +                        bin.setBlockDataMode(true);
 22.1360 +                        bin.peek();             // force header read
 22.1361 +                        throw new OptionalDataException(
 22.1362 +                            bin.currentBlockRemaining());
 22.1363 +                    } else {
 22.1364 +                        throw new StreamCorruptedException(
 22.1365 +                            "unexpected block data");
 22.1366 +                    }
 22.1367 +
 22.1368 +                case TC_ENDBLOCKDATA:
 22.1369 +                    if (oldMode) {
 22.1370 +                        throw new OptionalDataException(true);
 22.1371 +                    } else {
 22.1372 +                        throw new StreamCorruptedException(
 22.1373 +                            "unexpected end of block data");
 22.1374 +                    }
 22.1375 +
 22.1376 +                default:
 22.1377 +                    throw new StreamCorruptedException(
 22.1378 +                        String.format("invalid type code: %02X", tc));
 22.1379 +            }
 22.1380 +        } finally {
 22.1381 +            depth--;
 22.1382 +            bin.setBlockDataMode(oldMode);
 22.1383 +        }
 22.1384 +    }
 22.1385 +
 22.1386 +    /**
 22.1387 +     * If resolveObject has been enabled and given object does not have an
 22.1388 +     * exception associated with it, calls resolveObject to determine
 22.1389 +     * replacement for object, and updates handle table accordingly.  Returns
 22.1390 +     * replacement object, or echoes provided object if no replacement
 22.1391 +     * occurred.  Expects that passHandle is set to given object's handle prior
 22.1392 +     * to calling this method.
 22.1393 +     */
 22.1394 +    private Object checkResolve(Object obj) throws IOException {
 22.1395 +        if (!enableResolve || handles.lookupException(passHandle) != null) {
 22.1396 +            return obj;
 22.1397 +        }
 22.1398 +        Object rep = resolveObject(obj);
 22.1399 +        if (rep != obj) {
 22.1400 +            handles.setObject(passHandle, rep);
 22.1401 +        }
 22.1402 +        return rep;
 22.1403 +    }
 22.1404 +
 22.1405 +    /**
 22.1406 +     * Reads string without allowing it to be replaced in stream.  Called from
 22.1407 +     * within ObjectStreamClass.read().
 22.1408 +     */
 22.1409 +    String readTypeString() throws IOException {
 22.1410 +        int oldHandle = passHandle;
 22.1411 +        try {
 22.1412 +            byte tc = bin.peekByte();
 22.1413 +            switch (tc) {
 22.1414 +                case TC_NULL:
 22.1415 +                    return (String) readNull();
 22.1416 +
 22.1417 +                case TC_REFERENCE:
 22.1418 +                    return (String) readHandle(false);
 22.1419 +
 22.1420 +                case TC_STRING:
 22.1421 +                case TC_LONGSTRING:
 22.1422 +                    return readString(false);
 22.1423 +
 22.1424 +                default:
 22.1425 +                    throw new StreamCorruptedException(
 22.1426 +                        String.format("invalid type code: %02X", tc));
 22.1427 +            }
 22.1428 +        } finally {
 22.1429 +            passHandle = oldHandle;
 22.1430 +        }
 22.1431 +    }
 22.1432 +
 22.1433 +    /**
 22.1434 +     * Reads in null code, sets passHandle to NULL_HANDLE and returns null.
 22.1435 +     */
 22.1436 +    private Object readNull() throws IOException {
 22.1437 +        if (bin.readByte() != TC_NULL) {
 22.1438 +            throw new InternalError();
 22.1439 +        }
 22.1440 +        passHandle = NULL_HANDLE;
 22.1441 +        return null;
 22.1442 +    }
 22.1443 +
 22.1444 +    /**
 22.1445 +     * Reads in object handle, sets passHandle to the read handle, and returns
 22.1446 +     * object associated with the handle.
 22.1447 +     */
 22.1448 +    private Object readHandle(boolean unshared) throws IOException {
 22.1449 +        if (bin.readByte() != TC_REFERENCE) {
 22.1450 +            throw new InternalError();
 22.1451 +        }
 22.1452 +        passHandle = bin.readInt() - baseWireHandle;
 22.1453 +        if (passHandle < 0 || passHandle >= handles.size()) {
 22.1454 +            throw new StreamCorruptedException(
 22.1455 +                String.format("invalid handle value: %08X", passHandle +
 22.1456 +                baseWireHandle));
 22.1457 +        }
 22.1458 +        if (unshared) {
 22.1459 +            // REMIND: what type of exception to throw here?
 22.1460 +            throw new InvalidObjectException(
 22.1461 +                "cannot read back reference as unshared");
 22.1462 +        }
 22.1463 +
 22.1464 +        Object obj = handles.lookupObject(passHandle);
 22.1465 +        if (obj == unsharedMarker) {
 22.1466 +            // REMIND: what type of exception to throw here?
 22.1467 +            throw new InvalidObjectException(
 22.1468 +                "cannot read back reference to unshared object");
 22.1469 +        }
 22.1470 +        return obj;
 22.1471 +    }
 22.1472 +
 22.1473 +    /**
 22.1474 +     * Reads in and returns class object.  Sets passHandle to class object's
 22.1475 +     * assigned handle.  Returns null if class is unresolvable (in which case a
 22.1476 +     * ClassNotFoundException will be associated with the class' handle in the
 22.1477 +     * handle table).
 22.1478 +     */
 22.1479 +    private Class readClass(boolean unshared) throws IOException {
 22.1480 +        if (bin.readByte() != TC_CLASS) {
 22.1481 +            throw new InternalError();
 22.1482 +        }
 22.1483 +        ObjectStreamClass desc = readClassDesc(false);
 22.1484 +        Class cl = desc.forClass();
 22.1485 +        passHandle = handles.assign(unshared ? unsharedMarker : cl);
 22.1486 +
 22.1487 +        ClassNotFoundException resolveEx = desc.getResolveException();
 22.1488 +        if (resolveEx != null) {
 22.1489 +            handles.markException(passHandle, resolveEx);
 22.1490 +        }
 22.1491 +
 22.1492 +        handles.finish(passHandle);
 22.1493 +        return cl;
 22.1494 +    }
 22.1495 +
 22.1496 +    /**
 22.1497 +     * Reads in and returns (possibly null) class descriptor.  Sets passHandle
 22.1498 +     * to class descriptor's assigned handle.  If class descriptor cannot be
 22.1499 +     * resolved to a class in the local VM, a ClassNotFoundException is
 22.1500 +     * associated with the class descriptor's handle.
 22.1501 +     */
 22.1502 +    private ObjectStreamClass readClassDesc(boolean unshared)
 22.1503 +        throws IOException
 22.1504 +    {
 22.1505 +        byte tc = bin.peekByte();
 22.1506 +        switch (tc) {
 22.1507 +            case TC_NULL:
 22.1508 +                return (ObjectStreamClass) readNull();
 22.1509 +
 22.1510 +            case TC_REFERENCE:
 22.1511 +                return (ObjectStreamClass) readHandle(unshared);
 22.1512 +
 22.1513 +            case TC_PROXYCLASSDESC:
 22.1514 +                return readProxyDesc(unshared);
 22.1515 +
 22.1516 +            case TC_CLASSDESC:
 22.1517 +                return readNonProxyDesc(unshared);
 22.1518 +
 22.1519 +            default:
 22.1520 +                throw new StreamCorruptedException(
 22.1521 +                    String.format("invalid type code: %02X", tc));
 22.1522 +        }
 22.1523 +    }
 22.1524 +
 22.1525 +    /**
 22.1526 +     * Reads in and returns class descriptor for a dynamic proxy class.  Sets
 22.1527 +     * passHandle to proxy class descriptor's assigned handle.  If proxy class
 22.1528 +     * descriptor cannot be resolved to a class in the local VM, a
 22.1529 +     * ClassNotFoundException is associated with the descriptor's handle.
 22.1530 +     */
 22.1531 +    private ObjectStreamClass readProxyDesc(boolean unshared)
 22.1532 +        throws IOException
 22.1533 +    {
 22.1534 +        if (bin.readByte() != TC_PROXYCLASSDESC) {
 22.1535 +            throw new InternalError();
 22.1536 +        }
 22.1537 +
 22.1538 +        ObjectStreamClass desc = new ObjectStreamClass();
 22.1539 +        int descHandle = handles.assign(unshared ? unsharedMarker : desc);
 22.1540 +        passHandle = NULL_HANDLE;
 22.1541 +
 22.1542 +        int numIfaces = bin.readInt();
 22.1543 +        String[] ifaces = new String[numIfaces];
 22.1544 +        for (int i = 0; i < numIfaces; i++) {
 22.1545 +            ifaces[i] = bin.readUTF();
 22.1546 +        }
 22.1547 +
 22.1548 +        Class cl = null;
 22.1549 +        ClassNotFoundException resolveEx = null;
 22.1550 +        bin.setBlockDataMode(true);
 22.1551 +        try {
 22.1552 +            if ((cl = resolveProxyClass(ifaces)) == null) {
 22.1553 +                resolveEx = new ClassNotFoundException("null class");
 22.1554 +            }
 22.1555 +        } catch (ClassNotFoundException ex) {
 22.1556 +            resolveEx = ex;
 22.1557 +        }
 22.1558 +        skipCustomData();
 22.1559 +
 22.1560 +        desc.initProxy(cl, resolveEx, readClassDesc(false));
 22.1561 +
 22.1562 +        handles.finish(descHandle);
 22.1563 +        passHandle = descHandle;
 22.1564 +        return desc;
 22.1565 +    }
 22.1566 +
 22.1567 +    /**
 22.1568 +     * Reads in and returns class descriptor for a class that is not a dynamic
 22.1569 +     * proxy class.  Sets passHandle to class descriptor's assigned handle.  If
 22.1570 +     * class descriptor cannot be resolved to a class in the local VM, a
 22.1571 +     * ClassNotFoundException is associated with the descriptor's handle.
 22.1572 +     */
 22.1573 +    private ObjectStreamClass readNonProxyDesc(boolean unshared)
 22.1574 +        throws IOException
 22.1575 +    {
 22.1576 +        if (bin.readByte() != TC_CLASSDESC) {
 22.1577 +            throw new InternalError();
 22.1578 +        }
 22.1579 +
 22.1580 +        ObjectStreamClass desc = new ObjectStreamClass();
 22.1581 +        int descHandle = handles.assign(unshared ? unsharedMarker : desc);
 22.1582 +        passHandle = NULL_HANDLE;
 22.1583 +
 22.1584 +        ObjectStreamClass readDesc = null;
 22.1585 +        try {
 22.1586 +            readDesc = readClassDescriptor();
 22.1587 +        } catch (ClassNotFoundException ex) {
 22.1588 +            throw (IOException) new InvalidClassException(
 22.1589 +                "failed to read class descriptor").initCause(ex);
 22.1590 +        }
 22.1591 +
 22.1592 +        Class cl = null;
 22.1593 +        ClassNotFoundException resolveEx = null;
 22.1594 +        bin.setBlockDataMode(true);
 22.1595 +        try {
 22.1596 +            if ((cl = resolveClass(readDesc)) == null) {
 22.1597 +                resolveEx = new ClassNotFoundException("null class");
 22.1598 +            }
 22.1599 +        } catch (ClassNotFoundException ex) {
 22.1600 +            resolveEx = ex;
 22.1601 +        }
 22.1602 +        skipCustomData();
 22.1603 +
 22.1604 +        desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));
 22.1605 +
 22.1606 +        handles.finish(descHandle);
 22.1607 +        passHandle = descHandle;
 22.1608 +        return desc;
 22.1609 +    }
 22.1610 +
 22.1611 +    /**
 22.1612 +     * Reads in and returns new string.  Sets passHandle to new string's
 22.1613 +     * assigned handle.
 22.1614 +     */
 22.1615 +    private String readString(boolean unshared) throws IOException {
 22.1616 +        String str;
 22.1617 +        byte tc = bin.readByte();
 22.1618 +        switch (tc) {
 22.1619 +            case TC_STRING:
 22.1620 +                str = bin.readUTF();
 22.1621 +                break;
 22.1622 +
 22.1623 +            case TC_LONGSTRING:
 22.1624 +                str = bin.readLongUTF();
 22.1625 +                break;
 22.1626 +
 22.1627 +            default:
 22.1628 +                throw new StreamCorruptedException(
 22.1629 +                    String.format("invalid type code: %02X", tc));
 22.1630 +        }
 22.1631 +        passHandle = handles.assign(unshared ? unsharedMarker : str);
 22.1632 +        handles.finish(passHandle);
 22.1633 +        return str;
 22.1634 +    }
 22.1635 +
 22.1636 +    /**
 22.1637 +     * Reads in and returns array object, or null if array class is
 22.1638 +     * unresolvable.  Sets passHandle to array's assigned handle.
 22.1639 +     */
 22.1640 +    private Object readArray(boolean unshared) throws IOException {
 22.1641 +        if (bin.readByte() != TC_ARRAY) {
 22.1642 +            throw new InternalError();
 22.1643 +        }
 22.1644 +
 22.1645 +        ObjectStreamClass desc = readClassDesc(false);
 22.1646 +        int len = bin.readInt();
 22.1647 +
 22.1648 +        Object array = null;
 22.1649 +        Class cl, ccl = null;
 22.1650 +        if ((cl = desc.forClass()) != null) {
 22.1651 +            ccl = cl.getComponentType();
 22.1652 +            array = Array.newInstance(ccl, len);
 22.1653 +        }
 22.1654 +
 22.1655 +        int arrayHandle = handles.assign(unshared ? unsharedMarker : array);
 22.1656 +        ClassNotFoundException resolveEx = desc.getResolveException();
 22.1657 +        if (resolveEx != null) {
 22.1658 +            handles.markException(arrayHandle, resolveEx);
 22.1659 +        }
 22.1660 +
 22.1661 +        if (ccl == null) {
 22.1662 +            for (int i = 0; i < len; i++) {
 22.1663 +                readObject0(false);
 22.1664 +            }
 22.1665 +        } else if (ccl.isPrimitive()) {
 22.1666 +            if (ccl == Integer.TYPE) {
 22.1667 +                bin.readInts((int[]) array, 0, len);
 22.1668 +            } else if (ccl == Byte.TYPE) {
 22.1669 +                bin.readFully((byte[]) array, 0, len, true);
 22.1670 +            } else if (ccl == Long.TYPE) {
 22.1671 +                bin.readLongs((long[]) array, 0, len);
 22.1672 +            } else if (ccl == Float.TYPE) {
 22.1673 +                bin.readFloats((float[]) array, 0, len);
 22.1674 +            } else if (ccl == Double.TYPE) {
 22.1675 +                bin.readDoubles((double[]) array, 0, len);
 22.1676 +            } else if (ccl == Short.TYPE) {
 22.1677 +                bin.readShorts((short[]) array, 0, len);
 22.1678 +            } else if (ccl == Character.TYPE) {
 22.1679 +                bin.readChars((char[]) array, 0, len);
 22.1680 +            } else if (ccl == Boolean.TYPE) {
 22.1681 +                bin.readBooleans((boolean[]) array, 0, len);
 22.1682 +            } else {
 22.1683 +                throw new InternalError();
 22.1684 +            }
 22.1685 +        } else {
 22.1686 +            Object[] oa = (Object[]) array;
 22.1687 +            for (int i = 0; i < len; i++) {
 22.1688 +                oa[i] = readObject0(false);
 22.1689 +                handles.markDependency(arrayHandle, passHandle);
 22.1690 +            }
 22.1691 +        }
 22.1692 +
 22.1693 +        handles.finish(arrayHandle);
 22.1694 +        passHandle = arrayHandle;
 22.1695 +        return array;
 22.1696 +    }
 22.1697 +
 22.1698 +    /**
 22.1699 +     * Reads in and returns enum constant, or null if enum type is
 22.1700 +     * unresolvable.  Sets passHandle to enum constant's assigned handle.
 22.1701 +     */
 22.1702 +    private Enum readEnum(boolean unshared) throws IOException {
 22.1703 +        if (bin.readByte() != TC_ENUM) {
 22.1704 +            throw new InternalError();
 22.1705 +        }
 22.1706 +
 22.1707 +        ObjectStreamClass desc = readClassDesc(false);
 22.1708 +        if (!desc.isEnum()) {
 22.1709 +            throw new InvalidClassException("non-enum class: " + desc);
 22.1710 +        }
 22.1711 +
 22.1712 +        int enumHandle = handles.assign(unshared ? unsharedMarker : null);
 22.1713 +        ClassNotFoundException resolveEx = desc.getResolveException();
 22.1714 +        if (resolveEx != null) {
 22.1715 +            handles.markException(enumHandle, resolveEx);
 22.1716 +        }
 22.1717 +
 22.1718 +        String name = readString(false);
 22.1719 +        Enum en = null;
 22.1720 +        Class cl = desc.forClass();
 22.1721 +        if (cl != null) {
 22.1722 +            try {
 22.1723 +                en = Enum.valueOf(cl, name);
 22.1724 +            } catch (IllegalArgumentException ex) {
 22.1725 +                throw (IOException) new InvalidObjectException(
 22.1726 +                    "enum constant " + name + " does not exist in " +
 22.1727 +                    cl).initCause(ex);
 22.1728 +            }
 22.1729 +            if (!unshared) {
 22.1730 +                handles.setObject(enumHandle, en);
 22.1731 +            }
 22.1732 +        }
 22.1733 +
 22.1734 +        handles.finish(enumHandle);
 22.1735 +        passHandle = enumHandle;
 22.1736 +        return en;
 22.1737 +    }
 22.1738 +
 22.1739 +    /**
 22.1740 +     * Reads and returns "ordinary" (i.e., not a String, Class,
 22.1741 +     * ObjectStreamClass, array, or enum constant) object, or null if object's
 22.1742 +     * class is unresolvable (in which case a ClassNotFoundException will be
 22.1743 +     * associated with object's handle).  Sets passHandle to object's assigned
 22.1744 +     * handle.
 22.1745 +     */
 22.1746 +    private Object readOrdinaryObject(boolean unshared)
 22.1747 +        throws IOException
 22.1748 +    {
 22.1749 +        if (bin.readByte() != TC_OBJECT) {
 22.1750 +            throw new InternalError();
 22.1751 +        }
 22.1752 +
 22.1753 +        ObjectStreamClass desc = readClassDesc(false);
 22.1754 +        desc.checkDeserialize();
 22.1755 +
 22.1756 +        Object obj;
 22.1757 +        try {
 22.1758 +            obj = desc.isInstantiable() ? desc.newInstance() : null;
 22.1759 +        } catch (Exception ex) {
 22.1760 +            throw (IOException) new InvalidClassException(
 22.1761 +                desc.forClass().getName(),
 22.1762 +                "unable to create instance").initCause(ex);
 22.1763 +        }
 22.1764 +
 22.1765 +        passHandle = handles.assign(unshared ? unsharedMarker : obj);
 22.1766 +        ClassNotFoundException resolveEx = desc.getResolveException();
 22.1767 +        if (resolveEx != null) {
 22.1768 +            handles.markException(passHandle, resolveEx);
 22.1769 +        }
 22.1770 +
 22.1771 +        if (desc.isExternalizable()) {
 22.1772 +            readExternalData((Externalizable) obj, desc);
 22.1773 +        } else {
 22.1774 +            readSerialData(obj, desc);
 22.1775 +        }
 22.1776 +
 22.1777 +        handles.finish(passHandle);
 22.1778 +
 22.1779 +        if (obj != null &&
 22.1780 +            handles.lookupException(passHandle) == null &&
 22.1781 +            desc.hasReadResolveMethod())
 22.1782 +        {
 22.1783 +            Object rep = desc.invokeReadResolve(obj);
 22.1784 +            if (unshared && rep.getClass().isArray()) {
 22.1785 +                rep = cloneArray(rep);
 22.1786 +            }
 22.1787 +            if (rep != obj) {
 22.1788 +                handles.setObject(passHandle, obj = rep);
 22.1789 +            }
 22.1790 +        }
 22.1791 +
 22.1792 +        return obj;
 22.1793 +    }
 22.1794 +
 22.1795 +    /**
 22.1796 +     * If obj is non-null, reads externalizable data by invoking readExternal()
 22.1797 +     * method of obj; otherwise, attempts to skip over externalizable data.
 22.1798 +     * Expects that passHandle is set to obj's handle before this method is
 22.1799 +     * called.
 22.1800 +     */
 22.1801 +    private void readExternalData(Externalizable obj, ObjectStreamClass desc)
 22.1802 +        throws IOException
 22.1803 +    {
 22.1804 +        SerialCallbackContext oldContext = curContext;
 22.1805 +        curContext = null;
 22.1806 +        try {
 22.1807 +            boolean blocked = desc.hasBlockExternalData();
 22.1808 +            if (blocked) {
 22.1809 +                bin.setBlockDataMode(true);
 22.1810 +            }
 22.1811 +            if (obj != null) {
 22.1812 +                try {
 22.1813 +                    obj.readExternal(this);
 22.1814 +                } catch (ClassNotFoundException ex) {
 22.1815 +                    /*
 22.1816 +                     * In most cases, the handle table has already propagated
 22.1817 +                     * a CNFException to passHandle at this point; this mark
 22.1818 +                     * call is included to address cases where the readExternal
 22.1819 +                     * method has cons'ed and thrown a new CNFException of its
 22.1820 +                     * own.
 22.1821 +                     */
 22.1822 +                     handles.markException(passHandle, ex);
 22.1823 +                }
 22.1824 +            }
 22.1825 +            if (blocked) {
 22.1826 +                skipCustomData();
 22.1827 +            }
 22.1828 +        } finally {
 22.1829 +            curContext = oldContext;
 22.1830 +        }
 22.1831 +        /*
 22.1832 +         * At this point, if the externalizable data was not written in
 22.1833 +         * block-data form and either the externalizable class doesn't exist
 22.1834 +         * locally (i.e., obj == null) or readExternal() just threw a
 22.1835 +         * CNFException, then the stream is probably in an inconsistent state,
 22.1836 +         * since some (or all) of the externalizable data may not have been
 22.1837 +         * consumed.  Since there's no "correct" action to take in this case,
 22.1838 +         * we mimic the behavior of past serialization implementations and
 22.1839 +         * blindly hope that the stream is in sync; if it isn't and additional
 22.1840 +         * externalizable data remains in the stream, a subsequent read will
 22.1841 +         * most likely throw a StreamCorruptedException.
 22.1842 +         */
 22.1843 +    }
 22.1844 +
 22.1845 +    /**
 22.1846 +     * Reads (or attempts to skip, if obj is null or is tagged with a
 22.1847 +     * ClassNotFoundException) instance data for each serializable class of
 22.1848 +     * object in stream, from superclass to subclass.  Expects that passHandle
 22.1849 +     * is set to obj's handle before this method is called.
 22.1850 +     */
 22.1851 +    private void readSerialData(Object obj, ObjectStreamClass desc)
 22.1852 +        throws IOException
 22.1853 +    {
 22.1854 +        ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
 22.1855 +        for (int i = 0; i < slots.length; i++) {
 22.1856 +            ObjectStreamClass slotDesc = slots[i].desc;
 22.1857 +
 22.1858 +            if (slots[i].hasData) {
 22.1859 +                if (obj != null &&
 22.1860 +                    slotDesc.hasReadObjectMethod() &&
 22.1861 +                    handles.lookupException(passHandle) == null)
 22.1862 +                {
 22.1863 +                    SerialCallbackContext oldContext = curContext;
 22.1864 +
 22.1865 +                    try {
 22.1866 +                        curContext = new SerialCallbackContext(obj, slotDesc);
 22.1867 +
 22.1868 +                        bin.setBlockDataMode(true);
 22.1869 +                        slotDesc.invokeReadObject(obj, this);
 22.1870 +                    } catch (ClassNotFoundException ex) {
 22.1871 +                        /*
 22.1872 +                         * In most cases, the handle table has already
 22.1873 +                         * propagated a CNFException to passHandle at this
 22.1874 +                         * point; this mark call is included to address cases
 22.1875 +                         * where the custom readObject method has cons'ed and
 22.1876 +                         * thrown a new CNFException of its own.
 22.1877 +                         */
 22.1878 +                        handles.markException(passHandle, ex);
 22.1879 +                    } finally {
 22.1880 +                        curContext.setUsed();
 22.1881 +                        curContext = oldContext;
 22.1882 +                    }
 22.1883 +
 22.1884 +                    /*
 22.1885 +                     * defaultDataEnd may have been set indirectly by custom
 22.1886 +                     * readObject() method when calling defaultReadObject() or
 22.1887 +                     * readFields(); clear it to restore normal read behavior.
 22.1888 +                     */
 22.1889 +                    defaultDataEnd = false;
 22.1890 +                } else {
 22.1891 +                    defaultReadFields(obj, slotDesc);
 22.1892 +                }
 22.1893 +                if (slotDesc.hasWriteObjectData()) {
 22.1894 +                    skipCustomData();
 22.1895 +                } else {
 22.1896 +                    bin.setBlockDataMode(false);
 22.1897 +                }
 22.1898 +            } else {
 22.1899 +                if (obj != null &&
 22.1900 +                    slotDesc.hasReadObjectNoDataMethod() &&
 22.1901 +                    handles.lookupException(passHandle) == null)
 22.1902 +                {
 22.1903 +                    slotDesc.invokeReadObjectNoData(obj);
 22.1904 +                }
 22.1905 +            }
 22.1906 +        }
 22.1907 +    }
 22.1908 +
 22.1909 +    /**
 22.1910 +     * Skips over all block data and objects until TC_ENDBLOCKDATA is
 22.1911 +     * encountered.
 22.1912 +     */
 22.1913 +    private void skipCustomData() throws IOException {
 22.1914 +        int oldHandle = passHandle;
 22.1915 +        for (;;) {
 22.1916 +            if (bin.getBlockDataMode()) {
 22.1917 +                bin.skipBlockData();
 22.1918 +                bin.setBlockDataMode(false);
 22.1919 +            }
 22.1920 +            switch (bin.peekByte()) {
 22.1921 +                case TC_BLOCKDATA:
 22.1922 +                case TC_BLOCKDATALONG:
 22.1923 +                    bin.setBlockDataMode(true);
 22.1924 +                    break;
 22.1925 +
 22.1926 +                case TC_ENDBLOCKDATA:
 22.1927 +                    bin.readByte();
 22.1928 +                    passHandle = oldHandle;
 22.1929 +                    return;
 22.1930 +
 22.1931 +                default:
 22.1932 +                    readObject0(false);
 22.1933 +                    break;
 22.1934 +            }
 22.1935 +        }
 22.1936 +    }
 22.1937 +
 22.1938 +    /**
 22.1939 +     * Reads in values of serializable fields declared by given class
 22.1940 +     * descriptor.  If obj is non-null, sets field values in obj.  Expects that
 22.1941 +     * passHandle is set to obj's handle before this method is called.
 22.1942 +     */
 22.1943 +    private void defaultReadFields(Object obj, ObjectStreamClass desc)
 22.1944 +        throws IOException
 22.1945 +    {
 22.1946 +        // REMIND: is isInstance check necessary?
 22.1947 +        Class cl = desc.forClass();
 22.1948 +        if (cl != null && obj != null && !cl.isInstance(obj)) {
 22.1949 +            throw new ClassCastException();
 22.1950 +        }
 22.1951 +
 22.1952 +        int primDataSize = desc.getPrimDataSize();
 22.1953 +        if (primVals == null || primVals.length < primDataSize) {
 22.1954 +            primVals = new byte[primDataSize];
 22.1955 +        }
 22.1956 +        bin.readFully(primVals, 0, primDataSize, false);
 22.1957 +        if (obj != null) {
 22.1958 +            desc.setPrimFieldValues(obj, primVals);
 22.1959 +        }
 22.1960 +
 22.1961 +        int objHandle = passHandle;
 22.1962 +        ObjectStreamField[] fields = desc.getFields(false);
 22.1963 +        Object[] objVals = new Object[desc.getNumObjFields()];
 22.1964 +        int numPrimFields = fields.length - objVals.length;
 22.1965 +        for (int i = 0; i < objVals.length; i++) {
 22.1966 +            ObjectStreamField f = fields[numPrimFields + i];
 22.1967 +            objVals[i] = readObject0(f.isUnshared());
 22.1968 +            if (f.getField() != null) {
 22.1969 +                handles.markDependency(objHandle, passHandle);
 22.1970 +            }
 22.1971 +        }
 22.1972 +        if (obj != null) {
 22.1973 +            desc.setObjFieldValues(obj, objVals);
 22.1974 +        }
 22.1975 +        passHandle = objHandle;
 22.1976 +    }
 22.1977 +
 22.1978 +    /**
 22.1979 +     * Reads in and returns IOException that caused serialization to abort.
 22.1980 +     * All stream state is discarded prior to reading in fatal exception.  Sets
 22.1981 +     * passHandle to fatal exception's handle.
 22.1982 +     */
 22.1983 +    private IOException readFatalException() throws IOException {
 22.1984 +        if (bin.readByte() != TC_EXCEPTION) {
 22.1985 +            throw new InternalError();
 22.1986 +        }
 22.1987 +        clear();
 22.1988 +        return (IOException) readObject0(false);
 22.1989 +    }
 22.1990 +
 22.1991 +    /**
 22.1992 +     * If recursion depth is 0, clears internal data structures; otherwise,
 22.1993 +     * throws a StreamCorruptedException.  This method is called when a
 22.1994 +     * TC_RESET typecode is encountered.
 22.1995 +     */
 22.1996 +    private void handleReset() throws StreamCorruptedException {
 22.1997 +        if (depth > 0) {
 22.1998 +            throw new StreamCorruptedException(
 22.1999 +                "unexpected reset; recursion depth: " + depth);
 22.2000 +        }
 22.2001 +        clear();
 22.2002 +    }
 22.2003 +
 22.2004 +    /**
 22.2005 +     * Converts specified span of bytes into float values.
 22.2006 +     */
 22.2007 +    // REMIND: remove once hotspot inlines Float.intBitsToFloat
 22.2008 +    private static native void bytesToFloats(byte[] src, int srcpos,
 22.2009 +                                             float[] dst, int dstpos,
 22.2010 +                                             int nfloats);
 22.2011 +
 22.2012 +    /**
 22.2013 +     * Converts specified span of bytes into double values.
 22.2014 +     */
 22.2015 +    // REMIND: remove once hotspot inlines Double.longBitsToDouble
 22.2016 +    private static native void bytesToDoubles(byte[] src, int srcpos,
 22.2017 +                                              double[] dst, int dstpos,
 22.2018 +                                              int ndoubles);
 22.2019 +
 22.2020 +    /**
 22.2021 +     * Returns the first non-null class loader (not counting class loaders of
 22.2022 +     * generated reflection implementation classes) up the execution stack, or
 22.2023 +     * null if only code from the null class loader is on the stack.  This
 22.2024 +     * method is also called via reflection by the following RMI-IIOP class:
 22.2025 +     *
 22.2026 +     *     com.sun.corba.se.internal.util.JDKClassLoader
 22.2027 +     *
 22.2028 +     * This method should not be removed or its signature changed without
 22.2029 +     * corresponding modifications to the above class.
 22.2030 +     */
 22.2031 +    // REMIND: change name to something more accurate?
 22.2032 +    private static native ClassLoader latestUserDefinedLoader();
 22.2033 +
 22.2034 +    /**
 22.2035 +     * Default GetField implementation.
 22.2036 +     */
 22.2037 +    private class GetFieldImpl extends GetField {
 22.2038 +
 22.2039 +        /** class descriptor describing serializable fields */
 22.2040 +        private final ObjectStreamClass desc;
 22.2041 +        /** primitive field values */
 22.2042 +        private final byte[] primVals;
 22.2043 +        /** object field values */
 22.2044 +        private final Object[] objVals;
 22.2045 +        /** object field value handles */
 22.2046 +        private final int[] objHandles;
 22.2047 +
 22.2048 +        /**
 22.2049 +         * Creates GetFieldImpl object for reading fields defined in given
 22.2050 +         * class descriptor.
 22.2051 +         */
 22.2052 +        GetFieldImpl(ObjectStreamClass desc) {
 22.2053 +            this.desc = desc;
 22.2054 +            primVals = new byte[desc.getPrimDataSize()];
 22.2055 +            objVals = new Object[desc.getNumObjFields()];
 22.2056 +            objHandles = new int[objVals.length];
 22.2057 +        }
 22.2058 +
 22.2059 +        public ObjectStreamClass getObjectStreamClass() {
 22.2060 +            return desc;
 22.2061 +        }
 22.2062 +
 22.2063 +        public boolean defaulted(String name) throws IOException {
 22.2064 +            return (getFieldOffset(name, null) < 0);
 22.2065 +        }
 22.2066 +
 22.2067 +        public boolean get(String name, boolean val) throws IOException {
 22.2068 +            int off = getFieldOffset(name, Boolean.TYPE);
 22.2069 +            return (off >= 0) ? Bits.getBoolean(primVals, off) : val;
 22.2070 +        }
 22.2071 +
 22.2072 +        public byte get(String name, byte val) throws IOException {
 22.2073 +            int off = getFieldOffset(name, Byte.TYPE);
 22.2074 +            return (off >= 0) ? primVals[off] : val;
 22.2075 +        }
 22.2076 +
 22.2077 +        public char get(String name, char val) throws IOException {
 22.2078 +            int off = getFieldOffset(name, Character.TYPE);
 22.2079 +            return (off >= 0) ? Bits.getChar(primVals, off) : val;
 22.2080 +        }
 22.2081 +
 22.2082 +        public short get(String name, short val) throws IOException {
 22.2083 +            int off = getFieldOffset(name, Short.TYPE);
 22.2084 +            return (off >= 0) ? Bits.getShort(primVals, off) : val;
 22.2085 +        }
 22.2086 +
 22.2087 +        public int get(String name, int val) throws IOException {
 22.2088 +            int off = getFieldOffset(name, Integer.TYPE);
 22.2089 +            return (off >= 0) ? Bits.getInt(primVals, off) : val;
 22.2090 +        }
 22.2091 +
 22.2092 +        public float get(String name, float val) throws IOException {
 22.2093 +            int off = getFieldOffset(name, Float.TYPE);
 22.2094 +            return (off >= 0) ? Bits.getFloat(primVals, off) : val;
 22.2095 +        }
 22.2096 +
 22.2097 +        public long get(String name, long val) throws IOException {
 22.2098 +            int off = getFieldOffset(name, Long.TYPE);
 22.2099 +            return (off >= 0) ? Bits.getLong(primVals, off) : val;
 22.2100 +        }
 22.2101 +
 22.2102 +        public double get(String name, double val) throws IOException {
 22.2103 +            int off = getFieldOffset(name, Double.TYPE);
 22.2104 +            return (off >= 0) ? Bits.getDouble(primVals, off) : val;
 22.2105 +        }
 22.2106 +
 22.2107 +        public Object get(String name, Object val) throws IOException {
 22.2108 +            int off = getFieldOffset(name, Object.class);
 22.2109 +            if (off >= 0) {
 22.2110 +                int objHandle = objHandles[off];
 22.2111 +                handles.markDependency(passHandle, objHandle);
 22.2112 +                return (handles.lookupException(objHandle) == null) ?
 22.2113 +                    objVals[off] : null;
 22.2114 +            } else {
 22.2115 +                return val;
 22.2116 +            }
 22.2117 +        }
 22.2118 +
 22.2119 +        /**
 22.2120 +         * Reads primitive and object field values from stream.
 22.2121 +         */
 22.2122 +        void readFields() throws IOException {
 22.2123 +            bin.readFully(primVals, 0, primVals.length, false);
 22.2124 +
 22.2125 +            int oldHandle = passHandle;
 22.2126 +            ObjectStreamField[] fields = desc.getFields(false);
 22.2127 +            int numPrimFields = fields.length - objVals.length;
 22.2128 +            for (int i = 0; i < objVals.length; i++) {
 22.2129 +                objVals[i] =
 22.2130 +                    readObject0(fields[numPrimFields + i].isUnshared());
 22.2131 +                objHandles[i] = passHandle;
 22.2132 +            }
 22.2133 +            passHandle = oldHandle;
 22.2134 +        }
 22.2135 +
 22.2136 +        /**
 22.2137 +         * Returns offset of field with given name and type.  A specified type
 22.2138 +         * of null matches all types, Object.class matches all non-primitive
 22.2139 +         * types, and any other non-null type matches assignable types only.
 22.2140 +         * If no matching field is found in the (incoming) class
 22.2141 +         * descriptor but a matching field is present in the associated local
 22.2142 +         * class descriptor, returns -1.  Throws IllegalArgumentException if
 22.2143 +         * neither incoming nor local class descriptor contains a match.
 22.2144 +         */
 22.2145 +        private int getFieldOffset(String name, Class type) {
 22.2146 +            ObjectStreamField field = desc.getField(name, type);
 22.2147 +            if (field != null) {
 22.2148 +                return field.getOffset();
 22.2149 +            } else if (desc.getLocalDesc().getField(name, type) != null) {
 22.2150 +                return -1;
 22.2151 +            } else {
 22.2152 +                throw new IllegalArgumentException("no such field " + name +
 22.2153 +                                                   " with type " + type);
 22.2154 +            }
 22.2155 +        }
 22.2156 +    }
 22.2157 +
 22.2158 +    /**
 22.2159 +     * Prioritized list of callbacks to be performed once object graph has been
 22.2160 +     * completely deserialized.
 22.2161 +     */
 22.2162 +    private static class ValidationList {
 22.2163 +
 22.2164 +        private static class Callback {
 22.2165 +            final ObjectInputValidation obj;
 22.2166 +            final int priority;
 22.2167 +            Callback next;
 22.2168 +            final AccessControlContext acc;
 22.2169 +
 22.2170 +            Callback(ObjectInputValidation obj, int priority, Callback next,
 22.2171 +                AccessControlContext acc)
 22.2172 +            {
 22.2173 +                this.obj = obj;
 22.2174 +                this.priority = priority;
 22.2175 +                this.next = next;
 22.2176 +                this.acc = acc;
 22.2177 +            }
 22.2178 +        }
 22.2179 +
 22.2180 +        /** linked list of callbacks */
 22.2181 +        private Callback list;
 22.2182 +
 22.2183 +        /**
 22.2184 +         * Creates new (empty) ValidationList.
 22.2185 +         */
 22.2186 +        ValidationList() {
 22.2187 +        }
 22.2188 +
 22.2189 +        /**
 22.2190 +         * Registers callback.  Throws InvalidObjectException if callback
 22.2191 +         * object is null.
 22.2192 +         */
 22.2193 +        void register(ObjectInputValidation obj, int priority)
 22.2194 +            throws InvalidObjectException
 22.2195 +        {
 22.2196 +            if (obj == null) {
 22.2197 +                throw new InvalidObjectException("null callback");
 22.2198 +            }
 22.2199 +
 22.2200 +            Callback prev = null, cur = list;
 22.2201 +            while (cur != null && priority < cur.priority) {
 22.2202 +                prev = cur;
 22.2203 +                cur = cur.next;
 22.2204 +            }
 22.2205 +            AccessControlContext acc = AccessController.getContext();
 22.2206 +            if (prev != null) {
 22.2207 +                prev.next = new Callback(obj, priority, cur, acc);
 22.2208 +            } else {
 22.2209 +                list = new Callback(obj, priority, list, acc);
 22.2210 +            }
 22.2211 +        }
 22.2212 +
 22.2213 +        /**
 22.2214 +         * Invokes all registered callbacks and clears the callback list.
 22.2215 +         * Callbacks with higher priorities are called first; those with equal
 22.2216 +         * priorities may be called in any order.  If any of the callbacks
 22.2217 +         * throws an InvalidObjectException, the callback process is terminated
 22.2218 +         * and the exception propagated upwards.
 22.2219 +         */
 22.2220 +        void doCallbacks() throws InvalidObjectException {
 22.2221 +            try {
 22.2222 +                while (list != null) {
 22.2223 +                    AccessController.doPrivileged(
 22.2224 +                        new PrivilegedExceptionAction<Void>()
 22.2225 +                    {
 22.2226 +                        public Void run() throws InvalidObjectException {
 22.2227 +                            list.obj.validateObject();
 22.2228 +                            return null;
 22.2229 +                        }
 22.2230 +                    }, list.acc);
 22.2231 +                    list = list.next;
 22.2232 +                }
 22.2233 +            } catch (PrivilegedActionException ex) {
 22.2234 +                list = null;
 22.2235 +                throw (InvalidObjectException) ex.getException();
 22.2236 +            }
 22.2237 +        }
 22.2238 +
 22.2239 +        /**
 22.2240 +         * Resets the callback list to its initial (empty) state.
 22.2241 +         */
 22.2242 +        public void clear() {
 22.2243 +            list = null;
 22.2244 +        }
 22.2245 +    }
 22.2246 +
 22.2247 +    /**
 22.2248 +     * Input stream supporting single-byte peek operations.
 22.2249 +     */
 22.2250 +    private static class PeekInputStream extends InputStream {
 22.2251 +
 22.2252 +        /** underlying stream */
 22.2253 +        private final InputStream in;
 22.2254 +        /** peeked byte */
 22.2255 +        private int peekb = -1;
 22.2256 +
 22.2257 +        /**
 22.2258 +         * Creates new PeekInputStream on top of given underlying stream.
 22.2259 +         */
 22.2260 +        PeekInputStream(InputStream in) {
 22.2261 +            this.in = in;
 22.2262 +        }
 22.2263 +
 22.2264 +        /**
 22.2265 +         * Peeks at next byte value in stream.  Similar to read(), except
 22.2266 +         * that it does not consume the read value.
 22.2267 +         */
 22.2268 +        int peek() throws IOException {
 22.2269 +            return (peekb >= 0) ? peekb : (peekb = in.read());
 22.2270 +        }
 22.2271 +
 22.2272 +        public int read() throws IOException {
 22.2273 +            if (peekb >= 0) {
 22.2274 +                int v = peekb;
 22.2275 +                peekb = -1;
 22.2276 +                return v;
 22.2277 +            } else {
 22.2278 +                return in.read();
 22.2279 +            }
 22.2280 +        }
 22.2281 +
 22.2282 +        public int read(byte[] b, int off, int len) throws IOException {
 22.2283 +            if (len == 0) {
 22.2284 +                return 0;
 22.2285 +            } else if (peekb < 0) {
 22.2286 +                return in.read(b, off, len);
 22.2287 +            } else {
 22.2288 +                b[off++] = (byte) peekb;
 22.2289 +                len--;
 22.2290 +                peekb = -1;
 22.2291 +                int n = in.read(b, off, len);
 22.2292 +                return (n >= 0) ? (n + 1) : 1;
 22.2293 +            }
 22.2294 +        }
 22.2295 +
 22.2296 +        void readFully(byte[] b, int off, int len) throws IOException {
 22.2297 +            int n = 0;
 22.2298 +            while (n < len) {
 22.2299 +                int count = read(b, off + n, len - n);
 22.2300 +                if (count < 0) {
 22.2301 +                    throw new EOFException();
 22.2302 +                }
 22.2303 +                n += count;
 22.2304 +            }
 22.2305 +        }
 22.2306 +
 22.2307 +        public long skip(long n) throws IOException {
 22.2308 +            if (n <= 0) {
 22.2309 +                return 0;
 22.2310 +            }
 22.2311 +            int skipped = 0;
 22.2312 +            if (peekb >= 0) {
 22.2313 +                peekb = -1;
 22.2314 +                skipped++;
 22.2315 +                n--;
 22.2316 +            }
 22.2317 +            return skipped + skip(n);
 22.2318 +        }
 22.2319 +
 22.2320 +        public int available() throws IOException {
 22.2321 +            return in.available() + ((peekb >= 0) ? 1 : 0);
 22.2322 +        }
 22.2323 +
 22.2324 +        public void close() throws IOException {
 22.2325 +            in.close();
 22.2326 +        }
 22.2327 +    }
 22.2328 +
 22.2329 +    /**
 22.2330 +     * Input stream with two modes: in default mode, inputs data written in the
 22.2331 +     * same format as DataOutputStream; in "block data" mode, inputs data
 22.2332 +     * bracketed by block data markers (see object serialization specification
 22.2333 +     * for details).  Buffering depends on block data mode: when in default
 22.2334 +     * mode, no data is buffered in advance; when in block data mode, all data
 22.2335 +     * for the current data block is read in at once (and buffered).
 22.2336 +     */
 22.2337 +    private class BlockDataInputStream
 22.2338 +        extends InputStream implements DataInput
 22.2339 +    {
 22.2340 +        /** maximum data block length */
 22.2341 +        private static final int MAX_BLOCK_SIZE = 1024;
 22.2342 +        /** maximum data block header length */
 22.2343 +        private static final int MAX_HEADER_SIZE = 5;
 22.2344 +        /** (tunable) length of char buffer (for reading strings) */
 22.2345 +        private static final int CHAR_BUF_SIZE = 256;
 22.2346 +        /** readBlockHeader() return value indicating header read may block */
 22.2347 +        private static final int HEADER_BLOCKED = -2;
 22.2348 +
 22.2349 +        /** buffer for reading general/block data */
 22.2350 +        private final byte[] buf = new byte[MAX_BLOCK_SIZE];
 22.2351 +        /** buffer for reading block data headers */
 22.2352 +        private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
 22.2353 +        /** char buffer for fast string reads */
 22.2354 +        private final char[] cbuf = new char[CHAR_BUF_SIZE];
 22.2355 +
 22.2356 +        /** block data mode */
 22.2357 +        private boolean blkmode = false;
 22.2358 +
 22.2359 +        // block data state fields; values meaningful only when blkmode true
 22.2360 +        /** current offset into buf */
 22.2361 +        private int pos = 0;
 22.2362 +        /** end offset of valid data in buf, or -1 if no more block data */
 22.2363 +        private int end = -1;
 22.2364 +        /** number of bytes in current block yet to be read from stream */
 22.2365 +        private int unread = 0;
 22.2366 +
 22.2367 +        /** underlying stream (wrapped in peekable filter stream) */
 22.2368 +        private final PeekInputStream in;
 22.2369 +        /** loopback stream (for data reads that span data blocks) */
 22.2370 +        private final DataInputStream din;
 22.2371 +
 22.2372 +        /**
 22.2373 +         * Creates new BlockDataInputStream on top of given underlying stream.
 22.2374 +         * Block data mode is turned off by default.
 22.2375 +         */
 22.2376 +        BlockDataInputStream(InputStream in) {
 22.2377 +            this.in = new PeekInputStream(in);
 22.2378 +            din = new DataInputStream(this);
 22.2379 +        }
 22.2380 +
 22.2381 +        /**
 22.2382 +         * Sets block data mode to the given mode (true == on, false == off)
 22.2383 +         * and returns the previous mode value.  If the new mode is the same as
 22.2384 +         * the old mode, no action is taken.  Throws IllegalStateException if
 22.2385 +         * block data mode is being switched from on to off while unconsumed
 22.2386 +         * block data is still present in the stream.
 22.2387 +         */
 22.2388 +        boolean setBlockDataMode(boolean newmode) throws IOException {
 22.2389 +            if (blkmode == newmode) {
 22.2390 +                return blkmode;
 22.2391 +            }
 22.2392 +            if (newmode) {
 22.2393 +                pos = 0;
 22.2394 +                end = 0;
 22.2395 +                unread = 0;
 22.2396 +            } else if (pos < end) {
 22.2397 +                throw new IllegalStateException("unread block data");
 22.2398 +            }
 22.2399 +            blkmode = newmode;
 22.2400 +            return !blkmode;
 22.2401 +        }
 22.2402 +
 22.2403 +        /**
 22.2404 +         * Returns true if the stream is currently in block data mode, false
 22.2405 +         * otherwise.
 22.2406 +         */
 22.2407 +        boolean getBlockDataMode() {
 22.2408 +            return blkmode;
 22.2409 +        }
 22.2410 +
 22.2411 +        /**
 22.2412 +         * If in block data mode, skips to the end of the current group of data
 22.2413 +         * blocks (but does not unset block data mode).  If not in block data
 22.2414 +         * mode, throws an IllegalStateException.
 22.2415 +         */
 22.2416 +        void skipBlockData() throws IOException {
 22.2417 +            if (!blkmode) {
 22.2418 +                throw new IllegalStateException("not in block data mode");
 22.2419 +            }
 22.2420 +            while (end >= 0) {
 22.2421 +                refill();
 22.2422 +            }
 22.2423 +        }
 22.2424 +
 22.2425 +        /**
 22.2426 +         * Attempts to read in the next block data header (if any).  If
 22.2427 +         * canBlock is false and a full header cannot be read without possibly
 22.2428 +         * blocking, returns HEADER_BLOCKED, else if the next element in the
 22.2429 +         * stream is a block data header, returns the block data length
 22.2430 +         * specified by the header, else returns -1.
 22.2431 +         */
 22.2432 +        private int readBlockHeader(boolean canBlock) throws IOException {
 22.2433 +            if (defaultDataEnd) {
 22.2434 +                /*
 22.2435 +                 * Fix for 4360508: stream is currently at the end of a field
 22.2436 +                 * value block written via default serialization; since there
 22.2437 +                 * is no terminating TC_ENDBLOCKDATA tag, simulate
 22.2438 +                 * end-of-custom-data behavior explicitly.
 22.2439 +                 */
 22.2440 +                return -1;
 22.2441 +            }
 22.2442 +            try {
 22.2443 +                for (;;) {
 22.2444 +                    int avail = canBlock ? Integer.MAX_VALUE : in.available();
 22.2445 +                    if (avail == 0) {
 22.2446 +                        return HEADER_BLOCKED;
 22.2447 +                    }
 22.2448 +
 22.2449 +                    int tc = in.peek();
 22.2450 +                    switch (tc) {
 22.2451 +                        case TC_BLOCKDATA:
 22.2452 +                            if (avail < 2) {
 22.2453 +                                return HEADER_BLOCKED;
 22.2454 +                            }
 22.2455 +                            in.readFully(hbuf, 0, 2);
 22.2456 +                            return hbuf[1] & 0xFF;
 22.2457 +
 22.2458 +                        case TC_BLOCKDATALONG:
 22.2459 +                            if (avail < 5) {
 22.2460 +                                return HEADER_BLOCKED;
 22.2461 +                            }
 22.2462 +                            in.readFully(hbuf, 0, 5);
 22.2463 +                            int len = Bits.getInt(hbuf, 1);
 22.2464 +                            if (len < 0) {
 22.2465 +                                throw new StreamCorruptedException(
 22.2466 +                                    "illegal block data header length: " +
 22.2467 +                                    len);
 22.2468 +                            }
 22.2469 +                            return len;
 22.2470 +
 22.2471 +                        /*
 22.2472 +                         * TC_RESETs may occur in between data blocks.
 22.2473 +                         * Unfortunately, this case must be parsed at a lower
 22.2474 +                         * level than other typecodes, since primitive data
 22.2475 +                         * reads may span data blocks separated by a TC_RESET.
 22.2476 +                         */
 22.2477 +                        case TC_RESET:
 22.2478 +                            in.read();
 22.2479 +                            handleReset();
 22.2480 +                            break;
 22.2481 +
 22.2482 +                        default:
 22.2483 +                            if (tc >= 0 && (tc < TC_BASE || tc > TC_MAX)) {
 22.2484 +                                throw new StreamCorruptedException(
 22.2485 +                                    String.format("invalid type code: %02X",
 22.2486 +                                    tc));
 22.2487 +                            }
 22.2488 +                            return -1;
 22.2489 +                    }
 22.2490 +                }
 22.2491 +            } catch (EOFException ex) {
 22.2492 +                throw new StreamCorruptedException(
 22.2493 +                    "unexpected EOF while reading block data header");
 22.2494 +            }
 22.2495 +        }
 22.2496 +
 22.2497 +        /**
 22.2498 +         * Refills internal buffer buf with block data.  Any data in buf at the
 22.2499 +         * time of the call is considered consumed.  Sets the pos, end, and
 22.2500 +         * unread fields to reflect the new amount of available block data; if
 22.2501 +         * the next element in the stream is not a data block, sets pos and
 22.2502 +         * unread to 0 and end to -1.
 22.2503 +         */
 22.2504 +        private void refill() throws IOException {
 22.2505 +            try {
 22.2506 +                do {
 22.2507 +                    pos = 0;
 22.2508 +                    if (unread > 0) {
 22.2509 +                        int n =
 22.2510 +                            in.read(buf, 0, Math.min(unread, MAX_BLOCK_SIZE));
 22.2511 +                        if (n >= 0) {
 22.2512 +                            end = n;
 22.2513 +                            unread -= n;
 22.2514 +                        } else {
 22.2515 +                            throw new StreamCorruptedException(
 22.2516 +                                "unexpected EOF in middle of data block");
 22.2517 +                        }
 22.2518 +                    } else {
 22.2519 +                        int n = readBlockHeader(true);
 22.2520 +                        if (n >= 0) {
 22.2521 +                            end = 0;
 22.2522 +                            unread = n;
 22.2523 +                        } else {
 22.2524 +                            end = -1;
 22.2525 +                            unread = 0;
 22.2526 +                        }
 22.2527 +                    }
 22.2528 +                } while (pos == end);
 22.2529 +            } catch (IOException ex) {
 22.2530 +                pos = 0;
 22.2531 +                end = -1;
 22.2532 +                unread = 0;
 22.2533 +                throw ex;
 22.2534 +            }
 22.2535 +        }
 22.2536 +
 22.2537 +        /**
 22.2538 +         * If in block data mode, returns the number of unconsumed bytes
 22.2539 +         * remaining in the current data block.  If not in block data mode,
 22.2540 +         * throws an IllegalStateException.
 22.2541 +         */
 22.2542 +        int currentBlockRemaining() {
 22.2543 +            if (blkmode) {
 22.2544 +                return (end >= 0) ? (end - pos) + unread : 0;
 22.2545 +            } else {
 22.2546 +                throw new IllegalStateException();
 22.2547 +            }
 22.2548 +        }
 22.2549 +
 22.2550 +        /**
 22.2551 +         * Peeks at (but does not consume) and returns the next byte value in
 22.2552 +         * the stream, or -1 if the end of the stream/block data (if in block
 22.2553 +         * data mode) has been reached.
 22.2554 +         */
 22.2555 +        int peek() throws IOException {
 22.2556 +            if (blkmode) {
 22.2557 +                if (pos == end) {
 22.2558 +                    refill();
 22.2559 +                }
 22.2560 +                return (end >= 0) ? (buf[pos] & 0xFF) : -1;
 22.2561 +            } else {
 22.2562 +                return in.peek();
 22.2563 +            }
 22.2564 +        }
 22.2565 +
 22.2566 +        /**
 22.2567 +         * Peeks at (but does not consume) and returns the next byte value in
 22.2568 +         * the stream, or throws EOFException if end of stream/block data has
 22.2569 +         * been reached.
 22.2570 +         */
 22.2571 +        byte peekByte() throws IOException {
 22.2572 +            int val = peek();
 22.2573 +            if (val < 0) {
 22.2574 +                throw new EOFException();
 22.2575 +            }
 22.2576 +            return (byte) val;
 22.2577 +        }
 22.2578 +
 22.2579 +
 22.2580 +        /* ----------------- generic input stream methods ------------------ */
 22.2581 +        /*
 22.2582 +         * The following methods are equivalent to their counterparts in
 22.2583 +         * InputStream, except that they interpret data block boundaries and
 22.2584 +         * read the requested data from within data blocks when in block data
 22.2585 +         * mode.
 22.2586 +         */
 22.2587 +
 22.2588 +        public int read() throws IOException {
 22.2589 +            if (blkmode) {
 22.2590 +                if (pos == end) {
 22.2591 +                    refill();
 22.2592 +                }
 22.2593 +                return (end >= 0) ? (buf[pos++] & 0xFF) : -1;
 22.2594 +            } else {
 22.2595 +                return in.read();
 22.2596 +            }
 22.2597 +        }
 22.2598 +
 22.2599 +        public int read(byte[] b, int off, int len) throws IOException {
 22.2600 +            return read(b, off, len, false);
 22.2601 +        }
 22.2602 +
 22.2603 +        public long skip(long len) throws IOException {
 22.2604 +            long remain = len;
 22.2605 +            while (remain > 0) {
 22.2606 +                if (blkmode) {
 22.2607 +                    if (pos == end) {
 22.2608 +                        refill();
 22.2609 +                    }
 22.2610 +                    if (end < 0) {
 22.2611 +                        break;
 22.2612 +                    }
 22.2613 +                    int nread = (int) Math.min(remain, end - pos);
 22.2614 +                    remain -= nread;
 22.2615 +                    pos += nread;
 22.2616 +                } else {
 22.2617 +                    int nread = (int) Math.min(remain, MAX_BLOCK_SIZE);
 22.2618 +                    if ((nread = in.read(buf, 0, nread)) < 0) {
 22.2619 +                        break;
 22.2620 +                    }
 22.2621 +                    remain -= nread;
 22.2622 +                }
 22.2623 +            }
 22.2624 +            return len - remain;
 22.2625 +        }
 22.2626 +
 22.2627 +        public int available() throws IOException {
 22.2628 +            if (blkmode) {
 22.2629 +                if ((pos == end) && (unread == 0)) {
 22.2630 +                    int n;
 22.2631 +                    while ((n = readBlockHeader(false)) == 0) ;
 22.2632 +                    switch (n) {
 22.2633 +                        case HEADER_BLOCKED:
 22.2634 +                            break;
 22.2635 +
 22.2636 +                        case -1:
 22.2637 +                            pos = 0;
 22.2638 +                            end = -1;
 22.2639 +                            break;
 22.2640 +
 22.2641 +                        default:
 22.2642 +                            pos = 0;
 22.2643 +                            end = 0;
 22.2644 +                            unread = n;
 22.2645 +                            break;
 22.2646 +                    }
 22.2647 +                }
 22.2648 +                // avoid unnecessary call to in.available() if possible
 22.2649 +                int unreadAvail = (unread > 0) ?
 22.2650 +                    Math.min(in.available(), unread) : 0;
 22.2651 +                return (end >= 0) ? (end - pos) + unreadAvail : 0;
 22.2652 +            } else {
 22.2653 +                return in.available();
 22.2654 +            }
 22.2655 +        }
 22.2656 +
 22.2657 +        public void close() throws IOException {
 22.2658 +            if (blkmode) {
 22.2659 +                pos = 0;
 22.2660 +                end = -1;
 22.2661 +                unread = 0;
 22.2662 +            }
 22.2663 +            in.close();
 22.2664 +        }
 22.2665 +
 22.2666 +        /**
 22.2667 +         * Attempts to read len bytes into byte array b at offset off.  Returns
 22.2668 +         * the number of bytes read, or -1 if the end of stream/block data has
 22.2669 +         * been reached.  If copy is true, reads values into an intermediate
 22.2670 +         * buffer before copying them to b (to avoid exposing a reference to
 22.2671 +         * b).
 22.2672 +         */
 22.2673 +        int read(byte[] b, int off, int len, boolean copy) throws IOException {
 22.2674 +            if (len == 0) {
 22.2675 +                return 0;
 22.2676 +            } else if (blkmode) {
 22.2677 +                if (pos == end) {
 22.2678 +                    refill();
 22.2679 +                }
 22.2680 +                if (end < 0) {
 22.2681 +                    return -1;
 22.2682 +                }
 22.2683 +                int nread = Math.min(len, end - pos);
 22.2684 +                System.arraycopy(buf, pos, b, off, nread);
 22.2685 +                pos += nread;
 22.2686 +                return nread;
 22.2687 +            } else if (copy) {
 22.2688 +                int nread = in.read(buf, 0, Math.min(len, MAX_BLOCK_SIZE));
 22.2689 +                if (nread > 0) {
 22.2690 +                    System.arraycopy(buf, 0, b, off, nread);
 22.2691 +                }
 22.2692 +                return nread;
 22.2693 +            } else {
 22.2694 +                return in.read(b, off, len);
 22.2695 +            }
 22.2696 +        }
 22.2697 +
 22.2698 +        /* ----------------- primitive data input methods ------------------ */
 22.2699 +        /*
 22.2700 +         * The following methods are equivalent to their counterparts in
 22.2701 +         * DataInputStream, except that they interpret data block boundaries
 22.2702 +         * and read the requested data from within data blocks when in block
 22.2703 +         * data mode.
 22.2704 +         */
 22.2705 +
 22.2706 +        public void readFully(byte[] b) throws IOException {
 22.2707 +            readFully(b, 0, b.length, false);
 22.2708 +        }
 22.2709 +
 22.2710 +        public void readFully(byte[] b, int off, int len) throws IOException {
 22.2711 +            readFully(b, off, len, false);
 22.2712 +        }
 22.2713 +
 22.2714 +        public void readFully(byte[] b, int off, int len, boolean copy)
 22.2715 +            throws IOException
 22.2716 +        {
 22.2717 +            while (len > 0) {
 22.2718 +                int n = read(b, off, len, copy);
 22.2719 +                if (n < 0) {
 22.2720 +                    throw new EOFException();
 22.2721 +                }
 22.2722 +                off += n;
 22.2723 +                len -= n;
 22.2724 +            }
 22.2725 +        }
 22.2726 +
 22.2727 +        public int skipBytes(int n) throws IOException {
 22.2728 +            return din.skipBytes(n);
 22.2729 +        }
 22.2730 +
 22.2731 +        public boolean readBoolean() throws IOException {
 22.2732 +            int v = read();
 22.2733 +            if (v < 0) {
 22.2734 +                throw new EOFException();
 22.2735 +            }
 22.2736 +            return (v != 0);
 22.2737 +        }
 22.2738 +
 22.2739 +        public byte readByte() throws IOException {
 22.2740 +            int v = read();
 22.2741 +            if (v < 0) {
 22.2742 +                throw new EOFException();
 22.2743 +            }
 22.2744 +            return (byte) v;
 22.2745 +        }
 22.2746 +
 22.2747 +        public int readUnsignedByte() throws IOException {
 22.2748 +            int v = read();
 22.2749 +            if (v < 0) {
 22.2750 +                throw new EOFException();
 22.2751 +            }
 22.2752 +            return v;
 22.2753 +        }
 22.2754 +
 22.2755 +        public char readChar() throws IOException {
 22.2756 +            if (!blkmode) {
 22.2757 +                pos = 0;
 22.2758 +                in.readFully(buf, 0, 2);
 22.2759 +            } else if (end - pos < 2) {
 22.2760 +                return din.readChar();
 22.2761 +            }
 22.2762 +            char v = Bits.getChar(buf, pos);
 22.2763 +            pos += 2;
 22.2764 +            return v;
 22.2765 +        }
 22.2766 +
 22.2767 +        public short readShort() throws IOException {
 22.2768 +            if (!blkmode) {
 22.2769 +                pos = 0;
 22.2770 +                in.readFully(buf, 0, 2);
 22.2771 +            } else if (end - pos < 2) {
 22.2772 +                return din.readShort();
 22.2773 +            }
 22.2774 +            short v = Bits.getShort(buf, pos);
 22.2775 +            pos += 2;
 22.2776 +            return v;
 22.2777 +        }
 22.2778 +
 22.2779 +        public int readUnsignedShort() throws IOException {
 22.2780 +            if (!blkmode) {
 22.2781 +                pos = 0;
 22.2782 +                in.readFully(buf, 0, 2);
 22.2783 +            } else if (end - pos < 2) {
 22.2784 +                return din.readUnsignedShort();
 22.2785 +            }
 22.2786 +            int v = Bits.getShort(buf, pos) & 0xFFFF;
 22.2787 +            pos += 2;
 22.2788 +            return v;
 22.2789 +        }
 22.2790 +
 22.2791 +        public int readInt() throws IOException {
 22.2792 +            if (!blkmode) {
 22.2793 +                pos = 0;
 22.2794 +                in.readFully(buf, 0, 4);
 22.2795 +            } else if (end - pos < 4) {
 22.2796 +                return din.readInt();
 22.2797 +            }
 22.2798 +            int v = Bits.getInt(buf, pos);
 22.2799 +            pos += 4;
 22.2800 +            return v;
 22.2801 +        }
 22.2802 +
 22.2803 +        public float readFloat() throws IOException {
 22.2804 +            if (!blkmode) {
 22.2805 +                pos = 0;
 22.2806 +                in.readFully(buf, 0, 4);
 22.2807 +            } else if (end - pos < 4) {
 22.2808 +                return din.readFloat();
 22.2809 +            }
 22.2810 +            float v = Bits.getFloat(buf, pos);
 22.2811 +            pos += 4;
 22.2812 +            return v;
 22.2813 +        }
 22.2814 +
 22.2815 +        public long readLong() throws IOException {
 22.2816 +            if (!blkmode) {
 22.2817 +                pos = 0;
 22.2818 +                in.readFully(buf, 0, 8);
 22.2819 +            } else if (end - pos < 8) {
 22.2820 +                return din.readLong();
 22.2821 +            }
 22.2822 +            long v = Bits.getLong(buf, pos);
 22.2823 +            pos += 8;
 22.2824 +            return v;
 22.2825 +        }
 22.2826 +
 22.2827 +        public double readDouble() throws IOException {
 22.2828 +            if (!blkmode) {
 22.2829 +                pos = 0;
 22.2830 +                in.readFully(buf, 0, 8);
 22.2831 +            } else if (end - pos < 8) {
 22.2832 +                return din.readDouble();
 22.2833 +            }
 22.2834 +            double v = Bits.getDouble(buf, pos);
 22.2835 +            pos += 8;
 22.2836 +            return v;
 22.2837 +        }
 22.2838 +
 22.2839 +        public String readUTF() throws IOException {
 22.2840 +            return readUTFBody(readUnsignedShort());
 22.2841 +        }
 22.2842 +
 22.2843 +        public String readLine() throws IOException {
 22.2844 +            return din.readLine();      // deprecated, not worth optimizing
 22.2845 +        }
 22.2846 +
 22.2847 +        /* -------------- primitive data array input methods --------------- */
 22.2848 +        /*
 22.2849 +         * The following methods read in spans of primitive data values.
 22.2850 +         * Though equivalent to calling the corresponding primitive read
 22.2851 +         * methods repeatedly, these methods are optimized for reading groups
 22.2852 +         * of primitive data values more efficiently.
 22.2853 +         */
 22.2854 +
 22.2855 +        void readBooleans(boolean[] v, int off, int len) throws IOException {
 22.2856 +            int stop, endoff = off + len;
 22.2857 +            while (off < endoff) {
 22.2858 +                if (!blkmode) {
 22.2859 +                    int span = Math.min(endoff - off, MAX_BLOCK_SIZE);
 22.2860 +                    in.readFully(buf, 0, span);
 22.2861 +                    stop = off + span;
 22.2862 +                    pos = 0;
 22.2863 +                } else if (end - pos < 1) {
 22.2864 +                    v[off++] = din.readBoolean();
 22.2865 +                    continue;
 22.2866 +                } else {
 22.2867 +                    stop = Math.min(endoff, off + end - pos);
 22.2868 +                }
 22.2869 +
 22.2870 +                while (off < stop) {
 22.2871 +                    v[off++] = Bits.getBoolean(buf, pos++);
 22.2872 +                }
 22.2873 +            }
 22.2874 +        }
 22.2875 +
 22.2876 +        void readChars(char[] v, int off, int len) throws IOException {
 22.2877 +            int stop, endoff = off + len;
 22.2878 +            while (off < endoff) {
 22.2879 +                if (!blkmode) {
 22.2880 +                    int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
 22.2881 +                    in.readFully(buf, 0, span << 1);
 22.2882 +                    stop = off + span;
 22.2883 +                    pos = 0;
 22.2884 +                } else if (end - pos < 2) {
 22.2885 +                    v[off++] = din.readChar();
 22.2886 +                    continue;
 22.2887 +                } else {
 22.2888 +                    stop = Math.min(endoff, off + ((end - pos) >> 1));
 22.2889 +                }
 22.2890 +
 22.2891 +                while (off < stop) {
 22.2892 +                    v[off++] = Bits.getChar(buf, pos);
 22.2893 +                    pos += 2;
 22.2894 +                }
 22.2895 +            }
 22.2896 +        }
 22.2897 +
 22.2898 +        void readShorts(short[] v, int off, int len) throws IOException {
 22.2899 +            int stop, endoff = off + len;
 22.2900 +            while (off < endoff) {
 22.2901 +                if (!blkmode) {
 22.2902 +                    int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
 22.2903 +                    in.readFully(buf, 0, span << 1);
 22.2904 +                    stop = off + span;
 22.2905 +                    pos = 0;
 22.2906 +                } else if (end - pos < 2) {
 22.2907 +                    v[off++] = din.readShort();
 22.2908 +                    continue;
 22.2909 +                } else {
 22.2910 +                    stop = Math.min(endoff, off + ((end - pos) >> 1));
 22.2911 +                }
 22.2912 +
 22.2913 +                while (off < stop) {
 22.2914 +                    v[off++] = Bits.getShort(buf, pos);
 22.2915 +                    pos += 2;
 22.2916 +                }
 22.2917 +            }
 22.2918 +        }
 22.2919 +
 22.2920 +        void readInts(int[] v, int off, int len) throws IOException {
 22.2921 +            int stop, endoff = off + len;
 22.2922 +            while (off < endoff) {
 22.2923 +                if (!blkmode) {
 22.2924 +                    int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
 22.2925 +                    in.readFully(buf, 0, span << 2);
 22.2926 +                    stop = off + span;
 22.2927 +                    pos = 0;
 22.2928 +                } else if (end - pos < 4) {
 22.2929 +                    v[off++] = din.readInt();
 22.2930 +                    continue;
 22.2931 +                } else {
 22.2932 +                    stop = Math.min(endoff, off + ((end - pos) >> 2));
 22.2933 +                }
 22.2934 +
 22.2935 +                while (off < stop) {
 22.2936 +                    v[off++] = Bits.getInt(buf, pos);
 22.2937 +                    pos += 4;
 22.2938 +                }
 22.2939 +            }
 22.2940 +        }
 22.2941 +
 22.2942 +        void readFloats(float[] v, int off, int len) throws IOException {
 22.2943 +            int span, endoff = off + len;
 22.2944 +            while (off < endoff) {
 22.2945 +                if (!blkmode) {
 22.2946 +                    span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
 22.2947 +                    in.readFully(buf, 0, span << 2);
 22.2948 +                    pos = 0;
 22.2949 +                } else if (end - pos < 4) {
 22.2950 +                    v[off++] = din.readFloat();
 22.2951 +                    continue;
 22.2952 +                } else {
 22.2953 +                    span = Math.min(endoff - off, ((end - pos) >> 2));
 22.2954 +                }
 22.2955 +
 22.2956 +                bytesToFloats(buf, pos, v, off, span);
 22.2957 +                off += span;
 22.2958 +                pos += span << 2;
 22.2959 +            }
 22.2960 +        }
 22.2961 +
 22.2962 +        void readLongs(long[] v, int off, int len) throws IOException {
 22.2963 +            int stop, endoff = off + len;
 22.2964 +            while (off < endoff) {
 22.2965 +                if (!blkmode) {
 22.2966 +                    int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
 22.2967 +                    in.readFully(buf, 0, span << 3);
 22.2968 +                    stop = off + span;
 22.2969 +                    pos = 0;
 22.2970 +                } else if (end - pos < 8) {
 22.2971 +                    v[off++] = din.readLong();
 22.2972 +                    continue;
 22.2973 +                } else {
 22.2974 +                    stop = Math.min(endoff, off + ((end - pos) >> 3));
 22.2975 +                }
 22.2976 +
 22.2977 +                while (off < stop) {
 22.2978 +                    v[off++] = Bits.getLong(buf, pos);
 22.2979 +                    pos += 8;
 22.2980 +                }
 22.2981 +            }
 22.2982 +        }
 22.2983 +
 22.2984 +        void readDoubles(double[] v, int off, int len) throws IOException {
 22.2985 +            int span, endoff = off + len;
 22.2986 +            while (off < endoff) {
 22.2987 +                if (!blkmode) {
 22.2988 +                    span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
 22.2989 +                    in.readFully(buf, 0, span << 3);
 22.2990 +                    pos = 0;
 22.2991 +                } else if (end - pos < 8) {
 22.2992 +                    v[off++] = din.readDouble();
 22.2993 +                    continue;
 22.2994 +                } else {
 22.2995 +                    span = Math.min(endoff - off, ((end - pos) >> 3));
 22.2996 +                }
 22.2997 +
 22.2998 +                bytesToDoubles(buf, pos, v, off, span);
 22.2999 +                off += span;
 22.3000 +                pos += span << 3;
 22.3001 +            }
 22.3002 +        }
 22.3003 +
 22.3004 +        /**
 22.3005 +         * Reads in string written in "long" UTF format.  "Long" UTF format is
 22.3006 +         * identical to standard UTF, except that it uses an 8 byte header
 22.3007 +         * (instead of the standard 2 bytes) to convey the UTF encoding length.
 22.3008 +         */
 22.3009 +        String readLongUTF() throws IOException {
 22.3010 +            return readUTFBody(readLong());
 22.3011 +        }
 22.3012 +
 22.3013 +        /**
 22.3014 +         * Reads in the "body" (i.e., the UTF representation minus the 2-byte
 22.3015 +         * or 8-byte length header) of a UTF encoding, which occupies the next
 22.3016 +         * utflen bytes.
 22.3017 +         */
 22.3018 +        private String readUTFBody(long utflen) throws IOException {
 22.3019 +            StringBuilder sbuf = new StringBuilder();
 22.3020 +            if (!blkmode) {
 22.3021 +                end = pos = 0;
 22.3022 +            }
 22.3023 +
 22.3024 +            while (utflen > 0) {
 22.3025 +                int avail = end - pos;
 22.3026 +                if (avail >= 3 || (long) avail == utflen) {
 22.3027 +                    utflen -= readUTFSpan(sbuf, utflen);
 22.3028 +                } else {
 22.3029 +                    if (blkmode) {
 22.3030 +                        // near block boundary, read one byte at a time
 22.3031 +                        utflen -= readUTFChar(sbuf, utflen);
 22.3032 +                    } else {
 22.3033 +                        // shift and refill buffer manually
 22.3034 +                        if (avail > 0) {
 22.3035 +                            System.arraycopy(buf, pos, buf, 0, avail);
 22.3036 +                        }
 22.3037 +                        pos = 0;
 22.3038 +                        end = (int) Math.min(MAX_BLOCK_SIZE, utflen);
 22.3039 +                        in.readFully(buf, avail, end - avail);
 22.3040 +                    }
 22.3041 +                }
 22.3042 +            }
 22.3043 +
 22.3044 +            return sbuf.toString();
 22.3045 +        }
 22.3046 +
 22.3047 +        /**
 22.3048 +         * Reads span of UTF-encoded characters out of internal buffer
 22.3049 +         * (starting at offset pos and ending at or before offset end),
 22.3050 +         * consuming no more than utflen bytes.  Appends read characters to
 22.3051 +         * sbuf.  Returns the number of bytes consumed.
 22.3052 +         */
 22.3053 +        private long readUTFSpan(StringBuilder sbuf, long utflen)
 22.3054 +            throws IOException
 22.3055 +        {
 22.3056 +            int cpos = 0;
 22.3057 +            int start = pos;
 22.3058 +            int avail = Math.min(end - pos, CHAR_BUF_SIZE);
 22.3059 +            // stop short of last char unless all of utf bytes in buffer
 22.3060 +            int stop = pos + ((utflen > avail) ? avail - 2 : (int) utflen);
 22.3061 +            boolean outOfBounds = false;
 22.3062 +
 22.3063 +            try {
 22.3064 +                while (pos < stop) {
 22.3065 +                    int b1, b2, b3;
 22.3066 +                    b1 = buf[pos++] & 0xFF;
 22.3067 +                    switch (b1 >> 4) {
 22.3068 +                        case 0:
 22.3069 +                        case 1:
 22.3070 +                        case 2:
 22.3071 +                        case 3:
 22.3072 +                        case 4:
 22.3073 +                        case 5:
 22.3074 +                        case 6:
 22.3075 +                        case 7:   // 1 byte format: 0xxxxxxx
 22.3076 +                            cbuf[cpos++] = (char) b1;
 22.3077 +                            break;
 22.3078 +
 22.3079 +                        case 12:
 22.3080 +                        case 13:  // 2 byte format: 110xxxxx 10xxxxxx
 22.3081 +                            b2 = buf[pos++];
 22.3082 +                            if ((b2 & 0xC0) != 0x80) {
 22.3083 +                                throw new UTFDataFormatException();
 22.3084 +                            }
 22.3085 +                            cbuf[cpos++] = (char) (((b1 & 0x1F) << 6) |
 22.3086 +                                                   ((b2 & 0x3F) << 0));
 22.3087 +                            break;
 22.3088 +
 22.3089 +                        case 14:  // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
 22.3090 +                            b3 = buf[pos + 1];
 22.3091 +                            b2 = buf[pos + 0];
 22.3092 +                            pos += 2;
 22.3093 +                            if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
 22.3094 +                                throw new UTFDataFormatException();
 22.3095 +                            }
 22.3096 +                            cbuf[cpos++] = (char) (((b1 & 0x0F) << 12) |
 22.3097 +                                                   ((b2 & 0x3F) << 6) |
 22.3098 +                                                   ((b3 & 0x3F) << 0));
 22.3099 +                            break;
 22.3100 +
 22.3101 +                        default:  // 10xx xxxx, 1111 xxxx
 22.3102 +                            throw new UTFDataFormatException();
 22.3103 +                    }
 22.3104 +                }
 22.3105 +            } catch (ArrayIndexOutOfBoundsException ex) {
 22.3106 +                outOfBounds = true;
 22.3107 +            } finally {
 22.3108 +                if (outOfBounds || (pos - start) > utflen) {
 22.3109 +                    /*
 22.3110 +                     * Fix for 4450867: if a malformed utf char causes the
 22.3111 +                     * conversion loop to scan past the expected end of the utf
 22.3112 +                     * string, only consume the expected number of utf bytes.
 22.3113 +                     */
 22.3114 +                    pos = start + (int) utflen;
 22.3115 +                    throw new UTFDataFormatException();
 22.3116 +                }
 22.3117 +            }
 22.3118 +
 22.3119 +            sbuf.append(cbuf, 0, cpos);
 22.3120 +            return pos - start;
 22.3121 +        }
 22.3122 +
 22.3123 +        /**
 22.3124 +         * Reads in single UTF-encoded character one byte at a time, appends
 22.3125 +         * the character to sbuf, and returns the number of bytes consumed.
 22.3126 +         * This method is used when reading in UTF strings written in block
 22.3127 +         * data mode to handle UTF-encoded characters which (potentially)
 22.3128 +         * straddle block-data boundaries.
 22.3129 +         */
 22.3130 +        private int readUTFChar(StringBuilder sbuf, long utflen)
 22.3131 +            throws IOException
 22.3132 +        {
 22.3133 +            int b1, b2, b3;
 22.3134 +            b1 = readByte() & 0xFF;
 22.3135 +            switch (b1 >> 4) {
 22.3136 +                case 0:
 22.3137 +                case 1:
 22.3138 +                case 2:
 22.3139 +                case 3:
 22.3140 +                case 4:
 22.3141 +                case 5:
 22.3142 +                case 6:
 22.3143 +                case 7:     // 1 byte format: 0xxxxxxx
 22.3144 +                    sbuf.append((char) b1);
 22.3145 +                    return 1;
 22.3146 +
 22.3147 +                case 12:
 22.3148 +                case 13:    // 2 byte format: 110xxxxx 10xxxxxx
 22.3149 +                    if (utflen < 2) {
 22.3150 +                        throw new UTFDataFormatException();
 22.3151 +                    }
 22.3152 +                    b2 = readByte();
 22.3153 +                    if ((b2 & 0xC0) != 0x80) {
 22.3154 +                        throw new UTFDataFormatException();
 22.3155 +                    }
 22.3156 +                    sbuf.append((char) (((b1 & 0x1F) << 6) |
 22.3157 +                                        ((b2 & 0x3F) << 0)));
 22.3158 +                    return 2;
 22.3159 +
 22.3160 +                case 14:    // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
 22.3161 +                    if (utflen < 3) {
 22.3162 +                        if (utflen == 2) {
 22.3163 +                            readByte();         // consume remaining byte
 22.3164 +                        }
 22.3165 +                        throw new UTFDataFormatException();
 22.3166 +                    }
 22.3167 +                    b2 = readByte();
 22.3168 +                    b3 = readByte();
 22.3169 +                    if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
 22.3170 +                        throw new UTFDataFormatException();
 22.3171 +                    }
 22.3172 +                    sbuf.append((char) (((b1 & 0x0F) << 12) |
 22.3173 +                                        ((b2 & 0x3F) << 6) |
 22.3174 +                                        ((b3 & 0x3F) << 0)));
 22.3175 +                    return 3;
 22.3176 +
 22.3177 +                default:   // 10xx xxxx, 1111 xxxx
 22.3178 +                    throw new UTFDataFormatException();
 22.3179 +            }
 22.3180 +        }
 22.3181 +    }
 22.3182 +
 22.3183 +    /**
 22.3184 +     * Unsynchronized table which tracks wire handle to object mappings, as
 22.3185 +     * well as ClassNotFoundExceptions associated with deserialized objects.
 22.3186 +     * This class implements an exception-propagation algorithm for
 22.3187 +     * determining which objects should have ClassNotFoundExceptions associated
 22.3188 +     * with them, taking into account cycles and discontinuities (e.g., skipped
 22.3189 +     * fields) in the object graph.
 22.3190 +     *
 22.3191 +     * <p>General use of the table is as follows: during deserialization, a
 22.3192 +     * given object is first assigned a handle by calling the assign method.
 22.3193 +     * This method leaves the assigned handle in an "open" state, wherein
 22.3194 +     * dependencies on the exception status of other handles can be registered
 22.3195 +     * by calling the markDependency method, or an exception can be directly
 22.3196 +     * associated with the handle by calling markException.  When a handle is
 22.3197 +     * tagged with an exception, the HandleTable assumes responsibility for
 22.3198 +     * propagating the exception to any other objects which depend
 22.3199 +     * (transitively) on the exception-tagged object.
 22.3200 +     *
 22.3201 +     * <p>Once all exception information/dependencies for the handle have been
 22.3202 +     * registered, the handle should be "closed" by calling the finish method
 22.3203 +     * on it.  The act of finishing a handle allows the exception propagation
 22.3204 +     * algorithm to aggressively prune dependency links, lessening the
 22.3205 +     * performance/memory impact of exception tracking.
 22.3206 +     *
 22.3207 +     * <p>Note that the exception propagation algorithm used depends on handles
 22.3208 +     * being assigned/finished in LIFO order; however, for simplicity as well
 22.3209 +     * as memory conservation, it does not enforce this constraint.
 22.3210 +     */
 22.3211 +    // REMIND: add full description of exception propagation algorithm?
 22.3212 +    private static class HandleTable {
 22.3213 +
 22.3214 +        /* status codes indicating whether object has associated exception */
 22.3215 +        private static final byte STATUS_OK = 1;
 22.3216 +        private static final byte STATUS_UNKNOWN = 2;
 22.3217 +        private static final byte STATUS_EXCEPTION = 3;
 22.3218 +
 22.3219 +        /** array mapping handle -> object status */
 22.3220 +        byte[] status;
 22.3221 +        /** array mapping handle -> object/exception (depending on status) */
 22.3222 +        Object[] entries;
 22.3223 +        /** array mapping handle -> list of dependent handles (if any) */
 22.3224 +        HandleList[] deps;
 22.3225 +        /** lowest unresolved dependency */
 22.3226 +        int lowDep = -1;
 22.3227 +        /** number of handles in table */
 22.3228 +        int size = 0;
 22.3229 +
 22.3230 +        /**
 22.3231 +         * Creates handle table with the given initial capacity.
 22.3232 +         */
 22.3233 +        HandleTable(int initialCapacity) {
 22.3234 +            status = new byte[initialCapacity];
 22.3235 +            entries = new Object[initialCapacity];
 22.3236 +            deps = new HandleList[initialCapacity];
 22.3237 +        }
 22.3238 +
 22.3239 +        /**
 22.3240 +         * Assigns next available handle to given object, and returns assigned
 22.3241 +         * handle.  Once object has been completely deserialized (and all
 22.3242 +         * dependencies on other objects identified), the handle should be
 22.3243 +         * "closed" by passing it to finish().
 22.3244 +         */
 22.3245 +        int assign(Object obj) {
 22.3246 +            if (size >= entries.length) {
 22.3247 +                grow();
 22.3248 +            }
 22.3249 +            status[size] = STATUS_UNKNOWN;
 22.3250 +            entries[size] = obj;
 22.3251 +            return size++;
 22.3252 +        }
 22.3253 +
 22.3254 +        /**
 22.3255 +         * Registers a dependency (in exception status) of one handle on
 22.3256 +         * another.  The dependent handle must be "open" (i.e., assigned, but
 22.3257 +         * not finished yet).  No action is taken if either dependent or target
 22.3258 +         * handle is NULL_HANDLE.
 22.3259 +         */
 22.3260 +        void markDependency(int dependent, int target) {
 22.3261 +            if (dependent == NULL_HANDLE || target == NULL_HANDLE) {
 22.3262 +                return;
 22.3263 +            }
 22.3264 +            switch (status[dependent]) {
 22.3265 +
 22.3266 +                case STATUS_UNKNOWN:
 22.3267 +                    switch (status[target]) {
 22.3268 +                        case STATUS_OK:
 22.3269 +                            // ignore dependencies on objs with no exception
 22.3270 +                            break;
 22.3271 +
 22.3272 +                        case STATUS_EXCEPTION:
 22.3273 +                            // eagerly propagate exception
 22.3274 +                            markException(dependent,
 22.3275 +                                (ClassNotFoundException) entries[target]);
 22.3276 +                            break;
 22.3277 +
 22.3278 +                        case STATUS_UNKNOWN:
 22.3279 +                            // add to dependency list of target
 22.3280 +                            if (deps[target] == null) {
 22.3281 +                                deps[target] = new HandleList();
 22.3282 +                            }
 22.3283 +                            deps[target].add(dependent);
 22.3284 +
 22.3285 +                            // remember lowest unresolved target seen
 22.3286 +                            if (lowDep < 0 || lowDep > target) {
 22.3287 +                                lowDep = target;
 22.3288 +                            }
 22.3289 +                            break;
 22.3290 +
 22.3291 +                        default:
 22.3292 +                            throw new InternalError();
 22.3293 +                    }
 22.3294 +                    break;
 22.3295 +
 22.3296 +                case STATUS_EXCEPTION:
 22.3297 +                    break;
 22.3298 +
 22.3299 +                default:
 22.3300 +                    throw new InternalError();
 22.3301 +            }
 22.3302 +        }
 22.3303 +
 22.3304 +        /**
 22.3305 +         * Associates a ClassNotFoundException (if one not already associated)
 22.3306 +         * with the currently active handle and propagates it to other
 22.3307 +         * referencing objects as appropriate.  The specified handle must be
 22.3308 +         * "open" (i.e., assigned, but not finished yet).
 22.3309 +         */
 22.3310 +        void markException(int handle, ClassNotFoundException ex) {
 22.3311 +            switch (status[handle]) {
 22.3312 +                case STATUS_UNKNOWN:
 22.3313 +                    status[handle] = STATUS_EXCEPTION;
 22.3314 +                    entries[handle] = ex;
 22.3315 +
 22.3316 +                    // propagate exception to dependents
 22.3317 +                    HandleList dlist = deps[handle];
 22.3318 +                    if (dlist != null) {
 22.3319 +                        int ndeps = dlist.size();
 22.3320 +                        for (int i = 0; i < ndeps; i++) {
 22.3321 +                            markException(dlist.get(i), ex);
 22.3322 +                        }
 22.3323 +                        deps[handle] = null;
 22.3324 +                    }
 22.3325 +                    break;
 22.3326 +
 22.3327 +                case STATUS_EXCEPTION:
 22.3328 +                    break;
 22.3329 +
 22.3330 +                default:
 22.3331 +                    throw new InternalError();
 22.3332 +            }
 22.3333 +        }
 22.3334 +
 22.3335 +        /**
 22.3336 +         * Marks given handle as finished, meaning that no new dependencies
 22.3337 +         * will be marked for handle.  Calls to the assign and finish methods
 22.3338 +         * must occur in LIFO order.
 22.3339 +         */
 22.3340 +        void finish(int handle) {
 22.3341 +            int end;
 22.3342 +            if (lowDep < 0) {
 22.3343 +                // no pending unknowns, only resolve current handle
 22.3344 +                end = handle + 1;
 22.3345 +            } else if (lowDep >= handle) {
 22.3346 +                // pending unknowns now clearable, resolve all upward handles
 22.3347 +                end = size;
 22.3348 +                lowDep = -1;
 22.3349 +            } else {
 22.3350 +                // unresolved backrefs present, can't resolve anything yet
 22.3351 +                return;
 22.3352 +            }
 22.3353 +
 22.3354 +            // change STATUS_UNKNOWN -> STATUS_OK in selected span of handles
 22.3355 +            for (int i = handle; i < end; i++) {
 22.3356 +                switch (status[i]) {
 22.3357 +                    case STATUS_UNKNOWN:
 22.3358 +                        status[i] = STATUS_OK;
 22.3359 +                        deps[i] = null;
 22.3360 +                        break;
 22.3361 +
 22.3362 +                    case STATUS_OK:
 22.3363 +                    case STATUS_EXCEPTION:
 22.3364 +                        break;
 22.3365 +
 22.3366 +                    default:
 22.3367 +                        throw new InternalError();
 22.3368 +                }
 22.3369 +            }
 22.3370 +        }
 22.3371 +
 22.3372 +        /**
 22.3373 +         * Assigns a new object to the given handle.  The object previously
 22.3374 +         * associated with the handle is forgotten.  This method has no effect
 22.3375 +         * if the given handle already has an exception associated with it.
 22.3376 +         * This method may be called at any time after the handle is assigned.
 22.3377 +         */
 22.3378 +        void setObject(int handle, Object obj) {
 22.3379 +            switch (status[handle]) {
 22.3380 +                case STATUS_UNKNOWN:
 22.3381 +                case STATUS_OK:
 22.3382 +                    entries[handle] = obj;
 22.3383 +                    break;
 22.3384 +
 22.3385 +                case STATUS_EXCEPTION:
 22.3386 +                    break;
 22.3387 +
 22.3388 +                default:
 22.3389 +                    throw new InternalError();
 22.3390 +            }
 22.3391 +        }
 22.3392 +
 22.3393 +        /**
 22.3394 +         * Looks up and returns object associated with the given handle.
 22.3395 +         * Returns null if the given handle is NULL_HANDLE, or if it has an
 22.3396 +         * associated ClassNotFoundException.
 22.3397 +         */
 22.3398 +        Object lookupObject(int handle) {
 22.3399 +            return (handle != NULL_HANDLE &&
 22.3400 +                    status[handle] != STATUS_EXCEPTION) ?
 22.3401 +                entries[handle] : null;
 22.3402 +        }
 22.3403 +
 22.3404 +        /**
 22.3405 +         * Looks up and returns ClassNotFoundException associated with the
 22.3406 +         * given handle.  Returns null if the given handle is NULL_HANDLE, or
 22.3407 +         * if there is no ClassNotFoundException associated with the handle.
 22.3408 +         */
 22.3409 +        ClassNotFoundException lookupException(int handle) {
 22.3410 +            return (handle != NULL_HANDLE &&
 22.3411 +                    status[handle] == STATUS_EXCEPTION) ?
 22.3412 +                (ClassNotFoundException) entries[handle] : null;
 22.3413 +        }
 22.3414 +
 22.3415 +        /**
 22.3416 +         * Resets table to its initial state.
 22.3417 +         */
 22.3418 +        void clear() {
 22.3419 +            Arrays.fill(status, 0, size, (byte) 0);
 22.3420 +            Arrays.fill(entries, 0, size, null);
 22.3421 +            Arrays.fill(deps, 0, size, null);
 22.3422 +            lowDep = -1;
 22.3423 +            size = 0;
 22.3424 +        }
 22.3425 +
 22.3426 +        /**
 22.3427 +         * Returns number of handles registered in table.
 22.3428 +         */
 22.3429 +        int size() {
 22.3430 +            return size;
 22.3431 +        }
 22.3432 +
 22.3433 +        /**
 22.3434 +         * Expands capacity of internal arrays.
 22.3435 +         */
 22.3436 +        private void grow() {
 22.3437 +            int newCapacity = (entries.length << 1) + 1;
 22.3438 +
 22.3439 +            byte[] newStatus = new byte[newCapacity];
 22.3440 +            Object[] newEntries = new Object[newCapacity];
 22.3441 +            HandleList[] newDeps = new HandleList[newCapacity];
 22.3442 +
 22.3443 +            System.arraycopy(status, 0, newStatus, 0, size);
 22.3444 +            System.arraycopy(entries, 0, newEntries, 0, size);
 22.3445 +            System.arraycopy(deps, 0, newDeps, 0, size);
 22.3446 +
 22.3447 +            status = newStatus;
 22.3448 +            entries = newEntries;
 22.3449 +            deps = newDeps;
 22.3450 +        }
 22.3451 +
 22.3452 +        /**
 22.3453 +         * Simple growable list of (integer) handles.
 22.3454 +         */
 22.3455 +        private static class HandleList {
 22.3456 +            private int[] list = new int[4];
 22.3457 +            private int size = 0;
 22.3458 +
 22.3459 +            public HandleList() {
 22.3460 +            }
 22.3461 +
 22.3462 +            public void add(int handle) {
 22.3463 +                if (size >= list.length) {
 22.3464 +                    int[] newList = new int[list.length << 1];
 22.3465 +                    System.arraycopy(list, 0, newList, 0, list.length);
 22.3466 +                    list = newList;
 22.3467 +                }
 22.3468 +                list[size++] = handle;
 22.3469 +            }
 22.3470 +
 22.3471 +            public int get(int index) {
 22.3472 +                if (index >= size) {
 22.3473 +                    throw new ArrayIndexOutOfBoundsException();
 22.3474 +                }
 22.3475 +                return list[index];
 22.3476 +            }
 22.3477 +
 22.3478 +            public int size() {
 22.3479 +                return size;
 22.3480 +            }
 22.3481 +        }
 22.3482 +    }
 22.3483 +
 22.3484 +    /**
 22.3485 +     * Method for cloning arrays in case of using unsharing reading
 22.3486 +     */
 22.3487 +    private static Object cloneArray(Object array) {
 22.3488 +        if (array instanceof Object[]) {
 22.3489 +            return ((Object[]) array).clone();
 22.3490 +        } else if (array instanceof boolean[]) {
 22.3491 +            return ((boolean[]) array).clone();
 22.3492 +        } else if (array instanceof byte[]) {
 22.3493 +            return ((byte[]) array).clone();
 22.3494 +        } else if (array instanceof char[]) {
 22.3495 +            return ((char[]) array).clone();
 22.3496 +        } else if (array instanceof double[]) {
 22.3497 +            return ((double[]) array).clone();
 22.3498 +        } else if (array instanceof float[]) {
 22.3499 +            return ((float[]) array).clone();
 22.3500 +        } else if (array instanceof int[]) {
 22.3501 +            return ((int[]) array).clone();
 22.3502 +        } else if (array instanceof long[]) {
 22.3503 +            return ((long[]) array).clone();
 22.3504 +        } else if (array instanceof short[]) {
 22.3505 +            return ((short[]) array).clone();
 22.3506 +        } else {
 22.3507 +            throw new AssertionError();
 22.3508 +        }
 22.3509 +    }
 22.3510 +
 22.3511 +}
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/emul/compact/src/main/java/java/io/ObjectInputValidation.java	Mon Jan 28 18:14:14 2013 +0100
    23.3 @@ -0,0 +1,45 @@
    23.4 +/*
    23.5 + * Copyright (c) 1996, 1999, Oracle and/or its affiliates. All rights reserved.
    23.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    23.7 + *
    23.8 + * This code is free software; you can redistribute it and/or modify it
    23.9 + * under the terms of the GNU General Public License version 2 only, as
   23.10 + * published by the Free Software Foundation.  Oracle designates this
   23.11 + * particular file as subject to the "Classpath" exception as provided
   23.12 + * by Oracle in the LICENSE file that accompanied this code.
   23.13 + *
   23.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   23.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   23.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   23.17 + * version 2 for more details (a copy is included in the LICENSE file that
   23.18 + * accompanied this code).
   23.19 + *
   23.20 + * You should have received a copy of the GNU General Public License version
   23.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   23.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   23.23 + *
   23.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   23.25 + * or visit www.oracle.com if you need additional information or have any
   23.26 + * questions.
   23.27 + */
   23.28 +
   23.29 +package java.io;
   23.30 +
   23.31 +/**
   23.32 + * Callback interface to allow validation of objects within a graph.
   23.33 + * Allows an object to be called when a complete graph of objects has
   23.34 + * been deserialized.
   23.35 + *
   23.36 + * @author  unascribed
   23.37 + * @see     ObjectInputStream
   23.38 + * @see     ObjectInputStream#registerValidation(java.io.ObjectInputValidation, int)
   23.39 + * @since   JDK1.1
   23.40 + */
   23.41 +public interface ObjectInputValidation {
   23.42 +    /**
   23.43 +     * Validates the object.
   23.44 +     *
   23.45 +     * @exception InvalidObjectException If the object cannot validate itself.
   23.46 +     */
   23.47 +    public void validateObject() throws InvalidObjectException;
   23.48 +}
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/emul/compact/src/main/java/java/io/ObjectOutput.java	Mon Jan 28 18:14:14 2013 +0100
    24.3 @@ -0,0 +1,90 @@
    24.4 +/*
    24.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
    24.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    24.7 + *
    24.8 + * This code is free software; you can redistribute it and/or modify it
    24.9 + * under the terms of the GNU General Public License version 2 only, as
   24.10 + * published by the Free Software Foundation.  Oracle designates this
   24.11 + * particular file as subject to the "Classpath" exception as provided
   24.12 + * by Oracle in the LICENSE file that accompanied this code.
   24.13 + *
   24.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   24.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   24.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   24.17 + * version 2 for more details (a copy is included in the LICENSE file that
   24.18 + * accompanied this code).
   24.19 + *
   24.20 + * You should have received a copy of the GNU General Public License version
   24.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   24.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   24.23 + *
   24.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   24.25 + * or visit www.oracle.com if you need additional information or have any
   24.26 + * questions.
   24.27 + */
   24.28 +
   24.29 +package java.io;
   24.30 +
   24.31 +/**
   24.32 + * ObjectOutput extends the DataOutput interface to include writing of objects.
   24.33 + * DataOutput includes methods for output of primitive types, ObjectOutput
   24.34 + * extends that interface to include objects, arrays, and Strings.
   24.35 + *
   24.36 + * @author  unascribed
   24.37 + * @see java.io.InputStream
   24.38 + * @see java.io.ObjectOutputStream
   24.39 + * @see java.io.ObjectInputStream
   24.40 + * @since   JDK1.1
   24.41 + */
   24.42 +public interface ObjectOutput extends DataOutput, AutoCloseable {
   24.43 +    /**
   24.44 +     * Write an object to the underlying storage or stream.  The
   24.45 +     * class that implements this interface defines how the object is
   24.46 +     * written.
   24.47 +     *
   24.48 +     * @param obj the object to be written
   24.49 +     * @exception IOException Any of the usual Input/Output related exceptions.
   24.50 +     */
   24.51 +    public void writeObject(Object obj)
   24.52 +      throws IOException;
   24.53 +
   24.54 +    /**
   24.55 +     * Writes a byte. This method will block until the byte is actually
   24.56 +     * written.
   24.57 +     * @param b the byte
   24.58 +     * @exception IOException If an I/O error has occurred.
   24.59 +     */
   24.60 +    public void write(int b) throws IOException;
   24.61 +
   24.62 +    /**
   24.63 +     * Writes an array of bytes. This method will block until the bytes
   24.64 +     * are actually written.
   24.65 +     * @param b the data to be written
   24.66 +     * @exception IOException If an I/O error has occurred.
   24.67 +     */
   24.68 +    public void write(byte b[]) throws IOException;
   24.69 +
   24.70 +    /**
   24.71 +     * Writes a sub array of bytes.
   24.72 +     * @param b the data to be written
   24.73 +     * @param off       the start offset in the data
   24.74 +     * @param len       the number of bytes that are written
   24.75 +     * @exception IOException If an I/O error has occurred.
   24.76 +     */
   24.77 +    public void write(byte b[], int off, int len) throws IOException;
   24.78 +
   24.79 +    /**
   24.80 +     * Flushes the stream. This will write any buffered
   24.81 +     * output bytes.
   24.82 +     * @exception IOException If an I/O error has occurred.
   24.83 +     */
   24.84 +    public void flush() throws IOException;
   24.85 +
   24.86 +    /**
   24.87 +     * Closes the stream. This method must be called
   24.88 +     * to release any resources associated with the
   24.89 +     * stream.
   24.90 +     * @exception IOException If an I/O error has occurred.
   24.91 +     */
   24.92 +    public void close() throws IOException;
   24.93 +}
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/emul/compact/src/main/java/java/io/ObjectOutputStream.java	Mon Jan 28 18:14:14 2013 +0100
    25.3 @@ -0,0 +1,2454 @@
    25.4 +/*
    25.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
    25.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    25.7 + *
    25.8 + * This code is free software; you can redistribute it and/or modify it
    25.9 + * under the terms of the GNU General Public License version 2 only, as
   25.10 + * published by the Free Software Foundation.  Oracle designates this
   25.11 + * particular file as subject to the "Classpath" exception as provided
   25.12 + * by Oracle in the LICENSE file that accompanied this code.
   25.13 + *
   25.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   25.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   25.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   25.17 + * version 2 for more details (a copy is included in the LICENSE file that
   25.18 + * accompanied this code).
   25.19 + *
   25.20 + * You should have received a copy of the GNU General Public License version
   25.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   25.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   25.23 + *
   25.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   25.25 + * or visit www.oracle.com if you need additional information or have any
   25.26 + * questions.
   25.27 + */
   25.28 +
   25.29 +package java.io;
   25.30 +
   25.31 +import java.io.ObjectStreamClass.WeakClassKey;
   25.32 +import java.lang.ref.ReferenceQueue;
   25.33 +import java.security.AccessController;
   25.34 +import java.security.PrivilegedAction;
   25.35 +import java.util.ArrayList;
   25.36 +import java.util.Arrays;
   25.37 +import java.util.List;
   25.38 +import java.util.concurrent.ConcurrentHashMap;
   25.39 +import java.util.concurrent.ConcurrentMap;
   25.40 +import static java.io.ObjectStreamClass.processQueue;
   25.41 +import java.io.SerialCallbackContext;
   25.42 +
   25.43 +/**
   25.44 + * An ObjectOutputStream writes primitive data types and graphs of Java objects
   25.45 + * to an OutputStream.  The objects can be read (reconstituted) using an
   25.46 + * ObjectInputStream.  Persistent storage of objects can be accomplished by
   25.47 + * using a file for the stream.  If the stream is a network socket stream, the
   25.48 + * objects can be reconstituted on another host or in another process.
   25.49 + *
   25.50 + * <p>Only objects that support the java.io.Serializable interface can be
   25.51 + * written to streams.  The class of each serializable object is encoded
   25.52 + * including the class name and signature of the class, the values of the
   25.53 + * object's fields and arrays, and the closure of any other objects referenced
   25.54 + * from the initial objects.
   25.55 + *
   25.56 + * <p>The method writeObject is used to write an object to the stream.  Any
   25.57 + * object, including Strings and arrays, is written with writeObject. Multiple
   25.58 + * objects or primitives can be written to the stream.  The objects must be
   25.59 + * read back from the corresponding ObjectInputstream with the same types and
   25.60 + * in the same order as they were written.
   25.61 + *
   25.62 + * <p>Primitive data types can also be written to the stream using the
   25.63 + * appropriate methods from DataOutput. Strings can also be written using the
   25.64 + * writeUTF method.
   25.65 + *
   25.66 + * <p>The default serialization mechanism for an object writes the class of the
   25.67 + * object, the class signature, and the values of all non-transient and
   25.68 + * non-static fields.  References to other objects (except in transient or
   25.69 + * static fields) cause those objects to be written also. Multiple references
   25.70 + * to a single object are encoded using a reference sharing mechanism so that
   25.71 + * graphs of objects can be restored to the same shape as when the original was
   25.72 + * written.
   25.73 + *
   25.74 + * <p>For example to write an object that can be read by the example in
   25.75 + * ObjectInputStream:
   25.76 + * <br>
   25.77 + * <pre>
   25.78 + *      FileOutputStream fos = new FileOutputStream("t.tmp");
   25.79 + *      ObjectOutputStream oos = new ObjectOutputStream(fos);
   25.80 + *
   25.81 + *      oos.writeInt(12345);
   25.82 + *      oos.writeObject("Today");
   25.83 + *      oos.writeObject(new Date());
   25.84 + *
   25.85 + *      oos.close();
   25.86 + * </pre>
   25.87 + *
   25.88 + * <p>Classes that require special handling during the serialization and
   25.89 + * deserialization process must implement special methods with these exact
   25.90 + * signatures:
   25.91 + * <br>
   25.92 + * <pre>
   25.93 + * private void readObject(java.io.ObjectInputStream stream)
   25.94 + *     throws IOException, ClassNotFoundException;
   25.95 + * private void writeObject(java.io.ObjectOutputStream stream)
   25.96 + *     throws IOException
   25.97 + * private void readObjectNoData()
   25.98 + *     throws ObjectStreamException;
   25.99 + * </pre>
  25.100 + *
  25.101 + * <p>The writeObject method is responsible for writing the state of the object
  25.102 + * for its particular class so that the corresponding readObject method can
  25.103 + * restore it.  The method does not need to concern itself with the state
  25.104 + * belonging to the object's superclasses or subclasses.  State is saved by
  25.105 + * writing the individual fields to the ObjectOutputStream using the
  25.106 + * writeObject method or by using the methods for primitive data types
  25.107 + * supported by DataOutput.
  25.108 + *
  25.109 + * <p>Serialization does not write out the fields of any object that does not
  25.110 + * implement the java.io.Serializable interface.  Subclasses of Objects that
  25.111 + * are not serializable can be serializable. In this case the non-serializable
  25.112 + * class must have a no-arg constructor to allow its fields to be initialized.
  25.113 + * In this case it is the responsibility of the subclass to save and restore
  25.114 + * the state of the non-serializable class. It is frequently the case that the
  25.115 + * fields of that class are accessible (public, package, or protected) or that
  25.116 + * there are get and set methods that can be used to restore the state.
  25.117 + *
  25.118 + * <p>Serialization of an object can be prevented by implementing writeObject
  25.119 + * and readObject methods that throw the NotSerializableException.  The
  25.120 + * exception will be caught by the ObjectOutputStream and abort the
  25.121 + * serialization process.
  25.122 + *
  25.123 + * <p>Implementing the Externalizable interface allows the object to assume
  25.124 + * complete control over the contents and format of the object's serialized
  25.125 + * form.  The methods of the Externalizable interface, writeExternal and
  25.126 + * readExternal, are called to save and restore the objects state.  When
  25.127 + * implemented by a class they can write and read their own state using all of
  25.128 + * the methods of ObjectOutput and ObjectInput.  It is the responsibility of
  25.129 + * the objects to handle any versioning that occurs.
  25.130 + *
  25.131 + * <p>Enum constants are serialized differently than ordinary serializable or
  25.132 + * externalizable objects.  The serialized form of an enum constant consists
  25.133 + * solely of its name; field values of the constant are not transmitted.  To
  25.134 + * serialize an enum constant, ObjectOutputStream writes the string returned by
  25.135 + * the constant's name method.  Like other serializable or externalizable
  25.136 + * objects, enum constants can function as the targets of back references
  25.137 + * appearing subsequently in the serialization stream.  The process by which
  25.138 + * enum constants are serialized cannot be customized; any class-specific
  25.139 + * writeObject and writeReplace methods defined by enum types are ignored
  25.140 + * during serialization.  Similarly, any serialPersistentFields or
  25.141 + * serialVersionUID field declarations are also ignored--all enum types have a
  25.142 + * fixed serialVersionUID of 0L.
  25.143 + *
  25.144 + * <p>Primitive data, excluding serializable fields and externalizable data, is
  25.145 + * written to the ObjectOutputStream in block-data records. A block data record
  25.146 + * is composed of a header and data. The block data header consists of a marker
  25.147 + * and the number of bytes to follow the header.  Consecutive primitive data
  25.148 + * writes are merged into one block-data record.  The blocking factor used for
  25.149 + * a block-data record will be 1024 bytes.  Each block-data record will be
  25.150 + * filled up to 1024 bytes, or be written whenever there is a termination of
  25.151 + * block-data mode.  Calls to the ObjectOutputStream methods writeObject,
  25.152 + * defaultWriteObject and writeFields initially terminate any existing
  25.153 + * block-data record.
  25.154 + *
  25.155 + * @author      Mike Warres
  25.156 + * @author      Roger Riggs
  25.157 + * @see java.io.DataOutput
  25.158 + * @see java.io.ObjectInputStream
  25.159 + * @see java.io.Serializable
  25.160 + * @see java.io.Externalizable
  25.161 + * @see <a href="../../../platform/serialization/spec/output.html">Object Serialization Specification, Section 2, Object Output Classes</a>
  25.162 + * @since       JDK1.1
  25.163 + */
  25.164 +public class ObjectOutputStream
  25.165 +    extends OutputStream implements ObjectOutput, ObjectStreamConstants
  25.166 +{
  25.167 +
  25.168 +    private static class Caches {
  25.169 +        /** cache of subclass security audit results */
  25.170 +        static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits =
  25.171 +            new ConcurrentHashMap<>();
  25.172 +
  25.173 +        /** queue for WeakReferences to audited subclasses */
  25.174 +        static final ReferenceQueue<Class<?>> subclassAuditsQueue =
  25.175 +            new ReferenceQueue<>();
  25.176 +    }
  25.177 +
  25.178 +    /** filter stream for handling block data conversion */
  25.179 +    private final BlockDataOutputStream bout;
  25.180 +    /** obj -> wire handle map */
  25.181 +    private final HandleTable handles;
  25.182 +    /** obj -> replacement obj map */
  25.183 +    private final ReplaceTable subs;
  25.184 +    /** stream protocol version */
  25.185 +    private int protocol = PROTOCOL_VERSION_2;
  25.186 +    /** recursion depth */
  25.187 +    private int depth;
  25.188 +
  25.189 +    /** buffer for writing primitive field values */
  25.190 +    private byte[] primVals;
  25.191 +
  25.192 +    /** if true, invoke writeObjectOverride() instead of writeObject() */
  25.193 +    private final boolean enableOverride;
  25.194 +    /** if true, invoke replaceObject() */
  25.195 +    private boolean enableReplace;
  25.196 +
  25.197 +    // values below valid only during upcalls to writeObject()/writeExternal()
  25.198 +    /**
  25.199 +     * Context during upcalls to class-defined writeObject methods; holds
  25.200 +     * object currently being serialized and descriptor for current class.
  25.201 +     * Null when not during writeObject upcall.
  25.202 +     */
  25.203 +    private SerialCallbackContext curContext;
  25.204 +    /** current PutField object */
  25.205 +    private PutFieldImpl curPut;
  25.206 +
  25.207 +    /** custom storage for debug trace info */
  25.208 +    private final DebugTraceInfoStack debugInfoStack;
  25.209 +
  25.210 +    /**
  25.211 +     * value of "sun.io.serialization.extendedDebugInfo" property,
  25.212 +     * as true or false for extended information about exception's place
  25.213 +     */
  25.214 +    private static final boolean extendedDebugInfo =
  25.215 +        java.security.AccessController.doPrivileged(
  25.216 +            new sun.security.action.GetBooleanAction(
  25.217 +                "sun.io.serialization.extendedDebugInfo")).booleanValue();
  25.218 +
  25.219 +    /**
  25.220 +     * Creates an ObjectOutputStream that writes to the specified OutputStream.
  25.221 +     * This constructor writes the serialization stream header to the
  25.222 +     * underlying stream; callers may wish to flush the stream immediately to
  25.223 +     * ensure that constructors for receiving ObjectInputStreams will not block
  25.224 +     * when reading the header.
  25.225 +     *
  25.226 +     * <p>If a security manager is installed, this constructor will check for
  25.227 +     * the "enableSubclassImplementation" SerializablePermission when invoked
  25.228 +     * directly or indirectly by the constructor of a subclass which overrides
  25.229 +     * the ObjectOutputStream.putFields or ObjectOutputStream.writeUnshared
  25.230 +     * methods.
  25.231 +     *
  25.232 +     * @param   out output stream to write to
  25.233 +     * @throws  IOException if an I/O error occurs while writing stream header
  25.234 +     * @throws  SecurityException if untrusted subclass illegally overrides
  25.235 +     *          security-sensitive methods
  25.236 +     * @throws  NullPointerException if <code>out</code> is <code>null</code>
  25.237 +     * @since   1.4
  25.238 +     * @see     ObjectOutputStream#ObjectOutputStream()
  25.239 +     * @see     ObjectOutputStream#putFields()
  25.240 +     * @see     ObjectInputStream#ObjectInputStream(InputStream)
  25.241 +     */
  25.242 +    public ObjectOutputStream(OutputStream out) throws IOException {
  25.243 +        verifySubclass();
  25.244 +        bout = new BlockDataOutputStream(out);
  25.245 +        handles = new HandleTable(10, (float) 3.00);
  25.246 +        subs = new ReplaceTable(10, (float) 3.00);
  25.247 +        enableOverride = false;
  25.248 +        writeStreamHeader();
  25.249 +        bout.setBlockDataMode(true);
  25.250 +        if (extendedDebugInfo) {
  25.251 +            debugInfoStack = new DebugTraceInfoStack();
  25.252 +        } else {
  25.253 +            debugInfoStack = null;
  25.254 +        }
  25.255 +    }
  25.256 +
  25.257 +    /**
  25.258 +     * Provide a way for subclasses that are completely reimplementing
  25.259 +     * ObjectOutputStream to not have to allocate private data just used by
  25.260 +     * this implementation of ObjectOutputStream.
  25.261 +     *
  25.262 +     * <p>If there is a security manager installed, this method first calls the
  25.263 +     * security manager's <code>checkPermission</code> method with a
  25.264 +     * <code>SerializablePermission("enableSubclassImplementation")</code>
  25.265 +     * permission to ensure it's ok to enable subclassing.
  25.266 +     *
  25.267 +     * @throws  SecurityException if a security manager exists and its
  25.268 +     *          <code>checkPermission</code> method denies enabling
  25.269 +     *          subclassing.
  25.270 +     * @see SecurityManager#checkPermission
  25.271 +     * @see java.io.SerializablePermission
  25.272 +     */
  25.273 +    protected ObjectOutputStream() throws IOException, SecurityException {
  25.274 +        SecurityManager sm = System.getSecurityManager();
  25.275 +        if (sm != null) {
  25.276 +            sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
  25.277 +        }
  25.278 +        bout = null;
  25.279 +        handles = null;
  25.280 +        subs = null;
  25.281 +        enableOverride = true;
  25.282 +        debugInfoStack = null;
  25.283 +    }
  25.284 +
  25.285 +    /**
  25.286 +     * Specify stream protocol version to use when writing the stream.
  25.287 +     *
  25.288 +     * <p>This routine provides a hook to enable the current version of
  25.289 +     * Serialization to write in a format that is backwards compatible to a
  25.290 +     * previous version of the stream format.
  25.291 +     *
  25.292 +     * <p>Every effort will be made to avoid introducing additional
  25.293 +     * backwards incompatibilities; however, sometimes there is no
  25.294 +     * other alternative.
  25.295 +     *
  25.296 +     * @param   version use ProtocolVersion from java.io.ObjectStreamConstants.
  25.297 +     * @throws  IllegalStateException if called after any objects
  25.298 +     *          have been serialized.
  25.299 +     * @throws  IllegalArgumentException if invalid version is passed in.
  25.300 +     * @throws  IOException if I/O errors occur
  25.301 +     * @see java.io.ObjectStreamConstants#PROTOCOL_VERSION_1
  25.302 +     * @see java.io.ObjectStreamConstants#PROTOCOL_VERSION_2
  25.303 +     * @since   1.2
  25.304 +     */
  25.305 +    public void useProtocolVersion(int version) throws IOException {
  25.306 +        if (handles.size() != 0) {
  25.307 +            // REMIND: implement better check for pristine stream?
  25.308 +            throw new IllegalStateException("stream non-empty");
  25.309 +        }
  25.310 +        switch (version) {
  25.311 +            case PROTOCOL_VERSION_1:
  25.312 +            case PROTOCOL_VERSION_2:
  25.313 +                protocol = version;
  25.314 +                break;
  25.315 +
  25.316 +            default:
  25.317 +                throw new IllegalArgumentException(
  25.318 +                    "unknown version: " + version);
  25.319 +        }
  25.320 +    }
  25.321 +
  25.322 +    /**
  25.323 +     * Write the specified object to the ObjectOutputStream.  The class of the
  25.324 +     * object, the signature of the class, and the values of the non-transient
  25.325 +     * and non-static fields of the class and all of its supertypes are
  25.326 +     * written.  Default serialization for a class can be overridden using the
  25.327 +     * writeObject and the readObject methods.  Objects referenced by this
  25.328 +     * object are written transitively so that a complete equivalent graph of
  25.329 +     * objects can be reconstructed by an ObjectInputStream.
  25.330 +     *
  25.331 +     * <p>Exceptions are thrown for problems with the OutputStream and for
  25.332 +     * classes that should not be serialized.  All exceptions are fatal to the
  25.333 +     * OutputStream, which is left in an indeterminate state, and it is up to
  25.334 +     * the caller to ignore or recover the stream state.
  25.335 +     *
  25.336 +     * @throws  InvalidClassException Something is wrong with a class used by
  25.337 +     *          serialization.
  25.338 +     * @throws  NotSerializableException Some object to be serialized does not
  25.339 +     *          implement the java.io.Serializable interface.
  25.340 +     * @throws  IOException Any exception thrown by the underlying
  25.341 +     *          OutputStream.
  25.342 +     */
  25.343 +    public final void writeObject(Object obj) throws IOException {
  25.344 +        if (enableOverride) {
  25.345 +            writeObjectOverride(obj);
  25.346 +            return;
  25.347 +        }
  25.348 +        try {
  25.349 +            writeObject0(obj, false);
  25.350 +        } catch (IOException ex) {
  25.351 +            if (depth == 0) {
  25.352 +                writeFatalException(ex);
  25.353 +            }
  25.354 +            throw ex;
  25.355 +        }
  25.356 +    }
  25.357 +
  25.358 +    /**
  25.359 +     * Method used by subclasses to override the default writeObject method.
  25.360 +     * This method is called by trusted subclasses of ObjectInputStream that
  25.361 +     * constructed ObjectInputStream using the protected no-arg constructor.
  25.362 +     * The subclass is expected to provide an override method with the modifier
  25.363 +     * "final".
  25.364 +     *
  25.365 +     * @param   obj object to be written to the underlying stream
  25.366 +     * @throws  IOException if there are I/O errors while writing to the
  25.367 +     *          underlying stream
  25.368 +     * @see #ObjectOutputStream()
  25.369 +     * @see #writeObject(Object)
  25.370 +     * @since 1.2
  25.371 +     */
  25.372 +    protected void writeObjectOverride(Object obj) throws IOException {
  25.373 +    }
  25.374 +
  25.375 +    /**
  25.376 +     * Writes an "unshared" object to the ObjectOutputStream.  This method is
  25.377 +     * identical to writeObject, except that it always writes the given object
  25.378 +     * as a new, unique object in the stream (as opposed to a back-reference
  25.379 +     * pointing to a previously serialized instance).  Specifically:
  25.380 +     * <ul>
  25.381 +     *   <li>An object written via writeUnshared is always serialized in the
  25.382 +     *       same manner as a newly appearing object (an object that has not
  25.383 +     *       been written to the stream yet), regardless of whether or not the
  25.384 +     *       object has been written previously.
  25.385 +     *
  25.386 +     *   <li>If writeObject is used to write an object that has been previously
  25.387 +     *       written with writeUnshared, the previous writeUnshared operation
  25.388 +     *       is treated as if it were a write of a separate object.  In other
  25.389 +     *       words, ObjectOutputStream will never generate back-references to
  25.390 +     *       object data written by calls to writeUnshared.
  25.391 +     * </ul>
  25.392 +     * While writing an object via writeUnshared does not in itself guarantee a
  25.393 +     * unique reference to the object when it is deserialized, it allows a
  25.394 +     * single object to be defined multiple times in a stream, so that multiple
  25.395 +     * calls to readUnshared by the receiver will not conflict.  Note that the
  25.396 +     * rules described above only apply to the base-level object written with
  25.397 +     * writeUnshared, and not to any transitively referenced sub-objects in the
  25.398 +     * object graph to be serialized.
  25.399 +     *
  25.400 +     * <p>ObjectOutputStream subclasses which override this method can only be
  25.401 +     * constructed in security contexts possessing the
  25.402 +     * "enableSubclassImplementation" SerializablePermission; any attempt to
  25.403 +     * instantiate such a subclass without this permission will cause a
  25.404 +     * SecurityException to be thrown.
  25.405 +     *
  25.406 +     * @param   obj object to write to stream
  25.407 +     * @throws  NotSerializableException if an object in the graph to be
  25.408 +     *          serialized does not implement the Serializable interface
  25.409 +     * @throws  InvalidClassException if a problem exists with the class of an
  25.410 +     *          object to be serialized
  25.411 +     * @throws  IOException if an I/O error occurs during serialization
  25.412 +     * @since 1.4
  25.413 +     */
  25.414 +    public void writeUnshared(Object obj) throws IOException {
  25.415 +        try {
  25.416 +            writeObject0(obj, true);
  25.417 +        } catch (IOException ex) {
  25.418 +            if (depth == 0) {
  25.419 +                writeFatalException(ex);
  25.420 +            }
  25.421 +            throw ex;
  25.422 +        }
  25.423 +    }
  25.424 +
  25.425 +    /**
  25.426 +     * Write the non-static and non-transient fields of the current class to
  25.427 +     * this stream.  This may only be called from the writeObject method of the
  25.428 +     * class being serialized. It will throw the NotActiveException if it is
  25.429 +     * called otherwise.
  25.430 +     *
  25.431 +     * @throws  IOException if I/O errors occur while writing to the underlying
  25.432 +     *          <code>OutputStream</code>
  25.433 +     */
  25.434 +    public void defaultWriteObject() throws IOException {
  25.435 +        if ( curContext == null ) {
  25.436 +            throw new NotActiveException("not in call to writeObject");
  25.437 +        }
  25.438 +        Object curObj = curContext.getObj();
  25.439 +        ObjectStreamClass curDesc = curContext.getDesc();
  25.440 +        bout.setBlockDataMode(false);
  25.441 +        defaultWriteFields(curObj, curDesc);
  25.442 +        bout.setBlockDataMode(true);
  25.443 +    }
  25.444 +
  25.445 +    /**
  25.446 +     * Retrieve the object used to buffer persistent fields to be written to
  25.447 +     * the stream.  The fields will be written to the stream when writeFields
  25.448 +     * method is called.
  25.449 +     *
  25.450 +     * @return  an instance of the class Putfield that holds the serializable
  25.451 +     *          fields
  25.452 +     * @throws  IOException if I/O errors occur
  25.453 +     * @since 1.2
  25.454 +     */
  25.455 +    public ObjectOutputStream.PutField putFields() throws IOException {
  25.456 +        if (curPut == null) {
  25.457 +            if (curContext == null) {
  25.458 +                throw new NotActiveException("not in call to writeObject");
  25.459 +            }
  25.460 +            Object curObj = curContext.getObj();
  25.461 +            ObjectStreamClass curDesc = curContext.getDesc();
  25.462 +            curPut = new PutFieldImpl(curDesc);
  25.463 +        }
  25.464 +        return curPut;
  25.465 +    }
  25.466 +
  25.467 +    /**
  25.468 +     * Write the buffered fields to the stream.
  25.469 +     *
  25.470 +     * @throws  IOException if I/O errors occur while writing to the underlying
  25.471 +     *          stream
  25.472 +     * @throws  NotActiveException Called when a classes writeObject method was
  25.473 +     *          not called to write the state of the object.
  25.474 +     * @since 1.2
  25.475 +     */
  25.476 +    public void writeFields() throws IOException {
  25.477 +        if (curPut == null) {
  25.478 +            throw new NotActiveException("no current PutField object");
  25.479 +        }
  25.480 +        bout.setBlockDataMode(false);
  25.481 +        curPut.writeFields();
  25.482 +        bout.setBlockDataMode(true);
  25.483 +    }
  25.484 +
  25.485 +    /**
  25.486 +     * Reset will disregard the state of any objects already written to the
  25.487 +     * stream.  The state is reset to be the same as a new ObjectOutputStream.
  25.488 +     * The current point in the stream is marked as reset so the corresponding
  25.489 +     * ObjectInputStream will be reset at the same point.  Objects previously
  25.490 +     * written to the stream will not be refered to as already being in the
  25.491 +     * stream.  They will be written to the stream again.
  25.492 +     *
  25.493 +     * @throws  IOException if reset() is invoked while serializing an object.
  25.494 +     */
  25.495 +    public void reset() throws IOException {
  25.496 +        if (depth != 0) {
  25.497 +            throw new IOException("stream active");
  25.498 +        }
  25.499 +        bout.setBlockDataMode(false);
  25.500 +        bout.writeByte(TC_RESET);
  25.501 +        clear();
  25.502 +        bout.setBlockDataMode(true);
  25.503 +    }
  25.504 +
  25.505 +    /**
  25.506 +     * Subclasses may implement this method to allow class data to be stored in
  25.507 +     * the stream. By default this method does nothing.  The corresponding
  25.508 +     * method in ObjectInputStream is resolveClass.  This method is called
  25.509 +     * exactly once for each unique class in the stream.  The class name and
  25.510 +     * signature will have already been written to the stream.  This method may
  25.511 +     * make free use of the ObjectOutputStream to save any representation of
  25.512 +     * the class it deems suitable (for example, the bytes of the class file).
  25.513 +     * The resolveClass method in the corresponding subclass of
  25.514 +     * ObjectInputStream must read and use any data or objects written by
  25.515 +     * annotateClass.
  25.516 +     *
  25.517 +     * @param   cl the class to annotate custom data for
  25.518 +     * @throws  IOException Any exception thrown by the underlying
  25.519 +     *          OutputStream.
  25.520 +     */
  25.521 +    protected void annotateClass(Class<?> cl) throws IOException {
  25.522 +    }
  25.523 +
  25.524 +    /**
  25.525 +     * Subclasses may implement this method to store custom data in the stream
  25.526 +     * along with descriptors for dynamic proxy classes.
  25.527 +     *
  25.528 +     * <p>This method is called exactly once for each unique proxy class
  25.529 +     * descriptor in the stream.  The default implementation of this method in
  25.530 +     * <code>ObjectOutputStream</code> does nothing.
  25.531 +     *
  25.532 +     * <p>The corresponding method in <code>ObjectInputStream</code> is
  25.533 +     * <code>resolveProxyClass</code>.  For a given subclass of
  25.534 +     * <code>ObjectOutputStream</code> that overrides this method, the
  25.535 +     * <code>resolveProxyClass</code> method in the corresponding subclass of
  25.536 +     * <code>ObjectInputStream</code> must read any data or objects written by
  25.537 +     * <code>annotateProxyClass</code>.
  25.538 +     *
  25.539 +     * @param   cl the proxy class to annotate custom data for
  25.540 +     * @throws  IOException any exception thrown by the underlying
  25.541 +     *          <code>OutputStream</code>
  25.542 +     * @see ObjectInputStream#resolveProxyClass(String[])
  25.543 +     * @since   1.3
  25.544 +     */
  25.545 +    protected void annotateProxyClass(Class<?> cl) throws IOException {
  25.546 +    }
  25.547 +
  25.548 +    /**
  25.549 +     * This method will allow trusted subclasses of ObjectOutputStream to
  25.550 +     * substitute one object for another during serialization. Replacing
  25.551 +     * objects is disabled until enableReplaceObject is called. The
  25.552 +     * enableReplaceObject method checks that the stream requesting to do
  25.553 +     * replacement can be trusted.  The first occurrence of each object written
  25.554 +     * into the serialization stream is passed to replaceObject.  Subsequent
  25.555 +     * references to the object are replaced by the object returned by the
  25.556 +     * original call to replaceObject.  To ensure that the private state of
  25.557 +     * objects is not unintentionally exposed, only trusted streams may use
  25.558 +     * replaceObject.
  25.559 +     *
  25.560 +     * <p>The ObjectOutputStream.writeObject method takes a parameter of type
  25.561 +     * Object (as opposed to type Serializable) to allow for cases where
  25.562 +     * non-serializable objects are replaced by serializable ones.
  25.563 +     *
  25.564 +     * <p>When a subclass is replacing objects it must insure that either a
  25.565 +     * complementary substitution must be made during deserialization or that
  25.566 +     * the substituted object is compatible with every field where the
  25.567 +     * reference will be stored.  Objects whose type is not a subclass of the
  25.568 +     * type of the field or array element abort the serialization by raising an
  25.569 +     * exception and the object is not be stored.
  25.570 +     *
  25.571 +     * <p>This method is called only once when each object is first
  25.572 +     * encountered.  All subsequent references to the object will be redirected
  25.573 +     * to the new object. This method should return the object to be
  25.574 +     * substituted or the original object.
  25.575 +     *
  25.576 +     * <p>Null can be returned as the object to be substituted, but may cause
  25.577 +     * NullReferenceException in classes that contain references to the
  25.578 +     * original object since they may be expecting an object instead of
  25.579 +     * null.
  25.580 +     *
  25.581 +     * @param   obj the object to be replaced
  25.582 +     * @return  the alternate object that replaced the specified one
  25.583 +     * @throws  IOException Any exception thrown by the underlying
  25.584 +     *          OutputStream.
  25.585 +     */
  25.586 +    protected Object replaceObject(Object obj) throws IOException {
  25.587 +        return obj;
  25.588 +    }
  25.589 +
  25.590 +    /**
  25.591 +     * Enable the stream to do replacement of objects in the stream.  When
  25.592 +     * enabled, the replaceObject method is called for every object being
  25.593 +     * serialized.
  25.594 +     *
  25.595 +     * <p>If <code>enable</code> is true, and there is a security manager
  25.596 +     * installed, this method first calls the security manager's
  25.597 +     * <code>checkPermission</code> method with a
  25.598 +     * <code>SerializablePermission("enableSubstitution")</code> permission to
  25.599 +     * ensure it's ok to enable the stream to do replacement of objects in the
  25.600 +     * stream.
  25.601 +     *
  25.602 +     * @param   enable boolean parameter to enable replacement of objects
  25.603 +     * @return  the previous setting before this method was invoked
  25.604 +     * @throws  SecurityException if a security manager exists and its
  25.605 +     *          <code>checkPermission</code> method denies enabling the stream
  25.606 +     *          to do replacement of objects in the stream.
  25.607 +     * @see SecurityManager#checkPermission
  25.608 +     * @see java.io.SerializablePermission
  25.609 +     */
  25.610 +    protected boolean enableReplaceObject(boolean enable)
  25.611 +        throws SecurityException
  25.612 +    {
  25.613 +        if (enable == enableReplace) {
  25.614 +            return enable;
  25.615 +        }
  25.616 +        if (enable) {
  25.617 +            SecurityManager sm = System.getSecurityManager();
  25.618 +            if (sm != null) {
  25.619 +                sm.checkPermission(SUBSTITUTION_PERMISSION);
  25.620 +            }
  25.621 +        }
  25.622 +        enableReplace = enable;
  25.623 +        return !enableReplace;
  25.624 +    }
  25.625 +
  25.626 +    /**
  25.627 +     * The writeStreamHeader method is provided so subclasses can append or
  25.628 +     * prepend their own header to the stream.  It writes the magic number and
  25.629 +     * version to the stream.
  25.630 +     *
  25.631 +     * @throws  IOException if I/O errors occur while writing to the underlying
  25.632 +     *          stream
  25.633 +     */
  25.634 +    protected void writeStreamHeader() throws IOException {
  25.635 +        bout.writeShort(STREAM_MAGIC);
  25.636 +        bout.writeShort(STREAM_VERSION);
  25.637 +    }
  25.638 +
  25.639 +    /**
  25.640 +     * Write the specified class descriptor to the ObjectOutputStream.  Class
  25.641 +     * descriptors are used to identify the classes of objects written to the
  25.642 +     * stream.  Subclasses of ObjectOutputStream may override this method to
  25.643 +     * customize the way in which class descriptors are written to the
  25.644 +     * serialization stream.  The corresponding method in ObjectInputStream,
  25.645 +     * <code>readClassDescriptor</code>, should then be overridden to
  25.646 +     * reconstitute the class descriptor from its custom stream representation.
  25.647 +     * By default, this method writes class descriptors according to the format
  25.648 +     * defined in the Object Serialization specification.
  25.649 +     *
  25.650 +     * <p>Note that this method will only be called if the ObjectOutputStream
  25.651 +     * is not using the old serialization stream format (set by calling
  25.652 +     * ObjectOutputStream's <code>useProtocolVersion</code> method).  If this
  25.653 +     * serialization stream is using the old format
  25.654 +     * (<code>PROTOCOL_VERSION_1</code>), the class descriptor will be written
  25.655 +     * internally in a manner that cannot be overridden or customized.
  25.656 +     *
  25.657 +     * @param   desc class descriptor to write to the stream
  25.658 +     * @throws  IOException If an I/O error has occurred.
  25.659 +     * @see java.io.ObjectInputStream#readClassDescriptor()
  25.660 +     * @see #useProtocolVersion(int)
  25.661 +     * @see java.io.ObjectStreamConstants#PROTOCOL_VERSION_1
  25.662 +     * @since 1.3
  25.663 +     */
  25.664 +    protected void writeClassDescriptor(ObjectStreamClass desc)
  25.665 +        throws IOException
  25.666 +    {
  25.667 +        desc.writeNonProxy(this);
  25.668 +    }
  25.669 +
  25.670 +    /**
  25.671 +     * Writes a byte. This method will block until the byte is actually
  25.672 +     * written.
  25.673 +     *
  25.674 +     * @param   val the byte to be written to the stream
  25.675 +     * @throws  IOException If an I/O error has occurred.
  25.676 +     */
  25.677 +    public void write(int val) throws IOException {
  25.678 +        bout.write(val);
  25.679 +    }
  25.680 +
  25.681 +    /**
  25.682 +     * Writes an array of bytes. This method will block until the bytes are
  25.683 +     * actually written.
  25.684 +     *
  25.685 +     * @param   buf the data to be written
  25.686 +     * @throws  IOException If an I/O error has occurred.
  25.687 +     */
  25.688 +    public void write(byte[] buf) throws IOException {
  25.689 +        bout.write(buf, 0, buf.length, false);
  25.690 +    }
  25.691 +
  25.692 +    /**
  25.693 +     * Writes a sub array of bytes.
  25.694 +     *
  25.695 +     * @param   buf the data to be written
  25.696 +     * @param   off the start offset in the data
  25.697 +     * @param   len the number of bytes that are written
  25.698 +     * @throws  IOException If an I/O error has occurred.
  25.699 +     */
  25.700 +    public void write(byte[] buf, int off, int len) throws IOException {
  25.701 +        if (buf == null) {
  25.702 +            throw new NullPointerException();
  25.703 +        }
  25.704 +        int endoff = off + len;
  25.705 +        if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
  25.706 +            throw new IndexOutOfBoundsException();
  25.707 +        }
  25.708 +        bout.write(buf, off, len, false);
  25.709 +    }
  25.710 +
  25.711 +    /**
  25.712 +     * Flushes the stream. This will write any buffered output bytes and flush
  25.713 +     * through to the underlying stream.
  25.714 +     *
  25.715 +     * @throws  IOException If an I/O error has occurred.
  25.716 +     */
  25.717 +    public void flush() throws IOException {
  25.718 +        bout.flush();
  25.719 +    }
  25.720 +
  25.721 +    /**
  25.722 +     * Drain any buffered data in ObjectOutputStream.  Similar to flush but
  25.723 +     * does not propagate the flush to the underlying stream.
  25.724 +     *
  25.725 +     * @throws  IOException if I/O errors occur while writing to the underlying
  25.726 +     *          stream
  25.727 +     */
  25.728 +    protected void drain() throws IOException {
  25.729 +        bout.drain();
  25.730 +    }
  25.731 +
  25.732 +    /**
  25.733 +     * Closes the stream. This method must be called to release any resources
  25.734 +     * associated with the stream.
  25.735 +     *
  25.736 +     * @throws  IOException If an I/O error has occurred.
  25.737 +     */
  25.738 +    public void close() throws IOException {
  25.739 +        flush();
  25.740 +        clear();
  25.741 +        bout.close();
  25.742 +    }
  25.743 +
  25.744 +    /**
  25.745 +     * Writes a boolean.
  25.746 +     *
  25.747 +     * @param   val the boolean to be written
  25.748 +     * @throws  IOException if I/O errors occur while writing to the underlying
  25.749 +     *          stream
  25.750 +     */
  25.751 +    public void writeBoolean(boolean val) throws IOException {
  25.752 +        bout.writeBoolean(val);
  25.753 +    }
  25.754 +
  25.755 +    /**
  25.756 +     * Writes an 8 bit byte.
  25.757 +     *
  25.758 +     * @param   val the byte value to be written
  25.759 +     * @throws  IOException if I/O errors occur while writing to the underlying
  25.760 +     *          stream
  25.761 +     */
  25.762 +    public void writeByte(int val) throws IOException  {
  25.763 +        bout.writeByte(val);
  25.764 +    }
  25.765 +
  25.766 +    /**
  25.767 +     * Writes a 16 bit short.
  25.768 +     *
  25.769 +     * @param   val the short value to be written
  25.770 +     * @throws  IOException if I/O errors occur while writing to the underlying
  25.771 +     *          stream
  25.772 +     */
  25.773 +    public void writeShort(int val)  throws IOException {
  25.774 +        bout.writeShort(val);
  25.775 +    }
  25.776 +
  25.777 +    /**
  25.778 +     * Writes a 16 bit char.
  25.779 +     *
  25.780 +     * @param   val the char value to be written
  25.781 +     * @throws  IOException if I/O errors occur while writing to the underlying
  25.782 +     *          stream
  25.783 +     */
  25.784 +    public void writeChar(int val)  throws IOException {
  25.785 +        bout.writeChar(val);
  25.786 +    }
  25.787 +
  25.788 +    /**
  25.789 +     * Writes a 32 bit int.
  25.790 +     *
  25.791 +     * @param   val the integer value to be written
  25.792 +     * @throws  IOException if I/O errors occur while writing to the underlying
  25.793 +     *          stream
  25.794 +     */
  25.795 +    public void writeInt(int val)  throws IOException {
  25.796 +        bout.writeInt(val);
  25.797 +    }
  25.798 +
  25.799 +    /**
  25.800 +     * Writes a 64 bit long.
  25.801 +     *
  25.802 +     * @param   val the long value to be written
  25.803 +     * @throws  IOException if I/O errors occur while writing to the underlying
  25.804 +     *          stream
  25.805 +     */
  25.806 +    public void writeLong(long val)  throws IOException {
  25.807 +        bout.writeLong(val);
  25.808 +    }
  25.809 +
  25.810 +    /**
  25.811 +     * Writes a 32 bit float.
  25.812 +     *
  25.813 +     * @param   val the float value to be written
  25.814 +     * @throws  IOException if I/O errors occur while writing to the underlying
  25.815 +     *          stream
  25.816 +     */
  25.817 +    public void writeFloat(float val) throws IOException {
  25.818 +        bout.writeFloat(val);
  25.819 +    }
  25.820 +
  25.821 +    /**
  25.822 +     * Writes a 64 bit double.
  25.823 +     *
  25.824 +     * @param   val the double value to be written
  25.825 +     * @throws  IOException if I/O errors occur while writing to the underlying
  25.826 +     *          stream
  25.827 +     */
  25.828 +    public void writeDouble(double val) throws IOException {
  25.829 +        bout.writeDouble(val);
  25.830 +    }
  25.831 +
  25.832 +    /**
  25.833 +     * Writes a String as a sequence of bytes.
  25.834 +     *
  25.835 +     * @param   str the String of bytes to be written
  25.836 +     * @throws  IOException if I/O errors occur while writing to the underlying
  25.837 +     *          stream
  25.838 +     */
  25.839 +    public void writeBytes(String str) throws IOException {
  25.840 +        bout.writeBytes(str);
  25.841 +    }
  25.842 +
  25.843 +    /**
  25.844 +     * Writes a String as a sequence of chars.
  25.845 +     *
  25.846 +     * @param   str the String of chars to be written
  25.847 +     * @throws  IOException if I/O errors occur while writing to the underlying
  25.848 +     *          stream
  25.849 +     */
  25.850 +    public void writeChars(String str) throws IOException {
  25.851 +        bout.writeChars(str);
  25.852 +    }
  25.853 +
  25.854 +    /**
  25.855 +     * Primitive data write of this String in
  25.856 +     * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
  25.857 +     * format.  Note that there is a
  25.858 +     * significant difference between writing a String into the stream as
  25.859 +     * primitive data or as an Object. A String instance written by writeObject
  25.860 +     * is written into the stream as a String initially. Future writeObject()
  25.861 +     * calls write references to the string into the stream.
  25.862 +     *
  25.863 +     * @param   str the String to be written
  25.864 +     * @throws  IOException if I/O errors occur while writing to the underlying
  25.865 +     *          stream
  25.866 +     */
  25.867 +    public void writeUTF(String str) throws IOException {
  25.868 +        bout.writeUTF(str);
  25.869 +    }
  25.870 +
  25.871 +    /**
  25.872 +     * Provide programmatic access to the persistent fields to be written
  25.873 +     * to ObjectOutput.
  25.874 +     *
  25.875 +     * @since 1.2
  25.876 +     */
  25.877 +    public static abstract class PutField {
  25.878 +
  25.879 +        /**
  25.880 +         * Put the value of the named boolean field into the persistent field.
  25.881 +         *
  25.882 +         * @param  name the name of the serializable field
  25.883 +         * @param  val the value to assign to the field
  25.884 +         * @throws IllegalArgumentException if <code>name</code> does not
  25.885 +         * match the name of a serializable field for the class whose fields
  25.886 +         * are being written, or if the type of the named field is not
  25.887 +         * <code>boolean</code>
  25.888 +         */
  25.889 +        public abstract void put(String name, boolean val);
  25.890 +
  25.891 +        /**
  25.892 +         * Put the value of the named byte field into the persistent field.
  25.893 +         *
  25.894 +         * @param  name the name of the serializable field
  25.895 +         * @param  val the value to assign to the field
  25.896 +         * @throws IllegalArgumentException if <code>name</code> does not
  25.897 +         * match the name of a serializable field for the class whose fields
  25.898 +         * are being written, or if the type of the named field is not
  25.899 +         * <code>byte</code>
  25.900 +         */
  25.901 +        public abstract void put(String name, byte val);
  25.902 +
  25.903 +        /**
  25.904 +         * Put the value of the named char field into the persistent field.
  25.905 +         *
  25.906 +         * @param  name the name of the serializable field
  25.907 +         * @param  val the value to assign to the field
  25.908 +         * @throws IllegalArgumentException if <code>name</code> does not
  25.909 +         * match the name of a serializable field for the class whose fields
  25.910 +         * are being written, or if the type of the named field is not
  25.911 +         * <code>char</code>
  25.912 +         */
  25.913 +        public abstract void put(String name, char val);
  25.914 +
  25.915 +        /**
  25.916 +         * Put the value of the named short field into the persistent field.
  25.917 +         *
  25.918 +         * @param  name the name of the serializable field
  25.919 +         * @param  val the value to assign to the field
  25.920 +         * @throws IllegalArgumentException if <code>name</code> does not
  25.921 +         * match the name of a serializable field for the class whose fields
  25.922 +         * are being written, or if the type of the named field is not
  25.923 +         * <code>short</code>
  25.924 +         */
  25.925 +        public abstract void put(String name, short val);
  25.926 +
  25.927 +        /**
  25.928 +         * Put the value of the named int field into the persistent field.
  25.929 +         *
  25.930 +         * @param  name the name of the serializable field
  25.931 +         * @param  val the value to assign to the field
  25.932 +         * @throws IllegalArgumentException if <code>name</code> does not
  25.933 +         * match the name of a serializable field for the class whose fields
  25.934 +         * are being written, or if the type of the named field is not
  25.935 +         * <code>int</code>
  25.936 +         */
  25.937 +        public abstract void put(String name, int val);
  25.938 +
  25.939 +        /**
  25.940 +         * Put the value of the named long field into the persistent field.
  25.941 +         *
  25.942 +         * @param  name the name of the serializable field
  25.943 +         * @param  val the value to assign to the field
  25.944 +         * @throws IllegalArgumentException if <code>name</code> does not
  25.945 +         * match the name of a serializable field for the class whose fields
  25.946 +         * are being written, or if the type of the named field is not
  25.947 +         * <code>long</code>
  25.948 +         */
  25.949 +        public abstract void put(String name, long val);
  25.950 +
  25.951 +        /**
  25.952 +         * Put the value of the named float field into the persistent field.
  25.953 +         *
  25.954 +         * @param  name the name of the serializable field
  25.955 +         * @param  val the value to assign to the field
  25.956 +         * @throws IllegalArgumentException if <code>name</code> does not
  25.957 +         * match the name of a serializable field for the class whose fields
  25.958 +         * are being written, or if the type of the named field is not
  25.959 +         * <code>float</code>
  25.960 +         */
  25.961 +        public abstract void put(String name, float val);
  25.962 +
  25.963 +        /**
  25.964 +         * Put the value of the named double field into the persistent field.
  25.965 +         *
  25.966 +         * @param  name the name of the serializable field
  25.967 +         * @param  val the value to assign to the field
  25.968 +         * @throws IllegalArgumentException if <code>name</code> does not
  25.969 +         * match the name of a serializable field for the class whose fields
  25.970 +         * are being written, or if the type of the named field is not
  25.971 +         * <code>double</code>
  25.972 +         */
  25.973 +        public abstract void put(String name, double val);
  25.974 +
  25.975 +        /**
  25.976 +         * Put the value of the named Object field into the persistent field.
  25.977 +         *
  25.978 +         * @param  name the name of the serializable field
  25.979 +         * @param  val the value to assign to the field
  25.980 +         *         (which may be <code>null</code>)
  25.981 +         * @throws IllegalArgumentException if <code>name</code> does not
  25.982 +         * match the name of a serializable field for the class whose fields
  25.983 +         * are being written, or if the type of the named field is not a
  25.984 +         * reference type
  25.985 +         */
  25.986 +        public abstract void put(String name, Object val);
  25.987 +
  25.988 +        /**
  25.989 +         * Write the data and fields to the specified ObjectOutput stream,
  25.990 +         * which must be the same stream that produced this
  25.991 +         * <code>PutField</code> object.
  25.992 +         *
  25.993 +         * @param  out the stream to write the data and fields to
  25.994 +         * @throws IOException if I/O errors occur while writing to the
  25.995 +         *         underlying stream
  25.996 +         * @throws IllegalArgumentException if the specified stream is not
  25.997 +         *         the same stream that produced this <code>PutField</code>
  25.998 +         *         object
  25.999 +         * @deprecated This method does not write the values contained by this
 25.1000 +         *         <code>PutField</code> object in a proper format, and may
 25.1001 +         *         result in corruption of the serialization stream.  The
 25.1002 +         *         correct way to write <code>PutField</code> data is by
 25.1003 +         *         calling the {@link java.io.ObjectOutputStream#writeFields()}
 25.1004 +         *         method.
 25.1005 +         */
 25.1006 +        @Deprecated
 25.1007 +        public abstract void write(ObjectOutput out) throws IOException;
 25.1008 +    }
 25.1009 +
 25.1010 +
 25.1011 +    /**
 25.1012 +     * Returns protocol version in use.
 25.1013 +     */
 25.1014 +    int getProtocolVersion() {
 25.1015 +        return protocol;
 25.1016 +    }
 25.1017 +
 25.1018 +    /**
 25.1019 +     * Writes string without allowing it to be replaced in stream.  Used by
 25.1020 +     * ObjectStreamClass to write class descriptor type strings.
 25.1021 +     */
 25.1022 +    void writeTypeString(String str) throws IOException {
 25.1023 +        int handle;
 25.1024 +        if (str == null) {
 25.1025 +            writeNull();
 25.1026 +        } else if ((handle = handles.lookup(str)) != -1) {
 25.1027 +            writeHandle(handle);
 25.1028 +        } else {
 25.1029 +            writeString(str, false);
 25.1030 +        }
 25.1031 +    }
 25.1032 +
 25.1033 +    /**
 25.1034 +     * Verifies that this (possibly subclass) instance can be constructed
 25.1035 +     * without violating security constraints: the subclass must not override
 25.1036 +     * security-sensitive non-final methods, or else the
 25.1037 +     * "enableSubclassImplementation" SerializablePermission is checked.
 25.1038 +     */
 25.1039 +    private void verifySubclass() {
 25.1040 +        Class cl = getClass();
 25.1041 +        if (cl == ObjectOutputStream.class) {
 25.1042 +            return;
 25.1043 +        }
 25.1044 +        SecurityManager sm = System.getSecurityManager();
 25.1045 +        if (sm == null) {
 25.1046 +            return;
 25.1047 +        }
 25.1048 +        processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
 25.1049 +        WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
 25.1050 +        Boolean result = Caches.subclassAudits.get(key);
 25.1051 +        if (result == null) {
 25.1052 +            result = Boolean.valueOf(auditSubclass(cl));
 25.1053 +            Caches.subclassAudits.putIfAbsent(key, result);
 25.1054 +        }
 25.1055 +        if (result.booleanValue()) {
 25.1056 +            return;
 25.1057 +        }
 25.1058 +        sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
 25.1059 +    }
 25.1060 +
 25.1061 +    /**
 25.1062 +     * Performs reflective checks on given subclass to verify that it doesn't
 25.1063 +     * override security-sensitive non-final methods.  Returns true if subclass
 25.1064 +     * is "safe", false otherwise.
 25.1065 +     */
 25.1066 +    private static boolean auditSubclass(final Class subcl) {
 25.1067 +        Boolean result = AccessController.doPrivileged(
 25.1068 +            new PrivilegedAction<Boolean>() {
 25.1069 +                public Boolean run() {
 25.1070 +                    for (Class cl = subcl;
 25.1071 +                         cl != ObjectOutputStream.class;
 25.1072 +                         cl = cl.getSuperclass())
 25.1073 +                    {
 25.1074 +                        try {
 25.1075 +                            cl.getDeclaredMethod(
 25.1076 +                                "writeUnshared", new Class[] { Object.class });
 25.1077 +                            return Boolean.FALSE;
 25.1078 +                        } catch (NoSuchMethodException ex) {
 25.1079 +                        }
 25.1080 +                        try {
 25.1081 +                            cl.getDeclaredMethod("putFields", (Class[]) null);
 25.1082 +                            return Boolean.FALSE;
 25.1083 +                        } catch (NoSuchMethodException ex) {
 25.1084 +                        }
 25.1085 +                    }
 25.1086 +                    return Boolean.TRUE;
 25.1087 +                }
 25.1088 +            }
 25.1089 +        );
 25.1090 +        return result.booleanValue();
 25.1091 +    }
 25.1092 +
 25.1093 +    /**
 25.1094 +     * Clears internal data structures.
 25.1095 +     */
 25.1096 +    private void clear() {
 25.1097 +        subs.clear();
 25.1098 +        handles.clear();
 25.1099 +    }
 25.1100 +
 25.1101 +    /**
 25.1102 +     * Underlying writeObject/writeUnshared implementation.
 25.1103 +     */
 25.1104 +    private void writeObject0(Object obj, boolean unshared)
 25.1105 +        throws IOException
 25.1106 +    {
 25.1107 +        boolean oldMode = bout.setBlockDataMode(false);
 25.1108 +        depth++;
 25.1109 +        try {
 25.1110 +            // handle previously written and non-replaceable objects
 25.1111 +            int h;
 25.1112 +            if ((obj = subs.lookup(obj)) == null) {
 25.1113 +                writeNull();
 25.1114 +                return;
 25.1115 +            } else if (!unshared && (h = handles.lookup(obj)) != -1) {
 25.1116 +                writeHandle(h);
 25.1117 +                return;
 25.1118 +            } else if (obj instanceof Class) {
 25.1119 +                writeClass((Class) obj, unshared);
 25.1120 +                return;
 25.1121 +            } else if (obj instanceof ObjectStreamClass) {
 25.1122 +                writeClassDesc((ObjectStreamClass) obj, unshared);
 25.1123 +                return;
 25.1124 +            }
 25.1125 +
 25.1126 +            // check for replacement object
 25.1127 +            Object orig = obj;
 25.1128 +            Class cl = obj.getClass();
 25.1129 +            ObjectStreamClass desc;
 25.1130 +            for (;;) {
 25.1131 +                // REMIND: skip this check for strings/arrays?
 25.1132 +                Class repCl;
 25.1133 +                desc = ObjectStreamClass.lookup(cl, true);
 25.1134 +                if (!desc.hasWriteReplaceMethod() ||
 25.1135 +                    (obj = desc.invokeWriteReplace(obj)) == null ||
 25.1136 +                    (repCl = obj.getClass()) == cl)
 25.1137 +                {
 25.1138 +                    break;
 25.1139 +                }
 25.1140 +                cl = repCl;
 25.1141 +            }
 25.1142 +            if (enableReplace) {
 25.1143 +                Object rep = replaceObject(obj);
 25.1144 +                if (rep != obj && rep != null) {
 25.1145 +                    cl = rep.getClass();
 25.1146 +                    desc = ObjectStreamClass.lookup(cl, true);
 25.1147 +                }
 25.1148 +                obj = rep;
 25.1149 +            }
 25.1150 +
 25.1151 +            // if object replaced, run through original checks a second time
 25.1152 +            if (obj != orig) {
 25.1153 +                subs.assign(orig, obj);
 25.1154 +                if (obj == null) {
 25.1155 +                    writeNull();
 25.1156 +                    return;
 25.1157 +                } else if (!unshared && (h = handles.lookup(obj)) != -1) {
 25.1158 +                    writeHandle(h);
 25.1159 +                    return;
 25.1160 +                } else if (obj instanceof Class) {
 25.1161 +                    writeClass((Class) obj, unshared);
 25.1162 +                    return;
 25.1163 +                } else if (obj instanceof ObjectStreamClass) {
 25.1164 +                    writeClassDesc((ObjectStreamClass) obj, unshared);
 25.1165 +                    return;
 25.1166 +                }
 25.1167 +            }
 25.1168 +
 25.1169 +            // remaining cases
 25.1170 +            if (obj instanceof String) {
 25.1171 +                writeString((String) obj, unshared);
 25.1172 +            } else if (cl.isArray()) {
 25.1173 +                writeArray(obj, desc, unshared);
 25.1174 +            } else if (obj instanceof Enum) {
 25.1175 +                writeEnum((Enum) obj, desc, unshared);
 25.1176 +            } else if (obj instanceof Serializable) {
 25.1177 +                writeOrdinaryObject(obj, desc, unshared);
 25.1178 +            } else {
 25.1179 +                if (extendedDebugInfo) {
 25.1180 +                    throw new NotSerializableException(
 25.1181 +                        cl.getName() + "\n" + debugInfoStack.toString());
 25.1182 +                } else {
 25.1183 +                    throw new NotSerializableException(cl.getName());
 25.1184 +                }
 25.1185 +            }
 25.1186 +        } finally {
 25.1187 +            depth--;
 25.1188 +            bout.setBlockDataMode(oldMode);
 25.1189 +        }
 25.1190 +    }
 25.1191 +
 25.1192 +    /**
 25.1193 +     * Writes null code to stream.
 25.1194 +     */
 25.1195 +    private void writeNull() throws IOException {
 25.1196 +        bout.writeByte(TC_NULL);
 25.1197 +    }
 25.1198 +
 25.1199 +    /**
 25.1200 +     * Writes given object handle to stream.
 25.1201 +     */
 25.1202 +    private void writeHandle(int handle) throws IOException {
 25.1203 +        bout.writeByte(TC_REFERENCE);
 25.1204 +        bout.writeInt(baseWireHandle + handle);
 25.1205 +    }
 25.1206 +
 25.1207 +    /**
 25.1208 +     * Writes representation of given class to stream.
 25.1209 +     */
 25.1210 +    private void writeClass(Class cl, boolean unshared) throws IOException {
 25.1211 +        bout.writeByte(TC_CLASS);
 25.1212 +        writeClassDesc(ObjectStreamClass.lookup(cl, true), false);
 25.1213 +        handles.assign(unshared ? null : cl);
 25.1214 +    }
 25.1215 +
 25.1216 +    /**
 25.1217 +     * Writes representation of given class descriptor to stream.
 25.1218 +     */
 25.1219 +    private void writeClassDesc(ObjectStreamClass desc, boolean unshared)
 25.1220 +        throws IOException
 25.1221 +    {
 25.1222 +        int handle;
 25.1223 +        if (desc == null) {
 25.1224 +            writeNull();
 25.1225 +        } else if (!unshared && (handle = handles.lookup(desc)) != -1) {
 25.1226 +            writeHandle(handle);
 25.1227 +        } else if (desc.isProxy()) {
 25.1228 +            writeProxyDesc(desc, unshared);
 25.1229 +        } else {
 25.1230 +            writeNonProxyDesc(desc, unshared);
 25.1231 +        }
 25.1232 +    }
 25.1233 +
 25.1234 +    /**
 25.1235 +     * Writes class descriptor representing a dynamic proxy class to stream.
 25.1236 +     */
 25.1237 +    private void writeProxyDesc(ObjectStreamClass desc, boolean unshared)
 25.1238 +        throws IOException
 25.1239 +    {
 25.1240 +        bout.writeByte(TC_PROXYCLASSDESC);
 25.1241 +        handles.assign(unshared ? null : desc);
 25.1242 +
 25.1243 +        Class cl = desc.forClass();
 25.1244 +        Class[] ifaces = cl.getInterfaces();
 25.1245 +        bout.writeInt(ifaces.length);
 25.1246 +        for (int i = 0; i < ifaces.length; i++) {
 25.1247 +            bout.writeUTF(ifaces[i].getName());
 25.1248 +        }
 25.1249 +
 25.1250 +        bout.setBlockDataMode(true);
 25.1251 +        annotateProxyClass(cl);
 25.1252 +        bout.setBlockDataMode(false);
 25.1253 +        bout.writeByte(TC_ENDBLOCKDATA);
 25.1254 +
 25.1255 +        writeClassDesc(desc.getSuperDesc(), false);
 25.1256 +    }
 25.1257 +
 25.1258 +    /**
 25.1259 +     * Writes class descriptor representing a standard (i.e., not a dynamic
 25.1260 +     * proxy) class to stream.
 25.1261 +     */
 25.1262 +    private void writeNonProxyDesc(ObjectStreamClass desc, boolean unshared)
 25.1263 +        throws IOException
 25.1264 +    {
 25.1265 +        bout.writeByte(TC_CLASSDESC);
 25.1266 +        handles.assign(unshared ? null : desc);
 25.1267 +
 25.1268 +        if (protocol == PROTOCOL_VERSION_1) {
 25.1269 +            // do not invoke class descriptor write hook with old protocol
 25.1270 +            desc.writeNonProxy(this);
 25.1271 +        } else {
 25.1272 +            writeClassDescriptor(desc);
 25.1273 +        }
 25.1274 +
 25.1275 +        Class cl = desc.forClass();
 25.1276 +        bout.setBlockDataMode(true);
 25.1277 +        annotateClass(cl);
 25.1278 +        bout.setBlockDataMode(false);
 25.1279 +        bout.writeByte(TC_ENDBLOCKDATA);
 25.1280 +
 25.1281 +        writeClassDesc(desc.getSuperDesc(), false);
 25.1282 +    }
 25.1283 +
 25.1284 +    /**
 25.1285 +     * Writes given string to stream, using standard or long UTF format
 25.1286 +     * depending on string length.
 25.1287 +     */
 25.1288 +    private void writeString(String str, boolean unshared) throws IOException {
 25.1289 +        handles.assign(unshared ? null : str);
 25.1290 +        long utflen = bout.getUTFLength(str);
 25.1291 +        if (utflen <= 0xFFFF) {
 25.1292 +            bout.writeByte(TC_STRING);
 25.1293 +            bout.writeUTF(str, utflen);
 25.1294 +        } else {
 25.1295 +            bout.writeByte(TC_LONGSTRING);
 25.1296 +            bout.writeLongUTF(str, utflen);
 25.1297 +        }
 25.1298 +    }
 25.1299 +
 25.1300 +    /**
 25.1301 +     * Writes given array object to stream.
 25.1302 +     */
 25.1303 +    private void writeArray(Object array,
 25.1304 +                            ObjectStreamClass desc,
 25.1305 +                            boolean unshared)
 25.1306 +        throws IOException
 25.1307 +    {
 25.1308 +        bout.writeByte(TC_ARRAY);
 25.1309 +        writeClassDesc(desc, false);
 25.1310 +        handles.assign(unshared ? null : array);
 25.1311 +
 25.1312 +        Class ccl = desc.forClass().getComponentType();
 25.1313 +        if (ccl.isPrimitive()) {
 25.1314 +            if (ccl == Integer.TYPE) {
 25.1315 +                int[] ia = (int[]) array;
 25.1316 +                bout.writeInt(ia.length);
 25.1317 +                bout.writeInts(ia, 0, ia.length);
 25.1318 +            } else if (ccl == Byte.TYPE) {
 25.1319 +                byte[] ba = (byte[]) array;
 25.1320 +                bout.writeInt(ba.length);
 25.1321 +                bout.write(ba, 0, ba.length, true);
 25.1322 +            } else if (ccl == Long.TYPE) {
 25.1323 +                long[] ja = (long[]) array;
 25.1324 +                bout.writeInt(ja.length);
 25.1325 +                bout.writeLongs(ja, 0, ja.length);
 25.1326 +            } else if (ccl == Float.TYPE) {
 25.1327 +                float[] fa = (float[]) array;
 25.1328 +                bout.writeInt(fa.length);
 25.1329 +                bout.writeFloats(fa, 0, fa.length);
 25.1330 +            } else if (ccl == Double.TYPE) {
 25.1331 +                double[] da = (double[]) array;
 25.1332 +                bout.writeInt(da.length);
 25.1333 +                bout.writeDoubles(da, 0, da.length);
 25.1334 +            } else if (ccl == Short.TYPE) {
 25.1335 +                short[] sa = (short[]) array;
 25.1336 +                bout.writeInt(sa.length);
 25.1337 +                bout.writeShorts(sa, 0, sa.length);
 25.1338 +            } else if (ccl == Character.TYPE) {
 25.1339 +                char[] ca = (char[]) array;
 25.1340 +                bout.writeInt(ca.length);
 25.1341 +                bout.writeChars(ca, 0, ca.length);
 25.1342 +            } else if (ccl == Boolean.TYPE) {
 25.1343 +                boolean[] za = (boolean[]) array;
 25.1344 +                bout.writeInt(za.length);
 25.1345 +                bout.writeBooleans(za, 0, za.length);
 25.1346 +            } else {
 25.1347 +                throw new InternalError();
 25.1348 +            }
 25.1349 +        } else {
 25.1350 +            Object[] objs = (Object[]) array;
 25.1351 +            int len = objs.length;
 25.1352 +            bout.writeInt(len);
 25.1353 +            if (extendedDebugInfo) {
 25.1354 +                debugInfoStack.push(
 25.1355 +                    "array (class \"" + array.getClass().getName() +
 25.1356 +                    "\", size: " + len  + ")");
 25.1357 +            }
 25.1358 +            try {
 25.1359 +                for (int i = 0; i < len; i++) {
 25.1360 +                    if (extendedDebugInfo) {
 25.1361 +                        debugInfoStack.push(
 25.1362 +                            "element of array (index: " + i + ")");
 25.1363 +                    }
 25.1364 +                    try {
 25.1365 +                        writeObject0(objs[i], false);
 25.1366 +                    } finally {
 25.1367 +                        if (extendedDebugInfo) {
 25.1368 +                            debugInfoStack.pop();
 25.1369 +                        }
 25.1370 +                    }
 25.1371 +                }
 25.1372 +            } finally {
 25.1373 +                if (extendedDebugInfo) {
 25.1374 +                    debugInfoStack.pop();
 25.1375 +                }
 25.1376 +            }
 25.1377 +        }
 25.1378 +    }
 25.1379 +
 25.1380 +    /**
 25.1381 +     * Writes given enum constant to stream.
 25.1382 +     */
 25.1383 +    private void writeEnum(Enum en,
 25.1384 +                           ObjectStreamClass desc,
 25.1385 +                           boolean unshared)
 25.1386 +        throws IOException
 25.1387 +    {
 25.1388 +        bout.writeByte(TC_ENUM);
 25.1389 +        ObjectStreamClass sdesc = desc.getSuperDesc();
 25.1390 +        writeClassDesc((sdesc.forClass() == Enum.class) ? desc : sdesc, false);
 25.1391 +        handles.assign(unshared ? null : en);
 25.1392 +        writeString(en.name(), false);
 25.1393 +    }
 25.1394 +
 25.1395 +    /**
 25.1396 +     * Writes representation of a "ordinary" (i.e., not a String, Class,
 25.1397 +     * ObjectStreamClass, array, or enum constant) serializable object to the
 25.1398 +     * stream.
 25.1399 +     */
 25.1400 +    private void writeOrdinaryObject(Object obj,
 25.1401 +                                     ObjectStreamClass desc,
 25.1402 +                                     boolean unshared)
 25.1403 +        throws IOException
 25.1404 +    {
 25.1405 +        if (extendedDebugInfo) {
 25.1406 +            debugInfoStack.push(
 25.1407 +                (depth == 1 ? "root " : "") + "object (class \"" +
 25.1408 +                obj.getClass().getName() + "\", " + obj.toString() + ")");
 25.1409 +        }
 25.1410 +        try {
 25.1411 +            desc.checkSerialize();
 25.1412 +
 25.1413 +            bout.writeByte(TC_OBJECT);
 25.1414 +            writeClassDesc(desc, false);
 25.1415 +            handles.assign(unshared ? null : obj);
 25.1416 +            if (desc.isExternalizable() && !desc.isProxy()) {
 25.1417 +                writeExternalData((Externalizable) obj);
 25.1418 +            } else {
 25.1419 +                writeSerialData(obj, desc);
 25.1420 +            }
 25.1421 +        } finally {
 25.1422 +            if (extendedDebugInfo) {
 25.1423 +                debugInfoStack.pop();
 25.1424 +            }
 25.1425 +        }
 25.1426 +    }
 25.1427 +
 25.1428 +    /**
 25.1429 +     * Writes externalizable data of given object by invoking its
 25.1430 +     * writeExternal() method.
 25.1431 +     */
 25.1432 +    private void writeExternalData(Externalizable obj) throws IOException {
 25.1433 +        PutFieldImpl oldPut = curPut;
 25.1434 +        curPut = null;
 25.1435 +
 25.1436 +        if (extendedDebugInfo) {
 25.1437 +            debugInfoStack.push("writeExternal data");
 25.1438 +        }
 25.1439 +        SerialCallbackContext oldContext = curContext;
 25.1440 +        try {
 25.1441 +            curContext = null;
 25.1442 +            if (protocol == PROTOCOL_VERSION_1) {
 25.1443 +                obj.writeExternal(this);
 25.1444 +            } else {
 25.1445 +                bout.setBlockDataMode(true);
 25.1446 +                obj.writeExternal(this);
 25.1447 +                bout.setBlockDataMode(false);
 25.1448 +                bout.writeByte(TC_ENDBLOCKDATA);
 25.1449 +            }
 25.1450 +        } finally {
 25.1451 +            curContext = oldContext;
 25.1452 +            if (extendedDebugInfo) {
 25.1453 +                debugInfoStack.pop();
 25.1454 +            }
 25.1455 +        }
 25.1456 +
 25.1457 +        curPut = oldPut;
 25.1458 +    }
 25.1459 +
 25.1460 +    /**
 25.1461 +     * Writes instance data for each serializable class of given object, from
 25.1462 +     * superclass to subclass.
 25.1463 +     */
 25.1464 +    private void writeSerialData(Object obj, ObjectStreamClass desc)
 25.1465 +        throws IOException
 25.1466 +    {
 25.1467 +        ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
 25.1468 +        for (int i = 0; i < slots.length; i++) {
 25.1469 +            ObjectStreamClass slotDesc = slots[i].desc;
 25.1470 +            if (slotDesc.hasWriteObjectMethod()) {
 25.1471 +                PutFieldImpl oldPut = curPut;
 25.1472 +                curPut = null;
 25.1473 +                SerialCallbackContext oldContext = curContext;
 25.1474 +
 25.1475 +                if (extendedDebugInfo) {
 25.1476 +                    debugInfoStack.push(
 25.1477 +                        "custom writeObject data (class \"" +
 25.1478 +                        slotDesc.getName() + "\")");
 25.1479 +                }
 25.1480 +                try {
 25.1481 +                    curContext = new SerialCallbackContext(obj, slotDesc);
 25.1482 +                    bout.setBlockDataMode(true);
 25.1483 +                    slotDesc.invokeWriteObject(obj, this);
 25.1484 +                    bout.setBlockDataMode(false);
 25.1485 +                    bout.writeByte(TC_ENDBLOCKDATA);
 25.1486 +                } finally {
 25.1487 +                    curContext.setUsed();
 25.1488 +                    curContext = oldContext;
 25.1489 +                    if (extendedDebugInfo) {
 25.1490 +                        debugInfoStack.pop();
 25.1491 +                    }
 25.1492 +                }
 25.1493 +
 25.1494 +                curPut = oldPut;
 25.1495 +            } else {
 25.1496 +                defaultWriteFields(obj, slotDesc);
 25.1497 +            }
 25.1498 +        }
 25.1499 +    }
 25.1500 +
 25.1501 +    /**
 25.1502 +     * Fetches and writes values of serializable fields of given object to
 25.1503 +     * stream.  The given class descriptor specifies which field values to
 25.1504 +     * write, and in which order they should be written.
 25.1505 +     */
 25.1506 +    private void defaultWriteFields(Object obj, ObjectStreamClass desc)
 25.1507 +        throws IOException
 25.1508 +    {
 25.1509 +        // REMIND: perform conservative isInstance check here?
 25.1510 +        desc.checkDefaultSerialize();
 25.1511 +
 25.1512 +        int primDataSize = desc.getPrimDataSize();
 25.1513 +        if (primVals == null || primVals.length < primDataSize) {
 25.1514 +            primVals = new byte[primDataSize];
 25.1515 +        }
 25.1516 +        desc.getPrimFieldValues(obj, primVals);
 25.1517 +        bout.write(primVals, 0, primDataSize, false);
 25.1518 +
 25.1519 +        ObjectStreamField[] fields = desc.getFields(false);
 25.1520 +        Object[] objVals = new Object[desc.getNumObjFields()];
 25.1521 +        int numPrimFields = fields.length - objVals.length;
 25.1522 +        desc.getObjFieldValues(obj, objVals);
 25.1523 +        for (int i = 0; i < objVals.length; i++) {
 25.1524 +            if (extendedDebugInfo) {
 25.1525 +                debugInfoStack.push(
 25.1526 +                    "field (class \"" + desc.getName() + "\", name: \"" +
 25.1527 +                    fields[numPrimFields + i].getName() + "\", type: \"" +
 25.1528 +                    fields[numPrimFields + i].getType() + "\")");
 25.1529 +            }
 25.1530 +            try {
 25.1531 +                writeObject0(objVals[i],
 25.1532 +                             fields[numPrimFields + i].isUnshared());
 25.1533 +            } finally {
 25.1534 +                if (extendedDebugInfo) {
 25.1535 +                    debugInfoStack.pop();
 25.1536 +                }
 25.1537 +            }
 25.1538 +        }
 25.1539 +    }
 25.1540 +
 25.1541 +    /**
 25.1542 +     * Attempts to write to stream fatal IOException that has caused
 25.1543 +     * serialization to abort.
 25.1544 +     */
 25.1545 +    private void writeFatalException(IOException ex) throws IOException {
 25.1546 +        /*
 25.1547 +         * Note: the serialization specification states that if a second
 25.1548 +         * IOException occurs while attempting to serialize the original fatal
 25.1549 +         * exception to the stream, then a StreamCorruptedException should be
 25.1550 +         * thrown (section 2.1).  However, due to a bug in previous
 25.1551 +         * implementations of serialization, StreamCorruptedExceptions were
 25.1552 +         * rarely (if ever) actually thrown--the "root" exceptions from
 25.1553 +         * underlying streams were thrown instead.  This historical behavior is
 25.1554 +         * followed here for consistency.
 25.1555 +         */
 25.1556 +        clear();
 25.1557 +        boolean oldMode = bout.setBlockDataMode(false);
 25.1558 +        try {
 25.1559 +            bout.writeByte(TC_EXCEPTION);
 25.1560 +            writeObject0(ex, false);
 25.1561 +            clear();
 25.1562 +        } finally {
 25.1563 +            bout.setBlockDataMode(oldMode);
 25.1564 +        }
 25.1565 +    }
 25.1566 +
 25.1567 +    /**
 25.1568 +     * Converts specified span of float values into byte values.
 25.1569 +     */
 25.1570 +    // REMIND: remove once hotspot inlines Float.floatToIntBits
 25.1571 +    private static native void floatsToBytes(float[] src, int srcpos,
 25.1572 +                                             byte[] dst, int dstpos,
 25.1573 +                                             int nfloats);
 25.1574 +
 25.1575 +    /**
 25.1576 +     * Converts specified span of double values into byte values.
 25.1577 +     */
 25.1578 +    // REMIND: remove once hotspot inlines Double.doubleToLongBits
 25.1579 +    private static native void doublesToBytes(double[] src, int srcpos,
 25.1580 +                                              byte[] dst, int dstpos,
 25.1581 +                                              int ndoubles);
 25.1582 +
 25.1583 +    /**
 25.1584 +     * Default PutField implementation.
 25.1585 +     */
 25.1586 +    private class PutFieldImpl extends PutField {
 25.1587 +
 25.1588 +        /** class descriptor describing serializable fields */
 25.1589 +        private final ObjectStreamClass desc;
 25.1590 +        /** primitive field values */
 25.1591 +        private final byte[] primVals;
 25.1592 +        /** object field values */
 25.1593 +        private final Object[] objVals;
 25.1594 +
 25.1595 +        /**
 25.1596 +         * Creates PutFieldImpl object for writing fields defined in given
 25.1597 +         * class descriptor.
 25.1598 +         */
 25.1599 +        PutFieldImpl(ObjectStreamClass desc) {
 25.1600 +            this.desc = desc;
 25.1601 +            primVals = new byte[desc.getPrimDataSize()];
 25.1602 +            objVals = new Object[desc.getNumObjFields()];
 25.1603 +        }
 25.1604 +
 25.1605 +        public void put(String name, boolean val) {
 25.1606 +            Bits.putBoolean(primVals, getFieldOffset(name, Boolean.TYPE), val);
 25.1607 +        }
 25.1608 +
 25.1609 +        public void put(String name, byte val) {
 25.1610 +            primVals[getFieldOffset(name, Byte.TYPE)] = val;
 25.1611 +        }
 25.1612 +
 25.1613 +        public void put(String name, char val) {
 25.1614 +            Bits.putChar(primVals, getFieldOffset(name, Character.TYPE), val);
 25.1615 +        }
 25.1616 +
 25.1617 +        public void put(String name, short val) {
 25.1618 +            Bits.putShort(primVals, getFieldOffset(name, Short.TYPE), val);
 25.1619 +        }
 25.1620 +
 25.1621 +        public void put(String name, int val) {
 25.1622 +            Bits.putInt(primVals, getFieldOffset(name, Integer.TYPE), val);
 25.1623 +        }
 25.1624 +
 25.1625 +        public void put(String name, float val) {
 25.1626 +            Bits.putFloat(primVals, getFieldOffset(name, Float.TYPE), val);
 25.1627 +        }
 25.1628 +
 25.1629 +        public void put(String name, long val) {
 25.1630 +            Bits.putLong(primVals, getFieldOffset(name, Long.TYPE), val);
 25.1631 +        }
 25.1632 +
 25.1633 +        public void put(String name, double val) {
 25.1634 +            Bits.putDouble(primVals, getFieldOffset(name, Double.TYPE), val);
 25.1635 +        }
 25.1636 +
 25.1637 +        public void put(String name, Object val) {
 25.1638 +            objVals[getFieldOffset(name, Object.class)] = val;
 25.1639 +        }
 25.1640 +
 25.1641 +        // deprecated in ObjectOutputStream.PutField
 25.1642 +        public void write(ObjectOutput out) throws IOException {
 25.1643 +            /*
 25.1644 +             * Applications should *not* use this method to write PutField
 25.1645 +             * data, as it will lead to stream corruption if the PutField
 25.1646 +             * object writes any primitive data (since block data mode is not
 25.1647 +             * unset/set properly, as is done in OOS.writeFields()).  This
 25.1648 +             * broken implementation is being retained solely for behavioral
 25.1649 +             * compatibility, in order to support applications which use
 25.1650 +             * OOS.PutField.write() for writing only non-primitive data.
 25.1651 +             *
 25.1652 +             * Serialization of unshared objects is not implemented here since
 25.1653 +             * it is not necessary for backwards compatibility; also, unshared
 25.1654 +             * semantics may not be supported by the given ObjectOutput
 25.1655 +             * instance.  Applications which write unshared objects using the
 25.1656 +             * PutField API must use OOS.writeFields().
 25.1657 +             */
 25.1658 +            if (ObjectOutputStream.this != out) {
 25.1659 +                throw new IllegalArgumentException("wrong stream");
 25.1660 +            }
 25.1661 +            out.write(primVals, 0, primVals.length);
 25.1662 +
 25.1663 +            ObjectStreamField[] fields = desc.getFields(false);
 25.1664 +            int numPrimFields = fields.length - objVals.length;
 25.1665 +            // REMIND: warn if numPrimFields > 0?
 25.1666 +            for (int i = 0; i < objVals.length; i++) {
 25.1667 +                if (fields[numPrimFields + i].isUnshared()) {
 25.1668 +                    throw new IOException("cannot write unshared object");
 25.1669 +                }
 25.1670 +                out.writeObject(objVals[i]);
 25.1671 +            }
 25.1672 +        }
 25.1673 +
 25.1674 +        /**
 25.1675 +         * Writes buffered primitive data and object fields to stream.
 25.1676 +         */
 25.1677 +        void writeFields() throws IOException {
 25.1678 +            bout.write(primVals, 0, primVals.length, false);
 25.1679 +
 25.1680 +            ObjectStreamField[] fields = desc.getFields(false);
 25.1681 +            int numPrimFields = fields.length - objVals.length;
 25.1682 +            for (int i = 0; i < objVals.length; i++) {
 25.1683 +                if (extendedDebugInfo) {
 25.1684 +                    debugInfoStack.push(
 25.1685 +                        "field (class \"" + desc.getName() + "\", name: \"" +
 25.1686 +                        fields[numPrimFields + i].getName() + "\", type: \"" +
 25.1687 +                        fields[numPrimFields + i].getType() + "\")");
 25.1688 +                }
 25.1689 +                try {
 25.1690 +                    writeObject0(objVals[i],
 25.1691 +                                 fields[numPrimFields + i].isUnshared());
 25.1692 +                } finally {
 25.1693 +                    if (extendedDebugInfo) {
 25.1694 +                        debugInfoStack.pop();
 25.1695 +                    }
 25.1696 +                }
 25.1697 +            }
 25.1698 +        }
 25.1699 +
 25.1700 +        /**
 25.1701 +         * Returns offset of field with given name and type.  A specified type
 25.1702 +         * of null matches all types, Object.class matches all non-primitive
 25.1703 +         * types, and any other non-null type matches assignable types only.
 25.1704 +         * Throws IllegalArgumentException if no matching field found.
 25.1705 +         */
 25.1706 +        private int getFieldOffset(String name, Class type) {
 25.1707 +            ObjectStreamField field = desc.getField(name, type);
 25.1708 +            if (field == null) {
 25.1709 +                throw new IllegalArgumentException("no such field " + name +
 25.1710 +                                                   " with type " + type);
 25.1711 +            }
 25.1712 +            return field.getOffset();
 25.1713 +        }
 25.1714 +    }
 25.1715 +
 25.1716 +    /**
 25.1717 +     * Buffered output stream with two modes: in default mode, outputs data in
 25.1718 +     * same format as DataOutputStream; in "block data" mode, outputs data
 25.1719 +     * bracketed by block data markers (see object serialization specification
 25.1720 +     * for details).
 25.1721 +     */
 25.1722 +    private static class BlockDataOutputStream
 25.1723 +        extends OutputStream implements DataOutput
 25.1724 +    {
 25.1725 +        /** maximum data block length */
 25.1726 +        private static final int MAX_BLOCK_SIZE = 1024;
 25.1727 +        /** maximum data block header length */
 25.1728 +        private static final int MAX_HEADER_SIZE = 5;
 25.1729 +        /** (tunable) length of char buffer (for writing strings) */
 25.1730 +        private static final int CHAR_BUF_SIZE = 256;
 25.1731 +
 25.1732 +        /** buffer for writing general/block data */
 25.1733 +        private final byte[] buf = new byte[MAX_BLOCK_SIZE];
 25.1734 +        /** buffer for writing block data headers */
 25.1735 +        private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
 25.1736 +        /** char buffer for fast string writes */
 25.1737 +        private final char[] cbuf = new char[CHAR_BUF_SIZE];
 25.1738 +
 25.1739 +        /** block data mode */
 25.1740 +        private boolean blkmode = false;
 25.1741 +        /** current offset into buf */
 25.1742 +        private int pos = 0;
 25.1743 +
 25.1744 +        /** underlying output stream */
 25.1745 +        private final OutputStream out;
 25.1746 +        /** loopback stream (for data writes that span data blocks) */
 25.1747 +        private final DataOutputStream dout;
 25.1748 +
 25.1749 +        /**
 25.1750 +         * Creates new BlockDataOutputStream on top of given underlying stream.
 25.1751 +         * Block data mode is turned off by default.
 25.1752 +         */
 25.1753 +        BlockDataOutputStream(OutputStream out) {
 25.1754 +            this.out = out;
 25.1755 +            dout = new DataOutputStream(this);
 25.1756 +        }
 25.1757 +
 25.1758 +        /**
 25.1759 +         * Sets block data mode to the given mode (true == on, false == off)
 25.1760 +         * and returns the previous mode value.  If the new mode is the same as
 25.1761 +         * the old mode, no action is taken.  If the new mode differs from the
 25.1762 +         * old mode, any buffered data is flushed before switching to the new
 25.1763 +         * mode.
 25.1764 +         */
 25.1765 +        boolean setBlockDataMode(boolean mode) throws IOException {
 25.1766 +            if (blkmode == mode) {
 25.1767 +                return blkmode;
 25.1768 +            }
 25.1769 +            drain();
 25.1770 +            blkmode = mode;
 25.1771 +            return !blkmode;
 25.1772 +        }
 25.1773 +
 25.1774 +        /**
 25.1775 +         * Returns true if the stream is currently in block data mode, false
 25.1776 +         * otherwise.
 25.1777 +         */
 25.1778 +        boolean getBlockDataMode() {
 25.1779 +            return blkmode;
 25.1780 +        }
 25.1781 +
 25.1782 +        /* ----------------- generic output stream methods ----------------- */
 25.1783 +        /*
 25.1784 +         * The following methods are equivalent to their counterparts in
 25.1785 +         * OutputStream, except that they partition written data into data
 25.1786 +         * blocks when in block data mode.
 25.1787 +         */
 25.1788 +
 25.1789 +        public void write(int b) throws IOException {
 25.1790 +            if (pos >= MAX_BLOCK_SIZE) {
 25.1791 +                drain();
 25.1792 +            }
 25.1793 +            buf[pos++] = (byte) b;
 25.1794 +        }
 25.1795 +
 25.1796 +        public void write(byte[] b) throws IOException {
 25.1797 +            write(b, 0, b.length, false);
 25.1798 +        }
 25.1799 +
 25.1800 +        public void write(byte[] b, int off, int len) throws IOException {
 25.1801 +            write(b, off, len, false);
 25.1802 +        }
 25.1803 +
 25.1804 +        public void flush() throws IOException {
 25.1805 +            drain();
 25.1806 +            out.flush();
 25.1807 +        }
 25.1808 +
 25.1809 +        public void close() throws IOException {
 25.1810 +            flush();
 25.1811 +            out.close();
 25.1812 +        }
 25.1813 +
 25.1814 +        /**
 25.1815 +         * Writes specified span of byte values from given array.  If copy is
 25.1816 +         * true, copies the values to an intermediate buffer before writing
 25.1817 +         * them to underlying stream (to avoid exposing a reference to the
 25.1818 +         * original byte array).
 25.1819 +         */
 25.1820 +        void write(byte[] b, int off, int len, boolean copy)
 25.1821 +            throws IOException
 25.1822 +        {
 25.1823 +            if (!(copy || blkmode)) {           // write directly
 25.1824 +                drain();
 25.1825 +                out.write(b, off, len);
 25.1826 +                return;
 25.1827 +            }
 25.1828 +
 25.1829 +            while (len > 0) {
 25.1830 +                if (pos >= MAX_BLOCK_SIZE) {
 25.1831 +                    drain();
 25.1832 +                }
 25.1833 +                if (len >= MAX_BLOCK_SIZE && !copy && pos == 0) {
 25.1834 +                    // avoid unnecessary copy
 25.1835 +                    writeBlockHeader(MAX_BLOCK_SIZE);
 25.1836 +                    out.write(b, off, MAX_BLOCK_SIZE);
 25.1837 +                    off += MAX_BLOCK_SIZE;
 25.1838 +                    len -= MAX_BLOCK_SIZE;
 25.1839 +                } else {
 25.1840 +                    int wlen = Math.min(len, MAX_BLOCK_SIZE - pos);
 25.1841 +                    System.arraycopy(b, off, buf, pos, wlen);
 25.1842 +                    pos += wlen;
 25.1843 +                    off += wlen;
 25.1844 +                    len -= wlen;
 25.1845 +                }
 25.1846 +            }
 25.1847 +        }
 25.1848 +
 25.1849 +        /**
 25.1850 +         * Writes all buffered data from this stream to the underlying stream,
 25.1851 +         * but does not flush underlying stream.
 25.1852 +         */
 25.1853 +        void drain() throws IOException {
 25.1854 +            if (pos == 0) {
 25.1855 +                return;
 25.1856 +            }
 25.1857 +            if (blkmode) {
 25.1858 +                writeBlockHeader(pos);
 25.1859 +            }
 25.1860 +            out.write(buf, 0, pos);
 25.1861 +            pos = 0;
 25.1862 +        }
 25.1863 +
 25.1864 +        /**
 25.1865 +         * Writes block data header.  Data blocks shorter than 256 bytes are
 25.1866 +         * prefixed with a 2-byte header; all others start with a 5-byte
 25.1867 +         * header.
 25.1868 +         */
 25.1869 +        private void writeBlockHeader(int len) throws IOException {
 25.1870 +            if (len <= 0xFF) {
 25.1871 +                hbuf[0] = TC_BLOCKDATA;
 25.1872 +                hbuf[1] = (byte) len;
 25.1873 +                out.write(hbuf, 0, 2);
 25.1874 +            } else {
 25.1875 +                hbuf[0] = TC_BLOCKDATALONG;
 25.1876 +                Bits.putInt(hbuf, 1, len);
 25.1877 +                out.write(hbuf, 0, 5);
 25.1878 +            }
 25.1879 +        }
 25.1880 +
 25.1881 +
 25.1882 +        /* ----------------- primitive data output methods ----------------- */
 25.1883 +        /*
 25.1884 +         * The following methods are equivalent to their counterparts in
 25.1885 +         * DataOutputStream, except that they partition written data into data
 25.1886 +         * blocks when in block data mode.
 25.1887 +         */
 25.1888 +
 25.1889 +        public void writeBoolean(boolean v) throws IOException {
 25.1890 +            if (pos >= MAX_BLOCK_SIZE) {
 25.1891 +                drain();
 25.1892 +            }
 25.1893 +            Bits.putBoolean(buf, pos++, v);
 25.1894 +        }
 25.1895 +
 25.1896 +        public void writeByte(int v) throws IOException {
 25.1897 +            if (pos >= MAX_BLOCK_SIZE) {
 25.1898 +                drain();
 25.1899 +            }
 25.1900 +            buf[pos++] = (byte) v;
 25.1901 +        }
 25.1902 +
 25.1903 +        public void writeChar(int v) throws IOException {
 25.1904 +            if (pos + 2 <= MAX_BLOCK_SIZE) {
 25.1905 +                Bits.putChar(buf, pos, (char) v);
 25.1906 +                pos += 2;
 25.1907 +            } else {
 25.1908 +                dout.writeChar(v);
 25.1909 +            }
 25.1910 +        }
 25.1911 +
 25.1912 +        public void writeShort(int v) throws IOException {
 25.1913 +            if (pos + 2 <= MAX_BLOCK_SIZE) {
 25.1914 +                Bits.putShort(buf, pos, (short) v);
 25.1915 +                pos += 2;
 25.1916 +            } else {
 25.1917 +                dout.writeShort(v);
 25.1918 +            }
 25.1919 +        }
 25.1920 +
 25.1921 +        public void writeInt(int v) throws IOException {
 25.1922 +            if (pos + 4 <= MAX_BLOCK_SIZE) {
 25.1923 +                Bits.putInt(buf, pos, v);
 25.1924 +                pos += 4;
 25.1925 +            } else {
 25.1926 +                dout.writeInt(v);
 25.1927 +            }
 25.1928 +        }
 25.1929 +
 25.1930 +        public void writeFloat(float v) throws IOException {
 25.1931 +            if (pos + 4 <= MAX_BLOCK_SIZE) {
 25.1932 +                Bits.putFloat(buf, pos, v);
 25.1933 +                pos += 4;
 25.1934 +            } else {
 25.1935 +                dout.writeFloat(v);
 25.1936 +            }
 25.1937 +        }
 25.1938 +
 25.1939 +        public void writeLong(long v) throws IOException {
 25.1940 +            if (pos + 8 <= MAX_BLOCK_SIZE) {
 25.1941 +                Bits.putLong(buf, pos, v);
 25.1942 +                pos += 8;
 25.1943 +            } else {
 25.1944 +                dout.writeLong(v);
 25.1945 +            }
 25.1946 +        }
 25.1947 +
 25.1948 +        public void writeDouble(double v) throws IOException {
 25.1949 +            if (pos + 8 <= MAX_BLOCK_SIZE) {
 25.1950 +                Bits.putDouble(buf, pos, v);
 25.1951 +                pos += 8;
 25.1952 +            } else {
 25.1953 +                dout.writeDouble(v);
 25.1954 +            }
 25.1955 +        }
 25.1956 +
 25.1957 +        public void writeBytes(String s) throws IOException {
 25.1958 +            int endoff = s.length();
 25.1959 +            int cpos = 0;
 25.1960 +            int csize = 0;
 25.1961 +            for (int off = 0; off < endoff; ) {
 25.1962 +                if (cpos >= csize) {
 25.1963 +                    cpos = 0;
 25.1964 +                    csize = Math.min(endoff - off, CHAR_BUF_SIZE);
 25.1965 +                    s.getChars(off, off + csize, cbuf, 0);
 25.1966 +                }
 25.1967 +                if (pos >= MAX_BLOCK_SIZE) {
 25.1968 +                    drain();
 25.1969 +                }
 25.1970 +                int n = Math.min(csize - cpos, MAX_BLOCK_SIZE - pos);
 25.1971 +                int stop = pos + n;
 25.1972 +                while (pos < stop) {
 25.1973 +                    buf[pos++] = (byte) cbuf[cpos++];
 25.1974 +                }
 25.1975 +                off += n;
 25.1976 +            }
 25.1977 +        }
 25.1978 +
 25.1979 +        public void writeChars(String s) throws IOException {
 25.1980 +            int endoff = s.length();
 25.1981 +            for (int off = 0; off < endoff; ) {
 25.1982 +                int csize = Math.min(endoff - off, CHAR_BUF_SIZE);
 25.1983 +                s.getChars(off, off + csize, cbuf, 0);
 25.1984 +                writeChars(cbuf, 0, csize);
 25.1985 +                off += csize;
 25.1986 +            }
 25.1987 +        }
 25.1988 +
 25.1989 +        public void writeUTF(String s) throws IOException {
 25.1990 +            writeUTF(s, getUTFLength(s));
 25.1991 +        }
 25.1992 +
 25.1993 +
 25.1994 +        /* -------------- primitive data array output methods -------------- */
 25.1995 +        /*
 25.1996 +         * The following methods write out spans of primitive data values.
 25.1997 +         * Though equivalent to calling the corresponding primitive write
 25.1998 +         * methods repeatedly, these methods are optimized for writing groups
 25.1999 +         * of primitive data values more efficiently.
 25.2000 +         */
 25.2001 +
 25.2002 +        void writeBooleans(boolean[] v, int off, int len) throws IOException {
 25.2003 +            int endoff = off + len;
 25.2004 +            while (off < endoff) {
 25.2005 +                if (pos >= MAX_BLOCK_SIZE) {
 25.2006 +                    drain();
 25.2007 +                }
 25.2008 +                int stop = Math.min(endoff, off + (MAX_BLOCK_SIZE - pos));
 25.2009 +                while (off < stop) {
 25.2010 +                    Bits.putBoolean(buf, pos++, v[off++]);
 25.2011 +                }
 25.2012 +            }
 25.2013 +        }
 25.2014 +
 25.2015 +        void writeChars(char[] v, int off, int len) throws IOException {
 25.2016 +            int limit = MAX_BLOCK_SIZE - 2;
 25.2017 +            int endoff = off + len;
 25.2018 +            while (off < endoff) {
 25.2019 +                if (pos <= limit) {
 25.2020 +                    int avail = (MAX_BLOCK_SIZE - pos) >> 1;
 25.2021 +                    int stop = Math.min(endoff, off + avail);
 25.2022 +                    while (off < stop) {
 25.2023 +                        Bits.putChar(buf, pos, v[off++]);
 25.2024 +                        pos += 2;
 25.2025 +                    }
 25.2026 +                } else {
 25.2027 +                    dout.writeChar(v[off++]);
 25.2028 +                }
 25.2029 +            }
 25.2030 +        }
 25.2031 +
 25.2032 +        void writeShorts(short[] v, int off, int len) throws IOException {
 25.2033 +            int limit = MAX_BLOCK_SIZE - 2;
 25.2034 +            int endoff = off + len;
 25.2035 +            while (off < endoff) {
 25.2036 +                if (pos <= limit) {
 25.2037 +                    int avail = (MAX_BLOCK_SIZE - pos) >> 1;
 25.2038 +                    int stop = Math.min(endoff, off + avail);
 25.2039 +                    while (off < stop) {
 25.2040 +                        Bits.putShort(buf, pos, v[off++]);
 25.2041 +                        pos += 2;
 25.2042 +                    }
 25.2043 +                } else {
 25.2044 +                    dout.writeShort(v[off++]);
 25.2045 +                }
 25.2046 +            }
 25.2047 +        }
 25.2048 +
 25.2049 +        void writeInts(int[] v, int off, int len) throws IOException {
 25.2050 +            int limit = MAX_BLOCK_SIZE - 4;
 25.2051 +            int endoff = off + len;
 25.2052 +            while (off < endoff) {
 25.2053 +                if (pos <= limit) {
 25.2054 +                    int avail = (MAX_BLOCK_SIZE - pos) >> 2;
 25.2055 +                    int stop = Math.min(endoff, off + avail);
 25.2056 +                    while (off < stop) {
 25.2057 +                        Bits.putInt(buf, pos, v[off++]);
 25.2058 +                        pos += 4;
 25.2059 +                    }
 25.2060 +                } else {
 25.2061 +                    dout.writeInt(v[off++]);
 25.2062 +                }
 25.2063 +            }
 25.2064 +        }
 25.2065 +
 25.2066 +        void writeFloats(float[] v, int off, int len) throws IOException {
 25.2067 +            int limit = MAX_BLOCK_SIZE - 4;
 25.2068 +            int endoff = off + len;
 25.2069 +            while (off < endoff) {
 25.2070 +                if (pos <= limit) {
 25.2071 +                    int avail = (MAX_BLOCK_SIZE - pos) >> 2;
 25.2072 +                    int chunklen = Math.min(endoff - off, avail);
 25.2073 +                    floatsToBytes(v, off, buf, pos, chunklen);
 25.2074 +                    off += chunklen;
 25.2075 +                    pos += chunklen << 2;
 25.2076 +                } else {
 25.2077 +                    dout.writeFloat(v[off++]);
 25.2078 +                }
 25.2079 +            }
 25.2080 +        }
 25.2081 +
 25.2082 +        void writeLongs(long[] v, int off, int len) throws IOException {
 25.2083 +            int limit = MAX_BLOCK_SIZE - 8;
 25.2084 +            int endoff = off + len;
 25.2085 +            while (off < endoff) {
 25.2086 +                if (pos <= limit) {
 25.2087 +                    int avail = (MAX_BLOCK_SIZE - pos) >> 3;
 25.2088 +                    int stop = Math.min(endoff, off + avail);
 25.2089 +                    while (off < stop) {
 25.2090 +                        Bits.putLong(buf, pos, v[off++]);
 25.2091 +                        pos += 8;
 25.2092 +                    }
 25.2093 +                } else {
 25.2094 +                    dout.writeLong(v[off++]);
 25.2095 +                }
 25.2096 +            }
 25.2097 +        }
 25.2098 +
 25.2099 +        void writeDoubles(double[] v, int off, int len) throws IOException {
 25.2100 +            int limit = MAX_BLOCK_SIZE - 8;
 25.2101 +            int endoff = off + len;
 25.2102 +            while (off < endoff) {
 25.2103 +                if (pos <= limit) {
 25.2104 +                    int avail = (MAX_BLOCK_SIZE - pos) >> 3;
 25.2105 +                    int chunklen = Math.min(endoff - off, avail);
 25.2106 +                    doublesToBytes(v, off, buf, pos, chunklen);
 25.2107 +                    off += chunklen;
 25.2108 +                    pos += chunklen << 3;
 25.2109 +                } else {
 25.2110 +                    dout.writeDouble(v[off++]);
 25.2111 +                }
 25.2112 +            }
 25.2113 +        }
 25.2114 +
 25.2115 +        /**
 25.2116 +         * Returns the length in bytes of the UTF encoding of the given string.
 25.2117 +         */
 25.2118 +        long getUTFLength(String s) {
 25.2119 +            int len = s.length();
 25.2120 +            long utflen = 0;
 25.2121 +            for (int off = 0; off < len; ) {
 25.2122 +                int csize = Math.min(len - off, CHAR_BUF_SIZE);
 25.2123 +                s.getChars(off, off + csize, cbuf, 0);
 25.2124 +                for (int cpos = 0; cpos < csize; cpos++) {
 25.2125 +                    char c = cbuf[cpos];
 25.2126 +                    if (c >= 0x0001 && c <= 0x007F) {
 25.2127 +                        utflen++;
 25.2128 +                    } else if (c > 0x07FF) {
 25.2129 +                        utflen += 3;
 25.2130 +                    } else {
 25.2131 +                        utflen += 2;
 25.2132 +                    }
 25.2133 +                }
 25.2134 +                off += csize;
 25.2135 +            }
 25.2136 +            return utflen;
 25.2137 +        }
 25.2138 +
 25.2139 +        /**
 25.2140 +         * Writes the given string in UTF format.  This method is used in
 25.2141 +         * situations where the UTF encoding length of the string is already
 25.2142 +         * known; specifying it explicitly avoids a prescan of the string to
 25.2143 +         * determine its UTF length.
 25.2144 +         */
 25.2145 +        void writeUTF(String s, long utflen) throws IOException {
 25.2146 +            if (utflen > 0xFFFFL) {
 25.2147 +                throw new UTFDataFormatException();
 25.2148 +            }
 25.2149 +            writeShort((int) utflen);
 25.2150 +            if (utflen == (long) s.length()) {
 25.2151 +                writeBytes(s);
 25.2152 +            } else {
 25.2153 +                writeUTFBody(s);
 25.2154 +            }
 25.2155 +        }
 25.2156 +
 25.2157 +        /**
 25.2158 +         * Writes given string in "long" UTF format.  "Long" UTF format is
 25.2159 +         * identical to standard UTF, except that it uses an 8 byte header
 25.2160 +         * (instead of the standard 2 bytes) to convey the UTF encoding length.
 25.2161 +         */
 25.2162 +        void writeLongUTF(String s) throws IOException {
 25.2163 +            writeLongUTF(s, getUTFLength(s));
 25.2164 +        }
 25.2165 +
 25.2166 +        /**
 25.2167 +         * Writes given string in "long" UTF format, where the UTF encoding
 25.2168 +         * length of the string is already known.
 25.2169 +         */
 25.2170 +        void writeLongUTF(String s, long utflen) throws IOException {
 25.2171 +            writeLong(utflen);
 25.2172 +            if (utflen == (long) s.length()) {
 25.2173 +                writeBytes(s);
 25.2174 +            } else {
 25.2175 +                writeUTFBody(s);
 25.2176 +            }
 25.2177 +        }
 25.2178 +
 25.2179 +        /**
 25.2180 +         * Writes the "body" (i.e., the UTF representation minus the 2-byte or
 25.2181 +         * 8-byte length header) of the UTF encoding for the given string.
 25.2182 +         */
 25.2183 +        private void writeUTFBody(String s) throws IOException {
 25.2184 +            int limit = MAX_BLOCK_SIZE - 3;
 25.2185 +            int len = s.length();
 25.2186 +            for (int off = 0; off < len; ) {
 25.2187 +                int csize = Math.min(len - off, CHAR_BUF_SIZE);
 25.2188 +                s.getChars(off, off + csize, cbuf, 0);
 25.2189 +                for (int cpos = 0; cpos < csize; cpos++) {
 25.2190 +                    char c = cbuf[cpos];
 25.2191 +                    if (pos <= limit) {
 25.2192 +                        if (c <= 0x007F && c != 0) {
 25.2193 +                            buf[pos++] = (byte) c;
 25.2194 +                        } else if (c > 0x07FF) {
 25.2195 +                            buf[pos + 2] = (byte) (0x80 | ((c >> 0) & 0x3F));
 25.2196 +                            buf[pos + 1] = (byte) (0x80 | ((c >> 6) & 0x3F));
 25.2197 +                            buf[pos + 0] = (byte) (0xE0 | ((c >> 12) & 0x0F));
 25.2198 +                            pos += 3;
 25.2199 +                        } else {
 25.2200 +                            buf[pos + 1] = (byte) (0x80 | ((c >> 0) & 0x3F));
 25.2201 +                            buf[pos + 0] = (byte) (0xC0 | ((c >> 6) & 0x1F));
 25.2202 +                            pos += 2;
 25.2203 +                        }
 25.2204 +                    } else {    // write one byte at a time to normalize block
 25.2205 +                        if (c <= 0x007F && c != 0) {
 25.2206 +                            write(c);
 25.2207 +                        } else if (c > 0x07FF) {
 25.2208 +                            write(0xE0 | ((c >> 12) & 0x0F));
 25.2209 +                            write(0x80 | ((c >> 6) & 0x3F));
 25.2210 +                            write(0x80 | ((c >> 0) & 0x3F));
 25.2211 +                        } else {
 25.2212 +                            write(0xC0 | ((c >> 6) & 0x1F));
 25.2213 +                            write(0x80 | ((c >> 0) & 0x3F));
 25.2214 +                        }
 25.2215 +                    }
 25.2216 +                }
 25.2217 +                off += csize;
 25.2218 +            }
 25.2219 +        }
 25.2220 +    }
 25.2221 +
 25.2222 +    /**
 25.2223 +     * Lightweight identity hash table which maps objects to integer handles,
 25.2224 +     * assigned in ascending order.
 25.2225 +     */
 25.2226 +    private static class HandleTable {
 25.2227 +
 25.2228 +        /* number of mappings in table/next available handle */
 25.2229 +        private int size;
 25.2230 +        /* size threshold determining when to expand hash spine */
 25.2231 +        private int threshold;
 25.2232 +        /* factor for computing size threshold */
 25.2233 +        private final float loadFactor;
 25.2234 +        /* maps hash value -> candidate handle value */
 25.2235 +        private int[] spine;
 25.2236 +        /* maps handle value -> next candidate handle value */
 25.2237 +        private int[] next;
 25.2238 +        /* maps handle value -> associated object */
 25.2239 +        private Object[] objs;
 25.2240 +
 25.2241 +        /**
 25.2242 +         * Creates new HandleTable with given capacity and load factor.
 25.2243 +         */
 25.2244 +        HandleTable(int initialCapacity, float loadFactor) {
 25.2245 +            this.loadFactor = loadFactor;
 25.2246 +            spine = new int[initialCapacity];
 25.2247 +            next = new int[initialCapacity];
 25.2248 +            objs = new Object[initialCapacity];
 25.2249 +            threshold = (int) (initialCapacity * loadFactor);
 25.2250 +            clear();
 25.2251 +        }
 25.2252 +
 25.2253 +        /**
 25.2254 +         * Assigns next available handle to given object, and returns handle
 25.2255 +         * value.  Handles are assigned in ascending order starting at 0.
 25.2256 +         */
 25.2257 +        int assign(Object obj) {
 25.2258 +            if (size >= next.length) {
 25.2259 +                growEntries();
 25.2260 +            }
 25.2261 +            if (size >= threshold) {
 25.2262 +                growSpine();
 25.2263 +            }
 25.2264 +            insert(obj, size);
 25.2265 +            return size++;
 25.2266 +        }
 25.2267 +
 25.2268 +        /**
 25.2269 +         * Looks up and returns handle associated with given object, or -1 if
 25.2270 +         * no mapping found.
 25.2271 +         */
 25.2272 +        int lookup(Object obj) {
 25.2273 +            if (size == 0) {
 25.2274 +                return -1;
 25.2275 +            }
 25.2276 +            int index = hash(obj) % spine.length;
 25.2277 +            for (int i = spine[index]; i >= 0; i = next[i]) {
 25.2278 +                if (objs[i] == obj) {
 25.2279 +                    return i;
 25.2280 +                }
 25.2281 +            }
 25.2282 +            return -1;
 25.2283 +        }
 25.2284 +
 25.2285 +        /**
 25.2286 +         * Resets table to its initial (empty) state.
 25.2287 +         */
 25.2288 +        void clear() {
 25.2289 +            Arrays.fill(spine, -1);
 25.2290 +            Arrays.fill(objs, 0, size, null);
 25.2291 +            size = 0;
 25.2292 +        }
 25.2293 +
 25.2294 +        /**
 25.2295 +         * Returns the number of mappings currently in table.
 25.2296 +         */
 25.2297 +        int size() {
 25.2298 +            return size;
 25.2299 +        }
 25.2300 +
 25.2301 +        /**
 25.2302 +         * Inserts mapping object -> handle mapping into table.  Assumes table
 25.2303 +         * is large enough to accommodate new mapping.
 25.2304 +         */
 25.2305 +        private void insert(Object obj, int handle) {
 25.2306 +            int index = hash(obj) % spine.length;
 25.2307 +            objs[handle] = obj;
 25.2308 +            next[handle] = spine[index];
 25.2309 +            spine[index] = handle;
 25.2310 +        }
 25.2311 +
 25.2312 +        /**
 25.2313 +         * Expands the hash "spine" -- equivalent to increasing the number of
 25.2314 +         * buckets in a conventional hash table.
 25.2315 +         */
 25.2316 +        private void growSpine() {
 25.2317 +            spine = new int[(spine.length << 1) + 1];
 25.2318 +            threshold = (int) (spine.length * loadFactor);
 25.2319 +            Arrays.fill(spine, -1);
 25.2320 +            for (int i = 0; i < size; i++) {
 25.2321 +                insert(objs[i], i);
 25.2322 +            }
 25.2323 +        }
 25.2324 +
 25.2325 +        /**
 25.2326 +         * Increases hash table capacity by lengthening entry arrays.
 25.2327 +         */
 25.2328 +        private void growEntries() {
 25.2329 +            int newLength = (next.length << 1) + 1;
 25.2330 +            int[] newNext = new int[newLength];
 25.2331 +            System.arraycopy(next, 0, newNext, 0, size);
 25.2332 +            next = newNext;
 25.2333 +
 25.2334 +            Object[] newObjs = new Object[newLength];
 25.2335 +            System.arraycopy(objs, 0, newObjs, 0, size);
 25.2336 +            objs = newObjs;
 25.2337 +        }
 25.2338 +
 25.2339 +        /**
 25.2340 +         * Returns hash value for given object.
 25.2341 +         */
 25.2342 +        private int hash(Object obj) {
 25.2343 +            return System.identityHashCode(obj) & 0x7FFFFFFF;
 25.2344 +        }
 25.2345 +    }
 25.2346 +
 25.2347 +    /**
 25.2348 +     * Lightweight identity hash table which maps objects to replacement
 25.2349 +     * objects.
 25.2350 +     */
 25.2351 +    private static class ReplaceTable {
 25.2352 +
 25.2353 +        /* maps object -> index */
 25.2354 +        private final HandleTable htab;
 25.2355 +        /* maps index -> replacement object */
 25.2356 +        private Object[] reps;
 25.2357 +
 25.2358 +        /**
 25.2359 +         * Creates new ReplaceTable with given capacity and load factor.
 25.2360 +         */
 25.2361 +        ReplaceTable(int initialCapacity, float loadFactor) {
 25.2362 +            htab = new HandleTable(initialCapacity, loadFactor);
 25.2363 +            reps = new Object[initialCapacity];
 25.2364 +        }
 25.2365 +
 25.2366 +        /**
 25.2367 +         * Enters mapping from object to replacement object.
 25.2368 +         */
 25.2369 +        void assign(Object obj, Object rep) {
 25.2370 +            int index = htab.assign(obj);
 25.2371 +            while (index >= reps.length) {
 25.2372 +                grow();
 25.2373 +            }
 25.2374 +            reps[index] = rep;
 25.2375 +        }
 25.2376 +
 25.2377 +        /**
 25.2378 +         * Looks up and returns replacement for given object.  If no
 25.2379 +         * replacement is found, returns the lookup object itself.
 25.2380 +         */
 25.2381 +        Object lookup(Object obj) {
 25.2382 +            int index = htab.lookup(obj);
 25.2383 +            return (index >= 0) ? reps[index] : obj;
 25.2384 +        }
 25.2385 +
 25.2386 +        /**
 25.2387 +         * Resets table to its initial (empty) state.
 25.2388 +         */
 25.2389 +        void clear() {
 25.2390 +            Arrays.fill(reps, 0, htab.size(), null);
 25.2391 +            htab.clear();
 25.2392 +        }
 25.2393 +
 25.2394 +        /**
 25.2395 +         * Returns the number of mappings currently in table.
 25.2396 +         */
 25.2397 +        int size() {
 25.2398 +            return htab.size();
 25.2399 +        }
 25.2400 +
 25.2401 +        /**
 25.2402 +         * Increases table capacity.
 25.2403 +         */
 25.2404 +        private void grow() {
 25.2405 +            Object[] newReps = new Object[(reps.length << 1) + 1];
 25.2406 +            System.arraycopy(reps, 0, newReps, 0, reps.length);
 25.2407 +            reps = newReps;
 25.2408 +        }
 25.2409 +    }
 25.2410 +
 25.2411 +    /**
 25.2412 +     * Stack to keep debug information about the state of the
 25.2413 +     * serialization process, for embedding in exception messages.
 25.2414 +     */
 25.2415 +    private static class DebugTraceInfoStack {
 25.2416 +        private final List<String> stack;
 25.2417 +
 25.2418 +        DebugTraceInfoStack() {
 25.2419 +            stack = new ArrayList<>();
 25.2420 +        }
 25.2421 +
 25.2422 +        /**
 25.2423 +         * Removes all of the elements from enclosed list.
 25.2424 +         */
 25.2425 +        void clear() {
 25.2426 +            stack.clear();
 25.2427 +        }
 25.2428 +
 25.2429 +        /**
 25.2430 +         * Removes the object at the top of enclosed list.
 25.2431 +         */
 25.2432 +        void pop() {
 25.2433 +            stack.remove(stack.size()-1);
 25.2434 +        }
 25.2435 +
 25.2436 +        /**
 25.2437 +         * Pushes a String onto the top of enclosed list.
 25.2438 +         */
 25.2439 +        void push(String entry) {
 25.2440 +            stack.add("\t- " + entry);
 25.2441 +        }
 25.2442 +
 25.2443 +        /**
 25.2444 +         * Returns a string representation of this object
 25.2445 +         */
 25.2446 +        public String toString() {
 25.2447 +            StringBuilder buffer = new StringBuilder();
 25.2448 +            if (!stack.isEmpty()) {
 25.2449 +                for(int i = stack.size(); i > 0; i-- ) {
 25.2450 +                    buffer.append(stack.get(i-1) + ((i != 1) ? "\n" : ""));
 25.2451 +                }
 25.2452 +            }
 25.2453 +            return buffer.toString();
 25.2454 +        }
 25.2455 +    }
 25.2456 +
 25.2457 +}
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/emul/compact/src/main/java/java/io/ObjectStreamClass.java	Mon Jan 28 18:14:14 2013 +0100
    26.3 @@ -0,0 +1,2304 @@
    26.4 +/*
    26.5 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
    26.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    26.7 + *
    26.8 + * This code is free software; you can redistribute it and/or modify it
    26.9 + * under the terms of the GNU General Public License version 2 only, as
   26.10 + * published by the Free Software Foundation.  Oracle designates this
   26.11 + * particular file as subject to the "Classpath" exception as provided
   26.12 + * by Oracle in the LICENSE file that accompanied this code.
   26.13 + *
   26.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   26.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   26.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   26.17 + * version 2 for more details (a copy is included in the LICENSE file that
   26.18 + * accompanied this code).
   26.19 + *
   26.20 + * You should have received a copy of the GNU General Public License version
   26.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   26.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   26.23 + *
   26.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   26.25 + * or visit www.oracle.com if you need additional information or have any
   26.26 + * questions.
   26.27 + */
   26.28 +
   26.29 +package java.io;
   26.30 +
   26.31 +import java.lang.ref.Reference;
   26.32 +import java.lang.ref.ReferenceQueue;
   26.33 +import java.lang.ref.SoftReference;
   26.34 +import java.lang.ref.WeakReference;
   26.35 +import java.lang.reflect.Constructor;
   26.36 +import java.lang.reflect.Field;
   26.37 +import java.lang.reflect.InvocationTargetException;
   26.38 +import java.lang.reflect.Member;
   26.39 +import java.lang.reflect.Method;
   26.40 +import java.lang.reflect.Modifier;
   26.41 +import java.lang.reflect.Proxy;
   26.42 +import java.security.AccessController;
   26.43 +import java.security.MessageDigest;
   26.44 +import java.security.NoSuchAlgorithmException;
   26.45 +import java.security.PrivilegedAction;
   26.46 +import java.util.ArrayList;
   26.47 +import java.util.Arrays;
   26.48 +import java.util.Collections;
   26.49 +import java.util.Comparator;
   26.50 +import java.util.HashSet;
   26.51 +import java.util.Set;
   26.52 +import java.util.concurrent.ConcurrentHashMap;
   26.53 +import java.util.concurrent.ConcurrentMap;
   26.54 +import sun.misc.Unsafe;
   26.55 +import sun.reflect.ReflectionFactory;
   26.56 +
   26.57 +/**
   26.58 + * Serialization's descriptor for classes.  It contains the name and
   26.59 + * serialVersionUID of the class.  The ObjectStreamClass for a specific class
   26.60 + * loaded in this Java VM can be found/created using the lookup method.
   26.61 + *
   26.62 + * <p>The algorithm to compute the SerialVersionUID is described in
   26.63 + * <a href="../../../platform/serialization/spec/class.html#4100">Object
   26.64 + * Serialization Specification, Section 4.6, Stream Unique Identifiers</a>.
   26.65 + *
   26.66 + * @author      Mike Warres
   26.67 + * @author      Roger Riggs
   26.68 + * @see ObjectStreamField
   26.69 + * @see <a href="../../../platform/serialization/spec/class.html">Object Serialization Specification, Section 4, Class Descriptors</a>
   26.70 + * @since   JDK1.1
   26.71 + */
   26.72 +public class ObjectStreamClass implements Serializable {
   26.73 +
   26.74 +    /** serialPersistentFields value indicating no serializable fields */
   26.75 +    public static final ObjectStreamField[] NO_FIELDS =
   26.76 +        new ObjectStreamField[0];
   26.77 +
   26.78 +    private static final long serialVersionUID = -6120832682080437368L;
   26.79 +    private static final ObjectStreamField[] serialPersistentFields =
   26.80 +        NO_FIELDS;
   26.81 +
   26.82 +    /** reflection factory for obtaining serialization constructors */
   26.83 +    private static final ReflectionFactory reflFactory =
   26.84 +        AccessController.doPrivileged(
   26.85 +            new ReflectionFactory.GetReflectionFactoryAction());
   26.86 +
   26.87 +    private static class Caches {
   26.88 +        /** cache mapping local classes -> descriptors */
   26.89 +        static final ConcurrentMap<WeakClassKey,Reference<?>> localDescs =
   26.90 +            new ConcurrentHashMap<>();
   26.91 +
   26.92 +        /** cache mapping field group/local desc pairs -> field reflectors */
   26.93 +        static final ConcurrentMap<FieldReflectorKey,Reference<?>> reflectors =
   26.94 +            new ConcurrentHashMap<>();
   26.95 +
   26.96 +        /** queue for WeakReferences to local classes */
   26.97 +        private static final ReferenceQueue<Class<?>> localDescsQueue =
   26.98 +            new ReferenceQueue<>();
   26.99 +        /** queue for WeakReferences to field reflectors keys */
  26.100 +        private static final ReferenceQueue<Class<?>> reflectorsQueue =
  26.101 +            new ReferenceQueue<>();
  26.102 +    }
  26.103 +
  26.104 +    /** class associated with this descriptor (if any) */
  26.105 +    private Class<?> cl;
  26.106 +    /** name of class represented by this descriptor */
  26.107 +    private String name;
  26.108 +    /** serialVersionUID of represented class (null if not computed yet) */
  26.109 +    private volatile Long suid;
  26.110 +
  26.111 +    /** true if represents dynamic proxy class */
  26.112 +    private boolean isProxy;
  26.113 +    /** true if represents enum type */
  26.114 +    private boolean isEnum;
  26.115 +    /** true if represented class implements Serializable */
  26.116 +    private boolean serializable;
  26.117 +    /** true if represented class implements Externalizable */
  26.118 +    private boolean externalizable;
  26.119 +    /** true if desc has data written by class-defined writeObject method */
  26.120 +    private boolean hasWriteObjectData;
  26.121 +    /**
  26.122 +     * true if desc has externalizable data written in block data format; this
  26.123 +     * must be true by default to accommodate ObjectInputStream subclasses which
  26.124 +     * override readClassDescriptor() to return class descriptors obtained from
  26.125 +     * ObjectStreamClass.lookup() (see 4461737)
  26.126 +     */
  26.127 +    private boolean hasBlockExternalData = true;
  26.128 +
  26.129 +    /** exception (if any) thrown while attempting to resolve class */
  26.130 +    private ClassNotFoundException resolveEx;
  26.131 +    /** exception (if any) to throw if non-enum deserialization attempted */
  26.132 +    private InvalidClassException deserializeEx;
  26.133 +    /** exception (if any) to throw if non-enum serialization attempted */
  26.134 +    private InvalidClassException serializeEx;
  26.135 +    /** exception (if any) to throw if default serialization attempted */
  26.136 +    private InvalidClassException defaultSerializeEx;
  26.137 +
  26.138 +    /** serializable fields */
  26.139 +    private ObjectStreamField[] fields;
  26.140 +    /** aggregate marshalled size of primitive fields */
  26.141 +    private int primDataSize;
  26.142 +    /** number of non-primitive fields */
  26.143 +    private int numObjFields;
  26.144 +    /** reflector for setting/getting serializable field values */
  26.145 +    private FieldReflector fieldRefl;
  26.146 +    /** data layout of serialized objects described by this class desc */
  26.147 +    private volatile ClassDataSlot[] dataLayout;
  26.148 +
  26.149 +    /** serialization-appropriate constructor, or null if none */
  26.150 +    private Constructor cons;
  26.151 +    /** class-defined writeObject method, or null if none */
  26.152 +    private Method writeObjectMethod;
  26.153 +    /** class-defined readObject method, or null if none */
  26.154 +    private Method readObjectMethod;
  26.155 +    /** class-defined readObjectNoData method, or null if none */
  26.156 +    private Method readObjectNoDataMethod;
  26.157 +    /** class-defined writeReplace method, or null if none */
  26.158 +    private Method writeReplaceMethod;
  26.159 +    /** class-defined readResolve method, or null if none */
  26.160 +    private Method readResolveMethod;
  26.161 +
  26.162 +    /** local class descriptor for represented class (may point to self) */
  26.163 +    private ObjectStreamClass localDesc;
  26.164 +    /** superclass descriptor appearing in stream */
  26.165 +    private ObjectStreamClass superDesc;
  26.166 +
  26.167 +    /**
  26.168 +     * Initializes native code.
  26.169 +     */
  26.170 +    private static native void initNative();
  26.171 +    static {
  26.172 +        initNative();
  26.173 +    }
  26.174 +
  26.175 +    /**
  26.176 +     * Find the descriptor for a class that can be serialized.  Creates an
  26.177 +     * ObjectStreamClass instance if one does not exist yet for class. Null is
  26.178 +     * returned if the specified class does not implement java.io.Serializable
  26.179 +     * or java.io.Externalizable.
  26.180 +     *
  26.181 +     * @param   cl class for which to get the descriptor
  26.182 +     * @return  the class descriptor for the specified class
  26.183 +     */
  26.184 +    public static ObjectStreamClass lookup(Class<?> cl) {
  26.185 +        return lookup(cl, false);
  26.186 +    }
  26.187 +
  26.188 +    /**
  26.189 +     * Returns the descriptor for any class, regardless of whether it
  26.190 +     * implements {@link Serializable}.
  26.191 +     *
  26.192 +     * @param        cl class for which to get the descriptor
  26.193 +     * @return       the class descriptor for the specified class
  26.194 +     * @since 1.6
  26.195 +     */
  26.196 +    public static ObjectStreamClass lookupAny(Class<?> cl) {
  26.197 +        return lookup(cl, true);
  26.198 +    }
  26.199 +
  26.200 +    /**
  26.201 +     * Returns the name of the class described by this descriptor.
  26.202 +     * This method returns the name of the class in the format that
  26.203 +     * is used by the {@link Class#getName} method.
  26.204 +     *
  26.205 +     * @return a string representing the name of the class
  26.206 +     */
  26.207 +    public String getName() {
  26.208 +        return name;
  26.209 +    }
  26.210 +
  26.211 +    /**
  26.212 +     * Return the serialVersionUID for this class.  The serialVersionUID
  26.213 +     * defines a set of classes all with the same name that have evolved from a
  26.214 +     * common root class and agree to be serialized and deserialized using a
  26.215 +     * common format.  NonSerializable classes have a serialVersionUID of 0L.
  26.216 +     *
  26.217 +     * @return  the SUID of the class described by this descriptor
  26.218 +     */
  26.219 +    public long getSerialVersionUID() {
  26.220 +        // REMIND: synchronize instead of relying on volatile?
  26.221 +        if (suid == null) {
  26.222 +            suid = AccessController.doPrivileged(
  26.223 +                new PrivilegedAction<Long>() {
  26.224 +                    public Long run() {
  26.225 +                        return computeDefaultSUID(cl);
  26.226 +                    }
  26.227 +                }
  26.228 +            );
  26.229 +        }
  26.230 +        return suid.longValue();
  26.231 +    }
  26.232 +
  26.233 +    /**
  26.234 +     * Return the class in the local VM that this version is mapped to.  Null
  26.235 +     * is returned if there is no corresponding local class.
  26.236 +     *
  26.237 +     * @return  the <code>Class</code> instance that this descriptor represents
  26.238 +     */
  26.239 +    public Class<?> forClass() {
  26.240 +        return cl;
  26.241 +    }
  26.242 +
  26.243 +    /**
  26.244 +     * Return an array of the fields of this serializable class.
  26.245 +     *
  26.246 +     * @return  an array containing an element for each persistent field of
  26.247 +     *          this class. Returns an array of length zero if there are no
  26.248 +     *          fields.
  26.249 +     * @since 1.2
  26.250 +     */
  26.251 +    public ObjectStreamField[] getFields() {
  26.252 +        return getFields(true);
  26.253 +    }
  26.254 +
  26.255 +    /**
  26.256 +     * Get the field of this class by name.
  26.257 +     *
  26.258 +     * @param   name the name of the data field to look for
  26.259 +     * @return  The ObjectStreamField object of the named field or null if
  26.260 +     *          there is no such named field.
  26.261 +     */
  26.262 +    public ObjectStreamField getField(String name) {
  26.263 +        return getField(name, null);
  26.264 +    }
  26.265 +
  26.266 +    /**
  26.267 +     * Return a string describing this ObjectStreamClass.
  26.268 +     */
  26.269 +    public String toString() {
  26.270 +        return name + ": static final long serialVersionUID = " +
  26.271 +            getSerialVersionUID() + "L;";
  26.272 +    }
  26.273 +
  26.274 +    /**
  26.275 +     * Looks up and returns class descriptor for given class, or null if class
  26.276 +     * is non-serializable and "all" is set to false.
  26.277 +     *
  26.278 +     * @param   cl class to look up
  26.279 +     * @param   all if true, return descriptors for all classes; if false, only
  26.280 +     *          return descriptors for serializable classes
  26.281 +     */
  26.282 +    static ObjectStreamClass lookup(Class<?> cl, boolean all) {
  26.283 +        if (!(all || Serializable.class.isAssignableFrom(cl))) {
  26.284 +            return null;
  26.285 +        }
  26.286 +        processQueue(Caches.localDescsQueue, Caches.localDescs);
  26.287 +        WeakClassKey key = new WeakClassKey(cl, Caches.localDescsQueue);
  26.288 +        Reference<?> ref = Caches.localDescs.get(key);
  26.289 +        Object entry = null;
  26.290 +        if (ref != null) {
  26.291 +            entry = ref.get();
  26.292 +        }
  26.293 +        EntryFuture future = null;
  26.294 +        if (entry == null) {
  26.295 +            EntryFuture newEntry = new EntryFuture();
  26.296 +            Reference<?> newRef = new SoftReference<>(newEntry);
  26.297 +            do {
  26.298 +                if (ref != null) {
  26.299 +                    Caches.localDescs.remove(key, ref);
  26.300 +                }
  26.301 +                ref = Caches.localDescs.putIfAbsent(key, newRef);
  26.302 +                if (ref != null) {
  26.303 +                    entry = ref.get();
  26.304 +                }
  26.305 +            } while (ref != null && entry == null);
  26.306 +            if (entry == null) {
  26.307 +                future = newEntry;
  26.308 +            }
  26.309 +        }
  26.310 +
  26.311 +        if (entry instanceof ObjectStreamClass) {  // check common case first
  26.312 +            return (ObjectStreamClass) entry;
  26.313 +        }
  26.314 +        if (entry instanceof EntryFuture) {
  26.315 +            future = (EntryFuture) entry;
  26.316 +            if (future.getOwner() == Thread.currentThread()) {
  26.317 +                /*
  26.318 +                 * Handle nested call situation described by 4803747: waiting
  26.319 +                 * for future value to be set by a lookup() call further up the
  26.320 +                 * stack will result in deadlock, so calculate and set the
  26.321 +                 * future value here instead.
  26.322 +                 */
  26.323 +                entry = null;
  26.324 +            } else {
  26.325 +                entry = future.get();
  26.326 +            }
  26.327 +        }
  26.328 +        if (entry == null) {
  26.329 +            try {
  26.330 +                entry = new ObjectStreamClass(cl);
  26.331 +            } catch (Throwable th) {
  26.332 +                entry = th;
  26.333 +            }
  26.334 +            if (future.set(entry)) {
  26.335 +                Caches.localDescs.put(key, new SoftReference<Object>(entry));
  26.336 +            } else {
  26.337 +                // nested lookup call already set future
  26.338 +                entry = future.get();
  26.339 +            }
  26.340 +        }
  26.341 +
  26.342 +        if (entry instanceof ObjectStreamClass) {
  26.343 +            return (ObjectStreamClass) entry;
  26.344 +        } else if (entry instanceof RuntimeException) {
  26.345 +            throw (RuntimeException) entry;
  26.346 +        } else if (entry instanceof Error) {
  26.347 +            throw (Error) entry;
  26.348 +        } else {
  26.349 +            throw new InternalError("unexpected entry: " + entry);
  26.350 +        }
  26.351 +    }
  26.352 +
  26.353 +    /**
  26.354 +     * Placeholder used in class descriptor and field reflector lookup tables
  26.355 +     * for an entry in the process of being initialized.  (Internal) callers
  26.356 +     * which receive an EntryFuture belonging to another thread as the result
  26.357 +     * of a lookup should call the get() method of the EntryFuture; this will
  26.358 +     * return the actual entry once it is ready for use and has been set().  To
  26.359 +     * conserve objects, EntryFutures synchronize on themselves.
  26.360 +     */
  26.361 +    private static class EntryFuture {
  26.362 +
  26.363 +        private static final Object unset = new Object();
  26.364 +        private final Thread owner = Thread.currentThread();
  26.365 +        private Object entry = unset;
  26.366 +
  26.367 +        /**
  26.368 +         * Attempts to set the value contained by this EntryFuture.  If the
  26.369 +         * EntryFuture's value has not been set already, then the value is
  26.370 +         * saved, any callers blocked in the get() method are notified, and
  26.371 +         * true is returned.  If the value has already been set, then no saving
  26.372 +         * or notification occurs, and false is returned.
  26.373 +         */
  26.374 +        synchronized boolean set(Object entry) {
  26.375 +            if (this.entry != unset) {
  26.376 +                return false;
  26.377 +            }
  26.378 +            this.entry = entry;
  26.379 +            notifyAll();
  26.380 +            return true;
  26.381 +        }
  26.382 +
  26.383 +        /**
  26.384 +         * Returns the value contained by this EntryFuture, blocking if
  26.385 +         * necessary until a value is set.
  26.386 +         */
  26.387 +        synchronized Object get() {
  26.388 +            boolean interrupted = false;
  26.389 +            while (entry == unset) {
  26.390 +                try {
  26.391 +                    wait();
  26.392 +                } catch (InterruptedException ex) {
  26.393 +                    interrupted = true;
  26.394 +                }
  26.395 +            }
  26.396 +            if (interrupted) {
  26.397 +                AccessController.doPrivileged(
  26.398 +                    new PrivilegedAction<Void>() {
  26.399 +                        public Void run() {
  26.400 +                            Thread.currentThread().interrupt();
  26.401 +                            return null;
  26.402 +                        }
  26.403 +                    }
  26.404 +                );
  26.405 +            }
  26.406 +            return entry;
  26.407 +        }
  26.408 +
  26.409 +        /**
  26.410 +         * Returns the thread that created this EntryFuture.
  26.411 +         */
  26.412 +        Thread getOwner() {
  26.413 +            return owner;
  26.414 +        }
  26.415 +    }
  26.416 +
  26.417 +    /**
  26.418 +     * Creates local class descriptor representing given class.
  26.419 +     */
  26.420 +    private ObjectStreamClass(final Class<?> cl) {
  26.421 +        this.cl = cl;
  26.422 +        name = cl.getName();
  26.423 +        isProxy = Proxy.isProxyClass(cl);
  26.424 +        isEnum = Enum.class.isAssignableFrom(cl);
  26.425 +        serializable = Serializable.class.isAssignableFrom(cl);
  26.426 +        externalizable = Externalizable.class.isAssignableFrom(cl);
  26.427 +
  26.428 +        Class<?> superCl = cl.getSuperclass();
  26.429 +        superDesc = (superCl != null) ? lookup(superCl, false) : null;
  26.430 +        localDesc = this;
  26.431 +
  26.432 +        if (serializable) {
  26.433 +            AccessController.doPrivileged(new PrivilegedAction<Void>() {
  26.434 +                public Void run() {
  26.435 +                    if (isEnum) {
  26.436 +                        suid = Long.valueOf(0);
  26.437 +                        fields = NO_FIELDS;
  26.438 +                        return null;
  26.439 +                    }
  26.440 +                    if (cl.isArray()) {
  26.441 +                        fields = NO_FIELDS;
  26.442 +                        return null;
  26.443 +                    }
  26.444 +
  26.445 +                    suid = getDeclaredSUID(cl);
  26.446 +                    try {
  26.447 +                        fields = getSerialFields(cl);
  26.448 +                        computeFieldOffsets();
  26.449 +                    } catch (InvalidClassException e) {
  26.450 +                        serializeEx = deserializeEx = e;
  26.451 +                        fields = NO_FIELDS;
  26.452 +                    }
  26.453 +
  26.454 +                    if (externalizable) {
  26.455 +                        cons = getExternalizableConstructor(cl);
  26.456 +                    } else {
  26.457 +                        cons = getSerializableConstructor(cl);
  26.458 +                        writeObjectMethod = getPrivateMethod(cl, "writeObject",
  26.459 +                            new Class<?>[] { ObjectOutputStream.class },
  26.460 +                            Void.TYPE);
  26.461 +                        readObjectMethod = getPrivateMethod(cl, "readObject",
  26.462 +                            new Class<?>[] { ObjectInputStream.class },
  26.463 +                            Void.TYPE);
  26.464 +                        readObjectNoDataMethod = getPrivateMethod(
  26.465 +                            cl, "readObjectNoData", null, Void.TYPE);
  26.466 +                        hasWriteObjectData = (writeObjectMethod != null);
  26.467 +                    }
  26.468 +                    writeReplaceMethod = getInheritableMethod(
  26.469 +                        cl, "writeReplace", null, Object.class);
  26.470 +                    readResolveMethod = getInheritableMethod(
  26.471 +                        cl, "readResolve", null, Object.class);
  26.472 +                    return null;
  26.473 +                }
  26.474 +            });
  26.475 +        } else {
  26.476 +            suid = Long.valueOf(0);
  26.477 +            fields = NO_FIELDS;
  26.478 +        }
  26.479 +
  26.480 +        try {
  26.481 +            fieldRefl = getReflector(fields, this);
  26.482 +        } catch (InvalidClassException ex) {
  26.483 +            // field mismatches impossible when matching local fields vs. self
  26.484 +            throw new InternalError();
  26.485 +        }
  26.486 +
  26.487 +        if (deserializeEx == null) {
  26.488 +            if (isEnum) {
  26.489 +                deserializeEx = new InvalidClassException(name, "enum type");
  26.490 +            } else if (cons == null) {
  26.491 +                deserializeEx = new InvalidClassException(
  26.492 +                    name, "no valid constructor");
  26.493 +            }
  26.494 +        }
  26.495 +        for (int i = 0; i < fields.length; i++) {
  26.496 +            if (fields[i].getField() == null) {
  26.497 +                defaultSerializeEx = new InvalidClassException(
  26.498 +                    name, "unmatched serializable field(s) declared");
  26.499 +            }
  26.500 +        }
  26.501 +    }
  26.502 +
  26.503 +    /**
  26.504 +     * Creates blank class descriptor which should be initialized via a
  26.505 +     * subsequent call to initProxy(), initNonProxy() or readNonProxy().
  26.506 +     */
  26.507 +    ObjectStreamClass() {
  26.508 +    }
  26.509 +
  26.510 +    /**
  26.511 +     * Initializes class descriptor representing a proxy class.
  26.512 +     */
  26.513 +    void initProxy(Class<?> cl,
  26.514 +                   ClassNotFoundException resolveEx,
  26.515 +                   ObjectStreamClass superDesc)
  26.516 +        throws InvalidClassException
  26.517 +    {
  26.518 +        this.cl = cl;
  26.519 +        this.resolveEx = resolveEx;
  26.520 +        this.superDesc = superDesc;
  26.521 +        isProxy = true;
  26.522 +        serializable = true;
  26.523 +        suid = Long.valueOf(0);
  26.524 +        fields = NO_FIELDS;
  26.525 +
  26.526 +        if (cl != null) {
  26.527 +            localDesc = lookup(cl, true);
  26.528 +            if (!localDesc.isProxy) {
  26.529 +                throw new InvalidClassException(
  26.530 +                    "cannot bind proxy descriptor to a non-proxy class");
  26.531 +            }
  26.532 +            name = localDesc.name;
  26.533 +            externalizable = localDesc.externalizable;
  26.534 +            cons = localDesc.cons;
  26.535 +            writeReplaceMethod = localDesc.writeReplaceMethod;
  26.536 +            readResolveMethod = localDesc.readResolveMethod;
  26.537 +            deserializeEx = localDesc.deserializeEx;
  26.538 +        }
  26.539 +        fieldRefl = getReflector(fields, localDesc);
  26.540 +    }
  26.541 +
  26.542 +    /**
  26.543 +     * Initializes class descriptor representing a non-proxy class.
  26.544 +     */
  26.545 +    void initNonProxy(ObjectStreamClass model,
  26.546 +                      Class<?> cl,
  26.547 +                      ClassNotFoundException resolveEx,
  26.548 +                      ObjectStreamClass superDesc)
  26.549 +        throws InvalidClassException
  26.550 +    {
  26.551 +        this.cl = cl;
  26.552 +        this.resolveEx = resolveEx;
  26.553 +        this.superDesc = superDesc;
  26.554 +        name = model.name;
  26.555 +        suid = Long.valueOf(model.getSerialVersionUID());
  26.556 +        isProxy = false;
  26.557 +        isEnum = model.isEnum;
  26.558 +        serializable = model.serializable;
  26.559 +        externalizable = model.externalizable;
  26.560 +        hasBlockExternalData = model.hasBlockExternalData;
  26.561 +        hasWriteObjectData = model.hasWriteObjectData;
  26.562 +        fields = model.fields;
  26.563 +        primDataSize = model.primDataSize;
  26.564 +        numObjFields = model.numObjFields;
  26.565 +
  26.566 +        if (cl != null) {
  26.567 +            localDesc = lookup(cl, true);
  26.568 +            if (localDesc.isProxy) {
  26.569 +                throw new InvalidClassException(
  26.570 +                    "cannot bind non-proxy descriptor to a proxy class");
  26.571 +            }
  26.572 +            if (isEnum != localDesc.isEnum) {
  26.573 +                throw new InvalidClassException(isEnum ?
  26.574 +                    "cannot bind enum descriptor to a non-enum class" :
  26.575 +                    "cannot bind non-enum descriptor to an enum class");
  26.576 +            }
  26.577 +
  26.578 +            if (serializable == localDesc.serializable &&
  26.579 +                !cl.isArray() &&
  26.580 +                suid.longValue() != localDesc.getSerialVersionUID())
  26.581 +            {
  26.582 +                throw new InvalidClassException(localDesc.name,
  26.583 +                    "local class incompatible: " +
  26.584 +                    "stream classdesc serialVersionUID = " + suid +
  26.585 +                    ", local class serialVersionUID = " +
  26.586 +                    localDesc.getSerialVersionUID());
  26.587 +            }
  26.588 +
  26.589 +            if (!classNamesEqual(name, localDesc.name)) {
  26.590 +                throw new InvalidClassException(localDesc.name,
  26.591 +                    "local class name incompatible with stream class " +
  26.592 +                    "name \"" + name + "\"");
  26.593 +            }
  26.594 +
  26.595 +            if (!isEnum) {
  26.596 +                if ((serializable == localDesc.serializable) &&
  26.597 +                    (externalizable != localDesc.externalizable))
  26.598 +                {
  26.599 +                    throw new InvalidClassException(localDesc.name,
  26.600 +                        "Serializable incompatible with Externalizable");
  26.601 +                }
  26.602 +
  26.603 +                if ((serializable != localDesc.serializable) ||
  26.604 +                    (externalizable != localDesc.externalizable) ||
  26.605 +                    !(serializable || externalizable))
  26.606 +                {
  26.607 +                    deserializeEx = new InvalidClassException(localDesc.name,
  26.608 +                        "class invalid for deserialization");
  26.609 +                }
  26.610 +            }
  26.611 +
  26.612 +            cons = localDesc.cons;
  26.613 +            writeObjectMethod = localDesc.writeObjectMethod;
  26.614 +            readObjectMethod = localDesc.readObjectMethod;
  26.615 +            readObjectNoDataMethod = localDesc.readObjectNoDataMethod;
  26.616 +            writeReplaceMethod = localDesc.writeReplaceMethod;
  26.617 +            readResolveMethod = localDesc.readResolveMethod;
  26.618 +            if (deserializeEx == null) {
  26.619 +                deserializeEx = localDesc.deserializeEx;
  26.620 +            }
  26.621 +        }
  26.622 +        fieldRefl = getReflector(fields, localDesc);
  26.623 +        // reassign to matched fields so as to reflect local unshared settings
  26.624 +        fields = fieldRefl.getFields();
  26.625 +    }
  26.626 +
  26.627 +    /**
  26.628 +     * Reads non-proxy class descriptor information from given input stream.
  26.629 +     * The resulting class descriptor is not fully functional; it can only be
  26.630 +     * used as input to the ObjectInputStream.resolveClass() and
  26.631 +     * ObjectStreamClass.initNonProxy() methods.
  26.632 +     */
  26.633 +    void readNonProxy(ObjectInputStream in)
  26.634 +        throws IOException, ClassNotFoundException
  26.635 +    {
  26.636 +        name = in.readUTF();
  26.637 +        suid = Long.valueOf(in.readLong());
  26.638 +        isProxy = false;
  26.639 +
  26.640 +        byte flags = in.readByte();
  26.641 +        hasWriteObjectData =
  26.642 +            ((flags & ObjectStreamConstants.SC_WRITE_METHOD) != 0);
  26.643 +        hasBlockExternalData =
  26.644 +            ((flags & ObjectStreamConstants.SC_BLOCK_DATA) != 0);
  26.645 +        externalizable =
  26.646 +            ((flags & ObjectStreamConstants.SC_EXTERNALIZABLE) != 0);
  26.647 +        boolean sflag =
  26.648 +            ((flags & ObjectStreamConstants.SC_SERIALIZABLE) != 0);
  26.649 +        if (externalizable && sflag) {
  26.650 +            throw new InvalidClassException(
  26.651 +                name, "serializable and externalizable flags conflict");
  26.652 +        }
  26.653 +        serializable = externalizable || sflag;
  26.654 +        isEnum = ((flags & ObjectStreamConstants.SC_ENUM) != 0);
  26.655 +        if (isEnum && suid.longValue() != 0L) {
  26.656 +            throw new InvalidClassException(name,
  26.657 +                "enum descriptor has non-zero serialVersionUID: " + suid);
  26.658 +        }
  26.659 +
  26.660 +        int numFields = in.readShort();
  26.661 +        if (isEnum && numFields != 0) {
  26.662 +            throw new InvalidClassException(name,
  26.663 +                "enum descriptor has non-zero field count: " + numFields);
  26.664 +        }
  26.665 +        fields = (numFields > 0) ?
  26.666 +            new ObjectStreamField[numFields] : NO_FIELDS;
  26.667 +        for (int i = 0; i < numFields; i++) {
  26.668 +            char tcode = (char) in.readByte();
  26.669 +            String fname = in.readUTF();
  26.670 +            String signature = ((tcode == 'L') || (tcode == '[')) ?
  26.671 +                in.readTypeString() : new String(new char[] { tcode });
  26.672 +            try {
  26.673 +                fields[i] = new ObjectStreamField(fname, signature, false);
  26.674 +            } catch (RuntimeException e) {
  26.675 +                throw (IOException) new InvalidClassException(name,
  26.676 +                    "invalid descriptor for field " + fname).initCause(e);
  26.677 +            }
  26.678 +        }
  26.679 +        computeFieldOffsets();
  26.680 +    }
  26.681 +
  26.682 +    /**
  26.683 +     * Writes non-proxy class descriptor information to given output stream.
  26.684 +     */
  26.685 +    void writeNonProxy(ObjectOutputStream out) throws IOException {
  26.686 +        out.writeUTF(name);
  26.687 +        out.writeLong(getSerialVersionUID());
  26.688 +
  26.689 +        byte flags = 0;
  26.690 +        if (externalizable) {
  26.691 +            flags |= ObjectStreamConstants.SC_EXTERNALIZABLE;
  26.692 +            int protocol = out.getProtocolVersion();
  26.693 +            if (protocol != ObjectStreamConstants.PROTOCOL_VERSION_1) {
  26.694 +                flags |= ObjectStreamConstants.SC_BLOCK_DATA;
  26.695 +            }
  26.696 +        } else if (serializable) {
  26.697 +            flags |= ObjectStreamConstants.SC_SERIALIZABLE;
  26.698 +        }
  26.699 +        if (hasWriteObjectData) {
  26.700 +            flags |= ObjectStreamConstants.SC_WRITE_METHOD;
  26.701 +        }
  26.702 +        if (isEnum) {
  26.703 +            flags |= ObjectStreamConstants.SC_ENUM;
  26.704 +        }
  26.705 +        out.writeByte(flags);
  26.706 +
  26.707 +        out.writeShort(fields.length);
  26.708 +        for (int i = 0; i < fields.length; i++) {
  26.709 +            ObjectStreamField f = fields[i];
  26.710 +            out.writeByte(f.getTypeCode());
  26.711 +            out.writeUTF(f.getName());
  26.712 +            if (!f.isPrimitive()) {
  26.713 +                out.writeTypeString(f.getTypeString());
  26.714 +            }
  26.715 +        }
  26.716 +    }
  26.717 +
  26.718 +    /**
  26.719 +     * Returns ClassNotFoundException (if any) thrown while attempting to
  26.720 +     * resolve local class corresponding to this class descriptor.
  26.721 +     */
  26.722 +    ClassNotFoundException getResolveException() {
  26.723 +        return resolveEx;
  26.724 +    }
  26.725 +
  26.726 +    /**
  26.727 +     * Throws an InvalidClassException if object instances referencing this
  26.728 +     * class descriptor should not be allowed to deserialize.  This method does
  26.729 +     * not apply to deserialization of enum constants.
  26.730 +     */
  26.731 +    void checkDeserialize() throws InvalidClassException {
  26.732 +        if (deserializeEx != null) {
  26.733 +            InvalidClassException ice =
  26.734 +                new InvalidClassException(deserializeEx.classname,
  26.735 +                                          deserializeEx.getMessage());
  26.736 +            ice.initCause(deserializeEx);
  26.737 +            throw ice;
  26.738 +        }
  26.739 +    }
  26.740 +
  26.741 +    /**
  26.742 +     * Throws an InvalidClassException if objects whose class is represented by
  26.743 +     * this descriptor should not be allowed to serialize.  This method does
  26.744 +     * not apply to serialization of enum constants.
  26.745 +     */
  26.746 +    void checkSerialize() throws InvalidClassException {
  26.747 +        if (serializeEx != null) {
  26.748 +            InvalidClassException ice =
  26.749 +                new InvalidClassException(serializeEx.classname,
  26.750 +                                          serializeEx.getMessage());
  26.751 +            ice.initCause(serializeEx);
  26.752 +            throw ice;
  26.753 +        }
  26.754 +    }
  26.755 +
  26.756 +    /**
  26.757 +     * Throws an InvalidClassException if objects whose class is represented by
  26.758 +     * this descriptor should not be permitted to use default serialization
  26.759 +     * (e.g., if the class declares serializable fields that do not correspond
  26.760 +     * to actual fields, and hence must use the GetField API).  This method
  26.761 +     * does not apply to deserialization of enum constants.
  26.762 +     */
  26.763 +    void checkDefaultSerialize() throws InvalidClassException {
  26.764 +        if (defaultSerializeEx != null) {
  26.765 +            InvalidClassException ice =
  26.766 +                new InvalidClassException(defaultSerializeEx.classname,
  26.767 +                                          defaultSerializeEx.getMessage());
  26.768 +            ice.initCause(defaultSerializeEx);
  26.769 +            throw ice;
  26.770 +        }
  26.771 +    }
  26.772 +
  26.773 +    /**
  26.774 +     * Returns superclass descriptor.  Note that on the receiving side, the
  26.775 +     * superclass descriptor may be bound to a class that is not a superclass
  26.776 +     * of the subclass descriptor's bound class.
  26.777 +     */
  26.778 +    ObjectStreamClass getSuperDesc() {
  26.779 +        return superDesc;
  26.780 +    }
  26.781 +
  26.782 +    /**
  26.783 +     * Returns the "local" class descriptor for the class associated with this
  26.784 +     * class descriptor (i.e., the result of
  26.785 +     * ObjectStreamClass.lookup(this.forClass())) or null if there is no class
  26.786 +     * associated with this descriptor.
  26.787 +     */
  26.788 +    ObjectStreamClass getLocalDesc() {
  26.789 +        return localDesc;
  26.790 +    }
  26.791 +
  26.792 +    /**
  26.793 +     * Returns arrays of ObjectStreamFields representing the serializable
  26.794 +     * fields of the represented class.  If copy is true, a clone of this class
  26.795 +     * descriptor's field array is returned, otherwise the array itself is
  26.796 +     * returned.
  26.797 +     */
  26.798 +    ObjectStreamField[] getFields(boolean copy) {
  26.799 +        return copy ? fields.clone() : fields;
  26.800 +    }
  26.801 +
  26.802 +    /**
  26.803 +     * Looks up a serializable field of the represented class by name and type.
  26.804 +     * A specified type of null matches all types, Object.class matches all
  26.805 +     * non-primitive types, and any other non-null type matches assignable
  26.806 +     * types only.  Returns matching field, or null if no match found.
  26.807 +     */
  26.808 +    ObjectStreamField getField(String name, Class<?> type) {
  26.809 +        for (int i = 0; i < fields.length; i++) {
  26.810 +            ObjectStreamField f = fields[i];
  26.811 +            if (f.getName().equals(name)) {
  26.812 +                if (type == null ||
  26.813 +                    (type == Object.class && !f.isPrimitive()))
  26.814 +                {
  26.815 +                    return f;
  26.816 +                }
  26.817 +                Class<?> ftype = f.getType();
  26.818 +                if (ftype != null && type.isAssignableFrom(ftype)) {
  26.819 +                    return f;
  26.820 +                }
  26.821 +            }
  26.822 +        }
  26.823 +        return null;
  26.824 +    }
  26.825 +
  26.826 +    /**
  26.827 +     * Returns true if class descriptor represents a dynamic proxy class, false
  26.828 +     * otherwise.
  26.829 +     */
  26.830 +    boolean isProxy() {
  26.831 +        return isProxy;
  26.832 +    }
  26.833 +
  26.834 +    /**
  26.835 +     * Returns true if class descriptor represents an enum type, false
  26.836 +     * otherwise.
  26.837 +     */
  26.838 +    boolean isEnum() {
  26.839 +        return isEnum;
  26.840 +    }
  26.841 +
  26.842 +    /**
  26.843 +     * Returns true if represented class implements Externalizable, false
  26.844 +     * otherwise.
  26.845 +     */
  26.846 +    boolean isExternalizable() {
  26.847 +        return externalizable;
  26.848 +    }
  26.849 +
  26.850 +    /**
  26.851 +     * Returns true if represented class implements Serializable, false
  26.852 +     * otherwise.
  26.853 +     */
  26.854 +    boolean isSerializable() {
  26.855 +        return serializable;
  26.856 +    }
  26.857 +
  26.858 +    /**
  26.859 +     * Returns true if class descriptor represents externalizable class that
  26.860 +     * has written its data in 1.2 (block data) format, false otherwise.
  26.861 +     */
  26.862 +    boolean hasBlockExternalData() {
  26.863 +        return hasBlockExternalData;
  26.864 +    }
  26.865 +
  26.866 +    /**
  26.867 +     * Returns true if class descriptor represents serializable (but not
  26.868 +     * externalizable) class which has written its data via a custom
  26.869 +     * writeObject() method, false otherwise.
  26.870 +     */
  26.871 +    boolean hasWriteObjectData() {
  26.872 +        return hasWriteObjectData;
  26.873 +    }
  26.874 +
  26.875 +    /**
  26.876 +     * Returns true if represented class is serializable/externalizable and can
  26.877 +     * be instantiated by the serialization runtime--i.e., if it is
  26.878 +     * externalizable and defines a public no-arg constructor, or if it is
  26.879 +     * non-externalizable and its first non-serializable superclass defines an
  26.880 +     * accessible no-arg constructor.  Otherwise, returns false.
  26.881 +     */
  26.882 +    boolean isInstantiable() {
  26.883 +        return (cons != null);
  26.884 +    }
  26.885 +
  26.886 +    /**
  26.887 +     * Returns true if represented class is serializable (but not
  26.888 +     * externalizable) and defines a conformant writeObject method.  Otherwise,
  26.889 +     * returns false.
  26.890 +     */
  26.891 +    boolean hasWriteObjectMethod() {
  26.892 +        return (writeObjectMethod != null);
  26.893 +    }
  26.894 +
  26.895 +    /**
  26.896 +     * Returns true if represented class is serializable (but not
  26.897 +     * externalizable) and defines a conformant readObject method.  Otherwise,
  26.898 +     * returns false.
  26.899 +     */
  26.900 +    boolean hasReadObjectMethod() {
  26.901 +        return (readObjectMethod != null);
  26.902 +    }
  26.903 +
  26.904 +    /**
  26.905 +     * Returns true if represented class is serializable (but not
  26.906 +     * externalizable) and defines a conformant readObjectNoData method.
  26.907 +     * Otherwise, returns false.
  26.908 +     */
  26.909 +    boolean hasReadObjectNoDataMethod() {
  26.910 +        return (readObjectNoDataMethod != null);
  26.911 +    }
  26.912 +
  26.913 +    /**
  26.914 +     * Returns true if represented class is serializable or externalizable and
  26.915 +     * defines a conformant writeReplace method.  Otherwise, returns false.
  26.916 +     */
  26.917 +    boolean hasWriteReplaceMethod() {
  26.918 +        return (writeReplaceMethod != null);
  26.919 +    }
  26.920 +
  26.921 +    /**
  26.922 +     * Returns true if represented class is serializable or externalizable and
  26.923 +     * defines a conformant readResolve method.  Otherwise, returns false.
  26.924 +     */
  26.925 +    boolean hasReadResolveMethod() {
  26.926 +        return (readResolveMethod != null);
  26.927 +    }
  26.928 +
  26.929 +    /**
  26.930 +     * Creates a new instance of the represented class.  If the class is
  26.931 +     * externalizable, invokes its public no-arg constructor; otherwise, if the
  26.932 +     * class is serializable, invokes the no-arg constructor of the first
  26.933 +     * non-serializable superclass.  Throws UnsupportedOperationException if
  26.934 +     * this class descriptor is not associated with a class, if the associated
  26.935 +     * class is non-serializable or if the appropriate no-arg constructor is
  26.936 +     * inaccessible/unavailable.
  26.937 +     */
  26.938 +    Object newInstance()
  26.939 +        throws InstantiationException, InvocationTargetException,
  26.940 +               UnsupportedOperationException
  26.941 +    {
  26.942 +        if (cons != null) {
  26.943 +            try {
  26.944 +                return cons.newInstance();
  26.945 +            } catch (IllegalAccessException ex) {
  26.946 +                // should not occur, as access checks have been suppressed
  26.947 +                throw new InternalError();
  26.948 +            }
  26.949 +        } else {
  26.950 +            throw new UnsupportedOperationException();
  26.951 +        }
  26.952 +    }
  26.953 +
  26.954 +    /**
  26.955 +     * Invokes the writeObject method of the represented serializable class.
  26.956 +     * Throws UnsupportedOperationException if this class descriptor is not
  26.957 +     * associated with a class, or if the class is externalizable,
  26.958 +     * non-serializable or does not define writeObject.
  26.959 +     */
  26.960 +    void invokeWriteObject(Object obj, ObjectOutputStream out)
  26.961 +        throws IOException, UnsupportedOperationException
  26.962 +    {
  26.963 +        if (writeObjectMethod != null) {
  26.964 +            try {
  26.965 +                writeObjectMethod.invoke(obj, new Object[]{ out });
  26.966 +            } catch (InvocationTargetException ex) {
  26.967 +                Throwable th = ex.getTargetException();
  26.968 +                if (th instanceof IOException) {
  26.969 +                    throw (IOException) th;
  26.970 +                } else {
  26.971 +                    throwMiscException(th);
  26.972 +                }
  26.973 +            } catch (IllegalAccessException ex) {
  26.974 +                // should not occur, as access checks have been suppressed
  26.975 +                throw new InternalError();
  26.976 +            }
  26.977 +        } else {
  26.978 +            throw new UnsupportedOperationException();
  26.979 +        }
  26.980 +    }
  26.981 +
  26.982 +    /**
  26.983 +     * Invokes the readObject method of the represented serializable class.
  26.984 +     * Throws UnsupportedOperationException if this class descriptor is not
  26.985 +     * associated with a class, or if the class is externalizable,
  26.986 +     * non-serializable or does not define readObject.
  26.987 +     */
  26.988 +    void invokeReadObject(Object obj, ObjectInputStream in)
  26.989 +        throws ClassNotFoundException, IOException,
  26.990 +               UnsupportedOperationException
  26.991 +    {
  26.992 +        if (readObjectMethod != null) {
  26.993 +            try {
  26.994 +                readObjectMethod.invoke(obj, new Object[]{ in });
  26.995 +            } catch (InvocationTargetException ex) {
  26.996 +                Throwable th = ex.getTargetException();
  26.997 +                if (th instanceof ClassNotFoundException) {
  26.998 +                    throw (ClassNotFoundException) th;
  26.999 +                } else if (th instanceof IOException) {
 26.1000 +                    throw (IOException) th;
 26.1001 +                } else {
 26.1002 +                    throwMiscException(th);
 26.1003 +                }
 26.1004 +            } catch (IllegalAccessException ex) {
 26.1005 +                // should not occur, as access checks have been suppressed
 26.1006 +                throw new InternalError();
 26.1007 +            }
 26.1008 +        } else {
 26.1009 +            throw new UnsupportedOperationException();
 26.1010 +        }
 26.1011 +    }
 26.1012 +
 26.1013 +    /**
 26.1014 +     * Invokes the readObjectNoData method of the represented serializable
 26.1015 +     * class.  Throws UnsupportedOperationException if this class descriptor is
 26.1016 +     * not associated with a class, or if the class is externalizable,
 26.1017 +     * non-serializable or does not define readObjectNoData.
 26.1018 +     */
 26.1019 +    void invokeReadObjectNoData(Object obj)
 26.1020 +        throws IOException, UnsupportedOperationException
 26.1021 +    {
 26.1022 +        if (readObjectNoDataMethod != null) {
 26.1023 +            try {
 26.1024 +                readObjectNoDataMethod.invoke(obj, (Object[]) null);
 26.1025 +            } catch (InvocationTargetException ex) {
 26.1026 +                Throwable th = ex.getTargetException();
 26.1027 +                if (th instanceof ObjectStreamException) {
 26.1028 +                    throw (ObjectStreamException) th;
 26.1029 +                } else {
 26.1030 +                    throwMiscException(th);
 26.1031 +                }
 26.1032 +            } catch (IllegalAccessException ex) {
 26.1033 +                // should not occur, as access checks have been suppressed
 26.1034 +                throw new InternalError();
 26.1035 +            }
 26.1036 +        } else {
 26.1037 +            throw new UnsupportedOperationException();
 26.1038 +        }
 26.1039 +    }
 26.1040 +
 26.1041 +    /**
 26.1042 +     * Invokes the writeReplace method of the represented serializable class and
 26.1043 +     * returns the result.  Throws UnsupportedOperationException if this class
 26.1044 +     * descriptor is not associated with a class, or if the class is
 26.1045 +     * non-serializable or does not define writeReplace.
 26.1046 +     */
 26.1047 +    Object invokeWriteReplace(Object obj)
 26.1048 +        throws IOException, UnsupportedOperationException
 26.1049 +    {
 26.1050 +        if (writeReplaceMethod != null) {
 26.1051 +            try {
 26.1052 +                return writeReplaceMethod.invoke(obj, (Object[]) null);
 26.1053 +            } catch (InvocationTargetException ex) {
 26.1054 +                Throwable th = ex.getTargetException();
 26.1055 +                if (th instanceof ObjectStreamException) {
 26.1056 +                    throw (ObjectStreamException) th;
 26.1057 +                } else {
 26.1058 +                    throwMiscException(th);
 26.1059 +                    throw new InternalError();  // never reached
 26.1060 +                }
 26.1061 +            } catch (IllegalAccessException ex) {
 26.1062 +                // should not occur, as access checks have been suppressed
 26.1063 +                throw new InternalError();
 26.1064 +            }
 26.1065 +        } else {
 26.1066 +            throw new UnsupportedOperationException();
 26.1067 +        }
 26.1068 +    }
 26.1069 +
 26.1070 +    /**
 26.1071 +     * Invokes the readResolve method of the represented serializable class and
 26.1072 +     * returns the result.  Throws UnsupportedOperationException if this class
 26.1073 +     * descriptor is not associated with a class, or if the class is
 26.1074 +     * non-serializable or does not define readResolve.
 26.1075 +     */
 26.1076 +    Object invokeReadResolve(Object obj)
 26.1077 +        throws IOException, UnsupportedOperationException
 26.1078 +    {
 26.1079 +        if (readResolveMethod != null) {
 26.1080 +            try {
 26.1081 +                return readResolveMethod.invoke(obj, (Object[]) null);
 26.1082 +            } catch (InvocationTargetException ex) {
 26.1083 +                Throwable th = ex.getTargetException();
 26.1084 +                if (th instanceof ObjectStreamException) {
 26.1085 +                    throw (ObjectStreamException) th;
 26.1086 +                } else {
 26.1087 +                    throwMiscException(th);
 26.1088 +                    throw new InternalError();  // never reached
 26.1089 +                }
 26.1090 +            } catch (IllegalAccessException ex) {
 26.1091 +                // should not occur, as access checks have been suppressed
 26.1092 +                throw new InternalError();
 26.1093 +            }
 26.1094 +        } else {
 26.1095 +            throw new UnsupportedOperationException();
 26.1096 +        }
 26.1097 +    }
 26.1098 +
 26.1099 +    /**
 26.1100 +     * Class representing the portion of an object's serialized form allotted
 26.1101 +     * to data described by a given class descriptor.  If "hasData" is false,
 26.1102 +     * the object's serialized form does not contain data associated with the
 26.1103 +     * class descriptor.
 26.1104 +     */
 26.1105 +    static class ClassDataSlot {
 26.1106 +
 26.1107 +        /** class descriptor "occupying" this slot */
 26.1108 +        final ObjectStreamClass desc;
 26.1109 +        /** true if serialized form includes data for this slot's descriptor */
 26.1110 +        final boolean hasData;
 26.1111 +
 26.1112 +        ClassDataSlot(ObjectStreamClass desc, boolean hasData) {
 26.1113 +            this.desc = desc;
 26.1114 +            this.hasData = hasData;
 26.1115 +        }
 26.1116 +    }
 26.1117 +
 26.1118 +    /**
 26.1119 +     * Returns array of ClassDataSlot instances representing the data layout
 26.1120 +     * (including superclass data) for serialized objects described by this
 26.1121 +     * class descriptor.  ClassDataSlots are ordered by inheritance with those
 26.1122 +     * containing "higher" superclasses appearing first.  The final
 26.1123 +     * ClassDataSlot contains a reference to this descriptor.
 26.1124 +     */
 26.1125 +    ClassDataSlot[] getClassDataLayout() throws InvalidClassException {
 26.1126 +        // REMIND: synchronize instead of relying on volatile?
 26.1127 +        if (dataLayout == null) {
 26.1128 +            dataLayout = getClassDataLayout0();
 26.1129 +        }
 26.1130 +        return dataLayout;
 26.1131 +    }
 26.1132 +
 26.1133 +    private ClassDataSlot[] getClassDataLayout0()
 26.1134 +        throws InvalidClassException
 26.1135 +    {
 26.1136 +        ArrayList<ClassDataSlot> slots = new ArrayList<>();
 26.1137 +        Class<?> start = cl, end = cl;
 26.1138 +
 26.1139 +        // locate closest non-serializable superclass
 26.1140 +        while (end != null && Serializable.class.isAssignableFrom(end)) {
 26.1141 +            end = end.getSuperclass();
 26.1142 +        }
 26.1143 +
 26.1144 +        for (ObjectStreamClass d = this; d != null; d = d.superDesc) {
 26.1145 +
 26.1146 +            // search up inheritance hierarchy for class with matching name
 26.1147 +            String searchName = (d.cl != null) ? d.cl.getName() : d.name;
 26.1148 +            Class<?> match = null;
 26.1149 +            for (Class<?> c = start; c != end; c = c.getSuperclass()) {
 26.1150 +                if (searchName.equals(c.getName())) {
 26.1151 +                    match = c;
 26.1152 +                    break;
 26.1153 +                }
 26.1154 +            }
 26.1155 +
 26.1156 +            // add "no data" slot for each unmatched class below match
 26.1157 +            if (match != null) {
 26.1158 +                for (Class<?> c = start; c != match; c = c.getSuperclass()) {
 26.1159 +                    slots.add(new ClassDataSlot(
 26.1160 +                        ObjectStreamClass.lookup(c, true), false));
 26.1161 +                }
 26.1162 +                start = match.getSuperclass();
 26.1163 +            }
 26.1164 +
 26.1165 +            // record descriptor/class pairing
 26.1166 +            slots.add(new ClassDataSlot(d.getVariantFor(match), true));
 26.1167 +        }
 26.1168 +
 26.1169 +        // add "no data" slot for any leftover unmatched classes
 26.1170 +        for (Class<?> c = start; c != end; c = c.getSuperclass()) {
 26.1171 +            slots.add(new ClassDataSlot(
 26.1172 +                ObjectStreamClass.lookup(c, true), false));
 26.1173 +        }
 26.1174 +
 26.1175 +        // order slots from superclass -> subclass
 26.1176 +        Collections.reverse(slots);
 26.1177 +        return slots.toArray(new ClassDataSlot[slots.size()]);
 26.1178 +    }
 26.1179 +
 26.1180 +    /**
 26.1181 +     * Returns aggregate size (in bytes) of marshalled primitive field values
 26.1182 +     * for represented class.
 26.1183 +     */
 26.1184 +    int getPrimDataSize() {
 26.1185 +        return primDataSize;
 26.1186 +    }
 26.1187 +
 26.1188 +    /**
 26.1189 +     * Returns number of non-primitive serializable fields of represented
 26.1190 +     * class.
 26.1191 +     */
 26.1192 +    int getNumObjFields() {
 26.1193 +        return numObjFields;
 26.1194 +    }
 26.1195 +
 26.1196 +    /**
 26.1197 +     * Fetches the serializable primitive field values of object obj and
 26.1198 +     * marshals them into byte array buf starting at offset 0.  It is the
 26.1199 +     * responsibility of the caller to ensure that obj is of the proper type if
 26.1200 +     * non-null.
 26.1201 +     */
 26.1202 +    void getPrimFieldValues(Object obj, byte[] buf) {
 26.1203 +        fieldRefl.getPrimFieldValues(obj, buf);
 26.1204 +    }
 26.1205 +
 26.1206 +    /**
 26.1207 +     * Sets the serializable primitive fields of object obj using values
 26.1208 +     * unmarshalled from byte array buf starting at offset 0.  It is the
 26.1209 +     * responsibility of the caller to ensure that obj is of the proper type if
 26.1210 +     * non-null.
 26.1211 +     */
 26.1212 +    void setPrimFieldValues(Object obj, byte[] buf) {
 26.1213 +        fieldRefl.setPrimFieldValues(obj, buf);
 26.1214 +    }
 26.1215 +
 26.1216 +    /**
 26.1217 +     * Fetches the serializable object field values of object obj and stores
 26.1218 +     * them in array vals starting at offset 0.  It is the responsibility of
 26.1219 +     * the caller to ensure that obj is of the proper type if non-null.
 26.1220 +     */
 26.1221 +    void getObjFieldValues(Object obj, Object[] vals) {
 26.1222 +        fieldRefl.getObjFieldValues(obj, vals);
 26.1223 +    }
 26.1224 +
 26.1225 +    /**
 26.1226 +     * Sets the serializable object fields of object obj using values from
 26.1227 +     * array vals starting at offset 0.  It is the responsibility of the caller
 26.1228 +     * to ensure that obj is of the proper type if non-null.
 26.1229 +     */
 26.1230 +    void setObjFieldValues(Object obj, Object[] vals) {
 26.1231 +        fieldRefl.setObjFieldValues(obj, vals);
 26.1232 +    }
 26.1233 +
 26.1234 +    /**
 26.1235 +     * Calculates and sets serializable field offsets, as well as primitive
 26.1236 +     * data size and object field count totals.  Throws InvalidClassException
 26.1237 +     * if fields are illegally ordered.
 26.1238 +     */
 26.1239 +    private void computeFieldOffsets() throws InvalidClassException {
 26.1240 +        primDataSize = 0;
 26.1241 +        numObjFields = 0;
 26.1242 +        int firstObjIndex = -1;
 26.1243 +
 26.1244 +        for (int i = 0; i < fields.length; i++) {
 26.1245 +            ObjectStreamField f = fields[i];
 26.1246 +            switch (f.getTypeCode()) {
 26.1247 +                case 'Z':
 26.1248 +                case 'B':
 26.1249 +                    f.setOffset(primDataSize++);
 26.1250 +                    break;
 26.1251 +
 26.1252 +                case 'C':
 26.1253 +                case 'S':
 26.1254 +                    f.setOffset(primDataSize);
 26.1255 +                    primDataSize += 2;
 26.1256 +                    break;
 26.1257 +
 26.1258 +                case 'I':
 26.1259 +                case 'F':
 26.1260 +                    f.setOffset(primDataSize);
 26.1261 +                    primDataSize += 4;
 26.1262 +                    break;
 26.1263 +
 26.1264 +                case 'J':
 26.1265 +                case 'D':
 26.1266 +                    f.setOffset(primDataSize);
 26.1267 +                    primDataSize += 8;
 26.1268 +                    break;
 26.1269 +
 26.1270 +                case '[':
 26.1271 +                case 'L':
 26.1272 +                    f.setOffset(numObjFields++);
 26.1273 +                    if (firstObjIndex == -1) {
 26.1274 +                        firstObjIndex = i;
 26.1275 +                    }
 26.1276 +                    break;
 26.1277 +
 26.1278 +                default:
 26.1279 +                    throw new InternalError();
 26.1280 +            }
 26.1281 +        }
 26.1282 +        if (firstObjIndex != -1 &&
 26.1283 +            firstObjIndex + numObjFields != fields.length)
 26.1284 +        {
 26.1285 +            throw new InvalidClassException(name, "illegal field order");
 26.1286 +        }
 26.1287 +    }
 26.1288 +
 26.1289 +    /**
 26.1290 +     * If given class is the same as the class associated with this class
 26.1291 +     * descriptor, returns reference to this class descriptor.  Otherwise,
 26.1292 +     * returns variant of this class descriptor bound to given class.
 26.1293 +     */
 26.1294 +    private ObjectStreamClass getVariantFor(Class<?> cl)
 26.1295 +        throws InvalidClassException
 26.1296 +    {
 26.1297 +        if (this.cl == cl) {
 26.1298 +            return this;
 26.1299 +        }
 26.1300 +        ObjectStreamClass desc = new ObjectStreamClass();
 26.1301 +        if (isProxy) {
 26.1302 +            desc.initProxy(cl, null, superDesc);
 26.1303 +        } else {
 26.1304 +            desc.initNonProxy(this, cl, null, superDesc);
 26.1305 +        }
 26.1306 +        return desc;
 26.1307 +    }
 26.1308 +
 26.1309 +    /**
 26.1310 +     * Returns public no-arg constructor of given class, or null if none found.
 26.1311 +     * Access checks are disabled on the returned constructor (if any), since
 26.1312 +     * the defining class may still be non-public.
 26.1313 +     */
 26.1314 +    private static Constructor getExternalizableConstructor(Class<?> cl) {
 26.1315 +        try {
 26.1316 +            Constructor cons = cl.getDeclaredConstructor((Class<?>[]) null);
 26.1317 +            cons.setAccessible(true);
 26.1318 +            return ((cons.getModifiers() & Modifier.PUBLIC) != 0) ?
 26.1319 +                cons : null;
 26.1320 +        } catch (NoSuchMethodException ex) {
 26.1321 +            return null;
 26.1322 +        }
 26.1323 +    }
 26.1324 +
 26.1325 +    /**
 26.1326 +     * Returns subclass-accessible no-arg constructor of first non-serializable
 26.1327 +     * superclass, or null if none found.  Access checks are disabled on the
 26.1328 +     * returned constructor (if any).
 26.1329 +     */
 26.1330 +    private static Constructor getSerializableConstructor(Class<?> cl) {
 26.1331 +        Class<?> initCl = cl;
 26.1332 +        while (Serializable.class.isAssignableFrom(initCl)) {
 26.1333 +            if ((initCl = initCl.getSuperclass()) == null) {
 26.1334 +                return null;
 26.1335 +            }
 26.1336 +        }
 26.1337 +        try {
 26.1338 +            Constructor cons = initCl.getDeclaredConstructor((Class<?>[]) null);
 26.1339 +            int mods = cons.getModifiers();
 26.1340 +            if ((mods & Modifier.PRIVATE) != 0 ||
 26.1341 +                ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
 26.1342 +                 !packageEquals(cl, initCl)))
 26.1343 +            {
 26.1344 +                return null;
 26.1345 +            }
 26.1346 +            cons = reflFactory.newConstructorForSerialization(cl, cons);
 26.1347 +            cons.setAccessible(true);
 26.1348 +            return cons;
 26.1349 +        } catch (NoSuchMethodException ex) {
 26.1350 +            return null;
 26.1351 +        }
 26.1352 +    }
 26.1353 +
 26.1354 +    /**
 26.1355 +     * Returns non-static, non-abstract method with given signature provided it
 26.1356 +     * is defined by or accessible (via inheritance) by the given class, or
 26.1357 +     * null if no match found.  Access checks are disabled on the returned
 26.1358 +     * method (if any).
 26.1359 +     */
 26.1360 +    private static Method getInheritableMethod(Class<?> cl, String name,
 26.1361 +                                               Class<?>[] argTypes,
 26.1362 +                                               Class<?> returnType)
 26.1363 +    {
 26.1364 +        Method meth = null;
 26.1365 +        Class<?> defCl = cl;
 26.1366 +        while (defCl != null) {
 26.1367 +            try {
 26.1368 +                meth = defCl.getDeclaredMethod(name, argTypes);
 26.1369 +                break;
 26.1370 +            } catch (NoSuchMethodException ex) {
 26.1371 +                defCl = defCl.getSuperclass();
 26.1372 +            }
 26.1373 +        }
 26.1374 +
 26.1375 +        if ((meth == null) || (meth.getReturnType() != returnType)) {
 26.1376 +            return null;
 26.1377 +        }
 26.1378 +        meth.setAccessible(true);
 26.1379 +        int mods = meth.getModifiers();
 26.1380 +        if ((mods & (Modifier.STATIC | Modifier.ABSTRACT)) != 0) {
 26.1381 +            return null;
 26.1382 +        } else if ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0) {
 26.1383 +            return meth;
 26.1384 +        } else if ((mods & Modifier.PRIVATE) != 0) {
 26.1385 +            return (cl == defCl) ? meth : null;
 26.1386 +        } else {
 26.1387 +            return packageEquals(cl, defCl) ? meth : null;
 26.1388 +        }
 26.1389 +    }
 26.1390 +
 26.1391 +    /**
 26.1392 +     * Returns non-static private method with given signature defined by given
 26.1393 +     * class, or null if none found.  Access checks are disabled on the
 26.1394 +     * returned method (if any).
 26.1395 +     */
 26.1396 +    private static Method getPrivateMethod(Class<?> cl, String name,
 26.1397 +                                           Class<?>[] argTypes,
 26.1398 +                                           Class<?> returnType)
 26.1399 +    {
 26.1400 +        try {
 26.1401 +            Method meth = cl.getDeclaredMethod(name, argTypes);
 26.1402 +            meth.setAccessible(true);
 26.1403 +            int mods = meth.getModifiers();
 26.1404 +            return ((meth.getReturnType() == returnType) &&
 26.1405 +                    ((mods & Modifier.STATIC) == 0) &&
 26.1406 +                    ((mods & Modifier.PRIVATE) != 0)) ? meth : null;
 26.1407 +        } catch (NoSuchMethodException ex) {
 26.1408 +            return null;
 26.1409 +        }
 26.1410 +    }
 26.1411 +
 26.1412 +    /**
 26.1413 +     * Returns true if classes are defined in the same runtime package, false
 26.1414 +     * otherwise.
 26.1415 +     */
 26.1416 +    private static boolean packageEquals(Class<?> cl1, Class<?> cl2) {
 26.1417 +        return (cl1.getClassLoader() == cl2.getClassLoader() &&
 26.1418 +                getPackageName(cl1).equals(getPackageName(cl2)));
 26.1419 +    }
 26.1420 +
 26.1421 +    /**
 26.1422 +     * Returns package name of given class.
 26.1423 +     */
 26.1424 +    private static String getPackageName(Class<?> cl) {
 26.1425 +        String s = cl.getName();
 26.1426 +        int i = s.lastIndexOf('[');
 26.1427 +        if (i >= 0) {
 26.1428 +            s = s.substring(i + 2);
 26.1429 +        }
 26.1430 +        i = s.lastIndexOf('.');
 26.1431 +        return (i >= 0) ? s.substring(0, i) : "";
 26.1432 +    }
 26.1433 +
 26.1434 +    /**
 26.1435 +     * Compares class names for equality, ignoring package names.  Returns true
 26.1436 +     * if class names equal, false otherwise.
 26.1437 +     */
 26.1438 +    private static boolean classNamesEqual(String name1, String name2) {
 26.1439 +        name1 = name1.substring(name1.lastIndexOf('.') + 1);
 26.1440 +        name2 = name2.substring(name2.lastIndexOf('.') + 1);
 26.1441 +        return name1.equals(name2);
 26.1442 +    }
 26.1443 +
 26.1444 +    /**
 26.1445 +     * Returns JVM type signature for given class.
 26.1446 +     */
 26.1447 +    private static String getClassSignature(Class<?> cl) {
 26.1448 +        StringBuilder sbuf = new StringBuilder();
 26.1449 +        while (cl.isArray()) {
 26.1450 +            sbuf.append('[');
 26.1451 +            cl = cl.getComponentType();
 26.1452 +        }
 26.1453 +        if (cl.isPrimitive()) {
 26.1454 +            if (cl == Integer.TYPE) {
 26.1455 +                sbuf.append('I');
 26.1456 +            } else if (cl == Byte.TYPE) {
 26.1457 +                sbuf.append('B');
 26.1458 +            } else if (cl == Long.TYPE) {
 26.1459 +                sbuf.append('J');
 26.1460 +            } else if (cl == Float.TYPE) {
 26.1461 +                sbuf.append('F');
 26.1462 +            } else if (cl == Double.TYPE) {
 26.1463 +                sbuf.append('D');
 26.1464 +            } else if (cl == Short.TYPE) {
 26.1465 +                sbuf.append('S');
 26.1466 +            } else if (cl == Character.TYPE) {
 26.1467 +                sbuf.append('C');
 26.1468 +            } else if (cl == Boolean.TYPE) {
 26.1469 +                sbuf.append('Z');
 26.1470 +            } else if (cl == Void.TYPE) {
 26.1471 +                sbuf.append('V');
 26.1472 +            } else {
 26.1473 +                throw new InternalError();
 26.1474 +            }
 26.1475 +        } else {
 26.1476 +            sbuf.append('L' + cl.getName().replace('.', '/') + ';');
 26.1477 +        }
 26.1478 +        return sbuf.toString();
 26.1479 +    }
 26.1480 +
 26.1481 +    /**
 26.1482 +     * Returns JVM type signature for given list of parameters and return type.
 26.1483 +     */
 26.1484 +    private static String getMethodSignature(Class<?>[] paramTypes,
 26.1485 +                                             Class<?> retType)
 26.1486 +    {
 26.1487 +        StringBuilder sbuf = new StringBuilder();
 26.1488 +        sbuf.append('(');
 26.1489 +        for (int i = 0; i < paramTypes.length; i++) {
 26.1490 +            sbuf.append(getClassSignature(paramTypes[i]));
 26.1491 +        }
 26.1492 +        sbuf.append(')');
 26.1493 +        sbuf.append(getClassSignature(retType));
 26.1494 +        return sbuf.toString();
 26.1495 +    }
 26.1496 +
 26.1497 +    /**
 26.1498 +     * Convenience method for throwing an exception that is either a
 26.1499 +     * RuntimeException, Error, or of some unexpected type (in which case it is
 26.1500 +     * wrapped inside an IOException).
 26.1501 +     */
 26.1502 +    private static void throwMiscException(Throwable th) throws IOException {
 26.1503 +        if (th instanceof RuntimeException) {
 26.1504 +            throw (RuntimeException) th;
 26.1505 +        } else if (th instanceof Error) {
 26.1506 +            throw (Error) th;
 26.1507 +        } else {
 26.1508 +            IOException ex = new IOException("unexpected exception type");
 26.1509 +            ex.initCause(th);
 26.1510 +            throw ex;
 26.1511 +        }
 26.1512 +    }
 26.1513 +
 26.1514 +    /**
 26.1515 +     * Returns ObjectStreamField array describing the serializable fields of
 26.1516 +     * the given class.  Serializable fields backed by an actual field of the
 26.1517 +     * class are represented by ObjectStreamFields with corresponding non-null
 26.1518 +     * Field objects.  Throws InvalidClassException if the (explicitly
 26.1519 +     * declared) serializable fields are invalid.
 26.1520 +     */
 26.1521 +    private static ObjectStreamField[] getSerialFields(Class<?> cl)
 26.1522 +        throws InvalidClassException
 26.1523 +    {
 26.1524 +        ObjectStreamField[] fields;
 26.1525 +        if (Serializable.class.isAssignableFrom(cl) &&
 26.1526 +            !Externalizable.class.isAssignableFrom(cl) &&
 26.1527 +            !Proxy.isProxyClass(cl) &&
 26.1528 +            !cl.isInterface())
 26.1529 +        {
 26.1530 +            if ((fields = getDeclaredSerialFields(cl)) == null) {
 26.1531 +                fields = getDefaultSerialFields(cl);
 26.1532 +            }
 26.1533 +            Arrays.sort(fields);
 26.1534 +        } else {
 26.1535 +            fields = NO_FIELDS;
 26.1536 +        }
 26.1537 +        return fields;
 26.1538 +    }
 26.1539 +
 26.1540 +    /**
 26.1541 +     * Returns serializable fields of given class as defined explicitly by a
 26.1542 +     * "serialPersistentFields" field, or null if no appropriate
 26.1543 +     * "serialPersistentFields" field is defined.  Serializable fields backed
 26.1544 +     * by an actual field of the class are represented by ObjectStreamFields
 26.1545 +     * with corresponding non-null Field objects.  For compatibility with past
 26.1546 +     * releases, a "serialPersistentFields" field with a null value is
 26.1547 +     * considered equivalent to not declaring "serialPersistentFields".  Throws
 26.1548 +     * InvalidClassException if the declared serializable fields are
 26.1549 +     * invalid--e.g., if multiple fields share the same name.
 26.1550 +     */
 26.1551 +    private static ObjectStreamField[] getDeclaredSerialFields(Class<?> cl)
 26.1552 +        throws InvalidClassException
 26.1553 +    {
 26.1554 +        ObjectStreamField[] serialPersistentFields = null;
 26.1555 +        try {
 26.1556 +            Field f = cl.getDeclaredField("serialPersistentFields");
 26.1557 +            int mask = Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL;
 26.1558 +            if ((f.getModifiers() & mask) == mask) {
 26.1559 +                f.setAccessible(true);
 26.1560 +                serialPersistentFields = (ObjectStreamField[]) f.get(null);
 26.1561 +            }
 26.1562 +        } catch (Exception ex) {
 26.1563 +        }
 26.1564 +        if (serialPersistentFields == null) {
 26.1565 +            return null;
 26.1566 +        } else if (serialPersistentFields.length == 0) {
 26.1567 +            return NO_FIELDS;
 26.1568 +        }
 26.1569 +
 26.1570 +        ObjectStreamField[] boundFields =
 26.1571 +            new ObjectStreamField[serialPersistentFields.length];
 26.1572 +        Set<String> fieldNames = new HashSet<>(serialPersistentFields.length);
 26.1573 +
 26.1574 +        for (int i = 0; i < serialPersistentFields.length; i++) {
 26.1575 +            ObjectStreamField spf = serialPersistentFields[i];
 26.1576 +
 26.1577 +            String fname = spf.getName();
 26.1578 +            if (fieldNames.contains(fname)) {
 26.1579 +                throw new InvalidClassException(
 26.1580 +                    "multiple serializable fields named " + fname);
 26.1581 +            }
 26.1582 +            fieldNames.add(fname);
 26.1583 +
 26.1584 +            try {
 26.1585 +                Field f = cl.getDeclaredField(fname);
 26.1586 +                if ((f.getType() == spf.getType()) &&
 26.1587 +                    ((f.getModifiers() & Modifier.STATIC) == 0))
 26.1588 +                {
 26.1589 +                    boundFields[i] =
 26.1590 +                        new ObjectStreamField(f, spf.isUnshared(), true);
 26.1591 +                }
 26.1592 +            } catch (NoSuchFieldException ex) {
 26.1593 +            }
 26.1594 +            if (boundFields[i] == null) {
 26.1595 +                boundFields[i] = new ObjectStreamField(
 26.1596 +                    fname, spf.getType(), spf.isUnshared());
 26.1597 +            }
 26.1598 +        }
 26.1599 +        return boundFields;
 26.1600 +    }
 26.1601 +
 26.1602 +    /**
 26.1603 +     * Returns array of ObjectStreamFields corresponding to all non-static
 26.1604 +     * non-transient fields declared by given class.  Each ObjectStreamField
 26.1605 +     * contains a Field object for the field it represents.  If no default
 26.1606 +     * serializable fields exist, NO_FIELDS is returned.
 26.1607 +     */
 26.1608 +    private static ObjectStreamField[] getDefaultSerialFields(Class<?> cl) {
 26.1609 +        Field[] clFields = cl.getDeclaredFields();
 26.1610 +        ArrayList<ObjectStreamField> list = new ArrayList<>();
 26.1611 +        int mask = Modifier.STATIC | Modifier.TRANSIENT;
 26.1612 +
 26.1613 +        for (int i = 0; i < clFields.length; i++) {
 26.1614 +            if ((clFields[i].getModifiers() & mask) == 0) {
 26.1615 +                list.add(new ObjectStreamField(clFields[i], false, true));
 26.1616 +            }
 26.1617 +        }
 26.1618 +        int size = list.size();
 26.1619 +        return (size == 0) ? NO_FIELDS :
 26.1620 +            list.toArray(new ObjectStreamField[size]);
 26.1621 +    }
 26.1622 +
 26.1623 +    /**
 26.1624 +     * Returns explicit serial version UID value declared by given class, or
 26.1625 +     * null if none.
 26.1626 +     */
 26.1627 +    private static Long getDeclaredSUID(Class<?> cl) {
 26.1628 +        try {
 26.1629 +            Field f = cl.getDeclaredField("serialVersionUID");
 26.1630 +            int mask = Modifier.STATIC | Modifier.FINAL;
 26.1631 +            if ((f.getModifiers() & mask) == mask) {
 26.1632 +                f.setAccessible(true);
 26.1633 +                return Long.valueOf(f.getLong(null));
 26.1634 +            }
 26.1635 +        } catch (Exception ex) {
 26.1636 +        }
 26.1637 +        return null;
 26.1638 +    }
 26.1639 +
 26.1640 +    /**
 26.1641 +     * Computes the default serial version UID value for the given class.
 26.1642 +     */
 26.1643 +    private static long computeDefaultSUID(Class<?> cl) {
 26.1644 +        if (!Serializable.class.isAssignableFrom(cl) || Proxy.isProxyClass(cl))
 26.1645 +        {
 26.1646 +            return 0L;
 26.1647 +        }
 26.1648 +
 26.1649 +        try {
 26.1650 +            ByteArrayOutputStream bout = new ByteArrayOutputStream();
 26.1651 +            DataOutputStream dout = new DataOutputStream(bout);
 26.1652 +
 26.1653 +            dout.writeUTF(cl.getName());
 26.1654 +
 26.1655 +            int classMods = cl.getModifiers() &
 26.1656 +                (Modifier.PUBLIC | Modifier.FINAL |
 26.1657 +                 Modifier.INTERFACE | Modifier.ABSTRACT);
 26.1658 +
 26.1659 +            /*
 26.1660 +             * compensate for javac bug in which ABSTRACT bit was set for an
 26.1661 +             * interface only if the interface declared methods
 26.1662 +             */
 26.1663 +            Method[] methods = cl.getDeclaredMethods();
 26.1664 +            if ((classMods & Modifier.INTERFACE) != 0) {
 26.1665 +                classMods = (methods.length > 0) ?
 26.1666 +                    (classMods | Modifier.ABSTRACT) :
 26.1667 +                    (classMods & ~Modifier.ABSTRACT);
 26.1668 +            }
 26.1669 +            dout.writeInt(classMods);
 26.1670 +
 26.1671 +            if (!cl.isArray()) {
 26.1672 +                /*
 26.1673 +                 * compensate for change in 1.2FCS in which
 26.1674 +                 * Class.getInterfaces() was modified to return Cloneable and
 26.1675 +                 * Serializable for array classes.
 26.1676 +                 */
 26.1677 +                Class<?>[] interfaces = cl.getInterfaces();
 26.1678 +                String[] ifaceNames = new String[interfaces.length];
 26.1679 +                for (int i = 0; i < interfaces.length; i++) {
 26.1680 +                    ifaceNames[i] = interfaces[i].getName();
 26.1681 +                }
 26.1682 +                Arrays.sort(ifaceNames);
 26.1683 +                for (int i = 0; i < ifaceNames.length; i++) {
 26.1684 +                    dout.writeUTF(ifaceNames[i]);
 26.1685 +                }
 26.1686 +            }
 26.1687 +
 26.1688 +            Field[] fields = cl.getDeclaredFields();
 26.1689 +            MemberSignature[] fieldSigs = new MemberSignature[fields.length];
 26.1690 +            for (int i = 0; i < fields.length; i++) {
 26.1691 +                fieldSigs[i] = new MemberSignature(fields[i]);
 26.1692 +            }
 26.1693 +            Arrays.sort(fieldSigs, new Comparator<MemberSignature>() {
 26.1694 +                public int compare(MemberSignature ms1, MemberSignature ms2) {
 26.1695 +                    return ms1.name.compareTo(ms2.name);
 26.1696 +                }
 26.1697 +            });
 26.1698 +            for (int i = 0; i < fieldSigs.length; i++) {
 26.1699 +                MemberSignature sig = fieldSigs[i];
 26.1700 +                int mods = sig.member.getModifiers() &
 26.1701 +                    (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED |
 26.1702 +                     Modifier.STATIC | Modifier.FINAL | Modifier.VOLATILE |
 26.1703 +                     Modifier.TRANSIENT);
 26.1704 +                if (((mods & Modifier.PRIVATE) == 0) ||
 26.1705 +                    ((mods & (Modifier.STATIC | Modifier.TRANSIENT)) == 0))
 26.1706 +                {
 26.1707 +                    dout.writeUTF(sig.name);
 26.1708 +                    dout.writeInt(mods);
 26.1709 +                    dout.writeUTF(sig.signature);
 26.1710 +                }
 26.1711 +            }
 26.1712 +
 26.1713 +            if (hasStaticInitializer(cl)) {
 26.1714 +                dout.writeUTF("<clinit>");
 26.1715 +                dout.writeInt(Modifier.STATIC);
 26.1716 +                dout.writeUTF("()V");
 26.1717 +            }
 26.1718 +
 26.1719 +            Constructor[] cons = cl.getDeclaredConstructors();
 26.1720 +            MemberSignature[] consSigs = new MemberSignature[cons.length];
 26.1721 +            for (int i = 0; i < cons.length; i++) {
 26.1722 +                consSigs[i] = new MemberSignature(cons[i]);
 26.1723 +            }
 26.1724 +            Arrays.sort(consSigs, new Comparator<MemberSignature>() {
 26.1725 +                public int compare(MemberSignature ms1, MemberSignature ms2) {
 26.1726 +                    return ms1.signature.compareTo(ms2.signature);
 26.1727 +                }
 26.1728 +            });
 26.1729 +            for (int i = 0; i < consSigs.length; i++) {
 26.1730 +                MemberSignature sig = consSigs[i];
 26.1731 +                int mods = sig.member.getModifiers() &
 26.1732 +                    (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED |
 26.1733 +                     Modifier.STATIC | Modifier.FINAL |
 26.1734 +                     Modifier.SYNCHRONIZED | Modifier.NATIVE |
 26.1735 +                     Modifier.ABSTRACT | Modifier.STRICT);
 26.1736 +                if ((mods & Modifier.PRIVATE) == 0) {
 26.1737 +                    dout.writeUTF("<init>");
 26.1738 +                    dout.writeInt(mods);
 26.1739 +                    dout.writeUTF(sig.signature.replace('/', '.'));
 26.1740 +                }
 26.1741 +            }
 26.1742 +
 26.1743 +            MemberSignature[] methSigs = new MemberSignature[methods.length];
 26.1744 +            for (int i = 0; i < methods.length; i++) {
 26.1745 +                methSigs[i] = new MemberSignature(methods[i]);
 26.1746 +            }
 26.1747 +            Arrays.sort(methSigs, new Comparator<MemberSignature>() {
 26.1748 +                public int compare(MemberSignature ms1, MemberSignature ms2) {
 26.1749 +                    int comp = ms1.name.compareTo(ms2.name);
 26.1750 +                    if (comp == 0) {
 26.1751 +                        comp = ms1.signature.compareTo(ms2.signature);
 26.1752 +                    }
 26.1753 +                    return comp;
 26.1754 +                }
 26.1755 +            });
 26.1756 +            for (int i = 0; i < methSigs.length; i++) {
 26.1757 +                MemberSignature sig = methSigs[i];
 26.1758 +                int mods = sig.member.getModifiers() &
 26.1759 +                    (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED |
 26.1760 +                     Modifier.STATIC | Modifier.FINAL |
 26.1761 +                     Modifier.SYNCHRONIZED | Modifier.NATIVE |
 26.1762 +                     Modifier.ABSTRACT | Modifier.STRICT);
 26.1763 +                if ((mods & Modifier.PRIVATE) == 0) {
 26.1764 +                    dout.writeUTF(sig.name);
 26.1765 +                    dout.writeInt(mods);
 26.1766 +                    dout.writeUTF(sig.signature.replace('/', '.'));
 26.1767 +                }
 26.1768 +            }
 26.1769 +
 26.1770 +            dout.flush();
 26.1771 +
 26.1772 +            MessageDigest md = MessageDigest.getInstance("SHA");
 26.1773 +            byte[] hashBytes = md.digest(bout.toByteArray());
 26.1774 +            long hash = 0;
 26.1775 +            for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
 26.1776 +                hash = (hash << 8) | (hashBytes[i] & 0xFF);
 26.1777 +            }
 26.1778 +            return hash;
 26.1779 +        } catch (IOException ex) {
 26.1780 +            throw new InternalError();
 26.1781 +        } catch (NoSuchAlgorithmException ex) {
 26.1782 +            throw new SecurityException(ex.getMessage());
 26.1783 +        }
 26.1784 +    }
 26.1785 +
 26.1786 +    /**
 26.1787 +     * Returns true if the given class defines a static initializer method,
 26.1788 +     * false otherwise.
 26.1789 +     */
 26.1790 +    private native static boolean hasStaticInitializer(Class<?> cl);
 26.1791 +
 26.1792 +    /**
 26.1793 +     * Class for computing and caching field/constructor/method signatures
 26.1794 +     * during serialVersionUID calculation.
 26.1795 +     */
 26.1796 +    private static class MemberSignature {
 26.1797 +
 26.1798 +        public final Member member;
 26.1799 +        public final String name;
 26.1800 +        public final String signature;
 26.1801 +
 26.1802 +        public MemberSignature(Field field) {
 26.1803 +            member = field;
 26.1804 +            name = field.getName();
 26.1805 +            signature = getClassSignature(field.getType());
 26.1806 +        }
 26.1807 +
 26.1808 +        public MemberSignature(Constructor cons) {
 26.1809 +            member = cons;
 26.1810 +            name = cons.getName();
 26.1811 +            signature = getMethodSignature(
 26.1812 +                cons.getParameterTypes(), Void.TYPE);
 26.1813 +        }
 26.1814 +
 26.1815 +        public MemberSignature(Method meth) {
 26.1816 +            member = meth;
 26.1817 +            name = meth.getName();
 26.1818 +            signature = getMethodSignature(
 26.1819 +                meth.getParameterTypes(), meth.getReturnType());
 26.1820 +        }
 26.1821 +    }
 26.1822 +
 26.1823 +    /**
 26.1824 +     * Class for setting and retrieving serializable field values in batch.
 26.1825 +     */
 26.1826 +    // REMIND: dynamically generate these?
 26.1827 +    private static class FieldReflector {
 26.1828 +
 26.1829 +        /** handle for performing unsafe operations */
 26.1830 +        private static final Unsafe unsafe = Unsafe.getUnsafe();
 26.1831 +
 26.1832 +        /** fields to operate on */
 26.1833 +        private final ObjectStreamField[] fields;
 26.1834 +        /** number of primitive fields */
 26.1835 +        private final int numPrimFields;
 26.1836 +        /** unsafe field keys for reading fields - may contain dupes */
 26.1837 +        private final long[] readKeys;
 26.1838 +        /** unsafe fields keys for writing fields - no dupes */
 26.1839 +        private final long[] writeKeys;
 26.1840 +        /** field data offsets */
 26.1841 +        private final int[] offsets;
 26.1842 +        /** field type codes */
 26.1843 +        private final char[] typeCodes;
 26.1844 +        /** field types */
 26.1845 +        private final Class<?>[] types;
 26.1846 +
 26.1847 +        /**
 26.1848 +         * Constructs FieldReflector capable of setting/getting values from the
 26.1849 +         * subset of fields whose ObjectStreamFields contain non-null
 26.1850 +         * reflective Field objects.  ObjectStreamFields with null Fields are
 26.1851 +         * treated as filler, for which get operations return default values
 26.1852 +         * and set operations discard given values.
 26.1853 +         */
 26.1854 +        FieldReflector(ObjectStreamField[] fields) {
 26.1855 +            this.fields = fields;
 26.1856 +            int nfields = fields.length;
 26.1857 +            readKeys = new long[nfields];
 26.1858 +            writeKeys = new long[nfields];
 26.1859 +            offsets = new int[nfields];
 26.1860 +            typeCodes = new char[nfields];
 26.1861 +            ArrayList<Class<?>> typeList = new ArrayList<>();
 26.1862 +            Set<Long> usedKeys = new HashSet<>();
 26.1863 +
 26.1864 +
 26.1865 +            for (int i = 0; i < nfields; i++) {
 26.1866 +                ObjectStreamField f = fields[i];
 26.1867 +                Field rf = f.getField();
 26.1868 +                long key = (rf != null) ?
 26.1869 +                    unsafe.objectFieldOffset(rf) : Unsafe.INVALID_FIELD_OFFSET;
 26.1870 +                readKeys[i] = key;
 26.1871 +                writeKeys[i] = usedKeys.add(key) ?
 26.1872 +                    key : Unsafe.INVALID_FIELD_OFFSET;
 26.1873 +                offsets[i] = f.getOffset();
 26.1874 +                typeCodes[i] = f.getTypeCode();
 26.1875 +                if (!f.isPrimitive()) {
 26.1876 +                    typeList.add((rf != null) ? rf.getType() : null);
 26.1877 +                }
 26.1878 +            }
 26.1879 +
 26.1880 +            types = typeList.toArray(new Class<?>[typeList.size()]);
 26.1881 +            numPrimFields = nfields - types.length;
 26.1882 +        }
 26.1883 +
 26.1884 +        /**
 26.1885 +         * Returns list of ObjectStreamFields representing fields operated on
 26.1886 +         * by this reflector.  The shared/unshared values and Field objects
 26.1887 +         * contained by ObjectStreamFields in the list reflect their bindings
 26.1888 +         * to locally defined serializable fields.
 26.1889 +         */
 26.1890 +        ObjectStreamField[] getFields() {
 26.1891 +            return fields;
 26.1892 +        }
 26.1893 +
 26.1894 +        /**
 26.1895 +         * Fetches the serializable primitive field values of object obj and
 26.1896 +         * marshals them into byte array buf starting at offset 0.  The caller
 26.1897 +         * is responsible for ensuring that obj is of the proper type.
 26.1898 +         */
 26.1899 +        void getPrimFieldValues(Object obj, byte[] buf) {
 26.1900 +            if (obj == null) {
 26.1901 +                throw new NullPointerException();
 26.1902 +            }
 26.1903 +            /* assuming checkDefaultSerialize() has been called on the class
 26.1904 +             * descriptor this FieldReflector was obtained from, no field keys
 26.1905 +             * in array should be equal to Unsafe.INVALID_FIELD_OFFSET.
 26.1906 +             */
 26.1907 +            for (int i = 0; i < numPrimFields; i++) {
 26.1908 +                long key = readKeys[i];
 26.1909 +                int off = offsets[i];
 26.1910 +                switch (typeCodes[i]) {
 26.1911 +                    case 'Z':
 26.1912 +                        Bits.putBoolean(buf, off, unsafe.getBoolean(obj, key));
 26.1913 +                        break;
 26.1914 +
 26.1915 +                    case 'B':
 26.1916 +                        buf[off] = unsafe.getByte(obj, key);
 26.1917 +                        break;
 26.1918 +
 26.1919 +                    case 'C':
 26.1920 +                        Bits.putChar(buf, off, unsafe.getChar(obj, key));
 26.1921 +                        break;
 26.1922 +
 26.1923 +                    case 'S':
 26.1924 +                        Bits.putShort(buf, off, unsafe.getShort(obj, key));
 26.1925 +                        break;
 26.1926 +
 26.1927 +                    case 'I':
 26.1928 +                        Bits.putInt(buf, off, unsafe.getInt(obj, key));
 26.1929 +                        break;
 26.1930 +
 26.1931 +                    case 'F':
 26.1932 +                        Bits.putFloat(buf, off, unsafe.getFloat(obj, key));
 26.1933 +                        break;
 26.1934 +
 26.1935 +                    case 'J':
 26.1936 +                        Bits.putLong(buf, off, unsafe.getLong(obj, key));
 26.1937 +                        break;
 26.1938 +
 26.1939 +                    case 'D':
 26.1940 +                        Bits.putDouble(buf, off, unsafe.getDouble(obj, key));
 26.1941 +                        break;
 26.1942 +
 26.1943 +                    default:
 26.1944 +                        throw new InternalError();
 26.1945 +                }
 26.1946 +            }
 26.1947 +        }
 26.1948 +
 26.1949 +        /**
 26.1950 +         * Sets the serializable primitive fields of object obj using values
 26.1951 +         * unmarshalled from byte array buf starting at offset 0.  The caller
 26.1952 +         * is responsible for ensuring that obj is of the proper type.
 26.1953 +         */
 26.1954 +        void setPrimFieldValues(Object obj, byte[] buf) {
 26.1955 +            if (obj == null) {
 26.1956 +                throw new NullPointerException();
 26.1957 +            }
 26.1958 +            for (int i = 0; i < numPrimFields; i++) {
 26.1959 +                long key = writeKeys[i];
 26.1960 +                if (key == Unsafe.INVALID_FIELD_OFFSET) {
 26.1961 +                    continue;           // discard value
 26.1962 +                }
 26.1963 +                int off = offsets[i];
 26.1964 +                switch (typeCodes[i]) {
 26.1965 +                    case 'Z':
 26.1966 +                        unsafe.putBoolean(obj, key, Bits.getBoolean(buf, off));
 26.1967 +                        break;
 26.1968 +
 26.1969 +                    case 'B':
 26.1970 +                        unsafe.putByte(obj, key, buf[off]);
 26.1971 +                        break;
 26.1972 +
 26.1973 +                    case 'C':
 26.1974 +                        unsafe.putChar(obj, key, Bits.getChar(buf, off));
 26.1975 +                        break;
 26.1976 +
 26.1977 +                    case 'S':
 26.1978 +                        unsafe.putShort(obj, key, Bits.getShort(buf, off));
 26.1979 +                        break;
 26.1980 +
 26.1981 +                    case 'I':
 26.1982 +                        unsafe.putInt(obj, key, Bits.getInt(buf, off));
 26.1983 +                        break;
 26.1984 +
 26.1985 +                    case 'F':
 26.1986 +                        unsafe.putFloat(obj, key, Bits.getFloat(buf, off));
 26.1987 +                        break;
 26.1988 +
 26.1989 +                    case 'J':
 26.1990 +                        unsafe.putLong(obj, key, Bits.getLong(buf, off));
 26.1991 +                        break;
 26.1992 +
 26.1993 +                    case 'D':
 26.1994 +                        unsafe.putDouble(obj, key, Bits.getDouble(buf, off));
 26.1995 +                        break;
 26.1996 +
 26.1997 +                    default:
 26.1998 +                        throw new InternalError();
 26.1999 +                }
 26.2000 +            }
 26.2001 +        }
 26.2002 +
 26.2003 +        /**
 26.2004 +         * Fetches the serializable object field values of object obj and
 26.2005 +         * stores them in array vals starting at offset 0.  The caller is
 26.2006 +         * responsible for ensuring that obj is of the proper type.
 26.2007 +         */
 26.2008 +        void getObjFieldValues(Object obj, Object[] vals) {
 26.2009 +            if (obj == null) {
 26.2010 +                throw new NullPointerException();
 26.2011 +            }
 26.2012 +            /* assuming checkDefaultSerialize() has been called on the class
 26.2013 +             * descriptor this FieldReflector was obtained from, no field keys
 26.2014 +             * in array should be equal to Unsafe.INVALID_FIELD_OFFSET.
 26.2015 +             */
 26.2016 +            for (int i = numPrimFields; i < fields.length; i++) {
 26.2017 +                switch (typeCodes[i]) {
 26.2018 +                    case 'L':
 26.2019 +                    case '[':
 26.2020 +                        vals[offsets[i]] = unsafe.getObject(obj, readKeys[i]);
 26.2021 +                        break;
 26.2022 +
 26.2023 +                    default:
 26.2024 +                        throw new InternalError();
 26.2025 +                }
 26.2026 +            }
 26.2027 +        }
 26.2028 +
 26.2029 +        /**
 26.2030 +         * Sets the serializable object fields of object obj using values from
 26.2031 +         * array vals starting at offset 0.  The caller is responsible for
 26.2032 +         * ensuring that obj is of the proper type; however, attempts to set a
 26.2033 +         * field with a value of the wrong type will trigger an appropriate
 26.2034 +         * ClassCastException.
 26.2035 +         */
 26.2036 +        void setObjFieldValues(Object obj, Object[] vals) {
 26.2037 +            if (obj == null) {
 26.2038 +                throw new NullPointerException();
 26.2039 +            }
 26.2040 +            for (int i = numPrimFields; i < fields.length; i++) {
 26.2041 +                long key = writeKeys[i];
 26.2042 +                if (key == Unsafe.INVALID_FIELD_OFFSET) {
 26.2043 +                    continue;           // discard value
 26.2044 +                }
 26.2045 +                switch (typeCodes[i]) {
 26.2046 +                    case 'L':
 26.2047 +                    case '[':
 26.2048 +                        Object val = vals[offsets[i]];
 26.2049 +                        if (val != null &&
 26.2050 +                            !types[i - numPrimFields].isInstance(val))
 26.2051 +                        {
 26.2052 +                            Field f = fields[i].getField();
 26.2053 +                            throw new ClassCastException(
 26.2054 +                                "cannot assign instance of " +
 26.2055 +                                val.getClass().getName() + " to field " +
 26.2056 +                                f.getDeclaringClass().getName() + "." +
 26.2057 +                                f.getName() + " of type " +
 26.2058 +                                f.getType().getName() + " in instance of " +
 26.2059 +                                obj.getClass().getName());
 26.2060 +                        }
 26.2061 +                        unsafe.putObject(obj, key, val);
 26.2062 +                        break;
 26.2063 +
 26.2064 +                    default:
 26.2065 +                        throw new InternalError();
 26.2066 +                }
 26.2067 +            }
 26.2068 +        }
 26.2069 +    }
 26.2070 +
 26.2071 +    /**
 26.2072 +     * Matches given set of serializable fields with serializable fields
 26.2073 +     * described by the given local class descriptor, and returns a
 26.2074 +     * FieldReflector instance capable of setting/getting values from the
 26.2075 +     * subset of fields that match (non-matching fields are treated as filler,
 26.2076 +     * for which get operations return default values and set operations
 26.2077 +     * discard given values).  Throws InvalidClassException if unresolvable
 26.2078 +     * type conflicts exist between the two sets of fields.
 26.2079 +     */
 26.2080 +    private static FieldReflector getReflector(ObjectStreamField[] fields,
 26.2081 +                                               ObjectStreamClass localDesc)
 26.2082 +        throws InvalidClassException
 26.2083 +    {
 26.2084 +        // class irrelevant if no fields
 26.2085 +        Class<?> cl = (localDesc != null && fields.length > 0) ?
 26.2086 +            localDesc.cl : null;
 26.2087 +        processQueue(Caches.reflectorsQueue, Caches.reflectors);
 26.2088 +        FieldReflectorKey key = new FieldReflectorKey(cl, fields,
 26.2089 +                                                      Caches.reflectorsQueue);
 26.2090 +        Reference<?> ref = Caches.reflectors.get(key);
 26.2091 +        Object entry = null;
 26.2092 +        if (ref != null) {
 26.2093 +            entry = ref.get();
 26.2094 +        }
 26.2095 +        EntryFuture future = null;
 26.2096 +        if (entry == null) {
 26.2097 +            EntryFuture newEntry = new EntryFuture();
 26.2098 +            Reference<?> newRef = new SoftReference<>(newEntry);
 26.2099 +            do {
 26.2100 +                if (ref != null) {
 26.2101 +                    Caches.reflectors.remove(key, ref);
 26.2102 +                }
 26.2103 +                ref = Caches.reflectors.putIfAbsent(key, newRef);
 26.2104 +                if (ref != null) {
 26.2105 +                    entry = ref.get();
 26.2106 +                }
 26.2107 +            } while (ref != null && entry == null);
 26.2108 +            if (entry == null) {
 26.2109 +                future = newEntry;
 26.2110 +            }
 26.2111 +        }
 26.2112 +
 26.2113 +        if (entry instanceof FieldReflector) {  // check common case first
 26.2114 +            return (FieldReflector) entry;
 26.2115 +        } else if (entry instanceof EntryFuture) {
 26.2116 +            entry = ((EntryFuture) entry).get();
 26.2117 +        } else if (entry == null) {
 26.2118 +            try {
 26.2119 +                entry = new FieldReflector(matchFields(fields, localDesc));
 26.2120 +            } catch (Throwable th) {
 26.2121 +                entry = th;
 26.2122 +            }
 26.2123 +            future.set(entry);
 26.2124 +            Caches.reflectors.put(key, new SoftReference<Object>(entry));
 26.2125 +        }
 26.2126 +
 26.2127 +        if (entry instanceof FieldReflector) {
 26.2128 +            return (FieldReflector) entry;
 26.2129 +        } else if (entry instanceof InvalidClassException) {
 26.2130 +            throw (InvalidClassException) entry;
 26.2131 +        } else if (entry instanceof RuntimeException) {
 26.2132 +            throw (RuntimeException) entry;
 26.2133 +        } else if (entry instanceof Error) {
 26.2134 +            throw (Error) entry;
 26.2135 +        } else {
 26.2136 +            throw new InternalError("unexpected entry: " + entry);
 26.2137 +        }
 26.2138 +    }
 26.2139 +
 26.2140 +    /**
 26.2141 +     * FieldReflector cache lookup key.  Keys are considered equal if they
 26.2142 +     * refer to the same class and equivalent field formats.
 26.2143 +     */
 26.2144 +    private static class FieldReflectorKey extends WeakReference<Class<?>> {
 26.2145 +
 26.2146 +        private final String sigs;
 26.2147 +        private final int hash;
 26.2148 +        private final boolean nullClass;
 26.2149 +
 26.2150 +        FieldReflectorKey(Class<?> cl, ObjectStreamField[] fields,
 26.2151 +                          ReferenceQueue<Class<?>> queue)
 26.2152 +        {
 26.2153 +            super(cl, queue);
 26.2154 +            nullClass = (cl == null);
 26.2155 +            StringBuilder sbuf = new StringBuilder();
 26.2156 +            for (int i = 0; i < fields.length; i++) {
 26.2157 +                ObjectStreamField f = fields[i];
 26.2158 +                sbuf.append(f.getName()).append(f.getSignature());
 26.2159 +            }
 26.2160 +            sigs = sbuf.toString();
 26.2161 +            hash = System.identityHashCode(cl) + sigs.hashCode();
 26.2162 +        }
 26.2163 +
 26.2164 +        public int hashCode() {
 26.2165 +            return hash;
 26.2166 +        }
 26.2167 +
 26.2168 +        public boolean equals(Object obj) {
 26.2169 +            if (obj == this) {
 26.2170 +                return true;
 26.2171 +            }
 26.2172 +
 26.2173 +            if (obj instanceof FieldReflectorKey) {
 26.2174 +                FieldReflectorKey other = (FieldReflectorKey) obj;
 26.2175 +                Class<?> referent;
 26.2176 +                return (nullClass ? other.nullClass
 26.2177 +                                  : ((referent = get()) != null) &&
 26.2178 +                                    (referent == other.get())) &&
 26.2179 +                    sigs.equals(other.sigs);
 26.2180 +            } else {
 26.2181 +                return false;
 26.2182 +            }
 26.2183 +        }
 26.2184 +    }
 26.2185 +
 26.2186 +    /**
 26.2187 +     * Matches given set of serializable fields with serializable fields
 26.2188 +     * obtained from the given local class descriptor (which contain bindings
 26.2189 +     * to reflective Field objects).  Returns list of ObjectStreamFields in
 26.2190 +     * which each ObjectStreamField whose signature matches that of a local
 26.2191 +     * field contains a Field object for that field; unmatched
 26.2192 +     * ObjectStreamFields contain null Field objects.  Shared/unshared settings
 26.2193 +     * of the returned ObjectStreamFields also reflect those of matched local
 26.2194 +     * ObjectStreamFields.  Throws InvalidClassException if unresolvable type
 26.2195 +     * conflicts exist between the two sets of fields.
 26.2196 +     */
 26.2197 +    private static ObjectStreamField[] matchFields(ObjectStreamField[] fields,
 26.2198 +                                                   ObjectStreamClass localDesc)
 26.2199 +        throws InvalidClassException
 26.2200 +    {
 26.2201 +        ObjectStreamField[] localFields = (localDesc != null) ?
 26.2202 +            localDesc.fields : NO_FIELDS;
 26.2203 +
 26.2204 +        /*
 26.2205 +         * Even if fields == localFields, we cannot simply return localFields
 26.2206 +         * here.  In previous implementations of serialization,
 26.2207 +         * ObjectStreamField.getType() returned Object.class if the
 26.2208 +         * ObjectStreamField represented a non-primitive field and belonged to
 26.2209 +         * a non-local class descriptor.  To preserve this (questionable)
 26.2210 +         * behavior, the ObjectStreamField instances returned by matchFields
 26.2211 +         * cannot report non-primitive types other than Object.class; hence
 26.2212 +         * localFields cannot be returned directly.
 26.2213 +         */
 26.2214 +
 26.2215 +        ObjectStreamField[] matches = new ObjectStreamField[fields.length];
 26.2216 +        for (int i = 0; i < fields.length; i++) {
 26.2217 +            ObjectStreamField f = fields[i], m = null;
 26.2218 +            for (int j = 0; j < localFields.length; j++) {
 26.2219 +                ObjectStreamField lf = localFields[j];
 26.2220 +                if (f.getName().equals(lf.getName())) {
 26.2221 +                    if ((f.isPrimitive() || lf.isPrimitive()) &&
 26.2222 +                        f.getTypeCode() != lf.getTypeCode())
 26.2223 +                    {
 26.2224 +                        throw new InvalidClassException(localDesc.name,
 26.2225 +                            "incompatible types for field " + f.getName());
 26.2226 +                    }
 26.2227 +                    if (lf.getField() != null) {
 26.2228 +                        m = new ObjectStreamField(
 26.2229 +                            lf.getField(), lf.isUnshared(), false);
 26.2230 +                    } else {
 26.2231 +                        m = new ObjectStreamField(
 26.2232 +                            lf.getName(), lf.getSignature(), lf.isUnshared());
 26.2233 +                    }
 26.2234 +                }
 26.2235 +            }
 26.2236 +            if (m == null) {
 26.2237 +                m = new ObjectStreamField(
 26.2238 +                    f.getName(), f.getSignature(), false);
 26.2239 +            }
 26.2240 +            m.setOffset(f.getOffset());
 26.2241 +            matches[i] = m;
 26.2242 +        }
 26.2243 +        return matches;
 26.2244 +    }
 26.2245 +
 26.2246 +    /**
 26.2247 +     * Removes from the specified map any keys that have been enqueued
 26.2248 +     * on the specified reference queue.
 26.2249 +     */
 26.2250 +    static void processQueue(ReferenceQueue<Class<?>> queue,
 26.2251 +                             ConcurrentMap<? extends
 26.2252 +                             WeakReference<Class<?>>, ?> map)
 26.2253 +    {
 26.2254 +        Reference<? extends Class<?>> ref;
 26.2255 +        while((ref = queue.poll()) != null) {
 26.2256 +            map.remove(ref);
 26.2257 +        }
 26.2258 +    }
 26.2259 +
 26.2260 +    /**
 26.2261 +     *  Weak key for Class objects.
 26.2262 +     *
 26.2263 +     **/
 26.2264 +    static class WeakClassKey extends WeakReference<Class<?>> {
 26.2265 +        /**
 26.2266 +         * saved value of the referent's identity hash code, to maintain
 26.2267 +         * a consistent hash code after the referent has been cleared
 26.2268 +         */
 26.2269 +        private final int hash;
 26.2270 +
 26.2271 +        /**
 26.2272 +         * Create a new WeakClassKey to the given object, registered
 26.2273 +         * with a queue.
 26.2274 +         */
 26.2275 +        WeakClassKey(Class<?> cl, ReferenceQueue<Class<?>> refQueue) {
 26.2276 +            super(cl, refQueue);
 26.2277 +            hash = System.identityHashCode(cl);
 26.2278 +        }
 26.2279 +
 26.2280 +        /**
 26.2281 +         * Returns the identity hash code of the original referent.
 26.2282 +         */
 26.2283 +        public int hashCode() {
 26.2284 +            return hash;
 26.2285 +        }
 26.2286 +
 26.2287 +        /**
 26.2288 +         * Returns true if the given object is this identical
 26.2289 +         * WeakClassKey instance, or, if this object's referent has not
 26.2290 +         * been cleared, if the given object is another WeakClassKey
 26.2291 +         * instance with the identical non-null referent as this one.
 26.2292 +         */
 26.2293 +        public boolean equals(Object obj) {
 26.2294 +            if (obj == this) {
 26.2295 +                return true;
 26.2296 +            }
 26.2297 +
 26.2298 +            if (obj instanceof WeakClassKey) {
 26.2299 +                Object referent = get();
 26.2300 +                return (referent != null) &&
 26.2301 +                       (referent == ((WeakClassKey) obj).get());
 26.2302 +            } else {
 26.2303 +                return false;
 26.2304 +            }
 26.2305 +        }
 26.2306 +    }
 26.2307 +}
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/emul/compact/src/main/java/java/io/ObjectStreamConstants.java	Mon Jan 28 18:14:14 2013 +0100
    27.3 @@ -0,0 +1,235 @@
    27.4 +/*
    27.5 + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
    27.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    27.7 + *
    27.8 + * This code is free software; you can redistribute it and/or modify it
    27.9 + * under the terms of the GNU General Public License version 2 only, as
   27.10 + * published by the Free Software Foundation.  Oracle designates this
   27.11 + * particular file as subject to the "Classpath" exception as provided
   27.12 + * by Oracle in the LICENSE file that accompanied this code.
   27.13 + *
   27.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   27.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   27.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   27.17 + * version 2 for more details (a copy is included in the LICENSE file that
   27.18 + * accompanied this code).
   27.19 + *
   27.20 + * You should have received a copy of the GNU General Public License version
   27.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   27.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   27.23 + *
   27.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   27.25 + * or visit www.oracle.com if you need additional information or have any
   27.26 + * questions.
   27.27 + */
   27.28 +
   27.29 +package java.io;
   27.30 +
   27.31 +/**
   27.32 + * Constants written into the Object Serialization Stream.
   27.33 + *
   27.34 + * @author  unascribed
   27.35 + * @since JDK 1.1
   27.36 + */
   27.37 +public interface ObjectStreamConstants {
   27.38 +
   27.39 +    /**
   27.40 +     * Magic number that is written to the stream header.
   27.41 +     */
   27.42 +    final static short STREAM_MAGIC = (short)0xaced;
   27.43 +
   27.44 +    /**
   27.45 +     * Version number that is written to the stream header.
   27.46 +     */
   27.47 +    final static short STREAM_VERSION = 5;
   27.48 +
   27.49 +    /* Each item in the stream is preceded by a tag
   27.50 +     */
   27.51 +
   27.52 +    /**
   27.53 +     * First tag value.
   27.54 +     */
   27.55 +    final static byte TC_BASE = 0x70;
   27.56 +
   27.57 +    /**
   27.58 +     * Null object reference.
   27.59 +     */
   27.60 +    final static byte TC_NULL =         (byte)0x70;
   27.61 +
   27.62 +    /**
   27.63 +     * Reference to an object already written into the stream.
   27.64 +     */
   27.65 +    final static byte TC_REFERENCE =    (byte)0x71;
   27.66 +
   27.67 +    /**
   27.68 +     * new Class Descriptor.
   27.69 +     */
   27.70 +    final static byte TC_CLASSDESC =    (byte)0x72;
   27.71 +
   27.72 +    /**
   27.73 +     * new Object.
   27.74 +     */
   27.75 +    final static byte TC_OBJECT =       (byte)0x73;
   27.76 +
   27.77 +    /**
   27.78 +     * new String.
   27.79 +     */
   27.80 +    final static byte TC_STRING =       (byte)0x74;
   27.81 +
   27.82 +    /**
   27.83 +     * new Array.
   27.84 +     */
   27.85 +    final static byte TC_ARRAY =        (byte)0x75;
   27.86 +
   27.87 +    /**
   27.88 +     * Reference to Class.
   27.89 +     */
   27.90 +    final static byte TC_CLASS =        (byte)0x76;
   27.91 +
   27.92 +    /**
   27.93 +     * Block of optional data. Byte following tag indicates number
   27.94 +     * of bytes in this block data.
   27.95 +     */
   27.96 +    final static byte TC_BLOCKDATA =    (byte)0x77;
   27.97 +
   27.98 +    /**
   27.99 +     * End of optional block data blocks for an object.
  27.100 +     */
  27.101 +    final static byte TC_ENDBLOCKDATA = (byte)0x78;
  27.102 +
  27.103 +    /**
  27.104 +     * Reset stream context. All handles written into stream are reset.
  27.105 +     */
  27.106 +    final static byte TC_RESET =        (byte)0x79;
  27.107 +
  27.108 +    /**
  27.109 +     * long Block data. The long following the tag indicates the
  27.110 +     * number of bytes in this block data.
  27.111 +     */
  27.112 +    final static byte TC_BLOCKDATALONG= (byte)0x7A;
  27.113 +
  27.114 +    /**
  27.115 +     * Exception during write.
  27.116 +     */
  27.117 +    final static byte TC_EXCEPTION =    (byte)0x7B;
  27.118 +
  27.119 +    /**
  27.120 +     * Long string.
  27.121 +     */
  27.122 +    final static byte TC_LONGSTRING =   (byte)0x7C;
  27.123 +
  27.124 +    /**
  27.125 +     * new Proxy Class Descriptor.
  27.126 +     */
  27.127 +    final static byte TC_PROXYCLASSDESC =       (byte)0x7D;
  27.128 +
  27.129 +    /**
  27.130 +     * new Enum constant.
  27.131 +     * @since 1.5
  27.132 +     */
  27.133 +    final static byte TC_ENUM =         (byte)0x7E;
  27.134 +
  27.135 +    /**
  27.136 +     * Last tag value.
  27.137 +     */
  27.138 +    final static byte TC_MAX =          (byte)0x7E;
  27.139 +
  27.140 +    /**
  27.141 +     * First wire handle to be assigned.
  27.142 +     */
  27.143 +    final static int baseWireHandle = 0x7e0000;
  27.144 +
  27.145 +
  27.146 +    /******************************************************/
  27.147 +    /* Bit masks for ObjectStreamClass flag.*/
  27.148 +
  27.149 +    /**
  27.150 +     * Bit mask for ObjectStreamClass flag. Indicates a Serializable class
  27.151 +     * defines its own writeObject method.
  27.152 +     */
  27.153 +    final static byte SC_WRITE_METHOD = 0x01;
  27.154 +
  27.155 +    /**
  27.156 +     * Bit mask for ObjectStreamClass flag. Indicates Externalizable data
  27.157 +     * written in Block Data mode.
  27.158 +     * Added for PROTOCOL_VERSION_2.
  27.159 +     *
  27.160 +     * @see #PROTOCOL_VERSION_2
  27.161 +     * @since 1.2
  27.162 +     */
  27.163 +    final static byte SC_BLOCK_DATA = 0x08;
  27.164 +
  27.165 +    /**
  27.166 +     * Bit mask for ObjectStreamClass flag. Indicates class is Serializable.
  27.167 +     */
  27.168 +    final static byte SC_SERIALIZABLE = 0x02;
  27.169 +
  27.170 +    /**
  27.171 +     * Bit mask for ObjectStreamClass flag. Indicates class is Externalizable.
  27.172 +     */
  27.173 +    final static byte SC_EXTERNALIZABLE = 0x04;
  27.174 +
  27.175 +    /**
  27.176 +     * Bit mask for ObjectStreamClass flag. Indicates class is an enum type.
  27.177 +     * @since 1.5
  27.178 +     */
  27.179 +    final static byte SC_ENUM = 0x10;
  27.180 +
  27.181 +
  27.182 +    /* *******************************************************************/
  27.183 +    /* Security permissions */
  27.184 +
  27.185 +    /**
  27.186 +     * Enable substitution of one object for another during
  27.187 +     * serialization/deserialization.
  27.188 +     *
  27.189 +     * @see java.io.ObjectOutputStream#enableReplaceObject(boolean)
  27.190 +     * @see java.io.ObjectInputStream#enableResolveObject(boolean)
  27.191 +     * @since 1.2
  27.192 +     */
  27.193 +    final static SerializablePermission SUBSTITUTION_PERMISSION =
  27.194 +                           new SerializablePermission("enableSubstitution");
  27.195 +
  27.196 +    /**
  27.197 +     * Enable overriding of readObject and writeObject.
  27.198 +     *
  27.199 +     * @see java.io.ObjectOutputStream#writeObjectOverride(Object)
  27.200 +     * @see java.io.ObjectInputStream#readObjectOverride()
  27.201 +     * @since 1.2
  27.202 +     */
  27.203 +    final static SerializablePermission SUBCLASS_IMPLEMENTATION_PERMISSION =
  27.204 +                    new SerializablePermission("enableSubclassImplementation");
  27.205 +   /**
  27.206 +    * A Stream Protocol Version. <p>
  27.207 +    *
  27.208 +    * All externalizable data is written in JDK 1.1 external data
  27.209 +    * format after calling this method. This version is needed to write
  27.210 +    * streams containing Externalizable data that can be read by
  27.211 +    * pre-JDK 1.1.6 JVMs.
  27.212 +    *
  27.213 +    * @see java.io.ObjectOutputStream#useProtocolVersion(int)
  27.214 +    * @since 1.2
  27.215 +    */
  27.216 +    public final static int PROTOCOL_VERSION_1 = 1;
  27.217 +
  27.218 +
  27.219 +   /**
  27.220 +    * A Stream Protocol Version. <p>
  27.221 +    *
  27.222 +    * This protocol is written by JVM 1.2.
  27.223 +    *
  27.224 +    * Externalizable data is written in block data mode and is
  27.225 +    * terminated with TC_ENDBLOCKDATA. Externalizable classdescriptor
  27.226 +    * flags has SC_BLOCK_DATA enabled. JVM 1.1.6 and greater can
  27.227 +    * read this format change.
  27.228 +    *
  27.229 +    * Enables writing a nonSerializable class descriptor into the
  27.230 +    * stream. The serialVersionUID of a nonSerializable class is
  27.231 +    * set to 0L.
  27.232 +    *
  27.233 +    * @see java.io.ObjectOutputStream#useProtocolVersion(int)
  27.234 +    * @see #SC_BLOCK_DATA
  27.235 +    * @since 1.2
  27.236 +    */
  27.237 +    public final static int PROTOCOL_VERSION_2 = 2;
  27.238 +}
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/emul/compact/src/main/java/java/io/ObjectStreamException.java	Mon Jan 28 18:14:14 2013 +0100
    28.3 @@ -0,0 +1,53 @@
    28.4 +/*
    28.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
    28.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    28.7 + *
    28.8 + * This code is free software; you can redistribute it and/or modify it
    28.9 + * under the terms of the GNU General Public License version 2 only, as
   28.10 + * published by the Free Software Foundation.  Oracle designates this
   28.11 + * particular file as subject to the "Classpath" exception as provided
   28.12 + * by Oracle in the LICENSE file that accompanied this code.
   28.13 + *
   28.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   28.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   28.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   28.17 + * version 2 for more details (a copy is included in the LICENSE file that
   28.18 + * accompanied this code).
   28.19 + *
   28.20 + * You should have received a copy of the GNU General Public License version
   28.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   28.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   28.23 + *
   28.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   28.25 + * or visit www.oracle.com if you need additional information or have any
   28.26 + * questions.
   28.27 + */
   28.28 +
   28.29 +package java.io;
   28.30 +
   28.31 +/**
   28.32 + * Superclass of all exceptions specific to Object Stream classes.
   28.33 + *
   28.34 + * @author  unascribed
   28.35 + * @since   JDK1.1
   28.36 + */
   28.37 +public abstract class ObjectStreamException extends IOException {
   28.38 +
   28.39 +    private static final long serialVersionUID = 7260898174833392607L;
   28.40 +
   28.41 +    /**
   28.42 +     * Create an ObjectStreamException with the specified argument.
   28.43 +     *
   28.44 +     * @param classname the detailed message for the exception
   28.45 +     */
   28.46 +    protected ObjectStreamException(String classname) {
   28.47 +        super(classname);
   28.48 +    }
   28.49 +
   28.50 +    /**
   28.51 +     * Create an ObjectStreamException.
   28.52 +     */
   28.53 +    protected ObjectStreamException() {
   28.54 +        super();
   28.55 +    }
   28.56 +}
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/emul/compact/src/main/java/java/io/ObjectStreamField.java	Mon Jan 28 18:14:14 2013 +0100
    29.3 @@ -0,0 +1,314 @@
    29.4 +/*
    29.5 + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
    29.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    29.7 + *
    29.8 + * This code is free software; you can redistribute it and/or modify it
    29.9 + * under the terms of the GNU General Public License version 2 only, as
   29.10 + * published by the Free Software Foundation.  Oracle designates this
   29.11 + * particular file as subject to the "Classpath" exception as provided
   29.12 + * by Oracle in the LICENSE file that accompanied this code.
   29.13 + *
   29.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   29.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   29.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   29.17 + * version 2 for more details (a copy is included in the LICENSE file that
   29.18 + * accompanied this code).
   29.19 + *
   29.20 + * You should have received a copy of the GNU General Public License version
   29.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   29.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   29.23 + *
   29.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   29.25 + * or visit www.oracle.com if you need additional information or have any
   29.26 + * questions.
   29.27 + */
   29.28 +
   29.29 +package java.io;
   29.30 +
   29.31 +import java.lang.reflect.Field;
   29.32 +
   29.33 +/**
   29.34 + * A description of a Serializable field from a Serializable class.  An array
   29.35 + * of ObjectStreamFields is used to declare the Serializable fields of a class.
   29.36 + *
   29.37 + * @author      Mike Warres
   29.38 + * @author      Roger Riggs
   29.39 + * @see ObjectStreamClass
   29.40 + * @since 1.2
   29.41 + */
   29.42 +public class ObjectStreamField
   29.43 +    implements Comparable<Object>
   29.44 +{
   29.45 +
   29.46 +    /** field name */
   29.47 +    private final String name;
   29.48 +    /** canonical JVM signature of field type */
   29.49 +    private final String signature;
   29.50 +    /** field type (Object.class if unknown non-primitive type) */
   29.51 +    private final Class<?> type;
   29.52 +    /** whether or not to (de)serialize field values as unshared */
   29.53 +    private final boolean unshared;
   29.54 +    /** corresponding reflective field object, if any */
   29.55 +    private final Field field;
   29.56 +    /** offset of field value in enclosing field group */
   29.57 +    private int offset = 0;
   29.58 +
   29.59 +    /**
   29.60 +     * Create a Serializable field with the specified type.  This field should
   29.61 +     * be documented with a <code>serialField</code> tag.
   29.62 +     *
   29.63 +     * @param   name the name of the serializable field
   29.64 +     * @param   type the <code>Class</code> object of the serializable field
   29.65 +     */
   29.66 +    public ObjectStreamField(String name, Class<?> type) {
   29.67 +        this(name, type, false);
   29.68 +    }
   29.69 +
   29.70 +    /**
   29.71 +     * Creates an ObjectStreamField representing a serializable field with the
   29.72 +     * given name and type.  If unshared is false, values of the represented
   29.73 +     * field are serialized and deserialized in the default manner--if the
   29.74 +     * field is non-primitive, object values are serialized and deserialized as
   29.75 +     * if they had been written and read by calls to writeObject and
   29.76 +     * readObject.  If unshared is true, values of the represented field are
   29.77 +     * serialized and deserialized as if they had been written and read by
   29.78 +     * calls to writeUnshared and readUnshared.
   29.79 +     *
   29.80 +     * @param   name field name
   29.81 +     * @param   type field type
   29.82 +     * @param   unshared if false, write/read field values in the same manner
   29.83 +     *          as writeObject/readObject; if true, write/read in the same
   29.84 +     *          manner as writeUnshared/readUnshared
   29.85 +     * @since   1.4
   29.86 +     */
   29.87 +    public ObjectStreamField(String name, Class<?> type, boolean unshared) {
   29.88 +        if (name == null) {
   29.89 +            throw new NullPointerException();
   29.90 +        }
   29.91 +        this.name = name;
   29.92 +        this.type = type;
   29.93 +        this.unshared = unshared;
   29.94 +        signature = getClassSignature(type).intern();
   29.95 +        field = null;
   29.96 +    }
   29.97 +
   29.98 +    /**
   29.99 +     * Creates an ObjectStreamField representing a field with the given name,
  29.100 +     * signature and unshared setting.
  29.101 +     */
  29.102 +    ObjectStreamField(String name, String signature, boolean unshared) {
  29.103 +        if (name == null) {
  29.104 +            throw new NullPointerException();
  29.105 +        }
  29.106 +        this.name = name;
  29.107 +        this.signature = signature.intern();
  29.108 +        this.unshared = unshared;
  29.109 +        field = null;
  29.110 +
  29.111 +        switch (signature.charAt(0)) {
  29.112 +            case 'Z': type = Boolean.TYPE; break;
  29.113 +            case 'B': type = Byte.TYPE; break;
  29.114 +            case 'C': type = Character.TYPE; break;
  29.115 +            case 'S': type = Short.TYPE; break;
  29.116 +            case 'I': type = Integer.TYPE; break;
  29.117 +            case 'J': type = Long.TYPE; break;
  29.118 +            case 'F': type = Float.TYPE; break;
  29.119 +            case 'D': type = Double.TYPE; break;
  29.120 +            case 'L':
  29.121 +            case '[': type = Object.class; break;
  29.122 +            default: throw new IllegalArgumentException("illegal signature");
  29.123 +        }
  29.124 +    }
  29.125 +
  29.126 +    /**
  29.127 +     * Creates an ObjectStreamField representing the given field with the
  29.128 +     * specified unshared setting.  For compatibility with the behavior of
  29.129 +     * earlier serialization implementations, a "showType" parameter is
  29.130 +     * necessary to govern whether or not a getType() call on this
  29.131 +     * ObjectStreamField (if non-primitive) will return Object.class (as
  29.132 +     * opposed to a more specific reference type).
  29.133 +     */
  29.134 +    ObjectStreamField(Field field, boolean unshared, boolean showType) {
  29.135 +        this.field = field;
  29.136 +        this.unshared = unshared;
  29.137 +        name = field.getName();
  29.138 +        Class<?> ftype = field.getType();
  29.139 +        type = (showType || ftype.isPrimitive()) ? ftype : Object.class;
  29.140 +        signature = getClassSignature(ftype).intern();
  29.141 +    }
  29.142 +
  29.143 +    /**
  29.144 +     * Get the name of this field.
  29.145 +     *
  29.146 +     * @return  a <code>String</code> representing the name of the serializable
  29.147 +     *          field
  29.148 +     */
  29.149 +    public String getName() {
  29.150 +        return name;
  29.151 +    }
  29.152 +
  29.153 +    /**
  29.154 +     * Get the type of the field.  If the type is non-primitive and this
  29.155 +     * <code>ObjectStreamField</code> was obtained from a deserialized {@link
  29.156 +     * ObjectStreamClass} instance, then <code>Object.class</code> is returned.
  29.157 +     * Otherwise, the <code>Class</code> object for the type of the field is
  29.158 +     * returned.
  29.159 +     *
  29.160 +     * @return  a <code>Class</code> object representing the type of the
  29.161 +     *          serializable field
  29.162 +     */
  29.163 +    public Class<?> getType() {
  29.164 +        return type;
  29.165 +    }
  29.166 +
  29.167 +    /**
  29.168 +     * Returns character encoding of field type.  The encoding is as follows:
  29.169 +     * <blockquote><pre>
  29.170 +     * B            byte
  29.171 +     * C            char
  29.172 +     * D            double
  29.173 +     * F            float
  29.174 +     * I            int
  29.175 +     * J            long
  29.176 +     * L            class or interface
  29.177 +     * S            short
  29.178 +     * Z            boolean
  29.179 +     * [            array
  29.180 +     * </pre></blockquote>
  29.181 +     *
  29.182 +     * @return  the typecode of the serializable field
  29.183 +     */
  29.184 +    // REMIND: deprecate?
  29.185 +    public char getTypeCode() {
  29.186 +        return signature.charAt(0);
  29.187 +    }
  29.188 +
  29.189 +    /**
  29.190 +     * Return the JVM type signature.
  29.191 +     *
  29.192 +     * @return  null if this field has a primitive type.
  29.193 +     */
  29.194 +    // REMIND: deprecate?
  29.195 +    public String getTypeString() {
  29.196 +        return isPrimitive() ? null : signature;
  29.197 +    }
  29.198 +
  29.199 +    /**
  29.200 +     * Offset of field within instance data.
  29.201 +     *
  29.202 +     * @return  the offset of this field
  29.203 +     * @see #setOffset
  29.204 +     */
  29.205 +    // REMIND: deprecate?
  29.206 +    public int getOffset() {
  29.207 +        return offset;
  29.208 +    }
  29.209 +
  29.210 +    /**
  29.211 +     * Offset within instance data.
  29.212 +     *
  29.213 +     * @param   offset the offset of the field
  29.214 +     * @see #getOffset
  29.215 +     */
  29.216 +    // REMIND: deprecate?
  29.217 +    protected void setOffset(int offset) {
  29.218 +        this.offset = offset;
  29.219 +    }
  29.220 +
  29.221 +    /**
  29.222 +     * Return true if this field has a primitive type.
  29.223 +     *
  29.224 +     * @return  true if and only if this field corresponds to a primitive type
  29.225 +     */
  29.226 +    // REMIND: deprecate?
  29.227 +    public boolean isPrimitive() {
  29.228 +        char tcode = signature.charAt(0);
  29.229 +        return ((tcode != 'L') && (tcode != '['));
  29.230 +    }
  29.231 +
  29.232 +    /**
  29.233 +     * Returns boolean value indicating whether or not the serializable field
  29.234 +     * represented by this ObjectStreamField instance is unshared.
  29.235 +     *
  29.236 +     * @since 1.4
  29.237 +     */
  29.238 +    public boolean isUnshared() {
  29.239 +        return unshared;
  29.240 +    }
  29.241 +
  29.242 +    /**
  29.243 +     * Compare this field with another <code>ObjectStreamField</code>.  Return
  29.244 +     * -1 if this is smaller, 0 if equal, 1 if greater.  Types that are
  29.245 +     * primitives are "smaller" than object types.  If equal, the field names
  29.246 +     * are compared.
  29.247 +     */
  29.248 +    // REMIND: deprecate?
  29.249 +    public int compareTo(Object obj) {
  29.250 +        ObjectStreamField other = (ObjectStreamField) obj;
  29.251 +        boolean isPrim = isPrimitive();
  29.252 +        if (isPrim != other.isPrimitive()) {
  29.253 +            return isPrim ? -1 : 1;
  29.254 +        }
  29.255 +        return name.compareTo(other.name);
  29.256 +    }
  29.257 +
  29.258 +    /**
  29.259 +     * Return a string that describes this field.
  29.260 +     */
  29.261 +    public String toString() {
  29.262 +        return signature + ' ' + name;
  29.263 +    }
  29.264 +
  29.265 +    /**
  29.266 +     * Returns field represented by this ObjectStreamField, or null if
  29.267 +     * ObjectStreamField is not associated with an actual field.
  29.268 +     */
  29.269 +    Field getField() {
  29.270 +        return field;
  29.271 +    }
  29.272 +
  29.273 +    /**
  29.274 +     * Returns JVM type signature of field (similar to getTypeString, except
  29.275 +     * that signature strings are returned for primitive fields as well).
  29.276 +     */
  29.277 +    String getSignature() {
  29.278 +        return signature;
  29.279 +    }
  29.280 +
  29.281 +    /**
  29.282 +     * Returns JVM type signature for given class.
  29.283 +     */
  29.284 +    private static String getClassSignature(Class<?> cl) {
  29.285 +        StringBuilder sbuf = new StringBuilder();
  29.286 +        while (cl.isArray()) {
  29.287 +            sbuf.append('[');
  29.288 +            cl = cl.getComponentType();
  29.289 +        }
  29.290 +        if (cl.isPrimitive()) {
  29.291 +            if (cl == Integer.TYPE) {
  29.292 +                sbuf.append('I');
  29.293 +            } else if (cl == Byte.TYPE) {
  29.294 +                sbuf.append('B');
  29.295 +            } else if (cl == Long.TYPE) {
  29.296 +                sbuf.append('J');
  29.297 +            } else if (cl == Float.TYPE) {
  29.298 +                sbuf.append('F');
  29.299 +            } else if (cl == Double.TYPE) {
  29.300 +                sbuf.append('D');
  29.301 +            } else if (cl == Short.TYPE) {
  29.302 +                sbuf.append('S');
  29.303 +            } else if (cl == Character.TYPE) {
  29.304 +                sbuf.append('C');
  29.305 +            } else if (cl == Boolean.TYPE) {
  29.306 +                sbuf.append('Z');
  29.307 +            } else if (cl == Void.TYPE) {
  29.308 +                sbuf.append('V');
  29.309 +            } else {
  29.310 +                throw new InternalError();
  29.311 +            }
  29.312 +        } else {
  29.313 +            sbuf.append('L' + cl.getName().replace('.', '/') + ';');
  29.314 +        }
  29.315 +        return sbuf.toString();
  29.316 +    }
  29.317 +}
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/emul/compact/src/main/java/java/io/OptionalDataException.java	Mon Jan 28 18:14:14 2013 +0100
    30.3 @@ -0,0 +1,83 @@
    30.4 +/*
    30.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
    30.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    30.7 + *
    30.8 + * This code is free software; you can redistribute it and/or modify it
    30.9 + * under the terms of the GNU General Public License version 2 only, as
   30.10 + * published by the Free Software Foundation.  Oracle designates this
   30.11 + * particular file as subject to the "Classpath" exception as provided
   30.12 + * by Oracle in the LICENSE file that accompanied this code.
   30.13 + *
   30.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   30.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   30.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   30.17 + * version 2 for more details (a copy is included in the LICENSE file that
   30.18 + * accompanied this code).
   30.19 + *
   30.20 + * You should have received a copy of the GNU General Public License version
   30.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   30.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   30.23 + *
   30.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   30.25 + * or visit www.oracle.com if you need additional information or have any
   30.26 + * questions.
   30.27 + */
   30.28 +package java.io;
   30.29 +
   30.30 +/**
   30.31 + * Exception indicating the failure of an object read operation due to
   30.32 + * unread primitive data, or the end of data belonging to a serialized
   30.33 + * object in the stream.  This exception may be thrown in two cases:
   30.34 + *
   30.35 + * <ul>
   30.36 + *   <li>An attempt was made to read an object when the next element in the
   30.37 + *       stream is primitive data.  In this case, the OptionalDataException's
   30.38 + *       length field is set to the number of bytes of primitive data
   30.39 + *       immediately readable from the stream, and the eof field is set to
   30.40 + *       false.
   30.41 + *
   30.42 + *   <li>An attempt was made to read past the end of data consumable by a
   30.43 + *       class-defined readObject or readExternal method.  In this case, the
   30.44 + *       OptionalDataException's eof field is set to true, and the length field
   30.45 + *       is set to 0.
   30.46 + * </ul>
   30.47 + *
   30.48 + * @author  unascribed
   30.49 + * @since   JDK1.1
   30.50 + */
   30.51 +public class OptionalDataException extends ObjectStreamException {
   30.52 +
   30.53 +    private static final long serialVersionUID = -8011121865681257820L;
   30.54 +
   30.55 +    /*
   30.56 +     * Create an <code>OptionalDataException</code> with a length.
   30.57 +     */
   30.58 +    OptionalDataException(int len) {
   30.59 +        eof = false;
   30.60 +        length = len;
   30.61 +    }
   30.62 +
   30.63 +    /*
   30.64 +     * Create an <code>OptionalDataException</code> signifying no
   30.65 +     * more primitive data is available.
   30.66 +     */
   30.67 +    OptionalDataException(boolean end) {
   30.68 +        length = 0;
   30.69 +        eof = end;
   30.70 +    }
   30.71 +
   30.72 +    /**
   30.73 +     * The number of bytes of primitive data available to be read
   30.74 +     * in the current buffer.
   30.75 +     *
   30.76 +     * @serial
   30.77 +     */
   30.78 +    public int length;
   30.79 +
   30.80 +    /**
   30.81 +     * True if there is no more data in the buffered part of the stream.
   30.82 +     *
   30.83 +     * @serial
   30.84 +     */
   30.85 +    public boolean eof;
   30.86 +}
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/emul/compact/src/main/java/java/io/OutputStream.java	Mon Jan 28 18:14:14 2013 +0100
    31.3 @@ -0,0 +1,154 @@
    31.4 +/*
    31.5 + * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.
    31.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    31.7 + *
    31.8 + * This code is free software; you can redistribute it and/or modify it
    31.9 + * under the terms of the GNU General Public License version 2 only, as
   31.10 + * published by the Free Software Foundation.  Oracle designates this
   31.11 + * particular file as subject to the "Classpath" exception as provided
   31.12 + * by Oracle in the LICENSE file that accompanied this code.
   31.13 + *
   31.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   31.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   31.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   31.17 + * version 2 for more details (a copy is included in the LICENSE file that
   31.18 + * accompanied this code).
   31.19 + *
   31.20 + * You should have received a copy of the GNU General Public License version
   31.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   31.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   31.23 + *
   31.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   31.25 + * or visit www.oracle.com if you need additional information or have any
   31.26 + * questions.
   31.27 + */
   31.28 +
   31.29 +package java.io;
   31.30 +
   31.31 +/**
   31.32 + * This abstract class is the superclass of all classes representing
   31.33 + * an output stream of bytes. An output stream accepts output bytes
   31.34 + * and sends them to some sink.
   31.35 + * <p>
   31.36 + * Applications that need to define a subclass of
   31.37 + * <code>OutputStream</code> must always provide at least a method
   31.38 + * that writes one byte of output.
   31.39 + *
   31.40 + * @author  Arthur van Hoff
   31.41 + * @see     java.io.BufferedOutputStream
   31.42 + * @see     java.io.ByteArrayOutputStream
   31.43 + * @see     java.io.DataOutputStream
   31.44 + * @see     java.io.FilterOutputStream
   31.45 + * @see     java.io.InputStream
   31.46 + * @see     java.io.OutputStream#write(int)
   31.47 + * @since   JDK1.0
   31.48 + */
   31.49 +public abstract class OutputStream implements Closeable, Flushable {
   31.50 +    /**
   31.51 +     * Writes the specified byte to this output stream. The general
   31.52 +     * contract for <code>write</code> is that one byte is written
   31.53 +     * to the output stream. The byte to be written is the eight
   31.54 +     * low-order bits of the argument <code>b</code>. The 24
   31.55 +     * high-order bits of <code>b</code> are ignored.
   31.56 +     * <p>
   31.57 +     * Subclasses of <code>OutputStream</code> must provide an
   31.58 +     * implementation for this method.
   31.59 +     *
   31.60 +     * @param      b   the <code>byte</code>.
   31.61 +     * @exception  IOException  if an I/O error occurs. In particular,
   31.62 +     *             an <code>IOException</code> may be thrown if the
   31.63 +     *             output stream has been closed.
   31.64 +     */
   31.65 +    public abstract void write(int b) throws IOException;
   31.66 +
   31.67 +    /**
   31.68 +     * Writes <code>b.length</code> bytes from the specified byte array
   31.69 +     * to this output stream. The general contract for <code>write(b)</code>
   31.70 +     * is that it should have exactly the same effect as the call
   31.71 +     * <code>write(b, 0, b.length)</code>.
   31.72 +     *
   31.73 +     * @param      b   the data.
   31.74 +     * @exception  IOException  if an I/O error occurs.
   31.75 +     * @see        java.io.OutputStream#write(byte[], int, int)
   31.76 +     */
   31.77 +    public void write(byte b[]) throws IOException {
   31.78 +        write(b, 0, b.length);
   31.79 +    }
   31.80 +
   31.81 +    /**
   31.82 +     * Writes <code>len</code> bytes from the specified byte array
   31.83 +     * starting at offset <code>off</code> to this output stream.
   31.84 +     * The general contract for <code>write(b, off, len)</code> is that
   31.85 +     * some of the bytes in the array <code>b</code> are written to the
   31.86 +     * output stream in order; element <code>b[off]</code> is the first
   31.87 +     * byte written and <code>b[off+len-1]</code> is the last byte written
   31.88 +     * by this operation.
   31.89 +     * <p>
   31.90 +     * The <code>write</code> method of <code>OutputStream</code> calls
   31.91 +     * the write method of one argument on each of the bytes to be
   31.92 +     * written out. Subclasses are encouraged to override this method and
   31.93 +     * provide a more efficient implementation.
   31.94 +     * <p>
   31.95 +     * If <code>b</code> is <code>null</code>, a
   31.96 +     * <code>NullPointerException</code> is thrown.
   31.97 +     * <p>
   31.98 +     * If <code>off</code> is negative, or <code>len</code> is negative, or
   31.99 +     * <code>off+len</code> is greater than the length of the array
  31.100 +     * <code>b</code>, then an <tt>IndexOutOfBoundsException</tt> is thrown.
  31.101 +     *
  31.102 +     * @param      b     the data.
  31.103 +     * @param      off   the start offset in the data.
  31.104 +     * @param      len   the number of bytes to write.
  31.105 +     * @exception  IOException  if an I/O error occurs. In particular,
  31.106 +     *             an <code>IOException</code> is thrown if the output
  31.107 +     *             stream is closed.
  31.108 +     */
  31.109 +    public void write(byte b[], int off, int len) throws IOException {
  31.110 +        if (b == null) {
  31.111 +            throw new NullPointerException();
  31.112 +        } else if ((off < 0) || (off > b.length) || (len < 0) ||
  31.113 +                   ((off + len) > b.length) || ((off + len) < 0)) {
  31.114 +            throw new IndexOutOfBoundsException();
  31.115 +        } else if (len == 0) {
  31.116 +            return;
  31.117 +        }
  31.118 +        for (int i = 0 ; i < len ; i++) {
  31.119 +            write(b[off + i]);
  31.120 +        }
  31.121 +    }
  31.122 +
  31.123 +    /**
  31.124 +     * Flushes this output stream and forces any buffered output bytes
  31.125 +     * to be written out. The general contract of <code>flush</code> is
  31.126 +     * that calling it is an indication that, if any bytes previously
  31.127 +     * written have been buffered by the implementation of the output
  31.128 +     * stream, such bytes should immediately be written to their
  31.129 +     * intended destination.
  31.130 +     * <p>
  31.131 +     * If the intended destination of this stream is an abstraction provided by
  31.132 +     * the underlying operating system, for example a file, then flushing the
  31.133 +     * stream guarantees only that bytes previously written to the stream are
  31.134 +     * passed to the operating system for writing; it does not guarantee that
  31.135 +     * they are actually written to a physical device such as a disk drive.
  31.136 +     * <p>
  31.137 +     * The <code>flush</code> method of <code>OutputStream</code> does nothing.
  31.138 +     *
  31.139 +     * @exception  IOException  if an I/O error occurs.
  31.140 +     */
  31.141 +    public void flush() throws IOException {
  31.142 +    }
  31.143 +
  31.144 +    /**
  31.145 +     * Closes this output stream and releases any system resources
  31.146 +     * associated with this stream. The general contract of <code>close</code>
  31.147 +     * is that it closes the output stream. A closed stream cannot perform
  31.148 +     * output operations and cannot be reopened.
  31.149 +     * <p>
  31.150 +     * The <code>close</code> method of <code>OutputStream</code> does nothing.
  31.151 +     *
  31.152 +     * @exception  IOException  if an I/O error occurs.
  31.153 +     */
  31.154 +    public void close() throws IOException {
  31.155 +    }
  31.156 +
  31.157 +}
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/emul/compact/src/main/java/java/io/StreamCorruptedException.java	Mon Jan 28 18:14:14 2013 +0100
    32.3 @@ -0,0 +1,54 @@
    32.4 +/*
    32.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
    32.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    32.7 + *
    32.8 + * This code is free software; you can redistribute it and/or modify it
    32.9 + * under the terms of the GNU General Public License version 2 only, as
   32.10 + * published by the Free Software Foundation.  Oracle designates this
   32.11 + * particular file as subject to the "Classpath" exception as provided
   32.12 + * by Oracle in the LICENSE file that accompanied this code.
   32.13 + *
   32.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   32.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   32.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   32.17 + * version 2 for more details (a copy is included in the LICENSE file that
   32.18 + * accompanied this code).
   32.19 + *
   32.20 + * You should have received a copy of the GNU General Public License version
   32.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   32.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   32.23 + *
   32.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   32.25 + * or visit www.oracle.com if you need additional information or have any
   32.26 + * questions.
   32.27 + */
   32.28 +
   32.29 +package java.io;
   32.30 +
   32.31 +/**
   32.32 + * Thrown when control information that was read from an object stream
   32.33 + * violates internal consistency checks.
   32.34 + *
   32.35 + * @author  unascribed
   32.36 + * @since   JDK1.1
   32.37 + */
   32.38 +public class StreamCorruptedException extends ObjectStreamException {
   32.39 +
   32.40 +    private static final long serialVersionUID = 8983558202217591746L;
   32.41 +
   32.42 +    /**
   32.43 +     * Create a StreamCorruptedException and list a reason why thrown.
   32.44 +     *
   32.45 +     * @param reason  String describing the reason for the exception.
   32.46 +     */
   32.47 +    public StreamCorruptedException(String reason) {
   32.48 +        super(reason);
   32.49 +    }
   32.50 +
   32.51 +    /**
   32.52 +     * Create a StreamCorruptedException and list no reason why thrown.
   32.53 +     */
   32.54 +    public StreamCorruptedException() {
   32.55 +        super();
   32.56 +    }
   32.57 +}
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/emul/compact/src/main/java/java/io/WriteAbortedException.java	Mon Jan 28 18:14:14 2013 +0100
    33.3 @@ -0,0 +1,93 @@
    33.4 +/*
    33.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
    33.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    33.7 + *
    33.8 + * This code is free software; you can redistribute it and/or modify it
    33.9 + * under the terms of the GNU General Public License version 2 only, as
   33.10 + * published by the Free Software Foundation.  Oracle designates this
   33.11 + * particular file as subject to the "Classpath" exception as provided
   33.12 + * by Oracle in the LICENSE file that accompanied this code.
   33.13 + *
   33.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   33.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   33.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   33.17 + * version 2 for more details (a copy is included in the LICENSE file that
   33.18 + * accompanied this code).
   33.19 + *
   33.20 + * You should have received a copy of the GNU General Public License version
   33.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   33.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   33.23 + *
   33.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   33.25 + * or visit www.oracle.com if you need additional information or have any
   33.26 + * questions.
   33.27 + */
   33.28 +
   33.29 +package java.io;
   33.30 +
   33.31 +/**
   33.32 + * Signals that one of the ObjectStreamExceptions was thrown during a
   33.33 + * write operation.  Thrown during a read operation when one of the
   33.34 + * ObjectStreamExceptions was thrown during a write operation.  The
   33.35 + * exception that terminated the write can be found in the detail
   33.36 + * field. The stream is reset to it's initial state and all references
   33.37 + * to objects already deserialized are discarded.
   33.38 + *
   33.39 + * <p>As of release 1.4, this exception has been retrofitted to conform to
   33.40 + * the general purpose exception-chaining mechanism.  The "exception causing
   33.41 + * the abort" that is provided at construction time and
   33.42 + * accessed via the public {@link #detail} field is now known as the
   33.43 + * <i>cause</i>, and may be accessed via the {@link Throwable#getCause()}
   33.44 + * method, as well as the aforementioned "legacy field."
   33.45 + *
   33.46 + * @author  unascribed
   33.47 + * @since   JDK1.1
   33.48 + */
   33.49 +public class WriteAbortedException extends ObjectStreamException {
   33.50 +    private static final long serialVersionUID = -3326426625597282442L;
   33.51 +
   33.52 +    /**
   33.53 +     * Exception that was caught while writing the ObjectStream.
   33.54 +     *
   33.55 +     * <p>This field predates the general-purpose exception chaining facility.
   33.56 +     * The {@link Throwable#getCause()} method is now the preferred means of
   33.57 +     * obtaining this information.
   33.58 +     *
   33.59 +     * @serial
   33.60 +     */
   33.61 +    public Exception detail;
   33.62 +
   33.63 +    /**
   33.64 +     * Constructs a WriteAbortedException with a string describing
   33.65 +     * the exception and the exception causing the abort.
   33.66 +     * @param s   String describing the exception.
   33.67 +     * @param ex  Exception causing the abort.
   33.68 +     */
   33.69 +    public WriteAbortedException(String s, Exception ex) {
   33.70 +        super(s);
   33.71 +        initCause(null);  // Disallow subsequent initCause
   33.72 +        detail = ex;
   33.73 +    }
   33.74 +
   33.75 +    /**
   33.76 +     * Produce the message and include the message from the nested
   33.77 +     * exception, if there is one.
   33.78 +     */
   33.79 +    public String getMessage() {
   33.80 +        if (detail == null)
   33.81 +            return super.getMessage();
   33.82 +        else
   33.83 +            return super.getMessage() + "; " + detail.toString();
   33.84 +    }
   33.85 +
   33.86 +    /**
   33.87 +     * Returns the exception that terminated the operation (the <i>cause</i>).
   33.88 +     *
   33.89 +     * @return  the exception that terminated the operation (the <i>cause</i>),
   33.90 +     *          which may be null.
   33.91 +     * @since   1.4
   33.92 +     */
   33.93 +    public Throwable getCause() {
   33.94 +        return detail;
   33.95 +    }
   33.96 +}
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/emul/compact/src/main/java/java/lang/ref/PhantomReference.java	Mon Jan 28 18:14:14 2013 +0100
    34.3 @@ -0,0 +1,83 @@
    34.4 +/*
    34.5 + * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
    34.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    34.7 + *
    34.8 + * This code is free software; you can redistribute it and/or modify it
    34.9 + * under the terms of the GNU General Public License version 2 only, as
   34.10 + * published by the Free Software Foundation.  Oracle designates this
   34.11 + * particular file as subject to the "Classpath" exception as provided
   34.12 + * by Oracle in the LICENSE file that accompanied this code.
   34.13 + *
   34.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   34.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   34.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   34.17 + * version 2 for more details (a copy is included in the LICENSE file that
   34.18 + * accompanied this code).
   34.19 + *
   34.20 + * You should have received a copy of the GNU General Public License version
   34.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   34.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   34.23 + *
   34.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   34.25 + * or visit www.oracle.com if you need additional information or have any
   34.26 + * questions.
   34.27 + */
   34.28 +
   34.29 +package java.lang.ref;
   34.30 +
   34.31 +
   34.32 +/**
   34.33 + * Phantom reference objects, which are enqueued after the collector
   34.34 + * determines that their referents may otherwise be reclaimed.  Phantom
   34.35 + * references are most often used for scheduling pre-mortem cleanup actions in
   34.36 + * a more flexible way than is possible with the Java finalization mechanism.
   34.37 + *
   34.38 + * <p> If the garbage collector determines at a certain point in time that the
   34.39 + * referent of a phantom reference is <a
   34.40 + * href="package-summary.html#reachability">phantom reachable</a>, then at that
   34.41 + * time or at some later time it will enqueue the reference.
   34.42 + *
   34.43 + * <p> In order to ensure that a reclaimable object remains so, the referent of
   34.44 + * a phantom reference may not be retrieved: The <code>get</code> method of a
   34.45 + * phantom reference always returns <code>null</code>.
   34.46 + *
   34.47 + * <p> Unlike soft and weak references, phantom references are not
   34.48 + * automatically cleared by the garbage collector as they are enqueued.  An
   34.49 + * object that is reachable via phantom references will remain so until all
   34.50 + * such references are cleared or themselves become unreachable.
   34.51 + *
   34.52 + * @author   Mark Reinhold
   34.53 + * @since    1.2
   34.54 + */
   34.55 +
   34.56 +public class PhantomReference<T> extends Reference<T> {
   34.57 +
   34.58 +    /**
   34.59 +     * Returns this reference object's referent.  Because the referent of a
   34.60 +     * phantom reference is always inaccessible, this method always returns
   34.61 +     * <code>null</code>.
   34.62 +     *
   34.63 +     * @return  <code>null</code>
   34.64 +     */
   34.65 +    public T get() {
   34.66 +        return null;
   34.67 +    }
   34.68 +
   34.69 +    /**
   34.70 +     * Creates a new phantom reference that refers to the given object and
   34.71 +     * is registered with the given queue.
   34.72 +     *
   34.73 +     * <p> It is possible to create a phantom reference with a <tt>null</tt>
   34.74 +     * queue, but such a reference is completely useless: Its <tt>get</tt>
   34.75 +     * method will always return null and, since it does not have a queue, it
   34.76 +     * will never be enqueued.
   34.77 +     *
   34.78 +     * @param referent the object the new phantom reference will refer to
   34.79 +     * @param q the queue with which the reference is to be registered,
   34.80 +     *          or <tt>null</tt> if registration is not required
   34.81 +     */
   34.82 +    public PhantomReference(T referent, ReferenceQueue<? super T> q) {
   34.83 +        super(referent, q);
   34.84 +    }
   34.85 +
   34.86 +}
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/emul/compact/src/main/java/java/lang/ref/Reference.java	Mon Jan 28 18:14:14 2013 +0100
    35.3 @@ -0,0 +1,238 @@
    35.4 +/*
    35.5 + * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
    35.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    35.7 + *
    35.8 + * This code is free software; you can redistribute it and/or modify it
    35.9 + * under the terms of the GNU General Public License version 2 only, as
   35.10 + * published by the Free Software Foundation.  Oracle designates this
   35.11 + * particular file as subject to the "Classpath" exception as provided
   35.12 + * by Oracle in the LICENSE file that accompanied this code.
   35.13 + *
   35.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   35.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   35.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   35.17 + * version 2 for more details (a copy is included in the LICENSE file that
   35.18 + * accompanied this code).
   35.19 + *
   35.20 + * You should have received a copy of the GNU General Public License version
   35.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   35.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   35.23 + *
   35.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   35.25 + * or visit www.oracle.com if you need additional information or have any
   35.26 + * questions.
   35.27 + */
   35.28 +
   35.29 +package java.lang.ref;
   35.30 +
   35.31 +import sun.misc.Cleaner;
   35.32 +
   35.33 +
   35.34 +/**
   35.35 + * Abstract base class for reference objects.  This class defines the
   35.36 + * operations common to all reference objects.  Because reference objects are
   35.37 + * implemented in close cooperation with the garbage collector, this class may
   35.38 + * not be subclassed directly.
   35.39 + *
   35.40 + * @author   Mark Reinhold
   35.41 + * @since    1.2
   35.42 + */
   35.43 +
   35.44 +public abstract class Reference<T> {
   35.45 +
   35.46 +    /* A Reference instance is in one of four possible internal states:
   35.47 +     *
   35.48 +     *     Active: Subject to special treatment by the garbage collector.  Some
   35.49 +     *     time after the collector detects that the reachability of the
   35.50 +     *     referent has changed to the appropriate state, it changes the
   35.51 +     *     instance's state to either Pending or Inactive, depending upon
   35.52 +     *     whether or not the instance was registered with a queue when it was
   35.53 +     *     created.  In the former case it also adds the instance to the
   35.54 +     *     pending-Reference list.  Newly-created instances are Active.
   35.55 +     *
   35.56 +     *     Pending: An element of the pending-Reference list, waiting to be
   35.57 +     *     enqueued by the Reference-handler thread.  Unregistered instances
   35.58 +     *     are never in this state.
   35.59 +     *
   35.60 +     *     Enqueued: An element of the queue with which the instance was
   35.61 +     *     registered when it was created.  When an instance is removed from
   35.62 +     *     its ReferenceQueue, it is made Inactive.  Unregistered instances are
   35.63 +     *     never in this state.
   35.64 +     *
   35.65 +     *     Inactive: Nothing more to do.  Once an instance becomes Inactive its
   35.66 +     *     state will never change again.
   35.67 +     *
   35.68 +     * The state is encoded in the queue and next fields as follows:
   35.69 +     *
   35.70 +     *     Active: queue = ReferenceQueue with which instance is registered, or
   35.71 +     *     ReferenceQueue.NULL if it was not registered with a queue; next =
   35.72 +     *     null.
   35.73 +     *
   35.74 +     *     Pending: queue = ReferenceQueue with which instance is registered;
   35.75 +     *     next = Following instance in queue, or this if at end of list.
   35.76 +     *
   35.77 +     *     Enqueued: queue = ReferenceQueue.ENQUEUED; next = Following instance
   35.78 +     *     in queue, or this if at end of list.
   35.79 +     *
   35.80 +     *     Inactive: queue = ReferenceQueue.NULL; next = this.
   35.81 +     *
   35.82 +     * With this scheme the collector need only examine the next field in order
   35.83 +     * to determine whether a Reference instance requires special treatment: If
   35.84 +     * the next field is null then the instance is active; if it is non-null,
   35.85 +     * then the collector should treat the instance normally.
   35.86 +     *
   35.87 +     * To ensure that concurrent collector can discover active Reference
   35.88 +     * objects without interfering with application threads that may apply
   35.89 +     * the enqueue() method to those objects, collectors should link
   35.90 +     * discovered objects through the discovered field.
   35.91 +     */
   35.92 +
   35.93 +    private T referent;         /* Treated specially by GC */
   35.94 +
   35.95 +    ReferenceQueue<? super T> queue;
   35.96 +
   35.97 +    Reference next;
   35.98 +    transient private Reference<T> discovered;  /* used by VM */
   35.99 +
  35.100 +
  35.101 +    /* Object used to synchronize with the garbage collector.  The collector
  35.102 +     * must acquire this lock at the beginning of each collection cycle.  It is
  35.103 +     * therefore critical that any code holding this lock complete as quickly
  35.104 +     * as possible, allocate no new objects, and avoid calling user code.
  35.105 +     */
  35.106 +    static private class Lock { };
  35.107 +    private static Lock lock = new Lock();
  35.108 +
  35.109 +
  35.110 +    /* List of References waiting to be enqueued.  The collector adds
  35.111 +     * References to this list, while the Reference-handler thread removes
  35.112 +     * them.  This list is protected by the above lock object.
  35.113 +     */
  35.114 +    private static Reference pending = null;
  35.115 +
  35.116 +    /* High-priority thread to enqueue pending References
  35.117 +     */
  35.118 +    private static class ReferenceHandler extends Thread {
  35.119 +
  35.120 +        ReferenceHandler(ThreadGroup g, String name) {
  35.121 +            super(g, name);
  35.122 +        }
  35.123 +
  35.124 +        public void run() {
  35.125 +            for (;;) {
  35.126 +
  35.127 +                Reference r;
  35.128 +                synchronized (lock) {
  35.129 +                    if (pending != null) {
  35.130 +                        r = pending;
  35.131 +                        Reference rn = r.next;
  35.132 +                        pending = (rn == r) ? null : rn;
  35.133 +                        r.next = r;
  35.134 +                    } else {
  35.135 +                        try {
  35.136 +                            lock.wait();
  35.137 +                        } catch (InterruptedException x) { }
  35.138 +                        continue;
  35.139 +                    }
  35.140 +                }
  35.141 +
  35.142 +                // Fast path for cleaners
  35.143 +                if (r instanceof Cleaner) {
  35.144 +                    ((Cleaner)r).clean();
  35.145 +                    continue;
  35.146 +                }
  35.147 +
  35.148 +                ReferenceQueue q = r.queue;
  35.149 +                if (q != ReferenceQueue.NULL) q.enqueue(r);
  35.150 +            }
  35.151 +        }
  35.152 +    }
  35.153 +
  35.154 +    static {
  35.155 +        ThreadGroup tg = Thread.currentThread().getThreadGroup();
  35.156 +        for (ThreadGroup tgn = tg;
  35.157 +             tgn != null;
  35.158 +             tg = tgn, tgn = tg.getParent());
  35.159 +        Thread handler = new ReferenceHandler(tg, "Reference Handler");
  35.160 +        /* If there were a special system-only priority greater than
  35.161 +         * MAX_PRIORITY, it would be used here
  35.162 +         */
  35.163 +        handler.setPriority(Thread.MAX_PRIORITY);
  35.164 +        handler.setDaemon(true);
  35.165 +        handler.start();
  35.166 +    }
  35.167 +
  35.168 +
  35.169 +    /* -- Referent accessor and setters -- */
  35.170 +
  35.171 +    /**
  35.172 +     * Returns this reference object's referent.  If this reference object has
  35.173 +     * been cleared, either by the program or by the garbage collector, then
  35.174 +     * this method returns <code>null</code>.
  35.175 +     *
  35.176 +     * @return   The object to which this reference refers, or
  35.177 +     *           <code>null</code> if this reference object has been cleared
  35.178 +     */
  35.179 +    public T get() {
  35.180 +        return this.referent;
  35.181 +    }
  35.182 +
  35.183 +    /**
  35.184 +     * Clears this reference object.  Invoking this method will not cause this
  35.185 +     * object to be enqueued.
  35.186 +     *
  35.187 +     * <p> This method is invoked only by Java code; when the garbage collector
  35.188 +     * clears references it does so directly, without invoking this method.
  35.189 +     */
  35.190 +    public void clear() {
  35.191 +        this.referent = null;
  35.192 +    }
  35.193 +
  35.194 +
  35.195 +    /* -- Queue operations -- */
  35.196 +
  35.197 +    /**
  35.198 +     * Tells whether or not this reference object has been enqueued, either by
  35.199 +     * the program or by the garbage collector.  If this reference object was
  35.200 +     * not registered with a queue when it was created, then this method will
  35.201 +     * always return <code>false</code>.
  35.202 +     *
  35.203 +     * @return   <code>true</code> if and only if this reference object has
  35.204 +     *           been enqueued
  35.205 +     */
  35.206 +    public boolean isEnqueued() {
  35.207 +        /* In terms of the internal states, this predicate actually tests
  35.208 +           whether the instance is either Pending or Enqueued */
  35.209 +        synchronized (this) {
  35.210 +            return (this.queue != ReferenceQueue.NULL) && (this.next != null);
  35.211 +        }
  35.212 +    }
  35.213 +
  35.214 +    /**
  35.215 +     * Adds this reference object to the queue with which it is registered,
  35.216 +     * if any.
  35.217 +     *
  35.218 +     * <p> This method is invoked only by Java code; when the garbage collector
  35.219 +     * enqueues references it does so directly, without invoking this method.
  35.220 +     *
  35.221 +     * @return   <code>true</code> if this reference object was successfully
  35.222 +     *           enqueued; <code>false</code> if it was already enqueued or if
  35.223 +     *           it was not registered with a queue when it was created
  35.224 +     */
  35.225 +    public boolean enqueue() {
  35.226 +        return this.queue.enqueue(this);
  35.227 +    }
  35.228 +
  35.229 +
  35.230 +    /* -- Constructors -- */
  35.231 +
  35.232 +    Reference(T referent) {
  35.233 +        this(referent, null);
  35.234 +    }
  35.235 +
  35.236 +    Reference(T referent, ReferenceQueue<? super T> queue) {
  35.237 +        this.referent = referent;
  35.238 +        this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
  35.239 +    }
  35.240 +
  35.241 +}
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/emul/compact/src/main/java/java/lang/ref/ReferenceQueue.java	Mon Jan 28 18:14:14 2013 +0100
    36.3 @@ -0,0 +1,154 @@
    36.4 +/*
    36.5 + * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved.
    36.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    36.7 + *
    36.8 + * This code is free software; you can redistribute it and/or modify it
    36.9 + * under the terms of the GNU General Public License version 2 only, as
   36.10 + * published by the Free Software Foundation.  Oracle designates this
   36.11 + * particular file as subject to the "Classpath" exception as provided
   36.12 + * by Oracle in the LICENSE file that accompanied this code.
   36.13 + *
   36.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   36.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   36.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   36.17 + * version 2 for more details (a copy is included in the LICENSE file that
   36.18 + * accompanied this code).
   36.19 + *
   36.20 + * You should have received a copy of the GNU General Public License version
   36.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   36.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   36.23 + *
   36.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   36.25 + * or visit www.oracle.com if you need additional information or have any
   36.26 + * questions.
   36.27 + */
   36.28 +
   36.29 +package java.lang.ref;
   36.30 +
   36.31 +/**
   36.32 + * Reference queues, to which registered reference objects are appended by the
   36.33 + * garbage collector after the appropriate reachability changes are detected.
   36.34 + *
   36.35 + * @author   Mark Reinhold
   36.36 + * @since    1.2
   36.37 + */
   36.38 +
   36.39 +public class ReferenceQueue<T> {
   36.40 +
   36.41 +    /**
   36.42 +     * Constructs a new reference-object queue.
   36.43 +     */
   36.44 +    public ReferenceQueue() { }
   36.45 +
   36.46 +    private static class Null extends ReferenceQueue {
   36.47 +        boolean enqueue(Reference r) {
   36.48 +            return false;
   36.49 +        }
   36.50 +    }
   36.51 +
   36.52 +    static ReferenceQueue NULL = new Null();
   36.53 +    static ReferenceQueue ENQUEUED = new Null();
   36.54 +
   36.55 +    static private class Lock { };
   36.56 +    private Lock lock = new Lock();
   36.57 +    private volatile Reference<? extends T> head = null;
   36.58 +    private long queueLength = 0;
   36.59 +
   36.60 +    boolean enqueue(Reference<? extends T> r) { /* Called only by Reference class */
   36.61 +        synchronized (r) {
   36.62 +            if (r.queue == ENQUEUED) return false;
   36.63 +            synchronized (lock) {
   36.64 +                r.queue = ENQUEUED;
   36.65 +                r.next = (head == null) ? r : head;
   36.66 +                head = r;
   36.67 +                queueLength++;
   36.68 +                if (r instanceof FinalReference) {
   36.69 +                    sun.misc.VM.addFinalRefCount(1);
   36.70 +                }
   36.71 +                lock.notifyAll();
   36.72 +                return true;
   36.73 +            }
   36.74 +        }
   36.75 +    }
   36.76 +
   36.77 +    private Reference<? extends T> reallyPoll() {       /* Must hold lock */
   36.78 +        if (head != null) {
   36.79 +            Reference<? extends T> r = head;
   36.80 +            head = (r.next == r) ? null : r.next;
   36.81 +            r.queue = NULL;
   36.82 +            r.next = r;
   36.83 +            queueLength--;
   36.84 +            if (r instanceof FinalReference) {
   36.85 +                sun.misc.VM.addFinalRefCount(-1);
   36.86 +            }
   36.87 +            return r;
   36.88 +        }
   36.89 +        return null;
   36.90 +    }
   36.91 +
   36.92 +    /**
   36.93 +     * Polls this queue to see if a reference object is available.  If one is
   36.94 +     * available without further delay then it is removed from the queue and
   36.95 +     * returned.  Otherwise this method immediately returns <tt>null</tt>.
   36.96 +     *
   36.97 +     * @return  A reference object, if one was immediately available,
   36.98 +     *          otherwise <code>null</code>
   36.99 +     */
  36.100 +    public Reference<? extends T> poll() {
  36.101 +        if (head == null)
  36.102 +            return null;
  36.103 +        synchronized (lock) {
  36.104 +            return reallyPoll();
  36.105 +        }
  36.106 +    }
  36.107 +
  36.108 +    /**
  36.109 +     * Removes the next reference object in this queue, blocking until either
  36.110 +     * one becomes available or the given timeout period expires.
  36.111 +     *
  36.112 +     * <p> This method does not offer real-time guarantees: It schedules the
  36.113 +     * timeout as if by invoking the {@link Object#wait(long)} method.
  36.114 +     *
  36.115 +     * @param  timeout  If positive, block for up to <code>timeout</code>
  36.116 +     *                  milliseconds while waiting for a reference to be
  36.117 +     *                  added to this queue.  If zero, block indefinitely.
  36.118 +     *
  36.119 +     * @return  A reference object, if one was available within the specified
  36.120 +     *          timeout period, otherwise <code>null</code>
  36.121 +     *
  36.122 +     * @throws  IllegalArgumentException
  36.123 +     *          If the value of the timeout argument is negative
  36.124 +     *
  36.125 +     * @throws  InterruptedException
  36.126 +     *          If the timeout wait is interrupted
  36.127 +     */
  36.128 +    public Reference<? extends T> remove(long timeout)
  36.129 +        throws IllegalArgumentException, InterruptedException
  36.130 +    {
  36.131 +        if (timeout < 0) {
  36.132 +            throw new IllegalArgumentException("Negative timeout value");
  36.133 +        }
  36.134 +        synchronized (lock) {
  36.135 +            Reference<? extends T> r = reallyPoll();
  36.136 +            if (r != null) return r;
  36.137 +            for (;;) {
  36.138 +                lock.wait(timeout);
  36.139 +                r = reallyPoll();
  36.140 +                if (r != null) return r;
  36.141 +                if (timeout != 0) return null;
  36.142 +            }
  36.143 +        }
  36.144 +    }
  36.145 +
  36.146 +    /**
  36.147 +     * Removes the next reference object in this queue, blocking until one
  36.148 +     * becomes available.
  36.149 +     *
  36.150 +     * @return A reference object, blocking until one becomes available
  36.151 +     * @throws  InterruptedException  If the wait is interrupted
  36.152 +     */
  36.153 +    public Reference<? extends T> remove() throws InterruptedException {
  36.154 +        return remove(0);
  36.155 +    }
  36.156 +
  36.157 +}
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/emul/compact/src/main/java/java/lang/ref/SoftReference.java	Mon Jan 28 18:14:14 2013 +0100
    37.3 @@ -0,0 +1,118 @@
    37.4 +/*
    37.5 + * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
    37.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    37.7 + *
    37.8 + * This code is free software; you can redistribute it and/or modify it
    37.9 + * under the terms of the GNU General Public License version 2 only, as
   37.10 + * published by the Free Software Foundation.  Oracle designates this
   37.11 + * particular file as subject to the "Classpath" exception as provided
   37.12 + * by Oracle in the LICENSE file that accompanied this code.
   37.13 + *
   37.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   37.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   37.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   37.17 + * version 2 for more details (a copy is included in the LICENSE file that
   37.18 + * accompanied this code).
   37.19 + *
   37.20 + * You should have received a copy of the GNU General Public License version
   37.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   37.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   37.23 + *
   37.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   37.25 + * or visit www.oracle.com if you need additional information or have any
   37.26 + * questions.
   37.27 + */
   37.28 +
   37.29 +package java.lang.ref;
   37.30 +
   37.31 +
   37.32 +/**
   37.33 + * Soft reference objects, which are cleared at the discretion of the garbage
   37.34 + * collector in response to memory demand.  Soft references are most often used
   37.35 + * to implement memory-sensitive caches.
   37.36 + *
   37.37 + * <p> Suppose that the garbage collector determines at a certain point in time
   37.38 + * that an object is <a href="package-summary.html#reachability">softly
   37.39 + * reachable</a>.  At that time it may choose to clear atomically all soft
   37.40 + * references to that object and all soft references to any other
   37.41 + * softly-reachable objects from which that object is reachable through a chain
   37.42 + * of strong references.  At the same time or at some later time it will
   37.43 + * enqueue those newly-cleared soft references that are registered with
   37.44 + * reference queues.
   37.45 + *
   37.46 + * <p> All soft references to softly-reachable objects are guaranteed to have
   37.47 + * been cleared before the virtual machine throws an
   37.48 + * <code>OutOfMemoryError</code>.  Otherwise no constraints are placed upon the
   37.49 + * time at which a soft reference will be cleared or the order in which a set
   37.50 + * of such references to different objects will be cleared.  Virtual machine
   37.51 + * implementations are, however, encouraged to bias against clearing
   37.52 + * recently-created or recently-used soft references.
   37.53 + *
   37.54 + * <p> Direct instances of this class may be used to implement simple caches;
   37.55 + * this class or derived subclasses may also be used in larger data structures
   37.56 + * to implement more sophisticated caches.  As long as the referent of a soft
   37.57 + * reference is strongly reachable, that is, is actually in use, the soft
   37.58 + * reference will not be cleared.  Thus a sophisticated cache can, for example,
   37.59 + * prevent its most recently used entries from being discarded by keeping
   37.60 + * strong referents to those entries, leaving the remaining entries to be
   37.61 + * discarded at the discretion of the garbage collector.
   37.62 + *
   37.63 + * @author   Mark Reinhold
   37.64 + * @since    1.2
   37.65 + */
   37.66 +
   37.67 +public class SoftReference<T> extends Reference<T> {
   37.68 +
   37.69 +    /**
   37.70 +     * Timestamp clock, updated by the garbage collector
   37.71 +     */
   37.72 +    static private long clock;
   37.73 +
   37.74 +    /**
   37.75 +     * Timestamp updated by each invocation of the get method.  The VM may use
   37.76 +     * this field when selecting soft references to be cleared, but it is not
   37.77 +     * required to do so.
   37.78 +     */
   37.79 +    private long timestamp;
   37.80 +
   37.81 +    /**
   37.82 +     * Creates a new soft reference that refers to the given object.  The new
   37.83 +     * reference is not registered with any queue.
   37.84 +     *
   37.85 +     * @param referent object the new soft reference will refer to
   37.86 +     */
   37.87 +    public SoftReference(T referent) {
   37.88 +        super(referent);
   37.89 +        this.timestamp = clock;
   37.90 +    }
   37.91 +
   37.92 +    /**
   37.93 +     * Creates a new soft reference that refers to the given object and is
   37.94 +     * registered with the given queue.
   37.95 +     *
   37.96 +     * @param referent object the new soft reference will refer to
   37.97 +     * @param q the queue with which the reference is to be registered,
   37.98 +     *          or <tt>null</tt> if registration is not required
   37.99 +     *
  37.100 +     */
  37.101 +    public SoftReference(T referent, ReferenceQueue<? super T> q) {
  37.102 +        super(referent, q);
  37.103 +        this.timestamp = clock;
  37.104 +    }
  37.105 +
  37.106 +    /**
  37.107 +     * Returns this reference object's referent.  If this reference object has
  37.108 +     * been cleared, either by the program or by the garbage collector, then
  37.109 +     * this method returns <code>null</code>.
  37.110 +     *
  37.111 +     * @return   The object to which this reference refers, or
  37.112 +     *           <code>null</code> if this reference object has been cleared
  37.113 +     */
  37.114 +    public T get() {
  37.115 +        T o = super.get();
  37.116 +        if (o != null && this.timestamp != clock)
  37.117 +            this.timestamp = clock;
  37.118 +        return o;
  37.119 +    }
  37.120 +
  37.121 +}
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/emul/compact/src/main/java/java/lang/ref/WeakReference.java	Mon Jan 28 18:14:14 2013 +0100
    38.3 @@ -0,0 +1,72 @@
    38.4 +/*
    38.5 + * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
    38.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    38.7 + *
    38.8 + * This code is free software; you can redistribute it and/or modify it
    38.9 + * under the terms of the GNU General Public License version 2 only, as
   38.10 + * published by the Free Software Foundation.  Oracle designates this
   38.11 + * particular file as subject to the "Classpath" exception as provided
   38.12 + * by Oracle in the LICENSE file that accompanied this code.
   38.13 + *
   38.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   38.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   38.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   38.17 + * version 2 for more details (a copy is included in the LICENSE file that
   38.18 + * accompanied this code).
   38.19 + *
   38.20 + * You should have received a copy of the GNU General Public License version
   38.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   38.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   38.23 + *
   38.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   38.25 + * or visit www.oracle.com if you need additional information or have any
   38.26 + * questions.
   38.27 + */
   38.28 +
   38.29 +package java.lang.ref;
   38.30 +
   38.31 +
   38.32 +/**
   38.33 + * Weak reference objects, which do not prevent their referents from being
   38.34 + * made finalizable, finalized, and then reclaimed.  Weak references are most
   38.35 + * often used to implement canonicalizing mappings.
   38.36 + *
   38.37 + * <p> Suppose that the garbage collector determines at a certain point in time
   38.38 + * that an object is <a href="package-summary.html#reachability">weakly
   38.39 + * reachable</a>.  At that time it will atomically clear all weak references to
   38.40 + * that object and all weak references to any other weakly-reachable objects
   38.41 + * from which that object is reachable through a chain of strong and soft
   38.42 + * references.  At the same time it will declare all of the formerly
   38.43 + * weakly-reachable objects to be finalizable.  At the same time or at some
   38.44 + * later time it will enqueue those newly-cleared weak references that are
   38.45 + * registered with reference queues.
   38.46 + *
   38.47 + * @author   Mark Reinhold
   38.48 + * @since    1.2
   38.49 + */
   38.50 +
   38.51 +public class WeakReference<T> extends Reference<T> {
   38.52 +
   38.53 +    /**
   38.54 +     * Creates a new weak reference that refers to the given object.  The new
   38.55 +     * reference is not registered with any queue.
   38.56 +     *
   38.57 +     * @param referent object the new weak reference will refer to
   38.58 +     */
   38.59 +    public WeakReference(T referent) {
   38.60 +        super(referent);
   38.61 +    }
   38.62 +
   38.63 +    /**
   38.64 +     * Creates a new weak reference that refers to the given object and is
   38.65 +     * registered with the given queue.
   38.66 +     *
   38.67 +     * @param referent object the new weak reference will refer to
   38.68 +     * @param q the queue with which the reference is to be registered,
   38.69 +     *          or <tt>null</tt> if registration is not required
   38.70 +     */
   38.71 +    public WeakReference(T referent, ReferenceQueue<? super T> q) {
   38.72 +        super(referent, q);
   38.73 +    }
   38.74 +
   38.75 +}
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/emul/compact/src/main/java/java/lang/ref/package.html	Mon Jan 28 18:14:14 2013 +0100
    39.3 @@ -0,0 +1,147 @@
    39.4 +<!--
    39.5 + Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved.
    39.6 + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    39.7 +
    39.8 + This code is free software; you can redistribute it and/or modify it
    39.9 + under the terms of the GNU General Public License version 2 only, as
   39.10 + published by the Free Software Foundation.  Oracle designates this
   39.11 + particular file as subject to the "Classpath" exception as provided
   39.12 + by Oracle in the LICENSE file that accompanied this code.
   39.13 +
   39.14 + This code is distributed in the hope that it will be useful, but WITHOUT
   39.15 + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   39.16 + FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   39.17 + version 2 for more details (a copy is included in the LICENSE file that
   39.18 + accompanied this code).
   39.19 +
   39.20 + You should have received a copy of the GNU General Public License version
   39.21 + 2 along with this work; if not, write to the Free Software Foundation,
   39.22 + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   39.23 +
   39.24 + Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   39.25 + or visit www.oracle.com if you need additional information or have any
   39.26 + questions.
   39.27 +-->
   39.28 +
   39.29 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
   39.30 +<html>
   39.31 +<body bgcolor="white">
   39.32 +
   39.33 +
   39.34 +Provides reference-object classes, which support a limited degree of
   39.35 +interaction with the garbage collector.  A program may use a reference object
   39.36 +to maintain a reference to some other object in such a way that the latter
   39.37 +object may still be reclaimed by the collector.  A program may also arrange to
   39.38 +be notified some time after the collector has determined that the reachability
   39.39 +of a given object has changed.
   39.40 +
   39.41 +
   39.42 +<h2>Package Specification</h2>
   39.43 +
   39.44 +A <em>reference object</em> encapsulates a reference to some other object so
   39.45 +that the reference itself may be examined and manipulated like any other
   39.46 +object.  Three types of reference objects are provided, each weaker than the
   39.47 +last: <em>soft</em>, <em>weak</em>, and <em>phantom</em>.  Each type
   39.48 +corresponds to a different level of reachability, as defined below.  Soft
   39.49 +references are for implementing memory-sensitive caches, weak references are
   39.50 +for implementing canonicalizing mappings that do not prevent their keys (or
   39.51 +values) from being reclaimed, and phantom references are for scheduling
   39.52 +pre-mortem cleanup actions in a more flexible way than is possible with the
   39.53 +Java finalization mechanism.
   39.54 +
   39.55 +<p> Each reference-object type is implemented by a subclass of the abstract
   39.56 +base <code>{@link java.lang.ref.Reference}</code> class.  An instance of one of
   39.57 +these subclasses encapsulates a single reference to a particular object, called
   39.58 +the <em>referent</em>.  Every reference object provides methods for getting and
   39.59 +clearing the reference.  Aside from the clearing operation reference objects
   39.60 +are otherwise immutable, so no <code>set</code> operation is provided.  A
   39.61 +program may further subclass these subclasses, adding whatever fields and
   39.62 +methods are required for its purposes, or it may use these subclasses without
   39.63 +change.
   39.64 +
   39.65 +
   39.66 +<h3>Notification</h3>
   39.67 +
   39.68 +A program may request to be notified of changes in an object's reachability by
   39.69 +<em>registering</em> an appropriate reference object with a <em>reference
   39.70 +queue</em> at the time the reference object is created.  Some time after the
   39.71 +garbage collector determines that the reachability of the referent has changed
   39.72 +to the value corresponding to the type of the reference, it will add the
   39.73 +reference to the associated queue.  At this point, the reference is considered
   39.74 +to be <em>enqueued</em>.  The program may remove references from a queue either
   39.75 +by polling or by blocking until a reference becomes available.  Reference
   39.76 +queues are implemented by the <code>{@link java.lang.ref.ReferenceQueue}</code>
   39.77 +class.
   39.78 +
   39.79 +<p> The relationship between a registered reference object and its queue is
   39.80 +one-sided.  That is, a queue does not keep track of the references that are
   39.81 +registered with it.  If a registered reference becomes unreachable itself, then
   39.82 +it will never be enqueued.  It is the responsibility of the program using
   39.83 +reference objects to ensure that the objects remain reachable for as long as
   39.84 +the program is interested in their referents.
   39.85 +
   39.86 +<p> While some programs will choose to dedicate a thread to removing reference
   39.87 +objects from one or more queues and processing them, this is by no means
   39.88 +necessary.  A tactic that often works well is to examine a reference queue in
   39.89 +the course of performing some other fairly-frequent action.  For example, a
   39.90 +hashtable that uses weak references to implement weak keys could poll its
   39.91 +reference queue each time the table is accessed.  This is how the <code>{@link
   39.92 +java.util.WeakHashMap}</code> class works.  Because the <code>{@link
   39.93 +java.lang.ref.ReferenceQueue#poll ReferenceQueue.poll}</code> method simply
   39.94 +checks an internal data structure, this check will add little overhead to the
   39.95 +hashtable access methods.
   39.96 +
   39.97 +
   39.98 +<h3>Automatically-cleared references</h3>
   39.99 +
  39.100 +Soft and weak references are automatically cleared by the collector before
  39.101 +being added to the queues with which they are registered, if any.  Therefore
  39.102 +soft and weak references need not be registered with a queue in order to be
  39.103 +useful, while phantom references do.  An object that is reachable via phantom
  39.104 +references will remain so until all such references are cleared or themselves
  39.105 +become unreachable.
  39.106 +
  39.107 +
  39.108 +<a name="reachability"></a>
  39.109 +<h3>Reachability</h3>
  39.110 +
  39.111 +Going from strongest to weakest, the different levels of reachability reflect
  39.112 +the life cycle of an object.  They are operationally defined as follows:
  39.113 +
  39.114 +<ul>
  39.115 +
  39.116 +<li> An object is <em>strongly reachable</em> if it can be reached by some
  39.117 +thread without traversing any reference objects.  A newly-created object is
  39.118 +strongly reachable by the thread that created it.
  39.119 +
  39.120 +<li> An object is <em>softly reachable</em> if it is not strongly reachable but
  39.121 +can be reached by traversing a soft reference.
  39.122 +
  39.123 +<li> An object is <em>weakly reachable</em> if it is neither strongly nor
  39.124 +softly reachable but can be reached by traversing a weak reference.  When the
  39.125 +weak references to a weakly-reachable object are cleared, the object becomes
  39.126 +eligible for finalization.
  39.127 +
  39.128 +<li> An object is <em>phantom reachable</em> if it is neither strongly, softly,
  39.129 +nor weakly reachable, it has been finalized, and some phantom reference refers
  39.130 +to it.
  39.131 +
  39.132 +<li> Finally, an object is <em>unreachable</em>, and therefore eligible for
  39.133 +reclamation, when it is not reachable in any of the above ways.
  39.134 +
  39.135 +</ul>
  39.136 +
  39.137 +
  39.138 +@author	  Mark Reinhold
  39.139 +@since	  1.2
  39.140 +
  39.141 +<!--
  39.142 +<h2>Related Documentation</h2>
  39.143 +
  39.144 +For overviews, tutorials, examples, guides, and tool documentation, please see:
  39.145 +<ul>
  39.146 +  <li><a href="">##### REFER TO NON-SPEC DOCUMENTATION HERE #####</a>
  39.147 +</ul>
  39.148 +-->
  39.149 +</body>
  39.150 +</html>
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/emul/compact/src/main/java/java/util/EventListenerProxy.java	Mon Jan 28 18:14:14 2013 +0100
    40.3 @@ -0,0 +1,75 @@
    40.4 +/*
    40.5 + * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved.
    40.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    40.7 + *
    40.8 + * This code is free software; you can redistribute it and/or modify it
    40.9 + * under the terms of the GNU General Public License version 2 only, as
   40.10 + * published by the Free Software Foundation.  Oracle designates this
   40.11 + * particular file as subject to the "Classpath" exception as provided
   40.12 + * by Oracle in the LICENSE file that accompanied this code.
   40.13 + *
   40.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   40.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   40.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   40.17 + * version 2 for more details (a copy is included in the LICENSE file that
   40.18 + * accompanied this code).
   40.19 + *
   40.20 + * You should have received a copy of the GNU General Public License version
   40.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   40.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   40.23 + *
   40.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   40.25 + * or visit www.oracle.com if you need additional information or have any
   40.26 + * questions.
   40.27 + */
   40.28 +
   40.29 +package java.util;
   40.30 +
   40.31 +/**
   40.32 + * An abstract wrapper class for an {@code EventListener} class
   40.33 + * which associates a set of additional parameters with the listener.
   40.34 + * Subclasses must provide the storage and accessor methods
   40.35 + * for the additional arguments or parameters.
   40.36 + * <p>
   40.37 + * For example, a bean which supports named properties
   40.38 + * would have a two argument method signature for adding
   40.39 + * a {@code PropertyChangeListener} for a property:
   40.40 + * <pre>
   40.41 + * public void addPropertyChangeListener(String propertyName,
   40.42 + *                                       PropertyChangeListener listener)
   40.43 + * </pre>
   40.44 + * If the bean also implemented the zero argument get listener method:
   40.45 + * <pre>
   40.46 + * public PropertyChangeListener[] getPropertyChangeListeners()
   40.47 + * </pre>
   40.48 + * then the array may contain inner {@code PropertyChangeListeners}
   40.49 + * which are also {@code PropertyChangeListenerProxy} objects.
   40.50 + * <p>
   40.51 + * If the calling method is interested in retrieving the named property
   40.52 + * then it would have to test the element to see if it is a proxy class.
   40.53 + *
   40.54 + * @since 1.4
   40.55 + */
   40.56 +public abstract class EventListenerProxy<T extends EventListener>
   40.57 +        implements EventListener {
   40.58 +
   40.59 +    private final T listener;
   40.60 +
   40.61 +    /**
   40.62 +     * Creates a proxy for the specified listener.
   40.63 +     *
   40.64 +     * @param listener  the listener object
   40.65 +     */
   40.66 +    public EventListenerProxy(T listener) {
   40.67 +        this.listener = listener;
   40.68 +    }
   40.69 +
   40.70 +    /**
   40.71 +     * Returns the listener associated with the proxy.
   40.72 +     *
   40.73 +     * @return  the listener associated with the proxy
   40.74 +     */
   40.75 +    public T getListener() {
   40.76 +        return this.listener;
   40.77 +    }
   40.78 +}
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/emul/compact/src/main/java/java/util/concurrent/Callable.java	Mon Jan 28 18:14:14 2013 +0100
    41.3 @@ -0,0 +1,65 @@
    41.4 +/*
    41.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    41.6 + *
    41.7 + * This code is free software; you can redistribute it and/or modify it
    41.8 + * under the terms of the GNU General Public License version 2 only, as
    41.9 + * published by the Free Software Foundation.  Oracle designates this
   41.10 + * particular file as subject to the "Classpath" exception as provided
   41.11 + * by Oracle in the LICENSE file that accompanied this code.
   41.12 + *
   41.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
   41.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   41.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   41.16 + * version 2 for more details (a copy is included in the LICENSE file that
   41.17 + * accompanied this code).
   41.18 + *
   41.19 + * You should have received a copy of the GNU General Public License version
   41.20 + * 2 along with this work; if not, write to the Free Software Foundation,
   41.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   41.22 + *
   41.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   41.24 + * or visit www.oracle.com if you need additional information or have any
   41.25 + * questions.
   41.26 + */
   41.27 +
   41.28 +/*
   41.29 + * This file is available under and governed by the GNU General Public
   41.30 + * License version 2 only, as published by the Free Software Foundation.
   41.31 + * However, the following notice accompanied the original version of this
   41.32 + * file:
   41.33 + *
   41.34 + * Written by Doug Lea with assistance from members of JCP JSR-166
   41.35 + * Expert Group and released to the public domain, as explained at
   41.36 + * http://creativecommons.org/publicdomain/zero/1.0/
   41.37 + */
   41.38 +
   41.39 +package java.util.concurrent;
   41.40 +
   41.41 +/**
   41.42 + * A task that returns a result and may throw an exception.
   41.43 + * Implementors define a single method with no arguments called
   41.44 + * <tt>call</tt>.
   41.45 + *
   41.46 + * <p>The <tt>Callable</tt> interface is similar to {@link
   41.47 + * java.lang.Runnable}, in that both are designed for classes whose
   41.48 + * instances are potentially executed by another thread.  A
   41.49 + * <tt>Runnable</tt>, however, does not return a result and cannot
   41.50 + * throw a checked exception.
   41.51 + *
   41.52 + * <p> The {@link Executors} class contains utility methods to
   41.53 + * convert from other common forms to <tt>Callable</tt> classes.
   41.54 + *
   41.55 + * @see Executor
   41.56 + * @since 1.5
   41.57 + * @author Doug Lea
   41.58 + * @param <V> the result type of method <tt>call</tt>
   41.59 + */
   41.60 +public interface Callable<V> {
   41.61 +    /**
   41.62 +     * Computes a result, or throws an exception if unable to do so.
   41.63 +     *
   41.64 +     * @return computed result
   41.65 +     * @throws Exception if unable to compute a result
   41.66 +     */
   41.67 +    V call() throws Exception;
   41.68 +}
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/emul/mini/src/main/java/java/lang/IllegalAccessError.java	Mon Jan 28 18:14:14 2013 +0100
    42.3 @@ -0,0 +1,58 @@
    42.4 +/*
    42.5 + * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
    42.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    42.7 + *
    42.8 + * This code is free software; you can redistribute it and/or modify it
    42.9 + * under the terms of the GNU General Public License version 2 only, as
   42.10 + * published by the Free Software Foundation.  Oracle designates this
   42.11 + * particular file as subject to the "Classpath" exception as provided
   42.12 + * by Oracle in the LICENSE file that accompanied this code.
   42.13 + *
   42.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   42.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   42.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   42.17 + * version 2 for more details (a copy is included in the LICENSE file that
   42.18 + * accompanied this code).
   42.19 + *
   42.20 + * You should have received a copy of the GNU General Public License version
   42.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   42.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   42.23 + *
   42.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   42.25 + * or visit www.oracle.com if you need additional information or have any
   42.26 + * questions.
   42.27 + */
   42.28 +
   42.29 +package java.lang;
   42.30 +
   42.31 +/**
   42.32 + * Thrown if an application attempts to access or modify a field, or
   42.33 + * to call a method that it does not have access to.
   42.34 + * <p>
   42.35 + * Normally, this error is caught by the compiler; this error can
   42.36 + * only occur at run time if the definition of a class has
   42.37 + * incompatibly changed.
   42.38 + *
   42.39 + * @author  unascribed
   42.40 + * @since   JDK1.0
   42.41 + */
   42.42 +public class IllegalAccessError extends IncompatibleClassChangeError {
   42.43 +    private static final long serialVersionUID = -8988904074992417891L;
   42.44 +
   42.45 +    /**
   42.46 +     * Constructs an <code>IllegalAccessError</code> with no detail message.
   42.47 +     */
   42.48 +    public IllegalAccessError() {
   42.49 +        super();
   42.50 +    }
   42.51 +
   42.52 +    /**
   42.53 +     * Constructs an <code>IllegalAccessError</code> with the specified
   42.54 +     * detail message.
   42.55 +     *
   42.56 +     * @param   s   the detail message.
   42.57 +     */
   42.58 +    public IllegalAccessError(String s) {
   42.59 +        super(s);
   42.60 +    }
   42.61 +}
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/emul/mini/src/main/java/java/lang/IncompatibleClassChangeError.java	Mon Jan 28 18:14:14 2013 +0100
    43.3 @@ -0,0 +1,57 @@
    43.4 +/*
    43.5 + * Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved.
    43.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    43.7 + *
    43.8 + * This code is free software; you can redistribute it and/or modify it
    43.9 + * under the terms of the GNU General Public License version 2 only, as
   43.10 + * published by the Free Software Foundation.  Oracle designates this
   43.11 + * particular file as subject to the "Classpath" exception as provided
   43.12 + * by Oracle in the LICENSE file that accompanied this code.
   43.13 + *
   43.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   43.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   43.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   43.17 + * version 2 for more details (a copy is included in the LICENSE file that
   43.18 + * accompanied this code).
   43.19 + *
   43.20 + * You should have received a copy of the GNU General Public License version
   43.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   43.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   43.23 + *
   43.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   43.25 + * or visit www.oracle.com if you need additional information or have any
   43.26 + * questions.
   43.27 + */
   43.28 +
   43.29 +package java.lang;
   43.30 +
   43.31 +/**
   43.32 + * Thrown when an incompatible class change has occurred to some class
   43.33 + * definition. The definition of some class, on which the currently
   43.34 + * executing method depends, has since changed.
   43.35 + *
   43.36 + * @author  unascribed
   43.37 + * @since   JDK1.0
   43.38 + */
   43.39 +public
   43.40 +class IncompatibleClassChangeError extends LinkageError {
   43.41 +    private static final long serialVersionUID = -4914975503642802119L;
   43.42 +
   43.43 +    /**
   43.44 +     * Constructs an <code>IncompatibleClassChangeError</code> with no
   43.45 +     * detail message.
   43.46 +     */
   43.47 +    public IncompatibleClassChangeError () {
   43.48 +        super();
   43.49 +    }
   43.50 +
   43.51 +    /**
   43.52 +     * Constructs an <code>IncompatibleClassChangeError</code> with the
   43.53 +     * specified detail message.
   43.54 +     *
   43.55 +     * @param   s   the detail message.
   43.56 +     */
   43.57 +    public IncompatibleClassChangeError(String s) {
   43.58 +        super(s);
   43.59 +    }
   43.60 +}
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/emul/mini/src/main/java/java/lang/reflect/Constructor.java	Mon Jan 28 18:14:14 2013 +0100
    44.3 @@ -0,0 +1,683 @@
    44.4 +/*
    44.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
    44.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    44.7 + *
    44.8 + * This code is free software; you can redistribute it and/or modify it
    44.9 + * under the terms of the GNU General Public License version 2 only, as
   44.10 + * published by the Free Software Foundation.  Oracle designates this
   44.11 + * particular file as subject to the "Classpath" exception as provided
   44.12 + * by Oracle in the LICENSE file that accompanied this code.
   44.13 + *
   44.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   44.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   44.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   44.17 + * version 2 for more details (a copy is included in the LICENSE file that
   44.18 + * accompanied this code).
   44.19 + *
   44.20 + * You should have received a copy of the GNU General Public License version
   44.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   44.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   44.23 + *
   44.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   44.25 + * or visit www.oracle.com if you need additional information or have any
   44.26 + * questions.
   44.27 + */
   44.28 +
   44.29 +package java.lang.reflect;
   44.30 +
   44.31 +import sun.reflect.ConstructorAccessor;
   44.32 +import sun.reflect.Reflection;
   44.33 +import sun.reflect.generics.repository.ConstructorRepository;
   44.34 +import sun.reflect.generics.factory.CoreReflectionFactory;
   44.35 +import sun.reflect.generics.factory.GenericsFactory;
   44.36 +import sun.reflect.generics.scope.ConstructorScope;
   44.37 +import java.lang.annotation.Annotation;
   44.38 +import java.util.Map;
   44.39 +import sun.reflect.annotation.AnnotationParser;
   44.40 +import java.lang.annotation.AnnotationFormatError;
   44.41 +import java.lang.reflect.Modifier;
   44.42 +
   44.43 +/**
   44.44 + * {@code Constructor} provides information about, and access to, a single
   44.45 + * constructor for a class.
   44.46 + *
   44.47 + * <p>{@code Constructor} permits widening conversions to occur when matching the
   44.48 + * actual parameters to newInstance() with the underlying
   44.49 + * constructor's formal parameters, but throws an
   44.50 + * {@code IllegalArgumentException} if a narrowing conversion would occur.
   44.51 + *
   44.52 + * @param <T> the class in which the constructor is declared
   44.53 + *
   44.54 + * @see Member
   44.55 + * @see java.lang.Class
   44.56 + * @see java.lang.Class#getConstructors()
   44.57 + * @see java.lang.Class#getConstructor(Class[])
   44.58 + * @see java.lang.Class#getDeclaredConstructors()
   44.59 + *
   44.60 + * @author      Kenneth Russell
   44.61 + * @author      Nakul Saraiya
   44.62 + */
   44.63 +public final
   44.64 +    class Constructor<T> extends AccessibleObject implements
   44.65 +                                                    GenericDeclaration,
   44.66 +                                                    Member {
   44.67 +
   44.68 +    private Class<T>            clazz;
   44.69 +    private int                 slot;
   44.70 +    private Class<?>[]          parameterTypes;
   44.71 +    private Class<?>[]          exceptionTypes;
   44.72 +    private int                 modifiers;
   44.73 +    // Generics and annotations support
   44.74 +    private transient String    signature;
   44.75 +    // generic info repository; lazily initialized
   44.76 +    private transient ConstructorRepository genericInfo;
   44.77 +    private byte[]              annotations;
   44.78 +    private byte[]              parameterAnnotations;
   44.79 +
   44.80 +    // Generics infrastructure
   44.81 +    // Accessor for factory
   44.82 +    private GenericsFactory getFactory() {
   44.83 +        // create scope and factory
   44.84 +        return CoreReflectionFactory.make(this, ConstructorScope.make(this));
   44.85 +    }
   44.86 +
   44.87 +    // Accessor for generic info repository
   44.88 +    private ConstructorRepository getGenericInfo() {
   44.89 +        // lazily initialize repository if necessary
   44.90 +        if (genericInfo == null) {
   44.91 +            // create and cache generic info repository
   44.92 +            genericInfo =
   44.93 +                ConstructorRepository.make(getSignature(),
   44.94 +                                           getFactory());
   44.95 +        }
   44.96 +        return genericInfo; //return cached repository
   44.97 +    }
   44.98 +
   44.99 +    private volatile ConstructorAccessor constructorAccessor;
  44.100 +    // For sharing of ConstructorAccessors. This branching structure
  44.101 +    // is currently only two levels deep (i.e., one root Constructor
  44.102 +    // and potentially many Constructor objects pointing to it.)
  44.103 +    private Constructor<T>      root;
  44.104 +
  44.105 +    /**
  44.106 +     * Package-private constructor used by ReflectAccess to enable
  44.107 +     * instantiation of these objects in Java code from the java.lang
  44.108 +     * package via sun.reflect.LangReflectAccess.
  44.109 +     */
  44.110 +    Constructor(Class<T> declaringClass,
  44.111 +                Class<?>[] parameterTypes,
  44.112 +                Class<?>[] checkedExceptions,
  44.113 +                int modifiers,
  44.114 +                int slot,
  44.115 +                String signature,
  44.116 +                byte[] annotations,
  44.117 +                byte[] parameterAnnotations)
  44.118 +    {
  44.119 +        this.clazz = declaringClass;
  44.120 +        this.parameterTypes = parameterTypes;
  44.121 +        this.exceptionTypes = checkedExceptions;
  44.122 +        this.modifiers = modifiers;
  44.123 +        this.slot = slot;
  44.124 +        this.signature = signature;
  44.125 +        this.annotations = annotations;
  44.126 +        this.parameterAnnotations = parameterAnnotations;
  44.127 +    }
  44.128 +
  44.129 +    /**
  44.130 +     * Package-private routine (exposed to java.lang.Class via
  44.131 +     * ReflectAccess) which returns a copy of this Constructor. The copy's
  44.132 +     * "root" field points to this Constructor.
  44.133 +     */
  44.134 +    Constructor<T> copy() {
  44.135 +        // This routine enables sharing of ConstructorAccessor objects
  44.136 +        // among Constructor objects which refer to the same underlying
  44.137 +        // method in the VM. (All of this contortion is only necessary
  44.138 +        // because of the "accessibility" bit in AccessibleObject,
  44.139 +        // which implicitly requires that new java.lang.reflect
  44.140 +        // objects be fabricated for each reflective call on Class
  44.141 +        // objects.)
  44.142 +        Constructor<T> res = new Constructor<>(clazz,
  44.143 +                                                parameterTypes,
  44.144 +                                                exceptionTypes, modifiers, slot,
  44.145 +                                                signature,
  44.146 +                                                annotations,
  44.147 +                                                parameterAnnotations);
  44.148 +        res.root = this;
  44.149 +        // Might as well eagerly propagate this if already present
  44.150 +        res.constructorAccessor = constructorAccessor;
  44.151 +        return res;
  44.152 +    }
  44.153 +
  44.154 +    /**
  44.155 +     * Returns the {@code Class} object representing the class that declares
  44.156 +     * the constructor represented by this {@code Constructor} object.
  44.157 +     */
  44.158 +    public Class<T> getDeclaringClass() {
  44.159 +        return clazz;
  44.160 +    }
  44.161 +
  44.162 +    /**
  44.163 +     * Returns the name of this constructor, as a string.  This is
  44.164 +     * the binary name of the constructor's declaring class.
  44.165 +     */
  44.166 +    public String getName() {
  44.167 +        return getDeclaringClass().getName();
  44.168 +    }
  44.169 +
  44.170 +    /**
  44.171 +     * Returns the Java language modifiers for the constructor
  44.172 +     * represented by this {@code Constructor} object, as an integer. The
  44.173 +     * {@code Modifier} class should be used to decode the modifiers.
  44.174 +     *
  44.175 +     * @see Modifier
  44.176 +     */
  44.177 +    public int getModifiers() {
  44.178 +        return modifiers;
  44.179 +    }
  44.180 +
  44.181 +    /**
  44.182 +     * Returns an array of {@code TypeVariable} objects that represent the
  44.183 +     * type variables declared by the generic declaration represented by this
  44.184 +     * {@code GenericDeclaration} object, in declaration order.  Returns an
  44.185 +     * array of length 0 if the underlying generic declaration declares no type
  44.186 +     * variables.
  44.187 +     *
  44.188 +     * @return an array of {@code TypeVariable} objects that represent
  44.189 +     *     the type variables declared by this generic declaration
  44.190 +     * @throws GenericSignatureFormatError if the generic
  44.191 +     *     signature of this generic declaration does not conform to
  44.192 +     *     the format specified in
  44.193 +     *     <cite>The Java&trade; Virtual Machine Specification</cite>
  44.194 +     * @since 1.5
  44.195 +     */
  44.196 +    public TypeVariable<Constructor<T>>[] getTypeParameters() {
  44.197 +      if (getSignature() != null) {
  44.198 +        return (TypeVariable<Constructor<T>>[])getGenericInfo().getTypeParameters();
  44.199 +      } else
  44.200 +          return (TypeVariable<Constructor<T>>[])new TypeVariable[0];
  44.201 +    }
  44.202 +
  44.203 +
  44.204 +    /**
  44.205 +     * Returns an array of {@code Class} objects that represent the formal
  44.206 +     * parameter types, in declaration order, of the constructor
  44.207 +     * represented by this {@code Constructor} object.  Returns an array of
  44.208 +     * length 0 if the underlying constructor takes no parameters.
  44.209 +     *
  44.210 +     * @return the parameter types for the constructor this object
  44.211 +     * represents
  44.212 +     */
  44.213 +    public Class<?>[] getParameterTypes() {
  44.214 +        return (Class<?>[]) parameterTypes.clone();
  44.215 +    }
  44.216 +
  44.217 +
  44.218 +    /**
  44.219 +     * Returns an array of {@code Type} objects that represent the formal
  44.220 +     * parameter types, in declaration order, of the method represented by
  44.221 +     * this {@code Constructor} object. Returns an array of length 0 if the
  44.222 +     * underlying method takes no parameters.
  44.223 +     *
  44.224 +     * <p>If a formal parameter type is a parameterized type,
  44.225 +     * the {@code Type} object returned for it must accurately reflect
  44.226 +     * the actual type parameters used in the source code.
  44.227 +     *
  44.228 +     * <p>If a formal parameter type is a type variable or a parameterized
  44.229 +     * type, it is created. Otherwise, it is resolved.
  44.230 +     *
  44.231 +     * @return an array of {@code Type}s that represent the formal
  44.232 +     *     parameter types of the underlying method, in declaration order
  44.233 +     * @throws GenericSignatureFormatError
  44.234 +     *     if the generic method signature does not conform to the format
  44.235 +     *     specified in
  44.236 +     *     <cite>The Java&trade; Virtual Machine Specification</cite>
  44.237 +     * @throws TypeNotPresentException if any of the parameter
  44.238 +     *     types of the underlying method refers to a non-existent type
  44.239 +     *     declaration
  44.240 +     * @throws MalformedParameterizedTypeException if any of
  44.241 +     *     the underlying method's parameter types refer to a parameterized
  44.242 +     *     type that cannot be instantiated for any reason
  44.243 +     * @since 1.5
  44.244 +     */
  44.245 +    public Type[] getGenericParameterTypes() {
  44.246 +        if (getSignature() != null)
  44.247 +            return getGenericInfo().getParameterTypes();
  44.248 +        else
  44.249 +            return getParameterTypes();
  44.250 +    }
  44.251 +
  44.252 +
  44.253 +    /**
  44.254 +     * Returns an array of {@code Class} objects that represent the types
  44.255 +     * of exceptions declared to be thrown by the underlying constructor
  44.256 +     * represented by this {@code Constructor} object.  Returns an array of
  44.257 +     * length 0 if the constructor declares no exceptions in its {@code throws} clause.
  44.258 +     *
  44.259 +     * @return the exception types declared as being thrown by the
  44.260 +     * constructor this object represents
  44.261 +     */
  44.262 +    public Class<?>[] getExceptionTypes() {
  44.263 +        return (Class<?>[])exceptionTypes.clone();
  44.264 +    }
  44.265 +
  44.266 +
  44.267 +    /**
  44.268 +     * Returns an array of {@code Type} objects that represent the
  44.269 +     * exceptions declared to be thrown by this {@code Constructor} object.
  44.270 +     * Returns an array of length 0 if the underlying method declares
  44.271 +     * no exceptions in its {@code throws} clause.
  44.272 +     *
  44.273 +     * <p>If an exception type is a type variable or a parameterized
  44.274 +     * type, it is created. Otherwise, it is resolved.
  44.275 +     *
  44.276 +     * @return an array of Types that represent the exception types
  44.277 +     *     thrown by the underlying method
  44.278 +     * @throws GenericSignatureFormatError
  44.279 +     *     if the generic method signature does not conform to the format
  44.280 +     *     specified in
  44.281 +     *     <cite>The Java&trade; Virtual Machine Specification</cite>
  44.282 +     * @throws TypeNotPresentException if the underlying method's
  44.283 +     *     {@code throws} clause refers to a non-existent type declaration
  44.284 +     * @throws MalformedParameterizedTypeException if
  44.285 +     *     the underlying method's {@code throws} clause refers to a
  44.286 +     *     parameterized type that cannot be instantiated for any reason
  44.287 +     * @since 1.5
  44.288 +     */
  44.289 +      public Type[] getGenericExceptionTypes() {
  44.290 +          Type[] result;
  44.291 +          if (getSignature() != null &&
  44.292 +              ( (result = getGenericInfo().getExceptionTypes()).length > 0  ))
  44.293 +              return result;
  44.294 +          else
  44.295 +              return getExceptionTypes();
  44.296 +      }
  44.297 +
  44.298 +    /**
  44.299 +     * Compares this {@code Constructor} against the specified object.
  44.300 +     * Returns true if the objects are the same.  Two {@code Constructor} objects are
  44.301 +     * the same if they were declared by the same class and have the
  44.302 +     * same formal parameter types.
  44.303 +     */
  44.304 +    public boolean equals(Object obj) {
  44.305 +        if (obj != null && obj instanceof Constructor) {
  44.306 +            Constructor<?> other = (Constructor<?>)obj;
  44.307 +            if (getDeclaringClass() == other.getDeclaringClass()) {
  44.308 +                /* Avoid unnecessary cloning */
  44.309 +                Class<?>[] params1 = parameterTypes;
  44.310 +                Class<?>[] params2 = other.parameterTypes;
  44.311 +                if (params1.length == params2.length) {
  44.312 +                    for (int i = 0; i < params1.length; i++) {
  44.313 +                        if (params1[i] != params2[i])
  44.314 +                            return false;
  44.315 +                    }
  44.316 +                    return true;
  44.317 +                }
  44.318 +            }
  44.319 +        }
  44.320 +        return false;
  44.321 +    }
  44.322 +
  44.323 +    /**
  44.324 +     * Returns a hashcode for this {@code Constructor}. The hashcode is
  44.325 +     * the same as the hashcode for the underlying constructor's
  44.326 +     * declaring class name.
  44.327 +     */
  44.328 +    public int hashCode() {
  44.329 +        return getDeclaringClass().getName().hashCode();
  44.330 +    }
  44.331 +
  44.332 +    /**
  44.333 +     * Returns a string describing this {@code Constructor}.  The string is
  44.334 +     * formatted as the constructor access modifiers, if any,
  44.335 +     * followed by the fully-qualified name of the declaring class,
  44.336 +     * followed by a parenthesized, comma-separated list of the
  44.337 +     * constructor's formal parameter types.  For example:
  44.338 +     * <pre>
  44.339 +     *    public java.util.Hashtable(int,float)
  44.340 +     * </pre>
  44.341 +     *
  44.342 +     * <p>The only possible modifiers for constructors are the access
  44.343 +     * modifiers {@code public}, {@code protected} or
  44.344 +     * {@code private}.  Only one of these may appear, or none if the
  44.345 +     * constructor has default (package) access.
  44.346 +     */
  44.347 +    public String toString() {
  44.348 +        try {
  44.349 +            StringBuffer sb = new StringBuffer();
  44.350 +            int mod = getModifiers() & Modifier.constructorModifiers();
  44.351 +            if (mod != 0) {
  44.352 +                sb.append(Modifier.toString(mod) + " ");
  44.353 +            }
  44.354 +            sb.append(Field.getTypeName(getDeclaringClass()));
  44.355 +            sb.append("(");
  44.356 +            Class<?>[] params = parameterTypes; // avoid clone
  44.357 +            for (int j = 0; j < params.length; j++) {
  44.358 +                sb.append(Field.getTypeName(params[j]));
  44.359 +                if (j < (params.length - 1))
  44.360 +                    sb.append(",");
  44.361 +            }
  44.362 +            sb.append(")");
  44.363 +            Class<?>[] exceptions = exceptionTypes; // avoid clone
  44.364 +            if (exceptions.length > 0) {
  44.365 +                sb.append(" throws ");
  44.366 +                for (int k = 0; k < exceptions.length; k++) {
  44.367 +                    sb.append(exceptions[k].getName());
  44.368 +                    if (k < (exceptions.length - 1))
  44.369 +                        sb.append(",");
  44.370 +                }
  44.371 +            }
  44.372 +            return sb.toString();
  44.373 +        } catch (Exception e) {
  44.374 +            return "<" + e + ">";
  44.375 +        }
  44.376 +    }
  44.377 +
  44.378 +    /**
  44.379 +     * Returns a string describing this {@code Constructor},
  44.380 +     * including type parameters.  The string is formatted as the
  44.381 +     * constructor access modifiers, if any, followed by an
  44.382 +     * angle-bracketed comma separated list of the constructor's type
  44.383 +     * parameters, if any, followed by the fully-qualified name of the
  44.384 +     * declaring class, followed by a parenthesized, comma-separated
  44.385 +     * list of the constructor's generic formal parameter types.
  44.386 +     *
  44.387 +     * If this constructor was declared to take a variable number of
  44.388 +     * arguments, instead of denoting the last parameter as
  44.389 +     * "<tt><i>Type</i>[]</tt>", it is denoted as
  44.390 +     * "<tt><i>Type</i>...</tt>".
  44.391 +     *
  44.392 +     * A space is used to separate access modifiers from one another
  44.393 +     * and from the type parameters or return type.  If there are no
  44.394 +     * type parameters, the type parameter list is elided; if the type
  44.395 +     * parameter list is present, a space separates the list from the
  44.396 +     * class name.  If the constructor is declared to throw
  44.397 +     * exceptions, the parameter list is followed by a space, followed
  44.398 +     * by the word "{@code throws}" followed by a
  44.399 +     * comma-separated list of the thrown exception types.
  44.400 +     *
  44.401 +     * <p>The only possible modifiers for constructors are the access
  44.402 +     * modifiers {@code public}, {@code protected} or
  44.403 +     * {@code private}.  Only one of these may appear, or none if the
  44.404 +     * constructor has default (package) access.
  44.405 +     *
  44.406 +     * @return a string describing this {@code Constructor},
  44.407 +     * include type parameters
  44.408 +     *
  44.409 +     * @since 1.5
  44.410 +     */
  44.411 +    public String toGenericString() {
  44.412 +        try {
  44.413 +            StringBuilder sb = new StringBuilder();
  44.414 +            int mod = getModifiers() & Modifier.constructorModifiers();
  44.415 +            if (mod != 0) {
  44.416 +                sb.append(Modifier.toString(mod) + " ");
  44.417 +            }
  44.418 +            TypeVariable<?>[] typeparms = getTypeParameters();
  44.419 +            if (typeparms.length > 0) {
  44.420 +                boolean first = true;
  44.421 +                sb.append("<");
  44.422 +                for(TypeVariable<?> typeparm: typeparms) {
  44.423 +                    if (!first)
  44.424 +                        sb.append(",");
  44.425 +                    // Class objects can't occur here; no need to test
  44.426 +                    // and call Class.getName().
  44.427 +                    sb.append(typeparm.toString());
  44.428 +                    first = false;
  44.429 +                }
  44.430 +                sb.append("> ");
  44.431 +            }
  44.432 +            sb.append(Field.getTypeName(getDeclaringClass()));
  44.433 +            sb.append("(");
  44.434 +            Type[] params = getGenericParameterTypes();
  44.435 +            for (int j = 0; j < params.length; j++) {
  44.436 +                String param = (params[j] instanceof Class<?>)?
  44.437 +                    Field.getTypeName((Class<?>)params[j]):
  44.438 +                    (params[j].toString());
  44.439 +                if (isVarArgs() && (j == params.length - 1)) // replace T[] with T...
  44.440 +                    param = param.replaceFirst("\\[\\]$", "...");
  44.441 +                sb.append(param);
  44.442 +                if (j < (params.length - 1))
  44.443 +                    sb.append(",");
  44.444 +            }
  44.445 +            sb.append(")");
  44.446 +            Type[] exceptions = getGenericExceptionTypes();
  44.447 +            if (exceptions.length > 0) {
  44.448 +                sb.append(" throws ");
  44.449 +                for (int k = 0; k < exceptions.length; k++) {
  44.450 +                    sb.append((exceptions[k] instanceof Class)?
  44.451 +                              ((Class<?>)exceptions[k]).getName():
  44.452 +                              exceptions[k].toString());
  44.453 +                    if (k < (exceptions.length - 1))
  44.454 +                        sb.append(",");
  44.455 +                }
  44.456 +            }
  44.457 +            return sb.toString();
  44.458 +        } catch (Exception e) {
  44.459 +            return "<" + e + ">";
  44.460 +        }
  44.461 +    }
  44.462 +
  44.463 +    /**
  44.464 +     * Uses the constructor represented by this {@code Constructor} object to
  44.465 +     * create and initialize a new instance of the constructor's
  44.466 +     * declaring class, with the specified initialization parameters.
  44.467 +     * Individual parameters are automatically unwrapped to match
  44.468 +     * primitive formal parameters, and both primitive and reference
  44.469 +     * parameters are subject to method invocation conversions as necessary.
  44.470 +     *
  44.471 +     * <p>If the number of formal parameters required by the underlying constructor
  44.472 +     * is 0, the supplied {@code initargs} array may be of length 0 or null.
  44.473 +     *
  44.474 +     * <p>If the constructor's declaring class is an inner class in a
  44.475 +     * non-static context, the first argument to the constructor needs
  44.476 +     * to be the enclosing instance; see section 15.9.3 of
  44.477 +     * <cite>The Java&trade; Language Specification</cite>.
  44.478 +     *
  44.479 +     * <p>If the required access and argument checks succeed and the
  44.480 +     * instantiation will proceed, the constructor's declaring class
  44.481 +     * is initialized if it has not already been initialized.
  44.482 +     *
  44.483 +     * <p>If the constructor completes normally, returns the newly
  44.484 +     * created and initialized instance.
  44.485 +     *
  44.486 +     * @param initargs array of objects to be passed as arguments to
  44.487 +     * the constructor call; values of primitive types are wrapped in
  44.488 +     * a wrapper object of the appropriate type (e.g. a {@code float}
  44.489 +     * in a {@link java.lang.Float Float})
  44.490 +     *
  44.491 +     * @return a new object created by calling the constructor
  44.492 +     * this object represents
  44.493 +     *
  44.494 +     * @exception IllegalAccessException    if this {@code Constructor} object
  44.495 +     *              is enforcing Java language access control and the underlying
  44.496 +     *              constructor is inaccessible.
  44.497 +     * @exception IllegalArgumentException  if the number of actual
  44.498 +     *              and formal parameters differ; if an unwrapping
  44.499 +     *              conversion for primitive arguments fails; or if,
  44.500 +     *              after possible unwrapping, a parameter value
  44.501 +     *              cannot be converted to the corresponding formal
  44.502 +     *              parameter type by a method invocation conversion; if
  44.503 +     *              this constructor pertains to an enum type.
  44.504 +     * @exception InstantiationException    if the class that declares the
  44.505 +     *              underlying constructor represents an abstract class.
  44.506 +     * @exception InvocationTargetException if the underlying constructor
  44.507 +     *              throws an exception.
  44.508 +     * @exception ExceptionInInitializerError if the initialization provoked
  44.509 +     *              by this method fails.
  44.510 +     */
  44.511 +    public T newInstance(Object ... initargs)
  44.512 +        throws InstantiationException, IllegalAccessException,
  44.513 +               IllegalArgumentException, InvocationTargetException
  44.514 +    {
  44.515 +        if (!override) {
  44.516 +            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
  44.517 +                Class<?> caller = Reflection.getCallerClass(2);
  44.518 +
  44.519 +                checkAccess(caller, clazz, null, modifiers);
  44.520 +            }
  44.521 +        }
  44.522 +        if ((clazz.getModifiers() & Modifier.ENUM) != 0)
  44.523 +            throw new IllegalArgumentException("Cannot reflectively create enum objects");
  44.524 +        ConstructorAccessor ca = constructorAccessor;   // read volatile
  44.525 +        if (ca == null) {
  44.526 +            ca = acquireConstructorAccessor();
  44.527 +        }
  44.528 +        return (T) ca.newInstance(initargs);
  44.529 +    }
  44.530 +
  44.531 +    /**
  44.532 +     * Returns {@code true} if this constructor was declared to take
  44.533 +     * a variable number of arguments; returns {@code false}
  44.534 +     * otherwise.
  44.535 +     *
  44.536 +     * @return {@code true} if an only if this constructor was declared to
  44.537 +     * take a variable number of arguments.
  44.538 +     * @since 1.5
  44.539 +     */
  44.540 +    public boolean isVarArgs() {
  44.541 +        return (getModifiers() & Modifier.VARARGS) != 0;
  44.542 +    }
  44.543 +
  44.544 +    /**
  44.545 +     * Returns {@code true} if this constructor is a synthetic
  44.546 +     * constructor; returns {@code false} otherwise.
  44.547 +     *
  44.548 +     * @return true if and only if this constructor is a synthetic
  44.549 +     * constructor as defined by
  44.550 +     * <cite>The Java&trade; Language Specification</cite>.
  44.551 +     * @since 1.5
  44.552 +     */
  44.553 +    public boolean isSynthetic() {
  44.554 +        return Modifier.isSynthetic(getModifiers());
  44.555 +    }
  44.556 +
  44.557 +    // NOTE that there is no synchronization used here. It is correct
  44.558 +    // (though not efficient) to generate more than one
  44.559 +    // ConstructorAccessor for a given Constructor. However, avoiding
  44.560 +    // synchronization will probably make the implementation more
  44.561 +    // scalable.
  44.562 +    private ConstructorAccessor acquireConstructorAccessor() {
  44.563 +        // First check to see if one has been created yet, and take it
  44.564 +        // if so.
  44.565 +        ConstructorAccessor tmp = null;
  44.566 +        if (root != null) tmp = root.getConstructorAccessor();
  44.567 +        if (tmp != null) {
  44.568 +            constructorAccessor = tmp;
  44.569 +        } else {
  44.570 +            // Otherwise fabricate one and propagate it up to the root
  44.571 +            tmp = reflectionFactory.newConstructorAccessor(this);
  44.572 +            setConstructorAccessor(tmp);
  44.573 +        }
  44.574 +
  44.575 +        return tmp;
  44.576 +    }
  44.577 +
  44.578 +    // Returns ConstructorAccessor for this Constructor object, not
  44.579 +    // looking up the chain to the root
  44.580 +    ConstructorAccessor getConstructorAccessor() {
  44.581 +        return constructorAccessor;
  44.582 +    }
  44.583 +
  44.584 +    // Sets the ConstructorAccessor for this Constructor object and
  44.585 +    // (recursively) its root
  44.586 +    void setConstructorAccessor(ConstructorAccessor accessor) {
  44.587 +        constructorAccessor = accessor;
  44.588 +        // Propagate up
  44.589 +        if (root != null) {
  44.590 +            root.setConstructorAccessor(accessor);
  44.591 +        }
  44.592 +    }
  44.593 +
  44.594 +    int getSlot() {
  44.595 +        return slot;
  44.596 +    }
  44.597 +
  44.598 +   String getSignature() {
  44.599 +            return signature;
  44.600 +   }
  44.601 +
  44.602 +    byte[] getRawAnnotations() {
  44.603 +        return annotations;
  44.604 +    }
  44.605 +
  44.606 +    byte[] getRawParameterAnnotations() {
  44.607 +        return parameterAnnotations;
  44.608 +    }
  44.609 +
  44.610 +    /**
  44.611 +     * @throws NullPointerException {@inheritDoc}
  44.612 +     * @since 1.5
  44.613 +     */
  44.614 +    public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
  44.615 +        if (annotationClass == null)
  44.616 +            throw new NullPointerException();
  44.617 +
  44.618 +        return (T) declaredAnnotations().get(annotationClass);
  44.619 +    }
  44.620 +
  44.621 +    /**
  44.622 +     * @since 1.5
  44.623 +     */
  44.624 +    public Annotation[] getDeclaredAnnotations()  {
  44.625 +        return AnnotationParser.toArray(declaredAnnotations());
  44.626 +    }
  44.627 +
  44.628 +    private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
  44.629 +
  44.630 +    private synchronized  Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
  44.631 +        if (declaredAnnotations == null) {
  44.632 +            declaredAnnotations = AnnotationParser.parseAnnotations(
  44.633 +                annotations, sun.misc.SharedSecrets.getJavaLangAccess().
  44.634 +                getConstantPool(getDeclaringClass()),
  44.635 +                getDeclaringClass());
  44.636 +        }
  44.637 +        return declaredAnnotations;
  44.638 +    }
  44.639 +
  44.640 +    /**
  44.641 +     * Returns an array of arrays that represent the annotations on the formal
  44.642 +     * parameters, in declaration order, of the method represented by
  44.643 +     * this {@code Constructor} object. (Returns an array of length zero if the
  44.644 +     * underlying method is parameterless.  If the method has one or more
  44.645 +     * parameters, a nested array of length zero is returned for each parameter
  44.646 +     * with no annotations.) The annotation objects contained in the returned
  44.647 +     * arrays are serializable.  The caller of this method is free to modify
  44.648 +     * the returned arrays; it will have no effect on the arrays returned to
  44.649 +     * other callers.
  44.650 +     *
  44.651 +     * @return an array of arrays that represent the annotations on the formal
  44.652 +     *    parameters, in declaration order, of the method represented by this
  44.653 +     *    Constructor object
  44.654 +     * @since 1.5
  44.655 +     */
  44.656 +    public Annotation[][] getParameterAnnotations() {
  44.657 +        int numParameters = parameterTypes.length;
  44.658 +        if (parameterAnnotations == null)
  44.659 +            return new Annotation[numParameters][0];
  44.660 +
  44.661 +        Annotation[][] result = AnnotationParser.parseParameterAnnotations(
  44.662 +            parameterAnnotations,
  44.663 +            sun.misc.SharedSecrets.getJavaLangAccess().
  44.664 +                getConstantPool(getDeclaringClass()),
  44.665 +            getDeclaringClass());
  44.666 +        if (result.length != numParameters) {
  44.667 +            Class<?> declaringClass = getDeclaringClass();
  44.668 +            if (declaringClass.isEnum() ||
  44.669 +                declaringClass.isAnonymousClass() ||
  44.670 +                declaringClass.isLocalClass() )
  44.671 +                ; // Can't do reliable parameter counting
  44.672 +            else {
  44.673 +                if (!declaringClass.isMemberClass() || // top-level
  44.674 +                    // Check for the enclosing instance parameter for
  44.675 +                    // non-static member classes
  44.676 +                    (declaringClass.isMemberClass() &&
  44.677 +                     ((declaringClass.getModifiers() & Modifier.STATIC) == 0)  &&
  44.678 +                     result.length + 1 != numParameters) ) {
  44.679 +                    throw new AnnotationFormatError(
  44.680 +                              "Parameter annotations don't match number of parameters");
  44.681 +                }
  44.682 +            }
  44.683 +        }
  44.684 +        return result;
  44.685 +    }
  44.686 +}
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/emul/mini/src/main/java/java/lang/reflect/InvocationHandler.java	Mon Jan 28 18:14:14 2013 +0100
    45.3 @@ -0,0 +1,95 @@
    45.4 +/*
    45.5 + * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved.
    45.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    45.7 + *
    45.8 + * This code is free software; you can redistribute it and/or modify it
    45.9 + * under the terms of the GNU General Public License version 2 only, as
   45.10 + * published by the Free Software Foundation.  Oracle designates this
   45.11 + * particular file as subject to the "Classpath" exception as provided
   45.12 + * by Oracle in the LICENSE file that accompanied this code.
   45.13 + *
   45.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   45.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   45.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   45.17 + * version 2 for more details (a copy is included in the LICENSE file that
   45.18 + * accompanied this code).
   45.19 + *
   45.20 + * You should have received a copy of the GNU General Public License version
   45.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   45.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   45.23 + *
   45.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   45.25 + * or visit www.oracle.com if you need additional information or have any
   45.26 + * questions.
   45.27 + */
   45.28 +
   45.29 +package java.lang.reflect;
   45.30 +
   45.31 +/**
   45.32 + * {@code InvocationHandler} is the interface implemented by
   45.33 + * the <i>invocation handler</i> of a proxy instance.
   45.34 + *
   45.35 + * <p>Each proxy instance has an associated invocation handler.
   45.36 + * When a method is invoked on a proxy instance, the method
   45.37 + * invocation is encoded and dispatched to the {@code invoke}
   45.38 + * method of its invocation handler.
   45.39 + *
   45.40 + * @author      Peter Jones
   45.41 + * @see         Proxy
   45.42 + * @since       1.3
   45.43 + */
   45.44 +public interface InvocationHandler {
   45.45 +
   45.46 +    /**
   45.47 +     * Processes a method invocation on a proxy instance and returns
   45.48 +     * the result.  This method will be invoked on an invocation handler
   45.49 +     * when a method is invoked on a proxy instance that it is
   45.50 +     * associated with.
   45.51 +     *
   45.52 +     * @param   proxy the proxy instance that the method was invoked on
   45.53 +     *
   45.54 +     * @param   method the {@code Method} instance corresponding to
   45.55 +     * the interface method invoked on the proxy instance.  The declaring
   45.56 +     * class of the {@code Method} object will be the interface that
   45.57 +     * the method was declared in, which may be a superinterface of the
   45.58 +     * proxy interface that the proxy class inherits the method through.
   45.59 +     *
   45.60 +     * @param   args an array of objects containing the values of the
   45.61 +     * arguments passed in the method invocation on the proxy instance,
   45.62 +     * or {@code null} if interface method takes no arguments.
   45.63 +     * Arguments of primitive types are wrapped in instances of the
   45.64 +     * appropriate primitive wrapper class, such as
   45.65 +     * {@code java.lang.Integer} or {@code java.lang.Boolean}.
   45.66 +     *
   45.67 +     * @return  the value to return from the method invocation on the
   45.68 +     * proxy instance.  If the declared return type of the interface
   45.69 +     * method is a primitive type, then the value returned by
   45.70 +     * this method must be an instance of the corresponding primitive
   45.71 +     * wrapper class; otherwise, it must be a type assignable to the
   45.72 +     * declared return type.  If the value returned by this method is
   45.73 +     * {@code null} and the interface method's return type is
   45.74 +     * primitive, then a {@code NullPointerException} will be
   45.75 +     * thrown by the method invocation on the proxy instance.  If the
   45.76 +     * value returned by this method is otherwise not compatible with
   45.77 +     * the interface method's declared return type as described above,
   45.78 +     * a {@code ClassCastException} will be thrown by the method
   45.79 +     * invocation on the proxy instance.
   45.80 +     *
   45.81 +     * @throws  Throwable the exception to throw from the method
   45.82 +     * invocation on the proxy instance.  The exception's type must be
   45.83 +     * assignable either to any of the exception types declared in the
   45.84 +     * {@code throws} clause of the interface method or to the
   45.85 +     * unchecked exception types {@code java.lang.RuntimeException}
   45.86 +     * or {@code java.lang.Error}.  If a checked exception is
   45.87 +     * thrown by this method that is not assignable to any of the
   45.88 +     * exception types declared in the {@code throws} clause of
   45.89 +     * the interface method, then an
   45.90 +     * {@link UndeclaredThrowableException} containing the
   45.91 +     * exception that was thrown by this method will be thrown by the
   45.92 +     * method invocation on the proxy instance.
   45.93 +     *
   45.94 +     * @see     UndeclaredThrowableException
   45.95 +     */
   45.96 +    public Object invoke(Object proxy, Method method, Object[] args)
   45.97 +        throws Throwable;
   45.98 +}
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/emul/mini/src/main/java/java/lang/reflect/Proxy.java	Mon Jan 28 18:14:14 2013 +0100
    46.3 @@ -0,0 +1,666 @@
    46.4 +/*
    46.5 + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
    46.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    46.7 + *
    46.8 + * This code is free software; you can redistribute it and/or modify it
    46.9 + * under the terms of the GNU General Public License version 2 only, as
   46.10 + * published by the Free Software Foundation.  Oracle designates this
   46.11 + * particular file as subject to the "Classpath" exception as provided
   46.12 + * by Oracle in the LICENSE file that accompanied this code.
   46.13 + *
   46.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   46.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   46.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   46.17 + * version 2 for more details (a copy is included in the LICENSE file that
   46.18 + * accompanied this code).
   46.19 + *
   46.20 + * You should have received a copy of the GNU General Public License version
   46.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   46.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   46.23 + *
   46.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   46.25 + * or visit www.oracle.com if you need additional information or have any
   46.26 + * questions.
   46.27 + */
   46.28 +
   46.29 +package java.lang.reflect;
   46.30 +
   46.31 +import java.lang.ref.Reference;
   46.32 +import java.lang.ref.WeakReference;
   46.33 +import java.util.Arrays;
   46.34 +import java.util.Collections;
   46.35 +import java.util.HashMap;
   46.36 +import java.util.HashSet;
   46.37 +import java.util.Map;
   46.38 +import java.util.Set;
   46.39 +import java.util.List;
   46.40 +import java.util.WeakHashMap;
   46.41 +import sun.misc.ProxyGenerator;
   46.42 +
   46.43 +/**
   46.44 + * {@code Proxy} provides static methods for creating dynamic proxy
   46.45 + * classes and instances, and it is also the superclass of all
   46.46 + * dynamic proxy classes created by those methods.
   46.47 + *
   46.48 + * <p>To create a proxy for some interface {@code Foo}:
   46.49 + * <pre>
   46.50 + *     InvocationHandler handler = new MyInvocationHandler(...);
   46.51 + *     Class proxyClass = Proxy.getProxyClass(
   46.52 + *         Foo.class.getClassLoader(), new Class[] { Foo.class });
   46.53 + *     Foo f = (Foo) proxyClass.
   46.54 + *         getConstructor(new Class[] { InvocationHandler.class }).
   46.55 + *         newInstance(new Object[] { handler });
   46.56 + * </pre>
   46.57 + * or more simply:
   46.58 + * <pre>
   46.59 + *     Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
   46.60 + *                                          new Class[] { Foo.class },
   46.61 + *                                          handler);
   46.62 + * </pre>
   46.63 + *
   46.64 + * <p>A <i>dynamic proxy class</i> (simply referred to as a <i>proxy
   46.65 + * class</i> below) is a class that implements a list of interfaces
   46.66 + * specified at runtime when the class is created, with behavior as
   46.67 + * described below.
   46.68 + *
   46.69 + * A <i>proxy interface</i> is such an interface that is implemented
   46.70 + * by a proxy class.
   46.71 + *
   46.72 + * A <i>proxy instance</i> is an instance of a proxy class.
   46.73 + *
   46.74 + * Each proxy instance has an associated <i>invocation handler</i>
   46.75 + * object, which implements the interface {@link InvocationHandler}.
   46.76 + * A method invocation on a proxy instance through one of its proxy
   46.77 + * interfaces will be dispatched to the {@link InvocationHandler#invoke
   46.78 + * invoke} method of the instance's invocation handler, passing the proxy
   46.79 + * instance, a {@code java.lang.reflect.Method} object identifying
   46.80 + * the method that was invoked, and an array of type {@code Object}
   46.81 + * containing the arguments.  The invocation handler processes the
   46.82 + * encoded method invocation as appropriate and the result that it
   46.83 + * returns will be returned as the result of the method invocation on
   46.84 + * the proxy instance.
   46.85 + *
   46.86 + * <p>A proxy class has the following properties:
   46.87 + *
   46.88 + * <ul>
   46.89 + * <li>Proxy classes are public, final, and not abstract.
   46.90 + *
   46.91 + * <li>The unqualified name of a proxy class is unspecified.  The space
   46.92 + * of class names that begin with the string {@code "$Proxy"}
   46.93 + * should be, however, reserved for proxy classes.
   46.94 + *
   46.95 + * <li>A proxy class extends {@code java.lang.reflect.Proxy}.
   46.96 + *
   46.97 + * <li>A proxy class implements exactly the interfaces specified at its
   46.98 + * creation, in the same order.
   46.99 + *
  46.100 + * <li>If a proxy class implements a non-public interface, then it will
  46.101 + * be defined in the same package as that interface.  Otherwise, the
  46.102 + * package of a proxy class is also unspecified.  Note that package
  46.103 + * sealing will not prevent a proxy class from being successfully defined
  46.104 + * in a particular package at runtime, and neither will classes already
  46.105 + * defined by the same class loader and the same package with particular
  46.106 + * signers.
  46.107 + *
  46.108 + * <li>Since a proxy class implements all of the interfaces specified at
  46.109 + * its creation, invoking {@code getInterfaces} on its
  46.110 + * {@code Class} object will return an array containing the same
  46.111 + * list of interfaces (in the order specified at its creation), invoking
  46.112 + * {@code getMethods} on its {@code Class} object will return
  46.113 + * an array of {@code Method} objects that include all of the
  46.114 + * methods in those interfaces, and invoking {@code getMethod} will
  46.115 + * find methods in the proxy interfaces as would be expected.
  46.116 + *
  46.117 + * <li>The {@link Proxy#isProxyClass Proxy.isProxyClass} method will
  46.118 + * return true if it is passed a proxy class-- a class returned by
  46.119 + * {@code Proxy.getProxyClass} or the class of an object returned by
  46.120 + * {@code Proxy.newProxyInstance}-- and false otherwise.
  46.121 + *
  46.122 + * <li>The {@code java.security.ProtectionDomain} of a proxy class
  46.123 + * is the same as that of system classes loaded by the bootstrap class
  46.124 + * loader, such as {@code java.lang.Object}, because the code for a
  46.125 + * proxy class is generated by trusted system code.  This protection
  46.126 + * domain will typically be granted
  46.127 + * {@code java.security.AllPermission}.
  46.128 + *
  46.129 + * <li>Each proxy class has one public constructor that takes one argument,
  46.130 + * an implementation of the interface {@link InvocationHandler}, to set
  46.131 + * the invocation handler for a proxy instance.  Rather than having to use
  46.132 + * the reflection API to access the public constructor, a proxy instance
  46.133 + * can be also be created by calling the {@link Proxy#newProxyInstance
  46.134 + * Proxy.newProxyInstance} method, which combines the actions of calling
  46.135 + * {@link Proxy#getProxyClass Proxy.getProxyClass} with invoking the
  46.136 + * constructor with an invocation handler.
  46.137 + * </ul>
  46.138 + *
  46.139 + * <p>A proxy instance has the following properties:
  46.140 + *
  46.141 + * <ul>
  46.142 + * <li>Given a proxy instance {@code proxy} and one of the
  46.143 + * interfaces implemented by its proxy class {@code Foo}, the
  46.144 + * following expression will return true:
  46.145 + * <pre>
  46.146 + *     {@code proxy instanceof Foo}
  46.147 + * </pre>
  46.148 + * and the following cast operation will succeed (rather than throwing
  46.149 + * a {@code ClassCastException}):
  46.150 + * <pre>
  46.151 + *     {@code (Foo) proxy}
  46.152 + * </pre>
  46.153 + *
  46.154 + * <li>Each proxy instance has an associated invocation handler, the one
  46.155 + * that was passed to its constructor.  The static
  46.156 + * {@link Proxy#getInvocationHandler Proxy.getInvocationHandler} method
  46.157 + * will return the invocation handler associated with the proxy instance
  46.158 + * passed as its argument.
  46.159 + *
  46.160 + * <li>An interface method invocation on a proxy instance will be
  46.161 + * encoded and dispatched to the invocation handler's {@link
  46.162 + * InvocationHandler#invoke invoke} method as described in the
  46.163 + * documentation for that method.
  46.164 + *
  46.165 + * <li>An invocation of the {@code hashCode},
  46.166 + * {@code equals}, or {@code toString} methods declared in
  46.167 + * {@code java.lang.Object} on a proxy instance will be encoded and
  46.168 + * dispatched to the invocation handler's {@code invoke} method in
  46.169 + * the same manner as interface method invocations are encoded and
  46.170 + * dispatched, as described above.  The declaring class of the
  46.171 + * {@code Method} object passed to {@code invoke} will be
  46.172 + * {@code java.lang.Object}.  Other public methods of a proxy
  46.173 + * instance inherited from {@code java.lang.Object} are not
  46.174 + * overridden by a proxy class, so invocations of those methods behave
  46.175 + * like they do for instances of {@code java.lang.Object}.
  46.176 + * </ul>
  46.177 + *
  46.178 + * <h3>Methods Duplicated in Multiple Proxy Interfaces</h3>
  46.179 + *
  46.180 + * <p>When two or more interfaces of a proxy class contain a method with
  46.181 + * the same name and parameter signature, the order of the proxy class's
  46.182 + * interfaces becomes significant.  When such a <i>duplicate method</i>
  46.183 + * is invoked on a proxy instance, the {@code Method} object passed
  46.184 + * to the invocation handler will not necessarily be the one whose
  46.185 + * declaring class is assignable from the reference type of the interface
  46.186 + * that the proxy's method was invoked through.  This limitation exists
  46.187 + * because the corresponding method implementation in the generated proxy
  46.188 + * class cannot determine which interface it was invoked through.
  46.189 + * Therefore, when a duplicate method is invoked on a proxy instance,
  46.190 + * the {@code Method} object for the method in the foremost interface
  46.191 + * that contains the method (either directly or inherited through a
  46.192 + * superinterface) in the proxy class's list of interfaces is passed to
  46.193 + * the invocation handler's {@code invoke} method, regardless of the
  46.194 + * reference type through which the method invocation occurred.
  46.195 + *
  46.196 + * <p>If a proxy interface contains a method with the same name and
  46.197 + * parameter signature as the {@code hashCode}, {@code equals},
  46.198 + * or {@code toString} methods of {@code java.lang.Object},
  46.199 + * when such a method is invoked on a proxy instance, the
  46.200 + * {@code Method} object passed to the invocation handler will have
  46.201 + * {@code java.lang.Object} as its declaring class.  In other words,
  46.202 + * the public, non-final methods of {@code java.lang.Object}
  46.203 + * logically precede all of the proxy interfaces for the determination of
  46.204 + * which {@code Method} object to pass to the invocation handler.
  46.205 + *
  46.206 + * <p>Note also that when a duplicate method is dispatched to an
  46.207 + * invocation handler, the {@code invoke} method may only throw
  46.208 + * checked exception types that are assignable to one of the exception
  46.209 + * types in the {@code throws} clause of the method in <i>all</i> of
  46.210 + * the proxy interfaces that it can be invoked through.  If the
  46.211 + * {@code invoke} method throws a checked exception that is not
  46.212 + * assignable to any of the exception types declared by the method in one
  46.213 + * of the proxy interfaces that it can be invoked through, then an
  46.214 + * unchecked {@code UndeclaredThrowableException} will be thrown by
  46.215 + * the invocation on the proxy instance.  This restriction means that not
  46.216 + * all of the exception types returned by invoking
  46.217 + * {@code getExceptionTypes} on the {@code Method} object
  46.218 + * passed to the {@code invoke} method can necessarily be thrown
  46.219 + * successfully by the {@code invoke} method.
  46.220 + *
  46.221 + * @author      Peter Jones
  46.222 + * @see         InvocationHandler
  46.223 + * @since       1.3
  46.224 + */
  46.225 +public class Proxy implements java.io.Serializable {
  46.226 +
  46.227 +    private static final long serialVersionUID = -2222568056686623797L;
  46.228 +
  46.229 +    /** prefix for all proxy class names */
  46.230 +    private final static String proxyClassNamePrefix = "$Proxy";
  46.231 +
  46.232 +    /** parameter types of a proxy class constructor */
  46.233 +    private final static Class[] constructorParams =
  46.234 +        { InvocationHandler.class };
  46.235 +
  46.236 +    /** maps a class loader to the proxy class cache for that loader */
  46.237 +    private static Map<ClassLoader, Map<List<String>, Object>> loaderToCache
  46.238 +        = new WeakHashMap<>();
  46.239 +
  46.240 +    /** marks that a particular proxy class is currently being generated */
  46.241 +    private static Object pendingGenerationMarker = new Object();
  46.242 +
  46.243 +    /** next number to use for generation of unique proxy class names */
  46.244 +    private static long nextUniqueNumber = 0;
  46.245 +    private static Object nextUniqueNumberLock = new Object();
  46.246 +
  46.247 +    /** set of all generated proxy classes, for isProxyClass implementation */
  46.248 +    private static Map<Class<?>, Void> proxyClasses =
  46.249 +        Collections.synchronizedMap(new WeakHashMap<Class<?>, Void>());
  46.250 +
  46.251 +    /**
  46.252 +     * the invocation handler for this proxy instance.
  46.253 +     * @serial
  46.254 +     */
  46.255 +    protected InvocationHandler h;
  46.256 +
  46.257 +    /**
  46.258 +     * Prohibits instantiation.
  46.259 +     */
  46.260 +    private Proxy() {
  46.261 +    }
  46.262 +
  46.263 +    /**
  46.264 +     * Constructs a new {@code Proxy} instance from a subclass
  46.265 +     * (typically, a dynamic proxy class) with the specified value
  46.266 +     * for its invocation handler.
  46.267 +     *
  46.268 +     * @param   h the invocation handler for this proxy instance
  46.269 +     */
  46.270 +    protected Proxy(InvocationHandler h) {
  46.271 +        this.h = h;
  46.272 +    }
  46.273 +
  46.274 +    /**
  46.275 +     * Returns the {@code java.lang.Class} object for a proxy class
  46.276 +     * given a class loader and an array of interfaces.  The proxy class
  46.277 +     * will be defined by the specified class loader and will implement
  46.278 +     * all of the supplied interfaces.  If a proxy class for the same
  46.279 +     * permutation of interfaces has already been defined by the class
  46.280 +     * loader, then the existing proxy class will be returned; otherwise,
  46.281 +     * a proxy class for those interfaces will be generated dynamically
  46.282 +     * and defined by the class loader.
  46.283 +     *
  46.284 +     * <p>There are several restrictions on the parameters that may be
  46.285 +     * passed to {@code Proxy.getProxyClass}:
  46.286 +     *
  46.287 +     * <ul>
  46.288 +     * <li>All of the {@code Class} objects in the
  46.289 +     * {@code interfaces} array must represent interfaces, not
  46.290 +     * classes or primitive types.
  46.291 +     *
  46.292 +     * <li>No two elements in the {@code interfaces} array may
  46.293 +     * refer to identical {@code Class} objects.
  46.294 +     *
  46.295 +     * <li>All of the interface types must be visible by name through the
  46.296 +     * specified class loader.  In other words, for class loader
  46.297 +     * {@code cl} and every interface {@code i}, the following
  46.298 +     * expression must be true:
  46.299 +     * <pre>
  46.300 +     *     Class.forName(i.getName(), false, cl) == i
  46.301 +     * </pre>
  46.302 +     *
  46.303 +     * <li>All non-public interfaces must be in the same package;
  46.304 +     * otherwise, it would not be possible for the proxy class to
  46.305 +     * implement all of the interfaces, regardless of what package it is
  46.306 +     * defined in.
  46.307 +     *
  46.308 +     * <li>For any set of member methods of the specified interfaces
  46.309 +     * that have the same signature:
  46.310 +     * <ul>
  46.311 +     * <li>If the return type of any of the methods is a primitive
  46.312 +     * type or void, then all of the methods must have that same
  46.313 +     * return type.
  46.314 +     * <li>Otherwise, one of the methods must have a return type that
  46.315 +     * is assignable to all of the return types of the rest of the
  46.316 +     * methods.
  46.317 +     * </ul>
  46.318 +     *
  46.319 +     * <li>The resulting proxy class must not exceed any limits imposed
  46.320 +     * on classes by the virtual machine.  For example, the VM may limit
  46.321 +     * the number of interfaces that a class may implement to 65535; in
  46.322 +     * that case, the size of the {@code interfaces} array must not
  46.323 +     * exceed 65535.
  46.324 +     * </ul>
  46.325 +     *
  46.326 +     * <p>If any of these restrictions are violated,
  46.327 +     * {@code Proxy.getProxyClass} will throw an
  46.328 +     * {@code IllegalArgumentException}.  If the {@code interfaces}
  46.329 +     * array argument or any of its elements are {@code null}, a
  46.330 +     * {@code NullPointerException} will be thrown.
  46.331 +     *
  46.332 +     * <p>Note that the order of the specified proxy interfaces is
  46.333 +     * significant: two requests for a proxy class with the same combination
  46.334 +     * of interfaces but in a different order will result in two distinct
  46.335 +     * proxy classes.
  46.336 +     *
  46.337 +     * @param   loader the class loader to define the proxy class
  46.338 +     * @param   interfaces the list of interfaces for the proxy class
  46.339 +     *          to implement
  46.340 +     * @return  a proxy class that is defined in the specified class loader
  46.341 +     *          and that implements the specified interfaces
  46.342 +     * @throws  IllegalArgumentException if any of the restrictions on the
  46.343 +     *          parameters that may be passed to {@code getProxyClass}
  46.344 +     *          are violated
  46.345 +     * @throws  NullPointerException if the {@code interfaces} array
  46.346 +     *          argument or any of its elements are {@code null}
  46.347 +     */
  46.348 +    public static Class<?> getProxyClass(ClassLoader loader,
  46.349 +                                         Class<?>... interfaces)
  46.350 +        throws IllegalArgumentException
  46.351 +    {
  46.352 +        if (interfaces.length > 65535) {
  46.353 +            throw new IllegalArgumentException("interface limit exceeded");
  46.354 +        }
  46.355 +
  46.356 +        Class<?> proxyClass = null;
  46.357 +
  46.358 +        /* collect interface names to use as key for proxy class cache */
  46.359 +        String[] interfaceNames = new String[interfaces.length];
  46.360 +
  46.361 +        // for detecting duplicates
  46.362 +        Set<Class<?>> interfaceSet = new HashSet<>();
  46.363 +
  46.364 +        for (int i = 0; i < interfaces.length; i++) {
  46.365 +            /*
  46.366 +             * Verify that the class loader resolves the name of this
  46.367 +             * interface to the same Class object.
  46.368 +             */
  46.369 +            String interfaceName = interfaces[i].getName();
  46.370 +            Class<?> interfaceClass = null;
  46.371 +            try {
  46.372 +                interfaceClass = Class.forName(interfaceName, false, loader);
  46.373 +            } catch (ClassNotFoundException e) {
  46.374 +            }
  46.375 +            if (interfaceClass != interfaces[i]) {
  46.376 +                throw new IllegalArgumentException(
  46.377 +                    interfaces[i] + " is not visible from class loader");
  46.378 +            }
  46.379 +
  46.380 +            /*
  46.381 +             * Verify that the Class object actually represents an
  46.382 +             * interface.
  46.383 +             */
  46.384 +            if (!interfaceClass.isInterface()) {
  46.385 +                throw new IllegalArgumentException(
  46.386 +                    interfaceClass.getName() + " is not an interface");
  46.387 +            }
  46.388 +
  46.389 +            /*
  46.390 +             * Verify that this interface is not a duplicate.
  46.391 +             */
  46.392 +            if (interfaceSet.contains(interfaceClass)) {
  46.393 +                throw new IllegalArgumentException(
  46.394 +                    "repeated interface: " + interfaceClass.getName());
  46.395 +            }
  46.396 +            interfaceSet.add(interfaceClass);
  46.397 +
  46.398 +            interfaceNames[i] = interfaceName;
  46.399 +        }
  46.400 +
  46.401 +        /*
  46.402 +         * Using string representations of the proxy interfaces as
  46.403 +         * keys in the proxy class cache (instead of their Class
  46.404 +         * objects) is sufficient because we require the proxy
  46.405 +         * interfaces to be resolvable by name through the supplied
  46.406 +         * class loader, and it has the advantage that using a string
  46.407 +         * representation of a class makes for an implicit weak
  46.408 +         * reference to the class.
  46.409 +         */
  46.410 +        List<String> key = Arrays.asList(interfaceNames);
  46.411 +
  46.412 +        /*
  46.413 +         * Find or create the proxy class cache for the class loader.
  46.414 +         */
  46.415 +        Map<List<String>, Object> cache;
  46.416 +        synchronized (loaderToCache) {
  46.417 +            cache = loaderToCache.get(loader);
  46.418 +            if (cache == null) {
  46.419 +                cache = new HashMap<>();
  46.420 +                loaderToCache.put(loader, cache);
  46.421 +            }
  46.422 +            /*
  46.423 +             * This mapping will remain valid for the duration of this
  46.424 +             * method, without further synchronization, because the mapping
  46.425 +             * will only be removed if the class loader becomes unreachable.
  46.426 +             */
  46.427 +        }
  46.428 +
  46.429 +        /*
  46.430 +         * Look up the list of interfaces in the proxy class cache using
  46.431 +         * the key.  This lookup will result in one of three possible
  46.432 +         * kinds of values:
  46.433 +         *     null, if there is currently no proxy class for the list of
  46.434 +         *         interfaces in the class loader,
  46.435 +         *     the pendingGenerationMarker object, if a proxy class for the
  46.436 +         *         list of interfaces is currently being generated,
  46.437 +         *     or a weak reference to a Class object, if a proxy class for
  46.438 +         *         the list of interfaces has already been generated.
  46.439 +         */
  46.440 +        synchronized (cache) {
  46.441 +            /*
  46.442 +             * Note that we need not worry about reaping the cache for
  46.443 +             * entries with cleared weak references because if a proxy class
  46.444 +             * has been garbage collected, its class loader will have been
  46.445 +             * garbage collected as well, so the entire cache will be reaped
  46.446 +             * from the loaderToCache map.
  46.447 +             */
  46.448 +            do {
  46.449 +                Object value = cache.get(key);
  46.450 +                if (value instanceof Reference) {
  46.451 +                    proxyClass = (Class<?>) ((Reference) value).get();
  46.452 +                }
  46.453 +                if (proxyClass != null) {
  46.454 +                    // proxy class already generated: return it
  46.455 +                    return proxyClass;
  46.456 +                } else if (value == pendingGenerationMarker) {
  46.457 +                    // proxy class being generated: wait for it
  46.458 +                    try {
  46.459 +                        cache.wait();
  46.460 +                    } catch (InterruptedException e) {
  46.461 +                        /*
  46.462 +                         * The class generation that we are waiting for should
  46.463 +                         * take a small, bounded time, so we can safely ignore
  46.464 +                         * thread interrupts here.
  46.465 +                         */
  46.466 +                    }
  46.467 +                    continue;
  46.468 +                } else {
  46.469 +                    /*
  46.470 +                     * No proxy class for this list of interfaces has been
  46.471 +                     * generated or is being generated, so we will go and
  46.472 +                     * generate it now.  Mark it as pending generation.
  46.473 +                     */
  46.474 +                    cache.put(key, pendingGenerationMarker);
  46.475 +                    break;
  46.476 +                }
  46.477 +            } while (true);
  46.478 +        }
  46.479 +
  46.480 +        try {
  46.481 +            String proxyPkg = null;     // package to define proxy class in
  46.482 +
  46.483 +            /*
  46.484 +             * Record the package of a non-public proxy interface so that the
  46.485 +             * proxy class will be defined in the same package.  Verify that
  46.486 +             * all non-public proxy interfaces are in the same package.
  46.487 +             */
  46.488 +            for (int i = 0; i < interfaces.length; i++) {
  46.489 +                int flags = interfaces[i].getModifiers();
  46.490 +                if (!Modifier.isPublic(flags)) {
  46.491 +                    String name = interfaces[i].getName();
  46.492 +                    int n = name.lastIndexOf('.');
  46.493 +                    String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
  46.494 +                    if (proxyPkg == null) {
  46.495 +                        proxyPkg = pkg;
  46.496 +                    } else if (!pkg.equals(proxyPkg)) {
  46.497 +                        throw new IllegalArgumentException(
  46.498 +                            "non-public interfaces from different packages");
  46.499 +                    }
  46.500 +                }
  46.501 +            }
  46.502 +
  46.503 +            if (proxyPkg == null) {     // if no non-public proxy interfaces,
  46.504 +                proxyPkg = "";          // use the unnamed package
  46.505 +            }
  46.506 +
  46.507 +            {
  46.508 +                /*
  46.509 +                 * Choose a name for the proxy class to generate.
  46.510 +                 */
  46.511 +                long num;
  46.512 +                synchronized (nextUniqueNumberLock) {
  46.513 +                    num = nextUniqueNumber++;
  46.514 +                }
  46.515 +                String proxyName = proxyPkg + proxyClassNamePrefix + num;
  46.516 +                /*
  46.517 +                 * Verify that the class loader hasn't already
  46.518 +                 * defined a class with the chosen name.
  46.519 +                 */
  46.520 +
  46.521 +                /*
  46.522 +                 * Generate the specified proxy class.
  46.523 +                 */
  46.524 +                byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
  46.525 +                    proxyName, interfaces);
  46.526 +                try {
  46.527 +                    proxyClass = defineClass0(loader, proxyName,
  46.528 +                        proxyClassFile, 0, proxyClassFile.length);
  46.529 +                } catch (ClassFormatError e) {
  46.530 +                    /*
  46.531 +                     * A ClassFormatError here means that (barring bugs in the
  46.532 +                     * proxy class generation code) there was some other
  46.533 +                     * invalid aspect of the arguments supplied to the proxy
  46.534 +                     * class creation (such as virtual machine limitations
  46.535 +                     * exceeded).
  46.536 +                     */
  46.537 +                    throw new IllegalArgumentException(e.toString());
  46.538 +                }
  46.539 +            }
  46.540 +            // add to set of all generated proxy classes, for isProxyClass
  46.541 +            proxyClasses.put(proxyClass, null);
  46.542 +
  46.543 +        } finally {
  46.544 +            /*
  46.545 +             * We must clean up the "pending generation" state of the proxy
  46.546 +             * class cache entry somehow.  If a proxy class was successfully
  46.547 +             * generated, store it in the cache (with a weak reference);
  46.548 +             * otherwise, remove the reserved entry.  In all cases, notify
  46.549 +             * all waiters on reserved entries in this cache.
  46.550 +             */
  46.551 +            synchronized (cache) {
  46.552 +                if (proxyClass != null) {
  46.553 +                    cache.put(key, new WeakReference<Class<?>>(proxyClass));
  46.554 +                } else {
  46.555 +                    cache.remove(key);
  46.556 +                }
  46.557 +                cache.notifyAll();
  46.558 +            }
  46.559 +        }
  46.560 +        return proxyClass;
  46.561 +    }
  46.562 +
  46.563 +    /**
  46.564 +     * Returns an instance of a proxy class for the specified interfaces
  46.565 +     * that dispatches method invocations to the specified invocation
  46.566 +     * handler.  This method is equivalent to:
  46.567 +     * <pre>
  46.568 +     *     Proxy.getProxyClass(loader, interfaces).
  46.569 +     *         getConstructor(new Class[] { InvocationHandler.class }).
  46.570 +     *         newInstance(new Object[] { handler });
  46.571 +     * </pre>
  46.572 +     *
  46.573 +     * <p>{@code Proxy.newProxyInstance} throws
  46.574 +     * {@code IllegalArgumentException} for the same reasons that
  46.575 +     * {@code Proxy.getProxyClass} does.
  46.576 +     *
  46.577 +     * @param   loader the class loader to define the proxy class
  46.578 +     * @param   interfaces the list of interfaces for the proxy class
  46.579 +     *          to implement
  46.580 +     * @param   h the invocation handler to dispatch method invocations to
  46.581 +     * @return  a proxy instance with the specified invocation handler of a
  46.582 +     *          proxy class that is defined by the specified class loader
  46.583 +     *          and that implements the specified interfaces
  46.584 +     * @throws  IllegalArgumentException if any of the restrictions on the
  46.585 +     *          parameters that may be passed to {@code getProxyClass}
  46.586 +     *          are violated
  46.587 +     * @throws  NullPointerException if the {@code interfaces} array
  46.588 +     *          argument or any of its elements are {@code null}, or
  46.589 +     *          if the invocation handler, {@code h}, is
  46.590 +     *          {@code null}
  46.591 +     */
  46.592 +    public static Object newProxyInstance(ClassLoader loader,
  46.593 +                                          Class<?>[] interfaces,
  46.594 +                                          InvocationHandler h)
  46.595 +        throws IllegalArgumentException
  46.596 +    {
  46.597 +        if (h == null) {
  46.598 +            throw new NullPointerException();
  46.599 +        }
  46.600 +
  46.601 +        /*
  46.602 +         * Look up or generate the designated proxy class.
  46.603 +         */
  46.604 +        Class<?> cl = getProxyClass(loader, interfaces);
  46.605 +
  46.606 +        /*
  46.607 +         * Invoke its constructor with the designated invocation handler.
  46.608 +         */
  46.609 +        try {
  46.610 +            Constructor cons = cl.getConstructor(constructorParams);
  46.611 +            return cons.newInstance(new Object[] { h });
  46.612 +        } catch (NoSuchMethodException e) {
  46.613 +            throw new InternalError(e.toString());
  46.614 +        } catch (IllegalAccessException e) {
  46.615 +            throw new InternalError(e.toString());
  46.616 +        } catch (InstantiationException e) {
  46.617 +            throw new InternalError(e.toString());
  46.618 +        } catch (InvocationTargetException e) {
  46.619 +            throw new InternalError(e.toString());
  46.620 +        }
  46.621 +    }
  46.622 +
  46.623 +    /**
  46.624 +     * Returns true if and only if the specified class was dynamically
  46.625 +     * generated to be a proxy class using the {@code getProxyClass}
  46.626 +     * method or the {@code newProxyInstance} method.
  46.627 +     *
  46.628 +     * <p>The reliability of this method is important for the ability
  46.629 +     * to use it to make security decisions, so its implementation should
  46.630 +     * not just test if the class in question extends {@code Proxy}.
  46.631 +     *
  46.632 +     * @param   cl the class to test
  46.633 +     * @return  {@code true} if the class is a proxy class and
  46.634 +     *          {@code false} otherwise
  46.635 +     * @throws  NullPointerException if {@code cl} is {@code null}
  46.636 +     */
  46.637 +    public static boolean isProxyClass(Class<?> cl) {
  46.638 +        if (cl == null) {
  46.639 +            throw new NullPointerException();
  46.640 +        }
  46.641 +
  46.642 +        return proxyClasses.containsKey(cl);
  46.643 +    }
  46.644 +
  46.645 +    /**
  46.646 +     * Returns the invocation handler for the specified proxy instance.
  46.647 +     *
  46.648 +     * @param   proxy the proxy instance to return the invocation handler for
  46.649 +     * @return  the invocation handler for the proxy instance
  46.650 +     * @throws  IllegalArgumentException if the argument is not a
  46.651 +     *          proxy instance
  46.652 +     */
  46.653 +    public static InvocationHandler getInvocationHandler(Object proxy)
  46.654 +        throws IllegalArgumentException
  46.655 +    {
  46.656 +        /*
  46.657 +         * Verify that the object is actually a proxy instance.
  46.658 +         */
  46.659 +        if (!isProxyClass(proxy.getClass())) {
  46.660 +            throw new IllegalArgumentException("not a proxy instance");
  46.661 +        }
  46.662 +
  46.663 +        Proxy p = (Proxy) proxy;
  46.664 +        return p.h;
  46.665 +    }
  46.666 +
  46.667 +    private static native Class defineClass0(ClassLoader loader, String name,
  46.668 +                                             byte[] b, int off, int len);
  46.669 +}
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/emul/mini/src/main/java/java/lang/reflect/UndeclaredThrowableException.java	Mon Jan 28 18:14:14 2013 +0100
    47.3 @@ -0,0 +1,119 @@
    47.4 +/*
    47.5 + * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved.
    47.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    47.7 + *
    47.8 + * This code is free software; you can redistribute it and/or modify it
    47.9 + * under the terms of the GNU General Public License version 2 only, as
   47.10 + * published by the Free Software Foundation.  Oracle designates this
   47.11 + * particular file as subject to the "Classpath" exception as provided
   47.12 + * by Oracle in the LICENSE file that accompanied this code.
   47.13 + *
   47.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   47.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   47.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   47.17 + * version 2 for more details (a copy is included in the LICENSE file that
   47.18 + * accompanied this code).
   47.19 + *
   47.20 + * You should have received a copy of the GNU General Public License version
   47.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   47.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   47.23 + *
   47.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   47.25 + * or visit www.oracle.com if you need additional information or have any
   47.26 + * questions.
   47.27 + */
   47.28 +
   47.29 +package java.lang.reflect;
   47.30 +
   47.31 +/**
   47.32 + * Thrown by a method invocation on a proxy instance if its invocation
   47.33 + * handler's {@link InvocationHandler#invoke invoke} method throws a
   47.34 + * checked exception (a {@code Throwable} that is not assignable
   47.35 + * to {@code RuntimeException} or {@code Error}) that
   47.36 + * is not assignable to any of the exception types declared in the
   47.37 + * {@code throws} clause of the method that was invoked on the
   47.38 + * proxy instance and dispatched to the invocation handler.
   47.39 + *
   47.40 + * <p>An {@code UndeclaredThrowableException} instance contains
   47.41 + * the undeclared checked exception that was thrown by the invocation
   47.42 + * handler, and it can be retrieved with the
   47.43 + * {@code getUndeclaredThrowable()} method.
   47.44 + * {@code UndeclaredThrowableException} extends
   47.45 + * {@code RuntimeException}, so it is an unchecked exception
   47.46 + * that wraps a checked exception.
   47.47 + *
   47.48 + * <p>As of release 1.4, this exception has been retrofitted to
   47.49 + * conform to the general purpose exception-chaining mechanism.  The
   47.50 + * "undeclared checked exception that was thrown by the invocation
   47.51 + * handler" that may be provided at construction time and accessed via
   47.52 + * the {@link #getUndeclaredThrowable()} method is now known as the
   47.53 + * <i>cause</i>, and may be accessed via the {@link
   47.54 + * Throwable#getCause()} method, as well as the aforementioned "legacy
   47.55 + * method."
   47.56 + *
   47.57 + * @author      Peter Jones
   47.58 + * @see         InvocationHandler
   47.59 + * @since       1.3
   47.60 + */
   47.61 +public class UndeclaredThrowableException extends RuntimeException {
   47.62 +    static final long serialVersionUID = 330127114055056639L;
   47.63 +
   47.64 +    /**
   47.65 +     * the undeclared checked exception that was thrown
   47.66 +     * @serial
   47.67 +     */
   47.68 +    private Throwable undeclaredThrowable;
   47.69 +
   47.70 +    /**
   47.71 +     * Constructs an {@code UndeclaredThrowableException} with the
   47.72 +     * specified {@code Throwable}.
   47.73 +     *
   47.74 +     * @param   undeclaredThrowable the undeclared checked exception
   47.75 +     *          that was thrown
   47.76 +     */
   47.77 +    public UndeclaredThrowableException(Throwable undeclaredThrowable) {
   47.78 +        super((Throwable) null);  // Disallow initCause
   47.79 +        this.undeclaredThrowable = undeclaredThrowable;
   47.80 +    }
   47.81 +
   47.82 +    /**
   47.83 +     * Constructs an {@code UndeclaredThrowableException} with the
   47.84 +     * specified {@code Throwable} and a detail message.
   47.85 +     *
   47.86 +     * @param   undeclaredThrowable the undeclared checked exception
   47.87 +     *          that was thrown
   47.88 +     * @param   s the detail message
   47.89 +     */
   47.90 +    public UndeclaredThrowableException(Throwable undeclaredThrowable,
   47.91 +                                        String s)
   47.92 +    {
   47.93 +        super(s, null);  // Disallow initCause
   47.94 +        this.undeclaredThrowable = undeclaredThrowable;
   47.95 +    }
   47.96 +
   47.97 +    /**
   47.98 +     * Returns the {@code Throwable} instance wrapped in this
   47.99 +     * {@code UndeclaredThrowableException}, which may be {@code null}.
  47.100 +     *
  47.101 +     * <p>This method predates the general-purpose exception chaining facility.
  47.102 +     * The {@link Throwable#getCause()} method is now the preferred means of
  47.103 +     * obtaining this information.
  47.104 +     *
  47.105 +     * @return the undeclared checked exception that was thrown
  47.106 +     */
  47.107 +    public Throwable getUndeclaredThrowable() {
  47.108 +        return undeclaredThrowable;
  47.109 +    }
  47.110 +
  47.111 +    /**
  47.112 +     * Returns the cause of this exception (the {@code Throwable}
  47.113 +     * instance wrapped in this {@code UndeclaredThrowableException},
  47.114 +     * which may be {@code null}).
  47.115 +     *
  47.116 +     * @return  the cause of this exception.
  47.117 +     * @since   1.4
  47.118 +     */
  47.119 +    public Throwable getCause() {
  47.120 +        return undeclaredThrowable;
  47.121 +    }
  47.122 +}