Emulation of ZipInputStream seems to be in good shape. Merging, so David can use the latest achievements in main development line
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 04 Feb 2013 09:37:56 +0100
changeset 656ef21eeecf47c
parent 636 8d0be6a9a809
parent 647 6b77554987e0
child 668 b4354a30d4dd
Emulation of ZipInputStream seems to be in good shape. Merging, so David can use the latest achievements in main development line
emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/System.java
launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Console.java
launcher/src/main/java/org/apidesign/bck2brwsr/launcher/MethodInvocation.java
     1.1 --- a/core/pom.xml	Fri Feb 01 16:34:51 2013 +0100
     1.2 +++ b/core/pom.xml	Mon Feb 04 09:37:56 2013 +0100
     1.3 @@ -38,6 +38,7 @@
     1.4      <dependency>
     1.5        <groupId>org.netbeans.api</groupId>
     1.6        <artifactId>org-openide-util-lookup</artifactId>
     1.7 +      <scope>provided</scope>
     1.8      </dependency>
     1.9    </dependencies>
    1.10      <description>Contains esential annotations for associating JavaScript code with
     2.1 --- a/emul/compact/pom.xml	Fri Feb 01 16:34:51 2013 +0100
     2.2 +++ b/emul/compact/pom.xml	Mon Feb 04 09:37:56 2013 +0100
     2.3 @@ -27,6 +27,11 @@
     2.4        <version>${project.version}</version>
     2.5        <scope>test</scope>
     2.6      </dependency>
     2.7 +    <dependency>
     2.8 +      <groupId>org.netbeans.api</groupId>
     2.9 +      <artifactId>org-openide-util-lookup</artifactId>
    2.10 +      <scope>test</scope>
    2.11 +    </dependency>
    2.12    </dependencies>
    2.13    <build>
    2.14        <plugins>
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/emul/compact/src/main/java/java/beans/ChangeListenerMap.java	Mon Feb 04 09:37:56 2013 +0100
     3.3 @@ -0,0 +1,248 @@
     3.4 +/*
     3.5 + * Copyright (c) 2007, 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 +package java.beans;
    3.29 +
    3.30 +import java.util.ArrayList;
    3.31 +import java.util.Collections;
    3.32 +import java.util.EventListener;
    3.33 +import java.util.EventListenerProxy;
    3.34 +import java.util.HashMap;
    3.35 +import java.util.List;
    3.36 +import java.util.Map;
    3.37 +import java.util.Map.Entry;
    3.38 +import java.util.Set;
    3.39 +import org.apidesign.bck2brwsr.emul.lang.System;
    3.40 +
    3.41 +/**
    3.42 + * This is an abstract class that provides base functionality
    3.43 + * for the {@link PropertyChangeSupport PropertyChangeSupport} class
    3.44 + * and the {@link VetoableChangeSupport VetoableChangeSupport} class.
    3.45 + *
    3.46 + * @see PropertyChangeListenerMap
    3.47 + * @see VetoableChangeListenerMap
    3.48 + *
    3.49 + * @author Sergey A. Malenkov
    3.50 + */
    3.51 +abstract class ChangeListenerMap<L extends EventListener> {
    3.52 +    private Map<String, L[]> map;
    3.53 +
    3.54 +    /**
    3.55 +     * Creates an array of listeners.
    3.56 +     * This method can be optimized by using
    3.57 +     * the same instance of the empty array
    3.58 +     * when {@code length} is equal to {@code 0}.
    3.59 +     *
    3.60 +     * @param length  the array length
    3.61 +     * @return        an array with specified length
    3.62 +     */
    3.63 +    protected abstract L[] newArray(int length);
    3.64 +
    3.65 +    /**
    3.66 +     * Creates a proxy listener for the specified property.
    3.67 +     *
    3.68 +     * @param name      the name of the property to listen on
    3.69 +     * @param listener  the listener to process events
    3.70 +     * @return          a proxy listener
    3.71 +     */
    3.72 +    protected abstract L newProxy(String name, L listener);
    3.73 +
    3.74 +    /**
    3.75 +     * Adds a listener to the list of listeners for the specified property.
    3.76 +     * This listener is called as many times as it was added.
    3.77 +     *
    3.78 +     * @param name      the name of the property to listen on
    3.79 +     * @param listener  the listener to process events
    3.80 +     */
    3.81 +    public final synchronized void add(String name, L listener) {
    3.82 +        if (this.map == null) {
    3.83 +            this.map = new HashMap<String, L[]>();
    3.84 +        }
    3.85 +        L[] array = this.map.get(name);
    3.86 +        int size = (array != null)
    3.87 +                ? array.length
    3.88 +                : 0;
    3.89 +
    3.90 +        L[] clone = newArray(size + 1);
    3.91 +        clone[size] = listener;
    3.92 +        if (array != null) {
    3.93 +            System.arraycopy(array, 0, clone, 0, size);
    3.94 +        }
    3.95 +        this.map.put(name, clone);
    3.96 +    }
    3.97 +
    3.98 +    /**
    3.99 +     * Removes a listener from the list of listeners for the specified property.
   3.100 +     * If the listener was added more than once to the same event source,
   3.101 +     * this listener will be notified one less time after being removed.
   3.102 +     *
   3.103 +     * @param name      the name of the property to listen on
   3.104 +     * @param listener  the listener to process events
   3.105 +     */
   3.106 +    public final synchronized void remove(String name, L listener) {
   3.107 +        if (this.map != null) {
   3.108 +            L[] array = this.map.get(name);
   3.109 +            if (array != null) {
   3.110 +                for (int i = 0; i < array.length; i++) {
   3.111 +                    if (listener.equals(array[i])) {
   3.112 +                        int size = array.length - 1;
   3.113 +                        if (size > 0) {
   3.114 +                            L[] clone = newArray(size);
   3.115 +                            System.arraycopy(array, 0, clone, 0, i);
   3.116 +                            System.arraycopy(array, i + 1, clone, i, size - i);
   3.117 +                            this.map.put(name, clone);
   3.118 +                        }
   3.119 +                        else {
   3.120 +                            this.map.remove(name);
   3.121 +                            if (this.map.isEmpty()) {
   3.122 +                                this.map = null;
   3.123 +                            }
   3.124 +                        }
   3.125 +                        break;
   3.126 +                    }
   3.127 +                }
   3.128 +            }
   3.129 +        }
   3.130 +    }
   3.131 +
   3.132 +    /**
   3.133 +     * Returns the list of listeners for the specified property.
   3.134 +     *
   3.135 +     * @param name  the name of the property
   3.136 +     * @return      the corresponding list of listeners
   3.137 +     */
   3.138 +    public final synchronized L[] get(String name) {
   3.139 +        return (this.map != null)
   3.140 +                ? this.map.get(name)
   3.141 +                : null;
   3.142 +    }
   3.143 +
   3.144 +    /**
   3.145 +     * Sets new list of listeners for the specified property.
   3.146 +     *
   3.147 +     * @param name       the name of the property
   3.148 +     * @param listeners  new list of listeners
   3.149 +     */
   3.150 +    public final void set(String name, L[] listeners) {
   3.151 +        if (listeners != null) {
   3.152 +            if (this.map == null) {
   3.153 +                this.map = new HashMap<String, L[]>();
   3.154 +            }
   3.155 +            this.map.put(name, listeners);
   3.156 +        }
   3.157 +        else if (this.map != null) {
   3.158 +            this.map.remove(name);
   3.159 +            if (this.map.isEmpty()) {
   3.160 +                this.map = null;
   3.161 +            }
   3.162 +        }
   3.163 +    }
   3.164 +
   3.165 +    /**
   3.166 +     * Returns all listeners in the map.
   3.167 +     *
   3.168 +     * @return an array of all listeners
   3.169 +     */
   3.170 +    public final synchronized L[] getListeners() {
   3.171 +        if (this.map == null) {
   3.172 +            return newArray(0);
   3.173 +        }
   3.174 +        List<L> list = new ArrayList<L>();
   3.175 +
   3.176 +        L[] listeners = this.map.get(null);
   3.177 +        if (listeners != null) {
   3.178 +            for (L listener : listeners) {
   3.179 +                list.add(listener);
   3.180 +            }
   3.181 +        }
   3.182 +        for (Entry<String, L[]> entry : this.map.entrySet()) {
   3.183 +            String name = entry.getKey();
   3.184 +            if (name != null) {
   3.185 +                for (L listener : entry.getValue()) {
   3.186 +                    list.add(newProxy(name, listener));
   3.187 +                }
   3.188 +            }
   3.189 +        }
   3.190 +        return list.toArray(newArray(list.size()));
   3.191 +    }
   3.192 +
   3.193 +    /**
   3.194 +     * Returns listeners that have been associated with the named property.
   3.195 +     *
   3.196 +     * @param name  the name of the property
   3.197 +     * @return an array of listeners for the named property
   3.198 +     */
   3.199 +    public final L[] getListeners(String name) {
   3.200 +        if (name != null) {
   3.201 +            L[] listeners = get(name);
   3.202 +            if (listeners != null) {
   3.203 +                return listeners.clone();
   3.204 +            }
   3.205 +        }
   3.206 +        return newArray(0);
   3.207 +    }
   3.208 +
   3.209 +    /**
   3.210 +     * Indicates whether the map contains
   3.211 +     * at least one listener to be notified.
   3.212 +     *
   3.213 +     * @param name  the name of the property
   3.214 +     * @return      {@code true} if at least one listener exists or
   3.215 +     *              {@code false} otherwise
   3.216 +     */
   3.217 +    public final synchronized boolean hasListeners(String name) {
   3.218 +        if (this.map == null) {
   3.219 +            return false;
   3.220 +        }
   3.221 +        L[] array = this.map.get(null);
   3.222 +        return (array != null) || ((name != null) && (null != this.map.get(name)));
   3.223 +    }
   3.224 +
   3.225 +    /**
   3.226 +     * Returns a set of entries from the map.
   3.227 +     * Each entry is a pair consisted of the property name
   3.228 +     * and the corresponding list of listeners.
   3.229 +     *
   3.230 +     * @return a set of entries from the map
   3.231 +     */
   3.232 +    public final Set<Entry<String, L[]>> getEntries() {
   3.233 +        return (this.map != null)
   3.234 +                ? this.map.entrySet()
   3.235 +                : Collections.<Entry<String, L[]>>emptySet();
   3.236 +    }
   3.237 +
   3.238 +    /**
   3.239 +     * Extracts a real listener from the proxy listener.
   3.240 +     * It is necessary because default proxy class is not serializable.
   3.241 +     *
   3.242 +     * @return a real listener
   3.243 +     */
   3.244 +    public final L extract(L listener) {
   3.245 +        while (listener instanceof EventListenerProxy) {
   3.246 +            EventListenerProxy<L> proxy = (EventListenerProxy<L>) listener;
   3.247 +            listener = proxy.getListener();
   3.248 +        }
   3.249 +        return listener;
   3.250 +    }
   3.251 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/emul/compact/src/main/java/java/beans/IndexedPropertyChangeEvent.java	Mon Feb 04 09:37:56 2013 +0100
     4.3 @@ -0,0 +1,78 @@
     4.4 +/*
     4.5 + * Copyright (c) 2003, 2011, 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 +package java.beans;
    4.29 +
    4.30 +/**
    4.31 + * An "IndexedPropertyChange" event gets delivered whenever a component that
    4.32 + * conforms to the JavaBeans&trade; specification (a "bean") changes a bound
    4.33 + * indexed property. This class is an extension of <code>PropertyChangeEvent</code>
    4.34 + * but contains the index of the property that has changed.
    4.35 + * <P>
    4.36 + * Null values may be provided for the old and the new values if their
    4.37 + * true values are not known.
    4.38 + * <P>
    4.39 + * An event source may send a null object as the name to indicate that an
    4.40 + * arbitrary set of if its properties have changed.  In this case the
    4.41 + * old and new values should also be null.
    4.42 + *
    4.43 + * @since 1.5
    4.44 + * @author Mark Davidson
    4.45 + */
    4.46 +public class IndexedPropertyChangeEvent extends PropertyChangeEvent {
    4.47 +    private static final long serialVersionUID = -320227448495806870L;
    4.48 +
    4.49 +    private int index;
    4.50 +
    4.51 +    /**
    4.52 +     * Constructs a new <code>IndexedPropertyChangeEvent</code> object.
    4.53 +     *
    4.54 +     * @param source  The bean that fired the event.
    4.55 +     * @param propertyName  The programmatic name of the property that
    4.56 +     *             was changed.
    4.57 +     * @param oldValue      The old value of the property.
    4.58 +     * @param newValue      The new value of the property.
    4.59 +     * @param index index of the property element that was changed.
    4.60 +     */
    4.61 +    public IndexedPropertyChangeEvent(Object source, String propertyName,
    4.62 +                                      Object oldValue, Object newValue,
    4.63 +                                      int index) {
    4.64 +        super (source, propertyName, oldValue, newValue);
    4.65 +        this.index = index;
    4.66 +    }
    4.67 +
    4.68 +    /**
    4.69 +     * Gets the index of the property that was changed.
    4.70 +     *
    4.71 +     * @return The index specifying the property element that was
    4.72 +     *         changed.
    4.73 +     */
    4.74 +    public int getIndex() {
    4.75 +        return index;
    4.76 +    }
    4.77 +
    4.78 +    void appendTo(StringBuilder sb) {
    4.79 +        sb.append("; index=").append(getIndex());
    4.80 +    }
    4.81 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/emul/compact/src/main/java/java/beans/PropertyChangeEvent.java	Mon Feb 04 09:37:56 2013 +0100
     5.3 @@ -0,0 +1,164 @@
     5.4 +/*
     5.5 + * Copyright (c) 1996, 2010, 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 +/**
    5.32 + * A "PropertyChange" event gets delivered whenever a bean changes a "bound"
    5.33 + * or "constrained" property.  A PropertyChangeEvent object is sent as an
    5.34 + * argument to the PropertyChangeListener and VetoableChangeListener methods.
    5.35 + * <P>
    5.36 + * Normally PropertyChangeEvents are accompanied by the name and the old
    5.37 + * and new value of the changed property.  If the new value is a primitive
    5.38 + * type (such as int or boolean) it must be wrapped as the
    5.39 + * corresponding java.lang.* Object type (such as Integer or Boolean).
    5.40 + * <P>
    5.41 + * Null values may be provided for the old and the new values if their
    5.42 + * true values are not known.
    5.43 + * <P>
    5.44 + * An event source may send a null object as the name to indicate that an
    5.45 + * arbitrary set of if its properties have changed.  In this case the
    5.46 + * old and new values should also be null.
    5.47 + */
    5.48 +
    5.49 +public class PropertyChangeEvent extends java.util.EventObject {
    5.50 +    private static final long serialVersionUID = 7042693688939648123L;
    5.51 +
    5.52 +    /**
    5.53 +     * Constructs a new <code>PropertyChangeEvent</code>.
    5.54 +     *
    5.55 +     * @param source  The bean that fired the event.
    5.56 +     * @param propertyName  The programmatic name of the property
    5.57 +     *          that was changed.
    5.58 +     * @param oldValue  The old value of the property.
    5.59 +     * @param newValue  The new value of the property.
    5.60 +     */
    5.61 +    public PropertyChangeEvent(Object source, String propertyName,
    5.62 +                                     Object oldValue, Object newValue) {
    5.63 +        super(source);
    5.64 +        this.propertyName = propertyName;
    5.65 +        this.newValue = newValue;
    5.66 +        this.oldValue = oldValue;
    5.67 +    }
    5.68 +
    5.69 +    /**
    5.70 +     * Gets the programmatic name of the property that was changed.
    5.71 +     *
    5.72 +     * @return  The programmatic name of the property that was changed.
    5.73 +     *          May be null if multiple properties have changed.
    5.74 +     */
    5.75 +    public String getPropertyName() {
    5.76 +        return propertyName;
    5.77 +    }
    5.78 +
    5.79 +    /**
    5.80 +     * Gets the new value for the property, expressed as an Object.
    5.81 +     *
    5.82 +     * @return  The new value for the property, expressed as an Object.
    5.83 +     *          May be null if multiple properties have changed.
    5.84 +     */
    5.85 +    public Object getNewValue() {
    5.86 +        return newValue;
    5.87 +    }
    5.88 +
    5.89 +    /**
    5.90 +     * Gets the old value for the property, expressed as an Object.
    5.91 +     *
    5.92 +     * @return  The old value for the property, expressed as an Object.
    5.93 +     *          May be null if multiple properties have changed.
    5.94 +     */
    5.95 +    public Object getOldValue() {
    5.96 +        return oldValue;
    5.97 +    }
    5.98 +
    5.99 +    /**
   5.100 +     * Sets the propagationId object for the event.
   5.101 +     *
   5.102 +     * @param propagationId  The propagationId object for the event.
   5.103 +     */
   5.104 +    public void setPropagationId(Object propagationId) {
   5.105 +        this.propagationId = propagationId;
   5.106 +    }
   5.107 +
   5.108 +    /**
   5.109 +     * The "propagationId" field is reserved for future use.  In Beans 1.0
   5.110 +     * the sole requirement is that if a listener catches a PropertyChangeEvent
   5.111 +     * and then fires a PropertyChangeEvent of its own, then it should
   5.112 +     * make sure that it propagates the propagationId field from its
   5.113 +     * incoming event to its outgoing event.
   5.114 +     *
   5.115 +     * @return the propagationId object associated with a bound/constrained
   5.116 +     *          property update.
   5.117 +     */
   5.118 +    public Object getPropagationId() {
   5.119 +        return propagationId;
   5.120 +    }
   5.121 +
   5.122 +    /**
   5.123 +     * name of the property that changed.  May be null, if not known.
   5.124 +     * @serial
   5.125 +     */
   5.126 +    private String propertyName;
   5.127 +
   5.128 +    /**
   5.129 +     * New value for property.  May be null if not known.
   5.130 +     * @serial
   5.131 +     */
   5.132 +    private Object newValue;
   5.133 +
   5.134 +    /**
   5.135 +     * Previous value for property.  May be null if not known.
   5.136 +     * @serial
   5.137 +     */
   5.138 +    private Object oldValue;
   5.139 +
   5.140 +    /**
   5.141 +     * Propagation ID.  May be null.
   5.142 +     * @serial
   5.143 +     * @see #getPropagationId
   5.144 +     */
   5.145 +    private Object propagationId;
   5.146 +
   5.147 +    /**
   5.148 +     * Returns a string representation of the object.
   5.149 +     *
   5.150 +     * @return a string representation of the object
   5.151 +     *
   5.152 +     * @since 1.7
   5.153 +     */
   5.154 +    public String toString() {
   5.155 +        StringBuilder sb = new StringBuilder(getClass().getName());
   5.156 +        sb.append("[propertyName=").append(getPropertyName());
   5.157 +        appendTo(sb);
   5.158 +        sb.append("; oldValue=").append(getOldValue());
   5.159 +        sb.append("; newValue=").append(getNewValue());
   5.160 +        sb.append("; propagationId=").append(getPropagationId());
   5.161 +        sb.append("; source=").append(getSource());
   5.162 +        return sb.append("]").toString();
   5.163 +    }
   5.164 +
   5.165 +    void appendTo(StringBuilder sb) {
   5.166 +    }
   5.167 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/emul/compact/src/main/java/java/beans/PropertyChangeListener.java	Mon Feb 04 09:37:56 2013 +0100
     6.3 @@ -0,0 +1,44 @@
     6.4 +/*
     6.5 + * Copyright (c) 1996, 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 +
    6.29 +package java.beans;
    6.30 +
    6.31 +/**
    6.32 + * A "PropertyChange" event gets fired whenever a bean changes a "bound"
    6.33 + * property.  You can register a PropertyChangeListener with a source
    6.34 + * bean so as to be notified of any bound property updates.
    6.35 + */
    6.36 +
    6.37 +public interface PropertyChangeListener extends java.util.EventListener {
    6.38 +
    6.39 +    /**
    6.40 +     * This method gets called when a bound property is changed.
    6.41 +     * @param evt A PropertyChangeEvent object describing the event source
    6.42 +     *          and the property that has changed.
    6.43 +     */
    6.44 +
    6.45 +    void propertyChange(PropertyChangeEvent evt);
    6.46 +
    6.47 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/emul/compact/src/main/java/java/beans/PropertyChangeListenerProxy.java	Mon Feb 04 09:37:56 2013 +0100
     7.3 @@ -0,0 +1,81 @@
     7.4 +/*
     7.5 + * Copyright (c) 2000, 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 +import java.util.EventListenerProxy;
    7.32 +
    7.33 +/**
    7.34 + * A class which extends the {@code EventListenerProxy}
    7.35 + * specifically for adding a {@code PropertyChangeListener}
    7.36 + * with a "bound" property.
    7.37 + * Instances of this class can be added
    7.38 + * as {@code PropertyChangeListener}s to a bean
    7.39 + * which supports firing property change events.
    7.40 + * <p>
    7.41 + * If the object has a {@code getPropertyChangeListeners} method
    7.42 + * then the array returned could be a mixture of {@code PropertyChangeListener}
    7.43 + * and {@code PropertyChangeListenerProxy} objects.
    7.44 + *
    7.45 + * @see java.util.EventListenerProxy
    7.46 + * @see PropertyChangeSupport#getPropertyChangeListeners
    7.47 + * @since 1.4
    7.48 + */
    7.49 +public class PropertyChangeListenerProxy
    7.50 +        extends EventListenerProxy<PropertyChangeListener>
    7.51 +        implements PropertyChangeListener {
    7.52 +
    7.53 +    private final String propertyName;
    7.54 +
    7.55 +    /**
    7.56 +     * Constructor which binds the {@code PropertyChangeListener}
    7.57 +     * to a specific property.
    7.58 +     *
    7.59 +     * @param propertyName  the name of the property to listen on
    7.60 +     * @param listener      the listener object
    7.61 +     */
    7.62 +    public PropertyChangeListenerProxy(String propertyName, PropertyChangeListener listener) {
    7.63 +        super(listener);
    7.64 +        this.propertyName = propertyName;
    7.65 +    }
    7.66 +
    7.67 +    /**
    7.68 +     * Forwards the property change event to the listener delegate.
    7.69 +     *
    7.70 +     * @param event  the property change event
    7.71 +     */
    7.72 +    public void propertyChange(PropertyChangeEvent event) {
    7.73 +        getListener().propertyChange(event);
    7.74 +    }
    7.75 +
    7.76 +    /**
    7.77 +     * Returns the name of the named property associated with the listener.
    7.78 +     *
    7.79 +     * @return the name of the named property associated with the listener
    7.80 +     */
    7.81 +    public String getPropertyName() {
    7.82 +        return this.propertyName;
    7.83 +    }
    7.84 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/emul/compact/src/main/java/java/beans/PropertyChangeSupport.java	Mon Feb 04 09:37:56 2013 +0100
     8.3 @@ -0,0 +1,536 @@
     8.4 +/*
     8.5 + * Copyright (c) 1996, 2008, 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 +package java.beans;
    8.29 +
    8.30 +import java.io.Serializable;
    8.31 +import java.io.ObjectStreamField;
    8.32 +import java.io.ObjectOutputStream;
    8.33 +import java.io.ObjectInputStream;
    8.34 +import java.io.IOException;
    8.35 +import java.util.Hashtable;
    8.36 +import java.util.Map.Entry;
    8.37 +
    8.38 +/**
    8.39 + * This is a utility class that can be used by beans that support bound
    8.40 + * properties.  It manages a list of listeners and dispatches
    8.41 + * {@link PropertyChangeEvent}s to them.  You can use an instance of this class
    8.42 + * as a member field of your bean and delegate these types of work to it.
    8.43 + * The {@link PropertyChangeListener} can be registered for all properties
    8.44 + * or for a property specified by name.
    8.45 + * <p>
    8.46 + * Here is an example of {@code PropertyChangeSupport} usage that follows
    8.47 + * the rules and recommendations laid out in the JavaBeans&trade; specification:
    8.48 + * <pre>
    8.49 + * public class MyBean {
    8.50 + *     private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
    8.51 + *
    8.52 + *     public void addPropertyChangeListener(PropertyChangeListener listener) {
    8.53 + *         this.pcs.addPropertyChangeListener(listener);
    8.54 + *     }
    8.55 + *
    8.56 + *     public void removePropertyChangeListener(PropertyChangeListener listener) {
    8.57 + *         this.pcs.removePropertyChangeListener(listener);
    8.58 + *     }
    8.59 + *
    8.60 + *     private String value;
    8.61 + *
    8.62 + *     public String getValue() {
    8.63 + *         return this.value;
    8.64 + *     }
    8.65 + *
    8.66 + *     public void setValue(String newValue) {
    8.67 + *         String oldValue = this.value;
    8.68 + *         this.value = newValue;
    8.69 + *         this.pcs.firePropertyChange("value", oldValue, newValue);
    8.70 + *     }
    8.71 + *
    8.72 + *     [...]
    8.73 + * }
    8.74 + * </pre>
    8.75 + * <p>
    8.76 + * A {@code PropertyChangeSupport} instance is thread-safe.
    8.77 + * <p>
    8.78 + * This class is serializable.  When it is serialized it will save
    8.79 + * (and restore) any listeners that are themselves serializable.  Any
    8.80 + * non-serializable listeners will be skipped during serialization.
    8.81 + *
    8.82 + * @see VetoableChangeSupport
    8.83 + */
    8.84 +public class PropertyChangeSupport implements Serializable {
    8.85 +    private PropertyChangeListenerMap map = new PropertyChangeListenerMap();
    8.86 +
    8.87 +    /**
    8.88 +     * Constructs a <code>PropertyChangeSupport</code> object.
    8.89 +     *
    8.90 +     * @param sourceBean  The bean to be given as the source for any events.
    8.91 +     */
    8.92 +    public PropertyChangeSupport(Object sourceBean) {
    8.93 +        if (sourceBean == null) {
    8.94 +            throw new NullPointerException();
    8.95 +        }
    8.96 +        source = sourceBean;
    8.97 +    }
    8.98 +
    8.99 +    /**
   8.100 +     * Add a PropertyChangeListener to the listener list.
   8.101 +     * The listener is registered for all properties.
   8.102 +     * The same listener object may be added more than once, and will be called
   8.103 +     * as many times as it is added.
   8.104 +     * If <code>listener</code> is null, no exception is thrown and no action
   8.105 +     * is taken.
   8.106 +     *
   8.107 +     * @param listener  The PropertyChangeListener to be added
   8.108 +     */
   8.109 +    public void addPropertyChangeListener(PropertyChangeListener listener) {
   8.110 +        if (listener == null) {
   8.111 +            return;
   8.112 +        }
   8.113 +        if (listener instanceof PropertyChangeListenerProxy) {
   8.114 +            PropertyChangeListenerProxy proxy =
   8.115 +                   (PropertyChangeListenerProxy)listener;
   8.116 +            // Call two argument add method.
   8.117 +            addPropertyChangeListener(proxy.getPropertyName(),
   8.118 +                                      proxy.getListener());
   8.119 +        } else {
   8.120 +            this.map.add(null, listener);
   8.121 +        }
   8.122 +    }
   8.123 +
   8.124 +    /**
   8.125 +     * Remove a PropertyChangeListener from the listener list.
   8.126 +     * This removes a PropertyChangeListener that was registered
   8.127 +     * for all properties.
   8.128 +     * If <code>listener</code> was added more than once to the same event
   8.129 +     * source, it will be notified one less time after being removed.
   8.130 +     * If <code>listener</code> is null, or was never added, no exception is
   8.131 +     * thrown and no action is taken.
   8.132 +     *
   8.133 +     * @param listener  The PropertyChangeListener to be removed
   8.134 +     */
   8.135 +    public void removePropertyChangeListener(PropertyChangeListener listener) {
   8.136 +        if (listener == null) {
   8.137 +            return;
   8.138 +        }
   8.139 +        if (listener instanceof PropertyChangeListenerProxy) {
   8.140 +            PropertyChangeListenerProxy proxy =
   8.141 +                    (PropertyChangeListenerProxy)listener;
   8.142 +            // Call two argument remove method.
   8.143 +            removePropertyChangeListener(proxy.getPropertyName(),
   8.144 +                                         proxy.getListener());
   8.145 +        } else {
   8.146 +            this.map.remove(null, listener);
   8.147 +        }
   8.148 +    }
   8.149 +
   8.150 +    /**
   8.151 +     * Returns an array of all the listeners that were added to the
   8.152 +     * PropertyChangeSupport object with addPropertyChangeListener().
   8.153 +     * <p>
   8.154 +     * If some listeners have been added with a named property, then
   8.155 +     * the returned array will be a mixture of PropertyChangeListeners
   8.156 +     * and <code>PropertyChangeListenerProxy</code>s. If the calling
   8.157 +     * method is interested in distinguishing the listeners then it must
   8.158 +     * test each element to see if it's a
   8.159 +     * <code>PropertyChangeListenerProxy</code>, perform the cast, and examine
   8.160 +     * the parameter.
   8.161 +     *
   8.162 +     * <pre>
   8.163 +     * PropertyChangeListener[] listeners = bean.getPropertyChangeListeners();
   8.164 +     * for (int i = 0; i < listeners.length; i++) {
   8.165 +     *   if (listeners[i] instanceof PropertyChangeListenerProxy) {
   8.166 +     *     PropertyChangeListenerProxy proxy =
   8.167 +     *                    (PropertyChangeListenerProxy)listeners[i];
   8.168 +     *     if (proxy.getPropertyName().equals("foo")) {
   8.169 +     *       // proxy is a PropertyChangeListener which was associated
   8.170 +     *       // with the property named "foo"
   8.171 +     *     }
   8.172 +     *   }
   8.173 +     * }
   8.174 +     *</pre>
   8.175 +     *
   8.176 +     * @see PropertyChangeListenerProxy
   8.177 +     * @return all of the <code>PropertyChangeListeners</code> added or an
   8.178 +     *         empty array if no listeners have been added
   8.179 +     * @since 1.4
   8.180 +     */
   8.181 +    public PropertyChangeListener[] getPropertyChangeListeners() {
   8.182 +        return this.map.getListeners();
   8.183 +    }
   8.184 +
   8.185 +    /**
   8.186 +     * Add a PropertyChangeListener for a specific property.  The listener
   8.187 +     * will be invoked only when a call on firePropertyChange names that
   8.188 +     * specific property.
   8.189 +     * The same listener object may be added more than once.  For each
   8.190 +     * property,  the listener will be invoked the number of times it was added
   8.191 +     * for that property.
   8.192 +     * If <code>propertyName</code> or <code>listener</code> is null, no
   8.193 +     * exception is thrown and no action is taken.
   8.194 +     *
   8.195 +     * @param propertyName  The name of the property to listen on.
   8.196 +     * @param listener  The PropertyChangeListener to be added
   8.197 +     */
   8.198 +    public void addPropertyChangeListener(
   8.199 +                String propertyName,
   8.200 +                PropertyChangeListener listener) {
   8.201 +        if (listener == null || propertyName == null) {
   8.202 +            return;
   8.203 +        }
   8.204 +        listener = this.map.extract(listener);
   8.205 +        if (listener != null) {
   8.206 +            this.map.add(propertyName, listener);
   8.207 +        }
   8.208 +    }
   8.209 +
   8.210 +    /**
   8.211 +     * Remove a PropertyChangeListener for a specific property.
   8.212 +     * If <code>listener</code> was added more than once to the same event
   8.213 +     * source for the specified property, it will be notified one less time
   8.214 +     * after being removed.
   8.215 +     * If <code>propertyName</code> is null,  no exception is thrown and no
   8.216 +     * action is taken.
   8.217 +     * If <code>listener</code> is null, or was never added for the specified
   8.218 +     * property, no exception is thrown and no action is taken.
   8.219 +     *
   8.220 +     * @param propertyName  The name of the property that was listened on.
   8.221 +     * @param listener  The PropertyChangeListener to be removed
   8.222 +     */
   8.223 +    public void removePropertyChangeListener(
   8.224 +                String propertyName,
   8.225 +                PropertyChangeListener listener) {
   8.226 +        if (listener == null || propertyName == null) {
   8.227 +            return;
   8.228 +        }
   8.229 +        listener = this.map.extract(listener);
   8.230 +        if (listener != null) {
   8.231 +            this.map.remove(propertyName, listener);
   8.232 +        }
   8.233 +    }
   8.234 +
   8.235 +    /**
   8.236 +     * Returns an array of all the listeners which have been associated
   8.237 +     * with the named property.
   8.238 +     *
   8.239 +     * @param propertyName  The name of the property being listened to
   8.240 +     * @return all of the <code>PropertyChangeListeners</code> associated with
   8.241 +     *         the named property.  If no such listeners have been added,
   8.242 +     *         or if <code>propertyName</code> is null, an empty array is
   8.243 +     *         returned.
   8.244 +     * @since 1.4
   8.245 +     */
   8.246 +    public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
   8.247 +        return this.map.getListeners(propertyName);
   8.248 +    }
   8.249 +
   8.250 +    /**
   8.251 +     * Reports a bound property update to listeners
   8.252 +     * that have been registered to track updates of
   8.253 +     * all properties or a property with the specified name.
   8.254 +     * <p>
   8.255 +     * No event is fired if old and new values are equal and non-null.
   8.256 +     * <p>
   8.257 +     * This is merely a convenience wrapper around the more general
   8.258 +     * {@link #firePropertyChange(PropertyChangeEvent)} method.
   8.259 +     *
   8.260 +     * @param propertyName  the programmatic name of the property that was changed
   8.261 +     * @param oldValue      the old value of the property
   8.262 +     * @param newValue      the new value of the property
   8.263 +     */
   8.264 +    public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
   8.265 +        if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
   8.266 +            firePropertyChange(new PropertyChangeEvent(this.source, propertyName, oldValue, newValue));
   8.267 +        }
   8.268 +    }
   8.269 +
   8.270 +    /**
   8.271 +     * Reports an integer bound property update to listeners
   8.272 +     * that have been registered to track updates of
   8.273 +     * all properties or a property with the specified name.
   8.274 +     * <p>
   8.275 +     * No event is fired if old and new values are equal.
   8.276 +     * <p>
   8.277 +     * This is merely a convenience wrapper around the more general
   8.278 +     * {@link #firePropertyChange(String, Object, Object)}  method.
   8.279 +     *
   8.280 +     * @param propertyName  the programmatic name of the property that was changed
   8.281 +     * @param oldValue      the old value of the property
   8.282 +     * @param newValue      the new value of the property
   8.283 +     */
   8.284 +    public void firePropertyChange(String propertyName, int oldValue, int newValue) {
   8.285 +        if (oldValue != newValue) {
   8.286 +            firePropertyChange(propertyName, Integer.valueOf(oldValue), Integer.valueOf(newValue));
   8.287 +        }
   8.288 +    }
   8.289 +
   8.290 +    /**
   8.291 +     * Reports a boolean bound property update to listeners
   8.292 +     * that have been registered to track updates of
   8.293 +     * all properties or a property with the specified name.
   8.294 +     * <p>
   8.295 +     * No event is fired if old and new values are equal.
   8.296 +     * <p>
   8.297 +     * This is merely a convenience wrapper around the more general
   8.298 +     * {@link #firePropertyChange(String, Object, Object)}  method.
   8.299 +     *
   8.300 +     * @param propertyName  the programmatic name of the property that was changed
   8.301 +     * @param oldValue      the old value of the property
   8.302 +     * @param newValue      the new value of the property
   8.303 +     */
   8.304 +    public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {
   8.305 +        if (oldValue != newValue) {
   8.306 +            firePropertyChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
   8.307 +        }
   8.308 +    }
   8.309 +
   8.310 +    /**
   8.311 +     * Fires a property change event to listeners
   8.312 +     * that have been registered to track updates of
   8.313 +     * all properties or a property with the specified name.
   8.314 +     * <p>
   8.315 +     * No event is fired if the given event's old and new values are equal and non-null.
   8.316 +     *
   8.317 +     * @param event  the {@code PropertyChangeEvent} to be fired
   8.318 +     */
   8.319 +    public void firePropertyChange(PropertyChangeEvent event) {
   8.320 +        Object oldValue = event.getOldValue();
   8.321 +        Object newValue = event.getNewValue();
   8.322 +        if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
   8.323 +            String name = event.getPropertyName();
   8.324 +
   8.325 +            PropertyChangeListener[] common = this.map.get(null);
   8.326 +            PropertyChangeListener[] named = (name != null)
   8.327 +                        ? this.map.get(name)
   8.328 +                        : null;
   8.329 +
   8.330 +            fire(common, event);
   8.331 +            fire(named, event);
   8.332 +        }
   8.333 +    }
   8.334 +
   8.335 +    private static void fire(PropertyChangeListener[] listeners, PropertyChangeEvent event) {
   8.336 +        if (listeners != null) {
   8.337 +            for (PropertyChangeListener listener : listeners) {
   8.338 +                listener.propertyChange(event);
   8.339 +            }
   8.340 +        }
   8.341 +    }
   8.342 +
   8.343 +    /**
   8.344 +     * Reports a bound indexed property update to listeners
   8.345 +     * that have been registered to track updates of
   8.346 +     * all properties or a property with the specified name.
   8.347 +     * <p>
   8.348 +     * No event is fired if old and new values are equal and non-null.
   8.349 +     * <p>
   8.350 +     * This is merely a convenience wrapper around the more general
   8.351 +     * {@link #firePropertyChange(PropertyChangeEvent)} method.
   8.352 +     *
   8.353 +     * @param propertyName  the programmatic name of the property that was changed
   8.354 +     * @param index         the index of the property element that was changed
   8.355 +     * @param oldValue      the old value of the property
   8.356 +     * @param newValue      the new value of the property
   8.357 +     * @since 1.5
   8.358 +     */
   8.359 +    public void fireIndexedPropertyChange(String propertyName, int index, Object oldValue, Object newValue) {
   8.360 +        if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
   8.361 +            firePropertyChange(new IndexedPropertyChangeEvent(source, propertyName, oldValue, newValue, index));
   8.362 +        }
   8.363 +    }
   8.364 +
   8.365 +    /**
   8.366 +     * Reports an integer bound indexed property update to listeners
   8.367 +     * that have been registered to track updates of
   8.368 +     * all properties or a property with the specified name.
   8.369 +     * <p>
   8.370 +     * No event is fired if old and new values are equal.
   8.371 +     * <p>
   8.372 +     * This is merely a convenience wrapper around the more general
   8.373 +     * {@link #fireIndexedPropertyChange(String, int, Object, Object)} method.
   8.374 +     *
   8.375 +     * @param propertyName  the programmatic name of the property that was changed
   8.376 +     * @param index         the index of the property element that was changed
   8.377 +     * @param oldValue      the old value of the property
   8.378 +     * @param newValue      the new value of the property
   8.379 +     * @since 1.5
   8.380 +     */
   8.381 +    public void fireIndexedPropertyChange(String propertyName, int index, int oldValue, int newValue) {
   8.382 +        if (oldValue != newValue) {
   8.383 +            fireIndexedPropertyChange(propertyName, index, Integer.valueOf(oldValue), Integer.valueOf(newValue));
   8.384 +        }
   8.385 +    }
   8.386 +
   8.387 +    /**
   8.388 +     * Reports a boolean bound indexed property update to listeners
   8.389 +     * that have been registered to track updates of
   8.390 +     * all properties or a property with the specified name.
   8.391 +     * <p>
   8.392 +     * No event is fired if old and new values are equal.
   8.393 +     * <p>
   8.394 +     * This is merely a convenience wrapper around the more general
   8.395 +     * {@link #fireIndexedPropertyChange(String, int, Object, Object)} method.
   8.396 +     *
   8.397 +     * @param propertyName  the programmatic name of the property that was changed
   8.398 +     * @param index         the index of the property element that was changed
   8.399 +     * @param oldValue      the old value of the property
   8.400 +     * @param newValue      the new value of the property
   8.401 +     * @since 1.5
   8.402 +     */
   8.403 +    public void fireIndexedPropertyChange(String propertyName, int index, boolean oldValue, boolean newValue) {
   8.404 +        if (oldValue != newValue) {
   8.405 +            fireIndexedPropertyChange(propertyName, index, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
   8.406 +        }
   8.407 +    }
   8.408 +
   8.409 +    /**
   8.410 +     * Check if there are any listeners for a specific property, including
   8.411 +     * those registered on all properties.  If <code>propertyName</code>
   8.412 +     * is null, only check for listeners registered on all properties.
   8.413 +     *
   8.414 +     * @param propertyName  the property name.
   8.415 +     * @return true if there are one or more listeners for the given property
   8.416 +     */
   8.417 +    public boolean hasListeners(String propertyName) {
   8.418 +        return this.map.hasListeners(propertyName);
   8.419 +    }
   8.420 +
   8.421 +    /**
   8.422 +     * @serialData Null terminated list of <code>PropertyChangeListeners</code>.
   8.423 +     * <p>
   8.424 +     * At serialization time we skip non-serializable listeners and
   8.425 +     * only serialize the serializable listeners.
   8.426 +     */
   8.427 +    private void writeObject(ObjectOutputStream s) throws IOException {
   8.428 +        Hashtable<String, PropertyChangeSupport> children = null;
   8.429 +        PropertyChangeListener[] listeners = null;
   8.430 +        synchronized (this.map) {
   8.431 +            for (Entry<String, PropertyChangeListener[]> entry : this.map.getEntries()) {
   8.432 +                String property = entry.getKey();
   8.433 +                if (property == null) {
   8.434 +                    listeners = entry.getValue();
   8.435 +                } else {
   8.436 +                    if (children == null) {
   8.437 +                        children = new Hashtable<String, PropertyChangeSupport>();
   8.438 +                    }
   8.439 +                    PropertyChangeSupport pcs = new PropertyChangeSupport(this.source);
   8.440 +                    pcs.map.set(null, entry.getValue());
   8.441 +                    children.put(property, pcs);
   8.442 +                }
   8.443 +            }
   8.444 +        }
   8.445 +        ObjectOutputStream.PutField fields = s.putFields();
   8.446 +        fields.put("children", children);
   8.447 +        fields.put("source", this.source);
   8.448 +        fields.put("propertyChangeSupportSerializedDataVersion", 2);
   8.449 +        s.writeFields();
   8.450 +
   8.451 +        if (listeners != null) {
   8.452 +            for (PropertyChangeListener l : listeners) {
   8.453 +                if (l instanceof Serializable) {
   8.454 +                    s.writeObject(l);
   8.455 +                }
   8.456 +            }
   8.457 +        }
   8.458 +        s.writeObject(null);
   8.459 +    }
   8.460 +
   8.461 +    private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
   8.462 +        this.map = new PropertyChangeListenerMap();
   8.463 +
   8.464 +        ObjectInputStream.GetField fields = s.readFields();
   8.465 +
   8.466 +        Hashtable<String, PropertyChangeSupport> children = (Hashtable<String, PropertyChangeSupport>) fields.get("children", null);
   8.467 +        this.source = fields.get("source", null);
   8.468 +        fields.get("propertyChangeSupportSerializedDataVersion", 2);
   8.469 +
   8.470 +        Object listenerOrNull;
   8.471 +        while (null != (listenerOrNull = s.readObject())) {
   8.472 +            this.map.add(null, (PropertyChangeListener)listenerOrNull);
   8.473 +        }
   8.474 +        if (children != null) {
   8.475 +            for (Entry<String, PropertyChangeSupport> entry : children.entrySet()) {
   8.476 +                for (PropertyChangeListener listener : entry.getValue().getPropertyChangeListeners()) {
   8.477 +                    this.map.add(entry.getKey(), listener);
   8.478 +                }
   8.479 +            }
   8.480 +        }
   8.481 +    }
   8.482 +
   8.483 +    /**
   8.484 +     * The object to be provided as the "source" for any generated events.
   8.485 +     */
   8.486 +    private Object source;
   8.487 +
   8.488 +    /**
   8.489 +     * @serialField children                                   Hashtable
   8.490 +     * @serialField source                                     Object
   8.491 +     * @serialField propertyChangeSupportSerializedDataVersion int
   8.492 +     */
   8.493 +    private static final ObjectStreamField[] serialPersistentFields = {
   8.494 +            new ObjectStreamField("children", Hashtable.class),
   8.495 +            new ObjectStreamField("source", Object.class),
   8.496 +            new ObjectStreamField("propertyChangeSupportSerializedDataVersion", Integer.TYPE)
   8.497 +    };
   8.498 +
   8.499 +    /**
   8.500 +     * Serialization version ID, so we're compatible with JDK 1.1
   8.501 +     */
   8.502 +    static final long serialVersionUID = 6401253773779951803L;
   8.503 +
   8.504 +    /**
   8.505 +     * This is a {@link ChangeListenerMap ChangeListenerMap} implementation
   8.506 +     * that works with {@link PropertyChangeListener PropertyChangeListener} objects.
   8.507 +     */
   8.508 +    private static final class PropertyChangeListenerMap extends ChangeListenerMap<PropertyChangeListener> {
   8.509 +        private static final PropertyChangeListener[] EMPTY = {};
   8.510 +
   8.511 +        /**
   8.512 +         * Creates an array of {@link PropertyChangeListener PropertyChangeListener} objects.
   8.513 +         * This method uses the same instance of the empty array
   8.514 +         * when {@code length} equals {@code 0}.
   8.515 +         *
   8.516 +         * @param length  the array length
   8.517 +         * @return        an array with specified length
   8.518 +         */
   8.519 +        @Override
   8.520 +        protected PropertyChangeListener[] newArray(int length) {
   8.521 +            return (0 < length)
   8.522 +                    ? new PropertyChangeListener[length]
   8.523 +                    : EMPTY;
   8.524 +        }
   8.525 +
   8.526 +        /**
   8.527 +         * Creates a {@link PropertyChangeListenerProxy PropertyChangeListenerProxy}
   8.528 +         * object for the specified property.
   8.529 +         *
   8.530 +         * @param name      the name of the property to listen on
   8.531 +         * @param listener  the listener to process events
   8.532 +         * @return          a {@code PropertyChangeListenerProxy} object
   8.533 +         */
   8.534 +        @Override
   8.535 +        protected PropertyChangeListener newProxy(String name, PropertyChangeListener listener) {
   8.536 +            return new PropertyChangeListenerProxy(name, listener);
   8.537 +        }
   8.538 +    }
   8.539 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/emul/compact/src/main/java/java/beans/PropertyVetoException.java	Mon Feb 04 09:37:56 2013 +0100
     9.3 @@ -0,0 +1,64 @@
     9.4 +/*
     9.5 + * Copyright (c) 1996, 2009, 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 +
    9.32 +/**
    9.33 + * A PropertyVetoException is thrown when a proposed change to a
    9.34 + * property represents an unacceptable value.
    9.35 + */
    9.36 +
    9.37 +public
    9.38 +class PropertyVetoException extends Exception {
    9.39 +    private static final long serialVersionUID = 129596057694162164L;
    9.40 +
    9.41 +    /**
    9.42 +     * Constructs a <code>PropertyVetoException</code> with a
    9.43 +     * detailed message.
    9.44 +     *
    9.45 +     * @param mess Descriptive message
    9.46 +     * @param evt A PropertyChangeEvent describing the vetoed change.
    9.47 +     */
    9.48 +    public PropertyVetoException(String mess, PropertyChangeEvent evt) {
    9.49 +        super(mess);
    9.50 +        this.evt = evt;
    9.51 +    }
    9.52 +
    9.53 +     /**
    9.54 +     * Gets the vetoed <code>PropertyChangeEvent</code>.
    9.55 +     *
    9.56 +     * @return A PropertyChangeEvent describing the vetoed change.
    9.57 +     */
    9.58 +    public PropertyChangeEvent getPropertyChangeEvent() {
    9.59 +        return evt;
    9.60 +    }
    9.61 +
    9.62 +    /**
    9.63 +     * A PropertyChangeEvent describing the vetoed change.
    9.64 +     * @serial
    9.65 +     */
    9.66 +    private PropertyChangeEvent evt;
    9.67 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/emul/compact/src/main/java/java/beans/VetoableChangeListener.java	Mon Feb 04 09:37:56 2013 +0100
    10.3 @@ -0,0 +1,44 @@
    10.4 +/*
    10.5 + * Copyright (c) 1996, 1997, 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 +
   10.29 +package java.beans;
   10.30 +
   10.31 +/**
   10.32 + * A VetoableChange event gets fired whenever a bean changes a "constrained"
   10.33 + * property.  You can register a VetoableChangeListener with a source bean
   10.34 + * so as to be notified of any constrained property updates.
   10.35 + */
   10.36 +public interface VetoableChangeListener extends java.util.EventListener {
   10.37 +    /**
   10.38 +     * This method gets called when a constrained property is changed.
   10.39 +     *
   10.40 +     * @param     evt a <code>PropertyChangeEvent</code> object describing the
   10.41 +     *                event source and the property that has changed.
   10.42 +     * @exception PropertyVetoException if the recipient wishes the property
   10.43 +     *              change to be rolled back.
   10.44 +     */
   10.45 +    void vetoableChange(PropertyChangeEvent evt)
   10.46 +                                throws PropertyVetoException;
   10.47 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/emul/compact/src/main/java/java/beans/VetoableChangeListenerProxy.java	Mon Feb 04 09:37:56 2013 +0100
    11.3 @@ -0,0 +1,84 @@
    11.4 +/*
    11.5 + * Copyright (c) 2000, 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.beans;
   11.30 +
   11.31 +import java.util.EventListenerProxy;
   11.32 +
   11.33 +/**
   11.34 + * A class which extends the {@code EventListenerProxy}
   11.35 + * specifically for adding a {@code VetoableChangeListener}
   11.36 + * with a "constrained" property.
   11.37 + * Instances of this class can be added
   11.38 + * as {@code VetoableChangeListener}s to a bean
   11.39 + * which supports firing vetoable change events.
   11.40 + * <p>
   11.41 + * If the object has a {@code getVetoableChangeListeners} method
   11.42 + * then the array returned could be a mixture of {@code VetoableChangeListener}
   11.43 + * and {@code VetoableChangeListenerProxy} objects.
   11.44 + *
   11.45 + * @see java.util.EventListenerProxy
   11.46 + * @see VetoableChangeSupport#getVetoableChangeListeners
   11.47 + * @since 1.4
   11.48 + */
   11.49 +public class VetoableChangeListenerProxy
   11.50 +        extends EventListenerProxy<VetoableChangeListener>
   11.51 +        implements VetoableChangeListener {
   11.52 +
   11.53 +    private final String propertyName;
   11.54 +
   11.55 +    /**
   11.56 +     * Constructor which binds the {@code VetoableChangeListener}
   11.57 +     * to a specific property.
   11.58 +     *
   11.59 +     * @param propertyName  the name of the property to listen on
   11.60 +     * @param listener      the listener object
   11.61 +     */
   11.62 +    public VetoableChangeListenerProxy(String propertyName, VetoableChangeListener listener) {
   11.63 +        super(listener);
   11.64 +        this.propertyName = propertyName;
   11.65 +    }
   11.66 +
   11.67 +    /**
   11.68 +    * Forwards the property change event to the listener delegate.
   11.69 +    *
   11.70 +    * @param event  the property change event
   11.71 +    *
   11.72 +    * @exception PropertyVetoException if the recipient wishes the property
   11.73 +    *                                  change to be rolled back
   11.74 +    */
   11.75 +    public void vetoableChange(PropertyChangeEvent event) throws PropertyVetoException{
   11.76 +        getListener().vetoableChange(event);
   11.77 +    }
   11.78 +
   11.79 +    /**
   11.80 +     * Returns the name of the named property associated with the listener.
   11.81 +     *
   11.82 +     * @return the name of the named property associated with the listener
   11.83 +     */
   11.84 +    public String getPropertyName() {
   11.85 +        return this.propertyName;
   11.86 +    }
   11.87 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/emul/compact/src/main/java/java/beans/VetoableChangeSupport.java	Mon Feb 04 09:37:56 2013 +0100
    12.3 @@ -0,0 +1,526 @@
    12.4 +/*
    12.5 + * Copyright (c) 1996, 2011, 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 +package java.beans;
   12.29 +
   12.30 +import java.io.Serializable;
   12.31 +import java.io.ObjectStreamField;
   12.32 +import java.io.ObjectOutputStream;
   12.33 +import java.io.ObjectInputStream;
   12.34 +import java.io.IOException;
   12.35 +import java.util.Hashtable;
   12.36 +import java.util.Map.Entry;
   12.37 +import org.apidesign.bck2brwsr.emul.lang.System;
   12.38 +
   12.39 +/**
   12.40 + * This is a utility class that can be used by beans that support constrained
   12.41 + * properties.  It manages a list of listeners and dispatches
   12.42 + * {@link PropertyChangeEvent}s to them.  You can use an instance of this class
   12.43 + * as a member field of your bean and delegate these types of work to it.
   12.44 + * The {@link VetoableChangeListener} can be registered for all properties
   12.45 + * or for a property specified by name.
   12.46 + * <p>
   12.47 + * Here is an example of {@code VetoableChangeSupport} usage that follows
   12.48 + * the rules and recommendations laid out in the JavaBeans&trade; specification:
   12.49 + * <pre>
   12.50 + * public class MyBean {
   12.51 + *     private final VetoableChangeSupport vcs = new VetoableChangeSupport(this);
   12.52 + *
   12.53 + *     public void addVetoableChangeListener(VetoableChangeListener listener) {
   12.54 + *         this.vcs.addVetoableChangeListener(listener);
   12.55 + *     }
   12.56 + *
   12.57 + *     public void removeVetoableChangeListener(VetoableChangeListener listener) {
   12.58 + *         this.vcs.removeVetoableChangeListener(listener);
   12.59 + *     }
   12.60 + *
   12.61 + *     private String value;
   12.62 + *
   12.63 + *     public String getValue() {
   12.64 + *         return this.value;
   12.65 + *     }
   12.66 + *
   12.67 + *     public void setValue(String newValue) throws PropertyVetoException {
   12.68 + *         String oldValue = this.value;
   12.69 + *         this.vcs.fireVetoableChange("value", oldValue, newValue);
   12.70 + *         this.value = newValue;
   12.71 + *     }
   12.72 + *
   12.73 + *     [...]
   12.74 + * }
   12.75 + * </pre>
   12.76 + * <p>
   12.77 + * A {@code VetoableChangeSupport} instance is thread-safe.
   12.78 + * <p>
   12.79 + * This class is serializable.  When it is serialized it will save
   12.80 + * (and restore) any listeners that are themselves serializable.  Any
   12.81 + * non-serializable listeners will be skipped during serialization.
   12.82 + *
   12.83 + * @see PropertyChangeSupport
   12.84 + */
   12.85 +public class VetoableChangeSupport implements Serializable {
   12.86 +    private VetoableChangeListenerMap map = new VetoableChangeListenerMap();
   12.87 +
   12.88 +    /**
   12.89 +     * Constructs a <code>VetoableChangeSupport</code> object.
   12.90 +     *
   12.91 +     * @param sourceBean  The bean to be given as the source for any events.
   12.92 +     */
   12.93 +    public VetoableChangeSupport(Object sourceBean) {
   12.94 +        if (sourceBean == null) {
   12.95 +            throw new NullPointerException();
   12.96 +        }
   12.97 +        source = sourceBean;
   12.98 +    }
   12.99 +
  12.100 +    /**
  12.101 +     * Add a VetoableChangeListener to the listener list.
  12.102 +     * The listener is registered for all properties.
  12.103 +     * The same listener object may be added more than once, and will be called
  12.104 +     * as many times as it is added.
  12.105 +     * If <code>listener</code> is null, no exception is thrown and no action
  12.106 +     * is taken.
  12.107 +     *
  12.108 +     * @param listener  The VetoableChangeListener to be added
  12.109 +     */
  12.110 +    public void addVetoableChangeListener(VetoableChangeListener listener) {
  12.111 +        if (listener == null) {
  12.112 +            return;
  12.113 +        }
  12.114 +        if (listener instanceof VetoableChangeListenerProxy) {
  12.115 +            VetoableChangeListenerProxy proxy =
  12.116 +                    (VetoableChangeListenerProxy)listener;
  12.117 +            // Call two argument add method.
  12.118 +            addVetoableChangeListener(proxy.getPropertyName(),
  12.119 +                                      proxy.getListener());
  12.120 +        } else {
  12.121 +            this.map.add(null, listener);
  12.122 +        }
  12.123 +    }
  12.124 +
  12.125 +    /**
  12.126 +     * Remove a VetoableChangeListener from the listener list.
  12.127 +     * This removes a VetoableChangeListener that was registered
  12.128 +     * for all properties.
  12.129 +     * If <code>listener</code> was added more than once to the same event
  12.130 +     * source, it will be notified one less time after being removed.
  12.131 +     * If <code>listener</code> is null, or was never added, no exception is
  12.132 +     * thrown and no action is taken.
  12.133 +     *
  12.134 +     * @param listener  The VetoableChangeListener to be removed
  12.135 +     */
  12.136 +    public void removeVetoableChangeListener(VetoableChangeListener listener) {
  12.137 +        if (listener == null) {
  12.138 +            return;
  12.139 +        }
  12.140 +        if (listener instanceof VetoableChangeListenerProxy) {
  12.141 +            VetoableChangeListenerProxy proxy =
  12.142 +                    (VetoableChangeListenerProxy)listener;
  12.143 +            // Call two argument remove method.
  12.144 +            removeVetoableChangeListener(proxy.getPropertyName(),
  12.145 +                                         proxy.getListener());
  12.146 +        } else {
  12.147 +            this.map.remove(null, listener);
  12.148 +        }
  12.149 +    }
  12.150 +
  12.151 +    /**
  12.152 +     * Returns an array of all the listeners that were added to the
  12.153 +     * VetoableChangeSupport object with addVetoableChangeListener().
  12.154 +     * <p>
  12.155 +     * If some listeners have been added with a named property, then
  12.156 +     * the returned array will be a mixture of VetoableChangeListeners
  12.157 +     * and <code>VetoableChangeListenerProxy</code>s. If the calling
  12.158 +     * method is interested in distinguishing the listeners then it must
  12.159 +     * test each element to see if it's a
  12.160 +     * <code>VetoableChangeListenerProxy</code>, perform the cast, and examine
  12.161 +     * the parameter.
  12.162 +     *
  12.163 +     * <pre>
  12.164 +     * VetoableChangeListener[] listeners = bean.getVetoableChangeListeners();
  12.165 +     * for (int i = 0; i < listeners.length; i++) {
  12.166 +     *        if (listeners[i] instanceof VetoableChangeListenerProxy) {
  12.167 +     *     VetoableChangeListenerProxy proxy =
  12.168 +     *                    (VetoableChangeListenerProxy)listeners[i];
  12.169 +     *     if (proxy.getPropertyName().equals("foo")) {
  12.170 +     *       // proxy is a VetoableChangeListener which was associated
  12.171 +     *       // with the property named "foo"
  12.172 +     *     }
  12.173 +     *   }
  12.174 +     * }
  12.175 +     *</pre>
  12.176 +     *
  12.177 +     * @see VetoableChangeListenerProxy
  12.178 +     * @return all of the <code>VetoableChangeListeners</code> added or an
  12.179 +     *         empty array if no listeners have been added
  12.180 +     * @since 1.4
  12.181 +     */
  12.182 +    public VetoableChangeListener[] getVetoableChangeListeners(){
  12.183 +        return this.map.getListeners();
  12.184 +    }
  12.185 +
  12.186 +    /**
  12.187 +     * Add a VetoableChangeListener for a specific property.  The listener
  12.188 +     * will be invoked only when a call on fireVetoableChange names that
  12.189 +     * specific property.
  12.190 +     * The same listener object may be added more than once.  For each
  12.191 +     * property,  the listener will be invoked the number of times it was added
  12.192 +     * for that property.
  12.193 +     * If <code>propertyName</code> or <code>listener</code> is null, no
  12.194 +     * exception is thrown and no action is taken.
  12.195 +     *
  12.196 +     * @param propertyName  The name of the property to listen on.
  12.197 +     * @param listener  The VetoableChangeListener to be added
  12.198 +     */
  12.199 +    public void addVetoableChangeListener(
  12.200 +                                String propertyName,
  12.201 +                VetoableChangeListener listener) {
  12.202 +        if (listener == null || propertyName == null) {
  12.203 +            return;
  12.204 +        }
  12.205 +        listener = this.map.extract(listener);
  12.206 +        if (listener != null) {
  12.207 +            this.map.add(propertyName, listener);
  12.208 +        }
  12.209 +    }
  12.210 +
  12.211 +    /**
  12.212 +     * Remove a VetoableChangeListener for a specific property.
  12.213 +     * If <code>listener</code> was added more than once to the same event
  12.214 +     * source for the specified property, it will be notified one less time
  12.215 +     * after being removed.
  12.216 +     * If <code>propertyName</code> is null, no exception is thrown and no
  12.217 +     * action is taken.
  12.218 +     * If <code>listener</code> is null, or was never added for the specified
  12.219 +     * property, no exception is thrown and no action is taken.
  12.220 +     *
  12.221 +     * @param propertyName  The name of the property that was listened on.
  12.222 +     * @param listener  The VetoableChangeListener to be removed
  12.223 +     */
  12.224 +    public void removeVetoableChangeListener(
  12.225 +                                String propertyName,
  12.226 +                VetoableChangeListener listener) {
  12.227 +        if (listener == null || propertyName == null) {
  12.228 +            return;
  12.229 +        }
  12.230 +        listener = this.map.extract(listener);
  12.231 +        if (listener != null) {
  12.232 +            this.map.remove(propertyName, listener);
  12.233 +        }
  12.234 +    }
  12.235 +
  12.236 +    /**
  12.237 +     * Returns an array of all the listeners which have been associated
  12.238 +     * with the named property.
  12.239 +     *
  12.240 +     * @param propertyName  The name of the property being listened to
  12.241 +     * @return all the <code>VetoableChangeListeners</code> associated with
  12.242 +     *         the named property.  If no such listeners have been added,
  12.243 +     *         or if <code>propertyName</code> is null, an empty array is
  12.244 +     *         returned.
  12.245 +     * @since 1.4
  12.246 +     */
  12.247 +    public VetoableChangeListener[] getVetoableChangeListeners(String propertyName) {
  12.248 +        return this.map.getListeners(propertyName);
  12.249 +    }
  12.250 +
  12.251 +    /**
  12.252 +     * Reports a constrained property update to listeners
  12.253 +     * that have been registered to track updates of
  12.254 +     * all properties or a property with the specified name.
  12.255 +     * <p>
  12.256 +     * Any listener can throw a {@code PropertyVetoException} to veto the update.
  12.257 +     * If one of the listeners vetoes the update, this method passes
  12.258 +     * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
  12.259 +     * to all listeners that already confirmed this update
  12.260 +     * and throws the {@code PropertyVetoException} again.
  12.261 +     * <p>
  12.262 +     * No event is fired if old and new values are equal and non-null.
  12.263 +     * <p>
  12.264 +     * This is merely a convenience wrapper around the more general
  12.265 +     * {@link #fireVetoableChange(PropertyChangeEvent)} method.
  12.266 +     *
  12.267 +     * @param propertyName  the programmatic name of the property that is about to change
  12.268 +     * @param oldValue      the old value of the property
  12.269 +     * @param newValue      the new value of the property
  12.270 +     * @throws PropertyVetoException if one of listeners vetoes the property update
  12.271 +     */
  12.272 +    public void fireVetoableChange(String propertyName, Object oldValue, Object newValue)
  12.273 +            throws PropertyVetoException {
  12.274 +        if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
  12.275 +            fireVetoableChange(new PropertyChangeEvent(this.source, propertyName, oldValue, newValue));
  12.276 +        }
  12.277 +    }
  12.278 +
  12.279 +    /**
  12.280 +     * Reports an integer constrained property update to listeners
  12.281 +     * that have been registered to track updates of
  12.282 +     * all properties or a property with the specified name.
  12.283 +     * <p>
  12.284 +     * Any listener can throw a {@code PropertyVetoException} to veto the update.
  12.285 +     * If one of the listeners vetoes the update, this method passes
  12.286 +     * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
  12.287 +     * to all listeners that already confirmed this update
  12.288 +     * and throws the {@code PropertyVetoException} again.
  12.289 +     * <p>
  12.290 +     * No event is fired if old and new values are equal.
  12.291 +     * <p>
  12.292 +     * This is merely a convenience wrapper around the more general
  12.293 +     * {@link #fireVetoableChange(String, Object, Object)} method.
  12.294 +     *
  12.295 +     * @param propertyName  the programmatic name of the property that is about to change
  12.296 +     * @param oldValue      the old value of the property
  12.297 +     * @param newValue      the new value of the property
  12.298 +     * @throws PropertyVetoException if one of listeners vetoes the property update
  12.299 +     */
  12.300 +    public void fireVetoableChange(String propertyName, int oldValue, int newValue)
  12.301 +            throws PropertyVetoException {
  12.302 +        if (oldValue != newValue) {
  12.303 +            fireVetoableChange(propertyName, Integer.valueOf(oldValue), Integer.valueOf(newValue));
  12.304 +        }
  12.305 +    }
  12.306 +
  12.307 +    /**
  12.308 +     * Reports a boolean constrained property update to listeners
  12.309 +     * that have been registered to track updates of
  12.310 +     * all properties or a property with the specified name.
  12.311 +     * <p>
  12.312 +     * Any listener can throw a {@code PropertyVetoException} to veto the update.
  12.313 +     * If one of the listeners vetoes the update, this method passes
  12.314 +     * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
  12.315 +     * to all listeners that already confirmed this update
  12.316 +     * and throws the {@code PropertyVetoException} again.
  12.317 +     * <p>
  12.318 +     * No event is fired if old and new values are equal.
  12.319 +     * <p>
  12.320 +     * This is merely a convenience wrapper around the more general
  12.321 +     * {@link #fireVetoableChange(String, Object, Object)} method.
  12.322 +     *
  12.323 +     * @param propertyName  the programmatic name of the property that is about to change
  12.324 +     * @param oldValue      the old value of the property
  12.325 +     * @param newValue      the new value of the property
  12.326 +     * @throws PropertyVetoException if one of listeners vetoes the property update
  12.327 +     */
  12.328 +    public void fireVetoableChange(String propertyName, boolean oldValue, boolean newValue)
  12.329 +            throws PropertyVetoException {
  12.330 +        if (oldValue != newValue) {
  12.331 +            fireVetoableChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
  12.332 +        }
  12.333 +    }
  12.334 +
  12.335 +    /**
  12.336 +     * Fires a property change event to listeners
  12.337 +     * that have been registered to track updates of
  12.338 +     * all properties or a property with the specified name.
  12.339 +     * <p>
  12.340 +     * Any listener can throw a {@code PropertyVetoException} to veto the update.
  12.341 +     * If one of the listeners vetoes the update, this method passes
  12.342 +     * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
  12.343 +     * to all listeners that already confirmed this update
  12.344 +     * and throws the {@code PropertyVetoException} again.
  12.345 +     * <p>
  12.346 +     * No event is fired if the given event's old and new values are equal and non-null.
  12.347 +     *
  12.348 +     * @param event  the {@code PropertyChangeEvent} to be fired
  12.349 +     * @throws PropertyVetoException if one of listeners vetoes the property update
  12.350 +     */
  12.351 +    public void fireVetoableChange(PropertyChangeEvent event)
  12.352 +            throws PropertyVetoException {
  12.353 +        Object oldValue = event.getOldValue();
  12.354 +        Object newValue = event.getNewValue();
  12.355 +        if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
  12.356 +            String name = event.getPropertyName();
  12.357 +
  12.358 +            VetoableChangeListener[] common = this.map.get(null);
  12.359 +            VetoableChangeListener[] named = (name != null)
  12.360 +                        ? this.map.get(name)
  12.361 +                        : null;
  12.362 +
  12.363 +            VetoableChangeListener[] listeners;
  12.364 +            if (common == null) {
  12.365 +                listeners = named;
  12.366 +            }
  12.367 +            else if (named == null) {
  12.368 +                listeners = common;
  12.369 +            }
  12.370 +            else {
  12.371 +                listeners = new VetoableChangeListener[common.length + named.length];
  12.372 +                System.arraycopy(common, 0, listeners, 0, common.length);
  12.373 +                System.arraycopy(named, 0, listeners, common.length, named.length);
  12.374 +            }
  12.375 +            if (listeners != null) {
  12.376 +                int current = 0;
  12.377 +                try {
  12.378 +                    while (current < listeners.length) {
  12.379 +                        listeners[current].vetoableChange(event);
  12.380 +                        current++;
  12.381 +                    }
  12.382 +                }
  12.383 +                catch (PropertyVetoException veto) {
  12.384 +                    event = new PropertyChangeEvent(this.source, name, newValue, oldValue);
  12.385 +                    for (int i = 0; i < current; i++) {
  12.386 +                        try {
  12.387 +                            listeners[i].vetoableChange(event);
  12.388 +                        }
  12.389 +                        catch (PropertyVetoException exception) {
  12.390 +                            // ignore exceptions that occur during rolling back
  12.391 +                        }
  12.392 +                    }
  12.393 +                    throw veto; // rethrow the veto exception
  12.394 +                }
  12.395 +            }
  12.396 +        }
  12.397 +    }
  12.398 +
  12.399 +    /**
  12.400 +     * Check if there are any listeners for a specific property, including
  12.401 +     * those registered on all properties.  If <code>propertyName</code>
  12.402 +     * is null, only check for listeners registered on all properties.
  12.403 +     *
  12.404 +     * @param propertyName  the property name.
  12.405 +     * @return true if there are one or more listeners for the given property
  12.406 +     */
  12.407 +    public boolean hasListeners(String propertyName) {
  12.408 +        return this.map.hasListeners(propertyName);
  12.409 +    }
  12.410 +
  12.411 +    /**
  12.412 +     * @serialData Null terminated list of <code>VetoableChangeListeners</code>.
  12.413 +     * <p>
  12.414 +     * At serialization time we skip non-serializable listeners and
  12.415 +     * only serialize the serializable listeners.
  12.416 +     */
  12.417 +    private void writeObject(ObjectOutputStream s) throws IOException {
  12.418 +        Hashtable<String, VetoableChangeSupport> children = null;
  12.419 +        VetoableChangeListener[] listeners = null;
  12.420 +        synchronized (this.map) {
  12.421 +            for (Entry<String, VetoableChangeListener[]> entry : this.map.getEntries()) {
  12.422 +                String property = entry.getKey();
  12.423 +                if (property == null) {
  12.424 +                    listeners = entry.getValue();
  12.425 +                } else {
  12.426 +                    if (children == null) {
  12.427 +                        children = new Hashtable<String, VetoableChangeSupport>();
  12.428 +                    }
  12.429 +                    VetoableChangeSupport vcs = new VetoableChangeSupport(this.source);
  12.430 +                    vcs.map.set(null, entry.getValue());
  12.431 +                    children.put(property, vcs);
  12.432 +                }
  12.433 +            }
  12.434 +        }
  12.435 +        ObjectOutputStream.PutField fields = s.putFields();
  12.436 +        fields.put("children", children);
  12.437 +        fields.put("source", this.source);
  12.438 +        fields.put("vetoableChangeSupportSerializedDataVersion", 2);
  12.439 +        s.writeFields();
  12.440 +
  12.441 +        if (listeners != null) {
  12.442 +            for (VetoableChangeListener l : listeners) {
  12.443 +                if (l instanceof Serializable) {
  12.444 +                    s.writeObject(l);
  12.445 +                }
  12.446 +            }
  12.447 +        }
  12.448 +        s.writeObject(null);
  12.449 +    }
  12.450 +
  12.451 +    private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
  12.452 +        this.map = new VetoableChangeListenerMap();
  12.453 +
  12.454 +        ObjectInputStream.GetField fields = s.readFields();
  12.455 +
  12.456 +        Hashtable<String, VetoableChangeSupport> children = (Hashtable<String, VetoableChangeSupport>) fields.get("children", null);
  12.457 +        this.source = fields.get("source", null);
  12.458 +        fields.get("vetoableChangeSupportSerializedDataVersion", 2);
  12.459 +
  12.460 +        Object listenerOrNull;
  12.461 +        while (null != (listenerOrNull = s.readObject())) {
  12.462 +            this.map.add(null, (VetoableChangeListener)listenerOrNull);
  12.463 +        }
  12.464 +        if (children != null) {
  12.465 +            for (Entry<String, VetoableChangeSupport> entry : children.entrySet()) {
  12.466 +                for (VetoableChangeListener listener : entry.getValue().getVetoableChangeListeners()) {
  12.467 +                    this.map.add(entry.getKey(), listener);
  12.468 +                }
  12.469 +            }
  12.470 +        }
  12.471 +    }
  12.472 +
  12.473 +    /**
  12.474 +     * The object to be provided as the "source" for any generated events.
  12.475 +     */
  12.476 +    private Object source;
  12.477 +
  12.478 +    /**
  12.479 +     * @serialField children                                   Hashtable
  12.480 +     * @serialField source                                     Object
  12.481 +     * @serialField vetoableChangeSupportSerializedDataVersion int
  12.482 +     */
  12.483 +    private static final ObjectStreamField[] serialPersistentFields = {
  12.484 +            new ObjectStreamField("children", Hashtable.class),
  12.485 +            new ObjectStreamField("source", Object.class),
  12.486 +            new ObjectStreamField("vetoableChangeSupportSerializedDataVersion", Integer.TYPE)
  12.487 +    };
  12.488 +
  12.489 +    /**
  12.490 +     * Serialization version ID, so we're compatible with JDK 1.1
  12.491 +     */
  12.492 +    static final long serialVersionUID = -5090210921595982017L;
  12.493 +
  12.494 +    /**
  12.495 +     * This is a {@link ChangeListenerMap ChangeListenerMap} implementation
  12.496 +     * that works with {@link VetoableChangeListener VetoableChangeListener} objects.
  12.497 +     */
  12.498 +    private static final class VetoableChangeListenerMap extends ChangeListenerMap<VetoableChangeListener> {
  12.499 +        private static final VetoableChangeListener[] EMPTY = {};
  12.500 +
  12.501 +        /**
  12.502 +         * Creates an array of {@link VetoableChangeListener VetoableChangeListener} objects.
  12.503 +         * This method uses the same instance of the empty array
  12.504 +         * when {@code length} equals {@code 0}.
  12.505 +         *
  12.506 +         * @param length  the array length
  12.507 +         * @return        an array with specified length
  12.508 +         */
  12.509 +        @Override
  12.510 +        protected VetoableChangeListener[] newArray(int length) {
  12.511 +            return (0 < length)
  12.512 +                    ? new VetoableChangeListener[length]
  12.513 +                    : EMPTY;
  12.514 +        }
  12.515 +
  12.516 +        /**
  12.517 +         * Creates a {@link VetoableChangeListenerProxy VetoableChangeListenerProxy}
  12.518 +         * object for the specified property.
  12.519 +         *
  12.520 +         * @param name      the name of the property to listen on
  12.521 +         * @param listener  the listener to process events
  12.522 +         * @return          a {@code VetoableChangeListenerProxy} object
  12.523 +         */
  12.524 +        @Override
  12.525 +        protected VetoableChangeListener newProxy(String name, VetoableChangeListener listener) {
  12.526 +            return new VetoableChangeListenerProxy(name, listener);
  12.527 +        }
  12.528 +    }
  12.529 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/emul/compact/src/main/java/java/io/Bits.java	Mon Feb 04 09:37:56 2013 +0100
    13.3 @@ -0,0 +1,123 @@
    13.4 +/*
    13.5 + * Copyright (c) 2001, 2010, 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 + * Utility methods for packing/unpacking primitive values in/out of byte arrays
   13.33 + * using big-endian byte ordering.
   13.34 + */
   13.35 +class Bits {
   13.36 +
   13.37 +    /*
   13.38 +     * Methods for unpacking primitive values from byte arrays starting at
   13.39 +     * given offsets.
   13.40 +     */
   13.41 +
   13.42 +    static boolean getBoolean(byte[] b, int off) {
   13.43 +        return b[off] != 0;
   13.44 +    }
   13.45 +
   13.46 +    static char getChar(byte[] b, int off) {
   13.47 +        return (char) ((b[off + 1] & 0xFF) +
   13.48 +                       (b[off] << 8));
   13.49 +    }
   13.50 +
   13.51 +    static short getShort(byte[] b, int off) {
   13.52 +        return (short) ((b[off + 1] & 0xFF) +
   13.53 +                        (b[off] << 8));
   13.54 +    }
   13.55 +
   13.56 +    static int getInt(byte[] b, int off) {
   13.57 +        return ((b[off + 3] & 0xFF)      ) +
   13.58 +               ((b[off + 2] & 0xFF) <<  8) +
   13.59 +               ((b[off + 1] & 0xFF) << 16) +
   13.60 +               ((b[off    ]       ) << 24);
   13.61 +    }
   13.62 +
   13.63 +    static float getFloat(byte[] b, int off) {
   13.64 +        return Float.intBitsToFloat(getInt(b, off));
   13.65 +    }
   13.66 +
   13.67 +    static long getLong(byte[] b, int off) {
   13.68 +        return ((b[off + 7] & 0xFFL)      ) +
   13.69 +               ((b[off + 6] & 0xFFL) <<  8) +
   13.70 +               ((b[off + 5] & 0xFFL) << 16) +
   13.71 +               ((b[off + 4] & 0xFFL) << 24) +
   13.72 +               ((b[off + 3] & 0xFFL) << 32) +
   13.73 +               ((b[off + 2] & 0xFFL) << 40) +
   13.74 +               ((b[off + 1] & 0xFFL) << 48) +
   13.75 +               (((long) b[off])      << 56);
   13.76 +    }
   13.77 +
   13.78 +    static double getDouble(byte[] b, int off) {
   13.79 +        return Double.longBitsToDouble(getLong(b, off));
   13.80 +    }
   13.81 +
   13.82 +    /*
   13.83 +     * Methods for packing primitive values into byte arrays starting at given
   13.84 +     * offsets.
   13.85 +     */
   13.86 +
   13.87 +    static void putBoolean(byte[] b, int off, boolean val) {
   13.88 +        b[off] = (byte) (val ? 1 : 0);
   13.89 +    }
   13.90 +
   13.91 +    static void putChar(byte[] b, int off, char val) {
   13.92 +        b[off + 1] = (byte) (val      );
   13.93 +        b[off    ] = (byte) (val >>> 8);
   13.94 +    }
   13.95 +
   13.96 +    static void putShort(byte[] b, int off, short val) {
   13.97 +        b[off + 1] = (byte) (val      );
   13.98 +        b[off    ] = (byte) (val >>> 8);
   13.99 +    }
  13.100 +
  13.101 +    static void putInt(byte[] b, int off, int val) {
  13.102 +        b[off + 3] = (byte) (val       );
  13.103 +        b[off + 2] = (byte) (val >>>  8);
  13.104 +        b[off + 1] = (byte) (val >>> 16);
  13.105 +        b[off    ] = (byte) (val >>> 24);
  13.106 +    }
  13.107 +
  13.108 +    static void putFloat(byte[] b, int off, float val) {
  13.109 +        putInt(b, off,  Float.floatToIntBits(val));
  13.110 +    }
  13.111 +
  13.112 +    static void putLong(byte[] b, int off, long val) {
  13.113 +        b[off + 7] = (byte) (val       );
  13.114 +        b[off + 6] = (byte) (val >>>  8);
  13.115 +        b[off + 5] = (byte) (val >>> 16);
  13.116 +        b[off + 4] = (byte) (val >>> 24);
  13.117 +        b[off + 3] = (byte) (val >>> 32);
  13.118 +        b[off + 2] = (byte) (val >>> 40);
  13.119 +        b[off + 1] = (byte) (val >>> 48);
  13.120 +        b[off    ] = (byte) (val >>> 56);
  13.121 +    }
  13.122 +
  13.123 +    static void putDouble(byte[] b, int off, double val) {
  13.124 +        putLong(b, off, Double.doubleToLongBits(val));
  13.125 +    }
  13.126 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/emul/compact/src/main/java/java/io/DataOutput.java	Mon Feb 04 09:37:56 2013 +0100
    14.3 @@ -0,0 +1,354 @@
    14.4 +/*
    14.5 + * Copyright (c) 1995, 2006, 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 +/**
   14.32 + * The <code>DataOutput</code> interface provides
   14.33 + * for converting data from any of the Java
   14.34 + * primitive types to a series of bytes and
   14.35 + * writing these bytes to a binary stream.
   14.36 + * There is  also a facility for converting
   14.37 + * a <code>String</code> into
   14.38 + * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
   14.39 + * format and writing the resulting series
   14.40 + * of bytes.
   14.41 + * <p>
   14.42 + * For all the methods in this interface that
   14.43 + * write bytes, it is generally true that if
   14.44 + * a byte cannot be written for any reason,
   14.45 + * an <code>IOException</code> is thrown.
   14.46 + *
   14.47 + * @author  Frank Yellin
   14.48 + * @see     java.io.DataInput
   14.49 + * @see     java.io.DataOutputStream
   14.50 + * @since   JDK1.0
   14.51 + */
   14.52 +public
   14.53 +interface DataOutput {
   14.54 +    /**
   14.55 +     * Writes to the output stream the eight
   14.56 +     * low-order bits of the argument <code>b</code>.
   14.57 +     * The 24 high-order  bits of <code>b</code>
   14.58 +     * are ignored.
   14.59 +     *
   14.60 +     * @param      b   the byte to be written.
   14.61 +     * @throws     IOException  if an I/O error occurs.
   14.62 +     */
   14.63 +    void write(int b) throws IOException;
   14.64 +
   14.65 +    /**
   14.66 +     * Writes to the output stream all the bytes in array <code>b</code>.
   14.67 +     * If <code>b</code> is <code>null</code>,
   14.68 +     * a <code>NullPointerException</code> is thrown.
   14.69 +     * If <code>b.length</code> is zero, then
   14.70 +     * no bytes are written. Otherwise, the byte
   14.71 +     * <code>b[0]</code> is written first, then
   14.72 +     * <code>b[1]</code>, and so on; the last byte
   14.73 +     * written is <code>b[b.length-1]</code>.
   14.74 +     *
   14.75 +     * @param      b   the data.
   14.76 +     * @throws     IOException  if an I/O error occurs.
   14.77 +     */
   14.78 +    void write(byte b[]) throws IOException;
   14.79 +
   14.80 +    /**
   14.81 +     * Writes <code>len</code> bytes from array
   14.82 +     * <code>b</code>, in order,  to
   14.83 +     * the output stream.  If <code>b</code>
   14.84 +     * is <code>null</code>, a <code>NullPointerException</code>
   14.85 +     * is thrown.  If <code>off</code> is negative,
   14.86 +     * or <code>len</code> is negative, or <code>off+len</code>
   14.87 +     * is greater than the length of the array
   14.88 +     * <code>b</code>, then an <code>IndexOutOfBoundsException</code>
   14.89 +     * is thrown.  If <code>len</code> is zero,
   14.90 +     * then no bytes are written. Otherwise, the
   14.91 +     * byte <code>b[off]</code> is written first,
   14.92 +     * then <code>b[off+1]</code>, and so on; the
   14.93 +     * last byte written is <code>b[off+len-1]</code>.
   14.94 +     *
   14.95 +     * @param      b     the data.
   14.96 +     * @param      off   the start offset in the data.
   14.97 +     * @param      len   the number of bytes to write.
   14.98 +     * @throws     IOException  if an I/O error occurs.
   14.99 +     */
  14.100 +    void write(byte b[], int off, int len) throws IOException;
  14.101 +
  14.102 +    /**
  14.103 +     * Writes a <code>boolean</code> value to this output stream.
  14.104 +     * If the argument <code>v</code>
  14.105 +     * is <code>true</code>, the value <code>(byte)1</code>
  14.106 +     * is written; if <code>v</code> is <code>false</code>,
  14.107 +     * the  value <code>(byte)0</code> is written.
  14.108 +     * The byte written by this method may
  14.109 +     * be read by the <code>readBoolean</code>
  14.110 +     * method of interface <code>DataInput</code>,
  14.111 +     * which will then return a <code>boolean</code>
  14.112 +     * equal to <code>v</code>.
  14.113 +     *
  14.114 +     * @param      v   the boolean to be written.
  14.115 +     * @throws     IOException  if an I/O error occurs.
  14.116 +     */
  14.117 +    void writeBoolean(boolean v) throws IOException;
  14.118 +
  14.119 +    /**
  14.120 +     * Writes to the output stream the eight low-
  14.121 +     * order bits of the argument <code>v</code>.
  14.122 +     * The 24 high-order bits of <code>v</code>
  14.123 +     * are ignored. (This means  that <code>writeByte</code>
  14.124 +     * does exactly the same thing as <code>write</code>
  14.125 +     * for an integer argument.) The byte written
  14.126 +     * by this method may be read by the <code>readByte</code>
  14.127 +     * method of interface <code>DataInput</code>,
  14.128 +     * which will then return a <code>byte</code>
  14.129 +     * equal to <code>(byte)v</code>.
  14.130 +     *
  14.131 +     * @param      v   the byte value to be written.
  14.132 +     * @throws     IOException  if an I/O error occurs.
  14.133 +     */
  14.134 +    void writeByte(int v) throws IOException;
  14.135 +
  14.136 +    /**
  14.137 +     * Writes two bytes to the output
  14.138 +     * stream to represent the value of the argument.
  14.139 +     * The byte values to be written, in the  order
  14.140 +     * shown, are: <p>
  14.141 +     * <pre><code>
  14.142 +     * (byte)(0xff &amp; (v &gt;&gt; 8))
  14.143 +     * (byte)(0xff &amp; v)
  14.144 +     * </code> </pre> <p>
  14.145 +     * The bytes written by this method may be
  14.146 +     * read by the <code>readShort</code> method
  14.147 +     * of interface <code>DataInput</code> , which
  14.148 +     * will then return a <code>short</code> equal
  14.149 +     * to <code>(short)v</code>.
  14.150 +     *
  14.151 +     * @param      v   the <code>short</code> value to be written.
  14.152 +     * @throws     IOException  if an I/O error occurs.
  14.153 +     */
  14.154 +    void writeShort(int v) throws IOException;
  14.155 +
  14.156 +    /**
  14.157 +     * Writes a <code>char</code> value, which
  14.158 +     * is comprised of two bytes, to the
  14.159 +     * output stream.
  14.160 +     * The byte values to be written, in the  order
  14.161 +     * shown, are:
  14.162 +     * <p><pre><code>
  14.163 +     * (byte)(0xff &amp; (v &gt;&gt; 8))
  14.164 +     * (byte)(0xff &amp; v)
  14.165 +     * </code></pre><p>
  14.166 +     * The bytes written by this method may be
  14.167 +     * read by the <code>readChar</code> method
  14.168 +     * of interface <code>DataInput</code> , which
  14.169 +     * will then return a <code>char</code> equal
  14.170 +     * to <code>(char)v</code>.
  14.171 +     *
  14.172 +     * @param      v   the <code>char</code> value to be written.
  14.173 +     * @throws     IOException  if an I/O error occurs.
  14.174 +     */
  14.175 +    void writeChar(int v) throws IOException;
  14.176 +
  14.177 +    /**
  14.178 +     * Writes an <code>int</code> value, which is
  14.179 +     * comprised of four bytes, to the output stream.
  14.180 +     * The byte values to be written, in the  order
  14.181 +     * shown, are:
  14.182 +     * <p><pre><code>
  14.183 +     * (byte)(0xff &amp; (v &gt;&gt; 24))
  14.184 +     * (byte)(0xff &amp; (v &gt;&gt; 16))
  14.185 +     * (byte)(0xff &amp; (v &gt;&gt; &#32; &#32;8))
  14.186 +     * (byte)(0xff &amp; v)
  14.187 +     * </code></pre><p>
  14.188 +     * The bytes written by this method may be read
  14.189 +     * by the <code>readInt</code> method of interface
  14.190 +     * <code>DataInput</code> , which will then
  14.191 +     * return an <code>int</code> equal to <code>v</code>.
  14.192 +     *
  14.193 +     * @param      v   the <code>int</code> value to be written.
  14.194 +     * @throws     IOException  if an I/O error occurs.
  14.195 +     */
  14.196 +    void writeInt(int v) throws IOException;
  14.197 +
  14.198 +    /**
  14.199 +     * Writes a <code>long</code> value, which is
  14.200 +     * comprised of eight bytes, to the output stream.
  14.201 +     * The byte values to be written, in the  order
  14.202 +     * shown, are:
  14.203 +     * <p><pre><code>
  14.204 +     * (byte)(0xff &amp; (v &gt;&gt; 56))
  14.205 +     * (byte)(0xff &amp; (v &gt;&gt; 48))
  14.206 +     * (byte)(0xff &amp; (v &gt;&gt; 40))
  14.207 +     * (byte)(0xff &amp; (v &gt;&gt; 32))
  14.208 +     * (byte)(0xff &amp; (v &gt;&gt; 24))
  14.209 +     * (byte)(0xff &amp; (v &gt;&gt; 16))
  14.210 +     * (byte)(0xff &amp; (v &gt;&gt;  8))
  14.211 +     * (byte)(0xff &amp; v)
  14.212 +     * </code></pre><p>
  14.213 +     * The bytes written by this method may be
  14.214 +     * read by the <code>readLong</code> method
  14.215 +     * of interface <code>DataInput</code> , which
  14.216 +     * will then return a <code>long</code> equal
  14.217 +     * to <code>v</code>.
  14.218 +     *
  14.219 +     * @param      v   the <code>long</code> value to be written.
  14.220 +     * @throws     IOException  if an I/O error occurs.
  14.221 +     */
  14.222 +    void writeLong(long v) throws IOException;
  14.223 +
  14.224 +    /**
  14.225 +     * Writes a <code>float</code> value,
  14.226 +     * which is comprised of four bytes, to the output stream.
  14.227 +     * It does this as if it first converts this
  14.228 +     * <code>float</code> value to an <code>int</code>
  14.229 +     * in exactly the manner of the <code>Float.floatToIntBits</code>
  14.230 +     * method  and then writes the <code>int</code>
  14.231 +     * value in exactly the manner of the  <code>writeInt</code>
  14.232 +     * method.  The bytes written by this method
  14.233 +     * may be read by the <code>readFloat</code>
  14.234 +     * method of interface <code>DataInput</code>,
  14.235 +     * which will then return a <code>float</code>
  14.236 +     * equal to <code>v</code>.
  14.237 +     *
  14.238 +     * @param      v   the <code>float</code> value to be written.
  14.239 +     * @throws     IOException  if an I/O error occurs.
  14.240 +     */
  14.241 +    void writeFloat(float v) throws IOException;
  14.242 +
  14.243 +    /**
  14.244 +     * Writes a <code>double</code> value,
  14.245 +     * which is comprised of eight bytes, to the output stream.
  14.246 +     * It does this as if it first converts this
  14.247 +     * <code>double</code> value to a <code>long</code>
  14.248 +     * in exactly the manner of the <code>Double.doubleToLongBits</code>
  14.249 +     * method  and then writes the <code>long</code>
  14.250 +     * value in exactly the manner of the  <code>writeLong</code>
  14.251 +     * method. The bytes written by this method
  14.252 +     * may be read by the <code>readDouble</code>
  14.253 +     * method of interface <code>DataInput</code>,
  14.254 +     * which will then return a <code>double</code>
  14.255 +     * equal to <code>v</code>.
  14.256 +     *
  14.257 +     * @param      v   the <code>double</code> value to be written.
  14.258 +     * @throws     IOException  if an I/O error occurs.
  14.259 +     */
  14.260 +    void writeDouble(double v) throws IOException;
  14.261 +
  14.262 +    /**
  14.263 +     * Writes a string to the output stream.
  14.264 +     * For every character in the string
  14.265 +     * <code>s</code>,  taken in order, one byte
  14.266 +     * is written to the output stream.  If
  14.267 +     * <code>s</code> is <code>null</code>, a <code>NullPointerException</code>
  14.268 +     * is thrown.<p>  If <code>s.length</code>
  14.269 +     * is zero, then no bytes are written. Otherwise,
  14.270 +     * the character <code>s[0]</code> is written
  14.271 +     * first, then <code>s[1]</code>, and so on;
  14.272 +     * the last character written is <code>s[s.length-1]</code>.
  14.273 +     * For each character, one byte is written,
  14.274 +     * the low-order byte, in exactly the manner
  14.275 +     * of the <code>writeByte</code> method . The
  14.276 +     * high-order eight bits of each character
  14.277 +     * in the string are ignored.
  14.278 +     *
  14.279 +     * @param      s   the string of bytes to be written.
  14.280 +     * @throws     IOException  if an I/O error occurs.
  14.281 +     */
  14.282 +    void writeBytes(String s) throws IOException;
  14.283 +
  14.284 +    /**
  14.285 +     * Writes every character in the string <code>s</code>,
  14.286 +     * to the output stream, in order,
  14.287 +     * two bytes per character. If <code>s</code>
  14.288 +     * is <code>null</code>, a <code>NullPointerException</code>
  14.289 +     * is thrown.  If <code>s.length</code>
  14.290 +     * is zero, then no characters are written.
  14.291 +     * Otherwise, the character <code>s[0]</code>
  14.292 +     * is written first, then <code>s[1]</code>,
  14.293 +     * and so on; the last character written is
  14.294 +     * <code>s[s.length-1]</code>. For each character,
  14.295 +     * two bytes are actually written, high-order
  14.296 +     * byte first, in exactly the manner of the
  14.297 +     * <code>writeChar</code> method.
  14.298 +     *
  14.299 +     * @param      s   the string value to be written.
  14.300 +     * @throws     IOException  if an I/O error occurs.
  14.301 +     */
  14.302 +    void writeChars(String s) throws IOException;
  14.303 +
  14.304 +    /**
  14.305 +     * Writes two bytes of length information
  14.306 +     * to the output stream, followed
  14.307 +     * by the
  14.308 +     * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
  14.309 +     * representation
  14.310 +     * of  every character in the string <code>s</code>.
  14.311 +     * If <code>s</code> is <code>null</code>,
  14.312 +     * a <code>NullPointerException</code> is thrown.
  14.313 +     * Each character in the string <code>s</code>
  14.314 +     * is converted to a group of one, two, or
  14.315 +     * three bytes, depending on the value of the
  14.316 +     * character.<p>
  14.317 +     * If a character <code>c</code>
  14.318 +     * is in the range <code>&#92;u0001</code> through
  14.319 +     * <code>&#92;u007f</code>, it is represented
  14.320 +     * by one byte:<p>
  14.321 +     * <pre>(byte)c </pre>  <p>
  14.322 +     * If a character <code>c</code> is <code>&#92;u0000</code>
  14.323 +     * or is in the range <code>&#92;u0080</code>
  14.324 +     * through <code>&#92;u07ff</code>, then it is
  14.325 +     * represented by two bytes, to be written
  14.326 +     * in the order shown:<p> <pre><code>
  14.327 +     * (byte)(0xc0 | (0x1f &amp; (c &gt;&gt; 6)))
  14.328 +     * (byte)(0x80 | (0x3f &amp; c))
  14.329 +     *  </code></pre>  <p> If a character
  14.330 +     * <code>c</code> is in the range <code>&#92;u0800</code>
  14.331 +     * through <code>uffff</code>, then it is
  14.332 +     * represented by three bytes, to be written
  14.333 +     * in the order shown:<p> <pre><code>
  14.334 +     * (byte)(0xe0 | (0x0f &amp; (c &gt;&gt; 12)))
  14.335 +     * (byte)(0x80 | (0x3f &amp; (c &gt;&gt;  6)))
  14.336 +     * (byte)(0x80 | (0x3f &amp; c))
  14.337 +     *  </code></pre>  <p> First,
  14.338 +     * the total number of bytes needed to represent
  14.339 +     * all the characters of <code>s</code> is
  14.340 +     * calculated. If this number is larger than
  14.341 +     * <code>65535</code>, then a <code>UTFDataFormatException</code>
  14.342 +     * is thrown. Otherwise, this length is written
  14.343 +     * to the output stream in exactly the manner
  14.344 +     * of the <code>writeShort</code> method;
  14.345 +     * after this, the one-, two-, or three-byte
  14.346 +     * representation of each character in the
  14.347 +     * string <code>s</code> is written.<p>  The
  14.348 +     * bytes written by this method may be read
  14.349 +     * by the <code>readUTF</code> method of interface
  14.350 +     * <code>DataInput</code> , which will then
  14.351 +     * return a <code>String</code> equal to <code>s</code>.
  14.352 +     *
  14.353 +     * @param      s   the string value to be written.
  14.354 +     * @throws     IOException  if an I/O error occurs.
  14.355 +     */
  14.356 +    void writeUTF(String s) throws IOException;
  14.357 +}
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/emul/compact/src/main/java/java/io/DataOutputStream.java	Mon Feb 04 09:37:56 2013 +0100
    15.3 @@ -0,0 +1,416 @@
    15.4 +/*
    15.5 + * Copyright (c) 1994, 2004, 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 + * A data output stream lets an application write primitive Java data
   15.33 + * types to an output stream in a portable way. An application can
   15.34 + * then use a data input stream to read the data back in.
   15.35 + *
   15.36 + * @author  unascribed
   15.37 + * @see     java.io.DataInputStream
   15.38 + * @since   JDK1.0
   15.39 + */
   15.40 +public
   15.41 +class DataOutputStream extends FilterOutputStream implements DataOutput {
   15.42 +    /**
   15.43 +     * The number of bytes written to the data output stream so far.
   15.44 +     * If this counter overflows, it will be wrapped to Integer.MAX_VALUE.
   15.45 +     */
   15.46 +    protected int written;
   15.47 +
   15.48 +    /**
   15.49 +     * bytearr is initialized on demand by writeUTF
   15.50 +     */
   15.51 +    private byte[] bytearr = null;
   15.52 +
   15.53 +    /**
   15.54 +     * Creates a new data output stream to write data to the specified
   15.55 +     * underlying output stream. The counter <code>written</code> is
   15.56 +     * set to zero.
   15.57 +     *
   15.58 +     * @param   out   the underlying output stream, to be saved for later
   15.59 +     *                use.
   15.60 +     * @see     java.io.FilterOutputStream#out
   15.61 +     */
   15.62 +    public DataOutputStream(OutputStream out) {
   15.63 +        super(out);
   15.64 +    }
   15.65 +
   15.66 +    /**
   15.67 +     * Increases the written counter by the specified value
   15.68 +     * until it reaches Integer.MAX_VALUE.
   15.69 +     */
   15.70 +    private void incCount(int value) {
   15.71 +        int temp = written + value;
   15.72 +        if (temp < 0) {
   15.73 +            temp = Integer.MAX_VALUE;
   15.74 +        }
   15.75 +        written = temp;
   15.76 +    }
   15.77 +
   15.78 +    /**
   15.79 +     * Writes the specified byte (the low eight bits of the argument
   15.80 +     * <code>b</code>) to the underlying output stream. If no exception
   15.81 +     * is thrown, the counter <code>written</code> is incremented by
   15.82 +     * <code>1</code>.
   15.83 +     * <p>
   15.84 +     * Implements the <code>write</code> method of <code>OutputStream</code>.
   15.85 +     *
   15.86 +     * @param      b   the <code>byte</code> to be written.
   15.87 +     * @exception  IOException  if an I/O error occurs.
   15.88 +     * @see        java.io.FilterOutputStream#out
   15.89 +     */
   15.90 +    public synchronized void write(int b) throws IOException {
   15.91 +        out.write(b);
   15.92 +        incCount(1);
   15.93 +    }
   15.94 +
   15.95 +    /**
   15.96 +     * Writes <code>len</code> bytes from the specified byte array
   15.97 +     * starting at offset <code>off</code> to the underlying output stream.
   15.98 +     * If no exception is thrown, the counter <code>written</code> is
   15.99 +     * incremented by <code>len</code>.
  15.100 +     *
  15.101 +     * @param      b     the data.
  15.102 +     * @param      off   the start offset in the data.
  15.103 +     * @param      len   the number of bytes to write.
  15.104 +     * @exception  IOException  if an I/O error occurs.
  15.105 +     * @see        java.io.FilterOutputStream#out
  15.106 +     */
  15.107 +    public synchronized void write(byte b[], int off, int len)
  15.108 +        throws IOException
  15.109 +    {
  15.110 +        out.write(b, off, len);
  15.111 +        incCount(len);
  15.112 +    }
  15.113 +
  15.114 +    /**
  15.115 +     * Flushes this data output stream. This forces any buffered output
  15.116 +     * bytes to be written out to the stream.
  15.117 +     * <p>
  15.118 +     * The <code>flush</code> method of <code>DataOutputStream</code>
  15.119 +     * calls the <code>flush</code> method of its underlying output stream.
  15.120 +     *
  15.121 +     * @exception  IOException  if an I/O error occurs.
  15.122 +     * @see        java.io.FilterOutputStream#out
  15.123 +     * @see        java.io.OutputStream#flush()
  15.124 +     */
  15.125 +    public void flush() throws IOException {
  15.126 +        out.flush();
  15.127 +    }
  15.128 +
  15.129 +    /**
  15.130 +     * Writes a <code>boolean</code> to the underlying output stream as
  15.131 +     * a 1-byte value. The value <code>true</code> is written out as the
  15.132 +     * value <code>(byte)1</code>; the value <code>false</code> is
  15.133 +     * written out as the value <code>(byte)0</code>. If no exception is
  15.134 +     * thrown, the counter <code>written</code> is incremented by
  15.135 +     * <code>1</code>.
  15.136 +     *
  15.137 +     * @param      v   a <code>boolean</code> value to be written.
  15.138 +     * @exception  IOException  if an I/O error occurs.
  15.139 +     * @see        java.io.FilterOutputStream#out
  15.140 +     */
  15.141 +    public final void writeBoolean(boolean v) throws IOException {
  15.142 +        out.write(v ? 1 : 0);
  15.143 +        incCount(1);
  15.144 +    }
  15.145 +
  15.146 +    /**
  15.147 +     * Writes out a <code>byte</code> to the underlying output stream as
  15.148 +     * a 1-byte value. If no exception is thrown, the counter
  15.149 +     * <code>written</code> is incremented by <code>1</code>.
  15.150 +     *
  15.151 +     * @param      v   a <code>byte</code> value to be written.
  15.152 +     * @exception  IOException  if an I/O error occurs.
  15.153 +     * @see        java.io.FilterOutputStream#out
  15.154 +     */
  15.155 +    public final void writeByte(int v) throws IOException {
  15.156 +        out.write(v);
  15.157 +        incCount(1);
  15.158 +    }
  15.159 +
  15.160 +    /**
  15.161 +     * Writes a <code>short</code> to the underlying output stream as two
  15.162 +     * bytes, high byte first. If no exception is thrown, the counter
  15.163 +     * <code>written</code> is incremented by <code>2</code>.
  15.164 +     *
  15.165 +     * @param      v   a <code>short</code> to be written.
  15.166 +     * @exception  IOException  if an I/O error occurs.
  15.167 +     * @see        java.io.FilterOutputStream#out
  15.168 +     */
  15.169 +    public final void writeShort(int v) throws IOException {
  15.170 +        out.write((v >>> 8) & 0xFF);
  15.171 +        out.write((v >>> 0) & 0xFF);
  15.172 +        incCount(2);
  15.173 +    }
  15.174 +
  15.175 +    /**
  15.176 +     * Writes a <code>char</code> to the underlying output stream as a
  15.177 +     * 2-byte value, high byte first. If no exception is thrown, the
  15.178 +     * counter <code>written</code> is incremented by <code>2</code>.
  15.179 +     *
  15.180 +     * @param      v   a <code>char</code> value to be written.
  15.181 +     * @exception  IOException  if an I/O error occurs.
  15.182 +     * @see        java.io.FilterOutputStream#out
  15.183 +     */
  15.184 +    public final void writeChar(int v) throws IOException {
  15.185 +        out.write((v >>> 8) & 0xFF);
  15.186 +        out.write((v >>> 0) & 0xFF);
  15.187 +        incCount(2);
  15.188 +    }
  15.189 +
  15.190 +    /**
  15.191 +     * Writes an <code>int</code> to the underlying output stream as four
  15.192 +     * bytes, high byte first. If no exception is thrown, the counter
  15.193 +     * <code>written</code> is incremented by <code>4</code>.
  15.194 +     *
  15.195 +     * @param      v   an <code>int</code> to be written.
  15.196 +     * @exception  IOException  if an I/O error occurs.
  15.197 +     * @see        java.io.FilterOutputStream#out
  15.198 +     */
  15.199 +    public final void writeInt(int v) throws IOException {
  15.200 +        out.write((v >>> 24) & 0xFF);
  15.201 +        out.write((v >>> 16) & 0xFF);
  15.202 +        out.write((v >>>  8) & 0xFF);
  15.203 +        out.write((v >>>  0) & 0xFF);
  15.204 +        incCount(4);
  15.205 +    }
  15.206 +
  15.207 +    private byte writeBuffer[] = new byte[8];
  15.208 +
  15.209 +    /**
  15.210 +     * Writes a <code>long</code> to the underlying output stream as eight
  15.211 +     * bytes, high byte first. In no exception is thrown, the counter
  15.212 +     * <code>written</code> is incremented by <code>8</code>.
  15.213 +     *
  15.214 +     * @param      v   a <code>long</code> to be written.
  15.215 +     * @exception  IOException  if an I/O error occurs.
  15.216 +     * @see        java.io.FilterOutputStream#out
  15.217 +     */
  15.218 +    public final void writeLong(long v) throws IOException {
  15.219 +        writeBuffer[0] = (byte)(v >>> 56);
  15.220 +        writeBuffer[1] = (byte)(v >>> 48);
  15.221 +        writeBuffer[2] = (byte)(v >>> 40);
  15.222 +        writeBuffer[3] = (byte)(v >>> 32);
  15.223 +        writeBuffer[4] = (byte)(v >>> 24);
  15.224 +        writeBuffer[5] = (byte)(v >>> 16);
  15.225 +        writeBuffer[6] = (byte)(v >>>  8);
  15.226 +        writeBuffer[7] = (byte)(v >>>  0);
  15.227 +        out.write(writeBuffer, 0, 8);
  15.228 +        incCount(8);
  15.229 +    }
  15.230 +
  15.231 +    /**
  15.232 +     * Converts the float argument to an <code>int</code> using the
  15.233 +     * <code>floatToIntBits</code> method in class <code>Float</code>,
  15.234 +     * and then writes that <code>int</code> value to the underlying
  15.235 +     * output stream as a 4-byte quantity, high byte first. If no
  15.236 +     * exception is thrown, the counter <code>written</code> is
  15.237 +     * incremented by <code>4</code>.
  15.238 +     *
  15.239 +     * @param      v   a <code>float</code> value to be written.
  15.240 +     * @exception  IOException  if an I/O error occurs.
  15.241 +     * @see        java.io.FilterOutputStream#out
  15.242 +     * @see        java.lang.Float#floatToIntBits(float)
  15.243 +     */
  15.244 +    public final void writeFloat(float v) throws IOException {
  15.245 +        writeInt(Float.floatToIntBits(v));
  15.246 +    }
  15.247 +
  15.248 +    /**
  15.249 +     * Converts the double argument to a <code>long</code> using the
  15.250 +     * <code>doubleToLongBits</code> method in class <code>Double</code>,
  15.251 +     * and then writes that <code>long</code> value to the underlying
  15.252 +     * output stream as an 8-byte quantity, high byte first. If no
  15.253 +     * exception is thrown, the counter <code>written</code> is
  15.254 +     * incremented by <code>8</code>.
  15.255 +     *
  15.256 +     * @param      v   a <code>double</code> value to be written.
  15.257 +     * @exception  IOException  if an I/O error occurs.
  15.258 +     * @see        java.io.FilterOutputStream#out
  15.259 +     * @see        java.lang.Double#doubleToLongBits(double)
  15.260 +     */
  15.261 +    public final void writeDouble(double v) throws IOException {
  15.262 +        writeLong(Double.doubleToLongBits(v));
  15.263 +    }
  15.264 +
  15.265 +    /**
  15.266 +     * Writes out the string to the underlying output stream as a
  15.267 +     * sequence of bytes. Each character in the string is written out, in
  15.268 +     * sequence, by discarding its high eight bits. If no exception is
  15.269 +     * thrown, the counter <code>written</code> is incremented by the
  15.270 +     * length of <code>s</code>.
  15.271 +     *
  15.272 +     * @param      s   a string of bytes to be written.
  15.273 +     * @exception  IOException  if an I/O error occurs.
  15.274 +     * @see        java.io.FilterOutputStream#out
  15.275 +     */
  15.276 +    public final void writeBytes(String s) throws IOException {
  15.277 +        int len = s.length();
  15.278 +        for (int i = 0 ; i < len ; i++) {
  15.279 +            out.write((byte)s.charAt(i));
  15.280 +        }
  15.281 +        incCount(len);
  15.282 +    }
  15.283 +
  15.284 +    /**
  15.285 +     * Writes a string to the underlying output stream as a sequence of
  15.286 +     * characters. Each character is written to the data output stream as
  15.287 +     * if by the <code>writeChar</code> method. If no exception is
  15.288 +     * thrown, the counter <code>written</code> is incremented by twice
  15.289 +     * the length of <code>s</code>.
  15.290 +     *
  15.291 +     * @param      s   a <code>String</code> value to be written.
  15.292 +     * @exception  IOException  if an I/O error occurs.
  15.293 +     * @see        java.io.DataOutputStream#writeChar(int)
  15.294 +     * @see        java.io.FilterOutputStream#out
  15.295 +     */
  15.296 +    public final void writeChars(String s) throws IOException {
  15.297 +        int len = s.length();
  15.298 +        for (int i = 0 ; i < len ; i++) {
  15.299 +            int v = s.charAt(i);
  15.300 +            out.write((v >>> 8) & 0xFF);
  15.301 +            out.write((v >>> 0) & 0xFF);
  15.302 +        }
  15.303 +        incCount(len * 2);
  15.304 +    }
  15.305 +
  15.306 +    /**
  15.307 +     * Writes a string to the underlying output stream using
  15.308 +     * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
  15.309 +     * encoding in a machine-independent manner.
  15.310 +     * <p>
  15.311 +     * First, two bytes are written to the output stream as if by the
  15.312 +     * <code>writeShort</code> method giving the number of bytes to
  15.313 +     * follow. This value is the number of bytes actually written out,
  15.314 +     * not the length of the string. Following the length, each character
  15.315 +     * of the string is output, in sequence, using the modified UTF-8 encoding
  15.316 +     * for the character. If no exception is thrown, the counter
  15.317 +     * <code>written</code> is incremented by the total number of
  15.318 +     * bytes written to the output stream. This will be at least two
  15.319 +     * plus the length of <code>str</code>, and at most two plus
  15.320 +     * thrice the length of <code>str</code>.
  15.321 +     *
  15.322 +     * @param      str   a string to be written.
  15.323 +     * @exception  IOException  if an I/O error occurs.
  15.324 +     */
  15.325 +    public final void writeUTF(String str) throws IOException {
  15.326 +        writeUTF(str, this);
  15.327 +    }
  15.328 +
  15.329 +    /**
  15.330 +     * Writes a string to the specified DataOutput using
  15.331 +     * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
  15.332 +     * encoding in a machine-independent manner.
  15.333 +     * <p>
  15.334 +     * First, two bytes are written to out as if by the <code>writeShort</code>
  15.335 +     * method giving the number of bytes to follow. This value is the number of
  15.336 +     * bytes actually written out, not the length of the string. Following the
  15.337 +     * length, each character of the string is output, in sequence, using the
  15.338 +     * modified UTF-8 encoding for the character. If no exception is thrown, the
  15.339 +     * counter <code>written</code> is incremented by the total number of
  15.340 +     * bytes written to the output stream. This will be at least two
  15.341 +     * plus the length of <code>str</code>, and at most two plus
  15.342 +     * thrice the length of <code>str</code>.
  15.343 +     *
  15.344 +     * @param      str   a string to be written.
  15.345 +     * @param      out   destination to write to
  15.346 +     * @return     The number of bytes written out.
  15.347 +     * @exception  IOException  if an I/O error occurs.
  15.348 +     */
  15.349 +    static int writeUTF(String str, DataOutput out) throws IOException {
  15.350 +        int strlen = str.length();
  15.351 +        int utflen = 0;
  15.352 +        int c, count = 0;
  15.353 +
  15.354 +        /* use charAt instead of copying String to char array */
  15.355 +        for (int i = 0; i < strlen; i++) {
  15.356 +            c = str.charAt(i);
  15.357 +            if ((c >= 0x0001) && (c <= 0x007F)) {
  15.358 +                utflen++;
  15.359 +            } else if (c > 0x07FF) {
  15.360 +                utflen += 3;
  15.361 +            } else {
  15.362 +                utflen += 2;
  15.363 +            }
  15.364 +        }
  15.365 +
  15.366 +        if (utflen > 65535)
  15.367 +            throw new UTFDataFormatException(
  15.368 +                "encoded string too long: " + utflen + " bytes");
  15.369 +
  15.370 +        byte[] bytearr = null;
  15.371 +        if (out instanceof DataOutputStream) {
  15.372 +            DataOutputStream dos = (DataOutputStream)out;
  15.373 +            if(dos.bytearr == null || (dos.bytearr.length < (utflen+2)))
  15.374 +                dos.bytearr = new byte[(utflen*2) + 2];
  15.375 +            bytearr = dos.bytearr;
  15.376 +        } else {
  15.377 +            bytearr = new byte[utflen+2];
  15.378 +        }
  15.379 +
  15.380 +        bytearr[count++] = (byte) ((utflen >>> 8) & 0xFF);
  15.381 +        bytearr[count++] = (byte) ((utflen >>> 0) & 0xFF);
  15.382 +
  15.383 +        int i=0;
  15.384 +        for (i=0; i<strlen; i++) {
  15.385 +           c = str.charAt(i);
  15.386 +           if (!((c >= 0x0001) && (c <= 0x007F))) break;
  15.387 +           bytearr[count++] = (byte) c;
  15.388 +        }
  15.389 +
  15.390 +        for (;i < strlen; i++){
  15.391 +            c = str.charAt(i);
  15.392 +            if ((c >= 0x0001) && (c <= 0x007F)) {
  15.393 +                bytearr[count++] = (byte) c;
  15.394 +
  15.395 +            } else if (c > 0x07FF) {
  15.396 +                bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
  15.397 +                bytearr[count++] = (byte) (0x80 | ((c >>  6) & 0x3F));
  15.398 +                bytearr[count++] = (byte) (0x80 | ((c >>  0) & 0x3F));
  15.399 +            } else {
  15.400 +                bytearr[count++] = (byte) (0xC0 | ((c >>  6) & 0x1F));
  15.401 +                bytearr[count++] = (byte) (0x80 | ((c >>  0) & 0x3F));
  15.402 +            }
  15.403 +        }
  15.404 +        out.write(bytearr, 0, utflen+2);
  15.405 +        return utflen + 2;
  15.406 +    }
  15.407 +
  15.408 +    /**
  15.409 +     * Returns the current value of the counter <code>written</code>,
  15.410 +     * the number of bytes written to this data output stream so far.
  15.411 +     * If the counter overflows, it will be wrapped to Integer.MAX_VALUE.
  15.412 +     *
  15.413 +     * @return  the value of the <code>written</code> field.
  15.414 +     * @see     java.io.DataOutputStream#written
  15.415 +     */
  15.416 +    public final int size() {
  15.417 +        return written;
  15.418 +    }
  15.419 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/emul/compact/src/main/java/java/io/Externalizable.java	Mon Feb 04 09:37:56 2013 +0100
    16.3 @@ -0,0 +1,97 @@
    16.4 +/*
    16.5 + * Copyright (c) 1996, 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.ObjectOutput;
   16.32 +import java.io.ObjectInput;
   16.33 +
   16.34 +/**
   16.35 + * Only the identity of the class of an Externalizable instance is
   16.36 + * written in the serialization stream and it is the responsibility
   16.37 + * of the class to save and restore the contents of its instances.
   16.38 + *
   16.39 + * The writeExternal and readExternal methods of the Externalizable
   16.40 + * interface are implemented by a class to give the class complete
   16.41 + * control over the format and contents of the stream for an object
   16.42 + * and its supertypes. These methods must explicitly
   16.43 + * coordinate with the supertype to save its state. These methods supersede
   16.44 + * customized implementations of writeObject and readObject methods.<br>
   16.45 + *
   16.46 + * Object Serialization uses the Serializable and Externalizable
   16.47 + * interfaces.  Object persistence mechanisms can use them as well.  Each
   16.48 + * object to be stored is tested for the Externalizable interface. If
   16.49 + * the object supports Externalizable, the writeExternal method is called. If the
   16.50 + * object does not support Externalizable and does implement
   16.51 + * Serializable, the object is saved using
   16.52 + * ObjectOutputStream. <br> When an Externalizable object is
   16.53 + * reconstructed, an instance is created using the public no-arg
   16.54 + * constructor, then the readExternal method called.  Serializable
   16.55 + * objects are restored by reading them from an ObjectInputStream.<br>
   16.56 + *
   16.57 + * An Externalizable instance can designate a substitution object via
   16.58 + * the writeReplace and readResolve methods documented in the Serializable
   16.59 + * interface.<br>
   16.60 + *
   16.61 + * @author  unascribed
   16.62 + * @see java.io.ObjectOutputStream
   16.63 + * @see java.io.ObjectInputStream
   16.64 + * @see java.io.ObjectOutput
   16.65 + * @see java.io.ObjectInput
   16.66 + * @see java.io.Serializable
   16.67 + * @since   JDK1.1
   16.68 + */
   16.69 +public interface Externalizable extends java.io.Serializable {
   16.70 +    /**
   16.71 +     * The object implements the writeExternal method to save its contents
   16.72 +     * by calling the methods of DataOutput for its primitive values or
   16.73 +     * calling the writeObject method of ObjectOutput for objects, strings,
   16.74 +     * and arrays.
   16.75 +     *
   16.76 +     * @serialData Overriding methods should use this tag to describe
   16.77 +     *             the data layout of this Externalizable object.
   16.78 +     *             List the sequence of element types and, if possible,
   16.79 +     *             relate the element to a public/protected field and/or
   16.80 +     *             method of this Externalizable class.
   16.81 +     *
   16.82 +     * @param out the stream to write the object to
   16.83 +     * @exception IOException Includes any I/O exceptions that may occur
   16.84 +     */
   16.85 +    void writeExternal(ObjectOutput out) throws IOException;
   16.86 +
   16.87 +    /**
   16.88 +     * The object implements the readExternal method to restore its
   16.89 +     * contents by calling the methods of DataInput for primitive
   16.90 +     * types and readObject for objects, strings and arrays.  The
   16.91 +     * readExternal method must read the values in the same sequence
   16.92 +     * and with the same types as were written by writeExternal.
   16.93 +     *
   16.94 +     * @param in the stream to read data from in order to restore the object
   16.95 +     * @exception IOException if I/O errors occur
   16.96 +     * @exception ClassNotFoundException If the class for an object being
   16.97 +     *              restored cannot be found.
   16.98 +     */
   16.99 +    void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
  16.100 +}
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/emul/compact/src/main/java/java/io/FilterOutputStream.java	Mon Feb 04 09:37:56 2013 +0100
    17.3 @@ -0,0 +1,162 @@
    17.4 +/*
    17.5 + * Copyright (c) 1994, 2011, 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 + * This class is the superclass of all classes that filter output
   17.33 + * streams. These streams sit on top of an already existing output
   17.34 + * stream (the <i>underlying</i> output stream) which it uses as its
   17.35 + * basic sink of data, but possibly transforming the data along the
   17.36 + * way or providing additional functionality.
   17.37 + * <p>
   17.38 + * The class <code>FilterOutputStream</code> itself simply overrides
   17.39 + * all methods of <code>OutputStream</code> with versions that pass
   17.40 + * all requests to the underlying output stream. Subclasses of
   17.41 + * <code>FilterOutputStream</code> may further override some of these
   17.42 + * methods as well as provide additional methods and fields.
   17.43 + *
   17.44 + * @author  Jonathan Payne
   17.45 + * @since   JDK1.0
   17.46 + */
   17.47 +public
   17.48 +class FilterOutputStream extends OutputStream {
   17.49 +    /**
   17.50 +     * The underlying output stream to be filtered.
   17.51 +     */
   17.52 +    protected OutputStream out;
   17.53 +
   17.54 +    /**
   17.55 +     * Creates an output stream filter built on top of the specified
   17.56 +     * underlying output stream.
   17.57 +     *
   17.58 +     * @param   out   the underlying output stream to be assigned to
   17.59 +     *                the field <tt>this.out</tt> for later use, or
   17.60 +     *                <code>null</code> if this instance is to be
   17.61 +     *                created without an underlying stream.
   17.62 +     */
   17.63 +    public FilterOutputStream(OutputStream out) {
   17.64 +        this.out = out;
   17.65 +    }
   17.66 +
   17.67 +    /**
   17.68 +     * Writes the specified <code>byte</code> to this output stream.
   17.69 +     * <p>
   17.70 +     * The <code>write</code> method of <code>FilterOutputStream</code>
   17.71 +     * calls the <code>write</code> method of its underlying output stream,
   17.72 +     * that is, it performs <tt>out.write(b)</tt>.
   17.73 +     * <p>
   17.74 +     * Implements the abstract <tt>write</tt> method of <tt>OutputStream</tt>.
   17.75 +     *
   17.76 +     * @param      b   the <code>byte</code>.
   17.77 +     * @exception  IOException  if an I/O error occurs.
   17.78 +     */
   17.79 +    public void write(int b) throws IOException {
   17.80 +        out.write(b);
   17.81 +    }
   17.82 +
   17.83 +    /**
   17.84 +     * Writes <code>b.length</code> bytes to this output stream.
   17.85 +     * <p>
   17.86 +     * The <code>write</code> method of <code>FilterOutputStream</code>
   17.87 +     * calls its <code>write</code> method of three arguments with the
   17.88 +     * arguments <code>b</code>, <code>0</code>, and
   17.89 +     * <code>b.length</code>.
   17.90 +     * <p>
   17.91 +     * Note that this method does not call the one-argument
   17.92 +     * <code>write</code> method of its underlying stream with the single
   17.93 +     * argument <code>b</code>.
   17.94 +     *
   17.95 +     * @param      b   the data to be written.
   17.96 +     * @exception  IOException  if an I/O error occurs.
   17.97 +     * @see        java.io.FilterOutputStream#write(byte[], int, int)
   17.98 +     */
   17.99 +    public void write(byte b[]) throws IOException {
  17.100 +        write(b, 0, b.length);
  17.101 +    }
  17.102 +
  17.103 +    /**
  17.104 +     * Writes <code>len</code> bytes from the specified
  17.105 +     * <code>byte</code> array starting at offset <code>off</code> to
  17.106 +     * this output stream.
  17.107 +     * <p>
  17.108 +     * The <code>write</code> method of <code>FilterOutputStream</code>
  17.109 +     * calls the <code>write</code> method of one argument on each
  17.110 +     * <code>byte</code> to output.
  17.111 +     * <p>
  17.112 +     * Note that this method does not call the <code>write</code> method
  17.113 +     * of its underlying input stream with the same arguments. Subclasses
  17.114 +     * of <code>FilterOutputStream</code> should provide a more efficient
  17.115 +     * implementation of this method.
  17.116 +     *
  17.117 +     * @param      b     the data.
  17.118 +     * @param      off   the start offset in the data.
  17.119 +     * @param      len   the number of bytes to write.
  17.120 +     * @exception  IOException  if an I/O error occurs.
  17.121 +     * @see        java.io.FilterOutputStream#write(int)
  17.122 +     */
  17.123 +    public void write(byte b[], int off, int len) throws IOException {
  17.124 +        if ((off | len | (b.length - (len + off)) | (off + len)) < 0)
  17.125 +            throw new IndexOutOfBoundsException();
  17.126 +
  17.127 +        for (int i = 0 ; i < len ; i++) {
  17.128 +            write(b[off + i]);
  17.129 +        }
  17.130 +    }
  17.131 +
  17.132 +    /**
  17.133 +     * Flushes this output stream and forces any buffered output bytes
  17.134 +     * to be written out to the stream.
  17.135 +     * <p>
  17.136 +     * The <code>flush</code> method of <code>FilterOutputStream</code>
  17.137 +     * calls the <code>flush</code> method of its underlying output stream.
  17.138 +     *
  17.139 +     * @exception  IOException  if an I/O error occurs.
  17.140 +     * @see        java.io.FilterOutputStream#out
  17.141 +     */
  17.142 +    public void flush() throws IOException {
  17.143 +        out.flush();
  17.144 +    }
  17.145 +
  17.146 +    /**
  17.147 +     * Closes this output stream and releases any system resources
  17.148 +     * associated with the stream.
  17.149 +     * <p>
  17.150 +     * The <code>close</code> method of <code>FilterOutputStream</code>
  17.151 +     * calls its <code>flush</code> method, and then calls the
  17.152 +     * <code>close</code> method of its underlying output stream.
  17.153 +     *
  17.154 +     * @exception  IOException  if an I/O error occurs.
  17.155 +     * @see        java.io.FilterOutputStream#flush()
  17.156 +     * @see        java.io.FilterOutputStream#out
  17.157 +     */
  17.158 +    public void close() throws IOException {
  17.159 +        try {
  17.160 +          flush();
  17.161 +        } catch (IOException ignored) {
  17.162 +        }
  17.163 +        out.close();
  17.164 +    }
  17.165 +}
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/emul/compact/src/main/java/java/io/Flushable.java	Mon Feb 04 09:37:56 2013 +0100
    18.3 @@ -0,0 +1,47 @@
    18.4 +/*
    18.5 + * Copyright (c) 2004, 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 +import java.io.IOException;
   18.32 +
   18.33 +/**
   18.34 + * A <tt>Flushable</tt> is a destination of data that can be flushed.  The
   18.35 + * flush method is invoked to write any buffered output to the underlying
   18.36 + * stream.
   18.37 + *
   18.38 + * @since 1.5
   18.39 + */
   18.40 +
   18.41 +public interface Flushable {
   18.42 +
   18.43 +    /**
   18.44 +     * Flushes this stream by writing any buffered output to the underlying
   18.45 +     * stream.
   18.46 +     *
   18.47 +     * @throws IOException If an I/O error occurs
   18.48 +     */
   18.49 +    void flush() throws IOException;
   18.50 +}
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/emul/compact/src/main/java/java/io/InvalidClassException.java	Mon Feb 04 09:37:56 2013 +0100
    19.3 @@ -0,0 +1,81 @@
    19.4 +/*
    19.5 + * Copyright (c) 1996, 2006, 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 the Serialization runtime detects one of the following
   19.33 + * problems with a Class.
   19.34 + * <UL>
   19.35 + * <LI> The serial version of the class does not match that of the class
   19.36 + *      descriptor read from the stream
   19.37 + * <LI> The class contains unknown datatypes
   19.38 + * <LI> The class does not have an accessible no-arg constructor
   19.39 + * </UL>
   19.40 + *
   19.41 + * @author  unascribed
   19.42 + * @since   JDK1.1
   19.43 + */
   19.44 +public class InvalidClassException extends ObjectStreamException {
   19.45 +
   19.46 +    private static final long serialVersionUID = -4333316296251054416L;
   19.47 +
   19.48 +    /**
   19.49 +     * Name of the invalid class.
   19.50 +     *
   19.51 +     * @serial Name of the invalid class.
   19.52 +     */
   19.53 +    public String classname;
   19.54 +
   19.55 +    /**
   19.56 +     * Report an InvalidClassException for the reason specified.
   19.57 +     *
   19.58 +     * @param reason  String describing the reason for the exception.
   19.59 +     */
   19.60 +    public InvalidClassException(String reason) {
   19.61 +        super(reason);
   19.62 +    }
   19.63 +
   19.64 +    /**
   19.65 +     * Constructs an InvalidClassException object.
   19.66 +     *
   19.67 +     * @param cname   a String naming the invalid class.
   19.68 +     * @param reason  a String describing the reason for the exception.
   19.69 +     */
   19.70 +    public InvalidClassException(String cname, String reason) {
   19.71 +        super(reason);
   19.72 +        classname = cname;
   19.73 +    }
   19.74 +
   19.75 +    /**
   19.76 +     * Produce the message and include the classname, if present.
   19.77 +     */
   19.78 +    public String getMessage() {
   19.79 +        if (classname == null)
   19.80 +            return super.getMessage();
   19.81 +        else
   19.82 +            return classname + "; " + super.getMessage();
   19.83 +    }
   19.84 +}
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/emul/compact/src/main/java/java/io/InvalidObjectException.java	Mon Feb 04 09:37:56 2013 +0100
    20.3 @@ -0,0 +1,51 @@
    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 + * Indicates that one or more deserialized objects failed validation
   20.33 + * tests.  The argument should provide the reason for the failure.
   20.34 + *
   20.35 + * @see ObjectInputValidation
   20.36 + * @since JDK1.1
   20.37 + *
   20.38 + * @author  unascribed
   20.39 + * @since   JDK1.1
   20.40 + */
   20.41 +public class InvalidObjectException extends ObjectStreamException {
   20.42 +
   20.43 +    private static final long serialVersionUID = 3233174318281839583L;
   20.44 +
   20.45 +    /**
   20.46 +     * Constructs an <code>InvalidObjectException</code>.
   20.47 +     * @param reason Detailed message explaining the reason for the failure.
   20.48 +     *
   20.49 +     * @see ObjectInputValidation
   20.50 +     */
   20.51 +    public  InvalidObjectException(String reason) {
   20.52 +        super(reason);
   20.53 +    }
   20.54 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/emul/compact/src/main/java/java/io/NotActiveException.java	Mon Feb 04 09:37:56 2013 +0100
    21.3 @@ -0,0 +1,53 @@
    21.4 +/*
    21.5 + * Copyright (c) 1996, 2005, 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 + * Thrown when serialization or deserialization is not active.
   21.33 + *
   21.34 + * @author  unascribed
   21.35 + * @since   JDK1.1
   21.36 + */
   21.37 +public class NotActiveException extends ObjectStreamException {
   21.38 +
   21.39 +    private static final long serialVersionUID = -3893467273049808895L;
   21.40 +
   21.41 +    /**
   21.42 +     * Constructor to create a new NotActiveException with the reason given.
   21.43 +     *
   21.44 +     * @param reason  a String describing the reason for the exception.
   21.45 +     */
   21.46 +    public NotActiveException(String reason) {
   21.47 +        super(reason);
   21.48 +    }
   21.49 +
   21.50 +    /**
   21.51 +     * Constructor to create a new NotActiveException without a reason.
   21.52 +     */
   21.53 +    public NotActiveException() {
   21.54 +        super();
   21.55 +    }
   21.56 +}
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/emul/compact/src/main/java/java/io/NotSerializableException.java	Mon Feb 04 09:37:56 2013 +0100
    22.3 @@ -0,0 +1,55 @@
    22.4 +/*
    22.5 + * Copyright (c) 1996, 2005, 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 +/**
   22.32 + * Thrown when an instance is required to have a Serializable interface.
   22.33 + * The serialization runtime or the class of the instance can throw
   22.34 + * this exception. The argument should be the name of the class.
   22.35 + *
   22.36 + * @author  unascribed
   22.37 + * @since   JDK1.1
   22.38 + */
   22.39 +public class NotSerializableException extends ObjectStreamException {
   22.40 +
   22.41 +    private static final long serialVersionUID = 2906642554793891381L;
   22.42 +
   22.43 +    /**
   22.44 +     * Constructs a NotSerializableException object with message string.
   22.45 +     *
   22.46 +     * @param classname Class of the instance being serialized/deserialized.
   22.47 +     */
   22.48 +    public NotSerializableException(String classname) {
   22.49 +        super(classname);
   22.50 +    }
   22.51 +
   22.52 +    /**
   22.53 +     *  Constructs a NotSerializableException object.
   22.54 +     */
   22.55 +    public NotSerializableException() {
   22.56 +        super();
   22.57 +    }
   22.58 +}
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/emul/compact/src/main/java/java/io/ObjectInput.java	Mon Feb 04 09:37:56 2013 +0100
    23.3 @@ -0,0 +1,107 @@
    23.4 +/*
    23.5 + * Copyright (c) 1996, 2010, 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 + * ObjectInput extends the DataInput interface to include the reading of
   23.33 + * objects. DataInput includes methods for the input of primitive types,
   23.34 + * ObjectInput extends that interface to include objects, arrays, and Strings.
   23.35 + *
   23.36 + * @author  unascribed
   23.37 + * @see java.io.InputStream
   23.38 + * @see java.io.ObjectOutputStream
   23.39 + * @see java.io.ObjectInputStream
   23.40 + * @since   JDK1.1
   23.41 + */
   23.42 +public interface ObjectInput extends DataInput, AutoCloseable {
   23.43 +    /**
   23.44 +     * Read and return an object. The class that implements this interface
   23.45 +     * defines where the object is "read" from.
   23.46 +     *
   23.47 +     * @return the object read from the stream
   23.48 +     * @exception java.lang.ClassNotFoundException If the class of a serialized
   23.49 +     *      object cannot be found.
   23.50 +     * @exception IOException If any of the usual Input/Output
   23.51 +     * related exceptions occur.
   23.52 +     */
   23.53 +    public Object readObject()
   23.54 +        throws ClassNotFoundException, IOException;
   23.55 +
   23.56 +    /**
   23.57 +     * Reads a byte of data. This method will block if no input is
   23.58 +     * available.
   23.59 +     * @return  the byte read, or -1 if the end of the
   23.60 +     *          stream is reached.
   23.61 +     * @exception IOException If an I/O error has occurred.
   23.62 +     */
   23.63 +    public int read() throws IOException;
   23.64 +
   23.65 +    /**
   23.66 +     * Reads into an array of bytes.  This method will
   23.67 +     * block until some input is available.
   23.68 +     * @param b the buffer into which the data is read
   23.69 +     * @return  the actual number of bytes read, -1 is
   23.70 +     *          returned when the end of the stream is reached.
   23.71 +     * @exception IOException If an I/O error has occurred.
   23.72 +     */
   23.73 +    public int read(byte b[]) throws IOException;
   23.74 +
   23.75 +    /**
   23.76 +     * Reads into an array of bytes.  This method will
   23.77 +     * block until some input is available.
   23.78 +     * @param b the buffer into which the data is read
   23.79 +     * @param off the start offset of the data
   23.80 +     * @param len the maximum number of bytes read
   23.81 +     * @return  the actual number of bytes read, -1 is
   23.82 +     *          returned when the end of the stream is reached.
   23.83 +     * @exception IOException If an I/O error has occurred.
   23.84 +     */
   23.85 +    public int read(byte b[], int off, int len) throws IOException;
   23.86 +
   23.87 +    /**
   23.88 +     * Skips n bytes of input.
   23.89 +     * @param n the number of bytes to be skipped
   23.90 +     * @return  the actual number of bytes skipped.
   23.91 +     * @exception IOException If an I/O error has occurred.
   23.92 +     */
   23.93 +    public long skip(long n) throws IOException;
   23.94 +
   23.95 +    /**
   23.96 +     * Returns the number of bytes that can be read
   23.97 +     * without blocking.
   23.98 +     * @return the number of available bytes.
   23.99 +     * @exception IOException If an I/O error has occurred.
  23.100 +     */
  23.101 +    public int available() throws IOException;
  23.102 +
  23.103 +    /**
  23.104 +     * Closes the input stream. Must be called
  23.105 +     * to release any resources associated with
  23.106 +     * the stream.
  23.107 +     * @exception IOException If an I/O error has occurred.
  23.108 +     */
  23.109 +    public void close() throws IOException;
  23.110 +}
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/emul/compact/src/main/java/java/io/ObjectInputStream.java	Mon Feb 04 09:37:56 2013 +0100
    24.3 @@ -0,0 +1,3357 @@
    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 +import java.lang.reflect.Array;
   24.32 +import java.lang.reflect.Modifier;
   24.33 +import java.lang.reflect.Proxy;
   24.34 +import java.util.Arrays;
   24.35 +import java.util.HashMap;
   24.36 +import org.apidesign.bck2brwsr.emul.lang.System;
   24.37 +
   24.38 +/**
   24.39 + * An ObjectInputStream deserializes primitive data and objects previously
   24.40 + * written using an ObjectOutputStream.
   24.41 + *
   24.42 + * <p>ObjectOutputStream and ObjectInputStream can provide an application with
   24.43 + * persistent storage for graphs of objects when used with a FileOutputStream
   24.44 + * and FileInputStream respectively.  ObjectInputStream is used to recover
   24.45 + * those objects previously serialized. Other uses include passing objects
   24.46 + * between hosts using a socket stream or for marshaling and unmarshaling
   24.47 + * arguments and parameters in a remote communication system.
   24.48 + *
   24.49 + * <p>ObjectInputStream ensures that the types of all objects in the graph
   24.50 + * created from the stream match the classes present in the Java Virtual
   24.51 + * Machine.  Classes are loaded as required using the standard mechanisms.
   24.52 + *
   24.53 + * <p>Only objects that support the java.io.Serializable or
   24.54 + * java.io.Externalizable interface can be read from streams.
   24.55 + *
   24.56 + * <p>The method <code>readObject</code> is used to read an object from the
   24.57 + * stream.  Java's safe casting should be used to get the desired type.  In
   24.58 + * Java, strings and arrays are objects and are treated as objects during
   24.59 + * serialization. When read they need to be cast to the expected type.
   24.60 + *
   24.61 + * <p>Primitive data types can be read from the stream using the appropriate
   24.62 + * method on DataInput.
   24.63 + *
   24.64 + * <p>The default deserialization mechanism for objects restores the contents
   24.65 + * of each field to the value and type it had when it was written.  Fields
   24.66 + * declared as transient or static are ignored by the deserialization process.
   24.67 + * References to other objects cause those objects to be read from the stream
   24.68 + * as necessary.  Graphs of objects are restored correctly using a reference
   24.69 + * sharing mechanism.  New objects are always allocated when deserializing,
   24.70 + * which prevents existing objects from being overwritten.
   24.71 + *
   24.72 + * <p>Reading an object is analogous to running the constructors of a new
   24.73 + * object.  Memory is allocated for the object and initialized to zero (NULL).
   24.74 + * No-arg constructors are invoked for the non-serializable classes and then
   24.75 + * the fields of the serializable classes are restored from the stream starting
   24.76 + * with the serializable class closest to java.lang.object and finishing with
   24.77 + * the object's most specific class.
   24.78 + *
   24.79 + * <p>For example to read from a stream as written by the example in
   24.80 + * ObjectOutputStream:
   24.81 + * <br>
   24.82 + * <pre>
   24.83 + *      FileInputStream fis = new FileInputStream("t.tmp");
   24.84 + *      ObjectInputStream ois = new ObjectInputStream(fis);
   24.85 + *
   24.86 + *      int i = ois.readInt();
   24.87 + *      String today = (String) ois.readObject();
   24.88 + *      Date date = (Date) ois.readObject();
   24.89 + *
   24.90 + *      ois.close();
   24.91 + * </pre>
   24.92 + *
   24.93 + * <p>Classes control how they are serialized by implementing either the
   24.94 + * java.io.Serializable or java.io.Externalizable interfaces.
   24.95 + *
   24.96 + * <p>Implementing the Serializable interface allows object serialization to
   24.97 + * save and restore the entire state of the object and it allows classes to
   24.98 + * evolve between the time the stream is written and the time it is read.  It
   24.99 + * automatically traverses references between objects, saving and restoring
  24.100 + * entire graphs.
  24.101 + *
  24.102 + * <p>Serializable classes that require special handling during the
  24.103 + * serialization and deserialization process should implement the following
  24.104 + * methods:<p>
  24.105 + *
  24.106 + * <pre>
  24.107 + * private void writeObject(java.io.ObjectOutputStream stream)
  24.108 + *     throws IOException;
  24.109 + * private void readObject(java.io.ObjectInputStream stream)
  24.110 + *     throws IOException, ClassNotFoundException;
  24.111 + * private void readObjectNoData()
  24.112 + *     throws ObjectStreamException;
  24.113 + * </pre>
  24.114 + *
  24.115 + * <p>The readObject method is responsible for reading and restoring the state
  24.116 + * of the object for its particular class using data written to the stream by
  24.117 + * the corresponding writeObject method.  The method does not need to concern
  24.118 + * itself with the state belonging to its superclasses or subclasses.  State is
  24.119 + * restored by reading data from the ObjectInputStream for the individual
  24.120 + * fields and making assignments to the appropriate fields of the object.
  24.121 + * Reading primitive data types is supported by DataInput.
  24.122 + *
  24.123 + * <p>Any attempt to read object data which exceeds the boundaries of the
  24.124 + * custom data written by the corresponding writeObject method will cause an
  24.125 + * OptionalDataException to be thrown with an eof field value of true.
  24.126 + * Non-object reads which exceed the end of the allotted data will reflect the
  24.127 + * end of data in the same way that they would indicate the end of the stream:
  24.128 + * bytewise reads will return -1 as the byte read or number of bytes read, and
  24.129 + * primitive reads will throw EOFExceptions.  If there is no corresponding
  24.130 + * writeObject method, then the end of default serialized data marks the end of
  24.131 + * the allotted data.
  24.132 + *
  24.133 + * <p>Primitive and object read calls issued from within a readExternal method
  24.134 + * behave in the same manner--if the stream is already positioned at the end of
  24.135 + * data written by the corresponding writeExternal method, object reads will
  24.136 + * throw OptionalDataExceptions with eof set to true, bytewise reads will
  24.137 + * return -1, and primitive reads will throw EOFExceptions.  Note that this
  24.138 + * behavior does not hold for streams written with the old
  24.139 + * <code>ObjectStreamConstants.PROTOCOL_VERSION_1</code> protocol, in which the
  24.140 + * end of data written by writeExternal methods is not demarcated, and hence
  24.141 + * cannot be detected.
  24.142 + *
  24.143 + * <p>The readObjectNoData method is responsible for initializing the state of
  24.144 + * the object for its particular class in the event that the serialization
  24.145 + * stream does not list the given class as a superclass of the object being
  24.146 + * deserialized.  This may occur in cases where the receiving party uses a
  24.147 + * different version of the deserialized instance's class than the sending
  24.148 + * party, and the receiver's version extends classes that are not extended by
  24.149 + * the sender's version.  This may also occur if the serialization stream has
  24.150 + * been tampered; hence, readObjectNoData is useful for initializing
  24.151 + * deserialized objects properly despite a "hostile" or incomplete source
  24.152 + * stream.
  24.153 + *
  24.154 + * <p>Serialization does not read or assign values to the fields of any object
  24.155 + * that does not implement the java.io.Serializable interface.  Subclasses of
  24.156 + * Objects that are not serializable can be serializable. In this case the
  24.157 + * non-serializable class must have a no-arg constructor to allow its fields to
  24.158 + * be initialized.  In this case it is the responsibility of the subclass to
  24.159 + * save and restore the state of the non-serializable class. It is frequently
  24.160 + * the case that the fields of that class are accessible (public, package, or
  24.161 + * protected) or that there are get and set methods that can be used to restore
  24.162 + * the state.
  24.163 + *
  24.164 + * <p>Any exception that occurs while deserializing an object will be caught by
  24.165 + * the ObjectInputStream and abort the reading process.
  24.166 + *
  24.167 + * <p>Implementing the Externalizable interface allows the object to assume
  24.168 + * complete control over the contents and format of the object's serialized
  24.169 + * form.  The methods of the Externalizable interface, writeExternal and
  24.170 + * readExternal, are called to save and restore the objects state.  When
  24.171 + * implemented by a class they can write and read their own state using all of
  24.172 + * the methods of ObjectOutput and ObjectInput.  It is the responsibility of
  24.173 + * the objects to handle any versioning that occurs.
  24.174 + *
  24.175 + * <p>Enum constants are deserialized differently than ordinary serializable or
  24.176 + * externalizable objects.  The serialized form of an enum constant consists
  24.177 + * solely of its name; field values of the constant are not transmitted.  To
  24.178 + * deserialize an enum constant, ObjectInputStream reads the constant name from
  24.179 + * the stream; the deserialized constant is then obtained by calling the static
  24.180 + * method <code>Enum.valueOf(Class, String)</code> with the enum constant's
  24.181 + * base type and the received constant name as arguments.  Like other
  24.182 + * serializable or externalizable objects, enum constants can function as the
  24.183 + * targets of back references appearing subsequently in the serialization
  24.184 + * stream.  The process by which enum constants are deserialized cannot be
  24.185 + * customized: any class-specific readObject, readObjectNoData, and readResolve
  24.186 + * methods defined by enum types are ignored during deserialization.
  24.187 + * Similarly, any serialPersistentFields or serialVersionUID field declarations
  24.188 + * are also ignored--all enum types have a fixed serialVersionUID of 0L.
  24.189 + *
  24.190 + * @author      Mike Warres
  24.191 + * @author      Roger Riggs
  24.192 + * @see java.io.DataInput
  24.193 + * @see java.io.ObjectOutputStream
  24.194 + * @see java.io.Serializable
  24.195 + * @see <a href="../../../platform/serialization/spec/input.html"> Object Serialization Specification, Section 3, Object Input Classes</a>
  24.196 + * @since   JDK1.1
  24.197 + */
  24.198 +public class ObjectInputStream
  24.199 +    extends InputStream implements ObjectInput, ObjectStreamConstants
  24.200 +{
  24.201 +    /** handle value representing null */
  24.202 +    private static final int NULL_HANDLE = -1;
  24.203 +
  24.204 +    /** marker for unshared objects in internal handle table */
  24.205 +    private static final Object unsharedMarker = new Object();
  24.206 +
  24.207 +    /** table mapping primitive type names to corresponding class objects */
  24.208 +    private static final HashMap<String, Class<?>> primClasses
  24.209 +        = new HashMap<>(8, 1.0F);
  24.210 +    static {
  24.211 +        primClasses.put("boolean", boolean.class);
  24.212 +        primClasses.put("byte", byte.class);
  24.213 +        primClasses.put("char", char.class);
  24.214 +        primClasses.put("short", short.class);
  24.215 +        primClasses.put("int", int.class);
  24.216 +        primClasses.put("long", long.class);
  24.217 +        primClasses.put("float", float.class);
  24.218 +        primClasses.put("double", double.class);
  24.219 +        primClasses.put("void", void.class);
  24.220 +    }
  24.221 +
  24.222 +    /** filter stream for handling block data conversion */
  24.223 +    private final BlockDataInputStream bin;
  24.224 +    /** validation callback list */
  24.225 +    private final ValidationList vlist;
  24.226 +    /** recursion depth */
  24.227 +    private int depth;
  24.228 +    /** whether stream is closed */
  24.229 +    private boolean closed;
  24.230 +
  24.231 +    /** wire handle -> obj/exception map */
  24.232 +    private final HandleTable handles;
  24.233 +    /** scratch field for passing handle values up/down call stack */
  24.234 +    private int passHandle = NULL_HANDLE;
  24.235 +    /** flag set when at end of field value block with no TC_ENDBLOCKDATA */
  24.236 +    private boolean defaultDataEnd = false;
  24.237 +
  24.238 +    /** buffer for reading primitive field values */
  24.239 +    private byte[] primVals;
  24.240 +
  24.241 +    /** if true, invoke readObjectOverride() instead of readObject() */
  24.242 +    private final boolean enableOverride;
  24.243 +    /** if true, invoke resolveObject() */
  24.244 +    private boolean enableResolve;
  24.245 +
  24.246 +    /**
  24.247 +     * Context during upcalls to class-defined readObject methods; holds
  24.248 +     * object currently being deserialized and descriptor for current class.
  24.249 +     * Null when not during readObject upcall.
  24.250 +     */
  24.251 +    private Object curContext;
  24.252 +
  24.253 +    /**
  24.254 +     * Creates an ObjectInputStream that reads from the specified InputStream.
  24.255 +     * A serialization stream header is read from the stream and verified.
  24.256 +     * This constructor will block until the corresponding ObjectOutputStream
  24.257 +     * has written and flushed the header.
  24.258 +     *
  24.259 +     * <p>If a security manager is installed, this constructor will check for
  24.260 +     * the "enableSubclassImplementation" SerializablePermission when invoked
  24.261 +     * directly or indirectly by the constructor of a subclass which overrides
  24.262 +     * the ObjectInputStream.readFields or ObjectInputStream.readUnshared
  24.263 +     * methods.
  24.264 +     *
  24.265 +     * @param   in input stream to read from
  24.266 +     * @throws  StreamCorruptedException if the stream header is incorrect
  24.267 +     * @throws  IOException if an I/O error occurs while reading stream header
  24.268 +     * @throws  SecurityException if untrusted subclass illegally overrides
  24.269 +     *          security-sensitive methods
  24.270 +     * @throws  NullPointerException if <code>in</code> is <code>null</code>
  24.271 +     * @see     ObjectInputStream#ObjectInputStream()
  24.272 +     * @see     ObjectInputStream#readFields()
  24.273 +     * @see     ObjectOutputStream#ObjectOutputStream(OutputStream)
  24.274 +     */
  24.275 +    public ObjectInputStream(InputStream in) throws IOException {
  24.276 +        verifySubclass();
  24.277 +        bin = new BlockDataInputStream(in);
  24.278 +        handles = new HandleTable(10);
  24.279 +        vlist = new ValidationList();
  24.280 +        enableOverride = false;
  24.281 +        readStreamHeader();
  24.282 +        bin.setBlockDataMode(true);
  24.283 +    }
  24.284 +
  24.285 +    /**
  24.286 +     * Provide a way for subclasses that are completely reimplementing
  24.287 +     * ObjectInputStream to not have to allocate private data just used by this
  24.288 +     * implementation of ObjectInputStream.
  24.289 +     *
  24.290 +     * <p>If there is a security manager installed, this method first calls the
  24.291 +     * security manager's <code>checkPermission</code> method with the
  24.292 +     * <code>SerializablePermission("enableSubclassImplementation")</code>
  24.293 +     * permission to ensure it's ok to enable subclassing.
  24.294 +     *
  24.295 +     * @throws  SecurityException if a security manager exists and its
  24.296 +     *          <code>checkPermission</code> method denies enabling
  24.297 +     *          subclassing.
  24.298 +     * @see SecurityManager#checkPermission
  24.299 +     * @see java.io.SerializablePermission
  24.300 +     */
  24.301 +    protected ObjectInputStream() throws IOException, SecurityException {
  24.302 +        throw new SecurityException();
  24.303 +    }
  24.304 +
  24.305 +    /**
  24.306 +     * Read an object from the ObjectInputStream.  The class of the object, the
  24.307 +     * signature of the class, and the values of the non-transient and
  24.308 +     * non-static fields of the class and all of its supertypes are read.
  24.309 +     * Default deserializing for a class can be overriden using the writeObject
  24.310 +     * and readObject methods.  Objects referenced by this object are read
  24.311 +     * transitively so that a complete equivalent graph of objects is
  24.312 +     * reconstructed by readObject.
  24.313 +     *
  24.314 +     * <p>The root object is completely restored when all of its fields and the
  24.315 +     * objects it references are completely restored.  At this point the object
  24.316 +     * validation callbacks are executed in order based on their registered
  24.317 +     * priorities. The callbacks are registered by objects (in the readObject
  24.318 +     * special methods) as they are individually restored.
  24.319 +     *
  24.320 +     * <p>Exceptions are thrown for problems with the InputStream and for
  24.321 +     * classes that should not be deserialized.  All exceptions are fatal to
  24.322 +     * the InputStream and leave it in an indeterminate state; it is up to the
  24.323 +     * caller to ignore or recover the stream state.
  24.324 +     *
  24.325 +     * @throws  ClassNotFoundException Class of a serialized object cannot be
  24.326 +     *          found.
  24.327 +     * @throws  InvalidClassException Something is wrong with a class used by
  24.328 +     *          serialization.
  24.329 +     * @throws  StreamCorruptedException Control information in the
  24.330 +     *          stream is inconsistent.
  24.331 +     * @throws  OptionalDataException Primitive data was found in the
  24.332 +     *          stream instead of objects.
  24.333 +     * @throws  IOException Any of the usual Input/Output related exceptions.
  24.334 +     */
  24.335 +    public final Object readObject()
  24.336 +        throws IOException, ClassNotFoundException
  24.337 +    {
  24.338 +        throw new IOException();
  24.339 +    }
  24.340 +
  24.341 +    /**
  24.342 +     * This method is called by trusted subclasses of ObjectOutputStream that
  24.343 +     * constructed ObjectOutputStream using the protected no-arg constructor.
  24.344 +     * The subclass is expected to provide an override method with the modifier
  24.345 +     * "final".
  24.346 +     *
  24.347 +     * @return  the Object read from the stream.
  24.348 +     * @throws  ClassNotFoundException Class definition of a serialized object
  24.349 +     *          cannot be found.
  24.350 +     * @throws  OptionalDataException Primitive data was found in the stream
  24.351 +     *          instead of objects.
  24.352 +     * @throws  IOException if I/O errors occurred while reading from the
  24.353 +     *          underlying stream
  24.354 +     * @see #ObjectInputStream()
  24.355 +     * @see #readObject()
  24.356 +     * @since 1.2
  24.357 +     */
  24.358 +    protected Object readObjectOverride()
  24.359 +        throws IOException, ClassNotFoundException
  24.360 +    {
  24.361 +        return null;
  24.362 +    }
  24.363 +
  24.364 +    /**
  24.365 +     * Reads an "unshared" object from the ObjectInputStream.  This method is
  24.366 +     * identical to readObject, except that it prevents subsequent calls to
  24.367 +     * readObject and readUnshared from returning additional references to the
  24.368 +     * deserialized instance obtained via this call.  Specifically:
  24.369 +     * <ul>
  24.370 +     *   <li>If readUnshared is called to deserialize a back-reference (the
  24.371 +     *       stream representation of an object which has been written
  24.372 +     *       previously to the stream), an ObjectStreamException will be
  24.373 +     *       thrown.
  24.374 +     *
  24.375 +     *   <li>If readUnshared returns successfully, then any subsequent attempts
  24.376 +     *       to deserialize back-references to the stream handle deserialized
  24.377 +     *       by readUnshared will cause an ObjectStreamException to be thrown.
  24.378 +     * </ul>
  24.379 +     * Deserializing an object via readUnshared invalidates the stream handle
  24.380 +     * associated with the returned object.  Note that this in itself does not
  24.381 +     * always guarantee that the reference returned by readUnshared is unique;
  24.382 +     * the deserialized object may define a readResolve method which returns an
  24.383 +     * object visible to other parties, or readUnshared may return a Class
  24.384 +     * object or enum constant obtainable elsewhere in the stream or through
  24.385 +     * external means. If the deserialized object defines a readResolve method
  24.386 +     * and the invocation of that method returns an array, then readUnshared
  24.387 +     * returns a shallow clone of that array; this guarantees that the returned
  24.388 +     * array object is unique and cannot be obtained a second time from an
  24.389 +     * invocation of readObject or readUnshared on the ObjectInputStream,
  24.390 +     * even if the underlying data stream has been manipulated.
  24.391 +     *
  24.392 +     * <p>ObjectInputStream subclasses which override this method can only be
  24.393 +     * constructed in security contexts possessing the
  24.394 +     * "enableSubclassImplementation" SerializablePermission; any attempt to
  24.395 +     * instantiate such a subclass without this permission will cause a
  24.396 +     * SecurityException to be thrown.
  24.397 +     *
  24.398 +     * @return  reference to deserialized object
  24.399 +     * @throws  ClassNotFoundException if class of an object to deserialize
  24.400 +     *          cannot be found
  24.401 +     * @throws  StreamCorruptedException if control information in the stream
  24.402 +     *          is inconsistent
  24.403 +     * @throws  ObjectStreamException if object to deserialize has already
  24.404 +     *          appeared in stream
  24.405 +     * @throws  OptionalDataException if primitive data is next in stream
  24.406 +     * @throws  IOException if an I/O error occurs during deserialization
  24.407 +     * @since   1.4
  24.408 +     */
  24.409 +    public Object readUnshared() throws IOException, ClassNotFoundException {
  24.410 +        // if nested read, passHandle contains handle of enclosing object
  24.411 +        int outerHandle = passHandle;
  24.412 +        try {
  24.413 +            Object obj = readObject0(true);
  24.414 +            handles.markDependency(outerHandle, passHandle);
  24.415 +            ClassNotFoundException ex = handles.lookupException(passHandle);
  24.416 +            if (ex != null) {
  24.417 +                throw ex;
  24.418 +            }
  24.419 +            if (depth == 0) {
  24.420 +                vlist.doCallbacks();
  24.421 +            }
  24.422 +            return obj;
  24.423 +        } finally {
  24.424 +            passHandle = outerHandle;
  24.425 +            if (closed && depth == 0) {
  24.426 +                clear();
  24.427 +            }
  24.428 +        }
  24.429 +    }
  24.430 +
  24.431 +    /**
  24.432 +     * Read the non-static and non-transient fields of the current class from
  24.433 +     * this stream.  This may only be called from the readObject method of the
  24.434 +     * class being deserialized. It will throw the NotActiveException if it is
  24.435 +     * called otherwise.
  24.436 +     *
  24.437 +     * @throws  ClassNotFoundException if the class of a serialized object
  24.438 +     *          could not be found.
  24.439 +     * @throws  IOException if an I/O error occurs.
  24.440 +     * @throws  NotActiveException if the stream is not currently reading
  24.441 +     *          objects.
  24.442 +     */
  24.443 +    public void defaultReadObject()
  24.444 +        throws IOException, ClassNotFoundException
  24.445 +    {
  24.446 +        if (curContext == null) {
  24.447 +            throw new NotActiveException("not in call to readObject");
  24.448 +        }
  24.449 +        Object curObj = null; // curContext.getObj();
  24.450 +        ObjectStreamClass curDesc = null; // curContext.getDesc();
  24.451 +        bin.setBlockDataMode(false);
  24.452 +        defaultReadFields(curObj, curDesc);
  24.453 +        bin.setBlockDataMode(true);
  24.454 +        if (!curDesc.hasWriteObjectData()) {
  24.455 +            /*
  24.456 +             * Fix for 4360508: since stream does not contain terminating
  24.457 +             * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
  24.458 +             * knows to simulate end-of-custom-data behavior.
  24.459 +             */
  24.460 +            defaultDataEnd = true;
  24.461 +        }
  24.462 +        ClassNotFoundException ex = handles.lookupException(passHandle);
  24.463 +        if (ex != null) {
  24.464 +            throw ex;
  24.465 +        }
  24.466 +    }
  24.467 +
  24.468 +    /**
  24.469 +     * Reads the persistent fields from the stream and makes them available by
  24.470 +     * name.
  24.471 +     *
  24.472 +     * @return  the <code>GetField</code> object representing the persistent
  24.473 +     *          fields of the object being deserialized
  24.474 +     * @throws  ClassNotFoundException if the class of a serialized object
  24.475 +     *          could not be found.
  24.476 +     * @throws  IOException if an I/O error occurs.
  24.477 +     * @throws  NotActiveException if the stream is not currently reading
  24.478 +     *          objects.
  24.479 +     * @since 1.2
  24.480 +     */
  24.481 +    public ObjectInputStream.GetField readFields()
  24.482 +        throws IOException, ClassNotFoundException
  24.483 +    {
  24.484 +        if (curContext == null) {
  24.485 +            throw new NotActiveException("not in call to readObject");
  24.486 +        }
  24.487 +        Object curObj = null; // curContext.getObj();
  24.488 +        ObjectStreamClass curDesc = null; // curContext.getDesc();
  24.489 +        bin.setBlockDataMode(false);
  24.490 +        GetFieldImpl getField = new GetFieldImpl(curDesc);
  24.491 +        getField.readFields();
  24.492 +        bin.setBlockDataMode(true);
  24.493 +        if (!curDesc.hasWriteObjectData()) {
  24.494 +            /*
  24.495 +             * Fix for 4360508: since stream does not contain terminating
  24.496 +             * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
  24.497 +             * knows to simulate end-of-custom-data behavior.
  24.498 +             */
  24.499 +            defaultDataEnd = true;
  24.500 +        }
  24.501 +
  24.502 +        return getField;
  24.503 +    }
  24.504 +
  24.505 +    /**
  24.506 +     * Register an object to be validated before the graph is returned.  While
  24.507 +     * similar to resolveObject these validations are called after the entire
  24.508 +     * graph has been reconstituted.  Typically, a readObject method will
  24.509 +     * register the object with the stream so that when all of the objects are
  24.510 +     * restored a final set of validations can be performed.
  24.511 +     *
  24.512 +     * @param   obj the object to receive the validation callback.
  24.513 +     * @param   prio controls the order of callbacks;zero is a good default.
  24.514 +     *          Use higher numbers to be called back earlier, lower numbers for
  24.515 +     *          later callbacks. Within a priority, callbacks are processed in
  24.516 +     *          no particular order.
  24.517 +     * @throws  NotActiveException The stream is not currently reading objects
  24.518 +     *          so it is invalid to register a callback.
  24.519 +     * @throws  InvalidObjectException The validation object is null.
  24.520 +     */
  24.521 +    public void registerValidation(ObjectInputValidation obj, int prio)
  24.522 +        throws NotActiveException, InvalidObjectException
  24.523 +    {
  24.524 +        if (depth == 0) {
  24.525 +            throw new NotActiveException("stream inactive");
  24.526 +        }
  24.527 +        vlist.register(obj, prio);
  24.528 +    }
  24.529 +
  24.530 +    /**
  24.531 +     * Load the local class equivalent of the specified stream class
  24.532 +     * description.  Subclasses may implement this method to allow classes to
  24.533 +     * be fetched from an alternate source.
  24.534 +     *
  24.535 +     * <p>The corresponding method in <code>ObjectOutputStream</code> is
  24.536 +     * <code>annotateClass</code>.  This method will be invoked only once for
  24.537 +     * each unique class in the stream.  This method can be implemented by
  24.538 +     * subclasses to use an alternate loading mechanism but must return a
  24.539 +     * <code>Class</code> object. Once returned, if the class is not an array
  24.540 +     * class, its serialVersionUID is compared to the serialVersionUID of the
  24.541 +     * serialized class, and if there is a mismatch, the deserialization fails
  24.542 +     * and an {@link InvalidClassException} is thrown.
  24.543 +     *
  24.544 +     * <p>The default implementation of this method in
  24.545 +     * <code>ObjectInputStream</code> returns the result of calling
  24.546 +     * <pre>
  24.547 +     *     Class.forName(desc.getName(), false, loader)
  24.548 +     * </pre>
  24.549 +     * where <code>loader</code> is determined as follows: if there is a
  24.550 +     * method on the current thread's stack whose declaring class was
  24.551 +     * defined by a user-defined class loader (and was not a generated to
  24.552 +     * implement reflective invocations), then <code>loader</code> is class
  24.553 +     * loader corresponding to the closest such method to the currently
  24.554 +     * executing frame; otherwise, <code>loader</code> is
  24.555 +     * <code>null</code>. If this call results in a
  24.556 +     * <code>ClassNotFoundException</code> and the name of the passed
  24.557 +     * <code>ObjectStreamClass</code> instance is the Java language keyword
  24.558 +     * for a primitive type or void, then the <code>Class</code> object
  24.559 +     * representing that primitive type or void will be returned
  24.560 +     * (e.g., an <code>ObjectStreamClass</code> with the name
  24.561 +     * <code>"int"</code> will be resolved to <code>Integer.TYPE</code>).
  24.562 +     * Otherwise, the <code>ClassNotFoundException</code> will be thrown to
  24.563 +     * the caller of this method.
  24.564 +     *
  24.565 +     * @param   desc an instance of class <code>ObjectStreamClass</code>
  24.566 +     * @return  a <code>Class</code> object corresponding to <code>desc</code>
  24.567 +     * @throws  IOException any of the usual Input/Output exceptions.
  24.568 +     * @throws  ClassNotFoundException if class of a serialized object cannot
  24.569 +     *          be found.
  24.570 +     */
  24.571 +    protected Class<?> resolveClass(ObjectStreamClass desc)
  24.572 +        throws IOException, ClassNotFoundException
  24.573 +    {
  24.574 +        String name = desc.getName();
  24.575 +        try {
  24.576 +            return Class.forName(name, false, latestUserDefinedLoader());
  24.577 +        } catch (ClassNotFoundException ex) {
  24.578 +            Class<?> cl = primClasses.get(name);
  24.579 +            if (cl != null) {
  24.580 +                return cl;
  24.581 +            } else {
  24.582 +                throw ex;
  24.583 +            }
  24.584 +        }
  24.585 +    }
  24.586 +
  24.587 +    /**
  24.588 +     * Returns a proxy class that implements the interfaces named in a proxy
  24.589 +     * class descriptor; subclasses may implement this method to read custom
  24.590 +     * data from the stream along with the descriptors for dynamic proxy
  24.591 +     * classes, allowing them to use an alternate loading mechanism for the
  24.592 +     * interfaces and the proxy class.
  24.593 +     *
  24.594 +     * <p>This method is called exactly once for each unique proxy class
  24.595 +     * descriptor in the stream.
  24.596 +     *
  24.597 +     * <p>The corresponding method in <code>ObjectOutputStream</code> is
  24.598 +     * <code>annotateProxyClass</code>.  For a given subclass of
  24.599 +     * <code>ObjectInputStream</code> that overrides this method, the
  24.600 +     * <code>annotateProxyClass</code> method in the corresponding subclass of
  24.601 +     * <code>ObjectOutputStream</code> must write any data or objects read by
  24.602 +     * this method.
  24.603 +     *
  24.604 +     * <p>The default implementation of this method in
  24.605 +     * <code>ObjectInputStream</code> returns the result of calling
  24.606 +     * <code>Proxy.getProxyClass</code> with the list of <code>Class</code>
  24.607 +     * objects for the interfaces that are named in the <code>interfaces</code>
  24.608 +     * parameter.  The <code>Class</code> object for each interface name
  24.609 +     * <code>i</code> is the value returned by calling
  24.610 +     * <pre>
  24.611 +     *     Class.forName(i, false, loader)
  24.612 +     * </pre>
  24.613 +     * where <code>loader</code> is that of the first non-<code>null</code>
  24.614 +     * class loader up the execution stack, or <code>null</code> if no
  24.615 +     * non-<code>null</code> class loaders are on the stack (the same class
  24.616 +     * loader choice used by the <code>resolveClass</code> method).  Unless any
  24.617 +     * of the resolved interfaces are non-public, this same value of
  24.618 +     * <code>loader</code> is also the class loader passed to
  24.619 +     * <code>Proxy.getProxyClass</code>; if non-public interfaces are present,
  24.620 +     * their class loader is passed instead (if more than one non-public
  24.621 +     * interface class loader is encountered, an
  24.622 +     * <code>IllegalAccessError</code> is thrown).
  24.623 +     * If <code>Proxy.getProxyClass</code> throws an
  24.624 +     * <code>IllegalArgumentException</code>, <code>resolveProxyClass</code>
  24.625 +     * will throw a <code>ClassNotFoundException</code> containing the
  24.626 +     * <code>IllegalArgumentException</code>.
  24.627 +     *
  24.628 +     * @param interfaces the list of interface names that were
  24.629 +     *                deserialized in the proxy class descriptor
  24.630 +     * @return  a proxy class for the specified interfaces
  24.631 +     * @throws        IOException any exception thrown by the underlying
  24.632 +     *                <code>InputStream</code>
  24.633 +     * @throws        ClassNotFoundException if the proxy class or any of the
  24.634 +     *                named interfaces could not be found
  24.635 +     * @see ObjectOutputStream#annotateProxyClass(Class)
  24.636 +     * @since 1.3
  24.637 +     */
  24.638 +    protected Class<?> resolveProxyClass(String[] interfaces)
  24.639 +        throws IOException, ClassNotFoundException
  24.640 +    {
  24.641 +        ClassLoader latestLoader = latestUserDefinedLoader();
  24.642 +        ClassLoader nonPublicLoader = null;
  24.643 +        boolean hasNonPublicInterface = false;
  24.644 +
  24.645 +        // define proxy in class loader of non-public interface(s), if any
  24.646 +        Class[] classObjs = new Class[interfaces.length];
  24.647 +        for (int i = 0; i < interfaces.length; i++) {
  24.648 +            Class cl = Class.forName(interfaces[i], false, latestLoader);
  24.649 +            if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
  24.650 +                if (hasNonPublicInterface) {
  24.651 +                    if (nonPublicLoader != cl.getClassLoader()) {
  24.652 +                        throw new IllegalAccessError(
  24.653 +                            "conflicting non-public interface class loaders");
  24.654 +                    }
  24.655 +                } else {
  24.656 +                    nonPublicLoader = cl.getClassLoader();
  24.657 +                    hasNonPublicInterface = true;
  24.658 +                }
  24.659 +            }
  24.660 +            classObjs[i] = cl;
  24.661 +        }
  24.662 +        try {
  24.663 +            return Proxy.getProxyClass(
  24.664 +                hasNonPublicInterface ? nonPublicLoader : latestLoader,
  24.665 +                classObjs);
  24.666 +        } catch (IllegalArgumentException e) {
  24.667 +            throw new ClassNotFoundException(null, e);
  24.668 +        }
  24.669 +    }
  24.670 +
  24.671 +    /**
  24.672 +     * This method will allow trusted subclasses of ObjectInputStream to
  24.673 +     * substitute one object for another during deserialization. Replacing
  24.674 +     * objects is disabled until enableResolveObject is called. The
  24.675 +     * enableResolveObject method checks that the stream requesting to resolve
  24.676 +     * object can be trusted. Every reference to serializable objects is passed
  24.677 +     * to resolveObject.  To insure that the private state of objects is not
  24.678 +     * unintentionally exposed only trusted streams may use resolveObject.
  24.679 +     *
  24.680 +     * <p>This method is called after an object has been read but before it is
  24.681 +     * returned from readObject.  The default resolveObject method just returns
  24.682 +     * the same object.
  24.683 +     *
  24.684 +     * <p>When a subclass is replacing objects it must insure that the
  24.685 +     * substituted object is compatible with every field where the reference
  24.686 +     * will be stored.  Objects whose type is not a subclass of the type of the
  24.687 +     * field or array element abort the serialization by raising an exception
  24.688 +     * and the object is not be stored.
  24.689 +     *
  24.690 +     * <p>This method is called only once when each object is first
  24.691 +     * encountered.  All subsequent references to the object will be redirected
  24.692 +     * to the new object.
  24.693 +     *
  24.694 +     * @param   obj object to be substituted
  24.695 +     * @return  the substituted object
  24.696 +     * @throws  IOException Any of the usual Input/Output exceptions.
  24.697 +     */
  24.698 +    protected Object resolveObject(Object obj) throws IOException {
  24.699 +        return obj;
  24.700 +    }
  24.701 +
  24.702 +    /**
  24.703 +     * Enable the stream to allow objects read from the stream to be replaced.
  24.704 +     * When enabled, the resolveObject method is called for every object being
  24.705 +     * deserialized.
  24.706 +     *
  24.707 +     * <p>If <i>enable</i> is true, and there is a security manager installed,
  24.708 +     * this method first calls the security manager's
  24.709 +     * <code>checkPermission</code> method with the
  24.710 +     * <code>SerializablePermission("enableSubstitution")</code> permission to
  24.711 +     * ensure it's ok to enable the stream to allow objects read from the
  24.712 +     * stream to be replaced.
  24.713 +     *
  24.714 +     * @param   enable true for enabling use of <code>resolveObject</code> for
  24.715 +     *          every object being deserialized
  24.716 +     * @return  the previous setting before this method was invoked
  24.717 +     * @throws  SecurityException if a security manager exists and its
  24.718 +     *          <code>checkPermission</code> method denies enabling the stream
  24.719 +     *          to allow objects read from the stream to be replaced.
  24.720 +     * @see SecurityManager#checkPermission
  24.721 +     * @see java.io.SerializablePermission
  24.722 +     */
  24.723 +    protected boolean enableResolveObject(boolean enable)
  24.724 +        throws SecurityException
  24.725 +    {
  24.726 +        throw new SecurityException();
  24.727 +    }
  24.728 +
  24.729 +    /**
  24.730 +     * The readStreamHeader method is provided to allow subclasses to read and
  24.731 +     * verify their own stream headers. It reads and verifies the magic number
  24.732 +     * and version number.
  24.733 +     *
  24.734 +     * @throws  IOException if there are I/O errors while reading from the
  24.735 +     *          underlying <code>InputStream</code>
  24.736 +     * @throws  StreamCorruptedException if control information in the stream
  24.737 +     *          is inconsistent
  24.738 +     */
  24.739 +    protected void readStreamHeader()
  24.740 +        throws IOException, StreamCorruptedException
  24.741 +    {
  24.742 +        short s0 = bin.readShort();
  24.743 +        short s1 = bin.readShort();
  24.744 +        if (s0 != STREAM_MAGIC || s1 != STREAM_VERSION) {
  24.745 +            throw new StreamCorruptedException(
  24.746 +                String.format("invalid stream header: %04X%04X", s0, s1));
  24.747 +        }
  24.748 +    }
  24.749 +
  24.750 +    /**
  24.751 +     * Read a class descriptor from the serialization stream.  This method is
  24.752 +     * called when the ObjectInputStream expects a class descriptor as the next
  24.753 +     * item in the serialization stream.  Subclasses of ObjectInputStream may
  24.754 +     * override this method to read in class descriptors that have been written
  24.755 +     * in non-standard formats (by subclasses of ObjectOutputStream which have
  24.756 +     * overridden the <code>writeClassDescriptor</code> method).  By default,
  24.757 +     * this method reads class descriptors according to the format defined in
  24.758 +     * the Object Serialization specification.
  24.759 +     *
  24.760 +     * @return  the class descriptor read
  24.761 +     * @throws  IOException If an I/O error has occurred.
  24.762 +     * @throws  ClassNotFoundException If the Class of a serialized object used
  24.763 +     *          in the class descriptor representation cannot be found
  24.764 +     * @see java.io.ObjectOutputStream#writeClassDescriptor(java.io.ObjectStreamClass)
  24.765 +     * @since 1.3
  24.766 +     */
  24.767 +    protected ObjectStreamClass readClassDescriptor()
  24.768 +        throws IOException, ClassNotFoundException
  24.769 +    {
  24.770 +        ObjectStreamClass desc = new ObjectStreamClass();
  24.771 +        desc.readNonProxy(this);
  24.772 +        return desc;
  24.773 +    }
  24.774 +
  24.775 +    /**
  24.776 +     * Reads a byte of data. This method will block if no input is available.
  24.777 +     *
  24.778 +     * @return  the byte read, or -1 if the end of the stream is reached.
  24.779 +     * @throws  IOException If an I/O error has occurred.
  24.780 +     */
  24.781 +    public int read() throws IOException {
  24.782 +        return bin.read();
  24.783 +    }
  24.784 +
  24.785 +    /**
  24.786 +     * Reads into an array of bytes.  This method will block until some input
  24.787 +     * is available. Consider using java.io.DataInputStream.readFully to read
  24.788 +     * exactly 'length' bytes.
  24.789 +     *
  24.790 +     * @param   buf the buffer into which the data is read
  24.791 +     * @param   off the start offset of the data
  24.792 +     * @param   len the maximum number of bytes read
  24.793 +     * @return  the actual number of bytes read, -1 is returned when the end of
  24.794 +     *          the stream is reached.
  24.795 +     * @throws  IOException If an I/O error has occurred.
  24.796 +     * @see java.io.DataInputStream#readFully(byte[],int,int)
  24.797 +     */
  24.798 +    public int read(byte[] buf, int off, int len) throws IOException {
  24.799 +        if (buf == null) {
  24.800 +            throw new NullPointerException();
  24.801 +        }
  24.802 +        int endoff = off + len;
  24.803 +        if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
  24.804 +            throw new IndexOutOfBoundsException();
  24.805 +        }
  24.806 +        return bin.read(buf, off, len, false);
  24.807 +    }
  24.808 +
  24.809 +    /**
  24.810 +     * Returns the number of bytes that can be read without blocking.
  24.811 +     *
  24.812 +     * @return  the number of available bytes.
  24.813 +     * @throws  IOException if there are I/O errors while reading from the
  24.814 +     *          underlying <code>InputStream</code>
  24.815 +     */
  24.816 +    public int available() throws IOException {
  24.817 +        return bin.available();
  24.818 +    }
  24.819 +
  24.820 +    /**
  24.821 +     * Closes the input stream. Must be called to release any resources
  24.822 +     * associated with the stream.
  24.823 +     *
  24.824 +     * @throws  IOException If an I/O error has occurred.
  24.825 +     */
  24.826 +    public void close() throws IOException {
  24.827 +        /*
  24.828 +         * Even if stream already closed, propagate redundant close to
  24.829 +         * underlying stream to stay consistent with previous implementations.
  24.830 +         */
  24.831 +        closed = true;
  24.832 +        if (depth == 0) {
  24.833 +            clear();
  24.834 +        }
  24.835 +        bin.close();
  24.836 +    }
  24.837 +
  24.838 +    /**
  24.839 +     * Reads in a boolean.
  24.840 +     *
  24.841 +     * @return  the boolean read.
  24.842 +     * @throws  EOFException If end of file is reached.
  24.843 +     * @throws  IOException If other I/O error has occurred.
  24.844 +     */
  24.845 +    public boolean readBoolean() throws IOException {
  24.846 +        return bin.readBoolean();
  24.847 +    }
  24.848 +
  24.849 +    /**
  24.850 +     * Reads an 8 bit byte.
  24.851 +     *
  24.852 +     * @return  the 8 bit byte read.
  24.853 +     * @throws  EOFException If end of file is reached.
  24.854 +     * @throws  IOException If other I/O error has occurred.
  24.855 +     */
  24.856 +    public byte readByte() throws IOException  {
  24.857 +        return bin.readByte();
  24.858 +    }
  24.859 +
  24.860 +    /**
  24.861 +     * Reads an unsigned 8 bit byte.
  24.862 +     *
  24.863 +     * @return  the 8 bit byte read.
  24.864 +     * @throws  EOFException If end of file is reached.
  24.865 +     * @throws  IOException If other I/O error has occurred.
  24.866 +     */
  24.867 +    public int readUnsignedByte()  throws IOException {
  24.868 +        return bin.readUnsignedByte();
  24.869 +    }
  24.870 +
  24.871 +    /**
  24.872 +     * Reads a 16 bit char.
  24.873 +     *
  24.874 +     * @return  the 16 bit char read.
  24.875 +     * @throws  EOFException If end of file is reached.
  24.876 +     * @throws  IOException If other I/O error has occurred.
  24.877 +     */
  24.878 +    public char readChar()  throws IOException {
  24.879 +        return bin.readChar();
  24.880 +    }
  24.881 +
  24.882 +    /**
  24.883 +     * Reads a 16 bit short.
  24.884 +     *
  24.885 +     * @return  the 16 bit short read.
  24.886 +     * @throws  EOFException If end of file is reached.
  24.887 +     * @throws  IOException If other I/O error has occurred.
  24.888 +     */
  24.889 +    public short readShort()  throws IOException {
  24.890 +        return bin.readShort();
  24.891 +    }
  24.892 +
  24.893 +    /**
  24.894 +     * Reads an unsigned 16 bit short.
  24.895 +     *
  24.896 +     * @return  the 16 bit short read.
  24.897 +     * @throws  EOFException If end of file is reached.
  24.898 +     * @throws  IOException If other I/O error has occurred.
  24.899 +     */
  24.900 +    public int readUnsignedShort() throws IOException {
  24.901 +        return bin.readUnsignedShort();
  24.902 +    }
  24.903 +
  24.904 +    /**
  24.905 +     * Reads a 32 bit int.
  24.906 +     *
  24.907 +     * @return  the 32 bit integer read.
  24.908 +     * @throws  EOFException If end of file is reached.
  24.909 +     * @throws  IOException If other I/O error has occurred.
  24.910 +     */
  24.911 +    public int readInt()  throws IOException {
  24.912 +        return bin.readInt();
  24.913 +    }
  24.914 +
  24.915 +    /**
  24.916 +     * Reads a 64 bit long.
  24.917 +     *
  24.918 +     * @return  the read 64 bit long.
  24.919 +     * @throws  EOFException If end of file is reached.
  24.920 +     * @throws  IOException If other I/O error has occurred.
  24.921 +     */
  24.922 +    public long readLong()  throws IOException {
  24.923 +        return bin.readLong();
  24.924 +    }
  24.925 +
  24.926 +    /**
  24.927 +     * Reads a 32 bit float.
  24.928 +     *
  24.929 +     * @return  the 32 bit float read.
  24.930 +     * @throws  EOFException If end of file is reached.
  24.931 +     * @throws  IOException If other I/O error has occurred.
  24.932 +     */
  24.933 +    public float readFloat() throws IOException {
  24.934 +        return bin.readFloat();
  24.935 +    }
  24.936 +
  24.937 +    /**
  24.938 +     * Reads a 64 bit double.
  24.939 +     *
  24.940 +     * @return  the 64 bit double read.
  24.941 +     * @throws  EOFException If end of file is reached.
  24.942 +     * @throws  IOException If other I/O error has occurred.
  24.943 +     */
  24.944 +    public double readDouble() throws IOException {
  24.945 +        return bin.readDouble();
  24.946 +    }
  24.947 +
  24.948 +    /**
  24.949 +     * Reads bytes, blocking until all bytes are read.
  24.950 +     *
  24.951 +     * @param   buf the buffer into which the data is read
  24.952 +     * @throws  EOFException If end of file is reached.
  24.953 +     * @throws  IOException If other I/O error has occurred.
  24.954 +     */
  24.955 +    public void readFully(byte[] buf) throws IOException {
  24.956 +        bin.readFully(buf, 0, buf.length, false);
  24.957 +    }
  24.958 +
  24.959 +    /**
  24.960 +     * Reads bytes, blocking until all bytes are read.
  24.961 +     *
  24.962 +     * @param   buf the buffer into which the data is read
  24.963 +     * @param   off the start offset of the data
  24.964 +     * @param   len the maximum number of bytes to read
  24.965 +     * @throws  EOFException If end of file is reached.
  24.966 +     * @throws  IOException If other I/O error has occurred.
  24.967 +     */
  24.968 +    public void readFully(byte[] buf, int off, int len) throws IOException {
  24.969 +        int endoff = off + len;
  24.970 +        if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
  24.971 +            throw new IndexOutOfBoundsException();
  24.972 +        }
  24.973 +        bin.readFully(buf, off, len, false);
  24.974 +    }
  24.975 +
  24.976 +    /**
  24.977 +     * Skips bytes.
  24.978 +     *
  24.979 +     * @param   len the number of bytes to be skipped
  24.980 +     * @return  the actual number of bytes skipped.
  24.981 +     * @throws  IOException If an I/O error has occurred.
  24.982 +     */
  24.983 +    public int skipBytes(int len) throws IOException {
  24.984 +        return bin.skipBytes(len);
  24.985 +    }
  24.986 +
  24.987 +    /**
  24.988 +     * Reads in a line that has been terminated by a \n, \r, \r\n or EOF.
  24.989 +     *
  24.990 +     * @return  a String copy of the line.
  24.991 +     * @throws  IOException if there are I/O errors while reading from the
  24.992 +     *          underlying <code>InputStream</code>
  24.993 +     * @deprecated This method does not properly convert bytes to characters.
  24.994 +     *          see DataInputStream for the details and alternatives.
  24.995 +     */
  24.996 +    @Deprecated
  24.997 +    public String readLine() throws IOException {
  24.998 +        return bin.readLine();
  24.999 +    }
 24.1000 +
 24.1001 +    /**
 24.1002 +     * Reads a String in
 24.1003 +     * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
 24.1004 +     * format.
 24.1005 +     *
 24.1006 +     * @return  the String.
 24.1007 +     * @throws  IOException if there are I/O errors while reading from the
 24.1008 +     *          underlying <code>InputStream</code>
 24.1009 +     * @throws  UTFDataFormatException if read bytes do not represent a valid
 24.1010 +     *          modified UTF-8 encoding of a string
 24.1011 +     */
 24.1012 +    public String readUTF() throws IOException {
 24.1013 +        return bin.readUTF();
 24.1014 +    }
 24.1015 +
 24.1016 +    /**
 24.1017 +     * Provide access to the persistent fields read from the input stream.
 24.1018 +     */
 24.1019 +    public static abstract class GetField {
 24.1020 +
 24.1021 +        /**
 24.1022 +         * Get the ObjectStreamClass that describes the fields in the stream.
 24.1023 +         *
 24.1024 +         * @return  the descriptor class that describes the serializable fields
 24.1025 +         */
 24.1026 +        public abstract ObjectStreamClass getObjectStreamClass();
 24.1027 +
 24.1028 +        /**
 24.1029 +         * Return true if the named field is defaulted and has no value in this
 24.1030 +         * stream.
 24.1031 +         *
 24.1032 +         * @param  name the name of the field
 24.1033 +         * @return true, if and only if the named field is defaulted
 24.1034 +         * @throws IOException if there are I/O errors while reading from
 24.1035 +         *         the underlying <code>InputStream</code>
 24.1036 +         * @throws IllegalArgumentException if <code>name</code> does not
 24.1037 +         *         correspond to a serializable field
 24.1038 +         */
 24.1039 +        public abstract boolean defaulted(String name) throws IOException;
 24.1040 +
 24.1041 +        /**
 24.1042 +         * Get the value of the named boolean field from the persistent field.
 24.1043 +         *
 24.1044 +         * @param  name the name of the field
 24.1045 +         * @param  val the default value to use if <code>name</code> does not
 24.1046 +         *         have a value
 24.1047 +         * @return the value of the named <code>boolean</code> field
 24.1048 +         * @throws IOException if there are I/O errors while reading from the
 24.1049 +         *         underlying <code>InputStream</code>
 24.1050 +         * @throws IllegalArgumentException if type of <code>name</code> is
 24.1051 +         *         not serializable or if the field type is incorrect
 24.1052 +         */
 24.1053 +        public abstract boolean get(String name, boolean val)
 24.1054 +            throws IOException;
 24.1055 +
 24.1056 +        /**
 24.1057 +         * Get the value of the named byte field from the persistent field.
 24.1058 +         *
 24.1059 +         * @param  name the name of the field
 24.1060 +         * @param  val the default value to use if <code>name</code> does not
 24.1061 +         *         have a value
 24.1062 +         * @return the value of the named <code>byte</code> field
 24.1063 +         * @throws IOException if there are I/O errors while reading from the
 24.1064 +         *         underlying <code>InputStream</code>
 24.1065 +         * @throws IllegalArgumentException if type of <code>name</code> is
 24.1066 +         *         not serializable or if the field type is incorrect
 24.1067 +         */
 24.1068 +        public abstract byte get(String name, byte val) throws IOException;
 24.1069 +
 24.1070 +        /**
 24.1071 +         * Get the value of the named char field from the persistent field.
 24.1072 +         *
 24.1073 +         * @param  name the name of the field
 24.1074 +         * @param  val the default value to use if <code>name</code> does not
 24.1075 +         *         have a value
 24.1076 +         * @return the value of the named <code>char</code> field
 24.1077 +         * @throws IOException if there are I/O errors while reading from the
 24.1078 +         *         underlying <code>InputStream</code>
 24.1079 +         * @throws IllegalArgumentException if type of <code>name</code> is
 24.1080 +         *         not serializable or if the field type is incorrect
 24.1081 +         */
 24.1082 +        public abstract char get(String name, char val) throws IOException;
 24.1083 +
 24.1084 +        /**
 24.1085 +         * Get the value of the named short field from the persistent field.
 24.1086 +         *
 24.1087 +         * @param  name the name of the field
 24.1088 +         * @param  val the default value to use if <code>name</code> does not
 24.1089 +         *         have a value
 24.1090 +         * @return the value of the named <code>short</code> field
 24.1091 +         * @throws IOException if there are I/O errors while reading from the
 24.1092 +         *         underlying <code>InputStream</code>
 24.1093 +         * @throws IllegalArgumentException if type of <code>name</code> is
 24.1094 +         *         not serializable or if the field type is incorrect
 24.1095 +         */
 24.1096 +        public abstract short get(String name, short val) throws IOException;
 24.1097 +
 24.1098 +        /**
 24.1099 +         * Get the value of the named int field from the persistent field.
 24.1100 +         *
 24.1101 +         * @param  name the name of the field
 24.1102 +         * @param  val the default value to use if <code>name</code> does not
 24.1103 +         *         have a value
 24.1104 +         * @return the value of the named <code>int</code> field
 24.1105 +         * @throws IOException if there are I/O errors while reading from the
 24.1106 +         *         underlying <code>InputStream</code>
 24.1107 +         * @throws IllegalArgumentException if type of <code>name</code> is
 24.1108 +         *         not serializable or if the field type is incorrect
 24.1109 +         */
 24.1110 +        public abstract int get(String name, int val) throws IOException;
 24.1111 +
 24.1112 +        /**
 24.1113 +         * Get the value of the named long field from the persistent field.
 24.1114 +         *
 24.1115 +         * @param  name the name of the field
 24.1116 +         * @param  val the default value to use if <code>name</code> does not
 24.1117 +         *         have a value
 24.1118 +         * @return the value of the named <code>long</code> field
 24.1119 +         * @throws IOException if there are I/O errors while reading from the
 24.1120 +         *         underlying <code>InputStream</code>
 24.1121 +         * @throws IllegalArgumentException if type of <code>name</code> is
 24.1122 +         *         not serializable or if the field type is incorrect
 24.1123 +         */
 24.1124 +        public abstract long get(String name, long val) throws IOException;
 24.1125 +
 24.1126 +        /**
 24.1127 +         * Get the value of the named float field from the persistent field.
 24.1128 +         *
 24.1129 +         * @param  name the name of the field
 24.1130 +         * @param  val the default value to use if <code>name</code> does not
 24.1131 +         *         have a value
 24.1132 +         * @return the value of the named <code>float</code> field
 24.1133 +         * @throws IOException if there are I/O errors while reading from the
 24.1134 +         *         underlying <code>InputStream</code>
 24.1135 +         * @throws IllegalArgumentException if type of <code>name</code> is
 24.1136 +         *         not serializable or if the field type is incorrect
 24.1137 +         */
 24.1138 +        public abstract float get(String name, float val) throws IOException;
 24.1139 +
 24.1140 +        /**
 24.1141 +         * Get the value of the named double field from the persistent field.
 24.1142 +         *
 24.1143 +         * @param  name the name of the field
 24.1144 +         * @param  val the default value to use if <code>name</code> does not
 24.1145 +         *         have a value
 24.1146 +         * @return the value of the named <code>double</code> field
 24.1147 +         * @throws IOException if there are I/O errors while reading from the
 24.1148 +         *         underlying <code>InputStream</code>
 24.1149 +         * @throws IllegalArgumentException if type of <code>name</code> is
 24.1150 +         *         not serializable or if the field type is incorrect
 24.1151 +         */
 24.1152 +        public abstract double get(String name, double val) throws IOException;
 24.1153 +
 24.1154 +        /**
 24.1155 +         * Get the value of the named Object field from the persistent field.
 24.1156 +         *
 24.1157 +         * @param  name the name of the field
 24.1158 +         * @param  val the default value to use if <code>name</code> does not
 24.1159 +         *         have a value
 24.1160 +         * @return the value of the named <code>Object</code> field
 24.1161 +         * @throws IOException if there are I/O errors while reading from the
 24.1162 +         *         underlying <code>InputStream</code>
 24.1163 +         * @throws IllegalArgumentException if type of <code>name</code> is
 24.1164 +         *         not serializable or if the field type is incorrect
 24.1165 +         */
 24.1166 +        public abstract Object get(String name, Object val) throws IOException;
 24.1167 +    }
 24.1168 +
 24.1169 +    /**
 24.1170 +     * Verifies that this (possibly subclass) instance can be constructed
 24.1171 +     * without violating security constraints: the subclass must not override
 24.1172 +     * security-sensitive non-final methods, or else the
 24.1173 +     * "enableSubclassImplementation" SerializablePermission is checked.
 24.1174 +     */
 24.1175 +    private void verifySubclass() {
 24.1176 +        Class cl = getClass();
 24.1177 +        if (cl == ObjectInputStream.class) {
 24.1178 +            return;
 24.1179 +        }
 24.1180 +        throw new SecurityException();
 24.1181 +    }
 24.1182 +
 24.1183 +    /**
 24.1184 +     * Clears internal data structures.
 24.1185 +     */
 24.1186 +    private void clear() {
 24.1187 +        handles.clear();
 24.1188 +        vlist.clear();
 24.1189 +    }
 24.1190 +
 24.1191 +    /**
 24.1192 +     * Underlying readObject implementation.
 24.1193 +     */
 24.1194 +    private Object readObject0(boolean unshared) throws IOException {
 24.1195 +        boolean oldMode = bin.getBlockDataMode();
 24.1196 +        if (oldMode) {
 24.1197 +            int remain = bin.currentBlockRemaining();
 24.1198 +            if (remain > 0) {
 24.1199 +                throw new OptionalDataException(remain);
 24.1200 +            } else if (defaultDataEnd) {
 24.1201 +                /*
 24.1202 +                 * Fix for 4360508: stream is currently at the end of a field
 24.1203 +                 * value block written via default serialization; since there
 24.1204 +                 * is no terminating TC_ENDBLOCKDATA tag, simulate
 24.1205 +                 * end-of-custom-data behavior explicitly.
 24.1206 +                 */
 24.1207 +                throw new OptionalDataException(true);
 24.1208 +            }
 24.1209 +            bin.setBlockDataMode(false);
 24.1210 +        }
 24.1211 +
 24.1212 +        byte tc;
 24.1213 +        while ((tc = bin.peekByte()) == TC_RESET) {
 24.1214 +            bin.readByte();
 24.1215 +            handleReset();
 24.1216 +        }
 24.1217 +
 24.1218 +        depth++;
 24.1219 +        try {
 24.1220 +            switch (tc) {
 24.1221 +                case TC_NULL:
 24.1222 +                    return readNull();
 24.1223 +
 24.1224 +                case TC_REFERENCE:
 24.1225 +                    return readHandle(unshared);
 24.1226 +
 24.1227 +                case TC_CLASS:
 24.1228 +                    return readClass(unshared);
 24.1229 +
 24.1230 +                case TC_CLASSDESC:
 24.1231 +                case TC_PROXYCLASSDESC:
 24.1232 +                    return readClassDesc(unshared);
 24.1233 +
 24.1234 +                case TC_STRING:
 24.1235 +                case TC_LONGSTRING:
 24.1236 +                    return checkResolve(readString(unshared));
 24.1237 +
 24.1238 +                case TC_ARRAY:
 24.1239 +                    return checkResolve(readArray(unshared));
 24.1240 +
 24.1241 +                case TC_ENUM:
 24.1242 +                    return checkResolve(readEnum(unshared));
 24.1243 +
 24.1244 +                case TC_OBJECT:
 24.1245 +                    return checkResolve(readOrdinaryObject(unshared));
 24.1246 +
 24.1247 +                case TC_EXCEPTION:
 24.1248 +                    IOException ex = readFatalException();
 24.1249 +                    throw new WriteAbortedException("writing aborted", ex);
 24.1250 +
 24.1251 +                case TC_BLOCKDATA:
 24.1252 +                case TC_BLOCKDATALONG:
 24.1253 +                    if (oldMode) {
 24.1254 +                        bin.setBlockDataMode(true);
 24.1255 +                        bin.peek();             // force header read
 24.1256 +                        throw new OptionalDataException(
 24.1257 +                            bin.currentBlockRemaining());
 24.1258 +                    } else {
 24.1259 +                        throw new StreamCorruptedException(
 24.1260 +                            "unexpected block data");
 24.1261 +                    }
 24.1262 +
 24.1263 +                case TC_ENDBLOCKDATA:
 24.1264 +                    if (oldMode) {
 24.1265 +                        throw new OptionalDataException(true);
 24.1266 +                    } else {
 24.1267 +                        throw new StreamCorruptedException(
 24.1268 +                            "unexpected end of block data");
 24.1269 +                    }
 24.1270 +
 24.1271 +                default:
 24.1272 +                    throw new StreamCorruptedException(
 24.1273 +                        String.format("invalid type code: %02X", tc));
 24.1274 +            }
 24.1275 +        } finally {
 24.1276 +            depth--;
 24.1277 +            bin.setBlockDataMode(oldMode);
 24.1278 +        }
 24.1279 +    }
 24.1280 +
 24.1281 +    /**
 24.1282 +     * If resolveObject has been enabled and given object does not have an
 24.1283 +     * exception associated with it, calls resolveObject to determine
 24.1284 +     * replacement for object, and updates handle table accordingly.  Returns
 24.1285 +     * replacement object, or echoes provided object if no replacement
 24.1286 +     * occurred.  Expects that passHandle is set to given object's handle prior
 24.1287 +     * to calling this method.
 24.1288 +     */
 24.1289 +    private Object checkResolve(Object obj) throws IOException {
 24.1290 +        if (!enableResolve || handles.lookupException(passHandle) != null) {
 24.1291 +            return obj;
 24.1292 +        }
 24.1293 +        Object rep = resolveObject(obj);
 24.1294 +        if (rep != obj) {
 24.1295 +            handles.setObject(passHandle, rep);
 24.1296 +        }
 24.1297 +        return rep;
 24.1298 +    }
 24.1299 +
 24.1300 +    /**
 24.1301 +     * Reads string without allowing it to be replaced in stream.  Called from
 24.1302 +     * within ObjectStreamClass.read().
 24.1303 +     */
 24.1304 +    String readTypeString() throws IOException {
 24.1305 +        int oldHandle = passHandle;
 24.1306 +        try {
 24.1307 +            byte tc = bin.peekByte();
 24.1308 +            switch (tc) {
 24.1309 +                case TC_NULL:
 24.1310 +                    return (String) readNull();
 24.1311 +
 24.1312 +                case TC_REFERENCE:
 24.1313 +                    return (String) readHandle(false);
 24.1314 +
 24.1315 +                case TC_STRING:
 24.1316 +                case TC_LONGSTRING:
 24.1317 +                    return readString(false);
 24.1318 +
 24.1319 +                default:
 24.1320 +                    throw new StreamCorruptedException(
 24.1321 +                        String.format("invalid type code: %02X", tc));
 24.1322 +            }
 24.1323 +        } finally {
 24.1324 +            passHandle = oldHandle;
 24.1325 +        }
 24.1326 +    }
 24.1327 +
 24.1328 +    /**
 24.1329 +     * Reads in null code, sets passHandle to NULL_HANDLE and returns null.
 24.1330 +     */
 24.1331 +    private Object readNull() throws IOException {
 24.1332 +        if (bin.readByte() != TC_NULL) {
 24.1333 +            throw new InternalError();
 24.1334 +        }
 24.1335 +        passHandle = NULL_HANDLE;
 24.1336 +        return null;
 24.1337 +    }
 24.1338 +
 24.1339 +    /**
 24.1340 +     * Reads in object handle, sets passHandle to the read handle, and returns
 24.1341 +     * object associated with the handle.
 24.1342 +     */
 24.1343 +    private Object readHandle(boolean unshared) throws IOException {
 24.1344 +        if (bin.readByte() != TC_REFERENCE) {
 24.1345 +            throw new InternalError();
 24.1346 +        }
 24.1347 +        passHandle = bin.readInt() - baseWireHandle;
 24.1348 +        if (passHandle < 0 || passHandle >= handles.size()) {
 24.1349 +            throw new StreamCorruptedException(
 24.1350 +                String.format("invalid handle value: %08X", passHandle +
 24.1351 +                baseWireHandle));
 24.1352 +        }
 24.1353 +        if (unshared) {
 24.1354 +            // REMIND: what type of exception to throw here?
 24.1355 +            throw new InvalidObjectException(
 24.1356 +                "cannot read back reference as unshared");
 24.1357 +        }
 24.1358 +
 24.1359 +        Object obj = handles.lookupObject(passHandle);
 24.1360 +        if (obj == unsharedMarker) {
 24.1361 +            // REMIND: what type of exception to throw here?
 24.1362 +            throw new InvalidObjectException(
 24.1363 +                "cannot read back reference to unshared object");
 24.1364 +        }
 24.1365 +        return obj;
 24.1366 +    }
 24.1367 +
 24.1368 +    /**
 24.1369 +     * Reads in and returns class object.  Sets passHandle to class object's
 24.1370 +     * assigned handle.  Returns null if class is unresolvable (in which case a
 24.1371 +     * ClassNotFoundException will be associated with the class' handle in the
 24.1372 +     * handle table).
 24.1373 +     */
 24.1374 +    private Class readClass(boolean unshared) throws IOException {
 24.1375 +        if (bin.readByte() != TC_CLASS) {
 24.1376 +            throw new InternalError();
 24.1377 +        }
 24.1378 +        ObjectStreamClass desc = readClassDesc(false);
 24.1379 +        Class cl = desc.forClass();
 24.1380 +        passHandle = handles.assign(unshared ? unsharedMarker : cl);
 24.1381 +
 24.1382 +        ClassNotFoundException resolveEx = desc.getResolveException();
 24.1383 +        if (resolveEx != null) {
 24.1384 +            handles.markException(passHandle, resolveEx);
 24.1385 +        }
 24.1386 +
 24.1387 +        handles.finish(passHandle);
 24.1388 +        return cl;
 24.1389 +    }
 24.1390 +
 24.1391 +    /**
 24.1392 +     * Reads in and returns (possibly null) class descriptor.  Sets passHandle
 24.1393 +     * to class descriptor's assigned handle.  If class descriptor cannot be
 24.1394 +     * resolved to a class in the local VM, a ClassNotFoundException is
 24.1395 +     * associated with the class descriptor's handle.
 24.1396 +     */
 24.1397 +    private ObjectStreamClass readClassDesc(boolean unshared)
 24.1398 +        throws IOException
 24.1399 +    {
 24.1400 +        byte tc = bin.peekByte();
 24.1401 +        switch (tc) {
 24.1402 +            case TC_NULL:
 24.1403 +                return (ObjectStreamClass) readNull();
 24.1404 +
 24.1405 +            case TC_REFERENCE:
 24.1406 +                return (ObjectStreamClass) readHandle(unshared);
 24.1407 +
 24.1408 +            case TC_PROXYCLASSDESC:
 24.1409 +                return readProxyDesc(unshared);
 24.1410 +
 24.1411 +            case TC_CLASSDESC:
 24.1412 +                return readNonProxyDesc(unshared);
 24.1413 +
 24.1414 +            default:
 24.1415 +                throw new StreamCorruptedException(
 24.1416 +                    String.format("invalid type code: %02X", tc));
 24.1417 +        }
 24.1418 +    }
 24.1419 +
 24.1420 +    /**
 24.1421 +     * Reads in and returns class descriptor for a dynamic proxy class.  Sets
 24.1422 +     * passHandle to proxy class descriptor's assigned handle.  If proxy class
 24.1423 +     * descriptor cannot be resolved to a class in the local VM, a
 24.1424 +     * ClassNotFoundException is associated with the descriptor's handle.
 24.1425 +     */
 24.1426 +    private ObjectStreamClass readProxyDesc(boolean unshared)
 24.1427 +        throws IOException
 24.1428 +    {
 24.1429 +        if (bin.readByte() != TC_PROXYCLASSDESC) {
 24.1430 +            throw new InternalError();
 24.1431 +        }
 24.1432 +
 24.1433 +        ObjectStreamClass desc = new ObjectStreamClass();
 24.1434 +        int descHandle = handles.assign(unshared ? unsharedMarker : desc);
 24.1435 +        passHandle = NULL_HANDLE;
 24.1436 +
 24.1437 +        int numIfaces = bin.readInt();
 24.1438 +        String[] ifaces = new String[numIfaces];
 24.1439 +        for (int i = 0; i < numIfaces; i++) {
 24.1440 +            ifaces[i] = bin.readUTF();
 24.1441 +        }
 24.1442 +
 24.1443 +        Class cl = null;
 24.1444 +        ClassNotFoundException resolveEx = null;
 24.1445 +        bin.setBlockDataMode(true);
 24.1446 +        try {
 24.1447 +            if ((cl = resolveProxyClass(ifaces)) == null) {
 24.1448 +                resolveEx = new ClassNotFoundException("null class");
 24.1449 +            }
 24.1450 +        } catch (ClassNotFoundException ex) {
 24.1451 +            resolveEx = ex;
 24.1452 +        }
 24.1453 +        skipCustomData();
 24.1454 +
 24.1455 +        desc.initProxy(cl, resolveEx, readClassDesc(false));
 24.1456 +
 24.1457 +        handles.finish(descHandle);
 24.1458 +        passHandle = descHandle;
 24.1459 +        return desc;
 24.1460 +    }
 24.1461 +
 24.1462 +    /**
 24.1463 +     * Reads in and returns class descriptor for a class that is not a dynamic
 24.1464 +     * proxy class.  Sets passHandle to class descriptor's assigned handle.  If
 24.1465 +     * class descriptor cannot be resolved to a class in the local VM, a
 24.1466 +     * ClassNotFoundException is associated with the descriptor's handle.
 24.1467 +     */
 24.1468 +    private ObjectStreamClass readNonProxyDesc(boolean unshared)
 24.1469 +        throws IOException
 24.1470 +    {
 24.1471 +        if (bin.readByte() != TC_CLASSDESC) {
 24.1472 +            throw new InternalError();
 24.1473 +        }
 24.1474 +
 24.1475 +        ObjectStreamClass desc = new ObjectStreamClass();
 24.1476 +        int descHandle = handles.assign(unshared ? unsharedMarker : desc);
 24.1477 +        passHandle = NULL_HANDLE;
 24.1478 +
 24.1479 +        ObjectStreamClass readDesc = null;
 24.1480 +        try {
 24.1481 +            readDesc = readClassDescriptor();
 24.1482 +        } catch (ClassNotFoundException ex) {
 24.1483 +            throw (IOException) new InvalidClassException(
 24.1484 +                "failed to read class descriptor").initCause(ex);
 24.1485 +        }
 24.1486 +
 24.1487 +        Class cl = null;
 24.1488 +        ClassNotFoundException resolveEx = null;
 24.1489 +        bin.setBlockDataMode(true);
 24.1490 +        try {
 24.1491 +            if ((cl = resolveClass(readDesc)) == null) {
 24.1492 +                resolveEx = new ClassNotFoundException("null class");
 24.1493 +            }
 24.1494 +        } catch (ClassNotFoundException ex) {
 24.1495 +            resolveEx = ex;
 24.1496 +        }
 24.1497 +        skipCustomData();
 24.1498 +
 24.1499 +        desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));
 24.1500 +
 24.1501 +        handles.finish(descHandle);
 24.1502 +        passHandle = descHandle;
 24.1503 +        return desc;
 24.1504 +    }
 24.1505 +
 24.1506 +    /**
 24.1507 +     * Reads in and returns new string.  Sets passHandle to new string's
 24.1508 +     * assigned handle.
 24.1509 +     */
 24.1510 +    private String readString(boolean unshared) throws IOException {
 24.1511 +        String str;
 24.1512 +        byte tc = bin.readByte();
 24.1513 +        switch (tc) {
 24.1514 +            case TC_STRING:
 24.1515 +                str = bin.readUTF();
 24.1516 +                break;
 24.1517 +
 24.1518 +            case TC_LONGSTRING:
 24.1519 +                str = bin.readLongUTF();
 24.1520 +                break;
 24.1521 +
 24.1522 +            default:
 24.1523 +                throw new StreamCorruptedException(
 24.1524 +                    String.format("invalid type code: %02X", tc));
 24.1525 +        }
 24.1526 +        passHandle = handles.assign(unshared ? unsharedMarker : str);
 24.1527 +        handles.finish(passHandle);
 24.1528 +        return str;
 24.1529 +    }
 24.1530 +
 24.1531 +    /**
 24.1532 +     * Reads in and returns array object, or null if array class is
 24.1533 +     * unresolvable.  Sets passHandle to array's assigned handle.
 24.1534 +     */
 24.1535 +    private Object readArray(boolean unshared) throws IOException {
 24.1536 +        if (bin.readByte() != TC_ARRAY) {
 24.1537 +            throw new InternalError();
 24.1538 +        }
 24.1539 +
 24.1540 +        ObjectStreamClass desc = readClassDesc(false);
 24.1541 +        int len = bin.readInt();
 24.1542 +
 24.1543 +        Object array = null;
 24.1544 +        Class cl, ccl = null;
 24.1545 +        if ((cl = desc.forClass()) != null) {
 24.1546 +            ccl = cl.getComponentType();
 24.1547 +            array = Array.newInstance(ccl, len);
 24.1548 +        }
 24.1549 +
 24.1550 +        int arrayHandle = handles.assign(unshared ? unsharedMarker : array);
 24.1551 +        ClassNotFoundException resolveEx = desc.getResolveException();
 24.1552 +        if (resolveEx != null) {
 24.1553 +            handles.markException(arrayHandle, resolveEx);
 24.1554 +        }
 24.1555 +
 24.1556 +        if (ccl == null) {
 24.1557 +            for (int i = 0; i < len; i++) {
 24.1558 +                readObject0(false);
 24.1559 +            }
 24.1560 +        } else if (ccl.isPrimitive()) {
 24.1561 +            if (ccl == Integer.TYPE) {
 24.1562 +                bin.readInts((int[]) array, 0, len);
 24.1563 +            } else if (ccl == Byte.TYPE) {
 24.1564 +                bin.readFully((byte[]) array, 0, len, true);
 24.1565 +            } else if (ccl == Long.TYPE) {
 24.1566 +                bin.readLongs((long[]) array, 0, len);
 24.1567 +            } else if (ccl == Float.TYPE) {
 24.1568 +                bin.readFloats((float[]) array, 0, len);
 24.1569 +            } else if (ccl == Double.TYPE) {
 24.1570 +                bin.readDoubles((double[]) array, 0, len);
 24.1571 +            } else if (ccl == Short.TYPE) {
 24.1572 +                bin.readShorts((short[]) array, 0, len);
 24.1573 +            } else if (ccl == Character.TYPE) {
 24.1574 +                bin.readChars((char[]) array, 0, len);
 24.1575 +            } else if (ccl == Boolean.TYPE) {
 24.1576 +                bin.readBooleans((boolean[]) array, 0, len);
 24.1577 +            } else {
 24.1578 +                throw new InternalError();
 24.1579 +            }
 24.1580 +        } else {
 24.1581 +            Object[] oa = (Object[]) array;
 24.1582 +            for (int i = 0; i < len; i++) {
 24.1583 +                oa[i] = readObject0(false);
 24.1584 +                handles.markDependency(arrayHandle, passHandle);
 24.1585 +            }
 24.1586 +        }
 24.1587 +
 24.1588 +        handles.finish(arrayHandle);
 24.1589 +        passHandle = arrayHandle;
 24.1590 +        return array;
 24.1591 +    }
 24.1592 +
 24.1593 +    /**
 24.1594 +     * Reads in and returns enum constant, or null if enum type is
 24.1595 +     * unresolvable.  Sets passHandle to enum constant's assigned handle.
 24.1596 +     */
 24.1597 +    private Enum readEnum(boolean unshared) throws IOException {
 24.1598 +        if (bin.readByte() != TC_ENUM) {
 24.1599 +            throw new InternalError();
 24.1600 +        }
 24.1601 +
 24.1602 +        ObjectStreamClass desc = readClassDesc(false);
 24.1603 +        if (!desc.isEnum()) {
 24.1604 +            throw new InvalidClassException("non-enum class: " + desc);
 24.1605 +        }
 24.1606 +
 24.1607 +        int enumHandle = handles.assign(unshared ? unsharedMarker : null);
 24.1608 +        ClassNotFoundException resolveEx = desc.getResolveException();
 24.1609 +        if (resolveEx != null) {
 24.1610 +            handles.markException(enumHandle, resolveEx);
 24.1611 +        }
 24.1612 +
 24.1613 +        String name = readString(false);
 24.1614 +        Enum en = null;
 24.1615 +        Class cl = desc.forClass();
 24.1616 +        if (cl != null) {
 24.1617 +            try {
 24.1618 +                en = Enum.valueOf(cl, name);
 24.1619 +            } catch (IllegalArgumentException ex) {
 24.1620 +                throw (IOException) new InvalidObjectException(
 24.1621 +                    "enum constant " + name + " does not exist in " +
 24.1622 +                    cl).initCause(ex);
 24.1623 +            }
 24.1624 +            if (!unshared) {
 24.1625 +                handles.setObject(enumHandle, en);
 24.1626 +            }
 24.1627 +        }
 24.1628 +
 24.1629 +        handles.finish(enumHandle);
 24.1630 +        passHandle = enumHandle;
 24.1631 +        return en;
 24.1632 +    }
 24.1633 +
 24.1634 +    /**
 24.1635 +     * Reads and returns "ordinary" (i.e., not a String, Class,
 24.1636 +     * ObjectStreamClass, array, or enum constant) object, or null if object's
 24.1637 +     * class is unresolvable (in which case a ClassNotFoundException will be
 24.1638 +     * associated with object's handle).  Sets passHandle to object's assigned
 24.1639 +     * handle.
 24.1640 +     */
 24.1641 +    private Object readOrdinaryObject(boolean unshared)
 24.1642 +        throws IOException
 24.1643 +    {
 24.1644 +        if (bin.readByte() != TC_OBJECT) {
 24.1645 +            throw new InternalError();
 24.1646 +        }
 24.1647 +
 24.1648 +        ObjectStreamClass desc = readClassDesc(false);
 24.1649 +        desc.checkDeserialize();
 24.1650 +
 24.1651 +        Object obj;
 24.1652 +        try {
 24.1653 +            obj = desc.isInstantiable() ? desc.newInstance() : null;
 24.1654 +        } catch (Exception ex) {
 24.1655 +            throw (IOException) new InvalidClassException(
 24.1656 +                desc.forClass().getName(),
 24.1657 +                "unable to create instance").initCause(ex);
 24.1658 +        }
 24.1659 +
 24.1660 +        passHandle = handles.assign(unshared ? unsharedMarker : obj);
 24.1661 +        ClassNotFoundException resolveEx = desc.getResolveException();
 24.1662 +        if (resolveEx != null) {
 24.1663 +            handles.markException(passHandle, resolveEx);
 24.1664 +        }
 24.1665 +
 24.1666 +        if (desc.isExternalizable()) {
 24.1667 +            readExternalData((Externalizable) obj, desc);
 24.1668 +        } else {
 24.1669 +            readSerialData(obj, desc);
 24.1670 +        }
 24.1671 +
 24.1672 +        handles.finish(passHandle);
 24.1673 +
 24.1674 +        if (obj != null &&
 24.1675 +            handles.lookupException(passHandle) == null &&
 24.1676 +            desc.hasReadResolveMethod())
 24.1677 +        {
 24.1678 +            Object rep = desc.invokeReadResolve(obj);
 24.1679 +            if (unshared && rep.getClass().isArray()) {
 24.1680 +                rep = cloneArray(rep);
 24.1681 +            }
 24.1682 +            if (rep != obj) {
 24.1683 +                handles.setObject(passHandle, obj = rep);
 24.1684 +            }
 24.1685 +        }
 24.1686 +
 24.1687 +        return obj;
 24.1688 +    }
 24.1689 +
 24.1690 +    /**
 24.1691 +     * If obj is non-null, reads externalizable data by invoking readExternal()
 24.1692 +     * method of obj; otherwise, attempts to skip over externalizable data.
 24.1693 +     * Expects that passHandle is set to obj's handle before this method is
 24.1694 +     * called.
 24.1695 +     */
 24.1696 +    private void readExternalData(Externalizable obj, ObjectStreamClass desc)
 24.1697 +        throws IOException
 24.1698 +    {
 24.1699 +        Object oldContext = curContext;
 24.1700 +        curContext = null;
 24.1701 +        try {
 24.1702 +            boolean blocked = desc.hasBlockExternalData();
 24.1703 +            if (blocked) {
 24.1704 +                bin.setBlockDataMode(true);
 24.1705 +            }
 24.1706 +            if (obj != null) {
 24.1707 +                try {
 24.1708 +                    obj.readExternal(this);
 24.1709 +                } catch (ClassNotFoundException ex) {
 24.1710 +                    /*
 24.1711 +                     * In most cases, the handle table has already propagated
 24.1712 +                     * a CNFException to passHandle at this point; this mark
 24.1713 +                     * call is included to address cases where the readExternal
 24.1714 +                     * method has cons'ed and thrown a new CNFException of its
 24.1715 +                     * own.
 24.1716 +                     */
 24.1717 +                     handles.markException(passHandle, ex);
 24.1718 +                }
 24.1719 +            }
 24.1720 +            if (blocked) {
 24.1721 +                skipCustomData();
 24.1722 +            }
 24.1723 +        } finally {
 24.1724 +            curContext = oldContext;
 24.1725 +        }
 24.1726 +        /*
 24.1727 +         * At this point, if the externalizable data was not written in
 24.1728 +         * block-data form and either the externalizable class doesn't exist
 24.1729 +         * locally (i.e., obj == null) or readExternal() just threw a
 24.1730 +         * CNFException, then the stream is probably in an inconsistent state,
 24.1731 +         * since some (or all) of the externalizable data may not have been
 24.1732 +         * consumed.  Since there's no "correct" action to take in this case,
 24.1733 +         * we mimic the behavior of past serialization implementations and
 24.1734 +         * blindly hope that the stream is in sync; if it isn't and additional
 24.1735 +         * externalizable data remains in the stream, a subsequent read will
 24.1736 +         * most likely throw a StreamCorruptedException.
 24.1737 +         */
 24.1738 +    }
 24.1739 +
 24.1740 +    /**
 24.1741 +     * Reads (or attempts to skip, if obj is null or is tagged with a
 24.1742 +     * ClassNotFoundException) instance data for each serializable class of
 24.1743 +     * object in stream, from superclass to subclass.  Expects that passHandle
 24.1744 +     * is set to obj's handle before this method is called.
 24.1745 +     */
 24.1746 +    private void readSerialData(Object obj, ObjectStreamClass desc)
 24.1747 +        throws IOException
 24.1748 +    {
 24.1749 +        ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
 24.1750 +        for (int i = 0; i < slots.length; i++) {
 24.1751 +            ObjectStreamClass slotDesc = slots[i].desc;
 24.1752 +
 24.1753 +            if (slots[i].hasData) {
 24.1754 +                if (obj != null &&
 24.1755 +                    slotDesc.hasReadObjectMethod() &&
 24.1756 +                    handles.lookupException(passHandle) == null)
 24.1757 +                {
 24.1758 +                    Object oldContext = curContext;
 24.1759 +
 24.1760 +                    try {
 24.1761 +                        curContext = null; //new SerialCallbackContext(obj, slotDesc);
 24.1762 +
 24.1763 +                        bin.setBlockDataMode(true);
 24.1764 +                        slotDesc.invokeReadObject(obj, this);
 24.1765 +                    } catch (ClassNotFoundException ex) {
 24.1766 +                        /*
 24.1767 +                         * In most cases, the handle table has already
 24.1768 +                         * propagated a CNFException to passHandle at this
 24.1769 +                         * point; this mark call is included to address cases
 24.1770 +                         * where the custom readObject method has cons'ed and
 24.1771 +                         * thrown a new CNFException of its own.
 24.1772 +                         */
 24.1773 +                        handles.markException(passHandle, ex);
 24.1774 +                    } finally {
 24.1775 +                        //curContext.setUsed();
 24.1776 +                        curContext = oldContext;
 24.1777 +                    }
 24.1778 +
 24.1779 +                    /*
 24.1780 +                     * defaultDataEnd may have been set indirectly by custom
 24.1781 +                     * readObject() method when calling defaultReadObject() or
 24.1782 +                     * readFields(); clear it to restore normal read behavior.
 24.1783 +                     */
 24.1784 +                    defaultDataEnd = false;
 24.1785 +                } else {
 24.1786 +                    defaultReadFields(obj, slotDesc);
 24.1787 +                }
 24.1788 +                if (slotDesc.hasWriteObjectData()) {
 24.1789 +                    skipCustomData();
 24.1790 +                } else {
 24.1791 +                    bin.setBlockDataMode(false);
 24.1792 +                }
 24.1793 +            } else {
 24.1794 +                if (obj != null &&
 24.1795 +                    slotDesc.hasReadObjectNoDataMethod() &&
 24.1796 +                    handles.lookupException(passHandle) == null)
 24.1797 +                {
 24.1798 +                    slotDesc.invokeReadObjectNoData(obj);
 24.1799 +                }
 24.1800 +            }
 24.1801 +        }
 24.1802 +    }
 24.1803 +
 24.1804 +    /**
 24.1805 +     * Skips over all block data and objects until TC_ENDBLOCKDATA is
 24.1806 +     * encountered.
 24.1807 +     */
 24.1808 +    private void skipCustomData() throws IOException {
 24.1809 +        int oldHandle = passHandle;
 24.1810 +        for (;;) {
 24.1811 +            if (bin.getBlockDataMode()) {
 24.1812 +                bin.skipBlockData();
 24.1813 +                bin.setBlockDataMode(false);
 24.1814 +            }
 24.1815 +            switch (bin.peekByte()) {
 24.1816 +                case TC_BLOCKDATA:
 24.1817 +                case TC_BLOCKDATALONG:
 24.1818 +                    bin.setBlockDataMode(true);
 24.1819 +                    break;
 24.1820 +
 24.1821 +                case TC_ENDBLOCKDATA:
 24.1822 +                    bin.readByte();
 24.1823 +                    passHandle = oldHandle;
 24.1824 +                    return;
 24.1825 +
 24.1826 +                default:
 24.1827 +                    readObject0(false);
 24.1828 +                    break;
 24.1829 +            }
 24.1830 +        }
 24.1831 +    }
 24.1832 +
 24.1833 +    /**
 24.1834 +     * Reads in values of serializable fields declared by given class
 24.1835 +     * descriptor.  If obj is non-null, sets field values in obj.  Expects that
 24.1836 +     * passHandle is set to obj's handle before this method is called.
 24.1837 +     */
 24.1838 +    private void defaultReadFields(Object obj, ObjectStreamClass desc)
 24.1839 +        throws IOException
 24.1840 +    {
 24.1841 +        // REMIND: is isInstance check necessary?
 24.1842 +        Class cl = desc.forClass();
 24.1843 +        if (cl != null && obj != null && !cl.isInstance(obj)) {
 24.1844 +            throw new ClassCastException();
 24.1845 +        }
 24.1846 +
 24.1847 +        int primDataSize = desc.getPrimDataSize();
 24.1848 +        if (primVals == null || primVals.length < primDataSize) {
 24.1849 +            primVals = new byte[primDataSize];
 24.1850 +        }
 24.1851 +        bin.readFully(primVals, 0, primDataSize, false);
 24.1852 +        if (obj != null) {
 24.1853 +            desc.setPrimFieldValues(obj, primVals);
 24.1854 +        }
 24.1855 +
 24.1856 +        int objHandle = passHandle;
 24.1857 +        ObjectStreamField[] fields = desc.getFields(false);
 24.1858 +        Object[] objVals = new Object[desc.getNumObjFields()];
 24.1859 +        int numPrimFields = fields.length - objVals.length;
 24.1860 +        for (int i = 0; i < objVals.length; i++) {
 24.1861 +            ObjectStreamField f = fields[numPrimFields + i];
 24.1862 +            objVals[i] = readObject0(f.isUnshared());
 24.1863 +            if (f.getField() != null) {
 24.1864 +                handles.markDependency(objHandle, passHandle);
 24.1865 +            }
 24.1866 +        }
 24.1867 +        if (obj != null) {
 24.1868 +            desc.setObjFieldValues(obj, objVals);
 24.1869 +        }
 24.1870 +        passHandle = objHandle;
 24.1871 +    }
 24.1872 +
 24.1873 +    /**
 24.1874 +     * Reads in and returns IOException that caused serialization to abort.
 24.1875 +     * All stream state is discarded prior to reading in fatal exception.  Sets
 24.1876 +     * passHandle to fatal exception's handle.
 24.1877 +     */
 24.1878 +    private IOException readFatalException() throws IOException {
 24.1879 +        if (bin.readByte() != TC_EXCEPTION) {
 24.1880 +            throw new InternalError();
 24.1881 +        }
 24.1882 +        clear();
 24.1883 +        return (IOException) readObject0(false);
 24.1884 +    }
 24.1885 +
 24.1886 +    /**
 24.1887 +     * If recursion depth is 0, clears internal data structures; otherwise,
 24.1888 +     * throws a StreamCorruptedException.  This method is called when a
 24.1889 +     * TC_RESET typecode is encountered.
 24.1890 +     */
 24.1891 +    private void handleReset() throws StreamCorruptedException {
 24.1892 +        if (depth > 0) {
 24.1893 +            throw new StreamCorruptedException(
 24.1894 +                "unexpected reset; recursion depth: " + depth);
 24.1895 +        }
 24.1896 +        clear();
 24.1897 +    }
 24.1898 +
 24.1899 +    /**
 24.1900 +     * Converts specified span of bytes into float values.
 24.1901 +     */
 24.1902 +    // REMIND: remove once hotspot inlines Float.intBitsToFloat
 24.1903 +    private static native void bytesToFloats(byte[] src, int srcpos,
 24.1904 +                                             float[] dst, int dstpos,
 24.1905 +                                             int nfloats);
 24.1906 +
 24.1907 +    /**
 24.1908 +     * Converts specified span of bytes into double values.
 24.1909 +     */
 24.1910 +    // REMIND: remove once hotspot inlines Double.longBitsToDouble
 24.1911 +    private static native void bytesToDoubles(byte[] src, int srcpos,
 24.1912 +                                              double[] dst, int dstpos,
 24.1913 +                                              int ndoubles);
 24.1914 +
 24.1915 +    /**
 24.1916 +     * Returns the first non-null class loader (not counting class loaders of
 24.1917 +     * generated reflection implementation classes) up the execution stack, or
 24.1918 +     * null if only code from the null class loader is on the stack.  This
 24.1919 +     * method is also called via reflection by the following RMI-IIOP class:
 24.1920 +     *
 24.1921 +     *     com.sun.corba.se.internal.util.JDKClassLoader
 24.1922 +     *
 24.1923 +     * This method should not be removed or its signature changed without
 24.1924 +     * corresponding modifications to the above class.
 24.1925 +     */
 24.1926 +    // REMIND: change name to something more accurate?
 24.1927 +    private static native ClassLoader latestUserDefinedLoader();
 24.1928 +
 24.1929 +    /**
 24.1930 +     * Default GetField implementation.
 24.1931 +     */
 24.1932 +    private class GetFieldImpl extends GetField {
 24.1933 +
 24.1934 +        /** class descriptor describing serializable fields */
 24.1935 +        private final ObjectStreamClass desc;
 24.1936 +        /** primitive field values */
 24.1937 +        private final byte[] primVals;
 24.1938 +        /** object field values */
 24.1939 +        private final Object[] objVals;
 24.1940 +        /** object field value handles */
 24.1941 +        private final int[] objHandles;
 24.1942 +
 24.1943 +        /**
 24.1944 +         * Creates GetFieldImpl object for reading fields defined in given
 24.1945 +         * class descriptor.
 24.1946 +         */
 24.1947 +        GetFieldImpl(ObjectStreamClass desc) {
 24.1948 +            this.desc = desc;
 24.1949 +            primVals = new byte[desc.getPrimDataSize()];
 24.1950 +            objVals = new Object[desc.getNumObjFields()];
 24.1951 +            objHandles = new int[objVals.length];
 24.1952 +        }
 24.1953 +
 24.1954 +        public ObjectStreamClass getObjectStreamClass() {
 24.1955 +            return desc;
 24.1956 +        }
 24.1957 +
 24.1958 +        public boolean defaulted(String name) throws IOException {
 24.1959 +            return (getFieldOffset(name, null) < 0);
 24.1960 +        }
 24.1961 +
 24.1962 +        public boolean get(String name, boolean val) throws IOException {
 24.1963 +            int off = getFieldOffset(name, Boolean.TYPE);
 24.1964 +            return (off >= 0) ? Bits.getBoolean(primVals, off) : val;
 24.1965 +        }
 24.1966 +
 24.1967 +        public byte get(String name, byte val) throws IOException {
 24.1968 +            int off = getFieldOffset(name, Byte.TYPE);
 24.1969 +            return (off >= 0) ? primVals[off] : val;
 24.1970 +        }
 24.1971 +
 24.1972 +        public char get(String name, char val) throws IOException {
 24.1973 +            int off = getFieldOffset(name, Character.TYPE);
 24.1974 +            return (off >= 0) ? Bits.getChar(primVals, off) : val;
 24.1975 +        }
 24.1976 +
 24.1977 +        public short get(String name, short val) throws IOException {
 24.1978 +            int off = getFieldOffset(name, Short.TYPE);
 24.1979 +            return (off >= 0) ? Bits.getShort(primVals, off) : val;
 24.1980 +        }
 24.1981 +
 24.1982 +        public int get(String name, int val) throws IOException {
 24.1983 +            int off = getFieldOffset(name, Integer.TYPE);
 24.1984 +            return (off >= 0) ? Bits.getInt(primVals, off) : val;
 24.1985 +        }
 24.1986 +
 24.1987 +        public float get(String name, float val) throws IOException {
 24.1988 +            int off = getFieldOffset(name, Float.TYPE);
 24.1989 +            return (off >= 0) ? Bits.getFloat(primVals, off) : val;
 24.1990 +        }
 24.1991 +
 24.1992 +        public long get(String name, long val) throws IOException {
 24.1993 +            int off = getFieldOffset(name, Long.TYPE);
 24.1994 +            return (off >= 0) ? Bits.getLong(primVals, off) : val;
 24.1995 +        }
 24.1996 +
 24.1997 +        public double get(String name, double val) throws IOException {
 24.1998 +            int off = getFieldOffset(name, Double.TYPE);
 24.1999 +            return (off >= 0) ? Bits.getDouble(primVals, off) : val;
 24.2000 +        }
 24.2001 +
 24.2002 +        public Object get(String name, Object val) throws IOException {
 24.2003 +            int off = getFieldOffset(name, Object.class);
 24.2004 +            if (off >= 0) {
 24.2005 +                int objHandle = objHandles[off];
 24.2006 +                handles.markDependency(passHandle, objHandle);
 24.2007 +                return (handles.lookupException(objHandle) == null) ?
 24.2008 +                    objVals[off] : null;
 24.2009 +            } else {
 24.2010 +                return val;
 24.2011 +            }
 24.2012 +        }
 24.2013 +
 24.2014 +        /**
 24.2015 +         * Reads primitive and object field values from stream.
 24.2016 +         */
 24.2017 +        void readFields() throws IOException {
 24.2018 +            bin.readFully(primVals, 0, primVals.length, false);
 24.2019 +
 24.2020 +            int oldHandle = passHandle;
 24.2021 +            ObjectStreamField[] fields = desc.getFields(false);
 24.2022 +            int numPrimFields = fields.length - objVals.length;
 24.2023 +            for (int i = 0; i < objVals.length; i++) {
 24.2024 +                objVals[i] =
 24.2025 +                    readObject0(fields[numPrimFields + i].isUnshared());
 24.2026 +                objHandles[i] = passHandle;
 24.2027 +            }
 24.2028 +            passHandle = oldHandle;
 24.2029 +        }
 24.2030 +
 24.2031 +        /**
 24.2032 +         * Returns offset of field with given name and type.  A specified type
 24.2033 +         * of null matches all types, Object.class matches all non-primitive
 24.2034 +         * types, and any other non-null type matches assignable types only.
 24.2035 +         * If no matching field is found in the (incoming) class
 24.2036 +         * descriptor but a matching field is present in the associated local
 24.2037 +         * class descriptor, returns -1.  Throws IllegalArgumentException if
 24.2038 +         * neither incoming nor local class descriptor contains a match.
 24.2039 +         */
 24.2040 +        private int getFieldOffset(String name, Class type) {
 24.2041 +            ObjectStreamField field = desc.getField(name, type);
 24.2042 +            if (field != null) {
 24.2043 +                return field.getOffset();
 24.2044 +            } else if (desc.getLocalDesc().getField(name, type) != null) {
 24.2045 +                return -1;
 24.2046 +            } else {
 24.2047 +                throw new IllegalArgumentException("no such field " + name +
 24.2048 +                                                   " with type " + type);
 24.2049 +            }
 24.2050 +        }
 24.2051 +    }
 24.2052 +
 24.2053 +    /**
 24.2054 +     * Prioritized list of callbacks to be performed once object graph has been
 24.2055 +     * completely deserialized.
 24.2056 +     */
 24.2057 +    private static class ValidationList {
 24.2058 +
 24.2059 +
 24.2060 +        /**
 24.2061 +         * Creates new (empty) ValidationList.
 24.2062 +         */
 24.2063 +        ValidationList() {
 24.2064 +        }
 24.2065 +
 24.2066 +        /**
 24.2067 +         * Registers callback.  Throws InvalidObjectException if callback
 24.2068 +         * object is null.
 24.2069 +         */
 24.2070 +        void register(ObjectInputValidation obj, int priority)
 24.2071 +            throws InvalidObjectException
 24.2072 +        {
 24.2073 +            if (obj == null) {
 24.2074 +                throw new InvalidObjectException("null callback");
 24.2075 +            }
 24.2076 +            throw new InvalidObjectException("Does not work.");
 24.2077 +        }
 24.2078 +
 24.2079 +        /**
 24.2080 +         * Invokes all registered callbacks and clears the callback list.
 24.2081 +         * Callbacks with higher priorities are called first; those with equal
 24.2082 +         * priorities may be called in any order.  If any of the callbacks
 24.2083 +         * throws an InvalidObjectException, the callback process is terminated
 24.2084 +         * and the exception propagated upwards.
 24.2085 +         */
 24.2086 +        void doCallbacks() throws InvalidObjectException {
 24.2087 +        }
 24.2088 +
 24.2089 +        /**
 24.2090 +         * Resets the callback list to its initial (empty) state.
 24.2091 +         */
 24.2092 +        public void clear() {
 24.2093 +        }
 24.2094 +    }
 24.2095 +
 24.2096 +    /**
 24.2097 +     * Input stream supporting single-byte peek operations.
 24.2098 +     */
 24.2099 +    private static class PeekInputStream extends InputStream {
 24.2100 +
 24.2101 +        /** underlying stream */
 24.2102 +        private final InputStream in;
 24.2103 +        /** peeked byte */
 24.2104 +        private int peekb = -1;
 24.2105 +
 24.2106 +        /**
 24.2107 +         * Creates new PeekInputStream on top of given underlying stream.
 24.2108 +         */
 24.2109 +        PeekInputStream(InputStream in) {
 24.2110 +            this.in = in;
 24.2111 +        }
 24.2112 +
 24.2113 +        /**
 24.2114 +         * Peeks at next byte value in stream.  Similar to read(), except
 24.2115 +         * that it does not consume the read value.
 24.2116 +         */
 24.2117 +        int peek() throws IOException {
 24.2118 +            return (peekb >= 0) ? peekb : (peekb = in.read());
 24.2119 +        }
 24.2120 +
 24.2121 +        public int read() throws IOException {
 24.2122 +            if (peekb >= 0) {
 24.2123 +                int v = peekb;
 24.2124 +                peekb = -1;
 24.2125 +                return v;
 24.2126 +            } else {
 24.2127 +                return in.read();
 24.2128 +            }
 24.2129 +        }
 24.2130 +
 24.2131 +        public int read(byte[] b, int off, int len) throws IOException {
 24.2132 +            if (len == 0) {
 24.2133 +                return 0;
 24.2134 +            } else if (peekb < 0) {
 24.2135 +                return in.read(b, off, len);
 24.2136 +            } else {
 24.2137 +                b[off++] = (byte) peekb;
 24.2138 +                len--;
 24.2139 +                peekb = -1;
 24.2140 +                int n = in.read(b, off, len);
 24.2141 +                return (n >= 0) ? (n + 1) : 1;
 24.2142 +            }
 24.2143 +        }
 24.2144 +
 24.2145 +        void readFully(byte[] b, int off, int len) throws IOException {
 24.2146 +            int n = 0;
 24.2147 +            while (n < len) {
 24.2148 +                int count = read(b, off + n, len - n);
 24.2149 +                if (count < 0) {
 24.2150 +                    throw new EOFException();
 24.2151 +                }
 24.2152 +                n += count;
 24.2153 +            }
 24.2154 +        }
 24.2155 +
 24.2156 +        public long skip(long n) throws IOException {
 24.2157 +            if (n <= 0) {
 24.2158 +                return 0;
 24.2159 +            }
 24.2160 +            int skipped = 0;
 24.2161 +            if (peekb >= 0) {
 24.2162 +                peekb = -1;
 24.2163 +                skipped++;
 24.2164 +                n--;
 24.2165 +            }
 24.2166 +            return skipped + skip(n);
 24.2167 +        }
 24.2168 +
 24.2169 +        public int available() throws IOException {
 24.2170 +            return in.available() + ((peekb >= 0) ? 1 : 0);
 24.2171 +        }
 24.2172 +
 24.2173 +        public void close() throws IOException {
 24.2174 +            in.close();
 24.2175 +        }
 24.2176 +    }
 24.2177 +
 24.2178 +    /**
 24.2179 +     * Input stream with two modes: in default mode, inputs data written in the
 24.2180 +     * same format as DataOutputStream; in "block data" mode, inputs data
 24.2181 +     * bracketed by block data markers (see object serialization specification
 24.2182 +     * for details).  Buffering depends on block data mode: when in default
 24.2183 +     * mode, no data is buffered in advance; when in block data mode, all data
 24.2184 +     * for the current data block is read in at once (and buffered).
 24.2185 +     */
 24.2186 +    private class BlockDataInputStream
 24.2187 +        extends InputStream implements DataInput
 24.2188 +    {
 24.2189 +        /** maximum data block length */
 24.2190 +        private static final int MAX_BLOCK_SIZE = 1024;
 24.2191 +        /** maximum data block header length */
 24.2192 +        private static final int MAX_HEADER_SIZE = 5;
 24.2193 +        /** (tunable) length of char buffer (for reading strings) */
 24.2194 +        private static final int CHAR_BUF_SIZE = 256;
 24.2195 +        /** readBlockHeader() return value indicating header read may block */
 24.2196 +        private static final int HEADER_BLOCKED = -2;
 24.2197 +
 24.2198 +        /** buffer for reading general/block data */
 24.2199 +        private final byte[] buf = new byte[MAX_BLOCK_SIZE];
 24.2200 +        /** buffer for reading block data headers */
 24.2201 +        private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
 24.2202 +        /** char buffer for fast string reads */
 24.2203 +        private final char[] cbuf = new char[CHAR_BUF_SIZE];
 24.2204 +
 24.2205 +        /** block data mode */
 24.2206 +        private boolean blkmode = false;
 24.2207 +
 24.2208 +        // block data state fields; values meaningful only when blkmode true
 24.2209 +        /** current offset into buf */
 24.2210 +        private int pos = 0;
 24.2211 +        /** end offset of valid data in buf, or -1 if no more block data */
 24.2212 +        private int end = -1;
 24.2213 +        /** number of bytes in current block yet to be read from stream */
 24.2214 +        private int unread = 0;
 24.2215 +
 24.2216 +        /** underlying stream (wrapped in peekable filter stream) */
 24.2217 +        private final PeekInputStream in;
 24.2218 +        /** loopback stream (for data reads that span data blocks) */
 24.2219 +        private final DataInputStream din;
 24.2220 +
 24.2221 +        /**
 24.2222 +         * Creates new BlockDataInputStream on top of given underlying stream.
 24.2223 +         * Block data mode is turned off by default.
 24.2224 +         */
 24.2225 +        BlockDataInputStream(InputStream in) {
 24.2226 +            this.in = new PeekInputStream(in);
 24.2227 +            din = new DataInputStream(this);
 24.2228 +        }
 24.2229 +
 24.2230 +        /**
 24.2231 +         * Sets block data mode to the given mode (true == on, false == off)
 24.2232 +         * and returns the previous mode value.  If the new mode is the same as
 24.2233 +         * the old mode, no action is taken.  Throws IllegalStateException if
 24.2234 +         * block data mode is being switched from on to off while unconsumed
 24.2235 +         * block data is still present in the stream.
 24.2236 +         */
 24.2237 +        boolean setBlockDataMode(boolean newmode) throws IOException {
 24.2238 +            if (blkmode == newmode) {
 24.2239 +                return blkmode;
 24.2240 +            }
 24.2241 +            if (newmode) {
 24.2242 +                pos = 0;
 24.2243 +                end = 0;
 24.2244 +                unread = 0;
 24.2245 +            } else if (pos < end) {
 24.2246 +                throw new IllegalStateException("unread block data");
 24.2247 +            }
 24.2248 +            blkmode = newmode;
 24.2249 +            return !blkmode;
 24.2250 +        }
 24.2251 +
 24.2252 +        /**
 24.2253 +         * Returns true if the stream is currently in block data mode, false
 24.2254 +         * otherwise.
 24.2255 +         */
 24.2256 +        boolean getBlockDataMode() {
 24.2257 +            return blkmode;
 24.2258 +        }
 24.2259 +
 24.2260 +        /**
 24.2261 +         * If in block data mode, skips to the end of the current group of data
 24.2262 +         * blocks (but does not unset block data mode).  If not in block data
 24.2263 +         * mode, throws an IllegalStateException.
 24.2264 +         */
 24.2265 +        void skipBlockData() throws IOException {
 24.2266 +            if (!blkmode) {
 24.2267 +                throw new IllegalStateException("not in block data mode");
 24.2268 +            }
 24.2269 +            while (end >= 0) {
 24.2270 +                refill();
 24.2271 +            }
 24.2272 +        }
 24.2273 +
 24.2274 +        /**
 24.2275 +         * Attempts to read in the next block data header (if any).  If
 24.2276 +         * canBlock is false and a full header cannot be read without possibly
 24.2277 +         * blocking, returns HEADER_BLOCKED, else if the next element in the
 24.2278 +         * stream is a block data header, returns the block data length
 24.2279 +         * specified by the header, else returns -1.
 24.2280 +         */
 24.2281 +        private int readBlockHeader(boolean canBlock) throws IOException {
 24.2282 +            if (defaultDataEnd) {
 24.2283 +                /*
 24.2284 +                 * Fix for 4360508: stream is currently at the end of a field
 24.2285 +                 * value block written via default serialization; since there
 24.2286 +                 * is no terminating TC_ENDBLOCKDATA tag, simulate
 24.2287 +                 * end-of-custom-data behavior explicitly.
 24.2288 +                 */
 24.2289 +                return -1;
 24.2290 +            }
 24.2291 +            try {
 24.2292 +                for (;;) {
 24.2293 +                    int avail = canBlock ? Integer.MAX_VALUE : in.available();
 24.2294 +                    if (avail == 0) {
 24.2295 +                        return HEADER_BLOCKED;
 24.2296 +                    }
 24.2297 +
 24.2298 +                    int tc = in.peek();
 24.2299 +                    switch (tc) {
 24.2300 +                        case TC_BLOCKDATA:
 24.2301 +                            if (avail < 2) {
 24.2302 +                                return HEADER_BLOCKED;
 24.2303 +                            }
 24.2304 +                            in.readFully(hbuf, 0, 2);
 24.2305 +                            return hbuf[1] & 0xFF;
 24.2306 +
 24.2307 +                        case TC_BLOCKDATALONG:
 24.2308 +                            if (avail < 5) {
 24.2309 +                                return HEADER_BLOCKED;
 24.2310 +                            }
 24.2311 +                            in.readFully(hbuf, 0, 5);
 24.2312 +                            int len = Bits.getInt(hbuf, 1);
 24.2313 +                            if (len < 0) {
 24.2314 +                                throw new StreamCorruptedException(
 24.2315 +                                    "illegal block data header length: " +
 24.2316 +                                    len);
 24.2317 +                            }
 24.2318 +                            return len;
 24.2319 +
 24.2320 +                        /*
 24.2321 +                         * TC_RESETs may occur in between data blocks.
 24.2322 +                         * Unfortunately, this case must be parsed at a lower
 24.2323 +                         * level than other typecodes, since primitive data
 24.2324 +                         * reads may span data blocks separated by a TC_RESET.
 24.2325 +                         */
 24.2326 +                        case TC_RESET:
 24.2327 +                            in.read();
 24.2328 +                            handleReset();
 24.2329 +                            break;
 24.2330 +
 24.2331 +                        default:
 24.2332 +                            if (tc >= 0 && (tc < TC_BASE || tc > TC_MAX)) {
 24.2333 +                                throw new StreamCorruptedException(
 24.2334 +                                    String.format("invalid type code: %02X",
 24.2335 +                                    tc));
 24.2336 +                            }
 24.2337 +                            return -1;
 24.2338 +                    }
 24.2339 +                }
 24.2340 +            } catch (EOFException ex) {
 24.2341 +                throw new StreamCorruptedException(
 24.2342 +                    "unexpected EOF while reading block data header");
 24.2343 +            }
 24.2344 +        }
 24.2345 +
 24.2346 +        /**
 24.2347 +         * Refills internal buffer buf with block data.  Any data in buf at the
 24.2348 +         * time of the call is considered consumed.  Sets the pos, end, and
 24.2349 +         * unread fields to reflect the new amount of available block data; if
 24.2350 +         * the next element in the stream is not a data block, sets pos and
 24.2351 +         * unread to 0 and end to -1.
 24.2352 +         */
 24.2353 +        private void refill() throws IOException {
 24.2354 +            try {
 24.2355 +                do {
 24.2356 +                    pos = 0;
 24.2357 +                    if (unread > 0) {
 24.2358 +                        int n =
 24.2359 +                            in.read(buf, 0, Math.min(unread, MAX_BLOCK_SIZE));
 24.2360 +                        if (n >= 0) {
 24.2361 +                            end = n;
 24.2362 +                            unread -= n;
 24.2363 +                        } else {
 24.2364 +                            throw new StreamCorruptedException(
 24.2365 +                                "unexpected EOF in middle of data block");
 24.2366 +                        }
 24.2367 +                    } else {
 24.2368 +                        int n = readBlockHeader(true);
 24.2369 +                        if (n >= 0) {
 24.2370 +                            end = 0;
 24.2371 +                            unread = n;
 24.2372 +                        } else {
 24.2373 +                            end = -1;
 24.2374 +                            unread = 0;
 24.2375 +                        }
 24.2376 +                    }
 24.2377 +                } while (pos == end);
 24.2378 +            } catch (IOException ex) {
 24.2379 +                pos = 0;
 24.2380 +                end = -1;
 24.2381 +                unread = 0;
 24.2382 +                throw ex;
 24.2383 +            }
 24.2384 +        }
 24.2385 +
 24.2386 +        /**
 24.2387 +         * If in block data mode, returns the number of unconsumed bytes
 24.2388 +         * remaining in the current data block.  If not in block data mode,
 24.2389 +         * throws an IllegalStateException.
 24.2390 +         */
 24.2391 +        int currentBlockRemaining() {
 24.2392 +            if (blkmode) {
 24.2393 +                return (end >= 0) ? (end - pos) + unread : 0;
 24.2394 +            } else {
 24.2395 +                throw new IllegalStateException();
 24.2396 +            }
 24.2397 +        }
 24.2398 +
 24.2399 +        /**
 24.2400 +         * Peeks at (but does not consume) and returns the next byte value in
 24.2401 +         * the stream, or -1 if the end of the stream/block data (if in block
 24.2402 +         * data mode) has been reached.
 24.2403 +         */
 24.2404 +        int peek() throws IOException {
 24.2405 +            if (blkmode) {
 24.2406 +                if (pos == end) {
 24.2407 +                    refill();
 24.2408 +                }
 24.2409 +                return (end >= 0) ? (buf[pos] & 0xFF) : -1;
 24.2410 +            } else {
 24.2411 +                return in.peek();
 24.2412 +            }
 24.2413 +        }
 24.2414 +
 24.2415 +        /**
 24.2416 +         * Peeks at (but does not consume) and returns the next byte value in
 24.2417 +         * the stream, or throws EOFException if end of stream/block data has
 24.2418 +         * been reached.
 24.2419 +         */
 24.2420 +        byte peekByte() throws IOException {
 24.2421 +            int val = peek();
 24.2422 +            if (val < 0) {
 24.2423 +                throw new EOFException();
 24.2424 +            }
 24.2425 +            return (byte) val;
 24.2426 +        }
 24.2427 +
 24.2428 +
 24.2429 +        /* ----------------- generic input stream methods ------------------ */
 24.2430 +        /*
 24.2431 +         * The following methods are equivalent to their counterparts in
 24.2432 +         * InputStream, except that they interpret data block boundaries and
 24.2433 +         * read the requested data from within data blocks when in block data
 24.2434 +         * mode.
 24.2435 +         */
 24.2436 +
 24.2437 +        public int read() throws IOException {
 24.2438 +            if (blkmode) {
 24.2439 +                if (pos == end) {
 24.2440 +                    refill();
 24.2441 +                }
 24.2442 +                return (end >= 0) ? (buf[pos++] & 0xFF) : -1;
 24.2443 +            } else {
 24.2444 +                return in.read();
 24.2445 +            }
 24.2446 +        }
 24.2447 +
 24.2448 +        public int read(byte[] b, int off, int len) throws IOException {
 24.2449 +            return read(b, off, len, false);
 24.2450 +        }
 24.2451 +
 24.2452 +        public long skip(long len) throws IOException {
 24.2453 +            long remain = len;
 24.2454 +            while (remain > 0) {
 24.2455 +                if (blkmode) {
 24.2456 +                    if (pos == end) {
 24.2457 +                        refill();
 24.2458 +                    }
 24.2459 +                    if (end < 0) {
 24.2460 +                        break;
 24.2461 +                    }
 24.2462 +                    int nread = (int) Math.min(remain, end - pos);
 24.2463 +                    remain -= nread;
 24.2464 +                    pos += nread;
 24.2465 +                } else {
 24.2466 +                    int nread = (int) Math.min(remain, MAX_BLOCK_SIZE);
 24.2467 +                    if ((nread = in.read(buf, 0, nread)) < 0) {
 24.2468 +                        break;
 24.2469 +                    }
 24.2470 +                    remain -= nread;
 24.2471 +                }
 24.2472 +            }
 24.2473 +            return len - remain;
 24.2474 +        }
 24.2475 +
 24.2476 +        public int available() throws IOException {
 24.2477 +            if (blkmode) {
 24.2478 +                if ((pos == end) && (unread == 0)) {
 24.2479 +                    int n;
 24.2480 +                    while ((n = readBlockHeader(false)) == 0) ;
 24.2481 +                    switch (n) {
 24.2482 +                        case HEADER_BLOCKED:
 24.2483 +                            break;
 24.2484 +
 24.2485 +                        case -1:
 24.2486 +                            pos = 0;
 24.2487 +                            end = -1;
 24.2488 +                            break;
 24.2489 +
 24.2490 +                        default:
 24.2491 +                            pos = 0;
 24.2492 +                            end = 0;
 24.2493 +                            unread = n;
 24.2494 +                            break;
 24.2495 +                    }
 24.2496 +                }
 24.2497 +                // avoid unnecessary call to in.available() if possible
 24.2498 +                int unreadAvail = (unread > 0) ?
 24.2499 +                    Math.min(in.available(), unread) : 0;
 24.2500 +                return (end >= 0) ? (end - pos) + unreadAvail : 0;
 24.2501 +            } else {
 24.2502 +                return in.available();
 24.2503 +            }
 24.2504 +        }
 24.2505 +
 24.2506 +        public void close() throws IOException {
 24.2507 +            if (blkmode) {
 24.2508 +                pos = 0;
 24.2509 +                end = -1;
 24.2510 +                unread = 0;
 24.2511 +            }
 24.2512 +            in.close();
 24.2513 +        }
 24.2514 +
 24.2515 +        /**
 24.2516 +         * Attempts to read len bytes into byte array b at offset off.  Returns
 24.2517 +         * the number of bytes read, or -1 if the end of stream/block data has
 24.2518 +         * been reached.  If copy is true, reads values into an intermediate
 24.2519 +         * buffer before copying them to b (to avoid exposing a reference to
 24.2520 +         * b).
 24.2521 +         */
 24.2522 +        int read(byte[] b, int off, int len, boolean copy) throws IOException {
 24.2523 +            if (len == 0) {
 24.2524 +                return 0;
 24.2525 +            } else if (blkmode) {
 24.2526 +                if (pos == end) {
 24.2527 +                    refill();
 24.2528 +                }
 24.2529 +                if (end < 0) {
 24.2530 +                    return -1;
 24.2531 +                }
 24.2532 +                int nread = Math.min(len, end - pos);
 24.2533 +                System.arraycopy(buf, pos, b, off, nread);
 24.2534 +                pos += nread;
 24.2535 +                return nread;
 24.2536 +            } else if (copy) {
 24.2537 +                int nread = in.read(buf, 0, Math.min(len, MAX_BLOCK_SIZE));
 24.2538 +                if (nread > 0) {
 24.2539 +                    System.arraycopy(buf, 0, b, off, nread);
 24.2540 +                }
 24.2541 +                return nread;
 24.2542 +            } else {
 24.2543 +                return in.read(b, off, len);
 24.2544 +            }
 24.2545 +        }
 24.2546 +
 24.2547 +        /* ----------------- primitive data input methods ------------------ */
 24.2548 +        /*
 24.2549 +         * The following methods are equivalent to their counterparts in
 24.2550 +         * DataInputStream, except that they interpret data block boundaries
 24.2551 +         * and read the requested data from within data blocks when in block
 24.2552 +         * data mode.
 24.2553 +         */
 24.2554 +
 24.2555 +        public void readFully(byte[] b) throws IOException {
 24.2556 +            readFully(b, 0, b.length, false);
 24.2557 +        }
 24.2558 +
 24.2559 +        public void readFully(byte[] b, int off, int len) throws IOException {
 24.2560 +            readFully(b, off, len, false);
 24.2561 +        }
 24.2562 +
 24.2563 +        public void readFully(byte[] b, int off, int len, boolean copy)
 24.2564 +            throws IOException
 24.2565 +        {
 24.2566 +            while (len > 0) {
 24.2567 +                int n = read(b, off, len, copy);
 24.2568 +                if (n < 0) {
 24.2569 +                    throw new EOFException();
 24.2570 +                }
 24.2571 +                off += n;
 24.2572 +                len -= n;
 24.2573 +            }
 24.2574 +        }
 24.2575 +
 24.2576 +        public int skipBytes(int n) throws IOException {
 24.2577 +            return din.skipBytes(n);
 24.2578 +        }
 24.2579 +
 24.2580 +        public boolean readBoolean() throws IOException {
 24.2581 +            int v = read();
 24.2582 +            if (v < 0) {
 24.2583 +                throw new EOFException();
 24.2584 +            }
 24.2585 +            return (v != 0);
 24.2586 +        }
 24.2587 +
 24.2588 +        public byte readByte() throws IOException {
 24.2589 +            int v = read();
 24.2590 +            if (v < 0) {
 24.2591 +                throw new EOFException();
 24.2592 +            }
 24.2593 +            return (byte) v;
 24.2594 +        }
 24.2595 +
 24.2596 +        public int readUnsignedByte() throws IOException {
 24.2597 +            int v = read();
 24.2598 +            if (v < 0) {
 24.2599 +                throw new EOFException();
 24.2600 +            }
 24.2601 +            return v;
 24.2602 +        }
 24.2603 +
 24.2604 +        public char readChar() throws IOException {
 24.2605 +            if (!blkmode) {
 24.2606 +                pos = 0;
 24.2607 +                in.readFully(buf, 0, 2);
 24.2608 +            } else if (end - pos < 2) {
 24.2609 +                return din.readChar();
 24.2610 +            }
 24.2611 +            char v = Bits.getChar(buf, pos);
 24.2612 +            pos += 2;
 24.2613 +            return v;
 24.2614 +        }
 24.2615 +
 24.2616 +        public short readShort() throws IOException {
 24.2617 +            if (!blkmode) {
 24.2618 +                pos = 0;
 24.2619 +                in.readFully(buf, 0, 2);
 24.2620 +            } else if (end - pos < 2) {
 24.2621 +                return din.readShort();
 24.2622 +            }
 24.2623 +            short v = Bits.getShort(buf, pos);
 24.2624 +            pos += 2;
 24.2625 +            return v;
 24.2626 +        }
 24.2627 +
 24.2628 +        public int readUnsignedShort() throws IOException {
 24.2629 +            if (!blkmode) {
 24.2630 +                pos = 0;
 24.2631 +                in.readFully(buf, 0, 2);
 24.2632 +            } else if (end - pos < 2) {
 24.2633 +                return din.readUnsignedShort();
 24.2634 +            }
 24.2635 +            int v = Bits.getShort(buf, pos) & 0xFFFF;
 24.2636 +            pos += 2;
 24.2637 +            return v;
 24.2638 +        }
 24.2639 +
 24.2640 +        public int readInt() throws IOException {
 24.2641 +            if (!blkmode) {
 24.2642 +                pos = 0;
 24.2643 +                in.readFully(buf, 0, 4);
 24.2644 +            } else if (end - pos < 4) {
 24.2645 +                return din.readInt();
 24.2646 +            }
 24.2647 +            int v = Bits.getInt(buf, pos);
 24.2648 +            pos += 4;
 24.2649 +            return v;
 24.2650 +        }
 24.2651 +
 24.2652 +        public float readFloat() throws IOException {
 24.2653 +            if (!blkmode) {
 24.2654 +                pos = 0;
 24.2655 +                in.readFully(buf, 0, 4);
 24.2656 +            } else if (end - pos < 4) {
 24.2657 +                return din.readFloat();
 24.2658 +            }
 24.2659 +            float v = Bits.getFloat(buf, pos);
 24.2660 +            pos += 4;
 24.2661 +            return v;
 24.2662 +        }
 24.2663 +
 24.2664 +        public long readLong() throws IOException {
 24.2665 +            if (!blkmode) {
 24.2666 +                pos = 0;
 24.2667 +                in.readFully(buf, 0, 8);
 24.2668 +            } else if (end - pos < 8) {
 24.2669 +                return din.readLong();
 24.2670 +            }
 24.2671 +            long v = Bits.getLong(buf, pos);
 24.2672 +            pos += 8;
 24.2673 +            return v;
 24.2674 +        }
 24.2675 +
 24.2676 +        public double readDouble() throws IOException {
 24.2677 +            if (!blkmode) {
 24.2678 +                pos = 0;
 24.2679 +                in.readFully(buf, 0, 8);
 24.2680 +            } else if (end - pos < 8) {
 24.2681 +                return din.readDouble();
 24.2682 +            }
 24.2683 +            double v = Bits.getDouble(buf, pos);
 24.2684 +            pos += 8;
 24.2685 +            return v;
 24.2686 +        }
 24.2687 +
 24.2688 +        public String readUTF() throws IOException {
 24.2689 +            return readUTFBody(readUnsignedShort());
 24.2690 +        }
 24.2691 +
 24.2692 +        public String readLine() throws IOException {
 24.2693 +            return din.readLine();      // deprecated, not worth optimizing
 24.2694 +        }
 24.2695 +
 24.2696 +        /* -------------- primitive data array input methods --------------- */
 24.2697 +        /*
 24.2698 +         * The following methods read in spans of primitive data values.
 24.2699 +         * Though equivalent to calling the corresponding primitive read
 24.2700 +         * methods repeatedly, these methods are optimized for reading groups
 24.2701 +         * of primitive data values more efficiently.
 24.2702 +         */
 24.2703 +
 24.2704 +        void readBooleans(boolean[] v, int off, int len) throws IOException {
 24.2705 +            int stop, endoff = off + len;
 24.2706 +            while (off < endoff) {
 24.2707 +                if (!blkmode) {
 24.2708 +                    int span = Math.min(endoff - off, MAX_BLOCK_SIZE);
 24.2709 +                    in.readFully(buf, 0, span);
 24.2710 +                    stop = off + span;
 24.2711 +                    pos = 0;
 24.2712 +                } else if (end - pos < 1) {
 24.2713 +                    v[off++] = din.readBoolean();
 24.2714 +                    continue;
 24.2715 +                } else {
 24.2716 +                    stop = Math.min(endoff, off + end - pos);
 24.2717 +                }
 24.2718 +
 24.2719 +                while (off < stop) {
 24.2720 +                    v[off++] = Bits.getBoolean(buf, pos++);
 24.2721 +                }
 24.2722 +            }
 24.2723 +        }
 24.2724 +
 24.2725 +        void readChars(char[] v, int off, int len) throws IOException {
 24.2726 +            int stop, endoff = off + len;
 24.2727 +            while (off < endoff) {
 24.2728 +                if (!blkmode) {
 24.2729 +                    int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
 24.2730 +                    in.readFully(buf, 0, span << 1);
 24.2731 +                    stop = off + span;
 24.2732 +                    pos = 0;
 24.2733 +                } else if (end - pos < 2) {
 24.2734 +                    v[off++] = din.readChar();
 24.2735 +                    continue;
 24.2736 +                } else {
 24.2737 +                    stop = Math.min(endoff, off + ((end - pos) >> 1));
 24.2738 +                }
 24.2739 +
 24.2740 +                while (off < stop) {
 24.2741 +                    v[off++] = Bits.getChar(buf, pos);
 24.2742 +                    pos += 2;
 24.2743 +                }
 24.2744 +            }
 24.2745 +        }
 24.2746 +
 24.2747 +        void readShorts(short[] v, int off, int len) throws IOException {
 24.2748 +            int stop, endoff = off + len;
 24.2749 +            while (off < endoff) {
 24.2750 +                if (!blkmode) {
 24.2751 +                    int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
 24.2752 +                    in.readFully(buf, 0, span << 1);
 24.2753 +                    stop = off + span;
 24.2754 +                    pos = 0;
 24.2755 +                } else if (end - pos < 2) {
 24.2756 +                    v[off++] = din.readShort();
 24.2757 +                    continue;
 24.2758 +                } else {
 24.2759 +                    stop = Math.min(endoff, off + ((end - pos) >> 1));
 24.2760 +                }
 24.2761 +
 24.2762 +                while (off < stop) {
 24.2763 +                    v[off++] = Bits.getShort(buf, pos);
 24.2764 +                    pos += 2;
 24.2765 +                }
 24.2766 +            }
 24.2767 +        }
 24.2768 +
 24.2769 +        void readInts(int[] v, int off, int len) throws IOException {
 24.2770 +            int stop, endoff = off + len;
 24.2771 +            while (off < endoff) {
 24.2772 +                if (!blkmode) {
 24.2773 +                    int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
 24.2774 +                    in.readFully(buf, 0, span << 2);
 24.2775 +                    stop = off + span;
 24.2776 +                    pos = 0;
 24.2777 +                } else if (end - pos < 4) {
 24.2778 +                    v[off++] = din.readInt();
 24.2779 +                    continue;
 24.2780 +                } else {
 24.2781 +                    stop = Math.min(endoff, off + ((end - pos) >> 2));
 24.2782 +                }
 24.2783 +
 24.2784 +                while (off < stop) {
 24.2785 +                    v[off++] = Bits.getInt(buf, pos);
 24.2786 +                    pos += 4;
 24.2787 +                }
 24.2788 +            }
 24.2789 +        }
 24.2790 +
 24.2791 +        void readFloats(float[] v, int off, int len) throws IOException {
 24.2792 +            int span, endoff = off + len;
 24.2793 +            while (off < endoff) {
 24.2794 +                if (!blkmode) {
 24.2795 +                    span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
 24.2796 +                    in.readFully(buf, 0, span << 2);
 24.2797 +                    pos = 0;
 24.2798 +                } else if (end - pos < 4) {
 24.2799 +                    v[off++] = din.readFloat();
 24.2800 +                    continue;
 24.2801 +                } else {
 24.2802 +                    span = Math.min(endoff - off, ((end - pos) >> 2));
 24.2803 +                }
 24.2804 +
 24.2805 +                bytesToFloats(buf, pos, v, off, span);
 24.2806 +                off += span;
 24.2807 +                pos += span << 2;
 24.2808 +            }
 24.2809 +        }
 24.2810 +
 24.2811 +        void readLongs(long[] v, int off, int len) throws IOException {
 24.2812 +            int stop, endoff = off + len;
 24.2813 +            while (off < endoff) {
 24.2814 +                if (!blkmode) {
 24.2815 +                    int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
 24.2816 +                    in.readFully(buf, 0, span << 3);
 24.2817 +                    stop = off + span;
 24.2818 +                    pos = 0;
 24.2819 +                } else if (end - pos < 8) {
 24.2820 +                    v[off++] = din.readLong();
 24.2821 +                    continue;
 24.2822 +                } else {
 24.2823 +                    stop = Math.min(endoff, off + ((end - pos) >> 3));
 24.2824 +                }
 24.2825 +
 24.2826 +                while (off < stop) {
 24.2827 +                    v[off++] = Bits.getLong(buf, pos);
 24.2828 +                    pos += 8;
 24.2829 +                }
 24.2830 +            }
 24.2831 +        }
 24.2832 +
 24.2833 +        void readDoubles(double[] v, int off, int len) throws IOException {
 24.2834 +            int span, endoff = off + len;
 24.2835 +            while (off < endoff) {
 24.2836 +                if (!blkmode) {
 24.2837 +                    span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
 24.2838 +                    in.readFully(buf, 0, span << 3);
 24.2839 +                    pos = 0;
 24.2840 +                } else if (end - pos < 8) {
 24.2841 +                    v[off++] = din.readDouble();
 24.2842 +                    continue;
 24.2843 +                } else {
 24.2844 +                    span = Math.min(endoff - off, ((end - pos) >> 3));
 24.2845 +                }
 24.2846 +
 24.2847 +                bytesToDoubles(buf, pos, v, off, span);
 24.2848 +                off += span;
 24.2849 +                pos += span << 3;
 24.2850 +            }
 24.2851 +        }
 24.2852 +
 24.2853 +        /**
 24.2854 +         * Reads in string written in "long" UTF format.  "Long" UTF format is
 24.2855 +         * identical to standard UTF, except that it uses an 8 byte header
 24.2856 +         * (instead of the standard 2 bytes) to convey the UTF encoding length.
 24.2857 +         */
 24.2858 +        String readLongUTF() throws IOException {
 24.2859 +            return readUTFBody(readLong());
 24.2860 +        }
 24.2861 +
 24.2862 +        /**
 24.2863 +         * Reads in the "body" (i.e., the UTF representation minus the 2-byte
 24.2864 +         * or 8-byte length header) of a UTF encoding, which occupies the next
 24.2865 +         * utflen bytes.
 24.2866 +         */
 24.2867 +        private String readUTFBody(long utflen) throws IOException {
 24.2868 +            StringBuilder sbuf = new StringBuilder();
 24.2869 +            if (!blkmode) {
 24.2870 +                end = pos = 0;
 24.2871 +            }
 24.2872 +
 24.2873 +            while (utflen > 0) {
 24.2874 +                int avail = end - pos;
 24.2875 +                if (avail >= 3 || (long) avail == utflen) {
 24.2876 +                    utflen -= readUTFSpan(sbuf, utflen);
 24.2877 +                } else {
 24.2878 +                    if (blkmode) {
 24.2879 +                        // near block boundary, read one byte at a time
 24.2880 +                        utflen -= readUTFChar(sbuf, utflen);
 24.2881 +                    } else {
 24.2882 +                        // shift and refill buffer manually
 24.2883 +                        if (avail > 0) {
 24.2884 +                            System.arraycopy(buf, pos, buf, 0, avail);
 24.2885 +                        }
 24.2886 +                        pos = 0;
 24.2887 +                        end = (int) Math.min(MAX_BLOCK_SIZE, utflen);
 24.2888 +                        in.readFully(buf, avail, end - avail);
 24.2889 +                    }
 24.2890 +                }
 24.2891 +            }
 24.2892 +
 24.2893 +            return sbuf.toString();
 24.2894 +        }
 24.2895 +
 24.2896 +        /**
 24.2897 +         * Reads span of UTF-encoded characters out of internal buffer
 24.2898 +         * (starting at offset pos and ending at or before offset end),
 24.2899 +         * consuming no more than utflen bytes.  Appends read characters to
 24.2900 +         * sbuf.  Returns the number of bytes consumed.
 24.2901 +         */
 24.2902 +        private long readUTFSpan(StringBuilder sbuf, long utflen)
 24.2903 +            throws IOException
 24.2904 +        {
 24.2905 +            int cpos = 0;
 24.2906 +            int start = pos;
 24.2907 +            int avail = Math.min(end - pos, CHAR_BUF_SIZE);
 24.2908 +            // stop short of last char unless all of utf bytes in buffer
 24.2909 +            int stop = pos + ((utflen > avail) ? avail - 2 : (int) utflen);
 24.2910 +            boolean outOfBounds = false;
 24.2911 +
 24.2912 +            try {
 24.2913 +                while (pos < stop) {
 24.2914 +                    int b1, b2, b3;
 24.2915 +                    b1 = buf[pos++] & 0xFF;
 24.2916 +                    switch (b1 >> 4) {
 24.2917 +                        case 0:
 24.2918 +                        case 1:
 24.2919 +                        case 2:
 24.2920 +                        case 3:
 24.2921 +                        case 4:
 24.2922 +                        case 5:
 24.2923 +                        case 6:
 24.2924 +                        case 7:   // 1 byte format: 0xxxxxxx
 24.2925 +                            cbuf[cpos++] = (char) b1;
 24.2926 +                            break;
 24.2927 +
 24.2928 +                        case 12:
 24.2929 +                        case 13:  // 2 byte format: 110xxxxx 10xxxxxx
 24.2930 +                            b2 = buf[pos++];
 24.2931 +                            if ((b2 & 0xC0) != 0x80) {
 24.2932 +                                throw new UTFDataFormatException();
 24.2933 +                            }
 24.2934 +                            cbuf[cpos++] = (char) (((b1 & 0x1F) << 6) |
 24.2935 +                                                   ((b2 & 0x3F) << 0));
 24.2936 +                            break;
 24.2937 +
 24.2938 +                        case 14:  // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
 24.2939 +                            b3 = buf[pos + 1];
 24.2940 +                            b2 = buf[pos + 0];
 24.2941 +                            pos += 2;
 24.2942 +                            if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
 24.2943 +                                throw new UTFDataFormatException();
 24.2944 +                            }
 24.2945 +                            cbuf[cpos++] = (char) (((b1 & 0x0F) << 12) |
 24.2946 +                                                   ((b2 & 0x3F) << 6) |
 24.2947 +                                                   ((b3 & 0x3F) << 0));
 24.2948 +                            break;
 24.2949 +
 24.2950 +                        default:  // 10xx xxxx, 1111 xxxx
 24.2951 +                            throw new UTFDataFormatException();
 24.2952 +                    }
 24.2953 +                }
 24.2954 +            } catch (ArrayIndexOutOfBoundsException ex) {
 24.2955 +                outOfBounds = true;
 24.2956 +            } finally {
 24.2957 +                if (outOfBounds || (pos - start) > utflen) {
 24.2958 +                    /*
 24.2959 +                     * Fix for 4450867: if a malformed utf char causes the
 24.2960 +                     * conversion loop to scan past the expected end of the utf
 24.2961 +                     * string, only consume the expected number of utf bytes.
 24.2962 +                     */
 24.2963 +                    pos = start + (int) utflen;
 24.2964 +                    throw new UTFDataFormatException();
 24.2965 +                }
 24.2966 +            }
 24.2967 +
 24.2968 +            sbuf.append(cbuf, 0, cpos);
 24.2969 +            return pos - start;
 24.2970 +        }
 24.2971 +
 24.2972 +        /**
 24.2973 +         * Reads in single UTF-encoded character one byte at a time, appends
 24.2974 +         * the character to sbuf, and returns the number of bytes consumed.
 24.2975 +         * This method is used when reading in UTF strings written in block
 24.2976 +         * data mode to handle UTF-encoded characters which (potentially)
 24.2977 +         * straddle block-data boundaries.
 24.2978 +         */
 24.2979 +        private int readUTFChar(StringBuilder sbuf, long utflen)
 24.2980 +            throws IOException
 24.2981 +        {
 24.2982 +            int b1, b2, b3;
 24.2983 +            b1 = readByte() & 0xFF;
 24.2984 +            switch (b1 >> 4) {
 24.2985 +                case 0:
 24.2986 +                case 1:
 24.2987 +                case 2:
 24.2988 +                case 3:
 24.2989 +                case 4:
 24.2990 +                case 5:
 24.2991 +                case 6:
 24.2992 +                case 7:     // 1 byte format: 0xxxxxxx
 24.2993 +                    sbuf.append((char) b1);
 24.2994 +                    return 1;
 24.2995 +
 24.2996 +                case 12:
 24.2997 +                case 13:    // 2 byte format: 110xxxxx 10xxxxxx
 24.2998 +                    if (utflen < 2) {
 24.2999 +                        throw new UTFDataFormatException();
 24.3000 +                    }
 24.3001 +                    b2 = readByte();
 24.3002 +                    if ((b2 & 0xC0) != 0x80) {
 24.3003 +                        throw new UTFDataFormatException();
 24.3004 +                    }
 24.3005 +                    sbuf.append((char) (((b1 & 0x1F) << 6) |
 24.3006 +                                        ((b2 & 0x3F) << 0)));
 24.3007 +                    return 2;
 24.3008 +
 24.3009 +                case 14:    // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
 24.3010 +                    if (utflen < 3) {
 24.3011 +                        if (utflen == 2) {
 24.3012 +                            readByte();         // consume remaining byte
 24.3013 +                        }
 24.3014 +                        throw new UTFDataFormatException();
 24.3015 +                    }
 24.3016 +                    b2 = readByte();
 24.3017 +                    b3 = readByte();
 24.3018 +                    if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
 24.3019 +                        throw new UTFDataFormatException();
 24.3020 +                    }
 24.3021 +                    sbuf.append((char) (((b1 & 0x0F) << 12) |
 24.3022 +                                        ((b2 & 0x3F) << 6) |
 24.3023 +                                        ((b3 & 0x3F) << 0)));
 24.3024 +                    return 3;
 24.3025 +
 24.3026 +                default:   // 10xx xxxx, 1111 xxxx
 24.3027 +                    throw new UTFDataFormatException();
 24.3028 +            }
 24.3029 +        }
 24.3030 +    }
 24.3031 +
 24.3032 +    /**
 24.3033 +     * Unsynchronized table which tracks wire handle to object mappings, as
 24.3034 +     * well as ClassNotFoundExceptions associated with deserialized objects.
 24.3035 +     * This class implements an exception-propagation algorithm for
 24.3036 +     * determining which objects should have ClassNotFoundExceptions associated
 24.3037 +     * with them, taking into account cycles and discontinuities (e.g., skipped
 24.3038 +     * fields) in the object graph.
 24.3039 +     *
 24.3040 +     * <p>General use of the table is as follows: during deserialization, a
 24.3041 +     * given object is first assigned a handle by calling the assign method.
 24.3042 +     * This method leaves the assigned handle in an "open" state, wherein
 24.3043 +     * dependencies on the exception status of other handles can be registered
 24.3044 +     * by calling the markDependency method, or an exception can be directly
 24.3045 +     * associated with the handle by calling markException.  When a handle is
 24.3046 +     * tagged with an exception, the HandleTable assumes responsibility for
 24.3047 +     * propagating the exception to any other objects which depend
 24.3048 +     * (transitively) on the exception-tagged object.
 24.3049 +     *
 24.3050 +     * <p>Once all exception information/dependencies for the handle have been
 24.3051 +     * registered, the handle should be "closed" by calling the finish method
 24.3052 +     * on it.  The act of finishing a handle allows the exception propagation
 24.3053 +     * algorithm to aggressively prune dependency links, lessening the
 24.3054 +     * performance/memory impact of exception tracking.
 24.3055 +     *
 24.3056 +     * <p>Note that the exception propagation algorithm used depends on handles
 24.3057 +     * being assigned/finished in LIFO order; however, for simplicity as well
 24.3058 +     * as memory conservation, it does not enforce this constraint.
 24.3059 +     */
 24.3060 +    // REMIND: add full description of exception propagation algorithm?
 24.3061 +    private static class HandleTable {
 24.3062 +
 24.3063 +        /* status codes indicating whether object has associated exception */
 24.3064 +        private static final byte STATUS_OK = 1;
 24.3065 +        private static final byte STATUS_UNKNOWN = 2;
 24.3066 +        private static final byte STATUS_EXCEPTION = 3;
 24.3067 +
 24.3068 +        /** array mapping handle -> object status */
 24.3069 +        byte[] status;
 24.3070 +        /** array mapping handle -> object/exception (depending on status) */
 24.3071 +        Object[] entries;
 24.3072 +        /** array mapping handle -> list of dependent handles (if any) */
 24.3073 +        HandleList[] deps;
 24.3074 +        /** lowest unresolved dependency */
 24.3075 +        int lowDep = -1;
 24.3076 +        /** number of handles in table */
 24.3077 +        int size = 0;
 24.3078 +
 24.3079 +        /**
 24.3080 +         * Creates handle table with the given initial capacity.
 24.3081 +         */
 24.3082 +        HandleTable(int initialCapacity) {
 24.3083 +            status = new byte[initialCapacity];
 24.3084 +            entries = new Object[initialCapacity];
 24.3085 +            deps = new HandleList[initialCapacity];
 24.3086 +        }
 24.3087 +
 24.3088 +        /**
 24.3089 +         * Assigns next available handle to given object, and returns assigned
 24.3090 +         * handle.  Once object has been completely deserialized (and all
 24.3091 +         * dependencies on other objects identified), the handle should be
 24.3092 +         * "closed" by passing it to finish().
 24.3093 +         */
 24.3094 +        int assign(Object obj) {
 24.3095 +            if (size >= entries.length) {
 24.3096 +                grow();
 24.3097 +            }
 24.3098 +            status[size] = STATUS_UNKNOWN;
 24.3099 +            entries[size] = obj;
 24.3100 +            return size++;
 24.3101 +        }
 24.3102 +
 24.3103 +        /**
 24.3104 +         * Registers a dependency (in exception status) of one handle on
 24.3105 +         * another.  The dependent handle must be "open" (i.e., assigned, but
 24.3106 +         * not finished yet).  No action is taken if either dependent or target
 24.3107 +         * handle is NULL_HANDLE.
 24.3108 +         */
 24.3109 +        void markDependency(int dependent, int target) {
 24.3110 +            if (dependent == NULL_HANDLE || target == NULL_HANDLE) {
 24.3111 +                return;
 24.3112 +            }
 24.3113 +            switch (status[dependent]) {
 24.3114 +
 24.3115 +                case STATUS_UNKNOWN:
 24.3116 +                    switch (status[target]) {
 24.3117 +                        case STATUS_OK:
 24.3118 +                            // ignore dependencies on objs with no exception
 24.3119 +                            break;
 24.3120 +
 24.3121 +                        case STATUS_EXCEPTION:
 24.3122 +                            // eagerly propagate exception
 24.3123 +                            markException(dependent,
 24.3124 +                                (ClassNotFoundException) entries[target]);
 24.3125 +                            break;
 24.3126 +
 24.3127 +                        case STATUS_UNKNOWN:
 24.3128 +                            // add to dependency list of target
 24.3129 +                            if (deps[target] == null) {
 24.3130 +                                deps[target] = new HandleList();
 24.3131 +                            }
 24.3132 +                            deps[target].add(dependent);
 24.3133 +
 24.3134 +                            // remember lowest unresolved target seen
 24.3135 +                            if (lowDep < 0 || lowDep > target) {
 24.3136 +                                lowDep = target;
 24.3137 +                            }
 24.3138 +                            break;
 24.3139 +
 24.3140 +                        default:
 24.3141 +                            throw new InternalError();
 24.3142 +                    }
 24.3143 +                    break;
 24.3144 +
 24.3145 +                case STATUS_EXCEPTION:
 24.3146 +                    break;
 24.3147 +
 24.3148 +                default:
 24.3149 +                    throw new InternalError();
 24.3150 +            }
 24.3151 +        }
 24.3152 +
 24.3153 +        /**
 24.3154 +         * Associates a ClassNotFoundException (if one not already associated)
 24.3155 +         * with the currently active handle and propagates it to other
 24.3156 +         * referencing objects as appropriate.  The specified handle must be
 24.3157 +         * "open" (i.e., assigned, but not finished yet).
 24.3158 +         */
 24.3159 +        void markException(int handle, ClassNotFoundException ex) {
 24.3160 +            switch (status[handle]) {
 24.3161 +                case STATUS_UNKNOWN:
 24.3162 +                    status[handle] = STATUS_EXCEPTION;
 24.3163 +                    entries[handle] = ex;
 24.3164 +
 24.3165 +                    // propagate exception to dependents
 24.3166 +                    HandleList dlist = deps[handle];
 24.3167 +                    if (dlist != null) {
 24.3168 +                        int ndeps = dlist.size();
 24.3169 +                        for (int i = 0; i < ndeps; i++) {
 24.3170 +                            markException(dlist.get(i), ex);
 24.3171 +                        }
 24.3172 +                        deps[handle] = null;
 24.3173 +                    }
 24.3174 +                    break;
 24.3175 +
 24.3176 +                case STATUS_EXCEPTION:
 24.3177 +                    break;
 24.3178 +
 24.3179 +                default:
 24.3180 +                    throw new InternalError();
 24.3181 +            }
 24.3182 +        }
 24.3183 +
 24.3184 +        /**
 24.3185 +         * Marks given handle as finished, meaning that no new dependencies
 24.3186 +         * will be marked for handle.  Calls to the assign and finish methods
 24.3187 +         * must occur in LIFO order.
 24.3188 +         */
 24.3189 +        void finish(int handle) {
 24.3190 +            int end;
 24.3191 +            if (lowDep < 0) {
 24.3192 +                // no pending unknowns, only resolve current handle
 24.3193 +                end = handle + 1;
 24.3194 +            } else if (lowDep >= handle) {
 24.3195 +                // pending unknowns now clearable, resolve all upward handles
 24.3196 +                end = size;
 24.3197 +                lowDep = -1;
 24.3198 +            } else {
 24.3199 +                // unresolved backrefs present, can't resolve anything yet
 24.3200 +                return;
 24.3201 +            }
 24.3202 +
 24.3203 +            // change STATUS_UNKNOWN -> STATUS_OK in selected span of handles
 24.3204 +            for (int i = handle; i < end; i++) {
 24.3205 +                switch (status[i]) {
 24.3206 +                    case STATUS_UNKNOWN:
 24.3207 +                        status[i] = STATUS_OK;
 24.3208 +                        deps[i] = null;
 24.3209 +                        break;
 24.3210 +
 24.3211 +                    case STATUS_OK:
 24.3212 +                    case STATUS_EXCEPTION:
 24.3213 +                        break;
 24.3214 +
 24.3215 +                    default:
 24.3216 +                        throw new InternalError();
 24.3217 +                }
 24.3218 +            }
 24.3219 +        }
 24.3220 +
 24.3221 +        /**
 24.3222 +         * Assigns a new object to the given handle.  The object previously
 24.3223 +         * associated with the handle is forgotten.  This method has no effect
 24.3224 +         * if the given handle already has an exception associated with it.
 24.3225 +         * This method may be called at any time after the handle is assigned.
 24.3226 +         */
 24.3227 +        void setObject(int handle, Object obj) {
 24.3228 +            switch (status[handle]) {
 24.3229 +                case STATUS_UNKNOWN:
 24.3230 +                case STATUS_OK:
 24.3231 +                    entries[handle] = obj;
 24.3232 +                    break;
 24.3233 +
 24.3234 +                case STATUS_EXCEPTION:
 24.3235 +                    break;
 24.3236 +
 24.3237 +                default:
 24.3238 +                    throw new InternalError();
 24.3239 +            }
 24.3240 +        }
 24.3241 +
 24.3242 +        /**
 24.3243 +         * Looks up and returns object associated with the given handle.
 24.3244 +         * Returns null if the given handle is NULL_HANDLE, or if it has an
 24.3245 +         * associated ClassNotFoundException.
 24.3246 +         */
 24.3247 +        Object lookupObject(int handle) {
 24.3248 +            return (handle != NULL_HANDLE &&
 24.3249 +                    status[handle] != STATUS_EXCEPTION) ?
 24.3250 +                entries[handle] : null;
 24.3251 +        }
 24.3252 +
 24.3253 +        /**
 24.3254 +         * Looks up and returns ClassNotFoundException associated with the
 24.3255 +         * given handle.  Returns null if the given handle is NULL_HANDLE, or
 24.3256 +         * if there is no ClassNotFoundException associated with the handle.
 24.3257 +         */
 24.3258 +        ClassNotFoundException lookupException(int handle) {
 24.3259 +            return (handle != NULL_HANDLE &&
 24.3260 +                    status[handle] == STATUS_EXCEPTION) ?
 24.3261 +                (ClassNotFoundException) entries[handle] : null;
 24.3262 +        }
 24.3263 +
 24.3264 +        /**
 24.3265 +         * Resets table to its initial state.
 24.3266 +         */
 24.3267 +        void clear() {
 24.3268 +            Arrays.fill(status, 0, size, (byte) 0);
 24.3269 +            Arrays.fill(entries, 0, size, null);
 24.3270 +            Arrays.fill(deps, 0, size, null);
 24.3271 +            lowDep = -1;
 24.3272 +            size = 0;
 24.3273 +        }
 24.3274 +
 24.3275 +        /**
 24.3276 +         * Returns number of handles registered in table.
 24.3277 +         */
 24.3278 +        int size() {
 24.3279 +            return size;
 24.3280 +        }
 24.3281 +
 24.3282 +        /**
 24.3283 +         * Expands capacity of internal arrays.
 24.3284 +         */
 24.3285 +        private void grow() {
 24.3286 +            int newCapacity = (entries.length << 1) + 1;
 24.3287 +
 24.3288 +            byte[] newStatus = new byte[newCapacity];
 24.3289 +            Object[] newEntries = new Object[newCapacity];
 24.3290 +            HandleList[] newDeps = new HandleList[newCapacity];
 24.3291 +
 24.3292 +            System.arraycopy(status, 0, newStatus, 0, size);
 24.3293 +            System.arraycopy(entries, 0, newEntries, 0, size);
 24.3294 +            System.arraycopy(deps, 0, newDeps, 0, size);
 24.3295 +
 24.3296 +            status = newStatus;
 24.3297 +            entries = newEntries;
 24.3298 +            deps = newDeps;
 24.3299 +        }
 24.3300 +
 24.3301 +        /**
 24.3302 +         * Simple growable list of (integer) handles.
 24.3303 +         */
 24.3304 +        private static class HandleList {
 24.3305 +            private int[] list = new int[4];
 24.3306 +            private int size = 0;
 24.3307 +
 24.3308 +            public HandleList() {
 24.3309 +            }
 24.3310 +
 24.3311 +            public void add(int handle) {
 24.3312 +                if (size >= list.length) {
 24.3313 +                    int[] newList = new int[list.length << 1];
 24.3314 +                    System.arraycopy(list, 0, newList, 0, list.length);
 24.3315 +                    list = newList;
 24.3316 +                }
 24.3317 +                list[size++] = handle;
 24.3318 +            }
 24.3319 +
 24.3320 +            public int get(int index) {
 24.3321 +                if (index >= size) {
 24.3322 +                    throw new ArrayIndexOutOfBoundsException();
 24.3323 +                }
 24.3324 +                return list[index];
 24.3325 +            }
 24.3326 +
 24.3327 +            public int size() {
 24.3328 +                return size;
 24.3329 +            }
 24.3330 +        }
 24.3331 +    }
 24.3332 +
 24.3333 +    /**
 24.3334 +     * Method for cloning arrays in case of using unsharing reading
 24.3335 +     */
 24.3336 +    private static Object cloneArray(Object array) {
 24.3337 +        if (array instanceof Object[]) {
 24.3338 +            return ((Object[]) array).clone();
 24.3339 +        } else if (array instanceof boolean[]) {
 24.3340 +            return ((boolean[]) array).clone();
 24.3341 +        } else if (array instanceof byte[]) {
 24.3342 +            return ((byte[]) array).clone();
 24.3343 +        } else if (array instanceof char[]) {
 24.3344 +            return ((char[]) array).clone();
 24.3345 +        } else if (array instanceof double[]) {
 24.3346 +            return ((double[]) array).clone();
 24.3347 +        } else if (array instanceof float[]) {
 24.3348 +            return ((float[]) array).clone();
 24.3349 +        } else if (array instanceof int[]) {
 24.3350 +            return ((int[]) array).clone();
 24.3351 +        } else if (array instanceof long[]) {
 24.3352 +            return ((long[]) array).clone();
 24.3353 +        } else if (array instanceof short[]) {
 24.3354 +            return ((short[]) array).clone();
 24.3355 +        } else {
 24.3356 +            throw new AssertionError();
 24.3357 +        }
 24.3358 +    }
 24.3359 +
 24.3360 +}
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/emul/compact/src/main/java/java/io/ObjectInputValidation.java	Mon Feb 04 09:37:56 2013 +0100
    25.3 @@ -0,0 +1,45 @@
    25.4 +/*
    25.5 + * Copyright (c) 1996, 1999, 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 +/**
   25.32 + * Callback interface to allow validation of objects within a graph.
   25.33 + * Allows an object to be called when a complete graph of objects has
   25.34 + * been deserialized.
   25.35 + *
   25.36 + * @author  unascribed
   25.37 + * @see     ObjectInputStream
   25.38 + * @see     ObjectInputStream#registerValidation(java.io.ObjectInputValidation, int)
   25.39 + * @since   JDK1.1
   25.40 + */
   25.41 +public interface ObjectInputValidation {
   25.42 +    /**
   25.43 +     * Validates the object.
   25.44 +     *
   25.45 +     * @exception InvalidObjectException If the object cannot validate itself.
   25.46 +     */
   25.47 +    public void validateObject() throws InvalidObjectException;
   25.48 +}
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/emul/compact/src/main/java/java/io/ObjectOutput.java	Mon Feb 04 09:37:56 2013 +0100
    26.3 @@ -0,0 +1,90 @@
    26.4 +/*
    26.5 + * Copyright (c) 1996, 2010, 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 +/**
   26.32 + * ObjectOutput extends the DataOutput interface to include writing of objects.
   26.33 + * DataOutput includes methods for output of primitive types, ObjectOutput
   26.34 + * extends that interface to include objects, arrays, and Strings.
   26.35 + *
   26.36 + * @author  unascribed
   26.37 + * @see java.io.InputStream
   26.38 + * @see java.io.ObjectOutputStream
   26.39 + * @see java.io.ObjectInputStream
   26.40 + * @since   JDK1.1
   26.41 + */
   26.42 +public interface ObjectOutput extends DataOutput, AutoCloseable {
   26.43 +    /**
   26.44 +     * Write an object to the underlying storage or stream.  The
   26.45 +     * class that implements this interface defines how the object is
   26.46 +     * written.
   26.47 +     *
   26.48 +     * @param obj the object to be written
   26.49 +     * @exception IOException Any of the usual Input/Output related exceptions.
   26.50 +     */
   26.51 +    public void writeObject(Object obj)
   26.52 +      throws IOException;
   26.53 +
   26.54 +    /**
   26.55 +     * Writes a byte. This method will block until the byte is actually
   26.56 +     * written.
   26.57 +     * @param b the byte
   26.58 +     * @exception IOException If an I/O error has occurred.
   26.59 +     */
   26.60 +    public void write(int b) throws IOException;
   26.61 +
   26.62 +    /**
   26.63 +     * Writes an array of bytes. This method will block until the bytes
   26.64 +     * are actually written.
   26.65 +     * @param b the data to be written
   26.66 +     * @exception IOException If an I/O error has occurred.
   26.67 +     */
   26.68 +    public void write(byte b[]) throws IOException;
   26.69 +
   26.70 +    /**
   26.71 +     * Writes a sub array of bytes.
   26.72 +     * @param b the data to be written
   26.73 +     * @param off       the start offset in the data
   26.74 +     * @param len       the number of bytes that are written
   26.75 +     * @exception IOException If an I/O error has occurred.
   26.76 +     */
   26.77 +    public void write(byte b[], int off, int len) throws IOException;
   26.78 +
   26.79 +    /**
   26.80 +     * Flushes the stream. This will write any buffered
   26.81 +     * output bytes.
   26.82 +     * @exception IOException If an I/O error has occurred.
   26.83 +     */
   26.84 +    public void flush() throws IOException;
   26.85 +
   26.86 +    /**
   26.87 +     * Closes the stream. This method must be called
   26.88 +     * to release any resources associated with the
   26.89 +     * stream.
   26.90 +     * @exception IOException If an I/O error has occurred.
   26.91 +     */
   26.92 +    public void close() throws IOException;
   26.93 +}
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/emul/compact/src/main/java/java/io/ObjectOutputStream.java	Mon Feb 04 09:37:56 2013 +0100
    27.3 @@ -0,0 +1,2369 @@
    27.4 +/*
    27.5 + * Copyright (c) 1996, 2010, 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 +import java.util.ArrayList;
   27.32 +import java.util.Arrays;
   27.33 +import java.util.List;
   27.34 +import org.apidesign.bck2brwsr.emul.lang.System;
   27.35 +
   27.36 +/**
   27.37 + * An ObjectOutputStream writes primitive data types and graphs of Java objects
   27.38 + * to an OutputStream.  The objects can be read (reconstituted) using an
   27.39 + * ObjectInputStream.  Persistent storage of objects can be accomplished by
   27.40 + * using a file for the stream.  If the stream is a network socket stream, the
   27.41 + * objects can be reconstituted on another host or in another process.
   27.42 + *
   27.43 + * <p>Only objects that support the java.io.Serializable interface can be
   27.44 + * written to streams.  The class of each serializable object is encoded
   27.45 + * including the class name and signature of the class, the values of the
   27.46 + * object's fields and arrays, and the closure of any other objects referenced
   27.47 + * from the initial objects.
   27.48 + *
   27.49 + * <p>The method writeObject is used to write an object to the stream.  Any
   27.50 + * object, including Strings and arrays, is written with writeObject. Multiple
   27.51 + * objects or primitives can be written to the stream.  The objects must be
   27.52 + * read back from the corresponding ObjectInputstream with the same types and
   27.53 + * in the same order as they were written.
   27.54 + *
   27.55 + * <p>Primitive data types can also be written to the stream using the
   27.56 + * appropriate methods from DataOutput. Strings can also be written using the
   27.57 + * writeUTF method.
   27.58 + *
   27.59 + * <p>The default serialization mechanism for an object writes the class of the
   27.60 + * object, the class signature, and the values of all non-transient and
   27.61 + * non-static fields.  References to other objects (except in transient or
   27.62 + * static fields) cause those objects to be written also. Multiple references
   27.63 + * to a single object are encoded using a reference sharing mechanism so that
   27.64 + * graphs of objects can be restored to the same shape as when the original was
   27.65 + * written.
   27.66 + *
   27.67 + * <p>For example to write an object that can be read by the example in
   27.68 + * ObjectInputStream:
   27.69 + * <br>
   27.70 + * <pre>
   27.71 + *      FileOutputStream fos = new FileOutputStream("t.tmp");
   27.72 + *      ObjectOutputStream oos = new ObjectOutputStream(fos);
   27.73 + *
   27.74 + *      oos.writeInt(12345);
   27.75 + *      oos.writeObject("Today");
   27.76 + *      oos.writeObject(new Date());
   27.77 + *
   27.78 + *      oos.close();
   27.79 + * </pre>
   27.80 + *
   27.81 + * <p>Classes that require special handling during the serialization and
   27.82 + * deserialization process must implement special methods with these exact
   27.83 + * signatures:
   27.84 + * <br>
   27.85 + * <pre>
   27.86 + * private void readObject(java.io.ObjectInputStream stream)
   27.87 + *     throws IOException, ClassNotFoundException;
   27.88 + * private void writeObject(java.io.ObjectOutputStream stream)
   27.89 + *     throws IOException
   27.90 + * private void readObjectNoData()
   27.91 + *     throws ObjectStreamException;
   27.92 + * </pre>
   27.93 + *
   27.94 + * <p>The writeObject method is responsible for writing the state of the object
   27.95 + * for its particular class so that the corresponding readObject method can
   27.96 + * restore it.  The method does not need to concern itself with the state
   27.97 + * belonging to the object's superclasses or subclasses.  State is saved by
   27.98 + * writing the individual fields to the ObjectOutputStream using the
   27.99 + * writeObject method or by using the methods for primitive data types
  27.100 + * supported by DataOutput.
  27.101 + *
  27.102 + * <p>Serialization does not write out the fields of any object that does not
  27.103 + * implement the java.io.Serializable interface.  Subclasses of Objects that
  27.104 + * are not serializable can be serializable. In this case the non-serializable
  27.105 + * class must have a no-arg constructor to allow its fields to be initialized.
  27.106 + * In this case it is the responsibility of the subclass to save and restore
  27.107 + * the state of the non-serializable class. It is frequently the case that the
  27.108 + * fields of that class are accessible (public, package, or protected) or that
  27.109 + * there are get and set methods that can be used to restore the state.
  27.110 + *
  27.111 + * <p>Serialization of an object can be prevented by implementing writeObject
  27.112 + * and readObject methods that throw the NotSerializableException.  The
  27.113 + * exception will be caught by the ObjectOutputStream and abort the
  27.114 + * serialization process.
  27.115 + *
  27.116 + * <p>Implementing the Externalizable interface allows the object to assume
  27.117 + * complete control over the contents and format of the object's serialized
  27.118 + * form.  The methods of the Externalizable interface, writeExternal and
  27.119 + * readExternal, are called to save and restore the objects state.  When
  27.120 + * implemented by a class they can write and read their own state using all of
  27.121 + * the methods of ObjectOutput and ObjectInput.  It is the responsibility of
  27.122 + * the objects to handle any versioning that occurs.
  27.123 + *
  27.124 + * <p>Enum constants are serialized differently than ordinary serializable or
  27.125 + * externalizable objects.  The serialized form of an enum constant consists
  27.126 + * solely of its name; field values of the constant are not transmitted.  To
  27.127 + * serialize an enum constant, ObjectOutputStream writes the string returned by
  27.128 + * the constant's name method.  Like other serializable or externalizable
  27.129 + * objects, enum constants can function as the targets of back references
  27.130 + * appearing subsequently in the serialization stream.  The process by which
  27.131 + * enum constants are serialized cannot be customized; any class-specific
  27.132 + * writeObject and writeReplace methods defined by enum types are ignored
  27.133 + * during serialization.  Similarly, any serialPersistentFields or
  27.134 + * serialVersionUID field declarations are also ignored--all enum types have a
  27.135 + * fixed serialVersionUID of 0L.
  27.136 + *
  27.137 + * <p>Primitive data, excluding serializable fields and externalizable data, is
  27.138 + * written to the ObjectOutputStream in block-data records. A block data record
  27.139 + * is composed of a header and data. The block data header consists of a marker
  27.140 + * and the number of bytes to follow the header.  Consecutive primitive data
  27.141 + * writes are merged into one block-data record.  The blocking factor used for
  27.142 + * a block-data record will be 1024 bytes.  Each block-data record will be
  27.143 + * filled up to 1024 bytes, or be written whenever there is a termination of
  27.144 + * block-data mode.  Calls to the ObjectOutputStream methods writeObject,
  27.145 + * defaultWriteObject and writeFields initially terminate any existing
  27.146 + * block-data record.
  27.147 + *
  27.148 + * @author      Mike Warres
  27.149 + * @author      Roger Riggs
  27.150 + * @see java.io.DataOutput
  27.151 + * @see java.io.ObjectInputStream
  27.152 + * @see java.io.Serializable
  27.153 + * @see java.io.Externalizable
  27.154 + * @see <a href="../../../platform/serialization/spec/output.html">Object Serialization Specification, Section 2, Object Output Classes</a>
  27.155 + * @since       JDK1.1
  27.156 + */
  27.157 +public class ObjectOutputStream
  27.158 +    extends OutputStream implements ObjectOutput, ObjectStreamConstants
  27.159 +{
  27.160 +    /** filter stream for handling block data conversion */
  27.161 +    private final BlockDataOutputStream bout;
  27.162 +    /** obj -> wire handle map */
  27.163 +    private final HandleTable handles;
  27.164 +    /** obj -> replacement obj map */
  27.165 +    private final ReplaceTable subs;
  27.166 +    /** stream protocol version */
  27.167 +    private int protocol = PROTOCOL_VERSION_2;
  27.168 +    /** recursion depth */
  27.169 +    private int depth;
  27.170 +
  27.171 +    /** buffer for writing primitive field values */
  27.172 +    private byte[] primVals;
  27.173 +
  27.174 +    /** if true, invoke writeObjectOverride() instead of writeObject() */
  27.175 +    private final boolean enableOverride;
  27.176 +    /** if true, invoke replaceObject() */
  27.177 +    private boolean enableReplace;
  27.178 +
  27.179 +    // values below valid only during upcalls to writeObject()/writeExternal()
  27.180 +    /**
  27.181 +     * Context during upcalls to class-defined writeObject methods; holds
  27.182 +     * object currently being serialized and descriptor for current class.
  27.183 +     * Null when not during writeObject upcall.
  27.184 +     */
  27.185 +    private Object curContext;
  27.186 +    /** current PutField object */
  27.187 +    private PutFieldImpl curPut;
  27.188 +
  27.189 +    /** custom storage for debug trace info */
  27.190 +    private final DebugTraceInfoStack debugInfoStack;
  27.191 +
  27.192 +    /**
  27.193 +     * value of "sun.io.serialization.extendedDebugInfo" property,
  27.194 +     * as true or false for extended information about exception's place
  27.195 +     */
  27.196 +    private static final boolean extendedDebugInfo = false;
  27.197 +
  27.198 +    /**
  27.199 +     * Creates an ObjectOutputStream that writes to the specified OutputStream.
  27.200 +     * This constructor writes the serialization stream header to the
  27.201 +     * underlying stream; callers may wish to flush the stream immediately to
  27.202 +     * ensure that constructors for receiving ObjectInputStreams will not block
  27.203 +     * when reading the header.
  27.204 +     *
  27.205 +     * <p>If a security manager is installed, this constructor will check for
  27.206 +     * the "enableSubclassImplementation" SerializablePermission when invoked
  27.207 +     * directly or indirectly by the constructor of a subclass which overrides
  27.208 +     * the ObjectOutputStream.putFields or ObjectOutputStream.writeUnshared
  27.209 +     * methods.
  27.210 +     *
  27.211 +     * @param   out output stream to write to
  27.212 +     * @throws  IOException if an I/O error occurs while writing stream header
  27.213 +     * @throws  SecurityException if untrusted subclass illegally overrides
  27.214 +     *          security-sensitive methods
  27.215 +     * @throws  NullPointerException if <code>out</code> is <code>null</code>
  27.216 +     * @since   1.4
  27.217 +     * @see     ObjectOutputStream#ObjectOutputStream()
  27.218 +     * @see     ObjectOutputStream#putFields()
  27.219 +     * @see     ObjectInputStream#ObjectInputStream(InputStream)
  27.220 +     */
  27.221 +    public ObjectOutputStream(OutputStream out) throws IOException {
  27.222 +        verifySubclass();
  27.223 +        bout = new BlockDataOutputStream(out);
  27.224 +        handles = new HandleTable(10, (float) 3.00);
  27.225 +        subs = new ReplaceTable(10, (float) 3.00);
  27.226 +        enableOverride = false;
  27.227 +        writeStreamHeader();
  27.228 +        bout.setBlockDataMode(true);
  27.229 +        if (extendedDebugInfo) {
  27.230 +            debugInfoStack = new DebugTraceInfoStack();
  27.231 +        } else {
  27.232 +            debugInfoStack = null;
  27.233 +        }
  27.234 +    }
  27.235 +
  27.236 +    /**
  27.237 +     * Provide a way for subclasses that are completely reimplementing
  27.238 +     * ObjectOutputStream to not have to allocate private data just used by
  27.239 +     * this implementation of ObjectOutputStream.
  27.240 +     *
  27.241 +     * <p>If there is a security manager installed, this method first calls the
  27.242 +     * security manager's <code>checkPermission</code> method with a
  27.243 +     * <code>SerializablePermission("enableSubclassImplementation")</code>
  27.244 +     * permission to ensure it's ok to enable subclassing.
  27.245 +     *
  27.246 +     * @throws  SecurityException if a security manager exists and its
  27.247 +     *          <code>checkPermission</code> method denies enabling
  27.248 +     *          subclassing.
  27.249 +     * @see SecurityManager#checkPermission
  27.250 +     * @see java.io.SerializablePermission
  27.251 +     */
  27.252 +    protected ObjectOutputStream() throws IOException, SecurityException {
  27.253 +        throw new SecurityException();
  27.254 +    }
  27.255 +
  27.256 +    /**
  27.257 +     * Specify stream protocol version to use when writing the stream.
  27.258 +     *
  27.259 +     * <p>This routine provides a hook to enable the current version of
  27.260 +     * Serialization to write in a format that is backwards compatible to a
  27.261 +     * previous version of the stream format.
  27.262 +     *
  27.263 +     * <p>Every effort will be made to avoid introducing additional
  27.264 +     * backwards incompatibilities; however, sometimes there is no
  27.265 +     * other alternative.
  27.266 +     *
  27.267 +     * @param   version use ProtocolVersion from java.io.ObjectStreamConstants.
  27.268 +     * @throws  IllegalStateException if called after any objects
  27.269 +     *          have been serialized.
  27.270 +     * @throws  IllegalArgumentException if invalid version is passed in.
  27.271 +     * @throws  IOException if I/O errors occur
  27.272 +     * @see java.io.ObjectStreamConstants#PROTOCOL_VERSION_1
  27.273 +     * @see java.io.ObjectStreamConstants#PROTOCOL_VERSION_2
  27.274 +     * @since   1.2
  27.275 +     */
  27.276 +    public void useProtocolVersion(int version) throws IOException {
  27.277 +        if (handles.size() != 0) {
  27.278 +            // REMIND: implement better check for pristine stream?
  27.279 +            throw new IllegalStateException("stream non-empty");
  27.280 +        }
  27.281 +        switch (version) {
  27.282 +            case PROTOCOL_VERSION_1:
  27.283 +            case PROTOCOL_VERSION_2:
  27.284 +                protocol = version;
  27.285 +                break;
  27.286 +
  27.287 +            default:
  27.288 +                throw new IllegalArgumentException(
  27.289 +                    "unknown version: " + version);
  27.290 +        }
  27.291 +    }
  27.292 +
  27.293 +    /**
  27.294 +     * Write the specified object to the ObjectOutputStream.  The class of the
  27.295 +     * object, the signature of the class, and the values of the non-transient
  27.296 +     * and non-static fields of the class and all of its supertypes are
  27.297 +     * written.  Default serialization for a class can be overridden using the
  27.298 +     * writeObject and the readObject methods.  Objects referenced by this
  27.299 +     * object are written transitively so that a complete equivalent graph of
  27.300 +     * objects can be reconstructed by an ObjectInputStream.
  27.301 +     *
  27.302 +     * <p>Exceptions are thrown for problems with the OutputStream and for
  27.303 +     * classes that should not be serialized.  All exceptions are fatal to the
  27.304 +     * OutputStream, which is left in an indeterminate state, and it is up to
  27.305 +     * the caller to ignore or recover the stream state.
  27.306 +     *
  27.307 +     * @throws  InvalidClassException Something is wrong with a class used by
  27.308 +     *          serialization.
  27.309 +     * @throws  NotSerializableException Some object to be serialized does not
  27.310 +     *          implement the java.io.Serializable interface.
  27.311 +     * @throws  IOException Any exception thrown by the underlying
  27.312 +     *          OutputStream.
  27.313 +     */
  27.314 +    public final void writeObject(Object obj) throws IOException {
  27.315 +        if (enableOverride) {
  27.316 +            writeObjectOverride(obj);
  27.317 +            return;
  27.318 +        }
  27.319 +        try {
  27.320 +            writeObject0(obj, false);
  27.321 +        } catch (IOException ex) {
  27.322 +            if (depth == 0) {
  27.323 +                writeFatalException(ex);
  27.324 +            }
  27.325 +            throw ex;
  27.326 +        }
  27.327 +    }
  27.328 +
  27.329 +    /**
  27.330 +     * Method used by subclasses to override the default writeObject method.
  27.331 +     * This method is called by trusted subclasses of ObjectInputStream that
  27.332 +     * constructed ObjectInputStream using the protected no-arg constructor.
  27.333 +     * The subclass is expected to provide an override method with the modifier
  27.334 +     * "final".
  27.335 +     *
  27.336 +     * @param   obj object to be written to the underlying stream
  27.337 +     * @throws  IOException if there are I/O errors while writing to the
  27.338 +     *          underlying stream
  27.339 +     * @see #ObjectOutputStream()
  27.340 +     * @see #writeObject(Object)
  27.341 +     * @since 1.2
  27.342 +     */
  27.343 +    protected void writeObjectOverride(Object obj) throws IOException {
  27.344 +    }
  27.345 +
  27.346 +    /**
  27.347 +     * Writes an "unshared" object to the ObjectOutputStream.  This method is
  27.348 +     * identical to writeObject, except that it always writes the given object
  27.349 +     * as a new, unique object in the stream (as opposed to a back-reference
  27.350 +     * pointing to a previously serialized instance).  Specifically:
  27.351 +     * <ul>
  27.352 +     *   <li>An object written via writeUnshared is always serialized in the
  27.353 +     *       same manner as a newly appearing object (an object that has not
  27.354 +     *       been written to the stream yet), regardless of whether or not the
  27.355 +     *       object has been written previously.
  27.356 +     *
  27.357 +     *   <li>If writeObject is used to write an object that has been previously
  27.358 +     *       written with writeUnshared, the previous writeUnshared operation
  27.359 +     *       is treated as if it were a write of a separate object.  In other
  27.360 +     *       words, ObjectOutputStream will never generate back-references to
  27.361 +     *       object data written by calls to writeUnshared.
  27.362 +     * </ul>
  27.363 +     * While writing an object via writeUnshared does not in itself guarantee a
  27.364 +     * unique reference to the object when it is deserialized, it allows a
  27.365 +     * single object to be defined multiple times in a stream, so that multiple
  27.366 +     * calls to readUnshared by the receiver will not conflict.  Note that the
  27.367 +     * rules described above only apply to the base-level object written with
  27.368 +     * writeUnshared, and not to any transitively referenced sub-objects in the
  27.369 +     * object graph to be serialized.
  27.370 +     *
  27.371 +     * <p>ObjectOutputStream subclasses which override this method can only be
  27.372 +     * constructed in security contexts possessing the
  27.373 +     * "enableSubclassImplementation" SerializablePermission; any attempt to
  27.374 +     * instantiate such a subclass without this permission will cause a
  27.375 +     * SecurityException to be thrown.
  27.376 +     *
  27.377 +     * @param   obj object to write to stream
  27.378 +     * @throws  NotSerializableException if an object in the graph to be
  27.379 +     *          serialized does not implement the Serializable interface
  27.380 +     * @throws  InvalidClassException if a problem exists with the class of an
  27.381 +     *          object to be serialized
  27.382 +     * @throws  IOException if an I/O error occurs during serialization
  27.383 +     * @since 1.4
  27.384 +     */
  27.385 +    public void writeUnshared(Object obj) throws IOException {
  27.386 +        try {
  27.387 +            writeObject0(obj, true);
  27.388 +        } catch (IOException ex) {
  27.389 +            if (depth == 0) {
  27.390 +                writeFatalException(ex);
  27.391 +            }
  27.392 +            throw ex;
  27.393 +        }
  27.394 +    }
  27.395 +
  27.396 +    /**
  27.397 +     * Write the non-static and non-transient fields of the current class to
  27.398 +     * this stream.  This may only be called from the writeObject method of the
  27.399 +     * class being serialized. It will throw the NotActiveException if it is
  27.400 +     * called otherwise.
  27.401 +     *
  27.402 +     * @throws  IOException if I/O errors occur while writing to the underlying
  27.403 +     *          <code>OutputStream</code>
  27.404 +     */
  27.405 +    public void defaultWriteObject() throws IOException {
  27.406 +        if ( curContext == null ) {
  27.407 +            throw new NotActiveException("not in call to writeObject");
  27.408 +        }
  27.409 +        Object curObj = null; // curContext.getObj();
  27.410 +        ObjectStreamClass curDesc = null; // curContext.getDesc();
  27.411 +        bout.setBlockDataMode(false);
  27.412 +        defaultWriteFields(curObj, curDesc);
  27.413 +        bout.setBlockDataMode(true);
  27.414 +    }
  27.415 +
  27.416 +    /**
  27.417 +     * Retrieve the object used to buffer persistent fields to be written to
  27.418 +     * the stream.  The fields will be written to the stream when writeFields
  27.419 +     * method is called.
  27.420 +     *
  27.421 +     * @return  an instance of the class Putfield that holds the serializable
  27.422 +     *          fields
  27.423 +     * @throws  IOException if I/O errors occur
  27.424 +     * @since 1.2
  27.425 +     */
  27.426 +    public ObjectOutputStream.PutField putFields() throws IOException {
  27.427 +        if (curPut == null) {
  27.428 +            if (curContext == null) {
  27.429 +                throw new NotActiveException("not in call to writeObject");
  27.430 +            }
  27.431 +            Object curObj = null; // curContext.getObj();
  27.432 +            ObjectStreamClass curDesc = null; // curContext.getDesc();
  27.433 +            curPut = new PutFieldImpl(curDesc);
  27.434 +        }
  27.435 +        return curPut;
  27.436 +    }
  27.437 +
  27.438 +    /**
  27.439 +     * Write the buffered fields to the stream.
  27.440 +     *
  27.441 +     * @throws  IOException if I/O errors occur while writing to the underlying
  27.442 +     *          stream
  27.443 +     * @throws  NotActiveException Called when a classes writeObject method was
  27.444 +     *          not called to write the state of the object.
  27.445 +     * @since 1.2
  27.446 +     */
  27.447 +    public void writeFields() throws IOException {
  27.448 +        if (curPut == null) {
  27.449 +            throw new NotActiveException("no current PutField object");
  27.450 +        }
  27.451 +        bout.setBlockDataMode(false);
  27.452 +        curPut.writeFields();
  27.453 +        bout.setBlockDataMode(true);
  27.454 +    }
  27.455 +
  27.456 +    /**
  27.457 +     * Reset will disregard the state of any objects already written to the
  27.458 +     * stream.  The state is reset to be the same as a new ObjectOutputStream.
  27.459 +     * The current point in the stream is marked as reset so the corresponding
  27.460 +     * ObjectInputStream will be reset at the same point.  Objects previously
  27.461 +     * written to the stream will not be refered to as already being in the
  27.462 +     * stream.  They will be written to the stream again.
  27.463 +     *
  27.464 +     * @throws  IOException if reset() is invoked while serializing an object.
  27.465 +     */
  27.466 +    public void reset() throws IOException {
  27.467 +        if (depth != 0) {
  27.468 +            throw new IOException("stream active");
  27.469 +        }
  27.470 +        bout.setBlockDataMode(false);
  27.471 +        bout.writeByte(TC_RESET);
  27.472 +        clear();
  27.473 +        bout.setBlockDataMode(true);
  27.474 +    }
  27.475 +
  27.476 +    /**
  27.477 +     * Subclasses may implement this method to allow class data to be stored in
  27.478 +     * the stream. By default this method does nothing.  The corresponding
  27.479 +     * method in ObjectInputStream is resolveClass.  This method is called
  27.480 +     * exactly once for each unique class in the stream.  The class name and
  27.481 +     * signature will have already been written to the stream.  This method may
  27.482 +     * make free use of the ObjectOutputStream to save any representation of
  27.483 +     * the class it deems suitable (for example, the bytes of the class file).
  27.484 +     * The resolveClass method in the corresponding subclass of
  27.485 +     * ObjectInputStream must read and use any data or objects written by
  27.486 +     * annotateClass.
  27.487 +     *
  27.488 +     * @param   cl the class to annotate custom data for
  27.489 +     * @throws  IOException Any exception thrown by the underlying
  27.490 +     *          OutputStream.
  27.491 +     */
  27.492 +    protected void annotateClass(Class<?> cl) throws IOException {
  27.493 +    }
  27.494 +
  27.495 +    /**
  27.496 +     * Subclasses may implement this method to store custom data in the stream
  27.497 +     * along with descriptors for dynamic proxy classes.
  27.498 +     *
  27.499 +     * <p>This method is called exactly once for each unique proxy class
  27.500 +     * descriptor in the stream.  The default implementation of this method in
  27.501 +     * <code>ObjectOutputStream</code> does nothing.
  27.502 +     *
  27.503 +     * <p>The corresponding method in <code>ObjectInputStream</code> is
  27.504 +     * <code>resolveProxyClass</code>.  For a given subclass of
  27.505 +     * <code>ObjectOutputStream</code> that overrides this method, the
  27.506 +     * <code>resolveProxyClass</code> method in the corresponding subclass of
  27.507 +     * <code>ObjectInputStream</code> must read any data or objects written by
  27.508 +     * <code>annotateProxyClass</code>.
  27.509 +     *
  27.510 +     * @param   cl the proxy class to annotate custom data for
  27.511 +     * @throws  IOException any exception thrown by the underlying
  27.512 +     *          <code>OutputStream</code>
  27.513 +     * @see ObjectInputStream#resolveProxyClass(String[])
  27.514 +     * @since   1.3
  27.515 +     */
  27.516 +    protected void annotateProxyClass(Class<?> cl) throws IOException {
  27.517 +    }
  27.518 +
  27.519 +    /**
  27.520 +     * This method will allow trusted subclasses of ObjectOutputStream to
  27.521 +     * substitute one object for another during serialization. Replacing
  27.522 +     * objects is disabled until enableReplaceObject is called. The
  27.523 +     * enableReplaceObject method checks that the stream requesting to do
  27.524 +     * replacement can be trusted.  The first occurrence of each object written
  27.525 +     * into the serialization stream is passed to replaceObject.  Subsequent
  27.526 +     * references to the object are replaced by the object returned by the
  27.527 +     * original call to replaceObject.  To ensure that the private state of
  27.528 +     * objects is not unintentionally exposed, only trusted streams may use
  27.529 +     * replaceObject.
  27.530 +     *
  27.531 +     * <p>The ObjectOutputStream.writeObject method takes a parameter of type
  27.532 +     * Object (as opposed to type Serializable) to allow for cases where
  27.533 +     * non-serializable objects are replaced by serializable ones.
  27.534 +     *
  27.535 +     * <p>When a subclass is replacing objects it must insure that either a
  27.536 +     * complementary substitution must be made during deserialization or that
  27.537 +     * the substituted object is compatible with every field where the
  27.538 +     * reference will be stored.  Objects whose type is not a subclass of the
  27.539 +     * type of the field or array element abort the serialization by raising an
  27.540 +     * exception and the object is not be stored.
  27.541 +     *
  27.542 +     * <p>This method is called only once when each object is first
  27.543 +     * encountered.  All subsequent references to the object will be redirected
  27.544 +     * to the new object. This method should return the object to be
  27.545 +     * substituted or the original object.
  27.546 +     *
  27.547 +     * <p>Null can be returned as the object to be substituted, but may cause
  27.548 +     * NullReferenceException in classes that contain references to the
  27.549 +     * original object since they may be expecting an object instead of
  27.550 +     * null.
  27.551 +     *
  27.552 +     * @param   obj the object to be replaced
  27.553 +     * @return  the alternate object that replaced the specified one
  27.554 +     * @throws  IOException Any exception thrown by the underlying
  27.555 +     *          OutputStream.
  27.556 +     */
  27.557 +    protected Object replaceObject(Object obj) throws IOException {
  27.558 +        return obj;
  27.559 +    }
  27.560 +
  27.561 +    /**
  27.562 +     * Enable the stream to do replacement of objects in the stream.  When
  27.563 +     * enabled, the replaceObject method is called for every object being
  27.564 +     * serialized.
  27.565 +     *
  27.566 +     * <p>If <code>enable</code> is true, and there is a security manager
  27.567 +     * installed, this method first calls the security manager's
  27.568 +     * <code>checkPermission</code> method with a
  27.569 +     * <code>SerializablePermission("enableSubstitution")</code> permission to
  27.570 +     * ensure it's ok to enable the stream to do replacement of objects in the
  27.571 +     * stream.
  27.572 +     *
  27.573 +     * @param   enable boolean parameter to enable replacement of objects
  27.574 +     * @return  the previous setting before this method was invoked
  27.575 +     * @throws  SecurityException if a security manager exists and its
  27.576 +     *          <code>checkPermission</code> method denies enabling the stream
  27.577 +     *          to do replacement of objects in the stream.
  27.578 +     * @see SecurityManager#checkPermission
  27.579 +     * @see java.io.SerializablePermission
  27.580 +     */
  27.581 +    protected boolean enableReplaceObject(boolean enable)
  27.582 +        throws SecurityException
  27.583 +    {
  27.584 +        throw new SecurityException();
  27.585 +    }
  27.586 +
  27.587 +    /**
  27.588 +     * The writeStreamHeader method is provided so subclasses can append or
  27.589 +     * prepend their own header to the stream.  It writes the magic number and
  27.590 +     * version to the stream.
  27.591 +     *
  27.592 +     * @throws  IOException if I/O errors occur while writing to the underlying
  27.593 +     *          stream
  27.594 +     */
  27.595 +    protected void writeStreamHeader() throws IOException {
  27.596 +        bout.writeShort(STREAM_MAGIC);
  27.597 +        bout.writeShort(STREAM_VERSION);
  27.598 +    }
  27.599 +
  27.600 +    /**
  27.601 +     * Write the specified class descriptor to the ObjectOutputStream.  Class
  27.602 +     * descriptors are used to identify the classes of objects written to the
  27.603 +     * stream.  Subclasses of ObjectOutputStream may override this method to
  27.604 +     * customize the way in which class descriptors are written to the
  27.605 +     * serialization stream.  The corresponding method in ObjectInputStream,
  27.606 +     * <code>readClassDescriptor</code>, should then be overridden to
  27.607 +     * reconstitute the class descriptor from its custom stream representation.
  27.608 +     * By default, this method writes class descriptors according to the format
  27.609 +     * defined in the Object Serialization specification.
  27.610 +     *
  27.611 +     * <p>Note that this method will only be called if the ObjectOutputStream
  27.612 +     * is not using the old serialization stream format (set by calling
  27.613 +     * ObjectOutputStream's <code>useProtocolVersion</code> method).  If this
  27.614 +     * serialization stream is using the old format
  27.615 +     * (<code>PROTOCOL_VERSION_1</code>), the class descriptor will be written
  27.616 +     * internally in a manner that cannot be overridden or customized.
  27.617 +     *
  27.618 +     * @param   desc class descriptor to write to the stream
  27.619 +     * @throws  IOException If an I/O error has occurred.
  27.620 +     * @see java.io.ObjectInputStream#readClassDescriptor()
  27.621 +     * @see #useProtocolVersion(int)
  27.622 +     * @see java.io.ObjectStreamConstants#PROTOCOL_VERSION_1
  27.623 +     * @since 1.3
  27.624 +     */
  27.625 +    protected void writeClassDescriptor(ObjectStreamClass desc)
  27.626 +        throws IOException
  27.627 +    {
  27.628 +        desc.writeNonProxy(this);
  27.629 +    }
  27.630 +
  27.631 +    /**
  27.632 +     * Writes a byte. This method will block until the byte is actually
  27.633 +     * written.
  27.634 +     *
  27.635 +     * @param   val the byte to be written to the stream
  27.636 +     * @throws  IOException If an I/O error has occurred.
  27.637 +     */
  27.638 +    public void write(int val) throws IOException {
  27.639 +        bout.write(val);
  27.640 +    }
  27.641 +
  27.642 +    /**
  27.643 +     * Writes an array of bytes. This method will block until the bytes are
  27.644 +     * actually written.
  27.645 +     *
  27.646 +     * @param   buf the data to be written
  27.647 +     * @throws  IOException If an I/O error has occurred.
  27.648 +     */
  27.649 +    public void write(byte[] buf) throws IOException {
  27.650 +        bout.write(buf, 0, buf.length, false);
  27.651 +    }
  27.652 +
  27.653 +    /**
  27.654 +     * Writes a sub array of bytes.
  27.655 +     *
  27.656 +     * @param   buf the data to be written
  27.657 +     * @param   off the start offset in the data
  27.658 +     * @param   len the number of bytes that are written
  27.659 +     * @throws  IOException If an I/O error has occurred.
  27.660 +     */
  27.661 +    public void write(byte[] buf, int off, int len) throws IOException {
  27.662 +        if (buf == null) {
  27.663 +            throw new NullPointerException();
  27.664 +        }
  27.665 +        int endoff = off + len;
  27.666 +        if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
  27.667 +            throw new IndexOutOfBoundsException();
  27.668 +        }
  27.669 +        bout.write(buf, off, len, false);
  27.670 +    }
  27.671 +
  27.672 +    /**
  27.673 +     * Flushes the stream. This will write any buffered output bytes and flush
  27.674 +     * through to the underlying stream.
  27.675 +     *
  27.676 +     * @throws  IOException If an I/O error has occurred.
  27.677 +     */
  27.678 +    public void flush() throws IOException {
  27.679 +        bout.flush();
  27.680 +    }
  27.681 +
  27.682 +    /**
  27.683 +     * Drain any buffered data in ObjectOutputStream.  Similar to flush but
  27.684 +     * does not propagate the flush to the underlying stream.
  27.685 +     *
  27.686 +     * @throws  IOException if I/O errors occur while writing to the underlying
  27.687 +     *          stream
  27.688 +     */
  27.689 +    protected void drain() throws IOException {
  27.690 +        bout.drain();
  27.691 +    }
  27.692 +
  27.693 +    /**
  27.694 +     * Closes the stream. This method must be called to release any resources
  27.695 +     * associated with the stream.
  27.696 +     *
  27.697 +     * @throws  IOException If an I/O error has occurred.
  27.698 +     */
  27.699 +    public void close() throws IOException {
  27.700 +        flush();
  27.701 +        clear();
  27.702 +        bout.close();
  27.703 +    }
  27.704 +
  27.705 +    /**
  27.706 +     * Writes a boolean.
  27.707 +     *
  27.708 +     * @param   val the boolean to be written
  27.709 +     * @throws  IOException if I/O errors occur while writing to the underlying
  27.710 +     *          stream
  27.711 +     */
  27.712 +    public void writeBoolean(boolean val) throws IOException {
  27.713 +        bout.writeBoolean(val);
  27.714 +    }
  27.715 +
  27.716 +    /**
  27.717 +     * Writes an 8 bit byte.
  27.718 +     *
  27.719 +     * @param   val the byte value to be written
  27.720 +     * @throws  IOException if I/O errors occur while writing to the underlying
  27.721 +     *          stream
  27.722 +     */
  27.723 +    public void writeByte(int val) throws IOException  {
  27.724 +        bout.writeByte(val);
  27.725 +    }
  27.726 +
  27.727 +    /**
  27.728 +     * Writes a 16 bit short.
  27.729 +     *
  27.730 +     * @param   val the short value to be written
  27.731 +     * @throws  IOException if I/O errors occur while writing to the underlying
  27.732 +     *          stream
  27.733 +     */
  27.734 +    public void writeShort(int val)  throws IOException {
  27.735 +        bout.writeShort(val);
  27.736 +    }
  27.737 +
  27.738 +    /**
  27.739 +     * Writes a 16 bit char.
  27.740 +     *
  27.741 +     * @param   val the char value to be written
  27.742 +     * @throws  IOException if I/O errors occur while writing to the underlying
  27.743 +     *          stream
  27.744 +     */
  27.745 +    public void writeChar(int val)  throws IOException {
  27.746 +        bout.writeChar(val);
  27.747 +    }
  27.748 +
  27.749 +    /**
  27.750 +     * Writes a 32 bit int.
  27.751 +     *
  27.752 +     * @param   val the integer value to be written
  27.753 +     * @throws  IOException if I/O errors occur while writing to the underlying
  27.754 +     *          stream
  27.755 +     */
  27.756 +    public void writeInt(int val)  throws IOException {
  27.757 +        bout.writeInt(val);
  27.758 +    }
  27.759 +
  27.760 +    /**
  27.761 +     * Writes a 64 bit long.
  27.762 +     *
  27.763 +     * @param   val the long value to be written
  27.764 +     * @throws  IOException if I/O errors occur while writing to the underlying
  27.765 +     *          stream
  27.766 +     */
  27.767 +    public void writeLong(long val)  throws IOException {
  27.768 +        bout.writeLong(val);
  27.769 +    }
  27.770 +
  27.771 +    /**
  27.772 +     * Writes a 32 bit float.
  27.773 +     *
  27.774 +     * @param   val the float value to be written
  27.775 +     * @throws  IOException if I/O errors occur while writing to the underlying
  27.776 +     *          stream
  27.777 +     */
  27.778 +    public void writeFloat(float val) throws IOException {
  27.779 +        bout.writeFloat(val);
  27.780 +    }
  27.781 +
  27.782 +    /**
  27.783 +     * Writes a 64 bit double.
  27.784 +     *
  27.785 +     * @param   val the double value to be written
  27.786 +     * @throws  IOException if I/O errors occur while writing to the underlying
  27.787 +     *          stream
  27.788 +     */
  27.789 +    public void writeDouble(double val) throws IOException {
  27.790 +        bout.writeDouble(val);
  27.791 +    }
  27.792 +
  27.793 +    /**
  27.794 +     * Writes a String as a sequence of bytes.
  27.795 +     *
  27.796 +     * @param   str the String of bytes to be written
  27.797 +     * @throws  IOException if I/O errors occur while writing to the underlying
  27.798 +     *          stream
  27.799 +     */
  27.800 +    public void writeBytes(String str) throws IOException {
  27.801 +        bout.writeBytes(str);
  27.802 +    }
  27.803 +
  27.804 +    /**
  27.805 +     * Writes a String as a sequence of chars.
  27.806 +     *
  27.807 +     * @param   str the String of chars to be written
  27.808 +     * @throws  IOException if I/O errors occur while writing to the underlying
  27.809 +     *          stream
  27.810 +     */
  27.811 +    public void writeChars(String str) throws IOException {
  27.812 +        bout.writeChars(str);
  27.813 +    }
  27.814 +
  27.815 +    /**
  27.816 +     * Primitive data write of this String in
  27.817 +     * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
  27.818 +     * format.  Note that there is a
  27.819 +     * significant difference between writing a String into the stream as
  27.820 +     * primitive data or as an Object. A String instance written by writeObject
  27.821 +     * is written into the stream as a String initially. Future writeObject()
  27.822 +     * calls write references to the string into the stream.
  27.823 +     *
  27.824 +     * @param   str the String to be written
  27.825 +     * @throws  IOException if I/O errors occur while writing to the underlying
  27.826 +     *          stream
  27.827 +     */
  27.828 +    public void writeUTF(String str) throws IOException {
  27.829 +        bout.writeUTF(str);
  27.830 +    }
  27.831 +
  27.832 +    /**
  27.833 +     * Provide programmatic access to the persistent fields to be written
  27.834 +     * to ObjectOutput.
  27.835 +     *
  27.836 +     * @since 1.2
  27.837 +     */
  27.838 +    public static abstract class PutField {
  27.839 +
  27.840 +        /**
  27.841 +         * Put the value of the named boolean field into the persistent field.
  27.842 +         *
  27.843 +         * @param  name the name of the serializable field
  27.844 +         * @param  val the value to assign to the field
  27.845 +         * @throws IllegalArgumentException if <code>name</code> does not
  27.846 +         * match the name of a serializable field for the class whose fields
  27.847 +         * are being written, or if the type of the named field is not
  27.848 +         * <code>boolean</code>
  27.849 +         */
  27.850 +        public abstract void put(String name, boolean val);
  27.851 +
  27.852 +        /**
  27.853 +         * Put the value of the named byte field into the persistent field.
  27.854 +         *
  27.855 +         * @param  name the name of the serializable field
  27.856 +         * @param  val the value to assign to the field
  27.857 +         * @throws IllegalArgumentException if <code>name</code> does not
  27.858 +         * match the name of a serializable field for the class whose fields
  27.859 +         * are being written, or if the type of the named field is not
  27.860 +         * <code>byte</code>
  27.861 +         */
  27.862 +        public abstract void put(String name, byte val);
  27.863 +
  27.864 +        /**
  27.865 +         * Put the value of the named char field into the persistent field.
  27.866 +         *
  27.867 +         * @param  name the name of the serializable field
  27.868 +         * @param  val the value to assign to the field
  27.869 +         * @throws IllegalArgumentException if <code>name</code> does not
  27.870 +         * match the name of a serializable field for the class whose fields
  27.871 +         * are being written, or if the type of the named field is not
  27.872 +         * <code>char</code>
  27.873 +         */
  27.874 +        public abstract void put(String name, char val);
  27.875 +
  27.876 +        /**
  27.877 +         * Put the value of the named short field into the persistent field.
  27.878 +         *
  27.879 +         * @param  name the name of the serializable field
  27.880 +         * @param  val the value to assign to the field
  27.881 +         * @throws IllegalArgumentException if <code>name</code> does not
  27.882 +         * match the name of a serializable field for the class whose fields
  27.883 +         * are being written, or if the type of the named field is not
  27.884 +         * <code>short</code>
  27.885 +         */
  27.886 +        public abstract void put(String name, short val);
  27.887 +
  27.888 +        /**
  27.889 +         * Put the value of the named int field into the persistent field.
  27.890 +         *
  27.891 +         * @param  name the name of the serializable field
  27.892 +         * @param  val the value to assign to the field
  27.893 +         * @throws IllegalArgumentException if <code>name</code> does not
  27.894 +         * match the name of a serializable field for the class whose fields
  27.895 +         * are being written, or if the type of the named field is not
  27.896 +         * <code>int</code>
  27.897 +         */
  27.898 +        public abstract void put(String name, int val);
  27.899 +
  27.900 +        /**
  27.901 +         * Put the value of the named long field into the persistent field.
  27.902 +         *
  27.903 +         * @param  name the name of the serializable field
  27.904 +         * @param  val the value to assign to the field
  27.905 +         * @throws IllegalArgumentException if <code>name</code> does not
  27.906 +         * match the name of a serializable field for the class whose fields
  27.907 +         * are being written, or if the type of the named field is not
  27.908 +         * <code>long</code>
  27.909 +         */
  27.910 +        public abstract void put(String name, long val);
  27.911 +
  27.912 +        /**
  27.913 +         * Put the value of the named float field into the persistent field.
  27.914 +         *
  27.915 +         * @param  name the name of the serializable field
  27.916 +         * @param  val the value to assign to the field
  27.917 +         * @throws IllegalArgumentException if <code>name</code> does not
  27.918 +         * match the name of a serializable field for the class whose fields
  27.919 +         * are being written, or if the type of the named field is not
  27.920 +         * <code>float</code>
  27.921 +         */
  27.922 +        public abstract void put(String name, float val);
  27.923 +
  27.924 +        /**
  27.925 +         * Put the value of the named double field into the persistent field.
  27.926 +         *
  27.927 +         * @param  name the name of the serializable field
  27.928 +         * @param  val the value to assign to the field
  27.929 +         * @throws IllegalArgumentException if <code>name</code> does not
  27.930 +         * match the name of a serializable field for the class whose fields
  27.931 +         * are being written, or if the type of the named field is not
  27.932 +         * <code>double</code>
  27.933 +         */
  27.934 +        public abstract void put(String name, double val);
  27.935 +
  27.936 +        /**
  27.937 +         * Put the value of the named Object field into the persistent field.
  27.938 +         *
  27.939 +         * @param  name the name of the serializable field
  27.940 +         * @param  val the value to assign to the field
  27.941 +         *         (which may be <code>null</code>)
  27.942 +         * @throws IllegalArgumentException if <code>name</code> does not
  27.943 +         * match the name of a serializable field for the class whose fields
  27.944 +         * are being written, or if the type of the named field is not a
  27.945 +         * reference type
  27.946 +         */
  27.947 +        public abstract void put(String name, Object val);
  27.948 +
  27.949 +        /**
  27.950 +         * Write the data and fields to the specified ObjectOutput stream,
  27.951 +         * which must be the same stream that produced this
  27.952 +         * <code>PutField</code> object.
  27.953 +         *
  27.954 +         * @param  out the stream to write the data and fields to
  27.955 +         * @throws IOException if I/O errors occur while writing to the
  27.956 +         *         underlying stream
  27.957 +         * @throws IllegalArgumentException if the specified stream is not
  27.958 +         *         the same stream that produced this <code>PutField</code>
  27.959 +         *         object
  27.960 +         * @deprecated This method does not write the values contained by this
  27.961 +         *         <code>PutField</code> object in a proper format, and may
  27.962 +         *         result in corruption of the serialization stream.  The
  27.963 +         *         correct way to write <code>PutField</code> data is by
  27.964 +         *         calling the {@link java.io.ObjectOutputStream#writeFields()}
  27.965 +         *         method.
  27.966 +         */
  27.967 +        @Deprecated
  27.968 +        public abstract void write(ObjectOutput out) throws IOException;
  27.969 +    }
  27.970 +
  27.971 +
  27.972 +    /**
  27.973 +     * Returns protocol version in use.
  27.974 +     */
  27.975 +    int getProtocolVersion() {
  27.976 +        return protocol;
  27.977 +    }
  27.978 +
  27.979 +    /**
  27.980 +     * Writes string without allowing it to be replaced in stream.  Used by
  27.981 +     * ObjectStreamClass to write class descriptor type strings.
  27.982 +     */
  27.983 +    void writeTypeString(String str) throws IOException {
  27.984 +        int handle;
  27.985 +        if (str == null) {
  27.986 +            writeNull();
  27.987 +        } else if ((handle = handles.lookup(str)) != -1) {
  27.988 +            writeHandle(handle);
  27.989 +        } else {
  27.990 +            writeString(str, false);
  27.991 +        }
  27.992 +    }
  27.993 +
  27.994 +    /**
  27.995 +     * Verifies that this (possibly subclass) instance can be constructed
  27.996 +     * without violating security constraints: the subclass must not override
  27.997 +     * security-sensitive non-final methods, or else the
  27.998 +     * "enableSubclassImplementation" SerializablePermission is checked.
  27.999 +     */
 27.1000 +    private void verifySubclass() {
 27.1001 +        Class cl = getClass();
 27.1002 +        if (cl == ObjectOutputStream.class) {
 27.1003 +            return;
 27.1004 +        }
 27.1005 +        throw new SecurityException();
 27.1006 +    }
 27.1007 +
 27.1008 +    /**
 27.1009 +     * Clears internal data structures.
 27.1010 +     */
 27.1011 +    private void clear() {
 27.1012 +        subs.clear();
 27.1013 +        handles.clear();
 27.1014 +    }
 27.1015 +
 27.1016 +    /**
 27.1017 +     * Underlying writeObject/writeUnshared implementation.
 27.1018 +     */
 27.1019 +    private void writeObject0(Object obj, boolean unshared)
 27.1020 +        throws IOException
 27.1021 +    {
 27.1022 +        boolean oldMode = bout.setBlockDataMode(false);
 27.1023 +        depth++;
 27.1024 +        try {
 27.1025 +            // handle previously written and non-replaceable objects
 27.1026 +            int h;
 27.1027 +            if ((obj = subs.lookup(obj)) == null) {
 27.1028 +                writeNull();
 27.1029 +                return;
 27.1030 +            } else if (!unshared && (h = handles.lookup(obj)) != -1) {
 27.1031 +                writeHandle(h);
 27.1032 +                return;
 27.1033 +            } else if (obj instanceof Class) {
 27.1034 +                writeClass((Class) obj, unshared);
 27.1035 +                return;
 27.1036 +            } else if (obj instanceof ObjectStreamClass) {
 27.1037 +                writeClassDesc((ObjectStreamClass) obj, unshared);
 27.1038 +                return;
 27.1039 +            }
 27.1040 +
 27.1041 +            // check for replacement object
 27.1042 +            Object orig = obj;
 27.1043 +            Class cl = obj.getClass();
 27.1044 +            ObjectStreamClass desc;
 27.1045 +            for (;;) {
 27.1046 +                // REMIND: skip this check for strings/arrays?
 27.1047 +                Class repCl;
 27.1048 +                desc = ObjectStreamClass.lookup(cl, true);
 27.1049 +                if (!desc.hasWriteReplaceMethod() ||
 27.1050 +                    (obj = desc.invokeWriteReplace(obj)) == null ||
 27.1051 +                    (repCl = obj.getClass()) == cl)
 27.1052 +                {
 27.1053 +                    break;
 27.1054 +                }
 27.1055 +                cl = repCl;
 27.1056 +            }
 27.1057 +            if (enableReplace) {
 27.1058 +                Object rep = replaceObject(obj);
 27.1059 +                if (rep != obj && rep != null) {
 27.1060 +                    cl = rep.getClass();
 27.1061 +                    desc = ObjectStreamClass.lookup(cl, true);
 27.1062 +                }
 27.1063 +                obj = rep;
 27.1064 +            }
 27.1065 +
 27.1066 +            // if object replaced, run through original checks a second time
 27.1067 +            if (obj != orig) {
 27.1068 +                subs.assign(orig, obj);
 27.1069 +                if (obj == null) {
 27.1070 +                    writeNull();
 27.1071 +                    return;
 27.1072 +                } else if (!unshared && (h = handles.lookup(obj)) != -1) {
 27.1073 +                    writeHandle(h);
 27.1074 +                    return;
 27.1075 +                } else if (obj instanceof Class) {
 27.1076 +                    writeClass((Class) obj, unshared);
 27.1077 +                    return;
 27.1078 +                } else if (obj instanceof ObjectStreamClass) {
 27.1079 +                    writeClassDesc((ObjectStreamClass) obj, unshared);
 27.1080 +                    return;
 27.1081 +                }
 27.1082 +            }
 27.1083 +
 27.1084 +            // remaining cases
 27.1085 +            if (obj instanceof String) {
 27.1086 +                writeString((String) obj, unshared);
 27.1087 +            } else if (cl.isArray()) {
 27.1088 +                writeArray(obj, desc, unshared);
 27.1089 +            } else if (obj instanceof Enum) {
 27.1090 +                writeEnum((Enum) obj, desc, unshared);
 27.1091 +            } else if (obj instanceof Serializable) {
 27.1092 +                writeOrdinaryObject(obj, desc, unshared);
 27.1093 +            } else {
 27.1094 +                if (extendedDebugInfo) {
 27.1095 +                    throw new NotSerializableException(
 27.1096 +                        cl.getName() + "\n" + debugInfoStack.toString());
 27.1097 +                } else {
 27.1098 +                    throw new NotSerializableException(cl.getName());
 27.1099 +                }
 27.1100 +            }
 27.1101 +        } finally {
 27.1102 +            depth--;
 27.1103 +            bout.setBlockDataMode(oldMode);
 27.1104 +        }
 27.1105 +    }
 27.1106 +
 27.1107 +    /**
 27.1108 +     * Writes null code to stream.
 27.1109 +     */
 27.1110 +    private void writeNull() throws IOException {
 27.1111 +        bout.writeByte(TC_NULL);
 27.1112 +    }
 27.1113 +
 27.1114 +    /**
 27.1115 +     * Writes given object handle to stream.
 27.1116 +     */
 27.1117 +    private void writeHandle(int handle) throws IOException {
 27.1118 +        bout.writeByte(TC_REFERENCE);
 27.1119 +        bout.writeInt(baseWireHandle + handle);
 27.1120 +    }
 27.1121 +
 27.1122 +    /**
 27.1123 +     * Writes representation of given class to stream.
 27.1124 +     */
 27.1125 +    private void writeClass(Class cl, boolean unshared) throws IOException {
 27.1126 +        bout.writeByte(TC_CLASS);
 27.1127 +        writeClassDesc(ObjectStreamClass.lookup(cl, true), false);
 27.1128 +        handles.assign(unshared ? null : cl);
 27.1129 +    }
 27.1130 +
 27.1131 +    /**
 27.1132 +     * Writes representation of given class descriptor to stream.
 27.1133 +     */
 27.1134 +    private void writeClassDesc(ObjectStreamClass desc, boolean unshared)
 27.1135 +        throws IOException
 27.1136 +    {
 27.1137 +        int handle;
 27.1138 +        if (desc == null) {
 27.1139 +            writeNull();
 27.1140 +        } else if (!unshared && (handle = handles.lookup(desc)) != -1) {
 27.1141 +            writeHandle(handle);
 27.1142 +        } else if (desc.isProxy()) {
 27.1143 +            writeProxyDesc(desc, unshared);
 27.1144 +        } else {
 27.1145 +            writeNonProxyDesc(desc, unshared);
 27.1146 +        }
 27.1147 +    }
 27.1148 +
 27.1149 +    /**
 27.1150 +     * Writes class descriptor representing a dynamic proxy class to stream.
 27.1151 +     */
 27.1152 +    private void writeProxyDesc(ObjectStreamClass desc, boolean unshared)
 27.1153 +        throws IOException
 27.1154 +    {
 27.1155 +        bout.writeByte(TC_PROXYCLASSDESC);
 27.1156 +        handles.assign(unshared ? null : desc);
 27.1157 +
 27.1158 +        Class cl = desc.forClass();
 27.1159 +        Class[] ifaces = cl.getInterfaces();
 27.1160 +        bout.writeInt(ifaces.length);
 27.1161 +        for (int i = 0; i < ifaces.length; i++) {
 27.1162 +            bout.writeUTF(ifaces[i].getName());
 27.1163 +        }
 27.1164 +
 27.1165 +        bout.setBlockDataMode(true);
 27.1166 +        annotateProxyClass(cl);
 27.1167 +        bout.setBlockDataMode(false);
 27.1168 +        bout.writeByte(TC_ENDBLOCKDATA);
 27.1169 +
 27.1170 +        writeClassDesc(desc.getSuperDesc(), false);
 27.1171 +    }
 27.1172 +
 27.1173 +    /**
 27.1174 +     * Writes class descriptor representing a standard (i.e., not a dynamic
 27.1175 +     * proxy) class to stream.
 27.1176 +     */
 27.1177 +    private void writeNonProxyDesc(ObjectStreamClass desc, boolean unshared)
 27.1178 +        throws IOException
 27.1179 +    {
 27.1180 +        bout.writeByte(TC_CLASSDESC);
 27.1181 +        handles.assign(unshared ? null : desc);
 27.1182 +
 27.1183 +        if (protocol == PROTOCOL_VERSION_1) {
 27.1184 +            // do not invoke class descriptor write hook with old protocol
 27.1185 +            desc.writeNonProxy(this);
 27.1186 +        } else {
 27.1187 +            writeClassDescriptor(desc);
 27.1188 +        }
 27.1189 +
 27.1190 +        Class cl = desc.forClass();
 27.1191 +        bout.setBlockDataMode(true);
 27.1192 +        annotateClass(cl);
 27.1193 +        bout.setBlockDataMode(false);
 27.1194 +        bout.writeByte(TC_ENDBLOCKDATA);
 27.1195 +
 27.1196 +        writeClassDesc(desc.getSuperDesc(), false);
 27.1197 +    }
 27.1198 +
 27.1199 +    /**
 27.1200 +     * Writes given string to stream, using standard or long UTF format
 27.1201 +     * depending on string length.
 27.1202 +     */
 27.1203 +    private void writeString(String str, boolean unshared) throws IOException {
 27.1204 +        handles.assign(unshared ? null : str);
 27.1205 +        long utflen = bout.getUTFLength(str);
 27.1206 +        if (utflen <= 0xFFFF) {
 27.1207 +            bout.writeByte(TC_STRING);
 27.1208 +            bout.writeUTF(str, utflen);
 27.1209 +        } else {
 27.1210 +            bout.writeByte(TC_LONGSTRING);
 27.1211 +            bout.writeLongUTF(str, utflen);
 27.1212 +        }
 27.1213 +    }
 27.1214 +
 27.1215 +    /**
 27.1216 +     * Writes given array object to stream.
 27.1217 +     */
 27.1218 +    private void writeArray(Object array,
 27.1219 +                            ObjectStreamClass desc,
 27.1220 +                            boolean unshared)
 27.1221 +        throws IOException
 27.1222 +    {
 27.1223 +        bout.writeByte(TC_ARRAY);
 27.1224 +        writeClassDesc(desc, false);
 27.1225 +        handles.assign(unshared ? null : array);
 27.1226 +
 27.1227 +        Class ccl = desc.forClass().getComponentType();
 27.1228 +        if (ccl.isPrimitive()) {
 27.1229 +            if (ccl == Integer.TYPE) {
 27.1230 +                int[] ia = (int[]) array;
 27.1231 +                bout.writeInt(ia.length);
 27.1232 +                bout.writeInts(ia, 0, ia.length);
 27.1233 +            } else if (ccl == Byte.TYPE) {
 27.1234 +                byte[] ba = (byte[]) array;
 27.1235 +                bout.writeInt(ba.length);
 27.1236 +                bout.write(ba, 0, ba.length, true);
 27.1237 +            } else if (ccl == Long.TYPE) {
 27.1238 +                long[] ja = (long[]) array;
 27.1239 +                bout.writeInt(ja.length);
 27.1240 +                bout.writeLongs(ja, 0, ja.length);
 27.1241 +            } else if (ccl == Float.TYPE) {
 27.1242 +                float[] fa = (float[]) array;
 27.1243 +                bout.writeInt(fa.length);
 27.1244 +                bout.writeFloats(fa, 0, fa.length);
 27.1245 +            } else if (ccl == Double.TYPE) {
 27.1246 +                double[] da = (double[]) array;
 27.1247 +                bout.writeInt(da.length);
 27.1248 +                bout.writeDoubles(da, 0, da.length);
 27.1249 +            } else if (ccl == Short.TYPE) {
 27.1250 +                short[] sa = (short[]) array;
 27.1251 +                bout.writeInt(sa.length);
 27.1252 +                bout.writeShorts(sa, 0, sa.length);
 27.1253 +            } else if (ccl == Character.TYPE) {
 27.1254 +                char[] ca = (char[]) array;
 27.1255 +                bout.writeInt(ca.length);
 27.1256 +                bout.writeChars(ca, 0, ca.length);
 27.1257 +            } else if (ccl == Boolean.TYPE) {
 27.1258 +                boolean[] za = (boolean[]) array;
 27.1259 +                bout.writeInt(za.length);
 27.1260 +                bout.writeBooleans(za, 0, za.length);
 27.1261 +            } else {
 27.1262 +                throw new InternalError();
 27.1263 +            }
 27.1264 +        } else {
 27.1265 +            Object[] objs = (Object[]) array;
 27.1266 +            int len = objs.length;
 27.1267 +            bout.writeInt(len);
 27.1268 +            if (extendedDebugInfo) {
 27.1269 +                debugInfoStack.push(
 27.1270 +                    "array (class \"" + array.getClass().getName() +
 27.1271 +                    "\", size: " + len  + ")");
 27.1272 +            }
 27.1273 +            try {
 27.1274 +                for (int i = 0; i < len; i++) {
 27.1275 +                    if (extendedDebugInfo) {
 27.1276 +                        debugInfoStack.push(
 27.1277 +                            "element of array (index: " + i + ")");
 27.1278 +                    }
 27.1279 +                    try {
 27.1280 +                        writeObject0(objs[i], false);
 27.1281 +                    } finally {
 27.1282 +                        if (extendedDebugInfo) {
 27.1283 +                            debugInfoStack.pop();
 27.1284 +                        }
 27.1285 +                    }
 27.1286 +                }
 27.1287 +            } finally {
 27.1288 +                if (extendedDebugInfo) {
 27.1289 +                    debugInfoStack.pop();
 27.1290 +                }
 27.1291 +            }
 27.1292 +        }
 27.1293 +    }
 27.1294 +
 27.1295 +    /**
 27.1296 +     * Writes given enum constant to stream.
 27.1297 +     */
 27.1298 +    private void writeEnum(Enum en,
 27.1299 +                           ObjectStreamClass desc,
 27.1300 +                           boolean unshared)
 27.1301 +        throws IOException
 27.1302 +    {
 27.1303 +        bout.writeByte(TC_ENUM);
 27.1304 +        ObjectStreamClass sdesc = desc.getSuperDesc();
 27.1305 +        writeClassDesc((sdesc.forClass() == Enum.class) ? desc : sdesc, false);
 27.1306 +        handles.assign(unshared ? null : en);
 27.1307 +        writeString(en.name(), false);
 27.1308 +    }
 27.1309 +
 27.1310 +    /**
 27.1311 +     * Writes representation of a "ordinary" (i.e., not a String, Class,
 27.1312 +     * ObjectStreamClass, array, or enum constant) serializable object to the
 27.1313 +     * stream.
 27.1314 +     */
 27.1315 +    private void writeOrdinaryObject(Object obj,
 27.1316 +                                     ObjectStreamClass desc,
 27.1317 +                                     boolean unshared)
 27.1318 +        throws IOException
 27.1319 +    {
 27.1320 +        if (extendedDebugInfo) {
 27.1321 +            debugInfoStack.push(
 27.1322 +                (depth == 1 ? "root " : "") + "object (class \"" +
 27.1323 +                obj.getClass().getName() + "\", " + obj.toString() + ")");
 27.1324 +        }
 27.1325 +        try {
 27.1326 +            desc.checkSerialize();
 27.1327 +
 27.1328 +            bout.writeByte(TC_OBJECT);
 27.1329 +            writeClassDesc(desc, false);
 27.1330 +            handles.assign(unshared ? null : obj);
 27.1331 +            if (desc.isExternalizable() && !desc.isProxy()) {
 27.1332 +                writeExternalData((Externalizable) obj);
 27.1333 +            } else {
 27.1334 +                writeSerialData(obj, desc);
 27.1335 +            }
 27.1336 +        } finally {
 27.1337 +            if (extendedDebugInfo) {
 27.1338 +                debugInfoStack.pop();
 27.1339 +            }
 27.1340 +        }
 27.1341 +    }
 27.1342 +
 27.1343 +    /**
 27.1344 +     * Writes externalizable data of given object by invoking its
 27.1345 +     * writeExternal() method.
 27.1346 +     */
 27.1347 +    private void writeExternalData(Externalizable obj) throws IOException {
 27.1348 +        PutFieldImpl oldPut = curPut;
 27.1349 +        curPut = null;
 27.1350 +
 27.1351 +        if (extendedDebugInfo) {
 27.1352 +            debugInfoStack.push("writeExternal data");
 27.1353 +        }
 27.1354 +        Object oldContext = curContext;
 27.1355 +        try {
 27.1356 +            curContext = null;
 27.1357 +            if (protocol == PROTOCOL_VERSION_1) {
 27.1358 +                obj.writeExternal(this);
 27.1359 +            } else {
 27.1360 +                bout.setBlockDataMode(true);
 27.1361 +                obj.writeExternal(this);
 27.1362 +                bout.setBlockDataMode(false);
 27.1363 +                bout.writeByte(TC_ENDBLOCKDATA);
 27.1364 +            }
 27.1365 +        } finally {
 27.1366 +            curContext = oldContext;
 27.1367 +            if (extendedDebugInfo) {
 27.1368 +                debugInfoStack.pop();
 27.1369 +            }
 27.1370 +        }
 27.1371 +
 27.1372 +        curPut = oldPut;
 27.1373 +    }
 27.1374 +
 27.1375 +    /**
 27.1376 +     * Writes instance data for each serializable class of given object, from
 27.1377 +     * superclass to subclass.
 27.1378 +     */
 27.1379 +    private void writeSerialData(Object obj, ObjectStreamClass desc)
 27.1380 +        throws IOException
 27.1381 +    {
 27.1382 +        ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
 27.1383 +        for (int i = 0; i < slots.length; i++) {
 27.1384 +            ObjectStreamClass slotDesc = slots[i].desc;
 27.1385 +            if (slotDesc.hasWriteObjectMethod()) {
 27.1386 +                PutFieldImpl oldPut = curPut;
 27.1387 +                curPut = null;
 27.1388 +                Object oldContext = curContext;
 27.1389 +
 27.1390 +                if (extendedDebugInfo) {
 27.1391 +                    debugInfoStack.push(
 27.1392 +                        "custom writeObject data (class \"" +
 27.1393 +                        slotDesc.getName() + "\")");
 27.1394 +                }
 27.1395 +                try {
 27.1396 +                    curContext = new Object(); //new SerialCallbackContext(obj, slotDesc);
 27.1397 +                    bout.setBlockDataMode(true);
 27.1398 +                    slotDesc.invokeWriteObject(obj, this);
 27.1399 +                    bout.setBlockDataMode(false);
 27.1400 +                    bout.writeByte(TC_ENDBLOCKDATA);
 27.1401 +                } finally {
 27.1402 +                    //curContext.setUsed();
 27.1403 +                    curContext = oldContext;
 27.1404 +                    if (extendedDebugInfo) {
 27.1405 +                        debugInfoStack.pop();
 27.1406 +                    }
 27.1407 +                }
 27.1408 +
 27.1409 +                curPut = oldPut;
 27.1410 +            } else {
 27.1411 +                defaultWriteFields(obj, slotDesc);
 27.1412 +            }
 27.1413 +        }
 27.1414 +    }
 27.1415 +
 27.1416 +    /**
 27.1417 +     * Fetches and writes values of serializable fields of given object to
 27.1418 +     * stream.  The given class descriptor specifies which field values to
 27.1419 +     * write, and in which order they should be written.
 27.1420 +     */
 27.1421 +    private void defaultWriteFields(Object obj, ObjectStreamClass desc)
 27.1422 +        throws IOException
 27.1423 +    {
 27.1424 +        // REMIND: perform conservative isInstance check here?
 27.1425 +        desc.checkDefaultSerialize();
 27.1426 +
 27.1427 +        int primDataSize = desc.getPrimDataSize();
 27.1428 +        if (primVals == null || primVals.length < primDataSize) {
 27.1429 +            primVals = new byte[primDataSize];
 27.1430 +        }
 27.1431 +        desc.getPrimFieldValues(obj, primVals);
 27.1432 +        bout.write(primVals, 0, primDataSize, false);
 27.1433 +
 27.1434 +        ObjectStreamField[] fields = desc.getFields(false);
 27.1435 +        Object[] objVals = new Object[desc.getNumObjFields()];
 27.1436 +        int numPrimFields = fields.length - objVals.length;
 27.1437 +        desc.getObjFieldValues(obj, objVals);
 27.1438 +        for (int i = 0; i < objVals.length; i++) {
 27.1439 +            if (extendedDebugInfo) {
 27.1440 +                debugInfoStack.push(
 27.1441 +                    "field (class \"" + desc.getName() + "\", name: \"" +
 27.1442 +                    fields[numPrimFields + i].getName() + "\", type: \"" +
 27.1443 +                    fields[numPrimFields + i].getType() + "\")");
 27.1444 +            }
 27.1445 +            try {
 27.1446 +                writeObject0(objVals[i],
 27.1447 +                             fields[numPrimFields + i].isUnshared());
 27.1448 +            } finally {
 27.1449 +                if (extendedDebugInfo) {
 27.1450 +                    debugInfoStack.pop();
 27.1451 +                }
 27.1452 +            }
 27.1453 +        }
 27.1454 +    }
 27.1455 +
 27.1456 +    /**
 27.1457 +     * Attempts to write to stream fatal IOException that has caused
 27.1458 +     * serialization to abort.
 27.1459 +     */
 27.1460 +    private void writeFatalException(IOException ex) throws IOException {
 27.1461 +        /*
 27.1462 +         * Note: the serialization specification states that if a second
 27.1463 +         * IOException occurs while attempting to serialize the original fatal
 27.1464 +         * exception to the stream, then a StreamCorruptedException should be
 27.1465 +         * thrown (section 2.1).  However, due to a bug in previous
 27.1466 +         * implementations of serialization, StreamCorruptedExceptions were
 27.1467 +         * rarely (if ever) actually thrown--the "root" exceptions from
 27.1468 +         * underlying streams were thrown instead.  This historical behavior is
 27.1469 +         * followed here for consistency.
 27.1470 +         */
 27.1471 +        clear();
 27.1472 +        boolean oldMode = bout.setBlockDataMode(false);
 27.1473 +        try {
 27.1474 +            bout.writeByte(TC_EXCEPTION);
 27.1475 +            writeObject0(ex, false);
 27.1476 +            clear();
 27.1477 +        } finally {
 27.1478 +            bout.setBlockDataMode(oldMode);
 27.1479 +        }
 27.1480 +    }
 27.1481 +
 27.1482 +    /**
 27.1483 +     * Converts specified span of float values into byte values.
 27.1484 +     */
 27.1485 +    // REMIND: remove once hotspot inlines Float.floatToIntBits
 27.1486 +    private static native void floatsToBytes(float[] src, int srcpos,
 27.1487 +                                             byte[] dst, int dstpos,
 27.1488 +                                             int nfloats);
 27.1489 +
 27.1490 +    /**
 27.1491 +     * Converts specified span of double values into byte values.
 27.1492 +     */
 27.1493 +    // REMIND: remove once hotspot inlines Double.doubleToLongBits
 27.1494 +    private static native void doublesToBytes(double[] src, int srcpos,
 27.1495 +                                              byte[] dst, int dstpos,
 27.1496 +                                              int ndoubles);
 27.1497 +
 27.1498 +    /**
 27.1499 +     * Default PutField implementation.
 27.1500 +     */
 27.1501 +    private class PutFieldImpl extends PutField {
 27.1502 +
 27.1503 +        /** class descriptor describing serializable fields */
 27.1504 +        private final ObjectStreamClass desc;
 27.1505 +        /** primitive field values */
 27.1506 +        private final byte[] primVals;
 27.1507 +        /** object field values */
 27.1508 +        private final Object[] objVals;
 27.1509 +
 27.1510 +        /**
 27.1511 +         * Creates PutFieldImpl object for writing fields defined in given
 27.1512 +         * class descriptor.
 27.1513 +         */
 27.1514 +        PutFieldImpl(ObjectStreamClass desc) {
 27.1515 +            this.desc = desc;
 27.1516 +            primVals = new byte[desc.getPrimDataSize()];
 27.1517 +            objVals = new Object[desc.getNumObjFields()];
 27.1518 +        }
 27.1519 +
 27.1520 +        public void put(String name, boolean val) {
 27.1521 +            Bits.putBoolean(primVals, getFieldOffset(name, Boolean.TYPE), val);
 27.1522 +        }
 27.1523 +
 27.1524 +        public void put(String name, byte val) {
 27.1525 +            primVals[getFieldOffset(name, Byte.TYPE)] = val;
 27.1526 +        }
 27.1527 +
 27.1528 +        public void put(String name, char val) {
 27.1529 +            Bits.putChar(primVals, getFieldOffset(name, Character.TYPE), val);
 27.1530 +        }
 27.1531 +
 27.1532 +        public void put(String name, short val) {
 27.1533 +            Bits.putShort(primVals, getFieldOffset(name, Short.TYPE), val);
 27.1534 +        }
 27.1535 +
 27.1536 +        public void put(String name, int val) {
 27.1537 +            Bits.putInt(primVals, getFieldOffset(name, Integer.TYPE), val);
 27.1538 +        }
 27.1539 +
 27.1540 +        public void put(String name, float val) {
 27.1541 +            Bits.putFloat(primVals, getFieldOffset(name, Float.TYPE), val);
 27.1542 +        }
 27.1543 +
 27.1544 +        public void put(String name, long val) {
 27.1545 +            Bits.putLong(primVals, getFieldOffset(name, Long.TYPE), val);
 27.1546 +        }
 27.1547 +
 27.1548 +        public void put(String name, double val) {
 27.1549 +            Bits.putDouble(primVals, getFieldOffset(name, Double.TYPE), val);
 27.1550 +        }
 27.1551 +
 27.1552 +        public void put(String name, Object val) {
 27.1553 +            objVals[getFieldOffset(name, Object.class)] = val;
 27.1554 +        }
 27.1555 +
 27.1556 +        // deprecated in ObjectOutputStream.PutField
 27.1557 +        public void write(ObjectOutput out) throws IOException {
 27.1558 +            /*
 27.1559 +             * Applications should *not* use this method to write PutField
 27.1560 +             * data, as it will lead to stream corruption if the PutField
 27.1561 +             * object writes any primitive data (since block data mode is not
 27.1562 +             * unset/set properly, as is done in OOS.writeFields()).  This
 27.1563 +             * broken implementation is being retained solely for behavioral
 27.1564 +             * compatibility, in order to support applications which use
 27.1565 +             * OOS.PutField.write() for writing only non-primitive data.
 27.1566 +             *
 27.1567 +             * Serialization of unshared objects is not implemented here since
 27.1568 +             * it is not necessary for backwards compatibility; also, unshared
 27.1569 +             * semantics may not be supported by the given ObjectOutput
 27.1570 +             * instance.  Applications which write unshared objects using the
 27.1571 +             * PutField API must use OOS.writeFields().
 27.1572 +             */
 27.1573 +            if (ObjectOutputStream.this != out) {
 27.1574 +                throw new IllegalArgumentException("wrong stream");
 27.1575 +            }
 27.1576 +            out.write(primVals, 0, primVals.length);
 27.1577 +
 27.1578 +            ObjectStreamField[] fields = desc.getFields(false);
 27.1579 +            int numPrimFields = fields.length - objVals.length;
 27.1580 +            // REMIND: warn if numPrimFields > 0?
 27.1581 +            for (int i = 0; i < objVals.length; i++) {
 27.1582 +                if (fields[numPrimFields + i].isUnshared()) {
 27.1583 +                    throw new IOException("cannot write unshared object");
 27.1584 +                }
 27.1585 +                out.writeObject(objVals[i]);
 27.1586 +            }
 27.1587 +        }
 27.1588 +
 27.1589 +        /**
 27.1590 +         * Writes buffered primitive data and object fields to stream.
 27.1591 +         */
 27.1592 +        void writeFields() throws IOException {
 27.1593 +            bout.write(primVals, 0, primVals.length, false);
 27.1594 +
 27.1595 +            ObjectStreamField[] fields = desc.getFields(false);
 27.1596 +            int numPrimFields = fields.length - objVals.length;
 27.1597 +            for (int i = 0; i < objVals.length; i++) {
 27.1598 +                if (extendedDebugInfo) {
 27.1599 +                    debugInfoStack.push(
 27.1600 +                        "field (class \"" + desc.getName() + "\", name: \"" +
 27.1601 +                        fields[numPrimFields + i].getName() + "\", type: \"" +
 27.1602 +                        fields[numPrimFields + i].getType() + "\")");
 27.1603 +                }
 27.1604 +                try {
 27.1605 +                    writeObject0(objVals[i],
 27.1606 +                                 fields[numPrimFields + i].isUnshared());
 27.1607 +                } finally {
 27.1608 +                    if (extendedDebugInfo) {
 27.1609 +                        debugInfoStack.pop();
 27.1610 +                    }
 27.1611 +                }
 27.1612 +            }
 27.1613 +        }
 27.1614 +
 27.1615 +        /**
 27.1616 +         * Returns offset of field with given name and type.  A specified type
 27.1617 +         * of null matches all types, Object.class matches all non-primitive
 27.1618 +         * types, and any other non-null type matches assignable types only.
 27.1619 +         * Throws IllegalArgumentException if no matching field found.
 27.1620 +         */
 27.1621 +        private int getFieldOffset(String name, Class type) {
 27.1622 +            ObjectStreamField field = desc.getField(name, type);
 27.1623 +            if (field == null) {
 27.1624 +                throw new IllegalArgumentException("no such field " + name +
 27.1625 +                                                   " with type " + type);
 27.1626 +            }
 27.1627 +            return field.getOffset();
 27.1628 +        }
 27.1629 +    }
 27.1630 +
 27.1631 +    /**
 27.1632 +     * Buffered output stream with two modes: in default mode, outputs data in
 27.1633 +     * same format as DataOutputStream; in "block data" mode, outputs data
 27.1634 +     * bracketed by block data markers (see object serialization specification
 27.1635 +     * for details).
 27.1636 +     */
 27.1637 +    private static class BlockDataOutputStream
 27.1638 +        extends OutputStream implements DataOutput
 27.1639 +    {
 27.1640 +        /** maximum data block length */
 27.1641 +        private static final int MAX_BLOCK_SIZE = 1024;
 27.1642 +        /** maximum data block header length */
 27.1643 +        private static final int MAX_HEADER_SIZE = 5;
 27.1644 +        /** (tunable) length of char buffer (for writing strings) */
 27.1645 +        private static final int CHAR_BUF_SIZE = 256;
 27.1646 +
 27.1647 +        /** buffer for writing general/block data */
 27.1648 +        private final byte[] buf = new byte[MAX_BLOCK_SIZE];
 27.1649 +        /** buffer for writing block data headers */
 27.1650 +        private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
 27.1651 +        /** char buffer for fast string writes */
 27.1652 +        private final char[] cbuf = new char[CHAR_BUF_SIZE];
 27.1653 +
 27.1654 +        /** block data mode */
 27.1655 +        private boolean blkmode = false;
 27.1656 +        /** current offset into buf */
 27.1657 +        private int pos = 0;
 27.1658 +
 27.1659 +        /** underlying output stream */
 27.1660 +        private final OutputStream out;
 27.1661 +        /** loopback stream (for data writes that span data blocks) */
 27.1662 +        private final DataOutputStream dout;
 27.1663 +
 27.1664 +        /**
 27.1665 +         * Creates new BlockDataOutputStream on top of given underlying stream.
 27.1666 +         * Block data mode is turned off by default.
 27.1667 +         */
 27.1668 +        BlockDataOutputStream(OutputStream out) {
 27.1669 +            this.out = out;
 27.1670 +            dout = new DataOutputStream(this);
 27.1671 +        }
 27.1672 +
 27.1673 +        /**
 27.1674 +         * Sets block data mode to the given mode (true == on, false == off)
 27.1675 +         * and returns the previous mode value.  If the new mode is the same as
 27.1676 +         * the old mode, no action is taken.  If the new mode differs from the
 27.1677 +         * old mode, any buffered data is flushed before switching to the new
 27.1678 +         * mode.
 27.1679 +         */
 27.1680 +        boolean setBlockDataMode(boolean mode) throws IOException {
 27.1681 +            if (blkmode == mode) {
 27.1682 +                return blkmode;
 27.1683 +            }
 27.1684 +            drain();
 27.1685 +            blkmode = mode;
 27.1686 +            return !blkmode;
 27.1687 +        }
 27.1688 +
 27.1689 +        /**
 27.1690 +         * Returns true if the stream is currently in block data mode, false
 27.1691 +         * otherwise.
 27.1692 +         */
 27.1693 +        boolean getBlockDataMode() {
 27.1694 +            return blkmode;
 27.1695 +        }
 27.1696 +
 27.1697 +        /* ----------------- generic output stream methods ----------------- */
 27.1698 +        /*
 27.1699 +         * The following methods are equivalent to their counterparts in
 27.1700 +         * OutputStream, except that they partition written data into data
 27.1701 +         * blocks when in block data mode.
 27.1702 +         */
 27.1703 +
 27.1704 +        public void write(int b) throws IOException {
 27.1705 +            if (pos >= MAX_BLOCK_SIZE) {
 27.1706 +                drain();
 27.1707 +            }
 27.1708 +            buf[pos++] = (byte) b;
 27.1709 +        }
 27.1710 +
 27.1711 +        public void write(byte[] b) throws IOException {
 27.1712 +            write(b, 0, b.length, false);
 27.1713 +        }
 27.1714 +
 27.1715 +        public void write(byte[] b, int off, int len) throws IOException {
 27.1716 +            write(b, off, len, false);
 27.1717 +        }
 27.1718 +
 27.1719 +        public void flush() throws IOException {
 27.1720 +            drain();
 27.1721 +            out.flush();
 27.1722 +        }
 27.1723 +
 27.1724 +        public void close() throws IOException {
 27.1725 +            flush();
 27.1726 +            out.close();
 27.1727 +        }
 27.1728 +
 27.1729 +        /**
 27.1730 +         * Writes specified span of byte values from given array.  If copy is
 27.1731 +         * true, copies the values to an intermediate buffer before writing
 27.1732 +         * them to underlying stream (to avoid exposing a reference to the
 27.1733 +         * original byte array).
 27.1734 +         */
 27.1735 +        void write(byte[] b, int off, int len, boolean copy)
 27.1736 +            throws IOException
 27.1737 +        {
 27.1738 +            if (!(copy || blkmode)) {           // write directly
 27.1739 +                drain();
 27.1740 +                out.write(b, off, len);
 27.1741 +                return;
 27.1742 +            }
 27.1743 +
 27.1744 +            while (len > 0) {
 27.1745 +                if (pos >= MAX_BLOCK_SIZE) {
 27.1746 +                    drain();
 27.1747 +                }
 27.1748 +                if (len >= MAX_BLOCK_SIZE && !copy && pos == 0) {
 27.1749 +                    // avoid unnecessary copy
 27.1750 +                    writeBlockHeader(MAX_BLOCK_SIZE);
 27.1751 +                    out.write(b, off, MAX_BLOCK_SIZE);
 27.1752 +                    off += MAX_BLOCK_SIZE;
 27.1753 +                    len -= MAX_BLOCK_SIZE;
 27.1754 +                } else {
 27.1755 +                    int wlen = Math.min(len, MAX_BLOCK_SIZE - pos);
 27.1756 +                    System.arraycopy(b, off, buf, pos, wlen);
 27.1757 +                    pos += wlen;
 27.1758 +                    off += wlen;
 27.1759 +                    len -= wlen;
 27.1760 +                }
 27.1761 +            }
 27.1762 +        }
 27.1763 +
 27.1764 +        /**
 27.1765 +         * Writes all buffered data from this stream to the underlying stream,
 27.1766 +         * but does not flush underlying stream.
 27.1767 +         */
 27.1768 +        void drain() throws IOException {
 27.1769 +            if (pos == 0) {
 27.1770 +                return;
 27.1771 +            }
 27.1772 +            if (blkmode) {
 27.1773 +                writeBlockHeader(pos);
 27.1774 +            }
 27.1775 +            out.write(buf, 0, pos);
 27.1776 +            pos = 0;
 27.1777 +        }
 27.1778 +
 27.1779 +        /**
 27.1780 +         * Writes block data header.  Data blocks shorter than 256 bytes are
 27.1781 +         * prefixed with a 2-byte header; all others start with a 5-byte
 27.1782 +         * header.
 27.1783 +         */
 27.1784 +        private void writeBlockHeader(int len) throws IOException {
 27.1785 +            if (len <= 0xFF) {
 27.1786 +                hbuf[0] = TC_BLOCKDATA;
 27.1787 +                hbuf[1] = (byte) len;
 27.1788 +                out.write(hbuf, 0, 2);
 27.1789 +            } else {
 27.1790 +                hbuf[0] = TC_BLOCKDATALONG;
 27.1791 +                Bits.putInt(hbuf, 1, len);
 27.1792 +                out.write(hbuf, 0, 5);
 27.1793 +            }
 27.1794 +        }
 27.1795 +
 27.1796 +
 27.1797 +        /* ----------------- primitive data output methods ----------------- */
 27.1798 +        /*
 27.1799 +         * The following methods are equivalent to their counterparts in
 27.1800 +         * DataOutputStream, except that they partition written data into data
 27.1801 +         * blocks when in block data mode.
 27.1802 +         */
 27.1803 +
 27.1804 +        public void writeBoolean(boolean v) throws IOException {
 27.1805 +            if (pos >= MAX_BLOCK_SIZE) {
 27.1806 +                drain();
 27.1807 +            }
 27.1808 +            Bits.putBoolean(buf, pos++, v);
 27.1809 +        }
 27.1810 +
 27.1811 +        public void writeByte(int v) throws IOException {
 27.1812 +            if (pos >= MAX_BLOCK_SIZE) {
 27.1813 +                drain();
 27.1814 +            }
 27.1815 +            buf[pos++] = (byte) v;
 27.1816 +        }
 27.1817 +
 27.1818 +        public void writeChar(int v) throws IOException {
 27.1819 +            if (pos + 2 <= MAX_BLOCK_SIZE) {
 27.1820 +                Bits.putChar(buf, pos, (char) v);
 27.1821 +                pos += 2;
 27.1822 +            } else {
 27.1823 +                dout.writeChar(v);
 27.1824 +            }
 27.1825 +        }
 27.1826 +
 27.1827 +        public void writeShort(int v) throws IOException {
 27.1828 +            if (pos + 2 <= MAX_BLOCK_SIZE) {
 27.1829 +                Bits.putShort(buf, pos, (short) v);
 27.1830 +                pos += 2;
 27.1831 +            } else {
 27.1832 +                dout.writeShort(v);
 27.1833 +            }
 27.1834 +        }
 27.1835 +
 27.1836 +        public void writeInt(int v) throws IOException {
 27.1837 +            if (pos + 4 <= MAX_BLOCK_SIZE) {
 27.1838 +                Bits.putInt(buf, pos, v);
 27.1839 +                pos += 4;
 27.1840 +            } else {
 27.1841 +                dout.writeInt(v);
 27.1842 +            }
 27.1843 +        }
 27.1844 +
 27.1845 +        public void writeFloat(float v) throws IOException {
 27.1846 +            if (pos + 4 <= MAX_BLOCK_SIZE) {
 27.1847 +                Bits.putFloat(buf, pos, v);
 27.1848 +                pos += 4;
 27.1849 +            } else {
 27.1850 +                dout.writeFloat(v);
 27.1851 +            }
 27.1852 +        }
 27.1853 +
 27.1854 +        public void writeLong(long v) throws IOException {
 27.1855 +            if (pos + 8 <= MAX_BLOCK_SIZE) {
 27.1856 +                Bits.putLong(buf, pos, v);
 27.1857 +                pos += 8;
 27.1858 +            } else {
 27.1859 +                dout.writeLong(v);
 27.1860 +            }
 27.1861 +        }
 27.1862 +
 27.1863 +        public void writeDouble(double v) throws IOException {
 27.1864 +            if (pos + 8 <= MAX_BLOCK_SIZE) {
 27.1865 +                Bits.putDouble(buf, pos, v);
 27.1866 +                pos += 8;
 27.1867 +            } else {
 27.1868 +                dout.writeDouble(v);
 27.1869 +            }
 27.1870 +        }
 27.1871 +
 27.1872 +        public void writeBytes(String s) throws IOException {
 27.1873 +            int endoff = s.length();
 27.1874 +            int cpos = 0;
 27.1875 +            int csize = 0;
 27.1876 +            for (int off = 0; off < endoff; ) {
 27.1877 +                if (cpos >= csize) {
 27.1878 +                    cpos = 0;
 27.1879 +                    csize = Math.min(endoff - off, CHAR_BUF_SIZE);
 27.1880 +                    s.getChars(off, off + csize, cbuf, 0);
 27.1881 +                }
 27.1882 +                if (pos >= MAX_BLOCK_SIZE) {
 27.1883 +                    drain();
 27.1884 +                }
 27.1885 +                int n = Math.min(csize - cpos, MAX_BLOCK_SIZE - pos);
 27.1886 +                int stop = pos + n;
 27.1887 +                while (pos < stop) {
 27.1888 +                    buf[pos++] = (byte) cbuf[cpos++];
 27.1889 +                }
 27.1890 +                off += n;
 27.1891 +            }
 27.1892 +        }
 27.1893 +
 27.1894 +        public void writeChars(String s) throws IOException {
 27.1895 +            int endoff = s.length();
 27.1896 +            for (int off = 0; off < endoff; ) {
 27.1897 +                int csize = Math.min(endoff - off, CHAR_BUF_SIZE);
 27.1898 +                s.getChars(off, off + csize, cbuf, 0);
 27.1899 +                writeChars(cbuf, 0, csize);
 27.1900 +                off += csize;
 27.1901 +            }
 27.1902 +        }
 27.1903 +
 27.1904 +        public void writeUTF(String s) throws IOException {
 27.1905 +            writeUTF(s, getUTFLength(s));
 27.1906 +        }
 27.1907 +
 27.1908 +
 27.1909 +        /* -------------- primitive data array output methods -------------- */
 27.1910 +        /*
 27.1911 +         * The following methods write out spans of primitive data values.
 27.1912 +         * Though equivalent to calling the corresponding primitive write
 27.1913 +         * methods repeatedly, these methods are optimized for writing groups
 27.1914 +         * of primitive data values more efficiently.
 27.1915 +         */
 27.1916 +
 27.1917 +        void writeBooleans(boolean[] v, int off, int len) throws IOException {
 27.1918 +            int endoff = off + len;
 27.1919 +            while (off < endoff) {
 27.1920 +                if (pos >= MAX_BLOCK_SIZE) {
 27.1921 +                    drain();
 27.1922 +                }
 27.1923 +                int stop = Math.min(endoff, off + (MAX_BLOCK_SIZE - pos));
 27.1924 +                while (off < stop) {
 27.1925 +                    Bits.putBoolean(buf, pos++, v[off++]);
 27.1926 +                }
 27.1927 +            }
 27.1928 +        }
 27.1929 +
 27.1930 +        void writeChars(char[] v, int off, int len) throws IOException {
 27.1931 +            int limit = MAX_BLOCK_SIZE - 2;
 27.1932 +            int endoff = off + len;
 27.1933 +            while (off < endoff) {
 27.1934 +                if (pos <= limit) {
 27.1935 +                    int avail = (MAX_BLOCK_SIZE - pos) >> 1;
 27.1936 +                    int stop = Math.min(endoff, off + avail);
 27.1937 +                    while (off < stop) {
 27.1938 +                        Bits.putChar(buf, pos, v[off++]);
 27.1939 +                        pos += 2;
 27.1940 +                    }
 27.1941 +                } else {
 27.1942 +                    dout.writeChar(v[off++]);
 27.1943 +                }
 27.1944 +            }
 27.1945 +        }
 27.1946 +
 27.1947 +        void writeShorts(short[] v, int off, int len) throws IOException {
 27.1948 +            int limit = MAX_BLOCK_SIZE - 2;
 27.1949 +            int endoff = off + len;
 27.1950 +            while (off < endoff) {
 27.1951 +                if (pos <= limit) {
 27.1952 +                    int avail = (MAX_BLOCK_SIZE - pos) >> 1;
 27.1953 +                    int stop = Math.min(endoff, off + avail);
 27.1954 +                    while (off < stop) {
 27.1955 +                        Bits.putShort(buf, pos, v[off++]);
 27.1956 +                        pos += 2;
 27.1957 +                    }
 27.1958 +                } else {
 27.1959 +                    dout.writeShort(v[off++]);
 27.1960 +                }
 27.1961 +            }
 27.1962 +        }
 27.1963 +
 27.1964 +        void writeInts(int[] v, int off, int len) throws IOException {
 27.1965 +            int limit = MAX_BLOCK_SIZE - 4;
 27.1966 +            int endoff = off + len;
 27.1967 +            while (off < endoff) {
 27.1968 +                if (pos <= limit) {
 27.1969 +                    int avail = (MAX_BLOCK_SIZE - pos) >> 2;
 27.1970 +                    int stop = Math.min(endoff, off + avail);
 27.1971 +                    while (off < stop) {
 27.1972 +                        Bits.putInt(buf, pos, v[off++]);
 27.1973 +                        pos += 4;
 27.1974 +                    }
 27.1975 +                } else {
 27.1976 +                    dout.writeInt(v[off++]);
 27.1977 +                }
 27.1978 +            }
 27.1979 +        }
 27.1980 +
 27.1981 +        void writeFloats(float[] v, int off, int len) throws IOException {
 27.1982 +            int limit = MAX_BLOCK_SIZE - 4;
 27.1983 +            int endoff = off + len;
 27.1984 +            while (off < endoff) {
 27.1985 +                if (pos <= limit) {
 27.1986 +                    int avail = (MAX_BLOCK_SIZE - pos) >> 2;
 27.1987 +                    int chunklen = Math.min(endoff - off, avail);
 27.1988 +                    floatsToBytes(v, off, buf, pos, chunklen);
 27.1989 +                    off += chunklen;
 27.1990 +                    pos += chunklen << 2;
 27.1991 +                } else {
 27.1992 +                    dout.writeFloat(v[off++]);
 27.1993 +                }
 27.1994 +            }
 27.1995 +        }
 27.1996 +
 27.1997 +        void writeLongs(long[] v, int off, int len) throws IOException {
 27.1998 +            int limit = MAX_BLOCK_SIZE - 8;
 27.1999 +            int endoff = off + len;
 27.2000 +            while (off < endoff) {
 27.2001 +                if (pos <= limit) {
 27.2002 +                    int avail = (MAX_BLOCK_SIZE - pos) >> 3;
 27.2003 +                    int stop = Math.min(endoff, off + avail);
 27.2004 +                    while (off < stop) {
 27.2005 +                        Bits.putLong(buf, pos, v[off++]);
 27.2006 +                        pos += 8;
 27.2007 +                    }
 27.2008 +                } else {
 27.2009 +                    dout.writeLong(v[off++]);
 27.2010 +                }
 27.2011 +            }
 27.2012 +        }
 27.2013 +
 27.2014 +        void writeDoubles(double[] v, int off, int len) throws IOException {
 27.2015 +            int limit = MAX_BLOCK_SIZE - 8;
 27.2016 +            int endoff = off + len;
 27.2017 +            while (off < endoff) {
 27.2018 +                if (pos <= limit) {
 27.2019 +                    int avail = (MAX_BLOCK_SIZE - pos) >> 3;
 27.2020 +                    int chunklen = Math.min(endoff - off, avail);
 27.2021 +                    doublesToBytes(v, off, buf, pos, chunklen);
 27.2022 +                    off += chunklen;
 27.2023 +                    pos += chunklen << 3;
 27.2024 +                } else {
 27.2025 +                    dout.writeDouble(v[off++]);
 27.2026 +                }
 27.2027 +            }
 27.2028 +        }
 27.2029 +
 27.2030 +        /**
 27.2031 +         * Returns the length in bytes of the UTF encoding of the given string.
 27.2032 +         */
 27.2033 +        long getUTFLength(String s) {
 27.2034 +            int len = s.length();
 27.2035 +            long utflen = 0;
 27.2036 +            for (int off = 0; off < len; ) {
 27.2037 +                int csize = Math.min(len - off, CHAR_BUF_SIZE);
 27.2038 +                s.getChars(off, off + csize, cbuf, 0);
 27.2039 +                for (int cpos = 0; cpos < csize; cpos++) {
 27.2040 +                    char c = cbuf[cpos];
 27.2041 +                    if (c >= 0x0001 && c <= 0x007F) {
 27.2042 +                        utflen++;
 27.2043 +                    } else if (c > 0x07FF) {
 27.2044 +                        utflen += 3;
 27.2045 +                    } else {
 27.2046 +                        utflen += 2;
 27.2047 +                    }
 27.2048 +                }
 27.2049 +                off += csize;
 27.2050 +            }
 27.2051 +            return utflen;
 27.2052 +        }
 27.2053 +
 27.2054 +        /**
 27.2055 +         * Writes the given string in UTF format.  This method is used in
 27.2056 +         * situations where the UTF encoding length of the string is already
 27.2057 +         * known; specifying it explicitly avoids a prescan of the string to
 27.2058 +         * determine its UTF length.
 27.2059 +         */
 27.2060 +        void writeUTF(String s, long utflen) throws IOException {
 27.2061 +            if (utflen > 0xFFFFL) {
 27.2062 +                throw new UTFDataFormatException();
 27.2063 +            }
 27.2064 +            writeShort((int) utflen);
 27.2065 +            if (utflen == (long) s.length()) {
 27.2066 +                writeBytes(s);
 27.2067 +            } else {
 27.2068 +                writeUTFBody(s);
 27.2069 +            }
 27.2070 +        }
 27.2071 +
 27.2072 +        /**
 27.2073 +         * Writes given string in "long" UTF format.  "Long" UTF format is
 27.2074 +         * identical to standard UTF, except that it uses an 8 byte header
 27.2075 +         * (instead of the standard 2 bytes) to convey the UTF encoding length.
 27.2076 +         */
 27.2077 +        void writeLongUTF(String s) throws IOException {
 27.2078 +            writeLongUTF(s, getUTFLength(s));
 27.2079 +        }
 27.2080 +
 27.2081 +        /**
 27.2082 +         * Writes given string in "long" UTF format, where the UTF encoding
 27.2083 +         * length of the string is already known.
 27.2084 +         */
 27.2085 +        void writeLongUTF(String s, long utflen) throws IOException {
 27.2086 +            writeLong(utflen);
 27.2087 +            if (utflen == (long) s.length()) {
 27.2088 +                writeBytes(s);
 27.2089 +            } else {
 27.2090 +                writeUTFBody(s);
 27.2091 +            }
 27.2092 +        }
 27.2093 +
 27.2094 +        /**
 27.2095 +         * Writes the "body" (i.e., the UTF representation minus the 2-byte or
 27.2096 +         * 8-byte length header) of the UTF encoding for the given string.
 27.2097 +         */
 27.2098 +        private void writeUTFBody(String s) throws IOException {
 27.2099 +            int limit = MAX_BLOCK_SIZE - 3;
 27.2100 +            int len = s.length();
 27.2101 +            for (int off = 0; off < len; ) {
 27.2102 +                int csize = Math.min(len - off, CHAR_BUF_SIZE);
 27.2103 +                s.getChars(off, off + csize, cbuf, 0);
 27.2104 +                for (int cpos = 0; cpos < csize; cpos++) {
 27.2105 +                    char c = cbuf[cpos];
 27.2106 +                    if (pos <= limit) {
 27.2107 +                        if (c <= 0x007F && c != 0) {
 27.2108 +                            buf[pos++] = (byte) c;
 27.2109 +                        } else if (c > 0x07FF) {
 27.2110 +                            buf[pos + 2] = (byte) (0x80 | ((c >> 0) & 0x3F));
 27.2111 +                            buf[pos + 1] = (byte) (0x80 | ((c >> 6) & 0x3F));
 27.2112 +                            buf[pos + 0] = (byte) (0xE0 | ((c >> 12) & 0x0F));
 27.2113 +                            pos += 3;
 27.2114 +                        } else {
 27.2115 +                            buf[pos + 1] = (byte) (0x80 | ((c >> 0) & 0x3F));
 27.2116 +                            buf[pos + 0] = (byte) (0xC0 | ((c >> 6) & 0x1F));
 27.2117 +                            pos += 2;
 27.2118 +                        }
 27.2119 +                    } else {    // write one byte at a time to normalize block
 27.2120 +                        if (c <= 0x007F && c != 0) {
 27.2121 +                            write(c);
 27.2122 +                        } else if (c > 0x07FF) {
 27.2123 +                            write(0xE0 | ((c >> 12) & 0x0F));
 27.2124 +                            write(0x80 | ((c >> 6) & 0x3F));
 27.2125 +                            write(0x80 | ((c >> 0) & 0x3F));
 27.2126 +                        } else {
 27.2127 +                            write(0xC0 | ((c >> 6) & 0x1F));
 27.2128 +                            write(0x80 | ((c >> 0) & 0x3F));
 27.2129 +                        }
 27.2130 +                    }
 27.2131 +                }
 27.2132 +                off += csize;
 27.2133 +            }
 27.2134 +        }
 27.2135 +    }
 27.2136 +
 27.2137 +    /**
 27.2138 +     * Lightweight identity hash table which maps objects to integer handles,
 27.2139 +     * assigned in ascending order.
 27.2140 +     */
 27.2141 +    private static class HandleTable {
 27.2142 +
 27.2143 +        /* number of mappings in table/next available handle */
 27.2144 +        private int size;
 27.2145 +        /* size threshold determining when to expand hash spine */
 27.2146 +        private int threshold;
 27.2147 +        /* factor for computing size threshold */
 27.2148 +        private final float loadFactor;
 27.2149 +        /* maps hash value -> candidate handle value */
 27.2150 +        private int[] spine;
 27.2151 +        /* maps handle value -> next candidate handle value */
 27.2152 +        private int[] next;
 27.2153 +        /* maps handle value -> associated object */
 27.2154 +        private Object[] objs;
 27.2155 +
 27.2156 +        /**
 27.2157 +         * Creates new HandleTable with given capacity and load factor.
 27.2158 +         */
 27.2159 +        HandleTable(int initialCapacity, float loadFactor) {
 27.2160 +            this.loadFactor = loadFactor;
 27.2161 +            spine = new int[initialCapacity];
 27.2162 +            next = new int[initialCapacity];
 27.2163 +            objs = new Object[initialCapacity];
 27.2164 +            threshold = (int) (initialCapacity * loadFactor);
 27.2165 +            clear();
 27.2166 +        }
 27.2167 +
 27.2168 +        /**
 27.2169 +         * Assigns next available handle to given object, and returns handle
 27.2170 +         * value.  Handles are assigned in ascending order starting at 0.
 27.2171 +         */
 27.2172 +        int assign(Object obj) {
 27.2173 +            if (size >= next.length) {
 27.2174 +                growEntries();
 27.2175 +            }
 27.2176 +            if (size >= threshold) {
 27.2177 +                growSpine();
 27.2178 +            }
 27.2179 +            insert(obj, size);
 27.2180 +            return size++;
 27.2181 +        }
 27.2182 +
 27.2183 +        /**
 27.2184 +         * Looks up and returns handle associated with given object, or -1 if
 27.2185 +         * no mapping found.
 27.2186 +         */
 27.2187 +        int lookup(Object obj) {
 27.2188 +            if (size == 0) {
 27.2189 +                return -1;
 27.2190 +            }
 27.2191 +            int index = hash(obj) % spine.length;
 27.2192 +            for (int i = spine[index]; i >= 0; i = next[i]) {
 27.2193 +                if (objs[i] == obj) {
 27.2194 +                    return i;
 27.2195 +                }
 27.2196 +            }
 27.2197 +            return -1;
 27.2198 +        }
 27.2199 +
 27.2200 +        /**
 27.2201 +         * Resets table to its initial (empty) state.
 27.2202 +         */
 27.2203 +        void clear() {
 27.2204 +            Arrays.fill(spine, -1);
 27.2205 +            Arrays.fill(objs, 0, size, null);
 27.2206 +            size = 0;
 27.2207 +        }
 27.2208 +
 27.2209 +        /**
 27.2210 +         * Returns the number of mappings currently in table.
 27.2211 +         */
 27.2212 +        int size() {
 27.2213 +            return size;
 27.2214 +        }
 27.2215 +
 27.2216 +        /**
 27.2217 +         * Inserts mapping object -> handle mapping into table.  Assumes table
 27.2218 +         * is large enough to accommodate new mapping.
 27.2219 +         */
 27.2220 +        private void insert(Object obj, int handle) {
 27.2221 +            int index = hash(obj) % spine.length;
 27.2222 +            objs[handle] = obj;
 27.2223 +            next[handle] = spine[index];
 27.2224 +            spine[index] = handle;
 27.2225 +        }
 27.2226 +
 27.2227 +        /**
 27.2228 +         * Expands the hash "spine" -- equivalent to increasing the number of
 27.2229 +         * buckets in a conventional hash table.
 27.2230 +         */
 27.2231 +        private void growSpine() {
 27.2232 +            spine = new int[(spine.length << 1) + 1];
 27.2233 +            threshold = (int) (spine.length * loadFactor);
 27.2234 +            Arrays.fill(spine, -1);
 27.2235 +            for (int i = 0; i < size; i++) {
 27.2236 +                insert(objs[i], i);
 27.2237 +            }
 27.2238 +        }
 27.2239 +
 27.2240 +        /**
 27.2241 +         * Increases hash table capacity by lengthening entry arrays.
 27.2242 +         */
 27.2243 +        private void growEntries() {
 27.2244 +            int newLength = (next.length << 1) + 1;
 27.2245 +            int[] newNext = new int[newLength];
 27.2246 +            System.arraycopy(next, 0, newNext, 0, size);
 27.2247 +            next = newNext;
 27.2248 +
 27.2249 +            Object[] newObjs = new Object[newLength];
 27.2250 +            System.arraycopy(objs, 0, newObjs, 0, size);
 27.2251 +            objs = newObjs;
 27.2252 +        }
 27.2253 +
 27.2254 +        /**
 27.2255 +         * Returns hash value for given object.
 27.2256 +         */
 27.2257 +        private int hash(Object obj) {
 27.2258 +            return System.identityHashCode(obj) & 0x7FFFFFFF;
 27.2259 +        }
 27.2260 +    }
 27.2261 +
 27.2262 +    /**
 27.2263 +     * Lightweight identity hash table which maps objects to replacement
 27.2264 +     * objects.
 27.2265 +     */
 27.2266 +    private static class ReplaceTable {
 27.2267 +
 27.2268 +        /* maps object -> index */
 27.2269 +        private final HandleTable htab;
 27.2270 +        /* maps index -> replacement object */
 27.2271 +        private Object[] reps;
 27.2272 +
 27.2273 +        /**
 27.2274 +         * Creates new ReplaceTable with given capacity and load factor.
 27.2275 +         */
 27.2276 +        ReplaceTable(int initialCapacity, float loadFactor) {
 27.2277 +            htab = new HandleTable(initialCapacity, loadFactor);
 27.2278 +            reps = new Object[initialCapacity];
 27.2279 +        }
 27.2280 +
 27.2281 +        /**
 27.2282 +         * Enters mapping from object to replacement object.
 27.2283 +         */
 27.2284 +        void assign(Object obj, Object rep) {
 27.2285 +            int index = htab.assign(obj);
 27.2286 +            while (index >= reps.length) {
 27.2287 +                grow();
 27.2288 +            }
 27.2289 +            reps[index] = rep;
 27.2290 +        }
 27.2291 +
 27.2292 +        /**
 27.2293 +         * Looks up and returns replacement for given object.  If no
 27.2294 +         * replacement is found, returns the lookup object itself.
 27.2295 +         */
 27.2296 +        Object lookup(Object obj) {
 27.2297 +            int index = htab.lookup(obj);
 27.2298 +            return (index >= 0) ? reps[index] : obj;
 27.2299 +        }
 27.2300 +
 27.2301 +        /**
 27.2302 +         * Resets table to its initial (empty) state.
 27.2303 +         */
 27.2304 +        void clear() {
 27.2305 +            Arrays.fill(reps, 0, htab.size(), null);
 27.2306 +            htab.clear();
 27.2307 +        }
 27.2308 +
 27.2309 +        /**
 27.2310 +         * Returns the number of mappings currently in table.
 27.2311 +         */
 27.2312 +        int size() {
 27.2313 +            return htab.size();
 27.2314 +        }
 27.2315 +
 27.2316 +        /**
 27.2317 +         * Increases table capacity.
 27.2318 +         */
 27.2319 +        private void grow() {
 27.2320 +            Object[] newReps = new Object[(reps.length << 1) + 1];
 27.2321 +            System.arraycopy(reps, 0, newReps, 0, reps.length);
 27.2322 +            reps = newReps;
 27.2323 +        }
 27.2324 +    }
 27.2325 +
 27.2326 +    /**
 27.2327 +     * Stack to keep debug information about the state of the
 27.2328 +     * serialization process, for embedding in exception messages.
 27.2329 +     */
 27.2330 +    private static class DebugTraceInfoStack {
 27.2331 +        private final List<String> stack;
 27.2332 +
 27.2333 +        DebugTraceInfoStack() {
 27.2334 +            stack = new ArrayList<>();
 27.2335 +        }
 27.2336 +
 27.2337 +        /**
 27.2338 +         * Removes all of the elements from enclosed list.
 27.2339 +         */
 27.2340 +        void clear() {
 27.2341 +            stack.clear();
 27.2342 +        }
 27.2343 +
 27.2344 +        /**
 27.2345 +         * Removes the object at the top of enclosed list.
 27.2346 +         */
 27.2347 +        void pop() {
 27.2348 +            stack.remove(stack.size()-1);
 27.2349 +        }
 27.2350 +
 27.2351 +        /**
 27.2352 +         * Pushes a String onto the top of enclosed list.
 27.2353 +         */
 27.2354 +        void push(String entry) {
 27.2355 +            stack.add("\t- " + entry);
 27.2356 +        }
 27.2357 +
 27.2358 +        /**
 27.2359 +         * Returns a string representation of this object
 27.2360 +         */
 27.2361 +        public String toString() {
 27.2362 +            StringBuilder buffer = new StringBuilder();
 27.2363 +            if (!stack.isEmpty()) {
 27.2364 +                for(int i = stack.size(); i > 0; i-- ) {
 27.2365 +                    buffer.append(stack.get(i-1) + ((i != 1) ? "\n" : ""));
 27.2366 +                }
 27.2367 +            }
 27.2368 +            return buffer.toString();
 27.2369 +        }
 27.2370 +    }
 27.2371 +
 27.2372 +}
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/emul/compact/src/main/java/java/io/ObjectStreamClass.java	Mon Feb 04 09:37:56 2013 +0100
    28.3 @@ -0,0 +1,1396 @@
    28.4 +/*
    28.5 + * Copyright (c) 1996, 2011, 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 +import java.lang.ref.Reference;
   28.32 +import java.lang.ref.ReferenceQueue;
   28.33 +import java.lang.ref.SoftReference;
   28.34 +import java.lang.ref.WeakReference;
   28.35 +import java.lang.reflect.Constructor;
   28.36 +import java.lang.reflect.Field;
   28.37 +import java.lang.reflect.InvocationTargetException;
   28.38 +import java.lang.reflect.Member;
   28.39 +import java.lang.reflect.Method;
   28.40 +import java.lang.reflect.Modifier;
   28.41 +import java.lang.reflect.Proxy;
   28.42 +import java.util.ArrayList;
   28.43 +import java.util.Arrays;
   28.44 +import java.util.Collections;
   28.45 +import java.util.Comparator;
   28.46 +import java.util.HashSet;
   28.47 +import java.util.Set;
   28.48 +
   28.49 +/**
   28.50 + * Serialization's descriptor for classes.  It contains the name and
   28.51 + * serialVersionUID of the class.  The ObjectStreamClass for a specific class
   28.52 + * loaded in this Java VM can be found/created using the lookup method.
   28.53 + *
   28.54 + * <p>The algorithm to compute the SerialVersionUID is described in
   28.55 + * <a href="../../../platform/serialization/spec/class.html#4100">Object
   28.56 + * Serialization Specification, Section 4.6, Stream Unique Identifiers</a>.
   28.57 + *
   28.58 + * @author      Mike Warres
   28.59 + * @author      Roger Riggs
   28.60 + * @see ObjectStreamField
   28.61 + * @see <a href="../../../platform/serialization/spec/class.html">Object Serialization Specification, Section 4, Class Descriptors</a>
   28.62 + * @since   JDK1.1
   28.63 + */
   28.64 +public class ObjectStreamClass implements Serializable {
   28.65 +
   28.66 +    /** serialPersistentFields value indicating no serializable fields */
   28.67 +    public static final ObjectStreamField[] NO_FIELDS =
   28.68 +        new ObjectStreamField[0];
   28.69 +
   28.70 +    private static final long serialVersionUID = -6120832682080437368L;
   28.71 +    private static final ObjectStreamField[] serialPersistentFields =
   28.72 +        NO_FIELDS;
   28.73 +
   28.74 +
   28.75 +    /** class associated with this descriptor (if any) */
   28.76 +    private Class<?> cl;
   28.77 +    /** name of class represented by this descriptor */
   28.78 +    private String name;
   28.79 +    /** serialVersionUID of represented class (null if not computed yet) */
   28.80 +    private volatile Long suid;
   28.81 +
   28.82 +    /** true if represents dynamic proxy class */
   28.83 +    private boolean isProxy;
   28.84 +    /** true if represents enum type */
   28.85 +    private boolean isEnum;
   28.86 +    /** true if represented class implements Serializable */
   28.87 +    private boolean serializable;
   28.88 +    /** true if represented class implements Externalizable */
   28.89 +    private boolean externalizable;
   28.90 +    /** true if desc has data written by class-defined writeObject method */
   28.91 +    private boolean hasWriteObjectData;
   28.92 +    /**
   28.93 +     * true if desc has externalizable data written in block data format; this
   28.94 +     * must be true by default to accommodate ObjectInputStream subclasses which
   28.95 +     * override readClassDescriptor() to return class descriptors obtained from
   28.96 +     * ObjectStreamClass.lookup() (see 4461737)
   28.97 +     */
   28.98 +    private boolean hasBlockExternalData = true;
   28.99 +
  28.100 +    /** exception (if any) thrown while attempting to resolve class */
  28.101 +    private ClassNotFoundException resolveEx;
  28.102 +    /** exception (if any) to throw if non-enum deserialization attempted */
  28.103 +    private InvalidClassException deserializeEx;
  28.104 +    /** exception (if any) to throw if non-enum serialization attempted */
  28.105 +    private InvalidClassException serializeEx;
  28.106 +    /** exception (if any) to throw if default serialization attempted */
  28.107 +    private InvalidClassException defaultSerializeEx;
  28.108 +
  28.109 +    /** serializable fields */
  28.110 +    private ObjectStreamField[] fields;
  28.111 +    /** aggregate marshalled size of primitive fields */
  28.112 +    private int primDataSize;
  28.113 +    /** number of non-primitive fields */
  28.114 +    private int numObjFields;
  28.115 +    /** reflector for setting/getting serializable field values */
  28.116 +//    private FieldReflector fieldRefl;
  28.117 +    /** data layout of serialized objects described by this class desc */
  28.118 +    private volatile ClassDataSlot[] dataLayout;
  28.119 +
  28.120 +    /** serialization-appropriate constructor, or null if none */
  28.121 +    private Constructor cons;
  28.122 +    /** class-defined writeObject method, or null if none */
  28.123 +    private Method writeObjectMethod;
  28.124 +    /** class-defined readObject method, or null if none */
  28.125 +    private Method readObjectMethod;
  28.126 +    /** class-defined readObjectNoData method, or null if none */
  28.127 +    private Method readObjectNoDataMethod;
  28.128 +    /** class-defined writeReplace method, or null if none */
  28.129 +    private Method writeReplaceMethod;
  28.130 +    /** class-defined readResolve method, or null if none */
  28.131 +    private Method readResolveMethod;
  28.132 +
  28.133 +    /** local class descriptor for represented class (may point to self) */
  28.134 +    private ObjectStreamClass localDesc;
  28.135 +    /** superclass descriptor appearing in stream */
  28.136 +    private ObjectStreamClass superDesc;
  28.137 +
  28.138 +    /**
  28.139 +     * Initializes native code.
  28.140 +     */
  28.141 +    private static native void initNative();
  28.142 +    static {
  28.143 +        initNative();
  28.144 +    }
  28.145 +
  28.146 +    /**
  28.147 +     * Find the descriptor for a class that can be serialized.  Creates an
  28.148 +     * ObjectStreamClass instance if one does not exist yet for class. Null is
  28.149 +     * returned if the specified class does not implement java.io.Serializable
  28.150 +     * or java.io.Externalizable.
  28.151 +     *
  28.152 +     * @param   cl class for which to get the descriptor
  28.153 +     * @return  the class descriptor for the specified class
  28.154 +     */
  28.155 +    public static ObjectStreamClass lookup(Class<?> cl) {
  28.156 +        return lookup(cl, false);
  28.157 +    }
  28.158 +
  28.159 +    /**
  28.160 +     * Returns the descriptor for any class, regardless of whether it
  28.161 +     * implements {@link Serializable}.
  28.162 +     *
  28.163 +     * @param        cl class for which to get the descriptor
  28.164 +     * @return       the class descriptor for the specified class
  28.165 +     * @since 1.6
  28.166 +     */
  28.167 +    public static ObjectStreamClass lookupAny(Class<?> cl) {
  28.168 +        return lookup(cl, true);
  28.169 +    }
  28.170 +
  28.171 +    /**
  28.172 +     * Returns the name of the class described by this descriptor.
  28.173 +     * This method returns the name of the class in the format that
  28.174 +     * is used by the {@link Class#getName} method.
  28.175 +     *
  28.176 +     * @return a string representing the name of the class
  28.177 +     */
  28.178 +    public String getName() {
  28.179 +        return name;
  28.180 +    }
  28.181 +
  28.182 +    /**
  28.183 +     * Return the serialVersionUID for this class.  The serialVersionUID
  28.184 +     * defines a set of classes all with the same name that have evolved from a
  28.185 +     * common root class and agree to be serialized and deserialized using a
  28.186 +     * common format.  NonSerializable classes have a serialVersionUID of 0L.
  28.187 +     *
  28.188 +     * @return  the SUID of the class described by this descriptor
  28.189 +     */
  28.190 +    public long getSerialVersionUID() {
  28.191 +        // REMIND: synchronize instead of relying on volatile?
  28.192 +        if (suid == null) {
  28.193 +            return computeDefaultSUID(cl);
  28.194 +        }
  28.195 +        return suid.longValue();
  28.196 +    }
  28.197 +
  28.198 +    /**
  28.199 +     * Return the class in the local VM that this version is mapped to.  Null
  28.200 +     * is returned if there is no corresponding local class.
  28.201 +     *
  28.202 +     * @return  the <code>Class</code> instance that this descriptor represents
  28.203 +     */
  28.204 +    public Class<?> forClass() {
  28.205 +        return cl;
  28.206 +    }
  28.207 +
  28.208 +    /**
  28.209 +     * Return an array of the fields of this serializable class.
  28.210 +     *
  28.211 +     * @return  an array containing an element for each persistent field of
  28.212 +     *          this class. Returns an array of length zero if there are no
  28.213 +     *          fields.
  28.214 +     * @since 1.2
  28.215 +     */
  28.216 +    public ObjectStreamField[] getFields() {
  28.217 +        return getFields(true);
  28.218 +    }
  28.219 +
  28.220 +    /**
  28.221 +     * Get the field of this class by name.
  28.222 +     *
  28.223 +     * @param   name the name of the data field to look for
  28.224 +     * @return  The ObjectStreamField object of the named field or null if
  28.225 +     *          there is no such named field.
  28.226 +     */
  28.227 +    public ObjectStreamField getField(String name) {
  28.228 +        return getField(name, null);
  28.229 +    }
  28.230 +
  28.231 +    /**
  28.232 +     * Return a string describing this ObjectStreamClass.
  28.233 +     */
  28.234 +    public String toString() {
  28.235 +        return name + ": static final long serialVersionUID = " +
  28.236 +            getSerialVersionUID() + "L;";
  28.237 +    }
  28.238 +
  28.239 +    /**
  28.240 +     * Looks up and returns class descriptor for given class, or null if class
  28.241 +     * is non-serializable and "all" is set to false.
  28.242 +     *
  28.243 +     * @param   cl class to look up
  28.244 +     * @param   all if true, return descriptors for all classes; if false, only
  28.245 +     *          return descriptors for serializable classes
  28.246 +     */
  28.247 +    static ObjectStreamClass lookup(Class<?> cl, boolean all) {
  28.248 +        if (!(all || Serializable.class.isAssignableFrom(cl))) {
  28.249 +            return null;
  28.250 +        }
  28.251 +        Object entry = null;
  28.252 +        EntryFuture future = null;
  28.253 +        if (entry == null) {
  28.254 +            EntryFuture newEntry = new EntryFuture();
  28.255 +            Reference<?> newRef = new SoftReference<>(newEntry);
  28.256 +            if (entry == null) {
  28.257 +                future = newEntry;
  28.258 +            }
  28.259 +        }
  28.260 +
  28.261 +        if (entry instanceof ObjectStreamClass) {  // check common case first
  28.262 +            return (ObjectStreamClass) entry;
  28.263 +        }
  28.264 +        if (entry instanceof EntryFuture) {
  28.265 +            future = (EntryFuture) entry;
  28.266 +            if (true) {
  28.267 +                /*
  28.268 +                 * Handle nested call situation described by 4803747: waiting
  28.269 +                 * for future value to be set by a lookup() call further up the
  28.270 +                 * stack will result in deadlock, so calculate and set the
  28.271 +                 * future value here instead.
  28.272 +                 */
  28.273 +                entry = null;
  28.274 +            } else {
  28.275 +                entry = future.get();
  28.276 +            }
  28.277 +        }
  28.278 +        if (entry == null) {
  28.279 +            try {
  28.280 +                entry = new ObjectStreamClass(cl);
  28.281 +            } catch (Throwable th) {
  28.282 +                entry = th;
  28.283 +            }
  28.284 +            // nested lookup call already set future
  28.285 +            entry = future.get();
  28.286 +        }
  28.287 +
  28.288 +        if (entry instanceof ObjectStreamClass) {
  28.289 +            return (ObjectStreamClass) entry;
  28.290 +        } else if (entry instanceof RuntimeException) {
  28.291 +            throw (RuntimeException) entry;
  28.292 +        } else if (entry instanceof Error) {
  28.293 +            throw (Error) entry;
  28.294 +        } else {
  28.295 +            throw new InternalError("unexpected entry: " + entry);
  28.296 +        }
  28.297 +    }
  28.298 +
  28.299 +    /**
  28.300 +     * Placeholder used in class descriptor and field reflector lookup tables
  28.301 +     * for an entry in the process of being initialized.  (Internal) callers
  28.302 +     * which receive an EntryFuture belonging to another thread as the result
  28.303 +     * of a lookup should call the get() method of the EntryFuture; this will
  28.304 +     * return the actual entry once it is ready for use and has been set().  To
  28.305 +     * conserve objects, EntryFutures synchronize on themselves.
  28.306 +     */
  28.307 +    private static class EntryFuture {
  28.308 +
  28.309 +        private static final Object unset = new Object();
  28.310 +        private Object entry = unset;
  28.311 +
  28.312 +        /**
  28.313 +         * Attempts to set the value contained by this EntryFuture.  If the
  28.314 +         * EntryFuture's value has not been set already, then the value is
  28.315 +         * saved, any callers blocked in the get() method are notified, and
  28.316 +         * true is returned.  If the value has already been set, then no saving
  28.317 +         * or notification occurs, and false is returned.
  28.318 +         */
  28.319 +        synchronized boolean set(Object entry) {
  28.320 +            if (this.entry != unset) {
  28.321 +                return false;
  28.322 +            }
  28.323 +            this.entry = entry;
  28.324 +            notifyAll();
  28.325 +            return true;
  28.326 +        }
  28.327 +
  28.328 +        /**
  28.329 +         * Returns the value contained by this EntryFuture, blocking if
  28.330 +         * necessary until a value is set.
  28.331 +         */
  28.332 +        synchronized Object get() {
  28.333 +            boolean interrupted = false;
  28.334 +            while (entry == unset) {
  28.335 +                try {
  28.336 +                    wait();
  28.337 +                } catch (InterruptedException ex) {
  28.338 +                    interrupted = true;
  28.339 +                }
  28.340 +            }
  28.341 +            return entry;
  28.342 +        }
  28.343 +    }
  28.344 +
  28.345 +    /**
  28.346 +     * Creates local class descriptor representing given class.
  28.347 +     */
  28.348 +    private ObjectStreamClass(final Class<?> cl) {
  28.349 +        this.cl = cl;
  28.350 +        name = cl.getName();
  28.351 +        isProxy = Proxy.isProxyClass(cl);
  28.352 +        isEnum = Enum.class.isAssignableFrom(cl);
  28.353 +        serializable = Serializable.class.isAssignableFrom(cl);
  28.354 +        externalizable = Externalizable.class.isAssignableFrom(cl);
  28.355 +
  28.356 +        Class<?> superCl = cl.getSuperclass();
  28.357 +        superDesc = (superCl != null) ? lookup(superCl, false) : null;
  28.358 +        localDesc = this;
  28.359 +
  28.360 +        suid = Long.valueOf(0);
  28.361 +        fields = NO_FIELDS;
  28.362 +
  28.363 +
  28.364 +        if (deserializeEx == null) {
  28.365 +            if (isEnum) {
  28.366 +                deserializeEx = new InvalidClassException(name, "enum type");
  28.367 +            } else if (cons == null) {
  28.368 +                deserializeEx = new InvalidClassException(
  28.369 +                    name, "no valid constructor");
  28.370 +            }
  28.371 +        }
  28.372 +        for (int i = 0; i < fields.length; i++) {
  28.373 +            if (fields[i].getField() == null) {
  28.374 +                defaultSerializeEx = new InvalidClassException(
  28.375 +                    name, "unmatched serializable field(s) declared");
  28.376 +            }
  28.377 +        }
  28.378 +    }
  28.379 +
  28.380 +    /**
  28.381 +     * Creates blank class descriptor which should be initialized via a
  28.382 +     * subsequent call to initProxy(), initNonProxy() or readNonProxy().
  28.383 +     */
  28.384 +    ObjectStreamClass() {
  28.385 +    }
  28.386 +
  28.387 +    /**
  28.388 +     * Initializes class descriptor representing a proxy class.
  28.389 +     */
  28.390 +    void initProxy(Class<?> cl,
  28.391 +                   ClassNotFoundException resolveEx,
  28.392 +                   ObjectStreamClass superDesc)
  28.393 +        throws InvalidClassException
  28.394 +    {
  28.395 +        this.cl = cl;
  28.396 +        this.resolveEx = resolveEx;
  28.397 +        this.superDesc = superDesc;
  28.398 +        isProxy = true;
  28.399 +        serializable = true;
  28.400 +        suid = Long.valueOf(0);
  28.401 +        fields = NO_FIELDS;
  28.402 +
  28.403 +        if (cl != null) {
  28.404 +            localDesc = lookup(cl, true);
  28.405 +            if (!localDesc.isProxy) {
  28.406 +                throw new InvalidClassException(
  28.407 +                    "cannot bind proxy descriptor to a non-proxy class");
  28.408 +            }
  28.409 +            name = localDesc.name;
  28.410 +            externalizable = localDesc.externalizable;
  28.411 +            cons = localDesc.cons;
  28.412 +            writeReplaceMethod = localDesc.writeReplaceMethod;
  28.413 +            readResolveMethod = localDesc.readResolveMethod;
  28.414 +            deserializeEx = localDesc.deserializeEx;
  28.415 +        }
  28.416 +    }
  28.417 +
  28.418 +    /**
  28.419 +     * Initializes class descriptor representing a non-proxy class.
  28.420 +     */
  28.421 +    void initNonProxy(ObjectStreamClass model,
  28.422 +                      Class<?> cl,
  28.423 +                      ClassNotFoundException resolveEx,
  28.424 +                      ObjectStreamClass superDesc)
  28.425 +        throws InvalidClassException
  28.426 +    {
  28.427 +        this.cl = cl;
  28.428 +        this.resolveEx = resolveEx;
  28.429 +        this.superDesc = superDesc;
  28.430 +        name = model.name;
  28.431 +        suid = Long.valueOf(model.getSerialVersionUID());
  28.432 +        isProxy = false;
  28.433 +        isEnum = model.isEnum;
  28.434 +        serializable = model.serializable;
  28.435 +        externalizable = model.externalizable;
  28.436 +        hasBlockExternalData = model.hasBlockExternalData;
  28.437 +        hasWriteObjectData = model.hasWriteObjectData;
  28.438 +        fields = model.fields;
  28.439 +        primDataSize = model.primDataSize;
  28.440 +        numObjFields = model.numObjFields;
  28.441 +
  28.442 +        if (cl != null) {
  28.443 +            localDesc = lookup(cl, true);
  28.444 +            if (localDesc.isProxy) {
  28.445 +                throw new InvalidClassException(
  28.446 +                    "cannot bind non-proxy descriptor to a proxy class");
  28.447 +            }
  28.448 +            if (isEnum != localDesc.isEnum) {
  28.449 +                throw new InvalidClassException(isEnum ?
  28.450 +                    "cannot bind enum descriptor to a non-enum class" :
  28.451 +                    "cannot bind non-enum descriptor to an enum class");
  28.452 +            }
  28.453 +
  28.454 +            if (serializable == localDesc.serializable &&
  28.455 +                !cl.isArray() &&
  28.456 +                suid.longValue() != localDesc.getSerialVersionUID())
  28.457 +            {
  28.458 +                throw new InvalidClassException(localDesc.name,
  28.459 +                    "local class incompatible: " +
  28.460 +                    "stream classdesc serialVersionUID = " + suid +
  28.461 +                    ", local class serialVersionUID = " +
  28.462 +                    localDesc.getSerialVersionUID());
  28.463 +            }
  28.464 +
  28.465 +            if (!classNamesEqual(name, localDesc.name)) {
  28.466 +                throw new InvalidClassException(localDesc.name,
  28.467 +                    "local class name incompatible with stream class " +
  28.468 +                    "name \"" + name + "\"");
  28.469 +            }
  28.470 +
  28.471 +            if (!isEnum) {
  28.472 +                if ((serializable == localDesc.serializable) &&
  28.473 +                    (externalizable != localDesc.externalizable))
  28.474 +                {
  28.475 +                    throw new InvalidClassException(localDesc.name,
  28.476 +                        "Serializable incompatible with Externalizable");
  28.477 +                }
  28.478 +
  28.479 +                if ((serializable != localDesc.serializable) ||
  28.480 +                    (externalizable != localDesc.externalizable) ||
  28.481 +                    !(serializable || externalizable))
  28.482 +                {
  28.483 +                    deserializeEx = new InvalidClassException(localDesc.name,
  28.484 +                        "class invalid for deserialization");
  28.485 +                }
  28.486 +            }
  28.487 +
  28.488 +            cons = localDesc.cons;
  28.489 +            writeObjectMethod = localDesc.writeObjectMethod;
  28.490 +            readObjectMethod = localDesc.readObjectMethod;
  28.491 +            readObjectNoDataMethod = localDesc.readObjectNoDataMethod;
  28.492 +            writeReplaceMethod = localDesc.writeReplaceMethod;
  28.493 +            readResolveMethod = localDesc.readResolveMethod;
  28.494 +            if (deserializeEx == null) {
  28.495 +                deserializeEx = localDesc.deserializeEx;
  28.496 +            }
  28.497 +        }
  28.498 +        // reassign to matched fields so as to reflect local unshared settings
  28.499 +        fields = null;
  28.500 +    }
  28.501 +
  28.502 +    /**
  28.503 +     * Reads non-proxy class descriptor information from given input stream.
  28.504 +     * The resulting class descriptor is not fully functional; it can only be
  28.505 +     * used as input to the ObjectInputStream.resolveClass() and
  28.506 +     * ObjectStreamClass.initNonProxy() methods.
  28.507 +     */
  28.508 +    void readNonProxy(ObjectInputStream in)
  28.509 +        throws IOException, ClassNotFoundException
  28.510 +    {
  28.511 +        name = in.readUTF();
  28.512 +        suid = Long.valueOf(in.readLong());
  28.513 +        isProxy = false;
  28.514 +
  28.515 +        byte flags = in.readByte();
  28.516 +        hasWriteObjectData =
  28.517 +            ((flags & ObjectStreamConstants.SC_WRITE_METHOD) != 0);
  28.518 +        hasBlockExternalData =
  28.519 +            ((flags & ObjectStreamConstants.SC_BLOCK_DATA) != 0);
  28.520 +        externalizable =
  28.521 +            ((flags & ObjectStreamConstants.SC_EXTERNALIZABLE) != 0);
  28.522 +        boolean sflag =
  28.523 +            ((flags & ObjectStreamConstants.SC_SERIALIZABLE) != 0);
  28.524 +        if (externalizable && sflag) {
  28.525 +            throw new InvalidClassException(
  28.526 +                name, "serializable and externalizable flags conflict");
  28.527 +        }
  28.528 +        serializable = externalizable || sflag;
  28.529 +        isEnum = ((flags & ObjectStreamConstants.SC_ENUM) != 0);
  28.530 +        if (isEnum && suid.longValue() != 0L) {
  28.531 +            throw new InvalidClassException(name,
  28.532 +                "enum descriptor has non-zero serialVersionUID: " + suid);
  28.533 +        }
  28.534 +
  28.535 +        int numFields = in.readShort();
  28.536 +        if (isEnum && numFields != 0) {
  28.537 +            throw new InvalidClassException(name,
  28.538 +                "enum descriptor has non-zero field count: " + numFields);
  28.539 +        }
  28.540 +        fields = (numFields > 0) ?
  28.541 +            new ObjectStreamField[numFields] : NO_FIELDS;
  28.542 +        for (int i = 0; i < numFields; i++) {
  28.543 +            char tcode = (char) in.readByte();
  28.544 +            String fname = in.readUTF();
  28.545 +            String signature = ((tcode == 'L') || (tcode == '[')) ?
  28.546 +                in.readTypeString() : new String(new char[] { tcode });
  28.547 +            try {
  28.548 +                fields[i] = new ObjectStreamField(fname, signature, false);
  28.549 +            } catch (RuntimeException e) {
  28.550 +                throw (IOException) new InvalidClassException(name,
  28.551 +                    "invalid descriptor for field " + fname).initCause(e);
  28.552 +            }
  28.553 +        }
  28.554 +        computeFieldOffsets();
  28.555 +    }
  28.556 +
  28.557 +    /**
  28.558 +     * Writes non-proxy class descriptor information to given output stream.
  28.559 +     */
  28.560 +    void writeNonProxy(ObjectOutputStream out) throws IOException {
  28.561 +        out.writeUTF(name);
  28.562 +        out.writeLong(getSerialVersionUID());
  28.563 +
  28.564 +        byte flags = 0;
  28.565 +        if (externalizable) {
  28.566 +            flags |= ObjectStreamConstants.SC_EXTERNALIZABLE;
  28.567 +            int protocol = out.getProtocolVersion();
  28.568 +            if (protocol != ObjectStreamConstants.PROTOCOL_VERSION_1) {
  28.569 +                flags |= ObjectStreamConstants.SC_BLOCK_DATA;
  28.570 +            }
  28.571 +        } else if (serializable) {
  28.572 +            flags |= ObjectStreamConstants.SC_SERIALIZABLE;
  28.573 +        }
  28.574 +        if (hasWriteObjectData) {
  28.575 +            flags |= ObjectStreamConstants.SC_WRITE_METHOD;
  28.576 +        }
  28.577 +        if (isEnum) {
  28.578 +            flags |= ObjectStreamConstants.SC_ENUM;
  28.579 +        }
  28.580 +        out.writeByte(flags);
  28.581 +
  28.582 +        out.writeShort(fields.length);
  28.583 +        for (int i = 0; i < fields.length; i++) {
  28.584 +            ObjectStreamField f = fields[i];
  28.585 +            out.writeByte(f.getTypeCode());
  28.586 +            out.writeUTF(f.getName());
  28.587 +            if (!f.isPrimitive()) {
  28.588 +                out.writeTypeString(f.getTypeString());
  28.589 +            }
  28.590 +        }
  28.591 +    }
  28.592 +
  28.593 +    /**
  28.594 +     * Returns ClassNotFoundException (if any) thrown while attempting to
  28.595 +     * resolve local class corresponding to this class descriptor.
  28.596 +     */
  28.597 +    ClassNotFoundException getResolveException() {
  28.598 +        return resolveEx;
  28.599 +    }
  28.600 +
  28.601 +    /**
  28.602 +     * Throws an InvalidClassException if object instances referencing this
  28.603 +     * class descriptor should not be allowed to deserialize.  This method does
  28.604 +     * not apply to deserialization of enum constants.
  28.605 +     */
  28.606 +    void checkDeserialize() throws InvalidClassException {
  28.607 +        if (deserializeEx != null) {
  28.608 +            InvalidClassException ice =
  28.609 +                new InvalidClassException(deserializeEx.classname,
  28.610 +                                          deserializeEx.getMessage());
  28.611 +            ice.initCause(deserializeEx);
  28.612 +            throw ice;
  28.613 +        }
  28.614 +    }
  28.615 +
  28.616 +    /**
  28.617 +     * Throws an InvalidClassException if objects whose class is represented by
  28.618 +     * this descriptor should not be allowed to serialize.  This method does
  28.619 +     * not apply to serialization of enum constants.
  28.620 +     */
  28.621 +    void checkSerialize() throws InvalidClassException {
  28.622 +        if (serializeEx != null) {
  28.623 +            InvalidClassException ice =
  28.624 +                new InvalidClassException(serializeEx.classname,
  28.625 +                                          serializeEx.getMessage());
  28.626 +            ice.initCause(serializeEx);
  28.627 +            throw ice;
  28.628 +        }
  28.629 +    }
  28.630 +
  28.631 +    /**
  28.632 +     * Throws an InvalidClassException if objects whose class is represented by
  28.633 +     * this descriptor should not be permitted to use default serialization
  28.634 +     * (e.g., if the class declares serializable fields that do not correspond
  28.635 +     * to actual fields, and hence must use the GetField API).  This method
  28.636 +     * does not apply to deserialization of enum constants.
  28.637 +     */
  28.638 +    void checkDefaultSerialize() throws InvalidClassException {
  28.639 +        if (defaultSerializeEx != null) {
  28.640 +            InvalidClassException ice =
  28.641 +                new InvalidClassException(defaultSerializeEx.classname,
  28.642 +                                          defaultSerializeEx.getMessage());
  28.643 +            ice.initCause(defaultSerializeEx);
  28.644 +            throw ice;
  28.645 +        }
  28.646 +    }
  28.647 +
  28.648 +    /**
  28.649 +     * Returns superclass descriptor.  Note that on the receiving side, the
  28.650 +     * superclass descriptor may be bound to a class that is not a superclass
  28.651 +     * of the subclass descriptor's bound class.
  28.652 +     */
  28.653 +    ObjectStreamClass getSuperDesc() {
  28.654 +        return superDesc;
  28.655 +    }
  28.656 +
  28.657 +    /**
  28.658 +     * Returns the "local" class descriptor for the class associated with this
  28.659 +     * class descriptor (i.e., the result of
  28.660 +     * ObjectStreamClass.lookup(this.forClass())) or null if there is no class
  28.661 +     * associated with this descriptor.
  28.662 +     */
  28.663 +    ObjectStreamClass getLocalDesc() {
  28.664 +        return localDesc;
  28.665 +    }
  28.666 +
  28.667 +    /**
  28.668 +     * Returns arrays of ObjectStreamFields representing the serializable
  28.669 +     * fields of the represented class.  If copy is true, a clone of this class
  28.670 +     * descriptor's field array is returned, otherwise the array itself is
  28.671 +     * returned.
  28.672 +     */
  28.673 +    ObjectStreamField[] getFields(boolean copy) {
  28.674 +        return copy ? fields.clone() : fields;
  28.675 +    }
  28.676 +
  28.677 +    /**
  28.678 +     * Looks up a serializable field of the represented class by name and type.
  28.679 +     * A specified type of null matches all types, Object.class matches all
  28.680 +     * non-primitive types, and any other non-null type matches assignable
  28.681 +     * types only.  Returns matching field, or null if no match found.
  28.682 +     */
  28.683 +    ObjectStreamField getField(String name, Class<?> type) {
  28.684 +        for (int i = 0; i < fields.length; i++) {
  28.685 +            ObjectStreamField f = fields[i];
  28.686 +            if (f.getName().equals(name)) {
  28.687 +                if (type == null ||
  28.688 +                    (type == Object.class && !f.isPrimitive()))
  28.689 +                {
  28.690 +                    return f;
  28.691 +                }
  28.692 +                Class<?> ftype = f.getType();
  28.693 +                if (ftype != null && type.isAssignableFrom(ftype)) {
  28.694 +                    return f;
  28.695 +                }
  28.696 +            }
  28.697 +        }
  28.698 +        return null;
  28.699 +    }
  28.700 +
  28.701 +    /**
  28.702 +     * Returns true if class descriptor represents a dynamic proxy class, false
  28.703 +     * otherwise.
  28.704 +     */
  28.705 +    boolean isProxy() {
  28.706 +        return isProxy;
  28.707 +    }
  28.708 +
  28.709 +    /**
  28.710 +     * Returns true if class descriptor represents an enum type, false
  28.711 +     * otherwise.
  28.712 +     */
  28.713 +    boolean isEnum() {
  28.714 +        return isEnum;
  28.715 +    }
  28.716 +
  28.717 +    /**
  28.718 +     * Returns true if represented class implements Externalizable, false
  28.719 +     * otherwise.
  28.720 +     */
  28.721 +    boolean isExternalizable() {
  28.722 +        return externalizable;
  28.723 +    }
  28.724 +
  28.725 +    /**
  28.726 +     * Returns true if represented class implements Serializable, false
  28.727 +     * otherwise.
  28.728 +     */
  28.729 +    boolean isSerializable() {
  28.730 +        return serializable;
  28.731 +    }
  28.732 +
  28.733 +    /**
  28.734 +     * Returns true if class descriptor represents externalizable class that
  28.735 +     * has written its data in 1.2 (block data) format, false otherwise.
  28.736 +     */
  28.737 +    boolean hasBlockExternalData() {
  28.738 +        return hasBlockExternalData;
  28.739 +    }
  28.740 +
  28.741 +    /**
  28.742 +     * Returns true if class descriptor represents serializable (but not
  28.743 +     * externalizable) class which has written its data via a custom
  28.744 +     * writeObject() method, false otherwise.
  28.745 +     */
  28.746 +    boolean hasWriteObjectData() {
  28.747 +        return hasWriteObjectData;
  28.748 +    }
  28.749 +
  28.750 +    /**
  28.751 +     * Returns true if represented class is serializable/externalizable and can
  28.752 +     * be instantiated by the serialization runtime--i.e., if it is
  28.753 +     * externalizable and defines a public no-arg constructor, or if it is
  28.754 +     * non-externalizable and its first non-serializable superclass defines an
  28.755 +     * accessible no-arg constructor.  Otherwise, returns false.
  28.756 +     */
  28.757 +    boolean isInstantiable() {
  28.758 +        return (cons != null);
  28.759 +    }
  28.760 +
  28.761 +    /**
  28.762 +     * Returns true if represented class is serializable (but not
  28.763 +     * externalizable) and defines a conformant writeObject method.  Otherwise,
  28.764 +     * returns false.
  28.765 +     */
  28.766 +    boolean hasWriteObjectMethod() {
  28.767 +        return (writeObjectMethod != null);
  28.768 +    }
  28.769 +
  28.770 +    /**
  28.771 +     * Returns true if represented class is serializable (but not
  28.772 +     * externalizable) and defines a conformant readObject method.  Otherwise,
  28.773 +     * returns false.
  28.774 +     */
  28.775 +    boolean hasReadObjectMethod() {
  28.776 +        return (readObjectMethod != null);
  28.777 +    }
  28.778 +
  28.779 +    /**
  28.780 +     * Returns true if represented class is serializable (but not
  28.781 +     * externalizable) and defines a conformant readObjectNoData method.
  28.782 +     * Otherwise, returns false.
  28.783 +     */
  28.784 +    boolean hasReadObjectNoDataMethod() {
  28.785 +        return (readObjectNoDataMethod != null);
  28.786 +    }
  28.787 +
  28.788 +    /**
  28.789 +     * Returns true if represented class is serializable or externalizable and
  28.790 +     * defines a conformant writeReplace method.  Otherwise, returns false.
  28.791 +     */
  28.792 +    boolean hasWriteReplaceMethod() {
  28.793 +        return (writeReplaceMethod != null);
  28.794 +    }
  28.795 +
  28.796 +    /**
  28.797 +     * Returns true if represented class is serializable or externalizable and
  28.798 +     * defines a conformant readResolve method.  Otherwise, returns false.
  28.799 +     */
  28.800 +    boolean hasReadResolveMethod() {
  28.801 +        return (readResolveMethod != null);
  28.802 +    }
  28.803 +
  28.804 +    /**
  28.805 +     * Creates a new instance of the represented class.  If the class is
  28.806 +     * externalizable, invokes its public no-arg constructor; otherwise, if the
  28.807 +     * class is serializable, invokes the no-arg constructor of the first
  28.808 +     * non-serializable superclass.  Throws UnsupportedOperationException if
  28.809 +     * this class descriptor is not associated with a class, if the associated
  28.810 +     * class is non-serializable or if the appropriate no-arg constructor is
  28.811 +     * inaccessible/unavailable.
  28.812 +     */
  28.813 +    Object newInstance()
  28.814 +        throws InstantiationException, InvocationTargetException,
  28.815 +               UnsupportedOperationException
  28.816 +    {
  28.817 +        if (cons != null) {
  28.818 +            try {
  28.819 +                return cons.newInstance();
  28.820 +            } catch (IllegalAccessException ex) {
  28.821 +                // should not occur, as access checks have been suppressed
  28.822 +                throw new InternalError();
  28.823 +            }
  28.824 +        } else {
  28.825 +            throw new UnsupportedOperationException();
  28.826 +        }
  28.827 +    }
  28.828 +
  28.829 +    /**
  28.830 +     * Invokes the writeObject method of the represented serializable class.
  28.831 +     * Throws UnsupportedOperationException if this class descriptor is not
  28.832 +     * associated with a class, or if the class is externalizable,
  28.833 +     * non-serializable or does not define writeObject.
  28.834 +     */
  28.835 +    void invokeWriteObject(Object obj, ObjectOutputStream out)
  28.836 +        throws IOException, UnsupportedOperationException
  28.837 +    {
  28.838 +        if (writeObjectMethod != null) {
  28.839 +            try {
  28.840 +                writeObjectMethod.invoke(obj, new Object[]{ out });
  28.841 +            } catch (InvocationTargetException ex) {
  28.842 +                Throwable th = ex.getTargetException();
  28.843 +                if (th instanceof IOException) {
  28.844 +                    throw (IOException) th;
  28.845 +                } else {
  28.846 +                    throwMiscException(th);
  28.847 +                }
  28.848 +            } catch (IllegalAccessException ex) {
  28.849 +                // should not occur, as access checks have been suppressed
  28.850 +                throw new InternalError();
  28.851 +            }
  28.852 +        } else {
  28.853 +            throw new UnsupportedOperationException();
  28.854 +        }
  28.855 +    }
  28.856 +
  28.857 +    /**
  28.858 +     * Invokes the readObject method of the represented serializable class.
  28.859 +     * Throws UnsupportedOperationException if this class descriptor is not
  28.860 +     * associated with a class, or if the class is externalizable,
  28.861 +     * non-serializable or does not define readObject.
  28.862 +     */
  28.863 +    void invokeReadObject(Object obj, ObjectInputStream in)
  28.864 +        throws ClassNotFoundException, IOException,
  28.865 +               UnsupportedOperationException
  28.866 +    {
  28.867 +        if (readObjectMethod != null) {
  28.868 +            try {
  28.869 +                readObjectMethod.invoke(obj, new Object[]{ in });
  28.870 +            } catch (InvocationTargetException ex) {
  28.871 +                Throwable th = ex.getTargetException();
  28.872 +                if (th instanceof ClassNotFoundException) {
  28.873 +                    throw (ClassNotFoundException) th;
  28.874 +                } else if (th instanceof IOException) {
  28.875 +                    throw (IOException) th;
  28.876 +                } else {
  28.877 +                    throwMiscException(th);
  28.878 +                }
  28.879 +            } catch (IllegalAccessException ex) {
  28.880 +                // should not occur, as access checks have been suppressed
  28.881 +                throw new InternalError();
  28.882 +            }
  28.883 +        } else {
  28.884 +            throw new UnsupportedOperationException();
  28.885 +        }
  28.886 +    }
  28.887 +
  28.888 +    /**
  28.889 +     * Invokes the readObjectNoData method of the represented serializable
  28.890 +     * class.  Throws UnsupportedOperationException if this class descriptor is
  28.891 +     * not associated with a class, or if the class is externalizable,
  28.892 +     * non-serializable or does not define readObjectNoData.
  28.893 +     */
  28.894 +    void invokeReadObjectNoData(Object obj)
  28.895 +        throws IOException, UnsupportedOperationException
  28.896 +    {
  28.897 +        if (readObjectNoDataMethod != null) {
  28.898 +            try {
  28.899 +                readObjectNoDataMethod.invoke(obj, (Object[]) null);
  28.900 +            } catch (InvocationTargetException ex) {
  28.901 +                Throwable th = ex.getTargetException();
  28.902 +                if (th instanceof ObjectStreamException) {
  28.903 +                    throw (ObjectStreamException) th;
  28.904 +                } else {
  28.905 +                    throwMiscException(th);
  28.906 +                }
  28.907 +            } catch (IllegalAccessException ex) {
  28.908 +                // should not occur, as access checks have been suppressed
  28.909 +                throw new InternalError();
  28.910 +            }
  28.911 +        } else {
  28.912 +            throw new UnsupportedOperationException();
  28.913 +        }
  28.914 +    }
  28.915 +
  28.916 +    /**
  28.917 +     * Invokes the writeReplace method of the represented serializable class and
  28.918 +     * returns the result.  Throws UnsupportedOperationException if this class
  28.919 +     * descriptor is not associated with a class, or if the class is
  28.920 +     * non-serializable or does not define writeReplace.
  28.921 +     */
  28.922 +    Object invokeWriteReplace(Object obj)
  28.923 +        throws IOException, UnsupportedOperationException
  28.924 +    {
  28.925 +        if (writeReplaceMethod != null) {
  28.926 +            try {
  28.927 +                return writeReplaceMethod.invoke(obj, (Object[]) null);
  28.928 +            } catch (InvocationTargetException ex) {
  28.929 +                Throwable th = ex.getTargetException();
  28.930 +                if (th instanceof ObjectStreamException) {
  28.931 +                    throw (ObjectStreamException) th;
  28.932 +                } else {
  28.933 +                    throwMiscException(th);
  28.934 +                    throw new InternalError();  // never reached
  28.935 +                }
  28.936 +            } catch (IllegalAccessException ex) {
  28.937 +                // should not occur, as access checks have been suppressed
  28.938 +                throw new InternalError();
  28.939 +            }
  28.940 +        } else {
  28.941 +            throw new UnsupportedOperationException();
  28.942 +        }
  28.943 +    }
  28.944 +
  28.945 +    /**
  28.946 +     * Invokes the readResolve method of the represented serializable class and
  28.947 +     * returns the result.  Throws UnsupportedOperationException if this class
  28.948 +     * descriptor is not associated with a class, or if the class is
  28.949 +     * non-serializable or does not define readResolve.
  28.950 +     */
  28.951 +    Object invokeReadResolve(Object obj)
  28.952 +        throws IOException, UnsupportedOperationException
  28.953 +    {
  28.954 +        if (readResolveMethod != null) {
  28.955 +            try {
  28.956 +                return readResolveMethod.invoke(obj, (Object[]) null);
  28.957 +            } catch (InvocationTargetException ex) {
  28.958 +                Throwable th = ex.getTargetException();
  28.959 +                if (th instanceof ObjectStreamException) {
  28.960 +                    throw (ObjectStreamException) th;
  28.961 +                } else {
  28.962 +                    throwMiscException(th);
  28.963 +                    throw new InternalError();  // never reached
  28.964 +                }
  28.965 +            } catch (IllegalAccessException ex) {
  28.966 +                // should not occur, as access checks have been suppressed
  28.967 +                throw new InternalError();
  28.968 +            }
  28.969 +        } else {
  28.970 +            throw new UnsupportedOperationException();
  28.971 +        }
  28.972 +    }
  28.973 +
  28.974 +    /**
  28.975 +     * Class representing the portion of an object's serialized form allotted
  28.976 +     * to data described by a given class descriptor.  If "hasData" is false,
  28.977 +     * the object's serialized form does not contain data associated with the
  28.978 +     * class descriptor.
  28.979 +     */
  28.980 +    static class ClassDataSlot {
  28.981 +
  28.982 +        /** class descriptor "occupying" this slot */
  28.983 +        final ObjectStreamClass desc;
  28.984 +        /** true if serialized form includes data for this slot's descriptor */
  28.985 +        final boolean hasData;
  28.986 +
  28.987 +        ClassDataSlot(ObjectStreamClass desc, boolean hasData) {
  28.988 +            this.desc = desc;
  28.989 +            this.hasData = hasData;
  28.990 +        }
  28.991 +    }
  28.992 +
  28.993 +    /**
  28.994 +     * Returns array of ClassDataSlot instances representing the data layout
  28.995 +     * (including superclass data) for serialized objects described by this
  28.996 +     * class descriptor.  ClassDataSlots are ordered by inheritance with those
  28.997 +     * containing "higher" superclasses appearing first.  The final
  28.998 +     * ClassDataSlot contains a reference to this descriptor.
  28.999 +     */
 28.1000 +    ClassDataSlot[] getClassDataLayout() throws InvalidClassException {
 28.1001 +        // REMIND: synchronize instead of relying on volatile?
 28.1002 +        if (dataLayout == null) {
 28.1003 +            dataLayout = getClassDataLayout0();
 28.1004 +        }
 28.1005 +        return dataLayout;
 28.1006 +    }
 28.1007 +
 28.1008 +    private ClassDataSlot[] getClassDataLayout0()
 28.1009 +        throws InvalidClassException
 28.1010 +    {
 28.1011 +        ArrayList<ClassDataSlot> slots = new ArrayList<>();
 28.1012 +        Class<?> start = cl, end = cl;
 28.1013 +
 28.1014 +        // locate closest non-serializable superclass
 28.1015 +        while (end != null && Serializable.class.isAssignableFrom(end)) {
 28.1016 +            end = end.getSuperclass();
 28.1017 +        }
 28.1018 +
 28.1019 +        for (ObjectStreamClass d = this; d != null; d = d.superDesc) {
 28.1020 +
 28.1021 +            // search up inheritance hierarchy for class with matching name
 28.1022 +            String searchName = (d.cl != null) ? d.cl.getName() : d.name;
 28.1023 +            Class<?> match = null;
 28.1024 +            for (Class<?> c = start; c != end; c = c.getSuperclass()) {
 28.1025 +                if (searchName.equals(c.getName())) {
 28.1026 +                    match = c;
 28.1027 +                    break;
 28.1028 +                }
 28.1029 +            }
 28.1030 +
 28.1031 +            // add "no data" slot for each unmatched class below match
 28.1032 +            if (match != null) {
 28.1033 +                for (Class<?> c = start; c != match; c = c.getSuperclass()) {
 28.1034 +                    slots.add(new ClassDataSlot(
 28.1035 +                        ObjectStreamClass.lookup(c, true), false));
 28.1036 +                }
 28.1037 +                start = match.getSuperclass();
 28.1038 +            }
 28.1039 +
 28.1040 +            // record descriptor/class pairing
 28.1041 +            slots.add(new ClassDataSlot(d.getVariantFor(match), true));
 28.1042 +        }
 28.1043 +
 28.1044 +        // add "no data" slot for any leftover unmatched classes
 28.1045 +        for (Class<?> c = start; c != end; c = c.getSuperclass()) {
 28.1046 +            slots.add(new ClassDataSlot(
 28.1047 +                ObjectStreamClass.lookup(c, true), false));
 28.1048 +        }
 28.1049 +
 28.1050 +        // order slots from superclass -> subclass
 28.1051 +        Collections.reverse(slots);
 28.1052 +        return slots.toArray(new ClassDataSlot[slots.size()]);
 28.1053 +    }
 28.1054 +
 28.1055 +    /**
 28.1056 +     * Returns aggregate size (in bytes) of marshalled primitive field values
 28.1057 +     * for represented class.
 28.1058 +     */
 28.1059 +    int getPrimDataSize() {
 28.1060 +        return primDataSize;
 28.1061 +    }
 28.1062 +
 28.1063 +    /**
 28.1064 +     * Returns number of non-primitive serializable fields of represented
 28.1065 +     * class.
 28.1066 +     */
 28.1067 +    int getNumObjFields() {
 28.1068 +        return numObjFields;
 28.1069 +    }
 28.1070 +
 28.1071 +    /**
 28.1072 +     * Fetches the serializable primitive field values of object obj and
 28.1073 +     * marshals them into byte array buf starting at offset 0.  It is the
 28.1074 +     * responsibility of the caller to ensure that obj is of the proper type if
 28.1075 +     * non-null.
 28.1076 +     */
 28.1077 +    void getPrimFieldValues(Object obj, byte[] buf) {
 28.1078 +    }
 28.1079 +
 28.1080 +    /**
 28.1081 +     * Sets the serializable primitive fields of object obj using values
 28.1082 +     * unmarshalled from byte array buf starting at offset 0.  It is the
 28.1083 +     * responsibility of the caller to ensure that obj is of the proper type if
 28.1084 +     * non-null.
 28.1085 +     */
 28.1086 +    void setPrimFieldValues(Object obj, byte[] buf) {
 28.1087 +    }
 28.1088 +
 28.1089 +    /**
 28.1090 +     * Fetches the serializable object field values of object obj and stores
 28.1091 +     * them in array vals starting at offset 0.  It is the responsibility of
 28.1092 +     * the caller to ensure that obj is of the proper type if non-null.
 28.1093 +     */
 28.1094 +    void getObjFieldValues(Object obj, Object[] vals) {
 28.1095 +    }
 28.1096 +
 28.1097 +    /**
 28.1098 +     * Sets the serializable object fields of object obj using values from
 28.1099 +     * array vals starting at offset 0.  It is the responsibility of the caller
 28.1100 +     * to ensure that obj is of the proper type if non-null.
 28.1101 +     */
 28.1102 +    void setObjFieldValues(Object obj, Object[] vals) {
 28.1103 +    }
 28.1104 +
 28.1105 +    /**
 28.1106 +     * Calculates and sets serializable field offsets, as well as primitive
 28.1107 +     * data size and object field count totals.  Throws InvalidClassException
 28.1108 +     * if fields are illegally ordered.
 28.1109 +     */
 28.1110 +    private void computeFieldOffsets() throws InvalidClassException {
 28.1111 +        primDataSize = 0;
 28.1112 +        numObjFields = 0;
 28.1113 +        int firstObjIndex = -1;
 28.1114 +
 28.1115 +        for (int i = 0; i < fields.length; i++) {
 28.1116 +            ObjectStreamField f = fields[i];
 28.1117 +            switch (f.getTypeCode()) {
 28.1118 +                case 'Z':
 28.1119 +                case 'B':
 28.1120 +                    f.setOffset(primDataSize++);
 28.1121 +                    break;
 28.1122 +
 28.1123 +                case 'C':
 28.1124 +                case 'S':
 28.1125 +                    f.setOffset(primDataSize);
 28.1126 +                    primDataSize += 2;
 28.1127 +                    break;
 28.1128 +
 28.1129 +                case 'I':
 28.1130 +                case 'F':
 28.1131 +                    f.setOffset(primDataSize);
 28.1132 +                    primDataSize += 4;
 28.1133 +                    break;
 28.1134 +
 28.1135 +                case 'J':
 28.1136 +                case 'D':
 28.1137 +                    f.setOffset(primDataSize);
 28.1138 +                    primDataSize += 8;
 28.1139 +                    break;
 28.1140 +
 28.1141 +                case '[':
 28.1142 +                case 'L':
 28.1143 +                    f.setOffset(numObjFields++);
 28.1144 +                    if (firstObjIndex == -1) {
 28.1145 +                        firstObjIndex = i;
 28.1146 +                    }
 28.1147 +                    break;
 28.1148 +
 28.1149 +                default:
 28.1150 +                    throw new InternalError();
 28.1151 +            }
 28.1152 +        }
 28.1153 +        if (firstObjIndex != -1 &&
 28.1154 +            firstObjIndex + numObjFields != fields.length)
 28.1155 +        {
 28.1156 +            throw new InvalidClassException(name, "illegal field order");
 28.1157 +        }
 28.1158 +    }
 28.1159 +
 28.1160 +    /**
 28.1161 +     * If given class is the same as the class associated with this class
 28.1162 +     * descriptor, returns reference to this class descriptor.  Otherwise,
 28.1163 +     * returns variant of this class descriptor bound to given class.
 28.1164 +     */
 28.1165 +    private ObjectStreamClass getVariantFor(Class<?> cl)
 28.1166 +        throws InvalidClassException
 28.1167 +    {
 28.1168 +        if (this.cl == cl) {
 28.1169 +            return this;
 28.1170 +        }
 28.1171 +        ObjectStreamClass desc = new ObjectStreamClass();
 28.1172 +        if (isProxy) {
 28.1173 +            desc.initProxy(cl, null, superDesc);
 28.1174 +        } else {
 28.1175 +            desc.initNonProxy(this, cl, null, superDesc);
 28.1176 +        }
 28.1177 +        return desc;
 28.1178 +    }
 28.1179 +
 28.1180 +    /**
 28.1181 +     * Returns public no-arg constructor of given class, or null if none found.
 28.1182 +     * Access checks are disabled on the returned constructor (if any), since
 28.1183 +     * the defining class may still be non-public.
 28.1184 +     */
 28.1185 +    private static Constructor getExternalizableConstructor(Class<?> cl) {
 28.1186 +        throw new SecurityException();
 28.1187 +    }
 28.1188 +
 28.1189 +    /**
 28.1190 +     * Returns subclass-accessible no-arg constructor of first non-serializable
 28.1191 +     * superclass, or null if none found.  Access checks are disabled on the
 28.1192 +     * returned constructor (if any).
 28.1193 +     */
 28.1194 +    private static Constructor getSerializableConstructor(Class<?> cl) {
 28.1195 +        Class<?> initCl = cl;
 28.1196 +        while (Serializable.class.isAssignableFrom(initCl)) {
 28.1197 +            if ((initCl = initCl.getSuperclass()) == null) {
 28.1198 +                return null;
 28.1199 +            }
 28.1200 +        }
 28.1201 +        throw new SecurityException();
 28.1202 +    }
 28.1203 +
 28.1204 +    /**
 28.1205 +     * Returns non-static, non-abstract method with given signature provided it
 28.1206 +     * is defined by or accessible (via inheritance) by the given class, or
 28.1207 +     * null if no match found.  Access checks are disabled on the returned
 28.1208 +     * method (if any).
 28.1209 +     */
 28.1210 +    private static Method getInheritableMethod(Class<?> cl, String name,
 28.1211 +                                               Class<?>[] argTypes,
 28.1212 +                                               Class<?> returnType)
 28.1213 +    {
 28.1214 +        throw new SecurityException();
 28.1215 +    }
 28.1216 +
 28.1217 +    /**
 28.1218 +     * Returns non-static private method with given signature defined by given
 28.1219 +     * class, or null if none found.  Access checks are disabled on the
 28.1220 +     * returned method (if any).
 28.1221 +     */
 28.1222 +    private static Method getPrivateMethod(Class<?> cl, String name,
 28.1223 +                                           Class<?>[] argTypes,
 28.1224 +                                           Class<?> returnType)
 28.1225 +    {
 28.1226 +        throw new SecurityException();
 28.1227 +    }
 28.1228 +
 28.1229 +    /**
 28.1230 +     * Returns true if classes are defined in the same runtime package, false
 28.1231 +     * otherwise.
 28.1232 +     */
 28.1233 +    private static boolean packageEquals(Class<?> cl1, Class<?> cl2) {
 28.1234 +        return (cl1.getClassLoader() == cl2.getClassLoader() &&
 28.1235 +                getPackageName(cl1).equals(getPackageName(cl2)));
 28.1236 +    }
 28.1237 +
 28.1238 +    /**
 28.1239 +     * Returns package name of given class.
 28.1240 +     */
 28.1241 +    private static String getPackageName(Class<?> cl) {
 28.1242 +        String s = cl.getName();
 28.1243 +        int i = s.lastIndexOf('[');
 28.1244 +        if (i >= 0) {
 28.1245 +            s = s.substring(i + 2);
 28.1246 +        }
 28.1247 +        i = s.lastIndexOf('.');
 28.1248 +        return (i >= 0) ? s.substring(0, i) : "";
 28.1249 +    }
 28.1250 +
 28.1251 +    /**
 28.1252 +     * Compares class names for equality, ignoring package names.  Returns true
 28.1253 +     * if class names equal, false otherwise.
 28.1254 +     */
 28.1255 +    private static boolean classNamesEqual(String name1, String name2) {
 28.1256 +        name1 = name1.substring(name1.lastIndexOf('.') + 1);
 28.1257 +        name2 = name2.substring(name2.lastIndexOf('.') + 1);
 28.1258 +        return name1.equals(name2);
 28.1259 +    }
 28.1260 +
 28.1261 +    /**
 28.1262 +     * Returns JVM type signature for given class.
 28.1263 +     */
 28.1264 +    private static String getClassSignature(Class<?> cl) {
 28.1265 +        StringBuilder sbuf = new StringBuilder();
 28.1266 +        while (cl.isArray()) {
 28.1267 +            sbuf.append('[');
 28.1268 +            cl = cl.getComponentType();
 28.1269 +        }
 28.1270 +        if (cl.isPrimitive()) {
 28.1271 +            if (cl == Integer.TYPE) {
 28.1272 +                sbuf.append('I');
 28.1273 +            } else if (cl == Byte.TYPE) {
 28.1274 +                sbuf.append('B');
 28.1275 +            } else if (cl == Long.TYPE) {
 28.1276 +                sbuf.append('J');
 28.1277 +            } else if (cl == Float.TYPE) {
 28.1278 +                sbuf.append('F');
 28.1279 +            } else if (cl == Double.TYPE) {
 28.1280 +                sbuf.append('D');
 28.1281 +            } else if (cl == Short.TYPE) {
 28.1282 +                sbuf.append('S');
 28.1283 +            } else if (cl == Character.TYPE) {
 28.1284 +                sbuf.append('C');
 28.1285 +            } else if (cl == Boolean.TYPE) {
 28.1286 +                sbuf.append('Z');
 28.1287 +            } else if (cl == Void.TYPE) {
 28.1288 +                sbuf.append('V');
 28.1289 +            } else {
 28.1290 +                throw new InternalError();
 28.1291 +            }
 28.1292 +        } else {
 28.1293 +            sbuf.append('L' + cl.getName().replace('.', '/') + ';');
 28.1294 +        }
 28.1295 +        return sbuf.toString();
 28.1296 +    }
 28.1297 +
 28.1298 +    /**
 28.1299 +     * Returns JVM type signature for given list of parameters and return type.
 28.1300 +     */
 28.1301 +    private static String getMethodSignature(Class<?>[] paramTypes,
 28.1302 +                                             Class<?> retType)
 28.1303 +    {
 28.1304 +        StringBuilder sbuf = new StringBuilder();
 28.1305 +        sbuf.append('(');
 28.1306 +        for (int i = 0; i < paramTypes.length; i++) {
 28.1307 +            sbuf.append(getClassSignature(paramTypes[i]));
 28.1308 +        }
 28.1309 +        sbuf.append(')');
 28.1310 +        sbuf.append(getClassSignature(retType));
 28.1311 +        return sbuf.toString();
 28.1312 +    }
 28.1313 +
 28.1314 +    /**
 28.1315 +     * Convenience method for throwing an exception that is either a
 28.1316 +     * RuntimeException, Error, or of some unexpected type (in which case it is
 28.1317 +     * wrapped inside an IOException).
 28.1318 +     */
 28.1319 +    private static void throwMiscException(Throwable th) throws IOException {
 28.1320 +        if (th instanceof RuntimeException) {
 28.1321 +            throw (RuntimeException) th;
 28.1322 +        } else if (th instanceof Error) {
 28.1323 +            throw (Error) th;
 28.1324 +        } else {
 28.1325 +            IOException ex = new IOException("unexpected exception type");
 28.1326 +            ex.initCause(th);
 28.1327 +            throw ex;
 28.1328 +        }
 28.1329 +    }
 28.1330 +
 28.1331 +    /**
 28.1332 +     * Returns ObjectStreamField array describing the serializable fields of
 28.1333 +     * the given class.  Serializable fields backed by an actual field of the
 28.1334 +     * class are represented by ObjectStreamFields with corresponding non-null
 28.1335 +     * Field objects.  Throws InvalidClassException if the (explicitly
 28.1336 +     * declared) serializable fields are invalid.
 28.1337 +     */
 28.1338 +    private static ObjectStreamField[] getSerialFields(Class<?> cl)
 28.1339 +        throws InvalidClassException
 28.1340 +    {
 28.1341 +        ObjectStreamField[] fields;
 28.1342 +        if (Serializable.class.isAssignableFrom(cl) &&
 28.1343 +            !Externalizable.class.isAssignableFrom(cl) &&
 28.1344 +            !Proxy.isProxyClass(cl) &&
 28.1345 +            !cl.isInterface())
 28.1346 +        {
 28.1347 +            if ((fields = getDeclaredSerialFields(cl)) == null) {
 28.1348 +                fields = getDefaultSerialFields(cl);
 28.1349 +            }
 28.1350 +            Arrays.sort(fields);
 28.1351 +        } else {
 28.1352 +            fields = NO_FIELDS;
 28.1353 +        }
 28.1354 +        return fields;
 28.1355 +    }
 28.1356 +
 28.1357 +    /**
 28.1358 +     * Returns serializable fields of given class as defined explicitly by a
 28.1359 +     * "serialPersistentFields" field, or null if no appropriate
 28.1360 +     * "serialPersistentFields" field is defined.  Serializable fields backed
 28.1361 +     * by an actual field of the class are represented by ObjectStreamFields
 28.1362 +     * with corresponding non-null Field objects.  For compatibility with past
 28.1363 +     * releases, a "serialPersistentFields" field with a null value is
 28.1364 +     * considered equivalent to not declaring "serialPersistentFields".  Throws
 28.1365 +     * InvalidClassException if the declared serializable fields are
 28.1366 +     * invalid--e.g., if multiple fields share the same name.
 28.1367 +     */
 28.1368 +    private static ObjectStreamField[] getDeclaredSerialFields(Class<?> cl)
 28.1369 +        throws InvalidClassException
 28.1370 +    {
 28.1371 +        throw new SecurityException();
 28.1372 +    }
 28.1373 +
 28.1374 +    /**
 28.1375 +     * Returns array of ObjectStreamFields corresponding to all non-static
 28.1376 +     * non-transient fields declared by given class.  Each ObjectStreamField
 28.1377 +     * contains a Field object for the field it represents.  If no default
 28.1378 +     * serializable fields exist, NO_FIELDS is returned.
 28.1379 +     */
 28.1380 +    private static ObjectStreamField[] getDefaultSerialFields(Class<?> cl) {
 28.1381 +        throw new SecurityException();
 28.1382 +    }
 28.1383 +
 28.1384 +    /**
 28.1385 +     * Returns explicit serial version UID value declared by given class, or
 28.1386 +     * null if none.
 28.1387 +     */
 28.1388 +    private static Long getDeclaredSUID(Class<?> cl) {
 28.1389 +        return null;
 28.1390 +    }
 28.1391 +
 28.1392 +    /**
 28.1393 +     * Computes the default serial version UID value for the given class.
 28.1394 +     */
 28.1395 +    private static long computeDefaultSUID(Class<?> cl) {
 28.1396 +        throw new SecurityException();
 28.1397 +    }
 28.1398 +
 28.1399 +}
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/emul/compact/src/main/java/java/io/ObjectStreamConstants.java	Mon Feb 04 09:37:56 2013 +0100
    29.3 @@ -0,0 +1,215 @@
    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 +/**
   29.32 + * Constants written into the Object Serialization Stream.
   29.33 + *
   29.34 + * @author  unascribed
   29.35 + * @since JDK 1.1
   29.36 + */
   29.37 +public interface ObjectStreamConstants {
   29.38 +
   29.39 +    /**
   29.40 +     * Magic number that is written to the stream header.
   29.41 +     */
   29.42 +    final static short STREAM_MAGIC = (short)0xaced;
   29.43 +
   29.44 +    /**
   29.45 +     * Version number that is written to the stream header.
   29.46 +     */
   29.47 +    final static short STREAM_VERSION = 5;
   29.48 +
   29.49 +    /* Each item in the stream is preceded by a tag
   29.50 +     */
   29.51 +
   29.52 +    /**
   29.53 +     * First tag value.
   29.54 +     */
   29.55 +    final static byte TC_BASE = 0x70;
   29.56 +
   29.57 +    /**
   29.58 +     * Null object reference.
   29.59 +     */
   29.60 +    final static byte TC_NULL =         (byte)0x70;
   29.61 +
   29.62 +    /**
   29.63 +     * Reference to an object already written into the stream.
   29.64 +     */
   29.65 +    final static byte TC_REFERENCE =    (byte)0x71;
   29.66 +
   29.67 +    /**
   29.68 +     * new Class Descriptor.
   29.69 +     */
   29.70 +    final static byte TC_CLASSDESC =    (byte)0x72;
   29.71 +
   29.72 +    /**
   29.73 +     * new Object.
   29.74 +     */
   29.75 +    final static byte TC_OBJECT =       (byte)0x73;
   29.76 +
   29.77 +    /**
   29.78 +     * new String.
   29.79 +     */
   29.80 +    final static byte TC_STRING =       (byte)0x74;
   29.81 +
   29.82 +    /**
   29.83 +     * new Array.
   29.84 +     */
   29.85 +    final static byte TC_ARRAY =        (byte)0x75;
   29.86 +
   29.87 +    /**
   29.88 +     * Reference to Class.
   29.89 +     */
   29.90 +    final static byte TC_CLASS =        (byte)0x76;
   29.91 +
   29.92 +    /**
   29.93 +     * Block of optional data. Byte following tag indicates number
   29.94 +     * of bytes in this block data.
   29.95 +     */
   29.96 +    final static byte TC_BLOCKDATA =    (byte)0x77;
   29.97 +
   29.98 +    /**
   29.99 +     * End of optional block data blocks for an object.
  29.100 +     */
  29.101 +    final static byte TC_ENDBLOCKDATA = (byte)0x78;
  29.102 +
  29.103 +    /**
  29.104 +     * Reset stream context. All handles written into stream are reset.
  29.105 +     */
  29.106 +    final static byte TC_RESET =        (byte)0x79;
  29.107 +
  29.108 +    /**
  29.109 +     * long Block data. The long following the tag indicates the
  29.110 +     * number of bytes in this block data.
  29.111 +     */
  29.112 +    final static byte TC_BLOCKDATALONG= (byte)0x7A;
  29.113 +
  29.114 +    /**
  29.115 +     * Exception during write.
  29.116 +     */
  29.117 +    final static byte TC_EXCEPTION =    (byte)0x7B;
  29.118 +
  29.119 +    /**
  29.120 +     * Long string.
  29.121 +     */
  29.122 +    final static byte TC_LONGSTRING =   (byte)0x7C;
  29.123 +
  29.124 +    /**
  29.125 +     * new Proxy Class Descriptor.
  29.126 +     */
  29.127 +    final static byte TC_PROXYCLASSDESC =       (byte)0x7D;
  29.128 +
  29.129 +    /**
  29.130 +     * new Enum constant.
  29.131 +     * @since 1.5
  29.132 +     */
  29.133 +    final static byte TC_ENUM =         (byte)0x7E;
  29.134 +
  29.135 +    /**
  29.136 +     * Last tag value.
  29.137 +     */
  29.138 +    final static byte TC_MAX =          (byte)0x7E;
  29.139 +
  29.140 +    /**
  29.141 +     * First wire handle to be assigned.
  29.142 +     */
  29.143 +    final static int baseWireHandle = 0x7e0000;
  29.144 +
  29.145 +
  29.146 +    /******************************************************/
  29.147 +    /* Bit masks for ObjectStreamClass flag.*/
  29.148 +
  29.149 +    /**
  29.150 +     * Bit mask for ObjectStreamClass flag. Indicates a Serializable class
  29.151 +     * defines its own writeObject method.
  29.152 +     */
  29.153 +    final static byte SC_WRITE_METHOD = 0x01;
  29.154 +
  29.155 +    /**
  29.156 +     * Bit mask for ObjectStreamClass flag. Indicates Externalizable data
  29.157 +     * written in Block Data mode.
  29.158 +     * Added for PROTOCOL_VERSION_2.
  29.159 +     *
  29.160 +     * @see #PROTOCOL_VERSION_2
  29.161 +     * @since 1.2
  29.162 +     */
  29.163 +    final static byte SC_BLOCK_DATA = 0x08;
  29.164 +
  29.165 +    /**
  29.166 +     * Bit mask for ObjectStreamClass flag. Indicates class is Serializable.
  29.167 +     */
  29.168 +    final static byte SC_SERIALIZABLE = 0x02;
  29.169 +
  29.170 +    /**
  29.171 +     * Bit mask for ObjectStreamClass flag. Indicates class is Externalizable.
  29.172 +     */
  29.173 +    final static byte SC_EXTERNALIZABLE = 0x04;
  29.174 +
  29.175 +    /**
  29.176 +     * Bit mask for ObjectStreamClass flag. Indicates class is an enum type.
  29.177 +     * @since 1.5
  29.178 +     */
  29.179 +    final static byte SC_ENUM = 0x10;
  29.180 +
  29.181 +
  29.182 +    /* *******************************************************************/
  29.183 +    /* Security permissions */
  29.184 +
  29.185 +   /**
  29.186 +    * A Stream Protocol Version. <p>
  29.187 +    *
  29.188 +    * All externalizable data is written in JDK 1.1 external data
  29.189 +    * format after calling this method. This version is needed to write
  29.190 +    * streams containing Externalizable data that can be read by
  29.191 +    * pre-JDK 1.1.6 JVMs.
  29.192 +    *
  29.193 +    * @see java.io.ObjectOutputStream#useProtocolVersion(int)
  29.194 +    * @since 1.2
  29.195 +    */
  29.196 +    public final static int PROTOCOL_VERSION_1 = 1;
  29.197 +
  29.198 +
  29.199 +   /**
  29.200 +    * A Stream Protocol Version. <p>
  29.201 +    *
  29.202 +    * This protocol is written by JVM 1.2.
  29.203 +    *
  29.204 +    * Externalizable data is written in block data mode and is
  29.205 +    * terminated with TC_ENDBLOCKDATA. Externalizable classdescriptor
  29.206 +    * flags has SC_BLOCK_DATA enabled. JVM 1.1.6 and greater can
  29.207 +    * read this format change.
  29.208 +    *
  29.209 +    * Enables writing a nonSerializable class descriptor into the
  29.210 +    * stream. The serialVersionUID of a nonSerializable class is
  29.211 +    * set to 0L.
  29.212 +    *
  29.213 +    * @see java.io.ObjectOutputStream#useProtocolVersion(int)
  29.214 +    * @see #SC_BLOCK_DATA
  29.215 +    * @since 1.2
  29.216 +    */
  29.217 +    public final static int PROTOCOL_VERSION_2 = 2;
  29.218 +}
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/emul/compact/src/main/java/java/io/ObjectStreamException.java	Mon Feb 04 09:37:56 2013 +0100
    30.3 @@ -0,0 +1,53 @@
    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 +
   30.29 +package java.io;
   30.30 +
   30.31 +/**
   30.32 + * Superclass of all exceptions specific to Object Stream classes.
   30.33 + *
   30.34 + * @author  unascribed
   30.35 + * @since   JDK1.1
   30.36 + */
   30.37 +public abstract class ObjectStreamException extends IOException {
   30.38 +
   30.39 +    private static final long serialVersionUID = 7260898174833392607L;
   30.40 +
   30.41 +    /**
   30.42 +     * Create an ObjectStreamException with the specified argument.
   30.43 +     *
   30.44 +     * @param classname the detailed message for the exception
   30.45 +     */
   30.46 +    protected ObjectStreamException(String classname) {
   30.47 +        super(classname);
   30.48 +    }
   30.49 +
   30.50 +    /**
   30.51 +     * Create an ObjectStreamException.
   30.52 +     */
   30.53 +    protected ObjectStreamException() {
   30.54 +        super();
   30.55 +    }
   30.56 +}
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/emul/compact/src/main/java/java/io/ObjectStreamField.java	Mon Feb 04 09:37:56 2013 +0100
    31.3 @@ -0,0 +1,314 @@
    31.4 +/*
    31.5 + * Copyright (c) 1996, 2006, 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 +import java.lang.reflect.Field;
   31.32 +
   31.33 +/**
   31.34 + * A description of a Serializable field from a Serializable class.  An array
   31.35 + * of ObjectStreamFields is used to declare the Serializable fields of a class.
   31.36 + *
   31.37 + * @author      Mike Warres
   31.38 + * @author      Roger Riggs
   31.39 + * @see ObjectStreamClass
   31.40 + * @since 1.2
   31.41 + */
   31.42 +public class ObjectStreamField
   31.43 +    implements Comparable<Object>
   31.44 +{
   31.45 +
   31.46 +    /** field name */
   31.47 +    private final String name;
   31.48 +    /** canonical JVM signature of field type */
   31.49 +    private final String signature;
   31.50 +    /** field type (Object.class if unknown non-primitive type) */
   31.51 +    private final Class<?> type;
   31.52 +    /** whether or not to (de)serialize field values as unshared */
   31.53 +    private final boolean unshared;
   31.54 +    /** corresponding reflective field object, if any */
   31.55 +    private final Field field;
   31.56 +    /** offset of field value in enclosing field group */
   31.57 +    private int offset = 0;
   31.58 +
   31.59 +    /**
   31.60 +     * Create a Serializable field with the specified type.  This field should
   31.61 +     * be documented with a <code>serialField</code> tag.
   31.62 +     *
   31.63 +     * @param   name the name of the serializable field
   31.64 +     * @param   type the <code>Class</code> object of the serializable field
   31.65 +     */
   31.66 +    public ObjectStreamField(String name, Class<?> type) {
   31.67 +        this(name, type, false);
   31.68 +    }
   31.69 +
   31.70 +    /**
   31.71 +     * Creates an ObjectStreamField representing a serializable field with the
   31.72 +     * given name and type.  If unshared is false, values of the represented
   31.73 +     * field are serialized and deserialized in the default manner--if the
   31.74 +     * field is non-primitive, object values are serialized and deserialized as
   31.75 +     * if they had been written and read by calls to writeObject and
   31.76 +     * readObject.  If unshared is true, values of the represented field are
   31.77 +     * serialized and deserialized as if they had been written and read by
   31.78 +     * calls to writeUnshared and readUnshared.
   31.79 +     *
   31.80 +     * @param   name field name
   31.81 +     * @param   type field type
   31.82 +     * @param   unshared if false, write/read field values in the same manner
   31.83 +     *          as writeObject/readObject; if true, write/read in the same
   31.84 +     *          manner as writeUnshared/readUnshared
   31.85 +     * @since   1.4
   31.86 +     */
   31.87 +    public ObjectStreamField(String name, Class<?> type, boolean unshared) {
   31.88 +        if (name == null) {
   31.89 +            throw new NullPointerException();
   31.90 +        }
   31.91 +        this.name = name;
   31.92 +        this.type = type;
   31.93 +        this.unshared = unshared;
   31.94 +        signature = getClassSignature(type).intern();
   31.95 +        field = null;
   31.96 +    }
   31.97 +
   31.98 +    /**
   31.99 +     * Creates an ObjectStreamField representing a field with the given name,
  31.100 +     * signature and unshared setting.
  31.101 +     */
  31.102 +    ObjectStreamField(String name, String signature, boolean unshared) {
  31.103 +        if (name == null) {
  31.104 +            throw new NullPointerException();
  31.105 +        }
  31.106 +        this.name = name;
  31.107 +        this.signature = signature.intern();
  31.108 +        this.unshared = unshared;
  31.109 +        field = null;
  31.110 +
  31.111 +        switch (signature.charAt(0)) {
  31.112 +            case 'Z': type = Boolean.TYPE; break;
  31.113 +            case 'B': type = Byte.TYPE; break;
  31.114 +            case 'C': type = Character.TYPE; break;
  31.115 +            case 'S': type = Short.TYPE; break;
  31.116 +            case 'I': type = Integer.TYPE; break;
  31.117 +            case 'J': type = Long.TYPE; break;
  31.118 +            case 'F': type = Float.TYPE; break;
  31.119 +            case 'D': type = Double.TYPE; break;
  31.120 +            case 'L':
  31.121 +            case '[': type = Object.class; break;
  31.122 +            default: throw new IllegalArgumentException("illegal signature");
  31.123 +        }
  31.124 +    }
  31.125 +
  31.126 +    /**
  31.127 +     * Creates an ObjectStreamField representing the given field with the
  31.128 +     * specified unshared setting.  For compatibility with the behavior of
  31.129 +     * earlier serialization implementations, a "showType" parameter is
  31.130 +     * necessary to govern whether or not a getType() call on this
  31.131 +     * ObjectStreamField (if non-primitive) will return Object.class (as
  31.132 +     * opposed to a more specific reference type).
  31.133 +     */
  31.134 +    ObjectStreamField(Field field, boolean unshared, boolean showType) {
  31.135 +        this.field = field;
  31.136 +        this.unshared = unshared;
  31.137 +        name = field.getName();
  31.138 +        Class<?> ftype = field.getType();
  31.139 +        type = (showType || ftype.isPrimitive()) ? ftype : Object.class;
  31.140 +        signature = getClassSignature(ftype).intern();
  31.141 +    }
  31.142 +
  31.143 +    /**
  31.144 +     * Get the name of this field.
  31.145 +     *
  31.146 +     * @return  a <code>String</code> representing the name of the serializable
  31.147 +     *          field
  31.148 +     */
  31.149 +    public String getName() {
  31.150 +        return name;
  31.151 +    }
  31.152 +
  31.153 +    /**
  31.154 +     * Get the type of the field.  If the type is non-primitive and this
  31.155 +     * <code>ObjectStreamField</code> was obtained from a deserialized {@link
  31.156 +     * ObjectStreamClass} instance, then <code>Object.class</code> is returned.
  31.157 +     * Otherwise, the <code>Class</code> object for the type of the field is
  31.158 +     * returned.
  31.159 +     *
  31.160 +     * @return  a <code>Class</code> object representing the type of the
  31.161 +     *          serializable field
  31.162 +     */
  31.163 +    public Class<?> getType() {
  31.164 +        return type;
  31.165 +    }
  31.166 +
  31.167 +    /**
  31.168 +     * Returns character encoding of field type.  The encoding is as follows:
  31.169 +     * <blockquote><pre>
  31.170 +     * B            byte
  31.171 +     * C            char
  31.172 +     * D            double
  31.173 +     * F            float
  31.174 +     * I            int
  31.175 +     * J            long
  31.176 +     * L            class or interface
  31.177 +     * S            short
  31.178 +     * Z            boolean
  31.179 +     * [            array
  31.180 +     * </pre></blockquote>
  31.181 +     *
  31.182 +     * @return  the typecode of the serializable field
  31.183 +     */
  31.184 +    // REMIND: deprecate?
  31.185 +    public char getTypeCode() {
  31.186 +        return signature.charAt(0);
  31.187 +    }
  31.188 +
  31.189 +    /**
  31.190 +     * Return the JVM type signature.
  31.191 +     *
  31.192 +     * @return  null if this field has a primitive type.
  31.193 +     */
  31.194 +    // REMIND: deprecate?
  31.195 +    public String getTypeString() {
  31.196 +        return isPrimitive() ? null : signature;
  31.197 +    }
  31.198 +
  31.199 +    /**
  31.200 +     * Offset of field within instance data.
  31.201 +     *
  31.202 +     * @return  the offset of this field
  31.203 +     * @see #setOffset
  31.204 +     */
  31.205 +    // REMIND: deprecate?
  31.206 +    public int getOffset() {
  31.207 +        return offset;
  31.208 +    }
  31.209 +
  31.210 +    /**
  31.211 +     * Offset within instance data.
  31.212 +     *
  31.213 +     * @param   offset the offset of the field
  31.214 +     * @see #getOffset
  31.215 +     */
  31.216 +    // REMIND: deprecate?
  31.217 +    protected void setOffset(int offset) {
  31.218 +        this.offset = offset;
  31.219 +    }
  31.220 +
  31.221 +    /**
  31.222 +     * Return true if this field has a primitive type.
  31.223 +     *
  31.224 +     * @return  true if and only if this field corresponds to a primitive type
  31.225 +     */
  31.226 +    // REMIND: deprecate?
  31.227 +    public boolean isPrimitive() {
  31.228 +        char tcode = signature.charAt(0);
  31.229 +        return ((tcode != 'L') && (tcode != '['));
  31.230 +    }
  31.231 +
  31.232 +    /**
  31.233 +     * Returns boolean value indicating whether or not the serializable field
  31.234 +     * represented by this ObjectStreamField instance is unshared.
  31.235 +     *
  31.236 +     * @since 1.4
  31.237 +     */
  31.238 +    public boolean isUnshared() {
  31.239 +        return unshared;
  31.240 +    }
  31.241 +
  31.242 +    /**
  31.243 +     * Compare this field with another <code>ObjectStreamField</code>.  Return
  31.244 +     * -1 if this is smaller, 0 if equal, 1 if greater.  Types that are
  31.245 +     * primitives are "smaller" than object types.  If equal, the field names
  31.246 +     * are compared.
  31.247 +     */
  31.248 +    // REMIND: deprecate?
  31.249 +    public int compareTo(Object obj) {
  31.250 +        ObjectStreamField other = (ObjectStreamField) obj;
  31.251 +        boolean isPrim = isPrimitive();
  31.252 +        if (isPrim != other.isPrimitive()) {
  31.253 +            return isPrim ? -1 : 1;
  31.254 +        }
  31.255 +        return name.compareTo(other.name);
  31.256 +    }
  31.257 +
  31.258 +    /**
  31.259 +     * Return a string that describes this field.
  31.260 +     */
  31.261 +    public String toString() {
  31.262 +        return signature + ' ' + name;
  31.263 +    }
  31.264 +
  31.265 +    /**
  31.266 +     * Returns field represented by this ObjectStreamField, or null if
  31.267 +     * ObjectStreamField is not associated with an actual field.
  31.268 +     */
  31.269 +    Field getField() {
  31.270 +        return field;
  31.271 +    }
  31.272 +
  31.273 +    /**
  31.274 +     * Returns JVM type signature of field (similar to getTypeString, except
  31.275 +     * that signature strings are returned for primitive fields as well).
  31.276 +     */
  31.277 +    String getSignature() {
  31.278 +        return signature;
  31.279 +    }
  31.280 +
  31.281 +    /**
  31.282 +     * Returns JVM type signature for given class.
  31.283 +     */
  31.284 +    private static String getClassSignature(Class<?> cl) {
  31.285 +        StringBuilder sbuf = new StringBuilder();
  31.286 +        while (cl.isArray()) {
  31.287 +            sbuf.append('[');
  31.288 +            cl = cl.getComponentType();
  31.289 +        }
  31.290 +        if (cl.isPrimitive()) {
  31.291 +            if (cl == Integer.TYPE) {
  31.292 +                sbuf.append('I');
  31.293 +            } else if (cl == Byte.TYPE) {
  31.294 +                sbuf.append('B');
  31.295 +            } else if (cl == Long.TYPE) {
  31.296 +                sbuf.append('J');
  31.297 +            } else if (cl == Float.TYPE) {
  31.298 +                sbuf.append('F');
  31.299 +            } else if (cl == Double.TYPE) {
  31.300 +                sbuf.append('D');
  31.301 +            } else if (cl == Short.TYPE) {
  31.302 +                sbuf.append('S');
  31.303 +            } else if (cl == Character.TYPE) {
  31.304 +                sbuf.append('C');
  31.305 +            } else if (cl == Boolean.TYPE) {
  31.306 +                sbuf.append('Z');
  31.307 +            } else if (cl == Void.TYPE) {
  31.308 +                sbuf.append('V');
  31.309 +            } else {
  31.310 +                throw new InternalError();
  31.311 +            }
  31.312 +        } else {
  31.313 +            sbuf.append('L' + cl.getName().replace('.', '/') + ';');
  31.314 +        }
  31.315 +        return sbuf.toString();
  31.316 +    }
  31.317 +}
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/emul/compact/src/main/java/java/io/OptionalDataException.java	Mon Feb 04 09:37:56 2013 +0100
    32.3 @@ -0,0 +1,83 @@
    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 +package java.io;
   32.29 +
   32.30 +/**
   32.31 + * Exception indicating the failure of an object read operation due to
   32.32 + * unread primitive data, or the end of data belonging to a serialized
   32.33 + * object in the stream.  This exception may be thrown in two cases:
   32.34 + *
   32.35 + * <ul>
   32.36 + *   <li>An attempt was made to read an object when the next element in the
   32.37 + *       stream is primitive data.  In this case, the OptionalDataException's
   32.38 + *       length field is set to the number of bytes of primitive data
   32.39 + *       immediately readable from the stream, and the eof field is set to
   32.40 + *       false.
   32.41 + *
   32.42 + *   <li>An attempt was made to read past the end of data consumable by a
   32.43 + *       class-defined readObject or readExternal method.  In this case, the
   32.44 + *       OptionalDataException's eof field is set to true, and the length field
   32.45 + *       is set to 0.
   32.46 + * </ul>
   32.47 + *
   32.48 + * @author  unascribed
   32.49 + * @since   JDK1.1
   32.50 + */
   32.51 +public class OptionalDataException extends ObjectStreamException {
   32.52 +
   32.53 +    private static final long serialVersionUID = -8011121865681257820L;
   32.54 +
   32.55 +    /*
   32.56 +     * Create an <code>OptionalDataException</code> with a length.
   32.57 +     */
   32.58 +    OptionalDataException(int len) {
   32.59 +        eof = false;
   32.60 +        length = len;
   32.61 +    }
   32.62 +
   32.63 +    /*
   32.64 +     * Create an <code>OptionalDataException</code> signifying no
   32.65 +     * more primitive data is available.
   32.66 +     */
   32.67 +    OptionalDataException(boolean end) {
   32.68 +        length = 0;
   32.69 +        eof = end;
   32.70 +    }
   32.71 +
   32.72 +    /**
   32.73 +     * The number of bytes of primitive data available to be read
   32.74 +     * in the current buffer.
   32.75 +     *
   32.76 +     * @serial
   32.77 +     */
   32.78 +    public int length;
   32.79 +
   32.80 +    /**
   32.81 +     * True if there is no more data in the buffered part of the stream.
   32.82 +     *
   32.83 +     * @serial
   32.84 +     */
   32.85 +    public boolean eof;
   32.86 +}
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/emul/compact/src/main/java/java/io/OutputStream.java	Mon Feb 04 09:37:56 2013 +0100
    33.3 @@ -0,0 +1,154 @@
    33.4 +/*
    33.5 + * Copyright (c) 1994, 2004, 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 + * This abstract class is the superclass of all classes representing
   33.33 + * an output stream of bytes. An output stream accepts output bytes
   33.34 + * and sends them to some sink.
   33.35 + * <p>
   33.36 + * Applications that need to define a subclass of
   33.37 + * <code>OutputStream</code> must always provide at least a method
   33.38 + * that writes one byte of output.
   33.39 + *
   33.40 + * @author  Arthur van Hoff
   33.41 + * @see     java.io.BufferedOutputStream
   33.42 + * @see     java.io.ByteArrayOutputStream
   33.43 + * @see     java.io.DataOutputStream
   33.44 + * @see     java.io.FilterOutputStream
   33.45 + * @see     java.io.InputStream
   33.46 + * @see     java.io.OutputStream#write(int)
   33.47 + * @since   JDK1.0
   33.48 + */
   33.49 +public abstract class OutputStream implements Closeable, Flushable {
   33.50 +    /**
   33.51 +     * Writes the specified byte to this output stream. The general
   33.52 +     * contract for <code>write</code> is that one byte is written
   33.53 +     * to the output stream. The byte to be written is the eight
   33.54 +     * low-order bits of the argument <code>b</code>. The 24
   33.55 +     * high-order bits of <code>b</code> are ignored.
   33.56 +     * <p>
   33.57 +     * Subclasses of <code>OutputStream</code> must provide an
   33.58 +     * implementation for this method.
   33.59 +     *
   33.60 +     * @param      b   the <code>byte</code>.
   33.61 +     * @exception  IOException  if an I/O error occurs. In particular,
   33.62 +     *             an <code>IOException</code> may be thrown if the
   33.63 +     *             output stream has been closed.
   33.64 +     */
   33.65 +    public abstract void write(int b) throws IOException;
   33.66 +
   33.67 +    /**
   33.68 +     * Writes <code>b.length</code> bytes from the specified byte array
   33.69 +     * to this output stream. The general contract for <code>write(b)</code>
   33.70 +     * is that it should have exactly the same effect as the call
   33.71 +     * <code>write(b, 0, b.length)</code>.
   33.72 +     *
   33.73 +     * @param      b   the data.
   33.74 +     * @exception  IOException  if an I/O error occurs.
   33.75 +     * @see        java.io.OutputStream#write(byte[], int, int)
   33.76 +     */
   33.77 +    public void write(byte b[]) throws IOException {
   33.78 +        write(b, 0, b.length);
   33.79 +    }
   33.80 +
   33.81 +    /**
   33.82 +     * Writes <code>len</code> bytes from the specified byte array
   33.83 +     * starting at offset <code>off</code> to this output stream.
   33.84 +     * The general contract for <code>write(b, off, len)</code> is that
   33.85 +     * some of the bytes in the array <code>b</code> are written to the
   33.86 +     * output stream in order; element <code>b[off]</code> is the first
   33.87 +     * byte written and <code>b[off+len-1]</code> is the last byte written
   33.88 +     * by this operation.
   33.89 +     * <p>
   33.90 +     * The <code>write</code> method of <code>OutputStream</code> calls
   33.91 +     * the write method of one argument on each of the bytes to be
   33.92 +     * written out. Subclasses are encouraged to override this method and
   33.93 +     * provide a more efficient implementation.
   33.94 +     * <p>
   33.95 +     * If <code>b</code> is <code>null</code>, a
   33.96 +     * <code>NullPointerException</code> is thrown.
   33.97 +     * <p>
   33.98 +     * If <code>off</code> is negative, or <code>len</code> is negative, or
   33.99 +     * <code>off+len</code> is greater than the length of the array
  33.100 +     * <code>b</code>, then an <tt>IndexOutOfBoundsException</tt> is thrown.
  33.101 +     *
  33.102 +     * @param      b     the data.
  33.103 +     * @param      off   the start offset in the data.
  33.104 +     * @param      len   the number of bytes to write.
  33.105 +     * @exception  IOException  if an I/O error occurs. In particular,
  33.106 +     *             an <code>IOException</code> is thrown if the output
  33.107 +     *             stream is closed.
  33.108 +     */
  33.109 +    public void write(byte b[], int off, int len) throws IOException {
  33.110 +        if (b == null) {
  33.111 +            throw new NullPointerException();
  33.112 +        } else if ((off < 0) || (off > b.length) || (len < 0) ||
  33.113 +                   ((off + len) > b.length) || ((off + len) < 0)) {
  33.114 +            throw new IndexOutOfBoundsException();
  33.115 +        } else if (len == 0) {
  33.116 +            return;
  33.117 +        }
  33.118 +        for (int i = 0 ; i < len ; i++) {
  33.119 +            write(b[off + i]);
  33.120 +        }
  33.121 +    }
  33.122 +
  33.123 +    /**
  33.124 +     * Flushes this output stream and forces any buffered output bytes
  33.125 +     * to be written out. The general contract of <code>flush</code> is
  33.126 +     * that calling it is an indication that, if any bytes previously
  33.127 +     * written have been buffered by the implementation of the output
  33.128 +     * stream, such bytes should immediately be written to their
  33.129 +     * intended destination.
  33.130 +     * <p>
  33.131 +     * If the intended destination of this stream is an abstraction provided by
  33.132 +     * the underlying operating system, for example a file, then flushing the
  33.133 +     * stream guarantees only that bytes previously written to the stream are
  33.134 +     * passed to the operating system for writing; it does not guarantee that
  33.135 +     * they are actually written to a physical device such as a disk drive.
  33.136 +     * <p>
  33.137 +     * The <code>flush</code> method of <code>OutputStream</code> does nothing.
  33.138 +     *
  33.139 +     * @exception  IOException  if an I/O error occurs.
  33.140 +     */
  33.141 +    public void flush() throws IOException {
  33.142 +    }
  33.143 +
  33.144 +    /**
  33.145 +     * Closes this output stream and releases any system resources
  33.146 +     * associated with this stream. The general contract of <code>close</code>
  33.147 +     * is that it closes the output stream. A closed stream cannot perform
  33.148 +     * output operations and cannot be reopened.
  33.149 +     * <p>
  33.150 +     * The <code>close</code> method of <code>OutputStream</code> does nothing.
  33.151 +     *
  33.152 +     * @exception  IOException  if an I/O error occurs.
  33.153 +     */
  33.154 +    public void close() throws IOException {
  33.155 +    }
  33.156 +
  33.157 +}
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/emul/compact/src/main/java/java/io/StreamCorruptedException.java	Mon Feb 04 09:37:56 2013 +0100
    34.3 @@ -0,0 +1,54 @@
    34.4 +/*
    34.5 + * Copyright (c) 1996, 2005, 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.io;
   34.30 +
   34.31 +/**
   34.32 + * Thrown when control information that was read from an object stream
   34.33 + * violates internal consistency checks.
   34.34 + *
   34.35 + * @author  unascribed
   34.36 + * @since   JDK1.1
   34.37 + */
   34.38 +public class StreamCorruptedException extends ObjectStreamException {
   34.39 +
   34.40 +    private static final long serialVersionUID = 8983558202217591746L;
   34.41 +
   34.42 +    /**
   34.43 +     * Create a StreamCorruptedException and list a reason why thrown.
   34.44 +     *
   34.45 +     * @param reason  String describing the reason for the exception.
   34.46 +     */
   34.47 +    public StreamCorruptedException(String reason) {
   34.48 +        super(reason);
   34.49 +    }
   34.50 +
   34.51 +    /**
   34.52 +     * Create a StreamCorruptedException and list no reason why thrown.
   34.53 +     */
   34.54 +    public StreamCorruptedException() {
   34.55 +        super();
   34.56 +    }
   34.57 +}
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/emul/compact/src/main/java/java/io/WriteAbortedException.java	Mon Feb 04 09:37:56 2013 +0100
    35.3 @@ -0,0 +1,93 @@
    35.4 +/*
    35.5 + * Copyright (c) 1996, 2005, 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.io;
   35.30 +
   35.31 +/**
   35.32 + * Signals that one of the ObjectStreamExceptions was thrown during a
   35.33 + * write operation.  Thrown during a read operation when one of the
   35.34 + * ObjectStreamExceptions was thrown during a write operation.  The
   35.35 + * exception that terminated the write can be found in the detail
   35.36 + * field. The stream is reset to it's initial state and all references
   35.37 + * to objects already deserialized are discarded.
   35.38 + *
   35.39 + * <p>As of release 1.4, this exception has been retrofitted to conform to
   35.40 + * the general purpose exception-chaining mechanism.  The "exception causing
   35.41 + * the abort" that is provided at construction time and
   35.42 + * accessed via the public {@link #detail} field is now known as the
   35.43 + * <i>cause</i>, and may be accessed via the {@link Throwable#getCause()}
   35.44 + * method, as well as the aforementioned "legacy field."
   35.45 + *
   35.46 + * @author  unascribed
   35.47 + * @since   JDK1.1
   35.48 + */
   35.49 +public class WriteAbortedException extends ObjectStreamException {
   35.50 +    private static final long serialVersionUID = -3326426625597282442L;
   35.51 +
   35.52 +    /**
   35.53 +     * Exception that was caught while writing the ObjectStream.
   35.54 +     *
   35.55 +     * <p>This field predates the general-purpose exception chaining facility.
   35.56 +     * The {@link Throwable#getCause()} method is now the preferred means of
   35.57 +     * obtaining this information.
   35.58 +     *
   35.59 +     * @serial
   35.60 +     */
   35.61 +    public Exception detail;
   35.62 +
   35.63 +    /**
   35.64 +     * Constructs a WriteAbortedException with a string describing
   35.65 +     * the exception and the exception causing the abort.
   35.66 +     * @param s   String describing the exception.
   35.67 +     * @param ex  Exception causing the abort.
   35.68 +     */
   35.69 +    public WriteAbortedException(String s, Exception ex) {
   35.70 +        super(s);
   35.71 +        initCause(null);  // Disallow subsequent initCause
   35.72 +        detail = ex;
   35.73 +    }
   35.74 +
   35.75 +    /**
   35.76 +     * Produce the message and include the message from the nested
   35.77 +     * exception, if there is one.
   35.78 +     */
   35.79 +    public String getMessage() {
   35.80 +        if (detail == null)
   35.81 +            return super.getMessage();
   35.82 +        else
   35.83 +            return super.getMessage() + "; " + detail.toString();
   35.84 +    }
   35.85 +
   35.86 +    /**
   35.87 +     * Returns the exception that terminated the operation (the <i>cause</i>).
   35.88 +     *
   35.89 +     * @return  the exception that terminated the operation (the <i>cause</i>),
   35.90 +     *          which may be null.
   35.91 +     * @since   1.4
   35.92 +     */
   35.93 +    public Throwable getCause() {
   35.94 +        return detail;
   35.95 +    }
   35.96 +}
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/emul/compact/src/main/java/java/lang/ref/PhantomReference.java	Mon Feb 04 09:37:56 2013 +0100
    36.3 @@ -0,0 +1,83 @@
    36.4 +/*
    36.5 + * Copyright (c) 1997, 2003, 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 +/**
   36.33 + * Phantom reference objects, which are enqueued after the collector
   36.34 + * determines that their referents may otherwise be reclaimed.  Phantom
   36.35 + * references are most often used for scheduling pre-mortem cleanup actions in
   36.36 + * a more flexible way than is possible with the Java finalization mechanism.
   36.37 + *
   36.38 + * <p> If the garbage collector determines at a certain point in time that the
   36.39 + * referent of a phantom reference is <a
   36.40 + * href="package-summary.html#reachability">phantom reachable</a>, then at that
   36.41 + * time or at some later time it will enqueue the reference.
   36.42 + *
   36.43 + * <p> In order to ensure that a reclaimable object remains so, the referent of
   36.44 + * a phantom reference may not be retrieved: The <code>get</code> method of a
   36.45 + * phantom reference always returns <code>null</code>.
   36.46 + *
   36.47 + * <p> Unlike soft and weak references, phantom references are not
   36.48 + * automatically cleared by the garbage collector as they are enqueued.  An
   36.49 + * object that is reachable via phantom references will remain so until all
   36.50 + * such references are cleared or themselves become unreachable.
   36.51 + *
   36.52 + * @author   Mark Reinhold
   36.53 + * @since    1.2
   36.54 + */
   36.55 +
   36.56 +public class PhantomReference<T> extends Reference<T> {
   36.57 +
   36.58 +    /**
   36.59 +     * Returns this reference object's referent.  Because the referent of a
   36.60 +     * phantom reference is always inaccessible, this method always returns
   36.61 +     * <code>null</code>.
   36.62 +     *
   36.63 +     * @return  <code>null</code>
   36.64 +     */
   36.65 +    public T get() {
   36.66 +        return null;
   36.67 +    }
   36.68 +
   36.69 +    /**
   36.70 +     * Creates a new phantom reference that refers to the given object and
   36.71 +     * is registered with the given queue.
   36.72 +     *
   36.73 +     * <p> It is possible to create a phantom reference with a <tt>null</tt>
   36.74 +     * queue, but such a reference is completely useless: Its <tt>get</tt>
   36.75 +     * method will always return null and, since it does not have a queue, it
   36.76 +     * will never be enqueued.
   36.77 +     *
   36.78 +     * @param referent the object the new phantom reference will refer to
   36.79 +     * @param q the queue with which the reference is to be registered,
   36.80 +     *          or <tt>null</tt> if registration is not required
   36.81 +     */
   36.82 +    public PhantomReference(T referent, ReferenceQueue<? super T> q) {
   36.83 +        super(referent, q);
   36.84 +    }
   36.85 +
   36.86 +}
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/emul/compact/src/main/java/java/lang/ref/Reference.java	Mon Feb 04 09:37:56 2013 +0100
    37.3 @@ -0,0 +1,185 @@
    37.4 +/*
    37.5 + * Copyright (c) 1997, 2006, 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 + * Abstract base class for reference objects.  This class defines the
   37.34 + * operations common to all reference objects.  Because reference objects are
   37.35 + * implemented in close cooperation with the garbage collector, this class may
   37.36 + * not be subclassed directly.
   37.37 + *
   37.38 + * @author   Mark Reinhold
   37.39 + * @since    1.2
   37.40 + */
   37.41 +
   37.42 +public abstract class Reference<T> {
   37.43 +
   37.44 +    /* A Reference instance is in one of four possible internal states:
   37.45 +     *
   37.46 +     *     Active: Subject to special treatment by the garbage collector.  Some
   37.47 +     *     time after the collector detects that the reachability of the
   37.48 +     *     referent has changed to the appropriate state, it changes the
   37.49 +     *     instance's state to either Pending or Inactive, depending upon
   37.50 +     *     whether or not the instance was registered with a queue when it was
   37.51 +     *     created.  In the former case it also adds the instance to the
   37.52 +     *     pending-Reference list.  Newly-created instances are Active.
   37.53 +     *
   37.54 +     *     Pending: An element of the pending-Reference list, waiting to be
   37.55 +     *     enqueued by the Reference-handler thread.  Unregistered instances
   37.56 +     *     are never in this state.
   37.57 +     *
   37.58 +     *     Enqueued: An element of the queue with which the instance was
   37.59 +     *     registered when it was created.  When an instance is removed from
   37.60 +     *     its ReferenceQueue, it is made Inactive.  Unregistered instances are
   37.61 +     *     never in this state.
   37.62 +     *
   37.63 +     *     Inactive: Nothing more to do.  Once an instance becomes Inactive its
   37.64 +     *     state will never change again.
   37.65 +     *
   37.66 +     * The state is encoded in the queue and next fields as follows:
   37.67 +     *
   37.68 +     *     Active: queue = ReferenceQueue with which instance is registered, or
   37.69 +     *     ReferenceQueue.NULL if it was not registered with a queue; next =
   37.70 +     *     null.
   37.71 +     *
   37.72 +     *     Pending: queue = ReferenceQueue with which instance is registered;
   37.73 +     *     next = Following instance in queue, or this if at end of list.
   37.74 +     *
   37.75 +     *     Enqueued: queue = ReferenceQueue.ENQUEUED; next = Following instance
   37.76 +     *     in queue, or this if at end of list.
   37.77 +     *
   37.78 +     *     Inactive: queue = ReferenceQueue.NULL; next = this.
   37.79 +     *
   37.80 +     * With this scheme the collector need only examine the next field in order
   37.81 +     * to determine whether a Reference instance requires special treatment: If
   37.82 +     * the next field is null then the instance is active; if it is non-null,
   37.83 +     * then the collector should treat the instance normally.
   37.84 +     *
   37.85 +     * To ensure that concurrent collector can discover active Reference
   37.86 +     * objects without interfering with application threads that may apply
   37.87 +     * the enqueue() method to those objects, collectors should link
   37.88 +     * discovered objects through the discovered field.
   37.89 +     */
   37.90 +
   37.91 +    private T referent;         /* Treated specially by GC */
   37.92 +
   37.93 +    ReferenceQueue<? super T> queue;
   37.94 +
   37.95 +    Reference next;
   37.96 +    transient private Reference<T> discovered;  /* used by VM */
   37.97 +
   37.98 +
   37.99 +    /* Object used to synchronize with the garbage collector.  The collector
  37.100 +     * must acquire this lock at the beginning of each collection cycle.  It is
  37.101 +     * therefore critical that any code holding this lock complete as quickly
  37.102 +     * as possible, allocate no new objects, and avoid calling user code.
  37.103 +     */
  37.104 +    static private class Lock { };
  37.105 +    private static Lock lock = new Lock();
  37.106 +
  37.107 +
  37.108 +    /* List of References waiting to be enqueued.  The collector adds
  37.109 +     * References to this list, while the Reference-handler thread removes
  37.110 +     * them.  This list is protected by the above lock object.
  37.111 +     */
  37.112 +    private static Reference pending = null;
  37.113 +
  37.114 +
  37.115 +
  37.116 +    /* -- Referent accessor and setters -- */
  37.117 +
  37.118 +    /**
  37.119 +     * Returns this reference object's referent.  If this reference object has
  37.120 +     * been cleared, either by the program or by the garbage collector, then
  37.121 +     * this method returns <code>null</code>.
  37.122 +     *
  37.123 +     * @return   The object to which this reference refers, or
  37.124 +     *           <code>null</code> if this reference object has been cleared
  37.125 +     */
  37.126 +    public T get() {
  37.127 +        return this.referent;
  37.128 +    }
  37.129 +
  37.130 +    /**
  37.131 +     * Clears this reference object.  Invoking this method will not cause this
  37.132 +     * object to be enqueued.
  37.133 +     *
  37.134 +     * <p> This method is invoked only by Java code; when the garbage collector
  37.135 +     * clears references it does so directly, without invoking this method.
  37.136 +     */
  37.137 +    public void clear() {
  37.138 +        this.referent = null;
  37.139 +    }
  37.140 +
  37.141 +
  37.142 +    /* -- Queue operations -- */
  37.143 +
  37.144 +    /**
  37.145 +     * Tells whether or not this reference object has been enqueued, either by
  37.146 +     * the program or by the garbage collector.  If this reference object was
  37.147 +     * not registered with a queue when it was created, then this method will
  37.148 +     * always return <code>false</code>.
  37.149 +     *
  37.150 +     * @return   <code>true</code> if and only if this reference object has
  37.151 +     *           been enqueued
  37.152 +     */
  37.153 +    public boolean isEnqueued() {
  37.154 +        /* In terms of the internal states, this predicate actually tests
  37.155 +           whether the instance is either Pending or Enqueued */
  37.156 +        synchronized (this) {
  37.157 +            return (this.queue != ReferenceQueue.NULL) && (this.next != null);
  37.158 +        }
  37.159 +    }
  37.160 +
  37.161 +    /**
  37.162 +     * Adds this reference object to the queue with which it is registered,
  37.163 +     * if any.
  37.164 +     *
  37.165 +     * <p> This method is invoked only by Java code; when the garbage collector
  37.166 +     * enqueues references it does so directly, without invoking this method.
  37.167 +     *
  37.168 +     * @return   <code>true</code> if this reference object was successfully
  37.169 +     *           enqueued; <code>false</code> if it was already enqueued or if
  37.170 +     *           it was not registered with a queue when it was created
  37.171 +     */
  37.172 +    public boolean enqueue() {
  37.173 +        return this.queue.enqueue(this);
  37.174 +    }
  37.175 +
  37.176 +
  37.177 +    /* -- Constructors -- */
  37.178 +
  37.179 +    Reference(T referent) {
  37.180 +        this(referent, null);
  37.181 +    }
  37.182 +
  37.183 +    Reference(T referent, ReferenceQueue<? super T> queue) {
  37.184 +        this.referent = referent;
  37.185 +        this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
  37.186 +    }
  37.187 +
  37.188 +}
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/emul/compact/src/main/java/java/lang/ref/ReferenceQueue.java	Mon Feb 04 09:37:56 2013 +0100
    38.3 @@ -0,0 +1,148 @@
    38.4 +/*
    38.5 + * Copyright (c) 1997, 2005, 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 + * Reference queues, to which registered reference objects are appended by the
   38.33 + * garbage collector after the appropriate reachability changes are detected.
   38.34 + *
   38.35 + * @author   Mark Reinhold
   38.36 + * @since    1.2
   38.37 + */
   38.38 +
   38.39 +public class ReferenceQueue<T> {
   38.40 +
   38.41 +    /**
   38.42 +     * Constructs a new reference-object queue.
   38.43 +     */
   38.44 +    public ReferenceQueue() { }
   38.45 +
   38.46 +    private static class Null extends ReferenceQueue {
   38.47 +        boolean enqueue(Reference r) {
   38.48 +            return false;
   38.49 +        }
   38.50 +    }
   38.51 +
   38.52 +    static ReferenceQueue NULL = new Null();
   38.53 +    static ReferenceQueue ENQUEUED = new Null();
   38.54 +
   38.55 +    static private class Lock { };
   38.56 +    private Lock lock = new Lock();
   38.57 +    private volatile Reference<? extends T> head = null;
   38.58 +    private long queueLength = 0;
   38.59 +
   38.60 +    boolean enqueue(Reference<? extends T> r) { /* Called only by Reference class */
   38.61 +        synchronized (r) {
   38.62 +            if (r.queue == ENQUEUED) return false;
   38.63 +            synchronized (lock) {
   38.64 +                r.queue = ENQUEUED;
   38.65 +                r.next = (head == null) ? r : head;
   38.66 +                head = r;
   38.67 +                queueLength++;
   38.68 +                lock.notifyAll();
   38.69 +                return true;
   38.70 +            }
   38.71 +        }
   38.72 +    }
   38.73 +
   38.74 +    private Reference<? extends T> reallyPoll() {       /* Must hold lock */
   38.75 +        if (head != null) {
   38.76 +            Reference<? extends T> r = head;
   38.77 +            head = (r.next == r) ? null : r.next;
   38.78 +            r.queue = NULL;
   38.79 +            r.next = r;
   38.80 +            queueLength--;
   38.81 +            return r;
   38.82 +        }
   38.83 +        return null;
   38.84 +    }
   38.85 +
   38.86 +    /**
   38.87 +     * Polls this queue to see if a reference object is available.  If one is
   38.88 +     * available without further delay then it is removed from the queue and
   38.89 +     * returned.  Otherwise this method immediately returns <tt>null</tt>.
   38.90 +     *
   38.91 +     * @return  A reference object, if one was immediately available,
   38.92 +     *          otherwise <code>null</code>
   38.93 +     */
   38.94 +    public Reference<? extends T> poll() {
   38.95 +        if (head == null)
   38.96 +            return null;
   38.97 +        synchronized (lock) {
   38.98 +            return reallyPoll();
   38.99 +        }
  38.100 +    }
  38.101 +
  38.102 +    /**
  38.103 +     * Removes the next reference object in this queue, blocking until either
  38.104 +     * one becomes available or the given timeout period expires.
  38.105 +     *
  38.106 +     * <p> This method does not offer real-time guarantees: It schedules the
  38.107 +     * timeout as if by invoking the {@link Object#wait(long)} method.
  38.108 +     *
  38.109 +     * @param  timeout  If positive, block for up to <code>timeout</code>
  38.110 +     *                  milliseconds while waiting for a reference to be
  38.111 +     *                  added to this queue.  If zero, block indefinitely.
  38.112 +     *
  38.113 +     * @return  A reference object, if one was available within the specified
  38.114 +     *          timeout period, otherwise <code>null</code>
  38.115 +     *
  38.116 +     * @throws  IllegalArgumentException
  38.117 +     *          If the value of the timeout argument is negative
  38.118 +     *
  38.119 +     * @throws  InterruptedException
  38.120 +     *          If the timeout wait is interrupted
  38.121 +     */
  38.122 +    public Reference<? extends T> remove(long timeout)
  38.123 +        throws IllegalArgumentException, InterruptedException
  38.124 +    {
  38.125 +        if (timeout < 0) {
  38.126 +            throw new IllegalArgumentException("Negative timeout value");
  38.127 +        }
  38.128 +        synchronized (lock) {
  38.129 +            Reference<? extends T> r = reallyPoll();
  38.130 +            if (r != null) return r;
  38.131 +            for (;;) {
  38.132 +                lock.wait(timeout);
  38.133 +                r = reallyPoll();
  38.134 +                if (r != null) return r;
  38.135 +                if (timeout != 0) return null;
  38.136 +            }
  38.137 +        }
  38.138 +    }
  38.139 +
  38.140 +    /**
  38.141 +     * Removes the next reference object in this queue, blocking until one
  38.142 +     * becomes available.
  38.143 +     *
  38.144 +     * @return A reference object, blocking until one becomes available
  38.145 +     * @throws  InterruptedException  If the wait is interrupted
  38.146 +     */
  38.147 +    public Reference<? extends T> remove() throws InterruptedException {
  38.148 +        return remove(0);
  38.149 +    }
  38.150 +
  38.151 +}
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/emul/compact/src/main/java/java/lang/ref/SoftReference.java	Mon Feb 04 09:37:56 2013 +0100
    39.3 @@ -0,0 +1,118 @@
    39.4 +/*
    39.5 + * Copyright (c) 1997, 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 +package java.lang.ref;
   39.30 +
   39.31 +
   39.32 +/**
   39.33 + * Soft reference objects, which are cleared at the discretion of the garbage
   39.34 + * collector in response to memory demand.  Soft references are most often used
   39.35 + * to implement memory-sensitive caches.
   39.36 + *
   39.37 + * <p> Suppose that the garbage collector determines at a certain point in time
   39.38 + * that an object is <a href="package-summary.html#reachability">softly
   39.39 + * reachable</a>.  At that time it may choose to clear atomically all soft
   39.40 + * references to that object and all soft references to any other
   39.41 + * softly-reachable objects from which that object is reachable through a chain
   39.42 + * of strong references.  At the same time or at some later time it will
   39.43 + * enqueue those newly-cleared soft references that are registered with
   39.44 + * reference queues.
   39.45 + *
   39.46 + * <p> All soft references to softly-reachable objects are guaranteed to have
   39.47 + * been cleared before the virtual machine throws an
   39.48 + * <code>OutOfMemoryError</code>.  Otherwise no constraints are placed upon the
   39.49 + * time at which a soft reference will be cleared or the order in which a set
   39.50 + * of such references to different objects will be cleared.  Virtual machine
   39.51 + * implementations are, however, encouraged to bias against clearing
   39.52 + * recently-created or recently-used soft references.
   39.53 + *
   39.54 + * <p> Direct instances of this class may be used to implement simple caches;
   39.55 + * this class or derived subclasses may also be used in larger data structures
   39.56 + * to implement more sophisticated caches.  As long as the referent of a soft
   39.57 + * reference is strongly reachable, that is, is actually in use, the soft
   39.58 + * reference will not be cleared.  Thus a sophisticated cache can, for example,
   39.59 + * prevent its most recently used entries from being discarded by keeping
   39.60 + * strong referents to those entries, leaving the remaining entries to be
   39.61 + * discarded at the discretion of the garbage collector.
   39.62 + *
   39.63 + * @author   Mark Reinhold
   39.64 + * @since    1.2
   39.65 + */
   39.66 +
   39.67 +public class SoftReference<T> extends Reference<T> {
   39.68 +
   39.69 +    /**
   39.70 +     * Timestamp clock, updated by the garbage collector
   39.71 +     */
   39.72 +    static private long clock;
   39.73 +
   39.74 +    /**
   39.75 +     * Timestamp updated by each invocation of the get method.  The VM may use
   39.76 +     * this field when selecting soft references to be cleared, but it is not
   39.77 +     * required to do so.
   39.78 +     */
   39.79 +    private long timestamp;
   39.80 +
   39.81 +    /**
   39.82 +     * Creates a new soft reference that refers to the given object.  The new
   39.83 +     * reference is not registered with any queue.
   39.84 +     *
   39.85 +     * @param referent object the new soft reference will refer to
   39.86 +     */
   39.87 +    public SoftReference(T referent) {
   39.88 +        super(referent);
   39.89 +        this.timestamp = clock;
   39.90 +    }
   39.91 +
   39.92 +    /**
   39.93 +     * Creates a new soft reference that refers to the given object and is
   39.94 +     * registered with the given queue.
   39.95 +     *
   39.96 +     * @param referent object the new soft reference will refer to
   39.97 +     * @param q the queue with which the reference is to be registered,
   39.98 +     *          or <tt>null</tt> if registration is not required
   39.99 +     *
  39.100 +     */
  39.101 +    public SoftReference(T referent, ReferenceQueue<? super T> q) {
  39.102 +        super(referent, q);
  39.103 +        this.timestamp = clock;
  39.104 +    }
  39.105 +
  39.106 +    /**
  39.107 +     * Returns this reference object's referent.  If this reference object has
  39.108 +     * been cleared, either by the program or by the garbage collector, then
  39.109 +     * this method returns <code>null</code>.
  39.110 +     *
  39.111 +     * @return   The object to which this reference refers, or
  39.112 +     *           <code>null</code> if this reference object has been cleared
  39.113 +     */
  39.114 +    public T get() {
  39.115 +        T o = super.get();
  39.116 +        if (o != null && this.timestamp != clock)
  39.117 +            this.timestamp = clock;
  39.118 +        return o;
  39.119 +    }
  39.120 +
  39.121 +}
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/emul/compact/src/main/java/java/lang/ref/WeakReference.java	Mon Feb 04 09:37:56 2013 +0100
    40.3 @@ -0,0 +1,72 @@
    40.4 +/*
    40.5 + * Copyright (c) 1997, 2003, 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.lang.ref;
   40.30 +
   40.31 +
   40.32 +/**
   40.33 + * Weak reference objects, which do not prevent their referents from being
   40.34 + * made finalizable, finalized, and then reclaimed.  Weak references are most
   40.35 + * often used to implement canonicalizing mappings.
   40.36 + *
   40.37 + * <p> Suppose that the garbage collector determines at a certain point in time
   40.38 + * that an object is <a href="package-summary.html#reachability">weakly
   40.39 + * reachable</a>.  At that time it will atomically clear all weak references to
   40.40 + * that object and all weak references to any other weakly-reachable objects
   40.41 + * from which that object is reachable through a chain of strong and soft
   40.42 + * references.  At the same time it will declare all of the formerly
   40.43 + * weakly-reachable objects to be finalizable.  At the same time or at some
   40.44 + * later time it will enqueue those newly-cleared weak references that are
   40.45 + * registered with reference queues.
   40.46 + *
   40.47 + * @author   Mark Reinhold
   40.48 + * @since    1.2
   40.49 + */
   40.50 +
   40.51 +public class WeakReference<T> extends Reference<T> {
   40.52 +
   40.53 +    /**
   40.54 +     * Creates a new weak reference that refers to the given object.  The new
   40.55 +     * reference is not registered with any queue.
   40.56 +     *
   40.57 +     * @param referent object the new weak reference will refer to
   40.58 +     */
   40.59 +    public WeakReference(T referent) {
   40.60 +        super(referent);
   40.61 +    }
   40.62 +
   40.63 +    /**
   40.64 +     * Creates a new weak reference that refers to the given object and is
   40.65 +     * registered with the given queue.
   40.66 +     *
   40.67 +     * @param referent object the new weak reference will refer to
   40.68 +     * @param q the queue with which the reference is to be registered,
   40.69 +     *          or <tt>null</tt> if registration is not required
   40.70 +     */
   40.71 +    public WeakReference(T referent, ReferenceQueue<? super T> q) {
   40.72 +        super(referent, q);
   40.73 +    }
   40.74 +
   40.75 +}
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/emul/compact/src/main/java/java/lang/ref/package.html	Mon Feb 04 09:37:56 2013 +0100
    41.3 @@ -0,0 +1,147 @@
    41.4 +<!--
    41.5 + Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved.
    41.6 + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    41.7 +
    41.8 + This code is free software; you can redistribute it and/or modify it
    41.9 + under the terms of the GNU General Public License version 2 only, as
   41.10 + published by the Free Software Foundation.  Oracle designates this
   41.11 + particular file as subject to the "Classpath" exception as provided
   41.12 + by Oracle in the LICENSE file that accompanied this code.
   41.13 +
   41.14 + This code is distributed in the hope that it will be useful, but WITHOUT
   41.15 + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   41.16 + FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   41.17 + version 2 for more details (a copy is included in the LICENSE file that
   41.18 + accompanied this code).
   41.19 +
   41.20 + You should have received a copy of the GNU General Public License version
   41.21 + 2 along with this work; if not, write to the Free Software Foundation,
   41.22 + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   41.23 +
   41.24 + Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   41.25 + or visit www.oracle.com if you need additional information or have any
   41.26 + questions.
   41.27 +-->
   41.28 +
   41.29 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
   41.30 +<html>
   41.31 +<body bgcolor="white">
   41.32 +
   41.33 +
   41.34 +Provides reference-object classes, which support a limited degree of
   41.35 +interaction with the garbage collector.  A program may use a reference object
   41.36 +to maintain a reference to some other object in such a way that the latter
   41.37 +object may still be reclaimed by the collector.  A program may also arrange to
   41.38 +be notified some time after the collector has determined that the reachability
   41.39 +of a given object has changed.
   41.40 +
   41.41 +
   41.42 +<h2>Package Specification</h2>
   41.43 +
   41.44 +A <em>reference object</em> encapsulates a reference to some other object so
   41.45 +that the reference itself may be examined and manipulated like any other
   41.46 +object.  Three types of reference objects are provided, each weaker than the
   41.47 +last: <em>soft</em>, <em>weak</em>, and <em>phantom</em>.  Each type
   41.48 +corresponds to a different level of reachability, as defined below.  Soft
   41.49 +references are for implementing memory-sensitive caches, weak references are
   41.50 +for implementing canonicalizing mappings that do not prevent their keys (or
   41.51 +values) from being reclaimed, and phantom references are for scheduling
   41.52 +pre-mortem cleanup actions in a more flexible way than is possible with the
   41.53 +Java finalization mechanism.
   41.54 +
   41.55 +<p> Each reference-object type is implemented by a subclass of the abstract
   41.56 +base <code>{@link java.lang.ref.Reference}</code> class.  An instance of one of
   41.57 +these subclasses encapsulates a single reference to a particular object, called
   41.58 +the <em>referent</em>.  Every reference object provides methods for getting and
   41.59 +clearing the reference.  Aside from the clearing operation reference objects
   41.60 +are otherwise immutable, so no <code>set</code> operation is provided.  A
   41.61 +program may further subclass these subclasses, adding whatever fields and
   41.62 +methods are required for its purposes, or it may use these subclasses without
   41.63 +change.
   41.64 +
   41.65 +
   41.66 +<h3>Notification</h3>
   41.67 +
   41.68 +A program may request to be notified of changes in an object's reachability by
   41.69 +<em>registering</em> an appropriate reference object with a <em>reference
   41.70 +queue</em> at the time the reference object is created.  Some time after the
   41.71 +garbage collector determines that the reachability of the referent has changed
   41.72 +to the value corresponding to the type of the reference, it will add the
   41.73 +reference to the associated queue.  At this point, the reference is considered
   41.74 +to be <em>enqueued</em>.  The program may remove references from a queue either
   41.75 +by polling or by blocking until a reference becomes available.  Reference
   41.76 +queues are implemented by the <code>{@link java.lang.ref.ReferenceQueue}</code>
   41.77 +class.
   41.78 +
   41.79 +<p> The relationship between a registered reference object and its queue is
   41.80 +one-sided.  That is, a queue does not keep track of the references that are
   41.81 +registered with it.  If a registered reference becomes unreachable itself, then
   41.82 +it will never be enqueued.  It is the responsibility of the program using
   41.83 +reference objects to ensure that the objects remain reachable for as long as
   41.84 +the program is interested in their referents.
   41.85 +
   41.86 +<p> While some programs will choose to dedicate a thread to removing reference
   41.87 +objects from one or more queues and processing them, this is by no means
   41.88 +necessary.  A tactic that often works well is to examine a reference queue in
   41.89 +the course of performing some other fairly-frequent action.  For example, a
   41.90 +hashtable that uses weak references to implement weak keys could poll its
   41.91 +reference queue each time the table is accessed.  This is how the <code>{@link
   41.92 +java.util.WeakHashMap}</code> class works.  Because the <code>{@link
   41.93 +java.lang.ref.ReferenceQueue#poll ReferenceQueue.poll}</code> method simply
   41.94 +checks an internal data structure, this check will add little overhead to the
   41.95 +hashtable access methods.
   41.96 +
   41.97 +
   41.98 +<h3>Automatically-cleared references</h3>
   41.99 +
  41.100 +Soft and weak references are automatically cleared by the collector before
  41.101 +being added to the queues with which they are registered, if any.  Therefore
  41.102 +soft and weak references need not be registered with a queue in order to be
  41.103 +useful, while phantom references do.  An object that is reachable via phantom
  41.104 +references will remain so until all such references are cleared or themselves
  41.105 +become unreachable.
  41.106 +
  41.107 +
  41.108 +<a name="reachability"></a>
  41.109 +<h3>Reachability</h3>
  41.110 +
  41.111 +Going from strongest to weakest, the different levels of reachability reflect
  41.112 +the life cycle of an object.  They are operationally defined as follows:
  41.113 +
  41.114 +<ul>
  41.115 +
  41.116 +<li> An object is <em>strongly reachable</em> if it can be reached by some
  41.117 +thread without traversing any reference objects.  A newly-created object is
  41.118 +strongly reachable by the thread that created it.
  41.119 +
  41.120 +<li> An object is <em>softly reachable</em> if it is not strongly reachable but
  41.121 +can be reached by traversing a soft reference.
  41.122 +
  41.123 +<li> An object is <em>weakly reachable</em> if it is neither strongly nor
  41.124 +softly reachable but can be reached by traversing a weak reference.  When the
  41.125 +weak references to a weakly-reachable object are cleared, the object becomes
  41.126 +eligible for finalization.
  41.127 +
  41.128 +<li> An object is <em>phantom reachable</em> if it is neither strongly, softly,
  41.129 +nor weakly reachable, it has been finalized, and some phantom reference refers
  41.130 +to it.
  41.131 +
  41.132 +<li> Finally, an object is <em>unreachable</em>, and therefore eligible for
  41.133 +reclamation, when it is not reachable in any of the above ways.
  41.134 +
  41.135 +</ul>
  41.136 +
  41.137 +
  41.138 +@author	  Mark Reinhold
  41.139 +@since	  1.2
  41.140 +
  41.141 +<!--
  41.142 +<h2>Related Documentation</h2>
  41.143 +
  41.144 +For overviews, tutorials, examples, guides, and tool documentation, please see:
  41.145 +<ul>
  41.146 +  <li><a href="">##### REFER TO NON-SPEC DOCUMENTATION HERE #####</a>
  41.147 +</ul>
  41.148 +-->
  41.149 +</body>
  41.150 +</html>
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/emul/compact/src/main/java/java/util/EventListenerProxy.java	Mon Feb 04 09:37:56 2013 +0100
    42.3 @@ -0,0 +1,75 @@
    42.4 +/*
    42.5 + * Copyright (c) 2000, 2004, 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.util;
   42.30 +
   42.31 +/**
   42.32 + * An abstract wrapper class for an {@code EventListener} class
   42.33 + * which associates a set of additional parameters with the listener.
   42.34 + * Subclasses must provide the storage and accessor methods
   42.35 + * for the additional arguments or parameters.
   42.36 + * <p>
   42.37 + * For example, a bean which supports named properties
   42.38 + * would have a two argument method signature for adding
   42.39 + * a {@code PropertyChangeListener} for a property:
   42.40 + * <pre>
   42.41 + * public void addPropertyChangeListener(String propertyName,
   42.42 + *                                       PropertyChangeListener listener)
   42.43 + * </pre>
   42.44 + * If the bean also implemented the zero argument get listener method:
   42.45 + * <pre>
   42.46 + * public PropertyChangeListener[] getPropertyChangeListeners()
   42.47 + * </pre>
   42.48 + * then the array may contain inner {@code PropertyChangeListeners}
   42.49 + * which are also {@code PropertyChangeListenerProxy} objects.
   42.50 + * <p>
   42.51 + * If the calling method is interested in retrieving the named property
   42.52 + * then it would have to test the element to see if it is a proxy class.
   42.53 + *
   42.54 + * @since 1.4
   42.55 + */
   42.56 +public abstract class EventListenerProxy<T extends EventListener>
   42.57 +        implements EventListener {
   42.58 +
   42.59 +    private final T listener;
   42.60 +
   42.61 +    /**
   42.62 +     * Creates a proxy for the specified listener.
   42.63 +     *
   42.64 +     * @param listener  the listener object
   42.65 +     */
   42.66 +    public EventListenerProxy(T listener) {
   42.67 +        this.listener = listener;
   42.68 +    }
   42.69 +
   42.70 +    /**
   42.71 +     * Returns the listener associated with the proxy.
   42.72 +     *
   42.73 +     * @return  the listener associated with the proxy
   42.74 +     */
   42.75 +    public T getListener() {
   42.76 +        return this.listener;
   42.77 +    }
   42.78 +}
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/emul/compact/src/main/java/java/util/concurrent/Callable.java	Mon Feb 04 09:37:56 2013 +0100
    43.3 @@ -0,0 +1,65 @@
    43.4 +/*
    43.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    43.6 + *
    43.7 + * This code is free software; you can redistribute it and/or modify it
    43.8 + * under the terms of the GNU General Public License version 2 only, as
    43.9 + * published by the Free Software Foundation.  Oracle designates this
   43.10 + * particular file as subject to the "Classpath" exception as provided
   43.11 + * by Oracle in the LICENSE file that accompanied this code.
   43.12 + *
   43.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
   43.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   43.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   43.16 + * version 2 for more details (a copy is included in the LICENSE file that
   43.17 + * accompanied this code).
   43.18 + *
   43.19 + * You should have received a copy of the GNU General Public License version
   43.20 + * 2 along with this work; if not, write to the Free Software Foundation,
   43.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   43.22 + *
   43.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   43.24 + * or visit www.oracle.com if you need additional information or have any
   43.25 + * questions.
   43.26 + */
   43.27 +
   43.28 +/*
   43.29 + * This file is available under and governed by the GNU General Public
   43.30 + * License version 2 only, as published by the Free Software Foundation.
   43.31 + * However, the following notice accompanied the original version of this
   43.32 + * file:
   43.33 + *
   43.34 + * Written by Doug Lea with assistance from members of JCP JSR-166
   43.35 + * Expert Group and released to the public domain, as explained at
   43.36 + * http://creativecommons.org/publicdomain/zero/1.0/
   43.37 + */
   43.38 +
   43.39 +package java.util.concurrent;
   43.40 +
   43.41 +/**
   43.42 + * A task that returns a result and may throw an exception.
   43.43 + * Implementors define a single method with no arguments called
   43.44 + * <tt>call</tt>.
   43.45 + *
   43.46 + * <p>The <tt>Callable</tt> interface is similar to {@link
   43.47 + * java.lang.Runnable}, in that both are designed for classes whose
   43.48 + * instances are potentially executed by another thread.  A
   43.49 + * <tt>Runnable</tt>, however, does not return a result and cannot
   43.50 + * throw a checked exception.
   43.51 + *
   43.52 + * <p> The {@link Executors} class contains utility methods to
   43.53 + * convert from other common forms to <tt>Callable</tt> classes.
   43.54 + *
   43.55 + * @see Executor
   43.56 + * @since 1.5
   43.57 + * @author Doug Lea
   43.58 + * @param <V> the result type of method <tt>call</tt>
   43.59 + */
   43.60 +public interface Callable<V> {
   43.61 +    /**
   43.62 +     * Computes a result, or throws an exception if unable to do so.
   43.63 +     *
   43.64 +     * @return computed result
   43.65 +     * @throws Exception if unable to compute a result
   43.66 +     */
   43.67 +    V call() throws Exception;
   43.68 +}
    44.1 --- a/emul/mini/src/main/java/java/lang/Class.java	Fri Feb 01 16:34:51 2013 +0100
    44.2 +++ b/emul/mini/src/main/java/java/lang/Class.java	Mon Feb 04 09:37:56 2013 +0100
    44.3 @@ -347,6 +347,9 @@
    44.4       * @since JDK1.1
    44.5       */
    44.6      public boolean isInstance(Object obj) {
    44.7 +        if (obj == null) {
    44.8 +            return false;
    44.9 +        }
   44.10          if (isArray()) {
   44.11              return isAssignableFrom(obj.getClass());
   44.12          }
   44.13 @@ -909,7 +912,50 @@
   44.14          }
   44.15          return m;
   44.16      }
   44.17 -
   44.18 +    
   44.19 +    /**
   44.20 +     * Returns an array of {@code Method} objects reflecting all the
   44.21 +     * methods declared by the class or interface represented by this
   44.22 +     * {@code Class} object. This includes public, protected, default
   44.23 +     * (package) access, and private methods, but excludes inherited methods.
   44.24 +     * The elements in the array returned are not sorted and are not in any
   44.25 +     * particular order.  This method returns an array of length 0 if the class
   44.26 +     * or interface declares no methods, or if this {@code Class} object
   44.27 +     * represents a primitive type, an array class, or void.  The class
   44.28 +     * initialization method {@code <clinit>} is not included in the
   44.29 +     * returned array. If the class declares multiple public member methods
   44.30 +     * with the same parameter types, they are all included in the returned
   44.31 +     * array.
   44.32 +     *
   44.33 +     * <p> See <em>The Java Language Specification</em>, section 8.2.
   44.34 +     *
   44.35 +     * @return    the array of {@code Method} objects representing all the
   44.36 +     * declared methods of this class
   44.37 +     * @exception  SecurityException
   44.38 +     *             If a security manager, <i>s</i>, is present and any of the
   44.39 +     *             following conditions is met:
   44.40 +     *
   44.41 +     *             <ul>
   44.42 +     *
   44.43 +     *             <li> invocation of
   44.44 +     *             {@link SecurityManager#checkMemberAccess
   44.45 +     *             s.checkMemberAccess(this, Member.DECLARED)} denies
   44.46 +     *             access to the declared methods within this class
   44.47 +     *
   44.48 +     *             <li> the caller's class loader is not the same as or an
   44.49 +     *             ancestor of the class loader for the current class and
   44.50 +     *             invocation of {@link SecurityManager#checkPackageAccess
   44.51 +     *             s.checkPackageAccess()} denies access to the package
   44.52 +     *             of this class
   44.53 +     *
   44.54 +     *             </ul>
   44.55 +     *
   44.56 +     * @since JDK1.1
   44.57 +     */
   44.58 +    public Method[] getDeclaredMethods() throws SecurityException {
   44.59 +        throw new SecurityException();
   44.60 +    }
   44.61 +    
   44.62      /**
   44.63       * Character.isDigit answers {@code true} to some non-ascii
   44.64       * digits.  This one does not.
   44.65 @@ -1096,6 +1142,48 @@
   44.66      public ClassLoader getClassLoader() {
   44.67          throw new SecurityException();
   44.68      }
   44.69 +
   44.70 +    /**
   44.71 +     * Determines the interfaces implemented by the class or interface
   44.72 +     * represented by this object.
   44.73 +     *
   44.74 +     * <p> If this object represents a class, the return value is an array
   44.75 +     * containing objects representing all interfaces implemented by the
   44.76 +     * class. The order of the interface objects in the array corresponds to
   44.77 +     * the order of the interface names in the {@code implements} clause
   44.78 +     * of the declaration of the class represented by this object. For
   44.79 +     * example, given the declaration:
   44.80 +     * <blockquote>
   44.81 +     * {@code class Shimmer implements FloorWax, DessertTopping { ... }}
   44.82 +     * </blockquote>
   44.83 +     * suppose the value of {@code s} is an instance of
   44.84 +     * {@code Shimmer}; the value of the expression:
   44.85 +     * <blockquote>
   44.86 +     * {@code s.getClass().getInterfaces()[0]}
   44.87 +     * </blockquote>
   44.88 +     * is the {@code Class} object that represents interface
   44.89 +     * {@code FloorWax}; and the value of:
   44.90 +     * <blockquote>
   44.91 +     * {@code s.getClass().getInterfaces()[1]}
   44.92 +     * </blockquote>
   44.93 +     * is the {@code Class} object that represents interface
   44.94 +     * {@code DessertTopping}.
   44.95 +     *
   44.96 +     * <p> If this object represents an interface, the array contains objects
   44.97 +     * representing all interfaces extended by the interface. The order of the
   44.98 +     * interface objects in the array corresponds to the order of the interface
   44.99 +     * names in the {@code extends} clause of the declaration of the
  44.100 +     * interface represented by this object.
  44.101 +     *
  44.102 +     * <p> If this object represents a class or interface that implements no
  44.103 +     * interfaces, the method returns an array of length 0.
  44.104 +     *
  44.105 +     * <p> If this object represents a primitive type or void, the method
  44.106 +     * returns an array of length 0.
  44.107 +     *
  44.108 +     * @return an array of interfaces implemented by this class.
  44.109 +     */
  44.110 +    public native Class<?>[] getInterfaces();
  44.111      
  44.112      /**
  44.113       * Returns the {@code Class} representing the component type of an
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/emul/mini/src/main/java/java/lang/Cloneable.java	Mon Feb 04 09:37:56 2013 +0100
    45.3 @@ -0,0 +1,54 @@
    45.4 +/*
    45.5 + * Copyright (c) 1995, 2004, 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;
   45.30 +
   45.31 +/**
   45.32 + * A class implements the <code>Cloneable</code> interface to
   45.33 + * indicate to the {@link java.lang.Object#clone()} method that it
   45.34 + * is legal for that method to make a
   45.35 + * field-for-field copy of instances of that class.
   45.36 + * <p>
   45.37 + * Invoking Object's clone method on an instance that does not implement the
   45.38 + * <code>Cloneable</code> interface results in the exception
   45.39 + * <code>CloneNotSupportedException</code> being thrown.
   45.40 + * <p>
   45.41 + * By convention, classes that implement this interface should override
   45.42 + * <tt>Object.clone</tt> (which is protected) with a public method.
   45.43 + * See {@link java.lang.Object#clone()} for details on overriding this
   45.44 + * method.
   45.45 + * <p>
   45.46 + * Note that this interface does <i>not</i> contain the <tt>clone</tt> method.
   45.47 + * Therefore, it is not possible to clone an object merely by virtue of the
   45.48 + * fact that it implements this interface.  Even if the clone method is invoked
   45.49 + * reflectively, there is no guarantee that it will succeed.
   45.50 + *
   45.51 + * @author  unascribed
   45.52 + * @see     java.lang.CloneNotSupportedException
   45.53 + * @see     java.lang.Object#clone()
   45.54 + * @since   JDK1.0
   45.55 + */
   45.56 +public interface Cloneable {
   45.57 +}
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/emul/mini/src/main/java/java/lang/IllegalAccessError.java	Mon Feb 04 09:37:56 2013 +0100
    46.3 @@ -0,0 +1,58 @@
    46.4 +/*
    46.5 + * Copyright (c) 1995, 2008, 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;
   46.30 +
   46.31 +/**
   46.32 + * Thrown if an application attempts to access or modify a field, or
   46.33 + * to call a method that it does not have access to.
   46.34 + * <p>
   46.35 + * Normally, this error is caught by the compiler; this error can
   46.36 + * only occur at run time if the definition of a class has
   46.37 + * incompatibly changed.
   46.38 + *
   46.39 + * @author  unascribed
   46.40 + * @since   JDK1.0
   46.41 + */
   46.42 +public class IllegalAccessError extends IncompatibleClassChangeError {
   46.43 +    private static final long serialVersionUID = -8988904074992417891L;
   46.44 +
   46.45 +    /**
   46.46 +     * Constructs an <code>IllegalAccessError</code> with no detail message.
   46.47 +     */
   46.48 +    public IllegalAccessError() {
   46.49 +        super();
   46.50 +    }
   46.51 +
   46.52 +    /**
   46.53 +     * Constructs an <code>IllegalAccessError</code> with the specified
   46.54 +     * detail message.
   46.55 +     *
   46.56 +     * @param   s   the detail message.
   46.57 +     */
   46.58 +    public IllegalAccessError(String s) {
   46.59 +        super(s);
   46.60 +    }
   46.61 +}
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/emul/mini/src/main/java/java/lang/IncompatibleClassChangeError.java	Mon Feb 04 09:37:56 2013 +0100
    47.3 @@ -0,0 +1,57 @@
    47.4 +/*
    47.5 + * Copyright (c) 1994, 2008, 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;
   47.30 +
   47.31 +/**
   47.32 + * Thrown when an incompatible class change has occurred to some class
   47.33 + * definition. The definition of some class, on which the currently
   47.34 + * executing method depends, has since changed.
   47.35 + *
   47.36 + * @author  unascribed
   47.37 + * @since   JDK1.0
   47.38 + */
   47.39 +public
   47.40 +class IncompatibleClassChangeError extends LinkageError {
   47.41 +    private static final long serialVersionUID = -4914975503642802119L;
   47.42 +
   47.43 +    /**
   47.44 +     * Constructs an <code>IncompatibleClassChangeError</code> with no
   47.45 +     * detail message.
   47.46 +     */
   47.47 +    public IncompatibleClassChangeError () {
   47.48 +        super();
   47.49 +    }
   47.50 +
   47.51 +    /**
   47.52 +     * Constructs an <code>IncompatibleClassChangeError</code> with the
   47.53 +     * specified detail message.
   47.54 +     *
   47.55 +     * @param   s   the detail message.
   47.56 +     */
   47.57 +    public IncompatibleClassChangeError(String s) {
   47.58 +        super(s);
   47.59 +    }
   47.60 +}
    48.1 --- a/emul/mini/src/main/java/java/lang/String.java	Fri Feb 01 16:34:51 2013 +0100
    48.2 +++ b/emul/mini/src/main/java/java/lang/String.java	Mon Feb 04 09:37:56 2013 +0100
    48.3 @@ -25,6 +25,7 @@
    48.4  
    48.5  package java.lang;
    48.6  
    48.7 +import java.io.UnsupportedEncodingException;
    48.8  import java.util.Comparator;
    48.9  import org.apidesign.bck2brwsr.core.ExtraJavaScript;
   48.10  import org.apidesign.bck2brwsr.core.JavaScriptBody;
   48.11 @@ -200,6 +201,10 @@
   48.12       *          If the {@code offset} and {@code count} arguments index
   48.13       *          characters outside the bounds of the {@code value} array
   48.14       */
   48.15 +    public String(char value[], int offset, int count) {
   48.16 +        initFromCharArray(value, offset, count);
   48.17 +    }
   48.18 +    
   48.19      @JavaScriptBody(args = { "charArr", "off", "cnt" }, body =
   48.20          "var up = off + cnt;\n" +
   48.21          "for (var i = off; i < up; i++) {\n" +
   48.22 @@ -207,8 +212,7 @@
   48.23          "}\n" +
   48.24          "this._r(charArr.slice(off, up).join(\"\"));\n"
   48.25      )
   48.26 -    public String(char value[], int offset, int count) {
   48.27 -    }
   48.28 +    private native void initFromCharArray(char value[], int offset, int count);
   48.29  
   48.30      /**
   48.31       * Allocates a new {@code String} that contains characters from a subarray
   48.32 @@ -415,17 +419,11 @@
   48.33       *
   48.34       * @since  JDK1.1
   48.35       */
   48.36 -//    public String(byte bytes[], int offset, int length, String charsetName)
   48.37 -//        throws UnsupportedEncodingException
   48.38 -//    {
   48.39 -//        if (charsetName == null)
   48.40 -//            throw new NullPointerException("charsetName");
   48.41 -//        checkBounds(bytes, offset, length);
   48.42 -//        char[] v = StringCoding.decode(charsetName, bytes, offset, length);
   48.43 -//        this.offset = 0;
   48.44 -//        this.count = v.length;
   48.45 -//        this.value = v;
   48.46 -//    }
   48.47 +    public String(byte bytes[], int offset, int length, String charsetName)
   48.48 +        throws UnsupportedEncodingException
   48.49 +    {
   48.50 +        this(checkUTF8(bytes, charsetName), offset, length);
   48.51 +    }
   48.52  
   48.53      /**
   48.54       * Constructs a new {@code String} by decoding the specified subarray of
   48.55 @@ -492,11 +490,11 @@
   48.56       *
   48.57       * @since  JDK1.1
   48.58       */
   48.59 -//    public String(byte bytes[], String charsetName)
   48.60 -//        throws UnsupportedEncodingException
   48.61 -//    {
   48.62 -//        this(bytes, 0, bytes.length, charsetName);
   48.63 -//    }
   48.64 +    public String(byte bytes[], String charsetName)
   48.65 +        throws UnsupportedEncodingException
   48.66 +    {
   48.67 +        this(bytes, 0, bytes.length, charsetName);
   48.68 +    }
   48.69  
   48.70      /**
   48.71       * Constructs a new {@code String} by decoding the specified array of
   48.72 @@ -553,10 +551,14 @@
   48.73      public String(byte bytes[], int offset, int length) {
   48.74          checkBounds(bytes, offset, length);
   48.75          char[] v  = new char[length];
   48.76 -        for (int i = 0; i < length; i++) {
   48.77 -            v[i] = (char)bytes[offset++];
   48.78 +        int[] at = { offset };
   48.79 +        int end = offset + length;
   48.80 +        int chlen = 0;
   48.81 +        while (at[0] < end) {
   48.82 +            int ch = nextChar(bytes, at);
   48.83 +            v[chlen++] = (char)ch;
   48.84          }
   48.85 -        this.r = new String(v, 0, v.length);
   48.86 +        initFromCharArray(v, 0, chlen);
   48.87      }
   48.88  
   48.89      /**
   48.90 @@ -925,12 +927,12 @@
   48.91       *
   48.92       * @since  JDK1.1
   48.93       */
   48.94 -//    public byte[] getBytes(String charsetName)
   48.95 -//        throws UnsupportedEncodingException
   48.96 -//    {
   48.97 -//        if (charsetName == null) throw new NullPointerException();
   48.98 -//        return StringCoding.encode(charsetName, value, offset, count);
   48.99 -//    }
  48.100 +    public byte[] getBytes(String charsetName)
  48.101 +        throws UnsupportedEncodingException
  48.102 +    {
  48.103 +        checkUTF8(null, charsetName);
  48.104 +        return getBytes();
  48.105 +    }
  48.106  
  48.107      /**
  48.108       * Encodes this {@code String} into a sequence of bytes using the given
  48.109 @@ -1224,7 +1226,7 @@
  48.110      private static int offset() {
  48.111          return 0;
  48.112      }
  48.113 -    
  48.114 +
  48.115      private static class CaseInsensitiveComparator
  48.116                           implements Comparator<String>, java.io.Serializable {
  48.117          // use serialVersionUID from JDK 1.2.2 for interoperability
  48.118 @@ -3021,4 +3023,57 @@
  48.119       *          guaranteed to be from a pool of unique strings.
  48.120       */
  48.121      public native String intern();
  48.122 +    
  48.123 +    
  48.124 +    private static <T> T checkUTF8(T data, String charsetName)
  48.125 +        throws UnsupportedEncodingException {
  48.126 +        if (charsetName == null) {
  48.127 +            throw new NullPointerException("charsetName");
  48.128 +        }
  48.129 +        if (!charsetName.equalsIgnoreCase("UTF-8")
  48.130 +            && !charsetName.equalsIgnoreCase("UTF8")) {
  48.131 +            throw new UnsupportedEncodingException(charsetName);
  48.132 +        }
  48.133 +        return data;
  48.134 +    }
  48.135 +    
  48.136 +    private static int nextChar(byte[] arr, int[] index) throws IndexOutOfBoundsException {
  48.137 +        int c = arr[index[0]++] & 0xff;
  48.138 +        switch (c >> 4) {
  48.139 +            case 0:
  48.140 +            case 1:
  48.141 +            case 2:
  48.142 +            case 3:
  48.143 +            case 4:
  48.144 +            case 5:
  48.145 +            case 6:
  48.146 +            case 7:
  48.147 +                /* 0xxxxxxx*/
  48.148 +                return c;
  48.149 +            case 12:
  48.150 +            case 13: {
  48.151 +                /* 110x xxxx   10xx xxxx*/
  48.152 +                int char2 = (int) arr[index[0]++];
  48.153 +                if ((char2 & 0xC0) != 0x80) {
  48.154 +                    throw new IndexOutOfBoundsException("malformed input");
  48.155 +                }
  48.156 +                return (((c & 0x1F) << 6) | (char2 & 0x3F));
  48.157 +            }
  48.158 +            case 14: {
  48.159 +                /* 1110 xxxx  10xx xxxx  10xx xxxx */
  48.160 +                int char2 = arr[index[0]++];
  48.161 +                int char3 = arr[index[0]++];
  48.162 +                if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80)) {
  48.163 +                    throw new IndexOutOfBoundsException("malformed input");
  48.164 +                }
  48.165 +                return (((c & 0x0F) << 12)
  48.166 +                    | ((char2 & 0x3F) << 6)
  48.167 +                    | ((char3 & 0x3F) << 0));
  48.168 +            }
  48.169 +            default:
  48.170 +                /* 10xx xxxx,  1111 xxxx */
  48.171 +                throw new IndexOutOfBoundsException("malformed input");
  48.172 +        }
  48.173 +        
  48.174 +    }
  48.175  }
    49.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.2 +++ b/emul/mini/src/main/java/java/lang/reflect/Constructor.java	Mon Feb 04 09:37:56 2013 +0100
    49.3 @@ -0,0 +1,567 @@
    49.4 +/*
    49.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
    49.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    49.7 + *
    49.8 + * This code is free software; you can redistribute it and/or modify it
    49.9 + * under the terms of the GNU General Public License version 2 only, as
   49.10 + * published by the Free Software Foundation.  Oracle designates this
   49.11 + * particular file as subject to the "Classpath" exception as provided
   49.12 + * by Oracle in the LICENSE file that accompanied this code.
   49.13 + *
   49.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   49.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   49.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   49.17 + * version 2 for more details (a copy is included in the LICENSE file that
   49.18 + * accompanied this code).
   49.19 + *
   49.20 + * You should have received a copy of the GNU General Public License version
   49.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   49.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   49.23 + *
   49.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   49.25 + * or visit www.oracle.com if you need additional information or have any
   49.26 + * questions.
   49.27 + */
   49.28 +
   49.29 +package java.lang.reflect;
   49.30 +
   49.31 +import java.lang.annotation.Annotation;
   49.32 +import org.apidesign.bck2brwsr.emul.reflect.TypeProvider;
   49.33 +
   49.34 +/**
   49.35 + * {@code Constructor} provides information about, and access to, a single
   49.36 + * constructor for a class.
   49.37 + *
   49.38 + * <p>{@code Constructor} permits widening conversions to occur when matching the
   49.39 + * actual parameters to newInstance() with the underlying
   49.40 + * constructor's formal parameters, but throws an
   49.41 + * {@code IllegalArgumentException} if a narrowing conversion would occur.
   49.42 + *
   49.43 + * @param <T> the class in which the constructor is declared
   49.44 + *
   49.45 + * @see Member
   49.46 + * @see java.lang.Class
   49.47 + * @see java.lang.Class#getConstructors()
   49.48 + * @see java.lang.Class#getConstructor(Class[])
   49.49 + * @see java.lang.Class#getDeclaredConstructors()
   49.50 + *
   49.51 + * @author      Kenneth Russell
   49.52 + * @author      Nakul Saraiya
   49.53 + */
   49.54 +public final
   49.55 +    class Constructor<T> extends AccessibleObject implements
   49.56 +                                                    GenericDeclaration,
   49.57 +                                                    Member {
   49.58 +
   49.59 +    private Class<T>            clazz;
   49.60 +    private int                 slot;
   49.61 +    private Class<?>[]          parameterTypes;
   49.62 +    private Class<?>[]          exceptionTypes;
   49.63 +    private int                 modifiers;
   49.64 +    // Generics and annotations support
   49.65 +    private transient String    signature;
   49.66 +    private byte[]              annotations;
   49.67 +    private byte[]              parameterAnnotations;
   49.68 +
   49.69 +
   49.70 +    // For sharing of ConstructorAccessors. This branching structure
   49.71 +    // is currently only two levels deep (i.e., one root Constructor
   49.72 +    // and potentially many Constructor objects pointing to it.)
   49.73 +    private Constructor<T>      root;
   49.74 +
   49.75 +    /**
   49.76 +     * Package-private constructor used by ReflectAccess to enable
   49.77 +     * instantiation of these objects in Java code from the java.lang
   49.78 +     * package via sun.reflect.LangReflectAccess.
   49.79 +     */
   49.80 +    Constructor(Class<T> declaringClass,
   49.81 +                Class<?>[] parameterTypes,
   49.82 +                Class<?>[] checkedExceptions,
   49.83 +                int modifiers,
   49.84 +                int slot,
   49.85 +                String signature,
   49.86 +                byte[] annotations,
   49.87 +                byte[] parameterAnnotations)
   49.88 +    {
   49.89 +        this.clazz = declaringClass;
   49.90 +        this.parameterTypes = parameterTypes;
   49.91 +        this.exceptionTypes = checkedExceptions;
   49.92 +        this.modifiers = modifiers;
   49.93 +        this.slot = slot;
   49.94 +        this.signature = signature;
   49.95 +        this.annotations = annotations;
   49.96 +        this.parameterAnnotations = parameterAnnotations;
   49.97 +    }
   49.98 +
   49.99 +    /**
  49.100 +     * Package-private routine (exposed to java.lang.Class via
  49.101 +     * ReflectAccess) which returns a copy of this Constructor. The copy's
  49.102 +     * "root" field points to this Constructor.
  49.103 +     */
  49.104 +    Constructor<T> copy() {
  49.105 +        return this;
  49.106 +    }
  49.107 +
  49.108 +    /**
  49.109 +     * Returns the {@code Class} object representing the class that declares
  49.110 +     * the constructor represented by this {@code Constructor} object.
  49.111 +     */
  49.112 +    public Class<T> getDeclaringClass() {
  49.113 +        return clazz;
  49.114 +    }
  49.115 +
  49.116 +    /**
  49.117 +     * Returns the name of this constructor, as a string.  This is
  49.118 +     * the binary name of the constructor's declaring class.
  49.119 +     */
  49.120 +    public String getName() {
  49.121 +        return getDeclaringClass().getName();
  49.122 +    }
  49.123 +
  49.124 +    /**
  49.125 +     * Returns the Java language modifiers for the constructor
  49.126 +     * represented by this {@code Constructor} object, as an integer. The
  49.127 +     * {@code Modifier} class should be used to decode the modifiers.
  49.128 +     *
  49.129 +     * @see Modifier
  49.130 +     */
  49.131 +    public int getModifiers() {
  49.132 +        return modifiers;
  49.133 +    }
  49.134 +
  49.135 +    /**
  49.136 +     * Returns an array of {@code TypeVariable} objects that represent the
  49.137 +     * type variables declared by the generic declaration represented by this
  49.138 +     * {@code GenericDeclaration} object, in declaration order.  Returns an
  49.139 +     * array of length 0 if the underlying generic declaration declares no type
  49.140 +     * variables.
  49.141 +     *
  49.142 +     * @return an array of {@code TypeVariable} objects that represent
  49.143 +     *     the type variables declared by this generic declaration
  49.144 +     * @throws GenericSignatureFormatError if the generic
  49.145 +     *     signature of this generic declaration does not conform to
  49.146 +     *     the format specified in
  49.147 +     *     <cite>The Java&trade; Virtual Machine Specification</cite>
  49.148 +     * @since 1.5
  49.149 +     */
  49.150 +    public TypeVariable<Constructor<T>>[] getTypeParameters() {
  49.151 +        return TypeProvider.getDefault().getTypeParameters(this);
  49.152 +    }
  49.153 +
  49.154 +
  49.155 +    /**
  49.156 +     * Returns an array of {@code Class} objects that represent the formal
  49.157 +     * parameter types, in declaration order, of the constructor
  49.158 +     * represented by this {@code Constructor} object.  Returns an array of
  49.159 +     * length 0 if the underlying constructor takes no parameters.
  49.160 +     *
  49.161 +     * @return the parameter types for the constructor this object
  49.162 +     * represents
  49.163 +     */
  49.164 +    public Class<?>[] getParameterTypes() {
  49.165 +        return (Class<?>[]) parameterTypes.clone();
  49.166 +    }
  49.167 +
  49.168 +
  49.169 +    /**
  49.170 +     * Returns an array of {@code Type} objects that represent the formal
  49.171 +     * parameter types, in declaration order, of the method represented by
  49.172 +     * this {@code Constructor} object. Returns an array of length 0 if the
  49.173 +     * underlying method takes no parameters.
  49.174 +     *
  49.175 +     * <p>If a formal parameter type is a parameterized type,
  49.176 +     * the {@code Type} object returned for it must accurately reflect
  49.177 +     * the actual type parameters used in the source code.
  49.178 +     *
  49.179 +     * <p>If a formal parameter type is a type variable or a parameterized
  49.180 +     * type, it is created. Otherwise, it is resolved.
  49.181 +     *
  49.182 +     * @return an array of {@code Type}s that represent the formal
  49.183 +     *     parameter types of the underlying method, in declaration order
  49.184 +     * @throws GenericSignatureFormatError
  49.185 +     *     if the generic method signature does not conform to the format
  49.186 +     *     specified in
  49.187 +     *     <cite>The Java&trade; Virtual Machine Specification</cite>
  49.188 +     * @throws TypeNotPresentException if any of the parameter
  49.189 +     *     types of the underlying method refers to a non-existent type
  49.190 +     *     declaration
  49.191 +     * @throws MalformedParameterizedTypeException if any of
  49.192 +     *     the underlying method's parameter types refer to a parameterized
  49.193 +     *     type that cannot be instantiated for any reason
  49.194 +     * @since 1.5
  49.195 +     */
  49.196 +    public Type[] getGenericParameterTypes() {
  49.197 +        return TypeProvider.getDefault().getGenericParameterTypes(this);
  49.198 +    }
  49.199 +
  49.200 +
  49.201 +    /**
  49.202 +     * Returns an array of {@code Class} objects that represent the types
  49.203 +     * of exceptions declared to be thrown by the underlying constructor
  49.204 +     * represented by this {@code Constructor} object.  Returns an array of
  49.205 +     * length 0 if the constructor declares no exceptions in its {@code throws} clause.
  49.206 +     *
  49.207 +     * @return the exception types declared as being thrown by the
  49.208 +     * constructor this object represents
  49.209 +     */
  49.210 +    public Class<?>[] getExceptionTypes() {
  49.211 +        return (Class<?>[])exceptionTypes.clone();
  49.212 +    }
  49.213 +
  49.214 +
  49.215 +    /**
  49.216 +     * Returns an array of {@code Type} objects that represent the
  49.217 +     * exceptions declared to be thrown by this {@code Constructor} object.
  49.218 +     * Returns an array of length 0 if the underlying method declares
  49.219 +     * no exceptions in its {@code throws} clause.
  49.220 +     *
  49.221 +     * <p>If an exception type is a type variable or a parameterized
  49.222 +     * type, it is created. Otherwise, it is resolved.
  49.223 +     *
  49.224 +     * @return an array of Types that represent the exception types
  49.225 +     *     thrown by the underlying method
  49.226 +     * @throws GenericSignatureFormatError
  49.227 +     *     if the generic method signature does not conform to the format
  49.228 +     *     specified in
  49.229 +     *     <cite>The Java&trade; Virtual Machine Specification</cite>
  49.230 +     * @throws TypeNotPresentException if the underlying method's
  49.231 +     *     {@code throws} clause refers to a non-existent type declaration
  49.232 +     * @throws MalformedParameterizedTypeException if
  49.233 +     *     the underlying method's {@code throws} clause refers to a
  49.234 +     *     parameterized type that cannot be instantiated for any reason
  49.235 +     * @since 1.5
  49.236 +     */
  49.237 +      public Type[] getGenericExceptionTypes() {
  49.238 +          return TypeProvider.getDefault().getGenericExceptionTypes(this);
  49.239 +      }
  49.240 +
  49.241 +    /**
  49.242 +     * Compares this {@code Constructor} against the specified object.
  49.243 +     * Returns true if the objects are the same.  Two {@code Constructor} objects are
  49.244 +     * the same if they were declared by the same class and have the
  49.245 +     * same formal parameter types.
  49.246 +     */
  49.247 +    public boolean equals(Object obj) {
  49.248 +        if (obj != null && obj instanceof Constructor) {
  49.249 +            Constructor<?> other = (Constructor<?>)obj;
  49.250 +            if (getDeclaringClass() == other.getDeclaringClass()) {
  49.251 +                /* Avoid unnecessary cloning */
  49.252 +                Class<?>[] params1 = parameterTypes;
  49.253 +                Class<?>[] params2 = other.parameterTypes;
  49.254 +                if (params1.length == params2.length) {
  49.255 +                    for (int i = 0; i < params1.length; i++) {
  49.256 +                        if (params1[i] != params2[i])
  49.257 +                            return false;
  49.258 +                    }
  49.259 +                    return true;
  49.260 +                }
  49.261 +            }
  49.262 +        }
  49.263 +        return false;
  49.264 +    }
  49.265 +
  49.266 +    /**
  49.267 +     * Returns a hashcode for this {@code Constructor}. The hashcode is
  49.268 +     * the same as the hashcode for the underlying constructor's
  49.269 +     * declaring class name.
  49.270 +     */
  49.271 +    public int hashCode() {
  49.272 +        return getDeclaringClass().getName().hashCode();
  49.273 +    }
  49.274 +
  49.275 +    /**
  49.276 +     * Returns a string describing this {@code Constructor}.  The string is
  49.277 +     * formatted as the constructor access modifiers, if any,
  49.278 +     * followed by the fully-qualified name of the declaring class,
  49.279 +     * followed by a parenthesized, comma-separated list of the
  49.280 +     * constructor's formal parameter types.  For example:
  49.281 +     * <pre>
  49.282 +     *    public java.util.Hashtable(int,float)
  49.283 +     * </pre>
  49.284 +     *
  49.285 +     * <p>The only possible modifiers for constructors are the access
  49.286 +     * modifiers {@code public}, {@code protected} or
  49.287 +     * {@code private}.  Only one of these may appear, or none if the
  49.288 +     * constructor has default (package) access.
  49.289 +     */
  49.290 +    public String toString() {
  49.291 +        try {
  49.292 +            StringBuffer sb = new StringBuffer();
  49.293 +            int mod = getModifiers() & Modifier.constructorModifiers();
  49.294 +            if (mod != 0) {
  49.295 +                sb.append(Modifier.toString(mod) + " ");
  49.296 +            }
  49.297 +            sb.append(Field.getTypeName(getDeclaringClass()));
  49.298 +            sb.append("(");
  49.299 +            Class<?>[] params = parameterTypes; // avoid clone
  49.300 +            for (int j = 0; j < params.length; j++) {
  49.301 +                sb.append(Field.getTypeName(params[j]));
  49.302 +                if (j < (params.length - 1))
  49.303 +                    sb.append(",");
  49.304 +            }
  49.305 +            sb.append(")");
  49.306 +            Class<?>[] exceptions = exceptionTypes; // avoid clone
  49.307 +            if (exceptions.length > 0) {
  49.308 +                sb.append(" throws ");
  49.309 +                for (int k = 0; k < exceptions.length; k++) {
  49.310 +                    sb.append(exceptions[k].getName());
  49.311 +                    if (k < (exceptions.length - 1))
  49.312 +                        sb.append(",");
  49.313 +                }
  49.314 +            }
  49.315 +            return sb.toString();
  49.316 +        } catch (Exception e) {
  49.317 +            return "<" + e + ">";
  49.318 +        }
  49.319 +    }
  49.320 +
  49.321 +    /**
  49.322 +     * Returns a string describing this {@code Constructor},
  49.323 +     * including type parameters.  The string is formatted as the
  49.324 +     * constructor access modifiers, if any, followed by an
  49.325 +     * angle-bracketed comma separated list of the constructor's type
  49.326 +     * parameters, if any, followed by the fully-qualified name of the
  49.327 +     * declaring class, followed by a parenthesized, comma-separated
  49.328 +     * list of the constructor's generic formal parameter types.
  49.329 +     *
  49.330 +     * If this constructor was declared to take a variable number of
  49.331 +     * arguments, instead of denoting the last parameter as
  49.332 +     * "<tt><i>Type</i>[]</tt>", it is denoted as
  49.333 +     * "<tt><i>Type</i>...</tt>".
  49.334 +     *
  49.335 +     * A space is used to separate access modifiers from one another
  49.336 +     * and from the type parameters or return type.  If there are no
  49.337 +     * type parameters, the type parameter list is elided; if the type
  49.338 +     * parameter list is present, a space separates the list from the
  49.339 +     * class name.  If the constructor is declared to throw
  49.340 +     * exceptions, the parameter list is followed by a space, followed
  49.341 +     * by the word "{@code throws}" followed by a
  49.342 +     * comma-separated list of the thrown exception types.
  49.343 +     *
  49.344 +     * <p>The only possible modifiers for constructors are the access
  49.345 +     * modifiers {@code public}, {@code protected} or
  49.346 +     * {@code private}.  Only one of these may appear, or none if the
  49.347 +     * constructor has default (package) access.
  49.348 +     *
  49.349 +     * @return a string describing this {@code Constructor},
  49.350 +     * include type parameters
  49.351 +     *
  49.352 +     * @since 1.5
  49.353 +     */
  49.354 +    public String toGenericString() {
  49.355 +        try {
  49.356 +            StringBuilder sb = new StringBuilder();
  49.357 +            int mod = getModifiers() & Modifier.constructorModifiers();
  49.358 +            if (mod != 0) {
  49.359 +                sb.append(Modifier.toString(mod) + " ");
  49.360 +            }
  49.361 +            TypeVariable<?>[] typeparms = getTypeParameters();
  49.362 +            if (typeparms.length > 0) {
  49.363 +                boolean first = true;
  49.364 +                sb.append("<");
  49.365 +                for(TypeVariable<?> typeparm: typeparms) {
  49.366 +                    if (!first)
  49.367 +                        sb.append(",");
  49.368 +                    // Class objects can't occur here; no need to test
  49.369 +                    // and call Class.getName().
  49.370 +                    sb.append(typeparm.toString());
  49.371 +                    first = false;
  49.372 +                }
  49.373 +                sb.append("> ");
  49.374 +            }
  49.375 +            sb.append(Field.getTypeName(getDeclaringClass()));
  49.376 +            sb.append("(");
  49.377 +            Type[] params = getGenericParameterTypes();
  49.378 +            for (int j = 0; j < params.length; j++) {
  49.379 +                String param = (params[j] instanceof Class<?>)?
  49.380 +                    Field.getTypeName((Class<?>)params[j]):
  49.381 +                    (params[j].toString());
  49.382 +                if (isVarArgs() && (j == params.length - 1)) // replace T[] with T...
  49.383 +                    param = param.replaceFirst("\\[\\]$", "...");
  49.384 +                sb.append(param);
  49.385 +                if (j < (params.length - 1))
  49.386 +                    sb.append(",");
  49.387 +            }
  49.388 +            sb.append(")");
  49.389 +            Type[] exceptions = getGenericExceptionTypes();
  49.390 +            if (exceptions.length > 0) {
  49.391 +                sb.append(" throws ");
  49.392 +                for (int k = 0; k < exceptions.length; k++) {
  49.393 +                    sb.append((exceptions[k] instanceof Class)?
  49.394 +                              ((Class<?>)exceptions[k]).getName():
  49.395 +                              exceptions[k].toString());
  49.396 +                    if (k < (exceptions.length - 1))
  49.397 +                        sb.append(",");
  49.398 +                }
  49.399 +            }
  49.400 +            return sb.toString();
  49.401 +        } catch (Exception e) {
  49.402 +            return "<" + e + ">";
  49.403 +        }
  49.404 +    }
  49.405 +
  49.406 +    /**
  49.407 +     * Uses the constructor represented by this {@code Constructor} object to
  49.408 +     * create and initialize a new instance of the constructor's
  49.409 +     * declaring class, with the specified initialization parameters.
  49.410 +     * Individual parameters are automatically unwrapped to match
  49.411 +     * primitive formal parameters, and both primitive and reference
  49.412 +     * parameters are subject to method invocation conversions as necessary.
  49.413 +     *
  49.414 +     * <p>If the number of formal parameters required by the underlying constructor
  49.415 +     * is 0, the supplied {@code initargs} array may be of length 0 or null.
  49.416 +     *
  49.417 +     * <p>If the constructor's declaring class is an inner class in a
  49.418 +     * non-static context, the first argument to the constructor needs
  49.419 +     * to be the enclosing instance; see section 15.9.3 of
  49.420 +     * <cite>The Java&trade; Language Specification</cite>.
  49.421 +     *
  49.422 +     * <p>If the required access and argument checks succeed and the
  49.423 +     * instantiation will proceed, the constructor's declaring class
  49.424 +     * is initialized if it has not already been initialized.
  49.425 +     *
  49.426 +     * <p>If the constructor completes normally, returns the newly
  49.427 +     * created and initialized instance.
  49.428 +     *
  49.429 +     * @param initargs array of objects to be passed as arguments to
  49.430 +     * the constructor call; values of primitive types are wrapped in
  49.431 +     * a wrapper object of the appropriate type (e.g. a {@code float}
  49.432 +     * in a {@link java.lang.Float Float})
  49.433 +     *
  49.434 +     * @return a new object created by calling the constructor
  49.435 +     * this object represents
  49.436 +     *
  49.437 +     * @exception IllegalAccessException    if this {@code Constructor} object
  49.438 +     *              is enforcing Java language access control and the underlying
  49.439 +     *              constructor is inaccessible.
  49.440 +     * @exception IllegalArgumentException  if the number of actual
  49.441 +     *              and formal parameters differ; if an unwrapping
  49.442 +     *              conversion for primitive arguments fails; or if,
  49.443 +     *              after possible unwrapping, a parameter value
  49.444 +     *              cannot be converted to the corresponding formal
  49.445 +     *              parameter type by a method invocation conversion; if
  49.446 +     *              this constructor pertains to an enum type.
  49.447 +     * @exception InstantiationException    if the class that declares the
  49.448 +     *              underlying constructor represents an abstract class.
  49.449 +     * @exception InvocationTargetException if the underlying constructor
  49.450 +     *              throws an exception.
  49.451 +     * @exception ExceptionInInitializerError if the initialization provoked
  49.452 +     *              by this method fails.
  49.453 +     */
  49.454 +    public T newInstance(Object ... initargs)
  49.455 +        throws InstantiationException, IllegalAccessException,
  49.456 +               IllegalArgumentException, InvocationTargetException
  49.457 +    {
  49.458 +        throw new SecurityException();
  49.459 +    }
  49.460 +
  49.461 +    /**
  49.462 +     * Returns {@code true} if this constructor was declared to take
  49.463 +     * a variable number of arguments; returns {@code false}
  49.464 +     * otherwise.
  49.465 +     *
  49.466 +     * @return {@code true} if an only if this constructor was declared to
  49.467 +     * take a variable number of arguments.
  49.468 +     * @since 1.5
  49.469 +     */
  49.470 +    public boolean isVarArgs() {
  49.471 +        return (getModifiers() & Modifier.VARARGS) != 0;
  49.472 +    }
  49.473 +
  49.474 +    /**
  49.475 +     * Returns {@code true} if this constructor is a synthetic
  49.476 +     * constructor; returns {@code false} otherwise.
  49.477 +     *
  49.478 +     * @return true if and only if this constructor is a synthetic
  49.479 +     * constructor as defined by
  49.480 +     * <cite>The Java&trade; Language Specification</cite>.
  49.481 +     * @since 1.5
  49.482 +     */
  49.483 +    public boolean isSynthetic() {
  49.484 +        return Modifier.isSynthetic(getModifiers());
  49.485 +    }
  49.486 +
  49.487 +    int getSlot() {
  49.488 +        return slot;
  49.489 +    }
  49.490 +
  49.491 +   String getSignature() {
  49.492 +            return signature;
  49.493 +   }
  49.494 +
  49.495 +    byte[] getRawAnnotations() {
  49.496 +        return annotations;
  49.497 +    }
  49.498 +
  49.499 +    byte[] getRawParameterAnnotations() {
  49.500 +        return parameterAnnotations;
  49.501 +    }
  49.502 +
  49.503 +    /**
  49.504 +     * @throws NullPointerException {@inheritDoc}
  49.505 +     * @since 1.5
  49.506 +     */
  49.507 +    public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
  49.508 +        if (annotationClass == null)
  49.509 +            throw new NullPointerException();
  49.510 +
  49.511 +        return null; // XXX (T) declaredAnnotations().get(annotationClass);
  49.512 +    }
  49.513 +
  49.514 +    /**
  49.515 +     * @since 1.5
  49.516 +     */
  49.517 +    public Annotation[] getDeclaredAnnotations()  {
  49.518 +        return new Annotation[0]; // XXX AnnotationParser.toArray(declaredAnnotations());
  49.519 +    }
  49.520 +
  49.521 +    /**
  49.522 +     * Returns an array of arrays that represent the annotations on the formal
  49.523 +     * parameters, in declaration order, of the method represented by
  49.524 +     * this {@code Constructor} object. (Returns an array of length zero if the
  49.525 +     * underlying method is parameterless.  If the method has one or more
  49.526 +     * parameters, a nested array of length zero is returned for each parameter
  49.527 +     * with no annotations.) The annotation objects contained in the returned
  49.528 +     * arrays are serializable.  The caller of this method is free to modify
  49.529 +     * the returned arrays; it will have no effect on the arrays returned to
  49.530 +     * other callers.
  49.531 +     *
  49.532 +     * @return an array of arrays that represent the annotations on the formal
  49.533 +     *    parameters, in declaration order, of the method represented by this
  49.534 +     *    Constructor object
  49.535 +     * @since 1.5
  49.536 +     */
  49.537 +    public Annotation[][] getParameterAnnotations() {
  49.538 +        int numParameters = parameterTypes.length;
  49.539 +        if (parameterAnnotations == null)
  49.540 +            return new Annotation[numParameters][0];
  49.541 +        
  49.542 +        return new Annotation[numParameters][0]; // XXX
  49.543 +/*
  49.544 +        Annotation[][] result = AnnotationParser.parseParameterAnnotations(
  49.545 +            parameterAnnotations,
  49.546 +            sun.misc.SharedSecrets.getJavaLangAccess().
  49.547 +                getConstantPool(getDeclaringClass()),
  49.548 +            getDeclaringClass());
  49.549 +        if (result.length != numParameters) {
  49.550 +            Class<?> declaringClass = getDeclaringClass();
  49.551 +            if (declaringClass.isEnum() ||
  49.552 +                declaringClass.isAnonymousClass() ||
  49.553 +                declaringClass.isLocalClass() )
  49.554 +                ; // Can't do reliable parameter counting
  49.555 +            else {
  49.556 +                if (!declaringClass.isMemberClass() || // top-level
  49.557 +                    // Check for the enclosing instance parameter for
  49.558 +                    // non-static member classes
  49.559 +                    (declaringClass.isMemberClass() &&
  49.560 +                     ((declaringClass.getModifiers() & Modifier.STATIC) == 0)  &&
  49.561 +                     result.length + 1 != numParameters) ) {
  49.562 +                    throw new AnnotationFormatError(
  49.563 +                              "Parameter annotations don't match number of parameters");
  49.564 +                }
  49.565 +            }
  49.566 +        }
  49.567 +        return result;
  49.568 +        */
  49.569 +    }
  49.570 +}
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/emul/mini/src/main/java/java/lang/reflect/InvocationHandler.java	Mon Feb 04 09:37:56 2013 +0100
    50.3 @@ -0,0 +1,95 @@
    50.4 +/*
    50.5 + * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved.
    50.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    50.7 + *
    50.8 + * This code is free software; you can redistribute it and/or modify it
    50.9 + * under the terms of the GNU General Public License version 2 only, as
   50.10 + * published by the Free Software Foundation.  Oracle designates this
   50.11 + * particular file as subject to the "Classpath" exception as provided
   50.12 + * by Oracle in the LICENSE file that accompanied this code.
   50.13 + *
   50.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   50.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   50.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   50.17 + * version 2 for more details (a copy is included in the LICENSE file that
   50.18 + * accompanied this code).
   50.19 + *
   50.20 + * You should have received a copy of the GNU General Public License version
   50.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   50.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   50.23 + *
   50.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   50.25 + * or visit www.oracle.com if you need additional information or have any
   50.26 + * questions.
   50.27 + */
   50.28 +
   50.29 +package java.lang.reflect;
   50.30 +
   50.31 +/**
   50.32 + * {@code InvocationHandler} is the interface implemented by
   50.33 + * the <i>invocation handler</i> of a proxy instance.
   50.34 + *
   50.35 + * <p>Each proxy instance has an associated invocation handler.
   50.36 + * When a method is invoked on a proxy instance, the method
   50.37 + * invocation is encoded and dispatched to the {@code invoke}
   50.38 + * method of its invocation handler.
   50.39 + *
   50.40 + * @author      Peter Jones
   50.41 + * @see         Proxy
   50.42 + * @since       1.3
   50.43 + */
   50.44 +public interface InvocationHandler {
   50.45 +
   50.46 +    /**
   50.47 +     * Processes a method invocation on a proxy instance and returns
   50.48 +     * the result.  This method will be invoked on an invocation handler
   50.49 +     * when a method is invoked on a proxy instance that it is
   50.50 +     * associated with.
   50.51 +     *
   50.52 +     * @param   proxy the proxy instance that the method was invoked on
   50.53 +     *
   50.54 +     * @param   method the {@code Method} instance corresponding to
   50.55 +     * the interface method invoked on the proxy instance.  The declaring
   50.56 +     * class of the {@code Method} object will be the interface that
   50.57 +     * the method was declared in, which may be a superinterface of the
   50.58 +     * proxy interface that the proxy class inherits the method through.
   50.59 +     *
   50.60 +     * @param   args an array of objects containing the values of the
   50.61 +     * arguments passed in the method invocation on the proxy instance,
   50.62 +     * or {@code null} if interface method takes no arguments.
   50.63 +     * Arguments of primitive types are wrapped in instances of the
   50.64 +     * appropriate primitive wrapper class, such as
   50.65 +     * {@code java.lang.Integer} or {@code java.lang.Boolean}.
   50.66 +     *
   50.67 +     * @return  the value to return from the method invocation on the
   50.68 +     * proxy instance.  If the declared return type of the interface
   50.69 +     * method is a primitive type, then the value returned by
   50.70 +     * this method must be an instance of the corresponding primitive
   50.71 +     * wrapper class; otherwise, it must be a type assignable to the
   50.72 +     * declared return type.  If the value returned by this method is
   50.73 +     * {@code null} and the interface method's return type is
   50.74 +     * primitive, then a {@code NullPointerException} will be
   50.75 +     * thrown by the method invocation on the proxy instance.  If the
   50.76 +     * value returned by this method is otherwise not compatible with
   50.77 +     * the interface method's declared return type as described above,
   50.78 +     * a {@code ClassCastException} will be thrown by the method
   50.79 +     * invocation on the proxy instance.
   50.80 +     *
   50.81 +     * @throws  Throwable the exception to throw from the method
   50.82 +     * invocation on the proxy instance.  The exception's type must be
   50.83 +     * assignable either to any of the exception types declared in the
   50.84 +     * {@code throws} clause of the interface method or to the
   50.85 +     * unchecked exception types {@code java.lang.RuntimeException}
   50.86 +     * or {@code java.lang.Error}.  If a checked exception is
   50.87 +     * thrown by this method that is not assignable to any of the
   50.88 +     * exception types declared in the {@code throws} clause of
   50.89 +     * the interface method, then an
   50.90 +     * {@link UndeclaredThrowableException} containing the
   50.91 +     * exception that was thrown by this method will be thrown by the
   50.92 +     * method invocation on the proxy instance.
   50.93 +     *
   50.94 +     * @see     UndeclaredThrowableException
   50.95 +     */
   50.96 +    public Object invoke(Object proxy, Method method, Object[] args)
   50.97 +        throws Throwable;
   50.98 +}
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/emul/mini/src/main/java/java/lang/reflect/Proxy.java	Mon Feb 04 09:37:56 2013 +0100
    51.3 @@ -0,0 +1,407 @@
    51.4 +/*
    51.5 + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
    51.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    51.7 + *
    51.8 + * This code is free software; you can redistribute it and/or modify it
    51.9 + * under the terms of the GNU General Public License version 2 only, as
   51.10 + * published by the Free Software Foundation.  Oracle designates this
   51.11 + * particular file as subject to the "Classpath" exception as provided
   51.12 + * by Oracle in the LICENSE file that accompanied this code.
   51.13 + *
   51.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   51.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   51.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   51.17 + * version 2 for more details (a copy is included in the LICENSE file that
   51.18 + * accompanied this code).
   51.19 + *
   51.20 + * You should have received a copy of the GNU General Public License version
   51.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   51.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   51.23 + *
   51.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   51.25 + * or visit www.oracle.com if you need additional information or have any
   51.26 + * questions.
   51.27 + */
   51.28 +
   51.29 +package java.lang.reflect;
   51.30 +
   51.31 +
   51.32 +/**
   51.33 + * {@code Proxy} provides static methods for creating dynamic proxy
   51.34 + * classes and instances, and it is also the superclass of all
   51.35 + * dynamic proxy classes created by those methods.
   51.36 + *
   51.37 + * <p>To create a proxy for some interface {@code Foo}:
   51.38 + * <pre>
   51.39 + *     InvocationHandler handler = new MyInvocationHandler(...);
   51.40 + *     Class proxyClass = Proxy.getProxyClass(
   51.41 + *         Foo.class.getClassLoader(), new Class[] { Foo.class });
   51.42 + *     Foo f = (Foo) proxyClass.
   51.43 + *         getConstructor(new Class[] { InvocationHandler.class }).
   51.44 + *         newInstance(new Object[] { handler });
   51.45 + * </pre>
   51.46 + * or more simply:
   51.47 + * <pre>
   51.48 + *     Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
   51.49 + *                                          new Class[] { Foo.class },
   51.50 + *                                          handler);
   51.51 + * </pre>
   51.52 + *
   51.53 + * <p>A <i>dynamic proxy class</i> (simply referred to as a <i>proxy
   51.54 + * class</i> below) is a class that implements a list of interfaces
   51.55 + * specified at runtime when the class is created, with behavior as
   51.56 + * described below.
   51.57 + *
   51.58 + * A <i>proxy interface</i> is such an interface that is implemented
   51.59 + * by a proxy class.
   51.60 + *
   51.61 + * A <i>proxy instance</i> is an instance of a proxy class.
   51.62 + *
   51.63 + * Each proxy instance has an associated <i>invocation handler</i>
   51.64 + * object, which implements the interface {@link InvocationHandler}.
   51.65 + * A method invocation on a proxy instance through one of its proxy
   51.66 + * interfaces will be dispatched to the {@link InvocationHandler#invoke
   51.67 + * invoke} method of the instance's invocation handler, passing the proxy
   51.68 + * instance, a {@code java.lang.reflect.Method} object identifying
   51.69 + * the method that was invoked, and an array of type {@code Object}
   51.70 + * containing the arguments.  The invocation handler processes the
   51.71 + * encoded method invocation as appropriate and the result that it
   51.72 + * returns will be returned as the result of the method invocation on
   51.73 + * the proxy instance.
   51.74 + *
   51.75 + * <p>A proxy class has the following properties:
   51.76 + *
   51.77 + * <ul>
   51.78 + * <li>Proxy classes are public, final, and not abstract.
   51.79 + *
   51.80 + * <li>The unqualified name of a proxy class is unspecified.  The space
   51.81 + * of class names that begin with the string {@code "$Proxy"}
   51.82 + * should be, however, reserved for proxy classes.
   51.83 + *
   51.84 + * <li>A proxy class extends {@code java.lang.reflect.Proxy}.
   51.85 + *
   51.86 + * <li>A proxy class implements exactly the interfaces specified at its
   51.87 + * creation, in the same order.
   51.88 + *
   51.89 + * <li>If a proxy class implements a non-public interface, then it will
   51.90 + * be defined in the same package as that interface.  Otherwise, the
   51.91 + * package of a proxy class is also unspecified.  Note that package
   51.92 + * sealing will not prevent a proxy class from being successfully defined
   51.93 + * in a particular package at runtime, and neither will classes already
   51.94 + * defined by the same class loader and the same package with particular
   51.95 + * signers.
   51.96 + *
   51.97 + * <li>Since a proxy class implements all of the interfaces specified at
   51.98 + * its creation, invoking {@code getInterfaces} on its
   51.99 + * {@code Class} object will return an array containing the same
  51.100 + * list of interfaces (in the order specified at its creation), invoking
  51.101 + * {@code getMethods} on its {@code Class} object will return
  51.102 + * an array of {@code Method} objects that include all of the
  51.103 + * methods in those interfaces, and invoking {@code getMethod} will
  51.104 + * find methods in the proxy interfaces as would be expected.
  51.105 + *
  51.106 + * <li>The {@link Proxy#isProxyClass Proxy.isProxyClass} method will
  51.107 + * return true if it is passed a proxy class-- a class returned by
  51.108 + * {@code Proxy.getProxyClass} or the class of an object returned by
  51.109 + * {@code Proxy.newProxyInstance}-- and false otherwise.
  51.110 + *
  51.111 + * <li>The {@code java.security.ProtectionDomain} of a proxy class
  51.112 + * is the same as that of system classes loaded by the bootstrap class
  51.113 + * loader, such as {@code java.lang.Object}, because the code for a
  51.114 + * proxy class is generated by trusted system code.  This protection
  51.115 + * domain will typically be granted
  51.116 + * {@code java.security.AllPermission}.
  51.117 + *
  51.118 + * <li>Each proxy class has one public constructor that takes one argument,
  51.119 + * an implementation of the interface {@link InvocationHandler}, to set
  51.120 + * the invocation handler for a proxy instance.  Rather than having to use
  51.121 + * the reflection API to access the public constructor, a proxy instance
  51.122 + * can be also be created by calling the {@link Proxy#newProxyInstance
  51.123 + * Proxy.newProxyInstance} method, which combines the actions of calling
  51.124 + * {@link Proxy#getProxyClass Proxy.getProxyClass} with invoking the
  51.125 + * constructor with an invocation handler.
  51.126 + * </ul>
  51.127 + *
  51.128 + * <p>A proxy instance has the following properties:
  51.129 + *
  51.130 + * <ul>
  51.131 + * <li>Given a proxy instance {@code proxy} and one of the
  51.132 + * interfaces implemented by its proxy class {@code Foo}, the
  51.133 + * following expression will return true:
  51.134 + * <pre>
  51.135 + *     {@code proxy instanceof Foo}
  51.136 + * </pre>
  51.137 + * and the following cast operation will succeed (rather than throwing
  51.138 + * a {@code ClassCastException}):
  51.139 + * <pre>
  51.140 + *     {@code (Foo) proxy}
  51.141 + * </pre>
  51.142 + *
  51.143 + * <li>Each proxy instance has an associated invocation handler, the one
  51.144 + * that was passed to its constructor.  The static
  51.145 + * {@link Proxy#getInvocationHandler Proxy.getInvocationHandler} method
  51.146 + * will return the invocation handler associated with the proxy instance
  51.147 + * passed as its argument.
  51.148 + *
  51.149 + * <li>An interface method invocation on a proxy instance will be
  51.150 + * encoded and dispatched to the invocation handler's {@link
  51.151 + * InvocationHandler#invoke invoke} method as described in the
  51.152 + * documentation for that method.
  51.153 + *
  51.154 + * <li>An invocation of the {@code hashCode},
  51.155 + * {@code equals}, or {@code toString} methods declared in
  51.156 + * {@code java.lang.Object} on a proxy instance will be encoded and
  51.157 + * dispatched to the invocation handler's {@code invoke} method in
  51.158 + * the same manner as interface method invocations are encoded and
  51.159 + * dispatched, as described above.  The declaring class of the
  51.160 + * {@code Method} object passed to {@code invoke} will be
  51.161 + * {@code java.lang.Object}.  Other public methods of a proxy
  51.162 + * instance inherited from {@code java.lang.Object} are not
  51.163 + * overridden by a proxy class, so invocations of those methods behave
  51.164 + * like they do for instances of {@code java.lang.Object}.
  51.165 + * </ul>
  51.166 + *
  51.167 + * <h3>Methods Duplicated in Multiple Proxy Interfaces</h3>
  51.168 + *
  51.169 + * <p>When two or more interfaces of a proxy class contain a method with
  51.170 + * the same name and parameter signature, the order of the proxy class's
  51.171 + * interfaces becomes significant.  When such a <i>duplicate method</i>
  51.172 + * is invoked on a proxy instance, the {@code Method} object passed
  51.173 + * to the invocation handler will not necessarily be the one whose
  51.174 + * declaring class is assignable from the reference type of the interface
  51.175 + * that the proxy's method was invoked through.  This limitation exists
  51.176 + * because the corresponding method implementation in the generated proxy
  51.177 + * class cannot determine which interface it was invoked through.
  51.178 + * Therefore, when a duplicate method is invoked on a proxy instance,
  51.179 + * the {@code Method} object for the method in the foremost interface
  51.180 + * that contains the method (either directly or inherited through a
  51.181 + * superinterface) in the proxy class's list of interfaces is passed to
  51.182 + * the invocation handler's {@code invoke} method, regardless of the
  51.183 + * reference type through which the method invocation occurred.
  51.184 + *
  51.185 + * <p>If a proxy interface contains a method with the same name and
  51.186 + * parameter signature as the {@code hashCode}, {@code equals},
  51.187 + * or {@code toString} methods of {@code java.lang.Object},
  51.188 + * when such a method is invoked on a proxy instance, the
  51.189 + * {@code Method} object passed to the invocation handler will have
  51.190 + * {@code java.lang.Object} as its declaring class.  In other words,
  51.191 + * the public, non-final methods of {@code java.lang.Object}
  51.192 + * logically precede all of the proxy interfaces for the determination of
  51.193 + * which {@code Method} object to pass to the invocation handler.
  51.194 + *
  51.195 + * <p>Note also that when a duplicate method is dispatched to an
  51.196 + * invocation handler, the {@code invoke} method may only throw
  51.197 + * checked exception types that are assignable to one of the exception
  51.198 + * types in the {@code throws} clause of the method in <i>all</i> of
  51.199 + * the proxy interfaces that it can be invoked through.  If the
  51.200 + * {@code invoke} method throws a checked exception that is not
  51.201 + * assignable to any of the exception types declared by the method in one
  51.202 + * of the proxy interfaces that it can be invoked through, then an
  51.203 + * unchecked {@code UndeclaredThrowableException} will be thrown by
  51.204 + * the invocation on the proxy instance.  This restriction means that not
  51.205 + * all of the exception types returned by invoking
  51.206 + * {@code getExceptionTypes} on the {@code Method} object
  51.207 + * passed to the {@code invoke} method can necessarily be thrown
  51.208 + * successfully by the {@code invoke} method.
  51.209 + *
  51.210 + * @author      Peter Jones
  51.211 + * @see         InvocationHandler
  51.212 + * @since       1.3
  51.213 + */
  51.214 +public class Proxy implements java.io.Serializable {
  51.215 +
  51.216 +    private static final long serialVersionUID = -2222568056686623797L;
  51.217 +
  51.218 +
  51.219 +
  51.220 +    /**
  51.221 +     * the invocation handler for this proxy instance.
  51.222 +     * @serial
  51.223 +     */
  51.224 +    protected InvocationHandler h;
  51.225 +
  51.226 +    /**
  51.227 +     * Prohibits instantiation.
  51.228 +     */
  51.229 +    private Proxy() {
  51.230 +    }
  51.231 +
  51.232 +    /**
  51.233 +     * Constructs a new {@code Proxy} instance from a subclass
  51.234 +     * (typically, a dynamic proxy class) with the specified value
  51.235 +     * for its invocation handler.
  51.236 +     *
  51.237 +     * @param   h the invocation handler for this proxy instance
  51.238 +     */
  51.239 +    protected Proxy(InvocationHandler h) {
  51.240 +        this.h = h;
  51.241 +    }
  51.242 +
  51.243 +    /**
  51.244 +     * Returns the {@code java.lang.Class} object for a proxy class
  51.245 +     * given a class loader and an array of interfaces.  The proxy class
  51.246 +     * will be defined by the specified class loader and will implement
  51.247 +     * all of the supplied interfaces.  If a proxy class for the same
  51.248 +     * permutation of interfaces has already been defined by the class
  51.249 +     * loader, then the existing proxy class will be returned; otherwise,
  51.250 +     * a proxy class for those interfaces will be generated dynamically
  51.251 +     * and defined by the class loader.
  51.252 +     *
  51.253 +     * <p>There are several restrictions on the parameters that may be
  51.254 +     * passed to {@code Proxy.getProxyClass}:
  51.255 +     *
  51.256 +     * <ul>
  51.257 +     * <li>All of the {@code Class} objects in the
  51.258 +     * {@code interfaces} array must represent interfaces, not
  51.259 +     * classes or primitive types.
  51.260 +     *
  51.261 +     * <li>No two elements in the {@code interfaces} array may
  51.262 +     * refer to identical {@code Class} objects.
  51.263 +     *
  51.264 +     * <li>All of the interface types must be visible by name through the
  51.265 +     * specified class loader.  In other words, for class loader
  51.266 +     * {@code cl} and every interface {@code i}, the following
  51.267 +     * expression must be true:
  51.268 +     * <pre>
  51.269 +     *     Class.forName(i.getName(), false, cl) == i
  51.270 +     * </pre>
  51.271 +     *
  51.272 +     * <li>All non-public interfaces must be in the same package;
  51.273 +     * otherwise, it would not be possible for the proxy class to
  51.274 +     * implement all of the interfaces, regardless of what package it is
  51.275 +     * defined in.
  51.276 +     *
  51.277 +     * <li>For any set of member methods of the specified interfaces
  51.278 +     * that have the same signature:
  51.279 +     * <ul>
  51.280 +     * <li>If the return type of any of the methods is a primitive
  51.281 +     * type or void, then all of the methods must have that same
  51.282 +     * return type.
  51.283 +     * <li>Otherwise, one of the methods must have a return type that
  51.284 +     * is assignable to all of the return types of the rest of the
  51.285 +     * methods.
  51.286 +     * </ul>
  51.287 +     *
  51.288 +     * <li>The resulting proxy class must not exceed any limits imposed
  51.289 +     * on classes by the virtual machine.  For example, the VM may limit
  51.290 +     * the number of interfaces that a class may implement to 65535; in
  51.291 +     * that case, the size of the {@code interfaces} array must not
  51.292 +     * exceed 65535.
  51.293 +     * </ul>
  51.294 +     *
  51.295 +     * <p>If any of these restrictions are violated,
  51.296 +     * {@code Proxy.getProxyClass} will throw an
  51.297 +     * {@code IllegalArgumentException}.  If the {@code interfaces}
  51.298 +     * array argument or any of its elements are {@code null}, a
  51.299 +     * {@code NullPointerException} will be thrown.
  51.300 +     *
  51.301 +     * <p>Note that the order of the specified proxy interfaces is
  51.302 +     * significant: two requests for a proxy class with the same combination
  51.303 +     * of interfaces but in a different order will result in two distinct
  51.304 +     * proxy classes.
  51.305 +     *
  51.306 +     * @param   loader the class loader to define the proxy class
  51.307 +     * @param   interfaces the list of interfaces for the proxy class
  51.308 +     *          to implement
  51.309 +     * @return  a proxy class that is defined in the specified class loader
  51.310 +     *          and that implements the specified interfaces
  51.311 +     * @throws  IllegalArgumentException if any of the restrictions on the
  51.312 +     *          parameters that may be passed to {@code getProxyClass}
  51.313 +     *          are violated
  51.314 +     * @throws  NullPointerException if the {@code interfaces} array
  51.315 +     *          argument or any of its elements are {@code null}
  51.316 +     */
  51.317 +    public static Class<?> getProxyClass(ClassLoader loader,
  51.318 +                                         Class<?>... interfaces)
  51.319 +        throws IllegalArgumentException
  51.320 +    {
  51.321 +        throw new IllegalArgumentException();
  51.322 +    }
  51.323 +
  51.324 +    /**
  51.325 +     * Returns an instance of a proxy class for the specified interfaces
  51.326 +     * that dispatches method invocations to the specified invocation
  51.327 +     * handler.  This method is equivalent to:
  51.328 +     * <pre>
  51.329 +     *     Proxy.getProxyClass(loader, interfaces).
  51.330 +     *         getConstructor(new Class[] { InvocationHandler.class }).
  51.331 +     *         newInstance(new Object[] { handler });
  51.332 +     * </pre>
  51.333 +     *
  51.334 +     * <p>{@code Proxy.newProxyInstance} throws
  51.335 +     * {@code IllegalArgumentException} for the same reasons that
  51.336 +     * {@code Proxy.getProxyClass} does.
  51.337 +     *
  51.338 +     * @param   loader the class loader to define the proxy class
  51.339 +     * @param   interfaces the list of interfaces for the proxy class
  51.340 +     *          to implement
  51.341 +     * @param   h the invocation handler to dispatch method invocations to
  51.342 +     * @return  a proxy instance with the specified invocation handler of a
  51.343 +     *          proxy class that is defined by the specified class loader
  51.344 +     *          and that implements the specified interfaces
  51.345 +     * @throws  IllegalArgumentException if any of the restrictions on the
  51.346 +     *          parameters that may be passed to {@code getProxyClass}
  51.347 +     *          are violated
  51.348 +     * @throws  NullPointerException if the {@code interfaces} array
  51.349 +     *          argument or any of its elements are {@code null}, or
  51.350 +     *          if the invocation handler, {@code h}, is
  51.351 +     *          {@code null}
  51.352 +     */
  51.353 +    public static Object newProxyInstance(ClassLoader loader,
  51.354 +                                          Class<?>[] interfaces,
  51.355 +                                          InvocationHandler h)
  51.356 +        throws IllegalArgumentException
  51.357 +    {
  51.358 +        if (h == null) {
  51.359 +            throw new NullPointerException();
  51.360 +        }
  51.361 +        throw new IllegalArgumentException();
  51.362 +    }
  51.363 +
  51.364 +    /**
  51.365 +     * Returns true if and only if the specified class was dynamically
  51.366 +     * generated to be a proxy class using the {@code getProxyClass}
  51.367 +     * method or the {@code newProxyInstance} method.
  51.368 +     *
  51.369 +     * <p>The reliability of this method is important for the ability
  51.370 +     * to use it to make security decisions, so its implementation should
  51.371 +     * not just test if the class in question extends {@code Proxy}.
  51.372 +     *
  51.373 +     * @param   cl the class to test
  51.374 +     * @return  {@code true} if the class is a proxy class and
  51.375 +     *          {@code false} otherwise
  51.376 +     * @throws  NullPointerException if {@code cl} is {@code null}
  51.377 +     */
  51.378 +    public static boolean isProxyClass(Class<?> cl) {
  51.379 +        if (cl == null) {
  51.380 +            throw new NullPointerException();
  51.381 +        }
  51.382 +
  51.383 +        return false;
  51.384 +    }
  51.385 +
  51.386 +    /**
  51.387 +     * Returns the invocation handler for the specified proxy instance.
  51.388 +     *
  51.389 +     * @param   proxy the proxy instance to return the invocation handler for
  51.390 +     * @return  the invocation handler for the proxy instance
  51.391 +     * @throws  IllegalArgumentException if the argument is not a
  51.392 +     *          proxy instance
  51.393 +     */
  51.394 +    public static InvocationHandler getInvocationHandler(Object proxy)
  51.395 +        throws IllegalArgumentException
  51.396 +    {
  51.397 +        /*
  51.398 +         * Verify that the object is actually a proxy instance.
  51.399 +         */
  51.400 +        if (!isProxyClass(proxy.getClass())) {
  51.401 +            throw new IllegalArgumentException("not a proxy instance");
  51.402 +        }
  51.403 +
  51.404 +        Proxy p = (Proxy) proxy;
  51.405 +        return p.h;
  51.406 +    }
  51.407 +
  51.408 +    private static native Class defineClass0(ClassLoader loader, String name,
  51.409 +                                             byte[] b, int off, int len);
  51.410 +}
    52.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.2 +++ b/emul/mini/src/main/java/java/lang/reflect/UndeclaredThrowableException.java	Mon Feb 04 09:37:56 2013 +0100
    52.3 @@ -0,0 +1,119 @@
    52.4 +/*
    52.5 + * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved.
    52.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    52.7 + *
    52.8 + * This code is free software; you can redistribute it and/or modify it
    52.9 + * under the terms of the GNU General Public License version 2 only, as
   52.10 + * published by the Free Software Foundation.  Oracle designates this
   52.11 + * particular file as subject to the "Classpath" exception as provided
   52.12 + * by Oracle in the LICENSE file that accompanied this code.
   52.13 + *
   52.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   52.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   52.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   52.17 + * version 2 for more details (a copy is included in the LICENSE file that
   52.18 + * accompanied this code).
   52.19 + *
   52.20 + * You should have received a copy of the GNU General Public License version
   52.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   52.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   52.23 + *
   52.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   52.25 + * or visit www.oracle.com if you need additional information or have any
   52.26 + * questions.
   52.27 + */
   52.28 +
   52.29 +package java.lang.reflect;
   52.30 +
   52.31 +/**
   52.32 + * Thrown by a method invocation on a proxy instance if its invocation
   52.33 + * handler's {@link InvocationHandler#invoke invoke} method throws a
   52.34 + * checked exception (a {@code Throwable} that is not assignable
   52.35 + * to {@code RuntimeException} or {@code Error}) that
   52.36 + * is not assignable to any of the exception types declared in the
   52.37 + * {@code throws} clause of the method that was invoked on the
   52.38 + * proxy instance and dispatched to the invocation handler.
   52.39 + *
   52.40 + * <p>An {@code UndeclaredThrowableException} instance contains
   52.41 + * the undeclared checked exception that was thrown by the invocation
   52.42 + * handler, and it can be retrieved with the
   52.43 + * {@code getUndeclaredThrowable()} method.
   52.44 + * {@code UndeclaredThrowableException} extends
   52.45 + * {@code RuntimeException}, so it is an unchecked exception
   52.46 + * that wraps a checked exception.
   52.47 + *
   52.48 + * <p>As of release 1.4, this exception has been retrofitted to
   52.49 + * conform to the general purpose exception-chaining mechanism.  The
   52.50 + * "undeclared checked exception that was thrown by the invocation
   52.51 + * handler" that may be provided at construction time and accessed via
   52.52 + * the {@link #getUndeclaredThrowable()} method is now known as the
   52.53 + * <i>cause</i>, and may be accessed via the {@link
   52.54 + * Throwable#getCause()} method, as well as the aforementioned "legacy
   52.55 + * method."
   52.56 + *
   52.57 + * @author      Peter Jones
   52.58 + * @see         InvocationHandler
   52.59 + * @since       1.3
   52.60 + */
   52.61 +public class UndeclaredThrowableException extends RuntimeException {
   52.62 +    static final long serialVersionUID = 330127114055056639L;
   52.63 +
   52.64 +    /**
   52.65 +     * the undeclared checked exception that was thrown
   52.66 +     * @serial
   52.67 +     */
   52.68 +    private Throwable undeclaredThrowable;
   52.69 +
   52.70 +    /**
   52.71 +     * Constructs an {@code UndeclaredThrowableException} with the
   52.72 +     * specified {@code Throwable}.
   52.73 +     *
   52.74 +     * @param   undeclaredThrowable the undeclared checked exception
   52.75 +     *          that was thrown
   52.76 +     */
   52.77 +    public UndeclaredThrowableException(Throwable undeclaredThrowable) {
   52.78 +        super((Throwable) null);  // Disallow initCause
   52.79 +        this.undeclaredThrowable = undeclaredThrowable;
   52.80 +    }
   52.81 +
   52.82 +    /**
   52.83 +     * Constructs an {@code UndeclaredThrowableException} with the
   52.84 +     * specified {@code Throwable} and a detail message.
   52.85 +     *
   52.86 +     * @param   undeclaredThrowable the undeclared checked exception
   52.87 +     *          that was thrown
   52.88 +     * @param   s the detail message
   52.89 +     */
   52.90 +    public UndeclaredThrowableException(Throwable undeclaredThrowable,
   52.91 +                                        String s)
   52.92 +    {
   52.93 +        super(s, null);  // Disallow initCause
   52.94 +        this.undeclaredThrowable = undeclaredThrowable;
   52.95 +    }
   52.96 +
   52.97 +    /**
   52.98 +     * Returns the {@code Throwable} instance wrapped in this
   52.99 +     * {@code UndeclaredThrowableException}, which may be {@code null}.
  52.100 +     *
  52.101 +     * <p>This method predates the general-purpose exception chaining facility.
  52.102 +     * The {@link Throwable#getCause()} method is now the preferred means of
  52.103 +     * obtaining this information.
  52.104 +     *
  52.105 +     * @return the undeclared checked exception that was thrown
  52.106 +     */
  52.107 +    public Throwable getUndeclaredThrowable() {
  52.108 +        return undeclaredThrowable;
  52.109 +    }
  52.110 +
  52.111 +    /**
  52.112 +     * Returns the cause of this exception (the {@code Throwable}
  52.113 +     * instance wrapped in this {@code UndeclaredThrowableException},
  52.114 +     * which may be {@code null}).
  52.115 +     *
  52.116 +     * @return  the cause of this exception.
  52.117 +     * @since   1.4
  52.118 +     */
  52.119 +    public Throwable getCause() {
  52.120 +        return undeclaredThrowable;
  52.121 +    }
  52.122 +}
    53.1 --- a/emul/mini/src/main/java/java/net/URL.java	Fri Feb 01 16:34:51 2013 +0100
    53.2 +++ b/emul/mini/src/main/java/java/net/URL.java	Mon Feb 04 09:37:56 2013 +0100
    53.3 @@ -25,6 +25,7 @@
    53.4  
    53.5  package java.net;
    53.6  
    53.7 +import java.io.ByteArrayInputStream;
    53.8  import java.io.IOException;
    53.9  import java.io.InputStream;
   53.10  import org.apidesign.bck2brwsr.core.JavaScriptBody;
   53.11 @@ -505,6 +506,17 @@
   53.12      public URL(URL context, String spec, URLStreamHandler handler)
   53.13          throws MalformedURLException
   53.14      {
   53.15 +        this(findContext(context), spec, handler != null);
   53.16 +    }
   53.17 +    
   53.18 +    private URL(URL context, String spec, boolean ishandler)
   53.19 +    throws MalformedURLException {
   53.20 +        // Check for permission to specify a handler
   53.21 +        if (ishandler) {
   53.22 +            throw new SecurityException();
   53.23 +        }
   53.24 +        URLStreamHandler handler = null;
   53.25 +        
   53.26          String original = spec;
   53.27          int i, limit, c;
   53.28          int start = 0;
   53.29 @@ -512,10 +524,6 @@
   53.30          boolean aRef=false;
   53.31          boolean isRelative = false;
   53.32  
   53.33 -        // Check for permission to specify a handler
   53.34 -        if (handler != null) {
   53.35 -            throw new SecurityException();
   53.36 -        }
   53.37  
   53.38          try {
   53.39              limit = spec.length();
   53.40 @@ -962,7 +970,11 @@
   53.41          if (is != null) {
   53.42              return is;
   53.43          }
   53.44 -        throw new IOException();
   53.45 +        byte[] arr = (byte[]) getContent(new Class[] { byte[].class });
   53.46 +        if (arr == null) {
   53.47 +            throw new IOException();
   53.48 +        }
   53.49 +        return new ByteArrayInputStream(arr);
   53.50      }
   53.51  
   53.52      /**
   53.53 @@ -987,6 +999,17 @@
   53.54      )
   53.55      private static native String loadText(String url) throws IOException;
   53.56  
   53.57 +    @JavaScriptBody(args = { "url", "arr" }, body = ""
   53.58 +        + "var request = new XMLHttpRequest();\n"
   53.59 +        + "request.open('GET', url, false);\n"
   53.60 +        + "request.overrideMimeType('text\\/plain; charset=x-user-defined');\n"
   53.61 +        + "request.send();\n"
   53.62 +        + "var t = request.responseText;\n"
   53.63 +        + "for (var i = 0; i < t.length; i++) arr.push(t.charCodeAt(i) & 0xff);\n"
   53.64 +        + "return arr;\n"
   53.65 +    )
   53.66 +    private static native Object loadBytes(String url, byte[] arr) throws IOException;
   53.67 +
   53.68      /**
   53.69       * Gets the contents of this URL. This method is a shorthand for:
   53.70       * <blockquote><pre>
   53.71 @@ -1005,7 +1028,10 @@
   53.72      throws java.io.IOException {
   53.73          for (Class<?> c : classes) {
   53.74              if (c == String.class) {
   53.75 -                return getContent();
   53.76 +                return loadText(toExternalForm());
   53.77 +            }
   53.78 +            if (c == byte[].class) {
   53.79 +                return loadBytes(toExternalForm(), new byte[0]);
   53.80              }
   53.81          }
   53.82          return null;
   53.83 @@ -1016,6 +1042,23 @@
   53.84          return universal;
   53.85      }
   53.86  
   53.87 +    private static URL findContext(URL context) throws MalformedURLException {
   53.88 +        if (context == null) {
   53.89 +            String base = findBaseURL();
   53.90 +            if (base != null) {
   53.91 +                context = new URL(null, base, false);
   53.92 +            }
   53.93 +        }
   53.94 +        return context;
   53.95 +    }
   53.96 +    
   53.97 +    @JavaScriptBody(args = {}, body = 
   53.98 +          "if (typeof window !== 'object') return null;\n"
   53.99 +        + "if (!window.location) return null;\n"
  53.100 +        + "if (!window.location.href) return null;\n"
  53.101 +        + "return window.location.href;\n"
  53.102 +    )
  53.103 +    private static native String findBaseURL();
  53.104  }
  53.105  class Parts {
  53.106      String path, query, ref;
    54.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.2 +++ b/emul/mini/src/main/java/java/util/zip/Adler32.java	Mon Feb 04 09:37:56 2013 +0100
    54.3 @@ -0,0 +1,205 @@
    54.4 +/* Adler32.java - Computes Adler32 data checksum of a data stream
    54.5 +   Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
    54.6 +
    54.7 +This file is part of GNU Classpath.
    54.8 +
    54.9 +GNU Classpath is free software; you can redistribute it and/or modify
   54.10 +it under the terms of the GNU General Public License as published by
   54.11 +the Free Software Foundation; either version 2, or (at your option)
   54.12 +any later version.
   54.13 +
   54.14 +GNU Classpath is distributed in the hope that it will be useful, but
   54.15 +WITHOUT ANY WARRANTY; without even the implied warranty of
   54.16 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   54.17 +General Public License for more details.
   54.18 +
   54.19 +You should have received a copy of the GNU General Public License
   54.20 +along with GNU Classpath; see the file COPYING.  If not, write to the
   54.21 +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   54.22 +02111-1307 USA.
   54.23 +
   54.24 +Linking this library statically or dynamically with other modules is
   54.25 +making a combined work based on this library.  Thus, the terms and
   54.26 +conditions of the GNU General Public License cover the whole
   54.27 +combination.
   54.28 +
   54.29 +As a special exception, the copyright holders of this library give you
   54.30 +permission to link this library with independent modules to produce an
   54.31 +executable, regardless of the license terms of these independent
   54.32 +modules, and to copy and distribute the resulting executable under
   54.33 +terms of your choice, provided that you also meet, for each linked
   54.34 +independent module, the terms and conditions of the license of that
   54.35 +module.  An independent module is a module which is not derived from
   54.36 +or based on this library.  If you modify this library, you may extend
   54.37 +this exception to your version of the library, but you are not
   54.38 +obligated to do so.  If you do not wish to do so, delete this
   54.39 +exception statement from your version. */
   54.40 +
   54.41 +package java.util.zip;
   54.42 +
   54.43 +/*
   54.44 + * Written using on-line Java Platform 1.2 API Specification, as well
   54.45 + * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
   54.46 + * The actual Adler32 algorithm is taken from RFC 1950.
   54.47 + * Status:  Believed complete and correct.
   54.48 + */
   54.49 +
   54.50 +/**
   54.51 + * Computes Adler32 checksum for a stream of data. An Adler32 
   54.52 + * checksum is not as reliable as a CRC32 checksum, but a lot faster to 
   54.53 + * compute.
   54.54 + *<p>
   54.55 + * The specification for Adler32 may be found in RFC 1950.
   54.56 + * (ZLIB Compressed Data Format Specification version 3.3)
   54.57 + *<p>
   54.58 + *<p>
   54.59 + * From that document:
   54.60 + *<p>
   54.61 + *      "ADLER32 (Adler-32 checksum)
   54.62 + *       This contains a checksum value of the uncompressed data
   54.63 + *       (excluding any dictionary data) computed according to Adler-32
   54.64 + *       algorithm. This algorithm is a 32-bit extension and improvement
   54.65 + *       of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073
   54.66 + *       standard. 
   54.67 + *<p>
   54.68 + *       Adler-32 is composed of two sums accumulated per byte: s1 is
   54.69 + *       the sum of all bytes, s2 is the sum of all s1 values. Both sums
   54.70 + *       are done modulo 65521. s1 is initialized to 1, s2 to zero.  The
   54.71 + *       Adler-32 checksum is stored as s2*65536 + s1 in most-
   54.72 + *       significant-byte first (network) order."
   54.73 + *<p>
   54.74 + * "8.2. The Adler-32 algorithm
   54.75 + *<p>
   54.76 + *    The Adler-32 algorithm is much faster than the CRC32 algorithm yet
   54.77 + *    still provides an extremely low probability of undetected errors.
   54.78 + *<p>
   54.79 + *    The modulo on unsigned long accumulators can be delayed for 5552
   54.80 + *    bytes, so the modulo operation time is negligible.  If the bytes
   54.81 + *    are a, b, c, the second sum is 3a + 2b + c + 3, and so is position
   54.82 + *    and order sensitive, unlike the first sum, which is just a
   54.83 + *    checksum.  That 65521 is prime is important to avoid a possible
   54.84 + *    large class of two-byte errors that leave the check unchanged.
   54.85 + *    (The Fletcher checksum uses 255, which is not prime and which also
   54.86 + *    makes the Fletcher check insensitive to single byte changes 0 <->
   54.87 + *    255.)
   54.88 + *<p>
   54.89 + *    The sum s1 is initialized to 1 instead of zero to make the length
   54.90 + *    of the sequence part of s2, so that the length does not have to be
   54.91 + *   checked separately. (Any sequence of zeroes has a Fletcher
   54.92 + *    checksum of zero.)"
   54.93 + *
   54.94 + * @author John Leuner, Per Bothner
   54.95 + * @since JDK 1.1
   54.96 + *
   54.97 + * @see InflaterInputStream
   54.98 + * @see DeflaterOutputStream
   54.99 + */
  54.100 +public class Adler32 implements Checksum
  54.101 +{
  54.102 +
  54.103 +  /** largest prime smaller than 65536 */
  54.104 +  private static final int BASE = 65521;
  54.105 +
  54.106 +  private int checksum; //we do all in int.
  54.107 +
  54.108 +  //Note that java doesn't have unsigned integers,
  54.109 +  //so we have to be careful with what arithmetic 
  54.110 +  //we do. We return the checksum as a long to 
  54.111 +  //avoid sign confusion.
  54.112 +
  54.113 +  /**
  54.114 +   * Creates a new instance of the <code>Adler32</code> class. 
  54.115 +   * The checksum starts off with a value of 1. 
  54.116 +   */
  54.117 +  public Adler32 ()
  54.118 +  {
  54.119 +    reset();
  54.120 +  }
  54.121 +
  54.122 +  /**
  54.123 +   * Resets the Adler32 checksum to the initial value.
  54.124 +   */
  54.125 +  public void reset () 
  54.126 +  {
  54.127 +    checksum = 1; //Initialize to 1    
  54.128 +  }
  54.129 +
  54.130 +  /**
  54.131 +   * Updates the checksum with the byte b. 
  54.132 +   *
  54.133 +   * @param bval the data value to add. The high byte of the int is ignored.
  54.134 +   */
  54.135 +  public void update (int bval)
  54.136 +  {
  54.137 +    //We could make a length 1 byte array and call update again, but I
  54.138 +    //would rather not have that overhead
  54.139 +    int s1 = checksum & 0xffff;
  54.140 +    int s2 = checksum >>> 16;
  54.141 +    
  54.142 +    s1 = (s1 + (bval & 0xFF)) % BASE;
  54.143 +    s2 = (s1 + s2) % BASE;
  54.144 +    
  54.145 +    checksum = (s2 << 16) + s1;
  54.146 +  }
  54.147 +
  54.148 +  /**
  54.149 +   * Updates the checksum with the bytes taken from the array. 
  54.150 +   * 
  54.151 +   * @param buffer an array of bytes
  54.152 +   */
  54.153 +  public void update (byte[] buffer)
  54.154 +  {
  54.155 +    update(buffer, 0, buffer.length);
  54.156 +  }
  54.157 +
  54.158 +  /**
  54.159 +   * Updates the checksum with the bytes taken from the array. 
  54.160 +   * 
  54.161 +   * @param buf an array of bytes
  54.162 +   * @param off the start of the data used for this update
  54.163 +   * @param len the number of bytes to use for this update
  54.164 +   */
  54.165 +  public void update (byte[] buf, int off, int len)
  54.166 +  {
  54.167 +    //(By Per Bothner)
  54.168 +    int s1 = checksum & 0xffff;
  54.169 +    int s2 = checksum >>> 16;
  54.170 +
  54.171 +    while (len > 0)
  54.172 +      {
  54.173 +	// We can defer the modulo operation:
  54.174 +	// s1 maximally grows from 65521 to 65521 + 255 * 3800
  54.175 +	// s2 maximally grows by 3800 * median(s1) = 2090079800 < 2^31
  54.176 +	int n = 3800;
  54.177 +	if (n > len)
  54.178 +	  n = len;
  54.179 +	len -= n;
  54.180 +	while (--n >= 0)
  54.181 +	  {
  54.182 +	    s1 = s1 + (buf[off++] & 0xFF);
  54.183 +	    s2 = s2 + s1;
  54.184 +	  }
  54.185 +	s1 %= BASE;
  54.186 +	s2 %= BASE;
  54.187 +      }
  54.188 +
  54.189 +    /*Old implementation, borrowed from somewhere:
  54.190 +    int n;
  54.191 +    
  54.192 +    while (len-- > 0) {
  54.193 +
  54.194 +      s1 = (s1 + (bs[offset++] & 0xff)) % BASE; 
  54.195 +      s2 = (s2 + s1) % BASE;
  54.196 +    }*/
  54.197 +    
  54.198 +    checksum = (s2 << 16) | s1;
  54.199 +  }
  54.200 +
  54.201 +  /**
  54.202 +   * Returns the Adler32 data checksum computed so far.
  54.203 +   */
  54.204 +  public long getValue()
  54.205 +  {
  54.206 +    return (long) checksum & 0xffffffffL;
  54.207 +  }
  54.208 +}
    55.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.2 +++ b/emul/mini/src/main/java/java/util/zip/CRC32.java	Mon Feb 04 09:37:56 2013 +0100
    55.3 @@ -0,0 +1,132 @@
    55.4 +/* CRC32.java - Computes CRC32 data checksum of a data stream
    55.5 +   Copyright (C) 1999. 2000, 2001 Free Software Foundation, Inc.
    55.6 +
    55.7 +This file is part of GNU Classpath.
    55.8 +
    55.9 +GNU Classpath is free software; you can redistribute it and/or modify
   55.10 +it under the terms of the GNU General Public License as published by
   55.11 +the Free Software Foundation; either version 2, or (at your option)
   55.12 +any later version.
   55.13 +
   55.14 +GNU Classpath is distributed in the hope that it will be useful, but
   55.15 +WITHOUT ANY WARRANTY; without even the implied warranty of
   55.16 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   55.17 +General Public License for more details.
   55.18 +
   55.19 +You should have received a copy of the GNU General Public License
   55.20 +along with GNU Classpath; see the file COPYING.  If not, write to the
   55.21 +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   55.22 +02111-1307 USA.
   55.23 +
   55.24 +Linking this library statically or dynamically with other modules is
   55.25 +making a combined work based on this library.  Thus, the terms and
   55.26 +conditions of the GNU General Public License cover the whole
   55.27 +combination.
   55.28 +
   55.29 +As a special exception, the copyright holders of this library give you
   55.30 +permission to link this library with independent modules to produce an
   55.31 +executable, regardless of the license terms of these independent
   55.32 +modules, and to copy and distribute the resulting executable under
   55.33 +terms of your choice, provided that you also meet, for each linked
   55.34 +independent module, the terms and conditions of the license of that
   55.35 +module.  An independent module is a module which is not derived from
   55.36 +or based on this library.  If you modify this library, you may extend
   55.37 +this exception to your version of the library, but you are not
   55.38 +obligated to do so.  If you do not wish to do so, delete this
   55.39 +exception statement from your version. */
   55.40 +
   55.41 +package java.util.zip;
   55.42 +
   55.43 +/*
   55.44 + * Written using on-line Java Platform 1.2 API Specification, as well
   55.45 + * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
   55.46 + * The actual CRC32 algorithm is taken from RFC 1952.
   55.47 + * Status:  Believed complete and correct.
   55.48 + */
   55.49 +
   55.50 +/**
   55.51 + * Computes CRC32 data checksum of a data stream.
   55.52 + * The actual CRC32 algorithm is described in RFC 1952
   55.53 + * (GZIP file format specification version 4.3).
   55.54 + * Can be used to get the CRC32 over a stream if used with checked input/output
   55.55 + * streams.
   55.56 + *
   55.57 + * @see InflaterInputStream
   55.58 + * @see DeflaterOutputStream
   55.59 + *
   55.60 + * @author Per Bothner
   55.61 + * @date April 1, 1999.
   55.62 + */
   55.63 +public class CRC32 implements Checksum
   55.64 +{
   55.65 +  /** The crc data checksum so far. */
   55.66 +  private int crc = 0;
   55.67 +
   55.68 +  /** The fast CRC table. Computed once when the CRC32 class is loaded. */
   55.69 +  private static int[] crc_table = make_crc_table();
   55.70 +
   55.71 +  /** Make the table for a fast CRC. */
   55.72 +  private static int[] make_crc_table ()
   55.73 +  {
   55.74 +    int[] crc_table = new int[256];
   55.75 +    for (int n = 0; n < 256; n++)
   55.76 +      {
   55.77 +	int c = n;
   55.78 +	for (int k = 8;  --k >= 0; )
   55.79 +	  {
   55.80 +	    if ((c & 1) != 0)
   55.81 +	      c = 0xedb88320 ^ (c >>> 1);
   55.82 +	    else
   55.83 +	      c = c >>> 1;
   55.84 +	  }
   55.85 +	crc_table[n] = c;
   55.86 +      }
   55.87 +    return crc_table;
   55.88 +  }
   55.89 +
   55.90 +  /**
   55.91 +   * Returns the CRC32 data checksum computed so far.
   55.92 +   */
   55.93 +  public long getValue ()
   55.94 +  {
   55.95 +    return (long) crc & 0xffffffffL;
   55.96 +  }
   55.97 +
   55.98 +  /**
   55.99 +   * Resets the CRC32 data checksum as if no update was ever called.
  55.100 +   */
  55.101 +  public void reset () { crc = 0; }
  55.102 +
  55.103 +  /**
  55.104 +   * Updates the checksum with the int bval. 
  55.105 +   *
  55.106 +   * @param bval (the byte is taken as the lower 8 bits of bval)
  55.107 +   */
  55.108 +
  55.109 +  public void update (int bval)
  55.110 +  {
  55.111 +    int c = ~crc;
  55.112 +    c = crc_table[(c ^ bval) & 0xff] ^ (c >>> 8);
  55.113 +    crc = ~c;
  55.114 +  }
  55.115 +
  55.116 +  /**
  55.117 +   * Adds the byte array to the data checksum.
  55.118 +   *
  55.119 +   * @param buf the buffer which contains the data
  55.120 +   * @param off the offset in the buffer where the data starts
  55.121 +   * @param len the length of the data
  55.122 +   */
  55.123 +  public void update (byte[] buf, int off, int len)
  55.124 +  {
  55.125 +    int c = ~crc;
  55.126 +    while (--len >= 0)
  55.127 +      c = crc_table[(c ^ buf[off++]) & 0xff] ^ (c >>> 8);
  55.128 +    crc = ~c;
  55.129 +  }
  55.130 +
  55.131 +  /**
  55.132 +   * Adds the complete byte array to the data checksum.
  55.133 +   */
  55.134 +  public void update (byte[] buf) { update(buf, 0, buf.length); }
  55.135 +}
    56.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    56.2 +++ b/emul/mini/src/main/java/java/util/zip/Checksum.java	Mon Feb 04 09:37:56 2013 +0100
    56.3 @@ -0,0 +1,60 @@
    56.4 +/*
    56.5 + * Copyright (c) 1996, 1999, Oracle and/or its affiliates. All rights reserved.
    56.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    56.7 + *
    56.8 + * This code is free software; you can redistribute it and/or modify it
    56.9 + * under the terms of the GNU General Public License version 2 only, as
   56.10 + * published by the Free Software Foundation.  Oracle designates this
   56.11 + * particular file as subject to the "Classpath" exception as provided
   56.12 + * by Oracle in the LICENSE file that accompanied this code.
   56.13 + *
   56.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   56.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   56.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   56.17 + * version 2 for more details (a copy is included in the LICENSE file that
   56.18 + * accompanied this code).
   56.19 + *
   56.20 + * You should have received a copy of the GNU General Public License version
   56.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   56.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   56.23 + *
   56.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   56.25 + * or visit www.oracle.com if you need additional information or have any
   56.26 + * questions.
   56.27 + */
   56.28 +
   56.29 +package java.util.zip;
   56.30 +
   56.31 +/**
   56.32 + * An interface representing a data checksum.
   56.33 + *
   56.34 + * @author      David Connelly
   56.35 + */
   56.36 +public
   56.37 +interface Checksum {
   56.38 +    /**
   56.39 +     * Updates the current checksum with the specified byte.
   56.40 +     *
   56.41 +     * @param b the byte to update the checksum with
   56.42 +     */
   56.43 +    public void update(int b);
   56.44 +
   56.45 +    /**
   56.46 +     * Updates the current checksum with the specified array of bytes.
   56.47 +     * @param b the byte array to update the checksum with
   56.48 +     * @param off the start offset of the data
   56.49 +     * @param len the number of bytes to use for the update
   56.50 +     */
   56.51 +    public void update(byte[] b, int off, int len);
   56.52 +
   56.53 +    /**
   56.54 +     * Returns the current checksum value.
   56.55 +     * @return the current checksum value
   56.56 +     */
   56.57 +    public long getValue();
   56.58 +
   56.59 +    /**
   56.60 +     * Resets the checksum to its initial value.
   56.61 +     */
   56.62 +    public void reset();
   56.63 +}
    57.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.2 +++ b/emul/mini/src/main/java/java/util/zip/DataFormatException.java	Mon Feb 04 09:37:56 2013 +0100
    57.3 @@ -0,0 +1,52 @@
    57.4 +/*
    57.5 + * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
    57.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    57.7 + *
    57.8 + * This code is free software; you can redistribute it and/or modify it
    57.9 + * under the terms of the GNU General Public License version 2 only, as
   57.10 + * published by the Free Software Foundation.  Oracle designates this
   57.11 + * particular file as subject to the "Classpath" exception as provided
   57.12 + * by Oracle in the LICENSE file that accompanied this code.
   57.13 + *
   57.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   57.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   57.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   57.17 + * version 2 for more details (a copy is included in the LICENSE file that
   57.18 + * accompanied this code).
   57.19 + *
   57.20 + * You should have received a copy of the GNU General Public License version
   57.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   57.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   57.23 + *
   57.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   57.25 + * or visit www.oracle.com if you need additional information or have any
   57.26 + * questions.
   57.27 + */
   57.28 +
   57.29 +package java.util.zip;
   57.30 +
   57.31 +/**
   57.32 + * Signals that a data format error has occurred.
   57.33 + *
   57.34 + * @author      David Connelly
   57.35 + */
   57.36 +public
   57.37 +class DataFormatException extends Exception {
   57.38 +    private static final long serialVersionUID = 2219632870893641452L;
   57.39 +
   57.40 +    /**
   57.41 +     * Constructs a DataFormatException with no detail message.
   57.42 +     */
   57.43 +    public DataFormatException() {
   57.44 +        super();
   57.45 +    }
   57.46 +
   57.47 +    /**
   57.48 +     * Constructs a DataFormatException with the specified detail message.
   57.49 +     * A detail message is a String that describes this particular exception.
   57.50 +     * @param s the String containing a detail message
   57.51 +     */
   57.52 +    public DataFormatException(String s) {
   57.53 +        super(s);
   57.54 +    }
   57.55 +}
    58.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.2 +++ b/emul/mini/src/main/java/java/util/zip/Inflater.java	Mon Feb 04 09:37:56 2013 +0100
    58.3 @@ -0,0 +1,1475 @@
    58.4 +/* Inflater.java - Decompress a data stream
    58.5 +   Copyright (C) 1999, 2000, 2001, 2003  Free Software Foundation, Inc.
    58.6 +
    58.7 +This file is part of GNU Classpath.
    58.8 +
    58.9 +GNU Classpath is free software; you can redistribute it and/or modify
   58.10 +it under the terms of the GNU General Public License as published by
   58.11 +the Free Software Foundation; either version 2, or (at your option)
   58.12 +any later version.
   58.13 + 
   58.14 +GNU Classpath is distributed in the hope that it will be useful, but
   58.15 +WITHOUT ANY WARRANTY; without even the implied warranty of
   58.16 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   58.17 +General Public License for more details.
   58.18 +
   58.19 +You should have received a copy of the GNU General Public License
   58.20 +along with GNU Classpath; see the file COPYING.  If not, write to the
   58.21 +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   58.22 +02111-1307 USA.
   58.23 +
   58.24 +Linking this library statically or dynamically with other modules is
   58.25 +making a combined work based on this library.  Thus, the terms and
   58.26 +conditions of the GNU General Public License cover the whole
   58.27 +combination.
   58.28 +
   58.29 +As a special exception, the copyright holders of this library give you
   58.30 +permission to link this library with independent modules to produce an
   58.31 +executable, regardless of the license terms of these independent
   58.32 +modules, and to copy and distribute the resulting executable under
   58.33 +terms of your choice, provided that you also meet, for each linked
   58.34 +independent module, the terms and conditions of the license of that
   58.35 +module.  An independent module is a module which is not derived from
   58.36 +or based on this library.  If you modify this library, you may extend
   58.37 +this exception to your version of the library, but you are not
   58.38 +obligated to do so.  If you do not wish to do so, delete this
   58.39 +exception statement from your version. */
   58.40 +
   58.41 +package java.util.zip;
   58.42 +
   58.43 +import org.apidesign.bck2brwsr.emul.lang.System;
   58.44 +
   58.45 +/**
   58.46 + * This class provides support for general purpose decompression using the
   58.47 + * popular ZLIB compression library. The ZLIB compression library was
   58.48 + * initially developed as part of the PNG graphics standard and is not
   58.49 + * protected by patents. It is fully described in the specifications at
   58.50 + * the <a href="package-summary.html#package_description">java.util.zip
   58.51 + * package description</a>.
   58.52 + *
   58.53 + * <p>The following code fragment demonstrates a trivial compression
   58.54 + * and decompression of a string using <tt>Deflater</tt> and
   58.55 + * <tt>Inflater</tt>.
   58.56 + *
   58.57 + * <blockquote><pre>
   58.58 + * try {
   58.59 + *     // Encode a String into bytes
   58.60 + *     String inputString = "blahblahblah\u20AC\u20AC";
   58.61 + *     byte[] input = inputString.getBytes("UTF-8");
   58.62 + *
   58.63 + *     // Compress the bytes
   58.64 + *     byte[] output = new byte[100];
   58.65 + *     Deflater compresser = new Deflater();
   58.66 + *     compresser.setInput(input);
   58.67 + *     compresser.finish();
   58.68 + *     int compressedDataLength = compresser.deflate(output);
   58.69 + *
   58.70 + *     // Decompress the bytes
   58.71 + *     Inflater decompresser = new Inflater();
   58.72 + *     decompresser.setInput(output, 0, compressedDataLength);
   58.73 + *     byte[] result = new byte[100];
   58.74 + *     int resultLength = decompresser.inflate(result);
   58.75 + *     decompresser.end();
   58.76 + *
   58.77 + *     // Decode the bytes into a String
   58.78 + *     String outputString = new String(result, 0, resultLength, "UTF-8");
   58.79 + * } catch(java.io.UnsupportedEncodingException ex) {
   58.80 + *     // handle
   58.81 + * } catch (java.util.zip.DataFormatException ex) {
   58.82 + *     // handle
   58.83 + * }
   58.84 + * </pre></blockquote>
   58.85 + *
   58.86 + * @see         Deflater
   58.87 + * @author      David Connelly
   58.88 + *
   58.89 + */
   58.90 +
   58.91 +/* Written using on-line Java Platform 1.2 API Specification
   58.92 + * and JCL book.
   58.93 + * Believed complete and correct.
   58.94 + */
   58.95 +
   58.96 +/**
   58.97 + * Inflater is used to decompress data that has been compressed according 
   58.98 + * to the "deflate" standard described in rfc1950.
   58.99 + *
  58.100 + * The usage is as following.  First you have to set some input with
  58.101 + * <code>setInput()</code>, then inflate() it.  If inflate doesn't
  58.102 + * inflate any bytes there may be three reasons:
  58.103 + * <ul>
  58.104 + * <li>needsInput() returns true because the input buffer is empty.
  58.105 + * You have to provide more input with <code>setInput()</code>.  
  58.106 + * NOTE: needsInput() also returns true when, the stream is finished.
  58.107 + * </li>
  58.108 + * <li>needsDictionary() returns true, you have to provide a preset 
  58.109 + *     dictionary with <code>setDictionary()</code>.</li>
  58.110 + * <li>finished() returns true, the inflater has finished.</li>
  58.111 + * </ul>
  58.112 + * Once the first output byte is produced, a dictionary will not be
  58.113 + * needed at a later stage.
  58.114 + *
  58.115 + * @author John Leuner, Jochen Hoenicke
  58.116 + * @author Tom Tromey
  58.117 + * @date May 17, 1999
  58.118 + * @since JDK 1.1
  58.119 + */
  58.120 +public class Inflater
  58.121 +{
  58.122 +  /* Copy lengths for literal codes 257..285 */
  58.123 +  private static final int CPLENS[] = 
  58.124 +  { 
  58.125 +    3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
  58.126 +    35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
  58.127 +  };
  58.128 +  
  58.129 +  /* Extra bits for literal codes 257..285 */  
  58.130 +  private static final int CPLEXT[] = 
  58.131 +  { 
  58.132 +    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
  58.133 +    3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
  58.134 +  };
  58.135 +
  58.136 +  /* Copy offsets for distance codes 0..29 */
  58.137 +  private static final int CPDIST[] = {
  58.138 +    1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
  58.139 +    257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
  58.140 +    8193, 12289, 16385, 24577
  58.141 +  };
  58.142 +  
  58.143 +  /* Extra bits for distance codes */
  58.144 +  private static final int CPDEXT[] = {
  58.145 +    0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
  58.146 +    7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 
  58.147 +    12, 12, 13, 13
  58.148 +  };
  58.149 +
  58.150 +  /* This are the state in which the inflater can be.  */
  58.151 +  private static final int DECODE_HEADER           = 0;
  58.152 +  private static final int DECODE_DICT             = 1;
  58.153 +  private static final int DECODE_BLOCKS           = 2;
  58.154 +  private static final int DECODE_STORED_LEN1      = 3;
  58.155 +  private static final int DECODE_STORED_LEN2      = 4;
  58.156 +  private static final int DECODE_STORED           = 5;
  58.157 +  private static final int DECODE_DYN_HEADER       = 6;
  58.158 +  private static final int DECODE_HUFFMAN          = 7;
  58.159 +  private static final int DECODE_HUFFMAN_LENBITS  = 8;
  58.160 +  private static final int DECODE_HUFFMAN_DIST     = 9;
  58.161 +  private static final int DECODE_HUFFMAN_DISTBITS = 10;
  58.162 +  private static final int DECODE_CHKSUM           = 11;
  58.163 +  private static final int FINISHED                = 12;
  58.164 +
  58.165 +  /** This variable contains the current state. */
  58.166 +  private int mode;
  58.167 +
  58.168 +  /**
  58.169 +   * The adler checksum of the dictionary or of the decompressed
  58.170 +   * stream, as it is written in the header resp. footer of the
  58.171 +   * compressed stream.  <br>
  58.172 +   *
  58.173 +   * Only valid if mode is DECODE_DICT or DECODE_CHKSUM.
  58.174 +   */
  58.175 +  private int readAdler;
  58.176 +  /** 
  58.177 +   * The number of bits needed to complete the current state.  This
  58.178 +   * is valid, if mode is DECODE_DICT, DECODE_CHKSUM,
  58.179 +   * DECODE_HUFFMAN_LENBITS or DECODE_HUFFMAN_DISTBITS.  
  58.180 +   */
  58.181 +  private int neededBits;
  58.182 +  private int repLength, repDist;
  58.183 +  private int uncomprLen;
  58.184 +  /**
  58.185 +   * True, if the last block flag was set in the last block of the
  58.186 +   * inflated stream.  This means that the stream ends after the
  58.187 +   * current block.  
  58.188 +   */
  58.189 +  private boolean isLastBlock;
  58.190 +
  58.191 +  /**
  58.192 +   * The total number of inflated bytes.
  58.193 +   */
  58.194 +  private long totalOut;
  58.195 +  /**
  58.196 +   * The total number of bytes set with setInput().  This is not the
  58.197 +   * value returned by getTotalIn(), since this also includes the 
  58.198 +   * unprocessed input.
  58.199 +   */
  58.200 +  private long totalIn;
  58.201 +  /**
  58.202 +   * This variable stores the nowrap flag that was given to the constructor.
  58.203 +   * True means, that the inflated stream doesn't contain a header nor the
  58.204 +   * checksum in the footer.
  58.205 +   */
  58.206 +  private boolean nowrap;
  58.207 +
  58.208 +  private StreamManipulator input;
  58.209 +  private OutputWindow outputWindow;
  58.210 +  private InflaterDynHeader dynHeader;
  58.211 +  private InflaterHuffmanTree litlenTree, distTree;
  58.212 +  private Adler32 adler;
  58.213 +
  58.214 +  /**
  58.215 +   * Creates a new inflater.
  58.216 +   */
  58.217 +  public Inflater ()
  58.218 +  {
  58.219 +    this (false);
  58.220 +  }
  58.221 +
  58.222 +  /**
  58.223 +   * Creates a new inflater.
  58.224 +   * @param nowrap true if no header and checksum field appears in the
  58.225 +   * stream.  This is used for GZIPed input.  For compatibility with
  58.226 +   * Sun JDK you should provide one byte of input more than needed in
  58.227 +   * this case.
  58.228 +   */
  58.229 +  public Inflater (boolean nowrap)
  58.230 +  {
  58.231 +    this.nowrap = nowrap;
  58.232 +    this.adler = new Adler32();
  58.233 +    input = new StreamManipulator();
  58.234 +    outputWindow = new OutputWindow();
  58.235 +    mode = nowrap ? DECODE_BLOCKS : DECODE_HEADER;
  58.236 +  }
  58.237 +
  58.238 +  /**
  58.239 +   * Finalizes this object.
  58.240 +   */
  58.241 +  protected void finalize ()
  58.242 +  {
  58.243 +    /* Exists only for compatibility */
  58.244 +  }
  58.245 +
  58.246 +  /**
  58.247 +   * Frees all objects allocated by the inflater.  There's no reason
  58.248 +   * to call this, since you can just rely on garbage collection (even
  58.249 +   * for the Sun implementation).  Exists only for compatibility
  58.250 +   * with Sun's JDK, where the compressor allocates native memory.
  58.251 +   * If you call any method (even reset) afterwards the behaviour is
  58.252 +   * <i>undefined</i>.  
  58.253 +   * @deprecated Just clear all references to inflater instead.
  58.254 +   */
  58.255 +  public void end ()
  58.256 +  {
  58.257 +    outputWindow = null;
  58.258 +    input = null;
  58.259 +    dynHeader = null;
  58.260 +    litlenTree = null;
  58.261 +    distTree = null;
  58.262 +    adler = null;
  58.263 +  }
  58.264 +
  58.265 +  /**
  58.266 +   * Returns true, if the inflater has finished.  This means, that no
  58.267 +   * input is needed and no output can be produced.
  58.268 +   */
  58.269 +  public boolean finished() 
  58.270 +  {
  58.271 +    return mode == FINISHED && outputWindow.getAvailable() == 0;
  58.272 +  }
  58.273 +
  58.274 +  /**
  58.275 +   * Gets the adler checksum.  This is either the checksum of all
  58.276 +   * uncompressed bytes returned by inflate(), or if needsDictionary()
  58.277 +   * returns true (and thus no output was yet produced) this is the
  58.278 +   * adler checksum of the expected dictionary.
  58.279 +   * @returns the adler checksum.
  58.280 +   */
  58.281 +  public int getAdler()
  58.282 +  {
  58.283 +    return needsDictionary() ? readAdler : (int) adler.getValue();
  58.284 +  }
  58.285 +  
  58.286 +  /**
  58.287 +   * Gets the number of unprocessed input.  Useful, if the end of the
  58.288 +   * stream is reached and you want to further process the bytes after
  58.289 +   * the deflate stream.  
  58.290 +   * @return the number of bytes of the input which were not processed.
  58.291 +   */
  58.292 +  public int getRemaining()
  58.293 +  {
  58.294 +    return input.getAvailableBytes();
  58.295 +  }
  58.296 +  
  58.297 +  /**
  58.298 +   * Gets the total number of processed compressed input bytes.
  58.299 +   * @return the total number of bytes of processed input bytes.
  58.300 +   */
  58.301 +  public int getTotalIn()
  58.302 +  {
  58.303 +    return (int)getBytesRead();
  58.304 +  }
  58.305 +  
  58.306 +  /**
  58.307 +   * Gets the total number of output bytes returned by inflate().
  58.308 +   * @return the total number of output bytes.
  58.309 +   */
  58.310 +  public int getTotalOut()
  58.311 +  {
  58.312 +    return (int)totalOut;
  58.313 +  }
  58.314 +  
  58.315 +  public long getBytesWritten() {
  58.316 +     return totalOut;
  58.317 +  }
  58.318 +
  58.319 +  public long getBytesRead() {
  58.320 +    return totalIn - getRemaining();
  58.321 +  }
  58.322 +  
  58.323 +
  58.324 +  /**
  58.325 +   * Inflates the compressed stream to the output buffer.  If this
  58.326 +   * returns 0, you should check, whether needsDictionary(),
  58.327 +   * needsInput() or finished() returns true, to determine why no 
  58.328 +   * further output is produced.
  58.329 +   * @param buffer the output buffer.
  58.330 +   * @return the number of bytes written to the buffer, 0 if no further
  58.331 +   * output can be produced.  
  58.332 +   * @exception DataFormatException if deflated stream is invalid.
  58.333 +   * @exception IllegalArgumentException if buf has length 0.
  58.334 +   */
  58.335 +  public int inflate (byte[] buf) throws DataFormatException
  58.336 +  {
  58.337 +    return inflate (buf, 0, buf.length);
  58.338 +  }
  58.339 +
  58.340 +  /**
  58.341 +   * Inflates the compressed stream to the output buffer.  If this
  58.342 +   * returns 0, you should check, whether needsDictionary(),
  58.343 +   * needsInput() or finished() returns true, to determine why no 
  58.344 +   * further output is produced.
  58.345 +   * @param buffer the output buffer.
  58.346 +   * @param off the offset into buffer where the output should start.
  58.347 +   * @param len the maximum length of the output.
  58.348 +   * @return the number of bytes written to the buffer, 0 if no further
  58.349 +   * output can be produced.  
  58.350 +   * @exception DataFormatException if deflated stream is invalid.
  58.351 +   * @exception IndexOutOfBoundsException if the off and/or len are wrong.
  58.352 +   */
  58.353 +  public int inflate (byte[] buf, int off, int len) throws DataFormatException
  58.354 +  {
  58.355 +    /* Special case: len may be zero */
  58.356 +    if (len == 0)
  58.357 +      return 0;
  58.358 +    /* Check for correct buff, off, len triple */
  58.359 +    if (0 > off || off > off + len || off + len > buf.length)
  58.360 +      throw new ArrayIndexOutOfBoundsException();
  58.361 +    int count = 0;
  58.362 +    int more;
  58.363 +    do
  58.364 +      {
  58.365 +	if (mode != DECODE_CHKSUM)
  58.366 +	  {
  58.367 +	    /* Don't give away any output, if we are waiting for the
  58.368 +	     * checksum in the input stream.
  58.369 +	     *
  58.370 +	     * With this trick we have always:
  58.371 +	     *   needsInput() and not finished() 
  58.372 +	     *   implies more output can be produced.  
  58.373 +	     */
  58.374 +	    more = outputWindow.copyOutput(buf, off, len);
  58.375 +	    adler.update(buf, off, more);
  58.376 +	    off += more;
  58.377 +	    count += more;
  58.378 +	    totalOut += more;
  58.379 +	    len -= more;
  58.380 +	    if (len == 0)
  58.381 +	      return count;
  58.382 +	  }
  58.383 +      }
  58.384 +    while (decode() || (outputWindow.getAvailable() > 0
  58.385 +			&& mode != DECODE_CHKSUM));
  58.386 +    return count;
  58.387 +  }
  58.388 +
  58.389 +  /**
  58.390 +   * Returns true, if a preset dictionary is needed to inflate the input.
  58.391 +   */
  58.392 +  public boolean needsDictionary ()
  58.393 +  {
  58.394 +    return mode == DECODE_DICT && neededBits == 0;
  58.395 +  }
  58.396 +
  58.397 +  /**
  58.398 +   * Returns true, if the input buffer is empty.
  58.399 +   * You should then call setInput(). <br>
  58.400 +   *
  58.401 +   * <em>NOTE</em>: This method also returns true when the stream is finished.
  58.402 +   */
  58.403 +  public boolean needsInput () 
  58.404 +  {
  58.405 +    return input.needsInput ();
  58.406 +  }
  58.407 +
  58.408 +  /**
  58.409 +   * Resets the inflater so that a new stream can be decompressed.  All
  58.410 +   * pending input and output will be discarded.
  58.411 +   */
  58.412 +  public void reset ()
  58.413 +  {
  58.414 +    mode = nowrap ? DECODE_BLOCKS : DECODE_HEADER;
  58.415 +    totalIn = totalOut = 0;
  58.416 +    input.reset();
  58.417 +    outputWindow.reset();
  58.418 +    dynHeader = null;
  58.419 +    litlenTree = null;
  58.420 +    distTree = null;
  58.421 +    isLastBlock = false;
  58.422 +    adler.reset();
  58.423 +  }
  58.424 +
  58.425 +  /**
  58.426 +   * Sets the preset dictionary.  This should only be called, if
  58.427 +   * needsDictionary() returns true and it should set the same
  58.428 +   * dictionary, that was used for deflating.  The getAdler()
  58.429 +   * function returns the checksum of the dictionary needed.
  58.430 +   * @param buffer the dictionary.
  58.431 +   * @exception IllegalStateException if no dictionary is needed.
  58.432 +   * @exception IllegalArgumentException if the dictionary checksum is
  58.433 +   * wrong.  
  58.434 +   */
  58.435 +  public void setDictionary (byte[] buffer)
  58.436 +  {
  58.437 +    setDictionary(buffer, 0, buffer.length);
  58.438 +  }
  58.439 +
  58.440 +  /**
  58.441 +   * Sets the preset dictionary.  This should only be called, if
  58.442 +   * needsDictionary() returns true and it should set the same
  58.443 +   * dictionary, that was used for deflating.  The getAdler()
  58.444 +   * function returns the checksum of the dictionary needed.
  58.445 +   * @param buffer the dictionary.
  58.446 +   * @param off the offset into buffer where the dictionary starts.
  58.447 +   * @param len the length of the dictionary.
  58.448 +   * @exception IllegalStateException if no dictionary is needed.
  58.449 +   * @exception IllegalArgumentException if the dictionary checksum is
  58.450 +   * wrong.  
  58.451 +   * @exception IndexOutOfBoundsException if the off and/or len are wrong.
  58.452 +   */
  58.453 +  public void setDictionary (byte[] buffer, int off, int len)
  58.454 +  {
  58.455 +    if (!needsDictionary())
  58.456 +      throw new IllegalStateException();
  58.457 +
  58.458 +    adler.update(buffer, off, len);
  58.459 +    if ((int) adler.getValue() != readAdler)
  58.460 +      throw new IllegalArgumentException("Wrong adler checksum");
  58.461 +    adler.reset();
  58.462 +    outputWindow.copyDict(buffer, off, len);
  58.463 +    mode = DECODE_BLOCKS;
  58.464 +  }
  58.465 +
  58.466 +  /**
  58.467 +   * Sets the input.  This should only be called, if needsInput()
  58.468 +   * returns true.
  58.469 +   * @param buffer the input.
  58.470 +   * @exception IllegalStateException if no input is needed.
  58.471 +   */
  58.472 +  public void setInput (byte[] buf) 
  58.473 +  {
  58.474 +    setInput (buf, 0, buf.length);
  58.475 +  }
  58.476 +
  58.477 +  /**
  58.478 +   * Sets the input.  This should only be called, if needsInput()
  58.479 +   * returns true.
  58.480 +   * @param buffer the input.
  58.481 +   * @param off the offset into buffer where the input starts.
  58.482 +   * @param len the length of the input.  
  58.483 +   * @exception IllegalStateException if no input is needed.
  58.484 +   * @exception IndexOutOfBoundsException if the off and/or len are wrong.
  58.485 +   */
  58.486 +  public void setInput (byte[] buf, int off, int len) 
  58.487 +  {
  58.488 +    input.setInput (buf, off, len);
  58.489 +    totalIn += len;
  58.490 +  }
  58.491 +  private static final int DEFLATED = 8;
  58.492 +  /**
  58.493 +   * Decodes the deflate header.
  58.494 +   * @return false if more input is needed. 
  58.495 +   * @exception DataFormatException if header is invalid.
  58.496 +   */
  58.497 +  private boolean decodeHeader () throws DataFormatException
  58.498 +  {
  58.499 +    int header = input.peekBits(16);
  58.500 +    if (header < 0)
  58.501 +      return false;
  58.502 +    input.dropBits(16);
  58.503 +    
  58.504 +    /* The header is written in "wrong" byte order */
  58.505 +    header = ((header << 8) | (header >> 8)) & 0xffff;
  58.506 +    if (header % 31 != 0)
  58.507 +      throw new DataFormatException("Header checksum illegal");
  58.508 +    
  58.509 +    if ((header & 0x0f00) != (DEFLATED << 8))
  58.510 +      throw new DataFormatException("Compression Method unknown");
  58.511 +
  58.512 +    /* Maximum size of the backwards window in bits. 
  58.513 +     * We currently ignore this, but we could use it to make the
  58.514 +     * inflater window more space efficient. On the other hand the
  58.515 +     * full window (15 bits) is needed most times, anyway.
  58.516 +     int max_wbits = ((header & 0x7000) >> 12) + 8;
  58.517 +     */
  58.518 +    
  58.519 +    if ((header & 0x0020) == 0) // Dictionary flag?
  58.520 +      {
  58.521 +	mode = DECODE_BLOCKS;
  58.522 +      }
  58.523 +    else
  58.524 +      {
  58.525 +	mode = DECODE_DICT;
  58.526 +	neededBits = 32;      
  58.527 +      }
  58.528 +    return true;
  58.529 +  }
  58.530 +   
  58.531 +  /**
  58.532 +   * Decodes the dictionary checksum after the deflate header.
  58.533 +   * @return false if more input is needed. 
  58.534 +   */
  58.535 +  private boolean decodeDict ()
  58.536 +  {
  58.537 +    while (neededBits > 0)
  58.538 +      {
  58.539 +	int dictByte = input.peekBits(8);
  58.540 +	if (dictByte < 0)
  58.541 +	  return false;
  58.542 +	input.dropBits(8);
  58.543 +	readAdler = (readAdler << 8) | dictByte;
  58.544 +	neededBits -= 8;
  58.545 +      }
  58.546 +    return false;
  58.547 +  }
  58.548 +
  58.549 +  /**
  58.550 +   * Decodes the huffman encoded symbols in the input stream.
  58.551 +   * @return false if more input is needed, true if output window is
  58.552 +   * full or the current block ends.
  58.553 +   * @exception DataFormatException if deflated stream is invalid.  
  58.554 +   */
  58.555 +  private boolean decodeHuffman () throws DataFormatException
  58.556 +  {
  58.557 +    int free = outputWindow.getFreeSpace();
  58.558 +    while (free >= 258)
  58.559 +      {
  58.560 +	int symbol;
  58.561 +	switch (mode)
  58.562 +	  {
  58.563 +	  case DECODE_HUFFMAN:
  58.564 +	    /* This is the inner loop so it is optimized a bit */
  58.565 +	    while (((symbol = litlenTree.getSymbol(input)) & ~0xff) == 0)
  58.566 +	      {
  58.567 +		outputWindow.write(symbol);
  58.568 +		if (--free < 258)
  58.569 +		  return true;
  58.570 +	      } 
  58.571 +	    if (symbol < 257)
  58.572 +	      {
  58.573 +		if (symbol < 0)
  58.574 +		  return false;
  58.575 +		else
  58.576 +		  {
  58.577 +		    /* symbol == 256: end of block */
  58.578 +		    distTree = null;
  58.579 +		    litlenTree = null;
  58.580 +		    mode = DECODE_BLOCKS;
  58.581 +		    return true;
  58.582 +		  }
  58.583 +	      }
  58.584 +		
  58.585 +	    try
  58.586 +	      {
  58.587 +		repLength = CPLENS[symbol - 257];
  58.588 +		neededBits = CPLEXT[symbol - 257];
  58.589 +	      }
  58.590 +	    catch (ArrayIndexOutOfBoundsException ex)
  58.591 +	      {
  58.592 +		throw new DataFormatException("Illegal rep length code");
  58.593 +	      }
  58.594 +	    /* fall through */
  58.595 +	  case DECODE_HUFFMAN_LENBITS:
  58.596 +	    if (neededBits > 0)
  58.597 +	      {
  58.598 +		mode = DECODE_HUFFMAN_LENBITS;
  58.599 +		int i = input.peekBits(neededBits);
  58.600 +		if (i < 0)
  58.601 +		  return false;
  58.602 +		input.dropBits(neededBits);
  58.603 +		repLength += i;
  58.604 +	      }
  58.605 +	    mode = DECODE_HUFFMAN_DIST;
  58.606 +	    /* fall through */
  58.607 +	  case DECODE_HUFFMAN_DIST:
  58.608 +	    symbol = distTree.getSymbol(input);
  58.609 +	    if (symbol < 0)
  58.610 +	      return false;
  58.611 +	    try 
  58.612 +	      {
  58.613 +		repDist = CPDIST[symbol];
  58.614 +		neededBits = CPDEXT[symbol];
  58.615 +	      }
  58.616 +	    catch (ArrayIndexOutOfBoundsException ex)
  58.617 +	      {
  58.618 +		throw new DataFormatException("Illegal rep dist code");
  58.619 +	      }
  58.620 +	    /* fall through */
  58.621 +	  case DECODE_HUFFMAN_DISTBITS:
  58.622 +	    if (neededBits > 0)
  58.623 +	      {
  58.624 +		mode = DECODE_HUFFMAN_DISTBITS;
  58.625 +		int i = input.peekBits(neededBits);
  58.626 +		if (i < 0)
  58.627 +		  return false;
  58.628 +		input.dropBits(neededBits);
  58.629 +		repDist += i;
  58.630 +	      }
  58.631 +	    outputWindow.repeat(repLength, repDist);
  58.632 +	    free -= repLength;
  58.633 +	    mode = DECODE_HUFFMAN;
  58.634 +	    break;
  58.635 +	  default:
  58.636 +	    throw new IllegalStateException();
  58.637 +	  }
  58.638 +      }
  58.639 +    return true;
  58.640 +  }
  58.641 +
  58.642 +  /**
  58.643 +   * Decodes the adler checksum after the deflate stream.
  58.644 +   * @return false if more input is needed. 
  58.645 +   * @exception DataFormatException if checksum doesn't match.
  58.646 +   */
  58.647 +  private boolean decodeChksum () throws DataFormatException
  58.648 +  {
  58.649 +    while (neededBits > 0)
  58.650 +      {
  58.651 +	int chkByte = input.peekBits(8);
  58.652 +	if (chkByte < 0)
  58.653 +	  return false;
  58.654 +	input.dropBits(8);
  58.655 +	readAdler = (readAdler << 8) | chkByte;
  58.656 +	neededBits -= 8;
  58.657 +      }
  58.658 +    if ((int) adler.getValue() != readAdler)
  58.659 +      throw new DataFormatException("Adler chksum doesn't match: "
  58.660 +				    +Integer.toHexString((int)adler.getValue())
  58.661 +				    +" vs. "+Integer.toHexString(readAdler));
  58.662 +    mode = FINISHED;
  58.663 +    return false;
  58.664 +  }
  58.665 +
  58.666 +  /**
  58.667 +   * Decodes the deflated stream.
  58.668 +   * @return false if more input is needed, or if finished. 
  58.669 +   * @exception DataFormatException if deflated stream is invalid.
  58.670 +   */
  58.671 +  private boolean decode () throws DataFormatException
  58.672 +  {
  58.673 +    switch (mode) 
  58.674 +      {
  58.675 +      case DECODE_HEADER:
  58.676 +	return decodeHeader();
  58.677 +      case DECODE_DICT:
  58.678 +	return decodeDict();
  58.679 +      case DECODE_CHKSUM:
  58.680 +	return decodeChksum();
  58.681 +
  58.682 +      case DECODE_BLOCKS:
  58.683 +	if (isLastBlock)
  58.684 +	  {
  58.685 +	    if (nowrap)
  58.686 +	      {
  58.687 +		mode = FINISHED;
  58.688 +		return false;
  58.689 +	      }
  58.690 +	    else
  58.691 +	      {
  58.692 +		input.skipToByteBoundary();
  58.693 +		neededBits = 32;
  58.694 +		mode = DECODE_CHKSUM;
  58.695 +		return true;
  58.696 +	      }
  58.697 +	  }
  58.698 +
  58.699 +	int type = input.peekBits(3);
  58.700 +	if (type < 0)
  58.701 +	  return false;
  58.702 +	input.dropBits(3);
  58.703 +
  58.704 +	if ((type & 1) != 0)
  58.705 +	  isLastBlock = true;
  58.706 +	switch (type >> 1)
  58.707 +	  {
  58.708 +	  case DeflaterConstants.STORED_BLOCK:
  58.709 +	    input.skipToByteBoundary();
  58.710 +	    mode = DECODE_STORED_LEN1;
  58.711 +	    break;
  58.712 +	  case DeflaterConstants.STATIC_TREES:
  58.713 +	    litlenTree = InflaterHuffmanTree.defLitLenTree;
  58.714 +	    distTree = InflaterHuffmanTree.defDistTree;
  58.715 +	    mode = DECODE_HUFFMAN;
  58.716 +	    break;
  58.717 +	  case DeflaterConstants.DYN_TREES:
  58.718 +	    dynHeader = new InflaterDynHeader();
  58.719 +	    mode = DECODE_DYN_HEADER;
  58.720 +	    break;
  58.721 +	  default:
  58.722 +	    throw new DataFormatException("Unknown block type "+type);
  58.723 +	  }
  58.724 +	return true;
  58.725 +
  58.726 +      case DECODE_STORED_LEN1:
  58.727 +	{
  58.728 +	  if ((uncomprLen = input.peekBits(16)) < 0)
  58.729 +	    return false;
  58.730 +	  input.dropBits(16);
  58.731 +	  mode = DECODE_STORED_LEN2;
  58.732 +	}
  58.733 +	/* fall through */
  58.734 +      case DECODE_STORED_LEN2:
  58.735 +	{
  58.736 +	  int nlen = input.peekBits(16);
  58.737 +	  if (nlen < 0)
  58.738 +	    return false;
  58.739 +	  input.dropBits(16);
  58.740 +	  if (nlen != (uncomprLen ^ 0xffff))
  58.741 +	    throw new DataFormatException("broken uncompressed block");
  58.742 +	  mode = DECODE_STORED;
  58.743 +	}
  58.744 +	/* fall through */
  58.745 +      case DECODE_STORED:
  58.746 +	{
  58.747 +	  int more = outputWindow.copyStored(input, uncomprLen);
  58.748 +	  uncomprLen -= more;
  58.749 +	  if (uncomprLen == 0)
  58.750 +	    {
  58.751 +	      mode = DECODE_BLOCKS;
  58.752 +	      return true;
  58.753 +	    }
  58.754 +	  return !input.needsInput();
  58.755 +	}
  58.756 +
  58.757 +      case DECODE_DYN_HEADER:
  58.758 +	if (!dynHeader.decode(input))
  58.759 +	  return false;
  58.760 +	litlenTree = dynHeader.buildLitLenTree();
  58.761 +	distTree = dynHeader.buildDistTree();
  58.762 +	mode = DECODE_HUFFMAN;
  58.763 +	/* fall through */
  58.764 +      case DECODE_HUFFMAN:
  58.765 +      case DECODE_HUFFMAN_LENBITS:
  58.766 +      case DECODE_HUFFMAN_DIST:
  58.767 +      case DECODE_HUFFMAN_DISTBITS:
  58.768 +	return decodeHuffman();
  58.769 +      case FINISHED:
  58.770 +	return false;
  58.771 +      default:
  58.772 +	throw new IllegalStateException();
  58.773 +      }	
  58.774 +  }
  58.775 +
  58.776 +
  58.777 +    interface DeflaterConstants {
  58.778 +      final static boolean DEBUGGING = false;
  58.779 +
  58.780 +      final static int STORED_BLOCK = 0;
  58.781 +      final static int STATIC_TREES = 1;
  58.782 +      final static int DYN_TREES    = 2;
  58.783 +      final static int PRESET_DICT  = 0x20;
  58.784 +
  58.785 +      final static int DEFAULT_MEM_LEVEL = 8;
  58.786 +
  58.787 +      final static int MAX_MATCH = 258;
  58.788 +      final static int MIN_MATCH = 3;
  58.789 +
  58.790 +      final static int MAX_WBITS = 15;
  58.791 +      final static int WSIZE = 1 << MAX_WBITS;
  58.792 +      final static int WMASK = WSIZE - 1;
  58.793 +
  58.794 +      final static int HASH_BITS = DEFAULT_MEM_LEVEL + 7;
  58.795 +      final static int HASH_SIZE = 1 << HASH_BITS;
  58.796 +      final static int HASH_MASK = HASH_SIZE - 1;
  58.797 +      final static int HASH_SHIFT = (HASH_BITS + MIN_MATCH - 1) / MIN_MATCH;
  58.798 +
  58.799 +      final static int MIN_LOOKAHEAD = MAX_MATCH + MIN_MATCH + 1;
  58.800 +      final static int MAX_DIST = WSIZE - MIN_LOOKAHEAD;
  58.801 +
  58.802 +      final static int PENDING_BUF_SIZE = 1 << (DEFAULT_MEM_LEVEL + 8);
  58.803 +      final static int MAX_BLOCK_SIZE = Math.min(65535, PENDING_BUF_SIZE-5);
  58.804 +
  58.805 +      final static int DEFLATE_STORED = 0;
  58.806 +      final static int DEFLATE_FAST   = 1;
  58.807 +      final static int DEFLATE_SLOW   = 2;
  58.808 +
  58.809 +      final static int GOOD_LENGTH[] = { 0,4, 4, 4, 4, 8,  8,  8,  32,  32 };
  58.810 +      final static int MAX_LAZY[]    = { 0,4, 5, 6, 4,16, 16, 32, 128, 258 };
  58.811 +      final static int NICE_LENGTH[] = { 0,8,16,32,16,32,128,128, 258, 258 };
  58.812 +      final static int MAX_CHAIN[]   = { 0,4, 8,32,16,32,128,256,1024,4096 };
  58.813 +      final static int COMPR_FUNC[]  = { 0,1, 1, 1, 1, 2,  2,  2,   2,   2 };
  58.814 +    }
  58.815 +    private static class InflaterHuffmanTree {
  58.816 +      private final static int MAX_BITLEN = 15;
  58.817 +      private short[] tree;
  58.818 +
  58.819 +      public static InflaterHuffmanTree defLitLenTree, defDistTree;
  58.820 +
  58.821 +      static
  58.822 +      {
  58.823 +        try 
  58.824 +          {
  58.825 +        byte[] codeLengths = new byte[288];
  58.826 +        int i = 0;
  58.827 +        while (i < 144)
  58.828 +          codeLengths[i++] = 8;
  58.829 +        while (i < 256)
  58.830 +          codeLengths[i++] = 9;
  58.831 +        while (i < 280)
  58.832 +          codeLengths[i++] = 7;
  58.833 +        while (i < 288)
  58.834 +          codeLengths[i++] = 8;
  58.835 +        defLitLenTree = new InflaterHuffmanTree(codeLengths);
  58.836 +
  58.837 +        codeLengths = new byte[32];
  58.838 +        i = 0;
  58.839 +        while (i < 32)
  58.840 +          codeLengths[i++] = 5;
  58.841 +        defDistTree = new InflaterHuffmanTree(codeLengths);
  58.842 +          } 
  58.843 +        catch (DataFormatException ex)
  58.844 +          {
  58.845 +        throw new IllegalStateException
  58.846 +          ("InflaterHuffmanTree: static tree length illegal");
  58.847 +          }
  58.848 +      }
  58.849 +
  58.850 +      /**
  58.851 +       * Constructs a Huffman tree from the array of code lengths.
  58.852 +       *
  58.853 +       * @param codeLengths the array of code lengths
  58.854 +       */
  58.855 +      public InflaterHuffmanTree(byte[] codeLengths) throws DataFormatException
  58.856 +      {
  58.857 +        buildTree(codeLengths);
  58.858 +      }
  58.859 +
  58.860 +      private void buildTree(byte[] codeLengths) throws DataFormatException
  58.861 +      {
  58.862 +        int[] blCount = new int[MAX_BITLEN+1];
  58.863 +        int[] nextCode = new int[MAX_BITLEN+1];
  58.864 +        for (int i = 0; i < codeLengths.length; i++)
  58.865 +          {
  58.866 +        int bits = codeLengths[i];
  58.867 +        if (bits > 0)
  58.868 +          blCount[bits]++;
  58.869 +          }
  58.870 +
  58.871 +        int code = 0;
  58.872 +        int treeSize = 512;
  58.873 +        for (int bits = 1; bits <= MAX_BITLEN; bits++)
  58.874 +          {
  58.875 +        nextCode[bits] = code;
  58.876 +        code += blCount[bits] << (16 - bits);
  58.877 +        if (bits >= 10)
  58.878 +          {
  58.879 +            /* We need an extra table for bit lengths >= 10. */
  58.880 +            int start = nextCode[bits] & 0x1ff80;
  58.881 +            int end   = code & 0x1ff80;
  58.882 +            treeSize += (end - start) >> (16 - bits);
  58.883 +          }
  58.884 +          }
  58.885 +        if (code != 65536)
  58.886 +          throw new DataFormatException("Code lengths don't add up properly.");
  58.887 +
  58.888 +        /* Now create and fill the extra tables from longest to shortest
  58.889 +         * bit len.  This way the sub trees will be aligned.
  58.890 +         */
  58.891 +        tree = new short[treeSize];
  58.892 +        int treePtr = 512;
  58.893 +        for (int bits = MAX_BITLEN; bits >= 10; bits--)
  58.894 +          {
  58.895 +        int end   = code & 0x1ff80;
  58.896 +        code -= blCount[bits] << (16 - bits);
  58.897 +        int start = code & 0x1ff80;
  58.898 +        for (int i = start; i < end; i += 1 << 7)
  58.899 +          {
  58.900 +            tree[bitReverse(i)]
  58.901 +              = (short) ((-treePtr << 4) | bits);
  58.902 +            treePtr += 1 << (bits-9);
  58.903 +          }
  58.904 +          }
  58.905 +
  58.906 +        for (int i = 0; i < codeLengths.length; i++)
  58.907 +          {
  58.908 +        int bits = codeLengths[i];
  58.909 +        if (bits == 0)
  58.910 +          continue;
  58.911 +        code = nextCode[bits];
  58.912 +        int revcode = bitReverse(code);
  58.913 +        if (bits <= 9)
  58.914 +          {
  58.915 +            do
  58.916 +              {
  58.917 +            tree[revcode] = (short) ((i << 4) | bits);
  58.918 +            revcode += 1 << bits;
  58.919 +              }
  58.920 +            while (revcode < 512);
  58.921 +          }
  58.922 +        else
  58.923 +          {
  58.924 +            int subTree = tree[revcode & 511];
  58.925 +            int treeLen = 1 << (subTree & 15);
  58.926 +            subTree = -(subTree >> 4);
  58.927 +            do
  58.928 +              { 
  58.929 +            tree[subTree | (revcode >> 9)] = (short) ((i << 4) | bits);
  58.930 +            revcode += 1 << bits;
  58.931 +              }
  58.932 +            while (revcode < treeLen);
  58.933 +          }
  58.934 +        nextCode[bits] = code + (1 << (16 - bits));
  58.935 +          }
  58.936 +      }
  58.937 +      private final static String bit4Reverse =
  58.938 +        "\000\010\004\014\002\012\006\016\001\011\005\015\003\013\007\017";
  58.939 +      static short bitReverse(int value) {
  58.940 +            return (short) (bit4Reverse.charAt(value & 0xf) << 12
  58.941 +                | bit4Reverse.charAt((value >> 4) & 0xf) << 8
  58.942 +                | bit4Reverse.charAt((value >> 8) & 0xf) << 4
  58.943 +                | bit4Reverse.charAt(value >> 12));
  58.944 +      }
  58.945 +
  58.946 +      /**
  58.947 +       * Reads the next symbol from input.  The symbol is encoded using the
  58.948 +       * huffman tree.
  58.949 +       * @param input the input source.
  58.950 +       * @return the next symbol, or -1 if not enough input is available.
  58.951 +       */
  58.952 +      public int getSymbol(StreamManipulator input) throws DataFormatException
  58.953 +      {
  58.954 +        int lookahead, symbol;
  58.955 +        if ((lookahead = input.peekBits(9)) >= 0)
  58.956 +          {
  58.957 +        if ((symbol = tree[lookahead]) >= 0)
  58.958 +          {
  58.959 +            input.dropBits(symbol & 15);
  58.960 +            return symbol >> 4;
  58.961 +          }
  58.962 +        int subtree = -(symbol >> 4);
  58.963 +        int bitlen = symbol & 15;
  58.964 +        if ((lookahead = input.peekBits(bitlen)) >= 0)
  58.965 +          {
  58.966 +            symbol = tree[subtree | (lookahead >> 9)];
  58.967 +            input.dropBits(symbol & 15);
  58.968 +            return symbol >> 4;
  58.969 +          }
  58.970 +        else
  58.971 +          {
  58.972 +            int bits = input.getAvailableBits();
  58.973 +            lookahead = input.peekBits(bits);
  58.974 +            symbol = tree[subtree | (lookahead >> 9)];
  58.975 +            if ((symbol & 15) <= bits)
  58.976 +              {
  58.977 +            input.dropBits(symbol & 15);
  58.978 +            return symbol >> 4;
  58.979 +              }
  58.980 +            else
  58.981 +              return -1;
  58.982 +          }
  58.983 +          }
  58.984 +        else
  58.985 +          {
  58.986 +        int bits = input.getAvailableBits();
  58.987 +        lookahead = input.peekBits(bits);
  58.988 +        symbol = tree[lookahead];
  58.989 +        if (symbol >= 0 && (symbol & 15) <= bits)
  58.990 +          {
  58.991 +            input.dropBits(symbol & 15);
  58.992 +            return symbol >> 4;
  58.993 +          }
  58.994 +        else
  58.995 +          return -1;
  58.996 +          }
  58.997 +      }
  58.998 +    }
  58.999 +    private static class InflaterDynHeader
 58.1000 +    {
 58.1001 +      private static final int LNUM   = 0;
 58.1002 +      private static final int DNUM   = 1;
 58.1003 +      private static final int BLNUM  = 2;
 58.1004 +      private static final int BLLENS = 3;
 58.1005 +      private static final int LENS   = 4;
 58.1006 +      private static final int REPS   = 5;
 58.1007 +
 58.1008 +      private static final int repMin[]  = { 3, 3, 11 };
 58.1009 +      private static final int repBits[] = { 2, 3,  7 };
 58.1010 +
 58.1011 +
 58.1012 +      private byte[] blLens;
 58.1013 +      private byte[] litdistLens;
 58.1014 +
 58.1015 +      private InflaterHuffmanTree blTree;
 58.1016 +
 58.1017 +      private int mode;
 58.1018 +      private int lnum, dnum, blnum, num;
 58.1019 +      private int repSymbol;
 58.1020 +      private byte lastLen;
 58.1021 +      private int ptr;
 58.1022 +
 58.1023 +      private static final int[] BL_ORDER =
 58.1024 +      { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
 58.1025 +
 58.1026 +      public InflaterDynHeader()
 58.1027 +      {
 58.1028 +      }
 58.1029 +
 58.1030 +      public boolean decode(StreamManipulator input) throws DataFormatException
 58.1031 +      {
 58.1032 +      decode_loop:
 58.1033 +        for (;;)
 58.1034 +          {
 58.1035 +        switch (mode)
 58.1036 +          {
 58.1037 +          case LNUM:
 58.1038 +            lnum = input.peekBits(5);
 58.1039 +            if (lnum < 0)
 58.1040 +              return false;
 58.1041 +            lnum += 257;
 58.1042 +            input.dropBits(5);
 58.1043 +    //  	    System.err.println("LNUM: "+lnum);
 58.1044 +            mode = DNUM;
 58.1045 +            /* fall through */
 58.1046 +          case DNUM:
 58.1047 +            dnum = input.peekBits(5);
 58.1048 +            if (dnum < 0)
 58.1049 +              return false;
 58.1050 +            dnum++;
 58.1051 +            input.dropBits(5);
 58.1052 +    //  	    System.err.println("DNUM: "+dnum);
 58.1053 +            num = lnum+dnum;
 58.1054 +            litdistLens = new byte[num];
 58.1055 +            mode = BLNUM;
 58.1056 +            /* fall through */
 58.1057 +          case BLNUM:
 58.1058 +            blnum = input.peekBits(4);
 58.1059 +            if (blnum < 0)
 58.1060 +              return false;
 58.1061 +            blnum += 4;
 58.1062 +            input.dropBits(4);
 58.1063 +            blLens = new byte[19];
 58.1064 +            ptr = 0;
 58.1065 +    //  	    System.err.println("BLNUM: "+blnum);
 58.1066 +            mode = BLLENS;
 58.1067 +            /* fall through */
 58.1068 +          case BLLENS:
 58.1069 +            while (ptr < blnum)
 58.1070 +              {
 58.1071 +            int len = input.peekBits(3);
 58.1072 +            if (len < 0)
 58.1073 +              return false;
 58.1074 +            input.dropBits(3);
 58.1075 +    //  		System.err.println("blLens["+BL_ORDER[ptr]+"]: "+len);
 58.1076 +            blLens[BL_ORDER[ptr]] = (byte) len;
 58.1077 +            ptr++;
 58.1078 +              }
 58.1079 +            blTree = new InflaterHuffmanTree(blLens);
 58.1080 +            blLens = null;
 58.1081 +            ptr = 0;
 58.1082 +            mode = LENS;
 58.1083 +            /* fall through */
 58.1084 +          case LENS:
 58.1085 +            {
 58.1086 +              int symbol;
 58.1087 +              while (((symbol = blTree.getSymbol(input)) & ~15) == 0)
 58.1088 +            {
 58.1089 +              /* Normal case: symbol in [0..15] */
 58.1090 +
 58.1091 +    //  		  System.err.println("litdistLens["+ptr+"]: "+symbol);
 58.1092 +              litdistLens[ptr++] = lastLen = (byte) symbol;
 58.1093 +
 58.1094 +              if (ptr == num)
 58.1095 +                {
 58.1096 +                  /* Finished */
 58.1097 +                  return true;
 58.1098 +                }
 58.1099 +            }
 58.1100 +
 58.1101 +              /* need more input ? */
 58.1102 +              if (symbol < 0)
 58.1103 +            return false;
 58.1104 +
 58.1105 +              /* otherwise repeat code */
 58.1106 +              if (symbol >= 17)
 58.1107 +            {
 58.1108 +              /* repeat zero */
 58.1109 +    //  		  System.err.println("repeating zero");
 58.1110 +              lastLen = 0;
 58.1111 +            }
 58.1112 +              else
 58.1113 +            {
 58.1114 +              if (ptr == 0)
 58.1115 +                throw new DataFormatException();
 58.1116 +            }
 58.1117 +              repSymbol = symbol-16;
 58.1118 +              mode = REPS;
 58.1119 +            }
 58.1120 +            /* fall through */
 58.1121 +
 58.1122 +          case REPS:
 58.1123 +            {
 58.1124 +              int bits = repBits[repSymbol];
 58.1125 +              int count = input.peekBits(bits);
 58.1126 +              if (count < 0)
 58.1127 +            return false;
 58.1128 +              input.dropBits(bits);
 58.1129 +              count += repMin[repSymbol];
 58.1130 +    //  	      System.err.println("litdistLens repeated: "+count);
 58.1131 +
 58.1132 +              if (ptr + count > num)
 58.1133 +            throw new DataFormatException();
 58.1134 +              while (count-- > 0)
 58.1135 +            litdistLens[ptr++] = lastLen;
 58.1136 +
 58.1137 +              if (ptr == num)
 58.1138 +            {
 58.1139 +              /* Finished */
 58.1140 +              return true;
 58.1141 +            }
 58.1142 +            }
 58.1143 +            mode = LENS;
 58.1144 +            continue decode_loop;
 58.1145 +          }
 58.1146 +          }
 58.1147 +      }
 58.1148 +
 58.1149 +      public InflaterHuffmanTree buildLitLenTree() throws DataFormatException
 58.1150 +      {
 58.1151 +        byte[] litlenLens = new byte[lnum];
 58.1152 +        System.arraycopy(litdistLens, 0, litlenLens, 0, lnum);
 58.1153 +        return new InflaterHuffmanTree(litlenLens);
 58.1154 +      }
 58.1155 +
 58.1156 +      public InflaterHuffmanTree buildDistTree() throws DataFormatException
 58.1157 +      {
 58.1158 +        byte[] distLens = new byte[dnum];
 58.1159 +        System.arraycopy(litdistLens, lnum, distLens, 0, dnum);
 58.1160 +        return new InflaterHuffmanTree(distLens);
 58.1161 +      }
 58.1162 +    }
 58.1163 +    /**
 58.1164 +     * This class allows us to retrieve a specified amount of bits from
 58.1165 +     * the input buffer, as well as copy big byte blocks.
 58.1166 +     *
 58.1167 +     * It uses an int buffer to store up to 31 bits for direct
 58.1168 +     * manipulation.  This guarantees that we can get at least 16 bits,
 58.1169 +     * but we only need at most 15, so this is all safe.
 58.1170 +     *
 58.1171 +     * There are some optimizations in this class, for example, you must
 58.1172 +     * never peek more then 8 bits more than needed, and you must first 
 58.1173 +     * peek bits before you may drop them.  This is not a general purpose
 58.1174 +     * class but optimized for the behaviour of the Inflater.
 58.1175 +     *
 58.1176 +     * @author John Leuner, Jochen Hoenicke
 58.1177 +     */
 58.1178 +
 58.1179 +    private static class StreamManipulator
 58.1180 +    {
 58.1181 +      private byte[] window;
 58.1182 +      private int window_start = 0;
 58.1183 +      private int window_end = 0;
 58.1184 +
 58.1185 +      private int buffer = 0;
 58.1186 +      private int bits_in_buffer = 0;
 58.1187 +
 58.1188 +      /**
 58.1189 +       * Get the next n bits but don't increase input pointer.  n must be
 58.1190 +       * less or equal 16 and if you if this call succeeds, you must drop
 58.1191 +       * at least n-8 bits in the next call.
 58.1192 +       * 
 58.1193 +       * @return the value of the bits, or -1 if not enough bits available.  */
 58.1194 +      public final int peekBits(int n)
 58.1195 +      {
 58.1196 +        if (bits_in_buffer < n)
 58.1197 +          {
 58.1198 +        if (window_start == window_end)
 58.1199 +          return -1;
 58.1200 +        buffer |= (window[window_start++] & 0xff
 58.1201 +               | (window[window_start++] & 0xff) << 8) << bits_in_buffer;
 58.1202 +        bits_in_buffer += 16;
 58.1203 +          }
 58.1204 +        return buffer & ((1 << n) - 1);
 58.1205 +      }
 58.1206 +
 58.1207 +      /* Drops the next n bits from the input.  You should have called peekBits
 58.1208 +       * with a bigger or equal n before, to make sure that enough bits are in
 58.1209 +       * the bit buffer.
 58.1210 +       */
 58.1211 +      public final void dropBits(int n)
 58.1212 +      {
 58.1213 +        buffer >>>= n;
 58.1214 +        bits_in_buffer -= n;
 58.1215 +      }
 58.1216 +
 58.1217 +      /**
 58.1218 +       * Gets the next n bits and increases input pointer.  This is equivalent
 58.1219 +       * to peekBits followed by dropBits, except for correct error handling.
 58.1220 +       * @return the value of the bits, or -1 if not enough bits available. 
 58.1221 +       */
 58.1222 +      public final int getBits(int n)
 58.1223 +      {
 58.1224 +        int bits = peekBits(n);
 58.1225 +        if (bits >= 0)
 58.1226 +          dropBits(n);
 58.1227 +        return bits;
 58.1228 +      }
 58.1229 +      /**
 58.1230 +       * Gets the number of bits available in the bit buffer.  This must be
 58.1231 +       * only called when a previous peekBits() returned -1.
 58.1232 +       * @return the number of bits available.
 58.1233 +       */
 58.1234 +      public final int getAvailableBits()
 58.1235 +      {
 58.1236 +        return bits_in_buffer;
 58.1237 +      }
 58.1238 +
 58.1239 +      /**
 58.1240 +       * Gets the number of bytes available.  
 58.1241 +       * @return the number of bytes available.
 58.1242 +       */
 58.1243 +      public final int getAvailableBytes()
 58.1244 +      {
 58.1245 +        return window_end - window_start + (bits_in_buffer >> 3);
 58.1246 +      }
 58.1247 +
 58.1248 +      /**
 58.1249 +       * Skips to the next byte boundary.
 58.1250 +       */
 58.1251 +      public void skipToByteBoundary()
 58.1252 +      {
 58.1253 +        buffer >>= (bits_in_buffer & 7);
 58.1254 +        bits_in_buffer &= ~7;
 58.1255 +      }
 58.1256 +
 58.1257 +      public final boolean needsInput() {
 58.1258 +        return window_start == window_end;
 58.1259 +      }
 58.1260 +
 58.1261 +
 58.1262 +      /* Copies length bytes from input buffer to output buffer starting
 58.1263 +       * at output[offset].  You have to make sure, that the buffer is
 58.1264 +       * byte aligned.  If not enough bytes are available, copies fewer
 58.1265 +       * bytes.
 58.1266 +       * @param length the length to copy, 0 is allowed.
 58.1267 +       * @return the number of bytes copied, 0 if no byte is available.  
 58.1268 +       */
 58.1269 +      public int copyBytes(byte[] output, int offset, int length)
 58.1270 +      {
 58.1271 +        if (length < 0)
 58.1272 +          throw new IllegalArgumentException("length negative");
 58.1273 +        if ((bits_in_buffer & 7) != 0)  
 58.1274 +          /* bits_in_buffer may only be 0 or 8 */
 58.1275 +          throw new IllegalStateException("Bit buffer is not aligned!");
 58.1276 +
 58.1277 +        int count = 0;
 58.1278 +        while (bits_in_buffer > 0 && length > 0)
 58.1279 +          {
 58.1280 +        output[offset++] = (byte) buffer;
 58.1281 +        buffer >>>= 8;
 58.1282 +        bits_in_buffer -= 8;
 58.1283 +        length--;
 58.1284 +        count++;
 58.1285 +          }
 58.1286 +        if (length == 0)
 58.1287 +          return count;
 58.1288 +
 58.1289 +        int avail = window_end - window_start;
 58.1290 +        if (length > avail)
 58.1291 +          length = avail;
 58.1292 +        System.arraycopy(window, window_start, output, offset, length);
 58.1293 +        window_start += length;
 58.1294 +
 58.1295 +        if (((window_start - window_end) & 1) != 0)
 58.1296 +          {
 58.1297 +        /* We always want an even number of bytes in input, see peekBits */
 58.1298 +        buffer = (window[window_start++] & 0xff);
 58.1299 +        bits_in_buffer = 8;
 58.1300 +          }
 58.1301 +        return count + length;
 58.1302 +      }
 58.1303 +
 58.1304 +      public StreamManipulator()
 58.1305 +      {
 58.1306 +      }
 58.1307 +
 58.1308 +      public void reset()
 58.1309 +      {
 58.1310 +        window_start = window_end = buffer = bits_in_buffer = 0;
 58.1311 +      }
 58.1312 +
 58.1313 +      public void setInput(byte[] buf, int off, int len)
 58.1314 +      {
 58.1315 +        if (window_start < window_end)
 58.1316 +          throw new IllegalStateException
 58.1317 +        ("Old input was not completely processed");
 58.1318 +
 58.1319 +        int end = off + len;
 58.1320 +
 58.1321 +        /* We want to throw an ArrayIndexOutOfBoundsException early.  The
 58.1322 +         * check is very tricky: it also handles integer wrap around.  
 58.1323 +         */
 58.1324 +        if (0 > off || off > end || end > buf.length)
 58.1325 +          throw new ArrayIndexOutOfBoundsException();
 58.1326 +
 58.1327 +        if ((len & 1) != 0)
 58.1328 +          {
 58.1329 +        /* We always want an even number of bytes in input, see peekBits */
 58.1330 +        buffer |= (buf[off++] & 0xff) << bits_in_buffer;
 58.1331 +        bits_in_buffer += 8;
 58.1332 +          }
 58.1333 +
 58.1334 +        window = buf;
 58.1335 +        window_start = off;
 58.1336 +        window_end = end;
 58.1337 +      }
 58.1338 +    }
 58.1339 +    /*
 58.1340 +     * Contains the output from the Inflation process.
 58.1341 +     *
 58.1342 +     * We need to have a window so that we can refer backwards into the output stream
 58.1343 +     * to repeat stuff.
 58.1344 +     *
 58.1345 +     * @author John Leuner
 58.1346 +     * @since JDK 1.1
 58.1347 +     */
 58.1348 +
 58.1349 +    private static class OutputWindow
 58.1350 +    {
 58.1351 +      private final int WINDOW_SIZE = 1 << 15;
 58.1352 +      private final int WINDOW_MASK = WINDOW_SIZE - 1;
 58.1353 +
 58.1354 +      private byte[] window = new byte[WINDOW_SIZE]; //The window is 2^15 bytes
 58.1355 +      private int window_end  = 0;
 58.1356 +      private int window_filled = 0;
 58.1357 +
 58.1358 +      public void write(int abyte)
 58.1359 +      {
 58.1360 +        if (window_filled++ == WINDOW_SIZE)
 58.1361 +          throw new IllegalStateException("Window full");
 58.1362 +        window[window_end++] = (byte) abyte;
 58.1363 +        window_end &= WINDOW_MASK;
 58.1364 +      }
 58.1365 +
 58.1366 +
 58.1367 +      private final void slowRepeat(int rep_start, int len, int dist)
 58.1368 +      {
 58.1369 +        while (len-- > 0)
 58.1370 +          {
 58.1371 +        window[window_end++] = window[rep_start++];
 58.1372 +        window_end &= WINDOW_MASK;
 58.1373 +        rep_start &= WINDOW_MASK;
 58.1374 +          }
 58.1375 +      }
 58.1376 +
 58.1377 +      public void repeat(int len, int dist)
 58.1378 +      {
 58.1379 +        if ((window_filled += len) > WINDOW_SIZE)
 58.1380 +          throw new IllegalStateException("Window full");
 58.1381 +
 58.1382 +        int rep_start = (window_end - dist) & WINDOW_MASK;
 58.1383 +        int border = WINDOW_SIZE - len;
 58.1384 +        if (rep_start <= border && window_end < border)
 58.1385 +          {
 58.1386 +        if (len <= dist)
 58.1387 +          {
 58.1388 +            System.arraycopy(window, rep_start, window, window_end, len);
 58.1389 +            window_end += len;
 58.1390 +          }
 58.1391 +        else
 58.1392 +          {
 58.1393 +            /* We have to copy manually, since the repeat pattern overlaps.
 58.1394 +             */
 58.1395 +            while (len-- > 0)
 58.1396 +              window[window_end++] = window[rep_start++];
 58.1397 +          }
 58.1398 +          }
 58.1399 +        else
 58.1400 +          slowRepeat(rep_start, len, dist);
 58.1401 +      }
 58.1402 +
 58.1403 +      public int copyStored(StreamManipulator input, int len)
 58.1404 +      {
 58.1405 +        len = Math.min(Math.min(len, WINDOW_SIZE - window_filled), 
 58.1406 +               input.getAvailableBytes());
 58.1407 +        int copied;
 58.1408 +
 58.1409 +        int tailLen = WINDOW_SIZE - window_end;
 58.1410 +        if (len > tailLen)
 58.1411 +          {
 58.1412 +        copied = input.copyBytes(window, window_end, tailLen);
 58.1413 +        if (copied == tailLen)
 58.1414 +          copied += input.copyBytes(window, 0, len - tailLen);
 58.1415 +          }
 58.1416 +        else
 58.1417 +          copied = input.copyBytes(window, window_end, len);
 58.1418 +
 58.1419 +        window_end = (window_end + copied) & WINDOW_MASK;
 58.1420 +        window_filled += copied;
 58.1421 +        return copied;
 58.1422 +      }
 58.1423 +
 58.1424 +      public void copyDict(byte[] dict, int offset, int len)
 58.1425 +      {
 58.1426 +        if (window_filled > 0)
 58.1427 +          throw new IllegalStateException();
 58.1428 +
 58.1429 +        if (len > WINDOW_SIZE)
 58.1430 +          {
 58.1431 +        offset += len - WINDOW_SIZE;
 58.1432 +        len = WINDOW_SIZE;
 58.1433 +          }
 58.1434 +        System.arraycopy(dict, offset, window, 0, len);
 58.1435 +        window_end = len & WINDOW_MASK;
 58.1436 +      }
 58.1437 +
 58.1438 +      public int getFreeSpace()
 58.1439 +      {
 58.1440 +        return WINDOW_SIZE - window_filled;
 58.1441 +      }
 58.1442 +
 58.1443 +      public int getAvailable()
 58.1444 +      {
 58.1445 +        return window_filled;
 58.1446 +      }
 58.1447 +
 58.1448 +      public int copyOutput(byte[] output, int offset, int len)
 58.1449 +      {
 58.1450 +        int copy_end = window_end;
 58.1451 +        if (len > window_filled)
 58.1452 +          len = window_filled;
 58.1453 +        else
 58.1454 +          copy_end = (window_end - window_filled + len) & WINDOW_MASK;
 58.1455 +
 58.1456 +        int copied = len;
 58.1457 +        int tailLen = len - copy_end;
 58.1458 +
 58.1459 +        if (tailLen > 0)
 58.1460 +          {
 58.1461 +        System.arraycopy(window, WINDOW_SIZE - tailLen,
 58.1462 +                 output, offset, tailLen);
 58.1463 +        offset += tailLen;
 58.1464 +        len = copy_end;
 58.1465 +          }
 58.1466 +        System.arraycopy(window, copy_end - len, output, offset, len);
 58.1467 +        window_filled -= copied;
 58.1468 +        if (window_filled < 0)
 58.1469 +          throw new IllegalStateException();
 58.1470 +        return copied;
 58.1471 +      }
 58.1472 +
 58.1473 +      public void reset() {
 58.1474 +        window_filled = window_end = 0;
 58.1475 +      }
 58.1476 +    }
 58.1477 +  
 58.1478 +}
    59.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    59.2 +++ b/emul/mini/src/main/java/java/util/zip/InflaterInputStream.java	Mon Feb 04 09:37:56 2013 +0100
    59.3 @@ -0,0 +1,288 @@
    59.4 +/*
    59.5 + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
    59.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    59.7 + *
    59.8 + * This code is free software; you can redistribute it and/or modify it
    59.9 + * under the terms of the GNU General Public License version 2 only, as
   59.10 + * published by the Free Software Foundation.  Oracle designates this
   59.11 + * particular file as subject to the "Classpath" exception as provided
   59.12 + * by Oracle in the LICENSE file that accompanied this code.
   59.13 + *
   59.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   59.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   59.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   59.17 + * version 2 for more details (a copy is included in the LICENSE file that
   59.18 + * accompanied this code).
   59.19 + *
   59.20 + * You should have received a copy of the GNU General Public License version
   59.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   59.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   59.23 + *
   59.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   59.25 + * or visit www.oracle.com if you need additional information or have any
   59.26 + * questions.
   59.27 + */
   59.28 +
   59.29 +package java.util.zip;
   59.30 +
   59.31 +import java.io.FilterInputStream;
   59.32 +import java.io.InputStream;
   59.33 +import java.io.IOException;
   59.34 +import java.io.EOFException;
   59.35 +
   59.36 +/**
   59.37 + * This class implements a stream filter for uncompressing data in the
   59.38 + * "deflate" compression format. It is also used as the basis for other
   59.39 + * decompression filters, such as GZIPInputStream.
   59.40 + *
   59.41 + * @see         Inflater
   59.42 + * @author      David Connelly
   59.43 + */
   59.44 +public
   59.45 +class InflaterInputStream extends FilterInputStream {
   59.46 +    /**
   59.47 +     * Decompressor for this stream.
   59.48 +     */
   59.49 +    protected Inflater inf;
   59.50 +
   59.51 +    /**
   59.52 +     * Input buffer for decompression.
   59.53 +     */
   59.54 +    protected byte[] buf;
   59.55 +
   59.56 +    /**
   59.57 +     * Length of input buffer.
   59.58 +     */
   59.59 +    protected int len;
   59.60 +
   59.61 +    private boolean closed = false;
   59.62 +    // this flag is set to true after EOF has reached
   59.63 +    private boolean reachEOF = false;
   59.64 +
   59.65 +    /**
   59.66 +     * Check to make sure that this stream has not been closed
   59.67 +     */
   59.68 +    private void ensureOpen() throws IOException {
   59.69 +        if (closed) {
   59.70 +            throw new IOException("Stream closed");
   59.71 +        }
   59.72 +    }
   59.73 +
   59.74 +
   59.75 +    /**
   59.76 +     * Creates a new input stream with the specified decompressor and
   59.77 +     * buffer size.
   59.78 +     * @param in the input stream
   59.79 +     * @param inf the decompressor ("inflater")
   59.80 +     * @param size the input buffer size
   59.81 +     * @exception IllegalArgumentException if size is <= 0
   59.82 +     */
   59.83 +    public InflaterInputStream(InputStream in, Inflater inf, int size) {
   59.84 +        super(in);
   59.85 +        if (in == null || inf == null) {
   59.86 +            throw new NullPointerException();
   59.87 +        } else if (size <= 0) {
   59.88 +            throw new IllegalArgumentException("buffer size <= 0");
   59.89 +        }
   59.90 +        this.inf = inf;
   59.91 +        buf = new byte[size];
   59.92 +    }
   59.93 +
   59.94 +    /**
   59.95 +     * Creates a new input stream with the specified decompressor and a
   59.96 +     * default buffer size.
   59.97 +     * @param in the input stream
   59.98 +     * @param inf the decompressor ("inflater")
   59.99 +     */
  59.100 +    public InflaterInputStream(InputStream in, Inflater inf) {
  59.101 +        this(in, inf, 512);
  59.102 +    }
  59.103 +
  59.104 +    boolean usesDefaultInflater = false;
  59.105 +
  59.106 +    /**
  59.107 +     * Creates a new input stream with a default decompressor and buffer size.
  59.108 +     * @param in the input stream
  59.109 +     */
  59.110 +    public InflaterInputStream(InputStream in) {
  59.111 +        this(in, new Inflater());
  59.112 +        usesDefaultInflater = true;
  59.113 +    }
  59.114 +
  59.115 +    private byte[] singleByteBuf = new byte[1];
  59.116 +
  59.117 +    /**
  59.118 +     * Reads a byte of uncompressed data. This method will block until
  59.119 +     * enough input is available for decompression.
  59.120 +     * @return the byte read, or -1 if end of compressed input is reached
  59.121 +     * @exception IOException if an I/O error has occurred
  59.122 +     */
  59.123 +    public int read() throws IOException {
  59.124 +        ensureOpen();
  59.125 +        return read(singleByteBuf, 0, 1) == -1 ? -1 : singleByteBuf[0] & 0xff;
  59.126 +    }
  59.127 +
  59.128 +    /**
  59.129 +     * Reads uncompressed data into an array of bytes. If <code>len</code> is not
  59.130 +     * zero, the method will block until some input can be decompressed; otherwise,
  59.131 +     * no bytes are read and <code>0</code> is returned.
  59.132 +     * @param b the buffer into which the data is read
  59.133 +     * @param off the start offset in the destination array <code>b</code>
  59.134 +     * @param len the maximum number of bytes read
  59.135 +     * @return the actual number of bytes read, or -1 if the end of the
  59.136 +     *         compressed input is reached or a preset dictionary is needed
  59.137 +     * @exception  NullPointerException If <code>b</code> is <code>null</code>.
  59.138 +     * @exception  IndexOutOfBoundsException If <code>off</code> is negative,
  59.139 +     * <code>len</code> is negative, or <code>len</code> is greater than
  59.140 +     * <code>b.length - off</code>
  59.141 +     * @exception ZipException if a ZIP format error has occurred
  59.142 +     * @exception IOException if an I/O error has occurred
  59.143 +     */
  59.144 +    public int read(byte[] b, int off, int len) throws IOException {
  59.145 +        ensureOpen();
  59.146 +        if (b == null) {
  59.147 +            throw new NullPointerException();
  59.148 +        } else if (off < 0 || len < 0 || len > b.length - off) {
  59.149 +            throw new IndexOutOfBoundsException();
  59.150 +        } else if (len == 0) {
  59.151 +            return 0;
  59.152 +        }
  59.153 +        try {
  59.154 +            int n;
  59.155 +            while ((n = inf.inflate(b, off, len)) == 0) {
  59.156 +                if (inf.finished() || inf.needsDictionary()) {
  59.157 +                    reachEOF = true;
  59.158 +                    return -1;
  59.159 +                }
  59.160 +                if (inf.needsInput()) {
  59.161 +                    fill();
  59.162 +                }
  59.163 +            }
  59.164 +            return n;
  59.165 +        } catch (DataFormatException e) {
  59.166 +            String s = e.getMessage();
  59.167 +            throw new ZipException(s != null ? s : "Invalid ZLIB data format");
  59.168 +        }
  59.169 +    }
  59.170 +
  59.171 +    /**
  59.172 +     * Returns 0 after EOF has been reached, otherwise always return 1.
  59.173 +     * <p>
  59.174 +     * Programs should not count on this method to return the actual number
  59.175 +     * of bytes that could be read without blocking.
  59.176 +     *
  59.177 +     * @return     1 before EOF and 0 after EOF.
  59.178 +     * @exception  IOException  if an I/O error occurs.
  59.179 +     *
  59.180 +     */
  59.181 +    public int available() throws IOException {
  59.182 +        ensureOpen();
  59.183 +        if (reachEOF) {
  59.184 +            return 0;
  59.185 +        } else {
  59.186 +            return 1;
  59.187 +        }
  59.188 +    }
  59.189 +
  59.190 +    private byte[] b = new byte[512];
  59.191 +
  59.192 +    /**
  59.193 +     * Skips specified number of bytes of uncompressed data.
  59.194 +     * @param n the number of bytes to skip
  59.195 +     * @return the actual number of bytes skipped.
  59.196 +     * @exception IOException if an I/O error has occurred
  59.197 +     * @exception IllegalArgumentException if n < 0
  59.198 +     */
  59.199 +    public long skip(long n) throws IOException {
  59.200 +        if (n < 0) {
  59.201 +            throw new IllegalArgumentException("negative skip length");
  59.202 +        }
  59.203 +        ensureOpen();
  59.204 +        int max = (int)Math.min(n, Integer.MAX_VALUE);
  59.205 +        int total = 0;
  59.206 +        while (total < max) {
  59.207 +            int len = max - total;
  59.208 +            if (len > b.length) {
  59.209 +                len = b.length;
  59.210 +            }
  59.211 +            len = read(b, 0, len);
  59.212 +            if (len == -1) {
  59.213 +                reachEOF = true;
  59.214 +                break;
  59.215 +            }
  59.216 +            total += len;
  59.217 +        }
  59.218 +        return total;
  59.219 +    }
  59.220 +
  59.221 +    /**
  59.222 +     * Closes this input stream and releases any system resources associated
  59.223 +     * with the stream.
  59.224 +     * @exception IOException if an I/O error has occurred
  59.225 +     */
  59.226 +    public void close() throws IOException {
  59.227 +        if (!closed) {
  59.228 +            if (usesDefaultInflater)
  59.229 +                inf.end();
  59.230 +            in.close();
  59.231 +            closed = true;
  59.232 +        }
  59.233 +    }
  59.234 +
  59.235 +    /**
  59.236 +     * Fills input buffer with more data to decompress.
  59.237 +     * @exception IOException if an I/O error has occurred
  59.238 +     */
  59.239 +    protected void fill() throws IOException {
  59.240 +        ensureOpen();
  59.241 +        len = in.read(buf, 0, buf.length);
  59.242 +        if (len == -1) {
  59.243 +            throw new EOFException("Unexpected end of ZLIB input stream");
  59.244 +        }
  59.245 +        inf.setInput(buf, 0, len);
  59.246 +    }
  59.247 +
  59.248 +    /**
  59.249 +     * Tests if this input stream supports the <code>mark</code> and
  59.250 +     * <code>reset</code> methods. The <code>markSupported</code>
  59.251 +     * method of <code>InflaterInputStream</code> returns
  59.252 +     * <code>false</code>.
  59.253 +     *
  59.254 +     * @return  a <code>boolean</code> indicating if this stream type supports
  59.255 +     *          the <code>mark</code> and <code>reset</code> methods.
  59.256 +     * @see     java.io.InputStream#mark(int)
  59.257 +     * @see     java.io.InputStream#reset()
  59.258 +     */
  59.259 +    public boolean markSupported() {
  59.260 +        return false;
  59.261 +    }
  59.262 +
  59.263 +    /**
  59.264 +     * Marks the current position in this input stream.
  59.265 +     *
  59.266 +     * <p> The <code>mark</code> method of <code>InflaterInputStream</code>
  59.267 +     * does nothing.
  59.268 +     *
  59.269 +     * @param   readlimit   the maximum limit of bytes that can be read before
  59.270 +     *                      the mark position becomes invalid.
  59.271 +     * @see     java.io.InputStream#reset()
  59.272 +     */
  59.273 +    public synchronized void mark(int readlimit) {
  59.274 +    }
  59.275 +
  59.276 +    /**
  59.277 +     * Repositions this stream to the position at the time the
  59.278 +     * <code>mark</code> method was last called on this input stream.
  59.279 +     *
  59.280 +     * <p> The method <code>reset</code> for class
  59.281 +     * <code>InflaterInputStream</code> does nothing except throw an
  59.282 +     * <code>IOException</code>.
  59.283 +     *
  59.284 +     * @exception  IOException  if this method is invoked.
  59.285 +     * @see     java.io.InputStream#mark(int)
  59.286 +     * @see     java.io.IOException
  59.287 +     */
  59.288 +    public synchronized void reset() throws IOException {
  59.289 +        throw new IOException("mark/reset not supported");
  59.290 +    }
  59.291 +}
    60.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.2 +++ b/emul/mini/src/main/java/java/util/zip/ZStreamRef.java	Mon Feb 04 09:37:56 2013 +0100
    60.3 @@ -0,0 +1,46 @@
    60.4 +/*
    60.5 + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
    60.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    60.7 + *
    60.8 + * This code is free software; you can redistribute it and/or modify it
    60.9 + * under the terms of the GNU General Public License version 2 only, as
   60.10 + * published by the Free Software Foundation.  Oracle designates this
   60.11 + * particular file as subject to the "Classpath" exception as provided
   60.12 + * by Oracle in the LICENSE file that accompanied this code.
   60.13 + *
   60.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   60.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   60.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   60.17 + * version 2 for more details (a copy is included in the LICENSE file that
   60.18 + * accompanied this code).
   60.19 + *
   60.20 + * You should have received a copy of the GNU General Public License version
   60.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   60.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   60.23 + *
   60.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   60.25 + * or visit www.oracle.com if you need additional information or have any
   60.26 + * questions.
   60.27 + */
   60.28 +
   60.29 +package java.util.zip;
   60.30 +
   60.31 +/**
   60.32 + * A reference to the native zlib's z_stream structure.
   60.33 + */
   60.34 +
   60.35 +class ZStreamRef {
   60.36 +
   60.37 +    private long address;
   60.38 +    ZStreamRef (long address) {
   60.39 +        this.address = address;
   60.40 +    }
   60.41 +
   60.42 +    long address() {
   60.43 +        return address;
   60.44 +    }
   60.45 +
   60.46 +    void clear() {
   60.47 +        address = 0;
   60.48 +    }
   60.49 +}
    61.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    61.2 +++ b/emul/mini/src/main/java/java/util/zip/ZipConstants.java	Mon Feb 04 09:37:56 2013 +0100
    61.3 @@ -0,0 +1,98 @@
    61.4 +/*
    61.5 + * Copyright (c) 1995, 1996, Oracle and/or its affiliates. All rights reserved.
    61.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    61.7 + *
    61.8 + * This code is free software; you can redistribute it and/or modify it
    61.9 + * under the terms of the GNU General Public License version 2 only, as
   61.10 + * published by the Free Software Foundation.  Oracle designates this
   61.11 + * particular file as subject to the "Classpath" exception as provided
   61.12 + * by Oracle in the LICENSE file that accompanied this code.
   61.13 + *
   61.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   61.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   61.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   61.17 + * version 2 for more details (a copy is included in the LICENSE file that
   61.18 + * accompanied this code).
   61.19 + *
   61.20 + * You should have received a copy of the GNU General Public License version
   61.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   61.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   61.23 + *
   61.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   61.25 + * or visit www.oracle.com if you need additional information or have any
   61.26 + * questions.
   61.27 + */
   61.28 +
   61.29 +package java.util.zip;
   61.30 +
   61.31 +/*
   61.32 + * This interface defines the constants that are used by the classes
   61.33 + * which manipulate ZIP files.
   61.34 + *
   61.35 + * @author      David Connelly
   61.36 + */
   61.37 +interface ZipConstants {
   61.38 +    /*
   61.39 +     * Header signatures
   61.40 +     */
   61.41 +    static long LOCSIG = 0x04034b50L;   // "PK\003\004"
   61.42 +    static long EXTSIG = 0x08074b50L;   // "PK\007\008"
   61.43 +    static long CENSIG = 0x02014b50L;   // "PK\001\002"
   61.44 +    static long ENDSIG = 0x06054b50L;   // "PK\005\006"
   61.45 +
   61.46 +    /*
   61.47 +     * Header sizes in bytes (including signatures)
   61.48 +     */
   61.49 +    static final int LOCHDR = 30;       // LOC header size
   61.50 +    static final int EXTHDR = 16;       // EXT header size
   61.51 +    static final int CENHDR = 46;       // CEN header size
   61.52 +    static final int ENDHDR = 22;       // END header size
   61.53 +
   61.54 +    /*
   61.55 +     * Local file (LOC) header field offsets
   61.56 +     */
   61.57 +    static final int LOCVER = 4;        // version needed to extract
   61.58 +    static final int LOCFLG = 6;        // general purpose bit flag
   61.59 +    static final int LOCHOW = 8;        // compression method
   61.60 +    static final int LOCTIM = 10;       // modification time
   61.61 +    static final int LOCCRC = 14;       // uncompressed file crc-32 value
   61.62 +    static final int LOCSIZ = 18;       // compressed size
   61.63 +    static final int LOCLEN = 22;       // uncompressed size
   61.64 +    static final int LOCNAM = 26;       // filename length
   61.65 +    static final int LOCEXT = 28;       // extra field length
   61.66 +
   61.67 +    /*
   61.68 +     * Extra local (EXT) header field offsets
   61.69 +     */
   61.70 +    static final int EXTCRC = 4;        // uncompressed file crc-32 value
   61.71 +    static final int EXTSIZ = 8;        // compressed size
   61.72 +    static final int EXTLEN = 12;       // uncompressed size
   61.73 +
   61.74 +    /*
   61.75 +     * Central directory (CEN) header field offsets
   61.76 +     */
   61.77 +    static final int CENVEM = 4;        // version made by
   61.78 +    static final int CENVER = 6;        // version needed to extract
   61.79 +    static final int CENFLG = 8;        // encrypt, decrypt flags
   61.80 +    static final int CENHOW = 10;       // compression method
   61.81 +    static final int CENTIM = 12;       // modification time
   61.82 +    static final int CENCRC = 16;       // uncompressed file crc-32 value
   61.83 +    static final int CENSIZ = 20;       // compressed size
   61.84 +    static final int CENLEN = 24;       // uncompressed size
   61.85 +    static final int CENNAM = 28;       // filename length
   61.86 +    static final int CENEXT = 30;       // extra field length
   61.87 +    static final int CENCOM = 32;       // comment length
   61.88 +    static final int CENDSK = 34;       // disk number start
   61.89 +    static final int CENATT = 36;       // internal file attributes
   61.90 +    static final int CENATX = 38;       // external file attributes
   61.91 +    static final int CENOFF = 42;       // LOC header offset
   61.92 +
   61.93 +    /*
   61.94 +     * End of central directory (END) header field offsets
   61.95 +     */
   61.96 +    static final int ENDSUB = 8;        // number of entries on this disk
   61.97 +    static final int ENDTOT = 10;       // total number of entries
   61.98 +    static final int ENDSIZ = 12;       // central directory size in bytes
   61.99 +    static final int ENDOFF = 16;       // offset of first CEN header
  61.100 +    static final int ENDCOM = 20;       // zip file comment length
  61.101 +}
    62.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.2 +++ b/emul/mini/src/main/java/java/util/zip/ZipConstants64.java	Mon Feb 04 09:37:56 2013 +0100
    62.3 @@ -0,0 +1,84 @@
    62.4 +/*
    62.5 + * Copyright (c) 1995, 1996, Oracle and/or its affiliates. All rights reserved.
    62.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    62.7 + *
    62.8 + * This code is free software; you can redistribute it and/or modify it
    62.9 + * under the terms of the GNU General Public License version 2 only, as
   62.10 + * published by the Free Software Foundation.  Oracle designates this
   62.11 + * particular file as subject to the "Classpath" exception as provided
   62.12 + * by Oracle in the LICENSE file that accompanied this code.
   62.13 + *
   62.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   62.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   62.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   62.17 + * version 2 for more details (a copy is included in the LICENSE file that
   62.18 + * accompanied this code).
   62.19 + *
   62.20 + * You should have received a copy of the GNU General Public License version
   62.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   62.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   62.23 + *
   62.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   62.25 + * or visit www.oracle.com if you need additional information or have any
   62.26 + * questions.
   62.27 + */
   62.28 +
   62.29 +package java.util.zip;
   62.30 +
   62.31 +/*
   62.32 + * This class defines the constants that are used by the classes
   62.33 + * which manipulate Zip64 files.
   62.34 + */
   62.35 +
   62.36 +class ZipConstants64 {
   62.37 +
   62.38 +    /*
   62.39 +     * ZIP64 constants
   62.40 +     */
   62.41 +    static final long ZIP64_ENDSIG = 0x06064b50L;  // "PK\006\006"
   62.42 +    static final long ZIP64_LOCSIG = 0x07064b50L;  // "PK\006\007"
   62.43 +    static final int  ZIP64_ENDHDR = 56;           // ZIP64 end header size
   62.44 +    static final int  ZIP64_LOCHDR = 20;           // ZIP64 end loc header size
   62.45 +    static final int  ZIP64_EXTHDR = 24;           // EXT header size
   62.46 +    static final int  ZIP64_EXTID  = 0x0001;       // Extra field Zip64 header ID
   62.47 +
   62.48 +    static final int  ZIP64_MAGICCOUNT = 0xFFFF;
   62.49 +    static final long ZIP64_MAGICVAL = 0xFFFFFFFFL;
   62.50 +
   62.51 +    /*
   62.52 +     * Zip64 End of central directory (END) header field offsets
   62.53 +     */
   62.54 +    static final int  ZIP64_ENDLEN = 4;       // size of zip64 end of central dir
   62.55 +    static final int  ZIP64_ENDVEM = 12;      // version made by
   62.56 +    static final int  ZIP64_ENDVER = 14;      // version needed to extract
   62.57 +    static final int  ZIP64_ENDNMD = 16;      // number of this disk
   62.58 +    static final int  ZIP64_ENDDSK = 20;      // disk number of start
   62.59 +    static final int  ZIP64_ENDTOD = 24;      // total number of entries on this disk
   62.60 +    static final int  ZIP64_ENDTOT = 32;      // total number of entries
   62.61 +    static final int  ZIP64_ENDSIZ = 40;      // central directory size in bytes
   62.62 +    static final int  ZIP64_ENDOFF = 48;      // offset of first CEN header
   62.63 +    static final int  ZIP64_ENDEXT = 56;      // zip64 extensible data sector
   62.64 +
   62.65 +    /*
   62.66 +     * Zip64 End of central directory locator field offsets
   62.67 +     */
   62.68 +    static final int  ZIP64_LOCDSK = 4;       // disk number start
   62.69 +    static final int  ZIP64_LOCOFF = 8;       // offset of zip64 end
   62.70 +    static final int  ZIP64_LOCTOT = 16;      // total number of disks
   62.71 +
   62.72 +    /*
   62.73 +     * Zip64 Extra local (EXT) header field offsets
   62.74 +     */
   62.75 +    static final int  ZIP64_EXTCRC = 4;       // uncompressed file crc-32 value
   62.76 +    static final int  ZIP64_EXTSIZ = 8;       // compressed size, 8-byte
   62.77 +    static final int  ZIP64_EXTLEN = 16;      // uncompressed size, 8-byte
   62.78 +
   62.79 +    /*
   62.80 +     * Language encoding flag EFS
   62.81 +     */
   62.82 +    static final int EFS = 0x800;       // If this bit is set the filename and
   62.83 +                                        // comment fields for this file must be
   62.84 +                                        // encoded using UTF-8.
   62.85 +
   62.86 +    private ZipConstants64() {}
   62.87 +}
    63.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.2 +++ b/emul/mini/src/main/java/java/util/zip/ZipEntry.java	Mon Feb 04 09:37:56 2013 +0100
    63.3 @@ -0,0 +1,331 @@
    63.4 +/*
    63.5 + * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
    63.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    63.7 + *
    63.8 + * This code is free software; you can redistribute it and/or modify it
    63.9 + * under the terms of the GNU General Public License version 2 only, as
   63.10 + * published by the Free Software Foundation.  Oracle designates this
   63.11 + * particular file as subject to the "Classpath" exception as provided
   63.12 + * by Oracle in the LICENSE file that accompanied this code.
   63.13 + *
   63.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   63.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   63.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   63.17 + * version 2 for more details (a copy is included in the LICENSE file that
   63.18 + * accompanied this code).
   63.19 + *
   63.20 + * You should have received a copy of the GNU General Public License version
   63.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   63.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   63.23 + *
   63.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   63.25 + * or visit www.oracle.com if you need additional information or have any
   63.26 + * questions.
   63.27 + */
   63.28 +
   63.29 +package java.util.zip;
   63.30 +
   63.31 +/**
   63.32 + * This class is used to represent a ZIP file entry.
   63.33 + *
   63.34 + * @author      David Connelly
   63.35 + */
   63.36 +public
   63.37 +class ZipEntry implements ZipConstants, Cloneable {
   63.38 +    String name;        // entry name
   63.39 +    long time = -1;     // modification time (in DOS time)
   63.40 +    long crc = -1;      // crc-32 of entry data
   63.41 +    long size = -1;     // uncompressed size of entry data
   63.42 +    long csize = -1;    // compressed size of entry data
   63.43 +    int method = -1;    // compression method
   63.44 +    int flag = 0;       // general purpose flag
   63.45 +    byte[] extra;       // optional extra field data for entry
   63.46 +    String comment;     // optional comment string for entry
   63.47 +
   63.48 +    /**
   63.49 +     * Compression method for uncompressed entries.
   63.50 +     */
   63.51 +    public static final int STORED = 0;
   63.52 +
   63.53 +    /**
   63.54 +     * Compression method for compressed (deflated) entries.
   63.55 +     */
   63.56 +    public static final int DEFLATED = 8;
   63.57 +
   63.58 +    /**
   63.59 +     * Creates a new zip entry with the specified name.
   63.60 +     *
   63.61 +     * @param name the entry name
   63.62 +     * @exception NullPointerException if the entry name is null
   63.63 +     * @exception IllegalArgumentException if the entry name is longer than
   63.64 +     *            0xFFFF bytes
   63.65 +     */
   63.66 +    public ZipEntry(String name) {
   63.67 +        if (name == null) {
   63.68 +            throw new NullPointerException();
   63.69 +        }
   63.70 +        if (name.length() > 0xFFFF) {
   63.71 +            throw new IllegalArgumentException("entry name too long");
   63.72 +        }
   63.73 +        this.name = name;
   63.74 +    }
   63.75 +
   63.76 +    /**
   63.77 +     * Creates a new zip entry with fields taken from the specified
   63.78 +     * zip entry.
   63.79 +     * @param e a zip Entry object
   63.80 +     */
   63.81 +    public ZipEntry(ZipEntry e) {
   63.82 +        name = e.name;
   63.83 +        time = e.time;
   63.84 +        crc = e.crc;
   63.85 +        size = e.size;
   63.86 +        csize = e.csize;
   63.87 +        method = e.method;
   63.88 +        flag = e.flag;
   63.89 +        extra = e.extra;
   63.90 +        comment = e.comment;
   63.91 +    }
   63.92 +
   63.93 +    /*
   63.94 +     * Creates a new un-initialized zip entry
   63.95 +     */
   63.96 +    ZipEntry() {}
   63.97 +
   63.98 +    /**
   63.99 +     * Returns the name of the entry.
  63.100 +     * @return the name of the entry
  63.101 +     */
  63.102 +    public String getName() {
  63.103 +        return name;
  63.104 +    }
  63.105 +
  63.106 +    /**
  63.107 +     * Sets the modification time of the entry.
  63.108 +     * @param time the entry modification time in number of milliseconds
  63.109 +     *             since the epoch
  63.110 +     * @see #getTime()
  63.111 +     */
  63.112 +    public void setTime(long time) {
  63.113 +        this.time = javaToDosTime(time);
  63.114 +    }
  63.115 +
  63.116 +    /**
  63.117 +     * Returns the modification time of the entry, or -1 if not specified.
  63.118 +     * @return the modification time of the entry, or -1 if not specified
  63.119 +     * @see #setTime(long)
  63.120 +     */
  63.121 +    public long getTime() {
  63.122 +        return time != -1 ? dosToJavaTime(time) : -1;
  63.123 +    }
  63.124 +
  63.125 +    /**
  63.126 +     * Sets the uncompressed size of the entry data.
  63.127 +     * @param size the uncompressed size in bytes
  63.128 +     * @exception IllegalArgumentException if the specified size is less
  63.129 +     *            than 0, is greater than 0xFFFFFFFF when
  63.130 +     *            <a href="package-summary.html#zip64">ZIP64 format</a> is not supported,
  63.131 +     *            or is less than 0 when ZIP64 is supported
  63.132 +     * @see #getSize()
  63.133 +     */
  63.134 +    public void setSize(long size) {
  63.135 +        if (size < 0) {
  63.136 +            throw new IllegalArgumentException("invalid entry size");
  63.137 +        }
  63.138 +        this.size = size;
  63.139 +    }
  63.140 +
  63.141 +    /**
  63.142 +     * Returns the uncompressed size of the entry data, or -1 if not known.
  63.143 +     * @return the uncompressed size of the entry data, or -1 if not known
  63.144 +     * @see #setSize(long)
  63.145 +     */
  63.146 +    public long getSize() {
  63.147 +        return size;
  63.148 +    }
  63.149 +
  63.150 +    /**
  63.151 +     * Returns the size of the compressed entry data, or -1 if not known.
  63.152 +     * In the case of a stored entry, the compressed size will be the same
  63.153 +     * as the uncompressed size of the entry.
  63.154 +     * @return the size of the compressed entry data, or -1 if not known
  63.155 +     * @see #setCompressedSize(long)
  63.156 +     */
  63.157 +    public long getCompressedSize() {
  63.158 +        return csize;
  63.159 +    }
  63.160 +
  63.161 +    /**
  63.162 +     * Sets the size of the compressed entry data.
  63.163 +     * @param csize the compressed size to set to
  63.164 +     * @see #getCompressedSize()
  63.165 +     */
  63.166 +    public void setCompressedSize(long csize) {
  63.167 +        this.csize = csize;
  63.168 +    }
  63.169 +
  63.170 +    /**
  63.171 +     * Sets the CRC-32 checksum of the uncompressed entry data.
  63.172 +     * @param crc the CRC-32 value
  63.173 +     * @exception IllegalArgumentException if the specified CRC-32 value is
  63.174 +     *            less than 0 or greater than 0xFFFFFFFF
  63.175 +     * @see #getCrc()
  63.176 +     */
  63.177 +    public void setCrc(long crc) {
  63.178 +        if (crc < 0 || crc > 0xFFFFFFFFL) {
  63.179 +            throw new IllegalArgumentException("invalid entry crc-32");
  63.180 +        }
  63.181 +        this.crc = crc;
  63.182 +    }
  63.183 +
  63.184 +    /**
  63.185 +     * Returns the CRC-32 checksum of the uncompressed entry data, or -1 if
  63.186 +     * not known.
  63.187 +     * @return the CRC-32 checksum of the uncompressed entry data, or -1 if
  63.188 +     * not known
  63.189 +     * @see #setCrc(long)
  63.190 +     */
  63.191 +    public long getCrc() {
  63.192 +        return crc;
  63.193 +    }
  63.194 +
  63.195 +    /**
  63.196 +     * Sets the compression method for the entry.
  63.197 +     * @param method the compression method, either STORED or DEFLATED
  63.198 +     * @exception IllegalArgumentException if the specified compression
  63.199 +     *            method is invalid
  63.200 +     * @see #getMethod()
  63.201 +     */
  63.202 +    public void setMethod(int method) {
  63.203 +        if (method != STORED && method != DEFLATED) {
  63.204 +            throw new IllegalArgumentException("invalid compression method");
  63.205 +        }
  63.206 +        this.method = method;
  63.207 +    }
  63.208 +
  63.209 +    /**
  63.210 +     * Returns the compression method of the entry, or -1 if not specified.
  63.211 +     * @return the compression method of the entry, or -1 if not specified
  63.212 +     * @see #setMethod(int)
  63.213 +     */
  63.214 +    public int getMethod() {
  63.215 +        return method;
  63.216 +    }
  63.217 +
  63.218 +    /**
  63.219 +     * Sets the optional extra field data for the entry.
  63.220 +     * @param extra the extra field data bytes
  63.221 +     * @exception IllegalArgumentException if the length of the specified
  63.222 +     *            extra field data is greater than 0xFFFF bytes
  63.223 +     * @see #getExtra()
  63.224 +     */
  63.225 +    public void setExtra(byte[] extra) {
  63.226 +        if (extra != null && extra.length > 0xFFFF) {
  63.227 +            throw new IllegalArgumentException("invalid extra field length");
  63.228 +        }
  63.229 +        this.extra = extra;
  63.230 +    }
  63.231 +
  63.232 +    /**
  63.233 +     * Returns the extra field data for the entry, or null if none.
  63.234 +     * @return the extra field data for the entry, or null if none
  63.235 +     * @see #setExtra(byte[])
  63.236 +     */
  63.237 +    public byte[] getExtra() {
  63.238 +        return extra;
  63.239 +    }
  63.240 +
  63.241 +    /**
  63.242 +     * Sets the optional comment string for the entry.
  63.243 +     *
  63.244 +     * <p>ZIP entry comments have maximum length of 0xffff. If the length of the
  63.245 +     * specified comment string is greater than 0xFFFF bytes after encoding, only
  63.246 +     * the first 0xFFFF bytes are output to the ZIP file entry.
  63.247 +     *
  63.248 +     * @param comment the comment string
  63.249 +     *
  63.250 +     * @see #getComment()
  63.251 +     */
  63.252 +    public void setComment(String comment) {
  63.253 +        this.comment = comment;
  63.254 +    }
  63.255 +
  63.256 +    /**
  63.257 +     * Returns the comment string for the entry, or null if none.
  63.258 +     * @return the comment string for the entry, or null if none
  63.259 +     * @see #setComment(String)
  63.260 +     */
  63.261 +    public String getComment() {
  63.262 +        return comment;
  63.263 +    }
  63.264 +
  63.265 +    /**
  63.266 +     * Returns true if this is a directory entry. A directory entry is
  63.267 +     * defined to be one whose name ends with a '/'.
  63.268 +     * @return true if this is a directory entry
  63.269 +     */
  63.270 +    public boolean isDirectory() {
  63.271 +        return name.endsWith("/");
  63.272 +    }
  63.273 +
  63.274 +    /**
  63.275 +     * Returns a string representation of the ZIP entry.
  63.276 +     */
  63.277 +    public String toString() {
  63.278 +        return getName();
  63.279 +    }
  63.280 +
  63.281 +    /*
  63.282 +     * Converts DOS time to Java time (number of milliseconds since epoch).
  63.283 +     */
  63.284 +    private static long dosToJavaTime(long dtime) {
  63.285 +        return dtime;
  63.286 +        /* XXX:
  63.287 +        Date d = new Date((int)(((dtime >> 25) & 0x7f) + 80),
  63.288 +                          (int)(((dtime >> 21) & 0x0f) - 1),
  63.289 +                          (int)((dtime >> 16) & 0x1f),
  63.290 +                          (int)((dtime >> 11) & 0x1f),
  63.291 +                          (int)((dtime >> 5) & 0x3f),
  63.292 +                          (int)((dtime << 1) & 0x3e));
  63.293 +        return d.getTime();
  63.294 +        */
  63.295 +    }
  63.296 +
  63.297 +    /*
  63.298 +     * Converts Java time to DOS time.
  63.299 +     */
  63.300 +    private static long javaToDosTime(long time) {
  63.301 +        return time;
  63.302 +        /* XXX:
  63.303 +        Date d = new Date(time);
  63.304 +        int year = d.getYear() + 1900;
  63.305 +        if (year < 1980) {
  63.306 +            return (1 << 21) | (1 << 16);
  63.307 +        }
  63.308 +        return (year - 1980) << 25 | (d.getMonth() + 1) << 21 |
  63.309 +               d.getDate() << 16 | d.getHours() << 11 | d.getMinutes() << 5 |
  63.310 +               d.getSeconds() >> 1;
  63.311 +        */
  63.312 +    }
  63.313 +
  63.314 +    /**
  63.315 +     * Returns the hash code value for this entry.
  63.316 +     */
  63.317 +    public int hashCode() {
  63.318 +        return name.hashCode();
  63.319 +    }
  63.320 +
  63.321 +    /**
  63.322 +     * Returns a copy of this entry.
  63.323 +     */
  63.324 +    public Object clone() {
  63.325 +        try {
  63.326 +            ZipEntry e = (ZipEntry)super.clone();
  63.327 +            e.extra = (extra == null) ? null : extra.clone();
  63.328 +            return e;
  63.329 +        } catch (CloneNotSupportedException e) {
  63.330 +            // This should never happen, since we are Cloneable
  63.331 +            throw new IllegalStateException();
  63.332 +        }
  63.333 +    }
  63.334 +}
    64.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    64.2 +++ b/emul/mini/src/main/java/java/util/zip/ZipException.java	Mon Feb 04 09:37:56 2013 +0100
    64.3 @@ -0,0 +1,60 @@
    64.4 +/*
    64.5 + * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
    64.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    64.7 + *
    64.8 + * This code is free software; you can redistribute it and/or modify it
    64.9 + * under the terms of the GNU General Public License version 2 only, as
   64.10 + * published by the Free Software Foundation.  Oracle designates this
   64.11 + * particular file as subject to the "Classpath" exception as provided
   64.12 + * by Oracle in the LICENSE file that accompanied this code.
   64.13 + *
   64.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   64.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   64.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   64.17 + * version 2 for more details (a copy is included in the LICENSE file that
   64.18 + * accompanied this code).
   64.19 + *
   64.20 + * You should have received a copy of the GNU General Public License version
   64.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   64.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   64.23 + *
   64.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   64.25 + * or visit www.oracle.com if you need additional information or have any
   64.26 + * questions.
   64.27 + */
   64.28 +
   64.29 +package java.util.zip;
   64.30 +
   64.31 +import java.io.IOException;
   64.32 +
   64.33 +/**
   64.34 + * Signals that a Zip exception of some sort has occurred.
   64.35 + *
   64.36 + * @author  unascribed
   64.37 + * @see     java.io.IOException
   64.38 + * @since   JDK1.0
   64.39 + */
   64.40 +
   64.41 +public
   64.42 +class ZipException extends IOException {
   64.43 +    private static final long serialVersionUID = 8000196834066748623L;
   64.44 +
   64.45 +    /**
   64.46 +     * Constructs a <code>ZipException</code> with <code>null</code>
   64.47 +     * as its error detail message.
   64.48 +     */
   64.49 +    public ZipException() {
   64.50 +        super();
   64.51 +    }
   64.52 +
   64.53 +    /**
   64.54 +     * Constructs a <code>ZipException</code> with the specified detail
   64.55 +     * message.
   64.56 +     *
   64.57 +     * @param   s   the detail message.
   64.58 +     */
   64.59 +
   64.60 +    public ZipException(String s) {
   64.61 +        super(s);
   64.62 +    }
   64.63 +}
    65.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    65.2 +++ b/emul/mini/src/main/java/java/util/zip/ZipInputStream.java	Mon Feb 04 09:37:56 2013 +0100
    65.3 @@ -0,0 +1,467 @@
    65.4 +/*
    65.5 + * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
    65.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    65.7 + *
    65.8 + * This code is free software; you can redistribute it and/or modify it
    65.9 + * under the terms of the GNU General Public License version 2 only, as
   65.10 + * published by the Free Software Foundation.  Oracle designates this
   65.11 + * particular file as subject to the "Classpath" exception as provided
   65.12 + * by Oracle in the LICENSE file that accompanied this code.
   65.13 + *
   65.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   65.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   65.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   65.17 + * version 2 for more details (a copy is included in the LICENSE file that
   65.18 + * accompanied this code).
   65.19 + *
   65.20 + * You should have received a copy of the GNU General Public License version
   65.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   65.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   65.23 + *
   65.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   65.25 + * or visit www.oracle.com if you need additional information or have any
   65.26 + * questions.
   65.27 + */
   65.28 +
   65.29 +package java.util.zip;
   65.30 +
   65.31 +import java.io.InputStream;
   65.32 +import java.io.IOException;
   65.33 +import java.io.EOFException;
   65.34 +import java.io.PushbackInputStream;
   65.35 +import static java.util.zip.ZipConstants64.*;
   65.36 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
   65.37 +
   65.38 +/**
   65.39 + * This class implements an input stream filter for reading files in the
   65.40 + * ZIP file format. Includes support for both compressed and uncompressed
   65.41 + * entries.
   65.42 + *
   65.43 + * @author      David Connelly
   65.44 + */
   65.45 +public
   65.46 +class ZipInputStream extends InflaterInputStream implements ZipConstants {
   65.47 +    private ZipEntry entry;
   65.48 +    private int flag;
   65.49 +    private CRC32 crc = new CRC32();
   65.50 +    private long remaining;
   65.51 +    private byte[] tmpbuf = new byte[512];
   65.52 +
   65.53 +    private static final int STORED = ZipEntry.STORED;
   65.54 +    private static final int DEFLATED = ZipEntry.DEFLATED;
   65.55 +
   65.56 +    private boolean closed = false;
   65.57 +    // this flag is set to true after EOF has reached for
   65.58 +    // one entry
   65.59 +    private boolean entryEOF = false;
   65.60 +
   65.61 +    /**
   65.62 +     * Check to make sure that this stream has not been closed
   65.63 +     */
   65.64 +    private void ensureOpen() throws IOException {
   65.65 +        if (closed) {
   65.66 +            throw new IOException("Stream closed");
   65.67 +        }
   65.68 +    }
   65.69 +
   65.70 +    /**
   65.71 +     * Creates a new ZIP input stream.
   65.72 +     *
   65.73 +     * <p>The UTF-8 {@link java.nio.charset.Charset charset} is used to
   65.74 +     * decode the entry names.
   65.75 +     *
   65.76 +     * @param in the actual input stream
   65.77 +     */
   65.78 +    public ZipInputStream(InputStream in) {
   65.79 +//        this(in, "UTF-8");
   65.80 +        super(new PushbackInputStream(in, 512), new Inflater(true), 512);
   65.81 +        usesDefaultInflater = true;
   65.82 +        if(in == null) {
   65.83 +            throw new NullPointerException("in is null");
   65.84 +        }
   65.85 +    }
   65.86 +
   65.87 +    /**
   65.88 +     * Creates a new ZIP input stream.
   65.89 +     *
   65.90 +     * @param in the actual input stream
   65.91 +     *
   65.92 +     * @param charset
   65.93 +     *        The {@linkplain java.nio.charset.Charset charset} to be
   65.94 +     *        used to decode the ZIP entry name (ignored if the
   65.95 +     *        <a href="package-summary.html#lang_encoding"> language
   65.96 +     *        encoding bit</a> of the ZIP entry's general purpose bit
   65.97 +     *        flag is set).
   65.98 +     *
   65.99 +     * @since 1.7
  65.100 +     *
  65.101 +    public ZipInputStream(InputStream in, Charset charset) {
  65.102 +        super(new PushbackInputStream(in, 512), new Inflater(true), 512);
  65.103 +        usesDefaultInflater = true;
  65.104 +        if(in == null) {
  65.105 +            throw new NullPointerException("in is null");
  65.106 +        }
  65.107 +        if (charset == null)
  65.108 +            throw new NullPointerException("charset is null");
  65.109 +        this.zc = ZipCoder.get(charset);
  65.110 +    }
  65.111 +    */
  65.112 +
  65.113 +    /**
  65.114 +     * Reads the next ZIP file entry and positions the stream at the
  65.115 +     * beginning of the entry data.
  65.116 +     * @return the next ZIP file entry, or null if there are no more entries
  65.117 +     * @exception ZipException if a ZIP file error has occurred
  65.118 +     * @exception IOException if an I/O error has occurred
  65.119 +     */
  65.120 +    public ZipEntry getNextEntry() throws IOException {
  65.121 +        ensureOpen();
  65.122 +        if (entry != null) {
  65.123 +            closeEntry();
  65.124 +        }
  65.125 +        crc.reset();
  65.126 +        inf.reset();
  65.127 +        if ((entry = readLOC()) == null) {
  65.128 +            return null;
  65.129 +        }
  65.130 +        if (entry.method == STORED) {
  65.131 +            remaining = entry.size;
  65.132 +        }
  65.133 +        entryEOF = false;
  65.134 +        return entry;
  65.135 +    }
  65.136 +
  65.137 +    /**
  65.138 +     * Closes the current ZIP entry and positions the stream for reading the
  65.139 +     * next entry.
  65.140 +     * @exception ZipException if a ZIP file error has occurred
  65.141 +     * @exception IOException if an I/O error has occurred
  65.142 +     */
  65.143 +    public void closeEntry() throws IOException {
  65.144 +        ensureOpen();
  65.145 +        while (read(tmpbuf, 0, tmpbuf.length) != -1) ;
  65.146 +        entryEOF = true;
  65.147 +    }
  65.148 +
  65.149 +    /**
  65.150 +     * Returns 0 after EOF has reached for the current entry data,
  65.151 +     * otherwise always return 1.
  65.152 +     * <p>
  65.153 +     * Programs should not count on this method to return the actual number
  65.154 +     * of bytes that could be read without blocking.
  65.155 +     *
  65.156 +     * @return     1 before EOF and 0 after EOF has reached for current entry.
  65.157 +     * @exception  IOException  if an I/O error occurs.
  65.158 +     *
  65.159 +     */
  65.160 +    public int available() throws IOException {
  65.161 +        ensureOpen();
  65.162 +        if (entryEOF) {
  65.163 +            return 0;
  65.164 +        } else {
  65.165 +            return 1;
  65.166 +        }
  65.167 +    }
  65.168 +
  65.169 +    /**
  65.170 +     * Reads from the current ZIP entry into an array of bytes.
  65.171 +     * If <code>len</code> is not zero, the method
  65.172 +     * blocks until some input is available; otherwise, no
  65.173 +     * bytes are read and <code>0</code> is returned.
  65.174 +     * @param b the buffer into which the data is read
  65.175 +     * @param off the start offset in the destination array <code>b</code>
  65.176 +     * @param len the maximum number of bytes read
  65.177 +     * @return the actual number of bytes read, or -1 if the end of the
  65.178 +     *         entry is reached
  65.179 +     * @exception  NullPointerException if <code>b</code> is <code>null</code>.
  65.180 +     * @exception  IndexOutOfBoundsException if <code>off</code> is negative,
  65.181 +     * <code>len</code> is negative, or <code>len</code> is greater than
  65.182 +     * <code>b.length - off</code>
  65.183 +     * @exception ZipException if a ZIP file error has occurred
  65.184 +     * @exception IOException if an I/O error has occurred
  65.185 +     */
  65.186 +    public int read(byte[] b, int off, int len) throws IOException {
  65.187 +        ensureOpen();
  65.188 +        if (off < 0 || len < 0 || off > b.length - len) {
  65.189 +            throw new IndexOutOfBoundsException();
  65.190 +        } else if (len == 0) {
  65.191 +            return 0;
  65.192 +        }
  65.193 +
  65.194 +        if (entry == null) {
  65.195 +            return -1;
  65.196 +        }
  65.197 +        switch (entry.method) {
  65.198 +        case DEFLATED:
  65.199 +            len = super.read(b, off, len);
  65.200 +            if (len == -1) {
  65.201 +                readEnd(entry);
  65.202 +                entryEOF = true;
  65.203 +                entry = null;
  65.204 +            } else {
  65.205 +                crc.update(b, off, len);
  65.206 +            }
  65.207 +            return len;
  65.208 +        case STORED:
  65.209 +            if (remaining <= 0) {
  65.210 +                entryEOF = true;
  65.211 +                entry = null;
  65.212 +                return -1;
  65.213 +            }
  65.214 +            if (len > remaining) {
  65.215 +                len = (int)remaining;
  65.216 +            }
  65.217 +            len = in.read(b, off, len);
  65.218 +            if (len == -1) {
  65.219 +                throw new ZipException("unexpected EOF");
  65.220 +            }
  65.221 +            crc.update(b, off, len);
  65.222 +            remaining -= len;
  65.223 +            if (remaining == 0 && entry.crc != crc.getValue()) {
  65.224 +                throw new ZipException(
  65.225 +                    "invalid entry CRC (expected 0x" + Long.toHexString(entry.crc) +
  65.226 +                    " but got 0x" + Long.toHexString(crc.getValue()) + ")");
  65.227 +            }
  65.228 +            return len;
  65.229 +        default:
  65.230 +            throw new ZipException("invalid compression method");
  65.231 +        }
  65.232 +    }
  65.233 +
  65.234 +    /**
  65.235 +     * Skips specified number of bytes in the current ZIP entry.
  65.236 +     * @param n the number of bytes to skip
  65.237 +     * @return the actual number of bytes skipped
  65.238 +     * @exception ZipException if a ZIP file error has occurred
  65.239 +     * @exception IOException if an I/O error has occurred
  65.240 +     * @exception IllegalArgumentException if n < 0
  65.241 +     */
  65.242 +    public long skip(long n) throws IOException {
  65.243 +        if (n < 0) {
  65.244 +            throw new IllegalArgumentException("negative skip length");
  65.245 +        }
  65.246 +        ensureOpen();
  65.247 +        int max = (int)Math.min(n, Integer.MAX_VALUE);
  65.248 +        int total = 0;
  65.249 +        while (total < max) {
  65.250 +            int len = max - total;
  65.251 +            if (len > tmpbuf.length) {
  65.252 +                len = tmpbuf.length;
  65.253 +            }
  65.254 +            len = read(tmpbuf, 0, len);
  65.255 +            if (len == -1) {
  65.256 +                entryEOF = true;
  65.257 +                break;
  65.258 +            }
  65.259 +            total += len;
  65.260 +        }
  65.261 +        return total;
  65.262 +    }
  65.263 +
  65.264 +    /**
  65.265 +     * Closes this input stream and releases any system resources associated
  65.266 +     * with the stream.
  65.267 +     * @exception IOException if an I/O error has occurred
  65.268 +     */
  65.269 +    public void close() throws IOException {
  65.270 +        if (!closed) {
  65.271 +            super.close();
  65.272 +            closed = true;
  65.273 +        }
  65.274 +    }
  65.275 +
  65.276 +    private byte[] b = new byte[256];
  65.277 +
  65.278 +    /*
  65.279 +     * Reads local file (LOC) header for next entry.
  65.280 +     */
  65.281 +    private ZipEntry readLOC() throws IOException {
  65.282 +        try {
  65.283 +            readFully(tmpbuf, 0, LOCHDR);
  65.284 +        } catch (EOFException e) {
  65.285 +            return null;
  65.286 +        }
  65.287 +        if (get32(tmpbuf, 0) != LOCSIG) {
  65.288 +            return null;
  65.289 +        }
  65.290 +        // get flag first, we need check EFS.
  65.291 +        flag = get16(tmpbuf, LOCFLG);
  65.292 +        // get the entry name and create the ZipEntry first
  65.293 +        int len = get16(tmpbuf, LOCNAM);
  65.294 +        int blen = b.length;
  65.295 +        if (len > blen) {
  65.296 +            do
  65.297 +                blen = blen * 2;
  65.298 +            while (len > blen);
  65.299 +            b = new byte[blen];
  65.300 +        }
  65.301 +        readFully(b, 0, len);
  65.302 +        // Force to use UTF-8 if the EFS bit is ON, even the cs is NOT UTF-8
  65.303 +        ZipEntry e = createZipEntry(((flag & EFS) != 0)
  65.304 +                                    ? toStringUTF8(b, len)
  65.305 +                                    : toString(b, len));
  65.306 +        // now get the remaining fields for the entry
  65.307 +        if ((flag & 1) == 1) {
  65.308 +            throw new ZipException("encrypted ZIP entry not supported");
  65.309 +        }
  65.310 +        e.method = get16(tmpbuf, LOCHOW);
  65.311 +        e.time = get32(tmpbuf, LOCTIM);
  65.312 +        if ((flag & 8) == 8) {
  65.313 +            /* "Data Descriptor" present */
  65.314 +            if (e.method != DEFLATED) {
  65.315 +                throw new ZipException(
  65.316 +                        "only DEFLATED entries can have EXT descriptor");
  65.317 +            }
  65.318 +        } else {
  65.319 +            e.crc = get32(tmpbuf, LOCCRC);
  65.320 +            e.csize = get32(tmpbuf, LOCSIZ);
  65.321 +            e.size = get32(tmpbuf, LOCLEN);
  65.322 +        }
  65.323 +        len = get16(tmpbuf, LOCEXT);
  65.324 +        if (len > 0) {
  65.325 +            byte[] bb = new byte[len];
  65.326 +            readFully(bb, 0, len);
  65.327 +            e.setExtra(bb);
  65.328 +            // extra fields are in "HeaderID(2)DataSize(2)Data... format
  65.329 +            if (e.csize == ZIP64_MAGICVAL || e.size == ZIP64_MAGICVAL) {
  65.330 +                int off = 0;
  65.331 +                while (off + 4 < len) {
  65.332 +                    int sz = get16(bb, off + 2);
  65.333 +                    if (get16(bb, off) == ZIP64_EXTID) {
  65.334 +                        off += 4;
  65.335 +                        // LOC extra zip64 entry MUST include BOTH original and
  65.336 +                        // compressed file size fields
  65.337 +                        if (sz < 16 || (off + sz) > len ) {
  65.338 +                            // Invalid zip64 extra fields, simply skip. Even it's
  65.339 +                            // rare, it's possible the entry size happens to be
  65.340 +                            // the magic value and it "accidnetly" has some bytes
  65.341 +                            // in extra match the id.
  65.342 +                            return e;
  65.343 +                        }
  65.344 +                        e.size = get64(bb, off);
  65.345 +                        e.csize = get64(bb, off + 8);
  65.346 +                        break;
  65.347 +                    }
  65.348 +                    off += (sz + 4);
  65.349 +                }
  65.350 +            }
  65.351 +        }
  65.352 +        return e;
  65.353 +    }
  65.354 +
  65.355 +    /**
  65.356 +     * Creates a new <code>ZipEntry</code> object for the specified
  65.357 +     * entry name.
  65.358 +     *
  65.359 +     * @param name the ZIP file entry name
  65.360 +     * @return the ZipEntry just created
  65.361 +     */
  65.362 +    protected ZipEntry createZipEntry(String name) {
  65.363 +        return new ZipEntry(name);
  65.364 +    }
  65.365 +
  65.366 +    /*
  65.367 +     * Reads end of deflated entry as well as EXT descriptor if present.
  65.368 +     */
  65.369 +    private void readEnd(ZipEntry e) throws IOException {
  65.370 +        int n = inf.getRemaining();
  65.371 +        if (n > 0) {
  65.372 +            ((PushbackInputStream)in).unread(buf, len - n, n);
  65.373 +        }
  65.374 +        if ((flag & 8) == 8) {
  65.375 +            /* "Data Descriptor" present */
  65.376 +            if (inf.getBytesWritten() > ZIP64_MAGICVAL ||
  65.377 +                inf.getBytesRead() > ZIP64_MAGICVAL) {
  65.378 +                // ZIP64 format
  65.379 +                readFully(tmpbuf, 0, ZIP64_EXTHDR);
  65.380 +                long sig = get32(tmpbuf, 0);
  65.381 +                if (sig != EXTSIG) { // no EXTSIG present
  65.382 +                    e.crc = sig;
  65.383 +                    e.csize = get64(tmpbuf, ZIP64_EXTSIZ - ZIP64_EXTCRC);
  65.384 +                    e.size = get64(tmpbuf, ZIP64_EXTLEN - ZIP64_EXTCRC);
  65.385 +                    ((PushbackInputStream)in).unread(
  65.386 +                        tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC - 1, ZIP64_EXTCRC);
  65.387 +                } else {
  65.388 +                    e.crc = get32(tmpbuf, ZIP64_EXTCRC);
  65.389 +                    e.csize = get64(tmpbuf, ZIP64_EXTSIZ);
  65.390 +                    e.size = get64(tmpbuf, ZIP64_EXTLEN);
  65.391 +                }
  65.392 +            } else {
  65.393 +                readFully(tmpbuf, 0, EXTHDR);
  65.394 +                long sig = get32(tmpbuf, 0);
  65.395 +                if (sig != EXTSIG) { // no EXTSIG present
  65.396 +                    e.crc = sig;
  65.397 +                    e.csize = get32(tmpbuf, EXTSIZ - EXTCRC);
  65.398 +                    e.size = get32(tmpbuf, EXTLEN - EXTCRC);
  65.399 +                    ((PushbackInputStream)in).unread(
  65.400 +                                               tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC);
  65.401 +                } else {
  65.402 +                    e.crc = get32(tmpbuf, EXTCRC);
  65.403 +                    e.csize = get32(tmpbuf, EXTSIZ);
  65.404 +                    e.size = get32(tmpbuf, EXTLEN);
  65.405 +                }
  65.406 +            }
  65.407 +        }
  65.408 +        if (e.size != inf.getBytesWritten()) {
  65.409 +            throw new ZipException(
  65.410 +                "invalid entry size (expected " + e.size +
  65.411 +                " but got " + inf.getBytesWritten() + " bytes)");
  65.412 +        }
  65.413 +        if (e.csize != inf.getBytesRead()) {
  65.414 +            throw new ZipException(
  65.415 +                "invalid entry compressed size (expected " + e.csize +
  65.416 +                " but got " + inf.getBytesRead() + " bytes)");
  65.417 +        }
  65.418 +        if (e.crc != crc.getValue()) {
  65.419 +            throw new ZipException(
  65.420 +                "invalid entry CRC (expected 0x" + Long.toHexString(e.crc) +
  65.421 +                " but got 0x" + Long.toHexString(crc.getValue()) + ")");
  65.422 +        }
  65.423 +    }
  65.424 +
  65.425 +    /*
  65.426 +     * Reads bytes, blocking until all bytes are read.
  65.427 +     */
  65.428 +    private void readFully(byte[] b, int off, int len) throws IOException {
  65.429 +        while (len > 0) {
  65.430 +            int n = in.read(b, off, len);
  65.431 +            if (n == -1) {
  65.432 +                throw new EOFException();
  65.433 +            }
  65.434 +            off += n;
  65.435 +            len -= n;
  65.436 +        }
  65.437 +    }
  65.438 +
  65.439 +    /*
  65.440 +     * Fetches unsigned 16-bit value from byte array at specified offset.
  65.441 +     * The bytes are assumed to be in Intel (little-endian) byte order.
  65.442 +     */
  65.443 +    private static final int get16(byte b[], int off) {
  65.444 +        return (b[off] & 0xff) | ((b[off+1] & 0xff) << 8);
  65.445 +    }
  65.446 +
  65.447 +    /*
  65.448 +     * Fetches unsigned 32-bit value from byte array at specified offset.
  65.449 +     * The bytes are assumed to be in Intel (little-endian) byte order.
  65.450 +     */
  65.451 +    private static final long get32(byte b[], int off) {
  65.452 +        return (get16(b, off) | ((long)get16(b, off+2) << 16)) & 0xffffffffL;
  65.453 +    }
  65.454 +
  65.455 +    /*
  65.456 +     * Fetches signed 64-bit value from byte array at specified offset.
  65.457 +     * The bytes are assumed to be in Intel (little-endian) byte order.
  65.458 +     */
  65.459 +    private static final long get64(byte b[], int off) {
  65.460 +        return get32(b, off) | (get32(b, off+4) << 32);
  65.461 +    }
  65.462 +
  65.463 +    private static String toStringUTF8(byte[] arr, int len) {
  65.464 +        return new String(arr, 0, len);
  65.465 +    }
  65.466 +    
  65.467 +    private static String toString(byte[] b, int len) {
  65.468 +        return new String(b, 0, len);
  65.469 +    }
  65.470 +}
    66.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    66.2 +++ b/emul/mini/src/main/java/java/util/zip/package.html	Mon Feb 04 09:37:56 2013 +0100
    66.3 @@ -0,0 +1,98 @@
    66.4 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
    66.5 +<html>
    66.6 +<head>
    66.7 +<!--
    66.8 +Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
    66.9 +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   66.10 +
   66.11 +This code is free software; you can redistribute it and/or modify it
   66.12 +under the terms of the GNU General Public License version 2 only, as
   66.13 +published by the Free Software Foundation.  Oracle designates this
   66.14 +particular file as subject to the "Classpath" exception as provided
   66.15 +by Oracle in the LICENSE file that accompanied this code.
   66.16 +
   66.17 +This code is distributed in the hope that it will be useful, but WITHOUT
   66.18 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   66.19 +FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   66.20 +version 2 for more details (a copy is included in the LICENSE file that
   66.21 +accompanied this code).
   66.22 +
   66.23 +You should have received a copy of the GNU General Public License version
   66.24 +2 along with this work; if not, write to the Free Software Foundation,
   66.25 +Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   66.26 +
   66.27 +Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   66.28 +or visit www.oracle.com if you need additional information or have any
   66.29 +questions.
   66.30 +-->
   66.31 +
   66.32 +</head>
   66.33 +<body bgcolor="white">
   66.34 +
   66.35 +Provides classes for reading and writing the standard ZIP and GZIP
   66.36 +file formats.  Also includes classes for compressing and decompressing
   66.37 +data using the DEFLATE compression algorithm, which is used by the
   66.38 +ZIP and GZIP file formats. Additionally, there are utility classes
   66.39 +for computing the CRC-32 and Adler-32 checksums of arbitrary
   66.40 +input streams.
   66.41 +
   66.42 +
   66.43 +<h2>Package Specification</h2>
   66.44 +
   66.45 +</a>
   66.46 +<ul>
   66.47 +  <li><a href="ftp://ftp.uu.net/pub/archiving/zip/doc/appnote-970311-iz.zip">
   66.48 +      Info-ZIP Application Note 970311
   66.49 +      </a> - a detailed description of the Info-ZIP format upon which
   66.50 +      the <code>java.util.zip</code> classes are based.
   66.51 +<p>
   66.52 +  <a name="zip64">
   66.53 +  <li>An implementation may optionally support the ZIP64(tm) format extensions
   66.54 +      defined by the 
   66.55 +      <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">
   66.56 +      PKWARE ZIP File Format Specification</a>. The ZIP64(tm) format extensions
   66.57 +      are used to overcome the size limitations of the original ZIP format.
   66.58 +<p>
   66.59 +  <a name="lang_encoding">
   66.60 +  <li>APPENDIX D of <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">
   66.61 +      PKWARE ZIP File Format Specification</a> - Language Encoding Flag (EFS) to
   66.62 +      encode ZIP entry filename and comment fields using UTF-8.
   66.63 +<p>
   66.64 +  <li><a href="http://www.ietf.org/rfc/rfc1950.txt">
   66.65 +      ZLIB Compressed Data Format Specification version 3.3</a>
   66.66 +      &nbsp;
   66.67 +      <a href="http://www.ietf.org/rfc/rfc1950.txt.pdf">(pdf)</a>
   66.68 +      (RFC 1950)
   66.69 +<p>
   66.70 +  <li><a href="http://www.ietf.org/rfc/rfc1951.txt">
   66.71 +      DEFLATE Compressed Data Format Specification version 1.3</a>
   66.72 +      &nbsp;
   66.73 +      <a href="http://www.ietf.org/rfc/rfc1951.txt.pdf">(pdf)</a>
   66.74 +      (RFC 1951)
   66.75 +<p>
   66.76 +  <li><a href="http://www.ietf.org/rfc/rfc1952.txt">
   66.77 +      GZIP file format specification version 4.3</a>
   66.78 +      &nbsp;
   66.79 +      <a href="http://www.ietf.org/rfc/rfc1952.txt.pdf">(pdf)</a>
   66.80 +      (RFC 1952)
   66.81 +<p>
   66.82 +  <li>CRC-32 checksum is described in RFC 1952 (above)
   66.83 +<p>
   66.84 +  <li>Adler-32 checksum is described in RFC 1950 (above)
   66.85 +</ul>
   66.86 +
   66.87 +
   66.88 +<!--
   66.89 +<h2>Related Documentation</h2>
   66.90 +
   66.91 +For overviews, tutorials, examples, guides, and tool documentation, please see:
   66.92 +<ul>
   66.93 +  <li><a href="">##### REFER TO NON-SPEC DOCUMENTATION HERE #####</a>
   66.94 +</ul>
   66.95 +-->
   66.96 +
   66.97 +@since JDK1.1
   66.98 +</body>
   66.99 +</html>
  66.100 +
  66.101 +
    67.1 --- a/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/System.java	Fri Feb 01 16:34:51 2013 +0100
    67.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/System.java	Mon Feb 04 09:37:56 2013 +0100
    67.3 @@ -51,4 +51,7 @@
    67.4      public static long nanoTime() {
    67.5          return 1000L * currentTimeMillis();
    67.6      }
    67.7 +    @JavaScriptBody(args = { "obj" }, body="return vm.java_lang_Object(false).hashCode__I.call(obj);")
    67.8 +    public static native int identityHashCode(Object obj);
    67.9 +    
   67.10  }
    68.1 --- a/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/MethodImpl.java	Fri Feb 01 16:34:51 2013 +0100
    68.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/MethodImpl.java	Mon Feb 04 09:37:56 2013 +0100
    68.3 @@ -1,26 +1,19 @@
    68.4 -/*
    68.5 - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
    68.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    68.7 +/**
    68.8 + * Back 2 Browser Bytecode Translator
    68.9 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   68.10   *
   68.11 - * This code is free software; you can redistribute it and/or modify it
   68.12 - * under the terms of the GNU General Public License version 2 only, as
   68.13 - * published by the Free Software Foundation.  Oracle designates this
   68.14 - * particular file as subject to the "Classpath" exception as provided
   68.15 - * by Oracle in the LICENSE file that accompanied this code.
   68.16 + * This program is free software: you can redistribute it and/or modify
   68.17 + * it under the terms of the GNU General Public License as published by
   68.18 + * the Free Software Foundation, version 2 of the License.
   68.19   *
   68.20 - * This code is distributed in the hope that it will be useful, but WITHOUT
   68.21 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   68.22 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   68.23 - * version 2 for more details (a copy is included in the LICENSE file that
   68.24 - * accompanied this code).
   68.25 + * This program is distributed in the hope that it will be useful,
   68.26 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   68.27 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   68.28 + * GNU General Public License for more details.
   68.29   *
   68.30 - * You should have received a copy of the GNU General Public License version
   68.31 - * 2 along with this work; if not, write to the Free Software Foundation,
   68.32 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   68.33 - *
   68.34 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   68.35 - * or visit www.oracle.com if you need additional information or have any
   68.36 - * questions.
   68.37 + * You should have received a copy of the GNU General Public License
   68.38 + * along with this program. Look for COPYING file in the top folder.
   68.39 + * If not, see http://opensource.org/licenses/GPL-2.0.
   68.40   */
   68.41  package org.apidesign.bck2brwsr.emul.reflect;
   68.42  
    69.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    69.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/TypeProvider.java	Mon Feb 04 09:37:56 2013 +0100
    69.3 @@ -0,0 +1,40 @@
    69.4 +/**
    69.5 + * Back 2 Browser Bytecode Translator
    69.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    69.7 + *
    69.8 + * This program is free software: you can redistribute it and/or modify
    69.9 + * it under the terms of the GNU General Public License as published by
   69.10 + * the Free Software Foundation, version 2 of the License.
   69.11 + *
   69.12 + * This program is distributed in the hope that it will be useful,
   69.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   69.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   69.15 + * GNU General Public License for more details.
   69.16 + *
   69.17 + * You should have received a copy of the GNU General Public License
   69.18 + * along with this program. Look for COPYING file in the top folder.
   69.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   69.20 + */
   69.21 +package org.apidesign.bck2brwsr.emul.reflect;
   69.22 +
   69.23 +import java.lang.reflect.Constructor;
   69.24 +import java.lang.reflect.Type;
   69.25 +import java.lang.reflect.TypeVariable;
   69.26 +
   69.27 +/**
   69.28 + *
   69.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   69.30 + */
   69.31 +public abstract class TypeProvider {
   69.32 +    private TypeProvider() {
   69.33 +    }
   69.34 +    
   69.35 +    public static TypeProvider getDefault() {
   69.36 +        return null;
   69.37 +    }
   69.38 +    
   69.39 +    public abstract <T> TypeVariable<Constructor<T>>[] getTypeParameters(Constructor<T> c);
   69.40 +    public abstract <T> Type[] getGenericParameterTypes(Constructor<T> c);
   69.41 +    public abstract <T> Type[] getGenericExceptionTypes(Constructor<T> c);
   69.42 +    
   69.43 +}
    70.1 --- a/javaquery/api/pom.xml	Fri Feb 01 16:34:51 2013 +0100
    70.2 +++ b/javaquery/api/pom.xml	Mon Feb 04 09:37:56 2013 +0100
    70.3 @@ -43,6 +43,7 @@
    70.4      <dependency>
    70.5        <groupId>org.netbeans.api</groupId>
    70.6        <artifactId>org-openide-util-lookup</artifactId>
    70.7 +      <scope>provided</scope>
    70.8      </dependency>
    70.9      <dependency>
   70.10        <groupId>org.apidesign.bck2brwsr</groupId>
    71.1 --- a/javaquery/demo-calculator/nbactions.xml	Fri Feb 01 16:34:51 2013 +0100
    71.2 +++ b/javaquery/demo-calculator/nbactions.xml	Mon Feb 04 09:37:56 2013 +0100
    71.3 @@ -23,7 +23,7 @@
    71.4              <actionName>run</actionName>
    71.5              <goals>
    71.6                  <goal>process-classes</goal>
    71.7 -                <goal>org.codehaus.mojo:exec-maven-plugin:1.2.1:exec</goal>
    71.8 +                <goal>org.apidesign.bck2brwsr:mojo:0.3-SNAPSHOT:brwsr</goal>
    71.9              </goals>
   71.10          </action>
   71.11      </actions>
    72.1 --- a/javaquery/demo-calculator/pom.xml	Fri Feb 01 16:34:51 2013 +0100
    72.2 +++ b/javaquery/demo-calculator/pom.xml	Mon Feb 04 09:37:56 2013 +0100
    72.3 @@ -16,34 +16,21 @@
    72.4    </properties>
    72.5    <build>
    72.6        <plugins>
    72.7 -          <plugin>
    72.8 -              <groupId>org.apidesign.bck2brwsr</groupId>
    72.9 -              <artifactId>mojo</artifactId>
   72.10 -              <version>0.3-SNAPSHOT</version>
   72.11 -              <executions>
   72.12 -                  <execution>
   72.13 -                      <goals>
   72.14 -                          <goal>j2js</goal>
   72.15 -                      </goals>
   72.16 -                  </execution>
   72.17 -              </executions>
   72.18 -          </plugin>
   72.19              <plugin>
   72.20 -                <groupId>org.codehaus.mojo</groupId>
   72.21 -                <artifactId>exec-maven-plugin</artifactId>
   72.22 -                <version>1.2.1</version>
   72.23 +                <groupId>org.apidesign.bck2brwsr</groupId>
   72.24 +                <artifactId>mojo</artifactId>
   72.25 +                <version>0.3-SNAPSHOT</version>
   72.26                  <executions>
   72.27                      <execution>
   72.28                          <goals>
   72.29 -                            <goal>exec</goal>
   72.30 +                            <goal>j2js</goal>
   72.31 +                            <goal>brwsr</goal>
   72.32                          </goals>
   72.33                      </execution>
   72.34                  </executions>
   72.35                  <configuration>
   72.36 -                    <executable>xdg-open</executable>
   72.37 -                    <arguments>
   72.38 -                        <argument>${project.build.directory}/classes/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml</argument>
   72.39 -                    </arguments>
   72.40 +                    <directory>${project.build.directory}/${project.build.finalName}-bck2brwsr/public_html/</directory>
   72.41 +                    <startpage>index.xhtml</startpage>
   72.42                  </configuration>
   72.43              </plugin>
   72.44           <plugin>
   72.45 @@ -55,6 +42,24 @@
   72.46                 <target>1.7</target>
   72.47              </configuration>
   72.48           </plugin>
   72.49 +         <plugin>
   72.50 +            <artifactId>maven-assembly-plugin</artifactId>
   72.51 +                <version>2.4</version>
   72.52 +                <executions>
   72.53 +                    <execution>
   72.54 +                        <id>distro-assembly</id>
   72.55 +                        <phase>package</phase>
   72.56 +                        <goals>
   72.57 +                            <goal>single</goal>
   72.58 +                        </goals>
   72.59 +                        <configuration>
   72.60 +                            <descriptors>
   72.61 +                                <descriptor>src/main/assembly/bck2brwsr.xml</descriptor>
   72.62 +                            </descriptors>
   72.63 +                        </configuration>
   72.64 +                    </execution>
   72.65 +                </executions>                
   72.66 +            </plugin>      
   72.67        </plugins>
   72.68    </build>
   72.69  
    73.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    73.2 +++ b/javaquery/demo-calculator/src/main/assembly/bck2brwsr.xml	Mon Feb 04 09:37:56 2013 +0100
    73.3 @@ -0,0 +1,54 @@
    73.4 +<?xml version="1.0"?>
    73.5 +<!--
    73.6 +
    73.7 +    Back 2 Browser Bytecode Translator
    73.8 +    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    73.9 +
   73.10 +    This program is free software: you can redistribute it and/or modify
   73.11 +    it under the terms of the GNU General Public License as published by
   73.12 +    the Free Software Foundation, version 2 of the License.
   73.13 +
   73.14 +    This program is distributed in the hope that it will be useful,
   73.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   73.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   73.17 +    GNU General Public License for more details.
   73.18 +
   73.19 +    You should have received a copy of the GNU General Public License
   73.20 +    along with this program. Look for COPYING file in the top folder.
   73.21 +    If not, see http://opensource.org/licenses/GPL-2.0.
   73.22 +
   73.23 +-->
   73.24 +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   73.25 +  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
   73.26 +  
   73.27 +  <id>bck2brwsr</id>
   73.28 +  <formats>
   73.29 +      <format>zip</format>
   73.30 +      <format>dir</format>
   73.31 +  </formats>
   73.32 +  <baseDirectory>public_html</baseDirectory>
   73.33 +  <dependencySets>
   73.34 +    <dependencySet>
   73.35 +        <useProjectArtifact>false</useProjectArtifact>
   73.36 +        <scope>runtime</scope>
   73.37 +        <outputDirectory>lib</outputDirectory>
   73.38 +    </dependencySet>
   73.39 +  </dependencySets> 
   73.40 +  <files>
   73.41 +    <file>
   73.42 +      <source>${project.build.directory}/${project.build.finalName}.jar</source>
   73.43 +      <outputDirectory>/</outputDirectory>
   73.44 +    </file>
   73.45 +    <file>
   73.46 +      <source>${project.build.directory}/classes/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml</source>
   73.47 +      <outputDirectory>/</outputDirectory>
   73.48 +      <destName>index.xhtml</destName>
   73.49 +    </file>
   73.50 +    <file>
   73.51 +      <source>${project.build.directory}/classes/org/apidesign/bck2brwsr/demo/calc/staticcompilation/bootjava.js</source>
   73.52 +      <outputDirectory>/</outputDirectory>
   73.53 +      <destName>bck2brwsr.js</destName>
   73.54 +    </file>
   73.55 +  </files>
   73.56 +
   73.57 +</assembly>
   73.58 \ No newline at end of file
    74.1 --- a/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml	Fri Feb 01 16:34:51 2013 +0100
    74.2 +++ b/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml	Mon Feb 04 09:37:56 2013 +0100
    74.3 @@ -77,78 +77,6 @@
    74.4              </tbody>
    74.5          </table>
    74.6          <div data-bind="text: displayPreview"></div>
    74.7 -        <script src="bootjava.js"/>
    74.8 -        
    74.9 -        <hr/>
   74.10 -    <pre>
   74.11 -    <span class="keyword-directive">package</span> org.apidesign.bck2brwsr.mavenhtml;
   74.12 -
   74.13 -    <span class="keyword-directive">import</span> org.apidesign.bck2brwsr.htmlpage.api.OnClick;
   74.14 -    <span class="keyword-directive">import</span> org.apidesign.bck2brwsr.htmlpage.api.Page;
   74.15 -
   74.16 -    <span class="comment">/**</span> <span class="comment">HTML5</span><span class="comment"> &amp; </span><span class="comment">Java</span> <span class="comment">demo</span> <span class="comment">showing</span> <span class="comment">the</span> <span class="comment">power</span> <span class="comment">of</span> <a href="http://wiki.apidesign.org/wiki/AnnotationProcessor">annotation processors</a>
   74.17 -    <span class="comment"> * </span><span class="comment">as</span> <span class="comment">well</span> <span class="comment">as</span> <span class="comment">other</span> <span class="comment">goodies</span><span class="comment">, including type-safe association between</span>
   74.18 -    <span class="comment"> * </span><span class="comment">an XHTML page and Java.</span>
   74.19 -    <span class="comment"> * </span>
   74.20 -    <span class="comment"> * </span><span class="ST1">@author</span> <span class="comment">Jaroslav</span> <span class="comment">Tulach</span> <span class="ST0">&lt;jaroslav.tulach@apidesign.org&gt;</span>
   74.21 -     <span class="comment">*/</span>
   74.22 -    @Page(xhtml=<span class="string">&quot;</span><span class="string">Calculator.xhtml</span><span class="string">&quot;</span>)
   74.23 -    <span class="keyword-directive">public</span> <span class="keyword-directive">class</span> App {
   74.24 -        <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> <span class="keyword-directive">double</span> memory;
   74.25 -        <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> String operation;
   74.26 -
   74.27 -        @OnClick(id=<span class="string">&quot;</span><span class="string">clear</span><span class="string">&quot;</span>)
   74.28 -        <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> clear() {
   74.29 -            memory = <span class="number">0</span>;
   74.30 -            operation = <span class="keyword-directive">null</span>;
   74.31 -            Calculator.DISPLAY.setValue(<span class="string">&quot;</span><span class="string">0</span><span class="string">&quot;</span>);
   74.32 -        }
   74.33 -
   74.34 -        @OnClick(id= { <span class="string">&quot;</span><span class="string">plus</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">minus</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">mul</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">div</span><span class="string">&quot;</span> })
   74.35 -        <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> applyOp(String op) {
   74.36 -            memory = getValue();
   74.37 -            operation = op;
   74.38 -            Calculator.DISPLAY.setValue(<span class="string">&quot;</span><span class="string">0</span><span class="string">&quot;</span>);
   74.39 -        }
   74.40 -
   74.41 -        @OnClick(id=<span class="string">&quot;</span><span class="string">result</span><span class="string">&quot;</span>)
   74.42 -        <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> computeTheValue() {
   74.43 -            <span class="keyword-directive">switch</span> (operation) {
   74.44 -                <span class="keyword-directive">case</span> <span class="string">&quot;</span><span class="string">plus</span><span class="string">&quot;</span>: setValue(memory + getValue()); <span class="keyword-directive">break</span>;
   74.45 -                <span class="keyword-directive">case</span> <span class="string">&quot;</span><span class="string">minus</span><span class="string">&quot;</span>: setValue(memory - getValue()); <span class="keyword-directive">break</span>;
   74.46 -                <span class="keyword-directive">case</span> <span class="string">&quot;</span><span class="string">mul</span><span class="string">&quot;</span>: setValue(memory * getValue()); <span class="keyword-directive">break</span>;
   74.47 -                <span class="keyword-directive">case</span> <span class="string">&quot;</span><span class="string">div</span><span class="string">&quot;</span>: setValue(memory / getValue()); <span class="keyword-directive">break</span>;
   74.48 -                <span class="keyword-directive">default</span>: <span class="keyword-directive">throw</span> <span class="keyword-directive">new</span> IllegalStateException(operation);
   74.49 -            }
   74.50 -        }
   74.51 -
   74.52 -        @OnClick(id={<span class="string">&quot;</span><span class="string">n0</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n1</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n2</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n3</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n4</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n5</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n6</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n7</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n8</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n9</span><span class="string">&quot;</span>}) 
   74.53 -        <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> addDigit(String digit) {
   74.54 -            digit = digit.substring(<span class="number">1</span>);
   74.55 -            String v = Calculator.DISPLAY.getValue();
   74.56 -            <span class="keyword-directive">if</span> (getValue() == <span class="number">0.0</span>) {
   74.57 -                Calculator.DISPLAY.setValue(digit);
   74.58 -            } <span class="keyword-directive">else</span> {
   74.59 -                Calculator.DISPLAY.setValue(v + digit);
   74.60 -            }
   74.61 -        }
   74.62 -
   74.63 -        <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> setValue(<span class="keyword-directive">double</span> v) {
   74.64 -            StringBuilder sb = <span class="keyword-directive">new</span> StringBuilder();
   74.65 -            sb.append(v);
   74.66 -            Calculator.DISPLAY.setValue(sb.toString());
   74.67 -        }
   74.68 -
   74.69 -        <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> <span class="keyword-directive">double</span> getValue() {
   74.70 -            <span class="keyword-directive">try</span> {
   74.71 -                <span class="keyword-directive">return</span> Double.parseDouble(Calculator.DISPLAY.getValue());
   74.72 -            } <span class="keyword-directive">catch</span> (NumberFormatException ex) {
   74.73 -                Calculator.DISPLAY.setValue(<span class="string">&quot;</span><span class="string">err</span><span class="string">&quot;</span>);
   74.74 -                <span class="keyword-directive">return</span> <span class="number">0.0</span>;
   74.75 -            }
   74.76 -        }
   74.77 -    }
   74.78 -
   74.79 -    </pre>
   74.80 +        <script src="bck2brwsr.js"/>
   74.81      </body>
   74.82  </html>
    75.1 --- a/launcher/pom.xml	Fri Feb 01 16:34:51 2013 +0100
    75.2 +++ b/launcher/pom.xml	Mon Feb 04 09:37:56 2013 +0100
    75.3 @@ -23,6 +23,14 @@
    75.4                      <target>1.7</target>
    75.5                  </configuration>
    75.6              </plugin>
    75.7 +            <plugin>
    75.8 +                <groupId>org.apache.maven.plugins</groupId>
    75.9 +                <artifactId>maven-javadoc-plugin</artifactId>
   75.10 +                <version>2.8.1</version>
   75.11 +                <configuration>
   75.12 +                    <excludePackageNames>org.apidesign.bck2brwsr.launcher.impl</excludePackageNames>
   75.13 +                </configuration>
   75.14 +            </plugin>
   75.15          </plugins>
   75.16      </build>
   75.17      <properties>
    76.1 --- a/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java	Fri Feb 01 16:34:51 2013 +0100
    76.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java	Mon Feb 04 09:37:56 2013 +0100
    76.3 @@ -55,24 +55,23 @@
    76.4   */
    76.5  final class Bck2BrwsrLauncher extends Launcher implements Closeable {
    76.6      private static final Logger LOG = Logger.getLogger(Bck2BrwsrLauncher.class.getName());
    76.7 -    private static final MethodInvocation END = new MethodInvocation(null, null, null);
    76.8 -    private Set<ClassLoader> loaders = new LinkedHashSet<>();
    76.9 -    private BlockingQueue<MethodInvocation> methods = new LinkedBlockingQueue<>();
   76.10 +    private static final InvocationContext END = new InvocationContext(null, null, null);
   76.11 +    private final Set<ClassLoader> loaders = new LinkedHashSet<>();
   76.12 +    private final BlockingQueue<InvocationContext> methods = new LinkedBlockingQueue<>();
   76.13      private long timeOut;
   76.14      private final Res resources = new Res();
   76.15      private final String cmd;
   76.16      private Object[] brwsr;
   76.17      private HttpServer server;
   76.18      private CountDownLatch wait;
   76.19 -
   76.20 +    
   76.21      public Bck2BrwsrLauncher(String cmd) {
   76.22          this.cmd = cmd;
   76.23      }
   76.24      
   76.25      @Override
   76.26 -     MethodInvocation addMethod(Class<?> clazz, String method, String html) throws IOException {
   76.27 -        loaders.add(clazz.getClassLoader());
   76.28 -        MethodInvocation c = new MethodInvocation(clazz.getName(), method, html);
   76.29 +    InvocationContext runMethod(InvocationContext c) throws IOException {
   76.30 +        loaders.add(c.clazz.getClassLoader());
   76.31          methods.add(c);
   76.32          try {
   76.33              c.await(timeOut);
   76.34 @@ -94,7 +93,7 @@
   76.35          if (!startpage.startsWith("/")) {
   76.36              startpage = "/" + startpage;
   76.37          }
   76.38 -        HttpServer s = initServer();
   76.39 +        HttpServer s = initServer(".", true);
   76.40          s.getServerConfiguration().addHttpHandler(new Page(resources, null), "/");
   76.41          try {
   76.42              launchServerAndBrwsr(s, startpage);
   76.43 @@ -103,6 +102,18 @@
   76.44          }
   76.45      }
   76.46  
   76.47 +    void showDirectory(File dir, String startpage) throws IOException {
   76.48 +        if (!startpage.startsWith("/")) {
   76.49 +            startpage = "/" + startpage;
   76.50 +        }
   76.51 +        HttpServer s = initServer(dir.getPath(), false);
   76.52 +        try {
   76.53 +            launchServerAndBrwsr(s, startpage);
   76.54 +        } catch (URISyntaxException | InterruptedException ex) {
   76.55 +            throw new IOException(ex);
   76.56 +        }
   76.57 +    }
   76.58 +
   76.59      @Override
   76.60      public void initialize() throws IOException {
   76.61          try {
   76.62 @@ -122,25 +133,54 @@
   76.63          }
   76.64      }
   76.65      
   76.66 -    private HttpServer initServer() throws IOException {
   76.67 -        HttpServer s = HttpServer.createSimpleServer(".", new PortRange(8080, 65535));
   76.68 +    private HttpServer initServer(String path, boolean addClasses) throws IOException {
   76.69 +        HttpServer s = HttpServer.createSimpleServer(path, new PortRange(8080, 65535));
   76.70  
   76.71          final ServerConfiguration conf = s.getServerConfiguration();
   76.72 -        conf.addHttpHandler(new VM(resources), "/vm.js");
   76.73 -        conf.addHttpHandler(new Classes(resources), "/classes/");
   76.74 +        if (addClasses) {
   76.75 +            conf.addHttpHandler(new VM(resources), "/vm.js");
   76.76 +            conf.addHttpHandler(new Classes(resources), "/classes/");
   76.77 +        }
   76.78          return s;
   76.79      }
   76.80      
   76.81      private void executeInBrowser() throws InterruptedException, URISyntaxException, IOException {
   76.82          wait = new CountDownLatch(1);
   76.83 -        server = initServer();
   76.84 -        ServerConfiguration conf = server.getServerConfiguration();
   76.85 +        server = initServer(".", true);
   76.86 +        final ServerConfiguration conf = server.getServerConfiguration();
   76.87 +        
   76.88 +        class DynamicResourceHandler extends HttpHandler {
   76.89 +            private final InvocationContext ic;
   76.90 +            public DynamicResourceHandler(InvocationContext ic) {
   76.91 +                if (ic == null || ic.httpPath == null) {
   76.92 +                    throw new NullPointerException();
   76.93 +                }
   76.94 +                this.ic = ic;
   76.95 +                conf.addHttpHandler(this, ic.httpPath);
   76.96 +            }
   76.97 +
   76.98 +            public void close() {
   76.99 +                conf.removeHttpHandler(this);
  76.100 +            }
  76.101 +            
  76.102 +            @Override
  76.103 +            public void service(Request request, Response response) throws Exception {
  76.104 +                if (ic.httpPath.equals(request.getRequestURI())) {
  76.105 +                    LOG.log(Level.INFO, "Serving HttpResource for {0}", request.getRequestURI());
  76.106 +                    response.setContentType(ic.httpType);
  76.107 +                    copyStream(ic.httpContent, response.getOutputStream(), null);
  76.108 +                }
  76.109 +            }
  76.110 +        }
  76.111 +        
  76.112          conf.addHttpHandler(new Page(resources, 
  76.113              "org/apidesign/bck2brwsr/launcher/harness.xhtml"
  76.114          ), "/execute");
  76.115 +        
  76.116          conf.addHttpHandler(new HttpHandler() {
  76.117              int cnt;
  76.118 -            List<MethodInvocation> cases = new ArrayList<>();
  76.119 +            List<InvocationContext> cases = new ArrayList<>();
  76.120 +            DynamicResourceHandler prev;
  76.121              @Override
  76.122              public void service(Request request, Response response) throws Exception {
  76.123                  String id = request.getParameter("request");
  76.124 @@ -152,7 +192,12 @@
  76.125                      cases.get(Integer.parseInt(id)).result(value, null);
  76.126                  }
  76.127                  
  76.128 -                MethodInvocation mi = methods.take();
  76.129 +                if (prev != null) {
  76.130 +                    prev.close();
  76.131 +                    prev = null;
  76.132 +                }
  76.133 +                
  76.134 +                InvocationContext mi = methods.take();
  76.135                  if (mi == END) {
  76.136                      response.getWriter().write("");
  76.137                      wait.countDown();
  76.138 @@ -161,8 +206,12 @@
  76.139                      return;
  76.140                  }
  76.141                  
  76.142 +                if (mi.httpPath != null) {
  76.143 +                    prev = new DynamicResourceHandler(mi);
  76.144 +                }
  76.145 +                
  76.146                  cases.add(mi);
  76.147 -                final String cn = mi.className;
  76.148 +                final String cn = mi.clazz.getName();
  76.149                  final String mn = mi.methodName;
  76.150                  LOG.log(Level.INFO, "Request for {0} case. Sending {1}.{2}", new Object[]{cnt, cn, mn});
  76.151                  response.getWriter().write("{"
    77.1 --- a/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Console.java	Fri Feb 01 16:34:51 2013 +0100
    77.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    77.3 @@ -1,253 +0,0 @@
    77.4 -/**
    77.5 - * Back 2 Browser Bytecode Translator
    77.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    77.7 - *
    77.8 - * This program is free software: you can redistribute it and/or modify
    77.9 - * it under the terms of the GNU General Public License as published by
   77.10 - * the Free Software Foundation, version 2 of the License.
   77.11 - *
   77.12 - * This program is distributed in the hope that it will be useful,
   77.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   77.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   77.15 - * GNU General Public License for more details.
   77.16 - *
   77.17 - * You should have received a copy of the GNU General Public License
   77.18 - * along with this program. Look for COPYING file in the top folder.
   77.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
   77.20 - */
   77.21 -package org.apidesign.bck2brwsr.launcher;
   77.22 -
   77.23 -import java.io.IOException;
   77.24 -import java.io.InputStream;
   77.25 -import java.lang.reflect.InvocationTargetException;
   77.26 -import java.lang.reflect.Method;
   77.27 -import java.lang.reflect.Modifier;
   77.28 -import java.net.URL;
   77.29 -import java.util.Enumeration;
   77.30 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
   77.31 -
   77.32 -/**
   77.33 - *
   77.34 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   77.35 - */
   77.36 -public class Console {
   77.37 -    static {
   77.38 -        turnAssetionStatusOn();
   77.39 -    }
   77.40 -    
   77.41 -    @JavaScriptBody(args = {"id", "attr"}, body = 
   77.42 -        "return window.document.getElementById(id)[attr].toString();")
   77.43 -    private static native Object getAttr(String id, String attr);
   77.44 -
   77.45 -    @JavaScriptBody(args = {"id", "attr", "value"}, body = 
   77.46 -        "window.document.getElementById(id)[attr] = value;")
   77.47 -    private static native void setAttr(String id, String attr, Object value);
   77.48 -    
   77.49 -    @JavaScriptBody(args = {}, body = "return; window.close();")
   77.50 -    private static native void closeWindow();
   77.51 -
   77.52 -    private static void log(String newText) {
   77.53 -        String id = "bck2brwsr.result";
   77.54 -        String attr = "value";
   77.55 -        setAttr(id, attr, getAttr(id, attr) + "\n" + newText);
   77.56 -        setAttr(id, "scrollTop", getAttr(id, "scrollHeight"));
   77.57 -    }
   77.58 -    
   77.59 -    public static void execute() throws Exception {
   77.60 -        String clazz = (String) getAttr("clazz", "value");
   77.61 -        String method = (String) getAttr("method", "value");
   77.62 -        Object res = invokeMethod(clazz, method);
   77.63 -        setAttr("bck2brwsr.result", "value", res);
   77.64 -    }
   77.65 -
   77.66 -    @JavaScriptBody(args = { "url", "callback", "arr" }, body = ""
   77.67 -        + "var request = new XMLHttpRequest();\n"
   77.68 -        + "request.open('GET', url, true);\n"
   77.69 -        + "request.onreadystatechange = function() {\n"
   77.70 -        + "  if (this.readyState!==4) return;\n"
   77.71 -        + "  arr[0] = this.responseText;\n"
   77.72 -        + "  callback.run__V();\n"
   77.73 -        + "};"
   77.74 -        + "request.send();"
   77.75 -    )
   77.76 -    private static native void loadText(String url, Runnable callback, String[] arr) throws IOException;
   77.77 -    
   77.78 -    public static void harness(String url) throws IOException {
   77.79 -        log("Connecting to " + url);
   77.80 -        Request r = new Request(url);
   77.81 -    }
   77.82 -    
   77.83 -    private static class Request implements Runnable {
   77.84 -        private final String[] arr = { null };
   77.85 -        private final String url;
   77.86 -
   77.87 -        private Request(String url) throws IOException {
   77.88 -            this.url = url;
   77.89 -            loadText(url, this, arr);
   77.90 -        }
   77.91 -        
   77.92 -        @Override
   77.93 -        public void run() {
   77.94 -            try {
   77.95 -                String data = arr[0];
   77.96 -                log("\nGot \"" + data + "\"");
   77.97 -                
   77.98 -                if (data == null) {
   77.99 -                    log("Some error exiting");
  77.100 -                    closeWindow();
  77.101 -                    return;
  77.102 -                }
  77.103 -                
  77.104 -                if (data.isEmpty()) {
  77.105 -                    log("No data, exiting");
  77.106 -                    closeWindow();
  77.107 -                    return;
  77.108 -                }
  77.109 -                
  77.110 -                Case c = Case.parseData(data);
  77.111 -                if (c.getHtmlFragment() != null) {
  77.112 -                    setAttr("bck2brwsr.fragment", "innerHTML", c.getHtmlFragment());
  77.113 -                }
  77.114 -                log("Invoking " + c.getClassName() + '.' + c.getMethodName() + " as request: " + c.getRequestId());
  77.115 -
  77.116 -                Object result = invokeMethod(c.getClassName(), c.getMethodName());
  77.117 -                
  77.118 -                setAttr("bck2brwsr.fragment", "innerHTML", "");
  77.119 -                log("Result: " + result);
  77.120 -                
  77.121 -                result = encodeURL("" + result);
  77.122 -                
  77.123 -                log("Sending back: " + url + "?request=" + c.getRequestId() + "&result=" + result);
  77.124 -                String u = url + "?request=" + c.getRequestId() + "&result=" + result;
  77.125 -                
  77.126 -                loadText(u, this, arr);
  77.127 -                
  77.128 -            } catch (Exception ex) {
  77.129 -                log(ex.getMessage());
  77.130 -            }
  77.131 -        }
  77.132 -    }
  77.133 -    
  77.134 -    private static String encodeURL(String r) {
  77.135 -        StringBuilder sb = new StringBuilder();
  77.136 -        for (int i = 0; i < r.length(); i++) {
  77.137 -            int ch = r.charAt(i);
  77.138 -            if (ch < 32 || ch == '%' || ch == '+') {
  77.139 -                sb.append("%").append(("0" + Integer.toHexString(ch)).substring(0, 2));
  77.140 -            } else {
  77.141 -                if (ch == 32) {
  77.142 -                    sb.append("+");
  77.143 -                } else {
  77.144 -                    sb.append((char)ch);
  77.145 -                }
  77.146 -            }
  77.147 -        }
  77.148 -        return sb.toString();
  77.149 -    }
  77.150 -    
  77.151 -    static String invoke(String clazz, String method) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException, InstantiationException {
  77.152 -        final Object r = invokeMethod(clazz, method);
  77.153 -        return r == null ? "null" : r.toString().toString();
  77.154 -    }
  77.155 -
  77.156 -    /** Helper method that inspects the classpath and loads given resource
  77.157 -     * (usually a class file). Used while running tests in Rhino.
  77.158 -     * 
  77.159 -     * @param name resource name to find
  77.160 -     * @return the array of bytes in the given resource
  77.161 -     * @throws IOException I/O in case something goes wrong
  77.162 -     */
  77.163 -    public static byte[] read(String name) throws IOException {
  77.164 -        URL u = null;
  77.165 -        Enumeration<URL> en = Console.class.getClassLoader().getResources(name);
  77.166 -        while (en.hasMoreElements()) {
  77.167 -            u = en.nextElement();
  77.168 -        }
  77.169 -        if (u == null) {
  77.170 -            throw new IOException("Can't find " + name);
  77.171 -        }
  77.172 -        try (InputStream is = u.openStream()) {
  77.173 -            byte[] arr;
  77.174 -            arr = new byte[is.available()];
  77.175 -            int offset = 0;
  77.176 -            while (offset < arr.length) {
  77.177 -                int len = is.read(arr, offset, arr.length - offset);
  77.178 -                if (len == -1) {
  77.179 -                    throw new IOException("Can't read " + name);
  77.180 -                }
  77.181 -                offset += len;
  77.182 -            }
  77.183 -            return arr;
  77.184 -        }
  77.185 -    }
  77.186 -   
  77.187 -    private static Object invokeMethod(String clazz, String method) 
  77.188 -    throws ClassNotFoundException, InvocationTargetException, 
  77.189 -    SecurityException, IllegalAccessException, IllegalArgumentException,
  77.190 -    InstantiationException {
  77.191 -        Method found = null;
  77.192 -        Class<?> c = Class.forName(clazz);
  77.193 -        for (Method m : c.getMethods()) {
  77.194 -            if (m.getName().equals(method)) {
  77.195 -                found = m;
  77.196 -            }
  77.197 -        }
  77.198 -        Object res;
  77.199 -        if (found != null) {
  77.200 -            try {
  77.201 -                if ((found.getModifiers() & Modifier.STATIC) != 0) {
  77.202 -                    res = found.invoke(null);
  77.203 -                } else {
  77.204 -                    res = found.invoke(c.newInstance());
  77.205 -                }
  77.206 -            } catch (Throwable ex) {
  77.207 -                res = ex.getClass().getName() + ":" + ex.getMessage();
  77.208 -            }
  77.209 -        } else {
  77.210 -            res = "Can't find method " + method + " in " + clazz;
  77.211 -        }
  77.212 -        return res;
  77.213 -    }
  77.214 -
  77.215 -    @JavaScriptBody(args = {}, body = "vm.desiredAssertionStatus = true;")
  77.216 -    private static void turnAssetionStatusOn() {
  77.217 -    }
  77.218 -    
  77.219 -    private static final class Case {
  77.220 -        private final Object data;
  77.221 -
  77.222 -        private Case(Object data) {
  77.223 -            this.data = data;
  77.224 -        }
  77.225 -        
  77.226 -        public static Case parseData(String s) {
  77.227 -            return new Case(toJSON(s));
  77.228 -        }
  77.229 -        
  77.230 -        public String getMethodName() {
  77.231 -            return value("methodName", data);
  77.232 -        }
  77.233 -
  77.234 -        public String getClassName() {
  77.235 -            return value("className", data);
  77.236 -        }
  77.237 -        
  77.238 -        public String getRequestId() {
  77.239 -            return value("request", data);
  77.240 -        }
  77.241 -
  77.242 -        public String getHtmlFragment() {
  77.243 -            return value("html", data);
  77.244 -        }
  77.245 -        
  77.246 -        @JavaScriptBody(args = "s", body = "return eval('(' + s + ')');")
  77.247 -        private static native Object toJSON(String s);
  77.248 -        
  77.249 -        @JavaScriptBody(args = {"p", "d"}, body = 
  77.250 -              "var v = d[p];\n"
  77.251 -            + "if (typeof v === 'undefined') return null;\n"
  77.252 -            + "return v.toString();"
  77.253 -        )
  77.254 -        private static native String value(String p, Object d);
  77.255 -    }
  77.256 -}
    78.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    78.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/InvocationContext.java	Mon Feb 04 09:37:56 2013 +0100
    78.3 @@ -0,0 +1,101 @@
    78.4 +/**
    78.5 + * Back 2 Browser Bytecode Translator
    78.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    78.7 + *
    78.8 + * This program is free software: you can redistribute it and/or modify
    78.9 + * it under the terms of the GNU General Public License as published by
   78.10 + * the Free Software Foundation, version 2 of the License.
   78.11 + *
   78.12 + * This program is distributed in the hope that it will be useful,
   78.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   78.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   78.15 + * GNU General Public License for more details.
   78.16 + *
   78.17 + * You should have received a copy of the GNU General Public License
   78.18 + * along with this program. Look for COPYING file in the top folder.
   78.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   78.20 + */
   78.21 +package org.apidesign.bck2brwsr.launcher;
   78.22 +
   78.23 +import java.io.IOException;
   78.24 +import java.io.InputStream;
   78.25 +import java.util.concurrent.CountDownLatch;
   78.26 +import java.util.concurrent.TimeUnit;
   78.27 +
   78.28 +/** Represents individual method invocation, its context and its result.
   78.29 + *
   78.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   78.31 + */
   78.32 +public final class InvocationContext {
   78.33 +    final CountDownLatch wait = new CountDownLatch(1);
   78.34 +    final Class<?> clazz;
   78.35 +    final String methodName;
   78.36 +    private final Launcher launcher;
   78.37 +    private String result;
   78.38 +    private Throwable exception;
   78.39 +    String html;
   78.40 +    InputStream httpContent;
   78.41 +    String httpType;
   78.42 +    String httpPath;
   78.43 +
   78.44 +    InvocationContext(Launcher launcher, Class<?> clazz, String methodName) {
   78.45 +        this.launcher = launcher;
   78.46 +        this.clazz = clazz;
   78.47 +        this.methodName = methodName;
   78.48 +    }
   78.49 +    
   78.50 +    /** An HTML fragment to be available for the execution. Useful primarily when
   78.51 +     * executing in a browser via {@link Launcher#createBrowser(java.lang.String)}.
   78.52 +     * @param html the html fragment
   78.53 +     */
   78.54 +    public void setHtmlFragment(String html) {
   78.55 +        this.html = html;
   78.56 +    }
   78.57 +    
   78.58 +    /** HTTP resource to be available during execution. An invocation may
   78.59 +     * perform an HTTP query and obtain a resource relative to the page.
   78.60 +     */
   78.61 +    public void setHttpResource(String relativePath, String mimeType, InputStream content) {
   78.62 +        if (relativePath == null || mimeType == null || content == null) {
   78.63 +            throw new NullPointerException();
   78.64 +        }
   78.65 +        this.httpPath = relativePath;
   78.66 +        this.httpType = mimeType;
   78.67 +        this.httpContent = content;
   78.68 +    }
   78.69 +    
   78.70 +    /** Invokes the associated method. 
   78.71 +     * @return the textual result of the invocation
   78.72 +     */
   78.73 +    public String invoke() throws IOException {
   78.74 +        launcher.runMethod(this);
   78.75 +        return toString();
   78.76 +    }
   78.77 +    
   78.78 +    /** Obtains textual result of the invocation.
   78.79 +     * @return text representing the exception or result value
   78.80 +     */
   78.81 +    @Override
   78.82 +    public String toString() {
   78.83 +        if (exception != null) {
   78.84 +            return exception.toString();
   78.85 +        }
   78.86 +        return result;
   78.87 +    }
   78.88 +    
   78.89 +    /**
   78.90 +     * @param timeOut
   78.91 +     * @throws InterruptedException 
   78.92 +     */
   78.93 +    void await(long timeOut) throws InterruptedException {
   78.94 +        wait.await(timeOut, TimeUnit.MILLISECONDS);
   78.95 +    }
   78.96 +    
   78.97 +    void result(String r, Throwable e) {
   78.98 +        this.result = r;
   78.99 +        this.exception = e;
  78.100 +        wait.countDown();
  78.101 +    }
  78.102 +
  78.103 +    
  78.104 +}
    79.1 --- a/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/JSLauncher.java	Fri Feb 01 16:34:51 2013 +0100
    79.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/JSLauncher.java	Mon Feb 04 09:37:56 2013 +0100
    79.3 @@ -17,6 +17,7 @@
    79.4   */
    79.5  package org.apidesign.bck2brwsr.launcher;
    79.6  
    79.7 +import org.apidesign.bck2brwsr.launcher.impl.Console;
    79.8  import java.io.IOException;
    79.9  import java.io.InputStream;
   79.10  import java.net.URL;
   79.11 @@ -43,18 +44,17 @@
   79.12      private Object console;
   79.13      
   79.14      
   79.15 -    @Override MethodInvocation addMethod(Class<?> clazz, String method, String html) {
   79.16 -        loaders.add(clazz.getClassLoader());
   79.17 -        MethodInvocation mi = new MethodInvocation(clazz.getName(), method, html);
   79.18 +    @Override InvocationContext runMethod(InvocationContext mi) {
   79.19 +        loaders.add(mi.clazz.getClassLoader());
   79.20          try {
   79.21              long time = System.currentTimeMillis();
   79.22 -            LOG.log(Level.FINE, "Invoking {0}.{1}", new Object[]{mi.className, mi.methodName});
   79.23 +            LOG.log(Level.FINE, "Invoking {0}.{1}", new Object[]{mi.clazz.getName(), mi.methodName});
   79.24              String res = code.invokeMethod(
   79.25                  console,
   79.26                  "invoke__Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2",
   79.27 -                mi.className, mi.methodName).toString();
   79.28 +                mi.clazz.getName(), mi.methodName).toString();
   79.29              time = System.currentTimeMillis() - time;
   79.30 -            LOG.log(Level.FINE, "Resut of {0}.{1} = {2} in {3} ms", new Object[]{mi.className, mi.methodName, res, time});
   79.31 +            LOG.log(Level.FINE, "Resut of {0}.{1} = {2} in {3} ms", new Object[]{mi.clazz.getName(), mi.methodName, res, time});
   79.32              mi.result(res, null);
   79.33          } catch (ScriptException | NoSuchMethodException ex) {
   79.34              mi.result(null, ex);
   79.35 @@ -89,7 +89,7 @@
   79.36          ScriptEngine mach = sem.getEngineByExtension("js");
   79.37  
   79.38          sb.append(
   79.39 -              "\nvar vm = new bck2brwsr(org.apidesign.bck2brwsr.launcher.Console.read);"
   79.40 +              "\nvar vm = new bck2brwsr(org.apidesign.bck2brwsr.launcher.impl.Console.read);"
   79.41              + "\nfunction initVM() { return vm; };"
   79.42              + "\n");
   79.43  
    80.1 --- a/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java	Fri Feb 01 16:34:51 2013 +0100
    80.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java	Mon Feb 04 09:37:56 2013 +0100
    80.3 @@ -18,12 +18,14 @@
    80.4  package org.apidesign.bck2brwsr.launcher;
    80.5  
    80.6  import java.io.Closeable;
    80.7 +import java.io.File;
    80.8  import java.io.IOException;
    80.9  import java.net.URLClassLoader;
   80.10  import org.apidesign.vm4brwsr.Bck2Brwsr;
   80.11  
   80.12  /** An abstraction for executing tests in a Bck2Brwsr virtual machine.
   80.13 - * Either in JavaScript engine, or in external browser.
   80.14 + * Either in {@linkm Launcher#createJavaScript JavaScript engine}, 
   80.15 + * or in {@linkm Launcher#createBrowser external browser}.
   80.16   *
   80.17   * @author Jaroslav Tulach <jtulach@netbeans.org>
   80.18   */
   80.19 @@ -31,33 +33,83 @@
   80.20  
   80.21      Launcher() {
   80.22      }
   80.23 +
   80.24 +    /** Initializes the launcher. This may mean starting a web browser or
   80.25 +     * initializing execution engine.
   80.26 +     * @throws IOException if something goes wrong
   80.27 +     */
   80.28 +    public abstract void initialize() throws IOException;
   80.29      
   80.30 -    abstract MethodInvocation addMethod(Class<?> clazz, String method, String html) throws IOException; 
   80.31 -
   80.32 -    public abstract void initialize() throws IOException;
   80.33 +    /** Shuts down the launcher.
   80.34 +     * @throws IOException if something goes wrong
   80.35 +     */
   80.36      public abstract void shutdown() throws IOException;
   80.37 -    public MethodInvocation invokeMethod(Class<?> clazz, String method, String html) throws IOException {
   80.38 -        return addMethod(clazz, method, html);
   80.39 +    
   80.40 +    
   80.41 +    /** Builds an invocation context. The context can later be customized
   80.42 +     * and {@link InvocationContext#invoke() invoked}.
   80.43 +     * 
   80.44 +     * @param clazz the class to execute method from
   80.45 +     * @param method the method to execute
   80.46 +     * @return the context pointing to the selected method
   80.47 +     */
   80.48 +    public InvocationContext createInvocation(Class<?> clazz, String method) {
   80.49 +        return new InvocationContext(this, clazz, method);
   80.50      }
   80.51      
   80.52 -    
   80.53  
   80.54 +    /** Creates launcher that uses internal JavaScript engine (Rhino).
   80.55 +     * @return the launcher
   80.56 +     */
   80.57      public static Launcher createJavaScript() {
   80.58          final JSLauncher l = new JSLauncher();
   80.59          l.addClassLoader(Bck2Brwsr.class.getClassLoader());
   80.60          return l;
   80.61      }
   80.62      
   80.63 +    /** Creates launcher that is using external browser.
   80.64 +     * 
   80.65 +     * @param cmd <code>null</code> to use <code>java.awt.Desktop</code> to show the launcher
   80.66 +     *    or a string to execute in an external process (with a parameter to the URL)
   80.67 +     * @return launcher executing in external browser.
   80.68 +     */
   80.69      public static Launcher createBrowser(String cmd) {
   80.70          final Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(cmd);
   80.71          l.addClassLoader(Bck2Brwsr.class.getClassLoader());
   80.72          l.setTimeout(180000);
   80.73          return l;
   80.74      }
   80.75 +    
   80.76 +    /** Starts an HTTP server which provides access to classes and resources
   80.77 +     * available in the <code>classes</code> URL and shows a start page
   80.78 +     * available as {@link ClassLoader#getResource(java.lang.String)} from the
   80.79 +     * provide classloader. Opens a browser with URL showing the start page.
   80.80 +     * 
   80.81 +     * @param classes classloader offering access to classes and resources
   80.82 +     * @param startpage page to show in the browser
   80.83 +     * @return interface that allows one to stop the server
   80.84 +     * @throws IOException if something goes wrong
   80.85 +     */
   80.86      public static Closeable showURL(URLClassLoader classes, String startpage) throws IOException {
   80.87          Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(null);
   80.88          l.addClassLoader(classes);
   80.89          l.showURL(startpage);
   80.90          return l;
   80.91      }
   80.92 +    /** Starts an HTTP server which provides access to certain directory.
   80.93 +     * The <code>startpage</code> should be relative location inside the root 
   80.94 +     * driecotry
   80.95 +     * Opens a browser with URL showing the start page.
   80.96 +     * 
   80.97 +     * @param directory the root directory on disk
   80.98 +     * @praam startpage relative path from the root to the page
   80.99 +     * @exception IOException if something goes wrong.
  80.100 +     */
  80.101 +    public static Closeable showDir(File directory, String startpage) throws IOException {
  80.102 +        Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(null);
  80.103 +        l.showDirectory(directory, startpage);
  80.104 +        return l;
  80.105 +    }
  80.106 +
  80.107 +    abstract InvocationContext runMethod(InvocationContext c) throws IOException; 
  80.108  }
    81.1 --- a/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/MethodInvocation.java	Fri Feb 01 16:34:51 2013 +0100
    81.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    81.3 @@ -1,59 +0,0 @@
    81.4 -/**
    81.5 - * Back 2 Browser Bytecode Translator
    81.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    81.7 - *
    81.8 - * This program is free software: you can redistribute it and/or modify
    81.9 - * it under the terms of the GNU General Public License as published by
   81.10 - * the Free Software Foundation, version 2 of the License.
   81.11 - *
   81.12 - * This program is distributed in the hope that it will be useful,
   81.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   81.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   81.15 - * GNU General Public License for more details.
   81.16 - *
   81.17 - * You should have received a copy of the GNU General Public License
   81.18 - * along with this program. Look for COPYING file in the top folder.
   81.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
   81.20 - */
   81.21 -package org.apidesign.bck2brwsr.launcher;
   81.22 -
   81.23 -import java.util.concurrent.CountDownLatch;
   81.24 -import java.util.concurrent.TimeUnit;
   81.25 -
   81.26 -/**
   81.27 - *
   81.28 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   81.29 - */
   81.30 -public final class MethodInvocation {
   81.31 -    final CountDownLatch wait = new CountDownLatch(1);
   81.32 -    final String className;
   81.33 -    final String methodName;
   81.34 -    final String html;
   81.35 -    private String result;
   81.36 -    private Throwable exception;
   81.37 -
   81.38 -    MethodInvocation(String className, String methodName, String html) {
   81.39 -        this.className = className;
   81.40 -        this.methodName = methodName;
   81.41 -        this.html = html;
   81.42 -    }
   81.43 -    
   81.44 -    void await(long timeOut) throws InterruptedException {
   81.45 -        wait.await(timeOut, TimeUnit.MILLISECONDS);
   81.46 -    }
   81.47 -    
   81.48 -    void result(String r, Throwable e) {
   81.49 -        this.result = r;
   81.50 -        this.exception = e;
   81.51 -        wait.countDown();
   81.52 -    }
   81.53 -
   81.54 -    @Override
   81.55 -    public String toString() {
   81.56 -        if (exception != null) {
   81.57 -            return exception.toString();
   81.58 -        }
   81.59 -        return result;
   81.60 -    }
   81.61 -    
   81.62 -}
    82.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    82.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/impl/Console.java	Mon Feb 04 09:37:56 2013 +0100
    82.3 @@ -0,0 +1,255 @@
    82.4 +/**
    82.5 + * Back 2 Browser Bytecode Translator
    82.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    82.7 + *
    82.8 + * This program is free software: you can redistribute it and/or modify
    82.9 + * it under the terms of the GNU General Public License as published by
   82.10 + * the Free Software Foundation, version 2 of the License.
   82.11 + *
   82.12 + * This program is distributed in the hope that it will be useful,
   82.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   82.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   82.15 + * GNU General Public License for more details.
   82.16 + *
   82.17 + * You should have received a copy of the GNU General Public License
   82.18 + * along with this program. Look for COPYING file in the top folder.
   82.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   82.20 + */
   82.21 +package org.apidesign.bck2brwsr.launcher.impl;
   82.22 +
   82.23 +import java.io.IOException;
   82.24 +import java.io.InputStream;
   82.25 +import java.lang.reflect.InvocationTargetException;
   82.26 +import java.lang.reflect.Method;
   82.27 +import java.lang.reflect.Modifier;
   82.28 +import java.net.URL;
   82.29 +import java.util.Enumeration;
   82.30 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
   82.31 +
   82.32 +/**
   82.33 + *
   82.34 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   82.35 + */
   82.36 +public class Console {
   82.37 +    private Console() {
   82.38 +    }
   82.39 +    static {
   82.40 +        turnAssetionStatusOn();
   82.41 +    }
   82.42 +    
   82.43 +    @JavaScriptBody(args = {"id", "attr"}, body = 
   82.44 +        "return window.document.getElementById(id)[attr].toString();")
   82.45 +    private static native Object getAttr(String id, String attr);
   82.46 +
   82.47 +    @JavaScriptBody(args = {"id", "attr", "value"}, body = 
   82.48 +        "window.document.getElementById(id)[attr] = value;")
   82.49 +    private static native void setAttr(String id, String attr, Object value);
   82.50 +    
   82.51 +    @JavaScriptBody(args = {}, body = "return; window.close();")
   82.52 +    private static native void closeWindow();
   82.53 +
   82.54 +    private static void log(String newText) {
   82.55 +        String id = "bck2brwsr.result";
   82.56 +        String attr = "value";
   82.57 +        setAttr(id, attr, getAttr(id, attr) + "\n" + newText);
   82.58 +        setAttr(id, "scrollTop", getAttr(id, "scrollHeight"));
   82.59 +    }
   82.60 +    
   82.61 +    public static void execute() throws Exception {
   82.62 +        String clazz = (String) getAttr("clazz", "value");
   82.63 +        String method = (String) getAttr("method", "value");
   82.64 +        Object res = invokeMethod(clazz, method);
   82.65 +        setAttr("bck2brwsr.result", "value", res);
   82.66 +    }
   82.67 +
   82.68 +    @JavaScriptBody(args = { "url", "callback", "arr" }, body = ""
   82.69 +        + "var request = new XMLHttpRequest();\n"
   82.70 +        + "request.open('GET', url, true);\n"
   82.71 +        + "request.onreadystatechange = function() {\n"
   82.72 +        + "  if (this.readyState!==4) return;\n"
   82.73 +        + "  arr[0] = this.responseText;\n"
   82.74 +        + "  callback.run__V();\n"
   82.75 +        + "};"
   82.76 +        + "request.send();"
   82.77 +    )
   82.78 +    private static native void loadText(String url, Runnable callback, String[] arr) throws IOException;
   82.79 +    
   82.80 +    public static void harness(String url) throws IOException {
   82.81 +        log("Connecting to " + url);
   82.82 +        Request r = new Request(url);
   82.83 +    }
   82.84 +    
   82.85 +    private static class Request implements Runnable {
   82.86 +        private final String[] arr = { null };
   82.87 +        private final String url;
   82.88 +
   82.89 +        private Request(String url) throws IOException {
   82.90 +            this.url = url;
   82.91 +            loadText(url, this, arr);
   82.92 +        }
   82.93 +        
   82.94 +        @Override
   82.95 +        public void run() {
   82.96 +            try {
   82.97 +                String data = arr[0];
   82.98 +                log("\nGot \"" + data + "\"");
   82.99 +                
  82.100 +                if (data == null) {
  82.101 +                    log("Some error exiting");
  82.102 +                    closeWindow();
  82.103 +                    return;
  82.104 +                }
  82.105 +                
  82.106 +                if (data.isEmpty()) {
  82.107 +                    log("No data, exiting");
  82.108 +                    closeWindow();
  82.109 +                    return;
  82.110 +                }
  82.111 +                
  82.112 +                Case c = Case.parseData(data);
  82.113 +                if (c.getHtmlFragment() != null) {
  82.114 +                    setAttr("bck2brwsr.fragment", "innerHTML", c.getHtmlFragment());
  82.115 +                }
  82.116 +                log("Invoking " + c.getClassName() + '.' + c.getMethodName() + " as request: " + c.getRequestId());
  82.117 +
  82.118 +                Object result = invokeMethod(c.getClassName(), c.getMethodName());
  82.119 +                
  82.120 +                setAttr("bck2brwsr.fragment", "innerHTML", "");
  82.121 +                log("Result: " + result);
  82.122 +                
  82.123 +                result = encodeURL("" + result);
  82.124 +                
  82.125 +                log("Sending back: " + url + "?request=" + c.getRequestId() + "&result=" + result);
  82.126 +                String u = url + "?request=" + c.getRequestId() + "&result=" + result;
  82.127 +                
  82.128 +                loadText(u, this, arr);
  82.129 +                
  82.130 +            } catch (Exception ex) {
  82.131 +                log(ex.getMessage());
  82.132 +            }
  82.133 +        }
  82.134 +    }
  82.135 +    
  82.136 +    private static String encodeURL(String r) {
  82.137 +        StringBuilder sb = new StringBuilder();
  82.138 +        for (int i = 0; i < r.length(); i++) {
  82.139 +            int ch = r.charAt(i);
  82.140 +            if (ch < 32 || ch == '%' || ch == '+') {
  82.141 +                sb.append("%").append(("0" + Integer.toHexString(ch)).substring(0, 2));
  82.142 +            } else {
  82.143 +                if (ch == 32) {
  82.144 +                    sb.append("+");
  82.145 +                } else {
  82.146 +                    sb.append((char)ch);
  82.147 +                }
  82.148 +            }
  82.149 +        }
  82.150 +        return sb.toString();
  82.151 +    }
  82.152 +    
  82.153 +    static String invoke(String clazz, String method) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException, InstantiationException {
  82.154 +        final Object r = invokeMethod(clazz, method);
  82.155 +        return r == null ? "null" : r.toString().toString();
  82.156 +    }
  82.157 +
  82.158 +    /** Helper method that inspects the classpath and loads given resource
  82.159 +     * (usually a class file). Used while running tests in Rhino.
  82.160 +     * 
  82.161 +     * @param name resource name to find
  82.162 +     * @return the array of bytes in the given resource
  82.163 +     * @throws IOException I/O in case something goes wrong
  82.164 +     */
  82.165 +    public static byte[] read(String name) throws IOException {
  82.166 +        URL u = null;
  82.167 +        Enumeration<URL> en = Console.class.getClassLoader().getResources(name);
  82.168 +        while (en.hasMoreElements()) {
  82.169 +            u = en.nextElement();
  82.170 +        }
  82.171 +        if (u == null) {
  82.172 +            throw new IOException("Can't find " + name);
  82.173 +        }
  82.174 +        try (InputStream is = u.openStream()) {
  82.175 +            byte[] arr;
  82.176 +            arr = new byte[is.available()];
  82.177 +            int offset = 0;
  82.178 +            while (offset < arr.length) {
  82.179 +                int len = is.read(arr, offset, arr.length - offset);
  82.180 +                if (len == -1) {
  82.181 +                    throw new IOException("Can't read " + name);
  82.182 +                }
  82.183 +                offset += len;
  82.184 +            }
  82.185 +            return arr;
  82.186 +        }
  82.187 +    }
  82.188 +   
  82.189 +    private static Object invokeMethod(String clazz, String method) 
  82.190 +    throws ClassNotFoundException, InvocationTargetException, 
  82.191 +    SecurityException, IllegalAccessException, IllegalArgumentException,
  82.192 +    InstantiationException {
  82.193 +        Method found = null;
  82.194 +        Class<?> c = Class.forName(clazz);
  82.195 +        for (Method m : c.getMethods()) {
  82.196 +            if (m.getName().equals(method)) {
  82.197 +                found = m;
  82.198 +            }
  82.199 +        }
  82.200 +        Object res;
  82.201 +        if (found != null) {
  82.202 +            try {
  82.203 +                if ((found.getModifiers() & Modifier.STATIC) != 0) {
  82.204 +                    res = found.invoke(null);
  82.205 +                } else {
  82.206 +                    res = found.invoke(c.newInstance());
  82.207 +                }
  82.208 +            } catch (Throwable ex) {
  82.209 +                res = ex.getClass().getName() + ":" + ex.getMessage();
  82.210 +            }
  82.211 +        } else {
  82.212 +            res = "Can't find method " + method + " in " + clazz;
  82.213 +        }
  82.214 +        return res;
  82.215 +    }
  82.216 +
  82.217 +    @JavaScriptBody(args = {}, body = "vm.desiredAssertionStatus = true;")
  82.218 +    private static void turnAssetionStatusOn() {
  82.219 +    }
  82.220 +    
  82.221 +    private static final class Case {
  82.222 +        private final Object data;
  82.223 +
  82.224 +        private Case(Object data) {
  82.225 +            this.data = data;
  82.226 +        }
  82.227 +        
  82.228 +        public static Case parseData(String s) {
  82.229 +            return new Case(toJSON(s));
  82.230 +        }
  82.231 +        
  82.232 +        public String getMethodName() {
  82.233 +            return value("methodName", data);
  82.234 +        }
  82.235 +
  82.236 +        public String getClassName() {
  82.237 +            return value("className", data);
  82.238 +        }
  82.239 +        
  82.240 +        public String getRequestId() {
  82.241 +            return value("request", data);
  82.242 +        }
  82.243 +
  82.244 +        public String getHtmlFragment() {
  82.245 +            return value("html", data);
  82.246 +        }
  82.247 +        
  82.248 +        @JavaScriptBody(args = "s", body = "return eval('(' + s + ')');")
  82.249 +        private static native Object toJSON(String s);
  82.250 +        
  82.251 +        @JavaScriptBody(args = {"p", "d"}, body = 
  82.252 +              "var v = d[p];\n"
  82.253 +            + "if (typeof v === 'undefined') return null;\n"
  82.254 +            + "return v.toString();"
  82.255 +        )
  82.256 +        private static native String value(String p, Object d);
  82.257 +    }
  82.258 +}
    83.1 --- a/launcher/src/main/resources/org/apidesign/bck2brwsr/launcher/harness.xhtml	Fri Feb 01 16:34:51 2013 +0100
    83.2 +++ b/launcher/src/main/resources/org/apidesign/bck2brwsr/launcher/harness.xhtml	Mon Feb 04 09:37:56 2013 +0100
    83.3 @@ -34,7 +34,7 @@
    83.4          <div id="bck2brwsr.fragment"/>
    83.5          
    83.6          <script type="text/javascript">
    83.7 -            vm.loadClass('org.apidesign.bck2brwsr.launcher.Console').harness__VLjava_lang_String_2('$U/../data');
    83.8 +            vm.loadClass('org.apidesign.bck2brwsr.launcher.impl.Console').harness__VLjava_lang_String_2('$U/../data');
    83.9          </script>
   83.10      </body>
   83.11  </html>
    84.1 --- a/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrswrMojo.java	Fri Feb 01 16:34:51 2013 +0100
    84.2 +++ b/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrswrMojo.java	Mon Feb 04 09:37:56 2013 +0100
    84.3 @@ -51,21 +51,28 @@
    84.4      /** Root of the class files */
    84.5      @Parameter(defaultValue="${project.build.directory}/classes")
    84.6      private File classes;
    84.7 +    
    84.8 +    /** Root of all pages, and files, etc. */
    84.9 +    @Parameter
   84.10 +    private File directory;
   84.11  
   84.12      @Override
   84.13      public void execute() throws MojoExecutionException {
   84.14          if (startpage == null) {
   84.15              throw new MojoExecutionException("You have to provide a start page");
   84.16          }
   84.17 -
   84.18 +        
   84.19          try {
   84.20 -            URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts());
   84.21 -            
   84.22              Closeable httpServer;
   84.23 -            try {
   84.24 -                httpServer = Launcher.showURL(url, startpage());
   84.25 -            } catch (Exception ex) {
   84.26 -                throw new MojoExecutionException("Can't open " + startpage(), ex);
   84.27 +            if (directory != null) {
   84.28 +                httpServer = Launcher.showDir(directory, startpage);
   84.29 +            } else {
   84.30 +                URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts());
   84.31 +                try {
   84.32 +                    httpServer = Launcher.showURL(url, startpage());
   84.33 +                } catch (Exception ex) {
   84.34 +                    throw new MojoExecutionException("Can't open " + startpage(), ex);
   84.35 +                }
   84.36              }
   84.37              System.in.read();
   84.38              httpServer.close();
    85.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Fri Feb 01 16:34:51 2013 +0100
    85.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Mon Feb 04 09:37:56 2013 +0100
    85.3 @@ -1269,7 +1269,7 @@
    85.4                      int indx = readIntArg(byteCodes, i);
    85.5                      final String type = jc.getClassName(indx);
    85.6                      if (!type.startsWith("[")) {
    85.7 -                        emit(out, "var @2 = @1.$instOf_@3 ? 1 : 0;",
    85.8 +                        emit(out, "var @2 = @1 != null && @1.$instOf_@3 ? 1 : 0;",
    85.9                               smapper.popA(), smapper.pushI(),
   85.10                               type.replace('/', '_'));
   85.11                      } else {
    86.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/VM.java	Fri Feb 01 16:34:51 2013 +0100
    86.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/VM.java	Mon Feb 04 09:37:56 2013 +0100
    86.3 @@ -32,6 +32,7 @@
    86.4      static {
    86.5          // uses VMLazy to load dynamic classes
    86.6          VMLazy.init();
    86.7 +        Zips.init();
    86.8      }
    86.9  
   86.10      @Override
   86.11 @@ -116,6 +117,12 @@
   86.12              + "    var args = arguments;\n"
   86.13              + "    var loader = {};\n"
   86.14              + "    loader.vm = vm;\n"
   86.15 +            + "    if (args.length == 1 && typeof args[0] !== 'function') {;\n"
   86.16 +            + "      var classpath = args[0];\n"
   86.17 +            + "      args[0] = function(name) {\n"
   86.18 +            + "        return vm.org_apidesign_vm4brwsr_Zips(false).loadFromCp___3B_3Ljava_lang_Object_2Ljava_lang_String_2(classpath, name);\n"
   86.19 +            + "      };\n"
   86.20 +            + "    };\n"
   86.21              + "    loader.loadClass = function(name) {\n"
   86.22              + "      var attr = name.replace__Ljava_lang_String_2CC('.','_');\n"
   86.23              + "      var fn = vm[attr];\n"
    87.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    87.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/Zips.java	Mon Feb 04 09:37:56 2013 +0100
    87.3 @@ -0,0 +1,97 @@
    87.4 +/**
    87.5 + * Back 2 Browser Bytecode Translator
    87.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    87.7 + *
    87.8 + * This program is free software: you can redistribute it and/or modify
    87.9 + * it under the terms of the GNU General Public License as published by
   87.10 + * the Free Software Foundation, version 2 of the License.
   87.11 + *
   87.12 + * This program is distributed in the hope that it will be useful,
   87.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   87.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   87.15 + * GNU General Public License for more details.
   87.16 + *
   87.17 + * You should have received a copy of the GNU General Public License
   87.18 + * along with this program. Look for COPYING file in the top folder.
   87.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   87.20 + */
   87.21 +package org.apidesign.vm4brwsr;
   87.22 +
   87.23 +import java.io.IOException;
   87.24 +import java.net.URL;
   87.25 +import java.util.zip.ZipEntry;
   87.26 +import java.util.zip.ZipInputStream;
   87.27 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
   87.28 +
   87.29 +/** Conversion from classpath to load function.
   87.30 + *
   87.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   87.32 + */
   87.33 +final class Zips {
   87.34 +    private Zips() {
   87.35 +    }
   87.36 +    
   87.37 +    public static void init() {
   87.38 +    }
   87.39 +    
   87.40 +    public static byte[] loadFromCp(Object[] classpath, String res) {
   87.41 +        for (int i = 0; i < classpath.length; i++) {
   87.42 +            Object c = classpath[i];
   87.43 +            if (c instanceof String) {
   87.44 +                try {
   87.45 +                    c = classpath[i] = toZip((String)c);
   87.46 +                } catch (IOException ex) {
   87.47 +                    classpath[i] = ex;
   87.48 +                }
   87.49 +            }
   87.50 +            if (c instanceof Zips) {
   87.51 +                Object checkRes = ((Zips)c).findRes(res);
   87.52 +                if (checkRes instanceof byte[]) {
   87.53 +                    return (byte[])checkRes;
   87.54 +                }
   87.55 +            }
   87.56 +        }
   87.57 +        return null;
   87.58 +    }
   87.59 +
   87.60 +    @JavaScriptBody(args = { "res" }, body = "var r = this[res]; return r ? r : null;")
   87.61 +    private native byte[] findRes(String res);
   87.62 +
   87.63 +    @JavaScriptBody(args = { "res", "arr" }, body = "this[res] = arr;")
   87.64 +    private native void putRes(String res, byte[] arr);
   87.65 +    
   87.66 +    private static Zips toZip(String path) throws IOException {
   87.67 +        URL u = new URL(path);
   87.68 +        ZipInputStream zip = new ZipInputStream(u.openStream());
   87.69 +        Zips z = new Zips();
   87.70 +        for (;;) {
   87.71 +            ZipEntry entry = zip.getNextEntry();
   87.72 +            if (entry == null) {
   87.73 +                break;
   87.74 +            }
   87.75 +            byte[] arr = new byte[4096];
   87.76 +            int offset = 0;
   87.77 +            for (;;) {
   87.78 +                int len = zip.read(arr, offset, arr.length - offset);
   87.79 +                if (len == -1) {
   87.80 +                    break;
   87.81 +                }
   87.82 +                offset += len;
   87.83 +                if (offset == arr.length) {
   87.84 +                    enlargeArray(arr, arr.length + 4096);
   87.85 +                }
   87.86 +            }
   87.87 +            sliceArray(arr, offset);
   87.88 +            z.putRes(entry.getName(), arr);
   87.89 +        }
   87.90 +        return z;
   87.91 +    }
   87.92 +
   87.93 +    @JavaScriptBody(args = { "arr", "len" }, body = "while (arr.length < len) arr.push(0);")
   87.94 +    private static native void enlargeArray(byte[] arr, int len);
   87.95 +
   87.96 +    @JavaScriptBody(args = { "arr", "len" }, body = "arr.splice(len, arr.length - len);")
   87.97 +    private static native void sliceArray(byte[] arr, int len);
   87.98 +    
   87.99 +    
  87.100 +}
    88.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/Instance.java	Fri Feb 01 16:34:51 2013 +0100
    88.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Instance.java	Mon Feb 04 09:37:56 2013 +0100
    88.3 @@ -68,12 +68,12 @@
    88.4          GetByte i = new InstanceSub(7, 2.2d);
    88.5          return i.getByte();
    88.6      }
    88.7 -    public static boolean instanceOf(boolean sub) {
    88.8 +    public static boolean instanceOf(int sub) {
    88.9          Instance i = createInstance(sub);
   88.10          return isInstanceSubOf(i);
   88.11      }
   88.12      public static int castsWork(boolean interfc) {
   88.13 -        Instance i = createInstance(true);
   88.14 +        Instance i = createInstance(2);
   88.15          if (interfc) {
   88.16              GetByte b = (GetByte)i;
   88.17          } else {
   88.18 @@ -85,11 +85,16 @@
   88.19      private static boolean isInstanceSubOf(Instance instance) {
   88.20          return instance instanceof InstanceSub;
   88.21      }
   88.22 -    private static Instance createInstance(boolean sub) {
   88.23 -        return sub ? new InstanceSub(3, 0) : new Instance();
   88.24 +    private static Instance createInstance(int type) {
   88.25 +        switch (type) {
   88.26 +            case 0: return null;
   88.27 +            case 1: return new Instance();
   88.28 +            case 2: return new InstanceSub(3, 0);
   88.29 +        }
   88.30 +        throw new IllegalArgumentException();
   88.31      }
   88.32      private static boolean isNull() {
   88.33 -        return createInstance(true) == null;
   88.34 +        return createInstance(2) == null;
   88.35      }
   88.36      
   88.37      @JavaScriptBody(args = "obj", body = "return obj.constructor;")
    89.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/InstanceTest.java	Fri Feb 01 16:34:51 2013 +0100
    89.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/InstanceTest.java	Mon Feb 04 09:37:56 2013 +0100
    89.3 @@ -80,16 +80,23 @@
    89.4      @Test public void isInstanceOf() throws Exception {
    89.5          assertExec(
    89.6              "Yes, we are instance",
    89.7 -            Instance.class, "instanceOf__ZZ",
    89.8 -            Double.valueOf(1.0), true
    89.9 +            Instance.class, "instanceOf__ZI",
   89.10 +            Double.valueOf(1.0), 2
   89.11          );
   89.12      }
   89.13  
   89.14      @Test public void notInstanceOf() throws Exception {
   89.15          assertExec(
   89.16              "No, we are not an instance",
   89.17 -            Instance.class, "instanceOf__ZZ",
   89.18 -            Double.valueOf(0.0), false
   89.19 +            Instance.class, "instanceOf__ZI",
   89.20 +            Double.valueOf(0.0), 1
   89.21 +        );
   89.22 +    }
   89.23 +    @Test public void nullInstanceOf() throws Exception {
   89.24 +        assertExec(
   89.25 +            "No, null is not an instance",
   89.26 +            Instance.class, "instanceOf__ZI",
   89.27 +            Double.valueOf(0.0), 0
   89.28          );
   89.29      }
   89.30      
    90.1 --- a/vmtest/pom.xml	Fri Feb 01 16:34:51 2013 +0100
    90.2 +++ b/vmtest/pom.xml	Mon Feb 04 09:37:56 2013 +0100
    90.3 @@ -58,5 +58,10 @@
    90.4        <artifactId>launcher</artifactId>
    90.5        <version>${project.version}</version>
    90.6      </dependency>
    90.7 +    <dependency>
    90.8 +      <groupId>org.netbeans.api</groupId>
    90.9 +      <artifactId>org-openide-util-lookup</artifactId>
   90.10 +      <scope>provided</scope>
   90.11 +    </dependency>
   90.12    </dependencies>
   90.13  </project>
    91.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    91.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/HttpResource.java	Mon Feb 04 09:37:56 2013 +0100
    91.3 @@ -0,0 +1,43 @@
    91.4 +/**
    91.5 + * Back 2 Browser Bytecode Translator
    91.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    91.7 + *
    91.8 + * This program is free software: you can redistribute it and/or modify
    91.9 + * it under the terms of the GNU General Public License as published by
   91.10 + * the Free Software Foundation, version 2 of the License.
   91.11 + *
   91.12 + * This program is distributed in the hope that it will be useful,
   91.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   91.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   91.15 + * GNU General Public License for more details.
   91.16 + *
   91.17 + * You should have received a copy of the GNU General Public License
   91.18 + * along with this program. Look for COPYING file in the top folder.
   91.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   91.20 + */
   91.21 +package org.apidesign.bck2brwsr.vmtest;
   91.22 +
   91.23 +import java.lang.annotation.ElementType;
   91.24 +import java.lang.annotation.Retention;
   91.25 +import java.lang.annotation.RetentionPolicy;
   91.26 +import java.lang.annotation.Target;
   91.27 +
   91.28 +/** Exposes an HTTP page to the running {@link BrwsrTest}, so it can access
   91.29 + * under the relative path.
   91.30 + *
   91.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   91.32 + */
   91.33 +@Retention(RetentionPolicy.RUNTIME)
   91.34 +@Target({ ElementType.METHOD, ElementType.TYPE})
   91.35 +public @interface HttpResource {
   91.36 +    /** path on the server that the test can use to access the exposed resource */
   91.37 +    String path();
   91.38 +    /** the content of the HttpResource */
   91.39 +    String content();
   91.40 +    /** resource relative to the class that should be used instead of <code>content</code>.
   91.41 +     * Leave content equal to empty string.
   91.42 +     */
   91.43 +    String resource() default "";
   91.44 +    /** mime type of the resource */
   91.45 +    String mimeType();
   91.46 +}
    92.1 --- a/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java	Fri Feb 01 16:34:51 2013 +0100
    92.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java	Mon Feb 04 09:37:56 2013 +0100
    92.3 @@ -17,14 +17,18 @@
    92.4   */
    92.5  package org.apidesign.bck2brwsr.vmtest.impl;
    92.6  
    92.7 +import java.io.ByteArrayInputStream;
    92.8  import java.io.File;
    92.9  import java.io.FileWriter;
   92.10  import java.io.IOException;
   92.11 +import java.io.InputStream;
   92.12  import java.lang.reflect.Constructor;
   92.13  import java.lang.reflect.InvocationTargetException;
   92.14  import java.lang.reflect.Method;
   92.15  import org.apidesign.bck2brwsr.launcher.Launcher;
   92.16 -import org.apidesign.bck2brwsr.launcher.MethodInvocation;
   92.17 +import org.apidesign.bck2brwsr.launcher.InvocationContext;
   92.18 +import org.apidesign.bck2brwsr.vmtest.HtmlFragment;
   92.19 +import org.apidesign.bck2brwsr.vmtest.HttpResource;
   92.20  import org.testng.ITest;
   92.21  import org.testng.annotations.Test;
   92.22  
   92.23 @@ -37,22 +41,36 @@
   92.24      private final Launcher l;
   92.25      private final String type;
   92.26      private final boolean fail;
   92.27 +    private final HtmlFragment html;
   92.28 +    private final HttpResource http;
   92.29      Object value;
   92.30 -    private final String html;
   92.31  
   92.32 -    Bck2BrwsrCase(Method m, String type, Launcher l, boolean fail, String html) {
   92.33 +    Bck2BrwsrCase(Method m, String type, Launcher l, boolean fail, HtmlFragment html, HttpResource http) {
   92.34          this.l = l;
   92.35          this.m = m;
   92.36          this.type = type;
   92.37          this.fail = fail;
   92.38          this.html = html;
   92.39 +        this.http = http;
   92.40      }
   92.41  
   92.42      @Test(groups = "run")
   92.43      public void executeCode() throws Throwable {
   92.44          if (l != null) {
   92.45 -            MethodInvocation c = l.invokeMethod(m.getDeclaringClass(), m.getName(), html);
   92.46 -            String res = c.toString();
   92.47 +            InvocationContext c = l.createInvocation(m.getDeclaringClass(), m.getName());
   92.48 +            if (html != null) {
   92.49 +                c.setHtmlFragment(html.value());
   92.50 +            }
   92.51 +            if (http != null) {
   92.52 +                if (!http.content().isEmpty()) {
   92.53 +                    InputStream is = new ByteArrayInputStream(http.content().getBytes("UTF-8"));
   92.54 +                    c.setHttpResource(http.path(), http.mimeType(), is);
   92.55 +                } else {
   92.56 +                    InputStream is = m.getDeclaringClass().getResourceAsStream(http.resource());
   92.57 +                    c.setHttpResource(http.path(), http.mimeType(), is);
   92.58 +                }
   92.59 +            }
   92.60 +            String res = c.invoke();
   92.61              value = res;
   92.62              if (fail) {
   92.63                  int idx = res.indexOf(':');
   92.64 @@ -92,6 +110,9 @@
   92.65              } catch (InvocationTargetException ex) {
   92.66                  Throwable t = ex.getTargetException();
   92.67                  value = t.getClass().getName() + ":" + t.getMessage();
   92.68 +                if (t instanceof AssertionError) {
   92.69 +                    throw t;
   92.70 +                }
   92.71              }
   92.72          }
   92.73      }
    93.1 --- a/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java	Fri Feb 01 16:34:51 2013 +0100
    93.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java	Mon Feb 04 09:37:56 2013 +0100
    93.3 @@ -111,17 +111,17 @@
    93.4          if (c == null) {
    93.5              return;
    93.6          }
    93.7 -        final Bck2BrwsrCase real = new Bck2BrwsrCase(m, "Java", null, false, null);
    93.8 +        final Bck2BrwsrCase real = new Bck2BrwsrCase(m, "Java", null, false, null, null);
    93.9          ret.add(real);
   93.10          if (c.scripting()) {
   93.11 -            final Bck2BrwsrCase js = new Bck2BrwsrCase(m, "JavaScript", l.javaScript(), false, null);
   93.12 +            final Bck2BrwsrCase js = new Bck2BrwsrCase(m, "JavaScript", l.javaScript(), false, null, null);
   93.13              ret.add(js);
   93.14              ret.add(new CompareCase(m, real, js));
   93.15          }
   93.16          for (String b : brwsr) {
   93.17              final Launcher s = l.brwsr(b);
   93.18              ret.add(s);
   93.19 -            final Bck2BrwsrCase cse = new Bck2BrwsrCase(m, b, s, false, null);
   93.20 +            final Bck2BrwsrCase cse = new Bck2BrwsrCase(m, b, s, false, null, null);
   93.21              ret.add(cse);
   93.22              ret.add(new CompareCase(m, real, cse));
   93.23          }
   93.24 @@ -135,16 +135,19 @@
   93.25          if (f == null) {
   93.26              f = m.getDeclaringClass().getAnnotation(HtmlFragment.class);
   93.27          }
   93.28 -        String html = f == null ? null : f.value();
   93.29 +        HttpResource r = m.getAnnotation(HttpResource.class);
   93.30 +        if (r == null) {
   93.31 +            r = m.getDeclaringClass().getAnnotation(HttpResource.class);
   93.32 +        }
   93.33          if (brwsr.length == 0) {
   93.34              final Launcher s = l.brwsr(null);
   93.35              ret.add(s);
   93.36 -            ret.add(new Bck2BrwsrCase(m, "Brwsr", s, true, html));
   93.37 +            ret.add(new Bck2BrwsrCase(m, "Brwsr", s, true, f, r));
   93.38          } else {
   93.39              for (String b : brwsr) {
   93.40                  final Launcher s = l.brwsr(b);
   93.41                  ret.add(s);
   93.42 -                ret.add(new Bck2BrwsrCase(m, b, s, true, html));
   93.43 +                ret.add(new Bck2BrwsrCase(m, b, s, true, f, r));
   93.44              }
   93.45          }
   93.46      }
    94.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    94.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/GenerateZip.java	Mon Feb 04 09:37:56 2013 +0100
    94.3 @@ -0,0 +1,36 @@
    94.4 +/**
    94.5 + * Back 2 Browser Bytecode Translator
    94.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    94.7 + *
    94.8 + * This program is free software: you can redistribute it and/or modify
    94.9 + * it under the terms of the GNU General Public License as published by
   94.10 + * the Free Software Foundation, version 2 of the License.
   94.11 + *
   94.12 + * This program is distributed in the hope that it will be useful,
   94.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   94.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   94.15 + * GNU General Public License for more details.
   94.16 + *
   94.17 + * You should have received a copy of the GNU General Public License
   94.18 + * along with this program. Look for COPYING file in the top folder.
   94.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   94.20 + */
   94.21 +package org.apidesign.bck2brwsr.vmtest.impl;
   94.22 +
   94.23 +import java.lang.annotation.Retention;
   94.24 +import java.lang.annotation.RetentionPolicy;
   94.25 +
   94.26 +/** Annotation to generate a ZIP or JAR file during build.
   94.27 + *
   94.28 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   94.29 + */
   94.30 +@Retention(RetentionPolicy.SOURCE)
   94.31 +@interface GenerateZip {
   94.32 +    String name();
   94.33 +    
   94.34 +    /** manifest for the file */
   94.35 +    String manifest() default "";
   94.36 +
   94.37 +    /** Array of names (at odd positions) and their content (on even) */
   94.38 +    String[] contents();
   94.39 +}
    95.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    95.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/GenerateZipProcessor.java	Mon Feb 04 09:37:56 2013 +0100
    95.3 @@ -0,0 +1,98 @@
    95.4 +/**
    95.5 + * Back 2 Browser Bytecode Translator
    95.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    95.7 + *
    95.8 + * This program is free software: you can redistribute it and/or modify
    95.9 + * it under the terms of the GNU General Public License as published by
   95.10 + * the Free Software Foundation, version 2 of the License.
   95.11 + *
   95.12 + * This program is distributed in the hope that it will be useful,
   95.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   95.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   95.15 + * GNU General Public License for more details.
   95.16 + *
   95.17 + * You should have received a copy of the GNU General Public License
   95.18 + * along with this program. Look for COPYING file in the top folder.
   95.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   95.20 + */
   95.21 +package org.apidesign.bck2brwsr.vmtest.impl;
   95.22 +
   95.23 +import java.io.ByteArrayInputStream;
   95.24 +import java.io.IOException;
   95.25 +import java.io.OutputStream;
   95.26 +import java.util.Set;
   95.27 +import java.util.jar.JarEntry;
   95.28 +import java.util.jar.JarOutputStream;
   95.29 +import java.util.jar.Manifest;
   95.30 +import javax.annotation.processing.AbstractProcessor;
   95.31 +import javax.annotation.processing.Processor;
   95.32 +import javax.annotation.processing.RoundEnvironment;
   95.33 +import javax.annotation.processing.SupportedAnnotationTypes;
   95.34 +import javax.lang.model.element.Element;
   95.35 +import javax.lang.model.element.ElementKind;
   95.36 +import javax.lang.model.element.PackageElement;
   95.37 +import javax.lang.model.element.TypeElement;
   95.38 +import javax.tools.Diagnostic;
   95.39 +import javax.tools.FileObject;
   95.40 +import javax.tools.StandardLocation;
   95.41 +import org.openide.util.lookup.ServiceProvider;
   95.42 +
   95.43 +/**
   95.44 + *
   95.45 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   95.46 + */
   95.47 +@ServiceProvider(service = Processor.class)
   95.48 +@SupportedAnnotationTypes("org.apidesign.bck2brwsr.vmtest.impl.GenerateZip")
   95.49 +public class GenerateZipProcessor extends AbstractProcessor {
   95.50 +
   95.51 +    @Override
   95.52 +    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
   95.53 +        for (Element e : roundEnv.getElementsAnnotatedWith(GenerateZip.class)) {
   95.54 +            GenerateZip gz = e.getAnnotation(GenerateZip.class);
   95.55 +            if (gz == null) {
   95.56 +                continue;
   95.57 +            }
   95.58 +            PackageElement pe = findPackage(e);
   95.59 +            try {
   95.60 +                generateJar(pe, gz, e);
   95.61 +            } catch (IOException ex) {
   95.62 +                processingEnv.getMessager().printMessage(
   95.63 +                    Diagnostic.Kind.ERROR, 
   95.64 +                    "Can't generate JAR " + gz.name() + ": " + ex.getMessage()
   95.65 +                );
   95.66 +            }
   95.67 +        }
   95.68 +        return true;
   95.69 +    }
   95.70 +
   95.71 +    private static PackageElement findPackage(Element e) {
   95.72 +        while (e.getKind() != ElementKind.PACKAGE) {
   95.73 +            e = e.getEnclosingElement();
   95.74 +        }
   95.75 +        return (PackageElement)e;
   95.76 +    }
   95.77 +
   95.78 +    private void generateJar(PackageElement pe, GenerateZip gz, Element e) throws IOException {
   95.79 +        FileObject res = processingEnv.getFiler().createResource(
   95.80 +            StandardLocation.CLASS_OUTPUT, 
   95.81 +            pe.getQualifiedName().toString(), 
   95.82 +            gz.name(), e
   95.83 +        );
   95.84 +        OutputStream os = res.openOutputStream();
   95.85 +        JarOutputStream jar;
   95.86 +        if (gz.manifest().isEmpty()) {
   95.87 +            jar = new JarOutputStream(os);
   95.88 +        } else {
   95.89 +            Manifest mf = new Manifest(new ByteArrayInputStream(gz.manifest().getBytes("UTF-8")));
   95.90 +            jar = new JarOutputStream(os, mf);
   95.91 +        }
   95.92 +        String[] arr = gz.contents();
   95.93 +        for (int i = 0; i < arr.length; i += 2) {
   95.94 +            JarEntry je = new JarEntry(arr[i]);
   95.95 +            jar.putNextEntry(je);
   95.96 +            jar.write(arr[i + 1].getBytes("UTF-8"));
   95.97 +            jar.closeEntry();
   95.98 +        }
   95.99 +    }
  95.100 +    
  95.101 +}
    96.1 --- a/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/AssertionTest.java	Fri Feb 01 16:34:51 2013 +0100
    96.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/AssertionTest.java	Mon Feb 04 09:37:56 2013 +0100
    96.3 @@ -28,8 +28,12 @@
    96.4  public class AssertionTest {
    96.5  
    96.6      @Compare public Object checkAssert() throws ClassNotFoundException {
    96.7 -        assert false : "Is assertion status on?";
    96.8 -        return null;
    96.9 +        try {
   96.10 +            assert false : "Is assertion status on?";
   96.11 +            return null;
   96.12 +        } catch (AssertionError ex) {
   96.13 +            return ex.getClass().getName();
   96.14 +        }
   96.15      }
   96.16      
   96.17      @Factory
    97.1 --- a/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java	Fri Feb 01 16:34:51 2013 +0100
    97.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java	Mon Feb 04 09:37:56 2013 +0100
    97.3 @@ -17,6 +17,7 @@
    97.4   */
    97.5  package org.apidesign.bck2brwsr.tck;
    97.6  
    97.7 +import java.io.UnsupportedEncodingException;
    97.8  import java.net.MalformedURLException;
    97.9  import java.net.URL;
   97.10  import org.apidesign.bck2brwsr.vmtest.Compare;
   97.11 @@ -120,6 +121,21 @@
   97.12          NullField nf = new NullField();
   97.13          return ("" + nf.name).toString();
   97.14      }
   97.15 +    @Compare
   97.16 +    public String toUTFString() throws UnsupportedEncodingException {
   97.17 +        byte[] arr = {
   97.18 +            (byte) -59, (byte) -67, (byte) 108, (byte) 117, (byte) -59, (byte) -91,
   97.19 +            (byte) 111, (byte) 117, (byte) -60, (byte) -115, (byte) 107, (byte) -61,
   97.20 +            (byte) -67, (byte) 32, (byte) 107, (byte) -59, (byte) -81, (byte) -59,
   97.21 +            (byte) -120
   97.22 +        };
   97.23 +        return new String(arr, "utf-8");
   97.24 +    }
   97.25 +
   97.26 +    @Compare
   97.27 +    public int stringToBytesLenght() throws UnsupportedEncodingException {
   97.28 +        return "Žluťoučký kůň".getBytes("utf8").length;
   97.29 +    }
   97.30  
   97.31      @Factory
   97.32      public static Object[] create() {
    98.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    98.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/HttpResourceTest.java	Mon Feb 04 09:37:56 2013 +0100
    98.3 @@ -0,0 +1,94 @@
    98.4 +/**
    98.5 + * Back 2 Browser Bytecode Translator
    98.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    98.7 + *
    98.8 + * This program is free software: you can redistribute it and/or modify
    98.9 + * it under the terms of the GNU General Public License as published by
   98.10 + * the Free Software Foundation, version 2 of the License.
   98.11 + *
   98.12 + * This program is distributed in the hope that it will be useful,
   98.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   98.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   98.15 + * GNU General Public License for more details.
   98.16 + *
   98.17 + * You should have received a copy of the GNU General Public License
   98.18 + * along with this program. Look for COPYING file in the top folder.
   98.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   98.20 + */
   98.21 +package org.apidesign.bck2brwsr.tck;
   98.22 +
   98.23 +import java.io.InputStream;
   98.24 +import java.net.URL;
   98.25 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
   98.26 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
   98.27 +import org.apidesign.bck2brwsr.vmtest.HttpResource;
   98.28 +import org.apidesign.bck2brwsr.vmtest.VMTest;
   98.29 +import org.testng.annotations.Factory;
   98.30 +
   98.31 +/**
   98.32 + *
   98.33 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   98.34 + */
   98.35 +public class HttpResourceTest {
   98.36 +    
   98.37 +    @HttpResource(path = "/xhr", content = "Hello Brwsr!", mimeType = "text/plain")
   98.38 +    @BrwsrTest
   98.39 +    public String testReadContentViaXHR() throws Exception {
   98.40 +        String msg = read("/xhr");
   98.41 +        assert "Hello Brwsr!".equals(msg) : "The message was " + msg;
   98.42 +        return msg;
   98.43 +    }
   98.44 +
   98.45 +    @HttpResource(path = "/url", content = "Hello via URL!", mimeType = "text/plain")
   98.46 +    @BrwsrTest
   98.47 +    public String testReadContentViaURL() throws Exception {
   98.48 +        URL url = new URL("http:/url");
   98.49 +        String msg = (String) url.getContent();
   98.50 +        assert "Hello via URL!".equals(msg) : "The message was " + msg;
   98.51 +        return msg;
   98.52 +    }
   98.53 +    @HttpResource(path = "/url", content = "Hello via URL!", mimeType = "text/plain")
   98.54 +    @BrwsrTest
   98.55 +    public String testReadContentViaURLWithStringParam() throws Exception {
   98.56 +        URL url = new URL("http:/url");
   98.57 +        String msg = (String) url.getContent(new Class[] { String.class });
   98.58 +        assert "Hello via URL!".equals(msg) : "The message was " + msg;
   98.59 +        return msg;
   98.60 +    }
   98.61 +
   98.62 +    @HttpResource(path = "/bytes", content = "", resource = "0xfe", mimeType = "x-application/binary")
   98.63 +    @BrwsrTest
   98.64 +    public void testReadByte() throws Exception {
   98.65 +        URL url = new URL("http:/bytes");
   98.66 +        final Object res = url.getContent(new Class[] { byte[].class });
   98.67 +        assert res instanceof byte[] : "Expecting byte[]: " + res;
   98.68 +        byte[] arr = (byte[]) res;
   98.69 +        assert arr.length == 1 : "One byte " + arr.length;
   98.70 +        assert arr[0] == 0xfe : "It is 0xfe: " + Integer.toHexString(arr[0]);
   98.71 +    }
   98.72 +
   98.73 +    @HttpResource(path = "/bytes", content = "", resource = "0xfe", mimeType = "x-application/binary")
   98.74 +    @BrwsrTest
   98.75 +    public void testReadByteViaInputStream() throws Exception {
   98.76 +        URL url = new URL("http:/bytes");
   98.77 +        InputStream is = url.openStream();
   98.78 +        byte[] arr = new byte[10];
   98.79 +        int len = is.read(arr);
   98.80 +        assert len == 1 : "One byte " + len;
   98.81 +        assert arr[0] == 0xfe : "It is 0xfe: " + Integer.toHexString(arr[0]);
   98.82 +    }
   98.83 +    
   98.84 +    @JavaScriptBody(args = { "url" }, body = 
   98.85 +          "var req = new XMLHttpRequest();\n"
   98.86 +        + "req.open('GET', url, false);\n"
   98.87 +        + "req.send();\n"
   98.88 +        + "return req.responseText;"
   98.89 +    )
   98.90 +    private static native String read(String url);
   98.91 +    
   98.92 +    
   98.93 +    @Factory
   98.94 +    public static Object[] create() {
   98.95 +        return VMTest.create(HttpResourceTest.class);
   98.96 +    }
   98.97 +}
    99.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    99.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/CRC32Test.java	Mon Feb 04 09:37:56 2013 +0100
    99.3 @@ -0,0 +1,41 @@
    99.4 +/**
    99.5 + * Back 2 Browser Bytecode Translator
    99.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    99.7 + *
    99.8 + * This program is free software: you can redistribute it and/or modify
    99.9 + * it under the terms of the GNU General Public License as published by
   99.10 + * the Free Software Foundation, version 2 of the License.
   99.11 + *
   99.12 + * This program is distributed in the hope that it will be useful,
   99.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   99.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   99.15 + * GNU General Public License for more details.
   99.16 + *
   99.17 + * You should have received a copy of the GNU General Public License
   99.18 + * along with this program. Look for COPYING file in the top folder.
   99.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   99.20 + */
   99.21 +package org.apidesign.bck2brwsr.vmtest.impl;
   99.22 +
   99.23 +import java.io.UnsupportedEncodingException;
   99.24 +import java.util.zip.CRC32;
   99.25 +import org.apidesign.bck2brwsr.vmtest.Compare;
   99.26 +import org.apidesign.bck2brwsr.vmtest.VMTest;
   99.27 +import org.testng.annotations.Factory;
   99.28 +
   99.29 +/**
   99.30 + *
   99.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   99.32 + */
   99.33 +public class CRC32Test {
   99.34 +
   99.35 +    @Compare public long crc1() throws UnsupportedEncodingException {
   99.36 +        CRC32 crc = new CRC32();
   99.37 +        crc.update("Hello World!".getBytes("UTF-8"));
   99.38 +        return crc.getValue();
   99.39 +    }
   99.40 +    
   99.41 +    @Factory public static Object[] create() {
   99.42 +        return VMTest.create(CRC32Test.class);
   99.43 +    }
   99.44 +}
   100.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   100.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java	Mon Feb 04 09:37:56 2013 +0100
   100.3 @@ -0,0 +1,84 @@
   100.4 +/**
   100.5 + * Back 2 Browser Bytecode Translator
   100.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   100.7 + *
   100.8 + * This program is free software: you can redistribute it and/or modify
   100.9 + * it under the terms of the GNU General Public License as published by
  100.10 + * the Free Software Foundation, version 2 of the License.
  100.11 + *
  100.12 + * This program is distributed in the hope that it will be useful,
  100.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  100.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  100.15 + * GNU General Public License for more details.
  100.16 + *
  100.17 + * You should have received a copy of the GNU General Public License
  100.18 + * along with this program. Look for COPYING file in the top folder.
  100.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  100.20 + */
  100.21 +package org.apidesign.bck2brwsr.vmtest.impl;
  100.22 +
  100.23 +import java.io.IOException;
  100.24 +import java.io.InputStream;
  100.25 +import java.util.Objects;
  100.26 +import java.util.zip.ZipEntry;
  100.27 +import java.util.zip.ZipInputStream;
  100.28 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
  100.29 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
  100.30 +import org.apidesign.bck2brwsr.vmtest.Compare;
  100.31 +import org.apidesign.bck2brwsr.vmtest.HttpResource;
  100.32 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  100.33 +import org.testng.annotations.Factory;
  100.34 +
  100.35 +/**
  100.36 + *
  100.37 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  100.38 + */
  100.39 +@GenerateZip(name = "readAnEntry.zip", contents = { 
  100.40 +    "my/main/file.txt", "Hello World!"
  100.41 +})
  100.42 +public class ZipFileTest {
  100.43 +    
  100.44 +    @Compare public String readAnEntry() throws IOException {
  100.45 +        InputStream is = ZipFileTest.class.getResourceAsStream("readAnEntry.zip");
  100.46 +        ZipInputStream zip = new ZipInputStream(is);
  100.47 +        ZipEntry entry = zip.getNextEntry();
  100.48 +        assertEquals(entry.getName(), "my/main/file.txt", "Correct entry");
  100.49 +
  100.50 +        byte[] arr = new byte[4096];
  100.51 +        int len = zip.read(arr);
  100.52 +        
  100.53 +        assertEquals(zip.getNextEntry(), null, "No next entry");
  100.54 +        
  100.55 +        final String ret = new String(arr, 0, len, "UTF-8");
  100.56 +        return ret;
  100.57 +    }
  100.58 +    
  100.59 +    @JavaScriptBody(args = { "res", "path" }, body = 
  100.60 +          "var myvm = new bck2brwsr(path);\n"
  100.61 +        + "var cls = myvm.loadClass('java.lang.String');\n"
  100.62 +        + "return cls.getClass__Ljava_lang_Class_2().getResourceAsStream__Ljava_io_InputStream_2Ljava_lang_String_2(res);\n"
  100.63 +    )
  100.64 +    private static native Object loadVMResource(String res, String...path);
  100.65 +
  100.66 +    @HttpResource(path = "/readAnEntry.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip")
  100.67 +    @BrwsrTest  public void canVmLoadResourceFromZip() throws IOException {
  100.68 +        Object res = loadVMResource("/my/main/file.txt", "/readAnEntry.jar");
  100.69 +        assert res instanceof InputStream : "Got array of bytes: " + res;
  100.70 +        InputStream is = (InputStream)res;
  100.71 +        
  100.72 +        byte[] arr = new byte[4096];
  100.73 +        int len = is.read(arr);
  100.74 +        
  100.75 +        final String ret = new String(arr, 0, len, "UTF-8");
  100.76 +
  100.77 +        assertEquals(ret, "Hello World!", "Can read the bytes");
  100.78 +    }
  100.79 +    
  100.80 +    private static void assertEquals(Object real, Object exp, String msg) {
  100.81 +        assert Objects.equals(exp, real) : msg + " exp: " + exp + " real: " + real;
  100.82 +    }
  100.83 +    
  100.84 +    @Factory public static Object[] create() {
  100.85 +        return VMTest.create(ZipFileTest.class);
  100.86 +    }
  100.87 +}
   101.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   101.2 +++ b/vmtest/src/test/resources/org/apidesign/bck2brwsr/tck/0xfe	Mon Feb 04 09:37:56 2013 +0100
   101.3 @@ -0,0 +1,1 @@
   101.4 +
   101.5 \ No newline at end of file