1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/emul/compact/src/main/java/java/beans/ChangeListenerMap.java Fri Feb 01 16:35:42 2013 +0100
1.3 @@ -0,0 +1,247 @@
1.4 +/*
1.5 + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1.7 + *
1.8 + * This code is free software; you can redistribute it and/or modify it
1.9 + * under the terms of the GNU General Public License version 2 only, as
1.10 + * published by the Free Software Foundation. Oracle designates this
1.11 + * particular file as subject to the "Classpath" exception as provided
1.12 + * by Oracle in the LICENSE file that accompanied this code.
1.13 + *
1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1.17 + * version 2 for more details (a copy is included in the LICENSE file that
1.18 + * accompanied this code).
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License version
1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1.23 + *
1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1.25 + * or visit www.oracle.com if you need additional information or have any
1.26 + * questions.
1.27 + */
1.28 +package java.beans;
1.29 +
1.30 +import java.util.ArrayList;
1.31 +import java.util.Collections;
1.32 +import java.util.EventListener;
1.33 +import java.util.EventListenerProxy;
1.34 +import java.util.HashMap;
1.35 +import java.util.List;
1.36 +import java.util.Map;
1.37 +import java.util.Map.Entry;
1.38 +import java.util.Set;
1.39 +
1.40 +/**
1.41 + * This is an abstract class that provides base functionality
1.42 + * for the {@link PropertyChangeSupport PropertyChangeSupport} class
1.43 + * and the {@link VetoableChangeSupport VetoableChangeSupport} class.
1.44 + *
1.45 + * @see PropertyChangeListenerMap
1.46 + * @see VetoableChangeListenerMap
1.47 + *
1.48 + * @author Sergey A. Malenkov
1.49 + */
1.50 +abstract class ChangeListenerMap<L extends EventListener> {
1.51 + private Map<String, L[]> map;
1.52 +
1.53 + /**
1.54 + * Creates an array of listeners.
1.55 + * This method can be optimized by using
1.56 + * the same instance of the empty array
1.57 + * when {@code length} is equal to {@code 0}.
1.58 + *
1.59 + * @param length the array length
1.60 + * @return an array with specified length
1.61 + */
1.62 + protected abstract L[] newArray(int length);
1.63 +
1.64 + /**
1.65 + * Creates a proxy listener for the specified property.
1.66 + *
1.67 + * @param name the name of the property to listen on
1.68 + * @param listener the listener to process events
1.69 + * @return a proxy listener
1.70 + */
1.71 + protected abstract L newProxy(String name, L listener);
1.72 +
1.73 + /**
1.74 + * Adds a listener to the list of listeners for the specified property.
1.75 + * This listener is called as many times as it was added.
1.76 + *
1.77 + * @param name the name of the property to listen on
1.78 + * @param listener the listener to process events
1.79 + */
1.80 + public final synchronized void add(String name, L listener) {
1.81 + if (this.map == null) {
1.82 + this.map = new HashMap<String, L[]>();
1.83 + }
1.84 + L[] array = this.map.get(name);
1.85 + int size = (array != null)
1.86 + ? array.length
1.87 + : 0;
1.88 +
1.89 + L[] clone = newArray(size + 1);
1.90 + clone[size] = listener;
1.91 + if (array != null) {
1.92 + System.arraycopy(array, 0, clone, 0, size);
1.93 + }
1.94 + this.map.put(name, clone);
1.95 + }
1.96 +
1.97 + /**
1.98 + * Removes a listener from the list of listeners for the specified property.
1.99 + * If the listener was added more than once to the same event source,
1.100 + * this listener will be notified one less time after being removed.
1.101 + *
1.102 + * @param name the name of the property to listen on
1.103 + * @param listener the listener to process events
1.104 + */
1.105 + public final synchronized void remove(String name, L listener) {
1.106 + if (this.map != null) {
1.107 + L[] array = this.map.get(name);
1.108 + if (array != null) {
1.109 + for (int i = 0; i < array.length; i++) {
1.110 + if (listener.equals(array[i])) {
1.111 + int size = array.length - 1;
1.112 + if (size > 0) {
1.113 + L[] clone = newArray(size);
1.114 + System.arraycopy(array, 0, clone, 0, i);
1.115 + System.arraycopy(array, i + 1, clone, i, size - i);
1.116 + this.map.put(name, clone);
1.117 + }
1.118 + else {
1.119 + this.map.remove(name);
1.120 + if (this.map.isEmpty()) {
1.121 + this.map = null;
1.122 + }
1.123 + }
1.124 + break;
1.125 + }
1.126 + }
1.127 + }
1.128 + }
1.129 + }
1.130 +
1.131 + /**
1.132 + * Returns the list of listeners for the specified property.
1.133 + *
1.134 + * @param name the name of the property
1.135 + * @return the corresponding list of listeners
1.136 + */
1.137 + public final synchronized L[] get(String name) {
1.138 + return (this.map != null)
1.139 + ? this.map.get(name)
1.140 + : null;
1.141 + }
1.142 +
1.143 + /**
1.144 + * Sets new list of listeners for the specified property.
1.145 + *
1.146 + * @param name the name of the property
1.147 + * @param listeners new list of listeners
1.148 + */
1.149 + public final void set(String name, L[] listeners) {
1.150 + if (listeners != null) {
1.151 + if (this.map == null) {
1.152 + this.map = new HashMap<String, L[]>();
1.153 + }
1.154 + this.map.put(name, listeners);
1.155 + }
1.156 + else if (this.map != null) {
1.157 + this.map.remove(name);
1.158 + if (this.map.isEmpty()) {
1.159 + this.map = null;
1.160 + }
1.161 + }
1.162 + }
1.163 +
1.164 + /**
1.165 + * Returns all listeners in the map.
1.166 + *
1.167 + * @return an array of all listeners
1.168 + */
1.169 + public final synchronized L[] getListeners() {
1.170 + if (this.map == null) {
1.171 + return newArray(0);
1.172 + }
1.173 + List<L> list = new ArrayList<L>();
1.174 +
1.175 + L[] listeners = this.map.get(null);
1.176 + if (listeners != null) {
1.177 + for (L listener : listeners) {
1.178 + list.add(listener);
1.179 + }
1.180 + }
1.181 + for (Entry<String, L[]> entry : this.map.entrySet()) {
1.182 + String name = entry.getKey();
1.183 + if (name != null) {
1.184 + for (L listener : entry.getValue()) {
1.185 + list.add(newProxy(name, listener));
1.186 + }
1.187 + }
1.188 + }
1.189 + return list.toArray(newArray(list.size()));
1.190 + }
1.191 +
1.192 + /**
1.193 + * Returns listeners that have been associated with the named property.
1.194 + *
1.195 + * @param name the name of the property
1.196 + * @return an array of listeners for the named property
1.197 + */
1.198 + public final L[] getListeners(String name) {
1.199 + if (name != null) {
1.200 + L[] listeners = get(name);
1.201 + if (listeners != null) {
1.202 + return listeners.clone();
1.203 + }
1.204 + }
1.205 + return newArray(0);
1.206 + }
1.207 +
1.208 + /**
1.209 + * Indicates whether the map contains
1.210 + * at least one listener to be notified.
1.211 + *
1.212 + * @param name the name of the property
1.213 + * @return {@code true} if at least one listener exists or
1.214 + * {@code false} otherwise
1.215 + */
1.216 + public final synchronized boolean hasListeners(String name) {
1.217 + if (this.map == null) {
1.218 + return false;
1.219 + }
1.220 + L[] array = this.map.get(null);
1.221 + return (array != null) || ((name != null) && (null != this.map.get(name)));
1.222 + }
1.223 +
1.224 + /**
1.225 + * Returns a set of entries from the map.
1.226 + * Each entry is a pair consisted of the property name
1.227 + * and the corresponding list of listeners.
1.228 + *
1.229 + * @return a set of entries from the map
1.230 + */
1.231 + public final Set<Entry<String, L[]>> getEntries() {
1.232 + return (this.map != null)
1.233 + ? this.map.entrySet()
1.234 + : Collections.<Entry<String, L[]>>emptySet();
1.235 + }
1.236 +
1.237 + /**
1.238 + * Extracts a real listener from the proxy listener.
1.239 + * It is necessary because default proxy class is not serializable.
1.240 + *
1.241 + * @return a real listener
1.242 + */
1.243 + public final L extract(L listener) {
1.244 + while (listener instanceof EventListenerProxy) {
1.245 + EventListenerProxy<L> proxy = (EventListenerProxy<L>) listener;
1.246 + listener = proxy.getListener();
1.247 + }
1.248 + return listener;
1.249 + }
1.250 +}
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/emul/compact/src/main/java/java/beans/IndexedPropertyChangeEvent.java Fri Feb 01 16:35:42 2013 +0100
2.3 @@ -0,0 +1,78 @@
2.4 +/*
2.5 + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2.7 + *
2.8 + * This code is free software; you can redistribute it and/or modify it
2.9 + * under the terms of the GNU General Public License version 2 only, as
2.10 + * published by the Free Software Foundation. Oracle designates this
2.11 + * particular file as subject to the "Classpath" exception as provided
2.12 + * by Oracle in the LICENSE file that accompanied this code.
2.13 + *
2.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
2.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
2.17 + * version 2 for more details (a copy is included in the LICENSE file that
2.18 + * accompanied this code).
2.19 + *
2.20 + * You should have received a copy of the GNU General Public License version
2.21 + * 2 along with this work; if not, write to the Free Software Foundation,
2.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2.23 + *
2.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2.25 + * or visit www.oracle.com if you need additional information or have any
2.26 + * questions.
2.27 + */
2.28 +package java.beans;
2.29 +
2.30 +/**
2.31 + * An "IndexedPropertyChange" event gets delivered whenever a component that
2.32 + * conforms to the JavaBeans™ specification (a "bean") changes a bound
2.33 + * indexed property. This class is an extension of <code>PropertyChangeEvent</code>
2.34 + * but contains the index of the property that has changed.
2.35 + * <P>
2.36 + * Null values may be provided for the old and the new values if their
2.37 + * true values are not known.
2.38 + * <P>
2.39 + * An event source may send a null object as the name to indicate that an
2.40 + * arbitrary set of if its properties have changed. In this case the
2.41 + * old and new values should also be null.
2.42 + *
2.43 + * @since 1.5
2.44 + * @author Mark Davidson
2.45 + */
2.46 +public class IndexedPropertyChangeEvent extends PropertyChangeEvent {
2.47 + private static final long serialVersionUID = -320227448495806870L;
2.48 +
2.49 + private int index;
2.50 +
2.51 + /**
2.52 + * Constructs a new <code>IndexedPropertyChangeEvent</code> object.
2.53 + *
2.54 + * @param source The bean that fired the event.
2.55 + * @param propertyName The programmatic name of the property that
2.56 + * was changed.
2.57 + * @param oldValue The old value of the property.
2.58 + * @param newValue The new value of the property.
2.59 + * @param index index of the property element that was changed.
2.60 + */
2.61 + public IndexedPropertyChangeEvent(Object source, String propertyName,
2.62 + Object oldValue, Object newValue,
2.63 + int index) {
2.64 + super (source, propertyName, oldValue, newValue);
2.65 + this.index = index;
2.66 + }
2.67 +
2.68 + /**
2.69 + * Gets the index of the property that was changed.
2.70 + *
2.71 + * @return The index specifying the property element that was
2.72 + * changed.
2.73 + */
2.74 + public int getIndex() {
2.75 + return index;
2.76 + }
2.77 +
2.78 + void appendTo(StringBuilder sb) {
2.79 + sb.append("; index=").append(getIndex());
2.80 + }
2.81 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/emul/compact/src/main/java/java/beans/PropertyChangeEvent.java Fri Feb 01 16:35:42 2013 +0100
3.3 @@ -0,0 +1,164 @@
3.4 +/*
3.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3.7 + *
3.8 + * This code is free software; you can redistribute it and/or modify it
3.9 + * under the terms of the GNU General Public License version 2 only, as
3.10 + * published by the Free Software Foundation. Oracle designates this
3.11 + * particular file as subject to the "Classpath" exception as provided
3.12 + * by Oracle in the LICENSE file that accompanied this code.
3.13 + *
3.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
3.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
3.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
3.17 + * version 2 for more details (a copy is included in the LICENSE file that
3.18 + * accompanied this code).
3.19 + *
3.20 + * You should have received a copy of the GNU General Public License version
3.21 + * 2 along with this work; if not, write to the Free Software Foundation,
3.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
3.23 + *
3.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
3.25 + * or visit www.oracle.com if you need additional information or have any
3.26 + * questions.
3.27 + */
3.28 +
3.29 +package java.beans;
3.30 +
3.31 +/**
3.32 + * A "PropertyChange" event gets delivered whenever a bean changes a "bound"
3.33 + * or "constrained" property. A PropertyChangeEvent object is sent as an
3.34 + * argument to the PropertyChangeListener and VetoableChangeListener methods.
3.35 + * <P>
3.36 + * Normally PropertyChangeEvents are accompanied by the name and the old
3.37 + * and new value of the changed property. If the new value is a primitive
3.38 + * type (such as int or boolean) it must be wrapped as the
3.39 + * corresponding java.lang.* Object type (such as Integer or Boolean).
3.40 + * <P>
3.41 + * Null values may be provided for the old and the new values if their
3.42 + * true values are not known.
3.43 + * <P>
3.44 + * An event source may send a null object as the name to indicate that an
3.45 + * arbitrary set of if its properties have changed. In this case the
3.46 + * old and new values should also be null.
3.47 + */
3.48 +
3.49 +public class PropertyChangeEvent extends java.util.EventObject {
3.50 + private static final long serialVersionUID = 7042693688939648123L;
3.51 +
3.52 + /**
3.53 + * Constructs a new <code>PropertyChangeEvent</code>.
3.54 + *
3.55 + * @param source The bean that fired the event.
3.56 + * @param propertyName The programmatic name of the property
3.57 + * that was changed.
3.58 + * @param oldValue The old value of the property.
3.59 + * @param newValue The new value of the property.
3.60 + */
3.61 + public PropertyChangeEvent(Object source, String propertyName,
3.62 + Object oldValue, Object newValue) {
3.63 + super(source);
3.64 + this.propertyName = propertyName;
3.65 + this.newValue = newValue;
3.66 + this.oldValue = oldValue;
3.67 + }
3.68 +
3.69 + /**
3.70 + * Gets the programmatic name of the property that was changed.
3.71 + *
3.72 + * @return The programmatic name of the property that was changed.
3.73 + * May be null if multiple properties have changed.
3.74 + */
3.75 + public String getPropertyName() {
3.76 + return propertyName;
3.77 + }
3.78 +
3.79 + /**
3.80 + * Gets the new value for the property, expressed as an Object.
3.81 + *
3.82 + * @return The new value for the property, expressed as an Object.
3.83 + * May be null if multiple properties have changed.
3.84 + */
3.85 + public Object getNewValue() {
3.86 + return newValue;
3.87 + }
3.88 +
3.89 + /**
3.90 + * Gets the old value for the property, expressed as an Object.
3.91 + *
3.92 + * @return The old value for the property, expressed as an Object.
3.93 + * May be null if multiple properties have changed.
3.94 + */
3.95 + public Object getOldValue() {
3.96 + return oldValue;
3.97 + }
3.98 +
3.99 + /**
3.100 + * Sets the propagationId object for the event.
3.101 + *
3.102 + * @param propagationId The propagationId object for the event.
3.103 + */
3.104 + public void setPropagationId(Object propagationId) {
3.105 + this.propagationId = propagationId;
3.106 + }
3.107 +
3.108 + /**
3.109 + * The "propagationId" field is reserved for future use. In Beans 1.0
3.110 + * the sole requirement is that if a listener catches a PropertyChangeEvent
3.111 + * and then fires a PropertyChangeEvent of its own, then it should
3.112 + * make sure that it propagates the propagationId field from its
3.113 + * incoming event to its outgoing event.
3.114 + *
3.115 + * @return the propagationId object associated with a bound/constrained
3.116 + * property update.
3.117 + */
3.118 + public Object getPropagationId() {
3.119 + return propagationId;
3.120 + }
3.121 +
3.122 + /**
3.123 + * name of the property that changed. May be null, if not known.
3.124 + * @serial
3.125 + */
3.126 + private String propertyName;
3.127 +
3.128 + /**
3.129 + * New value for property. May be null if not known.
3.130 + * @serial
3.131 + */
3.132 + private Object newValue;
3.133 +
3.134 + /**
3.135 + * Previous value for property. May be null if not known.
3.136 + * @serial
3.137 + */
3.138 + private Object oldValue;
3.139 +
3.140 + /**
3.141 + * Propagation ID. May be null.
3.142 + * @serial
3.143 + * @see #getPropagationId
3.144 + */
3.145 + private Object propagationId;
3.146 +
3.147 + /**
3.148 + * Returns a string representation of the object.
3.149 + *
3.150 + * @return a string representation of the object
3.151 + *
3.152 + * @since 1.7
3.153 + */
3.154 + public String toString() {
3.155 + StringBuilder sb = new StringBuilder(getClass().getName());
3.156 + sb.append("[propertyName=").append(getPropertyName());
3.157 + appendTo(sb);
3.158 + sb.append("; oldValue=").append(getOldValue());
3.159 + sb.append("; newValue=").append(getNewValue());
3.160 + sb.append("; propagationId=").append(getPropagationId());
3.161 + sb.append("; source=").append(getSource());
3.162 + return sb.append("]").toString();
3.163 + }
3.164 +
3.165 + void appendTo(StringBuilder sb) {
3.166 + }
3.167 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/emul/compact/src/main/java/java/beans/PropertyChangeListener.java Fri Feb 01 16:35:42 2013 +0100
4.3 @@ -0,0 +1,44 @@
4.4 +/*
4.5 + * Copyright (c) 1996, Oracle and/or its affiliates. All rights reserved.
4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4.7 + *
4.8 + * This code is free software; you can redistribute it and/or modify it
4.9 + * under the terms of the GNU General Public License version 2 only, as
4.10 + * published by the Free Software Foundation. Oracle designates this
4.11 + * particular file as subject to the "Classpath" exception as provided
4.12 + * by Oracle in the LICENSE file that accompanied this code.
4.13 + *
4.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
4.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
4.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
4.17 + * version 2 for more details (a copy is included in the LICENSE file that
4.18 + * accompanied this code).
4.19 + *
4.20 + * You should have received a copy of the GNU General Public License version
4.21 + * 2 along with this work; if not, write to the Free Software Foundation,
4.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
4.23 + *
4.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
4.25 + * or visit www.oracle.com if you need additional information or have any
4.26 + * questions.
4.27 + */
4.28 +
4.29 +package java.beans;
4.30 +
4.31 +/**
4.32 + * A "PropertyChange" event gets fired whenever a bean changes a "bound"
4.33 + * property. You can register a PropertyChangeListener with a source
4.34 + * bean so as to be notified of any bound property updates.
4.35 + */
4.36 +
4.37 +public interface PropertyChangeListener extends java.util.EventListener {
4.38 +
4.39 + /**
4.40 + * This method gets called when a bound property is changed.
4.41 + * @param evt A PropertyChangeEvent object describing the event source
4.42 + * and the property that has changed.
4.43 + */
4.44 +
4.45 + void propertyChange(PropertyChangeEvent evt);
4.46 +
4.47 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/emul/compact/src/main/java/java/beans/PropertyChangeListenerProxy.java Fri Feb 01 16:35:42 2013 +0100
5.3 @@ -0,0 +1,81 @@
5.4 +/*
5.5 + * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5.7 + *
5.8 + * This code is free software; you can redistribute it and/or modify it
5.9 + * under the terms of the GNU General Public License version 2 only, as
5.10 + * published by the Free Software Foundation. Oracle designates this
5.11 + * particular file as subject to the "Classpath" exception as provided
5.12 + * by Oracle in the LICENSE file that accompanied this code.
5.13 + *
5.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
5.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
5.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
5.17 + * version 2 for more details (a copy is included in the LICENSE file that
5.18 + * accompanied this code).
5.19 + *
5.20 + * You should have received a copy of the GNU General Public License version
5.21 + * 2 along with this work; if not, write to the Free Software Foundation,
5.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
5.23 + *
5.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
5.25 + * or visit www.oracle.com if you need additional information or have any
5.26 + * questions.
5.27 + */
5.28 +
5.29 +package java.beans;
5.30 +
5.31 +import java.util.EventListenerProxy;
5.32 +
5.33 +/**
5.34 + * A class which extends the {@code EventListenerProxy}
5.35 + * specifically for adding a {@code PropertyChangeListener}
5.36 + * with a "bound" property.
5.37 + * Instances of this class can be added
5.38 + * as {@code PropertyChangeListener}s to a bean
5.39 + * which supports firing property change events.
5.40 + * <p>
5.41 + * If the object has a {@code getPropertyChangeListeners} method
5.42 + * then the array returned could be a mixture of {@code PropertyChangeListener}
5.43 + * and {@code PropertyChangeListenerProxy} objects.
5.44 + *
5.45 + * @see java.util.EventListenerProxy
5.46 + * @see PropertyChangeSupport#getPropertyChangeListeners
5.47 + * @since 1.4
5.48 + */
5.49 +public class PropertyChangeListenerProxy
5.50 + extends EventListenerProxy<PropertyChangeListener>
5.51 + implements PropertyChangeListener {
5.52 +
5.53 + private final String propertyName;
5.54 +
5.55 + /**
5.56 + * Constructor which binds the {@code PropertyChangeListener}
5.57 + * to a specific property.
5.58 + *
5.59 + * @param propertyName the name of the property to listen on
5.60 + * @param listener the listener object
5.61 + */
5.62 + public PropertyChangeListenerProxy(String propertyName, PropertyChangeListener listener) {
5.63 + super(listener);
5.64 + this.propertyName = propertyName;
5.65 + }
5.66 +
5.67 + /**
5.68 + * Forwards the property change event to the listener delegate.
5.69 + *
5.70 + * @param event the property change event
5.71 + */
5.72 + public void propertyChange(PropertyChangeEvent event) {
5.73 + getListener().propertyChange(event);
5.74 + }
5.75 +
5.76 + /**
5.77 + * Returns the name of the named property associated with the listener.
5.78 + *
5.79 + * @return the name of the named property associated with the listener
5.80 + */
5.81 + public String getPropertyName() {
5.82 + return this.propertyName;
5.83 + }
5.84 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/emul/compact/src/main/java/java/beans/PropertyChangeSupport.java Fri Feb 01 16:35:42 2013 +0100
6.3 @@ -0,0 +1,536 @@
6.4 +/*
6.5 + * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6.7 + *
6.8 + * This code is free software; you can redistribute it and/or modify it
6.9 + * under the terms of the GNU General Public License version 2 only, as
6.10 + * published by the Free Software Foundation. Oracle designates this
6.11 + * particular file as subject to the "Classpath" exception as provided
6.12 + * by Oracle in the LICENSE file that accompanied this code.
6.13 + *
6.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
6.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
6.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
6.17 + * version 2 for more details (a copy is included in the LICENSE file that
6.18 + * accompanied this code).
6.19 + *
6.20 + * You should have received a copy of the GNU General Public License version
6.21 + * 2 along with this work; if not, write to the Free Software Foundation,
6.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
6.23 + *
6.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
6.25 + * or visit www.oracle.com if you need additional information or have any
6.26 + * questions.
6.27 + */
6.28 +package java.beans;
6.29 +
6.30 +import java.io.Serializable;
6.31 +import java.io.ObjectStreamField;
6.32 +import java.io.ObjectOutputStream;
6.33 +import java.io.ObjectInputStream;
6.34 +import java.io.IOException;
6.35 +import java.util.Hashtable;
6.36 +import java.util.Map.Entry;
6.37 +
6.38 +/**
6.39 + * This is a utility class that can be used by beans that support bound
6.40 + * properties. It manages a list of listeners and dispatches
6.41 + * {@link PropertyChangeEvent}s to them. You can use an instance of this class
6.42 + * as a member field of your bean and delegate these types of work to it.
6.43 + * The {@link PropertyChangeListener} can be registered for all properties
6.44 + * or for a property specified by name.
6.45 + * <p>
6.46 + * Here is an example of {@code PropertyChangeSupport} usage that follows
6.47 + * the rules and recommendations laid out in the JavaBeans™ specification:
6.48 + * <pre>
6.49 + * public class MyBean {
6.50 + * private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
6.51 + *
6.52 + * public void addPropertyChangeListener(PropertyChangeListener listener) {
6.53 + * this.pcs.addPropertyChangeListener(listener);
6.54 + * }
6.55 + *
6.56 + * public void removePropertyChangeListener(PropertyChangeListener listener) {
6.57 + * this.pcs.removePropertyChangeListener(listener);
6.58 + * }
6.59 + *
6.60 + * private String value;
6.61 + *
6.62 + * public String getValue() {
6.63 + * return this.value;
6.64 + * }
6.65 + *
6.66 + * public void setValue(String newValue) {
6.67 + * String oldValue = this.value;
6.68 + * this.value = newValue;
6.69 + * this.pcs.firePropertyChange("value", oldValue, newValue);
6.70 + * }
6.71 + *
6.72 + * [...]
6.73 + * }
6.74 + * </pre>
6.75 + * <p>
6.76 + * A {@code PropertyChangeSupport} instance is thread-safe.
6.77 + * <p>
6.78 + * This class is serializable. When it is serialized it will save
6.79 + * (and restore) any listeners that are themselves serializable. Any
6.80 + * non-serializable listeners will be skipped during serialization.
6.81 + *
6.82 + * @see VetoableChangeSupport
6.83 + */
6.84 +public class PropertyChangeSupport implements Serializable {
6.85 + private PropertyChangeListenerMap map = new PropertyChangeListenerMap();
6.86 +
6.87 + /**
6.88 + * Constructs a <code>PropertyChangeSupport</code> object.
6.89 + *
6.90 + * @param sourceBean The bean to be given as the source for any events.
6.91 + */
6.92 + public PropertyChangeSupport(Object sourceBean) {
6.93 + if (sourceBean == null) {
6.94 + throw new NullPointerException();
6.95 + }
6.96 + source = sourceBean;
6.97 + }
6.98 +
6.99 + /**
6.100 + * Add a PropertyChangeListener to the listener list.
6.101 + * The listener is registered for all properties.
6.102 + * The same listener object may be added more than once, and will be called
6.103 + * as many times as it is added.
6.104 + * If <code>listener</code> is null, no exception is thrown and no action
6.105 + * is taken.
6.106 + *
6.107 + * @param listener The PropertyChangeListener to be added
6.108 + */
6.109 + public void addPropertyChangeListener(PropertyChangeListener listener) {
6.110 + if (listener == null) {
6.111 + return;
6.112 + }
6.113 + if (listener instanceof PropertyChangeListenerProxy) {
6.114 + PropertyChangeListenerProxy proxy =
6.115 + (PropertyChangeListenerProxy)listener;
6.116 + // Call two argument add method.
6.117 + addPropertyChangeListener(proxy.getPropertyName(),
6.118 + proxy.getListener());
6.119 + } else {
6.120 + this.map.add(null, listener);
6.121 + }
6.122 + }
6.123 +
6.124 + /**
6.125 + * Remove a PropertyChangeListener from the listener list.
6.126 + * This removes a PropertyChangeListener that was registered
6.127 + * for all properties.
6.128 + * If <code>listener</code> was added more than once to the same event
6.129 + * source, it will be notified one less time after being removed.
6.130 + * If <code>listener</code> is null, or was never added, no exception is
6.131 + * thrown and no action is taken.
6.132 + *
6.133 + * @param listener The PropertyChangeListener to be removed
6.134 + */
6.135 + public void removePropertyChangeListener(PropertyChangeListener listener) {
6.136 + if (listener == null) {
6.137 + return;
6.138 + }
6.139 + if (listener instanceof PropertyChangeListenerProxy) {
6.140 + PropertyChangeListenerProxy proxy =
6.141 + (PropertyChangeListenerProxy)listener;
6.142 + // Call two argument remove method.
6.143 + removePropertyChangeListener(proxy.getPropertyName(),
6.144 + proxy.getListener());
6.145 + } else {
6.146 + this.map.remove(null, listener);
6.147 + }
6.148 + }
6.149 +
6.150 + /**
6.151 + * Returns an array of all the listeners that were added to the
6.152 + * PropertyChangeSupport object with addPropertyChangeListener().
6.153 + * <p>
6.154 + * If some listeners have been added with a named property, then
6.155 + * the returned array will be a mixture of PropertyChangeListeners
6.156 + * and <code>PropertyChangeListenerProxy</code>s. If the calling
6.157 + * method is interested in distinguishing the listeners then it must
6.158 + * test each element to see if it's a
6.159 + * <code>PropertyChangeListenerProxy</code>, perform the cast, and examine
6.160 + * the parameter.
6.161 + *
6.162 + * <pre>
6.163 + * PropertyChangeListener[] listeners = bean.getPropertyChangeListeners();
6.164 + * for (int i = 0; i < listeners.length; i++) {
6.165 + * if (listeners[i] instanceof PropertyChangeListenerProxy) {
6.166 + * PropertyChangeListenerProxy proxy =
6.167 + * (PropertyChangeListenerProxy)listeners[i];
6.168 + * if (proxy.getPropertyName().equals("foo")) {
6.169 + * // proxy is a PropertyChangeListener which was associated
6.170 + * // with the property named "foo"
6.171 + * }
6.172 + * }
6.173 + * }
6.174 + *</pre>
6.175 + *
6.176 + * @see PropertyChangeListenerProxy
6.177 + * @return all of the <code>PropertyChangeListeners</code> added or an
6.178 + * empty array if no listeners have been added
6.179 + * @since 1.4
6.180 + */
6.181 + public PropertyChangeListener[] getPropertyChangeListeners() {
6.182 + return this.map.getListeners();
6.183 + }
6.184 +
6.185 + /**
6.186 + * Add a PropertyChangeListener for a specific property. The listener
6.187 + * will be invoked only when a call on firePropertyChange names that
6.188 + * specific property.
6.189 + * The same listener object may be added more than once. For each
6.190 + * property, the listener will be invoked the number of times it was added
6.191 + * for that property.
6.192 + * If <code>propertyName</code> or <code>listener</code> is null, no
6.193 + * exception is thrown and no action is taken.
6.194 + *
6.195 + * @param propertyName The name of the property to listen on.
6.196 + * @param listener The PropertyChangeListener to be added
6.197 + */
6.198 + public void addPropertyChangeListener(
6.199 + String propertyName,
6.200 + PropertyChangeListener listener) {
6.201 + if (listener == null || propertyName == null) {
6.202 + return;
6.203 + }
6.204 + listener = this.map.extract(listener);
6.205 + if (listener != null) {
6.206 + this.map.add(propertyName, listener);
6.207 + }
6.208 + }
6.209 +
6.210 + /**
6.211 + * Remove a PropertyChangeListener for a specific property.
6.212 + * If <code>listener</code> was added more than once to the same event
6.213 + * source for the specified property, it will be notified one less time
6.214 + * after being removed.
6.215 + * If <code>propertyName</code> is null, no exception is thrown and no
6.216 + * action is taken.
6.217 + * If <code>listener</code> is null, or was never added for the specified
6.218 + * property, no exception is thrown and no action is taken.
6.219 + *
6.220 + * @param propertyName The name of the property that was listened on.
6.221 + * @param listener The PropertyChangeListener to be removed
6.222 + */
6.223 + public void removePropertyChangeListener(
6.224 + String propertyName,
6.225 + PropertyChangeListener listener) {
6.226 + if (listener == null || propertyName == null) {
6.227 + return;
6.228 + }
6.229 + listener = this.map.extract(listener);
6.230 + if (listener != null) {
6.231 + this.map.remove(propertyName, listener);
6.232 + }
6.233 + }
6.234 +
6.235 + /**
6.236 + * Returns an array of all the listeners which have been associated
6.237 + * with the named property.
6.238 + *
6.239 + * @param propertyName The name of the property being listened to
6.240 + * @return all of the <code>PropertyChangeListeners</code> associated with
6.241 + * the named property. If no such listeners have been added,
6.242 + * or if <code>propertyName</code> is null, an empty array is
6.243 + * returned.
6.244 + * @since 1.4
6.245 + */
6.246 + public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
6.247 + return this.map.getListeners(propertyName);
6.248 + }
6.249 +
6.250 + /**
6.251 + * Reports a bound property update to listeners
6.252 + * that have been registered to track updates of
6.253 + * all properties or a property with the specified name.
6.254 + * <p>
6.255 + * No event is fired if old and new values are equal and non-null.
6.256 + * <p>
6.257 + * This is merely a convenience wrapper around the more general
6.258 + * {@link #firePropertyChange(PropertyChangeEvent)} method.
6.259 + *
6.260 + * @param propertyName the programmatic name of the property that was changed
6.261 + * @param oldValue the old value of the property
6.262 + * @param newValue the new value of the property
6.263 + */
6.264 + public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
6.265 + if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
6.266 + firePropertyChange(new PropertyChangeEvent(this.source, propertyName, oldValue, newValue));
6.267 + }
6.268 + }
6.269 +
6.270 + /**
6.271 + * Reports an integer bound property update to listeners
6.272 + * that have been registered to track updates of
6.273 + * all properties or a property with the specified name.
6.274 + * <p>
6.275 + * No event is fired if old and new values are equal.
6.276 + * <p>
6.277 + * This is merely a convenience wrapper around the more general
6.278 + * {@link #firePropertyChange(String, Object, Object)} method.
6.279 + *
6.280 + * @param propertyName the programmatic name of the property that was changed
6.281 + * @param oldValue the old value of the property
6.282 + * @param newValue the new value of the property
6.283 + */
6.284 + public void firePropertyChange(String propertyName, int oldValue, int newValue) {
6.285 + if (oldValue != newValue) {
6.286 + firePropertyChange(propertyName, Integer.valueOf(oldValue), Integer.valueOf(newValue));
6.287 + }
6.288 + }
6.289 +
6.290 + /**
6.291 + * Reports a boolean bound property update to listeners
6.292 + * that have been registered to track updates of
6.293 + * all properties or a property with the specified name.
6.294 + * <p>
6.295 + * No event is fired if old and new values are equal.
6.296 + * <p>
6.297 + * This is merely a convenience wrapper around the more general
6.298 + * {@link #firePropertyChange(String, Object, Object)} method.
6.299 + *
6.300 + * @param propertyName the programmatic name of the property that was changed
6.301 + * @param oldValue the old value of the property
6.302 + * @param newValue the new value of the property
6.303 + */
6.304 + public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {
6.305 + if (oldValue != newValue) {
6.306 + firePropertyChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
6.307 + }
6.308 + }
6.309 +
6.310 + /**
6.311 + * Fires a property change event to listeners
6.312 + * that have been registered to track updates of
6.313 + * all properties or a property with the specified name.
6.314 + * <p>
6.315 + * No event is fired if the given event's old and new values are equal and non-null.
6.316 + *
6.317 + * @param event the {@code PropertyChangeEvent} to be fired
6.318 + */
6.319 + public void firePropertyChange(PropertyChangeEvent event) {
6.320 + Object oldValue = event.getOldValue();
6.321 + Object newValue = event.getNewValue();
6.322 + if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
6.323 + String name = event.getPropertyName();
6.324 +
6.325 + PropertyChangeListener[] common = this.map.get(null);
6.326 + PropertyChangeListener[] named = (name != null)
6.327 + ? this.map.get(name)
6.328 + : null;
6.329 +
6.330 + fire(common, event);
6.331 + fire(named, event);
6.332 + }
6.333 + }
6.334 +
6.335 + private static void fire(PropertyChangeListener[] listeners, PropertyChangeEvent event) {
6.336 + if (listeners != null) {
6.337 + for (PropertyChangeListener listener : listeners) {
6.338 + listener.propertyChange(event);
6.339 + }
6.340 + }
6.341 + }
6.342 +
6.343 + /**
6.344 + * Reports a bound indexed property update to listeners
6.345 + * that have been registered to track updates of
6.346 + * all properties or a property with the specified name.
6.347 + * <p>
6.348 + * No event is fired if old and new values are equal and non-null.
6.349 + * <p>
6.350 + * This is merely a convenience wrapper around the more general
6.351 + * {@link #firePropertyChange(PropertyChangeEvent)} method.
6.352 + *
6.353 + * @param propertyName the programmatic name of the property that was changed
6.354 + * @param index the index of the property element that was changed
6.355 + * @param oldValue the old value of the property
6.356 + * @param newValue the new value of the property
6.357 + * @since 1.5
6.358 + */
6.359 + public void fireIndexedPropertyChange(String propertyName, int index, Object oldValue, Object newValue) {
6.360 + if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
6.361 + firePropertyChange(new IndexedPropertyChangeEvent(source, propertyName, oldValue, newValue, index));
6.362 + }
6.363 + }
6.364 +
6.365 + /**
6.366 + * Reports an integer bound indexed property update to listeners
6.367 + * that have been registered to track updates of
6.368 + * all properties or a property with the specified name.
6.369 + * <p>
6.370 + * No event is fired if old and new values are equal.
6.371 + * <p>
6.372 + * This is merely a convenience wrapper around the more general
6.373 + * {@link #fireIndexedPropertyChange(String, int, Object, Object)} method.
6.374 + *
6.375 + * @param propertyName the programmatic name of the property that was changed
6.376 + * @param index the index of the property element that was changed
6.377 + * @param oldValue the old value of the property
6.378 + * @param newValue the new value of the property
6.379 + * @since 1.5
6.380 + */
6.381 + public void fireIndexedPropertyChange(String propertyName, int index, int oldValue, int newValue) {
6.382 + if (oldValue != newValue) {
6.383 + fireIndexedPropertyChange(propertyName, index, Integer.valueOf(oldValue), Integer.valueOf(newValue));
6.384 + }
6.385 + }
6.386 +
6.387 + /**
6.388 + * Reports a boolean bound indexed property update to listeners
6.389 + * that have been registered to track updates of
6.390 + * all properties or a property with the specified name.
6.391 + * <p>
6.392 + * No event is fired if old and new values are equal.
6.393 + * <p>
6.394 + * This is merely a convenience wrapper around the more general
6.395 + * {@link #fireIndexedPropertyChange(String, int, Object, Object)} method.
6.396 + *
6.397 + * @param propertyName the programmatic name of the property that was changed
6.398 + * @param index the index of the property element that was changed
6.399 + * @param oldValue the old value of the property
6.400 + * @param newValue the new value of the property
6.401 + * @since 1.5
6.402 + */
6.403 + public void fireIndexedPropertyChange(String propertyName, int index, boolean oldValue, boolean newValue) {
6.404 + if (oldValue != newValue) {
6.405 + fireIndexedPropertyChange(propertyName, index, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
6.406 + }
6.407 + }
6.408 +
6.409 + /**
6.410 + * Check if there are any listeners for a specific property, including
6.411 + * those registered on all properties. If <code>propertyName</code>
6.412 + * is null, only check for listeners registered on all properties.
6.413 + *
6.414 + * @param propertyName the property name.
6.415 + * @return true if there are one or more listeners for the given property
6.416 + */
6.417 + public boolean hasListeners(String propertyName) {
6.418 + return this.map.hasListeners(propertyName);
6.419 + }
6.420 +
6.421 + /**
6.422 + * @serialData Null terminated list of <code>PropertyChangeListeners</code>.
6.423 + * <p>
6.424 + * At serialization time we skip non-serializable listeners and
6.425 + * only serialize the serializable listeners.
6.426 + */
6.427 + private void writeObject(ObjectOutputStream s) throws IOException {
6.428 + Hashtable<String, PropertyChangeSupport> children = null;
6.429 + PropertyChangeListener[] listeners = null;
6.430 + synchronized (this.map) {
6.431 + for (Entry<String, PropertyChangeListener[]> entry : this.map.getEntries()) {
6.432 + String property = entry.getKey();
6.433 + if (property == null) {
6.434 + listeners = entry.getValue();
6.435 + } else {
6.436 + if (children == null) {
6.437 + children = new Hashtable<String, PropertyChangeSupport>();
6.438 + }
6.439 + PropertyChangeSupport pcs = new PropertyChangeSupport(this.source);
6.440 + pcs.map.set(null, entry.getValue());
6.441 + children.put(property, pcs);
6.442 + }
6.443 + }
6.444 + }
6.445 + ObjectOutputStream.PutField fields = s.putFields();
6.446 + fields.put("children", children);
6.447 + fields.put("source", this.source);
6.448 + fields.put("propertyChangeSupportSerializedDataVersion", 2);
6.449 + s.writeFields();
6.450 +
6.451 + if (listeners != null) {
6.452 + for (PropertyChangeListener l : listeners) {
6.453 + if (l instanceof Serializable) {
6.454 + s.writeObject(l);
6.455 + }
6.456 + }
6.457 + }
6.458 + s.writeObject(null);
6.459 + }
6.460 +
6.461 + private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
6.462 + this.map = new PropertyChangeListenerMap();
6.463 +
6.464 + ObjectInputStream.GetField fields = s.readFields();
6.465 +
6.466 + Hashtable<String, PropertyChangeSupport> children = (Hashtable<String, PropertyChangeSupport>) fields.get("children", null);
6.467 + this.source = fields.get("source", null);
6.468 + fields.get("propertyChangeSupportSerializedDataVersion", 2);
6.469 +
6.470 + Object listenerOrNull;
6.471 + while (null != (listenerOrNull = s.readObject())) {
6.472 + this.map.add(null, (PropertyChangeListener)listenerOrNull);
6.473 + }
6.474 + if (children != null) {
6.475 + for (Entry<String, PropertyChangeSupport> entry : children.entrySet()) {
6.476 + for (PropertyChangeListener listener : entry.getValue().getPropertyChangeListeners()) {
6.477 + this.map.add(entry.getKey(), listener);
6.478 + }
6.479 + }
6.480 + }
6.481 + }
6.482 +
6.483 + /**
6.484 + * The object to be provided as the "source" for any generated events.
6.485 + */
6.486 + private Object source;
6.487 +
6.488 + /**
6.489 + * @serialField children Hashtable
6.490 + * @serialField source Object
6.491 + * @serialField propertyChangeSupportSerializedDataVersion int
6.492 + */
6.493 + private static final ObjectStreamField[] serialPersistentFields = {
6.494 + new ObjectStreamField("children", Hashtable.class),
6.495 + new ObjectStreamField("source", Object.class),
6.496 + new ObjectStreamField("propertyChangeSupportSerializedDataVersion", Integer.TYPE)
6.497 + };
6.498 +
6.499 + /**
6.500 + * Serialization version ID, so we're compatible with JDK 1.1
6.501 + */
6.502 + static final long serialVersionUID = 6401253773779951803L;
6.503 +
6.504 + /**
6.505 + * This is a {@link ChangeListenerMap ChangeListenerMap} implementation
6.506 + * that works with {@link PropertyChangeListener PropertyChangeListener} objects.
6.507 + */
6.508 + private static final class PropertyChangeListenerMap extends ChangeListenerMap<PropertyChangeListener> {
6.509 + private static final PropertyChangeListener[] EMPTY = {};
6.510 +
6.511 + /**
6.512 + * Creates an array of {@link PropertyChangeListener PropertyChangeListener} objects.
6.513 + * This method uses the same instance of the empty array
6.514 + * when {@code length} equals {@code 0}.
6.515 + *
6.516 + * @param length the array length
6.517 + * @return an array with specified length
6.518 + */
6.519 + @Override
6.520 + protected PropertyChangeListener[] newArray(int length) {
6.521 + return (0 < length)
6.522 + ? new PropertyChangeListener[length]
6.523 + : EMPTY;
6.524 + }
6.525 +
6.526 + /**
6.527 + * Creates a {@link PropertyChangeListenerProxy PropertyChangeListenerProxy}
6.528 + * object for the specified property.
6.529 + *
6.530 + * @param name the name of the property to listen on
6.531 + * @param listener the listener to process events
6.532 + * @return a {@code PropertyChangeListenerProxy} object
6.533 + */
6.534 + @Override
6.535 + protected PropertyChangeListener newProxy(String name, PropertyChangeListener listener) {
6.536 + return new PropertyChangeListenerProxy(name, listener);
6.537 + }
6.538 + }
6.539 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/emul/compact/src/main/java/java/beans/PropertyVetoException.java Fri Feb 01 16:35:42 2013 +0100
7.3 @@ -0,0 +1,64 @@
7.4 +/*
7.5 + * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
7.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7.7 + *
7.8 + * This code is free software; you can redistribute it and/or modify it
7.9 + * under the terms of the GNU General Public License version 2 only, as
7.10 + * published by the Free Software Foundation. Oracle designates this
7.11 + * particular file as subject to the "Classpath" exception as provided
7.12 + * by Oracle in the LICENSE file that accompanied this code.
7.13 + *
7.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
7.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7.17 + * version 2 for more details (a copy is included in the LICENSE file that
7.18 + * accompanied this code).
7.19 + *
7.20 + * You should have received a copy of the GNU General Public License version
7.21 + * 2 along with this work; if not, write to the Free Software Foundation,
7.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7.23 + *
7.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7.25 + * or visit www.oracle.com if you need additional information or have any
7.26 + * questions.
7.27 + */
7.28 +
7.29 +package java.beans;
7.30 +
7.31 +
7.32 +/**
7.33 + * A PropertyVetoException is thrown when a proposed change to a
7.34 + * property represents an unacceptable value.
7.35 + */
7.36 +
7.37 +public
7.38 +class PropertyVetoException extends Exception {
7.39 + private static final long serialVersionUID = 129596057694162164L;
7.40 +
7.41 + /**
7.42 + * Constructs a <code>PropertyVetoException</code> with a
7.43 + * detailed message.
7.44 + *
7.45 + * @param mess Descriptive message
7.46 + * @param evt A PropertyChangeEvent describing the vetoed change.
7.47 + */
7.48 + public PropertyVetoException(String mess, PropertyChangeEvent evt) {
7.49 + super(mess);
7.50 + this.evt = evt;
7.51 + }
7.52 +
7.53 + /**
7.54 + * Gets the vetoed <code>PropertyChangeEvent</code>.
7.55 + *
7.56 + * @return A PropertyChangeEvent describing the vetoed change.
7.57 + */
7.58 + public PropertyChangeEvent getPropertyChangeEvent() {
7.59 + return evt;
7.60 + }
7.61 +
7.62 + /**
7.63 + * A PropertyChangeEvent describing the vetoed change.
7.64 + * @serial
7.65 + */
7.66 + private PropertyChangeEvent evt;
7.67 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/emul/compact/src/main/java/java/beans/VetoableChangeListener.java Fri Feb 01 16:35:42 2013 +0100
8.3 @@ -0,0 +1,44 @@
8.4 +/*
8.5 + * Copyright (c) 1996, 1997, Oracle and/or its affiliates. All rights reserved.
8.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8.7 + *
8.8 + * This code is free software; you can redistribute it and/or modify it
8.9 + * under the terms of the GNU General Public License version 2 only, as
8.10 + * published by the Free Software Foundation. Oracle designates this
8.11 + * particular file as subject to the "Classpath" exception as provided
8.12 + * by Oracle in the LICENSE file that accompanied this code.
8.13 + *
8.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
8.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
8.17 + * version 2 for more details (a copy is included in the LICENSE file that
8.18 + * accompanied this code).
8.19 + *
8.20 + * You should have received a copy of the GNU General Public License version
8.21 + * 2 along with this work; if not, write to the Free Software Foundation,
8.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
8.23 + *
8.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
8.25 + * or visit www.oracle.com if you need additional information or have any
8.26 + * questions.
8.27 + */
8.28 +
8.29 +package java.beans;
8.30 +
8.31 +/**
8.32 + * A VetoableChange event gets fired whenever a bean changes a "constrained"
8.33 + * property. You can register a VetoableChangeListener with a source bean
8.34 + * so as to be notified of any constrained property updates.
8.35 + */
8.36 +public interface VetoableChangeListener extends java.util.EventListener {
8.37 + /**
8.38 + * This method gets called when a constrained property is changed.
8.39 + *
8.40 + * @param evt a <code>PropertyChangeEvent</code> object describing the
8.41 + * event source and the property that has changed.
8.42 + * @exception PropertyVetoException if the recipient wishes the property
8.43 + * change to be rolled back.
8.44 + */
8.45 + void vetoableChange(PropertyChangeEvent evt)
8.46 + throws PropertyVetoException;
8.47 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/emul/compact/src/main/java/java/beans/VetoableChangeListenerProxy.java Fri Feb 01 16:35:42 2013 +0100
9.3 @@ -0,0 +1,84 @@
9.4 +/*
9.5 + * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
9.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
9.7 + *
9.8 + * This code is free software; you can redistribute it and/or modify it
9.9 + * under the terms of the GNU General Public License version 2 only, as
9.10 + * published by the Free Software Foundation. Oracle designates this
9.11 + * particular file as subject to the "Classpath" exception as provided
9.12 + * by Oracle in the LICENSE file that accompanied this code.
9.13 + *
9.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
9.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9.17 + * version 2 for more details (a copy is included in the LICENSE file that
9.18 + * accompanied this code).
9.19 + *
9.20 + * You should have received a copy of the GNU General Public License version
9.21 + * 2 along with this work; if not, write to the Free Software Foundation,
9.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
9.23 + *
9.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
9.25 + * or visit www.oracle.com if you need additional information or have any
9.26 + * questions.
9.27 + */
9.28 +
9.29 +package java.beans;
9.30 +
9.31 +import java.util.EventListenerProxy;
9.32 +
9.33 +/**
9.34 + * A class which extends the {@code EventListenerProxy}
9.35 + * specifically for adding a {@code VetoableChangeListener}
9.36 + * with a "constrained" property.
9.37 + * Instances of this class can be added
9.38 + * as {@code VetoableChangeListener}s to a bean
9.39 + * which supports firing vetoable change events.
9.40 + * <p>
9.41 + * If the object has a {@code getVetoableChangeListeners} method
9.42 + * then the array returned could be a mixture of {@code VetoableChangeListener}
9.43 + * and {@code VetoableChangeListenerProxy} objects.
9.44 + *
9.45 + * @see java.util.EventListenerProxy
9.46 + * @see VetoableChangeSupport#getVetoableChangeListeners
9.47 + * @since 1.4
9.48 + */
9.49 +public class VetoableChangeListenerProxy
9.50 + extends EventListenerProxy<VetoableChangeListener>
9.51 + implements VetoableChangeListener {
9.52 +
9.53 + private final String propertyName;
9.54 +
9.55 + /**
9.56 + * Constructor which binds the {@code VetoableChangeListener}
9.57 + * to a specific property.
9.58 + *
9.59 + * @param propertyName the name of the property to listen on
9.60 + * @param listener the listener object
9.61 + */
9.62 + public VetoableChangeListenerProxy(String propertyName, VetoableChangeListener listener) {
9.63 + super(listener);
9.64 + this.propertyName = propertyName;
9.65 + }
9.66 +
9.67 + /**
9.68 + * Forwards the property change event to the listener delegate.
9.69 + *
9.70 + * @param event the property change event
9.71 + *
9.72 + * @exception PropertyVetoException if the recipient wishes the property
9.73 + * change to be rolled back
9.74 + */
9.75 + public void vetoableChange(PropertyChangeEvent event) throws PropertyVetoException{
9.76 + getListener().vetoableChange(event);
9.77 + }
9.78 +
9.79 + /**
9.80 + * Returns the name of the named property associated with the listener.
9.81 + *
9.82 + * @return the name of the named property associated with the listener
9.83 + */
9.84 + public String getPropertyName() {
9.85 + return this.propertyName;
9.86 + }
9.87 +}
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/emul/compact/src/main/java/java/beans/VetoableChangeSupport.java Fri Feb 01 16:35:42 2013 +0100
10.3 @@ -0,0 +1,525 @@
10.4 +/*
10.5 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
10.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10.7 + *
10.8 + * This code is free software; you can redistribute it and/or modify it
10.9 + * under the terms of the GNU General Public License version 2 only, as
10.10 + * published by the Free Software Foundation. Oracle designates this
10.11 + * particular file as subject to the "Classpath" exception as provided
10.12 + * by Oracle in the LICENSE file that accompanied this code.
10.13 + *
10.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
10.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10.17 + * version 2 for more details (a copy is included in the LICENSE file that
10.18 + * accompanied this code).
10.19 + *
10.20 + * You should have received a copy of the GNU General Public License version
10.21 + * 2 along with this work; if not, write to the Free Software Foundation,
10.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
10.23 + *
10.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
10.25 + * or visit www.oracle.com if you need additional information or have any
10.26 + * questions.
10.27 + */
10.28 +package java.beans;
10.29 +
10.30 +import java.io.Serializable;
10.31 +import java.io.ObjectStreamField;
10.32 +import java.io.ObjectOutputStream;
10.33 +import java.io.ObjectInputStream;
10.34 +import java.io.IOException;
10.35 +import java.util.Hashtable;
10.36 +import java.util.Map.Entry;
10.37 +
10.38 +/**
10.39 + * This is a utility class that can be used by beans that support constrained
10.40 + * properties. It manages a list of listeners and dispatches
10.41 + * {@link PropertyChangeEvent}s to them. You can use an instance of this class
10.42 + * as a member field of your bean and delegate these types of work to it.
10.43 + * The {@link VetoableChangeListener} can be registered for all properties
10.44 + * or for a property specified by name.
10.45 + * <p>
10.46 + * Here is an example of {@code VetoableChangeSupport} usage that follows
10.47 + * the rules and recommendations laid out in the JavaBeans™ specification:
10.48 + * <pre>
10.49 + * public class MyBean {
10.50 + * private final VetoableChangeSupport vcs = new VetoableChangeSupport(this);
10.51 + *
10.52 + * public void addVetoableChangeListener(VetoableChangeListener listener) {
10.53 + * this.vcs.addVetoableChangeListener(listener);
10.54 + * }
10.55 + *
10.56 + * public void removeVetoableChangeListener(VetoableChangeListener listener) {
10.57 + * this.vcs.removeVetoableChangeListener(listener);
10.58 + * }
10.59 + *
10.60 + * private String value;
10.61 + *
10.62 + * public String getValue() {
10.63 + * return this.value;
10.64 + * }
10.65 + *
10.66 + * public void setValue(String newValue) throws PropertyVetoException {
10.67 + * String oldValue = this.value;
10.68 + * this.vcs.fireVetoableChange("value", oldValue, newValue);
10.69 + * this.value = newValue;
10.70 + * }
10.71 + *
10.72 + * [...]
10.73 + * }
10.74 + * </pre>
10.75 + * <p>
10.76 + * A {@code VetoableChangeSupport} instance is thread-safe.
10.77 + * <p>
10.78 + * This class is serializable. When it is serialized it will save
10.79 + * (and restore) any listeners that are themselves serializable. Any
10.80 + * non-serializable listeners will be skipped during serialization.
10.81 + *
10.82 + * @see PropertyChangeSupport
10.83 + */
10.84 +public class VetoableChangeSupport implements Serializable {
10.85 + private VetoableChangeListenerMap map = new VetoableChangeListenerMap();
10.86 +
10.87 + /**
10.88 + * Constructs a <code>VetoableChangeSupport</code> object.
10.89 + *
10.90 + * @param sourceBean The bean to be given as the source for any events.
10.91 + */
10.92 + public VetoableChangeSupport(Object sourceBean) {
10.93 + if (sourceBean == null) {
10.94 + throw new NullPointerException();
10.95 + }
10.96 + source = sourceBean;
10.97 + }
10.98 +
10.99 + /**
10.100 + * Add a VetoableChangeListener to the listener list.
10.101 + * The listener is registered for all properties.
10.102 + * The same listener object may be added more than once, and will be called
10.103 + * as many times as it is added.
10.104 + * If <code>listener</code> is null, no exception is thrown and no action
10.105 + * is taken.
10.106 + *
10.107 + * @param listener The VetoableChangeListener to be added
10.108 + */
10.109 + public void addVetoableChangeListener(VetoableChangeListener listener) {
10.110 + if (listener == null) {
10.111 + return;
10.112 + }
10.113 + if (listener instanceof VetoableChangeListenerProxy) {
10.114 + VetoableChangeListenerProxy proxy =
10.115 + (VetoableChangeListenerProxy)listener;
10.116 + // Call two argument add method.
10.117 + addVetoableChangeListener(proxy.getPropertyName(),
10.118 + proxy.getListener());
10.119 + } else {
10.120 + this.map.add(null, listener);
10.121 + }
10.122 + }
10.123 +
10.124 + /**
10.125 + * Remove a VetoableChangeListener from the listener list.
10.126 + * This removes a VetoableChangeListener that was registered
10.127 + * for all properties.
10.128 + * If <code>listener</code> was added more than once to the same event
10.129 + * source, it will be notified one less time after being removed.
10.130 + * If <code>listener</code> is null, or was never added, no exception is
10.131 + * thrown and no action is taken.
10.132 + *
10.133 + * @param listener The VetoableChangeListener to be removed
10.134 + */
10.135 + public void removeVetoableChangeListener(VetoableChangeListener listener) {
10.136 + if (listener == null) {
10.137 + return;
10.138 + }
10.139 + if (listener instanceof VetoableChangeListenerProxy) {
10.140 + VetoableChangeListenerProxy proxy =
10.141 + (VetoableChangeListenerProxy)listener;
10.142 + // Call two argument remove method.
10.143 + removeVetoableChangeListener(proxy.getPropertyName(),
10.144 + proxy.getListener());
10.145 + } else {
10.146 + this.map.remove(null, listener);
10.147 + }
10.148 + }
10.149 +
10.150 + /**
10.151 + * Returns an array of all the listeners that were added to the
10.152 + * VetoableChangeSupport object with addVetoableChangeListener().
10.153 + * <p>
10.154 + * If some listeners have been added with a named property, then
10.155 + * the returned array will be a mixture of VetoableChangeListeners
10.156 + * and <code>VetoableChangeListenerProxy</code>s. If the calling
10.157 + * method is interested in distinguishing the listeners then it must
10.158 + * test each element to see if it's a
10.159 + * <code>VetoableChangeListenerProxy</code>, perform the cast, and examine
10.160 + * the parameter.
10.161 + *
10.162 + * <pre>
10.163 + * VetoableChangeListener[] listeners = bean.getVetoableChangeListeners();
10.164 + * for (int i = 0; i < listeners.length; i++) {
10.165 + * if (listeners[i] instanceof VetoableChangeListenerProxy) {
10.166 + * VetoableChangeListenerProxy proxy =
10.167 + * (VetoableChangeListenerProxy)listeners[i];
10.168 + * if (proxy.getPropertyName().equals("foo")) {
10.169 + * // proxy is a VetoableChangeListener which was associated
10.170 + * // with the property named "foo"
10.171 + * }
10.172 + * }
10.173 + * }
10.174 + *</pre>
10.175 + *
10.176 + * @see VetoableChangeListenerProxy
10.177 + * @return all of the <code>VetoableChangeListeners</code> added or an
10.178 + * empty array if no listeners have been added
10.179 + * @since 1.4
10.180 + */
10.181 + public VetoableChangeListener[] getVetoableChangeListeners(){
10.182 + return this.map.getListeners();
10.183 + }
10.184 +
10.185 + /**
10.186 + * Add a VetoableChangeListener for a specific property. The listener
10.187 + * will be invoked only when a call on fireVetoableChange names that
10.188 + * specific property.
10.189 + * The same listener object may be added more than once. For each
10.190 + * property, the listener will be invoked the number of times it was added
10.191 + * for that property.
10.192 + * If <code>propertyName</code> or <code>listener</code> is null, no
10.193 + * exception is thrown and no action is taken.
10.194 + *
10.195 + * @param propertyName The name of the property to listen on.
10.196 + * @param listener The VetoableChangeListener to be added
10.197 + */
10.198 + public void addVetoableChangeListener(
10.199 + String propertyName,
10.200 + VetoableChangeListener listener) {
10.201 + if (listener == null || propertyName == null) {
10.202 + return;
10.203 + }
10.204 + listener = this.map.extract(listener);
10.205 + if (listener != null) {
10.206 + this.map.add(propertyName, listener);
10.207 + }
10.208 + }
10.209 +
10.210 + /**
10.211 + * Remove a VetoableChangeListener for a specific property.
10.212 + * If <code>listener</code> was added more than once to the same event
10.213 + * source for the specified property, it will be notified one less time
10.214 + * after being removed.
10.215 + * If <code>propertyName</code> is null, no exception is thrown and no
10.216 + * action is taken.
10.217 + * If <code>listener</code> is null, or was never added for the specified
10.218 + * property, no exception is thrown and no action is taken.
10.219 + *
10.220 + * @param propertyName The name of the property that was listened on.
10.221 + * @param listener The VetoableChangeListener to be removed
10.222 + */
10.223 + public void removeVetoableChangeListener(
10.224 + String propertyName,
10.225 + VetoableChangeListener listener) {
10.226 + if (listener == null || propertyName == null) {
10.227 + return;
10.228 + }
10.229 + listener = this.map.extract(listener);
10.230 + if (listener != null) {
10.231 + this.map.remove(propertyName, listener);
10.232 + }
10.233 + }
10.234 +
10.235 + /**
10.236 + * Returns an array of all the listeners which have been associated
10.237 + * with the named property.
10.238 + *
10.239 + * @param propertyName The name of the property being listened to
10.240 + * @return all the <code>VetoableChangeListeners</code> associated with
10.241 + * the named property. If no such listeners have been added,
10.242 + * or if <code>propertyName</code> is null, an empty array is
10.243 + * returned.
10.244 + * @since 1.4
10.245 + */
10.246 + public VetoableChangeListener[] getVetoableChangeListeners(String propertyName) {
10.247 + return this.map.getListeners(propertyName);
10.248 + }
10.249 +
10.250 + /**
10.251 + * Reports a constrained property update to listeners
10.252 + * that have been registered to track updates of
10.253 + * all properties or a property with the specified name.
10.254 + * <p>
10.255 + * Any listener can throw a {@code PropertyVetoException} to veto the update.
10.256 + * If one of the listeners vetoes the update, this method passes
10.257 + * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
10.258 + * to all listeners that already confirmed this update
10.259 + * and throws the {@code PropertyVetoException} again.
10.260 + * <p>
10.261 + * No event is fired if old and new values are equal and non-null.
10.262 + * <p>
10.263 + * This is merely a convenience wrapper around the more general
10.264 + * {@link #fireVetoableChange(PropertyChangeEvent)} method.
10.265 + *
10.266 + * @param propertyName the programmatic name of the property that is about to change
10.267 + * @param oldValue the old value of the property
10.268 + * @param newValue the new value of the property
10.269 + * @throws PropertyVetoException if one of listeners vetoes the property update
10.270 + */
10.271 + public void fireVetoableChange(String propertyName, Object oldValue, Object newValue)
10.272 + throws PropertyVetoException {
10.273 + if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
10.274 + fireVetoableChange(new PropertyChangeEvent(this.source, propertyName, oldValue, newValue));
10.275 + }
10.276 + }
10.277 +
10.278 + /**
10.279 + * Reports an integer constrained property update to listeners
10.280 + * that have been registered to track updates of
10.281 + * all properties or a property with the specified name.
10.282 + * <p>
10.283 + * Any listener can throw a {@code PropertyVetoException} to veto the update.
10.284 + * If one of the listeners vetoes the update, this method passes
10.285 + * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
10.286 + * to all listeners that already confirmed this update
10.287 + * and throws the {@code PropertyVetoException} again.
10.288 + * <p>
10.289 + * No event is fired if old and new values are equal.
10.290 + * <p>
10.291 + * This is merely a convenience wrapper around the more general
10.292 + * {@link #fireVetoableChange(String, Object, Object)} method.
10.293 + *
10.294 + * @param propertyName the programmatic name of the property that is about to change
10.295 + * @param oldValue the old value of the property
10.296 + * @param newValue the new value of the property
10.297 + * @throws PropertyVetoException if one of listeners vetoes the property update
10.298 + */
10.299 + public void fireVetoableChange(String propertyName, int oldValue, int newValue)
10.300 + throws PropertyVetoException {
10.301 + if (oldValue != newValue) {
10.302 + fireVetoableChange(propertyName, Integer.valueOf(oldValue), Integer.valueOf(newValue));
10.303 + }
10.304 + }
10.305 +
10.306 + /**
10.307 + * Reports a boolean constrained property update to listeners
10.308 + * that have been registered to track updates of
10.309 + * all properties or a property with the specified name.
10.310 + * <p>
10.311 + * Any listener can throw a {@code PropertyVetoException} to veto the update.
10.312 + * If one of the listeners vetoes the update, this method passes
10.313 + * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
10.314 + * to all listeners that already confirmed this update
10.315 + * and throws the {@code PropertyVetoException} again.
10.316 + * <p>
10.317 + * No event is fired if old and new values are equal.
10.318 + * <p>
10.319 + * This is merely a convenience wrapper around the more general
10.320 + * {@link #fireVetoableChange(String, Object, Object)} method.
10.321 + *
10.322 + * @param propertyName the programmatic name of the property that is about to change
10.323 + * @param oldValue the old value of the property
10.324 + * @param newValue the new value of the property
10.325 + * @throws PropertyVetoException if one of listeners vetoes the property update
10.326 + */
10.327 + public void fireVetoableChange(String propertyName, boolean oldValue, boolean newValue)
10.328 + throws PropertyVetoException {
10.329 + if (oldValue != newValue) {
10.330 + fireVetoableChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
10.331 + }
10.332 + }
10.333 +
10.334 + /**
10.335 + * Fires a property change event to listeners
10.336 + * that have been registered to track updates of
10.337 + * all properties or a property with the specified name.
10.338 + * <p>
10.339 + * Any listener can throw a {@code PropertyVetoException} to veto the update.
10.340 + * If one of the listeners vetoes the update, this method passes
10.341 + * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
10.342 + * to all listeners that already confirmed this update
10.343 + * and throws the {@code PropertyVetoException} again.
10.344 + * <p>
10.345 + * No event is fired if the given event's old and new values are equal and non-null.
10.346 + *
10.347 + * @param event the {@code PropertyChangeEvent} to be fired
10.348 + * @throws PropertyVetoException if one of listeners vetoes the property update
10.349 + */
10.350 + public void fireVetoableChange(PropertyChangeEvent event)
10.351 + throws PropertyVetoException {
10.352 + Object oldValue = event.getOldValue();
10.353 + Object newValue = event.getNewValue();
10.354 + if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
10.355 + String name = event.getPropertyName();
10.356 +
10.357 + VetoableChangeListener[] common = this.map.get(null);
10.358 + VetoableChangeListener[] named = (name != null)
10.359 + ? this.map.get(name)
10.360 + : null;
10.361 +
10.362 + VetoableChangeListener[] listeners;
10.363 + if (common == null) {
10.364 + listeners = named;
10.365 + }
10.366 + else if (named == null) {
10.367 + listeners = common;
10.368 + }
10.369 + else {
10.370 + listeners = new VetoableChangeListener[common.length + named.length];
10.371 + System.arraycopy(common, 0, listeners, 0, common.length);
10.372 + System.arraycopy(named, 0, listeners, common.length, named.length);
10.373 + }
10.374 + if (listeners != null) {
10.375 + int current = 0;
10.376 + try {
10.377 + while (current < listeners.length) {
10.378 + listeners[current].vetoableChange(event);
10.379 + current++;
10.380 + }
10.381 + }
10.382 + catch (PropertyVetoException veto) {
10.383 + event = new PropertyChangeEvent(this.source, name, newValue, oldValue);
10.384 + for (int i = 0; i < current; i++) {
10.385 + try {
10.386 + listeners[i].vetoableChange(event);
10.387 + }
10.388 + catch (PropertyVetoException exception) {
10.389 + // ignore exceptions that occur during rolling back
10.390 + }
10.391 + }
10.392 + throw veto; // rethrow the veto exception
10.393 + }
10.394 + }
10.395 + }
10.396 + }
10.397 +
10.398 + /**
10.399 + * Check if there are any listeners for a specific property, including
10.400 + * those registered on all properties. If <code>propertyName</code>
10.401 + * is null, only check for listeners registered on all properties.
10.402 + *
10.403 + * @param propertyName the property name.
10.404 + * @return true if there are one or more listeners for the given property
10.405 + */
10.406 + public boolean hasListeners(String propertyName) {
10.407 + return this.map.hasListeners(propertyName);
10.408 + }
10.409 +
10.410 + /**
10.411 + * @serialData Null terminated list of <code>VetoableChangeListeners</code>.
10.412 + * <p>
10.413 + * At serialization time we skip non-serializable listeners and
10.414 + * only serialize the serializable listeners.
10.415 + */
10.416 + private void writeObject(ObjectOutputStream s) throws IOException {
10.417 + Hashtable<String, VetoableChangeSupport> children = null;
10.418 + VetoableChangeListener[] listeners = null;
10.419 + synchronized (this.map) {
10.420 + for (Entry<String, VetoableChangeListener[]> entry : this.map.getEntries()) {
10.421 + String property = entry.getKey();
10.422 + if (property == null) {
10.423 + listeners = entry.getValue();
10.424 + } else {
10.425 + if (children == null) {
10.426 + children = new Hashtable<String, VetoableChangeSupport>();
10.427 + }
10.428 + VetoableChangeSupport vcs = new VetoableChangeSupport(this.source);
10.429 + vcs.map.set(null, entry.getValue());
10.430 + children.put(property, vcs);
10.431 + }
10.432 + }
10.433 + }
10.434 + ObjectOutputStream.PutField fields = s.putFields();
10.435 + fields.put("children", children);
10.436 + fields.put("source", this.source);
10.437 + fields.put("vetoableChangeSupportSerializedDataVersion", 2);
10.438 + s.writeFields();
10.439 +
10.440 + if (listeners != null) {
10.441 + for (VetoableChangeListener l : listeners) {
10.442 + if (l instanceof Serializable) {
10.443 + s.writeObject(l);
10.444 + }
10.445 + }
10.446 + }
10.447 + s.writeObject(null);
10.448 + }
10.449 +
10.450 + private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
10.451 + this.map = new VetoableChangeListenerMap();
10.452 +
10.453 + ObjectInputStream.GetField fields = s.readFields();
10.454 +
10.455 + Hashtable<String, VetoableChangeSupport> children = (Hashtable<String, VetoableChangeSupport>) fields.get("children", null);
10.456 + this.source = fields.get("source", null);
10.457 + fields.get("vetoableChangeSupportSerializedDataVersion", 2);
10.458 +
10.459 + Object listenerOrNull;
10.460 + while (null != (listenerOrNull = s.readObject())) {
10.461 + this.map.add(null, (VetoableChangeListener)listenerOrNull);
10.462 + }
10.463 + if (children != null) {
10.464 + for (Entry<String, VetoableChangeSupport> entry : children.entrySet()) {
10.465 + for (VetoableChangeListener listener : entry.getValue().getVetoableChangeListeners()) {
10.466 + this.map.add(entry.getKey(), listener);
10.467 + }
10.468 + }
10.469 + }
10.470 + }
10.471 +
10.472 + /**
10.473 + * The object to be provided as the "source" for any generated events.
10.474 + */
10.475 + private Object source;
10.476 +
10.477 + /**
10.478 + * @serialField children Hashtable
10.479 + * @serialField source Object
10.480 + * @serialField vetoableChangeSupportSerializedDataVersion int
10.481 + */
10.482 + private static final ObjectStreamField[] serialPersistentFields = {
10.483 + new ObjectStreamField("children", Hashtable.class),
10.484 + new ObjectStreamField("source", Object.class),
10.485 + new ObjectStreamField("vetoableChangeSupportSerializedDataVersion", Integer.TYPE)
10.486 + };
10.487 +
10.488 + /**
10.489 + * Serialization version ID, so we're compatible with JDK 1.1
10.490 + */
10.491 + static final long serialVersionUID = -5090210921595982017L;
10.492 +
10.493 + /**
10.494 + * This is a {@link ChangeListenerMap ChangeListenerMap} implementation
10.495 + * that works with {@link VetoableChangeListener VetoableChangeListener} objects.
10.496 + */
10.497 + private static final class VetoableChangeListenerMap extends ChangeListenerMap<VetoableChangeListener> {
10.498 + private static final VetoableChangeListener[] EMPTY = {};
10.499 +
10.500 + /**
10.501 + * Creates an array of {@link VetoableChangeListener VetoableChangeListener} objects.
10.502 + * This method uses the same instance of the empty array
10.503 + * when {@code length} equals {@code 0}.
10.504 + *
10.505 + * @param length the array length
10.506 + * @return an array with specified length
10.507 + */
10.508 + @Override
10.509 + protected VetoableChangeListener[] newArray(int length) {
10.510 + return (0 < length)
10.511 + ? new VetoableChangeListener[length]
10.512 + : EMPTY;
10.513 + }
10.514 +
10.515 + /**
10.516 + * Creates a {@link VetoableChangeListenerProxy VetoableChangeListenerProxy}
10.517 + * object for the specified property.
10.518 + *
10.519 + * @param name the name of the property to listen on
10.520 + * @param listener the listener to process events
10.521 + * @return a {@code VetoableChangeListenerProxy} object
10.522 + */
10.523 + @Override
10.524 + protected VetoableChangeListener newProxy(String name, VetoableChangeListener listener) {
10.525 + return new VetoableChangeListenerProxy(name, listener);
10.526 + }
10.527 + }
10.528 +}
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/emul/compact/src/main/java/java/io/Bits.java Fri Feb 01 16:35:42 2013 +0100
11.3 @@ -0,0 +1,123 @@
11.4 +/*
11.5 + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
11.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
11.7 + *
11.8 + * This code is free software; you can redistribute it and/or modify it
11.9 + * under the terms of the GNU General Public License version 2 only, as
11.10 + * published by the Free Software Foundation. Oracle designates this
11.11 + * particular file as subject to the "Classpath" exception as provided
11.12 + * by Oracle in the LICENSE file that accompanied this code.
11.13 + *
11.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
11.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11.17 + * version 2 for more details (a copy is included in the LICENSE file that
11.18 + * accompanied this code).
11.19 + *
11.20 + * You should have received a copy of the GNU General Public License version
11.21 + * 2 along with this work; if not, write to the Free Software Foundation,
11.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
11.23 + *
11.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
11.25 + * or visit www.oracle.com if you need additional information or have any
11.26 + * questions.
11.27 + */
11.28 +
11.29 +package java.io;
11.30 +
11.31 +/**
11.32 + * Utility methods for packing/unpacking primitive values in/out of byte arrays
11.33 + * using big-endian byte ordering.
11.34 + */
11.35 +class Bits {
11.36 +
11.37 + /*
11.38 + * Methods for unpacking primitive values from byte arrays starting at
11.39 + * given offsets.
11.40 + */
11.41 +
11.42 + static boolean getBoolean(byte[] b, int off) {
11.43 + return b[off] != 0;
11.44 + }
11.45 +
11.46 + static char getChar(byte[] b, int off) {
11.47 + return (char) ((b[off + 1] & 0xFF) +
11.48 + (b[off] << 8));
11.49 + }
11.50 +
11.51 + static short getShort(byte[] b, int off) {
11.52 + return (short) ((b[off + 1] & 0xFF) +
11.53 + (b[off] << 8));
11.54 + }
11.55 +
11.56 + static int getInt(byte[] b, int off) {
11.57 + return ((b[off + 3] & 0xFF) ) +
11.58 + ((b[off + 2] & 0xFF) << 8) +
11.59 + ((b[off + 1] & 0xFF) << 16) +
11.60 + ((b[off ] ) << 24);
11.61 + }
11.62 +
11.63 + static float getFloat(byte[] b, int off) {
11.64 + return Float.intBitsToFloat(getInt(b, off));
11.65 + }
11.66 +
11.67 + static long getLong(byte[] b, int off) {
11.68 + return ((b[off + 7] & 0xFFL) ) +
11.69 + ((b[off + 6] & 0xFFL) << 8) +
11.70 + ((b[off + 5] & 0xFFL) << 16) +
11.71 + ((b[off + 4] & 0xFFL) << 24) +
11.72 + ((b[off + 3] & 0xFFL) << 32) +
11.73 + ((b[off + 2] & 0xFFL) << 40) +
11.74 + ((b[off + 1] & 0xFFL) << 48) +
11.75 + (((long) b[off]) << 56);
11.76 + }
11.77 +
11.78 + static double getDouble(byte[] b, int off) {
11.79 + return Double.longBitsToDouble(getLong(b, off));
11.80 + }
11.81 +
11.82 + /*
11.83 + * Methods for packing primitive values into byte arrays starting at given
11.84 + * offsets.
11.85 + */
11.86 +
11.87 + static void putBoolean(byte[] b, int off, boolean val) {
11.88 + b[off] = (byte) (val ? 1 : 0);
11.89 + }
11.90 +
11.91 + static void putChar(byte[] b, int off, char val) {
11.92 + b[off + 1] = (byte) (val );
11.93 + b[off ] = (byte) (val >>> 8);
11.94 + }
11.95 +
11.96 + static void putShort(byte[] b, int off, short val) {
11.97 + b[off + 1] = (byte) (val );
11.98 + b[off ] = (byte) (val >>> 8);
11.99 + }
11.100 +
11.101 + static void putInt(byte[] b, int off, int val) {
11.102 + b[off + 3] = (byte) (val );
11.103 + b[off + 2] = (byte) (val >>> 8);
11.104 + b[off + 1] = (byte) (val >>> 16);
11.105 + b[off ] = (byte) (val >>> 24);
11.106 + }
11.107 +
11.108 + static void putFloat(byte[] b, int off, float val) {
11.109 + putInt(b, off, Float.floatToIntBits(val));
11.110 + }
11.111 +
11.112 + static void putLong(byte[] b, int off, long val) {
11.113 + b[off + 7] = (byte) (val );
11.114 + b[off + 6] = (byte) (val >>> 8);
11.115 + b[off + 5] = (byte) (val >>> 16);
11.116 + b[off + 4] = (byte) (val >>> 24);
11.117 + b[off + 3] = (byte) (val >>> 32);
11.118 + b[off + 2] = (byte) (val >>> 40);
11.119 + b[off + 1] = (byte) (val >>> 48);
11.120 + b[off ] = (byte) (val >>> 56);
11.121 + }
11.122 +
11.123 + static void putDouble(byte[] b, int off, double val) {
11.124 + putLong(b, off, Double.doubleToLongBits(val));
11.125 + }
11.126 +}
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/emul/compact/src/main/java/java/io/DataOutput.java Fri Feb 01 16:35:42 2013 +0100
12.3 @@ -0,0 +1,354 @@
12.4 +/*
12.5 + * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved.
12.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
12.7 + *
12.8 + * This code is free software; you can redistribute it and/or modify it
12.9 + * under the terms of the GNU General Public License version 2 only, as
12.10 + * published by the Free Software Foundation. Oracle designates this
12.11 + * particular file as subject to the "Classpath" exception as provided
12.12 + * by Oracle in the LICENSE file that accompanied this code.
12.13 + *
12.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
12.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12.17 + * version 2 for more details (a copy is included in the LICENSE file that
12.18 + * accompanied this code).
12.19 + *
12.20 + * You should have received a copy of the GNU General Public License version
12.21 + * 2 along with this work; if not, write to the Free Software Foundation,
12.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
12.23 + *
12.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
12.25 + * or visit www.oracle.com if you need additional information or have any
12.26 + * questions.
12.27 + */
12.28 +
12.29 +package java.io;
12.30 +
12.31 +/**
12.32 + * The <code>DataOutput</code> interface provides
12.33 + * for converting data from any of the Java
12.34 + * primitive types to a series of bytes and
12.35 + * writing these bytes to a binary stream.
12.36 + * There is also a facility for converting
12.37 + * a <code>String</code> into
12.38 + * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
12.39 + * format and writing the resulting series
12.40 + * of bytes.
12.41 + * <p>
12.42 + * For all the methods in this interface that
12.43 + * write bytes, it is generally true that if
12.44 + * a byte cannot be written for any reason,
12.45 + * an <code>IOException</code> is thrown.
12.46 + *
12.47 + * @author Frank Yellin
12.48 + * @see java.io.DataInput
12.49 + * @see java.io.DataOutputStream
12.50 + * @since JDK1.0
12.51 + */
12.52 +public
12.53 +interface DataOutput {
12.54 + /**
12.55 + * Writes to the output stream the eight
12.56 + * low-order bits of the argument <code>b</code>.
12.57 + * The 24 high-order bits of <code>b</code>
12.58 + * are ignored.
12.59 + *
12.60 + * @param b the byte to be written.
12.61 + * @throws IOException if an I/O error occurs.
12.62 + */
12.63 + void write(int b) throws IOException;
12.64 +
12.65 + /**
12.66 + * Writes to the output stream all the bytes in array <code>b</code>.
12.67 + * If <code>b</code> is <code>null</code>,
12.68 + * a <code>NullPointerException</code> is thrown.
12.69 + * If <code>b.length</code> is zero, then
12.70 + * no bytes are written. Otherwise, the byte
12.71 + * <code>b[0]</code> is written first, then
12.72 + * <code>b[1]</code>, and so on; the last byte
12.73 + * written is <code>b[b.length-1]</code>.
12.74 + *
12.75 + * @param b the data.
12.76 + * @throws IOException if an I/O error occurs.
12.77 + */
12.78 + void write(byte b[]) throws IOException;
12.79 +
12.80 + /**
12.81 + * Writes <code>len</code> bytes from array
12.82 + * <code>b</code>, in order, to
12.83 + * the output stream. If <code>b</code>
12.84 + * is <code>null</code>, a <code>NullPointerException</code>
12.85 + * is thrown. If <code>off</code> is negative,
12.86 + * or <code>len</code> is negative, or <code>off+len</code>
12.87 + * is greater than the length of the array
12.88 + * <code>b</code>, then an <code>IndexOutOfBoundsException</code>
12.89 + * is thrown. If <code>len</code> is zero,
12.90 + * then no bytes are written. Otherwise, the
12.91 + * byte <code>b[off]</code> is written first,
12.92 + * then <code>b[off+1]</code>, and so on; the
12.93 + * last byte written is <code>b[off+len-1]</code>.
12.94 + *
12.95 + * @param b the data.
12.96 + * @param off the start offset in the data.
12.97 + * @param len the number of bytes to write.
12.98 + * @throws IOException if an I/O error occurs.
12.99 + */
12.100 + void write(byte b[], int off, int len) throws IOException;
12.101 +
12.102 + /**
12.103 + * Writes a <code>boolean</code> value to this output stream.
12.104 + * If the argument <code>v</code>
12.105 + * is <code>true</code>, the value <code>(byte)1</code>
12.106 + * is written; if <code>v</code> is <code>false</code>,
12.107 + * the value <code>(byte)0</code> is written.
12.108 + * The byte written by this method may
12.109 + * be read by the <code>readBoolean</code>
12.110 + * method of interface <code>DataInput</code>,
12.111 + * which will then return a <code>boolean</code>
12.112 + * equal to <code>v</code>.
12.113 + *
12.114 + * @param v the boolean to be written.
12.115 + * @throws IOException if an I/O error occurs.
12.116 + */
12.117 + void writeBoolean(boolean v) throws IOException;
12.118 +
12.119 + /**
12.120 + * Writes to the output stream the eight low-
12.121 + * order bits of the argument <code>v</code>.
12.122 + * The 24 high-order bits of <code>v</code>
12.123 + * are ignored. (This means that <code>writeByte</code>
12.124 + * does exactly the same thing as <code>write</code>
12.125 + * for an integer argument.) The byte written
12.126 + * by this method may be read by the <code>readByte</code>
12.127 + * method of interface <code>DataInput</code>,
12.128 + * which will then return a <code>byte</code>
12.129 + * equal to <code>(byte)v</code>.
12.130 + *
12.131 + * @param v the byte value to be written.
12.132 + * @throws IOException if an I/O error occurs.
12.133 + */
12.134 + void writeByte(int v) throws IOException;
12.135 +
12.136 + /**
12.137 + * Writes two bytes to the output
12.138 + * stream to represent the value of the argument.
12.139 + * The byte values to be written, in the order
12.140 + * shown, are: <p>
12.141 + * <pre><code>
12.142 + * (byte)(0xff & (v >> 8))
12.143 + * (byte)(0xff & v)
12.144 + * </code> </pre> <p>
12.145 + * The bytes written by this method may be
12.146 + * read by the <code>readShort</code> method
12.147 + * of interface <code>DataInput</code> , which
12.148 + * will then return a <code>short</code> equal
12.149 + * to <code>(short)v</code>.
12.150 + *
12.151 + * @param v the <code>short</code> value to be written.
12.152 + * @throws IOException if an I/O error occurs.
12.153 + */
12.154 + void writeShort(int v) throws IOException;
12.155 +
12.156 + /**
12.157 + * Writes a <code>char</code> value, which
12.158 + * is comprised of two bytes, to the
12.159 + * output stream.
12.160 + * The byte values to be written, in the order
12.161 + * shown, are:
12.162 + * <p><pre><code>
12.163 + * (byte)(0xff & (v >> 8))
12.164 + * (byte)(0xff & v)
12.165 + * </code></pre><p>
12.166 + * The bytes written by this method may be
12.167 + * read by the <code>readChar</code> method
12.168 + * of interface <code>DataInput</code> , which
12.169 + * will then return a <code>char</code> equal
12.170 + * to <code>(char)v</code>.
12.171 + *
12.172 + * @param v the <code>char</code> value to be written.
12.173 + * @throws IOException if an I/O error occurs.
12.174 + */
12.175 + void writeChar(int v) throws IOException;
12.176 +
12.177 + /**
12.178 + * Writes an <code>int</code> value, which is
12.179 + * comprised of four bytes, to the output stream.
12.180 + * The byte values to be written, in the order
12.181 + * shown, are:
12.182 + * <p><pre><code>
12.183 + * (byte)(0xff & (v >> 24))
12.184 + * (byte)(0xff & (v >> 16))
12.185 + * (byte)(0xff & (v >>    8))
12.186 + * (byte)(0xff & v)
12.187 + * </code></pre><p>
12.188 + * The bytes written by this method may be read
12.189 + * by the <code>readInt</code> method of interface
12.190 + * <code>DataInput</code> , which will then
12.191 + * return an <code>int</code> equal to <code>v</code>.
12.192 + *
12.193 + * @param v the <code>int</code> value to be written.
12.194 + * @throws IOException if an I/O error occurs.
12.195 + */
12.196 + void writeInt(int v) throws IOException;
12.197 +
12.198 + /**
12.199 + * Writes a <code>long</code> value, which is
12.200 + * comprised of eight bytes, to the output stream.
12.201 + * The byte values to be written, in the order
12.202 + * shown, are:
12.203 + * <p><pre><code>
12.204 + * (byte)(0xff & (v >> 56))
12.205 + * (byte)(0xff & (v >> 48))
12.206 + * (byte)(0xff & (v >> 40))
12.207 + * (byte)(0xff & (v >> 32))
12.208 + * (byte)(0xff & (v >> 24))
12.209 + * (byte)(0xff & (v >> 16))
12.210 + * (byte)(0xff & (v >> 8))
12.211 + * (byte)(0xff & v)
12.212 + * </code></pre><p>
12.213 + * The bytes written by this method may be
12.214 + * read by the <code>readLong</code> method
12.215 + * of interface <code>DataInput</code> , which
12.216 + * will then return a <code>long</code> equal
12.217 + * to <code>v</code>.
12.218 + *
12.219 + * @param v the <code>long</code> value to be written.
12.220 + * @throws IOException if an I/O error occurs.
12.221 + */
12.222 + void writeLong(long v) throws IOException;
12.223 +
12.224 + /**
12.225 + * Writes a <code>float</code> value,
12.226 + * which is comprised of four bytes, to the output stream.
12.227 + * It does this as if it first converts this
12.228 + * <code>float</code> value to an <code>int</code>
12.229 + * in exactly the manner of the <code>Float.floatToIntBits</code>
12.230 + * method and then writes the <code>int</code>
12.231 + * value in exactly the manner of the <code>writeInt</code>
12.232 + * method. The bytes written by this method
12.233 + * may be read by the <code>readFloat</code>
12.234 + * method of interface <code>DataInput</code>,
12.235 + * which will then return a <code>float</code>
12.236 + * equal to <code>v</code>.
12.237 + *
12.238 + * @param v the <code>float</code> value to be written.
12.239 + * @throws IOException if an I/O error occurs.
12.240 + */
12.241 + void writeFloat(float v) throws IOException;
12.242 +
12.243 + /**
12.244 + * Writes a <code>double</code> value,
12.245 + * which is comprised of eight bytes, to the output stream.
12.246 + * It does this as if it first converts this
12.247 + * <code>double</code> value to a <code>long</code>
12.248 + * in exactly the manner of the <code>Double.doubleToLongBits</code>
12.249 + * method and then writes the <code>long</code>
12.250 + * value in exactly the manner of the <code>writeLong</code>
12.251 + * method. The bytes written by this method
12.252 + * may be read by the <code>readDouble</code>
12.253 + * method of interface <code>DataInput</code>,
12.254 + * which will then return a <code>double</code>
12.255 + * equal to <code>v</code>.
12.256 + *
12.257 + * @param v the <code>double</code> value to be written.
12.258 + * @throws IOException if an I/O error occurs.
12.259 + */
12.260 + void writeDouble(double v) throws IOException;
12.261 +
12.262 + /**
12.263 + * Writes a string to the output stream.
12.264 + * For every character in the string
12.265 + * <code>s</code>, taken in order, one byte
12.266 + * is written to the output stream. If
12.267 + * <code>s</code> is <code>null</code>, a <code>NullPointerException</code>
12.268 + * is thrown.<p> If <code>s.length</code>
12.269 + * is zero, then no bytes are written. Otherwise,
12.270 + * the character <code>s[0]</code> is written
12.271 + * first, then <code>s[1]</code>, and so on;
12.272 + * the last character written is <code>s[s.length-1]</code>.
12.273 + * For each character, one byte is written,
12.274 + * the low-order byte, in exactly the manner
12.275 + * of the <code>writeByte</code> method . The
12.276 + * high-order eight bits of each character
12.277 + * in the string are ignored.
12.278 + *
12.279 + * @param s the string of bytes to be written.
12.280 + * @throws IOException if an I/O error occurs.
12.281 + */
12.282 + void writeBytes(String s) throws IOException;
12.283 +
12.284 + /**
12.285 + * Writes every character in the string <code>s</code>,
12.286 + * to the output stream, in order,
12.287 + * two bytes per character. If <code>s</code>
12.288 + * is <code>null</code>, a <code>NullPointerException</code>
12.289 + * is thrown. If <code>s.length</code>
12.290 + * is zero, then no characters are written.
12.291 + * Otherwise, the character <code>s[0]</code>
12.292 + * is written first, then <code>s[1]</code>,
12.293 + * and so on; the last character written is
12.294 + * <code>s[s.length-1]</code>. For each character,
12.295 + * two bytes are actually written, high-order
12.296 + * byte first, in exactly the manner of the
12.297 + * <code>writeChar</code> method.
12.298 + *
12.299 + * @param s the string value to be written.
12.300 + * @throws IOException if an I/O error occurs.
12.301 + */
12.302 + void writeChars(String s) throws IOException;
12.303 +
12.304 + /**
12.305 + * Writes two bytes of length information
12.306 + * to the output stream, followed
12.307 + * by the
12.308 + * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
12.309 + * representation
12.310 + * of every character in the string <code>s</code>.
12.311 + * If <code>s</code> is <code>null</code>,
12.312 + * a <code>NullPointerException</code> is thrown.
12.313 + * Each character in the string <code>s</code>
12.314 + * is converted to a group of one, two, or
12.315 + * three bytes, depending on the value of the
12.316 + * character.<p>
12.317 + * If a character <code>c</code>
12.318 + * is in the range <code>\u0001</code> through
12.319 + * <code>\u007f</code>, it is represented
12.320 + * by one byte:<p>
12.321 + * <pre>(byte)c </pre> <p>
12.322 + * If a character <code>c</code> is <code>\u0000</code>
12.323 + * or is in the range <code>\u0080</code>
12.324 + * through <code>\u07ff</code>, then it is
12.325 + * represented by two bytes, to be written
12.326 + * in the order shown:<p> <pre><code>
12.327 + * (byte)(0xc0 | (0x1f & (c >> 6)))
12.328 + * (byte)(0x80 | (0x3f & c))
12.329 + * </code></pre> <p> If a character
12.330 + * <code>c</code> is in the range <code>\u0800</code>
12.331 + * through <code>uffff</code>, then it is
12.332 + * represented by three bytes, to be written
12.333 + * in the order shown:<p> <pre><code>
12.334 + * (byte)(0xe0 | (0x0f & (c >> 12)))
12.335 + * (byte)(0x80 | (0x3f & (c >> 6)))
12.336 + * (byte)(0x80 | (0x3f & c))
12.337 + * </code></pre> <p> First,
12.338 + * the total number of bytes needed to represent
12.339 + * all the characters of <code>s</code> is
12.340 + * calculated. If this number is larger than
12.341 + * <code>65535</code>, then a <code>UTFDataFormatException</code>
12.342 + * is thrown. Otherwise, this length is written
12.343 + * to the output stream in exactly the manner
12.344 + * of the <code>writeShort</code> method;
12.345 + * after this, the one-, two-, or three-byte
12.346 + * representation of each character in the
12.347 + * string <code>s</code> is written.<p> The
12.348 + * bytes written by this method may be read
12.349 + * by the <code>readUTF</code> method of interface
12.350 + * <code>DataInput</code> , which will then
12.351 + * return a <code>String</code> equal to <code>s</code>.
12.352 + *
12.353 + * @param s the string value to be written.
12.354 + * @throws IOException if an I/O error occurs.
12.355 + */
12.356 + void writeUTF(String s) throws IOException;
12.357 +}
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/emul/compact/src/main/java/java/io/DataOutputStream.java Fri Feb 01 16:35:42 2013 +0100
13.3 @@ -0,0 +1,416 @@
13.4 +/*
13.5 + * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.
13.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
13.7 + *
13.8 + * This code is free software; you can redistribute it and/or modify it
13.9 + * under the terms of the GNU General Public License version 2 only, as
13.10 + * published by the Free Software Foundation. Oracle designates this
13.11 + * particular file as subject to the "Classpath" exception as provided
13.12 + * by Oracle in the LICENSE file that accompanied this code.
13.13 + *
13.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
13.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13.17 + * version 2 for more details (a copy is included in the LICENSE file that
13.18 + * accompanied this code).
13.19 + *
13.20 + * You should have received a copy of the GNU General Public License version
13.21 + * 2 along with this work; if not, write to the Free Software Foundation,
13.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
13.23 + *
13.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
13.25 + * or visit www.oracle.com if you need additional information or have any
13.26 + * questions.
13.27 + */
13.28 +
13.29 +package java.io;
13.30 +
13.31 +/**
13.32 + * A data output stream lets an application write primitive Java data
13.33 + * types to an output stream in a portable way. An application can
13.34 + * then use a data input stream to read the data back in.
13.35 + *
13.36 + * @author unascribed
13.37 + * @see java.io.DataInputStream
13.38 + * @since JDK1.0
13.39 + */
13.40 +public
13.41 +class DataOutputStream extends FilterOutputStream implements DataOutput {
13.42 + /**
13.43 + * The number of bytes written to the data output stream so far.
13.44 + * If this counter overflows, it will be wrapped to Integer.MAX_VALUE.
13.45 + */
13.46 + protected int written;
13.47 +
13.48 + /**
13.49 + * bytearr is initialized on demand by writeUTF
13.50 + */
13.51 + private byte[] bytearr = null;
13.52 +
13.53 + /**
13.54 + * Creates a new data output stream to write data to the specified
13.55 + * underlying output stream. The counter <code>written</code> is
13.56 + * set to zero.
13.57 + *
13.58 + * @param out the underlying output stream, to be saved for later
13.59 + * use.
13.60 + * @see java.io.FilterOutputStream#out
13.61 + */
13.62 + public DataOutputStream(OutputStream out) {
13.63 + super(out);
13.64 + }
13.65 +
13.66 + /**
13.67 + * Increases the written counter by the specified value
13.68 + * until it reaches Integer.MAX_VALUE.
13.69 + */
13.70 + private void incCount(int value) {
13.71 + int temp = written + value;
13.72 + if (temp < 0) {
13.73 + temp = Integer.MAX_VALUE;
13.74 + }
13.75 + written = temp;
13.76 + }
13.77 +
13.78 + /**
13.79 + * Writes the specified byte (the low eight bits of the argument
13.80 + * <code>b</code>) to the underlying output stream. If no exception
13.81 + * is thrown, the counter <code>written</code> is incremented by
13.82 + * <code>1</code>.
13.83 + * <p>
13.84 + * Implements the <code>write</code> method of <code>OutputStream</code>.
13.85 + *
13.86 + * @param b the <code>byte</code> to be written.
13.87 + * @exception IOException if an I/O error occurs.
13.88 + * @see java.io.FilterOutputStream#out
13.89 + */
13.90 + public synchronized void write(int b) throws IOException {
13.91 + out.write(b);
13.92 + incCount(1);
13.93 + }
13.94 +
13.95 + /**
13.96 + * Writes <code>len</code> bytes from the specified byte array
13.97 + * starting at offset <code>off</code> to the underlying output stream.
13.98 + * If no exception is thrown, the counter <code>written</code> is
13.99 + * incremented by <code>len</code>.
13.100 + *
13.101 + * @param b the data.
13.102 + * @param off the start offset in the data.
13.103 + * @param len the number of bytes to write.
13.104 + * @exception IOException if an I/O error occurs.
13.105 + * @see java.io.FilterOutputStream#out
13.106 + */
13.107 + public synchronized void write(byte b[], int off, int len)
13.108 + throws IOException
13.109 + {
13.110 + out.write(b, off, len);
13.111 + incCount(len);
13.112 + }
13.113 +
13.114 + /**
13.115 + * Flushes this data output stream. This forces any buffered output
13.116 + * bytes to be written out to the stream.
13.117 + * <p>
13.118 + * The <code>flush</code> method of <code>DataOutputStream</code>
13.119 + * calls the <code>flush</code> method of its underlying output stream.
13.120 + *
13.121 + * @exception IOException if an I/O error occurs.
13.122 + * @see java.io.FilterOutputStream#out
13.123 + * @see java.io.OutputStream#flush()
13.124 + */
13.125 + public void flush() throws IOException {
13.126 + out.flush();
13.127 + }
13.128 +
13.129 + /**
13.130 + * Writes a <code>boolean</code> to the underlying output stream as
13.131 + * a 1-byte value. The value <code>true</code> is written out as the
13.132 + * value <code>(byte)1</code>; the value <code>false</code> is
13.133 + * written out as the value <code>(byte)0</code>. If no exception is
13.134 + * thrown, the counter <code>written</code> is incremented by
13.135 + * <code>1</code>.
13.136 + *
13.137 + * @param v a <code>boolean</code> value to be written.
13.138 + * @exception IOException if an I/O error occurs.
13.139 + * @see java.io.FilterOutputStream#out
13.140 + */
13.141 + public final void writeBoolean(boolean v) throws IOException {
13.142 + out.write(v ? 1 : 0);
13.143 + incCount(1);
13.144 + }
13.145 +
13.146 + /**
13.147 + * Writes out a <code>byte</code> to the underlying output stream as
13.148 + * a 1-byte value. If no exception is thrown, the counter
13.149 + * <code>written</code> is incremented by <code>1</code>.
13.150 + *
13.151 + * @param v a <code>byte</code> value to be written.
13.152 + * @exception IOException if an I/O error occurs.
13.153 + * @see java.io.FilterOutputStream#out
13.154 + */
13.155 + public final void writeByte(int v) throws IOException {
13.156 + out.write(v);
13.157 + incCount(1);
13.158 + }
13.159 +
13.160 + /**
13.161 + * Writes a <code>short</code> to the underlying output stream as two
13.162 + * bytes, high byte first. If no exception is thrown, the counter
13.163 + * <code>written</code> is incremented by <code>2</code>.
13.164 + *
13.165 + * @param v a <code>short</code> to be written.
13.166 + * @exception IOException if an I/O error occurs.
13.167 + * @see java.io.FilterOutputStream#out
13.168 + */
13.169 + public final void writeShort(int v) throws IOException {
13.170 + out.write((v >>> 8) & 0xFF);
13.171 + out.write((v >>> 0) & 0xFF);
13.172 + incCount(2);
13.173 + }
13.174 +
13.175 + /**
13.176 + * Writes a <code>char</code> to the underlying output stream as a
13.177 + * 2-byte value, high byte first. If no exception is thrown, the
13.178 + * counter <code>written</code> is incremented by <code>2</code>.
13.179 + *
13.180 + * @param v a <code>char</code> value to be written.
13.181 + * @exception IOException if an I/O error occurs.
13.182 + * @see java.io.FilterOutputStream#out
13.183 + */
13.184 + public final void writeChar(int v) throws IOException {
13.185 + out.write((v >>> 8) & 0xFF);
13.186 + out.write((v >>> 0) & 0xFF);
13.187 + incCount(2);
13.188 + }
13.189 +
13.190 + /**
13.191 + * Writes an <code>int</code> to the underlying output stream as four
13.192 + * bytes, high byte first. If no exception is thrown, the counter
13.193 + * <code>written</code> is incremented by <code>4</code>.
13.194 + *
13.195 + * @param v an <code>int</code> to be written.
13.196 + * @exception IOException if an I/O error occurs.
13.197 + * @see java.io.FilterOutputStream#out
13.198 + */
13.199 + public final void writeInt(int v) throws IOException {
13.200 + out.write((v >>> 24) & 0xFF);
13.201 + out.write((v >>> 16) & 0xFF);
13.202 + out.write((v >>> 8) & 0xFF);
13.203 + out.write((v >>> 0) & 0xFF);
13.204 + incCount(4);
13.205 + }
13.206 +
13.207 + private byte writeBuffer[] = new byte[8];
13.208 +
13.209 + /**
13.210 + * Writes a <code>long</code> to the underlying output stream as eight
13.211 + * bytes, high byte first. In no exception is thrown, the counter
13.212 + * <code>written</code> is incremented by <code>8</code>.
13.213 + *
13.214 + * @param v a <code>long</code> to be written.
13.215 + * @exception IOException if an I/O error occurs.
13.216 + * @see java.io.FilterOutputStream#out
13.217 + */
13.218 + public final void writeLong(long v) throws IOException {
13.219 + writeBuffer[0] = (byte)(v >>> 56);
13.220 + writeBuffer[1] = (byte)(v >>> 48);
13.221 + writeBuffer[2] = (byte)(v >>> 40);
13.222 + writeBuffer[3] = (byte)(v >>> 32);
13.223 + writeBuffer[4] = (byte)(v >>> 24);
13.224 + writeBuffer[5] = (byte)(v >>> 16);
13.225 + writeBuffer[6] = (byte)(v >>> 8);
13.226 + writeBuffer[7] = (byte)(v >>> 0);
13.227 + out.write(writeBuffer, 0, 8);
13.228 + incCount(8);
13.229 + }
13.230 +
13.231 + /**
13.232 + * Converts the float argument to an <code>int</code> using the
13.233 + * <code>floatToIntBits</code> method in class <code>Float</code>,
13.234 + * and then writes that <code>int</code> value to the underlying
13.235 + * output stream as a 4-byte quantity, high byte first. If no
13.236 + * exception is thrown, the counter <code>written</code> is
13.237 + * incremented by <code>4</code>.
13.238 + *
13.239 + * @param v a <code>float</code> value to be written.
13.240 + * @exception IOException if an I/O error occurs.
13.241 + * @see java.io.FilterOutputStream#out
13.242 + * @see java.lang.Float#floatToIntBits(float)
13.243 + */
13.244 + public final void writeFloat(float v) throws IOException {
13.245 + writeInt(Float.floatToIntBits(v));
13.246 + }
13.247 +
13.248 + /**
13.249 + * Converts the double argument to a <code>long</code> using the
13.250 + * <code>doubleToLongBits</code> method in class <code>Double</code>,
13.251 + * and then writes that <code>long</code> value to the underlying
13.252 + * output stream as an 8-byte quantity, high byte first. If no
13.253 + * exception is thrown, the counter <code>written</code> is
13.254 + * incremented by <code>8</code>.
13.255 + *
13.256 + * @param v a <code>double</code> value to be written.
13.257 + * @exception IOException if an I/O error occurs.
13.258 + * @see java.io.FilterOutputStream#out
13.259 + * @see java.lang.Double#doubleToLongBits(double)
13.260 + */
13.261 + public final void writeDouble(double v) throws IOException {
13.262 + writeLong(Double.doubleToLongBits(v));
13.263 + }
13.264 +
13.265 + /**
13.266 + * Writes out the string to the underlying output stream as a
13.267 + * sequence of bytes. Each character in the string is written out, in
13.268 + * sequence, by discarding its high eight bits. If no exception is
13.269 + * thrown, the counter <code>written</code> is incremented by the
13.270 + * length of <code>s</code>.
13.271 + *
13.272 + * @param s a string of bytes to be written.
13.273 + * @exception IOException if an I/O error occurs.
13.274 + * @see java.io.FilterOutputStream#out
13.275 + */
13.276 + public final void writeBytes(String s) throws IOException {
13.277 + int len = s.length();
13.278 + for (int i = 0 ; i < len ; i++) {
13.279 + out.write((byte)s.charAt(i));
13.280 + }
13.281 + incCount(len);
13.282 + }
13.283 +
13.284 + /**
13.285 + * Writes a string to the underlying output stream as a sequence of
13.286 + * characters. Each character is written to the data output stream as
13.287 + * if by the <code>writeChar</code> method. If no exception is
13.288 + * thrown, the counter <code>written</code> is incremented by twice
13.289 + * the length of <code>s</code>.
13.290 + *
13.291 + * @param s a <code>String</code> value to be written.
13.292 + * @exception IOException if an I/O error occurs.
13.293 + * @see java.io.DataOutputStream#writeChar(int)
13.294 + * @see java.io.FilterOutputStream#out
13.295 + */
13.296 + public final void writeChars(String s) throws IOException {
13.297 + int len = s.length();
13.298 + for (int i = 0 ; i < len ; i++) {
13.299 + int v = s.charAt(i);
13.300 + out.write((v >>> 8) & 0xFF);
13.301 + out.write((v >>> 0) & 0xFF);
13.302 + }
13.303 + incCount(len * 2);
13.304 + }
13.305 +
13.306 + /**
13.307 + * Writes a string to the underlying output stream using
13.308 + * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
13.309 + * encoding in a machine-independent manner.
13.310 + * <p>
13.311 + * First, two bytes are written to the output stream as if by the
13.312 + * <code>writeShort</code> method giving the number of bytes to
13.313 + * follow. This value is the number of bytes actually written out,
13.314 + * not the length of the string. Following the length, each character
13.315 + * of the string is output, in sequence, using the modified UTF-8 encoding
13.316 + * for the character. If no exception is thrown, the counter
13.317 + * <code>written</code> is incremented by the total number of
13.318 + * bytes written to the output stream. This will be at least two
13.319 + * plus the length of <code>str</code>, and at most two plus
13.320 + * thrice the length of <code>str</code>.
13.321 + *
13.322 + * @param str a string to be written.
13.323 + * @exception IOException if an I/O error occurs.
13.324 + */
13.325 + public final void writeUTF(String str) throws IOException {
13.326 + writeUTF(str, this);
13.327 + }
13.328 +
13.329 + /**
13.330 + * Writes a string to the specified DataOutput using
13.331 + * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
13.332 + * encoding in a machine-independent manner.
13.333 + * <p>
13.334 + * First, two bytes are written to out as if by the <code>writeShort</code>
13.335 + * method giving the number of bytes to follow. This value is the number of
13.336 + * bytes actually written out, not the length of the string. Following the
13.337 + * length, each character of the string is output, in sequence, using the
13.338 + * modified UTF-8 encoding for the character. If no exception is thrown, the
13.339 + * counter <code>written</code> is incremented by the total number of
13.340 + * bytes written to the output stream. This will be at least two
13.341 + * plus the length of <code>str</code>, and at most two plus
13.342 + * thrice the length of <code>str</code>.
13.343 + *
13.344 + * @param str a string to be written.
13.345 + * @param out destination to write to
13.346 + * @return The number of bytes written out.
13.347 + * @exception IOException if an I/O error occurs.
13.348 + */
13.349 + static int writeUTF(String str, DataOutput out) throws IOException {
13.350 + int strlen = str.length();
13.351 + int utflen = 0;
13.352 + int c, count = 0;
13.353 +
13.354 + /* use charAt instead of copying String to char array */
13.355 + for (int i = 0; i < strlen; i++) {
13.356 + c = str.charAt(i);
13.357 + if ((c >= 0x0001) && (c <= 0x007F)) {
13.358 + utflen++;
13.359 + } else if (c > 0x07FF) {
13.360 + utflen += 3;
13.361 + } else {
13.362 + utflen += 2;
13.363 + }
13.364 + }
13.365 +
13.366 + if (utflen > 65535)
13.367 + throw new UTFDataFormatException(
13.368 + "encoded string too long: " + utflen + " bytes");
13.369 +
13.370 + byte[] bytearr = null;
13.371 + if (out instanceof DataOutputStream) {
13.372 + DataOutputStream dos = (DataOutputStream)out;
13.373 + if(dos.bytearr == null || (dos.bytearr.length < (utflen+2)))
13.374 + dos.bytearr = new byte[(utflen*2) + 2];
13.375 + bytearr = dos.bytearr;
13.376 + } else {
13.377 + bytearr = new byte[utflen+2];
13.378 + }
13.379 +
13.380 + bytearr[count++] = (byte) ((utflen >>> 8) & 0xFF);
13.381 + bytearr[count++] = (byte) ((utflen >>> 0) & 0xFF);
13.382 +
13.383 + int i=0;
13.384 + for (i=0; i<strlen; i++) {
13.385 + c = str.charAt(i);
13.386 + if (!((c >= 0x0001) && (c <= 0x007F))) break;
13.387 + bytearr[count++] = (byte) c;
13.388 + }
13.389 +
13.390 + for (;i < strlen; i++){
13.391 + c = str.charAt(i);
13.392 + if ((c >= 0x0001) && (c <= 0x007F)) {
13.393 + bytearr[count++] = (byte) c;
13.394 +
13.395 + } else if (c > 0x07FF) {
13.396 + bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
13.397 + bytearr[count++] = (byte) (0x80 | ((c >> 6) & 0x3F));
13.398 + bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
13.399 + } else {
13.400 + bytearr[count++] = (byte) (0xC0 | ((c >> 6) & 0x1F));
13.401 + bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
13.402 + }
13.403 + }
13.404 + out.write(bytearr, 0, utflen+2);
13.405 + return utflen + 2;
13.406 + }
13.407 +
13.408 + /**
13.409 + * Returns the current value of the counter <code>written</code>,
13.410 + * the number of bytes written to this data output stream so far.
13.411 + * If the counter overflows, it will be wrapped to Integer.MAX_VALUE.
13.412 + *
13.413 + * @return the value of the <code>written</code> field.
13.414 + * @see java.io.DataOutputStream#written
13.415 + */
13.416 + public final int size() {
13.417 + return written;
13.418 + }
13.419 +}
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/emul/compact/src/main/java/java/io/Externalizable.java Fri Feb 01 16:35:42 2013 +0100
14.3 @@ -0,0 +1,97 @@
14.4 +/*
14.5 + * Copyright (c) 1996, 2004, Oracle and/or its affiliates. All rights reserved.
14.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
14.7 + *
14.8 + * This code is free software; you can redistribute it and/or modify it
14.9 + * under the terms of the GNU General Public License version 2 only, as
14.10 + * published by the Free Software Foundation. Oracle designates this
14.11 + * particular file as subject to the "Classpath" exception as provided
14.12 + * by Oracle in the LICENSE file that accompanied this code.
14.13 + *
14.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
14.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14.17 + * version 2 for more details (a copy is included in the LICENSE file that
14.18 + * accompanied this code).
14.19 + *
14.20 + * You should have received a copy of the GNU General Public License version
14.21 + * 2 along with this work; if not, write to the Free Software Foundation,
14.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
14.23 + *
14.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
14.25 + * or visit www.oracle.com if you need additional information or have any
14.26 + * questions.
14.27 + */
14.28 +
14.29 +package java.io;
14.30 +
14.31 +import java.io.ObjectOutput;
14.32 +import java.io.ObjectInput;
14.33 +
14.34 +/**
14.35 + * Only the identity of the class of an Externalizable instance is
14.36 + * written in the serialization stream and it is the responsibility
14.37 + * of the class to save and restore the contents of its instances.
14.38 + *
14.39 + * The writeExternal and readExternal methods of the Externalizable
14.40 + * interface are implemented by a class to give the class complete
14.41 + * control over the format and contents of the stream for an object
14.42 + * and its supertypes. These methods must explicitly
14.43 + * coordinate with the supertype to save its state. These methods supersede
14.44 + * customized implementations of writeObject and readObject methods.<br>
14.45 + *
14.46 + * Object Serialization uses the Serializable and Externalizable
14.47 + * interfaces. Object persistence mechanisms can use them as well. Each
14.48 + * object to be stored is tested for the Externalizable interface. If
14.49 + * the object supports Externalizable, the writeExternal method is called. If the
14.50 + * object does not support Externalizable and does implement
14.51 + * Serializable, the object is saved using
14.52 + * ObjectOutputStream. <br> When an Externalizable object is
14.53 + * reconstructed, an instance is created using the public no-arg
14.54 + * constructor, then the readExternal method called. Serializable
14.55 + * objects are restored by reading them from an ObjectInputStream.<br>
14.56 + *
14.57 + * An Externalizable instance can designate a substitution object via
14.58 + * the writeReplace and readResolve methods documented in the Serializable
14.59 + * interface.<br>
14.60 + *
14.61 + * @author unascribed
14.62 + * @see java.io.ObjectOutputStream
14.63 + * @see java.io.ObjectInputStream
14.64 + * @see java.io.ObjectOutput
14.65 + * @see java.io.ObjectInput
14.66 + * @see java.io.Serializable
14.67 + * @since JDK1.1
14.68 + */
14.69 +public interface Externalizable extends java.io.Serializable {
14.70 + /**
14.71 + * The object implements the writeExternal method to save its contents
14.72 + * by calling the methods of DataOutput for its primitive values or
14.73 + * calling the writeObject method of ObjectOutput for objects, strings,
14.74 + * and arrays.
14.75 + *
14.76 + * @serialData Overriding methods should use this tag to describe
14.77 + * the data layout of this Externalizable object.
14.78 + * List the sequence of element types and, if possible,
14.79 + * relate the element to a public/protected field and/or
14.80 + * method of this Externalizable class.
14.81 + *
14.82 + * @param out the stream to write the object to
14.83 + * @exception IOException Includes any I/O exceptions that may occur
14.84 + */
14.85 + void writeExternal(ObjectOutput out) throws IOException;
14.86 +
14.87 + /**
14.88 + * The object implements the readExternal method to restore its
14.89 + * contents by calling the methods of DataInput for primitive
14.90 + * types and readObject for objects, strings and arrays. The
14.91 + * readExternal method must read the values in the same sequence
14.92 + * and with the same types as were written by writeExternal.
14.93 + *
14.94 + * @param in the stream to read data from in order to restore the object
14.95 + * @exception IOException if I/O errors occur
14.96 + * @exception ClassNotFoundException If the class for an object being
14.97 + * restored cannot be found.
14.98 + */
14.99 + void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
14.100 +}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/emul/compact/src/main/java/java/io/FilterOutputStream.java Fri Feb 01 16:35:42 2013 +0100
15.3 @@ -0,0 +1,162 @@
15.4 +/*
15.5 + * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
15.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
15.7 + *
15.8 + * This code is free software; you can redistribute it and/or modify it
15.9 + * under the terms of the GNU General Public License version 2 only, as
15.10 + * published by the Free Software Foundation. Oracle designates this
15.11 + * particular file as subject to the "Classpath" exception as provided
15.12 + * by Oracle in the LICENSE file that accompanied this code.
15.13 + *
15.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
15.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15.17 + * version 2 for more details (a copy is included in the LICENSE file that
15.18 + * accompanied this code).
15.19 + *
15.20 + * You should have received a copy of the GNU General Public License version
15.21 + * 2 along with this work; if not, write to the Free Software Foundation,
15.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
15.23 + *
15.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
15.25 + * or visit www.oracle.com if you need additional information or have any
15.26 + * questions.
15.27 + */
15.28 +
15.29 +package java.io;
15.30 +
15.31 +/**
15.32 + * This class is the superclass of all classes that filter output
15.33 + * streams. These streams sit on top of an already existing output
15.34 + * stream (the <i>underlying</i> output stream) which it uses as its
15.35 + * basic sink of data, but possibly transforming the data along the
15.36 + * way or providing additional functionality.
15.37 + * <p>
15.38 + * The class <code>FilterOutputStream</code> itself simply overrides
15.39 + * all methods of <code>OutputStream</code> with versions that pass
15.40 + * all requests to the underlying output stream. Subclasses of
15.41 + * <code>FilterOutputStream</code> may further override some of these
15.42 + * methods as well as provide additional methods and fields.
15.43 + *
15.44 + * @author Jonathan Payne
15.45 + * @since JDK1.0
15.46 + */
15.47 +public
15.48 +class FilterOutputStream extends OutputStream {
15.49 + /**
15.50 + * The underlying output stream to be filtered.
15.51 + */
15.52 + protected OutputStream out;
15.53 +
15.54 + /**
15.55 + * Creates an output stream filter built on top of the specified
15.56 + * underlying output stream.
15.57 + *
15.58 + * @param out the underlying output stream to be assigned to
15.59 + * the field <tt>this.out</tt> for later use, or
15.60 + * <code>null</code> if this instance is to be
15.61 + * created without an underlying stream.
15.62 + */
15.63 + public FilterOutputStream(OutputStream out) {
15.64 + this.out = out;
15.65 + }
15.66 +
15.67 + /**
15.68 + * Writes the specified <code>byte</code> to this output stream.
15.69 + * <p>
15.70 + * The <code>write</code> method of <code>FilterOutputStream</code>
15.71 + * calls the <code>write</code> method of its underlying output stream,
15.72 + * that is, it performs <tt>out.write(b)</tt>.
15.73 + * <p>
15.74 + * Implements the abstract <tt>write</tt> method of <tt>OutputStream</tt>.
15.75 + *
15.76 + * @param b the <code>byte</code>.
15.77 + * @exception IOException if an I/O error occurs.
15.78 + */
15.79 + public void write(int b) throws IOException {
15.80 + out.write(b);
15.81 + }
15.82 +
15.83 + /**
15.84 + * Writes <code>b.length</code> bytes to this output stream.
15.85 + * <p>
15.86 + * The <code>write</code> method of <code>FilterOutputStream</code>
15.87 + * calls its <code>write</code> method of three arguments with the
15.88 + * arguments <code>b</code>, <code>0</code>, and
15.89 + * <code>b.length</code>.
15.90 + * <p>
15.91 + * Note that this method does not call the one-argument
15.92 + * <code>write</code> method of its underlying stream with the single
15.93 + * argument <code>b</code>.
15.94 + *
15.95 + * @param b the data to be written.
15.96 + * @exception IOException if an I/O error occurs.
15.97 + * @see java.io.FilterOutputStream#write(byte[], int, int)
15.98 + */
15.99 + public void write(byte b[]) throws IOException {
15.100 + write(b, 0, b.length);
15.101 + }
15.102 +
15.103 + /**
15.104 + * Writes <code>len</code> bytes from the specified
15.105 + * <code>byte</code> array starting at offset <code>off</code> to
15.106 + * this output stream.
15.107 + * <p>
15.108 + * The <code>write</code> method of <code>FilterOutputStream</code>
15.109 + * calls the <code>write</code> method of one argument on each
15.110 + * <code>byte</code> to output.
15.111 + * <p>
15.112 + * Note that this method does not call the <code>write</code> method
15.113 + * of its underlying input stream with the same arguments. Subclasses
15.114 + * of <code>FilterOutputStream</code> should provide a more efficient
15.115 + * implementation of this method.
15.116 + *
15.117 + * @param b the data.
15.118 + * @param off the start offset in the data.
15.119 + * @param len the number of bytes to write.
15.120 + * @exception IOException if an I/O error occurs.
15.121 + * @see java.io.FilterOutputStream#write(int)
15.122 + */
15.123 + public void write(byte b[], int off, int len) throws IOException {
15.124 + if ((off | len | (b.length - (len + off)) | (off + len)) < 0)
15.125 + throw new IndexOutOfBoundsException();
15.126 +
15.127 + for (int i = 0 ; i < len ; i++) {
15.128 + write(b[off + i]);
15.129 + }
15.130 + }
15.131 +
15.132 + /**
15.133 + * Flushes this output stream and forces any buffered output bytes
15.134 + * to be written out to the stream.
15.135 + * <p>
15.136 + * The <code>flush</code> method of <code>FilterOutputStream</code>
15.137 + * calls the <code>flush</code> method of its underlying output stream.
15.138 + *
15.139 + * @exception IOException if an I/O error occurs.
15.140 + * @see java.io.FilterOutputStream#out
15.141 + */
15.142 + public void flush() throws IOException {
15.143 + out.flush();
15.144 + }
15.145 +
15.146 + /**
15.147 + * Closes this output stream and releases any system resources
15.148 + * associated with the stream.
15.149 + * <p>
15.150 + * The <code>close</code> method of <code>FilterOutputStream</code>
15.151 + * calls its <code>flush</code> method, and then calls the
15.152 + * <code>close</code> method of its underlying output stream.
15.153 + *
15.154 + * @exception IOException if an I/O error occurs.
15.155 + * @see java.io.FilterOutputStream#flush()
15.156 + * @see java.io.FilterOutputStream#out
15.157 + */
15.158 + public void close() throws IOException {
15.159 + try {
15.160 + flush();
15.161 + } catch (IOException ignored) {
15.162 + }
15.163 + out.close();
15.164 + }
15.165 +}
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/emul/compact/src/main/java/java/io/Flushable.java Fri Feb 01 16:35:42 2013 +0100
16.3 @@ -0,0 +1,47 @@
16.4 +/*
16.5 + * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
16.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
16.7 + *
16.8 + * This code is free software; you can redistribute it and/or modify it
16.9 + * under the terms of the GNU General Public License version 2 only, as
16.10 + * published by the Free Software Foundation. Oracle designates this
16.11 + * particular file as subject to the "Classpath" exception as provided
16.12 + * by Oracle in the LICENSE file that accompanied this code.
16.13 + *
16.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
16.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16.17 + * version 2 for more details (a copy is included in the LICENSE file that
16.18 + * accompanied this code).
16.19 + *
16.20 + * You should have received a copy of the GNU General Public License version
16.21 + * 2 along with this work; if not, write to the Free Software Foundation,
16.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
16.23 + *
16.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
16.25 + * or visit www.oracle.com if you need additional information or have any
16.26 + * questions.
16.27 + */
16.28 +
16.29 +package java.io;
16.30 +
16.31 +import java.io.IOException;
16.32 +
16.33 +/**
16.34 + * A <tt>Flushable</tt> is a destination of data that can be flushed. The
16.35 + * flush method is invoked to write any buffered output to the underlying
16.36 + * stream.
16.37 + *
16.38 + * @since 1.5
16.39 + */
16.40 +
16.41 +public interface Flushable {
16.42 +
16.43 + /**
16.44 + * Flushes this stream by writing any buffered output to the underlying
16.45 + * stream.
16.46 + *
16.47 + * @throws IOException If an I/O error occurs
16.48 + */
16.49 + void flush() throws IOException;
16.50 +}
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/emul/compact/src/main/java/java/io/InvalidClassException.java Fri Feb 01 16:35:42 2013 +0100
17.3 @@ -0,0 +1,81 @@
17.4 +/*
17.5 + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
17.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
17.7 + *
17.8 + * This code is free software; you can redistribute it and/or modify it
17.9 + * under the terms of the GNU General Public License version 2 only, as
17.10 + * published by the Free Software Foundation. Oracle designates this
17.11 + * particular file as subject to the "Classpath" exception as provided
17.12 + * by Oracle in the LICENSE file that accompanied this code.
17.13 + *
17.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
17.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17.17 + * version 2 for more details (a copy is included in the LICENSE file that
17.18 + * accompanied this code).
17.19 + *
17.20 + * You should have received a copy of the GNU General Public License version
17.21 + * 2 along with this work; if not, write to the Free Software Foundation,
17.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17.23 + *
17.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
17.25 + * or visit www.oracle.com if you need additional information or have any
17.26 + * questions.
17.27 + */
17.28 +
17.29 +package java.io;
17.30 +
17.31 +/**
17.32 + * Thrown when the Serialization runtime detects one of the following
17.33 + * problems with a Class.
17.34 + * <UL>
17.35 + * <LI> The serial version of the class does not match that of the class
17.36 + * descriptor read from the stream
17.37 + * <LI> The class contains unknown datatypes
17.38 + * <LI> The class does not have an accessible no-arg constructor
17.39 + * </UL>
17.40 + *
17.41 + * @author unascribed
17.42 + * @since JDK1.1
17.43 + */
17.44 +public class InvalidClassException extends ObjectStreamException {
17.45 +
17.46 + private static final long serialVersionUID = -4333316296251054416L;
17.47 +
17.48 + /**
17.49 + * Name of the invalid class.
17.50 + *
17.51 + * @serial Name of the invalid class.
17.52 + */
17.53 + public String classname;
17.54 +
17.55 + /**
17.56 + * Report an InvalidClassException for the reason specified.
17.57 + *
17.58 + * @param reason String describing the reason for the exception.
17.59 + */
17.60 + public InvalidClassException(String reason) {
17.61 + super(reason);
17.62 + }
17.63 +
17.64 + /**
17.65 + * Constructs an InvalidClassException object.
17.66 + *
17.67 + * @param cname a String naming the invalid class.
17.68 + * @param reason a String describing the reason for the exception.
17.69 + */
17.70 + public InvalidClassException(String cname, String reason) {
17.71 + super(reason);
17.72 + classname = cname;
17.73 + }
17.74 +
17.75 + /**
17.76 + * Produce the message and include the classname, if present.
17.77 + */
17.78 + public String getMessage() {
17.79 + if (classname == null)
17.80 + return super.getMessage();
17.81 + else
17.82 + return classname + "; " + super.getMessage();
17.83 + }
17.84 +}
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
18.2 +++ b/emul/compact/src/main/java/java/io/InvalidObjectException.java Fri Feb 01 16:35:42 2013 +0100
18.3 @@ -0,0 +1,51 @@
18.4 +/*
18.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
18.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
18.7 + *
18.8 + * This code is free software; you can redistribute it and/or modify it
18.9 + * under the terms of the GNU General Public License version 2 only, as
18.10 + * published by the Free Software Foundation. Oracle designates this
18.11 + * particular file as subject to the "Classpath" exception as provided
18.12 + * by Oracle in the LICENSE file that accompanied this code.
18.13 + *
18.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
18.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18.17 + * version 2 for more details (a copy is included in the LICENSE file that
18.18 + * accompanied this code).
18.19 + *
18.20 + * You should have received a copy of the GNU General Public License version
18.21 + * 2 along with this work; if not, write to the Free Software Foundation,
18.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18.23 + *
18.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
18.25 + * or visit www.oracle.com if you need additional information or have any
18.26 + * questions.
18.27 + */
18.28 +
18.29 +package java.io;
18.30 +
18.31 +/**
18.32 + * Indicates that one or more deserialized objects failed validation
18.33 + * tests. The argument should provide the reason for the failure.
18.34 + *
18.35 + * @see ObjectInputValidation
18.36 + * @since JDK1.1
18.37 + *
18.38 + * @author unascribed
18.39 + * @since JDK1.1
18.40 + */
18.41 +public class InvalidObjectException extends ObjectStreamException {
18.42 +
18.43 + private static final long serialVersionUID = 3233174318281839583L;
18.44 +
18.45 + /**
18.46 + * Constructs an <code>InvalidObjectException</code>.
18.47 + * @param reason Detailed message explaining the reason for the failure.
18.48 + *
18.49 + * @see ObjectInputValidation
18.50 + */
18.51 + public InvalidObjectException(String reason) {
18.52 + super(reason);
18.53 + }
18.54 +}
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
19.2 +++ b/emul/compact/src/main/java/java/io/NotActiveException.java Fri Feb 01 16:35:42 2013 +0100
19.3 @@ -0,0 +1,53 @@
19.4 +/*
19.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
19.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
19.7 + *
19.8 + * This code is free software; you can redistribute it and/or modify it
19.9 + * under the terms of the GNU General Public License version 2 only, as
19.10 + * published by the Free Software Foundation. Oracle designates this
19.11 + * particular file as subject to the "Classpath" exception as provided
19.12 + * by Oracle in the LICENSE file that accompanied this code.
19.13 + *
19.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
19.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19.17 + * version 2 for more details (a copy is included in the LICENSE file that
19.18 + * accompanied this code).
19.19 + *
19.20 + * You should have received a copy of the GNU General Public License version
19.21 + * 2 along with this work; if not, write to the Free Software Foundation,
19.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19.23 + *
19.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19.25 + * or visit www.oracle.com if you need additional information or have any
19.26 + * questions.
19.27 + */
19.28 +
19.29 +package java.io;
19.30 +
19.31 +/**
19.32 + * Thrown when serialization or deserialization is not active.
19.33 + *
19.34 + * @author unascribed
19.35 + * @since JDK1.1
19.36 + */
19.37 +public class NotActiveException extends ObjectStreamException {
19.38 +
19.39 + private static final long serialVersionUID = -3893467273049808895L;
19.40 +
19.41 + /**
19.42 + * Constructor to create a new NotActiveException with the reason given.
19.43 + *
19.44 + * @param reason a String describing the reason for the exception.
19.45 + */
19.46 + public NotActiveException(String reason) {
19.47 + super(reason);
19.48 + }
19.49 +
19.50 + /**
19.51 + * Constructor to create a new NotActiveException without a reason.
19.52 + */
19.53 + public NotActiveException() {
19.54 + super();
19.55 + }
19.56 +}
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
20.2 +++ b/emul/compact/src/main/java/java/io/NotSerializableException.java Fri Feb 01 16:35:42 2013 +0100
20.3 @@ -0,0 +1,55 @@
20.4 +/*
20.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
20.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
20.7 + *
20.8 + * This code is free software; you can redistribute it and/or modify it
20.9 + * under the terms of the GNU General Public License version 2 only, as
20.10 + * published by the Free Software Foundation. Oracle designates this
20.11 + * particular file as subject to the "Classpath" exception as provided
20.12 + * by Oracle in the LICENSE file that accompanied this code.
20.13 + *
20.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
20.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20.17 + * version 2 for more details (a copy is included in the LICENSE file that
20.18 + * accompanied this code).
20.19 + *
20.20 + * You should have received a copy of the GNU General Public License version
20.21 + * 2 along with this work; if not, write to the Free Software Foundation,
20.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20.23 + *
20.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20.25 + * or visit www.oracle.com if you need additional information or have any
20.26 + * questions.
20.27 + */
20.28 +
20.29 +package java.io;
20.30 +
20.31 +/**
20.32 + * Thrown when an instance is required to have a Serializable interface.
20.33 + * The serialization runtime or the class of the instance can throw
20.34 + * this exception. The argument should be the name of the class.
20.35 + *
20.36 + * @author unascribed
20.37 + * @since JDK1.1
20.38 + */
20.39 +public class NotSerializableException extends ObjectStreamException {
20.40 +
20.41 + private static final long serialVersionUID = 2906642554793891381L;
20.42 +
20.43 + /**
20.44 + * Constructs a NotSerializableException object with message string.
20.45 + *
20.46 + * @param classname Class of the instance being serialized/deserialized.
20.47 + */
20.48 + public NotSerializableException(String classname) {
20.49 + super(classname);
20.50 + }
20.51 +
20.52 + /**
20.53 + * Constructs a NotSerializableException object.
20.54 + */
20.55 + public NotSerializableException() {
20.56 + super();
20.57 + }
20.58 +}
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/emul/compact/src/main/java/java/io/ObjectInput.java Fri Feb 01 16:35:42 2013 +0100
21.3 @@ -0,0 +1,107 @@
21.4 +/*
21.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
21.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
21.7 + *
21.8 + * This code is free software; you can redistribute it and/or modify it
21.9 + * under the terms of the GNU General Public License version 2 only, as
21.10 + * published by the Free Software Foundation. Oracle designates this
21.11 + * particular file as subject to the "Classpath" exception as provided
21.12 + * by Oracle in the LICENSE file that accompanied this code.
21.13 + *
21.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
21.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21.17 + * version 2 for more details (a copy is included in the LICENSE file that
21.18 + * accompanied this code).
21.19 + *
21.20 + * You should have received a copy of the GNU General Public License version
21.21 + * 2 along with this work; if not, write to the Free Software Foundation,
21.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21.23 + *
21.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21.25 + * or visit www.oracle.com if you need additional information or have any
21.26 + * questions.
21.27 + */
21.28 +
21.29 +package java.io;
21.30 +
21.31 +/**
21.32 + * ObjectInput extends the DataInput interface to include the reading of
21.33 + * objects. DataInput includes methods for the input of primitive types,
21.34 + * ObjectInput extends that interface to include objects, arrays, and Strings.
21.35 + *
21.36 + * @author unascribed
21.37 + * @see java.io.InputStream
21.38 + * @see java.io.ObjectOutputStream
21.39 + * @see java.io.ObjectInputStream
21.40 + * @since JDK1.1
21.41 + */
21.42 +public interface ObjectInput extends DataInput, AutoCloseable {
21.43 + /**
21.44 + * Read and return an object. The class that implements this interface
21.45 + * defines where the object is "read" from.
21.46 + *
21.47 + * @return the object read from the stream
21.48 + * @exception java.lang.ClassNotFoundException If the class of a serialized
21.49 + * object cannot be found.
21.50 + * @exception IOException If any of the usual Input/Output
21.51 + * related exceptions occur.
21.52 + */
21.53 + public Object readObject()
21.54 + throws ClassNotFoundException, IOException;
21.55 +
21.56 + /**
21.57 + * Reads a byte of data. This method will block if no input is
21.58 + * available.
21.59 + * @return the byte read, or -1 if the end of the
21.60 + * stream is reached.
21.61 + * @exception IOException If an I/O error has occurred.
21.62 + */
21.63 + public int read() throws IOException;
21.64 +
21.65 + /**
21.66 + * Reads into an array of bytes. This method will
21.67 + * block until some input is available.
21.68 + * @param b the buffer into which the data is read
21.69 + * @return the actual number of bytes read, -1 is
21.70 + * returned when the end of the stream is reached.
21.71 + * @exception IOException If an I/O error has occurred.
21.72 + */
21.73 + public int read(byte b[]) throws IOException;
21.74 +
21.75 + /**
21.76 + * Reads into an array of bytes. This method will
21.77 + * block until some input is available.
21.78 + * @param b the buffer into which the data is read
21.79 + * @param off the start offset of the data
21.80 + * @param len the maximum number of bytes read
21.81 + * @return the actual number of bytes read, -1 is
21.82 + * returned when the end of the stream is reached.
21.83 + * @exception IOException If an I/O error has occurred.
21.84 + */
21.85 + public int read(byte b[], int off, int len) throws IOException;
21.86 +
21.87 + /**
21.88 + * Skips n bytes of input.
21.89 + * @param n the number of bytes to be skipped
21.90 + * @return the actual number of bytes skipped.
21.91 + * @exception IOException If an I/O error has occurred.
21.92 + */
21.93 + public long skip(long n) throws IOException;
21.94 +
21.95 + /**
21.96 + * Returns the number of bytes that can be read
21.97 + * without blocking.
21.98 + * @return the number of available bytes.
21.99 + * @exception IOException If an I/O error has occurred.
21.100 + */
21.101 + public int available() throws IOException;
21.102 +
21.103 + /**
21.104 + * Closes the input stream. Must be called
21.105 + * to release any resources associated with
21.106 + * the stream.
21.107 + * @exception IOException If an I/O error has occurred.
21.108 + */
21.109 + public void close() throws IOException;
21.110 +}
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
22.2 +++ b/emul/compact/src/main/java/java/io/ObjectInputStream.java Fri Feb 01 16:35:42 2013 +0100
22.3 @@ -0,0 +1,3508 @@
22.4 +/*
22.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
22.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
22.7 + *
22.8 + * This code is free software; you can redistribute it and/or modify it
22.9 + * under the terms of the GNU General Public License version 2 only, as
22.10 + * published by the Free Software Foundation. Oracle designates this
22.11 + * particular file as subject to the "Classpath" exception as provided
22.12 + * by Oracle in the LICENSE file that accompanied this code.
22.13 + *
22.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
22.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22.17 + * version 2 for more details (a copy is included in the LICENSE file that
22.18 + * accompanied this code).
22.19 + *
22.20 + * You should have received a copy of the GNU General Public License version
22.21 + * 2 along with this work; if not, write to the Free Software Foundation,
22.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22.23 + *
22.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22.25 + * or visit www.oracle.com if you need additional information or have any
22.26 + * questions.
22.27 + */
22.28 +
22.29 +package java.io;
22.30 +
22.31 +import java.io.ObjectStreamClass.WeakClassKey;
22.32 +import java.lang.ref.ReferenceQueue;
22.33 +import java.lang.reflect.Array;
22.34 +import java.lang.reflect.Modifier;
22.35 +import java.lang.reflect.Proxy;
22.36 +import java.security.AccessControlContext;
22.37 +import java.security.AccessController;
22.38 +import java.security.PrivilegedAction;
22.39 +import java.security.PrivilegedActionException;
22.40 +import java.security.PrivilegedExceptionAction;
22.41 +import java.util.Arrays;
22.42 +import java.util.HashMap;
22.43 +import java.util.concurrent.ConcurrentHashMap;
22.44 +import java.util.concurrent.ConcurrentMap;
22.45 +import java.util.concurrent.atomic.AtomicBoolean;
22.46 +import static java.io.ObjectStreamClass.processQueue;
22.47 +
22.48 +/**
22.49 + * An ObjectInputStream deserializes primitive data and objects previously
22.50 + * written using an ObjectOutputStream.
22.51 + *
22.52 + * <p>ObjectOutputStream and ObjectInputStream can provide an application with
22.53 + * persistent storage for graphs of objects when used with a FileOutputStream
22.54 + * and FileInputStream respectively. ObjectInputStream is used to recover
22.55 + * those objects previously serialized. Other uses include passing objects
22.56 + * between hosts using a socket stream or for marshaling and unmarshaling
22.57 + * arguments and parameters in a remote communication system.
22.58 + *
22.59 + * <p>ObjectInputStream ensures that the types of all objects in the graph
22.60 + * created from the stream match the classes present in the Java Virtual
22.61 + * Machine. Classes are loaded as required using the standard mechanisms.
22.62 + *
22.63 + * <p>Only objects that support the java.io.Serializable or
22.64 + * java.io.Externalizable interface can be read from streams.
22.65 + *
22.66 + * <p>The method <code>readObject</code> is used to read an object from the
22.67 + * stream. Java's safe casting should be used to get the desired type. In
22.68 + * Java, strings and arrays are objects and are treated as objects during
22.69 + * serialization. When read they need to be cast to the expected type.
22.70 + *
22.71 + * <p>Primitive data types can be read from the stream using the appropriate
22.72 + * method on DataInput.
22.73 + *
22.74 + * <p>The default deserialization mechanism for objects restores the contents
22.75 + * of each field to the value and type it had when it was written. Fields
22.76 + * declared as transient or static are ignored by the deserialization process.
22.77 + * References to other objects cause those objects to be read from the stream
22.78 + * as necessary. Graphs of objects are restored correctly using a reference
22.79 + * sharing mechanism. New objects are always allocated when deserializing,
22.80 + * which prevents existing objects from being overwritten.
22.81 + *
22.82 + * <p>Reading an object is analogous to running the constructors of a new
22.83 + * object. Memory is allocated for the object and initialized to zero (NULL).
22.84 + * No-arg constructors are invoked for the non-serializable classes and then
22.85 + * the fields of the serializable classes are restored from the stream starting
22.86 + * with the serializable class closest to java.lang.object and finishing with
22.87 + * the object's most specific class.
22.88 + *
22.89 + * <p>For example to read from a stream as written by the example in
22.90 + * ObjectOutputStream:
22.91 + * <br>
22.92 + * <pre>
22.93 + * FileInputStream fis = new FileInputStream("t.tmp");
22.94 + * ObjectInputStream ois = new ObjectInputStream(fis);
22.95 + *
22.96 + * int i = ois.readInt();
22.97 + * String today = (String) ois.readObject();
22.98 + * Date date = (Date) ois.readObject();
22.99 + *
22.100 + * ois.close();
22.101 + * </pre>
22.102 + *
22.103 + * <p>Classes control how they are serialized by implementing either the
22.104 + * java.io.Serializable or java.io.Externalizable interfaces.
22.105 + *
22.106 + * <p>Implementing the Serializable interface allows object serialization to
22.107 + * save and restore the entire state of the object and it allows classes to
22.108 + * evolve between the time the stream is written and the time it is read. It
22.109 + * automatically traverses references between objects, saving and restoring
22.110 + * entire graphs.
22.111 + *
22.112 + * <p>Serializable classes that require special handling during the
22.113 + * serialization and deserialization process should implement the following
22.114 + * methods:<p>
22.115 + *
22.116 + * <pre>
22.117 + * private void writeObject(java.io.ObjectOutputStream stream)
22.118 + * throws IOException;
22.119 + * private void readObject(java.io.ObjectInputStream stream)
22.120 + * throws IOException, ClassNotFoundException;
22.121 + * private void readObjectNoData()
22.122 + * throws ObjectStreamException;
22.123 + * </pre>
22.124 + *
22.125 + * <p>The readObject method is responsible for reading and restoring the state
22.126 + * of the object for its particular class using data written to the stream by
22.127 + * the corresponding writeObject method. The method does not need to concern
22.128 + * itself with the state belonging to its superclasses or subclasses. State is
22.129 + * restored by reading data from the ObjectInputStream for the individual
22.130 + * fields and making assignments to the appropriate fields of the object.
22.131 + * Reading primitive data types is supported by DataInput.
22.132 + *
22.133 + * <p>Any attempt to read object data which exceeds the boundaries of the
22.134 + * custom data written by the corresponding writeObject method will cause an
22.135 + * OptionalDataException to be thrown with an eof field value of true.
22.136 + * Non-object reads which exceed the end of the allotted data will reflect the
22.137 + * end of data in the same way that they would indicate the end of the stream:
22.138 + * bytewise reads will return -1 as the byte read or number of bytes read, and
22.139 + * primitive reads will throw EOFExceptions. If there is no corresponding
22.140 + * writeObject method, then the end of default serialized data marks the end of
22.141 + * the allotted data.
22.142 + *
22.143 + * <p>Primitive and object read calls issued from within a readExternal method
22.144 + * behave in the same manner--if the stream is already positioned at the end of
22.145 + * data written by the corresponding writeExternal method, object reads will
22.146 + * throw OptionalDataExceptions with eof set to true, bytewise reads will
22.147 + * return -1, and primitive reads will throw EOFExceptions. Note that this
22.148 + * behavior does not hold for streams written with the old
22.149 + * <code>ObjectStreamConstants.PROTOCOL_VERSION_1</code> protocol, in which the
22.150 + * end of data written by writeExternal methods is not demarcated, and hence
22.151 + * cannot be detected.
22.152 + *
22.153 + * <p>The readObjectNoData method is responsible for initializing the state of
22.154 + * the object for its particular class in the event that the serialization
22.155 + * stream does not list the given class as a superclass of the object being
22.156 + * deserialized. This may occur in cases where the receiving party uses a
22.157 + * different version of the deserialized instance's class than the sending
22.158 + * party, and the receiver's version extends classes that are not extended by
22.159 + * the sender's version. This may also occur if the serialization stream has
22.160 + * been tampered; hence, readObjectNoData is useful for initializing
22.161 + * deserialized objects properly despite a "hostile" or incomplete source
22.162 + * stream.
22.163 + *
22.164 + * <p>Serialization does not read or assign values to the fields of any object
22.165 + * that does not implement the java.io.Serializable interface. Subclasses of
22.166 + * Objects that are not serializable can be serializable. In this case the
22.167 + * non-serializable class must have a no-arg constructor to allow its fields to
22.168 + * be initialized. In this case it is the responsibility of the subclass to
22.169 + * save and restore the state of the non-serializable class. It is frequently
22.170 + * the case that the fields of that class are accessible (public, package, or
22.171 + * protected) or that there are get and set methods that can be used to restore
22.172 + * the state.
22.173 + *
22.174 + * <p>Any exception that occurs while deserializing an object will be caught by
22.175 + * the ObjectInputStream and abort the reading process.
22.176 + *
22.177 + * <p>Implementing the Externalizable interface allows the object to assume
22.178 + * complete control over the contents and format of the object's serialized
22.179 + * form. The methods of the Externalizable interface, writeExternal and
22.180 + * readExternal, are called to save and restore the objects state. When
22.181 + * implemented by a class they can write and read their own state using all of
22.182 + * the methods of ObjectOutput and ObjectInput. It is the responsibility of
22.183 + * the objects to handle any versioning that occurs.
22.184 + *
22.185 + * <p>Enum constants are deserialized differently than ordinary serializable or
22.186 + * externalizable objects. The serialized form of an enum constant consists
22.187 + * solely of its name; field values of the constant are not transmitted. To
22.188 + * deserialize an enum constant, ObjectInputStream reads the constant name from
22.189 + * the stream; the deserialized constant is then obtained by calling the static
22.190 + * method <code>Enum.valueOf(Class, String)</code> with the enum constant's
22.191 + * base type and the received constant name as arguments. Like other
22.192 + * serializable or externalizable objects, enum constants can function as the
22.193 + * targets of back references appearing subsequently in the serialization
22.194 + * stream. The process by which enum constants are deserialized cannot be
22.195 + * customized: any class-specific readObject, readObjectNoData, and readResolve
22.196 + * methods defined by enum types are ignored during deserialization.
22.197 + * Similarly, any serialPersistentFields or serialVersionUID field declarations
22.198 + * are also ignored--all enum types have a fixed serialVersionUID of 0L.
22.199 + *
22.200 + * @author Mike Warres
22.201 + * @author Roger Riggs
22.202 + * @see java.io.DataInput
22.203 + * @see java.io.ObjectOutputStream
22.204 + * @see java.io.Serializable
22.205 + * @see <a href="../../../platform/serialization/spec/input.html"> Object Serialization Specification, Section 3, Object Input Classes</a>
22.206 + * @since JDK1.1
22.207 + */
22.208 +public class ObjectInputStream
22.209 + extends InputStream implements ObjectInput, ObjectStreamConstants
22.210 +{
22.211 + /** handle value representing null */
22.212 + private static final int NULL_HANDLE = -1;
22.213 +
22.214 + /** marker for unshared objects in internal handle table */
22.215 + private static final Object unsharedMarker = new Object();
22.216 +
22.217 + /** table mapping primitive type names to corresponding class objects */
22.218 + private static final HashMap<String, Class<?>> primClasses
22.219 + = new HashMap<>(8, 1.0F);
22.220 + static {
22.221 + primClasses.put("boolean", boolean.class);
22.222 + primClasses.put("byte", byte.class);
22.223 + primClasses.put("char", char.class);
22.224 + primClasses.put("short", short.class);
22.225 + primClasses.put("int", int.class);
22.226 + primClasses.put("long", long.class);
22.227 + primClasses.put("float", float.class);
22.228 + primClasses.put("double", double.class);
22.229 + primClasses.put("void", void.class);
22.230 + }
22.231 +
22.232 + private static class Caches {
22.233 + /** cache of subclass security audit results */
22.234 + static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits =
22.235 + new ConcurrentHashMap<>();
22.236 +
22.237 + /** queue for WeakReferences to audited subclasses */
22.238 + static final ReferenceQueue<Class<?>> subclassAuditsQueue =
22.239 + new ReferenceQueue<>();
22.240 + }
22.241 +
22.242 + /** filter stream for handling block data conversion */
22.243 + private final BlockDataInputStream bin;
22.244 + /** validation callback list */
22.245 + private final ValidationList vlist;
22.246 + /** recursion depth */
22.247 + private int depth;
22.248 + /** whether stream is closed */
22.249 + private boolean closed;
22.250 +
22.251 + /** wire handle -> obj/exception map */
22.252 + private final HandleTable handles;
22.253 + /** scratch field for passing handle values up/down call stack */
22.254 + private int passHandle = NULL_HANDLE;
22.255 + /** flag set when at end of field value block with no TC_ENDBLOCKDATA */
22.256 + private boolean defaultDataEnd = false;
22.257 +
22.258 + /** buffer for reading primitive field values */
22.259 + private byte[] primVals;
22.260 +
22.261 + /** if true, invoke readObjectOverride() instead of readObject() */
22.262 + private final boolean enableOverride;
22.263 + /** if true, invoke resolveObject() */
22.264 + private boolean enableResolve;
22.265 +
22.266 + /**
22.267 + * Context during upcalls to class-defined readObject methods; holds
22.268 + * object currently being deserialized and descriptor for current class.
22.269 + * Null when not during readObject upcall.
22.270 + */
22.271 + private SerialCallbackContext curContext;
22.272 +
22.273 + /**
22.274 + * Creates an ObjectInputStream that reads from the specified InputStream.
22.275 + * A serialization stream header is read from the stream and verified.
22.276 + * This constructor will block until the corresponding ObjectOutputStream
22.277 + * has written and flushed the header.
22.278 + *
22.279 + * <p>If a security manager is installed, this constructor will check for
22.280 + * the "enableSubclassImplementation" SerializablePermission when invoked
22.281 + * directly or indirectly by the constructor of a subclass which overrides
22.282 + * the ObjectInputStream.readFields or ObjectInputStream.readUnshared
22.283 + * methods.
22.284 + *
22.285 + * @param in input stream to read from
22.286 + * @throws StreamCorruptedException if the stream header is incorrect
22.287 + * @throws IOException if an I/O error occurs while reading stream header
22.288 + * @throws SecurityException if untrusted subclass illegally overrides
22.289 + * security-sensitive methods
22.290 + * @throws NullPointerException if <code>in</code> is <code>null</code>
22.291 + * @see ObjectInputStream#ObjectInputStream()
22.292 + * @see ObjectInputStream#readFields()
22.293 + * @see ObjectOutputStream#ObjectOutputStream(OutputStream)
22.294 + */
22.295 + public ObjectInputStream(InputStream in) throws IOException {
22.296 + verifySubclass();
22.297 + bin = new BlockDataInputStream(in);
22.298 + handles = new HandleTable(10);
22.299 + vlist = new ValidationList();
22.300 + enableOverride = false;
22.301 + readStreamHeader();
22.302 + bin.setBlockDataMode(true);
22.303 + }
22.304 +
22.305 + /**
22.306 + * Provide a way for subclasses that are completely reimplementing
22.307 + * ObjectInputStream to not have to allocate private data just used by this
22.308 + * implementation of ObjectInputStream.
22.309 + *
22.310 + * <p>If there is a security manager installed, this method first calls the
22.311 + * security manager's <code>checkPermission</code> method with the
22.312 + * <code>SerializablePermission("enableSubclassImplementation")</code>
22.313 + * permission to ensure it's ok to enable subclassing.
22.314 + *
22.315 + * @throws SecurityException if a security manager exists and its
22.316 + * <code>checkPermission</code> method denies enabling
22.317 + * subclassing.
22.318 + * @see SecurityManager#checkPermission
22.319 + * @see java.io.SerializablePermission
22.320 + */
22.321 + protected ObjectInputStream() throws IOException, SecurityException {
22.322 + SecurityManager sm = System.getSecurityManager();
22.323 + if (sm != null) {
22.324 + sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
22.325 + }
22.326 + bin = null;
22.327 + handles = null;
22.328 + vlist = null;
22.329 + enableOverride = true;
22.330 + }
22.331 +
22.332 + /**
22.333 + * Read an object from the ObjectInputStream. The class of the object, the
22.334 + * signature of the class, and the values of the non-transient and
22.335 + * non-static fields of the class and all of its supertypes are read.
22.336 + * Default deserializing for a class can be overriden using the writeObject
22.337 + * and readObject methods. Objects referenced by this object are read
22.338 + * transitively so that a complete equivalent graph of objects is
22.339 + * reconstructed by readObject.
22.340 + *
22.341 + * <p>The root object is completely restored when all of its fields and the
22.342 + * objects it references are completely restored. At this point the object
22.343 + * validation callbacks are executed in order based on their registered
22.344 + * priorities. The callbacks are registered by objects (in the readObject
22.345 + * special methods) as they are individually restored.
22.346 + *
22.347 + * <p>Exceptions are thrown for problems with the InputStream and for
22.348 + * classes that should not be deserialized. All exceptions are fatal to
22.349 + * the InputStream and leave it in an indeterminate state; it is up to the
22.350 + * caller to ignore or recover the stream state.
22.351 + *
22.352 + * @throws ClassNotFoundException Class of a serialized object cannot be
22.353 + * found.
22.354 + * @throws InvalidClassException Something is wrong with a class used by
22.355 + * serialization.
22.356 + * @throws StreamCorruptedException Control information in the
22.357 + * stream is inconsistent.
22.358 + * @throws OptionalDataException Primitive data was found in the
22.359 + * stream instead of objects.
22.360 + * @throws IOException Any of the usual Input/Output related exceptions.
22.361 + */
22.362 + public final Object readObject()
22.363 + throws IOException, ClassNotFoundException
22.364 + {
22.365 + if (enableOverride) {
22.366 + return readObjectOverride();
22.367 + }
22.368 +
22.369 + // if nested read, passHandle contains handle of enclosing object
22.370 + int outerHandle = passHandle;
22.371 + try {
22.372 + Object obj = readObject0(false);
22.373 + handles.markDependency(outerHandle, passHandle);
22.374 + ClassNotFoundException ex = handles.lookupException(passHandle);
22.375 + if (ex != null) {
22.376 + throw ex;
22.377 + }
22.378 + if (depth == 0) {
22.379 + vlist.doCallbacks();
22.380 + }
22.381 + return obj;
22.382 + } finally {
22.383 + passHandle = outerHandle;
22.384 + if (closed && depth == 0) {
22.385 + clear();
22.386 + }
22.387 + }
22.388 + }
22.389 +
22.390 + /**
22.391 + * This method is called by trusted subclasses of ObjectOutputStream that
22.392 + * constructed ObjectOutputStream using the protected no-arg constructor.
22.393 + * The subclass is expected to provide an override method with the modifier
22.394 + * "final".
22.395 + *
22.396 + * @return the Object read from the stream.
22.397 + * @throws ClassNotFoundException Class definition of a serialized object
22.398 + * cannot be found.
22.399 + * @throws OptionalDataException Primitive data was found in the stream
22.400 + * instead of objects.
22.401 + * @throws IOException if I/O errors occurred while reading from the
22.402 + * underlying stream
22.403 + * @see #ObjectInputStream()
22.404 + * @see #readObject()
22.405 + * @since 1.2
22.406 + */
22.407 + protected Object readObjectOverride()
22.408 + throws IOException, ClassNotFoundException
22.409 + {
22.410 + return null;
22.411 + }
22.412 +
22.413 + /**
22.414 + * Reads an "unshared" object from the ObjectInputStream. This method is
22.415 + * identical to readObject, except that it prevents subsequent calls to
22.416 + * readObject and readUnshared from returning additional references to the
22.417 + * deserialized instance obtained via this call. Specifically:
22.418 + * <ul>
22.419 + * <li>If readUnshared is called to deserialize a back-reference (the
22.420 + * stream representation of an object which has been written
22.421 + * previously to the stream), an ObjectStreamException will be
22.422 + * thrown.
22.423 + *
22.424 + * <li>If readUnshared returns successfully, then any subsequent attempts
22.425 + * to deserialize back-references to the stream handle deserialized
22.426 + * by readUnshared will cause an ObjectStreamException to be thrown.
22.427 + * </ul>
22.428 + * Deserializing an object via readUnshared invalidates the stream handle
22.429 + * associated with the returned object. Note that this in itself does not
22.430 + * always guarantee that the reference returned by readUnshared is unique;
22.431 + * the deserialized object may define a readResolve method which returns an
22.432 + * object visible to other parties, or readUnshared may return a Class
22.433 + * object or enum constant obtainable elsewhere in the stream or through
22.434 + * external means. If the deserialized object defines a readResolve method
22.435 + * and the invocation of that method returns an array, then readUnshared
22.436 + * returns a shallow clone of that array; this guarantees that the returned
22.437 + * array object is unique and cannot be obtained a second time from an
22.438 + * invocation of readObject or readUnshared on the ObjectInputStream,
22.439 + * even if the underlying data stream has been manipulated.
22.440 + *
22.441 + * <p>ObjectInputStream subclasses which override this method can only be
22.442 + * constructed in security contexts possessing the
22.443 + * "enableSubclassImplementation" SerializablePermission; any attempt to
22.444 + * instantiate such a subclass without this permission will cause a
22.445 + * SecurityException to be thrown.
22.446 + *
22.447 + * @return reference to deserialized object
22.448 + * @throws ClassNotFoundException if class of an object to deserialize
22.449 + * cannot be found
22.450 + * @throws StreamCorruptedException if control information in the stream
22.451 + * is inconsistent
22.452 + * @throws ObjectStreamException if object to deserialize has already
22.453 + * appeared in stream
22.454 + * @throws OptionalDataException if primitive data is next in stream
22.455 + * @throws IOException if an I/O error occurs during deserialization
22.456 + * @since 1.4
22.457 + */
22.458 + public Object readUnshared() throws IOException, ClassNotFoundException {
22.459 + // if nested read, passHandle contains handle of enclosing object
22.460 + int outerHandle = passHandle;
22.461 + try {
22.462 + Object obj = readObject0(true);
22.463 + handles.markDependency(outerHandle, passHandle);
22.464 + ClassNotFoundException ex = handles.lookupException(passHandle);
22.465 + if (ex != null) {
22.466 + throw ex;
22.467 + }
22.468 + if (depth == 0) {
22.469 + vlist.doCallbacks();
22.470 + }
22.471 + return obj;
22.472 + } finally {
22.473 + passHandle = outerHandle;
22.474 + if (closed && depth == 0) {
22.475 + clear();
22.476 + }
22.477 + }
22.478 + }
22.479 +
22.480 + /**
22.481 + * Read the non-static and non-transient fields of the current class from
22.482 + * this stream. This may only be called from the readObject method of the
22.483 + * class being deserialized. It will throw the NotActiveException if it is
22.484 + * called otherwise.
22.485 + *
22.486 + * @throws ClassNotFoundException if the class of a serialized object
22.487 + * could not be found.
22.488 + * @throws IOException if an I/O error occurs.
22.489 + * @throws NotActiveException if the stream is not currently reading
22.490 + * objects.
22.491 + */
22.492 + public void defaultReadObject()
22.493 + throws IOException, ClassNotFoundException
22.494 + {
22.495 + if (curContext == null) {
22.496 + throw new NotActiveException("not in call to readObject");
22.497 + }
22.498 + Object curObj = curContext.getObj();
22.499 + ObjectStreamClass curDesc = curContext.getDesc();
22.500 + bin.setBlockDataMode(false);
22.501 + defaultReadFields(curObj, curDesc);
22.502 + bin.setBlockDataMode(true);
22.503 + if (!curDesc.hasWriteObjectData()) {
22.504 + /*
22.505 + * Fix for 4360508: since stream does not contain terminating
22.506 + * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
22.507 + * knows to simulate end-of-custom-data behavior.
22.508 + */
22.509 + defaultDataEnd = true;
22.510 + }
22.511 + ClassNotFoundException ex = handles.lookupException(passHandle);
22.512 + if (ex != null) {
22.513 + throw ex;
22.514 + }
22.515 + }
22.516 +
22.517 + /**
22.518 + * Reads the persistent fields from the stream and makes them available by
22.519 + * name.
22.520 + *
22.521 + * @return the <code>GetField</code> object representing the persistent
22.522 + * fields of the object being deserialized
22.523 + * @throws ClassNotFoundException if the class of a serialized object
22.524 + * could not be found.
22.525 + * @throws IOException if an I/O error occurs.
22.526 + * @throws NotActiveException if the stream is not currently reading
22.527 + * objects.
22.528 + * @since 1.2
22.529 + */
22.530 + public ObjectInputStream.GetField readFields()
22.531 + throws IOException, ClassNotFoundException
22.532 + {
22.533 + if (curContext == null) {
22.534 + throw new NotActiveException("not in call to readObject");
22.535 + }
22.536 + Object curObj = curContext.getObj();
22.537 + ObjectStreamClass curDesc = curContext.getDesc();
22.538 + bin.setBlockDataMode(false);
22.539 + GetFieldImpl getField = new GetFieldImpl(curDesc);
22.540 + getField.readFields();
22.541 + bin.setBlockDataMode(true);
22.542 + if (!curDesc.hasWriteObjectData()) {
22.543 + /*
22.544 + * Fix for 4360508: since stream does not contain terminating
22.545 + * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
22.546 + * knows to simulate end-of-custom-data behavior.
22.547 + */
22.548 + defaultDataEnd = true;
22.549 + }
22.550 +
22.551 + return getField;
22.552 + }
22.553 +
22.554 + /**
22.555 + * Register an object to be validated before the graph is returned. While
22.556 + * similar to resolveObject these validations are called after the entire
22.557 + * graph has been reconstituted. Typically, a readObject method will
22.558 + * register the object with the stream so that when all of the objects are
22.559 + * restored a final set of validations can be performed.
22.560 + *
22.561 + * @param obj the object to receive the validation callback.
22.562 + * @param prio controls the order of callbacks;zero is a good default.
22.563 + * Use higher numbers to be called back earlier, lower numbers for
22.564 + * later callbacks. Within a priority, callbacks are processed in
22.565 + * no particular order.
22.566 + * @throws NotActiveException The stream is not currently reading objects
22.567 + * so it is invalid to register a callback.
22.568 + * @throws InvalidObjectException The validation object is null.
22.569 + */
22.570 + public void registerValidation(ObjectInputValidation obj, int prio)
22.571 + throws NotActiveException, InvalidObjectException
22.572 + {
22.573 + if (depth == 0) {
22.574 + throw new NotActiveException("stream inactive");
22.575 + }
22.576 + vlist.register(obj, prio);
22.577 + }
22.578 +
22.579 + /**
22.580 + * Load the local class equivalent of the specified stream class
22.581 + * description. Subclasses may implement this method to allow classes to
22.582 + * be fetched from an alternate source.
22.583 + *
22.584 + * <p>The corresponding method in <code>ObjectOutputStream</code> is
22.585 + * <code>annotateClass</code>. This method will be invoked only once for
22.586 + * each unique class in the stream. This method can be implemented by
22.587 + * subclasses to use an alternate loading mechanism but must return a
22.588 + * <code>Class</code> object. Once returned, if the class is not an array
22.589 + * class, its serialVersionUID is compared to the serialVersionUID of the
22.590 + * serialized class, and if there is a mismatch, the deserialization fails
22.591 + * and an {@link InvalidClassException} is thrown.
22.592 + *
22.593 + * <p>The default implementation of this method in
22.594 + * <code>ObjectInputStream</code> returns the result of calling
22.595 + * <pre>
22.596 + * Class.forName(desc.getName(), false, loader)
22.597 + * </pre>
22.598 + * where <code>loader</code> is determined as follows: if there is a
22.599 + * method on the current thread's stack whose declaring class was
22.600 + * defined by a user-defined class loader (and was not a generated to
22.601 + * implement reflective invocations), then <code>loader</code> is class
22.602 + * loader corresponding to the closest such method to the currently
22.603 + * executing frame; otherwise, <code>loader</code> is
22.604 + * <code>null</code>. If this call results in a
22.605 + * <code>ClassNotFoundException</code> and the name of the passed
22.606 + * <code>ObjectStreamClass</code> instance is the Java language keyword
22.607 + * for a primitive type or void, then the <code>Class</code> object
22.608 + * representing that primitive type or void will be returned
22.609 + * (e.g., an <code>ObjectStreamClass</code> with the name
22.610 + * <code>"int"</code> will be resolved to <code>Integer.TYPE</code>).
22.611 + * Otherwise, the <code>ClassNotFoundException</code> will be thrown to
22.612 + * the caller of this method.
22.613 + *
22.614 + * @param desc an instance of class <code>ObjectStreamClass</code>
22.615 + * @return a <code>Class</code> object corresponding to <code>desc</code>
22.616 + * @throws IOException any of the usual Input/Output exceptions.
22.617 + * @throws ClassNotFoundException if class of a serialized object cannot
22.618 + * be found.
22.619 + */
22.620 + protected Class<?> resolveClass(ObjectStreamClass desc)
22.621 + throws IOException, ClassNotFoundException
22.622 + {
22.623 + String name = desc.getName();
22.624 + try {
22.625 + return Class.forName(name, false, latestUserDefinedLoader());
22.626 + } catch (ClassNotFoundException ex) {
22.627 + Class<?> cl = primClasses.get(name);
22.628 + if (cl != null) {
22.629 + return cl;
22.630 + } else {
22.631 + throw ex;
22.632 + }
22.633 + }
22.634 + }
22.635 +
22.636 + /**
22.637 + * Returns a proxy class that implements the interfaces named in a proxy
22.638 + * class descriptor; subclasses may implement this method to read custom
22.639 + * data from the stream along with the descriptors for dynamic proxy
22.640 + * classes, allowing them to use an alternate loading mechanism for the
22.641 + * interfaces and the proxy class.
22.642 + *
22.643 + * <p>This method is called exactly once for each unique proxy class
22.644 + * descriptor in the stream.
22.645 + *
22.646 + * <p>The corresponding method in <code>ObjectOutputStream</code> is
22.647 + * <code>annotateProxyClass</code>. For a given subclass of
22.648 + * <code>ObjectInputStream</code> that overrides this method, the
22.649 + * <code>annotateProxyClass</code> method in the corresponding subclass of
22.650 + * <code>ObjectOutputStream</code> must write any data or objects read by
22.651 + * this method.
22.652 + *
22.653 + * <p>The default implementation of this method in
22.654 + * <code>ObjectInputStream</code> returns the result of calling
22.655 + * <code>Proxy.getProxyClass</code> with the list of <code>Class</code>
22.656 + * objects for the interfaces that are named in the <code>interfaces</code>
22.657 + * parameter. The <code>Class</code> object for each interface name
22.658 + * <code>i</code> is the value returned by calling
22.659 + * <pre>
22.660 + * Class.forName(i, false, loader)
22.661 + * </pre>
22.662 + * where <code>loader</code> is that of the first non-<code>null</code>
22.663 + * class loader up the execution stack, or <code>null</code> if no
22.664 + * non-<code>null</code> class loaders are on the stack (the same class
22.665 + * loader choice used by the <code>resolveClass</code> method). Unless any
22.666 + * of the resolved interfaces are non-public, this same value of
22.667 + * <code>loader</code> is also the class loader passed to
22.668 + * <code>Proxy.getProxyClass</code>; if non-public interfaces are present,
22.669 + * their class loader is passed instead (if more than one non-public
22.670 + * interface class loader is encountered, an
22.671 + * <code>IllegalAccessError</code> is thrown).
22.672 + * If <code>Proxy.getProxyClass</code> throws an
22.673 + * <code>IllegalArgumentException</code>, <code>resolveProxyClass</code>
22.674 + * will throw a <code>ClassNotFoundException</code> containing the
22.675 + * <code>IllegalArgumentException</code>.
22.676 + *
22.677 + * @param interfaces the list of interface names that were
22.678 + * deserialized in the proxy class descriptor
22.679 + * @return a proxy class for the specified interfaces
22.680 + * @throws IOException any exception thrown by the underlying
22.681 + * <code>InputStream</code>
22.682 + * @throws ClassNotFoundException if the proxy class or any of the
22.683 + * named interfaces could not be found
22.684 + * @see ObjectOutputStream#annotateProxyClass(Class)
22.685 + * @since 1.3
22.686 + */
22.687 + protected Class<?> resolveProxyClass(String[] interfaces)
22.688 + throws IOException, ClassNotFoundException
22.689 + {
22.690 + ClassLoader latestLoader = latestUserDefinedLoader();
22.691 + ClassLoader nonPublicLoader = null;
22.692 + boolean hasNonPublicInterface = false;
22.693 +
22.694 + // define proxy in class loader of non-public interface(s), if any
22.695 + Class[] classObjs = new Class[interfaces.length];
22.696 + for (int i = 0; i < interfaces.length; i++) {
22.697 + Class cl = Class.forName(interfaces[i], false, latestLoader);
22.698 + if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
22.699 + if (hasNonPublicInterface) {
22.700 + if (nonPublicLoader != cl.getClassLoader()) {
22.701 + throw new IllegalAccessError(
22.702 + "conflicting non-public interface class loaders");
22.703 + }
22.704 + } else {
22.705 + nonPublicLoader = cl.getClassLoader();
22.706 + hasNonPublicInterface = true;
22.707 + }
22.708 + }
22.709 + classObjs[i] = cl;
22.710 + }
22.711 + try {
22.712 + return Proxy.getProxyClass(
22.713 + hasNonPublicInterface ? nonPublicLoader : latestLoader,
22.714 + classObjs);
22.715 + } catch (IllegalArgumentException e) {
22.716 + throw new ClassNotFoundException(null, e);
22.717 + }
22.718 + }
22.719 +
22.720 + /**
22.721 + * This method will allow trusted subclasses of ObjectInputStream to
22.722 + * substitute one object for another during deserialization. Replacing
22.723 + * objects is disabled until enableResolveObject is called. The
22.724 + * enableResolveObject method checks that the stream requesting to resolve
22.725 + * object can be trusted. Every reference to serializable objects is passed
22.726 + * to resolveObject. To insure that the private state of objects is not
22.727 + * unintentionally exposed only trusted streams may use resolveObject.
22.728 + *
22.729 + * <p>This method is called after an object has been read but before it is
22.730 + * returned from readObject. The default resolveObject method just returns
22.731 + * the same object.
22.732 + *
22.733 + * <p>When a subclass is replacing objects it must insure that the
22.734 + * substituted object is compatible with every field where the reference
22.735 + * will be stored. Objects whose type is not a subclass of the type of the
22.736 + * field or array element abort the serialization by raising an exception
22.737 + * and the object is not be stored.
22.738 + *
22.739 + * <p>This method is called only once when each object is first
22.740 + * encountered. All subsequent references to the object will be redirected
22.741 + * to the new object.
22.742 + *
22.743 + * @param obj object to be substituted
22.744 + * @return the substituted object
22.745 + * @throws IOException Any of the usual Input/Output exceptions.
22.746 + */
22.747 + protected Object resolveObject(Object obj) throws IOException {
22.748 + return obj;
22.749 + }
22.750 +
22.751 + /**
22.752 + * Enable the stream to allow objects read from the stream to be replaced.
22.753 + * When enabled, the resolveObject method is called for every object being
22.754 + * deserialized.
22.755 + *
22.756 + * <p>If <i>enable</i> is true, and there is a security manager installed,
22.757 + * this method first calls the security manager's
22.758 + * <code>checkPermission</code> method with the
22.759 + * <code>SerializablePermission("enableSubstitution")</code> permission to
22.760 + * ensure it's ok to enable the stream to allow objects read from the
22.761 + * stream to be replaced.
22.762 + *
22.763 + * @param enable true for enabling use of <code>resolveObject</code> for
22.764 + * every object being deserialized
22.765 + * @return the previous setting before this method was invoked
22.766 + * @throws SecurityException if a security manager exists and its
22.767 + * <code>checkPermission</code> method denies enabling the stream
22.768 + * to allow objects read from the stream to be replaced.
22.769 + * @see SecurityManager#checkPermission
22.770 + * @see java.io.SerializablePermission
22.771 + */
22.772 + protected boolean enableResolveObject(boolean enable)
22.773 + throws SecurityException
22.774 + {
22.775 + if (enable == enableResolve) {
22.776 + return enable;
22.777 + }
22.778 + if (enable) {
22.779 + SecurityManager sm = System.getSecurityManager();
22.780 + if (sm != null) {
22.781 + sm.checkPermission(SUBSTITUTION_PERMISSION);
22.782 + }
22.783 + }
22.784 + enableResolve = enable;
22.785 + return !enableResolve;
22.786 + }
22.787 +
22.788 + /**
22.789 + * The readStreamHeader method is provided to allow subclasses to read and
22.790 + * verify their own stream headers. It reads and verifies the magic number
22.791 + * and version number.
22.792 + *
22.793 + * @throws IOException if there are I/O errors while reading from the
22.794 + * underlying <code>InputStream</code>
22.795 + * @throws StreamCorruptedException if control information in the stream
22.796 + * is inconsistent
22.797 + */
22.798 + protected void readStreamHeader()
22.799 + throws IOException, StreamCorruptedException
22.800 + {
22.801 + short s0 = bin.readShort();
22.802 + short s1 = bin.readShort();
22.803 + if (s0 != STREAM_MAGIC || s1 != STREAM_VERSION) {
22.804 + throw new StreamCorruptedException(
22.805 + String.format("invalid stream header: %04X%04X", s0, s1));
22.806 + }
22.807 + }
22.808 +
22.809 + /**
22.810 + * Read a class descriptor from the serialization stream. This method is
22.811 + * called when the ObjectInputStream expects a class descriptor as the next
22.812 + * item in the serialization stream. Subclasses of ObjectInputStream may
22.813 + * override this method to read in class descriptors that have been written
22.814 + * in non-standard formats (by subclasses of ObjectOutputStream which have
22.815 + * overridden the <code>writeClassDescriptor</code> method). By default,
22.816 + * this method reads class descriptors according to the format defined in
22.817 + * the Object Serialization specification.
22.818 + *
22.819 + * @return the class descriptor read
22.820 + * @throws IOException If an I/O error has occurred.
22.821 + * @throws ClassNotFoundException If the Class of a serialized object used
22.822 + * in the class descriptor representation cannot be found
22.823 + * @see java.io.ObjectOutputStream#writeClassDescriptor(java.io.ObjectStreamClass)
22.824 + * @since 1.3
22.825 + */
22.826 + protected ObjectStreamClass readClassDescriptor()
22.827 + throws IOException, ClassNotFoundException
22.828 + {
22.829 + ObjectStreamClass desc = new ObjectStreamClass();
22.830 + desc.readNonProxy(this);
22.831 + return desc;
22.832 + }
22.833 +
22.834 + /**
22.835 + * Reads a byte of data. This method will block if no input is available.
22.836 + *
22.837 + * @return the byte read, or -1 if the end of the stream is reached.
22.838 + * @throws IOException If an I/O error has occurred.
22.839 + */
22.840 + public int read() throws IOException {
22.841 + return bin.read();
22.842 + }
22.843 +
22.844 + /**
22.845 + * Reads into an array of bytes. This method will block until some input
22.846 + * is available. Consider using java.io.DataInputStream.readFully to read
22.847 + * exactly 'length' bytes.
22.848 + *
22.849 + * @param buf the buffer into which the data is read
22.850 + * @param off the start offset of the data
22.851 + * @param len the maximum number of bytes read
22.852 + * @return the actual number of bytes read, -1 is returned when the end of
22.853 + * the stream is reached.
22.854 + * @throws IOException If an I/O error has occurred.
22.855 + * @see java.io.DataInputStream#readFully(byte[],int,int)
22.856 + */
22.857 + public int read(byte[] buf, int off, int len) throws IOException {
22.858 + if (buf == null) {
22.859 + throw new NullPointerException();
22.860 + }
22.861 + int endoff = off + len;
22.862 + if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
22.863 + throw new IndexOutOfBoundsException();
22.864 + }
22.865 + return bin.read(buf, off, len, false);
22.866 + }
22.867 +
22.868 + /**
22.869 + * Returns the number of bytes that can be read without blocking.
22.870 + *
22.871 + * @return the number of available bytes.
22.872 + * @throws IOException if there are I/O errors while reading from the
22.873 + * underlying <code>InputStream</code>
22.874 + */
22.875 + public int available() throws IOException {
22.876 + return bin.available();
22.877 + }
22.878 +
22.879 + /**
22.880 + * Closes the input stream. Must be called to release any resources
22.881 + * associated with the stream.
22.882 + *
22.883 + * @throws IOException If an I/O error has occurred.
22.884 + */
22.885 + public void close() throws IOException {
22.886 + /*
22.887 + * Even if stream already closed, propagate redundant close to
22.888 + * underlying stream to stay consistent with previous implementations.
22.889 + */
22.890 + closed = true;
22.891 + if (depth == 0) {
22.892 + clear();
22.893 + }
22.894 + bin.close();
22.895 + }
22.896 +
22.897 + /**
22.898 + * Reads in a boolean.
22.899 + *
22.900 + * @return the boolean read.
22.901 + * @throws EOFException If end of file is reached.
22.902 + * @throws IOException If other I/O error has occurred.
22.903 + */
22.904 + public boolean readBoolean() throws IOException {
22.905 + return bin.readBoolean();
22.906 + }
22.907 +
22.908 + /**
22.909 + * Reads an 8 bit byte.
22.910 + *
22.911 + * @return the 8 bit byte read.
22.912 + * @throws EOFException If end of file is reached.
22.913 + * @throws IOException If other I/O error has occurred.
22.914 + */
22.915 + public byte readByte() throws IOException {
22.916 + return bin.readByte();
22.917 + }
22.918 +
22.919 + /**
22.920 + * Reads an unsigned 8 bit byte.
22.921 + *
22.922 + * @return the 8 bit byte read.
22.923 + * @throws EOFException If end of file is reached.
22.924 + * @throws IOException If other I/O error has occurred.
22.925 + */
22.926 + public int readUnsignedByte() throws IOException {
22.927 + return bin.readUnsignedByte();
22.928 + }
22.929 +
22.930 + /**
22.931 + * Reads a 16 bit char.
22.932 + *
22.933 + * @return the 16 bit char read.
22.934 + * @throws EOFException If end of file is reached.
22.935 + * @throws IOException If other I/O error has occurred.
22.936 + */
22.937 + public char readChar() throws IOException {
22.938 + return bin.readChar();
22.939 + }
22.940 +
22.941 + /**
22.942 + * Reads a 16 bit short.
22.943 + *
22.944 + * @return the 16 bit short read.
22.945 + * @throws EOFException If end of file is reached.
22.946 + * @throws IOException If other I/O error has occurred.
22.947 + */
22.948 + public short readShort() throws IOException {
22.949 + return bin.readShort();
22.950 + }
22.951 +
22.952 + /**
22.953 + * Reads an unsigned 16 bit short.
22.954 + *
22.955 + * @return the 16 bit short read.
22.956 + * @throws EOFException If end of file is reached.
22.957 + * @throws IOException If other I/O error has occurred.
22.958 + */
22.959 + public int readUnsignedShort() throws IOException {
22.960 + return bin.readUnsignedShort();
22.961 + }
22.962 +
22.963 + /**
22.964 + * Reads a 32 bit int.
22.965 + *
22.966 + * @return the 32 bit integer read.
22.967 + * @throws EOFException If end of file is reached.
22.968 + * @throws IOException If other I/O error has occurred.
22.969 + */
22.970 + public int readInt() throws IOException {
22.971 + return bin.readInt();
22.972 + }
22.973 +
22.974 + /**
22.975 + * Reads a 64 bit long.
22.976 + *
22.977 + * @return the read 64 bit long.
22.978 + * @throws EOFException If end of file is reached.
22.979 + * @throws IOException If other I/O error has occurred.
22.980 + */
22.981 + public long readLong() throws IOException {
22.982 + return bin.readLong();
22.983 + }
22.984 +
22.985 + /**
22.986 + * Reads a 32 bit float.
22.987 + *
22.988 + * @return the 32 bit float read.
22.989 + * @throws EOFException If end of file is reached.
22.990 + * @throws IOException If other I/O error has occurred.
22.991 + */
22.992 + public float readFloat() throws IOException {
22.993 + return bin.readFloat();
22.994 + }
22.995 +
22.996 + /**
22.997 + * Reads a 64 bit double.
22.998 + *
22.999 + * @return the 64 bit double read.
22.1000 + * @throws EOFException If end of file is reached.
22.1001 + * @throws IOException If other I/O error has occurred.
22.1002 + */
22.1003 + public double readDouble() throws IOException {
22.1004 + return bin.readDouble();
22.1005 + }
22.1006 +
22.1007 + /**
22.1008 + * Reads bytes, blocking until all bytes are read.
22.1009 + *
22.1010 + * @param buf the buffer into which the data is read
22.1011 + * @throws EOFException If end of file is reached.
22.1012 + * @throws IOException If other I/O error has occurred.
22.1013 + */
22.1014 + public void readFully(byte[] buf) throws IOException {
22.1015 + bin.readFully(buf, 0, buf.length, false);
22.1016 + }
22.1017 +
22.1018 + /**
22.1019 + * Reads bytes, blocking until all bytes are read.
22.1020 + *
22.1021 + * @param buf the buffer into which the data is read
22.1022 + * @param off the start offset of the data
22.1023 + * @param len the maximum number of bytes to read
22.1024 + * @throws EOFException If end of file is reached.
22.1025 + * @throws IOException If other I/O error has occurred.
22.1026 + */
22.1027 + public void readFully(byte[] buf, int off, int len) throws IOException {
22.1028 + int endoff = off + len;
22.1029 + if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
22.1030 + throw new IndexOutOfBoundsException();
22.1031 + }
22.1032 + bin.readFully(buf, off, len, false);
22.1033 + }
22.1034 +
22.1035 + /**
22.1036 + * Skips bytes.
22.1037 + *
22.1038 + * @param len the number of bytes to be skipped
22.1039 + * @return the actual number of bytes skipped.
22.1040 + * @throws IOException If an I/O error has occurred.
22.1041 + */
22.1042 + public int skipBytes(int len) throws IOException {
22.1043 + return bin.skipBytes(len);
22.1044 + }
22.1045 +
22.1046 + /**
22.1047 + * Reads in a line that has been terminated by a \n, \r, \r\n or EOF.
22.1048 + *
22.1049 + * @return a String copy of the line.
22.1050 + * @throws IOException if there are I/O errors while reading from the
22.1051 + * underlying <code>InputStream</code>
22.1052 + * @deprecated This method does not properly convert bytes to characters.
22.1053 + * see DataInputStream for the details and alternatives.
22.1054 + */
22.1055 + @Deprecated
22.1056 + public String readLine() throws IOException {
22.1057 + return bin.readLine();
22.1058 + }
22.1059 +
22.1060 + /**
22.1061 + * Reads a String in
22.1062 + * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
22.1063 + * format.
22.1064 + *
22.1065 + * @return the String.
22.1066 + * @throws IOException if there are I/O errors while reading from the
22.1067 + * underlying <code>InputStream</code>
22.1068 + * @throws UTFDataFormatException if read bytes do not represent a valid
22.1069 + * modified UTF-8 encoding of a string
22.1070 + */
22.1071 + public String readUTF() throws IOException {
22.1072 + return bin.readUTF();
22.1073 + }
22.1074 +
22.1075 + /**
22.1076 + * Provide access to the persistent fields read from the input stream.
22.1077 + */
22.1078 + public static abstract class GetField {
22.1079 +
22.1080 + /**
22.1081 + * Get the ObjectStreamClass that describes the fields in the stream.
22.1082 + *
22.1083 + * @return the descriptor class that describes the serializable fields
22.1084 + */
22.1085 + public abstract ObjectStreamClass getObjectStreamClass();
22.1086 +
22.1087 + /**
22.1088 + * Return true if the named field is defaulted and has no value in this
22.1089 + * stream.
22.1090 + *
22.1091 + * @param name the name of the field
22.1092 + * @return true, if and only if the named field is defaulted
22.1093 + * @throws IOException if there are I/O errors while reading from
22.1094 + * the underlying <code>InputStream</code>
22.1095 + * @throws IllegalArgumentException if <code>name</code> does not
22.1096 + * correspond to a serializable field
22.1097 + */
22.1098 + public abstract boolean defaulted(String name) throws IOException;
22.1099 +
22.1100 + /**
22.1101 + * Get the value of the named boolean field from the persistent field.
22.1102 + *
22.1103 + * @param name the name of the field
22.1104 + * @param val the default value to use if <code>name</code> does not
22.1105 + * have a value
22.1106 + * @return the value of the named <code>boolean</code> field
22.1107 + * @throws IOException if there are I/O errors while reading from the
22.1108 + * underlying <code>InputStream</code>
22.1109 + * @throws IllegalArgumentException if type of <code>name</code> is
22.1110 + * not serializable or if the field type is incorrect
22.1111 + */
22.1112 + public abstract boolean get(String name, boolean val)
22.1113 + throws IOException;
22.1114 +
22.1115 + /**
22.1116 + * Get the value of the named byte field from the persistent field.
22.1117 + *
22.1118 + * @param name the name of the field
22.1119 + * @param val the default value to use if <code>name</code> does not
22.1120 + * have a value
22.1121 + * @return the value of the named <code>byte</code> field
22.1122 + * @throws IOException if there are I/O errors while reading from the
22.1123 + * underlying <code>InputStream</code>
22.1124 + * @throws IllegalArgumentException if type of <code>name</code> is
22.1125 + * not serializable or if the field type is incorrect
22.1126 + */
22.1127 + public abstract byte get(String name, byte val) throws IOException;
22.1128 +
22.1129 + /**
22.1130 + * Get the value of the named char field from the persistent field.
22.1131 + *
22.1132 + * @param name the name of the field
22.1133 + * @param val the default value to use if <code>name</code> does not
22.1134 + * have a value
22.1135 + * @return the value of the named <code>char</code> field
22.1136 + * @throws IOException if there are I/O errors while reading from the
22.1137 + * underlying <code>InputStream</code>
22.1138 + * @throws IllegalArgumentException if type of <code>name</code> is
22.1139 + * not serializable or if the field type is incorrect
22.1140 + */
22.1141 + public abstract char get(String name, char val) throws IOException;
22.1142 +
22.1143 + /**
22.1144 + * Get the value of the named short field from the persistent field.
22.1145 + *
22.1146 + * @param name the name of the field
22.1147 + * @param val the default value to use if <code>name</code> does not
22.1148 + * have a value
22.1149 + * @return the value of the named <code>short</code> field
22.1150 + * @throws IOException if there are I/O errors while reading from the
22.1151 + * underlying <code>InputStream</code>
22.1152 + * @throws IllegalArgumentException if type of <code>name</code> is
22.1153 + * not serializable or if the field type is incorrect
22.1154 + */
22.1155 + public abstract short get(String name, short val) throws IOException;
22.1156 +
22.1157 + /**
22.1158 + * Get the value of the named int field from the persistent field.
22.1159 + *
22.1160 + * @param name the name of the field
22.1161 + * @param val the default value to use if <code>name</code> does not
22.1162 + * have a value
22.1163 + * @return the value of the named <code>int</code> field
22.1164 + * @throws IOException if there are I/O errors while reading from the
22.1165 + * underlying <code>InputStream</code>
22.1166 + * @throws IllegalArgumentException if type of <code>name</code> is
22.1167 + * not serializable or if the field type is incorrect
22.1168 + */
22.1169 + public abstract int get(String name, int val) throws IOException;
22.1170 +
22.1171 + /**
22.1172 + * Get the value of the named long field from the persistent field.
22.1173 + *
22.1174 + * @param name the name of the field
22.1175 + * @param val the default value to use if <code>name</code> does not
22.1176 + * have a value
22.1177 + * @return the value of the named <code>long</code> field
22.1178 + * @throws IOException if there are I/O errors while reading from the
22.1179 + * underlying <code>InputStream</code>
22.1180 + * @throws IllegalArgumentException if type of <code>name</code> is
22.1181 + * not serializable or if the field type is incorrect
22.1182 + */
22.1183 + public abstract long get(String name, long val) throws IOException;
22.1184 +
22.1185 + /**
22.1186 + * Get the value of the named float field from the persistent field.
22.1187 + *
22.1188 + * @param name the name of the field
22.1189 + * @param val the default value to use if <code>name</code> does not
22.1190 + * have a value
22.1191 + * @return the value of the named <code>float</code> field
22.1192 + * @throws IOException if there are I/O errors while reading from the
22.1193 + * underlying <code>InputStream</code>
22.1194 + * @throws IllegalArgumentException if type of <code>name</code> is
22.1195 + * not serializable or if the field type is incorrect
22.1196 + */
22.1197 + public abstract float get(String name, float val) throws IOException;
22.1198 +
22.1199 + /**
22.1200 + * Get the value of the named double field from the persistent field.
22.1201 + *
22.1202 + * @param name the name of the field
22.1203 + * @param val the default value to use if <code>name</code> does not
22.1204 + * have a value
22.1205 + * @return the value of the named <code>double</code> field
22.1206 + * @throws IOException if there are I/O errors while reading from the
22.1207 + * underlying <code>InputStream</code>
22.1208 + * @throws IllegalArgumentException if type of <code>name</code> is
22.1209 + * not serializable or if the field type is incorrect
22.1210 + */
22.1211 + public abstract double get(String name, double val) throws IOException;
22.1212 +
22.1213 + /**
22.1214 + * Get the value of the named Object field from the persistent field.
22.1215 + *
22.1216 + * @param name the name of the field
22.1217 + * @param val the default value to use if <code>name</code> does not
22.1218 + * have a value
22.1219 + * @return the value of the named <code>Object</code> field
22.1220 + * @throws IOException if there are I/O errors while reading from the
22.1221 + * underlying <code>InputStream</code>
22.1222 + * @throws IllegalArgumentException if type of <code>name</code> is
22.1223 + * not serializable or if the field type is incorrect
22.1224 + */
22.1225 + public abstract Object get(String name, Object val) throws IOException;
22.1226 + }
22.1227 +
22.1228 + /**
22.1229 + * Verifies that this (possibly subclass) instance can be constructed
22.1230 + * without violating security constraints: the subclass must not override
22.1231 + * security-sensitive non-final methods, or else the
22.1232 + * "enableSubclassImplementation" SerializablePermission is checked.
22.1233 + */
22.1234 + private void verifySubclass() {
22.1235 + Class cl = getClass();
22.1236 + if (cl == ObjectInputStream.class) {
22.1237 + return;
22.1238 + }
22.1239 + SecurityManager sm = System.getSecurityManager();
22.1240 + if (sm == null) {
22.1241 + return;
22.1242 + }
22.1243 + processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
22.1244 + WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
22.1245 + Boolean result = Caches.subclassAudits.get(key);
22.1246 + if (result == null) {
22.1247 + result = Boolean.valueOf(auditSubclass(cl));
22.1248 + Caches.subclassAudits.putIfAbsent(key, result);
22.1249 + }
22.1250 + if (result.booleanValue()) {
22.1251 + return;
22.1252 + }
22.1253 + sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
22.1254 + }
22.1255 +
22.1256 + /**
22.1257 + * Performs reflective checks on given subclass to verify that it doesn't
22.1258 + * override security-sensitive non-final methods. Returns true if subclass
22.1259 + * is "safe", false otherwise.
22.1260 + */
22.1261 + private static boolean auditSubclass(final Class<?> subcl) {
22.1262 + Boolean result = AccessController.doPrivileged(
22.1263 + new PrivilegedAction<Boolean>() {
22.1264 + public Boolean run() {
22.1265 + for (Class<?> cl = subcl;
22.1266 + cl != ObjectInputStream.class;
22.1267 + cl = cl.getSuperclass())
22.1268 + {
22.1269 + try {
22.1270 + cl.getDeclaredMethod(
22.1271 + "readUnshared", (Class[]) null);
22.1272 + return Boolean.FALSE;
22.1273 + } catch (NoSuchMethodException ex) {
22.1274 + }
22.1275 + try {
22.1276 + cl.getDeclaredMethod("readFields", (Class[]) null);
22.1277 + return Boolean.FALSE;
22.1278 + } catch (NoSuchMethodException ex) {
22.1279 + }
22.1280 + }
22.1281 + return Boolean.TRUE;
22.1282 + }
22.1283 + }
22.1284 + );
22.1285 + return result.booleanValue();
22.1286 + }
22.1287 +
22.1288 + /**
22.1289 + * Clears internal data structures.
22.1290 + */
22.1291 + private void clear() {
22.1292 + handles.clear();
22.1293 + vlist.clear();
22.1294 + }
22.1295 +
22.1296 + /**
22.1297 + * Underlying readObject implementation.
22.1298 + */
22.1299 + private Object readObject0(boolean unshared) throws IOException {
22.1300 + boolean oldMode = bin.getBlockDataMode();
22.1301 + if (oldMode) {
22.1302 + int remain = bin.currentBlockRemaining();
22.1303 + if (remain > 0) {
22.1304 + throw new OptionalDataException(remain);
22.1305 + } else if (defaultDataEnd) {
22.1306 + /*
22.1307 + * Fix for 4360508: stream is currently at the end of a field
22.1308 + * value block written via default serialization; since there
22.1309 + * is no terminating TC_ENDBLOCKDATA tag, simulate
22.1310 + * end-of-custom-data behavior explicitly.
22.1311 + */
22.1312 + throw new OptionalDataException(true);
22.1313 + }
22.1314 + bin.setBlockDataMode(false);
22.1315 + }
22.1316 +
22.1317 + byte tc;
22.1318 + while ((tc = bin.peekByte()) == TC_RESET) {
22.1319 + bin.readByte();
22.1320 + handleReset();
22.1321 + }
22.1322 +
22.1323 + depth++;
22.1324 + try {
22.1325 + switch (tc) {
22.1326 + case TC_NULL:
22.1327 + return readNull();
22.1328 +
22.1329 + case TC_REFERENCE:
22.1330 + return readHandle(unshared);
22.1331 +
22.1332 + case TC_CLASS:
22.1333 + return readClass(unshared);
22.1334 +
22.1335 + case TC_CLASSDESC:
22.1336 + case TC_PROXYCLASSDESC:
22.1337 + return readClassDesc(unshared);
22.1338 +
22.1339 + case TC_STRING:
22.1340 + case TC_LONGSTRING:
22.1341 + return checkResolve(readString(unshared));
22.1342 +
22.1343 + case TC_ARRAY:
22.1344 + return checkResolve(readArray(unshared));
22.1345 +
22.1346 + case TC_ENUM:
22.1347 + return checkResolve(readEnum(unshared));
22.1348 +
22.1349 + case TC_OBJECT:
22.1350 + return checkResolve(readOrdinaryObject(unshared));
22.1351 +
22.1352 + case TC_EXCEPTION:
22.1353 + IOException ex = readFatalException();
22.1354 + throw new WriteAbortedException("writing aborted", ex);
22.1355 +
22.1356 + case TC_BLOCKDATA:
22.1357 + case TC_BLOCKDATALONG:
22.1358 + if (oldMode) {
22.1359 + bin.setBlockDataMode(true);
22.1360 + bin.peek(); // force header read
22.1361 + throw new OptionalDataException(
22.1362 + bin.currentBlockRemaining());
22.1363 + } else {
22.1364 + throw new StreamCorruptedException(
22.1365 + "unexpected block data");
22.1366 + }
22.1367 +
22.1368 + case TC_ENDBLOCKDATA:
22.1369 + if (oldMode) {
22.1370 + throw new OptionalDataException(true);
22.1371 + } else {
22.1372 + throw new StreamCorruptedException(
22.1373 + "unexpected end of block data");
22.1374 + }
22.1375 +
22.1376 + default:
22.1377 + throw new StreamCorruptedException(
22.1378 + String.format("invalid type code: %02X", tc));
22.1379 + }
22.1380 + } finally {
22.1381 + depth--;
22.1382 + bin.setBlockDataMode(oldMode);
22.1383 + }
22.1384 + }
22.1385 +
22.1386 + /**
22.1387 + * If resolveObject has been enabled and given object does not have an
22.1388 + * exception associated with it, calls resolveObject to determine
22.1389 + * replacement for object, and updates handle table accordingly. Returns
22.1390 + * replacement object, or echoes provided object if no replacement
22.1391 + * occurred. Expects that passHandle is set to given object's handle prior
22.1392 + * to calling this method.
22.1393 + */
22.1394 + private Object checkResolve(Object obj) throws IOException {
22.1395 + if (!enableResolve || handles.lookupException(passHandle) != null) {
22.1396 + return obj;
22.1397 + }
22.1398 + Object rep = resolveObject(obj);
22.1399 + if (rep != obj) {
22.1400 + handles.setObject(passHandle, rep);
22.1401 + }
22.1402 + return rep;
22.1403 + }
22.1404 +
22.1405 + /**
22.1406 + * Reads string without allowing it to be replaced in stream. Called from
22.1407 + * within ObjectStreamClass.read().
22.1408 + */
22.1409 + String readTypeString() throws IOException {
22.1410 + int oldHandle = passHandle;
22.1411 + try {
22.1412 + byte tc = bin.peekByte();
22.1413 + switch (tc) {
22.1414 + case TC_NULL:
22.1415 + return (String) readNull();
22.1416 +
22.1417 + case TC_REFERENCE:
22.1418 + return (String) readHandle(false);
22.1419 +
22.1420 + case TC_STRING:
22.1421 + case TC_LONGSTRING:
22.1422 + return readString(false);
22.1423 +
22.1424 + default:
22.1425 + throw new StreamCorruptedException(
22.1426 + String.format("invalid type code: %02X", tc));
22.1427 + }
22.1428 + } finally {
22.1429 + passHandle = oldHandle;
22.1430 + }
22.1431 + }
22.1432 +
22.1433 + /**
22.1434 + * Reads in null code, sets passHandle to NULL_HANDLE and returns null.
22.1435 + */
22.1436 + private Object readNull() throws IOException {
22.1437 + if (bin.readByte() != TC_NULL) {
22.1438 + throw new InternalError();
22.1439 + }
22.1440 + passHandle = NULL_HANDLE;
22.1441 + return null;
22.1442 + }
22.1443 +
22.1444 + /**
22.1445 + * Reads in object handle, sets passHandle to the read handle, and returns
22.1446 + * object associated with the handle.
22.1447 + */
22.1448 + private Object readHandle(boolean unshared) throws IOException {
22.1449 + if (bin.readByte() != TC_REFERENCE) {
22.1450 + throw new InternalError();
22.1451 + }
22.1452 + passHandle = bin.readInt() - baseWireHandle;
22.1453 + if (passHandle < 0 || passHandle >= handles.size()) {
22.1454 + throw new StreamCorruptedException(
22.1455 + String.format("invalid handle value: %08X", passHandle +
22.1456 + baseWireHandle));
22.1457 + }
22.1458 + if (unshared) {
22.1459 + // REMIND: what type of exception to throw here?
22.1460 + throw new InvalidObjectException(
22.1461 + "cannot read back reference as unshared");
22.1462 + }
22.1463 +
22.1464 + Object obj = handles.lookupObject(passHandle);
22.1465 + if (obj == unsharedMarker) {
22.1466 + // REMIND: what type of exception to throw here?
22.1467 + throw new InvalidObjectException(
22.1468 + "cannot read back reference to unshared object");
22.1469 + }
22.1470 + return obj;
22.1471 + }
22.1472 +
22.1473 + /**
22.1474 + * Reads in and returns class object. Sets passHandle to class object's
22.1475 + * assigned handle. Returns null if class is unresolvable (in which case a
22.1476 + * ClassNotFoundException will be associated with the class' handle in the
22.1477 + * handle table).
22.1478 + */
22.1479 + private Class readClass(boolean unshared) throws IOException {
22.1480 + if (bin.readByte() != TC_CLASS) {
22.1481 + throw new InternalError();
22.1482 + }
22.1483 + ObjectStreamClass desc = readClassDesc(false);
22.1484 + Class cl = desc.forClass();
22.1485 + passHandle = handles.assign(unshared ? unsharedMarker : cl);
22.1486 +
22.1487 + ClassNotFoundException resolveEx = desc.getResolveException();
22.1488 + if (resolveEx != null) {
22.1489 + handles.markException(passHandle, resolveEx);
22.1490 + }
22.1491 +
22.1492 + handles.finish(passHandle);
22.1493 + return cl;
22.1494 + }
22.1495 +
22.1496 + /**
22.1497 + * Reads in and returns (possibly null) class descriptor. Sets passHandle
22.1498 + * to class descriptor's assigned handle. If class descriptor cannot be
22.1499 + * resolved to a class in the local VM, a ClassNotFoundException is
22.1500 + * associated with the class descriptor's handle.
22.1501 + */
22.1502 + private ObjectStreamClass readClassDesc(boolean unshared)
22.1503 + throws IOException
22.1504 + {
22.1505 + byte tc = bin.peekByte();
22.1506 + switch (tc) {
22.1507 + case TC_NULL:
22.1508 + return (ObjectStreamClass) readNull();
22.1509 +
22.1510 + case TC_REFERENCE:
22.1511 + return (ObjectStreamClass) readHandle(unshared);
22.1512 +
22.1513 + case TC_PROXYCLASSDESC:
22.1514 + return readProxyDesc(unshared);
22.1515 +
22.1516 + case TC_CLASSDESC:
22.1517 + return readNonProxyDesc(unshared);
22.1518 +
22.1519 + default:
22.1520 + throw new StreamCorruptedException(
22.1521 + String.format("invalid type code: %02X", tc));
22.1522 + }
22.1523 + }
22.1524 +
22.1525 + /**
22.1526 + * Reads in and returns class descriptor for a dynamic proxy class. Sets
22.1527 + * passHandle to proxy class descriptor's assigned handle. If proxy class
22.1528 + * descriptor cannot be resolved to a class in the local VM, a
22.1529 + * ClassNotFoundException is associated with the descriptor's handle.
22.1530 + */
22.1531 + private ObjectStreamClass readProxyDesc(boolean unshared)
22.1532 + throws IOException
22.1533 + {
22.1534 + if (bin.readByte() != TC_PROXYCLASSDESC) {
22.1535 + throw new InternalError();
22.1536 + }
22.1537 +
22.1538 + ObjectStreamClass desc = new ObjectStreamClass();
22.1539 + int descHandle = handles.assign(unshared ? unsharedMarker : desc);
22.1540 + passHandle = NULL_HANDLE;
22.1541 +
22.1542 + int numIfaces = bin.readInt();
22.1543 + String[] ifaces = new String[numIfaces];
22.1544 + for (int i = 0; i < numIfaces; i++) {
22.1545 + ifaces[i] = bin.readUTF();
22.1546 + }
22.1547 +
22.1548 + Class cl = null;
22.1549 + ClassNotFoundException resolveEx = null;
22.1550 + bin.setBlockDataMode(true);
22.1551 + try {
22.1552 + if ((cl = resolveProxyClass(ifaces)) == null) {
22.1553 + resolveEx = new ClassNotFoundException("null class");
22.1554 + }
22.1555 + } catch (ClassNotFoundException ex) {
22.1556 + resolveEx = ex;
22.1557 + }
22.1558 + skipCustomData();
22.1559 +
22.1560 + desc.initProxy(cl, resolveEx, readClassDesc(false));
22.1561 +
22.1562 + handles.finish(descHandle);
22.1563 + passHandle = descHandle;
22.1564 + return desc;
22.1565 + }
22.1566 +
22.1567 + /**
22.1568 + * Reads in and returns class descriptor for a class that is not a dynamic
22.1569 + * proxy class. Sets passHandle to class descriptor's assigned handle. If
22.1570 + * class descriptor cannot be resolved to a class in the local VM, a
22.1571 + * ClassNotFoundException is associated with the descriptor's handle.
22.1572 + */
22.1573 + private ObjectStreamClass readNonProxyDesc(boolean unshared)
22.1574 + throws IOException
22.1575 + {
22.1576 + if (bin.readByte() != TC_CLASSDESC) {
22.1577 + throw new InternalError();
22.1578 + }
22.1579 +
22.1580 + ObjectStreamClass desc = new ObjectStreamClass();
22.1581 + int descHandle = handles.assign(unshared ? unsharedMarker : desc);
22.1582 + passHandle = NULL_HANDLE;
22.1583 +
22.1584 + ObjectStreamClass readDesc = null;
22.1585 + try {
22.1586 + readDesc = readClassDescriptor();
22.1587 + } catch (ClassNotFoundException ex) {
22.1588 + throw (IOException) new InvalidClassException(
22.1589 + "failed to read class descriptor").initCause(ex);
22.1590 + }
22.1591 +
22.1592 + Class cl = null;
22.1593 + ClassNotFoundException resolveEx = null;
22.1594 + bin.setBlockDataMode(true);
22.1595 + try {
22.1596 + if ((cl = resolveClass(readDesc)) == null) {
22.1597 + resolveEx = new ClassNotFoundException("null class");
22.1598 + }
22.1599 + } catch (ClassNotFoundException ex) {
22.1600 + resolveEx = ex;
22.1601 + }
22.1602 + skipCustomData();
22.1603 +
22.1604 + desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));
22.1605 +
22.1606 + handles.finish(descHandle);
22.1607 + passHandle = descHandle;
22.1608 + return desc;
22.1609 + }
22.1610 +
22.1611 + /**
22.1612 + * Reads in and returns new string. Sets passHandle to new string's
22.1613 + * assigned handle.
22.1614 + */
22.1615 + private String readString(boolean unshared) throws IOException {
22.1616 + String str;
22.1617 + byte tc = bin.readByte();
22.1618 + switch (tc) {
22.1619 + case TC_STRING:
22.1620 + str = bin.readUTF();
22.1621 + break;
22.1622 +
22.1623 + case TC_LONGSTRING:
22.1624 + str = bin.readLongUTF();
22.1625 + break;
22.1626 +
22.1627 + default:
22.1628 + throw new StreamCorruptedException(
22.1629 + String.format("invalid type code: %02X", tc));
22.1630 + }
22.1631 + passHandle = handles.assign(unshared ? unsharedMarker : str);
22.1632 + handles.finish(passHandle);
22.1633 + return str;
22.1634 + }
22.1635 +
22.1636 + /**
22.1637 + * Reads in and returns array object, or null if array class is
22.1638 + * unresolvable. Sets passHandle to array's assigned handle.
22.1639 + */
22.1640 + private Object readArray(boolean unshared) throws IOException {
22.1641 + if (bin.readByte() != TC_ARRAY) {
22.1642 + throw new InternalError();
22.1643 + }
22.1644 +
22.1645 + ObjectStreamClass desc = readClassDesc(false);
22.1646 + int len = bin.readInt();
22.1647 +
22.1648 + Object array = null;
22.1649 + Class cl, ccl = null;
22.1650 + if ((cl = desc.forClass()) != null) {
22.1651 + ccl = cl.getComponentType();
22.1652 + array = Array.newInstance(ccl, len);
22.1653 + }
22.1654 +
22.1655 + int arrayHandle = handles.assign(unshared ? unsharedMarker : array);
22.1656 + ClassNotFoundException resolveEx = desc.getResolveException();
22.1657 + if (resolveEx != null) {
22.1658 + handles.markException(arrayHandle, resolveEx);
22.1659 + }
22.1660 +
22.1661 + if (ccl == null) {
22.1662 + for (int i = 0; i < len; i++) {
22.1663 + readObject0(false);
22.1664 + }
22.1665 + } else if (ccl.isPrimitive()) {
22.1666 + if (ccl == Integer.TYPE) {
22.1667 + bin.readInts((int[]) array, 0, len);
22.1668 + } else if (ccl == Byte.TYPE) {
22.1669 + bin.readFully((byte[]) array, 0, len, true);
22.1670 + } else if (ccl == Long.TYPE) {
22.1671 + bin.readLongs((long[]) array, 0, len);
22.1672 + } else if (ccl == Float.TYPE) {
22.1673 + bin.readFloats((float[]) array, 0, len);
22.1674 + } else if (ccl == Double.TYPE) {
22.1675 + bin.readDoubles((double[]) array, 0, len);
22.1676 + } else if (ccl == Short.TYPE) {
22.1677 + bin.readShorts((short[]) array, 0, len);
22.1678 + } else if (ccl == Character.TYPE) {
22.1679 + bin.readChars((char[]) array, 0, len);
22.1680 + } else if (ccl == Boolean.TYPE) {
22.1681 + bin.readBooleans((boolean[]) array, 0, len);
22.1682 + } else {
22.1683 + throw new InternalError();
22.1684 + }
22.1685 + } else {
22.1686 + Object[] oa = (Object[]) array;
22.1687 + for (int i = 0; i < len; i++) {
22.1688 + oa[i] = readObject0(false);
22.1689 + handles.markDependency(arrayHandle, passHandle);
22.1690 + }
22.1691 + }
22.1692 +
22.1693 + handles.finish(arrayHandle);
22.1694 + passHandle = arrayHandle;
22.1695 + return array;
22.1696 + }
22.1697 +
22.1698 + /**
22.1699 + * Reads in and returns enum constant, or null if enum type is
22.1700 + * unresolvable. Sets passHandle to enum constant's assigned handle.
22.1701 + */
22.1702 + private Enum readEnum(boolean unshared) throws IOException {
22.1703 + if (bin.readByte() != TC_ENUM) {
22.1704 + throw new InternalError();
22.1705 + }
22.1706 +
22.1707 + ObjectStreamClass desc = readClassDesc(false);
22.1708 + if (!desc.isEnum()) {
22.1709 + throw new InvalidClassException("non-enum class: " + desc);
22.1710 + }
22.1711 +
22.1712 + int enumHandle = handles.assign(unshared ? unsharedMarker : null);
22.1713 + ClassNotFoundException resolveEx = desc.getResolveException();
22.1714 + if (resolveEx != null) {
22.1715 + handles.markException(enumHandle, resolveEx);
22.1716 + }
22.1717 +
22.1718 + String name = readString(false);
22.1719 + Enum en = null;
22.1720 + Class cl = desc.forClass();
22.1721 + if (cl != null) {
22.1722 + try {
22.1723 + en = Enum.valueOf(cl, name);
22.1724 + } catch (IllegalArgumentException ex) {
22.1725 + throw (IOException) new InvalidObjectException(
22.1726 + "enum constant " + name + " does not exist in " +
22.1727 + cl).initCause(ex);
22.1728 + }
22.1729 + if (!unshared) {
22.1730 + handles.setObject(enumHandle, en);
22.1731 + }
22.1732 + }
22.1733 +
22.1734 + handles.finish(enumHandle);
22.1735 + passHandle = enumHandle;
22.1736 + return en;
22.1737 + }
22.1738 +
22.1739 + /**
22.1740 + * Reads and returns "ordinary" (i.e., not a String, Class,
22.1741 + * ObjectStreamClass, array, or enum constant) object, or null if object's
22.1742 + * class is unresolvable (in which case a ClassNotFoundException will be
22.1743 + * associated with object's handle). Sets passHandle to object's assigned
22.1744 + * handle.
22.1745 + */
22.1746 + private Object readOrdinaryObject(boolean unshared)
22.1747 + throws IOException
22.1748 + {
22.1749 + if (bin.readByte() != TC_OBJECT) {
22.1750 + throw new InternalError();
22.1751 + }
22.1752 +
22.1753 + ObjectStreamClass desc = readClassDesc(false);
22.1754 + desc.checkDeserialize();
22.1755 +
22.1756 + Object obj;
22.1757 + try {
22.1758 + obj = desc.isInstantiable() ? desc.newInstance() : null;
22.1759 + } catch (Exception ex) {
22.1760 + throw (IOException) new InvalidClassException(
22.1761 + desc.forClass().getName(),
22.1762 + "unable to create instance").initCause(ex);
22.1763 + }
22.1764 +
22.1765 + passHandle = handles.assign(unshared ? unsharedMarker : obj);
22.1766 + ClassNotFoundException resolveEx = desc.getResolveException();
22.1767 + if (resolveEx != null) {
22.1768 + handles.markException(passHandle, resolveEx);
22.1769 + }
22.1770 +
22.1771 + if (desc.isExternalizable()) {
22.1772 + readExternalData((Externalizable) obj, desc);
22.1773 + } else {
22.1774 + readSerialData(obj, desc);
22.1775 + }
22.1776 +
22.1777 + handles.finish(passHandle);
22.1778 +
22.1779 + if (obj != null &&
22.1780 + handles.lookupException(passHandle) == null &&
22.1781 + desc.hasReadResolveMethod())
22.1782 + {
22.1783 + Object rep = desc.invokeReadResolve(obj);
22.1784 + if (unshared && rep.getClass().isArray()) {
22.1785 + rep = cloneArray(rep);
22.1786 + }
22.1787 + if (rep != obj) {
22.1788 + handles.setObject(passHandle, obj = rep);
22.1789 + }
22.1790 + }
22.1791 +
22.1792 + return obj;
22.1793 + }
22.1794 +
22.1795 + /**
22.1796 + * If obj is non-null, reads externalizable data by invoking readExternal()
22.1797 + * method of obj; otherwise, attempts to skip over externalizable data.
22.1798 + * Expects that passHandle is set to obj's handle before this method is
22.1799 + * called.
22.1800 + */
22.1801 + private void readExternalData(Externalizable obj, ObjectStreamClass desc)
22.1802 + throws IOException
22.1803 + {
22.1804 + SerialCallbackContext oldContext = curContext;
22.1805 + curContext = null;
22.1806 + try {
22.1807 + boolean blocked = desc.hasBlockExternalData();
22.1808 + if (blocked) {
22.1809 + bin.setBlockDataMode(true);
22.1810 + }
22.1811 + if (obj != null) {
22.1812 + try {
22.1813 + obj.readExternal(this);
22.1814 + } catch (ClassNotFoundException ex) {
22.1815 + /*
22.1816 + * In most cases, the handle table has already propagated
22.1817 + * a CNFException to passHandle at this point; this mark
22.1818 + * call is included to address cases where the readExternal
22.1819 + * method has cons'ed and thrown a new CNFException of its
22.1820 + * own.
22.1821 + */
22.1822 + handles.markException(passHandle, ex);
22.1823 + }
22.1824 + }
22.1825 + if (blocked) {
22.1826 + skipCustomData();
22.1827 + }
22.1828 + } finally {
22.1829 + curContext = oldContext;
22.1830 + }
22.1831 + /*
22.1832 + * At this point, if the externalizable data was not written in
22.1833 + * block-data form and either the externalizable class doesn't exist
22.1834 + * locally (i.e., obj == null) or readExternal() just threw a
22.1835 + * CNFException, then the stream is probably in an inconsistent state,
22.1836 + * since some (or all) of the externalizable data may not have been
22.1837 + * consumed. Since there's no "correct" action to take in this case,
22.1838 + * we mimic the behavior of past serialization implementations and
22.1839 + * blindly hope that the stream is in sync; if it isn't and additional
22.1840 + * externalizable data remains in the stream, a subsequent read will
22.1841 + * most likely throw a StreamCorruptedException.
22.1842 + */
22.1843 + }
22.1844 +
22.1845 + /**
22.1846 + * Reads (or attempts to skip, if obj is null or is tagged with a
22.1847 + * ClassNotFoundException) instance data for each serializable class of
22.1848 + * object in stream, from superclass to subclass. Expects that passHandle
22.1849 + * is set to obj's handle before this method is called.
22.1850 + */
22.1851 + private void readSerialData(Object obj, ObjectStreamClass desc)
22.1852 + throws IOException
22.1853 + {
22.1854 + ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
22.1855 + for (int i = 0; i < slots.length; i++) {
22.1856 + ObjectStreamClass slotDesc = slots[i].desc;
22.1857 +
22.1858 + if (slots[i].hasData) {
22.1859 + if (obj != null &&
22.1860 + slotDesc.hasReadObjectMethod() &&
22.1861 + handles.lookupException(passHandle) == null)
22.1862 + {
22.1863 + SerialCallbackContext oldContext = curContext;
22.1864 +
22.1865 + try {
22.1866 + curContext = new SerialCallbackContext(obj, slotDesc);
22.1867 +
22.1868 + bin.setBlockDataMode(true);
22.1869 + slotDesc.invokeReadObject(obj, this);
22.1870 + } catch (ClassNotFoundException ex) {
22.1871 + /*
22.1872 + * In most cases, the handle table has already
22.1873 + * propagated a CNFException to passHandle at this
22.1874 + * point; this mark call is included to address cases
22.1875 + * where the custom readObject method has cons'ed and
22.1876 + * thrown a new CNFException of its own.
22.1877 + */
22.1878 + handles.markException(passHandle, ex);
22.1879 + } finally {
22.1880 + curContext.setUsed();
22.1881 + curContext = oldContext;
22.1882 + }
22.1883 +
22.1884 + /*
22.1885 + * defaultDataEnd may have been set indirectly by custom
22.1886 + * readObject() method when calling defaultReadObject() or
22.1887 + * readFields(); clear it to restore normal read behavior.
22.1888 + */
22.1889 + defaultDataEnd = false;
22.1890 + } else {
22.1891 + defaultReadFields(obj, slotDesc);
22.1892 + }
22.1893 + if (slotDesc.hasWriteObjectData()) {
22.1894 + skipCustomData();
22.1895 + } else {
22.1896 + bin.setBlockDataMode(false);
22.1897 + }
22.1898 + } else {
22.1899 + if (obj != null &&
22.1900 + slotDesc.hasReadObjectNoDataMethod() &&
22.1901 + handles.lookupException(passHandle) == null)
22.1902 + {
22.1903 + slotDesc.invokeReadObjectNoData(obj);
22.1904 + }
22.1905 + }
22.1906 + }
22.1907 + }
22.1908 +
22.1909 + /**
22.1910 + * Skips over all block data and objects until TC_ENDBLOCKDATA is
22.1911 + * encountered.
22.1912 + */
22.1913 + private void skipCustomData() throws IOException {
22.1914 + int oldHandle = passHandle;
22.1915 + for (;;) {
22.1916 + if (bin.getBlockDataMode()) {
22.1917 + bin.skipBlockData();
22.1918 + bin.setBlockDataMode(false);
22.1919 + }
22.1920 + switch (bin.peekByte()) {
22.1921 + case TC_BLOCKDATA:
22.1922 + case TC_BLOCKDATALONG:
22.1923 + bin.setBlockDataMode(true);
22.1924 + break;
22.1925 +
22.1926 + case TC_ENDBLOCKDATA:
22.1927 + bin.readByte();
22.1928 + passHandle = oldHandle;
22.1929 + return;
22.1930 +
22.1931 + default:
22.1932 + readObject0(false);
22.1933 + break;
22.1934 + }
22.1935 + }
22.1936 + }
22.1937 +
22.1938 + /**
22.1939 + * Reads in values of serializable fields declared by given class
22.1940 + * descriptor. If obj is non-null, sets field values in obj. Expects that
22.1941 + * passHandle is set to obj's handle before this method is called.
22.1942 + */
22.1943 + private void defaultReadFields(Object obj, ObjectStreamClass desc)
22.1944 + throws IOException
22.1945 + {
22.1946 + // REMIND: is isInstance check necessary?
22.1947 + Class cl = desc.forClass();
22.1948 + if (cl != null && obj != null && !cl.isInstance(obj)) {
22.1949 + throw new ClassCastException();
22.1950 + }
22.1951 +
22.1952 + int primDataSize = desc.getPrimDataSize();
22.1953 + if (primVals == null || primVals.length < primDataSize) {
22.1954 + primVals = new byte[primDataSize];
22.1955 + }
22.1956 + bin.readFully(primVals, 0, primDataSize, false);
22.1957 + if (obj != null) {
22.1958 + desc.setPrimFieldValues(obj, primVals);
22.1959 + }
22.1960 +
22.1961 + int objHandle = passHandle;
22.1962 + ObjectStreamField[] fields = desc.getFields(false);
22.1963 + Object[] objVals = new Object[desc.getNumObjFields()];
22.1964 + int numPrimFields = fields.length - objVals.length;
22.1965 + for (int i = 0; i < objVals.length; i++) {
22.1966 + ObjectStreamField f = fields[numPrimFields + i];
22.1967 + objVals[i] = readObject0(f.isUnshared());
22.1968 + if (f.getField() != null) {
22.1969 + handles.markDependency(objHandle, passHandle);
22.1970 + }
22.1971 + }
22.1972 + if (obj != null) {
22.1973 + desc.setObjFieldValues(obj, objVals);
22.1974 + }
22.1975 + passHandle = objHandle;
22.1976 + }
22.1977 +
22.1978 + /**
22.1979 + * Reads in and returns IOException that caused serialization to abort.
22.1980 + * All stream state is discarded prior to reading in fatal exception. Sets
22.1981 + * passHandle to fatal exception's handle.
22.1982 + */
22.1983 + private IOException readFatalException() throws IOException {
22.1984 + if (bin.readByte() != TC_EXCEPTION) {
22.1985 + throw new InternalError();
22.1986 + }
22.1987 + clear();
22.1988 + return (IOException) readObject0(false);
22.1989 + }
22.1990 +
22.1991 + /**
22.1992 + * If recursion depth is 0, clears internal data structures; otherwise,
22.1993 + * throws a StreamCorruptedException. This method is called when a
22.1994 + * TC_RESET typecode is encountered.
22.1995 + */
22.1996 + private void handleReset() throws StreamCorruptedException {
22.1997 + if (depth > 0) {
22.1998 + throw new StreamCorruptedException(
22.1999 + "unexpected reset; recursion depth: " + depth);
22.2000 + }
22.2001 + clear();
22.2002 + }
22.2003 +
22.2004 + /**
22.2005 + * Converts specified span of bytes into float values.
22.2006 + */
22.2007 + // REMIND: remove once hotspot inlines Float.intBitsToFloat
22.2008 + private static native void bytesToFloats(byte[] src, int srcpos,
22.2009 + float[] dst, int dstpos,
22.2010 + int nfloats);
22.2011 +
22.2012 + /**
22.2013 + * Converts specified span of bytes into double values.
22.2014 + */
22.2015 + // REMIND: remove once hotspot inlines Double.longBitsToDouble
22.2016 + private static native void bytesToDoubles(byte[] src, int srcpos,
22.2017 + double[] dst, int dstpos,
22.2018 + int ndoubles);
22.2019 +
22.2020 + /**
22.2021 + * Returns the first non-null class loader (not counting class loaders of
22.2022 + * generated reflection implementation classes) up the execution stack, or
22.2023 + * null if only code from the null class loader is on the stack. This
22.2024 + * method is also called via reflection by the following RMI-IIOP class:
22.2025 + *
22.2026 + * com.sun.corba.se.internal.util.JDKClassLoader
22.2027 + *
22.2028 + * This method should not be removed or its signature changed without
22.2029 + * corresponding modifications to the above class.
22.2030 + */
22.2031 + // REMIND: change name to something more accurate?
22.2032 + private static native ClassLoader latestUserDefinedLoader();
22.2033 +
22.2034 + /**
22.2035 + * Default GetField implementation.
22.2036 + */
22.2037 + private class GetFieldImpl extends GetField {
22.2038 +
22.2039 + /** class descriptor describing serializable fields */
22.2040 + private final ObjectStreamClass desc;
22.2041 + /** primitive field values */
22.2042 + private final byte[] primVals;
22.2043 + /** object field values */
22.2044 + private final Object[] objVals;
22.2045 + /** object field value handles */
22.2046 + private final int[] objHandles;
22.2047 +
22.2048 + /**
22.2049 + * Creates GetFieldImpl object for reading fields defined in given
22.2050 + * class descriptor.
22.2051 + */
22.2052 + GetFieldImpl(ObjectStreamClass desc) {
22.2053 + this.desc = desc;
22.2054 + primVals = new byte[desc.getPrimDataSize()];
22.2055 + objVals = new Object[desc.getNumObjFields()];
22.2056 + objHandles = new int[objVals.length];
22.2057 + }
22.2058 +
22.2059 + public ObjectStreamClass getObjectStreamClass() {
22.2060 + return desc;
22.2061 + }
22.2062 +
22.2063 + public boolean defaulted(String name) throws IOException {
22.2064 + return (getFieldOffset(name, null) < 0);
22.2065 + }
22.2066 +
22.2067 + public boolean get(String name, boolean val) throws IOException {
22.2068 + int off = getFieldOffset(name, Boolean.TYPE);
22.2069 + return (off >= 0) ? Bits.getBoolean(primVals, off) : val;
22.2070 + }
22.2071 +
22.2072 + public byte get(String name, byte val) throws IOException {
22.2073 + int off = getFieldOffset(name, Byte.TYPE);
22.2074 + return (off >= 0) ? primVals[off] : val;
22.2075 + }
22.2076 +
22.2077 + public char get(String name, char val) throws IOException {
22.2078 + int off = getFieldOffset(name, Character.TYPE);
22.2079 + return (off >= 0) ? Bits.getChar(primVals, off) : val;
22.2080 + }
22.2081 +
22.2082 + public short get(String name, short val) throws IOException {
22.2083 + int off = getFieldOffset(name, Short.TYPE);
22.2084 + return (off >= 0) ? Bits.getShort(primVals, off) : val;
22.2085 + }
22.2086 +
22.2087 + public int get(String name, int val) throws IOException {
22.2088 + int off = getFieldOffset(name, Integer.TYPE);
22.2089 + return (off >= 0) ? Bits.getInt(primVals, off) : val;
22.2090 + }
22.2091 +
22.2092 + public float get(String name, float val) throws IOException {
22.2093 + int off = getFieldOffset(name, Float.TYPE);
22.2094 + return (off >= 0) ? Bits.getFloat(primVals, off) : val;
22.2095 + }
22.2096 +
22.2097 + public long get(String name, long val) throws IOException {
22.2098 + int off = getFieldOffset(name, Long.TYPE);
22.2099 + return (off >= 0) ? Bits.getLong(primVals, off) : val;
22.2100 + }
22.2101 +
22.2102 + public double get(String name, double val) throws IOException {
22.2103 + int off = getFieldOffset(name, Double.TYPE);
22.2104 + return (off >= 0) ? Bits.getDouble(primVals, off) : val;
22.2105 + }
22.2106 +
22.2107 + public Object get(String name, Object val) throws IOException {
22.2108 + int off = getFieldOffset(name, Object.class);
22.2109 + if (off >= 0) {
22.2110 + int objHandle = objHandles[off];
22.2111 + handles.markDependency(passHandle, objHandle);
22.2112 + return (handles.lookupException(objHandle) == null) ?
22.2113 + objVals[off] : null;
22.2114 + } else {
22.2115 + return val;
22.2116 + }
22.2117 + }
22.2118 +
22.2119 + /**
22.2120 + * Reads primitive and object field values from stream.
22.2121 + */
22.2122 + void readFields() throws IOException {
22.2123 + bin.readFully(primVals, 0, primVals.length, false);
22.2124 +
22.2125 + int oldHandle = passHandle;
22.2126 + ObjectStreamField[] fields = desc.getFields(false);
22.2127 + int numPrimFields = fields.length - objVals.length;
22.2128 + for (int i = 0; i < objVals.length; i++) {
22.2129 + objVals[i] =
22.2130 + readObject0(fields[numPrimFields + i].isUnshared());
22.2131 + objHandles[i] = passHandle;
22.2132 + }
22.2133 + passHandle = oldHandle;
22.2134 + }
22.2135 +
22.2136 + /**
22.2137 + * Returns offset of field with given name and type. A specified type
22.2138 + * of null matches all types, Object.class matches all non-primitive
22.2139 + * types, and any other non-null type matches assignable types only.
22.2140 + * If no matching field is found in the (incoming) class
22.2141 + * descriptor but a matching field is present in the associated local
22.2142 + * class descriptor, returns -1. Throws IllegalArgumentException if
22.2143 + * neither incoming nor local class descriptor contains a match.
22.2144 + */
22.2145 + private int getFieldOffset(String name, Class type) {
22.2146 + ObjectStreamField field = desc.getField(name, type);
22.2147 + if (field != null) {
22.2148 + return field.getOffset();
22.2149 + } else if (desc.getLocalDesc().getField(name, type) != null) {
22.2150 + return -1;
22.2151 + } else {
22.2152 + throw new IllegalArgumentException("no such field " + name +
22.2153 + " with type " + type);
22.2154 + }
22.2155 + }
22.2156 + }
22.2157 +
22.2158 + /**
22.2159 + * Prioritized list of callbacks to be performed once object graph has been
22.2160 + * completely deserialized.
22.2161 + */
22.2162 + private static class ValidationList {
22.2163 +
22.2164 + private static class Callback {
22.2165 + final ObjectInputValidation obj;
22.2166 + final int priority;
22.2167 + Callback next;
22.2168 + final AccessControlContext acc;
22.2169 +
22.2170 + Callback(ObjectInputValidation obj, int priority, Callback next,
22.2171 + AccessControlContext acc)
22.2172 + {
22.2173 + this.obj = obj;
22.2174 + this.priority = priority;
22.2175 + this.next = next;
22.2176 + this.acc = acc;
22.2177 + }
22.2178 + }
22.2179 +
22.2180 + /** linked list of callbacks */
22.2181 + private Callback list;
22.2182 +
22.2183 + /**
22.2184 + * Creates new (empty) ValidationList.
22.2185 + */
22.2186 + ValidationList() {
22.2187 + }
22.2188 +
22.2189 + /**
22.2190 + * Registers callback. Throws InvalidObjectException if callback
22.2191 + * object is null.
22.2192 + */
22.2193 + void register(ObjectInputValidation obj, int priority)
22.2194 + throws InvalidObjectException
22.2195 + {
22.2196 + if (obj == null) {
22.2197 + throw new InvalidObjectException("null callback");
22.2198 + }
22.2199 +
22.2200 + Callback prev = null, cur = list;
22.2201 + while (cur != null && priority < cur.priority) {
22.2202 + prev = cur;
22.2203 + cur = cur.next;
22.2204 + }
22.2205 + AccessControlContext acc = AccessController.getContext();
22.2206 + if (prev != null) {
22.2207 + prev.next = new Callback(obj, priority, cur, acc);
22.2208 + } else {
22.2209 + list = new Callback(obj, priority, list, acc);
22.2210 + }
22.2211 + }
22.2212 +
22.2213 + /**
22.2214 + * Invokes all registered callbacks and clears the callback list.
22.2215 + * Callbacks with higher priorities are called first; those with equal
22.2216 + * priorities may be called in any order. If any of the callbacks
22.2217 + * throws an InvalidObjectException, the callback process is terminated
22.2218 + * and the exception propagated upwards.
22.2219 + */
22.2220 + void doCallbacks() throws InvalidObjectException {
22.2221 + try {
22.2222 + while (list != null) {
22.2223 + AccessController.doPrivileged(
22.2224 + new PrivilegedExceptionAction<Void>()
22.2225 + {
22.2226 + public Void run() throws InvalidObjectException {
22.2227 + list.obj.validateObject();
22.2228 + return null;
22.2229 + }
22.2230 + }, list.acc);
22.2231 + list = list.next;
22.2232 + }
22.2233 + } catch (PrivilegedActionException ex) {
22.2234 + list = null;
22.2235 + throw (InvalidObjectException) ex.getException();
22.2236 + }
22.2237 + }
22.2238 +
22.2239 + /**
22.2240 + * Resets the callback list to its initial (empty) state.
22.2241 + */
22.2242 + public void clear() {
22.2243 + list = null;
22.2244 + }
22.2245 + }
22.2246 +
22.2247 + /**
22.2248 + * Input stream supporting single-byte peek operations.
22.2249 + */
22.2250 + private static class PeekInputStream extends InputStream {
22.2251 +
22.2252 + /** underlying stream */
22.2253 + private final InputStream in;
22.2254 + /** peeked byte */
22.2255 + private int peekb = -1;
22.2256 +
22.2257 + /**
22.2258 + * Creates new PeekInputStream on top of given underlying stream.
22.2259 + */
22.2260 + PeekInputStream(InputStream in) {
22.2261 + this.in = in;
22.2262 + }
22.2263 +
22.2264 + /**
22.2265 + * Peeks at next byte value in stream. Similar to read(), except
22.2266 + * that it does not consume the read value.
22.2267 + */
22.2268 + int peek() throws IOException {
22.2269 + return (peekb >= 0) ? peekb : (peekb = in.read());
22.2270 + }
22.2271 +
22.2272 + public int read() throws IOException {
22.2273 + if (peekb >= 0) {
22.2274 + int v = peekb;
22.2275 + peekb = -1;
22.2276 + return v;
22.2277 + } else {
22.2278 + return in.read();
22.2279 + }
22.2280 + }
22.2281 +
22.2282 + public int read(byte[] b, int off, int len) throws IOException {
22.2283 + if (len == 0) {
22.2284 + return 0;
22.2285 + } else if (peekb < 0) {
22.2286 + return in.read(b, off, len);
22.2287 + } else {
22.2288 + b[off++] = (byte) peekb;
22.2289 + len--;
22.2290 + peekb = -1;
22.2291 + int n = in.read(b, off, len);
22.2292 + return (n >= 0) ? (n + 1) : 1;
22.2293 + }
22.2294 + }
22.2295 +
22.2296 + void readFully(byte[] b, int off, int len) throws IOException {
22.2297 + int n = 0;
22.2298 + while (n < len) {
22.2299 + int count = read(b, off + n, len - n);
22.2300 + if (count < 0) {
22.2301 + throw new EOFException();
22.2302 + }
22.2303 + n += count;
22.2304 + }
22.2305 + }
22.2306 +
22.2307 + public long skip(long n) throws IOException {
22.2308 + if (n <= 0) {
22.2309 + return 0;
22.2310 + }
22.2311 + int skipped = 0;
22.2312 + if (peekb >= 0) {
22.2313 + peekb = -1;
22.2314 + skipped++;
22.2315 + n--;
22.2316 + }
22.2317 + return skipped + skip(n);
22.2318 + }
22.2319 +
22.2320 + public int available() throws IOException {
22.2321 + return in.available() + ((peekb >= 0) ? 1 : 0);
22.2322 + }
22.2323 +
22.2324 + public void close() throws IOException {
22.2325 + in.close();
22.2326 + }
22.2327 + }
22.2328 +
22.2329 + /**
22.2330 + * Input stream with two modes: in default mode, inputs data written in the
22.2331 + * same format as DataOutputStream; in "block data" mode, inputs data
22.2332 + * bracketed by block data markers (see object serialization specification
22.2333 + * for details). Buffering depends on block data mode: when in default
22.2334 + * mode, no data is buffered in advance; when in block data mode, all data
22.2335 + * for the current data block is read in at once (and buffered).
22.2336 + */
22.2337 + private class BlockDataInputStream
22.2338 + extends InputStream implements DataInput
22.2339 + {
22.2340 + /** maximum data block length */
22.2341 + private static final int MAX_BLOCK_SIZE = 1024;
22.2342 + /** maximum data block header length */
22.2343 + private static final int MAX_HEADER_SIZE = 5;
22.2344 + /** (tunable) length of char buffer (for reading strings) */
22.2345 + private static final int CHAR_BUF_SIZE = 256;
22.2346 + /** readBlockHeader() return value indicating header read may block */
22.2347 + private static final int HEADER_BLOCKED = -2;
22.2348 +
22.2349 + /** buffer for reading general/block data */
22.2350 + private final byte[] buf = new byte[MAX_BLOCK_SIZE];
22.2351 + /** buffer for reading block data headers */
22.2352 + private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
22.2353 + /** char buffer for fast string reads */
22.2354 + private final char[] cbuf = new char[CHAR_BUF_SIZE];
22.2355 +
22.2356 + /** block data mode */
22.2357 + private boolean blkmode = false;
22.2358 +
22.2359 + // block data state fields; values meaningful only when blkmode true
22.2360 + /** current offset into buf */
22.2361 + private int pos = 0;
22.2362 + /** end offset of valid data in buf, or -1 if no more block data */
22.2363 + private int end = -1;
22.2364 + /** number of bytes in current block yet to be read from stream */
22.2365 + private int unread = 0;
22.2366 +
22.2367 + /** underlying stream (wrapped in peekable filter stream) */
22.2368 + private final PeekInputStream in;
22.2369 + /** loopback stream (for data reads that span data blocks) */
22.2370 + private final DataInputStream din;
22.2371 +
22.2372 + /**
22.2373 + * Creates new BlockDataInputStream on top of given underlying stream.
22.2374 + * Block data mode is turned off by default.
22.2375 + */
22.2376 + BlockDataInputStream(InputStream in) {
22.2377 + this.in = new PeekInputStream(in);
22.2378 + din = new DataInputStream(this);
22.2379 + }
22.2380 +
22.2381 + /**
22.2382 + * Sets block data mode to the given mode (true == on, false == off)
22.2383 + * and returns the previous mode value. If the new mode is the same as
22.2384 + * the old mode, no action is taken. Throws IllegalStateException if
22.2385 + * block data mode is being switched from on to off while unconsumed
22.2386 + * block data is still present in the stream.
22.2387 + */
22.2388 + boolean setBlockDataMode(boolean newmode) throws IOException {
22.2389 + if (blkmode == newmode) {
22.2390 + return blkmode;
22.2391 + }
22.2392 + if (newmode) {
22.2393 + pos = 0;
22.2394 + end = 0;
22.2395 + unread = 0;
22.2396 + } else if (pos < end) {
22.2397 + throw new IllegalStateException("unread block data");
22.2398 + }
22.2399 + blkmode = newmode;
22.2400 + return !blkmode;
22.2401 + }
22.2402 +
22.2403 + /**
22.2404 + * Returns true if the stream is currently in block data mode, false
22.2405 + * otherwise.
22.2406 + */
22.2407 + boolean getBlockDataMode() {
22.2408 + return blkmode;
22.2409 + }
22.2410 +
22.2411 + /**
22.2412 + * If in block data mode, skips to the end of the current group of data
22.2413 + * blocks (but does not unset block data mode). If not in block data
22.2414 + * mode, throws an IllegalStateException.
22.2415 + */
22.2416 + void skipBlockData() throws IOException {
22.2417 + if (!blkmode) {
22.2418 + throw new IllegalStateException("not in block data mode");
22.2419 + }
22.2420 + while (end >= 0) {
22.2421 + refill();
22.2422 + }
22.2423 + }
22.2424 +
22.2425 + /**
22.2426 + * Attempts to read in the next block data header (if any). If
22.2427 + * canBlock is false and a full header cannot be read without possibly
22.2428 + * blocking, returns HEADER_BLOCKED, else if the next element in the
22.2429 + * stream is a block data header, returns the block data length
22.2430 + * specified by the header, else returns -1.
22.2431 + */
22.2432 + private int readBlockHeader(boolean canBlock) throws IOException {
22.2433 + if (defaultDataEnd) {
22.2434 + /*
22.2435 + * Fix for 4360508: stream is currently at the end of a field
22.2436 + * value block written via default serialization; since there
22.2437 + * is no terminating TC_ENDBLOCKDATA tag, simulate
22.2438 + * end-of-custom-data behavior explicitly.
22.2439 + */
22.2440 + return -1;
22.2441 + }
22.2442 + try {
22.2443 + for (;;) {
22.2444 + int avail = canBlock ? Integer.MAX_VALUE : in.available();
22.2445 + if (avail == 0) {
22.2446 + return HEADER_BLOCKED;
22.2447 + }
22.2448 +
22.2449 + int tc = in.peek();
22.2450 + switch (tc) {
22.2451 + case TC_BLOCKDATA:
22.2452 + if (avail < 2) {
22.2453 + return HEADER_BLOCKED;
22.2454 + }
22.2455 + in.readFully(hbuf, 0, 2);
22.2456 + return hbuf[1] & 0xFF;
22.2457 +
22.2458 + case TC_BLOCKDATALONG:
22.2459 + if (avail < 5) {
22.2460 + return HEADER_BLOCKED;
22.2461 + }
22.2462 + in.readFully(hbuf, 0, 5);
22.2463 + int len = Bits.getInt(hbuf, 1);
22.2464 + if (len < 0) {
22.2465 + throw new StreamCorruptedException(
22.2466 + "illegal block data header length: " +
22.2467 + len);
22.2468 + }
22.2469 + return len;
22.2470 +
22.2471 + /*
22.2472 + * TC_RESETs may occur in between data blocks.
22.2473 + * Unfortunately, this case must be parsed at a lower
22.2474 + * level than other typecodes, since primitive data
22.2475 + * reads may span data blocks separated by a TC_RESET.
22.2476 + */
22.2477 + case TC_RESET:
22.2478 + in.read();
22.2479 + handleReset();
22.2480 + break;
22.2481 +
22.2482 + default:
22.2483 + if (tc >= 0 && (tc < TC_BASE || tc > TC_MAX)) {
22.2484 + throw new StreamCorruptedException(
22.2485 + String.format("invalid type code: %02X",
22.2486 + tc));
22.2487 + }
22.2488 + return -1;
22.2489 + }
22.2490 + }
22.2491 + } catch (EOFException ex) {
22.2492 + throw new StreamCorruptedException(
22.2493 + "unexpected EOF while reading block data header");
22.2494 + }
22.2495 + }
22.2496 +
22.2497 + /**
22.2498 + * Refills internal buffer buf with block data. Any data in buf at the
22.2499 + * time of the call is considered consumed. Sets the pos, end, and
22.2500 + * unread fields to reflect the new amount of available block data; if
22.2501 + * the next element in the stream is not a data block, sets pos and
22.2502 + * unread to 0 and end to -1.
22.2503 + */
22.2504 + private void refill() throws IOException {
22.2505 + try {
22.2506 + do {
22.2507 + pos = 0;
22.2508 + if (unread > 0) {
22.2509 + int n =
22.2510 + in.read(buf, 0, Math.min(unread, MAX_BLOCK_SIZE));
22.2511 + if (n >= 0) {
22.2512 + end = n;
22.2513 + unread -= n;
22.2514 + } else {
22.2515 + throw new StreamCorruptedException(
22.2516 + "unexpected EOF in middle of data block");
22.2517 + }
22.2518 + } else {
22.2519 + int n = readBlockHeader(true);
22.2520 + if (n >= 0) {
22.2521 + end = 0;
22.2522 + unread = n;
22.2523 + } else {
22.2524 + end = -1;
22.2525 + unread = 0;
22.2526 + }
22.2527 + }
22.2528 + } while (pos == end);
22.2529 + } catch (IOException ex) {
22.2530 + pos = 0;
22.2531 + end = -1;
22.2532 + unread = 0;
22.2533 + throw ex;
22.2534 + }
22.2535 + }
22.2536 +
22.2537 + /**
22.2538 + * If in block data mode, returns the number of unconsumed bytes
22.2539 + * remaining in the current data block. If not in block data mode,
22.2540 + * throws an IllegalStateException.
22.2541 + */
22.2542 + int currentBlockRemaining() {
22.2543 + if (blkmode) {
22.2544 + return (end >= 0) ? (end - pos) + unread : 0;
22.2545 + } else {
22.2546 + throw new IllegalStateException();
22.2547 + }
22.2548 + }
22.2549 +
22.2550 + /**
22.2551 + * Peeks at (but does not consume) and returns the next byte value in
22.2552 + * the stream, or -1 if the end of the stream/block data (if in block
22.2553 + * data mode) has been reached.
22.2554 + */
22.2555 + int peek() throws IOException {
22.2556 + if (blkmode) {
22.2557 + if (pos == end) {
22.2558 + refill();
22.2559 + }
22.2560 + return (end >= 0) ? (buf[pos] & 0xFF) : -1;
22.2561 + } else {
22.2562 + return in.peek();
22.2563 + }
22.2564 + }
22.2565 +
22.2566 + /**
22.2567 + * Peeks at (but does not consume) and returns the next byte value in
22.2568 + * the stream, or throws EOFException if end of stream/block data has
22.2569 + * been reached.
22.2570 + */
22.2571 + byte peekByte() throws IOException {
22.2572 + int val = peek();
22.2573 + if (val < 0) {
22.2574 + throw new EOFException();
22.2575 + }
22.2576 + return (byte) val;
22.2577 + }
22.2578 +
22.2579 +
22.2580 + /* ----------------- generic input stream methods ------------------ */
22.2581 + /*
22.2582 + * The following methods are equivalent to their counterparts in
22.2583 + * InputStream, except that they interpret data block boundaries and
22.2584 + * read the requested data from within data blocks when in block data
22.2585 + * mode.
22.2586 + */
22.2587 +
22.2588 + public int read() throws IOException {
22.2589 + if (blkmode) {
22.2590 + if (pos == end) {
22.2591 + refill();
22.2592 + }
22.2593 + return (end >= 0) ? (buf[pos++] & 0xFF) : -1;
22.2594 + } else {
22.2595 + return in.read();
22.2596 + }
22.2597 + }
22.2598 +
22.2599 + public int read(byte[] b, int off, int len) throws IOException {
22.2600 + return read(b, off, len, false);
22.2601 + }
22.2602 +
22.2603 + public long skip(long len) throws IOException {
22.2604 + long remain = len;
22.2605 + while (remain > 0) {
22.2606 + if (blkmode) {
22.2607 + if (pos == end) {
22.2608 + refill();
22.2609 + }
22.2610 + if (end < 0) {
22.2611 + break;
22.2612 + }
22.2613 + int nread = (int) Math.min(remain, end - pos);
22.2614 + remain -= nread;
22.2615 + pos += nread;
22.2616 + } else {
22.2617 + int nread = (int) Math.min(remain, MAX_BLOCK_SIZE);
22.2618 + if ((nread = in.read(buf, 0, nread)) < 0) {
22.2619 + break;
22.2620 + }
22.2621 + remain -= nread;
22.2622 + }
22.2623 + }
22.2624 + return len - remain;
22.2625 + }
22.2626 +
22.2627 + public int available() throws IOException {
22.2628 + if (blkmode) {
22.2629 + if ((pos == end) && (unread == 0)) {
22.2630 + int n;
22.2631 + while ((n = readBlockHeader(false)) == 0) ;
22.2632 + switch (n) {
22.2633 + case HEADER_BLOCKED:
22.2634 + break;
22.2635 +
22.2636 + case -1:
22.2637 + pos = 0;
22.2638 + end = -1;
22.2639 + break;
22.2640 +
22.2641 + default:
22.2642 + pos = 0;
22.2643 + end = 0;
22.2644 + unread = n;
22.2645 + break;
22.2646 + }
22.2647 + }
22.2648 + // avoid unnecessary call to in.available() if possible
22.2649 + int unreadAvail = (unread > 0) ?
22.2650 + Math.min(in.available(), unread) : 0;
22.2651 + return (end >= 0) ? (end - pos) + unreadAvail : 0;
22.2652 + } else {
22.2653 + return in.available();
22.2654 + }
22.2655 + }
22.2656 +
22.2657 + public void close() throws IOException {
22.2658 + if (blkmode) {
22.2659 + pos = 0;
22.2660 + end = -1;
22.2661 + unread = 0;
22.2662 + }
22.2663 + in.close();
22.2664 + }
22.2665 +
22.2666 + /**
22.2667 + * Attempts to read len bytes into byte array b at offset off. Returns
22.2668 + * the number of bytes read, or -1 if the end of stream/block data has
22.2669 + * been reached. If copy is true, reads values into an intermediate
22.2670 + * buffer before copying them to b (to avoid exposing a reference to
22.2671 + * b).
22.2672 + */
22.2673 + int read(byte[] b, int off, int len, boolean copy) throws IOException {
22.2674 + if (len == 0) {
22.2675 + return 0;
22.2676 + } else if (blkmode) {
22.2677 + if (pos == end) {
22.2678 + refill();
22.2679 + }
22.2680 + if (end < 0) {
22.2681 + return -1;
22.2682 + }
22.2683 + int nread = Math.min(len, end - pos);
22.2684 + System.arraycopy(buf, pos, b, off, nread);
22.2685 + pos += nread;
22.2686 + return nread;
22.2687 + } else if (copy) {
22.2688 + int nread = in.read(buf, 0, Math.min(len, MAX_BLOCK_SIZE));
22.2689 + if (nread > 0) {
22.2690 + System.arraycopy(buf, 0, b, off, nread);
22.2691 + }
22.2692 + return nread;
22.2693 + } else {
22.2694 + return in.read(b, off, len);
22.2695 + }
22.2696 + }
22.2697 +
22.2698 + /* ----------------- primitive data input methods ------------------ */
22.2699 + /*
22.2700 + * The following methods are equivalent to their counterparts in
22.2701 + * DataInputStream, except that they interpret data block boundaries
22.2702 + * and read the requested data from within data blocks when in block
22.2703 + * data mode.
22.2704 + */
22.2705 +
22.2706 + public void readFully(byte[] b) throws IOException {
22.2707 + readFully(b, 0, b.length, false);
22.2708 + }
22.2709 +
22.2710 + public void readFully(byte[] b, int off, int len) throws IOException {
22.2711 + readFully(b, off, len, false);
22.2712 + }
22.2713 +
22.2714 + public void readFully(byte[] b, int off, int len, boolean copy)
22.2715 + throws IOException
22.2716 + {
22.2717 + while (len > 0) {
22.2718 + int n = read(b, off, len, copy);
22.2719 + if (n < 0) {
22.2720 + throw new EOFException();
22.2721 + }
22.2722 + off += n;
22.2723 + len -= n;
22.2724 + }
22.2725 + }
22.2726 +
22.2727 + public int skipBytes(int n) throws IOException {
22.2728 + return din.skipBytes(n);
22.2729 + }
22.2730 +
22.2731 + public boolean readBoolean() throws IOException {
22.2732 + int v = read();
22.2733 + if (v < 0) {
22.2734 + throw new EOFException();
22.2735 + }
22.2736 + return (v != 0);
22.2737 + }
22.2738 +
22.2739 + public byte readByte() throws IOException {
22.2740 + int v = read();
22.2741 + if (v < 0) {
22.2742 + throw new EOFException();
22.2743 + }
22.2744 + return (byte) v;
22.2745 + }
22.2746 +
22.2747 + public int readUnsignedByte() throws IOException {
22.2748 + int v = read();
22.2749 + if (v < 0) {
22.2750 + throw new EOFException();
22.2751 + }
22.2752 + return v;
22.2753 + }
22.2754 +
22.2755 + public char readChar() throws IOException {
22.2756 + if (!blkmode) {
22.2757 + pos = 0;
22.2758 + in.readFully(buf, 0, 2);
22.2759 + } else if (end - pos < 2) {
22.2760 + return din.readChar();
22.2761 + }
22.2762 + char v = Bits.getChar(buf, pos);
22.2763 + pos += 2;
22.2764 + return v;
22.2765 + }
22.2766 +
22.2767 + public short readShort() throws IOException {
22.2768 + if (!blkmode) {
22.2769 + pos = 0;
22.2770 + in.readFully(buf, 0, 2);
22.2771 + } else if (end - pos < 2) {
22.2772 + return din.readShort();
22.2773 + }
22.2774 + short v = Bits.getShort(buf, pos);
22.2775 + pos += 2;
22.2776 + return v;
22.2777 + }
22.2778 +
22.2779 + public int readUnsignedShort() throws IOException {
22.2780 + if (!blkmode) {
22.2781 + pos = 0;
22.2782 + in.readFully(buf, 0, 2);
22.2783 + } else if (end - pos < 2) {
22.2784 + return din.readUnsignedShort();
22.2785 + }
22.2786 + int v = Bits.getShort(buf, pos) & 0xFFFF;
22.2787 + pos += 2;
22.2788 + return v;
22.2789 + }
22.2790 +
22.2791 + public int readInt() throws IOException {
22.2792 + if (!blkmode) {
22.2793 + pos = 0;
22.2794 + in.readFully(buf, 0, 4);
22.2795 + } else if (end - pos < 4) {
22.2796 + return din.readInt();
22.2797 + }
22.2798 + int v = Bits.getInt(buf, pos);
22.2799 + pos += 4;
22.2800 + return v;
22.2801 + }
22.2802 +
22.2803 + public float readFloat() throws IOException {
22.2804 + if (!blkmode) {
22.2805 + pos = 0;
22.2806 + in.readFully(buf, 0, 4);
22.2807 + } else if (end - pos < 4) {
22.2808 + return din.readFloat();
22.2809 + }
22.2810 + float v = Bits.getFloat(buf, pos);
22.2811 + pos += 4;
22.2812 + return v;
22.2813 + }
22.2814 +
22.2815 + public long readLong() throws IOException {
22.2816 + if (!blkmode) {
22.2817 + pos = 0;
22.2818 + in.readFully(buf, 0, 8);
22.2819 + } else if (end - pos < 8) {
22.2820 + return din.readLong();
22.2821 + }
22.2822 + long v = Bits.getLong(buf, pos);
22.2823 + pos += 8;
22.2824 + return v;
22.2825 + }
22.2826 +
22.2827 + public double readDouble() throws IOException {
22.2828 + if (!blkmode) {
22.2829 + pos = 0;
22.2830 + in.readFully(buf, 0, 8);
22.2831 + } else if (end - pos < 8) {
22.2832 + return din.readDouble();
22.2833 + }
22.2834 + double v = Bits.getDouble(buf, pos);
22.2835 + pos += 8;
22.2836 + return v;
22.2837 + }
22.2838 +
22.2839 + public String readUTF() throws IOException {
22.2840 + return readUTFBody(readUnsignedShort());
22.2841 + }
22.2842 +
22.2843 + public String readLine() throws IOException {
22.2844 + return din.readLine(); // deprecated, not worth optimizing
22.2845 + }
22.2846 +
22.2847 + /* -------------- primitive data array input methods --------------- */
22.2848 + /*
22.2849 + * The following methods read in spans of primitive data values.
22.2850 + * Though equivalent to calling the corresponding primitive read
22.2851 + * methods repeatedly, these methods are optimized for reading groups
22.2852 + * of primitive data values more efficiently.
22.2853 + */
22.2854 +
22.2855 + void readBooleans(boolean[] v, int off, int len) throws IOException {
22.2856 + int stop, endoff = off + len;
22.2857 + while (off < endoff) {
22.2858 + if (!blkmode) {
22.2859 + int span = Math.min(endoff - off, MAX_BLOCK_SIZE);
22.2860 + in.readFully(buf, 0, span);
22.2861 + stop = off + span;
22.2862 + pos = 0;
22.2863 + } else if (end - pos < 1) {
22.2864 + v[off++] = din.readBoolean();
22.2865 + continue;
22.2866 + } else {
22.2867 + stop = Math.min(endoff, off + end - pos);
22.2868 + }
22.2869 +
22.2870 + while (off < stop) {
22.2871 + v[off++] = Bits.getBoolean(buf, pos++);
22.2872 + }
22.2873 + }
22.2874 + }
22.2875 +
22.2876 + void readChars(char[] v, int off, int len) throws IOException {
22.2877 + int stop, endoff = off + len;
22.2878 + while (off < endoff) {
22.2879 + if (!blkmode) {
22.2880 + int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
22.2881 + in.readFully(buf, 0, span << 1);
22.2882 + stop = off + span;
22.2883 + pos = 0;
22.2884 + } else if (end - pos < 2) {
22.2885 + v[off++] = din.readChar();
22.2886 + continue;
22.2887 + } else {
22.2888 + stop = Math.min(endoff, off + ((end - pos) >> 1));
22.2889 + }
22.2890 +
22.2891 + while (off < stop) {
22.2892 + v[off++] = Bits.getChar(buf, pos);
22.2893 + pos += 2;
22.2894 + }
22.2895 + }
22.2896 + }
22.2897 +
22.2898 + void readShorts(short[] v, int off, int len) throws IOException {
22.2899 + int stop, endoff = off + len;
22.2900 + while (off < endoff) {
22.2901 + if (!blkmode) {
22.2902 + int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
22.2903 + in.readFully(buf, 0, span << 1);
22.2904 + stop = off + span;
22.2905 + pos = 0;
22.2906 + } else if (end - pos < 2) {
22.2907 + v[off++] = din.readShort();
22.2908 + continue;
22.2909 + } else {
22.2910 + stop = Math.min(endoff, off + ((end - pos) >> 1));
22.2911 + }
22.2912 +
22.2913 + while (off < stop) {
22.2914 + v[off++] = Bits.getShort(buf, pos);
22.2915 + pos += 2;
22.2916 + }
22.2917 + }
22.2918 + }
22.2919 +
22.2920 + void readInts(int[] v, int off, int len) throws IOException {
22.2921 + int stop, endoff = off + len;
22.2922 + while (off < endoff) {
22.2923 + if (!blkmode) {
22.2924 + int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
22.2925 + in.readFully(buf, 0, span << 2);
22.2926 + stop = off + span;
22.2927 + pos = 0;
22.2928 + } else if (end - pos < 4) {
22.2929 + v[off++] = din.readInt();
22.2930 + continue;
22.2931 + } else {
22.2932 + stop = Math.min(endoff, off + ((end - pos) >> 2));
22.2933 + }
22.2934 +
22.2935 + while (off < stop) {
22.2936 + v[off++] = Bits.getInt(buf, pos);
22.2937 + pos += 4;
22.2938 + }
22.2939 + }
22.2940 + }
22.2941 +
22.2942 + void readFloats(float[] v, int off, int len) throws IOException {
22.2943 + int span, endoff = off + len;
22.2944 + while (off < endoff) {
22.2945 + if (!blkmode) {
22.2946 + span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
22.2947 + in.readFully(buf, 0, span << 2);
22.2948 + pos = 0;
22.2949 + } else if (end - pos < 4) {
22.2950 + v[off++] = din.readFloat();
22.2951 + continue;
22.2952 + } else {
22.2953 + span = Math.min(endoff - off, ((end - pos) >> 2));
22.2954 + }
22.2955 +
22.2956 + bytesToFloats(buf, pos, v, off, span);
22.2957 + off += span;
22.2958 + pos += span << 2;
22.2959 + }
22.2960 + }
22.2961 +
22.2962 + void readLongs(long[] v, int off, int len) throws IOException {
22.2963 + int stop, endoff = off + len;
22.2964 + while (off < endoff) {
22.2965 + if (!blkmode) {
22.2966 + int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
22.2967 + in.readFully(buf, 0, span << 3);
22.2968 + stop = off + span;
22.2969 + pos = 0;
22.2970 + } else if (end - pos < 8) {
22.2971 + v[off++] = din.readLong();
22.2972 + continue;
22.2973 + } else {
22.2974 + stop = Math.min(endoff, off + ((end - pos) >> 3));
22.2975 + }
22.2976 +
22.2977 + while (off < stop) {
22.2978 + v[off++] = Bits.getLong(buf, pos);
22.2979 + pos += 8;
22.2980 + }
22.2981 + }
22.2982 + }
22.2983 +
22.2984 + void readDoubles(double[] v, int off, int len) throws IOException {
22.2985 + int span, endoff = off + len;
22.2986 + while (off < endoff) {
22.2987 + if (!blkmode) {
22.2988 + span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
22.2989 + in.readFully(buf, 0, span << 3);
22.2990 + pos = 0;
22.2991 + } else if (end - pos < 8) {
22.2992 + v[off++] = din.readDouble();
22.2993 + continue;
22.2994 + } else {
22.2995 + span = Math.min(endoff - off, ((end - pos) >> 3));
22.2996 + }
22.2997 +
22.2998 + bytesToDoubles(buf, pos, v, off, span);
22.2999 + off += span;
22.3000 + pos += span << 3;
22.3001 + }
22.3002 + }
22.3003 +
22.3004 + /**
22.3005 + * Reads in string written in "long" UTF format. "Long" UTF format is
22.3006 + * identical to standard UTF, except that it uses an 8 byte header
22.3007 + * (instead of the standard 2 bytes) to convey the UTF encoding length.
22.3008 + */
22.3009 + String readLongUTF() throws IOException {
22.3010 + return readUTFBody(readLong());
22.3011 + }
22.3012 +
22.3013 + /**
22.3014 + * Reads in the "body" (i.e., the UTF representation minus the 2-byte
22.3015 + * or 8-byte length header) of a UTF encoding, which occupies the next
22.3016 + * utflen bytes.
22.3017 + */
22.3018 + private String readUTFBody(long utflen) throws IOException {
22.3019 + StringBuilder sbuf = new StringBuilder();
22.3020 + if (!blkmode) {
22.3021 + end = pos = 0;
22.3022 + }
22.3023 +
22.3024 + while (utflen > 0) {
22.3025 + int avail = end - pos;
22.3026 + if (avail >= 3 || (long) avail == utflen) {
22.3027 + utflen -= readUTFSpan(sbuf, utflen);
22.3028 + } else {
22.3029 + if (blkmode) {
22.3030 + // near block boundary, read one byte at a time
22.3031 + utflen -= readUTFChar(sbuf, utflen);
22.3032 + } else {
22.3033 + // shift and refill buffer manually
22.3034 + if (avail > 0) {
22.3035 + System.arraycopy(buf, pos, buf, 0, avail);
22.3036 + }
22.3037 + pos = 0;
22.3038 + end = (int) Math.min(MAX_BLOCK_SIZE, utflen);
22.3039 + in.readFully(buf, avail, end - avail);
22.3040 + }
22.3041 + }
22.3042 + }
22.3043 +
22.3044 + return sbuf.toString();
22.3045 + }
22.3046 +
22.3047 + /**
22.3048 + * Reads span of UTF-encoded characters out of internal buffer
22.3049 + * (starting at offset pos and ending at or before offset end),
22.3050 + * consuming no more than utflen bytes. Appends read characters to
22.3051 + * sbuf. Returns the number of bytes consumed.
22.3052 + */
22.3053 + private long readUTFSpan(StringBuilder sbuf, long utflen)
22.3054 + throws IOException
22.3055 + {
22.3056 + int cpos = 0;
22.3057 + int start = pos;
22.3058 + int avail = Math.min(end - pos, CHAR_BUF_SIZE);
22.3059 + // stop short of last char unless all of utf bytes in buffer
22.3060 + int stop = pos + ((utflen > avail) ? avail - 2 : (int) utflen);
22.3061 + boolean outOfBounds = false;
22.3062 +
22.3063 + try {
22.3064 + while (pos < stop) {
22.3065 + int b1, b2, b3;
22.3066 + b1 = buf[pos++] & 0xFF;
22.3067 + switch (b1 >> 4) {
22.3068 + case 0:
22.3069 + case 1:
22.3070 + case 2:
22.3071 + case 3:
22.3072 + case 4:
22.3073 + case 5:
22.3074 + case 6:
22.3075 + case 7: // 1 byte format: 0xxxxxxx
22.3076 + cbuf[cpos++] = (char) b1;
22.3077 + break;
22.3078 +
22.3079 + case 12:
22.3080 + case 13: // 2 byte format: 110xxxxx 10xxxxxx
22.3081 + b2 = buf[pos++];
22.3082 + if ((b2 & 0xC0) != 0x80) {
22.3083 + throw new UTFDataFormatException();
22.3084 + }
22.3085 + cbuf[cpos++] = (char) (((b1 & 0x1F) << 6) |
22.3086 + ((b2 & 0x3F) << 0));
22.3087 + break;
22.3088 +
22.3089 + case 14: // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
22.3090 + b3 = buf[pos + 1];
22.3091 + b2 = buf[pos + 0];
22.3092 + pos += 2;
22.3093 + if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
22.3094 + throw new UTFDataFormatException();
22.3095 + }
22.3096 + cbuf[cpos++] = (char) (((b1 & 0x0F) << 12) |
22.3097 + ((b2 & 0x3F) << 6) |
22.3098 + ((b3 & 0x3F) << 0));
22.3099 + break;
22.3100 +
22.3101 + default: // 10xx xxxx, 1111 xxxx
22.3102 + throw new UTFDataFormatException();
22.3103 + }
22.3104 + }
22.3105 + } catch (ArrayIndexOutOfBoundsException ex) {
22.3106 + outOfBounds = true;
22.3107 + } finally {
22.3108 + if (outOfBounds || (pos - start) > utflen) {
22.3109 + /*
22.3110 + * Fix for 4450867: if a malformed utf char causes the
22.3111 + * conversion loop to scan past the expected end of the utf
22.3112 + * string, only consume the expected number of utf bytes.
22.3113 + */
22.3114 + pos = start + (int) utflen;
22.3115 + throw new UTFDataFormatException();
22.3116 + }
22.3117 + }
22.3118 +
22.3119 + sbuf.append(cbuf, 0, cpos);
22.3120 + return pos - start;
22.3121 + }
22.3122 +
22.3123 + /**
22.3124 + * Reads in single UTF-encoded character one byte at a time, appends
22.3125 + * the character to sbuf, and returns the number of bytes consumed.
22.3126 + * This method is used when reading in UTF strings written in block
22.3127 + * data mode to handle UTF-encoded characters which (potentially)
22.3128 + * straddle block-data boundaries.
22.3129 + */
22.3130 + private int readUTFChar(StringBuilder sbuf, long utflen)
22.3131 + throws IOException
22.3132 + {
22.3133 + int b1, b2, b3;
22.3134 + b1 = readByte() & 0xFF;
22.3135 + switch (b1 >> 4) {
22.3136 + case 0:
22.3137 + case 1:
22.3138 + case 2:
22.3139 + case 3:
22.3140 + case 4:
22.3141 + case 5:
22.3142 + case 6:
22.3143 + case 7: // 1 byte format: 0xxxxxxx
22.3144 + sbuf.append((char) b1);
22.3145 + return 1;
22.3146 +
22.3147 + case 12:
22.3148 + case 13: // 2 byte format: 110xxxxx 10xxxxxx
22.3149 + if (utflen < 2) {
22.3150 + throw new UTFDataFormatException();
22.3151 + }
22.3152 + b2 = readByte();
22.3153 + if ((b2 & 0xC0) != 0x80) {
22.3154 + throw new UTFDataFormatException();
22.3155 + }
22.3156 + sbuf.append((char) (((b1 & 0x1F) << 6) |
22.3157 + ((b2 & 0x3F) << 0)));
22.3158 + return 2;
22.3159 +
22.3160 + case 14: // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
22.3161 + if (utflen < 3) {
22.3162 + if (utflen == 2) {
22.3163 + readByte(); // consume remaining byte
22.3164 + }
22.3165 + throw new UTFDataFormatException();
22.3166 + }
22.3167 + b2 = readByte();
22.3168 + b3 = readByte();
22.3169 + if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
22.3170 + throw new UTFDataFormatException();
22.3171 + }
22.3172 + sbuf.append((char) (((b1 & 0x0F) << 12) |
22.3173 + ((b2 & 0x3F) << 6) |
22.3174 + ((b3 & 0x3F) << 0)));
22.3175 + return 3;
22.3176 +
22.3177 + default: // 10xx xxxx, 1111 xxxx
22.3178 + throw new UTFDataFormatException();
22.3179 + }
22.3180 + }
22.3181 + }
22.3182 +
22.3183 + /**
22.3184 + * Unsynchronized table which tracks wire handle to object mappings, as
22.3185 + * well as ClassNotFoundExceptions associated with deserialized objects.
22.3186 + * This class implements an exception-propagation algorithm for
22.3187 + * determining which objects should have ClassNotFoundExceptions associated
22.3188 + * with them, taking into account cycles and discontinuities (e.g., skipped
22.3189 + * fields) in the object graph.
22.3190 + *
22.3191 + * <p>General use of the table is as follows: during deserialization, a
22.3192 + * given object is first assigned a handle by calling the assign method.
22.3193 + * This method leaves the assigned handle in an "open" state, wherein
22.3194 + * dependencies on the exception status of other handles can be registered
22.3195 + * by calling the markDependency method, or an exception can be directly
22.3196 + * associated with the handle by calling markException. When a handle is
22.3197 + * tagged with an exception, the HandleTable assumes responsibility for
22.3198 + * propagating the exception to any other objects which depend
22.3199 + * (transitively) on the exception-tagged object.
22.3200 + *
22.3201 + * <p>Once all exception information/dependencies for the handle have been
22.3202 + * registered, the handle should be "closed" by calling the finish method
22.3203 + * on it. The act of finishing a handle allows the exception propagation
22.3204 + * algorithm to aggressively prune dependency links, lessening the
22.3205 + * performance/memory impact of exception tracking.
22.3206 + *
22.3207 + * <p>Note that the exception propagation algorithm used depends on handles
22.3208 + * being assigned/finished in LIFO order; however, for simplicity as well
22.3209 + * as memory conservation, it does not enforce this constraint.
22.3210 + */
22.3211 + // REMIND: add full description of exception propagation algorithm?
22.3212 + private static class HandleTable {
22.3213 +
22.3214 + /* status codes indicating whether object has associated exception */
22.3215 + private static final byte STATUS_OK = 1;
22.3216 + private static final byte STATUS_UNKNOWN = 2;
22.3217 + private static final byte STATUS_EXCEPTION = 3;
22.3218 +
22.3219 + /** array mapping handle -> object status */
22.3220 + byte[] status;
22.3221 + /** array mapping handle -> object/exception (depending on status) */
22.3222 + Object[] entries;
22.3223 + /** array mapping handle -> list of dependent handles (if any) */
22.3224 + HandleList[] deps;
22.3225 + /** lowest unresolved dependency */
22.3226 + int lowDep = -1;
22.3227 + /** number of handles in table */
22.3228 + int size = 0;
22.3229 +
22.3230 + /**
22.3231 + * Creates handle table with the given initial capacity.
22.3232 + */
22.3233 + HandleTable(int initialCapacity) {
22.3234 + status = new byte[initialCapacity];
22.3235 + entries = new Object[initialCapacity];
22.3236 + deps = new HandleList[initialCapacity];
22.3237 + }
22.3238 +
22.3239 + /**
22.3240 + * Assigns next available handle to given object, and returns assigned
22.3241 + * handle. Once object has been completely deserialized (and all
22.3242 + * dependencies on other objects identified), the handle should be
22.3243 + * "closed" by passing it to finish().
22.3244 + */
22.3245 + int assign(Object obj) {
22.3246 + if (size >= entries.length) {
22.3247 + grow();
22.3248 + }
22.3249 + status[size] = STATUS_UNKNOWN;
22.3250 + entries[size] = obj;
22.3251 + return size++;
22.3252 + }
22.3253 +
22.3254 + /**
22.3255 + * Registers a dependency (in exception status) of one handle on
22.3256 + * another. The dependent handle must be "open" (i.e., assigned, but
22.3257 + * not finished yet). No action is taken if either dependent or target
22.3258 + * handle is NULL_HANDLE.
22.3259 + */
22.3260 + void markDependency(int dependent, int target) {
22.3261 + if (dependent == NULL_HANDLE || target == NULL_HANDLE) {
22.3262 + return;
22.3263 + }
22.3264 + switch (status[dependent]) {
22.3265 +
22.3266 + case STATUS_UNKNOWN:
22.3267 + switch (status[target]) {
22.3268 + case STATUS_OK:
22.3269 + // ignore dependencies on objs with no exception
22.3270 + break;
22.3271 +
22.3272 + case STATUS_EXCEPTION:
22.3273 + // eagerly propagate exception
22.3274 + markException(dependent,
22.3275 + (ClassNotFoundException) entries[target]);
22.3276 + break;
22.3277 +
22.3278 + case STATUS_UNKNOWN:
22.3279 + // add to dependency list of target
22.3280 + if (deps[target] == null) {
22.3281 + deps[target] = new HandleList();
22.3282 + }
22.3283 + deps[target].add(dependent);
22.3284 +
22.3285 + // remember lowest unresolved target seen
22.3286 + if (lowDep < 0 || lowDep > target) {
22.3287 + lowDep = target;
22.3288 + }
22.3289 + break;
22.3290 +
22.3291 + default:
22.3292 + throw new InternalError();
22.3293 + }
22.3294 + break;
22.3295 +
22.3296 + case STATUS_EXCEPTION:
22.3297 + break;
22.3298 +
22.3299 + default:
22.3300 + throw new InternalError();
22.3301 + }
22.3302 + }
22.3303 +
22.3304 + /**
22.3305 + * Associates a ClassNotFoundException (if one not already associated)
22.3306 + * with the currently active handle and propagates it to other
22.3307 + * referencing objects as appropriate. The specified handle must be
22.3308 + * "open" (i.e., assigned, but not finished yet).
22.3309 + */
22.3310 + void markException(int handle, ClassNotFoundException ex) {
22.3311 + switch (status[handle]) {
22.3312 + case STATUS_UNKNOWN:
22.3313 + status[handle] = STATUS_EXCEPTION;
22.3314 + entries[handle] = ex;
22.3315 +
22.3316 + // propagate exception to dependents
22.3317 + HandleList dlist = deps[handle];
22.3318 + if (dlist != null) {
22.3319 + int ndeps = dlist.size();
22.3320 + for (int i = 0; i < ndeps; i++) {
22.3321 + markException(dlist.get(i), ex);
22.3322 + }
22.3323 + deps[handle] = null;
22.3324 + }
22.3325 + break;
22.3326 +
22.3327 + case STATUS_EXCEPTION:
22.3328 + break;
22.3329 +
22.3330 + default:
22.3331 + throw new InternalError();
22.3332 + }
22.3333 + }
22.3334 +
22.3335 + /**
22.3336 + * Marks given handle as finished, meaning that no new dependencies
22.3337 + * will be marked for handle. Calls to the assign and finish methods
22.3338 + * must occur in LIFO order.
22.3339 + */
22.3340 + void finish(int handle) {
22.3341 + int end;
22.3342 + if (lowDep < 0) {
22.3343 + // no pending unknowns, only resolve current handle
22.3344 + end = handle + 1;
22.3345 + } else if (lowDep >= handle) {
22.3346 + // pending unknowns now clearable, resolve all upward handles
22.3347 + end = size;
22.3348 + lowDep = -1;
22.3349 + } else {
22.3350 + // unresolved backrefs present, can't resolve anything yet
22.3351 + return;
22.3352 + }
22.3353 +
22.3354 + // change STATUS_UNKNOWN -> STATUS_OK in selected span of handles
22.3355 + for (int i = handle; i < end; i++) {
22.3356 + switch (status[i]) {
22.3357 + case STATUS_UNKNOWN:
22.3358 + status[i] = STATUS_OK;
22.3359 + deps[i] = null;
22.3360 + break;
22.3361 +
22.3362 + case STATUS_OK:
22.3363 + case STATUS_EXCEPTION:
22.3364 + break;
22.3365 +
22.3366 + default:
22.3367 + throw new InternalError();
22.3368 + }
22.3369 + }
22.3370 + }
22.3371 +
22.3372 + /**
22.3373 + * Assigns a new object to the given handle. The object previously
22.3374 + * associated with the handle is forgotten. This method has no effect
22.3375 + * if the given handle already has an exception associated with it.
22.3376 + * This method may be called at any time after the handle is assigned.
22.3377 + */
22.3378 + void setObject(int handle, Object obj) {
22.3379 + switch (status[handle]) {
22.3380 + case STATUS_UNKNOWN:
22.3381 + case STATUS_OK:
22.3382 + entries[handle] = obj;
22.3383 + break;
22.3384 +
22.3385 + case STATUS_EXCEPTION:
22.3386 + break;
22.3387 +
22.3388 + default:
22.3389 + throw new InternalError();
22.3390 + }
22.3391 + }
22.3392 +
22.3393 + /**
22.3394 + * Looks up and returns object associated with the given handle.
22.3395 + * Returns null if the given handle is NULL_HANDLE, or if it has an
22.3396 + * associated ClassNotFoundException.
22.3397 + */
22.3398 + Object lookupObject(int handle) {
22.3399 + return (handle != NULL_HANDLE &&
22.3400 + status[handle] != STATUS_EXCEPTION) ?
22.3401 + entries[handle] : null;
22.3402 + }
22.3403 +
22.3404 + /**
22.3405 + * Looks up and returns ClassNotFoundException associated with the
22.3406 + * given handle. Returns null if the given handle is NULL_HANDLE, or
22.3407 + * if there is no ClassNotFoundException associated with the handle.
22.3408 + */
22.3409 + ClassNotFoundException lookupException(int handle) {
22.3410 + return (handle != NULL_HANDLE &&
22.3411 + status[handle] == STATUS_EXCEPTION) ?
22.3412 + (ClassNotFoundException) entries[handle] : null;
22.3413 + }
22.3414 +
22.3415 + /**
22.3416 + * Resets table to its initial state.
22.3417 + */
22.3418 + void clear() {
22.3419 + Arrays.fill(status, 0, size, (byte) 0);
22.3420 + Arrays.fill(entries, 0, size, null);
22.3421 + Arrays.fill(deps, 0, size, null);
22.3422 + lowDep = -1;
22.3423 + size = 0;
22.3424 + }
22.3425 +
22.3426 + /**
22.3427 + * Returns number of handles registered in table.
22.3428 + */
22.3429 + int size() {
22.3430 + return size;
22.3431 + }
22.3432 +
22.3433 + /**
22.3434 + * Expands capacity of internal arrays.
22.3435 + */
22.3436 + private void grow() {
22.3437 + int newCapacity = (entries.length << 1) + 1;
22.3438 +
22.3439 + byte[] newStatus = new byte[newCapacity];
22.3440 + Object[] newEntries = new Object[newCapacity];
22.3441 + HandleList[] newDeps = new HandleList[newCapacity];
22.3442 +
22.3443 + System.arraycopy(status, 0, newStatus, 0, size);
22.3444 + System.arraycopy(entries, 0, newEntries, 0, size);
22.3445 + System.arraycopy(deps, 0, newDeps, 0, size);
22.3446 +
22.3447 + status = newStatus;
22.3448 + entries = newEntries;
22.3449 + deps = newDeps;
22.3450 + }
22.3451 +
22.3452 + /**
22.3453 + * Simple growable list of (integer) handles.
22.3454 + */
22.3455 + private static class HandleList {
22.3456 + private int[] list = new int[4];
22.3457 + private int size = 0;
22.3458 +
22.3459 + public HandleList() {
22.3460 + }
22.3461 +
22.3462 + public void add(int handle) {
22.3463 + if (size >= list.length) {
22.3464 + int[] newList = new int[list.length << 1];
22.3465 + System.arraycopy(list, 0, newList, 0, list.length);
22.3466 + list = newList;
22.3467 + }
22.3468 + list[size++] = handle;
22.3469 + }
22.3470 +
22.3471 + public int get(int index) {
22.3472 + if (index >= size) {
22.3473 + throw new ArrayIndexOutOfBoundsException();
22.3474 + }
22.3475 + return list[index];
22.3476 + }
22.3477 +
22.3478 + public int size() {
22.3479 + return size;
22.3480 + }
22.3481 + }
22.3482 + }
22.3483 +
22.3484 + /**
22.3485 + * Method for cloning arrays in case of using unsharing reading
22.3486 + */
22.3487 + private static Object cloneArray(Object array) {
22.3488 + if (array instanceof Object[]) {
22.3489 + return ((Object[]) array).clone();
22.3490 + } else if (array instanceof boolean[]) {
22.3491 + return ((boolean[]) array).clone();
22.3492 + } else if (array instanceof byte[]) {
22.3493 + return ((byte[]) array).clone();
22.3494 + } else if (array instanceof char[]) {
22.3495 + return ((char[]) array).clone();
22.3496 + } else if (array instanceof double[]) {
22.3497 + return ((double[]) array).clone();
22.3498 + } else if (array instanceof float[]) {
22.3499 + return ((float[]) array).clone();
22.3500 + } else if (array instanceof int[]) {
22.3501 + return ((int[]) array).clone();
22.3502 + } else if (array instanceof long[]) {
22.3503 + return ((long[]) array).clone();
22.3504 + } else if (array instanceof short[]) {
22.3505 + return ((short[]) array).clone();
22.3506 + } else {
22.3507 + throw new AssertionError();
22.3508 + }
22.3509 + }
22.3510 +
22.3511 +}
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
23.2 +++ b/emul/compact/src/main/java/java/io/ObjectInputValidation.java Fri Feb 01 16:35:42 2013 +0100
23.3 @@ -0,0 +1,45 @@
23.4 +/*
23.5 + * Copyright (c) 1996, 1999, Oracle and/or its affiliates. All rights reserved.
23.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
23.7 + *
23.8 + * This code is free software; you can redistribute it and/or modify it
23.9 + * under the terms of the GNU General Public License version 2 only, as
23.10 + * published by the Free Software Foundation. Oracle designates this
23.11 + * particular file as subject to the "Classpath" exception as provided
23.12 + * by Oracle in the LICENSE file that accompanied this code.
23.13 + *
23.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
23.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23.17 + * version 2 for more details (a copy is included in the LICENSE file that
23.18 + * accompanied this code).
23.19 + *
23.20 + * You should have received a copy of the GNU General Public License version
23.21 + * 2 along with this work; if not, write to the Free Software Foundation,
23.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
23.23 + *
23.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23.25 + * or visit www.oracle.com if you need additional information or have any
23.26 + * questions.
23.27 + */
23.28 +
23.29 +package java.io;
23.30 +
23.31 +/**
23.32 + * Callback interface to allow validation of objects within a graph.
23.33 + * Allows an object to be called when a complete graph of objects has
23.34 + * been deserialized.
23.35 + *
23.36 + * @author unascribed
23.37 + * @see ObjectInputStream
23.38 + * @see ObjectInputStream#registerValidation(java.io.ObjectInputValidation, int)
23.39 + * @since JDK1.1
23.40 + */
23.41 +public interface ObjectInputValidation {
23.42 + /**
23.43 + * Validates the object.
23.44 + *
23.45 + * @exception InvalidObjectException If the object cannot validate itself.
23.46 + */
23.47 + public void validateObject() throws InvalidObjectException;
23.48 +}
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
24.2 +++ b/emul/compact/src/main/java/java/io/ObjectOutput.java Fri Feb 01 16:35:42 2013 +0100
24.3 @@ -0,0 +1,90 @@
24.4 +/*
24.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
24.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
24.7 + *
24.8 + * This code is free software; you can redistribute it and/or modify it
24.9 + * under the terms of the GNU General Public License version 2 only, as
24.10 + * published by the Free Software Foundation. Oracle designates this
24.11 + * particular file as subject to the "Classpath" exception as provided
24.12 + * by Oracle in the LICENSE file that accompanied this code.
24.13 + *
24.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
24.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
24.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24.17 + * version 2 for more details (a copy is included in the LICENSE file that
24.18 + * accompanied this code).
24.19 + *
24.20 + * You should have received a copy of the GNU General Public License version
24.21 + * 2 along with this work; if not, write to the Free Software Foundation,
24.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24.23 + *
24.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
24.25 + * or visit www.oracle.com if you need additional information or have any
24.26 + * questions.
24.27 + */
24.28 +
24.29 +package java.io;
24.30 +
24.31 +/**
24.32 + * ObjectOutput extends the DataOutput interface to include writing of objects.
24.33 + * DataOutput includes methods for output of primitive types, ObjectOutput
24.34 + * extends that interface to include objects, arrays, and Strings.
24.35 + *
24.36 + * @author unascribed
24.37 + * @see java.io.InputStream
24.38 + * @see java.io.ObjectOutputStream
24.39 + * @see java.io.ObjectInputStream
24.40 + * @since JDK1.1
24.41 + */
24.42 +public interface ObjectOutput extends DataOutput, AutoCloseable {
24.43 + /**
24.44 + * Write an object to the underlying storage or stream. The
24.45 + * class that implements this interface defines how the object is
24.46 + * written.
24.47 + *
24.48 + * @param obj the object to be written
24.49 + * @exception IOException Any of the usual Input/Output related exceptions.
24.50 + */
24.51 + public void writeObject(Object obj)
24.52 + throws IOException;
24.53 +
24.54 + /**
24.55 + * Writes a byte. This method will block until the byte is actually
24.56 + * written.
24.57 + * @param b the byte
24.58 + * @exception IOException If an I/O error has occurred.
24.59 + */
24.60 + public void write(int b) throws IOException;
24.61 +
24.62 + /**
24.63 + * Writes an array of bytes. This method will block until the bytes
24.64 + * are actually written.
24.65 + * @param b the data to be written
24.66 + * @exception IOException If an I/O error has occurred.
24.67 + */
24.68 + public void write(byte b[]) throws IOException;
24.69 +
24.70 + /**
24.71 + * Writes a sub array of bytes.
24.72 + * @param b the data to be written
24.73 + * @param off the start offset in the data
24.74 + * @param len the number of bytes that are written
24.75 + * @exception IOException If an I/O error has occurred.
24.76 + */
24.77 + public void write(byte b[], int off, int len) throws IOException;
24.78 +
24.79 + /**
24.80 + * Flushes the stream. This will write any buffered
24.81 + * output bytes.
24.82 + * @exception IOException If an I/O error has occurred.
24.83 + */
24.84 + public void flush() throws IOException;
24.85 +
24.86 + /**
24.87 + * Closes the stream. This method must be called
24.88 + * to release any resources associated with the
24.89 + * stream.
24.90 + * @exception IOException If an I/O error has occurred.
24.91 + */
24.92 + public void close() throws IOException;
24.93 +}
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
25.2 +++ b/emul/compact/src/main/java/java/io/ObjectOutputStream.java Fri Feb 01 16:35:42 2013 +0100
25.3 @@ -0,0 +1,2454 @@
25.4 +/*
25.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
25.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
25.7 + *
25.8 + * This code is free software; you can redistribute it and/or modify it
25.9 + * under the terms of the GNU General Public License version 2 only, as
25.10 + * published by the Free Software Foundation. Oracle designates this
25.11 + * particular file as subject to the "Classpath" exception as provided
25.12 + * by Oracle in the LICENSE file that accompanied this code.
25.13 + *
25.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
25.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
25.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25.17 + * version 2 for more details (a copy is included in the LICENSE file that
25.18 + * accompanied this code).
25.19 + *
25.20 + * You should have received a copy of the GNU General Public License version
25.21 + * 2 along with this work; if not, write to the Free Software Foundation,
25.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
25.23 + *
25.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
25.25 + * or visit www.oracle.com if you need additional information or have any
25.26 + * questions.
25.27 + */
25.28 +
25.29 +package java.io;
25.30 +
25.31 +import java.io.ObjectStreamClass.WeakClassKey;
25.32 +import java.lang.ref.ReferenceQueue;
25.33 +import java.security.AccessController;
25.34 +import java.security.PrivilegedAction;
25.35 +import java.util.ArrayList;
25.36 +import java.util.Arrays;
25.37 +import java.util.List;
25.38 +import java.util.concurrent.ConcurrentHashMap;
25.39 +import java.util.concurrent.ConcurrentMap;
25.40 +import static java.io.ObjectStreamClass.processQueue;
25.41 +import java.io.SerialCallbackContext;
25.42 +
25.43 +/**
25.44 + * An ObjectOutputStream writes primitive data types and graphs of Java objects
25.45 + * to an OutputStream. The objects can be read (reconstituted) using an
25.46 + * ObjectInputStream. Persistent storage of objects can be accomplished by
25.47 + * using a file for the stream. If the stream is a network socket stream, the
25.48 + * objects can be reconstituted on another host or in another process.
25.49 + *
25.50 + * <p>Only objects that support the java.io.Serializable interface can be
25.51 + * written to streams. The class of each serializable object is encoded
25.52 + * including the class name and signature of the class, the values of the
25.53 + * object's fields and arrays, and the closure of any other objects referenced
25.54 + * from the initial objects.
25.55 + *
25.56 + * <p>The method writeObject is used to write an object to the stream. Any
25.57 + * object, including Strings and arrays, is written with writeObject. Multiple
25.58 + * objects or primitives can be written to the stream. The objects must be
25.59 + * read back from the corresponding ObjectInputstream with the same types and
25.60 + * in the same order as they were written.
25.61 + *
25.62 + * <p>Primitive data types can also be written to the stream using the
25.63 + * appropriate methods from DataOutput. Strings can also be written using the
25.64 + * writeUTF method.
25.65 + *
25.66 + * <p>The default serialization mechanism for an object writes the class of the
25.67 + * object, the class signature, and the values of all non-transient and
25.68 + * non-static fields. References to other objects (except in transient or
25.69 + * static fields) cause those objects to be written also. Multiple references
25.70 + * to a single object are encoded using a reference sharing mechanism so that
25.71 + * graphs of objects can be restored to the same shape as when the original was
25.72 + * written.
25.73 + *
25.74 + * <p>For example to write an object that can be read by the example in
25.75 + * ObjectInputStream:
25.76 + * <br>
25.77 + * <pre>
25.78 + * FileOutputStream fos = new FileOutputStream("t.tmp");
25.79 + * ObjectOutputStream oos = new ObjectOutputStream(fos);
25.80 + *
25.81 + * oos.writeInt(12345);
25.82 + * oos.writeObject("Today");
25.83 + * oos.writeObject(new Date());
25.84 + *
25.85 + * oos.close();
25.86 + * </pre>
25.87 + *
25.88 + * <p>Classes that require special handling during the serialization and
25.89 + * deserialization process must implement special methods with these exact
25.90 + * signatures:
25.91 + * <br>
25.92 + * <pre>
25.93 + * private void readObject(java.io.ObjectInputStream stream)
25.94 + * throws IOException, ClassNotFoundException;
25.95 + * private void writeObject(java.io.ObjectOutputStream stream)
25.96 + * throws IOException
25.97 + * private void readObjectNoData()
25.98 + * throws ObjectStreamException;
25.99 + * </pre>
25.100 + *
25.101 + * <p>The writeObject method is responsible for writing the state of the object
25.102 + * for its particular class so that the corresponding readObject method can
25.103 + * restore it. The method does not need to concern itself with the state
25.104 + * belonging to the object's superclasses or subclasses. State is saved by
25.105 + * writing the individual fields to the ObjectOutputStream using the
25.106 + * writeObject method or by using the methods for primitive data types
25.107 + * supported by DataOutput.
25.108 + *
25.109 + * <p>Serialization does not write out the fields of any object that does not
25.110 + * implement the java.io.Serializable interface. Subclasses of Objects that
25.111 + * are not serializable can be serializable. In this case the non-serializable
25.112 + * class must have a no-arg constructor to allow its fields to be initialized.
25.113 + * In this case it is the responsibility of the subclass to save and restore
25.114 + * the state of the non-serializable class. It is frequently the case that the
25.115 + * fields of that class are accessible (public, package, or protected) or that
25.116 + * there are get and set methods that can be used to restore the state.
25.117 + *
25.118 + * <p>Serialization of an object can be prevented by implementing writeObject
25.119 + * and readObject methods that throw the NotSerializableException. The
25.120 + * exception will be caught by the ObjectOutputStream and abort the
25.121 + * serialization process.
25.122 + *
25.123 + * <p>Implementing the Externalizable interface allows the object to assume
25.124 + * complete control over the contents and format of the object's serialized
25.125 + * form. The methods of the Externalizable interface, writeExternal and
25.126 + * readExternal, are called to save and restore the objects state. When
25.127 + * implemented by a class they can write and read their own state using all of
25.128 + * the methods of ObjectOutput and ObjectInput. It is the responsibility of
25.129 + * the objects to handle any versioning that occurs.
25.130 + *
25.131 + * <p>Enum constants are serialized differently than ordinary serializable or
25.132 + * externalizable objects. The serialized form of an enum constant consists
25.133 + * solely of its name; field values of the constant are not transmitted. To
25.134 + * serialize an enum constant, ObjectOutputStream writes the string returned by
25.135 + * the constant's name method. Like other serializable or externalizable
25.136 + * objects, enum constants can function as the targets of back references
25.137 + * appearing subsequently in the serialization stream. The process by which
25.138 + * enum constants are serialized cannot be customized; any class-specific
25.139 + * writeObject and writeReplace methods defined by enum types are ignored
25.140 + * during serialization. Similarly, any serialPersistentFields or
25.141 + * serialVersionUID field declarations are also ignored--all enum types have a
25.142 + * fixed serialVersionUID of 0L.
25.143 + *
25.144 + * <p>Primitive data, excluding serializable fields and externalizable data, is
25.145 + * written to the ObjectOutputStream in block-data records. A block data record
25.146 + * is composed of a header and data. The block data header consists of a marker
25.147 + * and the number of bytes to follow the header. Consecutive primitive data
25.148 + * writes are merged into one block-data record. The blocking factor used for
25.149 + * a block-data record will be 1024 bytes. Each block-data record will be
25.150 + * filled up to 1024 bytes, or be written whenever there is a termination of
25.151 + * block-data mode. Calls to the ObjectOutputStream methods writeObject,
25.152 + * defaultWriteObject and writeFields initially terminate any existing
25.153 + * block-data record.
25.154 + *
25.155 + * @author Mike Warres
25.156 + * @author Roger Riggs
25.157 + * @see java.io.DataOutput
25.158 + * @see java.io.ObjectInputStream
25.159 + * @see java.io.Serializable
25.160 + * @see java.io.Externalizable
25.161 + * @see <a href="../../../platform/serialization/spec/output.html">Object Serialization Specification, Section 2, Object Output Classes</a>
25.162 + * @since JDK1.1
25.163 + */
25.164 +public class ObjectOutputStream
25.165 + extends OutputStream implements ObjectOutput, ObjectStreamConstants
25.166 +{
25.167 +
25.168 + private static class Caches {
25.169 + /** cache of subclass security audit results */
25.170 + static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits =
25.171 + new ConcurrentHashMap<>();
25.172 +
25.173 + /** queue for WeakReferences to audited subclasses */
25.174 + static final ReferenceQueue<Class<?>> subclassAuditsQueue =
25.175 + new ReferenceQueue<>();
25.176 + }
25.177 +
25.178 + /** filter stream for handling block data conversion */
25.179 + private final BlockDataOutputStream bout;
25.180 + /** obj -> wire handle map */
25.181 + private final HandleTable handles;
25.182 + /** obj -> replacement obj map */
25.183 + private final ReplaceTable subs;
25.184 + /** stream protocol version */
25.185 + private int protocol = PROTOCOL_VERSION_2;
25.186 + /** recursion depth */
25.187 + private int depth;
25.188 +
25.189 + /** buffer for writing primitive field values */
25.190 + private byte[] primVals;
25.191 +
25.192 + /** if true, invoke writeObjectOverride() instead of writeObject() */
25.193 + private final boolean enableOverride;
25.194 + /** if true, invoke replaceObject() */
25.195 + private boolean enableReplace;
25.196 +
25.197 + // values below valid only during upcalls to writeObject()/writeExternal()
25.198 + /**
25.199 + * Context during upcalls to class-defined writeObject methods; holds
25.200 + * object currently being serialized and descriptor for current class.
25.201 + * Null when not during writeObject upcall.
25.202 + */
25.203 + private SerialCallbackContext curContext;
25.204 + /** current PutField object */
25.205 + private PutFieldImpl curPut;
25.206 +
25.207 + /** custom storage for debug trace info */
25.208 + private final DebugTraceInfoStack debugInfoStack;
25.209 +
25.210 + /**
25.211 + * value of "sun.io.serialization.extendedDebugInfo" property,
25.212 + * as true or false for extended information about exception's place
25.213 + */
25.214 + private static final boolean extendedDebugInfo =
25.215 + java.security.AccessController.doPrivileged(
25.216 + new sun.security.action.GetBooleanAction(
25.217 + "sun.io.serialization.extendedDebugInfo")).booleanValue();
25.218 +
25.219 + /**
25.220 + * Creates an ObjectOutputStream that writes to the specified OutputStream.
25.221 + * This constructor writes the serialization stream header to the
25.222 + * underlying stream; callers may wish to flush the stream immediately to
25.223 + * ensure that constructors for receiving ObjectInputStreams will not block
25.224 + * when reading the header.
25.225 + *
25.226 + * <p>If a security manager is installed, this constructor will check for
25.227 + * the "enableSubclassImplementation" SerializablePermission when invoked
25.228 + * directly or indirectly by the constructor of a subclass which overrides
25.229 + * the ObjectOutputStream.putFields or ObjectOutputStream.writeUnshared
25.230 + * methods.
25.231 + *
25.232 + * @param out output stream to write to
25.233 + * @throws IOException if an I/O error occurs while writing stream header
25.234 + * @throws SecurityException if untrusted subclass illegally overrides
25.235 + * security-sensitive methods
25.236 + * @throws NullPointerException if <code>out</code> is <code>null</code>
25.237 + * @since 1.4
25.238 + * @see ObjectOutputStream#ObjectOutputStream()
25.239 + * @see ObjectOutputStream#putFields()
25.240 + * @see ObjectInputStream#ObjectInputStream(InputStream)
25.241 + */
25.242 + public ObjectOutputStream(OutputStream out) throws IOException {
25.243 + verifySubclass();
25.244 + bout = new BlockDataOutputStream(out);
25.245 + handles = new HandleTable(10, (float) 3.00);
25.246 + subs = new ReplaceTable(10, (float) 3.00);
25.247 + enableOverride = false;
25.248 + writeStreamHeader();
25.249 + bout.setBlockDataMode(true);
25.250 + if (extendedDebugInfo) {
25.251 + debugInfoStack = new DebugTraceInfoStack();
25.252 + } else {
25.253 + debugInfoStack = null;
25.254 + }
25.255 + }
25.256 +
25.257 + /**
25.258 + * Provide a way for subclasses that are completely reimplementing
25.259 + * ObjectOutputStream to not have to allocate private data just used by
25.260 + * this implementation of ObjectOutputStream.
25.261 + *
25.262 + * <p>If there is a security manager installed, this method first calls the
25.263 + * security manager's <code>checkPermission</code> method with a
25.264 + * <code>SerializablePermission("enableSubclassImplementation")</code>
25.265 + * permission to ensure it's ok to enable subclassing.
25.266 + *
25.267 + * @throws SecurityException if a security manager exists and its
25.268 + * <code>checkPermission</code> method denies enabling
25.269 + * subclassing.
25.270 + * @see SecurityManager#checkPermission
25.271 + * @see java.io.SerializablePermission
25.272 + */
25.273 + protected ObjectOutputStream() throws IOException, SecurityException {
25.274 + SecurityManager sm = System.getSecurityManager();
25.275 + if (sm != null) {
25.276 + sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
25.277 + }
25.278 + bout = null;
25.279 + handles = null;
25.280 + subs = null;
25.281 + enableOverride = true;
25.282 + debugInfoStack = null;
25.283 + }
25.284 +
25.285 + /**
25.286 + * Specify stream protocol version to use when writing the stream.
25.287 + *
25.288 + * <p>This routine provides a hook to enable the current version of
25.289 + * Serialization to write in a format that is backwards compatible to a
25.290 + * previous version of the stream format.
25.291 + *
25.292 + * <p>Every effort will be made to avoid introducing additional
25.293 + * backwards incompatibilities; however, sometimes there is no
25.294 + * other alternative.
25.295 + *
25.296 + * @param version use ProtocolVersion from java.io.ObjectStreamConstants.
25.297 + * @throws IllegalStateException if called after any objects
25.298 + * have been serialized.
25.299 + * @throws IllegalArgumentException if invalid version is passed in.
25.300 + * @throws IOException if I/O errors occur
25.301 + * @see java.io.ObjectStreamConstants#PROTOCOL_VERSION_1
25.302 + * @see java.io.ObjectStreamConstants#PROTOCOL_VERSION_2
25.303 + * @since 1.2
25.304 + */
25.305 + public void useProtocolVersion(int version) throws IOException {
25.306 + if (handles.size() != 0) {
25.307 + // REMIND: implement better check for pristine stream?
25.308 + throw new IllegalStateException("stream non-empty");
25.309 + }
25.310 + switch (version) {
25.311 + case PROTOCOL_VERSION_1:
25.312 + case PROTOCOL_VERSION_2:
25.313 + protocol = version;
25.314 + break;
25.315 +
25.316 + default:
25.317 + throw new IllegalArgumentException(
25.318 + "unknown version: " + version);
25.319 + }
25.320 + }
25.321 +
25.322 + /**
25.323 + * Write the specified object to the ObjectOutputStream. The class of the
25.324 + * object, the signature of the class, and the values of the non-transient
25.325 + * and non-static fields of the class and all of its supertypes are
25.326 + * written. Default serialization for a class can be overridden using the
25.327 + * writeObject and the readObject methods. Objects referenced by this
25.328 + * object are written transitively so that a complete equivalent graph of
25.329 + * objects can be reconstructed by an ObjectInputStream.
25.330 + *
25.331 + * <p>Exceptions are thrown for problems with the OutputStream and for
25.332 + * classes that should not be serialized. All exceptions are fatal to the
25.333 + * OutputStream, which is left in an indeterminate state, and it is up to
25.334 + * the caller to ignore or recover the stream state.
25.335 + *
25.336 + * @throws InvalidClassException Something is wrong with a class used by
25.337 + * serialization.
25.338 + * @throws NotSerializableException Some object to be serialized does not
25.339 + * implement the java.io.Serializable interface.
25.340 + * @throws IOException Any exception thrown by the underlying
25.341 + * OutputStream.
25.342 + */
25.343 + public final void writeObject(Object obj) throws IOException {
25.344 + if (enableOverride) {
25.345 + writeObjectOverride(obj);
25.346 + return;
25.347 + }
25.348 + try {
25.349 + writeObject0(obj, false);
25.350 + } catch (IOException ex) {
25.351 + if (depth == 0) {
25.352 + writeFatalException(ex);
25.353 + }
25.354 + throw ex;
25.355 + }
25.356 + }
25.357 +
25.358 + /**
25.359 + * Method used by subclasses to override the default writeObject method.
25.360 + * This method is called by trusted subclasses of ObjectInputStream that
25.361 + * constructed ObjectInputStream using the protected no-arg constructor.
25.362 + * The subclass is expected to provide an override method with the modifier
25.363 + * "final".
25.364 + *
25.365 + * @param obj object to be written to the underlying stream
25.366 + * @throws IOException if there are I/O errors while writing to the
25.367 + * underlying stream
25.368 + * @see #ObjectOutputStream()
25.369 + * @see #writeObject(Object)
25.370 + * @since 1.2
25.371 + */
25.372 + protected void writeObjectOverride(Object obj) throws IOException {
25.373 + }
25.374 +
25.375 + /**
25.376 + * Writes an "unshared" object to the ObjectOutputStream. This method is
25.377 + * identical to writeObject, except that it always writes the given object
25.378 + * as a new, unique object in the stream (as opposed to a back-reference
25.379 + * pointing to a previously serialized instance). Specifically:
25.380 + * <ul>
25.381 + * <li>An object written via writeUnshared is always serialized in the
25.382 + * same manner as a newly appearing object (an object that has not
25.383 + * been written to the stream yet), regardless of whether or not the
25.384 + * object has been written previously.
25.385 + *
25.386 + * <li>If writeObject is used to write an object that has been previously
25.387 + * written with writeUnshared, the previous writeUnshared operation
25.388 + * is treated as if it were a write of a separate object. In other
25.389 + * words, ObjectOutputStream will never generate back-references to
25.390 + * object data written by calls to writeUnshared.
25.391 + * </ul>
25.392 + * While writing an object via writeUnshared does not in itself guarantee a
25.393 + * unique reference to the object when it is deserialized, it allows a
25.394 + * single object to be defined multiple times in a stream, so that multiple
25.395 + * calls to readUnshared by the receiver will not conflict. Note that the
25.396 + * rules described above only apply to the base-level object written with
25.397 + * writeUnshared, and not to any transitively referenced sub-objects in the
25.398 + * object graph to be serialized.
25.399 + *
25.400 + * <p>ObjectOutputStream subclasses which override this method can only be
25.401 + * constructed in security contexts possessing the
25.402 + * "enableSubclassImplementation" SerializablePermission; any attempt to
25.403 + * instantiate such a subclass without this permission will cause a
25.404 + * SecurityException to be thrown.
25.405 + *
25.406 + * @param obj object to write to stream
25.407 + * @throws NotSerializableException if an object in the graph to be
25.408 + * serialized does not implement the Serializable interface
25.409 + * @throws InvalidClassException if a problem exists with the class of an
25.410 + * object to be serialized
25.411 + * @throws IOException if an I/O error occurs during serialization
25.412 + * @since 1.4
25.413 + */
25.414 + public void writeUnshared(Object obj) throws IOException {
25.415 + try {
25.416 + writeObject0(obj, true);
25.417 + } catch (IOException ex) {
25.418 + if (depth == 0) {
25.419 + writeFatalException(ex);
25.420 + }
25.421 + throw ex;
25.422 + }
25.423 + }
25.424 +
25.425 + /**
25.426 + * Write the non-static and non-transient fields of the current class to
25.427 + * this stream. This may only be called from the writeObject method of the
25.428 + * class being serialized. It will throw the NotActiveException if it is
25.429 + * called otherwise.
25.430 + *
25.431 + * @throws IOException if I/O errors occur while writing to the underlying
25.432 + * <code>OutputStream</code>
25.433 + */
25.434 + public void defaultWriteObject() throws IOException {
25.435 + if ( curContext == null ) {
25.436 + throw new NotActiveException("not in call to writeObject");
25.437 + }
25.438 + Object curObj = curContext.getObj();
25.439 + ObjectStreamClass curDesc = curContext.getDesc();
25.440 + bout.setBlockDataMode(false);
25.441 + defaultWriteFields(curObj, curDesc);
25.442 + bout.setBlockDataMode(true);
25.443 + }
25.444 +
25.445 + /**
25.446 + * Retrieve the object used to buffer persistent fields to be written to
25.447 + * the stream. The fields will be written to the stream when writeFields
25.448 + * method is called.
25.449 + *
25.450 + * @return an instance of the class Putfield that holds the serializable
25.451 + * fields
25.452 + * @throws IOException if I/O errors occur
25.453 + * @since 1.2
25.454 + */
25.455 + public ObjectOutputStream.PutField putFields() throws IOException {
25.456 + if (curPut == null) {
25.457 + if (curContext == null) {
25.458 + throw new NotActiveException("not in call to writeObject");
25.459 + }
25.460 + Object curObj = curContext.getObj();
25.461 + ObjectStreamClass curDesc = curContext.getDesc();
25.462 + curPut = new PutFieldImpl(curDesc);
25.463 + }
25.464 + return curPut;
25.465 + }
25.466 +
25.467 + /**
25.468 + * Write the buffered fields to the stream.
25.469 + *
25.470 + * @throws IOException if I/O errors occur while writing to the underlying
25.471 + * stream
25.472 + * @throws NotActiveException Called when a classes writeObject method was
25.473 + * not called to write the state of the object.
25.474 + * @since 1.2
25.475 + */
25.476 + public void writeFields() throws IOException {
25.477 + if (curPut == null) {
25.478 + throw new NotActiveException("no current PutField object");
25.479 + }
25.480 + bout.setBlockDataMode(false);
25.481 + curPut.writeFields();
25.482 + bout.setBlockDataMode(true);
25.483 + }
25.484 +
25.485 + /**
25.486 + * Reset will disregard the state of any objects already written to the
25.487 + * stream. The state is reset to be the same as a new ObjectOutputStream.
25.488 + * The current point in the stream is marked as reset so the corresponding
25.489 + * ObjectInputStream will be reset at the same point. Objects previously
25.490 + * written to the stream will not be refered to as already being in the
25.491 + * stream. They will be written to the stream again.
25.492 + *
25.493 + * @throws IOException if reset() is invoked while serializing an object.
25.494 + */
25.495 + public void reset() throws IOException {
25.496 + if (depth != 0) {
25.497 + throw new IOException("stream active");
25.498 + }
25.499 + bout.setBlockDataMode(false);
25.500 + bout.writeByte(TC_RESET);
25.501 + clear();
25.502 + bout.setBlockDataMode(true);
25.503 + }
25.504 +
25.505 + /**
25.506 + * Subclasses may implement this method to allow class data to be stored in
25.507 + * the stream. By default this method does nothing. The corresponding
25.508 + * method in ObjectInputStream is resolveClass. This method is called
25.509 + * exactly once for each unique class in the stream. The class name and
25.510 + * signature will have already been written to the stream. This method may
25.511 + * make free use of the ObjectOutputStream to save any representation of
25.512 + * the class it deems suitable (for example, the bytes of the class file).
25.513 + * The resolveClass method in the corresponding subclass of
25.514 + * ObjectInputStream must read and use any data or objects written by
25.515 + * annotateClass.
25.516 + *
25.517 + * @param cl the class to annotate custom data for
25.518 + * @throws IOException Any exception thrown by the underlying
25.519 + * OutputStream.
25.520 + */
25.521 + protected void annotateClass(Class<?> cl) throws IOException {
25.522 + }
25.523 +
25.524 + /**
25.525 + * Subclasses may implement this method to store custom data in the stream
25.526 + * along with descriptors for dynamic proxy classes.
25.527 + *
25.528 + * <p>This method is called exactly once for each unique proxy class
25.529 + * descriptor in the stream. The default implementation of this method in
25.530 + * <code>ObjectOutputStream</code> does nothing.
25.531 + *
25.532 + * <p>The corresponding method in <code>ObjectInputStream</code> is
25.533 + * <code>resolveProxyClass</code>. For a given subclass of
25.534 + * <code>ObjectOutputStream</code> that overrides this method, the
25.535 + * <code>resolveProxyClass</code> method in the corresponding subclass of
25.536 + * <code>ObjectInputStream</code> must read any data or objects written by
25.537 + * <code>annotateProxyClass</code>.
25.538 + *
25.539 + * @param cl the proxy class to annotate custom data for
25.540 + * @throws IOException any exception thrown by the underlying
25.541 + * <code>OutputStream</code>
25.542 + * @see ObjectInputStream#resolveProxyClass(String[])
25.543 + * @since 1.3
25.544 + */
25.545 + protected void annotateProxyClass(Class<?> cl) throws IOException {
25.546 + }
25.547 +
25.548 + /**
25.549 + * This method will allow trusted subclasses of ObjectOutputStream to
25.550 + * substitute one object for another during serialization. Replacing
25.551 + * objects is disabled until enableReplaceObject is called. The
25.552 + * enableReplaceObject method checks that the stream requesting to do
25.553 + * replacement can be trusted. The first occurrence of each object written
25.554 + * into the serialization stream is passed to replaceObject. Subsequent
25.555 + * references to the object are replaced by the object returned by the
25.556 + * original call to replaceObject. To ensure that the private state of
25.557 + * objects is not unintentionally exposed, only trusted streams may use
25.558 + * replaceObject.
25.559 + *
25.560 + * <p>The ObjectOutputStream.writeObject method takes a parameter of type
25.561 + * Object (as opposed to type Serializable) to allow for cases where
25.562 + * non-serializable objects are replaced by serializable ones.
25.563 + *
25.564 + * <p>When a subclass is replacing objects it must insure that either a
25.565 + * complementary substitution must be made during deserialization or that
25.566 + * the substituted object is compatible with every field where the
25.567 + * reference will be stored. Objects whose type is not a subclass of the
25.568 + * type of the field or array element abort the serialization by raising an
25.569 + * exception and the object is not be stored.
25.570 + *
25.571 + * <p>This method is called only once when each object is first
25.572 + * encountered. All subsequent references to the object will be redirected
25.573 + * to the new object. This method should return the object to be
25.574 + * substituted or the original object.
25.575 + *
25.576 + * <p>Null can be returned as the object to be substituted, but may cause
25.577 + * NullReferenceException in classes that contain references to the
25.578 + * original object since they may be expecting an object instead of
25.579 + * null.
25.580 + *
25.581 + * @param obj the object to be replaced
25.582 + * @return the alternate object that replaced the specified one
25.583 + * @throws IOException Any exception thrown by the underlying
25.584 + * OutputStream.
25.585 + */
25.586 + protected Object replaceObject(Object obj) throws IOException {
25.587 + return obj;
25.588 + }
25.589 +
25.590 + /**
25.591 + * Enable the stream to do replacement of objects in the stream. When
25.592 + * enabled, the replaceObject method is called for every object being
25.593 + * serialized.
25.594 + *
25.595 + * <p>If <code>enable</code> is true, and there is a security manager
25.596 + * installed, this method first calls the security manager's
25.597 + * <code>checkPermission</code> method with a
25.598 + * <code>SerializablePermission("enableSubstitution")</code> permission to
25.599 + * ensure it's ok to enable the stream to do replacement of objects in the
25.600 + * stream.
25.601 + *
25.602 + * @param enable boolean parameter to enable replacement of objects
25.603 + * @return the previous setting before this method was invoked
25.604 + * @throws SecurityException if a security manager exists and its
25.605 + * <code>checkPermission</code> method denies enabling the stream
25.606 + * to do replacement of objects in the stream.
25.607 + * @see SecurityManager#checkPermission
25.608 + * @see java.io.SerializablePermission
25.609 + */
25.610 + protected boolean enableReplaceObject(boolean enable)
25.611 + throws SecurityException
25.612 + {
25.613 + if (enable == enableReplace) {
25.614 + return enable;
25.615 + }
25.616 + if (enable) {
25.617 + SecurityManager sm = System.getSecurityManager();
25.618 + if (sm != null) {
25.619 + sm.checkPermission(SUBSTITUTION_PERMISSION);
25.620 + }
25.621 + }
25.622 + enableReplace = enable;
25.623 + return !enableReplace;
25.624 + }
25.625 +
25.626 + /**
25.627 + * The writeStreamHeader method is provided so subclasses can append or
25.628 + * prepend their own header to the stream. It writes the magic number and
25.629 + * version to the stream.
25.630 + *
25.631 + * @throws IOException if I/O errors occur while writing to the underlying
25.632 + * stream
25.633 + */
25.634 + protected void writeStreamHeader() throws IOException {
25.635 + bout.writeShort(STREAM_MAGIC);
25.636 + bout.writeShort(STREAM_VERSION);
25.637 + }
25.638 +
25.639 + /**
25.640 + * Write the specified class descriptor to the ObjectOutputStream. Class
25.641 + * descriptors are used to identify the classes of objects written to the
25.642 + * stream. Subclasses of ObjectOutputStream may override this method to
25.643 + * customize the way in which class descriptors are written to the
25.644 + * serialization stream. The corresponding method in ObjectInputStream,
25.645 + * <code>readClassDescriptor</code>, should then be overridden to
25.646 + * reconstitute the class descriptor from its custom stream representation.
25.647 + * By default, this method writes class descriptors according to the format
25.648 + * defined in the Object Serialization specification.
25.649 + *
25.650 + * <p>Note that this method will only be called if the ObjectOutputStream
25.651 + * is not using the old serialization stream format (set by calling
25.652 + * ObjectOutputStream's <code>useProtocolVersion</code> method). If this
25.653 + * serialization stream is using the old format
25.654 + * (<code>PROTOCOL_VERSION_1</code>), the class descriptor will be written
25.655 + * internally in a manner that cannot be overridden or customized.
25.656 + *
25.657 + * @param desc class descriptor to write to the stream
25.658 + * @throws IOException If an I/O error has occurred.
25.659 + * @see java.io.ObjectInputStream#readClassDescriptor()
25.660 + * @see #useProtocolVersion(int)
25.661 + * @see java.io.ObjectStreamConstants#PROTOCOL_VERSION_1
25.662 + * @since 1.3
25.663 + */
25.664 + protected void writeClassDescriptor(ObjectStreamClass desc)
25.665 + throws IOException
25.666 + {
25.667 + desc.writeNonProxy(this);
25.668 + }
25.669 +
25.670 + /**
25.671 + * Writes a byte. This method will block until the byte is actually
25.672 + * written.
25.673 + *
25.674 + * @param val the byte to be written to the stream
25.675 + * @throws IOException If an I/O error has occurred.
25.676 + */
25.677 + public void write(int val) throws IOException {
25.678 + bout.write(val);
25.679 + }
25.680 +
25.681 + /**
25.682 + * Writes an array of bytes. This method will block until the bytes are
25.683 + * actually written.
25.684 + *
25.685 + * @param buf the data to be written
25.686 + * @throws IOException If an I/O error has occurred.
25.687 + */
25.688 + public void write(byte[] buf) throws IOException {
25.689 + bout.write(buf, 0, buf.length, false);
25.690 + }
25.691 +
25.692 + /**
25.693 + * Writes a sub array of bytes.
25.694 + *
25.695 + * @param buf the data to be written
25.696 + * @param off the start offset in the data
25.697 + * @param len the number of bytes that are written
25.698 + * @throws IOException If an I/O error has occurred.
25.699 + */
25.700 + public void write(byte[] buf, int off, int len) throws IOException {
25.701 + if (buf == null) {
25.702 + throw new NullPointerException();
25.703 + }
25.704 + int endoff = off + len;
25.705 + if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
25.706 + throw new IndexOutOfBoundsException();
25.707 + }
25.708 + bout.write(buf, off, len, false);
25.709 + }
25.710 +
25.711 + /**
25.712 + * Flushes the stream. This will write any buffered output bytes and flush
25.713 + * through to the underlying stream.
25.714 + *
25.715 + * @throws IOException If an I/O error has occurred.
25.716 + */
25.717 + public void flush() throws IOException {
25.718 + bout.flush();
25.719 + }
25.720 +
25.721 + /**
25.722 + * Drain any buffered data in ObjectOutputStream. Similar to flush but
25.723 + * does not propagate the flush to the underlying stream.
25.724 + *
25.725 + * @throws IOException if I/O errors occur while writing to the underlying
25.726 + * stream
25.727 + */
25.728 + protected void drain() throws IOException {
25.729 + bout.drain();
25.730 + }
25.731 +
25.732 + /**
25.733 + * Closes the stream. This method must be called to release any resources
25.734 + * associated with the stream.
25.735 + *
25.736 + * @throws IOException If an I/O error has occurred.
25.737 + */
25.738 + public void close() throws IOException {
25.739 + flush();
25.740 + clear();
25.741 + bout.close();
25.742 + }
25.743 +
25.744 + /**
25.745 + * Writes a boolean.
25.746 + *
25.747 + * @param val the boolean to be written
25.748 + * @throws IOException if I/O errors occur while writing to the underlying
25.749 + * stream
25.750 + */
25.751 + public void writeBoolean(boolean val) throws IOException {
25.752 + bout.writeBoolean(val);
25.753 + }
25.754 +
25.755 + /**
25.756 + * Writes an 8 bit byte.
25.757 + *
25.758 + * @param val the byte value to be written
25.759 + * @throws IOException if I/O errors occur while writing to the underlying
25.760 + * stream
25.761 + */
25.762 + public void writeByte(int val) throws IOException {
25.763 + bout.writeByte(val);
25.764 + }
25.765 +
25.766 + /**
25.767 + * Writes a 16 bit short.
25.768 + *
25.769 + * @param val the short value to be written
25.770 + * @throws IOException if I/O errors occur while writing to the underlying
25.771 + * stream
25.772 + */
25.773 + public void writeShort(int val) throws IOException {
25.774 + bout.writeShort(val);
25.775 + }
25.776 +
25.777 + /**
25.778 + * Writes a 16 bit char.
25.779 + *
25.780 + * @param val the char value to be written
25.781 + * @throws IOException if I/O errors occur while writing to the underlying
25.782 + * stream
25.783 + */
25.784 + public void writeChar(int val) throws IOException {
25.785 + bout.writeChar(val);
25.786 + }
25.787 +
25.788 + /**
25.789 + * Writes a 32 bit int.
25.790 + *
25.791 + * @param val the integer value to be written
25.792 + * @throws IOException if I/O errors occur while writing to the underlying
25.793 + * stream
25.794 + */
25.795 + public void writeInt(int val) throws IOException {
25.796 + bout.writeInt(val);
25.797 + }
25.798 +
25.799 + /**
25.800 + * Writes a 64 bit long.
25.801 + *
25.802 + * @param val the long value to be written
25.803 + * @throws IOException if I/O errors occur while writing to the underlying
25.804 + * stream
25.805 + */
25.806 + public void writeLong(long val) throws IOException {
25.807 + bout.writeLong(val);
25.808 + }
25.809 +
25.810 + /**
25.811 + * Writes a 32 bit float.
25.812 + *
25.813 + * @param val the float value to be written
25.814 + * @throws IOException if I/O errors occur while writing to the underlying
25.815 + * stream
25.816 + */
25.817 + public void writeFloat(float val) throws IOException {
25.818 + bout.writeFloat(val);
25.819 + }
25.820 +
25.821 + /**
25.822 + * Writes a 64 bit double.
25.823 + *
25.824 + * @param val the double value to be written
25.825 + * @throws IOException if I/O errors occur while writing to the underlying
25.826 + * stream
25.827 + */
25.828 + public void writeDouble(double val) throws IOException {
25.829 + bout.writeDouble(val);
25.830 + }
25.831 +
25.832 + /**
25.833 + * Writes a String as a sequence of bytes.
25.834 + *
25.835 + * @param str the String of bytes to be written
25.836 + * @throws IOException if I/O errors occur while writing to the underlying
25.837 + * stream
25.838 + */
25.839 + public void writeBytes(String str) throws IOException {
25.840 + bout.writeBytes(str);
25.841 + }
25.842 +
25.843 + /**
25.844 + * Writes a String as a sequence of chars.
25.845 + *
25.846 + * @param str the String of chars to be written
25.847 + * @throws IOException if I/O errors occur while writing to the underlying
25.848 + * stream
25.849 + */
25.850 + public void writeChars(String str) throws IOException {
25.851 + bout.writeChars(str);
25.852 + }
25.853 +
25.854 + /**
25.855 + * Primitive data write of this String in
25.856 + * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
25.857 + * format. Note that there is a
25.858 + * significant difference between writing a String into the stream as
25.859 + * primitive data or as an Object. A String instance written by writeObject
25.860 + * is written into the stream as a String initially. Future writeObject()
25.861 + * calls write references to the string into the stream.
25.862 + *
25.863 + * @param str the String to be written
25.864 + * @throws IOException if I/O errors occur while writing to the underlying
25.865 + * stream
25.866 + */
25.867 + public void writeUTF(String str) throws IOException {
25.868 + bout.writeUTF(str);
25.869 + }
25.870 +
25.871 + /**
25.872 + * Provide programmatic access to the persistent fields to be written
25.873 + * to ObjectOutput.
25.874 + *
25.875 + * @since 1.2
25.876 + */
25.877 + public static abstract class PutField {
25.878 +
25.879 + /**
25.880 + * Put the value of the named boolean field into the persistent field.
25.881 + *
25.882 + * @param name the name of the serializable field
25.883 + * @param val the value to assign to the field
25.884 + * @throws IllegalArgumentException if <code>name</code> does not
25.885 + * match the name of a serializable field for the class whose fields
25.886 + * are being written, or if the type of the named field is not
25.887 + * <code>boolean</code>
25.888 + */
25.889 + public abstract void put(String name, boolean val);
25.890 +
25.891 + /**
25.892 + * Put the value of the named byte field into the persistent field.
25.893 + *
25.894 + * @param name the name of the serializable field
25.895 + * @param val the value to assign to the field
25.896 + * @throws IllegalArgumentException if <code>name</code> does not
25.897 + * match the name of a serializable field for the class whose fields
25.898 + * are being written, or if the type of the named field is not
25.899 + * <code>byte</code>
25.900 + */
25.901 + public abstract void put(String name, byte val);
25.902 +
25.903 + /**
25.904 + * Put the value of the named char field into the persistent field.
25.905 + *
25.906 + * @param name the name of the serializable field
25.907 + * @param val the value to assign to the field
25.908 + * @throws IllegalArgumentException if <code>name</code> does not
25.909 + * match the name of a serializable field for the class whose fields
25.910 + * are being written, or if the type of the named field is not
25.911 + * <code>char</code>
25.912 + */
25.913 + public abstract void put(String name, char val);
25.914 +
25.915 + /**
25.916 + * Put the value of the named short field into the persistent field.
25.917 + *
25.918 + * @param name the name of the serializable field
25.919 + * @param val the value to assign to the field
25.920 + * @throws IllegalArgumentException if <code>name</code> does not
25.921 + * match the name of a serializable field for the class whose fields
25.922 + * are being written, or if the type of the named field is not
25.923 + * <code>short</code>
25.924 + */
25.925 + public abstract void put(String name, short val);
25.926 +
25.927 + /**
25.928 + * Put the value of the named int field into the persistent field.
25.929 + *
25.930 + * @param name the name of the serializable field
25.931 + * @param val the value to assign to the field
25.932 + * @throws IllegalArgumentException if <code>name</code> does not
25.933 + * match the name of a serializable field for the class whose fields
25.934 + * are being written, or if the type of the named field is not
25.935 + * <code>int</code>
25.936 + */
25.937 + public abstract void put(String name, int val);
25.938 +
25.939 + /**
25.940 + * Put the value of the named long field into the persistent field.
25.941 + *
25.942 + * @param name the name of the serializable field
25.943 + * @param val the value to assign to the field
25.944 + * @throws IllegalArgumentException if <code>name</code> does not
25.945 + * match the name of a serializable field for the class whose fields
25.946 + * are being written, or if the type of the named field is not
25.947 + * <code>long</code>
25.948 + */
25.949 + public abstract void put(String name, long val);
25.950 +
25.951 + /**
25.952 + * Put the value of the named float field into the persistent field.
25.953 + *
25.954 + * @param name the name of the serializable field
25.955 + * @param val the value to assign to the field
25.956 + * @throws IllegalArgumentException if <code>name</code> does not
25.957 + * match the name of a serializable field for the class whose fields
25.958 + * are being written, or if the type of the named field is not
25.959 + * <code>float</code>
25.960 + */
25.961 + public abstract void put(String name, float val);
25.962 +
25.963 + /**
25.964 + * Put the value of the named double field into the persistent field.
25.965 + *
25.966 + * @param name the name of the serializable field
25.967 + * @param val the value to assign to the field
25.968 + * @throws IllegalArgumentException if <code>name</code> does not
25.969 + * match the name of a serializable field for the class whose fields
25.970 + * are being written, or if the type of the named field is not
25.971 + * <code>double</code>
25.972 + */
25.973 + public abstract void put(String name, double val);
25.974 +
25.975 + /**
25.976 + * Put the value of the named Object field into the persistent field.
25.977 + *
25.978 + * @param name the name of the serializable field
25.979 + * @param val the value to assign to the field
25.980 + * (which may be <code>null</code>)
25.981 + * @throws IllegalArgumentException if <code>name</code> does not
25.982 + * match the name of a serializable field for the class whose fields
25.983 + * are being written, or if the type of the named field is not a
25.984 + * reference type
25.985 + */
25.986 + public abstract void put(String name, Object val);
25.987 +
25.988 + /**
25.989 + * Write the data and fields to the specified ObjectOutput stream,
25.990 + * which must be the same stream that produced this
25.991 + * <code>PutField</code> object.
25.992 + *
25.993 + * @param out the stream to write the data and fields to
25.994 + * @throws IOException if I/O errors occur while writing to the
25.995 + * underlying stream
25.996 + * @throws IllegalArgumentException if the specified stream is not
25.997 + * the same stream that produced this <code>PutField</code>
25.998 + * object
25.999 + * @deprecated This method does not write the values contained by this
25.1000 + * <code>PutField</code> object in a proper format, and may
25.1001 + * result in corruption of the serialization stream. The
25.1002 + * correct way to write <code>PutField</code> data is by
25.1003 + * calling the {@link java.io.ObjectOutputStream#writeFields()}
25.1004 + * method.
25.1005 + */
25.1006 + @Deprecated
25.1007 + public abstract void write(ObjectOutput out) throws IOException;
25.1008 + }
25.1009 +
25.1010 +
25.1011 + /**
25.1012 + * Returns protocol version in use.
25.1013 + */
25.1014 + int getProtocolVersion() {
25.1015 + return protocol;
25.1016 + }
25.1017 +
25.1018 + /**
25.1019 + * Writes string without allowing it to be replaced in stream. Used by
25.1020 + * ObjectStreamClass to write class descriptor type strings.
25.1021 + */
25.1022 + void writeTypeString(String str) throws IOException {
25.1023 + int handle;
25.1024 + if (str == null) {
25.1025 + writeNull();
25.1026 + } else if ((handle = handles.lookup(str)) != -1) {
25.1027 + writeHandle(handle);
25.1028 + } else {
25.1029 + writeString(str, false);
25.1030 + }
25.1031 + }
25.1032 +
25.1033 + /**
25.1034 + * Verifies that this (possibly subclass) instance can be constructed
25.1035 + * without violating security constraints: the subclass must not override
25.1036 + * security-sensitive non-final methods, or else the
25.1037 + * "enableSubclassImplementation" SerializablePermission is checked.
25.1038 + */
25.1039 + private void verifySubclass() {
25.1040 + Class cl = getClass();
25.1041 + if (cl == ObjectOutputStream.class) {
25.1042 + return;
25.1043 + }
25.1044 + SecurityManager sm = System.getSecurityManager();
25.1045 + if (sm == null) {
25.1046 + return;
25.1047 + }
25.1048 + processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
25.1049 + WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
25.1050 + Boolean result = Caches.subclassAudits.get(key);
25.1051 + if (result == null) {
25.1052 + result = Boolean.valueOf(auditSubclass(cl));
25.1053 + Caches.subclassAudits.putIfAbsent(key, result);
25.1054 + }
25.1055 + if (result.booleanValue()) {
25.1056 + return;
25.1057 + }
25.1058 + sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
25.1059 + }
25.1060 +
25.1061 + /**
25.1062 + * Performs reflective checks on given subclass to verify that it doesn't
25.1063 + * override security-sensitive non-final methods. Returns true if subclass
25.1064 + * is "safe", false otherwise.
25.1065 + */
25.1066 + private static boolean auditSubclass(final Class subcl) {
25.1067 + Boolean result = AccessController.doPrivileged(
25.1068 + new PrivilegedAction<Boolean>() {
25.1069 + public Boolean run() {
25.1070 + for (Class cl = subcl;
25.1071 + cl != ObjectOutputStream.class;
25.1072 + cl = cl.getSuperclass())
25.1073 + {
25.1074 + try {
25.1075 + cl.getDeclaredMethod(
25.1076 + "writeUnshared", new Class[] { Object.class });
25.1077 + return Boolean.FALSE;
25.1078 + } catch (NoSuchMethodException ex) {
25.1079 + }
25.1080 + try {
25.1081 + cl.getDeclaredMethod("putFields", (Class[]) null);
25.1082 + return Boolean.FALSE;
25.1083 + } catch (NoSuchMethodException ex) {
25.1084 + }
25.1085 + }
25.1086 + return Boolean.TRUE;
25.1087 + }
25.1088 + }
25.1089 + );
25.1090 + return result.booleanValue();
25.1091 + }
25.1092 +
25.1093 + /**
25.1094 + * Clears internal data structures.
25.1095 + */
25.1096 + private void clear() {
25.1097 + subs.clear();
25.1098 + handles.clear();
25.1099 + }
25.1100 +
25.1101 + /**
25.1102 + * Underlying writeObject/writeUnshared implementation.
25.1103 + */
25.1104 + private void writeObject0(Object obj, boolean unshared)
25.1105 + throws IOException
25.1106 + {
25.1107 + boolean oldMode = bout.setBlockDataMode(false);
25.1108 + depth++;
25.1109 + try {
25.1110 + // handle previously written and non-replaceable objects
25.1111 + int h;
25.1112 + if ((obj = subs.lookup(obj)) == null) {
25.1113 + writeNull();
25.1114 + return;
25.1115 + } else if (!unshared && (h = handles.lookup(obj)) != -1) {
25.1116 + writeHandle(h);
25.1117 + return;
25.1118 + } else if (obj instanceof Class) {
25.1119 + writeClass((Class) obj, unshared);
25.1120 + return;
25.1121 + } else if (obj instanceof ObjectStreamClass) {
25.1122 + writeClassDesc((ObjectStreamClass) obj, unshared);
25.1123 + return;
25.1124 + }
25.1125 +
25.1126 + // check for replacement object
25.1127 + Object orig = obj;
25.1128 + Class cl = obj.getClass();
25.1129 + ObjectStreamClass desc;
25.1130 + for (;;) {
25.1131 + // REMIND: skip this check for strings/arrays?
25.1132 + Class repCl;
25.1133 + desc = ObjectStreamClass.lookup(cl, true);
25.1134 + if (!desc.hasWriteReplaceMethod() ||
25.1135 + (obj = desc.invokeWriteReplace(obj)) == null ||
25.1136 + (repCl = obj.getClass()) == cl)
25.1137 + {
25.1138 + break;
25.1139 + }
25.1140 + cl = repCl;
25.1141 + }
25.1142 + if (enableReplace) {
25.1143 + Object rep = replaceObject(obj);
25.1144 + if (rep != obj && rep != null) {
25.1145 + cl = rep.getClass();
25.1146 + desc = ObjectStreamClass.lookup(cl, true);
25.1147 + }
25.1148 + obj = rep;
25.1149 + }
25.1150 +
25.1151 + // if object replaced, run through original checks a second time
25.1152 + if (obj != orig) {
25.1153 + subs.assign(orig, obj);
25.1154 + if (obj == null) {
25.1155 + writeNull();
25.1156 + return;
25.1157 + } else if (!unshared && (h = handles.lookup(obj)) != -1) {
25.1158 + writeHandle(h);
25.1159 + return;
25.1160 + } else if (obj instanceof Class) {
25.1161 + writeClass((Class) obj, unshared);
25.1162 + return;
25.1163 + } else if (obj instanceof ObjectStreamClass) {
25.1164 + writeClassDesc((ObjectStreamClass) obj, unshared);
25.1165 + return;
25.1166 + }
25.1167 + }
25.1168 +
25.1169 + // remaining cases
25.1170 + if (obj instanceof String) {
25.1171 + writeString((String) obj, unshared);
25.1172 + } else if (cl.isArray()) {
25.1173 + writeArray(obj, desc, unshared);
25.1174 + } else if (obj instanceof Enum) {
25.1175 + writeEnum((Enum) obj, desc, unshared);
25.1176 + } else if (obj instanceof Serializable) {
25.1177 + writeOrdinaryObject(obj, desc, unshared);
25.1178 + } else {
25.1179 + if (extendedDebugInfo) {
25.1180 + throw new NotSerializableException(
25.1181 + cl.getName() + "\n" + debugInfoStack.toString());
25.1182 + } else {
25.1183 + throw new NotSerializableException(cl.getName());
25.1184 + }
25.1185 + }
25.1186 + } finally {
25.1187 + depth--;
25.1188 + bout.setBlockDataMode(oldMode);
25.1189 + }
25.1190 + }
25.1191 +
25.1192 + /**
25.1193 + * Writes null code to stream.
25.1194 + */
25.1195 + private void writeNull() throws IOException {
25.1196 + bout.writeByte(TC_NULL);
25.1197 + }
25.1198 +
25.1199 + /**
25.1200 + * Writes given object handle to stream.
25.1201 + */
25.1202 + private void writeHandle(int handle) throws IOException {
25.1203 + bout.writeByte(TC_REFERENCE);
25.1204 + bout.writeInt(baseWireHandle + handle);
25.1205 + }
25.1206 +
25.1207 + /**
25.1208 + * Writes representation of given class to stream.
25.1209 + */
25.1210 + private void writeClass(Class cl, boolean unshared) throws IOException {
25.1211 + bout.writeByte(TC_CLASS);
25.1212 + writeClassDesc(ObjectStreamClass.lookup(cl, true), false);
25.1213 + handles.assign(unshared ? null : cl);
25.1214 + }
25.1215 +
25.1216 + /**
25.1217 + * Writes representation of given class descriptor to stream.
25.1218 + */
25.1219 + private void writeClassDesc(ObjectStreamClass desc, boolean unshared)
25.1220 + throws IOException
25.1221 + {
25.1222 + int handle;
25.1223 + if (desc == null) {
25.1224 + writeNull();
25.1225 + } else if (!unshared && (handle = handles.lookup(desc)) != -1) {
25.1226 + writeHandle(handle);
25.1227 + } else if (desc.isProxy()) {
25.1228 + writeProxyDesc(desc, unshared);
25.1229 + } else {
25.1230 + writeNonProxyDesc(desc, unshared);
25.1231 + }
25.1232 + }
25.1233 +
25.1234 + /**
25.1235 + * Writes class descriptor representing a dynamic proxy class to stream.
25.1236 + */
25.1237 + private void writeProxyDesc(ObjectStreamClass desc, boolean unshared)
25.1238 + throws IOException
25.1239 + {
25.1240 + bout.writeByte(TC_PROXYCLASSDESC);
25.1241 + handles.assign(unshared ? null : desc);
25.1242 +
25.1243 + Class cl = desc.forClass();
25.1244 + Class[] ifaces = cl.getInterfaces();
25.1245 + bout.writeInt(ifaces.length);
25.1246 + for (int i = 0; i < ifaces.length; i++) {
25.1247 + bout.writeUTF(ifaces[i].getName());
25.1248 + }
25.1249 +
25.1250 + bout.setBlockDataMode(true);
25.1251 + annotateProxyClass(cl);
25.1252 + bout.setBlockDataMode(false);
25.1253 + bout.writeByte(TC_ENDBLOCKDATA);
25.1254 +
25.1255 + writeClassDesc(desc.getSuperDesc(), false);
25.1256 + }
25.1257 +
25.1258 + /**
25.1259 + * Writes class descriptor representing a standard (i.e., not a dynamic
25.1260 + * proxy) class to stream.
25.1261 + */
25.1262 + private void writeNonProxyDesc(ObjectStreamClass desc, boolean unshared)
25.1263 + throws IOException
25.1264 + {
25.1265 + bout.writeByte(TC_CLASSDESC);
25.1266 + handles.assign(unshared ? null : desc);
25.1267 +
25.1268 + if (protocol == PROTOCOL_VERSION_1) {
25.1269 + // do not invoke class descriptor write hook with old protocol
25.1270 + desc.writeNonProxy(this);
25.1271 + } else {
25.1272 + writeClassDescriptor(desc);
25.1273 + }
25.1274 +
25.1275 + Class cl = desc.forClass();
25.1276 + bout.setBlockDataMode(true);
25.1277 + annotateClass(cl);
25.1278 + bout.setBlockDataMode(false);
25.1279 + bout.writeByte(TC_ENDBLOCKDATA);
25.1280 +
25.1281 + writeClassDesc(desc.getSuperDesc(), false);
25.1282 + }
25.1283 +
25.1284 + /**
25.1285 + * Writes given string to stream, using standard or long UTF format
25.1286 + * depending on string length.
25.1287 + */
25.1288 + private void writeString(String str, boolean unshared) throws IOException {
25.1289 + handles.assign(unshared ? null : str);
25.1290 + long utflen = bout.getUTFLength(str);
25.1291 + if (utflen <= 0xFFFF) {
25.1292 + bout.writeByte(TC_STRING);
25.1293 + bout.writeUTF(str, utflen);
25.1294 + } else {
25.1295 + bout.writeByte(TC_LONGSTRING);
25.1296 + bout.writeLongUTF(str, utflen);
25.1297 + }
25.1298 + }
25.1299 +
25.1300 + /**
25.1301 + * Writes given array object to stream.
25.1302 + */
25.1303 + private void writeArray(Object array,
25.1304 + ObjectStreamClass desc,
25.1305 + boolean unshared)
25.1306 + throws IOException
25.1307 + {
25.1308 + bout.writeByte(TC_ARRAY);
25.1309 + writeClassDesc(desc, false);
25.1310 + handles.assign(unshared ? null : array);
25.1311 +
25.1312 + Class ccl = desc.forClass().getComponentType();
25.1313 + if (ccl.isPrimitive()) {
25.1314 + if (ccl == Integer.TYPE) {
25.1315 + int[] ia = (int[]) array;
25.1316 + bout.writeInt(ia.length);
25.1317 + bout.writeInts(ia, 0, ia.length);
25.1318 + } else if (ccl == Byte.TYPE) {
25.1319 + byte[] ba = (byte[]) array;
25.1320 + bout.writeInt(ba.length);
25.1321 + bout.write(ba, 0, ba.length, true);
25.1322 + } else if (ccl == Long.TYPE) {
25.1323 + long[] ja = (long[]) array;
25.1324 + bout.writeInt(ja.length);
25.1325 + bout.writeLongs(ja, 0, ja.length);
25.1326 + } else if (ccl == Float.TYPE) {
25.1327 + float[] fa = (float[]) array;
25.1328 + bout.writeInt(fa.length);
25.1329 + bout.writeFloats(fa, 0, fa.length);
25.1330 + } else if (ccl == Double.TYPE) {
25.1331 + double[] da = (double[]) array;
25.1332 + bout.writeInt(da.length);
25.1333 + bout.writeDoubles(da, 0, da.length);
25.1334 + } else if (ccl == Short.TYPE) {
25.1335 + short[] sa = (short[]) array;
25.1336 + bout.writeInt(sa.length);
25.1337 + bout.writeShorts(sa, 0, sa.length);
25.1338 + } else if (ccl == Character.TYPE) {
25.1339 + char[] ca = (char[]) array;
25.1340 + bout.writeInt(ca.length);
25.1341 + bout.writeChars(ca, 0, ca.length);
25.1342 + } else if (ccl == Boolean.TYPE) {
25.1343 + boolean[] za = (boolean[]) array;
25.1344 + bout.writeInt(za.length);
25.1345 + bout.writeBooleans(za, 0, za.length);
25.1346 + } else {
25.1347 + throw new InternalError();
25.1348 + }
25.1349 + } else {
25.1350 + Object[] objs = (Object[]) array;
25.1351 + int len = objs.length;
25.1352 + bout.writeInt(len);
25.1353 + if (extendedDebugInfo) {
25.1354 + debugInfoStack.push(
25.1355 + "array (class \"" + array.getClass().getName() +
25.1356 + "\", size: " + len + ")");
25.1357 + }
25.1358 + try {
25.1359 + for (int i = 0; i < len; i++) {
25.1360 + if (extendedDebugInfo) {
25.1361 + debugInfoStack.push(
25.1362 + "element of array (index: " + i + ")");
25.1363 + }
25.1364 + try {
25.1365 + writeObject0(objs[i], false);
25.1366 + } finally {
25.1367 + if (extendedDebugInfo) {
25.1368 + debugInfoStack.pop();
25.1369 + }
25.1370 + }
25.1371 + }
25.1372 + } finally {
25.1373 + if (extendedDebugInfo) {
25.1374 + debugInfoStack.pop();
25.1375 + }
25.1376 + }
25.1377 + }
25.1378 + }
25.1379 +
25.1380 + /**
25.1381 + * Writes given enum constant to stream.
25.1382 + */
25.1383 + private void writeEnum(Enum en,
25.1384 + ObjectStreamClass desc,
25.1385 + boolean unshared)
25.1386 + throws IOException
25.1387 + {
25.1388 + bout.writeByte(TC_ENUM);
25.1389 + ObjectStreamClass sdesc = desc.getSuperDesc();
25.1390 + writeClassDesc((sdesc.forClass() == Enum.class) ? desc : sdesc, false);
25.1391 + handles.assign(unshared ? null : en);
25.1392 + writeString(en.name(), false);
25.1393 + }
25.1394 +
25.1395 + /**
25.1396 + * Writes representation of a "ordinary" (i.e., not a String, Class,
25.1397 + * ObjectStreamClass, array, or enum constant) serializable object to the
25.1398 + * stream.
25.1399 + */
25.1400 + private void writeOrdinaryObject(Object obj,
25.1401 + ObjectStreamClass desc,
25.1402 + boolean unshared)
25.1403 + throws IOException
25.1404 + {
25.1405 + if (extendedDebugInfo) {
25.1406 + debugInfoStack.push(
25.1407 + (depth == 1 ? "root " : "") + "object (class \"" +
25.1408 + obj.getClass().getName() + "\", " + obj.toString() + ")");
25.1409 + }
25.1410 + try {
25.1411 + desc.checkSerialize();
25.1412 +
25.1413 + bout.writeByte(TC_OBJECT);
25.1414 + writeClassDesc(desc, false);
25.1415 + handles.assign(unshared ? null : obj);
25.1416 + if (desc.isExternalizable() && !desc.isProxy()) {
25.1417 + writeExternalData((Externalizable) obj);
25.1418 + } else {
25.1419 + writeSerialData(obj, desc);
25.1420 + }
25.1421 + } finally {
25.1422 + if (extendedDebugInfo) {
25.1423 + debugInfoStack.pop();
25.1424 + }
25.1425 + }
25.1426 + }
25.1427 +
25.1428 + /**
25.1429 + * Writes externalizable data of given object by invoking its
25.1430 + * writeExternal() method.
25.1431 + */
25.1432 + private void writeExternalData(Externalizable obj) throws IOException {
25.1433 + PutFieldImpl oldPut = curPut;
25.1434 + curPut = null;
25.1435 +
25.1436 + if (extendedDebugInfo) {
25.1437 + debugInfoStack.push("writeExternal data");
25.1438 + }
25.1439 + SerialCallbackContext oldContext = curContext;
25.1440 + try {
25.1441 + curContext = null;
25.1442 + if (protocol == PROTOCOL_VERSION_1) {
25.1443 + obj.writeExternal(this);
25.1444 + } else {
25.1445 + bout.setBlockDataMode(true);
25.1446 + obj.writeExternal(this);
25.1447 + bout.setBlockDataMode(false);
25.1448 + bout.writeByte(TC_ENDBLOCKDATA);
25.1449 + }
25.1450 + } finally {
25.1451 + curContext = oldContext;
25.1452 + if (extendedDebugInfo) {
25.1453 + debugInfoStack.pop();
25.1454 + }
25.1455 + }
25.1456 +
25.1457 + curPut = oldPut;
25.1458 + }
25.1459 +
25.1460 + /**
25.1461 + * Writes instance data for each serializable class of given object, from
25.1462 + * superclass to subclass.
25.1463 + */
25.1464 + private void writeSerialData(Object obj, ObjectStreamClass desc)
25.1465 + throws IOException
25.1466 + {
25.1467 + ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
25.1468 + for (int i = 0; i < slots.length; i++) {
25.1469 + ObjectStreamClass slotDesc = slots[i].desc;
25.1470 + if (slotDesc.hasWriteObjectMethod()) {
25.1471 + PutFieldImpl oldPut = curPut;
25.1472 + curPut = null;
25.1473 + SerialCallbackContext oldContext = curContext;
25.1474 +
25.1475 + if (extendedDebugInfo) {
25.1476 + debugInfoStack.push(
25.1477 + "custom writeObject data (class \"" +
25.1478 + slotDesc.getName() + "\")");
25.1479 + }
25.1480 + try {
25.1481 + curContext = new SerialCallbackContext(obj, slotDesc);
25.1482 + bout.setBlockDataMode(true);
25.1483 + slotDesc.invokeWriteObject(obj, this);
25.1484 + bout.setBlockDataMode(false);
25.1485 + bout.writeByte(TC_ENDBLOCKDATA);
25.1486 + } finally {
25.1487 + curContext.setUsed();
25.1488 + curContext = oldContext;
25.1489 + if (extendedDebugInfo) {
25.1490 + debugInfoStack.pop();
25.1491 + }
25.1492 + }
25.1493 +
25.1494 + curPut = oldPut;
25.1495 + } else {
25.1496 + defaultWriteFields(obj, slotDesc);
25.1497 + }
25.1498 + }
25.1499 + }
25.1500 +
25.1501 + /**
25.1502 + * Fetches and writes values of serializable fields of given object to
25.1503 + * stream. The given class descriptor specifies which field values to
25.1504 + * write, and in which order they should be written.
25.1505 + */
25.1506 + private void defaultWriteFields(Object obj, ObjectStreamClass desc)
25.1507 + throws IOException
25.1508 + {
25.1509 + // REMIND: perform conservative isInstance check here?
25.1510 + desc.checkDefaultSerialize();
25.1511 +
25.1512 + int primDataSize = desc.getPrimDataSize();
25.1513 + if (primVals == null || primVals.length < primDataSize) {
25.1514 + primVals = new byte[primDataSize];
25.1515 + }
25.1516 + desc.getPrimFieldValues(obj, primVals);
25.1517 + bout.write(primVals, 0, primDataSize, false);
25.1518 +
25.1519 + ObjectStreamField[] fields = desc.getFields(false);
25.1520 + Object[] objVals = new Object[desc.getNumObjFields()];
25.1521 + int numPrimFields = fields.length - objVals.length;
25.1522 + desc.getObjFieldValues(obj, objVals);
25.1523 + for (int i = 0; i < objVals.length; i++) {
25.1524 + if (extendedDebugInfo) {
25.1525 + debugInfoStack.push(
25.1526 + "field (class \"" + desc.getName() + "\", name: \"" +
25.1527 + fields[numPrimFields + i].getName() + "\", type: \"" +
25.1528 + fields[numPrimFields + i].getType() + "\")");
25.1529 + }
25.1530 + try {
25.1531 + writeObject0(objVals[i],
25.1532 + fields[numPrimFields + i].isUnshared());
25.1533 + } finally {
25.1534 + if (extendedDebugInfo) {
25.1535 + debugInfoStack.pop();
25.1536 + }
25.1537 + }
25.1538 + }
25.1539 + }
25.1540 +
25.1541 + /**
25.1542 + * Attempts to write to stream fatal IOException that has caused
25.1543 + * serialization to abort.
25.1544 + */
25.1545 + private void writeFatalException(IOException ex) throws IOException {
25.1546 + /*
25.1547 + * Note: the serialization specification states that if a second
25.1548 + * IOException occurs while attempting to serialize the original fatal
25.1549 + * exception to the stream, then a StreamCorruptedException should be
25.1550 + * thrown (section 2.1). However, due to a bug in previous
25.1551 + * implementations of serialization, StreamCorruptedExceptions were
25.1552 + * rarely (if ever) actually thrown--the "root" exceptions from
25.1553 + * underlying streams were thrown instead. This historical behavior is
25.1554 + * followed here for consistency.
25.1555 + */
25.1556 + clear();
25.1557 + boolean oldMode = bout.setBlockDataMode(false);
25.1558 + try {
25.1559 + bout.writeByte(TC_EXCEPTION);
25.1560 + writeObject0(ex, false);
25.1561 + clear();
25.1562 + } finally {
25.1563 + bout.setBlockDataMode(oldMode);
25.1564 + }
25.1565 + }
25.1566 +
25.1567 + /**
25.1568 + * Converts specified span of float values into byte values.
25.1569 + */
25.1570 + // REMIND: remove once hotspot inlines Float.floatToIntBits
25.1571 + private static native void floatsToBytes(float[] src, int srcpos,
25.1572 + byte[] dst, int dstpos,
25.1573 + int nfloats);
25.1574 +
25.1575 + /**
25.1576 + * Converts specified span of double values into byte values.
25.1577 + */
25.1578 + // REMIND: remove once hotspot inlines Double.doubleToLongBits
25.1579 + private static native void doublesToBytes(double[] src, int srcpos,
25.1580 + byte[] dst, int dstpos,
25.1581 + int ndoubles);
25.1582 +
25.1583 + /**
25.1584 + * Default PutField implementation.
25.1585 + */
25.1586 + private class PutFieldImpl extends PutField {
25.1587 +
25.1588 + /** class descriptor describing serializable fields */
25.1589 + private final ObjectStreamClass desc;
25.1590 + /** primitive field values */
25.1591 + private final byte[] primVals;
25.1592 + /** object field values */
25.1593 + private final Object[] objVals;
25.1594 +
25.1595 + /**
25.1596 + * Creates PutFieldImpl object for writing fields defined in given
25.1597 + * class descriptor.
25.1598 + */
25.1599 + PutFieldImpl(ObjectStreamClass desc) {
25.1600 + this.desc = desc;
25.1601 + primVals = new byte[desc.getPrimDataSize()];
25.1602 + objVals = new Object[desc.getNumObjFields()];
25.1603 + }
25.1604 +
25.1605 + public void put(String name, boolean val) {
25.1606 + Bits.putBoolean(primVals, getFieldOffset(name, Boolean.TYPE), val);
25.1607 + }
25.1608 +
25.1609 + public void put(String name, byte val) {
25.1610 + primVals[getFieldOffset(name, Byte.TYPE)] = val;
25.1611 + }
25.1612 +
25.1613 + public void put(String name, char val) {
25.1614 + Bits.putChar(primVals, getFieldOffset(name, Character.TYPE), val);
25.1615 + }
25.1616 +
25.1617 + public void put(String name, short val) {
25.1618 + Bits.putShort(primVals, getFieldOffset(name, Short.TYPE), val);
25.1619 + }
25.1620 +
25.1621 + public void put(String name, int val) {
25.1622 + Bits.putInt(primVals, getFieldOffset(name, Integer.TYPE), val);
25.1623 + }
25.1624 +
25.1625 + public void put(String name, float val) {
25.1626 + Bits.putFloat(primVals, getFieldOffset(name, Float.TYPE), val);
25.1627 + }
25.1628 +
25.1629 + public void put(String name, long val) {
25.1630 + Bits.putLong(primVals, getFieldOffset(name, Long.TYPE), val);
25.1631 + }
25.1632 +
25.1633 + public void put(String name, double val) {
25.1634 + Bits.putDouble(primVals, getFieldOffset(name, Double.TYPE), val);
25.1635 + }
25.1636 +
25.1637 + public void put(String name, Object val) {
25.1638 + objVals[getFieldOffset(name, Object.class)] = val;
25.1639 + }
25.1640 +
25.1641 + // deprecated in ObjectOutputStream.PutField
25.1642 + public void write(ObjectOutput out) throws IOException {
25.1643 + /*
25.1644 + * Applications should *not* use this method to write PutField
25.1645 + * data, as it will lead to stream corruption if the PutField
25.1646 + * object writes any primitive data (since block data mode is not
25.1647 + * unset/set properly, as is done in OOS.writeFields()). This
25.1648 + * broken implementation is being retained solely for behavioral
25.1649 + * compatibility, in order to support applications which use
25.1650 + * OOS.PutField.write() for writing only non-primitive data.
25.1651 + *
25.1652 + * Serialization of unshared objects is not implemented here since
25.1653 + * it is not necessary for backwards compatibility; also, unshared
25.1654 + * semantics may not be supported by the given ObjectOutput
25.1655 + * instance. Applications which write unshared objects using the
25.1656 + * PutField API must use OOS.writeFields().
25.1657 + */
25.1658 + if (ObjectOutputStream.this != out) {
25.1659 + throw new IllegalArgumentException("wrong stream");
25.1660 + }
25.1661 + out.write(primVals, 0, primVals.length);
25.1662 +
25.1663 + ObjectStreamField[] fields = desc.getFields(false);
25.1664 + int numPrimFields = fields.length - objVals.length;
25.1665 + // REMIND: warn if numPrimFields > 0?
25.1666 + for (int i = 0; i < objVals.length; i++) {
25.1667 + if (fields[numPrimFields + i].isUnshared()) {
25.1668 + throw new IOException("cannot write unshared object");
25.1669 + }
25.1670 + out.writeObject(objVals[i]);
25.1671 + }
25.1672 + }
25.1673 +
25.1674 + /**
25.1675 + * Writes buffered primitive data and object fields to stream.
25.1676 + */
25.1677 + void writeFields() throws IOException {
25.1678 + bout.write(primVals, 0, primVals.length, false);
25.1679 +
25.1680 + ObjectStreamField[] fields = desc.getFields(false);
25.1681 + int numPrimFields = fields.length - objVals.length;
25.1682 + for (int i = 0; i < objVals.length; i++) {
25.1683 + if (extendedDebugInfo) {
25.1684 + debugInfoStack.push(
25.1685 + "field (class \"" + desc.getName() + "\", name: \"" +
25.1686 + fields[numPrimFields + i].getName() + "\", type: \"" +
25.1687 + fields[numPrimFields + i].getType() + "\")");
25.1688 + }
25.1689 + try {
25.1690 + writeObject0(objVals[i],
25.1691 + fields[numPrimFields + i].isUnshared());
25.1692 + } finally {
25.1693 + if (extendedDebugInfo) {
25.1694 + debugInfoStack.pop();
25.1695 + }
25.1696 + }
25.1697 + }
25.1698 + }
25.1699 +
25.1700 + /**
25.1701 + * Returns offset of field with given name and type. A specified type
25.1702 + * of null matches all types, Object.class matches all non-primitive
25.1703 + * types, and any other non-null type matches assignable types only.
25.1704 + * Throws IllegalArgumentException if no matching field found.
25.1705 + */
25.1706 + private int getFieldOffset(String name, Class type) {
25.1707 + ObjectStreamField field = desc.getField(name, type);
25.1708 + if (field == null) {
25.1709 + throw new IllegalArgumentException("no such field " + name +
25.1710 + " with type " + type);
25.1711 + }
25.1712 + return field.getOffset();
25.1713 + }
25.1714 + }
25.1715 +
25.1716 + /**
25.1717 + * Buffered output stream with two modes: in default mode, outputs data in
25.1718 + * same format as DataOutputStream; in "block data" mode, outputs data
25.1719 + * bracketed by block data markers (see object serialization specification
25.1720 + * for details).
25.1721 + */
25.1722 + private static class BlockDataOutputStream
25.1723 + extends OutputStream implements DataOutput
25.1724 + {
25.1725 + /** maximum data block length */
25.1726 + private static final int MAX_BLOCK_SIZE = 1024;
25.1727 + /** maximum data block header length */
25.1728 + private static final int MAX_HEADER_SIZE = 5;
25.1729 + /** (tunable) length of char buffer (for writing strings) */
25.1730 + private static final int CHAR_BUF_SIZE = 256;
25.1731 +
25.1732 + /** buffer for writing general/block data */
25.1733 + private final byte[] buf = new byte[MAX_BLOCK_SIZE];
25.1734 + /** buffer for writing block data headers */
25.1735 + private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
25.1736 + /** char buffer for fast string writes */
25.1737 + private final char[] cbuf = new char[CHAR_BUF_SIZE];
25.1738 +
25.1739 + /** block data mode */
25.1740 + private boolean blkmode = false;
25.1741 + /** current offset into buf */
25.1742 + private int pos = 0;
25.1743 +
25.1744 + /** underlying output stream */
25.1745 + private final OutputStream out;
25.1746 + /** loopback stream (for data writes that span data blocks) */
25.1747 + private final DataOutputStream dout;
25.1748 +
25.1749 + /**
25.1750 + * Creates new BlockDataOutputStream on top of given underlying stream.
25.1751 + * Block data mode is turned off by default.
25.1752 + */
25.1753 + BlockDataOutputStream(OutputStream out) {
25.1754 + this.out = out;
25.1755 + dout = new DataOutputStream(this);
25.1756 + }
25.1757 +
25.1758 + /**
25.1759 + * Sets block data mode to the given mode (true == on, false == off)
25.1760 + * and returns the previous mode value. If the new mode is the same as
25.1761 + * the old mode, no action is taken. If the new mode differs from the
25.1762 + * old mode, any buffered data is flushed before switching to the new
25.1763 + * mode.
25.1764 + */
25.1765 + boolean setBlockDataMode(boolean mode) throws IOException {
25.1766 + if (blkmode == mode) {
25.1767 + return blkmode;
25.1768 + }
25.1769 + drain();
25.1770 + blkmode = mode;
25.1771 + return !blkmode;
25.1772 + }
25.1773 +
25.1774 + /**
25.1775 + * Returns true if the stream is currently in block data mode, false
25.1776 + * otherwise.
25.1777 + */
25.1778 + boolean getBlockDataMode() {
25.1779 + return blkmode;
25.1780 + }
25.1781 +
25.1782 + /* ----------------- generic output stream methods ----------------- */
25.1783 + /*
25.1784 + * The following methods are equivalent to their counterparts in
25.1785 + * OutputStream, except that they partition written data into data
25.1786 + * blocks when in block data mode.
25.1787 + */
25.1788 +
25.1789 + public void write(int b) throws IOException {
25.1790 + if (pos >= MAX_BLOCK_SIZE) {
25.1791 + drain();
25.1792 + }
25.1793 + buf[pos++] = (byte) b;
25.1794 + }
25.1795 +
25.1796 + public void write(byte[] b) throws IOException {
25.1797 + write(b, 0, b.length, false);
25.1798 + }
25.1799 +
25.1800 + public void write(byte[] b, int off, int len) throws IOException {
25.1801 + write(b, off, len, false);
25.1802 + }
25.1803 +
25.1804 + public void flush() throws IOException {
25.1805 + drain();
25.1806 + out.flush();
25.1807 + }
25.1808 +
25.1809 + public void close() throws IOException {
25.1810 + flush();
25.1811 + out.close();
25.1812 + }
25.1813 +
25.1814 + /**
25.1815 + * Writes specified span of byte values from given array. If copy is
25.1816 + * true, copies the values to an intermediate buffer before writing
25.1817 + * them to underlying stream (to avoid exposing a reference to the
25.1818 + * original byte array).
25.1819 + */
25.1820 + void write(byte[] b, int off, int len, boolean copy)
25.1821 + throws IOException
25.1822 + {
25.1823 + if (!(copy || blkmode)) { // write directly
25.1824 + drain();
25.1825 + out.write(b, off, len);
25.1826 + return;
25.1827 + }
25.1828 +
25.1829 + while (len > 0) {
25.1830 + if (pos >= MAX_BLOCK_SIZE) {
25.1831 + drain();
25.1832 + }
25.1833 + if (len >= MAX_BLOCK_SIZE && !copy && pos == 0) {
25.1834 + // avoid unnecessary copy
25.1835 + writeBlockHeader(MAX_BLOCK_SIZE);
25.1836 + out.write(b, off, MAX_BLOCK_SIZE);
25.1837 + off += MAX_BLOCK_SIZE;
25.1838 + len -= MAX_BLOCK_SIZE;
25.1839 + } else {
25.1840 + int wlen = Math.min(len, MAX_BLOCK_SIZE - pos);
25.1841 + System.arraycopy(b, off, buf, pos, wlen);
25.1842 + pos += wlen;
25.1843 + off += wlen;
25.1844 + len -= wlen;
25.1845 + }
25.1846 + }
25.1847 + }
25.1848 +
25.1849 + /**
25.1850 + * Writes all buffered data from this stream to the underlying stream,
25.1851 + * but does not flush underlying stream.
25.1852 + */
25.1853 + void drain() throws IOException {
25.1854 + if (pos == 0) {
25.1855 + return;
25.1856 + }
25.1857 + if (blkmode) {
25.1858 + writeBlockHeader(pos);
25.1859 + }
25.1860 + out.write(buf, 0, pos);
25.1861 + pos = 0;
25.1862 + }
25.1863 +
25.1864 + /**
25.1865 + * Writes block data header. Data blocks shorter than 256 bytes are
25.1866 + * prefixed with a 2-byte header; all others start with a 5-byte
25.1867 + * header.
25.1868 + */
25.1869 + private void writeBlockHeader(int len) throws IOException {
25.1870 + if (len <= 0xFF) {
25.1871 + hbuf[0] = TC_BLOCKDATA;
25.1872 + hbuf[1] = (byte) len;
25.1873 + out.write(hbuf, 0, 2);
25.1874 + } else {
25.1875 + hbuf[0] = TC_BLOCKDATALONG;
25.1876 + Bits.putInt(hbuf, 1, len);
25.1877 + out.write(hbuf, 0, 5);
25.1878 + }
25.1879 + }
25.1880 +
25.1881 +
25.1882 + /* ----------------- primitive data output methods ----------------- */
25.1883 + /*
25.1884 + * The following methods are equivalent to their counterparts in
25.1885 + * DataOutputStream, except that they partition written data into data
25.1886 + * blocks when in block data mode.
25.1887 + */
25.1888 +
25.1889 + public void writeBoolean(boolean v) throws IOException {
25.1890 + if (pos >= MAX_BLOCK_SIZE) {
25.1891 + drain();
25.1892 + }
25.1893 + Bits.putBoolean(buf, pos++, v);
25.1894 + }
25.1895 +
25.1896 + public void writeByte(int v) throws IOException {
25.1897 + if (pos >= MAX_BLOCK_SIZE) {
25.1898 + drain();
25.1899 + }
25.1900 + buf[pos++] = (byte) v;
25.1901 + }
25.1902 +
25.1903 + public void writeChar(int v) throws IOException {
25.1904 + if (pos + 2 <= MAX_BLOCK_SIZE) {
25.1905 + Bits.putChar(buf, pos, (char) v);
25.1906 + pos += 2;
25.1907 + } else {
25.1908 + dout.writeChar(v);
25.1909 + }
25.1910 + }
25.1911 +
25.1912 + public void writeShort(int v) throws IOException {
25.1913 + if (pos + 2 <= MAX_BLOCK_SIZE) {
25.1914 + Bits.putShort(buf, pos, (short) v);
25.1915 + pos += 2;
25.1916 + } else {
25.1917 + dout.writeShort(v);
25.1918 + }
25.1919 + }
25.1920 +
25.1921 + public void writeInt(int v) throws IOException {
25.1922 + if (pos + 4 <= MAX_BLOCK_SIZE) {
25.1923 + Bits.putInt(buf, pos, v);
25.1924 + pos += 4;
25.1925 + } else {
25.1926 + dout.writeInt(v);
25.1927 + }
25.1928 + }
25.1929 +
25.1930 + public void writeFloat(float v) throws IOException {
25.1931 + if (pos + 4 <= MAX_BLOCK_SIZE) {
25.1932 + Bits.putFloat(buf, pos, v);
25.1933 + pos += 4;
25.1934 + } else {
25.1935 + dout.writeFloat(v);
25.1936 + }
25.1937 + }
25.1938 +
25.1939 + public void writeLong(long v) throws IOException {
25.1940 + if (pos + 8 <= MAX_BLOCK_SIZE) {
25.1941 + Bits.putLong(buf, pos, v);
25.1942 + pos += 8;
25.1943 + } else {
25.1944 + dout.writeLong(v);
25.1945 + }
25.1946 + }
25.1947 +
25.1948 + public void writeDouble(double v) throws IOException {
25.1949 + if (pos + 8 <= MAX_BLOCK_SIZE) {
25.1950 + Bits.putDouble(buf, pos, v);
25.1951 + pos += 8;
25.1952 + } else {
25.1953 + dout.writeDouble(v);
25.1954 + }
25.1955 + }
25.1956 +
25.1957 + public void writeBytes(String s) throws IOException {
25.1958 + int endoff = s.length();
25.1959 + int cpos = 0;
25.1960 + int csize = 0;
25.1961 + for (int off = 0; off < endoff; ) {
25.1962 + if (cpos >= csize) {
25.1963 + cpos = 0;
25.1964 + csize = Math.min(endoff - off, CHAR_BUF_SIZE);
25.1965 + s.getChars(off, off + csize, cbuf, 0);
25.1966 + }
25.1967 + if (pos >= MAX_BLOCK_SIZE) {
25.1968 + drain();
25.1969 + }
25.1970 + int n = Math.min(csize - cpos, MAX_BLOCK_SIZE - pos);
25.1971 + int stop = pos + n;
25.1972 + while (pos < stop) {
25.1973 + buf[pos++] = (byte) cbuf[cpos++];
25.1974 + }
25.1975 + off += n;
25.1976 + }
25.1977 + }
25.1978 +
25.1979 + public void writeChars(String s) throws IOException {
25.1980 + int endoff = s.length();
25.1981 + for (int off = 0; off < endoff; ) {
25.1982 + int csize = Math.min(endoff - off, CHAR_BUF_SIZE);
25.1983 + s.getChars(off, off + csize, cbuf, 0);
25.1984 + writeChars(cbuf, 0, csize);
25.1985 + off += csize;
25.1986 + }
25.1987 + }
25.1988 +
25.1989 + public void writeUTF(String s) throws IOException {
25.1990 + writeUTF(s, getUTFLength(s));
25.1991 + }
25.1992 +
25.1993 +
25.1994 + /* -------------- primitive data array output methods -------------- */
25.1995 + /*
25.1996 + * The following methods write out spans of primitive data values.
25.1997 + * Though equivalent to calling the corresponding primitive write
25.1998 + * methods repeatedly, these methods are optimized for writing groups
25.1999 + * of primitive data values more efficiently.
25.2000 + */
25.2001 +
25.2002 + void writeBooleans(boolean[] v, int off, int len) throws IOException {
25.2003 + int endoff = off + len;
25.2004 + while (off < endoff) {
25.2005 + if (pos >= MAX_BLOCK_SIZE) {
25.2006 + drain();
25.2007 + }
25.2008 + int stop = Math.min(endoff, off + (MAX_BLOCK_SIZE - pos));
25.2009 + while (off < stop) {
25.2010 + Bits.putBoolean(buf, pos++, v[off++]);
25.2011 + }
25.2012 + }
25.2013 + }
25.2014 +
25.2015 + void writeChars(char[] v, int off, int len) throws IOException {
25.2016 + int limit = MAX_BLOCK_SIZE - 2;
25.2017 + int endoff = off + len;
25.2018 + while (off < endoff) {
25.2019 + if (pos <= limit) {
25.2020 + int avail = (MAX_BLOCK_SIZE - pos) >> 1;
25.2021 + int stop = Math.min(endoff, off + avail);
25.2022 + while (off < stop) {
25.2023 + Bits.putChar(buf, pos, v[off++]);
25.2024 + pos += 2;
25.2025 + }
25.2026 + } else {
25.2027 + dout.writeChar(v[off++]);
25.2028 + }
25.2029 + }
25.2030 + }
25.2031 +
25.2032 + void writeShorts(short[] v, int off, int len) throws IOException {
25.2033 + int limit = MAX_BLOCK_SIZE - 2;
25.2034 + int endoff = off + len;
25.2035 + while (off < endoff) {
25.2036 + if (pos <= limit) {
25.2037 + int avail = (MAX_BLOCK_SIZE - pos) >> 1;
25.2038 + int stop = Math.min(endoff, off + avail);
25.2039 + while (off < stop) {
25.2040 + Bits.putShort(buf, pos, v[off++]);
25.2041 + pos += 2;
25.2042 + }
25.2043 + } else {
25.2044 + dout.writeShort(v[off++]);
25.2045 + }
25.2046 + }
25.2047 + }
25.2048 +
25.2049 + void writeInts(int[] v, int off, int len) throws IOException {
25.2050 + int limit = MAX_BLOCK_SIZE - 4;
25.2051 + int endoff = off + len;
25.2052 + while (off < endoff) {
25.2053 + if (pos <= limit) {
25.2054 + int avail = (MAX_BLOCK_SIZE - pos) >> 2;
25.2055 + int stop = Math.min(endoff, off + avail);
25.2056 + while (off < stop) {
25.2057 + Bits.putInt(buf, pos, v[off++]);
25.2058 + pos += 4;
25.2059 + }
25.2060 + } else {
25.2061 + dout.writeInt(v[off++]);
25.2062 + }
25.2063 + }
25.2064 + }
25.2065 +
25.2066 + void writeFloats(float[] v, int off, int len) throws IOException {
25.2067 + int limit = MAX_BLOCK_SIZE - 4;
25.2068 + int endoff = off + len;
25.2069 + while (off < endoff) {
25.2070 + if (pos <= limit) {
25.2071 + int avail = (MAX_BLOCK_SIZE - pos) >> 2;
25.2072 + int chunklen = Math.min(endoff - off, avail);
25.2073 + floatsToBytes(v, off, buf, pos, chunklen);
25.2074 + off += chunklen;
25.2075 + pos += chunklen << 2;
25.2076 + } else {
25.2077 + dout.writeFloat(v[off++]);
25.2078 + }
25.2079 + }
25.2080 + }
25.2081 +
25.2082 + void writeLongs(long[] v, int off, int len) throws IOException {
25.2083 + int limit = MAX_BLOCK_SIZE - 8;
25.2084 + int endoff = off + len;
25.2085 + while (off < endoff) {
25.2086 + if (pos <= limit) {
25.2087 + int avail = (MAX_BLOCK_SIZE - pos) >> 3;
25.2088 + int stop = Math.min(endoff, off + avail);
25.2089 + while (off < stop) {
25.2090 + Bits.putLong(buf, pos, v[off++]);
25.2091 + pos += 8;
25.2092 + }
25.2093 + } else {
25.2094 + dout.writeLong(v[off++]);
25.2095 + }
25.2096 + }
25.2097 + }
25.2098 +
25.2099 + void writeDoubles(double[] v, int off, int len) throws IOException {
25.2100 + int limit = MAX_BLOCK_SIZE - 8;
25.2101 + int endoff = off + len;
25.2102 + while (off < endoff) {
25.2103 + if (pos <= limit) {
25.2104 + int avail = (MAX_BLOCK_SIZE - pos) >> 3;
25.2105 + int chunklen = Math.min(endoff - off, avail);
25.2106 + doublesToBytes(v, off, buf, pos, chunklen);
25.2107 + off += chunklen;
25.2108 + pos += chunklen << 3;
25.2109 + } else {
25.2110 + dout.writeDouble(v[off++]);
25.2111 + }
25.2112 + }
25.2113 + }
25.2114 +
25.2115 + /**
25.2116 + * Returns the length in bytes of the UTF encoding of the given string.
25.2117 + */
25.2118 + long getUTFLength(String s) {
25.2119 + int len = s.length();
25.2120 + long utflen = 0;
25.2121 + for (int off = 0; off < len; ) {
25.2122 + int csize = Math.min(len - off, CHAR_BUF_SIZE);
25.2123 + s.getChars(off, off + csize, cbuf, 0);
25.2124 + for (int cpos = 0; cpos < csize; cpos++) {
25.2125 + char c = cbuf[cpos];
25.2126 + if (c >= 0x0001 && c <= 0x007F) {
25.2127 + utflen++;
25.2128 + } else if (c > 0x07FF) {
25.2129 + utflen += 3;
25.2130 + } else {
25.2131 + utflen += 2;
25.2132 + }
25.2133 + }
25.2134 + off += csize;
25.2135 + }
25.2136 + return utflen;
25.2137 + }
25.2138 +
25.2139 + /**
25.2140 + * Writes the given string in UTF format. This method is used in
25.2141 + * situations where the UTF encoding length of the string is already
25.2142 + * known; specifying it explicitly avoids a prescan of the string to
25.2143 + * determine its UTF length.
25.2144 + */
25.2145 + void writeUTF(String s, long utflen) throws IOException {
25.2146 + if (utflen > 0xFFFFL) {
25.2147 + throw new UTFDataFormatException();
25.2148 + }
25.2149 + writeShort((int) utflen);
25.2150 + if (utflen == (long) s.length()) {
25.2151 + writeBytes(s);
25.2152 + } else {
25.2153 + writeUTFBody(s);
25.2154 + }
25.2155 + }
25.2156 +
25.2157 + /**
25.2158 + * Writes given string in "long" UTF format. "Long" UTF format is
25.2159 + * identical to standard UTF, except that it uses an 8 byte header
25.2160 + * (instead of the standard 2 bytes) to convey the UTF encoding length.
25.2161 + */
25.2162 + void writeLongUTF(String s) throws IOException {
25.2163 + writeLongUTF(s, getUTFLength(s));
25.2164 + }
25.2165 +
25.2166 + /**
25.2167 + * Writes given string in "long" UTF format, where the UTF encoding
25.2168 + * length of the string is already known.
25.2169 + */
25.2170 + void writeLongUTF(String s, long utflen) throws IOException {
25.2171 + writeLong(utflen);
25.2172 + if (utflen == (long) s.length()) {
25.2173 + writeBytes(s);
25.2174 + } else {
25.2175 + writeUTFBody(s);
25.2176 + }
25.2177 + }
25.2178 +
25.2179 + /**
25.2180 + * Writes the "body" (i.e., the UTF representation minus the 2-byte or
25.2181 + * 8-byte length header) of the UTF encoding for the given string.
25.2182 + */
25.2183 + private void writeUTFBody(String s) throws IOException {
25.2184 + int limit = MAX_BLOCK_SIZE - 3;
25.2185 + int len = s.length();
25.2186 + for (int off = 0; off < len; ) {
25.2187 + int csize = Math.min(len - off, CHAR_BUF_SIZE);
25.2188 + s.getChars(off, off + csize, cbuf, 0);
25.2189 + for (int cpos = 0; cpos < csize; cpos++) {
25.2190 + char c = cbuf[cpos];
25.2191 + if (pos <= limit) {
25.2192 + if (c <= 0x007F && c != 0) {
25.2193 + buf[pos++] = (byte) c;
25.2194 + } else if (c > 0x07FF) {
25.2195 + buf[pos + 2] = (byte) (0x80 | ((c >> 0) & 0x3F));
25.2196 + buf[pos + 1] = (byte) (0x80 | ((c >> 6) & 0x3F));
25.2197 + buf[pos + 0] = (byte) (0xE0 | ((c >> 12) & 0x0F));
25.2198 + pos += 3;
25.2199 + } else {
25.2200 + buf[pos + 1] = (byte) (0x80 | ((c >> 0) & 0x3F));
25.2201 + buf[pos + 0] = (byte) (0xC0 | ((c >> 6) & 0x1F));
25.2202 + pos += 2;
25.2203 + }
25.2204 + } else { // write one byte at a time to normalize block
25.2205 + if (c <= 0x007F && c != 0) {
25.2206 + write(c);
25.2207 + } else if (c > 0x07FF) {
25.2208 + write(0xE0 | ((c >> 12) & 0x0F));
25.2209 + write(0x80 | ((c >> 6) & 0x3F));
25.2210 + write(0x80 | ((c >> 0) & 0x3F));
25.2211 + } else {
25.2212 + write(0xC0 | ((c >> 6) & 0x1F));
25.2213 + write(0x80 | ((c >> 0) & 0x3F));
25.2214 + }
25.2215 + }
25.2216 + }
25.2217 + off += csize;
25.2218 + }
25.2219 + }
25.2220 + }
25.2221 +
25.2222 + /**
25.2223 + * Lightweight identity hash table which maps objects to integer handles,
25.2224 + * assigned in ascending order.
25.2225 + */
25.2226 + private static class HandleTable {
25.2227 +
25.2228 + /* number of mappings in table/next available handle */
25.2229 + private int size;
25.2230 + /* size threshold determining when to expand hash spine */
25.2231 + private int threshold;
25.2232 + /* factor for computing size threshold */
25.2233 + private final float loadFactor;
25.2234 + /* maps hash value -> candidate handle value */
25.2235 + private int[] spine;
25.2236 + /* maps handle value -> next candidate handle value */
25.2237 + private int[] next;
25.2238 + /* maps handle value -> associated object */
25.2239 + private Object[] objs;
25.2240 +
25.2241 + /**
25.2242 + * Creates new HandleTable with given capacity and load factor.
25.2243 + */
25.2244 + HandleTable(int initialCapacity, float loadFactor) {
25.2245 + this.loadFactor = loadFactor;
25.2246 + spine = new int[initialCapacity];
25.2247 + next = new int[initialCapacity];
25.2248 + objs = new Object[initialCapacity];
25.2249 + threshold = (int) (initialCapacity * loadFactor);
25.2250 + clear();
25.2251 + }
25.2252 +
25.2253 + /**
25.2254 + * Assigns next available handle to given object, and returns handle
25.2255 + * value. Handles are assigned in ascending order starting at 0.
25.2256 + */
25.2257 + int assign(Object obj) {
25.2258 + if (size >= next.length) {
25.2259 + growEntries();
25.2260 + }
25.2261 + if (size >= threshold) {
25.2262 + growSpine();
25.2263 + }
25.2264 + insert(obj, size);
25.2265 + return size++;
25.2266 + }
25.2267 +
25.2268 + /**
25.2269 + * Looks up and returns handle associated with given object, or -1 if
25.2270 + * no mapping found.
25.2271 + */
25.2272 + int lookup(Object obj) {
25.2273 + if (size == 0) {
25.2274 + return -1;
25.2275 + }
25.2276 + int index = hash(obj) % spine.length;
25.2277 + for (int i = spine[index]; i >= 0; i = next[i]) {
25.2278 + if (objs[i] == obj) {
25.2279 + return i;
25.2280 + }
25.2281 + }
25.2282 + return -1;
25.2283 + }
25.2284 +
25.2285 + /**
25.2286 + * Resets table to its initial (empty) state.
25.2287 + */
25.2288 + void clear() {
25.2289 + Arrays.fill(spine, -1);
25.2290 + Arrays.fill(objs, 0, size, null);
25.2291 + size = 0;
25.2292 + }
25.2293 +
25.2294 + /**
25.2295 + * Returns the number of mappings currently in table.
25.2296 + */
25.2297 + int size() {
25.2298 + return size;
25.2299 + }
25.2300 +
25.2301 + /**
25.2302 + * Inserts mapping object -> handle mapping into table. Assumes table
25.2303 + * is large enough to accommodate new mapping.
25.2304 + */
25.2305 + private void insert(Object obj, int handle) {
25.2306 + int index = hash(obj) % spine.length;
25.2307 + objs[handle] = obj;
25.2308 + next[handle] = spine[index];
25.2309 + spine[index] = handle;
25.2310 + }
25.2311 +
25.2312 + /**
25.2313 + * Expands the hash "spine" -- equivalent to increasing the number of
25.2314 + * buckets in a conventional hash table.
25.2315 + */
25.2316 + private void growSpine() {
25.2317 + spine = new int[(spine.length << 1) + 1];
25.2318 + threshold = (int) (spine.length * loadFactor);
25.2319 + Arrays.fill(spine, -1);
25.2320 + for (int i = 0; i < size; i++) {
25.2321 + insert(objs[i], i);
25.2322 + }
25.2323 + }
25.2324 +
25.2325 + /**
25.2326 + * Increases hash table capacity by lengthening entry arrays.
25.2327 + */
25.2328 + private void growEntries() {
25.2329 + int newLength = (next.length << 1) + 1;
25.2330 + int[] newNext = new int[newLength];
25.2331 + System.arraycopy(next, 0, newNext, 0, size);
25.2332 + next = newNext;
25.2333 +
25.2334 + Object[] newObjs = new Object[newLength];
25.2335 + System.arraycopy(objs, 0, newObjs, 0, size);
25.2336 + objs = newObjs;
25.2337 + }
25.2338 +
25.2339 + /**
25.2340 + * Returns hash value for given object.
25.2341 + */
25.2342 + private int hash(Object obj) {
25.2343 + return System.identityHashCode(obj) & 0x7FFFFFFF;
25.2344 + }
25.2345 + }
25.2346 +
25.2347 + /**
25.2348 + * Lightweight identity hash table which maps objects to replacement
25.2349 + * objects.
25.2350 + */
25.2351 + private static class ReplaceTable {
25.2352 +
25.2353 + /* maps object -> index */
25.2354 + private final HandleTable htab;
25.2355 + /* maps index -> replacement object */
25.2356 + private Object[] reps;
25.2357 +
25.2358 + /**
25.2359 + * Creates new ReplaceTable with given capacity and load factor.
25.2360 + */
25.2361 + ReplaceTable(int initialCapacity, float loadFactor) {
25.2362 + htab = new HandleTable(initialCapacity, loadFactor);
25.2363 + reps = new Object[initialCapacity];
25.2364 + }
25.2365 +
25.2366 + /**
25.2367 + * Enters mapping from object to replacement object.
25.2368 + */
25.2369 + void assign(Object obj, Object rep) {
25.2370 + int index = htab.assign(obj);
25.2371 + while (index >= reps.length) {
25.2372 + grow();
25.2373 + }
25.2374 + reps[index] = rep;
25.2375 + }
25.2376 +
25.2377 + /**
25.2378 + * Looks up and returns replacement for given object. If no
25.2379 + * replacement is found, returns the lookup object itself.
25.2380 + */
25.2381 + Object lookup(Object obj) {
25.2382 + int index = htab.lookup(obj);
25.2383 + return (index >= 0) ? reps[index] : obj;
25.2384 + }
25.2385 +
25.2386 + /**
25.2387 + * Resets table to its initial (empty) state.
25.2388 + */
25.2389 + void clear() {
25.2390 + Arrays.fill(reps, 0, htab.size(), null);
25.2391 + htab.clear();
25.2392 + }
25.2393 +
25.2394 + /**
25.2395 + * Returns the number of mappings currently in table.
25.2396 + */
25.2397 + int size() {
25.2398 + return htab.size();
25.2399 + }
25.2400 +
25.2401 + /**
25.2402 + * Increases table capacity.
25.2403 + */
25.2404 + private void grow() {
25.2405 + Object[] newReps = new Object[(reps.length << 1) + 1];
25.2406 + System.arraycopy(reps, 0, newReps, 0, reps.length);
25.2407 + reps = newReps;
25.2408 + }
25.2409 + }
25.2410 +
25.2411 + /**
25.2412 + * Stack to keep debug information about the state of the
25.2413 + * serialization process, for embedding in exception messages.
25.2414 + */
25.2415 + private static class DebugTraceInfoStack {
25.2416 + private final List<String> stack;
25.2417 +
25.2418 + DebugTraceInfoStack() {
25.2419 + stack = new ArrayList<>();
25.2420 + }
25.2421 +
25.2422 + /**
25.2423 + * Removes all of the elements from enclosed list.
25.2424 + */
25.2425 + void clear() {
25.2426 + stack.clear();
25.2427 + }
25.2428 +
25.2429 + /**
25.2430 + * Removes the object at the top of enclosed list.
25.2431 + */
25.2432 + void pop() {
25.2433 + stack.remove(stack.size()-1);
25.2434 + }
25.2435 +
25.2436 + /**
25.2437 + * Pushes a String onto the top of enclosed list.
25.2438 + */
25.2439 + void push(String entry) {
25.2440 + stack.add("\t- " + entry);
25.2441 + }
25.2442 +
25.2443 + /**
25.2444 + * Returns a string representation of this object
25.2445 + */
25.2446 + public String toString() {
25.2447 + StringBuilder buffer = new StringBuilder();
25.2448 + if (!stack.isEmpty()) {
25.2449 + for(int i = stack.size(); i > 0; i-- ) {
25.2450 + buffer.append(stack.get(i-1) + ((i != 1) ? "\n" : ""));
25.2451 + }
25.2452 + }
25.2453 + return buffer.toString();
25.2454 + }
25.2455 + }
25.2456 +
25.2457 +}
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
26.2 +++ b/emul/compact/src/main/java/java/io/ObjectStreamClass.java Fri Feb 01 16:35:42 2013 +0100
26.3 @@ -0,0 +1,2304 @@
26.4 +/*
26.5 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
26.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
26.7 + *
26.8 + * This code is free software; you can redistribute it and/or modify it
26.9 + * under the terms of the GNU General Public License version 2 only, as
26.10 + * published by the Free Software Foundation. Oracle designates this
26.11 + * particular file as subject to the "Classpath" exception as provided
26.12 + * by Oracle in the LICENSE file that accompanied this code.
26.13 + *
26.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
26.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
26.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26.17 + * version 2 for more details (a copy is included in the LICENSE file that
26.18 + * accompanied this code).
26.19 + *
26.20 + * You should have received a copy of the GNU General Public License version
26.21 + * 2 along with this work; if not, write to the Free Software Foundation,
26.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26.23 + *
26.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
26.25 + * or visit www.oracle.com if you need additional information or have any
26.26 + * questions.
26.27 + */
26.28 +
26.29 +package java.io;
26.30 +
26.31 +import java.lang.ref.Reference;
26.32 +import java.lang.ref.ReferenceQueue;
26.33 +import java.lang.ref.SoftReference;
26.34 +import java.lang.ref.WeakReference;
26.35 +import java.lang.reflect.Constructor;
26.36 +import java.lang.reflect.Field;
26.37 +import java.lang.reflect.InvocationTargetException;
26.38 +import java.lang.reflect.Member;
26.39 +import java.lang.reflect.Method;
26.40 +import java.lang.reflect.Modifier;
26.41 +import java.lang.reflect.Proxy;
26.42 +import java.security.AccessController;
26.43 +import java.security.MessageDigest;
26.44 +import java.security.NoSuchAlgorithmException;
26.45 +import java.security.PrivilegedAction;
26.46 +import java.util.ArrayList;
26.47 +import java.util.Arrays;
26.48 +import java.util.Collections;
26.49 +import java.util.Comparator;
26.50 +import java.util.HashSet;
26.51 +import java.util.Set;
26.52 +import java.util.concurrent.ConcurrentHashMap;
26.53 +import java.util.concurrent.ConcurrentMap;
26.54 +import sun.misc.Unsafe;
26.55 +import sun.reflect.ReflectionFactory;
26.56 +
26.57 +/**
26.58 + * Serialization's descriptor for classes. It contains the name and
26.59 + * serialVersionUID of the class. The ObjectStreamClass for a specific class
26.60 + * loaded in this Java VM can be found/created using the lookup method.
26.61 + *
26.62 + * <p>The algorithm to compute the SerialVersionUID is described in
26.63 + * <a href="../../../platform/serialization/spec/class.html#4100">Object
26.64 + * Serialization Specification, Section 4.6, Stream Unique Identifiers</a>.
26.65 + *
26.66 + * @author Mike Warres
26.67 + * @author Roger Riggs
26.68 + * @see ObjectStreamField
26.69 + * @see <a href="../../../platform/serialization/spec/class.html">Object Serialization Specification, Section 4, Class Descriptors</a>
26.70 + * @since JDK1.1
26.71 + */
26.72 +public class ObjectStreamClass implements Serializable {
26.73 +
26.74 + /** serialPersistentFields value indicating no serializable fields */
26.75 + public static final ObjectStreamField[] NO_FIELDS =
26.76 + new ObjectStreamField[0];
26.77 +
26.78 + private static final long serialVersionUID = -6120832682080437368L;
26.79 + private static final ObjectStreamField[] serialPersistentFields =
26.80 + NO_FIELDS;
26.81 +
26.82 + /** reflection factory for obtaining serialization constructors */
26.83 + private static final ReflectionFactory reflFactory =
26.84 + AccessController.doPrivileged(
26.85 + new ReflectionFactory.GetReflectionFactoryAction());
26.86 +
26.87 + private static class Caches {
26.88 + /** cache mapping local classes -> descriptors */
26.89 + static final ConcurrentMap<WeakClassKey,Reference<?>> localDescs =
26.90 + new ConcurrentHashMap<>();
26.91 +
26.92 + /** cache mapping field group/local desc pairs -> field reflectors */
26.93 + static final ConcurrentMap<FieldReflectorKey,Reference<?>> reflectors =
26.94 + new ConcurrentHashMap<>();
26.95 +
26.96 + /** queue for WeakReferences to local classes */
26.97 + private static final ReferenceQueue<Class<?>> localDescsQueue =
26.98 + new ReferenceQueue<>();
26.99 + /** queue for WeakReferences to field reflectors keys */
26.100 + private static final ReferenceQueue<Class<?>> reflectorsQueue =
26.101 + new ReferenceQueue<>();
26.102 + }
26.103 +
26.104 + /** class associated with this descriptor (if any) */
26.105 + private Class<?> cl;
26.106 + /** name of class represented by this descriptor */
26.107 + private String name;
26.108 + /** serialVersionUID of represented class (null if not computed yet) */
26.109 + private volatile Long suid;
26.110 +
26.111 + /** true if represents dynamic proxy class */
26.112 + private boolean isProxy;
26.113 + /** true if represents enum type */
26.114 + private boolean isEnum;
26.115 + /** true if represented class implements Serializable */
26.116 + private boolean serializable;
26.117 + /** true if represented class implements Externalizable */
26.118 + private boolean externalizable;
26.119 + /** true if desc has data written by class-defined writeObject method */
26.120 + private boolean hasWriteObjectData;
26.121 + /**
26.122 + * true if desc has externalizable data written in block data format; this
26.123 + * must be true by default to accommodate ObjectInputStream subclasses which
26.124 + * override readClassDescriptor() to return class descriptors obtained from
26.125 + * ObjectStreamClass.lookup() (see 4461737)
26.126 + */
26.127 + private boolean hasBlockExternalData = true;
26.128 +
26.129 + /** exception (if any) thrown while attempting to resolve class */
26.130 + private ClassNotFoundException resolveEx;
26.131 + /** exception (if any) to throw if non-enum deserialization attempted */
26.132 + private InvalidClassException deserializeEx;
26.133 + /** exception (if any) to throw if non-enum serialization attempted */
26.134 + private InvalidClassException serializeEx;
26.135 + /** exception (if any) to throw if default serialization attempted */
26.136 + private InvalidClassException defaultSerializeEx;
26.137 +
26.138 + /** serializable fields */
26.139 + private ObjectStreamField[] fields;
26.140 + /** aggregate marshalled size of primitive fields */
26.141 + private int primDataSize;
26.142 + /** number of non-primitive fields */
26.143 + private int numObjFields;
26.144 + /** reflector for setting/getting serializable field values */
26.145 + private FieldReflector fieldRefl;
26.146 + /** data layout of serialized objects described by this class desc */
26.147 + private volatile ClassDataSlot[] dataLayout;
26.148 +
26.149 + /** serialization-appropriate constructor, or null if none */
26.150 + private Constructor cons;
26.151 + /** class-defined writeObject method, or null if none */
26.152 + private Method writeObjectMethod;
26.153 + /** class-defined readObject method, or null if none */
26.154 + private Method readObjectMethod;
26.155 + /** class-defined readObjectNoData method, or null if none */
26.156 + private Method readObjectNoDataMethod;
26.157 + /** class-defined writeReplace method, or null if none */
26.158 + private Method writeReplaceMethod;
26.159 + /** class-defined readResolve method, or null if none */
26.160 + private Method readResolveMethod;
26.161 +
26.162 + /** local class descriptor for represented class (may point to self) */
26.163 + private ObjectStreamClass localDesc;
26.164 + /** superclass descriptor appearing in stream */
26.165 + private ObjectStreamClass superDesc;
26.166 +
26.167 + /**
26.168 + * Initializes native code.
26.169 + */
26.170 + private static native void initNative();
26.171 + static {
26.172 + initNative();
26.173 + }
26.174 +
26.175 + /**
26.176 + * Find the descriptor for a class that can be serialized. Creates an
26.177 + * ObjectStreamClass instance if one does not exist yet for class. Null is
26.178 + * returned if the specified class does not implement java.io.Serializable
26.179 + * or java.io.Externalizable.
26.180 + *
26.181 + * @param cl class for which to get the descriptor
26.182 + * @return the class descriptor for the specified class
26.183 + */
26.184 + public static ObjectStreamClass lookup(Class<?> cl) {
26.185 + return lookup(cl, false);
26.186 + }
26.187 +
26.188 + /**
26.189 + * Returns the descriptor for any class, regardless of whether it
26.190 + * implements {@link Serializable}.
26.191 + *
26.192 + * @param cl class for which to get the descriptor
26.193 + * @return the class descriptor for the specified class
26.194 + * @since 1.6
26.195 + */
26.196 + public static ObjectStreamClass lookupAny(Class<?> cl) {
26.197 + return lookup(cl, true);
26.198 + }
26.199 +
26.200 + /**
26.201 + * Returns the name of the class described by this descriptor.
26.202 + * This method returns the name of the class in the format that
26.203 + * is used by the {@link Class#getName} method.
26.204 + *
26.205 + * @return a string representing the name of the class
26.206 + */
26.207 + public String getName() {
26.208 + return name;
26.209 + }
26.210 +
26.211 + /**
26.212 + * Return the serialVersionUID for this class. The serialVersionUID
26.213 + * defines a set of classes all with the same name that have evolved from a
26.214 + * common root class and agree to be serialized and deserialized using a
26.215 + * common format. NonSerializable classes have a serialVersionUID of 0L.
26.216 + *
26.217 + * @return the SUID of the class described by this descriptor
26.218 + */
26.219 + public long getSerialVersionUID() {
26.220 + // REMIND: synchronize instead of relying on volatile?
26.221 + if (suid == null) {
26.222 + suid = AccessController.doPrivileged(
26.223 + new PrivilegedAction<Long>() {
26.224 + public Long run() {
26.225 + return computeDefaultSUID(cl);
26.226 + }
26.227 + }
26.228 + );
26.229 + }
26.230 + return suid.longValue();
26.231 + }
26.232 +
26.233 + /**
26.234 + * Return the class in the local VM that this version is mapped to. Null
26.235 + * is returned if there is no corresponding local class.
26.236 + *
26.237 + * @return the <code>Class</code> instance that this descriptor represents
26.238 + */
26.239 + public Class<?> forClass() {
26.240 + return cl;
26.241 + }
26.242 +
26.243 + /**
26.244 + * Return an array of the fields of this serializable class.
26.245 + *
26.246 + * @return an array containing an element for each persistent field of
26.247 + * this class. Returns an array of length zero if there are no
26.248 + * fields.
26.249 + * @since 1.2
26.250 + */
26.251 + public ObjectStreamField[] getFields() {
26.252 + return getFields(true);
26.253 + }
26.254 +
26.255 + /**
26.256 + * Get the field of this class by name.
26.257 + *
26.258 + * @param name the name of the data field to look for
26.259 + * @return The ObjectStreamField object of the named field or null if
26.260 + * there is no such named field.
26.261 + */
26.262 + public ObjectStreamField getField(String name) {
26.263 + return getField(name, null);
26.264 + }
26.265 +
26.266 + /**
26.267 + * Return a string describing this ObjectStreamClass.
26.268 + */
26.269 + public String toString() {
26.270 + return name + ": static final long serialVersionUID = " +
26.271 + getSerialVersionUID() + "L;";
26.272 + }
26.273 +
26.274 + /**
26.275 + * Looks up and returns class descriptor for given class, or null if class
26.276 + * is non-serializable and "all" is set to false.
26.277 + *
26.278 + * @param cl class to look up
26.279 + * @param all if true, return descriptors for all classes; if false, only
26.280 + * return descriptors for serializable classes
26.281 + */
26.282 + static ObjectStreamClass lookup(Class<?> cl, boolean all) {
26.283 + if (!(all || Serializable.class.isAssignableFrom(cl))) {
26.284 + return null;
26.285 + }
26.286 + processQueue(Caches.localDescsQueue, Caches.localDescs);
26.287 + WeakClassKey key = new WeakClassKey(cl, Caches.localDescsQueue);
26.288 + Reference<?> ref = Caches.localDescs.get(key);
26.289 + Object entry = null;
26.290 + if (ref != null) {
26.291 + entry = ref.get();
26.292 + }
26.293 + EntryFuture future = null;
26.294 + if (entry == null) {
26.295 + EntryFuture newEntry = new EntryFuture();
26.296 + Reference<?> newRef = new SoftReference<>(newEntry);
26.297 + do {
26.298 + if (ref != null) {
26.299 + Caches.localDescs.remove(key, ref);
26.300 + }
26.301 + ref = Caches.localDescs.putIfAbsent(key, newRef);
26.302 + if (ref != null) {
26.303 + entry = ref.get();
26.304 + }
26.305 + } while (ref != null && entry == null);
26.306 + if (entry == null) {
26.307 + future = newEntry;
26.308 + }
26.309 + }
26.310 +
26.311 + if (entry instanceof ObjectStreamClass) { // check common case first
26.312 + return (ObjectStreamClass) entry;
26.313 + }
26.314 + if (entry instanceof EntryFuture) {
26.315 + future = (EntryFuture) entry;
26.316 + if (future.getOwner() == Thread.currentThread()) {
26.317 + /*
26.318 + * Handle nested call situation described by 4803747: waiting
26.319 + * for future value to be set by a lookup() call further up the
26.320 + * stack will result in deadlock, so calculate and set the
26.321 + * future value here instead.
26.322 + */
26.323 + entry = null;
26.324 + } else {
26.325 + entry = future.get();
26.326 + }
26.327 + }
26.328 + if (entry == null) {
26.329 + try {
26.330 + entry = new ObjectStreamClass(cl);
26.331 + } catch (Throwable th) {
26.332 + entry = th;
26.333 + }
26.334 + if (future.set(entry)) {
26.335 + Caches.localDescs.put(key, new SoftReference<Object>(entry));
26.336 + } else {
26.337 + // nested lookup call already set future
26.338 + entry = future.get();
26.339 + }
26.340 + }
26.341 +
26.342 + if (entry instanceof ObjectStreamClass) {
26.343 + return (ObjectStreamClass) entry;
26.344 + } else if (entry instanceof RuntimeException) {
26.345 + throw (RuntimeException) entry;
26.346 + } else if (entry instanceof Error) {
26.347 + throw (Error) entry;
26.348 + } else {
26.349 + throw new InternalError("unexpected entry: " + entry);
26.350 + }
26.351 + }
26.352 +
26.353 + /**
26.354 + * Placeholder used in class descriptor and field reflector lookup tables
26.355 + * for an entry in the process of being initialized. (Internal) callers
26.356 + * which receive an EntryFuture belonging to another thread as the result
26.357 + * of a lookup should call the get() method of the EntryFuture; this will
26.358 + * return the actual entry once it is ready for use and has been set(). To
26.359 + * conserve objects, EntryFutures synchronize on themselves.
26.360 + */
26.361 + private static class EntryFuture {
26.362 +
26.363 + private static final Object unset = new Object();
26.364 + private final Thread owner = Thread.currentThread();
26.365 + private Object entry = unset;
26.366 +
26.367 + /**
26.368 + * Attempts to set the value contained by this EntryFuture. If the
26.369 + * EntryFuture's value has not been set already, then the value is
26.370 + * saved, any callers blocked in the get() method are notified, and
26.371 + * true is returned. If the value has already been set, then no saving
26.372 + * or notification occurs, and false is returned.
26.373 + */
26.374 + synchronized boolean set(Object entry) {
26.375 + if (this.entry != unset) {
26.376 + return false;
26.377 + }
26.378 + this.entry = entry;
26.379 + notifyAll();
26.380 + return true;
26.381 + }
26.382 +
26.383 + /**
26.384 + * Returns the value contained by this EntryFuture, blocking if
26.385 + * necessary until a value is set.
26.386 + */
26.387 + synchronized Object get() {
26.388 + boolean interrupted = false;
26.389 + while (entry == unset) {
26.390 + try {
26.391 + wait();
26.392 + } catch (InterruptedException ex) {
26.393 + interrupted = true;
26.394 + }
26.395 + }
26.396 + if (interrupted) {
26.397 + AccessController.doPrivileged(
26.398 + new PrivilegedAction<Void>() {
26.399 + public Void run() {
26.400 + Thread.currentThread().interrupt();
26.401 + return null;
26.402 + }
26.403 + }
26.404 + );
26.405 + }
26.406 + return entry;
26.407 + }
26.408 +
26.409 + /**
26.410 + * Returns the thread that created this EntryFuture.
26.411 + */
26.412 + Thread getOwner() {
26.413 + return owner;
26.414 + }
26.415 + }
26.416 +
26.417 + /**
26.418 + * Creates local class descriptor representing given class.
26.419 + */
26.420 + private ObjectStreamClass(final Class<?> cl) {
26.421 + this.cl = cl;
26.422 + name = cl.getName();
26.423 + isProxy = Proxy.isProxyClass(cl);
26.424 + isEnum = Enum.class.isAssignableFrom(cl);
26.425 + serializable = Serializable.class.isAssignableFrom(cl);
26.426 + externalizable = Externalizable.class.isAssignableFrom(cl);
26.427 +
26.428 + Class<?> superCl = cl.getSuperclass();
26.429 + superDesc = (superCl != null) ? lookup(superCl, false) : null;
26.430 + localDesc = this;
26.431 +
26.432 + if (serializable) {
26.433 + AccessController.doPrivileged(new PrivilegedAction<Void>() {
26.434 + public Void run() {
26.435 + if (isEnum) {
26.436 + suid = Long.valueOf(0);
26.437 + fields = NO_FIELDS;
26.438 + return null;
26.439 + }
26.440 + if (cl.isArray()) {
26.441 + fields = NO_FIELDS;
26.442 + return null;
26.443 + }
26.444 +
26.445 + suid = getDeclaredSUID(cl);
26.446 + try {
26.447 + fields = getSerialFields(cl);
26.448 + computeFieldOffsets();
26.449 + } catch (InvalidClassException e) {
26.450 + serializeEx = deserializeEx = e;
26.451 + fields = NO_FIELDS;
26.452 + }
26.453 +
26.454 + if (externalizable) {
26.455 + cons = getExternalizableConstructor(cl);
26.456 + } else {
26.457 + cons = getSerializableConstructor(cl);
26.458 + writeObjectMethod = getPrivateMethod(cl, "writeObject",
26.459 + new Class<?>[] { ObjectOutputStream.class },
26.460 + Void.TYPE);
26.461 + readObjectMethod = getPrivateMethod(cl, "readObject",
26.462 + new Class<?>[] { ObjectInputStream.class },
26.463 + Void.TYPE);
26.464 + readObjectNoDataMethod = getPrivateMethod(
26.465 + cl, "readObjectNoData", null, Void.TYPE);
26.466 + hasWriteObjectData = (writeObjectMethod != null);
26.467 + }
26.468 + writeReplaceMethod = getInheritableMethod(
26.469 + cl, "writeReplace", null, Object.class);
26.470 + readResolveMethod = getInheritableMethod(
26.471 + cl, "readResolve", null, Object.class);
26.472 + return null;
26.473 + }
26.474 + });
26.475 + } else {
26.476 + suid = Long.valueOf(0);
26.477 + fields = NO_FIELDS;
26.478 + }
26.479 +
26.480 + try {
26.481 + fieldRefl = getReflector(fields, this);
26.482 + } catch (InvalidClassException ex) {
26.483 + // field mismatches impossible when matching local fields vs. self
26.484 + throw new InternalError();
26.485 + }
26.486 +
26.487 + if (deserializeEx == null) {
26.488 + if (isEnum) {
26.489 + deserializeEx = new InvalidClassException(name, "enum type");
26.490 + } else if (cons == null) {
26.491 + deserializeEx = new InvalidClassException(
26.492 + name, "no valid constructor");
26.493 + }
26.494 + }
26.495 + for (int i = 0; i < fields.length; i++) {
26.496 + if (fields[i].getField() == null) {
26.497 + defaultSerializeEx = new InvalidClassException(
26.498 + name, "unmatched serializable field(s) declared");
26.499 + }
26.500 + }
26.501 + }
26.502 +
26.503 + /**
26.504 + * Creates blank class descriptor which should be initialized via a
26.505 + * subsequent call to initProxy(), initNonProxy() or readNonProxy().
26.506 + */
26.507 + ObjectStreamClass() {
26.508 + }
26.509 +
26.510 + /**
26.511 + * Initializes class descriptor representing a proxy class.
26.512 + */
26.513 + void initProxy(Class<?> cl,
26.514 + ClassNotFoundException resolveEx,
26.515 + ObjectStreamClass superDesc)
26.516 + throws InvalidClassException
26.517 + {
26.518 + this.cl = cl;
26.519 + this.resolveEx = resolveEx;
26.520 + this.superDesc = superDesc;
26.521 + isProxy = true;
26.522 + serializable = true;
26.523 + suid = Long.valueOf(0);
26.524 + fields = NO_FIELDS;
26.525 +
26.526 + if (cl != null) {
26.527 + localDesc = lookup(cl, true);
26.528 + if (!localDesc.isProxy) {
26.529 + throw new InvalidClassException(
26.530 + "cannot bind proxy descriptor to a non-proxy class");
26.531 + }
26.532 + name = localDesc.name;
26.533 + externalizable = localDesc.externalizable;
26.534 + cons = localDesc.cons;
26.535 + writeReplaceMethod = localDesc.writeReplaceMethod;
26.536 + readResolveMethod = localDesc.readResolveMethod;
26.537 + deserializeEx = localDesc.deserializeEx;
26.538 + }
26.539 + fieldRefl = getReflector(fields, localDesc);
26.540 + }
26.541 +
26.542 + /**
26.543 + * Initializes class descriptor representing a non-proxy class.
26.544 + */
26.545 + void initNonProxy(ObjectStreamClass model,
26.546 + Class<?> cl,
26.547 + ClassNotFoundException resolveEx,
26.548 + ObjectStreamClass superDesc)
26.549 + throws InvalidClassException
26.550 + {
26.551 + this.cl = cl;
26.552 + this.resolveEx = resolveEx;
26.553 + this.superDesc = superDesc;
26.554 + name = model.name;
26.555 + suid = Long.valueOf(model.getSerialVersionUID());
26.556 + isProxy = false;
26.557 + isEnum = model.isEnum;
26.558 + serializable = model.serializable;
26.559 + externalizable = model.externalizable;
26.560 + hasBlockExternalData = model.hasBlockExternalData;
26.561 + hasWriteObjectData = model.hasWriteObjectData;
26.562 + fields = model.fields;
26.563 + primDataSize = model.primDataSize;
26.564 + numObjFields = model.numObjFields;
26.565 +
26.566 + if (cl != null) {
26.567 + localDesc = lookup(cl, true);
26.568 + if (localDesc.isProxy) {
26.569 + throw new InvalidClassException(
26.570 + "cannot bind non-proxy descriptor to a proxy class");
26.571 + }
26.572 + if (isEnum != localDesc.isEnum) {
26.573 + throw new InvalidClassException(isEnum ?
26.574 + "cannot bind enum descriptor to a non-enum class" :
26.575 + "cannot bind non-enum descriptor to an enum class");
26.576 + }
26.577 +
26.578 + if (serializable == localDesc.serializable &&
26.579 + !cl.isArray() &&
26.580 + suid.longValue() != localDesc.getSerialVersionUID())
26.581 + {
26.582 + throw new InvalidClassException(localDesc.name,
26.583 + "local class incompatible: " +
26.584 + "stream classdesc serialVersionUID = " + suid +
26.585 + ", local class serialVersionUID = " +
26.586 + localDesc.getSerialVersionUID());
26.587 + }
26.588 +
26.589 + if (!classNamesEqual(name, localDesc.name)) {
26.590 + throw new InvalidClassException(localDesc.name,
26.591 + "local class name incompatible with stream class " +
26.592 + "name \"" + name + "\"");
26.593 + }
26.594 +
26.595 + if (!isEnum) {
26.596 + if ((serializable == localDesc.serializable) &&
26.597 + (externalizable != localDesc.externalizable))
26.598 + {
26.599 + throw new InvalidClassException(localDesc.name,
26.600 + "Serializable incompatible with Externalizable");
26.601 + }
26.602 +
26.603 + if ((serializable != localDesc.serializable) ||
26.604 + (externalizable != localDesc.externalizable) ||
26.605 + !(serializable || externalizable))
26.606 + {
26.607 + deserializeEx = new InvalidClassException(localDesc.name,
26.608 + "class invalid for deserialization");
26.609 + }
26.610 + }
26.611 +
26.612 + cons = localDesc.cons;
26.613 + writeObjectMethod = localDesc.writeObjectMethod;
26.614 + readObjectMethod = localDesc.readObjectMethod;
26.615 + readObjectNoDataMethod = localDesc.readObjectNoDataMethod;
26.616 + writeReplaceMethod = localDesc.writeReplaceMethod;
26.617 + readResolveMethod = localDesc.readResolveMethod;
26.618 + if (deserializeEx == null) {
26.619 + deserializeEx = localDesc.deserializeEx;
26.620 + }
26.621 + }
26.622 + fieldRefl = getReflector(fields, localDesc);
26.623 + // reassign to matched fields so as to reflect local unshared settings
26.624 + fields = fieldRefl.getFields();
26.625 + }
26.626 +
26.627 + /**
26.628 + * Reads non-proxy class descriptor information from given input stream.
26.629 + * The resulting class descriptor is not fully functional; it can only be
26.630 + * used as input to the ObjectInputStream.resolveClass() and
26.631 + * ObjectStreamClass.initNonProxy() methods.
26.632 + */
26.633 + void readNonProxy(ObjectInputStream in)
26.634 + throws IOException, ClassNotFoundException
26.635 + {
26.636 + name = in.readUTF();
26.637 + suid = Long.valueOf(in.readLong());
26.638 + isProxy = false;
26.639 +
26.640 + byte flags = in.readByte();
26.641 + hasWriteObjectData =
26.642 + ((flags & ObjectStreamConstants.SC_WRITE_METHOD) != 0);
26.643 + hasBlockExternalData =
26.644 + ((flags & ObjectStreamConstants.SC_BLOCK_DATA) != 0);
26.645 + externalizable =
26.646 + ((flags & ObjectStreamConstants.SC_EXTERNALIZABLE) != 0);
26.647 + boolean sflag =
26.648 + ((flags & ObjectStreamConstants.SC_SERIALIZABLE) != 0);
26.649 + if (externalizable && sflag) {
26.650 + throw new InvalidClassException(
26.651 + name, "serializable and externalizable flags conflict");
26.652 + }
26.653 + serializable = externalizable || sflag;
26.654 + isEnum = ((flags & ObjectStreamConstants.SC_ENUM) != 0);
26.655 + if (isEnum && suid.longValue() != 0L) {
26.656 + throw new InvalidClassException(name,
26.657 + "enum descriptor has non-zero serialVersionUID: " + suid);
26.658 + }
26.659 +
26.660 + int numFields = in.readShort();
26.661 + if (isEnum && numFields != 0) {
26.662 + throw new InvalidClassException(name,
26.663 + "enum descriptor has non-zero field count: " + numFields);
26.664 + }
26.665 + fields = (numFields > 0) ?
26.666 + new ObjectStreamField[numFields] : NO_FIELDS;
26.667 + for (int i = 0; i < numFields; i++) {
26.668 + char tcode = (char) in.readByte();
26.669 + String fname = in.readUTF();
26.670 + String signature = ((tcode == 'L') || (tcode == '[')) ?
26.671 + in.readTypeString() : new String(new char[] { tcode });
26.672 + try {
26.673 + fields[i] = new ObjectStreamField(fname, signature, false);
26.674 + } catch (RuntimeException e) {
26.675 + throw (IOException) new InvalidClassException(name,
26.676 + "invalid descriptor for field " + fname).initCause(e);
26.677 + }
26.678 + }
26.679 + computeFieldOffsets();
26.680 + }
26.681 +
26.682 + /**
26.683 + * Writes non-proxy class descriptor information to given output stream.
26.684 + */
26.685 + void writeNonProxy(ObjectOutputStream out) throws IOException {
26.686 + out.writeUTF(name);
26.687 + out.writeLong(getSerialVersionUID());
26.688 +
26.689 + byte flags = 0;
26.690 + if (externalizable) {
26.691 + flags |= ObjectStreamConstants.SC_EXTERNALIZABLE;
26.692 + int protocol = out.getProtocolVersion();
26.693 + if (protocol != ObjectStreamConstants.PROTOCOL_VERSION_1) {
26.694 + flags |= ObjectStreamConstants.SC_BLOCK_DATA;
26.695 + }
26.696 + } else if (serializable) {
26.697 + flags |= ObjectStreamConstants.SC_SERIALIZABLE;
26.698 + }
26.699 + if (hasWriteObjectData) {
26.700 + flags |= ObjectStreamConstants.SC_WRITE_METHOD;
26.701 + }
26.702 + if (isEnum) {
26.703 + flags |= ObjectStreamConstants.SC_ENUM;
26.704 + }
26.705 + out.writeByte(flags);
26.706 +
26.707 + out.writeShort(fields.length);
26.708 + for (int i = 0; i < fields.length; i++) {
26.709 + ObjectStreamField f = fields[i];
26.710 + out.writeByte(f.getTypeCode());
26.711 + out.writeUTF(f.getName());
26.712 + if (!f.isPrimitive()) {
26.713 + out.writeTypeString(f.getTypeString());
26.714 + }
26.715 + }
26.716 + }
26.717 +
26.718 + /**
26.719 + * Returns ClassNotFoundException (if any) thrown while attempting to
26.720 + * resolve local class corresponding to this class descriptor.
26.721 + */
26.722 + ClassNotFoundException getResolveException() {
26.723 + return resolveEx;
26.724 + }
26.725 +
26.726 + /**
26.727 + * Throws an InvalidClassException if object instances referencing this
26.728 + * class descriptor should not be allowed to deserialize. This method does
26.729 + * not apply to deserialization of enum constants.
26.730 + */
26.731 + void checkDeserialize() throws InvalidClassException {
26.732 + if (deserializeEx != null) {
26.733 + InvalidClassException ice =
26.734 + new InvalidClassException(deserializeEx.classname,
26.735 + deserializeEx.getMessage());
26.736 + ice.initCause(deserializeEx);
26.737 + throw ice;
26.738 + }
26.739 + }
26.740 +
26.741 + /**
26.742 + * Throws an InvalidClassException if objects whose class is represented by
26.743 + * this descriptor should not be allowed to serialize. This method does
26.744 + * not apply to serialization of enum constants.
26.745 + */
26.746 + void checkSerialize() throws InvalidClassException {
26.747 + if (serializeEx != null) {
26.748 + InvalidClassException ice =
26.749 + new InvalidClassException(serializeEx.classname,
26.750 + serializeEx.getMessage());
26.751 + ice.initCause(serializeEx);
26.752 + throw ice;
26.753 + }
26.754 + }
26.755 +
26.756 + /**
26.757 + * Throws an InvalidClassException if objects whose class is represented by
26.758 + * this descriptor should not be permitted to use default serialization
26.759 + * (e.g., if the class declares serializable fields that do not correspond
26.760 + * to actual fields, and hence must use the GetField API). This method
26.761 + * does not apply to deserialization of enum constants.
26.762 + */
26.763 + void checkDefaultSerialize() throws InvalidClassException {
26.764 + if (defaultSerializeEx != null) {
26.765 + InvalidClassException ice =
26.766 + new InvalidClassException(defaultSerializeEx.classname,
26.767 + defaultSerializeEx.getMessage());
26.768 + ice.initCause(defaultSerializeEx);
26.769 + throw ice;
26.770 + }
26.771 + }
26.772 +
26.773 + /**
26.774 + * Returns superclass descriptor. Note that on the receiving side, the
26.775 + * superclass descriptor may be bound to a class that is not a superclass
26.776 + * of the subclass descriptor's bound class.
26.777 + */
26.778 + ObjectStreamClass getSuperDesc() {
26.779 + return superDesc;
26.780 + }
26.781 +
26.782 + /**
26.783 + * Returns the "local" class descriptor for the class associated with this
26.784 + * class descriptor (i.e., the result of
26.785 + * ObjectStreamClass.lookup(this.forClass())) or null if there is no class
26.786 + * associated with this descriptor.
26.787 + */
26.788 + ObjectStreamClass getLocalDesc() {
26.789 + return localDesc;
26.790 + }
26.791 +
26.792 + /**
26.793 + * Returns arrays of ObjectStreamFields representing the serializable
26.794 + * fields of the represented class. If copy is true, a clone of this class
26.795 + * descriptor's field array is returned, otherwise the array itself is
26.796 + * returned.
26.797 + */
26.798 + ObjectStreamField[] getFields(boolean copy) {
26.799 + return copy ? fields.clone() : fields;
26.800 + }
26.801 +
26.802 + /**
26.803 + * Looks up a serializable field of the represented class by name and type.
26.804 + * A specified type of null matches all types, Object.class matches all
26.805 + * non-primitive types, and any other non-null type matches assignable
26.806 + * types only. Returns matching field, or null if no match found.
26.807 + */
26.808 + ObjectStreamField getField(String name, Class<?> type) {
26.809 + for (int i = 0; i < fields.length; i++) {
26.810 + ObjectStreamField f = fields[i];
26.811 + if (f.getName().equals(name)) {
26.812 + if (type == null ||
26.813 + (type == Object.class && !f.isPrimitive()))
26.814 + {
26.815 + return f;
26.816 + }
26.817 + Class<?> ftype = f.getType();
26.818 + if (ftype != null && type.isAssignableFrom(ftype)) {
26.819 + return f;
26.820 + }
26.821 + }
26.822 + }
26.823 + return null;
26.824 + }
26.825 +
26.826 + /**
26.827 + * Returns true if class descriptor represents a dynamic proxy class, false
26.828 + * otherwise.
26.829 + */
26.830 + boolean isProxy() {
26.831 + return isProxy;
26.832 + }
26.833 +
26.834 + /**
26.835 + * Returns true if class descriptor represents an enum type, false
26.836 + * otherwise.
26.837 + */
26.838 + boolean isEnum() {
26.839 + return isEnum;
26.840 + }
26.841 +
26.842 + /**
26.843 + * Returns true if represented class implements Externalizable, false
26.844 + * otherwise.
26.845 + */
26.846 + boolean isExternalizable() {
26.847 + return externalizable;
26.848 + }
26.849 +
26.850 + /**
26.851 + * Returns true if represented class implements Serializable, false
26.852 + * otherwise.
26.853 + */
26.854 + boolean isSerializable() {
26.855 + return serializable;
26.856 + }
26.857 +
26.858 + /**
26.859 + * Returns true if class descriptor represents externalizable class that
26.860 + * has written its data in 1.2 (block data) format, false otherwise.
26.861 + */
26.862 + boolean hasBlockExternalData() {
26.863 + return hasBlockExternalData;
26.864 + }
26.865 +
26.866 + /**
26.867 + * Returns true if class descriptor represents serializable (but not
26.868 + * externalizable) class which has written its data via a custom
26.869 + * writeObject() method, false otherwise.
26.870 + */
26.871 + boolean hasWriteObjectData() {
26.872 + return hasWriteObjectData;
26.873 + }
26.874 +
26.875 + /**
26.876 + * Returns true if represented class is serializable/externalizable and can
26.877 + * be instantiated by the serialization runtime--i.e., if it is
26.878 + * externalizable and defines a public no-arg constructor, or if it is
26.879 + * non-externalizable and its first non-serializable superclass defines an
26.880 + * accessible no-arg constructor. Otherwise, returns false.
26.881 + */
26.882 + boolean isInstantiable() {
26.883 + return (cons != null);
26.884 + }
26.885 +
26.886 + /**
26.887 + * Returns true if represented class is serializable (but not
26.888 + * externalizable) and defines a conformant writeObject method. Otherwise,
26.889 + * returns false.
26.890 + */
26.891 + boolean hasWriteObjectMethod() {
26.892 + return (writeObjectMethod != null);
26.893 + }
26.894 +
26.895 + /**
26.896 + * Returns true if represented class is serializable (but not
26.897 + * externalizable) and defines a conformant readObject method. Otherwise,
26.898 + * returns false.
26.899 + */
26.900 + boolean hasReadObjectMethod() {
26.901 + return (readObjectMethod != null);
26.902 + }
26.903 +
26.904 + /**
26.905 + * Returns true if represented class is serializable (but not
26.906 + * externalizable) and defines a conformant readObjectNoData method.
26.907 + * Otherwise, returns false.
26.908 + */
26.909 + boolean hasReadObjectNoDataMethod() {
26.910 + return (readObjectNoDataMethod != null);
26.911 + }
26.912 +
26.913 + /**
26.914 + * Returns true if represented class is serializable or externalizable and
26.915 + * defines a conformant writeReplace method. Otherwise, returns false.
26.916 + */
26.917 + boolean hasWriteReplaceMethod() {
26.918 + return (writeReplaceMethod != null);
26.919 + }
26.920 +
26.921 + /**
26.922 + * Returns true if represented class is serializable or externalizable and
26.923 + * defines a conformant readResolve method. Otherwise, returns false.
26.924 + */
26.925 + boolean hasReadResolveMethod() {
26.926 + return (readResolveMethod != null);
26.927 + }
26.928 +
26.929 + /**
26.930 + * Creates a new instance of the represented class. If the class is
26.931 + * externalizable, invokes its public no-arg constructor; otherwise, if the
26.932 + * class is serializable, invokes the no-arg constructor of the first
26.933 + * non-serializable superclass. Throws UnsupportedOperationException if
26.934 + * this class descriptor is not associated with a class, if the associated
26.935 + * class is non-serializable or if the appropriate no-arg constructor is
26.936 + * inaccessible/unavailable.
26.937 + */
26.938 + Object newInstance()
26.939 + throws InstantiationException, InvocationTargetException,
26.940 + UnsupportedOperationException
26.941 + {
26.942 + if (cons != null) {
26.943 + try {
26.944 + return cons.newInstance();
26.945 + } catch (IllegalAccessException ex) {
26.946 + // should not occur, as access checks have been suppressed
26.947 + throw new InternalError();
26.948 + }
26.949 + } else {
26.950 + throw new UnsupportedOperationException();
26.951 + }
26.952 + }
26.953 +
26.954 + /**
26.955 + * Invokes the writeObject method of the represented serializable class.
26.956 + * Throws UnsupportedOperationException if this class descriptor is not
26.957 + * associated with a class, or if the class is externalizable,
26.958 + * non-serializable or does not define writeObject.
26.959 + */
26.960 + void invokeWriteObject(Object obj, ObjectOutputStream out)
26.961 + throws IOException, UnsupportedOperationException
26.962 + {
26.963 + if (writeObjectMethod != null) {
26.964 + try {
26.965 + writeObjectMethod.invoke(obj, new Object[]{ out });
26.966 + } catch (InvocationTargetException ex) {
26.967 + Throwable th = ex.getTargetException();
26.968 + if (th instanceof IOException) {
26.969 + throw (IOException) th;
26.970 + } else {
26.971 + throwMiscException(th);
26.972 + }
26.973 + } catch (IllegalAccessException ex) {
26.974 + // should not occur, as access checks have been suppressed
26.975 + throw new InternalError();
26.976 + }
26.977 + } else {
26.978 + throw new UnsupportedOperationException();
26.979 + }
26.980 + }
26.981 +
26.982 + /**
26.983 + * Invokes the readObject method of the represented serializable class.
26.984 + * Throws UnsupportedOperationException if this class descriptor is not
26.985 + * associated with a class, or if the class is externalizable,
26.986 + * non-serializable or does not define readObject.
26.987 + */
26.988 + void invokeReadObject(Object obj, ObjectInputStream in)
26.989 + throws ClassNotFoundException, IOException,
26.990 + UnsupportedOperationException
26.991 + {
26.992 + if (readObjectMethod != null) {
26.993 + try {
26.994 + readObjectMethod.invoke(obj, new Object[]{ in });
26.995 + } catch (InvocationTargetException ex) {
26.996 + Throwable th = ex.getTargetException();
26.997 + if (th instanceof ClassNotFoundException) {
26.998 + throw (ClassNotFoundException) th;
26.999 + } else if (th instanceof IOException) {
26.1000 + throw (IOException) th;
26.1001 + } else {
26.1002 + throwMiscException(th);
26.1003 + }
26.1004 + } catch (IllegalAccessException ex) {
26.1005 + // should not occur, as access checks have been suppressed
26.1006 + throw new InternalError();
26.1007 + }
26.1008 + } else {
26.1009 + throw new UnsupportedOperationException();
26.1010 + }
26.1011 + }
26.1012 +
26.1013 + /**
26.1014 + * Invokes the readObjectNoData method of the represented serializable
26.1015 + * class. Throws UnsupportedOperationException if this class descriptor is
26.1016 + * not associated with a class, or if the class is externalizable,
26.1017 + * non-serializable or does not define readObjectNoData.
26.1018 + */
26.1019 + void invokeReadObjectNoData(Object obj)
26.1020 + throws IOException, UnsupportedOperationException
26.1021 + {
26.1022 + if (readObjectNoDataMethod != null) {
26.1023 + try {
26.1024 + readObjectNoDataMethod.invoke(obj, (Object[]) null);
26.1025 + } catch (InvocationTargetException ex) {
26.1026 + Throwable th = ex.getTargetException();
26.1027 + if (th instanceof ObjectStreamException) {
26.1028 + throw (ObjectStreamException) th;
26.1029 + } else {
26.1030 + throwMiscException(th);
26.1031 + }
26.1032 + } catch (IllegalAccessException ex) {
26.1033 + // should not occur, as access checks have been suppressed
26.1034 + throw new InternalError();
26.1035 + }
26.1036 + } else {
26.1037 + throw new UnsupportedOperationException();
26.1038 + }
26.1039 + }
26.1040 +
26.1041 + /**
26.1042 + * Invokes the writeReplace method of the represented serializable class and
26.1043 + * returns the result. Throws UnsupportedOperationException if this class
26.1044 + * descriptor is not associated with a class, or if the class is
26.1045 + * non-serializable or does not define writeReplace.
26.1046 + */
26.1047 + Object invokeWriteReplace(Object obj)
26.1048 + throws IOException, UnsupportedOperationException
26.1049 + {
26.1050 + if (writeReplaceMethod != null) {
26.1051 + try {
26.1052 + return writeReplaceMethod.invoke(obj, (Object[]) null);
26.1053 + } catch (InvocationTargetException ex) {
26.1054 + Throwable th = ex.getTargetException();
26.1055 + if (th instanceof ObjectStreamException) {
26.1056 + throw (ObjectStreamException) th;
26.1057 + } else {
26.1058 + throwMiscException(th);
26.1059 + throw new InternalError(); // never reached
26.1060 + }
26.1061 + } catch (IllegalAccessException ex) {
26.1062 + // should not occur, as access checks have been suppressed
26.1063 + throw new InternalError();
26.1064 + }
26.1065 + } else {
26.1066 + throw new UnsupportedOperationException();
26.1067 + }
26.1068 + }
26.1069 +
26.1070 + /**
26.1071 + * Invokes the readResolve method of the represented serializable class and
26.1072 + * returns the result. Throws UnsupportedOperationException if this class
26.1073 + * descriptor is not associated with a class, or if the class is
26.1074 + * non-serializable or does not define readResolve.
26.1075 + */
26.1076 + Object invokeReadResolve(Object obj)
26.1077 + throws IOException, UnsupportedOperationException
26.1078 + {
26.1079 + if (readResolveMethod != null) {
26.1080 + try {
26.1081 + return readResolveMethod.invoke(obj, (Object[]) null);
26.1082 + } catch (InvocationTargetException ex) {
26.1083 + Throwable th = ex.getTargetException();
26.1084 + if (th instanceof ObjectStreamException) {
26.1085 + throw (ObjectStreamException) th;
26.1086 + } else {
26.1087 + throwMiscException(th);
26.1088 + throw new InternalError(); // never reached
26.1089 + }
26.1090 + } catch (IllegalAccessException ex) {
26.1091 + // should not occur, as access checks have been suppressed
26.1092 + throw new InternalError();
26.1093 + }
26.1094 + } else {
26.1095 + throw new UnsupportedOperationException();
26.1096 + }
26.1097 + }
26.1098 +
26.1099 + /**
26.1100 + * Class representing the portion of an object's serialized form allotted
26.1101 + * to data described by a given class descriptor. If "hasData" is false,
26.1102 + * the object's serialized form does not contain data associated with the
26.1103 + * class descriptor.
26.1104 + */
26.1105 + static class ClassDataSlot {
26.1106 +
26.1107 + /** class descriptor "occupying" this slot */
26.1108 + final ObjectStreamClass desc;
26.1109 + /** true if serialized form includes data for this slot's descriptor */
26.1110 + final boolean hasData;
26.1111 +
26.1112 + ClassDataSlot(ObjectStreamClass desc, boolean hasData) {
26.1113 + this.desc = desc;
26.1114 + this.hasData = hasData;
26.1115 + }
26.1116 + }
26.1117 +
26.1118 + /**
26.1119 + * Returns array of ClassDataSlot instances representing the data layout
26.1120 + * (including superclass data) for serialized objects described by this
26.1121 + * class descriptor. ClassDataSlots are ordered by inheritance with those
26.1122 + * containing "higher" superclasses appearing first. The final
26.1123 + * ClassDataSlot contains a reference to this descriptor.
26.1124 + */
26.1125 + ClassDataSlot[] getClassDataLayout() throws InvalidClassException {
26.1126 + // REMIND: synchronize instead of relying on volatile?
26.1127 + if (dataLayout == null) {
26.1128 + dataLayout = getClassDataLayout0();
26.1129 + }
26.1130 + return dataLayout;
26.1131 + }
26.1132 +
26.1133 + private ClassDataSlot[] getClassDataLayout0()
26.1134 + throws InvalidClassException
26.1135 + {
26.1136 + ArrayList<ClassDataSlot> slots = new ArrayList<>();
26.1137 + Class<?> start = cl, end = cl;
26.1138 +
26.1139 + // locate closest non-serializable superclass
26.1140 + while (end != null && Serializable.class.isAssignableFrom(end)) {
26.1141 + end = end.getSuperclass();
26.1142 + }
26.1143 +
26.1144 + for (ObjectStreamClass d = this; d != null; d = d.superDesc) {
26.1145 +
26.1146 + // search up inheritance hierarchy for class with matching name
26.1147 + String searchName = (d.cl != null) ? d.cl.getName() : d.name;
26.1148 + Class<?> match = null;
26.1149 + for (Class<?> c = start; c != end; c = c.getSuperclass()) {
26.1150 + if (searchName.equals(c.getName())) {
26.1151 + match = c;
26.1152 + break;
26.1153 + }
26.1154 + }
26.1155 +
26.1156 + // add "no data" slot for each unmatched class below match
26.1157 + if (match != null) {
26.1158 + for (Class<?> c = start; c != match; c = c.getSuperclass()) {
26.1159 + slots.add(new ClassDataSlot(
26.1160 + ObjectStreamClass.lookup(c, true), false));
26.1161 + }
26.1162 + start = match.getSuperclass();
26.1163 + }
26.1164 +
26.1165 + // record descriptor/class pairing
26.1166 + slots.add(new ClassDataSlot(d.getVariantFor(match), true));
26.1167 + }
26.1168 +
26.1169 + // add "no data" slot for any leftover unmatched classes
26.1170 + for (Class<?> c = start; c != end; c = c.getSuperclass()) {
26.1171 + slots.add(new ClassDataSlot(
26.1172 + ObjectStreamClass.lookup(c, true), false));
26.1173 + }
26.1174 +
26.1175 + // order slots from superclass -> subclass
26.1176 + Collections.reverse(slots);
26.1177 + return slots.toArray(new ClassDataSlot[slots.size()]);
26.1178 + }
26.1179 +
26.1180 + /**
26.1181 + * Returns aggregate size (in bytes) of marshalled primitive field values
26.1182 + * for represented class.
26.1183 + */
26.1184 + int getPrimDataSize() {
26.1185 + return primDataSize;
26.1186 + }
26.1187 +
26.1188 + /**
26.1189 + * Returns number of non-primitive serializable fields of represented
26.1190 + * class.
26.1191 + */
26.1192 + int getNumObjFields() {
26.1193 + return numObjFields;
26.1194 + }
26.1195 +
26.1196 + /**
26.1197 + * Fetches the serializable primitive field values of object obj and
26.1198 + * marshals them into byte array buf starting at offset 0. It is the
26.1199 + * responsibility of the caller to ensure that obj is of the proper type if
26.1200 + * non-null.
26.1201 + */
26.1202 + void getPrimFieldValues(Object obj, byte[] buf) {
26.1203 + fieldRefl.getPrimFieldValues(obj, buf);
26.1204 + }
26.1205 +
26.1206 + /**
26.1207 + * Sets the serializable primitive fields of object obj using values
26.1208 + * unmarshalled from byte array buf starting at offset 0. It is the
26.1209 + * responsibility of the caller to ensure that obj is of the proper type if
26.1210 + * non-null.
26.1211 + */
26.1212 + void setPrimFieldValues(Object obj, byte[] buf) {
26.1213 + fieldRefl.setPrimFieldValues(obj, buf);
26.1214 + }
26.1215 +
26.1216 + /**
26.1217 + * Fetches the serializable object field values of object obj and stores
26.1218 + * them in array vals starting at offset 0. It is the responsibility of
26.1219 + * the caller to ensure that obj is of the proper type if non-null.
26.1220 + */
26.1221 + void getObjFieldValues(Object obj, Object[] vals) {
26.1222 + fieldRefl.getObjFieldValues(obj, vals);
26.1223 + }
26.1224 +
26.1225 + /**
26.1226 + * Sets the serializable object fields of object obj using values from
26.1227 + * array vals starting at offset 0. It is the responsibility of the caller
26.1228 + * to ensure that obj is of the proper type if non-null.
26.1229 + */
26.1230 + void setObjFieldValues(Object obj, Object[] vals) {
26.1231 + fieldRefl.setObjFieldValues(obj, vals);
26.1232 + }
26.1233 +
26.1234 + /**
26.1235 + * Calculates and sets serializable field offsets, as well as primitive
26.1236 + * data size and object field count totals. Throws InvalidClassException
26.1237 + * if fields are illegally ordered.
26.1238 + */
26.1239 + private void computeFieldOffsets() throws InvalidClassException {
26.1240 + primDataSize = 0;
26.1241 + numObjFields = 0;
26.1242 + int firstObjIndex = -1;
26.1243 +
26.1244 + for (int i = 0; i < fields.length; i++) {
26.1245 + ObjectStreamField f = fields[i];
26.1246 + switch (f.getTypeCode()) {
26.1247 + case 'Z':
26.1248 + case 'B':
26.1249 + f.setOffset(primDataSize++);
26.1250 + break;
26.1251 +
26.1252 + case 'C':
26.1253 + case 'S':
26.1254 + f.setOffset(primDataSize);
26.1255 + primDataSize += 2;
26.1256 + break;
26.1257 +
26.1258 + case 'I':
26.1259 + case 'F':
26.1260 + f.setOffset(primDataSize);
26.1261 + primDataSize += 4;
26.1262 + break;
26.1263 +
26.1264 + case 'J':
26.1265 + case 'D':
26.1266 + f.setOffset(primDataSize);
26.1267 + primDataSize += 8;
26.1268 + break;
26.1269 +
26.1270 + case '[':
26.1271 + case 'L':
26.1272 + f.setOffset(numObjFields++);
26.1273 + if (firstObjIndex == -1) {
26.1274 + firstObjIndex = i;
26.1275 + }
26.1276 + break;
26.1277 +
26.1278 + default:
26.1279 + throw new InternalError();
26.1280 + }
26.1281 + }
26.1282 + if (firstObjIndex != -1 &&
26.1283 + firstObjIndex + numObjFields != fields.length)
26.1284 + {
26.1285 + throw new InvalidClassException(name, "illegal field order");
26.1286 + }
26.1287 + }
26.1288 +
26.1289 + /**
26.1290 + * If given class is the same as the class associated with this class
26.1291 + * descriptor, returns reference to this class descriptor. Otherwise,
26.1292 + * returns variant of this class descriptor bound to given class.
26.1293 + */
26.1294 + private ObjectStreamClass getVariantFor(Class<?> cl)
26.1295 + throws InvalidClassException
26.1296 + {
26.1297 + if (this.cl == cl) {
26.1298 + return this;
26.1299 + }
26.1300 + ObjectStreamClass desc = new ObjectStreamClass();
26.1301 + if (isProxy) {
26.1302 + desc.initProxy(cl, null, superDesc);
26.1303 + } else {
26.1304 + desc.initNonProxy(this, cl, null, superDesc);
26.1305 + }
26.1306 + return desc;
26.1307 + }
26.1308 +
26.1309 + /**
26.1310 + * Returns public no-arg constructor of given class, or null if none found.
26.1311 + * Access checks are disabled on the returned constructor (if any), since
26.1312 + * the defining class may still be non-public.
26.1313 + */
26.1314 + private static Constructor getExternalizableConstructor(Class<?> cl) {
26.1315 + try {
26.1316 + Constructor cons = cl.getDeclaredConstructor((Class<?>[]) null);
26.1317 + cons.setAccessible(true);
26.1318 + return ((cons.getModifiers() & Modifier.PUBLIC) != 0) ?
26.1319 + cons : null;
26.1320 + } catch (NoSuchMethodException ex) {
26.1321 + return null;
26.1322 + }
26.1323 + }
26.1324 +
26.1325 + /**
26.1326 + * Returns subclass-accessible no-arg constructor of first non-serializable
26.1327 + * superclass, or null if none found. Access checks are disabled on the
26.1328 + * returned constructor (if any).
26.1329 + */
26.1330 + private static Constructor getSerializableConstructor(Class<?> cl) {
26.1331 + Class<?> initCl = cl;
26.1332 + while (Serializable.class.isAssignableFrom(initCl)) {
26.1333 + if ((initCl = initCl.getSuperclass()) == null) {
26.1334 + return null;
26.1335 + }
26.1336 + }
26.1337 + try {
26.1338 + Constructor cons = initCl.getDeclaredConstructor((Class<?>[]) null);
26.1339 + int mods = cons.getModifiers();
26.1340 + if ((mods & Modifier.PRIVATE) != 0 ||
26.1341 + ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
26.1342 + !packageEquals(cl, initCl)))
26.1343 + {
26.1344 + return null;
26.1345 + }
26.1346 + cons = reflFactory.newConstructorForSerialization(cl, cons);
26.1347 + cons.setAccessible(true);
26.1348 + return cons;
26.1349 + } catch (NoSuchMethodException ex) {
26.1350 + return null;
26.1351 + }
26.1352 + }
26.1353 +
26.1354 + /**
26.1355 + * Returns non-static, non-abstract method with given signature provided it
26.1356 + * is defined by or accessible (via inheritance) by the given class, or
26.1357 + * null if no match found. Access checks are disabled on the returned
26.1358 + * method (if any).
26.1359 + */
26.1360 + private static Method getInheritableMethod(Class<?> cl, String name,
26.1361 + Class<?>[] argTypes,
26.1362 + Class<?> returnType)
26.1363 + {
26.1364 + Method meth = null;
26.1365 + Class<?> defCl = cl;
26.1366 + while (defCl != null) {
26.1367 + try {
26.1368 + meth = defCl.getDeclaredMethod(name, argTypes);
26.1369 + break;
26.1370 + } catch (NoSuchMethodException ex) {
26.1371 + defCl = defCl.getSuperclass();
26.1372 + }
26.1373 + }
26.1374 +
26.1375 + if ((meth == null) || (meth.getReturnType() != returnType)) {
26.1376 + return null;
26.1377 + }
26.1378 + meth.setAccessible(true);
26.1379 + int mods = meth.getModifiers();
26.1380 + if ((mods & (Modifier.STATIC | Modifier.ABSTRACT)) != 0) {
26.1381 + return null;
26.1382 + } else if ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0) {
26.1383 + return meth;
26.1384 + } else if ((mods & Modifier.PRIVATE) != 0) {
26.1385 + return (cl == defCl) ? meth : null;
26.1386 + } else {
26.1387 + return packageEquals(cl, defCl) ? meth : null;
26.1388 + }
26.1389 + }
26.1390 +
26.1391 + /**
26.1392 + * Returns non-static private method with given signature defined by given
26.1393 + * class, or null if none found. Access checks are disabled on the
26.1394 + * returned method (if any).
26.1395 + */
26.1396 + private static Method getPrivateMethod(Class<?> cl, String name,
26.1397 + Class<?>[] argTypes,
26.1398 + Class<?> returnType)
26.1399 + {
26.1400 + try {
26.1401 + Method meth = cl.getDeclaredMethod(name, argTypes);
26.1402 + meth.setAccessible(true);
26.1403 + int mods = meth.getModifiers();
26.1404 + return ((meth.getReturnType() == returnType) &&
26.1405 + ((mods & Modifier.STATIC) == 0) &&
26.1406 + ((mods & Modifier.PRIVATE) != 0)) ? meth : null;
26.1407 + } catch (NoSuchMethodException ex) {
26.1408 + return null;
26.1409 + }
26.1410 + }
26.1411 +
26.1412 + /**
26.1413 + * Returns true if classes are defined in the same runtime package, false
26.1414 + * otherwise.
26.1415 + */
26.1416 + private static boolean packageEquals(Class<?> cl1, Class<?> cl2) {
26.1417 + return (cl1.getClassLoader() == cl2.getClassLoader() &&
26.1418 + getPackageName(cl1).equals(getPackageName(cl2)));
26.1419 + }
26.1420 +
26.1421 + /**
26.1422 + * Returns package name of given class.
26.1423 + */
26.1424 + private static String getPackageName(Class<?> cl) {
26.1425 + String s = cl.getName();
26.1426 + int i = s.lastIndexOf('[');
26.1427 + if (i >= 0) {
26.1428 + s = s.substring(i + 2);
26.1429 + }
26.1430 + i = s.lastIndexOf('.');
26.1431 + return (i >= 0) ? s.substring(0, i) : "";
26.1432 + }
26.1433 +
26.1434 + /**
26.1435 + * Compares class names for equality, ignoring package names. Returns true
26.1436 + * if class names equal, false otherwise.
26.1437 + */
26.1438 + private static boolean classNamesEqual(String name1, String name2) {
26.1439 + name1 = name1.substring(name1.lastIndexOf('.') + 1);
26.1440 + name2 = name2.substring(name2.lastIndexOf('.') + 1);
26.1441 + return name1.equals(name2);
26.1442 + }
26.1443 +
26.1444 + /**
26.1445 + * Returns JVM type signature for given class.
26.1446 + */
26.1447 + private static String getClassSignature(Class<?> cl) {
26.1448 + StringBuilder sbuf = new StringBuilder();
26.1449 + while (cl.isArray()) {
26.1450 + sbuf.append('[');
26.1451 + cl = cl.getComponentType();
26.1452 + }
26.1453 + if (cl.isPrimitive()) {
26.1454 + if (cl == Integer.TYPE) {
26.1455 + sbuf.append('I');
26.1456 + } else if (cl == Byte.TYPE) {
26.1457 + sbuf.append('B');
26.1458 + } else if (cl == Long.TYPE) {
26.1459 + sbuf.append('J');
26.1460 + } else if (cl == Float.TYPE) {
26.1461 + sbuf.append('F');
26.1462 + } else if (cl == Double.TYPE) {
26.1463 + sbuf.append('D');
26.1464 + } else if (cl == Short.TYPE) {
26.1465 + sbuf.append('S');
26.1466 + } else if (cl == Character.TYPE) {
26.1467 + sbuf.append('C');
26.1468 + } else if (cl == Boolean.TYPE) {
26.1469 + sbuf.append('Z');
26.1470 + } else if (cl == Void.TYPE) {
26.1471 + sbuf.append('V');
26.1472 + } else {
26.1473 + throw new InternalError();
26.1474 + }
26.1475 + } else {
26.1476 + sbuf.append('L' + cl.getName().replace('.', '/') + ';');
26.1477 + }
26.1478 + return sbuf.toString();
26.1479 + }
26.1480 +
26.1481 + /**
26.1482 + * Returns JVM type signature for given list of parameters and return type.
26.1483 + */
26.1484 + private static String getMethodSignature(Class<?>[] paramTypes,
26.1485 + Class<?> retType)
26.1486 + {
26.1487 + StringBuilder sbuf = new StringBuilder();
26.1488 + sbuf.append('(');
26.1489 + for (int i = 0; i < paramTypes.length; i++) {
26.1490 + sbuf.append(getClassSignature(paramTypes[i]));
26.1491 + }
26.1492 + sbuf.append(')');
26.1493 + sbuf.append(getClassSignature(retType));
26.1494 + return sbuf.toString();
26.1495 + }
26.1496 +
26.1497 + /**
26.1498 + * Convenience method for throwing an exception that is either a
26.1499 + * RuntimeException, Error, or of some unexpected type (in which case it is
26.1500 + * wrapped inside an IOException).
26.1501 + */
26.1502 + private static void throwMiscException(Throwable th) throws IOException {
26.1503 + if (th instanceof RuntimeException) {
26.1504 + throw (RuntimeException) th;
26.1505 + } else if (th instanceof Error) {
26.1506 + throw (Error) th;
26.1507 + } else {
26.1508 + IOException ex = new IOException("unexpected exception type");
26.1509 + ex.initCause(th);
26.1510 + throw ex;
26.1511 + }
26.1512 + }
26.1513 +
26.1514 + /**
26.1515 + * Returns ObjectStreamField array describing the serializable fields of
26.1516 + * the given class. Serializable fields backed by an actual field of the
26.1517 + * class are represented by ObjectStreamFields with corresponding non-null
26.1518 + * Field objects. Throws InvalidClassException if the (explicitly
26.1519 + * declared) serializable fields are invalid.
26.1520 + */
26.1521 + private static ObjectStreamField[] getSerialFields(Class<?> cl)
26.1522 + throws InvalidClassException
26.1523 + {
26.1524 + ObjectStreamField[] fields;
26.1525 + if (Serializable.class.isAssignableFrom(cl) &&
26.1526 + !Externalizable.class.isAssignableFrom(cl) &&
26.1527 + !Proxy.isProxyClass(cl) &&
26.1528 + !cl.isInterface())
26.1529 + {
26.1530 + if ((fields = getDeclaredSerialFields(cl)) == null) {
26.1531 + fields = getDefaultSerialFields(cl);
26.1532 + }
26.1533 + Arrays.sort(fields);
26.1534 + } else {
26.1535 + fields = NO_FIELDS;
26.1536 + }
26.1537 + return fields;
26.1538 + }
26.1539 +
26.1540 + /**
26.1541 + * Returns serializable fields of given class as defined explicitly by a
26.1542 + * "serialPersistentFields" field, or null if no appropriate
26.1543 + * "serialPersistentFields" field is defined. Serializable fields backed
26.1544 + * by an actual field of the class are represented by ObjectStreamFields
26.1545 + * with corresponding non-null Field objects. For compatibility with past
26.1546 + * releases, a "serialPersistentFields" field with a null value is
26.1547 + * considered equivalent to not declaring "serialPersistentFields". Throws
26.1548 + * InvalidClassException if the declared serializable fields are
26.1549 + * invalid--e.g., if multiple fields share the same name.
26.1550 + */
26.1551 + private static ObjectStreamField[] getDeclaredSerialFields(Class<?> cl)
26.1552 + throws InvalidClassException
26.1553 + {
26.1554 + ObjectStreamField[] serialPersistentFields = null;
26.1555 + try {
26.1556 + Field f = cl.getDeclaredField("serialPersistentFields");
26.1557 + int mask = Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL;
26.1558 + if ((f.getModifiers() & mask) == mask) {
26.1559 + f.setAccessible(true);
26.1560 + serialPersistentFields = (ObjectStreamField[]) f.get(null);
26.1561 + }
26.1562 + } catch (Exception ex) {
26.1563 + }
26.1564 + if (serialPersistentFields == null) {
26.1565 + return null;
26.1566 + } else if (serialPersistentFields.length == 0) {
26.1567 + return NO_FIELDS;
26.1568 + }
26.1569 +
26.1570 + ObjectStreamField[] boundFields =
26.1571 + new ObjectStreamField[serialPersistentFields.length];
26.1572 + Set<String> fieldNames = new HashSet<>(serialPersistentFields.length);
26.1573 +
26.1574 + for (int i = 0; i < serialPersistentFields.length; i++) {
26.1575 + ObjectStreamField spf = serialPersistentFields[i];
26.1576 +
26.1577 + String fname = spf.getName();
26.1578 + if (fieldNames.contains(fname)) {
26.1579 + throw new InvalidClassException(
26.1580 + "multiple serializable fields named " + fname);
26.1581 + }
26.1582 + fieldNames.add(fname);
26.1583 +
26.1584 + try {
26.1585 + Field f = cl.getDeclaredField(fname);
26.1586 + if ((f.getType() == spf.getType()) &&
26.1587 + ((f.getModifiers() & Modifier.STATIC) == 0))
26.1588 + {
26.1589 + boundFields[i] =
26.1590 + new ObjectStreamField(f, spf.isUnshared(), true);
26.1591 + }
26.1592 + } catch (NoSuchFieldException ex) {
26.1593 + }
26.1594 + if (boundFields[i] == null) {
26.1595 + boundFields[i] = new ObjectStreamField(
26.1596 + fname, spf.getType(), spf.isUnshared());
26.1597 + }
26.1598 + }
26.1599 + return boundFields;
26.1600 + }
26.1601 +
26.1602 + /**
26.1603 + * Returns array of ObjectStreamFields corresponding to all non-static
26.1604 + * non-transient fields declared by given class. Each ObjectStreamField
26.1605 + * contains a Field object for the field it represents. If no default
26.1606 + * serializable fields exist, NO_FIELDS is returned.
26.1607 + */
26.1608 + private static ObjectStreamField[] getDefaultSerialFields(Class<?> cl) {
26.1609 + Field[] clFields = cl.getDeclaredFields();
26.1610 + ArrayList<ObjectStreamField> list = new ArrayList<>();
26.1611 + int mask = Modifier.STATIC | Modifier.TRANSIENT;
26.1612 +
26.1613 + for (int i = 0; i < clFields.length; i++) {
26.1614 + if ((clFields[i].getModifiers() & mask) == 0) {
26.1615 + list.add(new ObjectStreamField(clFields[i], false, true));
26.1616 + }
26.1617 + }
26.1618 + int size = list.size();
26.1619 + return (size == 0) ? NO_FIELDS :
26.1620 + list.toArray(new ObjectStreamField[size]);
26.1621 + }
26.1622 +
26.1623 + /**
26.1624 + * Returns explicit serial version UID value declared by given class, or
26.1625 + * null if none.
26.1626 + */
26.1627 + private static Long getDeclaredSUID(Class<?> cl) {
26.1628 + try {
26.1629 + Field f = cl.getDeclaredField("serialVersionUID");
26.1630 + int mask = Modifier.STATIC | Modifier.FINAL;
26.1631 + if ((f.getModifiers() & mask) == mask) {
26.1632 + f.setAccessible(true);
26.1633 + return Long.valueOf(f.getLong(null));
26.1634 + }
26.1635 + } catch (Exception ex) {
26.1636 + }
26.1637 + return null;
26.1638 + }
26.1639 +
26.1640 + /**
26.1641 + * Computes the default serial version UID value for the given class.
26.1642 + */
26.1643 + private static long computeDefaultSUID(Class<?> cl) {
26.1644 + if (!Serializable.class.isAssignableFrom(cl) || Proxy.isProxyClass(cl))
26.1645 + {
26.1646 + return 0L;
26.1647 + }
26.1648 +
26.1649 + try {
26.1650 + ByteArrayOutputStream bout = new ByteArrayOutputStream();
26.1651 + DataOutputStream dout = new DataOutputStream(bout);
26.1652 +
26.1653 + dout.writeUTF(cl.getName());
26.1654 +
26.1655 + int classMods = cl.getModifiers() &
26.1656 + (Modifier.PUBLIC | Modifier.FINAL |
26.1657 + Modifier.INTERFACE | Modifier.ABSTRACT);
26.1658 +
26.1659 + /*
26.1660 + * compensate for javac bug in which ABSTRACT bit was set for an
26.1661 + * interface only if the interface declared methods
26.1662 + */
26.1663 + Method[] methods = cl.getDeclaredMethods();
26.1664 + if ((classMods & Modifier.INTERFACE) != 0) {
26.1665 + classMods = (methods.length > 0) ?
26.1666 + (classMods | Modifier.ABSTRACT) :
26.1667 + (classMods & ~Modifier.ABSTRACT);
26.1668 + }
26.1669 + dout.writeInt(classMods);
26.1670 +
26.1671 + if (!cl.isArray()) {
26.1672 + /*
26.1673 + * compensate for change in 1.2FCS in which
26.1674 + * Class.getInterfaces() was modified to return Cloneable and
26.1675 + * Serializable for array classes.
26.1676 + */
26.1677 + Class<?>[] interfaces = cl.getInterfaces();
26.1678 + String[] ifaceNames = new String[interfaces.length];
26.1679 + for (int i = 0; i < interfaces.length; i++) {
26.1680 + ifaceNames[i] = interfaces[i].getName();
26.1681 + }
26.1682 + Arrays.sort(ifaceNames);
26.1683 + for (int i = 0; i < ifaceNames.length; i++) {
26.1684 + dout.writeUTF(ifaceNames[i]);
26.1685 + }
26.1686 + }
26.1687 +
26.1688 + Field[] fields = cl.getDeclaredFields();
26.1689 + MemberSignature[] fieldSigs = new MemberSignature[fields.length];
26.1690 + for (int i = 0; i < fields.length; i++) {
26.1691 + fieldSigs[i] = new MemberSignature(fields[i]);
26.1692 + }
26.1693 + Arrays.sort(fieldSigs, new Comparator<MemberSignature>() {
26.1694 + public int compare(MemberSignature ms1, MemberSignature ms2) {
26.1695 + return ms1.name.compareTo(ms2.name);
26.1696 + }
26.1697 + });
26.1698 + for (int i = 0; i < fieldSigs.length; i++) {
26.1699 + MemberSignature sig = fieldSigs[i];
26.1700 + int mods = sig.member.getModifiers() &
26.1701 + (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED |
26.1702 + Modifier.STATIC | Modifier.FINAL | Modifier.VOLATILE |
26.1703 + Modifier.TRANSIENT);
26.1704 + if (((mods & Modifier.PRIVATE) == 0) ||
26.1705 + ((mods & (Modifier.STATIC | Modifier.TRANSIENT)) == 0))
26.1706 + {
26.1707 + dout.writeUTF(sig.name);
26.1708 + dout.writeInt(mods);
26.1709 + dout.writeUTF(sig.signature);
26.1710 + }
26.1711 + }
26.1712 +
26.1713 + if (hasStaticInitializer(cl)) {
26.1714 + dout.writeUTF("<clinit>");
26.1715 + dout.writeInt(Modifier.STATIC);
26.1716 + dout.writeUTF("()V");
26.1717 + }
26.1718 +
26.1719 + Constructor[] cons = cl.getDeclaredConstructors();
26.1720 + MemberSignature[] consSigs = new MemberSignature[cons.length];
26.1721 + for (int i = 0; i < cons.length; i++) {
26.1722 + consSigs[i] = new MemberSignature(cons[i]);
26.1723 + }
26.1724 + Arrays.sort(consSigs, new Comparator<MemberSignature>() {
26.1725 + public int compare(MemberSignature ms1, MemberSignature ms2) {
26.1726 + return ms1.signature.compareTo(ms2.signature);
26.1727 + }
26.1728 + });
26.1729 + for (int i = 0; i < consSigs.length; i++) {
26.1730 + MemberSignature sig = consSigs[i];
26.1731 + int mods = sig.member.getModifiers() &
26.1732 + (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED |
26.1733 + Modifier.STATIC | Modifier.FINAL |
26.1734 + Modifier.SYNCHRONIZED | Modifier.NATIVE |
26.1735 + Modifier.ABSTRACT | Modifier.STRICT);
26.1736 + if ((mods & Modifier.PRIVATE) == 0) {
26.1737 + dout.writeUTF("<init>");
26.1738 + dout.writeInt(mods);
26.1739 + dout.writeUTF(sig.signature.replace('/', '.'));
26.1740 + }
26.1741 + }
26.1742 +
26.1743 + MemberSignature[] methSigs = new MemberSignature[methods.length];
26.1744 + for (int i = 0; i < methods.length; i++) {
26.1745 + methSigs[i] = new MemberSignature(methods[i]);
26.1746 + }
26.1747 + Arrays.sort(methSigs, new Comparator<MemberSignature>() {
26.1748 + public int compare(MemberSignature ms1, MemberSignature ms2) {
26.1749 + int comp = ms1.name.compareTo(ms2.name);
26.1750 + if (comp == 0) {
26.1751 + comp = ms1.signature.compareTo(ms2.signature);
26.1752 + }
26.1753 + return comp;
26.1754 + }
26.1755 + });
26.1756 + for (int i = 0; i < methSigs.length; i++) {
26.1757 + MemberSignature sig = methSigs[i];
26.1758 + int mods = sig.member.getModifiers() &
26.1759 + (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED |
26.1760 + Modifier.STATIC | Modifier.FINAL |
26.1761 + Modifier.SYNCHRONIZED | Modifier.NATIVE |
26.1762 + Modifier.ABSTRACT | Modifier.STRICT);
26.1763 + if ((mods & Modifier.PRIVATE) == 0) {
26.1764 + dout.writeUTF(sig.name);
26.1765 + dout.writeInt(mods);
26.1766 + dout.writeUTF(sig.signature.replace('/', '.'));
26.1767 + }
26.1768 + }
26.1769 +
26.1770 + dout.flush();
26.1771 +
26.1772 + MessageDigest md = MessageDigest.getInstance("SHA");
26.1773 + byte[] hashBytes = md.digest(bout.toByteArray());
26.1774 + long hash = 0;
26.1775 + for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
26.1776 + hash = (hash << 8) | (hashBytes[i] & 0xFF);
26.1777 + }
26.1778 + return hash;
26.1779 + } catch (IOException ex) {
26.1780 + throw new InternalError();
26.1781 + } catch (NoSuchAlgorithmException ex) {
26.1782 + throw new SecurityException(ex.getMessage());
26.1783 + }
26.1784 + }
26.1785 +
26.1786 + /**
26.1787 + * Returns true if the given class defines a static initializer method,
26.1788 + * false otherwise.
26.1789 + */
26.1790 + private native static boolean hasStaticInitializer(Class<?> cl);
26.1791 +
26.1792 + /**
26.1793 + * Class for computing and caching field/constructor/method signatures
26.1794 + * during serialVersionUID calculation.
26.1795 + */
26.1796 + private static class MemberSignature {
26.1797 +
26.1798 + public final Member member;
26.1799 + public final String name;
26.1800 + public final String signature;
26.1801 +
26.1802 + public MemberSignature(Field field) {
26.1803 + member = field;
26.1804 + name = field.getName();
26.1805 + signature = getClassSignature(field.getType());
26.1806 + }
26.1807 +
26.1808 + public MemberSignature(Constructor cons) {
26.1809 + member = cons;
26.1810 + name = cons.getName();
26.1811 + signature = getMethodSignature(
26.1812 + cons.getParameterTypes(), Void.TYPE);
26.1813 + }
26.1814 +
26.1815 + public MemberSignature(Method meth) {
26.1816 + member = meth;
26.1817 + name = meth.getName();
26.1818 + signature = getMethodSignature(
26.1819 + meth.getParameterTypes(), meth.getReturnType());
26.1820 + }
26.1821 + }
26.1822 +
26.1823 + /**
26.1824 + * Class for setting and retrieving serializable field values in batch.
26.1825 + */
26.1826 + // REMIND: dynamically generate these?
26.1827 + private static class FieldReflector {
26.1828 +
26.1829 + /** handle for performing unsafe operations */
26.1830 + private static final Unsafe unsafe = Unsafe.getUnsafe();
26.1831 +
26.1832 + /** fields to operate on */
26.1833 + private final ObjectStreamField[] fields;
26.1834 + /** number of primitive fields */
26.1835 + private final int numPrimFields;
26.1836 + /** unsafe field keys for reading fields - may contain dupes */
26.1837 + private final long[] readKeys;
26.1838 + /** unsafe fields keys for writing fields - no dupes */
26.1839 + private final long[] writeKeys;
26.1840 + /** field data offsets */
26.1841 + private final int[] offsets;
26.1842 + /** field type codes */
26.1843 + private final char[] typeCodes;
26.1844 + /** field types */
26.1845 + private final Class<?>[] types;
26.1846 +
26.1847 + /**
26.1848 + * Constructs FieldReflector capable of setting/getting values from the
26.1849 + * subset of fields whose ObjectStreamFields contain non-null
26.1850 + * reflective Field objects. ObjectStreamFields with null Fields are
26.1851 + * treated as filler, for which get operations return default values
26.1852 + * and set operations discard given values.
26.1853 + */
26.1854 + FieldReflector(ObjectStreamField[] fields) {
26.1855 + this.fields = fields;
26.1856 + int nfields = fields.length;
26.1857 + readKeys = new long[nfields];
26.1858 + writeKeys = new long[nfields];
26.1859 + offsets = new int[nfields];
26.1860 + typeCodes = new char[nfields];
26.1861 + ArrayList<Class<?>> typeList = new ArrayList<>();
26.1862 + Set<Long> usedKeys = new HashSet<>();
26.1863 +
26.1864 +
26.1865 + for (int i = 0; i < nfields; i++) {
26.1866 + ObjectStreamField f = fields[i];
26.1867 + Field rf = f.getField();
26.1868 + long key = (rf != null) ?
26.1869 + unsafe.objectFieldOffset(rf) : Unsafe.INVALID_FIELD_OFFSET;
26.1870 + readKeys[i] = key;
26.1871 + writeKeys[i] = usedKeys.add(key) ?
26.1872 + key : Unsafe.INVALID_FIELD_OFFSET;
26.1873 + offsets[i] = f.getOffset();
26.1874 + typeCodes[i] = f.getTypeCode();
26.1875 + if (!f.isPrimitive()) {
26.1876 + typeList.add((rf != null) ? rf.getType() : null);
26.1877 + }
26.1878 + }
26.1879 +
26.1880 + types = typeList.toArray(new Class<?>[typeList.size()]);
26.1881 + numPrimFields = nfields - types.length;
26.1882 + }
26.1883 +
26.1884 + /**
26.1885 + * Returns list of ObjectStreamFields representing fields operated on
26.1886 + * by this reflector. The shared/unshared values and Field objects
26.1887 + * contained by ObjectStreamFields in the list reflect their bindings
26.1888 + * to locally defined serializable fields.
26.1889 + */
26.1890 + ObjectStreamField[] getFields() {
26.1891 + return fields;
26.1892 + }
26.1893 +
26.1894 + /**
26.1895 + * Fetches the serializable primitive field values of object obj and
26.1896 + * marshals them into byte array buf starting at offset 0. The caller
26.1897 + * is responsible for ensuring that obj is of the proper type.
26.1898 + */
26.1899 + void getPrimFieldValues(Object obj, byte[] buf) {
26.1900 + if (obj == null) {
26.1901 + throw new NullPointerException();
26.1902 + }
26.1903 + /* assuming checkDefaultSerialize() has been called on the class
26.1904 + * descriptor this FieldReflector was obtained from, no field keys
26.1905 + * in array should be equal to Unsafe.INVALID_FIELD_OFFSET.
26.1906 + */
26.1907 + for (int i = 0; i < numPrimFields; i++) {
26.1908 + long key = readKeys[i];
26.1909 + int off = offsets[i];
26.1910 + switch (typeCodes[i]) {
26.1911 + case 'Z':
26.1912 + Bits.putBoolean(buf, off, unsafe.getBoolean(obj, key));
26.1913 + break;
26.1914 +
26.1915 + case 'B':
26.1916 + buf[off] = unsafe.getByte(obj, key);
26.1917 + break;
26.1918 +
26.1919 + case 'C':
26.1920 + Bits.putChar(buf, off, unsafe.getChar(obj, key));
26.1921 + break;
26.1922 +
26.1923 + case 'S':
26.1924 + Bits.putShort(buf, off, unsafe.getShort(obj, key));
26.1925 + break;
26.1926 +
26.1927 + case 'I':
26.1928 + Bits.putInt(buf, off, unsafe.getInt(obj, key));
26.1929 + break;
26.1930 +
26.1931 + case 'F':
26.1932 + Bits.putFloat(buf, off, unsafe.getFloat(obj, key));
26.1933 + break;
26.1934 +
26.1935 + case 'J':
26.1936 + Bits.putLong(buf, off, unsafe.getLong(obj, key));
26.1937 + break;
26.1938 +
26.1939 + case 'D':
26.1940 + Bits.putDouble(buf, off, unsafe.getDouble(obj, key));
26.1941 + break;
26.1942 +
26.1943 + default:
26.1944 + throw new InternalError();
26.1945 + }
26.1946 + }
26.1947 + }
26.1948 +
26.1949 + /**
26.1950 + * Sets the serializable primitive fields of object obj using values
26.1951 + * unmarshalled from byte array buf starting at offset 0. The caller
26.1952 + * is responsible for ensuring that obj is of the proper type.
26.1953 + */
26.1954 + void setPrimFieldValues(Object obj, byte[] buf) {
26.1955 + if (obj == null) {
26.1956 + throw new NullPointerException();
26.1957 + }
26.1958 + for (int i = 0; i < numPrimFields; i++) {
26.1959 + long key = writeKeys[i];
26.1960 + if (key == Unsafe.INVALID_FIELD_OFFSET) {
26.1961 + continue; // discard value
26.1962 + }
26.1963 + int off = offsets[i];
26.1964 + switch (typeCodes[i]) {
26.1965 + case 'Z':
26.1966 + unsafe.putBoolean(obj, key, Bits.getBoolean(buf, off));
26.1967 + break;
26.1968 +
26.1969 + case 'B':
26.1970 + unsafe.putByte(obj, key, buf[off]);
26.1971 + break;
26.1972 +
26.1973 + case 'C':
26.1974 + unsafe.putChar(obj, key, Bits.getChar(buf, off));
26.1975 + break;
26.1976 +
26.1977 + case 'S':
26.1978 + unsafe.putShort(obj, key, Bits.getShort(buf, off));
26.1979 + break;
26.1980 +
26.1981 + case 'I':
26.1982 + unsafe.putInt(obj, key, Bits.getInt(buf, off));
26.1983 + break;
26.1984 +
26.1985 + case 'F':
26.1986 + unsafe.putFloat(obj, key, Bits.getFloat(buf, off));
26.1987 + break;
26.1988 +
26.1989 + case 'J':
26.1990 + unsafe.putLong(obj, key, Bits.getLong(buf, off));
26.1991 + break;
26.1992 +
26.1993 + case 'D':
26.1994 + unsafe.putDouble(obj, key, Bits.getDouble(buf, off));
26.1995 + break;
26.1996 +
26.1997 + default:
26.1998 + throw new InternalError();
26.1999 + }
26.2000 + }
26.2001 + }
26.2002 +
26.2003 + /**
26.2004 + * Fetches the serializable object field values of object obj and
26.2005 + * stores them in array vals starting at offset 0. The caller is
26.2006 + * responsible for ensuring that obj is of the proper type.
26.2007 + */
26.2008 + void getObjFieldValues(Object obj, Object[] vals) {
26.2009 + if (obj == null) {
26.2010 + throw new NullPointerException();
26.2011 + }
26.2012 + /* assuming checkDefaultSerialize() has been called on the class
26.2013 + * descriptor this FieldReflector was obtained from, no field keys
26.2014 + * in array should be equal to Unsafe.INVALID_FIELD_OFFSET.
26.2015 + */
26.2016 + for (int i = numPrimFields; i < fields.length; i++) {
26.2017 + switch (typeCodes[i]) {
26.2018 + case 'L':
26.2019 + case '[':
26.2020 + vals[offsets[i]] = unsafe.getObject(obj, readKeys[i]);
26.2021 + break;
26.2022 +
26.2023 + default:
26.2024 + throw new InternalError();
26.2025 + }
26.2026 + }
26.2027 + }
26.2028 +
26.2029 + /**
26.2030 + * Sets the serializable object fields of object obj using values from
26.2031 + * array vals starting at offset 0. The caller is responsible for
26.2032 + * ensuring that obj is of the proper type; however, attempts to set a
26.2033 + * field with a value of the wrong type will trigger an appropriate
26.2034 + * ClassCastException.
26.2035 + */
26.2036 + void setObjFieldValues(Object obj, Object[] vals) {
26.2037 + if (obj == null) {
26.2038 + throw new NullPointerException();
26.2039 + }
26.2040 + for (int i = numPrimFields; i < fields.length; i++) {
26.2041 + long key = writeKeys[i];
26.2042 + if (key == Unsafe.INVALID_FIELD_OFFSET) {
26.2043 + continue; // discard value
26.2044 + }
26.2045 + switch (typeCodes[i]) {
26.2046 + case 'L':
26.2047 + case '[':
26.2048 + Object val = vals[offsets[i]];
26.2049 + if (val != null &&
26.2050 + !types[i - numPrimFields].isInstance(val))
26.2051 + {
26.2052 + Field f = fields[i].getField();
26.2053 + throw new ClassCastException(
26.2054 + "cannot assign instance of " +
26.2055 + val.getClass().getName() + " to field " +
26.2056 + f.getDeclaringClass().getName() + "." +
26.2057 + f.getName() + " of type " +
26.2058 + f.getType().getName() + " in instance of " +
26.2059 + obj.getClass().getName());
26.2060 + }
26.2061 + unsafe.putObject(obj, key, val);
26.2062 + break;
26.2063 +
26.2064 + default:
26.2065 + throw new InternalError();
26.2066 + }
26.2067 + }
26.2068 + }
26.2069 + }
26.2070 +
26.2071 + /**
26.2072 + * Matches given set of serializable fields with serializable fields
26.2073 + * described by the given local class descriptor, and returns a
26.2074 + * FieldReflector instance capable of setting/getting values from the
26.2075 + * subset of fields that match (non-matching fields are treated as filler,
26.2076 + * for which get operations return default values and set operations
26.2077 + * discard given values). Throws InvalidClassException if unresolvable
26.2078 + * type conflicts exist between the two sets of fields.
26.2079 + */
26.2080 + private static FieldReflector getReflector(ObjectStreamField[] fields,
26.2081 + ObjectStreamClass localDesc)
26.2082 + throws InvalidClassException
26.2083 + {
26.2084 + // class irrelevant if no fields
26.2085 + Class<?> cl = (localDesc != null && fields.length > 0) ?
26.2086 + localDesc.cl : null;
26.2087 + processQueue(Caches.reflectorsQueue, Caches.reflectors);
26.2088 + FieldReflectorKey key = new FieldReflectorKey(cl, fields,
26.2089 + Caches.reflectorsQueue);
26.2090 + Reference<?> ref = Caches.reflectors.get(key);
26.2091 + Object entry = null;
26.2092 + if (ref != null) {
26.2093 + entry = ref.get();
26.2094 + }
26.2095 + EntryFuture future = null;
26.2096 + if (entry == null) {
26.2097 + EntryFuture newEntry = new EntryFuture();
26.2098 + Reference<?> newRef = new SoftReference<>(newEntry);
26.2099 + do {
26.2100 + if (ref != null) {
26.2101 + Caches.reflectors.remove(key, ref);
26.2102 + }
26.2103 + ref = Caches.reflectors.putIfAbsent(key, newRef);
26.2104 + if (ref != null) {
26.2105 + entry = ref.get();
26.2106 + }
26.2107 + } while (ref != null && entry == null);
26.2108 + if (entry == null) {
26.2109 + future = newEntry;
26.2110 + }
26.2111 + }
26.2112 +
26.2113 + if (entry instanceof FieldReflector) { // check common case first
26.2114 + return (FieldReflector) entry;
26.2115 + } else if (entry instanceof EntryFuture) {
26.2116 + entry = ((EntryFuture) entry).get();
26.2117 + } else if (entry == null) {
26.2118 + try {
26.2119 + entry = new FieldReflector(matchFields(fields, localDesc));
26.2120 + } catch (Throwable th) {
26.2121 + entry = th;
26.2122 + }
26.2123 + future.set(entry);
26.2124 + Caches.reflectors.put(key, new SoftReference<Object>(entry));
26.2125 + }
26.2126 +
26.2127 + if (entry instanceof FieldReflector) {
26.2128 + return (FieldReflector) entry;
26.2129 + } else if (entry instanceof InvalidClassException) {
26.2130 + throw (InvalidClassException) entry;
26.2131 + } else if (entry instanceof RuntimeException) {
26.2132 + throw (RuntimeException) entry;
26.2133 + } else if (entry instanceof Error) {
26.2134 + throw (Error) entry;
26.2135 + } else {
26.2136 + throw new InternalError("unexpected entry: " + entry);
26.2137 + }
26.2138 + }
26.2139 +
26.2140 + /**
26.2141 + * FieldReflector cache lookup key. Keys are considered equal if they
26.2142 + * refer to the same class and equivalent field formats.
26.2143 + */
26.2144 + private static class FieldReflectorKey extends WeakReference<Class<?>> {
26.2145 +
26.2146 + private final String sigs;
26.2147 + private final int hash;
26.2148 + private final boolean nullClass;
26.2149 +
26.2150 + FieldReflectorKey(Class<?> cl, ObjectStreamField[] fields,
26.2151 + ReferenceQueue<Class<?>> queue)
26.2152 + {
26.2153 + super(cl, queue);
26.2154 + nullClass = (cl == null);
26.2155 + StringBuilder sbuf = new StringBuilder();
26.2156 + for (int i = 0; i < fields.length; i++) {
26.2157 + ObjectStreamField f = fields[i];
26.2158 + sbuf.append(f.getName()).append(f.getSignature());
26.2159 + }
26.2160 + sigs = sbuf.toString();
26.2161 + hash = System.identityHashCode(cl) + sigs.hashCode();
26.2162 + }
26.2163 +
26.2164 + public int hashCode() {
26.2165 + return hash;
26.2166 + }
26.2167 +
26.2168 + public boolean equals(Object obj) {
26.2169 + if (obj == this) {
26.2170 + return true;
26.2171 + }
26.2172 +
26.2173 + if (obj instanceof FieldReflectorKey) {
26.2174 + FieldReflectorKey other = (FieldReflectorKey) obj;
26.2175 + Class<?> referent;
26.2176 + return (nullClass ? other.nullClass
26.2177 + : ((referent = get()) != null) &&
26.2178 + (referent == other.get())) &&
26.2179 + sigs.equals(other.sigs);
26.2180 + } else {
26.2181 + return false;
26.2182 + }
26.2183 + }
26.2184 + }
26.2185 +
26.2186 + /**
26.2187 + * Matches given set of serializable fields with serializable fields
26.2188 + * obtained from the given local class descriptor (which contain bindings
26.2189 + * to reflective Field objects). Returns list of ObjectStreamFields in
26.2190 + * which each ObjectStreamField whose signature matches that of a local
26.2191 + * field contains a Field object for that field; unmatched
26.2192 + * ObjectStreamFields contain null Field objects. Shared/unshared settings
26.2193 + * of the returned ObjectStreamFields also reflect those of matched local
26.2194 + * ObjectStreamFields. Throws InvalidClassException if unresolvable type
26.2195 + * conflicts exist between the two sets of fields.
26.2196 + */
26.2197 + private static ObjectStreamField[] matchFields(ObjectStreamField[] fields,
26.2198 + ObjectStreamClass localDesc)
26.2199 + throws InvalidClassException
26.2200 + {
26.2201 + ObjectStreamField[] localFields = (localDesc != null) ?
26.2202 + localDesc.fields : NO_FIELDS;
26.2203 +
26.2204 + /*
26.2205 + * Even if fields == localFields, we cannot simply return localFields
26.2206 + * here. In previous implementations of serialization,
26.2207 + * ObjectStreamField.getType() returned Object.class if the
26.2208 + * ObjectStreamField represented a non-primitive field and belonged to
26.2209 + * a non-local class descriptor. To preserve this (questionable)
26.2210 + * behavior, the ObjectStreamField instances returned by matchFields
26.2211 + * cannot report non-primitive types other than Object.class; hence
26.2212 + * localFields cannot be returned directly.
26.2213 + */
26.2214 +
26.2215 + ObjectStreamField[] matches = new ObjectStreamField[fields.length];
26.2216 + for (int i = 0; i < fields.length; i++) {
26.2217 + ObjectStreamField f = fields[i], m = null;
26.2218 + for (int j = 0; j < localFields.length; j++) {
26.2219 + ObjectStreamField lf = localFields[j];
26.2220 + if (f.getName().equals(lf.getName())) {
26.2221 + if ((f.isPrimitive() || lf.isPrimitive()) &&
26.2222 + f.getTypeCode() != lf.getTypeCode())
26.2223 + {
26.2224 + throw new InvalidClassException(localDesc.name,
26.2225 + "incompatible types for field " + f.getName());
26.2226 + }
26.2227 + if (lf.getField() != null) {
26.2228 + m = new ObjectStreamField(
26.2229 + lf.getField(), lf.isUnshared(), false);
26.2230 + } else {
26.2231 + m = new ObjectStreamField(
26.2232 + lf.getName(), lf.getSignature(), lf.isUnshared());
26.2233 + }
26.2234 + }
26.2235 + }
26.2236 + if (m == null) {
26.2237 + m = new ObjectStreamField(
26.2238 + f.getName(), f.getSignature(), false);
26.2239 + }
26.2240 + m.setOffset(f.getOffset());
26.2241 + matches[i] = m;
26.2242 + }
26.2243 + return matches;
26.2244 + }
26.2245 +
26.2246 + /**
26.2247 + * Removes from the specified map any keys that have been enqueued
26.2248 + * on the specified reference queue.
26.2249 + */
26.2250 + static void processQueue(ReferenceQueue<Class<?>> queue,
26.2251 + ConcurrentMap<? extends
26.2252 + WeakReference<Class<?>>, ?> map)
26.2253 + {
26.2254 + Reference<? extends Class<?>> ref;
26.2255 + while((ref = queue.poll()) != null) {
26.2256 + map.remove(ref);
26.2257 + }
26.2258 + }
26.2259 +
26.2260 + /**
26.2261 + * Weak key for Class objects.
26.2262 + *
26.2263 + **/
26.2264 + static class WeakClassKey extends WeakReference<Class<?>> {
26.2265 + /**
26.2266 + * saved value of the referent's identity hash code, to maintain
26.2267 + * a consistent hash code after the referent has been cleared
26.2268 + */
26.2269 + private final int hash;
26.2270 +
26.2271 + /**
26.2272 + * Create a new WeakClassKey to the given object, registered
26.2273 + * with a queue.
26.2274 + */
26.2275 + WeakClassKey(Class<?> cl, ReferenceQueue<Class<?>> refQueue) {
26.2276 + super(cl, refQueue);
26.2277 + hash = System.identityHashCode(cl);
26.2278 + }
26.2279 +
26.2280 + /**
26.2281 + * Returns the identity hash code of the original referent.
26.2282 + */
26.2283 + public int hashCode() {
26.2284 + return hash;
26.2285 + }
26.2286 +
26.2287 + /**
26.2288 + * Returns true if the given object is this identical
26.2289 + * WeakClassKey instance, or, if this object's referent has not
26.2290 + * been cleared, if the given object is another WeakClassKey
26.2291 + * instance with the identical non-null referent as this one.
26.2292 + */
26.2293 + public boolean equals(Object obj) {
26.2294 + if (obj == this) {
26.2295 + return true;
26.2296 + }
26.2297 +
26.2298 + if (obj instanceof WeakClassKey) {
26.2299 + Object referent = get();
26.2300 + return (referent != null) &&
26.2301 + (referent == ((WeakClassKey) obj).get());
26.2302 + } else {
26.2303 + return false;
26.2304 + }
26.2305 + }
26.2306 + }
26.2307 +}
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
27.2 +++ b/emul/compact/src/main/java/java/io/ObjectStreamConstants.java Fri Feb 01 16:35:42 2013 +0100
27.3 @@ -0,0 +1,235 @@
27.4 +/*
27.5 + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
27.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
27.7 + *
27.8 + * This code is free software; you can redistribute it and/or modify it
27.9 + * under the terms of the GNU General Public License version 2 only, as
27.10 + * published by the Free Software Foundation. Oracle designates this
27.11 + * particular file as subject to the "Classpath" exception as provided
27.12 + * by Oracle in the LICENSE file that accompanied this code.
27.13 + *
27.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
27.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
27.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
27.17 + * version 2 for more details (a copy is included in the LICENSE file that
27.18 + * accompanied this code).
27.19 + *
27.20 + * You should have received a copy of the GNU General Public License version
27.21 + * 2 along with this work; if not, write to the Free Software Foundation,
27.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
27.23 + *
27.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
27.25 + * or visit www.oracle.com if you need additional information or have any
27.26 + * questions.
27.27 + */
27.28 +
27.29 +package java.io;
27.30 +
27.31 +/**
27.32 + * Constants written into the Object Serialization Stream.
27.33 + *
27.34 + * @author unascribed
27.35 + * @since JDK 1.1
27.36 + */
27.37 +public interface ObjectStreamConstants {
27.38 +
27.39 + /**
27.40 + * Magic number that is written to the stream header.
27.41 + */
27.42 + final static short STREAM_MAGIC = (short)0xaced;
27.43 +
27.44 + /**
27.45 + * Version number that is written to the stream header.
27.46 + */
27.47 + final static short STREAM_VERSION = 5;
27.48 +
27.49 + /* Each item in the stream is preceded by a tag
27.50 + */
27.51 +
27.52 + /**
27.53 + * First tag value.
27.54 + */
27.55 + final static byte TC_BASE = 0x70;
27.56 +
27.57 + /**
27.58 + * Null object reference.
27.59 + */
27.60 + final static byte TC_NULL = (byte)0x70;
27.61 +
27.62 + /**
27.63 + * Reference to an object already written into the stream.
27.64 + */
27.65 + final static byte TC_REFERENCE = (byte)0x71;
27.66 +
27.67 + /**
27.68 + * new Class Descriptor.
27.69 + */
27.70 + final static byte TC_CLASSDESC = (byte)0x72;
27.71 +
27.72 + /**
27.73 + * new Object.
27.74 + */
27.75 + final static byte TC_OBJECT = (byte)0x73;
27.76 +
27.77 + /**
27.78 + * new String.
27.79 + */
27.80 + final static byte TC_STRING = (byte)0x74;
27.81 +
27.82 + /**
27.83 + * new Array.
27.84 + */
27.85 + final static byte TC_ARRAY = (byte)0x75;
27.86 +
27.87 + /**
27.88 + * Reference to Class.
27.89 + */
27.90 + final static byte TC_CLASS = (byte)0x76;
27.91 +
27.92 + /**
27.93 + * Block of optional data. Byte following tag indicates number
27.94 + * of bytes in this block data.
27.95 + */
27.96 + final static byte TC_BLOCKDATA = (byte)0x77;
27.97 +
27.98 + /**
27.99 + * End of optional block data blocks for an object.
27.100 + */
27.101 + final static byte TC_ENDBLOCKDATA = (byte)0x78;
27.102 +
27.103 + /**
27.104 + * Reset stream context. All handles written into stream are reset.
27.105 + */
27.106 + final static byte TC_RESET = (byte)0x79;
27.107 +
27.108 + /**
27.109 + * long Block data. The long following the tag indicates the
27.110 + * number of bytes in this block data.
27.111 + */
27.112 + final static byte TC_BLOCKDATALONG= (byte)0x7A;
27.113 +
27.114 + /**
27.115 + * Exception during write.
27.116 + */
27.117 + final static byte TC_EXCEPTION = (byte)0x7B;
27.118 +
27.119 + /**
27.120 + * Long string.
27.121 + */
27.122 + final static byte TC_LONGSTRING = (byte)0x7C;
27.123 +
27.124 + /**
27.125 + * new Proxy Class Descriptor.
27.126 + */
27.127 + final static byte TC_PROXYCLASSDESC = (byte)0x7D;
27.128 +
27.129 + /**
27.130 + * new Enum constant.
27.131 + * @since 1.5
27.132 + */
27.133 + final static byte TC_ENUM = (byte)0x7E;
27.134 +
27.135 + /**
27.136 + * Last tag value.
27.137 + */
27.138 + final static byte TC_MAX = (byte)0x7E;
27.139 +
27.140 + /**
27.141 + * First wire handle to be assigned.
27.142 + */
27.143 + final static int baseWireHandle = 0x7e0000;
27.144 +
27.145 +
27.146 + /******************************************************/
27.147 + /* Bit masks for ObjectStreamClass flag.*/
27.148 +
27.149 + /**
27.150 + * Bit mask for ObjectStreamClass flag. Indicates a Serializable class
27.151 + * defines its own writeObject method.
27.152 + */
27.153 + final static byte SC_WRITE_METHOD = 0x01;
27.154 +
27.155 + /**
27.156 + * Bit mask for ObjectStreamClass flag. Indicates Externalizable data
27.157 + * written in Block Data mode.
27.158 + * Added for PROTOCOL_VERSION_2.
27.159 + *
27.160 + * @see #PROTOCOL_VERSION_2
27.161 + * @since 1.2
27.162 + */
27.163 + final static byte SC_BLOCK_DATA = 0x08;
27.164 +
27.165 + /**
27.166 + * Bit mask for ObjectStreamClass flag. Indicates class is Serializable.
27.167 + */
27.168 + final static byte SC_SERIALIZABLE = 0x02;
27.169 +
27.170 + /**
27.171 + * Bit mask for ObjectStreamClass flag. Indicates class is Externalizable.
27.172 + */
27.173 + final static byte SC_EXTERNALIZABLE = 0x04;
27.174 +
27.175 + /**
27.176 + * Bit mask for ObjectStreamClass flag. Indicates class is an enum type.
27.177 + * @since 1.5
27.178 + */
27.179 + final static byte SC_ENUM = 0x10;
27.180 +
27.181 +
27.182 + /* *******************************************************************/
27.183 + /* Security permissions */
27.184 +
27.185 + /**
27.186 + * Enable substitution of one object for another during
27.187 + * serialization/deserialization.
27.188 + *
27.189 + * @see java.io.ObjectOutputStream#enableReplaceObject(boolean)
27.190 + * @see java.io.ObjectInputStream#enableResolveObject(boolean)
27.191 + * @since 1.2
27.192 + */
27.193 + final static SerializablePermission SUBSTITUTION_PERMISSION =
27.194 + new SerializablePermission("enableSubstitution");
27.195 +
27.196 + /**
27.197 + * Enable overriding of readObject and writeObject.
27.198 + *
27.199 + * @see java.io.ObjectOutputStream#writeObjectOverride(Object)
27.200 + * @see java.io.ObjectInputStream#readObjectOverride()
27.201 + * @since 1.2
27.202 + */
27.203 + final static SerializablePermission SUBCLASS_IMPLEMENTATION_PERMISSION =
27.204 + new SerializablePermission("enableSubclassImplementation");
27.205 + /**
27.206 + * A Stream Protocol Version. <p>
27.207 + *
27.208 + * All externalizable data is written in JDK 1.1 external data
27.209 + * format after calling this method. This version is needed to write
27.210 + * streams containing Externalizable data that can be read by
27.211 + * pre-JDK 1.1.6 JVMs.
27.212 + *
27.213 + * @see java.io.ObjectOutputStream#useProtocolVersion(int)
27.214 + * @since 1.2
27.215 + */
27.216 + public final static int PROTOCOL_VERSION_1 = 1;
27.217 +
27.218 +
27.219 + /**
27.220 + * A Stream Protocol Version. <p>
27.221 + *
27.222 + * This protocol is written by JVM 1.2.
27.223 + *
27.224 + * Externalizable data is written in block data mode and is
27.225 + * terminated with TC_ENDBLOCKDATA. Externalizable classdescriptor
27.226 + * flags has SC_BLOCK_DATA enabled. JVM 1.1.6 and greater can
27.227 + * read this format change.
27.228 + *
27.229 + * Enables writing a nonSerializable class descriptor into the
27.230 + * stream. The serialVersionUID of a nonSerializable class is
27.231 + * set to 0L.
27.232 + *
27.233 + * @see java.io.ObjectOutputStream#useProtocolVersion(int)
27.234 + * @see #SC_BLOCK_DATA
27.235 + * @since 1.2
27.236 + */
27.237 + public final static int PROTOCOL_VERSION_2 = 2;
27.238 +}
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
28.2 +++ b/emul/compact/src/main/java/java/io/ObjectStreamException.java Fri Feb 01 16:35:42 2013 +0100
28.3 @@ -0,0 +1,53 @@
28.4 +/*
28.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
28.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
28.7 + *
28.8 + * This code is free software; you can redistribute it and/or modify it
28.9 + * under the terms of the GNU General Public License version 2 only, as
28.10 + * published by the Free Software Foundation. Oracle designates this
28.11 + * particular file as subject to the "Classpath" exception as provided
28.12 + * by Oracle in the LICENSE file that accompanied this code.
28.13 + *
28.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
28.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
28.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
28.17 + * version 2 for more details (a copy is included in the LICENSE file that
28.18 + * accompanied this code).
28.19 + *
28.20 + * You should have received a copy of the GNU General Public License version
28.21 + * 2 along with this work; if not, write to the Free Software Foundation,
28.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
28.23 + *
28.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
28.25 + * or visit www.oracle.com if you need additional information or have any
28.26 + * questions.
28.27 + */
28.28 +
28.29 +package java.io;
28.30 +
28.31 +/**
28.32 + * Superclass of all exceptions specific to Object Stream classes.
28.33 + *
28.34 + * @author unascribed
28.35 + * @since JDK1.1
28.36 + */
28.37 +public abstract class ObjectStreamException extends IOException {
28.38 +
28.39 + private static final long serialVersionUID = 7260898174833392607L;
28.40 +
28.41 + /**
28.42 + * Create an ObjectStreamException with the specified argument.
28.43 + *
28.44 + * @param classname the detailed message for the exception
28.45 + */
28.46 + protected ObjectStreamException(String classname) {
28.47 + super(classname);
28.48 + }
28.49 +
28.50 + /**
28.51 + * Create an ObjectStreamException.
28.52 + */
28.53 + protected ObjectStreamException() {
28.54 + super();
28.55 + }
28.56 +}
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
29.2 +++ b/emul/compact/src/main/java/java/io/ObjectStreamField.java Fri Feb 01 16:35:42 2013 +0100
29.3 @@ -0,0 +1,314 @@
29.4 +/*
29.5 + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
29.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
29.7 + *
29.8 + * This code is free software; you can redistribute it and/or modify it
29.9 + * under the terms of the GNU General Public License version 2 only, as
29.10 + * published by the Free Software Foundation. Oracle designates this
29.11 + * particular file as subject to the "Classpath" exception as provided
29.12 + * by Oracle in the LICENSE file that accompanied this code.
29.13 + *
29.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
29.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
29.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
29.17 + * version 2 for more details (a copy is included in the LICENSE file that
29.18 + * accompanied this code).
29.19 + *
29.20 + * You should have received a copy of the GNU General Public License version
29.21 + * 2 along with this work; if not, write to the Free Software Foundation,
29.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
29.23 + *
29.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
29.25 + * or visit www.oracle.com if you need additional information or have any
29.26 + * questions.
29.27 + */
29.28 +
29.29 +package java.io;
29.30 +
29.31 +import java.lang.reflect.Field;
29.32 +
29.33 +/**
29.34 + * A description of a Serializable field from a Serializable class. An array
29.35 + * of ObjectStreamFields is used to declare the Serializable fields of a class.
29.36 + *
29.37 + * @author Mike Warres
29.38 + * @author Roger Riggs
29.39 + * @see ObjectStreamClass
29.40 + * @since 1.2
29.41 + */
29.42 +public class ObjectStreamField
29.43 + implements Comparable<Object>
29.44 +{
29.45 +
29.46 + /** field name */
29.47 + private final String name;
29.48 + /** canonical JVM signature of field type */
29.49 + private final String signature;
29.50 + /** field type (Object.class if unknown non-primitive type) */
29.51 + private final Class<?> type;
29.52 + /** whether or not to (de)serialize field values as unshared */
29.53 + private final boolean unshared;
29.54 + /** corresponding reflective field object, if any */
29.55 + private final Field field;
29.56 + /** offset of field value in enclosing field group */
29.57 + private int offset = 0;
29.58 +
29.59 + /**
29.60 + * Create a Serializable field with the specified type. This field should
29.61 + * be documented with a <code>serialField</code> tag.
29.62 + *
29.63 + * @param name the name of the serializable field
29.64 + * @param type the <code>Class</code> object of the serializable field
29.65 + */
29.66 + public ObjectStreamField(String name, Class<?> type) {
29.67 + this(name, type, false);
29.68 + }
29.69 +
29.70 + /**
29.71 + * Creates an ObjectStreamField representing a serializable field with the
29.72 + * given name and type. If unshared is false, values of the represented
29.73 + * field are serialized and deserialized in the default manner--if the
29.74 + * field is non-primitive, object values are serialized and deserialized as
29.75 + * if they had been written and read by calls to writeObject and
29.76 + * readObject. If unshared is true, values of the represented field are
29.77 + * serialized and deserialized as if they had been written and read by
29.78 + * calls to writeUnshared and readUnshared.
29.79 + *
29.80 + * @param name field name
29.81 + * @param type field type
29.82 + * @param unshared if false, write/read field values in the same manner
29.83 + * as writeObject/readObject; if true, write/read in the same
29.84 + * manner as writeUnshared/readUnshared
29.85 + * @since 1.4
29.86 + */
29.87 + public ObjectStreamField(String name, Class<?> type, boolean unshared) {
29.88 + if (name == null) {
29.89 + throw new NullPointerException();
29.90 + }
29.91 + this.name = name;
29.92 + this.type = type;
29.93 + this.unshared = unshared;
29.94 + signature = getClassSignature(type).intern();
29.95 + field = null;
29.96 + }
29.97 +
29.98 + /**
29.99 + * Creates an ObjectStreamField representing a field with the given name,
29.100 + * signature and unshared setting.
29.101 + */
29.102 + ObjectStreamField(String name, String signature, boolean unshared) {
29.103 + if (name == null) {
29.104 + throw new NullPointerException();
29.105 + }
29.106 + this.name = name;
29.107 + this.signature = signature.intern();
29.108 + this.unshared = unshared;
29.109 + field = null;
29.110 +
29.111 + switch (signature.charAt(0)) {
29.112 + case 'Z': type = Boolean.TYPE; break;
29.113 + case 'B': type = Byte.TYPE; break;
29.114 + case 'C': type = Character.TYPE; break;
29.115 + case 'S': type = Short.TYPE; break;
29.116 + case 'I': type = Integer.TYPE; break;
29.117 + case 'J': type = Long.TYPE; break;
29.118 + case 'F': type = Float.TYPE; break;
29.119 + case 'D': type = Double.TYPE; break;
29.120 + case 'L':
29.121 + case '[': type = Object.class; break;
29.122 + default: throw new IllegalArgumentException("illegal signature");
29.123 + }
29.124 + }
29.125 +
29.126 + /**
29.127 + * Creates an ObjectStreamField representing the given field with the
29.128 + * specified unshared setting. For compatibility with the behavior of
29.129 + * earlier serialization implementations, a "showType" parameter is
29.130 + * necessary to govern whether or not a getType() call on this
29.131 + * ObjectStreamField (if non-primitive) will return Object.class (as
29.132 + * opposed to a more specific reference type).
29.133 + */
29.134 + ObjectStreamField(Field field, boolean unshared, boolean showType) {
29.135 + this.field = field;
29.136 + this.unshared = unshared;
29.137 + name = field.getName();
29.138 + Class<?> ftype = field.getType();
29.139 + type = (showType || ftype.isPrimitive()) ? ftype : Object.class;
29.140 + signature = getClassSignature(ftype).intern();
29.141 + }
29.142 +
29.143 + /**
29.144 + * Get the name of this field.
29.145 + *
29.146 + * @return a <code>String</code> representing the name of the serializable
29.147 + * field
29.148 + */
29.149 + public String getName() {
29.150 + return name;
29.151 + }
29.152 +
29.153 + /**
29.154 + * Get the type of the field. If the type is non-primitive and this
29.155 + * <code>ObjectStreamField</code> was obtained from a deserialized {@link
29.156 + * ObjectStreamClass} instance, then <code>Object.class</code> is returned.
29.157 + * Otherwise, the <code>Class</code> object for the type of the field is
29.158 + * returned.
29.159 + *
29.160 + * @return a <code>Class</code> object representing the type of the
29.161 + * serializable field
29.162 + */
29.163 + public Class<?> getType() {
29.164 + return type;
29.165 + }
29.166 +
29.167 + /**
29.168 + * Returns character encoding of field type. The encoding is as follows:
29.169 + * <blockquote><pre>
29.170 + * B byte
29.171 + * C char
29.172 + * D double
29.173 + * F float
29.174 + * I int
29.175 + * J long
29.176 + * L class or interface
29.177 + * S short
29.178 + * Z boolean
29.179 + * [ array
29.180 + * </pre></blockquote>
29.181 + *
29.182 + * @return the typecode of the serializable field
29.183 + */
29.184 + // REMIND: deprecate?
29.185 + public char getTypeCode() {
29.186 + return signature.charAt(0);
29.187 + }
29.188 +
29.189 + /**
29.190 + * Return the JVM type signature.
29.191 + *
29.192 + * @return null if this field has a primitive type.
29.193 + */
29.194 + // REMIND: deprecate?
29.195 + public String getTypeString() {
29.196 + return isPrimitive() ? null : signature;
29.197 + }
29.198 +
29.199 + /**
29.200 + * Offset of field within instance data.
29.201 + *
29.202 + * @return the offset of this field
29.203 + * @see #setOffset
29.204 + */
29.205 + // REMIND: deprecate?
29.206 + public int getOffset() {
29.207 + return offset;
29.208 + }
29.209 +
29.210 + /**
29.211 + * Offset within instance data.
29.212 + *
29.213 + * @param offset the offset of the field
29.214 + * @see #getOffset
29.215 + */
29.216 + // REMIND: deprecate?
29.217 + protected void setOffset(int offset) {
29.218 + this.offset = offset;
29.219 + }
29.220 +
29.221 + /**
29.222 + * Return true if this field has a primitive type.
29.223 + *
29.224 + * @return true if and only if this field corresponds to a primitive type
29.225 + */
29.226 + // REMIND: deprecate?
29.227 + public boolean isPrimitive() {
29.228 + char tcode = signature.charAt(0);
29.229 + return ((tcode != 'L') && (tcode != '['));
29.230 + }
29.231 +
29.232 + /**
29.233 + * Returns boolean value indicating whether or not the serializable field
29.234 + * represented by this ObjectStreamField instance is unshared.
29.235 + *
29.236 + * @since 1.4
29.237 + */
29.238 + public boolean isUnshared() {
29.239 + return unshared;
29.240 + }
29.241 +
29.242 + /**
29.243 + * Compare this field with another <code>ObjectStreamField</code>. Return
29.244 + * -1 if this is smaller, 0 if equal, 1 if greater. Types that are
29.245 + * primitives are "smaller" than object types. If equal, the field names
29.246 + * are compared.
29.247 + */
29.248 + // REMIND: deprecate?
29.249 + public int compareTo(Object obj) {
29.250 + ObjectStreamField other = (ObjectStreamField) obj;
29.251 + boolean isPrim = isPrimitive();
29.252 + if (isPrim != other.isPrimitive()) {
29.253 + return isPrim ? -1 : 1;
29.254 + }
29.255 + return name.compareTo(other.name);
29.256 + }
29.257 +
29.258 + /**
29.259 + * Return a string that describes this field.
29.260 + */
29.261 + public String toString() {
29.262 + return signature + ' ' + name;
29.263 + }
29.264 +
29.265 + /**
29.266 + * Returns field represented by this ObjectStreamField, or null if
29.267 + * ObjectStreamField is not associated with an actual field.
29.268 + */
29.269 + Field getField() {
29.270 + return field;
29.271 + }
29.272 +
29.273 + /**
29.274 + * Returns JVM type signature of field (similar to getTypeString, except
29.275 + * that signature strings are returned for primitive fields as well).
29.276 + */
29.277 + String getSignature() {
29.278 + return signature;
29.279 + }
29.280 +
29.281 + /**
29.282 + * Returns JVM type signature for given class.
29.283 + */
29.284 + private static String getClassSignature(Class<?> cl) {
29.285 + StringBuilder sbuf = new StringBuilder();
29.286 + while (cl.isArray()) {
29.287 + sbuf.append('[');
29.288 + cl = cl.getComponentType();
29.289 + }
29.290 + if (cl.isPrimitive()) {
29.291 + if (cl == Integer.TYPE) {
29.292 + sbuf.append('I');
29.293 + } else if (cl == Byte.TYPE) {
29.294 + sbuf.append('B');
29.295 + } else if (cl == Long.TYPE) {
29.296 + sbuf.append('J');
29.297 + } else if (cl == Float.TYPE) {
29.298 + sbuf.append('F');
29.299 + } else if (cl == Double.TYPE) {
29.300 + sbuf.append('D');
29.301 + } else if (cl == Short.TYPE) {
29.302 + sbuf.append('S');
29.303 + } else if (cl == Character.TYPE) {
29.304 + sbuf.append('C');
29.305 + } else if (cl == Boolean.TYPE) {
29.306 + sbuf.append('Z');
29.307 + } else if (cl == Void.TYPE) {
29.308 + sbuf.append('V');
29.309 + } else {
29.310 + throw new InternalError();
29.311 + }
29.312 + } else {
29.313 + sbuf.append('L' + cl.getName().replace('.', '/') + ';');
29.314 + }
29.315 + return sbuf.toString();
29.316 + }
29.317 +}
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
30.2 +++ b/emul/compact/src/main/java/java/io/OptionalDataException.java Fri Feb 01 16:35:42 2013 +0100
30.3 @@ -0,0 +1,83 @@
30.4 +/*
30.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
30.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
30.7 + *
30.8 + * This code is free software; you can redistribute it and/or modify it
30.9 + * under the terms of the GNU General Public License version 2 only, as
30.10 + * published by the Free Software Foundation. Oracle designates this
30.11 + * particular file as subject to the "Classpath" exception as provided
30.12 + * by Oracle in the LICENSE file that accompanied this code.
30.13 + *
30.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
30.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
30.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
30.17 + * version 2 for more details (a copy is included in the LICENSE file that
30.18 + * accompanied this code).
30.19 + *
30.20 + * You should have received a copy of the GNU General Public License version
30.21 + * 2 along with this work; if not, write to the Free Software Foundation,
30.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
30.23 + *
30.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
30.25 + * or visit www.oracle.com if you need additional information or have any
30.26 + * questions.
30.27 + */
30.28 +package java.io;
30.29 +
30.30 +/**
30.31 + * Exception indicating the failure of an object read operation due to
30.32 + * unread primitive data, or the end of data belonging to a serialized
30.33 + * object in the stream. This exception may be thrown in two cases:
30.34 + *
30.35 + * <ul>
30.36 + * <li>An attempt was made to read an object when the next element in the
30.37 + * stream is primitive data. In this case, the OptionalDataException's
30.38 + * length field is set to the number of bytes of primitive data
30.39 + * immediately readable from the stream, and the eof field is set to
30.40 + * false.
30.41 + *
30.42 + * <li>An attempt was made to read past the end of data consumable by a
30.43 + * class-defined readObject or readExternal method. In this case, the
30.44 + * OptionalDataException's eof field is set to true, and the length field
30.45 + * is set to 0.
30.46 + * </ul>
30.47 + *
30.48 + * @author unascribed
30.49 + * @since JDK1.1
30.50 + */
30.51 +public class OptionalDataException extends ObjectStreamException {
30.52 +
30.53 + private static final long serialVersionUID = -8011121865681257820L;
30.54 +
30.55 + /*
30.56 + * Create an <code>OptionalDataException</code> with a length.
30.57 + */
30.58 + OptionalDataException(int len) {
30.59 + eof = false;
30.60 + length = len;
30.61 + }
30.62 +
30.63 + /*
30.64 + * Create an <code>OptionalDataException</code> signifying no
30.65 + * more primitive data is available.
30.66 + */
30.67 + OptionalDataException(boolean end) {
30.68 + length = 0;
30.69 + eof = end;
30.70 + }
30.71 +
30.72 + /**
30.73 + * The number of bytes of primitive data available to be read
30.74 + * in the current buffer.
30.75 + *
30.76 + * @serial
30.77 + */
30.78 + public int length;
30.79 +
30.80 + /**
30.81 + * True if there is no more data in the buffered part of the stream.
30.82 + *
30.83 + * @serial
30.84 + */
30.85 + public boolean eof;
30.86 +}
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
31.2 +++ b/emul/compact/src/main/java/java/io/OutputStream.java Fri Feb 01 16:35:42 2013 +0100
31.3 @@ -0,0 +1,154 @@
31.4 +/*
31.5 + * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.
31.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
31.7 + *
31.8 + * This code is free software; you can redistribute it and/or modify it
31.9 + * under the terms of the GNU General Public License version 2 only, as
31.10 + * published by the Free Software Foundation. Oracle designates this
31.11 + * particular file as subject to the "Classpath" exception as provided
31.12 + * by Oracle in the LICENSE file that accompanied this code.
31.13 + *
31.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
31.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
31.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
31.17 + * version 2 for more details (a copy is included in the LICENSE file that
31.18 + * accompanied this code).
31.19 + *
31.20 + * You should have received a copy of the GNU General Public License version
31.21 + * 2 along with this work; if not, write to the Free Software Foundation,
31.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
31.23 + *
31.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
31.25 + * or visit www.oracle.com if you need additional information or have any
31.26 + * questions.
31.27 + */
31.28 +
31.29 +package java.io;
31.30 +
31.31 +/**
31.32 + * This abstract class is the superclass of all classes representing
31.33 + * an output stream of bytes. An output stream accepts output bytes
31.34 + * and sends them to some sink.
31.35 + * <p>
31.36 + * Applications that need to define a subclass of
31.37 + * <code>OutputStream</code> must always provide at least a method
31.38 + * that writes one byte of output.
31.39 + *
31.40 + * @author Arthur van Hoff
31.41 + * @see java.io.BufferedOutputStream
31.42 + * @see java.io.ByteArrayOutputStream
31.43 + * @see java.io.DataOutputStream
31.44 + * @see java.io.FilterOutputStream
31.45 + * @see java.io.InputStream
31.46 + * @see java.io.OutputStream#write(int)
31.47 + * @since JDK1.0
31.48 + */
31.49 +public abstract class OutputStream implements Closeable, Flushable {
31.50 + /**
31.51 + * Writes the specified byte to this output stream. The general
31.52 + * contract for <code>write</code> is that one byte is written
31.53 + * to the output stream. The byte to be written is the eight
31.54 + * low-order bits of the argument <code>b</code>. The 24
31.55 + * high-order bits of <code>b</code> are ignored.
31.56 + * <p>
31.57 + * Subclasses of <code>OutputStream</code> must provide an
31.58 + * implementation for this method.
31.59 + *
31.60 + * @param b the <code>byte</code>.
31.61 + * @exception IOException if an I/O error occurs. In particular,
31.62 + * an <code>IOException</code> may be thrown if the
31.63 + * output stream has been closed.
31.64 + */
31.65 + public abstract void write(int b) throws IOException;
31.66 +
31.67 + /**
31.68 + * Writes <code>b.length</code> bytes from the specified byte array
31.69 + * to this output stream. The general contract for <code>write(b)</code>
31.70 + * is that it should have exactly the same effect as the call
31.71 + * <code>write(b, 0, b.length)</code>.
31.72 + *
31.73 + * @param b the data.
31.74 + * @exception IOException if an I/O error occurs.
31.75 + * @see java.io.OutputStream#write(byte[], int, int)
31.76 + */
31.77 + public void write(byte b[]) throws IOException {
31.78 + write(b, 0, b.length);
31.79 + }
31.80 +
31.81 + /**
31.82 + * Writes <code>len</code> bytes from the specified byte array
31.83 + * starting at offset <code>off</code> to this output stream.
31.84 + * The general contract for <code>write(b, off, len)</code> is that
31.85 + * some of the bytes in the array <code>b</code> are written to the
31.86 + * output stream in order; element <code>b[off]</code> is the first
31.87 + * byte written and <code>b[off+len-1]</code> is the last byte written
31.88 + * by this operation.
31.89 + * <p>
31.90 + * The <code>write</code> method of <code>OutputStream</code> calls
31.91 + * the write method of one argument on each of the bytes to be
31.92 + * written out. Subclasses are encouraged to override this method and
31.93 + * provide a more efficient implementation.
31.94 + * <p>
31.95 + * If <code>b</code> is <code>null</code>, a
31.96 + * <code>NullPointerException</code> is thrown.
31.97 + * <p>
31.98 + * If <code>off</code> is negative, or <code>len</code> is negative, or
31.99 + * <code>off+len</code> is greater than the length of the array
31.100 + * <code>b</code>, then an <tt>IndexOutOfBoundsException</tt> is thrown.
31.101 + *
31.102 + * @param b the data.
31.103 + * @param off the start offset in the data.
31.104 + * @param len the number of bytes to write.
31.105 + * @exception IOException if an I/O error occurs. In particular,
31.106 + * an <code>IOException</code> is thrown if the output
31.107 + * stream is closed.
31.108 + */
31.109 + public void write(byte b[], int off, int len) throws IOException {
31.110 + if (b == null) {
31.111 + throw new NullPointerException();
31.112 + } else if ((off < 0) || (off > b.length) || (len < 0) ||
31.113 + ((off + len) > b.length) || ((off + len) < 0)) {
31.114 + throw new IndexOutOfBoundsException();
31.115 + } else if (len == 0) {
31.116 + return;
31.117 + }
31.118 + for (int i = 0 ; i < len ; i++) {
31.119 + write(b[off + i]);
31.120 + }
31.121 + }
31.122 +
31.123 + /**
31.124 + * Flushes this output stream and forces any buffered output bytes
31.125 + * to be written out. The general contract of <code>flush</code> is
31.126 + * that calling it is an indication that, if any bytes previously
31.127 + * written have been buffered by the implementation of the output
31.128 + * stream, such bytes should immediately be written to their
31.129 + * intended destination.
31.130 + * <p>
31.131 + * If the intended destination of this stream is an abstraction provided by
31.132 + * the underlying operating system, for example a file, then flushing the
31.133 + * stream guarantees only that bytes previously written to the stream are
31.134 + * passed to the operating system for writing; it does not guarantee that
31.135 + * they are actually written to a physical device such as a disk drive.
31.136 + * <p>
31.137 + * The <code>flush</code> method of <code>OutputStream</code> does nothing.
31.138 + *
31.139 + * @exception IOException if an I/O error occurs.
31.140 + */
31.141 + public void flush() throws IOException {
31.142 + }
31.143 +
31.144 + /**
31.145 + * Closes this output stream and releases any system resources
31.146 + * associated with this stream. The general contract of <code>close</code>
31.147 + * is that it closes the output stream. A closed stream cannot perform
31.148 + * output operations and cannot be reopened.
31.149 + * <p>
31.150 + * The <code>close</code> method of <code>OutputStream</code> does nothing.
31.151 + *
31.152 + * @exception IOException if an I/O error occurs.
31.153 + */
31.154 + public void close() throws IOException {
31.155 + }
31.156 +
31.157 +}
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
32.2 +++ b/emul/compact/src/main/java/java/io/StreamCorruptedException.java Fri Feb 01 16:35:42 2013 +0100
32.3 @@ -0,0 +1,54 @@
32.4 +/*
32.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
32.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
32.7 + *
32.8 + * This code is free software; you can redistribute it and/or modify it
32.9 + * under the terms of the GNU General Public License version 2 only, as
32.10 + * published by the Free Software Foundation. Oracle designates this
32.11 + * particular file as subject to the "Classpath" exception as provided
32.12 + * by Oracle in the LICENSE file that accompanied this code.
32.13 + *
32.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
32.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
32.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
32.17 + * version 2 for more details (a copy is included in the LICENSE file that
32.18 + * accompanied this code).
32.19 + *
32.20 + * You should have received a copy of the GNU General Public License version
32.21 + * 2 along with this work; if not, write to the Free Software Foundation,
32.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
32.23 + *
32.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
32.25 + * or visit www.oracle.com if you need additional information or have any
32.26 + * questions.
32.27 + */
32.28 +
32.29 +package java.io;
32.30 +
32.31 +/**
32.32 + * Thrown when control information that was read from an object stream
32.33 + * violates internal consistency checks.
32.34 + *
32.35 + * @author unascribed
32.36 + * @since JDK1.1
32.37 + */
32.38 +public class StreamCorruptedException extends ObjectStreamException {
32.39 +
32.40 + private static final long serialVersionUID = 8983558202217591746L;
32.41 +
32.42 + /**
32.43 + * Create a StreamCorruptedException and list a reason why thrown.
32.44 + *
32.45 + * @param reason String describing the reason for the exception.
32.46 + */
32.47 + public StreamCorruptedException(String reason) {
32.48 + super(reason);
32.49 + }
32.50 +
32.51 + /**
32.52 + * Create a StreamCorruptedException and list no reason why thrown.
32.53 + */
32.54 + public StreamCorruptedException() {
32.55 + super();
32.56 + }
32.57 +}
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
33.2 +++ b/emul/compact/src/main/java/java/io/WriteAbortedException.java Fri Feb 01 16:35:42 2013 +0100
33.3 @@ -0,0 +1,93 @@
33.4 +/*
33.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
33.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33.7 + *
33.8 + * This code is free software; you can redistribute it and/or modify it
33.9 + * under the terms of the GNU General Public License version 2 only, as
33.10 + * published by the Free Software Foundation. Oracle designates this
33.11 + * particular file as subject to the "Classpath" exception as provided
33.12 + * by Oracle in the LICENSE file that accompanied this code.
33.13 + *
33.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
33.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
33.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
33.17 + * version 2 for more details (a copy is included in the LICENSE file that
33.18 + * accompanied this code).
33.19 + *
33.20 + * You should have received a copy of the GNU General Public License version
33.21 + * 2 along with this work; if not, write to the Free Software Foundation,
33.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
33.23 + *
33.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
33.25 + * or visit www.oracle.com if you need additional information or have any
33.26 + * questions.
33.27 + */
33.28 +
33.29 +package java.io;
33.30 +
33.31 +/**
33.32 + * Signals that one of the ObjectStreamExceptions was thrown during a
33.33 + * write operation. Thrown during a read operation when one of the
33.34 + * ObjectStreamExceptions was thrown during a write operation. The
33.35 + * exception that terminated the write can be found in the detail
33.36 + * field. The stream is reset to it's initial state and all references
33.37 + * to objects already deserialized are discarded.
33.38 + *
33.39 + * <p>As of release 1.4, this exception has been retrofitted to conform to
33.40 + * the general purpose exception-chaining mechanism. The "exception causing
33.41 + * the abort" that is provided at construction time and
33.42 + * accessed via the public {@link #detail} field is now known as the
33.43 + * <i>cause</i>, and may be accessed via the {@link Throwable#getCause()}
33.44 + * method, as well as the aforementioned "legacy field."
33.45 + *
33.46 + * @author unascribed
33.47 + * @since JDK1.1
33.48 + */
33.49 +public class WriteAbortedException extends ObjectStreamException {
33.50 + private static final long serialVersionUID = -3326426625597282442L;
33.51 +
33.52 + /**
33.53 + * Exception that was caught while writing the ObjectStream.
33.54 + *
33.55 + * <p>This field predates the general-purpose exception chaining facility.
33.56 + * The {@link Throwable#getCause()} method is now the preferred means of
33.57 + * obtaining this information.
33.58 + *
33.59 + * @serial
33.60 + */
33.61 + public Exception detail;
33.62 +
33.63 + /**
33.64 + * Constructs a WriteAbortedException with a string describing
33.65 + * the exception and the exception causing the abort.
33.66 + * @param s String describing the exception.
33.67 + * @param ex Exception causing the abort.
33.68 + */
33.69 + public WriteAbortedException(String s, Exception ex) {
33.70 + super(s);
33.71 + initCause(null); // Disallow subsequent initCause
33.72 + detail = ex;
33.73 + }
33.74 +
33.75 + /**
33.76 + * Produce the message and include the message from the nested
33.77 + * exception, if there is one.
33.78 + */
33.79 + public String getMessage() {
33.80 + if (detail == null)
33.81 + return super.getMessage();
33.82 + else
33.83 + return super.getMessage() + "; " + detail.toString();
33.84 + }
33.85 +
33.86 + /**
33.87 + * Returns the exception that terminated the operation (the <i>cause</i>).
33.88 + *
33.89 + * @return the exception that terminated the operation (the <i>cause</i>),
33.90 + * which may be null.
33.91 + * @since 1.4
33.92 + */
33.93 + public Throwable getCause() {
33.94 + return detail;
33.95 + }
33.96 +}
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
34.2 +++ b/emul/compact/src/main/java/java/lang/ref/PhantomReference.java Fri Feb 01 16:35:42 2013 +0100
34.3 @@ -0,0 +1,83 @@
34.4 +/*
34.5 + * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
34.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
34.7 + *
34.8 + * This code is free software; you can redistribute it and/or modify it
34.9 + * under the terms of the GNU General Public License version 2 only, as
34.10 + * published by the Free Software Foundation. Oracle designates this
34.11 + * particular file as subject to the "Classpath" exception as provided
34.12 + * by Oracle in the LICENSE file that accompanied this code.
34.13 + *
34.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
34.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
34.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
34.17 + * version 2 for more details (a copy is included in the LICENSE file that
34.18 + * accompanied this code).
34.19 + *
34.20 + * You should have received a copy of the GNU General Public License version
34.21 + * 2 along with this work; if not, write to the Free Software Foundation,
34.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
34.23 + *
34.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
34.25 + * or visit www.oracle.com if you need additional information or have any
34.26 + * questions.
34.27 + */
34.28 +
34.29 +package java.lang.ref;
34.30 +
34.31 +
34.32 +/**
34.33 + * Phantom reference objects, which are enqueued after the collector
34.34 + * determines that their referents may otherwise be reclaimed. Phantom
34.35 + * references are most often used for scheduling pre-mortem cleanup actions in
34.36 + * a more flexible way than is possible with the Java finalization mechanism.
34.37 + *
34.38 + * <p> If the garbage collector determines at a certain point in time that the
34.39 + * referent of a phantom reference is <a
34.40 + * href="package-summary.html#reachability">phantom reachable</a>, then at that
34.41 + * time or at some later time it will enqueue the reference.
34.42 + *
34.43 + * <p> In order to ensure that a reclaimable object remains so, the referent of
34.44 + * a phantom reference may not be retrieved: The <code>get</code> method of a
34.45 + * phantom reference always returns <code>null</code>.
34.46 + *
34.47 + * <p> Unlike soft and weak references, phantom references are not
34.48 + * automatically cleared by the garbage collector as they are enqueued. An
34.49 + * object that is reachable via phantom references will remain so until all
34.50 + * such references are cleared or themselves become unreachable.
34.51 + *
34.52 + * @author Mark Reinhold
34.53 + * @since 1.2
34.54 + */
34.55 +
34.56 +public class PhantomReference<T> extends Reference<T> {
34.57 +
34.58 + /**
34.59 + * Returns this reference object's referent. Because the referent of a
34.60 + * phantom reference is always inaccessible, this method always returns
34.61 + * <code>null</code>.
34.62 + *
34.63 + * @return <code>null</code>
34.64 + */
34.65 + public T get() {
34.66 + return null;
34.67 + }
34.68 +
34.69 + /**
34.70 + * Creates a new phantom reference that refers to the given object and
34.71 + * is registered with the given queue.
34.72 + *
34.73 + * <p> It is possible to create a phantom reference with a <tt>null</tt>
34.74 + * queue, but such a reference is completely useless: Its <tt>get</tt>
34.75 + * method will always return null and, since it does not have a queue, it
34.76 + * will never be enqueued.
34.77 + *
34.78 + * @param referent the object the new phantom reference will refer to
34.79 + * @param q the queue with which the reference is to be registered,
34.80 + * or <tt>null</tt> if registration is not required
34.81 + */
34.82 + public PhantomReference(T referent, ReferenceQueue<? super T> q) {
34.83 + super(referent, q);
34.84 + }
34.85 +
34.86 +}
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
35.2 +++ b/emul/compact/src/main/java/java/lang/ref/Reference.java Fri Feb 01 16:35:42 2013 +0100
35.3 @@ -0,0 +1,238 @@
35.4 +/*
35.5 + * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
35.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
35.7 + *
35.8 + * This code is free software; you can redistribute it and/or modify it
35.9 + * under the terms of the GNU General Public License version 2 only, as
35.10 + * published by the Free Software Foundation. Oracle designates this
35.11 + * particular file as subject to the "Classpath" exception as provided
35.12 + * by Oracle in the LICENSE file that accompanied this code.
35.13 + *
35.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
35.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
35.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
35.17 + * version 2 for more details (a copy is included in the LICENSE file that
35.18 + * accompanied this code).
35.19 + *
35.20 + * You should have received a copy of the GNU General Public License version
35.21 + * 2 along with this work; if not, write to the Free Software Foundation,
35.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
35.23 + *
35.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
35.25 + * or visit www.oracle.com if you need additional information or have any
35.26 + * questions.
35.27 + */
35.28 +
35.29 +package java.lang.ref;
35.30 +
35.31 +import sun.misc.Cleaner;
35.32 +
35.33 +
35.34 +/**
35.35 + * Abstract base class for reference objects. This class defines the
35.36 + * operations common to all reference objects. Because reference objects are
35.37 + * implemented in close cooperation with the garbage collector, this class may
35.38 + * not be subclassed directly.
35.39 + *
35.40 + * @author Mark Reinhold
35.41 + * @since 1.2
35.42 + */
35.43 +
35.44 +public abstract class Reference<T> {
35.45 +
35.46 + /* A Reference instance is in one of four possible internal states:
35.47 + *
35.48 + * Active: Subject to special treatment by the garbage collector. Some
35.49 + * time after the collector detects that the reachability of the
35.50 + * referent has changed to the appropriate state, it changes the
35.51 + * instance's state to either Pending or Inactive, depending upon
35.52 + * whether or not the instance was registered with a queue when it was
35.53 + * created. In the former case it also adds the instance to the
35.54 + * pending-Reference list. Newly-created instances are Active.
35.55 + *
35.56 + * Pending: An element of the pending-Reference list, waiting to be
35.57 + * enqueued by the Reference-handler thread. Unregistered instances
35.58 + * are never in this state.
35.59 + *
35.60 + * Enqueued: An element of the queue with which the instance was
35.61 + * registered when it was created. When an instance is removed from
35.62 + * its ReferenceQueue, it is made Inactive. Unregistered instances are
35.63 + * never in this state.
35.64 + *
35.65 + * Inactive: Nothing more to do. Once an instance becomes Inactive its
35.66 + * state will never change again.
35.67 + *
35.68 + * The state is encoded in the queue and next fields as follows:
35.69 + *
35.70 + * Active: queue = ReferenceQueue with which instance is registered, or
35.71 + * ReferenceQueue.NULL if it was not registered with a queue; next =
35.72 + * null.
35.73 + *
35.74 + * Pending: queue = ReferenceQueue with which instance is registered;
35.75 + * next = Following instance in queue, or this if at end of list.
35.76 + *
35.77 + * Enqueued: queue = ReferenceQueue.ENQUEUED; next = Following instance
35.78 + * in queue, or this if at end of list.
35.79 + *
35.80 + * Inactive: queue = ReferenceQueue.NULL; next = this.
35.81 + *
35.82 + * With this scheme the collector need only examine the next field in order
35.83 + * to determine whether a Reference instance requires special treatment: If
35.84 + * the next field is null then the instance is active; if it is non-null,
35.85 + * then the collector should treat the instance normally.
35.86 + *
35.87 + * To ensure that concurrent collector can discover active Reference
35.88 + * objects without interfering with application threads that may apply
35.89 + * the enqueue() method to those objects, collectors should link
35.90 + * discovered objects through the discovered field.
35.91 + */
35.92 +
35.93 + private T referent; /* Treated specially by GC */
35.94 +
35.95 + ReferenceQueue<? super T> queue;
35.96 +
35.97 + Reference next;
35.98 + transient private Reference<T> discovered; /* used by VM */
35.99 +
35.100 +
35.101 + /* Object used to synchronize with the garbage collector. The collector
35.102 + * must acquire this lock at the beginning of each collection cycle. It is
35.103 + * therefore critical that any code holding this lock complete as quickly
35.104 + * as possible, allocate no new objects, and avoid calling user code.
35.105 + */
35.106 + static private class Lock { };
35.107 + private static Lock lock = new Lock();
35.108 +
35.109 +
35.110 + /* List of References waiting to be enqueued. The collector adds
35.111 + * References to this list, while the Reference-handler thread removes
35.112 + * them. This list is protected by the above lock object.
35.113 + */
35.114 + private static Reference pending = null;
35.115 +
35.116 + /* High-priority thread to enqueue pending References
35.117 + */
35.118 + private static class ReferenceHandler extends Thread {
35.119 +
35.120 + ReferenceHandler(ThreadGroup g, String name) {
35.121 + super(g, name);
35.122 + }
35.123 +
35.124 + public void run() {
35.125 + for (;;) {
35.126 +
35.127 + Reference r;
35.128 + synchronized (lock) {
35.129 + if (pending != null) {
35.130 + r = pending;
35.131 + Reference rn = r.next;
35.132 + pending = (rn == r) ? null : rn;
35.133 + r.next = r;
35.134 + } else {
35.135 + try {
35.136 + lock.wait();
35.137 + } catch (InterruptedException x) { }
35.138 + continue;
35.139 + }
35.140 + }
35.141 +
35.142 + // Fast path for cleaners
35.143 + if (r instanceof Cleaner) {
35.144 + ((Cleaner)r).clean();
35.145 + continue;
35.146 + }
35.147 +
35.148 + ReferenceQueue q = r.queue;
35.149 + if (q != ReferenceQueue.NULL) q.enqueue(r);
35.150 + }
35.151 + }
35.152 + }
35.153 +
35.154 + static {
35.155 + ThreadGroup tg = Thread.currentThread().getThreadGroup();
35.156 + for (ThreadGroup tgn = tg;
35.157 + tgn != null;
35.158 + tg = tgn, tgn = tg.getParent());
35.159 + Thread handler = new ReferenceHandler(tg, "Reference Handler");
35.160 + /* If there were a special system-only priority greater than
35.161 + * MAX_PRIORITY, it would be used here
35.162 + */
35.163 + handler.setPriority(Thread.MAX_PRIORITY);
35.164 + handler.setDaemon(true);
35.165 + handler.start();
35.166 + }
35.167 +
35.168 +
35.169 + /* -- Referent accessor and setters -- */
35.170 +
35.171 + /**
35.172 + * Returns this reference object's referent. If this reference object has
35.173 + * been cleared, either by the program or by the garbage collector, then
35.174 + * this method returns <code>null</code>.
35.175 + *
35.176 + * @return The object to which this reference refers, or
35.177 + * <code>null</code> if this reference object has been cleared
35.178 + */
35.179 + public T get() {
35.180 + return this.referent;
35.181 + }
35.182 +
35.183 + /**
35.184 + * Clears this reference object. Invoking this method will not cause this
35.185 + * object to be enqueued.
35.186 + *
35.187 + * <p> This method is invoked only by Java code; when the garbage collector
35.188 + * clears references it does so directly, without invoking this method.
35.189 + */
35.190 + public void clear() {
35.191 + this.referent = null;
35.192 + }
35.193 +
35.194 +
35.195 + /* -- Queue operations -- */
35.196 +
35.197 + /**
35.198 + * Tells whether or not this reference object has been enqueued, either by
35.199 + * the program or by the garbage collector. If this reference object was
35.200 + * not registered with a queue when it was created, then this method will
35.201 + * always return <code>false</code>.
35.202 + *
35.203 + * @return <code>true</code> if and only if this reference object has
35.204 + * been enqueued
35.205 + */
35.206 + public boolean isEnqueued() {
35.207 + /* In terms of the internal states, this predicate actually tests
35.208 + whether the instance is either Pending or Enqueued */
35.209 + synchronized (this) {
35.210 + return (this.queue != ReferenceQueue.NULL) && (this.next != null);
35.211 + }
35.212 + }
35.213 +
35.214 + /**
35.215 + * Adds this reference object to the queue with which it is registered,
35.216 + * if any.
35.217 + *
35.218 + * <p> This method is invoked only by Java code; when the garbage collector
35.219 + * enqueues references it does so directly, without invoking this method.
35.220 + *
35.221 + * @return <code>true</code> if this reference object was successfully
35.222 + * enqueued; <code>false</code> if it was already enqueued or if
35.223 + * it was not registered with a queue when it was created
35.224 + */
35.225 + public boolean enqueue() {
35.226 + return this.queue.enqueue(this);
35.227 + }
35.228 +
35.229 +
35.230 + /* -- Constructors -- */
35.231 +
35.232 + Reference(T referent) {
35.233 + this(referent, null);
35.234 + }
35.235 +
35.236 + Reference(T referent, ReferenceQueue<? super T> queue) {
35.237 + this.referent = referent;
35.238 + this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
35.239 + }
35.240 +
35.241 +}
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
36.2 +++ b/emul/compact/src/main/java/java/lang/ref/ReferenceQueue.java Fri Feb 01 16:35:42 2013 +0100
36.3 @@ -0,0 +1,154 @@
36.4 +/*
36.5 + * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved.
36.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
36.7 + *
36.8 + * This code is free software; you can redistribute it and/or modify it
36.9 + * under the terms of the GNU General Public License version 2 only, as
36.10 + * published by the Free Software Foundation. Oracle designates this
36.11 + * particular file as subject to the "Classpath" exception as provided
36.12 + * by Oracle in the LICENSE file that accompanied this code.
36.13 + *
36.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
36.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
36.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
36.17 + * version 2 for more details (a copy is included in the LICENSE file that
36.18 + * accompanied this code).
36.19 + *
36.20 + * You should have received a copy of the GNU General Public License version
36.21 + * 2 along with this work; if not, write to the Free Software Foundation,
36.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
36.23 + *
36.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
36.25 + * or visit www.oracle.com if you need additional information or have any
36.26 + * questions.
36.27 + */
36.28 +
36.29 +package java.lang.ref;
36.30 +
36.31 +/**
36.32 + * Reference queues, to which registered reference objects are appended by the
36.33 + * garbage collector after the appropriate reachability changes are detected.
36.34 + *
36.35 + * @author Mark Reinhold
36.36 + * @since 1.2
36.37 + */
36.38 +
36.39 +public class ReferenceQueue<T> {
36.40 +
36.41 + /**
36.42 + * Constructs a new reference-object queue.
36.43 + */
36.44 + public ReferenceQueue() { }
36.45 +
36.46 + private static class Null extends ReferenceQueue {
36.47 + boolean enqueue(Reference r) {
36.48 + return false;
36.49 + }
36.50 + }
36.51 +
36.52 + static ReferenceQueue NULL = new Null();
36.53 + static ReferenceQueue ENQUEUED = new Null();
36.54 +
36.55 + static private class Lock { };
36.56 + private Lock lock = new Lock();
36.57 + private volatile Reference<? extends T> head = null;
36.58 + private long queueLength = 0;
36.59 +
36.60 + boolean enqueue(Reference<? extends T> r) { /* Called only by Reference class */
36.61 + synchronized (r) {
36.62 + if (r.queue == ENQUEUED) return false;
36.63 + synchronized (lock) {
36.64 + r.queue = ENQUEUED;
36.65 + r.next = (head == null) ? r : head;
36.66 + head = r;
36.67 + queueLength++;
36.68 + if (r instanceof FinalReference) {
36.69 + sun.misc.VM.addFinalRefCount(1);
36.70 + }
36.71 + lock.notifyAll();
36.72 + return true;
36.73 + }
36.74 + }
36.75 + }
36.76 +
36.77 + private Reference<? extends T> reallyPoll() { /* Must hold lock */
36.78 + if (head != null) {
36.79 + Reference<? extends T> r = head;
36.80 + head = (r.next == r) ? null : r.next;
36.81 + r.queue = NULL;
36.82 + r.next = r;
36.83 + queueLength--;
36.84 + if (r instanceof FinalReference) {
36.85 + sun.misc.VM.addFinalRefCount(-1);
36.86 + }
36.87 + return r;
36.88 + }
36.89 + return null;
36.90 + }
36.91 +
36.92 + /**
36.93 + * Polls this queue to see if a reference object is available. If one is
36.94 + * available without further delay then it is removed from the queue and
36.95 + * returned. Otherwise this method immediately returns <tt>null</tt>.
36.96 + *
36.97 + * @return A reference object, if one was immediately available,
36.98 + * otherwise <code>null</code>
36.99 + */
36.100 + public Reference<? extends T> poll() {
36.101 + if (head == null)
36.102 + return null;
36.103 + synchronized (lock) {
36.104 + return reallyPoll();
36.105 + }
36.106 + }
36.107 +
36.108 + /**
36.109 + * Removes the next reference object in this queue, blocking until either
36.110 + * one becomes available or the given timeout period expires.
36.111 + *
36.112 + * <p> This method does not offer real-time guarantees: It schedules the
36.113 + * timeout as if by invoking the {@link Object#wait(long)} method.
36.114 + *
36.115 + * @param timeout If positive, block for up to <code>timeout</code>
36.116 + * milliseconds while waiting for a reference to be
36.117 + * added to this queue. If zero, block indefinitely.
36.118 + *
36.119 + * @return A reference object, if one was available within the specified
36.120 + * timeout period, otherwise <code>null</code>
36.121 + *
36.122 + * @throws IllegalArgumentException
36.123 + * If the value of the timeout argument is negative
36.124 + *
36.125 + * @throws InterruptedException
36.126 + * If the timeout wait is interrupted
36.127 + */
36.128 + public Reference<? extends T> remove(long timeout)
36.129 + throws IllegalArgumentException, InterruptedException
36.130 + {
36.131 + if (timeout < 0) {
36.132 + throw new IllegalArgumentException("Negative timeout value");
36.133 + }
36.134 + synchronized (lock) {
36.135 + Reference<? extends T> r = reallyPoll();
36.136 + if (r != null) return r;
36.137 + for (;;) {
36.138 + lock.wait(timeout);
36.139 + r = reallyPoll();
36.140 + if (r != null) return r;
36.141 + if (timeout != 0) return null;
36.142 + }
36.143 + }
36.144 + }
36.145 +
36.146 + /**
36.147 + * Removes the next reference object in this queue, blocking until one
36.148 + * becomes available.
36.149 + *
36.150 + * @return A reference object, blocking until one becomes available
36.151 + * @throws InterruptedException If the wait is interrupted
36.152 + */
36.153 + public Reference<? extends T> remove() throws InterruptedException {
36.154 + return remove(0);
36.155 + }
36.156 +
36.157 +}
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
37.2 +++ b/emul/compact/src/main/java/java/lang/ref/SoftReference.java Fri Feb 01 16:35:42 2013 +0100
37.3 @@ -0,0 +1,118 @@
37.4 +/*
37.5 + * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
37.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
37.7 + *
37.8 + * This code is free software; you can redistribute it and/or modify it
37.9 + * under the terms of the GNU General Public License version 2 only, as
37.10 + * published by the Free Software Foundation. Oracle designates this
37.11 + * particular file as subject to the "Classpath" exception as provided
37.12 + * by Oracle in the LICENSE file that accompanied this code.
37.13 + *
37.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
37.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
37.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
37.17 + * version 2 for more details (a copy is included in the LICENSE file that
37.18 + * accompanied this code).
37.19 + *
37.20 + * You should have received a copy of the GNU General Public License version
37.21 + * 2 along with this work; if not, write to the Free Software Foundation,
37.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
37.23 + *
37.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
37.25 + * or visit www.oracle.com if you need additional information or have any
37.26 + * questions.
37.27 + */
37.28 +
37.29 +package java.lang.ref;
37.30 +
37.31 +
37.32 +/**
37.33 + * Soft reference objects, which are cleared at the discretion of the garbage
37.34 + * collector in response to memory demand. Soft references are most often used
37.35 + * to implement memory-sensitive caches.
37.36 + *
37.37 + * <p> Suppose that the garbage collector determines at a certain point in time
37.38 + * that an object is <a href="package-summary.html#reachability">softly
37.39 + * reachable</a>. At that time it may choose to clear atomically all soft
37.40 + * references to that object and all soft references to any other
37.41 + * softly-reachable objects from which that object is reachable through a chain
37.42 + * of strong references. At the same time or at some later time it will
37.43 + * enqueue those newly-cleared soft references that are registered with
37.44 + * reference queues.
37.45 + *
37.46 + * <p> All soft references to softly-reachable objects are guaranteed to have
37.47 + * been cleared before the virtual machine throws an
37.48 + * <code>OutOfMemoryError</code>. Otherwise no constraints are placed upon the
37.49 + * time at which a soft reference will be cleared or the order in which a set
37.50 + * of such references to different objects will be cleared. Virtual machine
37.51 + * implementations are, however, encouraged to bias against clearing
37.52 + * recently-created or recently-used soft references.
37.53 + *
37.54 + * <p> Direct instances of this class may be used to implement simple caches;
37.55 + * this class or derived subclasses may also be used in larger data structures
37.56 + * to implement more sophisticated caches. As long as the referent of a soft
37.57 + * reference is strongly reachable, that is, is actually in use, the soft
37.58 + * reference will not be cleared. Thus a sophisticated cache can, for example,
37.59 + * prevent its most recently used entries from being discarded by keeping
37.60 + * strong referents to those entries, leaving the remaining entries to be
37.61 + * discarded at the discretion of the garbage collector.
37.62 + *
37.63 + * @author Mark Reinhold
37.64 + * @since 1.2
37.65 + */
37.66 +
37.67 +public class SoftReference<T> extends Reference<T> {
37.68 +
37.69 + /**
37.70 + * Timestamp clock, updated by the garbage collector
37.71 + */
37.72 + static private long clock;
37.73 +
37.74 + /**
37.75 + * Timestamp updated by each invocation of the get method. The VM may use
37.76 + * this field when selecting soft references to be cleared, but it is not
37.77 + * required to do so.
37.78 + */
37.79 + private long timestamp;
37.80 +
37.81 + /**
37.82 + * Creates a new soft reference that refers to the given object. The new
37.83 + * reference is not registered with any queue.
37.84 + *
37.85 + * @param referent object the new soft reference will refer to
37.86 + */
37.87 + public SoftReference(T referent) {
37.88 + super(referent);
37.89 + this.timestamp = clock;
37.90 + }
37.91 +
37.92 + /**
37.93 + * Creates a new soft reference that refers to the given object and is
37.94 + * registered with the given queue.
37.95 + *
37.96 + * @param referent object the new soft reference will refer to
37.97 + * @param q the queue with which the reference is to be registered,
37.98 + * or <tt>null</tt> if registration is not required
37.99 + *
37.100 + */
37.101 + public SoftReference(T referent, ReferenceQueue<? super T> q) {
37.102 + super(referent, q);
37.103 + this.timestamp = clock;
37.104 + }
37.105 +
37.106 + /**
37.107 + * Returns this reference object's referent. If this reference object has
37.108 + * been cleared, either by the program or by the garbage collector, then
37.109 + * this method returns <code>null</code>.
37.110 + *
37.111 + * @return The object to which this reference refers, or
37.112 + * <code>null</code> if this reference object has been cleared
37.113 + */
37.114 + public T get() {
37.115 + T o = super.get();
37.116 + if (o != null && this.timestamp != clock)
37.117 + this.timestamp = clock;
37.118 + return o;
37.119 + }
37.120 +
37.121 +}
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
38.2 +++ b/emul/compact/src/main/java/java/lang/ref/WeakReference.java Fri Feb 01 16:35:42 2013 +0100
38.3 @@ -0,0 +1,72 @@
38.4 +/*
38.5 + * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
38.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
38.7 + *
38.8 + * This code is free software; you can redistribute it and/or modify it
38.9 + * under the terms of the GNU General Public License version 2 only, as
38.10 + * published by the Free Software Foundation. Oracle designates this
38.11 + * particular file as subject to the "Classpath" exception as provided
38.12 + * by Oracle in the LICENSE file that accompanied this code.
38.13 + *
38.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
38.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
38.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
38.17 + * version 2 for more details (a copy is included in the LICENSE file that
38.18 + * accompanied this code).
38.19 + *
38.20 + * You should have received a copy of the GNU General Public License version
38.21 + * 2 along with this work; if not, write to the Free Software Foundation,
38.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
38.23 + *
38.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
38.25 + * or visit www.oracle.com if you need additional information or have any
38.26 + * questions.
38.27 + */
38.28 +
38.29 +package java.lang.ref;
38.30 +
38.31 +
38.32 +/**
38.33 + * Weak reference objects, which do not prevent their referents from being
38.34 + * made finalizable, finalized, and then reclaimed. Weak references are most
38.35 + * often used to implement canonicalizing mappings.
38.36 + *
38.37 + * <p> Suppose that the garbage collector determines at a certain point in time
38.38 + * that an object is <a href="package-summary.html#reachability">weakly
38.39 + * reachable</a>. At that time it will atomically clear all weak references to
38.40 + * that object and all weak references to any other weakly-reachable objects
38.41 + * from which that object is reachable through a chain of strong and soft
38.42 + * references. At the same time it will declare all of the formerly
38.43 + * weakly-reachable objects to be finalizable. At the same time or at some
38.44 + * later time it will enqueue those newly-cleared weak references that are
38.45 + * registered with reference queues.
38.46 + *
38.47 + * @author Mark Reinhold
38.48 + * @since 1.2
38.49 + */
38.50 +
38.51 +public class WeakReference<T> extends Reference<T> {
38.52 +
38.53 + /**
38.54 + * Creates a new weak reference that refers to the given object. The new
38.55 + * reference is not registered with any queue.
38.56 + *
38.57 + * @param referent object the new weak reference will refer to
38.58 + */
38.59 + public WeakReference(T referent) {
38.60 + super(referent);
38.61 + }
38.62 +
38.63 + /**
38.64 + * Creates a new weak reference that refers to the given object and is
38.65 + * registered with the given queue.
38.66 + *
38.67 + * @param referent object the new weak reference will refer to
38.68 + * @param q the queue with which the reference is to be registered,
38.69 + * or <tt>null</tt> if registration is not required
38.70 + */
38.71 + public WeakReference(T referent, ReferenceQueue<? super T> q) {
38.72 + super(referent, q);
38.73 + }
38.74 +
38.75 +}
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
39.2 +++ b/emul/compact/src/main/java/java/lang/ref/package.html Fri Feb 01 16:35:42 2013 +0100
39.3 @@ -0,0 +1,147 @@
39.4 +<!--
39.5 + Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved.
39.6 + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
39.7 +
39.8 + This code is free software; you can redistribute it and/or modify it
39.9 + under the terms of the GNU General Public License version 2 only, as
39.10 + published by the Free Software Foundation. Oracle designates this
39.11 + particular file as subject to the "Classpath" exception as provided
39.12 + by Oracle in the LICENSE file that accompanied this code.
39.13 +
39.14 + This code is distributed in the hope that it will be useful, but WITHOUT
39.15 + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
39.16 + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
39.17 + version 2 for more details (a copy is included in the LICENSE file that
39.18 + accompanied this code).
39.19 +
39.20 + You should have received a copy of the GNU General Public License version
39.21 + 2 along with this work; if not, write to the Free Software Foundation,
39.22 + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
39.23 +
39.24 + Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
39.25 + or visit www.oracle.com if you need additional information or have any
39.26 + questions.
39.27 +-->
39.28 +
39.29 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
39.30 +<html>
39.31 +<body bgcolor="white">
39.32 +
39.33 +
39.34 +Provides reference-object classes, which support a limited degree of
39.35 +interaction with the garbage collector. A program may use a reference object
39.36 +to maintain a reference to some other object in such a way that the latter
39.37 +object may still be reclaimed by the collector. A program may also arrange to
39.38 +be notified some time after the collector has determined that the reachability
39.39 +of a given object has changed.
39.40 +
39.41 +
39.42 +<h2>Package Specification</h2>
39.43 +
39.44 +A <em>reference object</em> encapsulates a reference to some other object so
39.45 +that the reference itself may be examined and manipulated like any other
39.46 +object. Three types of reference objects are provided, each weaker than the
39.47 +last: <em>soft</em>, <em>weak</em>, and <em>phantom</em>. Each type
39.48 +corresponds to a different level of reachability, as defined below. Soft
39.49 +references are for implementing memory-sensitive caches, weak references are
39.50 +for implementing canonicalizing mappings that do not prevent their keys (or
39.51 +values) from being reclaimed, and phantom references are for scheduling
39.52 +pre-mortem cleanup actions in a more flexible way than is possible with the
39.53 +Java finalization mechanism.
39.54 +
39.55 +<p> Each reference-object type is implemented by a subclass of the abstract
39.56 +base <code>{@link java.lang.ref.Reference}</code> class. An instance of one of
39.57 +these subclasses encapsulates a single reference to a particular object, called
39.58 +the <em>referent</em>. Every reference object provides methods for getting and
39.59 +clearing the reference. Aside from the clearing operation reference objects
39.60 +are otherwise immutable, so no <code>set</code> operation is provided. A
39.61 +program may further subclass these subclasses, adding whatever fields and
39.62 +methods are required for its purposes, or it may use these subclasses without
39.63 +change.
39.64 +
39.65 +
39.66 +<h3>Notification</h3>
39.67 +
39.68 +A program may request to be notified of changes in an object's reachability by
39.69 +<em>registering</em> an appropriate reference object with a <em>reference
39.70 +queue</em> at the time the reference object is created. Some time after the
39.71 +garbage collector determines that the reachability of the referent has changed
39.72 +to the value corresponding to the type of the reference, it will add the
39.73 +reference to the associated queue. At this point, the reference is considered
39.74 +to be <em>enqueued</em>. The program may remove references from a queue either
39.75 +by polling or by blocking until a reference becomes available. Reference
39.76 +queues are implemented by the <code>{@link java.lang.ref.ReferenceQueue}</code>
39.77 +class.
39.78 +
39.79 +<p> The relationship between a registered reference object and its queue is
39.80 +one-sided. That is, a queue does not keep track of the references that are
39.81 +registered with it. If a registered reference becomes unreachable itself, then
39.82 +it will never be enqueued. It is the responsibility of the program using
39.83 +reference objects to ensure that the objects remain reachable for as long as
39.84 +the program is interested in their referents.
39.85 +
39.86 +<p> While some programs will choose to dedicate a thread to removing reference
39.87 +objects from one or more queues and processing them, this is by no means
39.88 +necessary. A tactic that often works well is to examine a reference queue in
39.89 +the course of performing some other fairly-frequent action. For example, a
39.90 +hashtable that uses weak references to implement weak keys could poll its
39.91 +reference queue each time the table is accessed. This is how the <code>{@link
39.92 +java.util.WeakHashMap}</code> class works. Because the <code>{@link
39.93 +java.lang.ref.ReferenceQueue#poll ReferenceQueue.poll}</code> method simply
39.94 +checks an internal data structure, this check will add little overhead to the
39.95 +hashtable access methods.
39.96 +
39.97 +
39.98 +<h3>Automatically-cleared references</h3>
39.99 +
39.100 +Soft and weak references are automatically cleared by the collector before
39.101 +being added to the queues with which they are registered, if any. Therefore
39.102 +soft and weak references need not be registered with a queue in order to be
39.103 +useful, while phantom references do. An object that is reachable via phantom
39.104 +references will remain so until all such references are cleared or themselves
39.105 +become unreachable.
39.106 +
39.107 +
39.108 +<a name="reachability"></a>
39.109 +<h3>Reachability</h3>
39.110 +
39.111 +Going from strongest to weakest, the different levels of reachability reflect
39.112 +the life cycle of an object. They are operationally defined as follows:
39.113 +
39.114 +<ul>
39.115 +
39.116 +<li> An object is <em>strongly reachable</em> if it can be reached by some
39.117 +thread without traversing any reference objects. A newly-created object is
39.118 +strongly reachable by the thread that created it.
39.119 +
39.120 +<li> An object is <em>softly reachable</em> if it is not strongly reachable but
39.121 +can be reached by traversing a soft reference.
39.122 +
39.123 +<li> An object is <em>weakly reachable</em> if it is neither strongly nor
39.124 +softly reachable but can be reached by traversing a weak reference. When the
39.125 +weak references to a weakly-reachable object are cleared, the object becomes
39.126 +eligible for finalization.
39.127 +
39.128 +<li> An object is <em>phantom reachable</em> if it is neither strongly, softly,
39.129 +nor weakly reachable, it has been finalized, and some phantom reference refers
39.130 +to it.
39.131 +
39.132 +<li> Finally, an object is <em>unreachable</em>, and therefore eligible for
39.133 +reclamation, when it is not reachable in any of the above ways.
39.134 +
39.135 +</ul>
39.136 +
39.137 +
39.138 +@author Mark Reinhold
39.139 +@since 1.2
39.140 +
39.141 +<!--
39.142 +<h2>Related Documentation</h2>
39.143 +
39.144 +For overviews, tutorials, examples, guides, and tool documentation, please see:
39.145 +<ul>
39.146 + <li><a href="">##### REFER TO NON-SPEC DOCUMENTATION HERE #####</a>
39.147 +</ul>
39.148 +-->
39.149 +</body>
39.150 +</html>
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
40.2 +++ b/emul/compact/src/main/java/java/util/EventListenerProxy.java Fri Feb 01 16:35:42 2013 +0100
40.3 @@ -0,0 +1,75 @@
40.4 +/*
40.5 + * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved.
40.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
40.7 + *
40.8 + * This code is free software; you can redistribute it and/or modify it
40.9 + * under the terms of the GNU General Public License version 2 only, as
40.10 + * published by the Free Software Foundation. Oracle designates this
40.11 + * particular file as subject to the "Classpath" exception as provided
40.12 + * by Oracle in the LICENSE file that accompanied this code.
40.13 + *
40.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
40.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
40.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
40.17 + * version 2 for more details (a copy is included in the LICENSE file that
40.18 + * accompanied this code).
40.19 + *
40.20 + * You should have received a copy of the GNU General Public License version
40.21 + * 2 along with this work; if not, write to the Free Software Foundation,
40.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
40.23 + *
40.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
40.25 + * or visit www.oracle.com if you need additional information or have any
40.26 + * questions.
40.27 + */
40.28 +
40.29 +package java.util;
40.30 +
40.31 +/**
40.32 + * An abstract wrapper class for an {@code EventListener} class
40.33 + * which associates a set of additional parameters with the listener.
40.34 + * Subclasses must provide the storage and accessor methods
40.35 + * for the additional arguments or parameters.
40.36 + * <p>
40.37 + * For example, a bean which supports named properties
40.38 + * would have a two argument method signature for adding
40.39 + * a {@code PropertyChangeListener} for a property:
40.40 + * <pre>
40.41 + * public void addPropertyChangeListener(String propertyName,
40.42 + * PropertyChangeListener listener)
40.43 + * </pre>
40.44 + * If the bean also implemented the zero argument get listener method:
40.45 + * <pre>
40.46 + * public PropertyChangeListener[] getPropertyChangeListeners()
40.47 + * </pre>
40.48 + * then the array may contain inner {@code PropertyChangeListeners}
40.49 + * which are also {@code PropertyChangeListenerProxy} objects.
40.50 + * <p>
40.51 + * If the calling method is interested in retrieving the named property
40.52 + * then it would have to test the element to see if it is a proxy class.
40.53 + *
40.54 + * @since 1.4
40.55 + */
40.56 +public abstract class EventListenerProxy<T extends EventListener>
40.57 + implements EventListener {
40.58 +
40.59 + private final T listener;
40.60 +
40.61 + /**
40.62 + * Creates a proxy for the specified listener.
40.63 + *
40.64 + * @param listener the listener object
40.65 + */
40.66 + public EventListenerProxy(T listener) {
40.67 + this.listener = listener;
40.68 + }
40.69 +
40.70 + /**
40.71 + * Returns the listener associated with the proxy.
40.72 + *
40.73 + * @return the listener associated with the proxy
40.74 + */
40.75 + public T getListener() {
40.76 + return this.listener;
40.77 + }
40.78 +}
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
41.2 +++ b/emul/compact/src/main/java/java/util/concurrent/Callable.java Fri Feb 01 16:35:42 2013 +0100
41.3 @@ -0,0 +1,65 @@
41.4 +/*
41.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
41.6 + *
41.7 + * This code is free software; you can redistribute it and/or modify it
41.8 + * under the terms of the GNU General Public License version 2 only, as
41.9 + * published by the Free Software Foundation. Oracle designates this
41.10 + * particular file as subject to the "Classpath" exception as provided
41.11 + * by Oracle in the LICENSE file that accompanied this code.
41.12 + *
41.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
41.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
41.15 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
41.16 + * version 2 for more details (a copy is included in the LICENSE file that
41.17 + * accompanied this code).
41.18 + *
41.19 + * You should have received a copy of the GNU General Public License version
41.20 + * 2 along with this work; if not, write to the Free Software Foundation,
41.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
41.22 + *
41.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
41.24 + * or visit www.oracle.com if you need additional information or have any
41.25 + * questions.
41.26 + */
41.27 +
41.28 +/*
41.29 + * This file is available under and governed by the GNU General Public
41.30 + * License version 2 only, as published by the Free Software Foundation.
41.31 + * However, the following notice accompanied the original version of this
41.32 + * file:
41.33 + *
41.34 + * Written by Doug Lea with assistance from members of JCP JSR-166
41.35 + * Expert Group and released to the public domain, as explained at
41.36 + * http://creativecommons.org/publicdomain/zero/1.0/
41.37 + */
41.38 +
41.39 +package java.util.concurrent;
41.40 +
41.41 +/**
41.42 + * A task that returns a result and may throw an exception.
41.43 + * Implementors define a single method with no arguments called
41.44 + * <tt>call</tt>.
41.45 + *
41.46 + * <p>The <tt>Callable</tt> interface is similar to {@link
41.47 + * java.lang.Runnable}, in that both are designed for classes whose
41.48 + * instances are potentially executed by another thread. A
41.49 + * <tt>Runnable</tt>, however, does not return a result and cannot
41.50 + * throw a checked exception.
41.51 + *
41.52 + * <p> The {@link Executors} class contains utility methods to
41.53 + * convert from other common forms to <tt>Callable</tt> classes.
41.54 + *
41.55 + * @see Executor
41.56 + * @since 1.5
41.57 + * @author Doug Lea
41.58 + * @param <V> the result type of method <tt>call</tt>
41.59 + */
41.60 +public interface Callable<V> {
41.61 + /**
41.62 + * Computes a result, or throws an exception if unable to do so.
41.63 + *
41.64 + * @return computed result
41.65 + * @throws Exception if unable to compute a result
41.66 + */
41.67 + V call() throws Exception;
41.68 +}
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
42.2 +++ b/emul/mini/src/main/java/java/lang/IllegalAccessError.java Fri Feb 01 16:35:42 2013 +0100
42.3 @@ -0,0 +1,58 @@
42.4 +/*
42.5 + * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
42.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
42.7 + *
42.8 + * This code is free software; you can redistribute it and/or modify it
42.9 + * under the terms of the GNU General Public License version 2 only, as
42.10 + * published by the Free Software Foundation. Oracle designates this
42.11 + * particular file as subject to the "Classpath" exception as provided
42.12 + * by Oracle in the LICENSE file that accompanied this code.
42.13 + *
42.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
42.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
42.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
42.17 + * version 2 for more details (a copy is included in the LICENSE file that
42.18 + * accompanied this code).
42.19 + *
42.20 + * You should have received a copy of the GNU General Public License version
42.21 + * 2 along with this work; if not, write to the Free Software Foundation,
42.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
42.23 + *
42.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
42.25 + * or visit www.oracle.com if you need additional information or have any
42.26 + * questions.
42.27 + */
42.28 +
42.29 +package java.lang;
42.30 +
42.31 +/**
42.32 + * Thrown if an application attempts to access or modify a field, or
42.33 + * to call a method that it does not have access to.
42.34 + * <p>
42.35 + * Normally, this error is caught by the compiler; this error can
42.36 + * only occur at run time if the definition of a class has
42.37 + * incompatibly changed.
42.38 + *
42.39 + * @author unascribed
42.40 + * @since JDK1.0
42.41 + */
42.42 +public class IllegalAccessError extends IncompatibleClassChangeError {
42.43 + private static final long serialVersionUID = -8988904074992417891L;
42.44 +
42.45 + /**
42.46 + * Constructs an <code>IllegalAccessError</code> with no detail message.
42.47 + */
42.48 + public IllegalAccessError() {
42.49 + super();
42.50 + }
42.51 +
42.52 + /**
42.53 + * Constructs an <code>IllegalAccessError</code> with the specified
42.54 + * detail message.
42.55 + *
42.56 + * @param s the detail message.
42.57 + */
42.58 + public IllegalAccessError(String s) {
42.59 + super(s);
42.60 + }
42.61 +}
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
43.2 +++ b/emul/mini/src/main/java/java/lang/IncompatibleClassChangeError.java Fri Feb 01 16:35:42 2013 +0100
43.3 @@ -0,0 +1,57 @@
43.4 +/*
43.5 + * Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved.
43.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
43.7 + *
43.8 + * This code is free software; you can redistribute it and/or modify it
43.9 + * under the terms of the GNU General Public License version 2 only, as
43.10 + * published by the Free Software Foundation. Oracle designates this
43.11 + * particular file as subject to the "Classpath" exception as provided
43.12 + * by Oracle in the LICENSE file that accompanied this code.
43.13 + *
43.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
43.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
43.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
43.17 + * version 2 for more details (a copy is included in the LICENSE file that
43.18 + * accompanied this code).
43.19 + *
43.20 + * You should have received a copy of the GNU General Public License version
43.21 + * 2 along with this work; if not, write to the Free Software Foundation,
43.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
43.23 + *
43.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
43.25 + * or visit www.oracle.com if you need additional information or have any
43.26 + * questions.
43.27 + */
43.28 +
43.29 +package java.lang;
43.30 +
43.31 +/**
43.32 + * Thrown when an incompatible class change has occurred to some class
43.33 + * definition. The definition of some class, on which the currently
43.34 + * executing method depends, has since changed.
43.35 + *
43.36 + * @author unascribed
43.37 + * @since JDK1.0
43.38 + */
43.39 +public
43.40 +class IncompatibleClassChangeError extends LinkageError {
43.41 + private static final long serialVersionUID = -4914975503642802119L;
43.42 +
43.43 + /**
43.44 + * Constructs an <code>IncompatibleClassChangeError</code> with no
43.45 + * detail message.
43.46 + */
43.47 + public IncompatibleClassChangeError () {
43.48 + super();
43.49 + }
43.50 +
43.51 + /**
43.52 + * Constructs an <code>IncompatibleClassChangeError</code> with the
43.53 + * specified detail message.
43.54 + *
43.55 + * @param s the detail message.
43.56 + */
43.57 + public IncompatibleClassChangeError(String s) {
43.58 + super(s);
43.59 + }
43.60 +}
44.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
44.2 +++ b/emul/mini/src/main/java/java/lang/reflect/Constructor.java Fri Feb 01 16:35:42 2013 +0100
44.3 @@ -0,0 +1,683 @@
44.4 +/*
44.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
44.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44.7 + *
44.8 + * This code is free software; you can redistribute it and/or modify it
44.9 + * under the terms of the GNU General Public License version 2 only, as
44.10 + * published by the Free Software Foundation. Oracle designates this
44.11 + * particular file as subject to the "Classpath" exception as provided
44.12 + * by Oracle in the LICENSE file that accompanied this code.
44.13 + *
44.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
44.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
44.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
44.17 + * version 2 for more details (a copy is included in the LICENSE file that
44.18 + * accompanied this code).
44.19 + *
44.20 + * You should have received a copy of the GNU General Public License version
44.21 + * 2 along with this work; if not, write to the Free Software Foundation,
44.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
44.23 + *
44.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
44.25 + * or visit www.oracle.com if you need additional information or have any
44.26 + * questions.
44.27 + */
44.28 +
44.29 +package java.lang.reflect;
44.30 +
44.31 +import sun.reflect.ConstructorAccessor;
44.32 +import sun.reflect.Reflection;
44.33 +import sun.reflect.generics.repository.ConstructorRepository;
44.34 +import sun.reflect.generics.factory.CoreReflectionFactory;
44.35 +import sun.reflect.generics.factory.GenericsFactory;
44.36 +import sun.reflect.generics.scope.ConstructorScope;
44.37 +import java.lang.annotation.Annotation;
44.38 +import java.util.Map;
44.39 +import sun.reflect.annotation.AnnotationParser;
44.40 +import java.lang.annotation.AnnotationFormatError;
44.41 +import java.lang.reflect.Modifier;
44.42 +
44.43 +/**
44.44 + * {@code Constructor} provides information about, and access to, a single
44.45 + * constructor for a class.
44.46 + *
44.47 + * <p>{@code Constructor} permits widening conversions to occur when matching the
44.48 + * actual parameters to newInstance() with the underlying
44.49 + * constructor's formal parameters, but throws an
44.50 + * {@code IllegalArgumentException} if a narrowing conversion would occur.
44.51 + *
44.52 + * @param <T> the class in which the constructor is declared
44.53 + *
44.54 + * @see Member
44.55 + * @see java.lang.Class
44.56 + * @see java.lang.Class#getConstructors()
44.57 + * @see java.lang.Class#getConstructor(Class[])
44.58 + * @see java.lang.Class#getDeclaredConstructors()
44.59 + *
44.60 + * @author Kenneth Russell
44.61 + * @author Nakul Saraiya
44.62 + */
44.63 +public final
44.64 + class Constructor<T> extends AccessibleObject implements
44.65 + GenericDeclaration,
44.66 + Member {
44.67 +
44.68 + private Class<T> clazz;
44.69 + private int slot;
44.70 + private Class<?>[] parameterTypes;
44.71 + private Class<?>[] exceptionTypes;
44.72 + private int modifiers;
44.73 + // Generics and annotations support
44.74 + private transient String signature;
44.75 + // generic info repository; lazily initialized
44.76 + private transient ConstructorRepository genericInfo;
44.77 + private byte[] annotations;
44.78 + private byte[] parameterAnnotations;
44.79 +
44.80 + // Generics infrastructure
44.81 + // Accessor for factory
44.82 + private GenericsFactory getFactory() {
44.83 + // create scope and factory
44.84 + return CoreReflectionFactory.make(this, ConstructorScope.make(this));
44.85 + }
44.86 +
44.87 + // Accessor for generic info repository
44.88 + private ConstructorRepository getGenericInfo() {
44.89 + // lazily initialize repository if necessary
44.90 + if (genericInfo == null) {
44.91 + // create and cache generic info repository
44.92 + genericInfo =
44.93 + ConstructorRepository.make(getSignature(),
44.94 + getFactory());
44.95 + }
44.96 + return genericInfo; //return cached repository
44.97 + }
44.98 +
44.99 + private volatile ConstructorAccessor constructorAccessor;
44.100 + // For sharing of ConstructorAccessors. This branching structure
44.101 + // is currently only two levels deep (i.e., one root Constructor
44.102 + // and potentially many Constructor objects pointing to it.)
44.103 + private Constructor<T> root;
44.104 +
44.105 + /**
44.106 + * Package-private constructor used by ReflectAccess to enable
44.107 + * instantiation of these objects in Java code from the java.lang
44.108 + * package via sun.reflect.LangReflectAccess.
44.109 + */
44.110 + Constructor(Class<T> declaringClass,
44.111 + Class<?>[] parameterTypes,
44.112 + Class<?>[] checkedExceptions,
44.113 + int modifiers,
44.114 + int slot,
44.115 + String signature,
44.116 + byte[] annotations,
44.117 + byte[] parameterAnnotations)
44.118 + {
44.119 + this.clazz = declaringClass;
44.120 + this.parameterTypes = parameterTypes;
44.121 + this.exceptionTypes = checkedExceptions;
44.122 + this.modifiers = modifiers;
44.123 + this.slot = slot;
44.124 + this.signature = signature;
44.125 + this.annotations = annotations;
44.126 + this.parameterAnnotations = parameterAnnotations;
44.127 + }
44.128 +
44.129 + /**
44.130 + * Package-private routine (exposed to java.lang.Class via
44.131 + * ReflectAccess) which returns a copy of this Constructor. The copy's
44.132 + * "root" field points to this Constructor.
44.133 + */
44.134 + Constructor<T> copy() {
44.135 + // This routine enables sharing of ConstructorAccessor objects
44.136 + // among Constructor objects which refer to the same underlying
44.137 + // method in the VM. (All of this contortion is only necessary
44.138 + // because of the "accessibility" bit in AccessibleObject,
44.139 + // which implicitly requires that new java.lang.reflect
44.140 + // objects be fabricated for each reflective call on Class
44.141 + // objects.)
44.142 + Constructor<T> res = new Constructor<>(clazz,
44.143 + parameterTypes,
44.144 + exceptionTypes, modifiers, slot,
44.145 + signature,
44.146 + annotations,
44.147 + parameterAnnotations);
44.148 + res.root = this;
44.149 + // Might as well eagerly propagate this if already present
44.150 + res.constructorAccessor = constructorAccessor;
44.151 + return res;
44.152 + }
44.153 +
44.154 + /**
44.155 + * Returns the {@code Class} object representing the class that declares
44.156 + * the constructor represented by this {@code Constructor} object.
44.157 + */
44.158 + public Class<T> getDeclaringClass() {
44.159 + return clazz;
44.160 + }
44.161 +
44.162 + /**
44.163 + * Returns the name of this constructor, as a string. This is
44.164 + * the binary name of the constructor's declaring class.
44.165 + */
44.166 + public String getName() {
44.167 + return getDeclaringClass().getName();
44.168 + }
44.169 +
44.170 + /**
44.171 + * Returns the Java language modifiers for the constructor
44.172 + * represented by this {@code Constructor} object, as an integer. The
44.173 + * {@code Modifier} class should be used to decode the modifiers.
44.174 + *
44.175 + * @see Modifier
44.176 + */
44.177 + public int getModifiers() {
44.178 + return modifiers;
44.179 + }
44.180 +
44.181 + /**
44.182 + * Returns an array of {@code TypeVariable} objects that represent the
44.183 + * type variables declared by the generic declaration represented by this
44.184 + * {@code GenericDeclaration} object, in declaration order. Returns an
44.185 + * array of length 0 if the underlying generic declaration declares no type
44.186 + * variables.
44.187 + *
44.188 + * @return an array of {@code TypeVariable} objects that represent
44.189 + * the type variables declared by this generic declaration
44.190 + * @throws GenericSignatureFormatError if the generic
44.191 + * signature of this generic declaration does not conform to
44.192 + * the format specified in
44.193 + * <cite>The Java™ Virtual Machine Specification</cite>
44.194 + * @since 1.5
44.195 + */
44.196 + public TypeVariable<Constructor<T>>[] getTypeParameters() {
44.197 + if (getSignature() != null) {
44.198 + return (TypeVariable<Constructor<T>>[])getGenericInfo().getTypeParameters();
44.199 + } else
44.200 + return (TypeVariable<Constructor<T>>[])new TypeVariable[0];
44.201 + }
44.202 +
44.203 +
44.204 + /**
44.205 + * Returns an array of {@code Class} objects that represent the formal
44.206 + * parameter types, in declaration order, of the constructor
44.207 + * represented by this {@code Constructor} object. Returns an array of
44.208 + * length 0 if the underlying constructor takes no parameters.
44.209 + *
44.210 + * @return the parameter types for the constructor this object
44.211 + * represents
44.212 + */
44.213 + public Class<?>[] getParameterTypes() {
44.214 + return (Class<?>[]) parameterTypes.clone();
44.215 + }
44.216 +
44.217 +
44.218 + /**
44.219 + * Returns an array of {@code Type} objects that represent the formal
44.220 + * parameter types, in declaration order, of the method represented by
44.221 + * this {@code Constructor} object. Returns an array of length 0 if the
44.222 + * underlying method takes no parameters.
44.223 + *
44.224 + * <p>If a formal parameter type is a parameterized type,
44.225 + * the {@code Type} object returned for it must accurately reflect
44.226 + * the actual type parameters used in the source code.
44.227 + *
44.228 + * <p>If a formal parameter type is a type variable or a parameterized
44.229 + * type, it is created. Otherwise, it is resolved.
44.230 + *
44.231 + * @return an array of {@code Type}s that represent the formal
44.232 + * parameter types of the underlying method, in declaration order
44.233 + * @throws GenericSignatureFormatError
44.234 + * if the generic method signature does not conform to the format
44.235 + * specified in
44.236 + * <cite>The Java™ Virtual Machine Specification</cite>
44.237 + * @throws TypeNotPresentException if any of the parameter
44.238 + * types of the underlying method refers to a non-existent type
44.239 + * declaration
44.240 + * @throws MalformedParameterizedTypeException if any of
44.241 + * the underlying method's parameter types refer to a parameterized
44.242 + * type that cannot be instantiated for any reason
44.243 + * @since 1.5
44.244 + */
44.245 + public Type[] getGenericParameterTypes() {
44.246 + if (getSignature() != null)
44.247 + return getGenericInfo().getParameterTypes();
44.248 + else
44.249 + return getParameterTypes();
44.250 + }
44.251 +
44.252 +
44.253 + /**
44.254 + * Returns an array of {@code Class} objects that represent the types
44.255 + * of exceptions declared to be thrown by the underlying constructor
44.256 + * represented by this {@code Constructor} object. Returns an array of
44.257 + * length 0 if the constructor declares no exceptions in its {@code throws} clause.
44.258 + *
44.259 + * @return the exception types declared as being thrown by the
44.260 + * constructor this object represents
44.261 + */
44.262 + public Class<?>[] getExceptionTypes() {
44.263 + return (Class<?>[])exceptionTypes.clone();
44.264 + }
44.265 +
44.266 +
44.267 + /**
44.268 + * Returns an array of {@code Type} objects that represent the
44.269 + * exceptions declared to be thrown by this {@code Constructor} object.
44.270 + * Returns an array of length 0 if the underlying method declares
44.271 + * no exceptions in its {@code throws} clause.
44.272 + *
44.273 + * <p>If an exception type is a type variable or a parameterized
44.274 + * type, it is created. Otherwise, it is resolved.
44.275 + *
44.276 + * @return an array of Types that represent the exception types
44.277 + * thrown by the underlying method
44.278 + * @throws GenericSignatureFormatError
44.279 + * if the generic method signature does not conform to the format
44.280 + * specified in
44.281 + * <cite>The Java™ Virtual Machine Specification</cite>
44.282 + * @throws TypeNotPresentException if the underlying method's
44.283 + * {@code throws} clause refers to a non-existent type declaration
44.284 + * @throws MalformedParameterizedTypeException if
44.285 + * the underlying method's {@code throws} clause refers to a
44.286 + * parameterized type that cannot be instantiated for any reason
44.287 + * @since 1.5
44.288 + */
44.289 + public Type[] getGenericExceptionTypes() {
44.290 + Type[] result;
44.291 + if (getSignature() != null &&
44.292 + ( (result = getGenericInfo().getExceptionTypes()).length > 0 ))
44.293 + return result;
44.294 + else
44.295 + return getExceptionTypes();
44.296 + }
44.297 +
44.298 + /**
44.299 + * Compares this {@code Constructor} against the specified object.
44.300 + * Returns true if the objects are the same. Two {@code Constructor} objects are
44.301 + * the same if they were declared by the same class and have the
44.302 + * same formal parameter types.
44.303 + */
44.304 + public boolean equals(Object obj) {
44.305 + if (obj != null && obj instanceof Constructor) {
44.306 + Constructor<?> other = (Constructor<?>)obj;
44.307 + if (getDeclaringClass() == other.getDeclaringClass()) {
44.308 + /* Avoid unnecessary cloning */
44.309 + Class<?>[] params1 = parameterTypes;
44.310 + Class<?>[] params2 = other.parameterTypes;
44.311 + if (params1.length == params2.length) {
44.312 + for (int i = 0; i < params1.length; i++) {
44.313 + if (params1[i] != params2[i])
44.314 + return false;
44.315 + }
44.316 + return true;
44.317 + }
44.318 + }
44.319 + }
44.320 + return false;
44.321 + }
44.322 +
44.323 + /**
44.324 + * Returns a hashcode for this {@code Constructor}. The hashcode is
44.325 + * the same as the hashcode for the underlying constructor's
44.326 + * declaring class name.
44.327 + */
44.328 + public int hashCode() {
44.329 + return getDeclaringClass().getName().hashCode();
44.330 + }
44.331 +
44.332 + /**
44.333 + * Returns a string describing this {@code Constructor}. The string is
44.334 + * formatted as the constructor access modifiers, if any,
44.335 + * followed by the fully-qualified name of the declaring class,
44.336 + * followed by a parenthesized, comma-separated list of the
44.337 + * constructor's formal parameter types. For example:
44.338 + * <pre>
44.339 + * public java.util.Hashtable(int,float)
44.340 + * </pre>
44.341 + *
44.342 + * <p>The only possible modifiers for constructors are the access
44.343 + * modifiers {@code public}, {@code protected} or
44.344 + * {@code private}. Only one of these may appear, or none if the
44.345 + * constructor has default (package) access.
44.346 + */
44.347 + public String toString() {
44.348 + try {
44.349 + StringBuffer sb = new StringBuffer();
44.350 + int mod = getModifiers() & Modifier.constructorModifiers();
44.351 + if (mod != 0) {
44.352 + sb.append(Modifier.toString(mod) + " ");
44.353 + }
44.354 + sb.append(Field.getTypeName(getDeclaringClass()));
44.355 + sb.append("(");
44.356 + Class<?>[] params = parameterTypes; // avoid clone
44.357 + for (int j = 0; j < params.length; j++) {
44.358 + sb.append(Field.getTypeName(params[j]));
44.359 + if (j < (params.length - 1))
44.360 + sb.append(",");
44.361 + }
44.362 + sb.append(")");
44.363 + Class<?>[] exceptions = exceptionTypes; // avoid clone
44.364 + if (exceptions.length > 0) {
44.365 + sb.append(" throws ");
44.366 + for (int k = 0; k < exceptions.length; k++) {
44.367 + sb.append(exceptions[k].getName());
44.368 + if (k < (exceptions.length - 1))
44.369 + sb.append(",");
44.370 + }
44.371 + }
44.372 + return sb.toString();
44.373 + } catch (Exception e) {
44.374 + return "<" + e + ">";
44.375 + }
44.376 + }
44.377 +
44.378 + /**
44.379 + * Returns a string describing this {@code Constructor},
44.380 + * including type parameters. The string is formatted as the
44.381 + * constructor access modifiers, if any, followed by an
44.382 + * angle-bracketed comma separated list of the constructor's type
44.383 + * parameters, if any, followed by the fully-qualified name of the
44.384 + * declaring class, followed by a parenthesized, comma-separated
44.385 + * list of the constructor's generic formal parameter types.
44.386 + *
44.387 + * If this constructor was declared to take a variable number of
44.388 + * arguments, instead of denoting the last parameter as
44.389 + * "<tt><i>Type</i>[]</tt>", it is denoted as
44.390 + * "<tt><i>Type</i>...</tt>".
44.391 + *
44.392 + * A space is used to separate access modifiers from one another
44.393 + * and from the type parameters or return type. If there are no
44.394 + * type parameters, the type parameter list is elided; if the type
44.395 + * parameter list is present, a space separates the list from the
44.396 + * class name. If the constructor is declared to throw
44.397 + * exceptions, the parameter list is followed by a space, followed
44.398 + * by the word "{@code throws}" followed by a
44.399 + * comma-separated list of the thrown exception types.
44.400 + *
44.401 + * <p>The only possible modifiers for constructors are the access
44.402 + * modifiers {@code public}, {@code protected} or
44.403 + * {@code private}. Only one of these may appear, or none if the
44.404 + * constructor has default (package) access.
44.405 + *
44.406 + * @return a string describing this {@code Constructor},
44.407 + * include type parameters
44.408 + *
44.409 + * @since 1.5
44.410 + */
44.411 + public String toGenericString() {
44.412 + try {
44.413 + StringBuilder sb = new StringBuilder();
44.414 + int mod = getModifiers() & Modifier.constructorModifiers();
44.415 + if (mod != 0) {
44.416 + sb.append(Modifier.toString(mod) + " ");
44.417 + }
44.418 + TypeVariable<?>[] typeparms = getTypeParameters();
44.419 + if (typeparms.length > 0) {
44.420 + boolean first = true;
44.421 + sb.append("<");
44.422 + for(TypeVariable<?> typeparm: typeparms) {
44.423 + if (!first)
44.424 + sb.append(",");
44.425 + // Class objects can't occur here; no need to test
44.426 + // and call Class.getName().
44.427 + sb.append(typeparm.toString());
44.428 + first = false;
44.429 + }
44.430 + sb.append("> ");
44.431 + }
44.432 + sb.append(Field.getTypeName(getDeclaringClass()));
44.433 + sb.append("(");
44.434 + Type[] params = getGenericParameterTypes();
44.435 + for (int j = 0; j < params.length; j++) {
44.436 + String param = (params[j] instanceof Class<?>)?
44.437 + Field.getTypeName((Class<?>)params[j]):
44.438 + (params[j].toString());
44.439 + if (isVarArgs() && (j == params.length - 1)) // replace T[] with T...
44.440 + param = param.replaceFirst("\\[\\]$", "...");
44.441 + sb.append(param);
44.442 + if (j < (params.length - 1))
44.443 + sb.append(",");
44.444 + }
44.445 + sb.append(")");
44.446 + Type[] exceptions = getGenericExceptionTypes();
44.447 + if (exceptions.length > 0) {
44.448 + sb.append(" throws ");
44.449 + for (int k = 0; k < exceptions.length; k++) {
44.450 + sb.append((exceptions[k] instanceof Class)?
44.451 + ((Class<?>)exceptions[k]).getName():
44.452 + exceptions[k].toString());
44.453 + if (k < (exceptions.length - 1))
44.454 + sb.append(",");
44.455 + }
44.456 + }
44.457 + return sb.toString();
44.458 + } catch (Exception e) {
44.459 + return "<" + e + ">";
44.460 + }
44.461 + }
44.462 +
44.463 + /**
44.464 + * Uses the constructor represented by this {@code Constructor} object to
44.465 + * create and initialize a new instance of the constructor's
44.466 + * declaring class, with the specified initialization parameters.
44.467 + * Individual parameters are automatically unwrapped to match
44.468 + * primitive formal parameters, and both primitive and reference
44.469 + * parameters are subject to method invocation conversions as necessary.
44.470 + *
44.471 + * <p>If the number of formal parameters required by the underlying constructor
44.472 + * is 0, the supplied {@code initargs} array may be of length 0 or null.
44.473 + *
44.474 + * <p>If the constructor's declaring class is an inner class in a
44.475 + * non-static context, the first argument to the constructor needs
44.476 + * to be the enclosing instance; see section 15.9.3 of
44.477 + * <cite>The Java™ Language Specification</cite>.
44.478 + *
44.479 + * <p>If the required access and argument checks succeed and the
44.480 + * instantiation will proceed, the constructor's declaring class
44.481 + * is initialized if it has not already been initialized.
44.482 + *
44.483 + * <p>If the constructor completes normally, returns the newly
44.484 + * created and initialized instance.
44.485 + *
44.486 + * @param initargs array of objects to be passed as arguments to
44.487 + * the constructor call; values of primitive types are wrapped in
44.488 + * a wrapper object of the appropriate type (e.g. a {@code float}
44.489 + * in a {@link java.lang.Float Float})
44.490 + *
44.491 + * @return a new object created by calling the constructor
44.492 + * this object represents
44.493 + *
44.494 + * @exception IllegalAccessException if this {@code Constructor} object
44.495 + * is enforcing Java language access control and the underlying
44.496 + * constructor is inaccessible.
44.497 + * @exception IllegalArgumentException if the number of actual
44.498 + * and formal parameters differ; if an unwrapping
44.499 + * conversion for primitive arguments fails; or if,
44.500 + * after possible unwrapping, a parameter value
44.501 + * cannot be converted to the corresponding formal
44.502 + * parameter type by a method invocation conversion; if
44.503 + * this constructor pertains to an enum type.
44.504 + * @exception InstantiationException if the class that declares the
44.505 + * underlying constructor represents an abstract class.
44.506 + * @exception InvocationTargetException if the underlying constructor
44.507 + * throws an exception.
44.508 + * @exception ExceptionInInitializerError if the initialization provoked
44.509 + * by this method fails.
44.510 + */
44.511 + public T newInstance(Object ... initargs)
44.512 + throws InstantiationException, IllegalAccessException,
44.513 + IllegalArgumentException, InvocationTargetException
44.514 + {
44.515 + if (!override) {
44.516 + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
44.517 + Class<?> caller = Reflection.getCallerClass(2);
44.518 +
44.519 + checkAccess(caller, clazz, null, modifiers);
44.520 + }
44.521 + }
44.522 + if ((clazz.getModifiers() & Modifier.ENUM) != 0)
44.523 + throw new IllegalArgumentException("Cannot reflectively create enum objects");
44.524 + ConstructorAccessor ca = constructorAccessor; // read volatile
44.525 + if (ca == null) {
44.526 + ca = acquireConstructorAccessor();
44.527 + }
44.528 + return (T) ca.newInstance(initargs);
44.529 + }
44.530 +
44.531 + /**
44.532 + * Returns {@code true} if this constructor was declared to take
44.533 + * a variable number of arguments; returns {@code false}
44.534 + * otherwise.
44.535 + *
44.536 + * @return {@code true} if an only if this constructor was declared to
44.537 + * take a variable number of arguments.
44.538 + * @since 1.5
44.539 + */
44.540 + public boolean isVarArgs() {
44.541 + return (getModifiers() & Modifier.VARARGS) != 0;
44.542 + }
44.543 +
44.544 + /**
44.545 + * Returns {@code true} if this constructor is a synthetic
44.546 + * constructor; returns {@code false} otherwise.
44.547 + *
44.548 + * @return true if and only if this constructor is a synthetic
44.549 + * constructor as defined by
44.550 + * <cite>The Java™ Language Specification</cite>.
44.551 + * @since 1.5
44.552 + */
44.553 + public boolean isSynthetic() {
44.554 + return Modifier.isSynthetic(getModifiers());
44.555 + }
44.556 +
44.557 + // NOTE that there is no synchronization used here. It is correct
44.558 + // (though not efficient) to generate more than one
44.559 + // ConstructorAccessor for a given Constructor. However, avoiding
44.560 + // synchronization will probably make the implementation more
44.561 + // scalable.
44.562 + private ConstructorAccessor acquireConstructorAccessor() {
44.563 + // First check to see if one has been created yet, and take it
44.564 + // if so.
44.565 + ConstructorAccessor tmp = null;
44.566 + if (root != null) tmp = root.getConstructorAccessor();
44.567 + if (tmp != null) {
44.568 + constructorAccessor = tmp;
44.569 + } else {
44.570 + // Otherwise fabricate one and propagate it up to the root
44.571 + tmp = reflectionFactory.newConstructorAccessor(this);
44.572 + setConstructorAccessor(tmp);
44.573 + }
44.574 +
44.575 + return tmp;
44.576 + }
44.577 +
44.578 + // Returns ConstructorAccessor for this Constructor object, not
44.579 + // looking up the chain to the root
44.580 + ConstructorAccessor getConstructorAccessor() {
44.581 + return constructorAccessor;
44.582 + }
44.583 +
44.584 + // Sets the ConstructorAccessor for this Constructor object and
44.585 + // (recursively) its root
44.586 + void setConstructorAccessor(ConstructorAccessor accessor) {
44.587 + constructorAccessor = accessor;
44.588 + // Propagate up
44.589 + if (root != null) {
44.590 + root.setConstructorAccessor(accessor);
44.591 + }
44.592 + }
44.593 +
44.594 + int getSlot() {
44.595 + return slot;
44.596 + }
44.597 +
44.598 + String getSignature() {
44.599 + return signature;
44.600 + }
44.601 +
44.602 + byte[] getRawAnnotations() {
44.603 + return annotations;
44.604 + }
44.605 +
44.606 + byte[] getRawParameterAnnotations() {
44.607 + return parameterAnnotations;
44.608 + }
44.609 +
44.610 + /**
44.611 + * @throws NullPointerException {@inheritDoc}
44.612 + * @since 1.5
44.613 + */
44.614 + public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
44.615 + if (annotationClass == null)
44.616 + throw new NullPointerException();
44.617 +
44.618 + return (T) declaredAnnotations().get(annotationClass);
44.619 + }
44.620 +
44.621 + /**
44.622 + * @since 1.5
44.623 + */
44.624 + public Annotation[] getDeclaredAnnotations() {
44.625 + return AnnotationParser.toArray(declaredAnnotations());
44.626 + }
44.627 +
44.628 + private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
44.629 +
44.630 + private synchronized Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
44.631 + if (declaredAnnotations == null) {
44.632 + declaredAnnotations = AnnotationParser.parseAnnotations(
44.633 + annotations, sun.misc.SharedSecrets.getJavaLangAccess().
44.634 + getConstantPool(getDeclaringClass()),
44.635 + getDeclaringClass());
44.636 + }
44.637 + return declaredAnnotations;
44.638 + }
44.639 +
44.640 + /**
44.641 + * Returns an array of arrays that represent the annotations on the formal
44.642 + * parameters, in declaration order, of the method represented by
44.643 + * this {@code Constructor} object. (Returns an array of length zero if the
44.644 + * underlying method is parameterless. If the method has one or more
44.645 + * parameters, a nested array of length zero is returned for each parameter
44.646 + * with no annotations.) The annotation objects contained in the returned
44.647 + * arrays are serializable. The caller of this method is free to modify
44.648 + * the returned arrays; it will have no effect on the arrays returned to
44.649 + * other callers.
44.650 + *
44.651 + * @return an array of arrays that represent the annotations on the formal
44.652 + * parameters, in declaration order, of the method represented by this
44.653 + * Constructor object
44.654 + * @since 1.5
44.655 + */
44.656 + public Annotation[][] getParameterAnnotations() {
44.657 + int numParameters = parameterTypes.length;
44.658 + if (parameterAnnotations == null)
44.659 + return new Annotation[numParameters][0];
44.660 +
44.661 + Annotation[][] result = AnnotationParser.parseParameterAnnotations(
44.662 + parameterAnnotations,
44.663 + sun.misc.SharedSecrets.getJavaLangAccess().
44.664 + getConstantPool(getDeclaringClass()),
44.665 + getDeclaringClass());
44.666 + if (result.length != numParameters) {
44.667 + Class<?> declaringClass = getDeclaringClass();
44.668 + if (declaringClass.isEnum() ||
44.669 + declaringClass.isAnonymousClass() ||
44.670 + declaringClass.isLocalClass() )
44.671 + ; // Can't do reliable parameter counting
44.672 + else {
44.673 + if (!declaringClass.isMemberClass() || // top-level
44.674 + // Check for the enclosing instance parameter for
44.675 + // non-static member classes
44.676 + (declaringClass.isMemberClass() &&
44.677 + ((declaringClass.getModifiers() & Modifier.STATIC) == 0) &&
44.678 + result.length + 1 != numParameters) ) {
44.679 + throw new AnnotationFormatError(
44.680 + "Parameter annotations don't match number of parameters");
44.681 + }
44.682 + }
44.683 + }
44.684 + return result;
44.685 + }
44.686 +}
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
45.2 +++ b/emul/mini/src/main/java/java/lang/reflect/InvocationHandler.java Fri Feb 01 16:35:42 2013 +0100
45.3 @@ -0,0 +1,95 @@
45.4 +/*
45.5 + * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved.
45.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
45.7 + *
45.8 + * This code is free software; you can redistribute it and/or modify it
45.9 + * under the terms of the GNU General Public License version 2 only, as
45.10 + * published by the Free Software Foundation. Oracle designates this
45.11 + * particular file as subject to the "Classpath" exception as provided
45.12 + * by Oracle in the LICENSE file that accompanied this code.
45.13 + *
45.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
45.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
45.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
45.17 + * version 2 for more details (a copy is included in the LICENSE file that
45.18 + * accompanied this code).
45.19 + *
45.20 + * You should have received a copy of the GNU General Public License version
45.21 + * 2 along with this work; if not, write to the Free Software Foundation,
45.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
45.23 + *
45.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
45.25 + * or visit www.oracle.com if you need additional information or have any
45.26 + * questions.
45.27 + */
45.28 +
45.29 +package java.lang.reflect;
45.30 +
45.31 +/**
45.32 + * {@code InvocationHandler} is the interface implemented by
45.33 + * the <i>invocation handler</i> of a proxy instance.
45.34 + *
45.35 + * <p>Each proxy instance has an associated invocation handler.
45.36 + * When a method is invoked on a proxy instance, the method
45.37 + * invocation is encoded and dispatched to the {@code invoke}
45.38 + * method of its invocation handler.
45.39 + *
45.40 + * @author Peter Jones
45.41 + * @see Proxy
45.42 + * @since 1.3
45.43 + */
45.44 +public interface InvocationHandler {
45.45 +
45.46 + /**
45.47 + * Processes a method invocation on a proxy instance and returns
45.48 + * the result. This method will be invoked on an invocation handler
45.49 + * when a method is invoked on a proxy instance that it is
45.50 + * associated with.
45.51 + *
45.52 + * @param proxy the proxy instance that the method was invoked on
45.53 + *
45.54 + * @param method the {@code Method} instance corresponding to
45.55 + * the interface method invoked on the proxy instance. The declaring
45.56 + * class of the {@code Method} object will be the interface that
45.57 + * the method was declared in, which may be a superinterface of the
45.58 + * proxy interface that the proxy class inherits the method through.
45.59 + *
45.60 + * @param args an array of objects containing the values of the
45.61 + * arguments passed in the method invocation on the proxy instance,
45.62 + * or {@code null} if interface method takes no arguments.
45.63 + * Arguments of primitive types are wrapped in instances of the
45.64 + * appropriate primitive wrapper class, such as
45.65 + * {@code java.lang.Integer} or {@code java.lang.Boolean}.
45.66 + *
45.67 + * @return the value to return from the method invocation on the
45.68 + * proxy instance. If the declared return type of the interface
45.69 + * method is a primitive type, then the value returned by
45.70 + * this method must be an instance of the corresponding primitive
45.71 + * wrapper class; otherwise, it must be a type assignable to the
45.72 + * declared return type. If the value returned by this method is
45.73 + * {@code null} and the interface method's return type is
45.74 + * primitive, then a {@code NullPointerException} will be
45.75 + * thrown by the method invocation on the proxy instance. If the
45.76 + * value returned by this method is otherwise not compatible with
45.77 + * the interface method's declared return type as described above,
45.78 + * a {@code ClassCastException} will be thrown by the method
45.79 + * invocation on the proxy instance.
45.80 + *
45.81 + * @throws Throwable the exception to throw from the method
45.82 + * invocation on the proxy instance. The exception's type must be
45.83 + * assignable either to any of the exception types declared in the
45.84 + * {@code throws} clause of the interface method or to the
45.85 + * unchecked exception types {@code java.lang.RuntimeException}
45.86 + * or {@code java.lang.Error}. If a checked exception is
45.87 + * thrown by this method that is not assignable to any of the
45.88 + * exception types declared in the {@code throws} clause of
45.89 + * the interface method, then an
45.90 + * {@link UndeclaredThrowableException} containing the
45.91 + * exception that was thrown by this method will be thrown by the
45.92 + * method invocation on the proxy instance.
45.93 + *
45.94 + * @see UndeclaredThrowableException
45.95 + */
45.96 + public Object invoke(Object proxy, Method method, Object[] args)
45.97 + throws Throwable;
45.98 +}
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
46.2 +++ b/emul/mini/src/main/java/java/lang/reflect/Proxy.java Fri Feb 01 16:35:42 2013 +0100
46.3 @@ -0,0 +1,666 @@
46.4 +/*
46.5 + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
46.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
46.7 + *
46.8 + * This code is free software; you can redistribute it and/or modify it
46.9 + * under the terms of the GNU General Public License version 2 only, as
46.10 + * published by the Free Software Foundation. Oracle designates this
46.11 + * particular file as subject to the "Classpath" exception as provided
46.12 + * by Oracle in the LICENSE file that accompanied this code.
46.13 + *
46.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
46.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
46.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
46.17 + * version 2 for more details (a copy is included in the LICENSE file that
46.18 + * accompanied this code).
46.19 + *
46.20 + * You should have received a copy of the GNU General Public License version
46.21 + * 2 along with this work; if not, write to the Free Software Foundation,
46.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
46.23 + *
46.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
46.25 + * or visit www.oracle.com if you need additional information or have any
46.26 + * questions.
46.27 + */
46.28 +
46.29 +package java.lang.reflect;
46.30 +
46.31 +import java.lang.ref.Reference;
46.32 +import java.lang.ref.WeakReference;
46.33 +import java.util.Arrays;
46.34 +import java.util.Collections;
46.35 +import java.util.HashMap;
46.36 +import java.util.HashSet;
46.37 +import java.util.Map;
46.38 +import java.util.Set;
46.39 +import java.util.List;
46.40 +import java.util.WeakHashMap;
46.41 +import sun.misc.ProxyGenerator;
46.42 +
46.43 +/**
46.44 + * {@code Proxy} provides static methods for creating dynamic proxy
46.45 + * classes and instances, and it is also the superclass of all
46.46 + * dynamic proxy classes created by those methods.
46.47 + *
46.48 + * <p>To create a proxy for some interface {@code Foo}:
46.49 + * <pre>
46.50 + * InvocationHandler handler = new MyInvocationHandler(...);
46.51 + * Class proxyClass = Proxy.getProxyClass(
46.52 + * Foo.class.getClassLoader(), new Class[] { Foo.class });
46.53 + * Foo f = (Foo) proxyClass.
46.54 + * getConstructor(new Class[] { InvocationHandler.class }).
46.55 + * newInstance(new Object[] { handler });
46.56 + * </pre>
46.57 + * or more simply:
46.58 + * <pre>
46.59 + * Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
46.60 + * new Class[] { Foo.class },
46.61 + * handler);
46.62 + * </pre>
46.63 + *
46.64 + * <p>A <i>dynamic proxy class</i> (simply referred to as a <i>proxy
46.65 + * class</i> below) is a class that implements a list of interfaces
46.66 + * specified at runtime when the class is created, with behavior as
46.67 + * described below.
46.68 + *
46.69 + * A <i>proxy interface</i> is such an interface that is implemented
46.70 + * by a proxy class.
46.71 + *
46.72 + * A <i>proxy instance</i> is an instance of a proxy class.
46.73 + *
46.74 + * Each proxy instance has an associated <i>invocation handler</i>
46.75 + * object, which implements the interface {@link InvocationHandler}.
46.76 + * A method invocation on a proxy instance through one of its proxy
46.77 + * interfaces will be dispatched to the {@link InvocationHandler#invoke
46.78 + * invoke} method of the instance's invocation handler, passing the proxy
46.79 + * instance, a {@code java.lang.reflect.Method} object identifying
46.80 + * the method that was invoked, and an array of type {@code Object}
46.81 + * containing the arguments. The invocation handler processes the
46.82 + * encoded method invocation as appropriate and the result that it
46.83 + * returns will be returned as the result of the method invocation on
46.84 + * the proxy instance.
46.85 + *
46.86 + * <p>A proxy class has the following properties:
46.87 + *
46.88 + * <ul>
46.89 + * <li>Proxy classes are public, final, and not abstract.
46.90 + *
46.91 + * <li>The unqualified name of a proxy class is unspecified. The space
46.92 + * of class names that begin with the string {@code "$Proxy"}
46.93 + * should be, however, reserved for proxy classes.
46.94 + *
46.95 + * <li>A proxy class extends {@code java.lang.reflect.Proxy}.
46.96 + *
46.97 + * <li>A proxy class implements exactly the interfaces specified at its
46.98 + * creation, in the same order.
46.99 + *
46.100 + * <li>If a proxy class implements a non-public interface, then it will
46.101 + * be defined in the same package as that interface. Otherwise, the
46.102 + * package of a proxy class is also unspecified. Note that package
46.103 + * sealing will not prevent a proxy class from being successfully defined
46.104 + * in a particular package at runtime, and neither will classes already
46.105 + * defined by the same class loader and the same package with particular
46.106 + * signers.
46.107 + *
46.108 + * <li>Since a proxy class implements all of the interfaces specified at
46.109 + * its creation, invoking {@code getInterfaces} on its
46.110 + * {@code Class} object will return an array containing the same
46.111 + * list of interfaces (in the order specified at its creation), invoking
46.112 + * {@code getMethods} on its {@code Class} object will return
46.113 + * an array of {@code Method} objects that include all of the
46.114 + * methods in those interfaces, and invoking {@code getMethod} will
46.115 + * find methods in the proxy interfaces as would be expected.
46.116 + *
46.117 + * <li>The {@link Proxy#isProxyClass Proxy.isProxyClass} method will
46.118 + * return true if it is passed a proxy class-- a class returned by
46.119 + * {@code Proxy.getProxyClass} or the class of an object returned by
46.120 + * {@code Proxy.newProxyInstance}-- and false otherwise.
46.121 + *
46.122 + * <li>The {@code java.security.ProtectionDomain} of a proxy class
46.123 + * is the same as that of system classes loaded by the bootstrap class
46.124 + * loader, such as {@code java.lang.Object}, because the code for a
46.125 + * proxy class is generated by trusted system code. This protection
46.126 + * domain will typically be granted
46.127 + * {@code java.security.AllPermission}.
46.128 + *
46.129 + * <li>Each proxy class has one public constructor that takes one argument,
46.130 + * an implementation of the interface {@link InvocationHandler}, to set
46.131 + * the invocation handler for a proxy instance. Rather than having to use
46.132 + * the reflection API to access the public constructor, a proxy instance
46.133 + * can be also be created by calling the {@link Proxy#newProxyInstance
46.134 + * Proxy.newProxyInstance} method, which combines the actions of calling
46.135 + * {@link Proxy#getProxyClass Proxy.getProxyClass} with invoking the
46.136 + * constructor with an invocation handler.
46.137 + * </ul>
46.138 + *
46.139 + * <p>A proxy instance has the following properties:
46.140 + *
46.141 + * <ul>
46.142 + * <li>Given a proxy instance {@code proxy} and one of the
46.143 + * interfaces implemented by its proxy class {@code Foo}, the
46.144 + * following expression will return true:
46.145 + * <pre>
46.146 + * {@code proxy instanceof Foo}
46.147 + * </pre>
46.148 + * and the following cast operation will succeed (rather than throwing
46.149 + * a {@code ClassCastException}):
46.150 + * <pre>
46.151 + * {@code (Foo) proxy}
46.152 + * </pre>
46.153 + *
46.154 + * <li>Each proxy instance has an associated invocation handler, the one
46.155 + * that was passed to its constructor. The static
46.156 + * {@link Proxy#getInvocationHandler Proxy.getInvocationHandler} method
46.157 + * will return the invocation handler associated with the proxy instance
46.158 + * passed as its argument.
46.159 + *
46.160 + * <li>An interface method invocation on a proxy instance will be
46.161 + * encoded and dispatched to the invocation handler's {@link
46.162 + * InvocationHandler#invoke invoke} method as described in the
46.163 + * documentation for that method.
46.164 + *
46.165 + * <li>An invocation of the {@code hashCode},
46.166 + * {@code equals}, or {@code toString} methods declared in
46.167 + * {@code java.lang.Object} on a proxy instance will be encoded and
46.168 + * dispatched to the invocation handler's {@code invoke} method in
46.169 + * the same manner as interface method invocations are encoded and
46.170 + * dispatched, as described above. The declaring class of the
46.171 + * {@code Method} object passed to {@code invoke} will be
46.172 + * {@code java.lang.Object}. Other public methods of a proxy
46.173 + * instance inherited from {@code java.lang.Object} are not
46.174 + * overridden by a proxy class, so invocations of those methods behave
46.175 + * like they do for instances of {@code java.lang.Object}.
46.176 + * </ul>
46.177 + *
46.178 + * <h3>Methods Duplicated in Multiple Proxy Interfaces</h3>
46.179 + *
46.180 + * <p>When two or more interfaces of a proxy class contain a method with
46.181 + * the same name and parameter signature, the order of the proxy class's
46.182 + * interfaces becomes significant. When such a <i>duplicate method</i>
46.183 + * is invoked on a proxy instance, the {@code Method} object passed
46.184 + * to the invocation handler will not necessarily be the one whose
46.185 + * declaring class is assignable from the reference type of the interface
46.186 + * that the proxy's method was invoked through. This limitation exists
46.187 + * because the corresponding method implementation in the generated proxy
46.188 + * class cannot determine which interface it was invoked through.
46.189 + * Therefore, when a duplicate method is invoked on a proxy instance,
46.190 + * the {@code Method} object for the method in the foremost interface
46.191 + * that contains the method (either directly or inherited through a
46.192 + * superinterface) in the proxy class's list of interfaces is passed to
46.193 + * the invocation handler's {@code invoke} method, regardless of the
46.194 + * reference type through which the method invocation occurred.
46.195 + *
46.196 + * <p>If a proxy interface contains a method with the same name and
46.197 + * parameter signature as the {@code hashCode}, {@code equals},
46.198 + * or {@code toString} methods of {@code java.lang.Object},
46.199 + * when such a method is invoked on a proxy instance, the
46.200 + * {@code Method} object passed to the invocation handler will have
46.201 + * {@code java.lang.Object} as its declaring class. In other words,
46.202 + * the public, non-final methods of {@code java.lang.Object}
46.203 + * logically precede all of the proxy interfaces for the determination of
46.204 + * which {@code Method} object to pass to the invocation handler.
46.205 + *
46.206 + * <p>Note also that when a duplicate method is dispatched to an
46.207 + * invocation handler, the {@code invoke} method may only throw
46.208 + * checked exception types that are assignable to one of the exception
46.209 + * types in the {@code throws} clause of the method in <i>all</i> of
46.210 + * the proxy interfaces that it can be invoked through. If the
46.211 + * {@code invoke} method throws a checked exception that is not
46.212 + * assignable to any of the exception types declared by the method in one
46.213 + * of the proxy interfaces that it can be invoked through, then an
46.214 + * unchecked {@code UndeclaredThrowableException} will be thrown by
46.215 + * the invocation on the proxy instance. This restriction means that not
46.216 + * all of the exception types returned by invoking
46.217 + * {@code getExceptionTypes} on the {@code Method} object
46.218 + * passed to the {@code invoke} method can necessarily be thrown
46.219 + * successfully by the {@code invoke} method.
46.220 + *
46.221 + * @author Peter Jones
46.222 + * @see InvocationHandler
46.223 + * @since 1.3
46.224 + */
46.225 +public class Proxy implements java.io.Serializable {
46.226 +
46.227 + private static final long serialVersionUID = -2222568056686623797L;
46.228 +
46.229 + /** prefix for all proxy class names */
46.230 + private final static String proxyClassNamePrefix = "$Proxy";
46.231 +
46.232 + /** parameter types of a proxy class constructor */
46.233 + private final static Class[] constructorParams =
46.234 + { InvocationHandler.class };
46.235 +
46.236 + /** maps a class loader to the proxy class cache for that loader */
46.237 + private static Map<ClassLoader, Map<List<String>, Object>> loaderToCache
46.238 + = new WeakHashMap<>();
46.239 +
46.240 + /** marks that a particular proxy class is currently being generated */
46.241 + private static Object pendingGenerationMarker = new Object();
46.242 +
46.243 + /** next number to use for generation of unique proxy class names */
46.244 + private static long nextUniqueNumber = 0;
46.245 + private static Object nextUniqueNumberLock = new Object();
46.246 +
46.247 + /** set of all generated proxy classes, for isProxyClass implementation */
46.248 + private static Map<Class<?>, Void> proxyClasses =
46.249 + Collections.synchronizedMap(new WeakHashMap<Class<?>, Void>());
46.250 +
46.251 + /**
46.252 + * the invocation handler for this proxy instance.
46.253 + * @serial
46.254 + */
46.255 + protected InvocationHandler h;
46.256 +
46.257 + /**
46.258 + * Prohibits instantiation.
46.259 + */
46.260 + private Proxy() {
46.261 + }
46.262 +
46.263 + /**
46.264 + * Constructs a new {@code Proxy} instance from a subclass
46.265 + * (typically, a dynamic proxy class) with the specified value
46.266 + * for its invocation handler.
46.267 + *
46.268 + * @param h the invocation handler for this proxy instance
46.269 + */
46.270 + protected Proxy(InvocationHandler h) {
46.271 + this.h = h;
46.272 + }
46.273 +
46.274 + /**
46.275 + * Returns the {@code java.lang.Class} object for a proxy class
46.276 + * given a class loader and an array of interfaces. The proxy class
46.277 + * will be defined by the specified class loader and will implement
46.278 + * all of the supplied interfaces. If a proxy class for the same
46.279 + * permutation of interfaces has already been defined by the class
46.280 + * loader, then the existing proxy class will be returned; otherwise,
46.281 + * a proxy class for those interfaces will be generated dynamically
46.282 + * and defined by the class loader.
46.283 + *
46.284 + * <p>There are several restrictions on the parameters that may be
46.285 + * passed to {@code Proxy.getProxyClass}:
46.286 + *
46.287 + * <ul>
46.288 + * <li>All of the {@code Class} objects in the
46.289 + * {@code interfaces} array must represent interfaces, not
46.290 + * classes or primitive types.
46.291 + *
46.292 + * <li>No two elements in the {@code interfaces} array may
46.293 + * refer to identical {@code Class} objects.
46.294 + *
46.295 + * <li>All of the interface types must be visible by name through the
46.296 + * specified class loader. In other words, for class loader
46.297 + * {@code cl} and every interface {@code i}, the following
46.298 + * expression must be true:
46.299 + * <pre>
46.300 + * Class.forName(i.getName(), false, cl) == i
46.301 + * </pre>
46.302 + *
46.303 + * <li>All non-public interfaces must be in the same package;
46.304 + * otherwise, it would not be possible for the proxy class to
46.305 + * implement all of the interfaces, regardless of what package it is
46.306 + * defined in.
46.307 + *
46.308 + * <li>For any set of member methods of the specified interfaces
46.309 + * that have the same signature:
46.310 + * <ul>
46.311 + * <li>If the return type of any of the methods is a primitive
46.312 + * type or void, then all of the methods must have that same
46.313 + * return type.
46.314 + * <li>Otherwise, one of the methods must have a return type that
46.315 + * is assignable to all of the return types of the rest of the
46.316 + * methods.
46.317 + * </ul>
46.318 + *
46.319 + * <li>The resulting proxy class must not exceed any limits imposed
46.320 + * on classes by the virtual machine. For example, the VM may limit
46.321 + * the number of interfaces that a class may implement to 65535; in
46.322 + * that case, the size of the {@code interfaces} array must not
46.323 + * exceed 65535.
46.324 + * </ul>
46.325 + *
46.326 + * <p>If any of these restrictions are violated,
46.327 + * {@code Proxy.getProxyClass} will throw an
46.328 + * {@code IllegalArgumentException}. If the {@code interfaces}
46.329 + * array argument or any of its elements are {@code null}, a
46.330 + * {@code NullPointerException} will be thrown.
46.331 + *
46.332 + * <p>Note that the order of the specified proxy interfaces is
46.333 + * significant: two requests for a proxy class with the same combination
46.334 + * of interfaces but in a different order will result in two distinct
46.335 + * proxy classes.
46.336 + *
46.337 + * @param loader the class loader to define the proxy class
46.338 + * @param interfaces the list of interfaces for the proxy class
46.339 + * to implement
46.340 + * @return a proxy class that is defined in the specified class loader
46.341 + * and that implements the specified interfaces
46.342 + * @throws IllegalArgumentException if any of the restrictions on the
46.343 + * parameters that may be passed to {@code getProxyClass}
46.344 + * are violated
46.345 + * @throws NullPointerException if the {@code interfaces} array
46.346 + * argument or any of its elements are {@code null}
46.347 + */
46.348 + public static Class<?> getProxyClass(ClassLoader loader,
46.349 + Class<?>... interfaces)
46.350 + throws IllegalArgumentException
46.351 + {
46.352 + if (interfaces.length > 65535) {
46.353 + throw new IllegalArgumentException("interface limit exceeded");
46.354 + }
46.355 +
46.356 + Class<?> proxyClass = null;
46.357 +
46.358 + /* collect interface names to use as key for proxy class cache */
46.359 + String[] interfaceNames = new String[interfaces.length];
46.360 +
46.361 + // for detecting duplicates
46.362 + Set<Class<?>> interfaceSet = new HashSet<>();
46.363 +
46.364 + for (int i = 0; i < interfaces.length; i++) {
46.365 + /*
46.366 + * Verify that the class loader resolves the name of this
46.367 + * interface to the same Class object.
46.368 + */
46.369 + String interfaceName = interfaces[i].getName();
46.370 + Class<?> interfaceClass = null;
46.371 + try {
46.372 + interfaceClass = Class.forName(interfaceName, false, loader);
46.373 + } catch (ClassNotFoundException e) {
46.374 + }
46.375 + if (interfaceClass != interfaces[i]) {
46.376 + throw new IllegalArgumentException(
46.377 + interfaces[i] + " is not visible from class loader");
46.378 + }
46.379 +
46.380 + /*
46.381 + * Verify that the Class object actually represents an
46.382 + * interface.
46.383 + */
46.384 + if (!interfaceClass.isInterface()) {
46.385 + throw new IllegalArgumentException(
46.386 + interfaceClass.getName() + " is not an interface");
46.387 + }
46.388 +
46.389 + /*
46.390 + * Verify that this interface is not a duplicate.
46.391 + */
46.392 + if (interfaceSet.contains(interfaceClass)) {
46.393 + throw new IllegalArgumentException(
46.394 + "repeated interface: " + interfaceClass.getName());
46.395 + }
46.396 + interfaceSet.add(interfaceClass);
46.397 +
46.398 + interfaceNames[i] = interfaceName;
46.399 + }
46.400 +
46.401 + /*
46.402 + * Using string representations of the proxy interfaces as
46.403 + * keys in the proxy class cache (instead of their Class
46.404 + * objects) is sufficient because we require the proxy
46.405 + * interfaces to be resolvable by name through the supplied
46.406 + * class loader, and it has the advantage that using a string
46.407 + * representation of a class makes for an implicit weak
46.408 + * reference to the class.
46.409 + */
46.410 + List<String> key = Arrays.asList(interfaceNames);
46.411 +
46.412 + /*
46.413 + * Find or create the proxy class cache for the class loader.
46.414 + */
46.415 + Map<List<String>, Object> cache;
46.416 + synchronized (loaderToCache) {
46.417 + cache = loaderToCache.get(loader);
46.418 + if (cache == null) {
46.419 + cache = new HashMap<>();
46.420 + loaderToCache.put(loader, cache);
46.421 + }
46.422 + /*
46.423 + * This mapping will remain valid for the duration of this
46.424 + * method, without further synchronization, because the mapping
46.425 + * will only be removed if the class loader becomes unreachable.
46.426 + */
46.427 + }
46.428 +
46.429 + /*
46.430 + * Look up the list of interfaces in the proxy class cache using
46.431 + * the key. This lookup will result in one of three possible
46.432 + * kinds of values:
46.433 + * null, if there is currently no proxy class for the list of
46.434 + * interfaces in the class loader,
46.435 + * the pendingGenerationMarker object, if a proxy class for the
46.436 + * list of interfaces is currently being generated,
46.437 + * or a weak reference to a Class object, if a proxy class for
46.438 + * the list of interfaces has already been generated.
46.439 + */
46.440 + synchronized (cache) {
46.441 + /*
46.442 + * Note that we need not worry about reaping the cache for
46.443 + * entries with cleared weak references because if a proxy class
46.444 + * has been garbage collected, its class loader will have been
46.445 + * garbage collected as well, so the entire cache will be reaped
46.446 + * from the loaderToCache map.
46.447 + */
46.448 + do {
46.449 + Object value = cache.get(key);
46.450 + if (value instanceof Reference) {
46.451 + proxyClass = (Class<?>) ((Reference) value).get();
46.452 + }
46.453 + if (proxyClass != null) {
46.454 + // proxy class already generated: return it
46.455 + return proxyClass;
46.456 + } else if (value == pendingGenerationMarker) {
46.457 + // proxy class being generated: wait for it
46.458 + try {
46.459 + cache.wait();
46.460 + } catch (InterruptedException e) {
46.461 + /*
46.462 + * The class generation that we are waiting for should
46.463 + * take a small, bounded time, so we can safely ignore
46.464 + * thread interrupts here.
46.465 + */
46.466 + }
46.467 + continue;
46.468 + } else {
46.469 + /*
46.470 + * No proxy class for this list of interfaces has been
46.471 + * generated or is being generated, so we will go and
46.472 + * generate it now. Mark it as pending generation.
46.473 + */
46.474 + cache.put(key, pendingGenerationMarker);
46.475 + break;
46.476 + }
46.477 + } while (true);
46.478 + }
46.479 +
46.480 + try {
46.481 + String proxyPkg = null; // package to define proxy class in
46.482 +
46.483 + /*
46.484 + * Record the package of a non-public proxy interface so that the
46.485 + * proxy class will be defined in the same package. Verify that
46.486 + * all non-public proxy interfaces are in the same package.
46.487 + */
46.488 + for (int i = 0; i < interfaces.length; i++) {
46.489 + int flags = interfaces[i].getModifiers();
46.490 + if (!Modifier.isPublic(flags)) {
46.491 + String name = interfaces[i].getName();
46.492 + int n = name.lastIndexOf('.');
46.493 + String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
46.494 + if (proxyPkg == null) {
46.495 + proxyPkg = pkg;
46.496 + } else if (!pkg.equals(proxyPkg)) {
46.497 + throw new IllegalArgumentException(
46.498 + "non-public interfaces from different packages");
46.499 + }
46.500 + }
46.501 + }
46.502 +
46.503 + if (proxyPkg == null) { // if no non-public proxy interfaces,
46.504 + proxyPkg = ""; // use the unnamed package
46.505 + }
46.506 +
46.507 + {
46.508 + /*
46.509 + * Choose a name for the proxy class to generate.
46.510 + */
46.511 + long num;
46.512 + synchronized (nextUniqueNumberLock) {
46.513 + num = nextUniqueNumber++;
46.514 + }
46.515 + String proxyName = proxyPkg + proxyClassNamePrefix + num;
46.516 + /*
46.517 + * Verify that the class loader hasn't already
46.518 + * defined a class with the chosen name.
46.519 + */
46.520 +
46.521 + /*
46.522 + * Generate the specified proxy class.
46.523 + */
46.524 + byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
46.525 + proxyName, interfaces);
46.526 + try {
46.527 + proxyClass = defineClass0(loader, proxyName,
46.528 + proxyClassFile, 0, proxyClassFile.length);
46.529 + } catch (ClassFormatError e) {
46.530 + /*
46.531 + * A ClassFormatError here means that (barring bugs in the
46.532 + * proxy class generation code) there was some other
46.533 + * invalid aspect of the arguments supplied to the proxy
46.534 + * class creation (such as virtual machine limitations
46.535 + * exceeded).
46.536 + */
46.537 + throw new IllegalArgumentException(e.toString());
46.538 + }
46.539 + }
46.540 + // add to set of all generated proxy classes, for isProxyClass
46.541 + proxyClasses.put(proxyClass, null);
46.542 +
46.543 + } finally {
46.544 + /*
46.545 + * We must clean up the "pending generation" state of the proxy
46.546 + * class cache entry somehow. If a proxy class was successfully
46.547 + * generated, store it in the cache (with a weak reference);
46.548 + * otherwise, remove the reserved entry. In all cases, notify
46.549 + * all waiters on reserved entries in this cache.
46.550 + */
46.551 + synchronized (cache) {
46.552 + if (proxyClass != null) {
46.553 + cache.put(key, new WeakReference<Class<?>>(proxyClass));
46.554 + } else {
46.555 + cache.remove(key);
46.556 + }
46.557 + cache.notifyAll();
46.558 + }
46.559 + }
46.560 + return proxyClass;
46.561 + }
46.562 +
46.563 + /**
46.564 + * Returns an instance of a proxy class for the specified interfaces
46.565 + * that dispatches method invocations to the specified invocation
46.566 + * handler. This method is equivalent to:
46.567 + * <pre>
46.568 + * Proxy.getProxyClass(loader, interfaces).
46.569 + * getConstructor(new Class[] { InvocationHandler.class }).
46.570 + * newInstance(new Object[] { handler });
46.571 + * </pre>
46.572 + *
46.573 + * <p>{@code Proxy.newProxyInstance} throws
46.574 + * {@code IllegalArgumentException} for the same reasons that
46.575 + * {@code Proxy.getProxyClass} does.
46.576 + *
46.577 + * @param loader the class loader to define the proxy class
46.578 + * @param interfaces the list of interfaces for the proxy class
46.579 + * to implement
46.580 + * @param h the invocation handler to dispatch method invocations to
46.581 + * @return a proxy instance with the specified invocation handler of a
46.582 + * proxy class that is defined by the specified class loader
46.583 + * and that implements the specified interfaces
46.584 + * @throws IllegalArgumentException if any of the restrictions on the
46.585 + * parameters that may be passed to {@code getProxyClass}
46.586 + * are violated
46.587 + * @throws NullPointerException if the {@code interfaces} array
46.588 + * argument or any of its elements are {@code null}, or
46.589 + * if the invocation handler, {@code h}, is
46.590 + * {@code null}
46.591 + */
46.592 + public static Object newProxyInstance(ClassLoader loader,
46.593 + Class<?>[] interfaces,
46.594 + InvocationHandler h)
46.595 + throws IllegalArgumentException
46.596 + {
46.597 + if (h == null) {
46.598 + throw new NullPointerException();
46.599 + }
46.600 +
46.601 + /*
46.602 + * Look up or generate the designated proxy class.
46.603 + */
46.604 + Class<?> cl = getProxyClass(loader, interfaces);
46.605 +
46.606 + /*
46.607 + * Invoke its constructor with the designated invocation handler.
46.608 + */
46.609 + try {
46.610 + Constructor cons = cl.getConstructor(constructorParams);
46.611 + return cons.newInstance(new Object[] { h });
46.612 + } catch (NoSuchMethodException e) {
46.613 + throw new InternalError(e.toString());
46.614 + } catch (IllegalAccessException e) {
46.615 + throw new InternalError(e.toString());
46.616 + } catch (InstantiationException e) {
46.617 + throw new InternalError(e.toString());
46.618 + } catch (InvocationTargetException e) {
46.619 + throw new InternalError(e.toString());
46.620 + }
46.621 + }
46.622 +
46.623 + /**
46.624 + * Returns true if and only if the specified class was dynamically
46.625 + * generated to be a proxy class using the {@code getProxyClass}
46.626 + * method or the {@code newProxyInstance} method.
46.627 + *
46.628 + * <p>The reliability of this method is important for the ability
46.629 + * to use it to make security decisions, so its implementation should
46.630 + * not just test if the class in question extends {@code Proxy}.
46.631 + *
46.632 + * @param cl the class to test
46.633 + * @return {@code true} if the class is a proxy class and
46.634 + * {@code false} otherwise
46.635 + * @throws NullPointerException if {@code cl} is {@code null}
46.636 + */
46.637 + public static boolean isProxyClass(Class<?> cl) {
46.638 + if (cl == null) {
46.639 + throw new NullPointerException();
46.640 + }
46.641 +
46.642 + return proxyClasses.containsKey(cl);
46.643 + }
46.644 +
46.645 + /**
46.646 + * Returns the invocation handler for the specified proxy instance.
46.647 + *
46.648 + * @param proxy the proxy instance to return the invocation handler for
46.649 + * @return the invocation handler for the proxy instance
46.650 + * @throws IllegalArgumentException if the argument is not a
46.651 + * proxy instance
46.652 + */
46.653 + public static InvocationHandler getInvocationHandler(Object proxy)
46.654 + throws IllegalArgumentException
46.655 + {
46.656 + /*
46.657 + * Verify that the object is actually a proxy instance.
46.658 + */
46.659 + if (!isProxyClass(proxy.getClass())) {
46.660 + throw new IllegalArgumentException("not a proxy instance");
46.661 + }
46.662 +
46.663 + Proxy p = (Proxy) proxy;
46.664 + return p.h;
46.665 + }
46.666 +
46.667 + private static native Class defineClass0(ClassLoader loader, String name,
46.668 + byte[] b, int off, int len);
46.669 +}
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
47.2 +++ b/emul/mini/src/main/java/java/lang/reflect/UndeclaredThrowableException.java Fri Feb 01 16:35:42 2013 +0100
47.3 @@ -0,0 +1,119 @@
47.4 +/*
47.5 + * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved.
47.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
47.7 + *
47.8 + * This code is free software; you can redistribute it and/or modify it
47.9 + * under the terms of the GNU General Public License version 2 only, as
47.10 + * published by the Free Software Foundation. Oracle designates this
47.11 + * particular file as subject to the "Classpath" exception as provided
47.12 + * by Oracle in the LICENSE file that accompanied this code.
47.13 + *
47.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
47.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
47.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
47.17 + * version 2 for more details (a copy is included in the LICENSE file that
47.18 + * accompanied this code).
47.19 + *
47.20 + * You should have received a copy of the GNU General Public License version
47.21 + * 2 along with this work; if not, write to the Free Software Foundation,
47.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
47.23 + *
47.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
47.25 + * or visit www.oracle.com if you need additional information or have any
47.26 + * questions.
47.27 + */
47.28 +
47.29 +package java.lang.reflect;
47.30 +
47.31 +/**
47.32 + * Thrown by a method invocation on a proxy instance if its invocation
47.33 + * handler's {@link InvocationHandler#invoke invoke} method throws a
47.34 + * checked exception (a {@code Throwable} that is not assignable
47.35 + * to {@code RuntimeException} or {@code Error}) that
47.36 + * is not assignable to any of the exception types declared in the
47.37 + * {@code throws} clause of the method that was invoked on the
47.38 + * proxy instance and dispatched to the invocation handler.
47.39 + *
47.40 + * <p>An {@code UndeclaredThrowableException} instance contains
47.41 + * the undeclared checked exception that was thrown by the invocation
47.42 + * handler, and it can be retrieved with the
47.43 + * {@code getUndeclaredThrowable()} method.
47.44 + * {@code UndeclaredThrowableException} extends
47.45 + * {@code RuntimeException}, so it is an unchecked exception
47.46 + * that wraps a checked exception.
47.47 + *
47.48 + * <p>As of release 1.4, this exception has been retrofitted to
47.49 + * conform to the general purpose exception-chaining mechanism. The
47.50 + * "undeclared checked exception that was thrown by the invocation
47.51 + * handler" that may be provided at construction time and accessed via
47.52 + * the {@link #getUndeclaredThrowable()} method is now known as the
47.53 + * <i>cause</i>, and may be accessed via the {@link
47.54 + * Throwable#getCause()} method, as well as the aforementioned "legacy
47.55 + * method."
47.56 + *
47.57 + * @author Peter Jones
47.58 + * @see InvocationHandler
47.59 + * @since 1.3
47.60 + */
47.61 +public class UndeclaredThrowableException extends RuntimeException {
47.62 + static final long serialVersionUID = 330127114055056639L;
47.63 +
47.64 + /**
47.65 + * the undeclared checked exception that was thrown
47.66 + * @serial
47.67 + */
47.68 + private Throwable undeclaredThrowable;
47.69 +
47.70 + /**
47.71 + * Constructs an {@code UndeclaredThrowableException} with the
47.72 + * specified {@code Throwable}.
47.73 + *
47.74 + * @param undeclaredThrowable the undeclared checked exception
47.75 + * that was thrown
47.76 + */
47.77 + public UndeclaredThrowableException(Throwable undeclaredThrowable) {
47.78 + super((Throwable) null); // Disallow initCause
47.79 + this.undeclaredThrowable = undeclaredThrowable;
47.80 + }
47.81 +
47.82 + /**
47.83 + * Constructs an {@code UndeclaredThrowableException} with the
47.84 + * specified {@code Throwable} and a detail message.
47.85 + *
47.86 + * @param undeclaredThrowable the undeclared checked exception
47.87 + * that was thrown
47.88 + * @param s the detail message
47.89 + */
47.90 + public UndeclaredThrowableException(Throwable undeclaredThrowable,
47.91 + String s)
47.92 + {
47.93 + super(s, null); // Disallow initCause
47.94 + this.undeclaredThrowable = undeclaredThrowable;
47.95 + }
47.96 +
47.97 + /**
47.98 + * Returns the {@code Throwable} instance wrapped in this
47.99 + * {@code UndeclaredThrowableException}, which may be {@code null}.
47.100 + *
47.101 + * <p>This method predates the general-purpose exception chaining facility.
47.102 + * The {@link Throwable#getCause()} method is now the preferred means of
47.103 + * obtaining this information.
47.104 + *
47.105 + * @return the undeclared checked exception that was thrown
47.106 + */
47.107 + public Throwable getUndeclaredThrowable() {
47.108 + return undeclaredThrowable;
47.109 + }
47.110 +
47.111 + /**
47.112 + * Returns the cause of this exception (the {@code Throwable}
47.113 + * instance wrapped in this {@code UndeclaredThrowableException},
47.114 + * which may be {@code null}).
47.115 + *
47.116 + * @return the cause of this exception.
47.117 + * @since 1.4
47.118 + */
47.119 + public Throwable getCause() {
47.120 + return undeclaredThrowable;
47.121 + }
47.122 +}
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
48.2 +++ b/emul/mini/src/main/java/java/util/zip/CRC32.java Fri Feb 01 16:35:42 2013 +0100
48.3 @@ -0,0 +1,93 @@
48.4 +/*
48.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
48.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
48.7 + *
48.8 + * This code is free software; you can redistribute it and/or modify it
48.9 + * under the terms of the GNU General Public License version 2 only, as
48.10 + * published by the Free Software Foundation. Oracle designates this
48.11 + * particular file as subject to the "Classpath" exception as provided
48.12 + * by Oracle in the LICENSE file that accompanied this code.
48.13 + *
48.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
48.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
48.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
48.17 + * version 2 for more details (a copy is included in the LICENSE file that
48.18 + * accompanied this code).
48.19 + *
48.20 + * You should have received a copy of the GNU General Public License version
48.21 + * 2 along with this work; if not, write to the Free Software Foundation,
48.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
48.23 + *
48.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
48.25 + * or visit www.oracle.com if you need additional information or have any
48.26 + * questions.
48.27 + */
48.28 +
48.29 +package java.util.zip;
48.30 +
48.31 +/**
48.32 + * A class that can be used to compute the CRC-32 of a data stream.
48.33 + *
48.34 + * @see Checksum
48.35 + * @author David Connelly
48.36 + */
48.37 +public
48.38 +class CRC32 implements Checksum {
48.39 + private int crc;
48.40 +
48.41 + /**
48.42 + * Creates a new CRC32 object.
48.43 + */
48.44 + public CRC32() {
48.45 + }
48.46 +
48.47 +
48.48 + /**
48.49 + * Updates the CRC-32 checksum with the specified byte (the low
48.50 + * eight bits of the argument b).
48.51 + *
48.52 + * @param b the byte to update the checksum with
48.53 + */
48.54 + public void update(int b) {
48.55 + crc = update(crc, b);
48.56 + }
48.57 +
48.58 + /**
48.59 + * Updates the CRC-32 checksum with the specified array of bytes.
48.60 + */
48.61 + public void update(byte[] b, int off, int len) {
48.62 + if (b == null) {
48.63 + throw new NullPointerException();
48.64 + }
48.65 + if (off < 0 || len < 0 || off > b.length - len) {
48.66 + throw new ArrayIndexOutOfBoundsException();
48.67 + }
48.68 + crc = updateBytes(crc, b, off, len);
48.69 + }
48.70 +
48.71 + /**
48.72 + * Updates the CRC-32 checksum with the specified array of bytes.
48.73 + *
48.74 + * @param b the array of bytes to update the checksum with
48.75 + */
48.76 + public void update(byte[] b) {
48.77 + crc = updateBytes(crc, b, 0, b.length);
48.78 + }
48.79 +
48.80 + /**
48.81 + * Resets CRC-32 to initial value.
48.82 + */
48.83 + public void reset() {
48.84 + crc = 0;
48.85 + }
48.86 +
48.87 + /**
48.88 + * Returns CRC-32 value.
48.89 + */
48.90 + public long getValue() {
48.91 + return (long)crc & 0xffffffffL;
48.92 + }
48.93 +
48.94 + private native static int update(int crc, int b);
48.95 + private native static int updateBytes(int crc, byte[] b, int off, int len);
48.96 +}
49.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
49.2 +++ b/emul/mini/src/main/java/java/util/zip/Checksum.java Fri Feb 01 16:35:42 2013 +0100
49.3 @@ -0,0 +1,60 @@
49.4 +/*
49.5 + * Copyright (c) 1996, 1999, 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.util.zip;
49.30 +
49.31 +/**
49.32 + * An interface representing a data checksum.
49.33 + *
49.34 + * @author David Connelly
49.35 + */
49.36 +public
49.37 +interface Checksum {
49.38 + /**
49.39 + * Updates the current checksum with the specified byte.
49.40 + *
49.41 + * @param b the byte to update the checksum with
49.42 + */
49.43 + public void update(int b);
49.44 +
49.45 + /**
49.46 + * Updates the current checksum with the specified array of bytes.
49.47 + * @param b the byte array to update the checksum with
49.48 + * @param off the start offset of the data
49.49 + * @param len the number of bytes to use for the update
49.50 + */
49.51 + public void update(byte[] b, int off, int len);
49.52 +
49.53 + /**
49.54 + * Returns the current checksum value.
49.55 + * @return the current checksum value
49.56 + */
49.57 + public long getValue();
49.58 +
49.59 + /**
49.60 + * Resets the checksum to its initial value.
49.61 + */
49.62 + public void reset();
49.63 +}
50.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
50.2 +++ b/emul/mini/src/main/java/java/util/zip/DataFormatException.java Fri Feb 01 16:35:42 2013 +0100
50.3 @@ -0,0 +1,52 @@
50.4 +/*
50.5 + * Copyright (c) 1996, 2008, 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.util.zip;
50.30 +
50.31 +/**
50.32 + * Signals that a data format error has occurred.
50.33 + *
50.34 + * @author David Connelly
50.35 + */
50.36 +public
50.37 +class DataFormatException extends Exception {
50.38 + private static final long serialVersionUID = 2219632870893641452L;
50.39 +
50.40 + /**
50.41 + * Constructs a DataFormatException with no detail message.
50.42 + */
50.43 + public DataFormatException() {
50.44 + super();
50.45 + }
50.46 +
50.47 + /**
50.48 + * Constructs a DataFormatException with the specified detail message.
50.49 + * A detail message is a String that describes this particular exception.
50.50 + * @param s the String containing a detail message
50.51 + */
50.52 + public DataFormatException(String s) {
50.53 + super(s);
50.54 + }
50.55 +}
51.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
51.2 +++ b/emul/mini/src/main/java/java/util/zip/Inflater.java Fri Feb 01 16:35:42 2013 +0100
51.3 @@ -0,0 +1,402 @@
51.4 +/*
51.5 + * Copyright (c) 1996, 2011, 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.util.zip;
51.30 +
51.31 +/**
51.32 + * This class provides support for general purpose decompression using the
51.33 + * popular ZLIB compression library. The ZLIB compression library was
51.34 + * initially developed as part of the PNG graphics standard and is not
51.35 + * protected by patents. It is fully described in the specifications at
51.36 + * the <a href="package-summary.html#package_description">java.util.zip
51.37 + * package description</a>.
51.38 + *
51.39 + * <p>The following code fragment demonstrates a trivial compression
51.40 + * and decompression of a string using <tt>Deflater</tt> and
51.41 + * <tt>Inflater</tt>.
51.42 + *
51.43 + * <blockquote><pre>
51.44 + * try {
51.45 + * // Encode a String into bytes
51.46 + * String inputString = "blahblahblah\u20AC\u20AC";
51.47 + * byte[] input = inputString.getBytes("UTF-8");
51.48 + *
51.49 + * // Compress the bytes
51.50 + * byte[] output = new byte[100];
51.51 + * Deflater compresser = new Deflater();
51.52 + * compresser.setInput(input);
51.53 + * compresser.finish();
51.54 + * int compressedDataLength = compresser.deflate(output);
51.55 + *
51.56 + * // Decompress the bytes
51.57 + * Inflater decompresser = new Inflater();
51.58 + * decompresser.setInput(output, 0, compressedDataLength);
51.59 + * byte[] result = new byte[100];
51.60 + * int resultLength = decompresser.inflate(result);
51.61 + * decompresser.end();
51.62 + *
51.63 + * // Decode the bytes into a String
51.64 + * String outputString = new String(result, 0, resultLength, "UTF-8");
51.65 + * } catch(java.io.UnsupportedEncodingException ex) {
51.66 + * // handle
51.67 + * } catch (java.util.zip.DataFormatException ex) {
51.68 + * // handle
51.69 + * }
51.70 + * </pre></blockquote>
51.71 + *
51.72 + * @see Deflater
51.73 + * @author David Connelly
51.74 + *
51.75 + */
51.76 +public
51.77 +class Inflater {
51.78 +
51.79 + private final ZStreamRef zsRef;
51.80 + private byte[] buf = defaultBuf;
51.81 + private int off, len;
51.82 + private boolean finished;
51.83 + private boolean needDict;
51.84 +
51.85 + private static final byte[] defaultBuf = new byte[0];
51.86 +
51.87 + static {
51.88 + /* Zip library is loaded from System.initializeSystemClass */
51.89 + initIDs();
51.90 + }
51.91 +
51.92 + /**
51.93 + * Creates a new decompressor. If the parameter 'nowrap' is true then
51.94 + * the ZLIB header and checksum fields will not be used. This provides
51.95 + * compatibility with the compression format used by both GZIP and PKZIP.
51.96 + * <p>
51.97 + * Note: When using the 'nowrap' option it is also necessary to provide
51.98 + * an extra "dummy" byte as input. This is required by the ZLIB native
51.99 + * library in order to support certain optimizations.
51.100 + *
51.101 + * @param nowrap if true then support GZIP compatible compression
51.102 + */
51.103 + public Inflater(boolean nowrap) {
51.104 + zsRef = new ZStreamRef(init(nowrap));
51.105 + }
51.106 +
51.107 + /**
51.108 + * Creates a new decompressor.
51.109 + */
51.110 + public Inflater() {
51.111 + this(false);
51.112 + }
51.113 +
51.114 + /**
51.115 + * Sets input data for decompression. Should be called whenever
51.116 + * needsInput() returns true indicating that more input data is
51.117 + * required.
51.118 + * @param b the input data bytes
51.119 + * @param off the start offset of the input data
51.120 + * @param len the length of the input data
51.121 + * @see Inflater#needsInput
51.122 + */
51.123 + public void setInput(byte[] b, int off, int len) {
51.124 + if (b == null) {
51.125 + throw new NullPointerException();
51.126 + }
51.127 + if (off < 0 || len < 0 || off > b.length - len) {
51.128 + throw new ArrayIndexOutOfBoundsException();
51.129 + }
51.130 + synchronized (zsRef) {
51.131 + this.buf = b;
51.132 + this.off = off;
51.133 + this.len = len;
51.134 + }
51.135 + }
51.136 +
51.137 + /**
51.138 + * Sets input data for decompression. Should be called whenever
51.139 + * needsInput() returns true indicating that more input data is
51.140 + * required.
51.141 + * @param b the input data bytes
51.142 + * @see Inflater#needsInput
51.143 + */
51.144 + public void setInput(byte[] b) {
51.145 + setInput(b, 0, b.length);
51.146 + }
51.147 +
51.148 + /**
51.149 + * Sets the preset dictionary to the given array of bytes. Should be
51.150 + * called when inflate() returns 0 and needsDictionary() returns true
51.151 + * indicating that a preset dictionary is required. The method getAdler()
51.152 + * can be used to get the Adler-32 value of the dictionary needed.
51.153 + * @param b the dictionary data bytes
51.154 + * @param off the start offset of the data
51.155 + * @param len the length of the data
51.156 + * @see Inflater#needsDictionary
51.157 + * @see Inflater#getAdler
51.158 + */
51.159 + public void setDictionary(byte[] b, int off, int len) {
51.160 + if (b == null) {
51.161 + throw new NullPointerException();
51.162 + }
51.163 + if (off < 0 || len < 0 || off > b.length - len) {
51.164 + throw new ArrayIndexOutOfBoundsException();
51.165 + }
51.166 + synchronized (zsRef) {
51.167 + ensureOpen();
51.168 + setDictionary(zsRef.address(), b, off, len);
51.169 + needDict = false;
51.170 + }
51.171 + }
51.172 +
51.173 + /**
51.174 + * Sets the preset dictionary to the given array of bytes. Should be
51.175 + * called when inflate() returns 0 and needsDictionary() returns true
51.176 + * indicating that a preset dictionary is required. The method getAdler()
51.177 + * can be used to get the Adler-32 value of the dictionary needed.
51.178 + * @param b the dictionary data bytes
51.179 + * @see Inflater#needsDictionary
51.180 + * @see Inflater#getAdler
51.181 + */
51.182 + public void setDictionary(byte[] b) {
51.183 + setDictionary(b, 0, b.length);
51.184 + }
51.185 +
51.186 + /**
51.187 + * Returns the total number of bytes remaining in the input buffer.
51.188 + * This can be used to find out what bytes still remain in the input
51.189 + * buffer after decompression has finished.
51.190 + * @return the total number of bytes remaining in the input buffer
51.191 + */
51.192 + public int getRemaining() {
51.193 + synchronized (zsRef) {
51.194 + return len;
51.195 + }
51.196 + }
51.197 +
51.198 + /**
51.199 + * Returns true if no data remains in the input buffer. This can
51.200 + * be used to determine if #setInput should be called in order
51.201 + * to provide more input.
51.202 + * @return true if no data remains in the input buffer
51.203 + */
51.204 + public boolean needsInput() {
51.205 + synchronized (zsRef) {
51.206 + return len <= 0;
51.207 + }
51.208 + }
51.209 +
51.210 + /**
51.211 + * Returns true if a preset dictionary is needed for decompression.
51.212 + * @return true if a preset dictionary is needed for decompression
51.213 + * @see Inflater#setDictionary
51.214 + */
51.215 + public boolean needsDictionary() {
51.216 + synchronized (zsRef) {
51.217 + return needDict;
51.218 + }
51.219 + }
51.220 +
51.221 + /**
51.222 + * Returns true if the end of the compressed data stream has been
51.223 + * reached.
51.224 + * @return true if the end of the compressed data stream has been
51.225 + * reached
51.226 + */
51.227 + public boolean finished() {
51.228 + synchronized (zsRef) {
51.229 + return finished;
51.230 + }
51.231 + }
51.232 +
51.233 + /**
51.234 + * Uncompresses bytes into specified buffer. Returns actual number
51.235 + * of bytes uncompressed. A return value of 0 indicates that
51.236 + * needsInput() or needsDictionary() should be called in order to
51.237 + * determine if more input data or a preset dictionary is required.
51.238 + * In the latter case, getAdler() can be used to get the Adler-32
51.239 + * value of the dictionary required.
51.240 + * @param b the buffer for the uncompressed data
51.241 + * @param off the start offset of the data
51.242 + * @param len the maximum number of uncompressed bytes
51.243 + * @return the actual number of uncompressed bytes
51.244 + * @exception DataFormatException if the compressed data format is invalid
51.245 + * @see Inflater#needsInput
51.246 + * @see Inflater#needsDictionary
51.247 + */
51.248 + public int inflate(byte[] b, int off, int len)
51.249 + throws DataFormatException
51.250 + {
51.251 + if (b == null) {
51.252 + throw new NullPointerException();
51.253 + }
51.254 + if (off < 0 || len < 0 || off > b.length - len) {
51.255 + throw new ArrayIndexOutOfBoundsException();
51.256 + }
51.257 + synchronized (zsRef) {
51.258 + ensureOpen();
51.259 + return inflateBytes(zsRef.address(), b, off, len);
51.260 + }
51.261 + }
51.262 +
51.263 + /**
51.264 + * Uncompresses bytes into specified buffer. Returns actual number
51.265 + * of bytes uncompressed. A return value of 0 indicates that
51.266 + * needsInput() or needsDictionary() should be called in order to
51.267 + * determine if more input data or a preset dictionary is required.
51.268 + * In the latter case, getAdler() can be used to get the Adler-32
51.269 + * value of the dictionary required.
51.270 + * @param b the buffer for the uncompressed data
51.271 + * @return the actual number of uncompressed bytes
51.272 + * @exception DataFormatException if the compressed data format is invalid
51.273 + * @see Inflater#needsInput
51.274 + * @see Inflater#needsDictionary
51.275 + */
51.276 + public int inflate(byte[] b) throws DataFormatException {
51.277 + return inflate(b, 0, b.length);
51.278 + }
51.279 +
51.280 + /**
51.281 + * Returns the ADLER-32 value of the uncompressed data.
51.282 + * @return the ADLER-32 value of the uncompressed data
51.283 + */
51.284 + public int getAdler() {
51.285 + synchronized (zsRef) {
51.286 + ensureOpen();
51.287 + return getAdler(zsRef.address());
51.288 + }
51.289 + }
51.290 +
51.291 + /**
51.292 + * Returns the total number of compressed bytes input so far.
51.293 + *
51.294 + * <p>Since the number of bytes may be greater than
51.295 + * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now
51.296 + * the preferred means of obtaining this information.</p>
51.297 + *
51.298 + * @return the total number of compressed bytes input so far
51.299 + */
51.300 + public int getTotalIn() {
51.301 + return (int) getBytesRead();
51.302 + }
51.303 +
51.304 + /**
51.305 + * Returns the total number of compressed bytes input so far.</p>
51.306 + *
51.307 + * @return the total (non-negative) number of compressed bytes input so far
51.308 + * @since 1.5
51.309 + */
51.310 + public long getBytesRead() {
51.311 + synchronized (zsRef) {
51.312 + ensureOpen();
51.313 + return getBytesRead(zsRef.address());
51.314 + }
51.315 + }
51.316 +
51.317 + /**
51.318 + * Returns the total number of uncompressed bytes output so far.
51.319 + *
51.320 + * <p>Since the number of bytes may be greater than
51.321 + * Integer.MAX_VALUE, the {@link #getBytesWritten()} method is now
51.322 + * the preferred means of obtaining this information.</p>
51.323 + *
51.324 + * @return the total number of uncompressed bytes output so far
51.325 + */
51.326 + public int getTotalOut() {
51.327 + return (int) getBytesWritten();
51.328 + }
51.329 +
51.330 + /**
51.331 + * Returns the total number of uncompressed bytes output so far.</p>
51.332 + *
51.333 + * @return the total (non-negative) number of uncompressed bytes output so far
51.334 + * @since 1.5
51.335 + */
51.336 + public long getBytesWritten() {
51.337 + synchronized (zsRef) {
51.338 + ensureOpen();
51.339 + return getBytesWritten(zsRef.address());
51.340 + }
51.341 + }
51.342 +
51.343 + /**
51.344 + * Resets inflater so that a new set of input data can be processed.
51.345 + */
51.346 + public void reset() {
51.347 + synchronized (zsRef) {
51.348 + ensureOpen();
51.349 + reset(zsRef.address());
51.350 + buf = defaultBuf;
51.351 + finished = false;
51.352 + needDict = false;
51.353 + off = len = 0;
51.354 + }
51.355 + }
51.356 +
51.357 + /**
51.358 + * Closes the decompressor and discards any unprocessed input.
51.359 + * This method should be called when the decompressor is no longer
51.360 + * being used, but will also be called automatically by the finalize()
51.361 + * method. Once this method is called, the behavior of the Inflater
51.362 + * object is undefined.
51.363 + */
51.364 + public void end() {
51.365 + synchronized (zsRef) {
51.366 + long addr = zsRef.address();
51.367 + zsRef.clear();
51.368 + if (addr != 0) {
51.369 + end(addr);
51.370 + buf = null;
51.371 + }
51.372 + }
51.373 + }
51.374 +
51.375 + /**
51.376 + * Closes the decompressor when garbage is collected.
51.377 + */
51.378 + protected void finalize() {
51.379 + end();
51.380 + }
51.381 +
51.382 + private void ensureOpen () {
51.383 + assert Thread.holdsLock(zsRef);
51.384 + if (zsRef.address() == 0)
51.385 + throw new NullPointerException("Inflater has been closed");
51.386 + }
51.387 +
51.388 + boolean ended() {
51.389 + synchronized (zsRef) {
51.390 + return zsRef.address() == 0;
51.391 + }
51.392 + }
51.393 +
51.394 + private native static void initIDs();
51.395 + private native static long init(boolean nowrap);
51.396 + private native static void setDictionary(long addr, byte[] b, int off,
51.397 + int len);
51.398 + private native int inflateBytes(long addr, byte[] b, int off, int len)
51.399 + throws DataFormatException;
51.400 + private native static int getAdler(long addr);
51.401 + private native static long getBytesRead(long addr);
51.402 + private native static long getBytesWritten(long addr);
51.403 + private native static void reset(long addr);
51.404 + private native static void end(long addr);
51.405 +}
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
52.2 +++ b/emul/mini/src/main/java/java/util/zip/InflaterInputStream.java Fri Feb 01 16:35:42 2013 +0100
52.3 @@ -0,0 +1,288 @@
52.4 +/*
52.5 + * Copyright (c) 1996, 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.util.zip;
52.30 +
52.31 +import java.io.FilterInputStream;
52.32 +import java.io.InputStream;
52.33 +import java.io.IOException;
52.34 +import java.io.EOFException;
52.35 +
52.36 +/**
52.37 + * This class implements a stream filter for uncompressing data in the
52.38 + * "deflate" compression format. It is also used as the basis for other
52.39 + * decompression filters, such as GZIPInputStream.
52.40 + *
52.41 + * @see Inflater
52.42 + * @author David Connelly
52.43 + */
52.44 +public
52.45 +class InflaterInputStream extends FilterInputStream {
52.46 + /**
52.47 + * Decompressor for this stream.
52.48 + */
52.49 + protected Inflater inf;
52.50 +
52.51 + /**
52.52 + * Input buffer for decompression.
52.53 + */
52.54 + protected byte[] buf;
52.55 +
52.56 + /**
52.57 + * Length of input buffer.
52.58 + */
52.59 + protected int len;
52.60 +
52.61 + private boolean closed = false;
52.62 + // this flag is set to true after EOF has reached
52.63 + private boolean reachEOF = false;
52.64 +
52.65 + /**
52.66 + * Check to make sure that this stream has not been closed
52.67 + */
52.68 + private void ensureOpen() throws IOException {
52.69 + if (closed) {
52.70 + throw new IOException("Stream closed");
52.71 + }
52.72 + }
52.73 +
52.74 +
52.75 + /**
52.76 + * Creates a new input stream with the specified decompressor and
52.77 + * buffer size.
52.78 + * @param in the input stream
52.79 + * @param inf the decompressor ("inflater")
52.80 + * @param size the input buffer size
52.81 + * @exception IllegalArgumentException if size is <= 0
52.82 + */
52.83 + public InflaterInputStream(InputStream in, Inflater inf, int size) {
52.84 + super(in);
52.85 + if (in == null || inf == null) {
52.86 + throw new NullPointerException();
52.87 + } else if (size <= 0) {
52.88 + throw new IllegalArgumentException("buffer size <= 0");
52.89 + }
52.90 + this.inf = inf;
52.91 + buf = new byte[size];
52.92 + }
52.93 +
52.94 + /**
52.95 + * Creates a new input stream with the specified decompressor and a
52.96 + * default buffer size.
52.97 + * @param in the input stream
52.98 + * @param inf the decompressor ("inflater")
52.99 + */
52.100 + public InflaterInputStream(InputStream in, Inflater inf) {
52.101 + this(in, inf, 512);
52.102 + }
52.103 +
52.104 + boolean usesDefaultInflater = false;
52.105 +
52.106 + /**
52.107 + * Creates a new input stream with a default decompressor and buffer size.
52.108 + * @param in the input stream
52.109 + */
52.110 + public InflaterInputStream(InputStream in) {
52.111 + this(in, new Inflater());
52.112 + usesDefaultInflater = true;
52.113 + }
52.114 +
52.115 + private byte[] singleByteBuf = new byte[1];
52.116 +
52.117 + /**
52.118 + * Reads a byte of uncompressed data. This method will block until
52.119 + * enough input is available for decompression.
52.120 + * @return the byte read, or -1 if end of compressed input is reached
52.121 + * @exception IOException if an I/O error has occurred
52.122 + */
52.123 + public int read() throws IOException {
52.124 + ensureOpen();
52.125 + return read(singleByteBuf, 0, 1) == -1 ? -1 : singleByteBuf[0] & 0xff;
52.126 + }
52.127 +
52.128 + /**
52.129 + * Reads uncompressed data into an array of bytes. If <code>len</code> is not
52.130 + * zero, the method will block until some input can be decompressed; otherwise,
52.131 + * no bytes are read and <code>0</code> is returned.
52.132 + * @param b the buffer into which the data is read
52.133 + * @param off the start offset in the destination array <code>b</code>
52.134 + * @param len the maximum number of bytes read
52.135 + * @return the actual number of bytes read, or -1 if the end of the
52.136 + * compressed input is reached or a preset dictionary is needed
52.137 + * @exception NullPointerException If <code>b</code> is <code>null</code>.
52.138 + * @exception IndexOutOfBoundsException If <code>off</code> is negative,
52.139 + * <code>len</code> is negative, or <code>len</code> is greater than
52.140 + * <code>b.length - off</code>
52.141 + * @exception ZipException if a ZIP format error has occurred
52.142 + * @exception IOException if an I/O error has occurred
52.143 + */
52.144 + public int read(byte[] b, int off, int len) throws IOException {
52.145 + ensureOpen();
52.146 + if (b == null) {
52.147 + throw new NullPointerException();
52.148 + } else if (off < 0 || len < 0 || len > b.length - off) {
52.149 + throw new IndexOutOfBoundsException();
52.150 + } else if (len == 0) {
52.151 + return 0;
52.152 + }
52.153 + try {
52.154 + int n;
52.155 + while ((n = inf.inflate(b, off, len)) == 0) {
52.156 + if (inf.finished() || inf.needsDictionary()) {
52.157 + reachEOF = true;
52.158 + return -1;
52.159 + }
52.160 + if (inf.needsInput()) {
52.161 + fill();
52.162 + }
52.163 + }
52.164 + return n;
52.165 + } catch (DataFormatException e) {
52.166 + String s = e.getMessage();
52.167 + throw new ZipException(s != null ? s : "Invalid ZLIB data format");
52.168 + }
52.169 + }
52.170 +
52.171 + /**
52.172 + * Returns 0 after EOF has been reached, otherwise always return 1.
52.173 + * <p>
52.174 + * Programs should not count on this method to return the actual number
52.175 + * of bytes that could be read without blocking.
52.176 + *
52.177 + * @return 1 before EOF and 0 after EOF.
52.178 + * @exception IOException if an I/O error occurs.
52.179 + *
52.180 + */
52.181 + public int available() throws IOException {
52.182 + ensureOpen();
52.183 + if (reachEOF) {
52.184 + return 0;
52.185 + } else {
52.186 + return 1;
52.187 + }
52.188 + }
52.189 +
52.190 + private byte[] b = new byte[512];
52.191 +
52.192 + /**
52.193 + * Skips specified number of bytes of uncompressed data.
52.194 + * @param n the number of bytes to skip
52.195 + * @return the actual number of bytes skipped.
52.196 + * @exception IOException if an I/O error has occurred
52.197 + * @exception IllegalArgumentException if n < 0
52.198 + */
52.199 + public long skip(long n) throws IOException {
52.200 + if (n < 0) {
52.201 + throw new IllegalArgumentException("negative skip length");
52.202 + }
52.203 + ensureOpen();
52.204 + int max = (int)Math.min(n, Integer.MAX_VALUE);
52.205 + int total = 0;
52.206 + while (total < max) {
52.207 + int len = max - total;
52.208 + if (len > b.length) {
52.209 + len = b.length;
52.210 + }
52.211 + len = read(b, 0, len);
52.212 + if (len == -1) {
52.213 + reachEOF = true;
52.214 + break;
52.215 + }
52.216 + total += len;
52.217 + }
52.218 + return total;
52.219 + }
52.220 +
52.221 + /**
52.222 + * Closes this input stream and releases any system resources associated
52.223 + * with the stream.
52.224 + * @exception IOException if an I/O error has occurred
52.225 + */
52.226 + public void close() throws IOException {
52.227 + if (!closed) {
52.228 + if (usesDefaultInflater)
52.229 + inf.end();
52.230 + in.close();
52.231 + closed = true;
52.232 + }
52.233 + }
52.234 +
52.235 + /**
52.236 + * Fills input buffer with more data to decompress.
52.237 + * @exception IOException if an I/O error has occurred
52.238 + */
52.239 + protected void fill() throws IOException {
52.240 + ensureOpen();
52.241 + len = in.read(buf, 0, buf.length);
52.242 + if (len == -1) {
52.243 + throw new EOFException("Unexpected end of ZLIB input stream");
52.244 + }
52.245 + inf.setInput(buf, 0, len);
52.246 + }
52.247 +
52.248 + /**
52.249 + * Tests if this input stream supports the <code>mark</code> and
52.250 + * <code>reset</code> methods. The <code>markSupported</code>
52.251 + * method of <code>InflaterInputStream</code> returns
52.252 + * <code>false</code>.
52.253 + *
52.254 + * @return a <code>boolean</code> indicating if this stream type supports
52.255 + * the <code>mark</code> and <code>reset</code> methods.
52.256 + * @see java.io.InputStream#mark(int)
52.257 + * @see java.io.InputStream#reset()
52.258 + */
52.259 + public boolean markSupported() {
52.260 + return false;
52.261 + }
52.262 +
52.263 + /**
52.264 + * Marks the current position in this input stream.
52.265 + *
52.266 + * <p> The <code>mark</code> method of <code>InflaterInputStream</code>
52.267 + * does nothing.
52.268 + *
52.269 + * @param readlimit the maximum limit of bytes that can be read before
52.270 + * the mark position becomes invalid.
52.271 + * @see java.io.InputStream#reset()
52.272 + */
52.273 + public synchronized void mark(int readlimit) {
52.274 + }
52.275 +
52.276 + /**
52.277 + * Repositions this stream to the position at the time the
52.278 + * <code>mark</code> method was last called on this input stream.
52.279 + *
52.280 + * <p> The method <code>reset</code> for class
52.281 + * <code>InflaterInputStream</code> does nothing except throw an
52.282 + * <code>IOException</code>.
52.283 + *
52.284 + * @exception IOException if this method is invoked.
52.285 + * @see java.io.InputStream#mark(int)
52.286 + * @see java.io.IOException
52.287 + */
52.288 + public synchronized void reset() throws IOException {
52.289 + throw new IOException("mark/reset not supported");
52.290 + }
52.291 +}
53.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
53.2 +++ b/emul/mini/src/main/java/java/util/zip/ZStreamRef.java Fri Feb 01 16:35:42 2013 +0100
53.3 @@ -0,0 +1,46 @@
53.4 +/*
53.5 + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
53.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
53.7 + *
53.8 + * This code is free software; you can redistribute it and/or modify it
53.9 + * under the terms of the GNU General Public License version 2 only, as
53.10 + * published by the Free Software Foundation. Oracle designates this
53.11 + * particular file as subject to the "Classpath" exception as provided
53.12 + * by Oracle in the LICENSE file that accompanied this code.
53.13 + *
53.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
53.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
53.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
53.17 + * version 2 for more details (a copy is included in the LICENSE file that
53.18 + * accompanied this code).
53.19 + *
53.20 + * You should have received a copy of the GNU General Public License version
53.21 + * 2 along with this work; if not, write to the Free Software Foundation,
53.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
53.23 + *
53.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
53.25 + * or visit www.oracle.com if you need additional information or have any
53.26 + * questions.
53.27 + */
53.28 +
53.29 +package java.util.zip;
53.30 +
53.31 +/**
53.32 + * A reference to the native zlib's z_stream structure.
53.33 + */
53.34 +
53.35 +class ZStreamRef {
53.36 +
53.37 + private long address;
53.38 + ZStreamRef (long address) {
53.39 + this.address = address;
53.40 + }
53.41 +
53.42 + long address() {
53.43 + return address;
53.44 + }
53.45 +
53.46 + void clear() {
53.47 + address = 0;
53.48 + }
53.49 +}
54.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
54.2 +++ b/emul/mini/src/main/java/java/util/zip/ZipConstants.java Fri Feb 01 16:35:42 2013 +0100
54.3 @@ -0,0 +1,98 @@
54.4 +/*
54.5 + * Copyright (c) 1995, 1996, Oracle and/or its affiliates. All rights reserved.
54.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
54.7 + *
54.8 + * This code is free software; you can redistribute it and/or modify it
54.9 + * under the terms of the GNU General Public License version 2 only, as
54.10 + * published by the Free Software Foundation. Oracle designates this
54.11 + * particular file as subject to the "Classpath" exception as provided
54.12 + * by Oracle in the LICENSE file that accompanied this code.
54.13 + *
54.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
54.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
54.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
54.17 + * version 2 for more details (a copy is included in the LICENSE file that
54.18 + * accompanied this code).
54.19 + *
54.20 + * You should have received a copy of the GNU General Public License version
54.21 + * 2 along with this work; if not, write to the Free Software Foundation,
54.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
54.23 + *
54.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
54.25 + * or visit www.oracle.com if you need additional information or have any
54.26 + * questions.
54.27 + */
54.28 +
54.29 +package java.util.zip;
54.30 +
54.31 +/*
54.32 + * This interface defines the constants that are used by the classes
54.33 + * which manipulate ZIP files.
54.34 + *
54.35 + * @author David Connelly
54.36 + */
54.37 +interface ZipConstants {
54.38 + /*
54.39 + * Header signatures
54.40 + */
54.41 + static long LOCSIG = 0x04034b50L; // "PK\003\004"
54.42 + static long EXTSIG = 0x08074b50L; // "PK\007\008"
54.43 + static long CENSIG = 0x02014b50L; // "PK\001\002"
54.44 + static long ENDSIG = 0x06054b50L; // "PK\005\006"
54.45 +
54.46 + /*
54.47 + * Header sizes in bytes (including signatures)
54.48 + */
54.49 + static final int LOCHDR = 30; // LOC header size
54.50 + static final int EXTHDR = 16; // EXT header size
54.51 + static final int CENHDR = 46; // CEN header size
54.52 + static final int ENDHDR = 22; // END header size
54.53 +
54.54 + /*
54.55 + * Local file (LOC) header field offsets
54.56 + */
54.57 + static final int LOCVER = 4; // version needed to extract
54.58 + static final int LOCFLG = 6; // general purpose bit flag
54.59 + static final int LOCHOW = 8; // compression method
54.60 + static final int LOCTIM = 10; // modification time
54.61 + static final int LOCCRC = 14; // uncompressed file crc-32 value
54.62 + static final int LOCSIZ = 18; // compressed size
54.63 + static final int LOCLEN = 22; // uncompressed size
54.64 + static final int LOCNAM = 26; // filename length
54.65 + static final int LOCEXT = 28; // extra field length
54.66 +
54.67 + /*
54.68 + * Extra local (EXT) header field offsets
54.69 + */
54.70 + static final int EXTCRC = 4; // uncompressed file crc-32 value
54.71 + static final int EXTSIZ = 8; // compressed size
54.72 + static final int EXTLEN = 12; // uncompressed size
54.73 +
54.74 + /*
54.75 + * Central directory (CEN) header field offsets
54.76 + */
54.77 + static final int CENVEM = 4; // version made by
54.78 + static final int CENVER = 6; // version needed to extract
54.79 + static final int CENFLG = 8; // encrypt, decrypt flags
54.80 + static final int CENHOW = 10; // compression method
54.81 + static final int CENTIM = 12; // modification time
54.82 + static final int CENCRC = 16; // uncompressed file crc-32 value
54.83 + static final int CENSIZ = 20; // compressed size
54.84 + static final int CENLEN = 24; // uncompressed size
54.85 + static final int CENNAM = 28; // filename length
54.86 + static final int CENEXT = 30; // extra field length
54.87 + static final int CENCOM = 32; // comment length
54.88 + static final int CENDSK = 34; // disk number start
54.89 + static final int CENATT = 36; // internal file attributes
54.90 + static final int CENATX = 38; // external file attributes
54.91 + static final int CENOFF = 42; // LOC header offset
54.92 +
54.93 + /*
54.94 + * End of central directory (END) header field offsets
54.95 + */
54.96 + static final int ENDSUB = 8; // number of entries on this disk
54.97 + static final int ENDTOT = 10; // total number of entries
54.98 + static final int ENDSIZ = 12; // central directory size in bytes
54.99 + static final int ENDOFF = 16; // offset of first CEN header
54.100 + static final int ENDCOM = 20; // zip file comment length
54.101 +}
55.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
55.2 +++ b/emul/mini/src/main/java/java/util/zip/ZipConstants64.java Fri Feb 01 16:35:42 2013 +0100
55.3 @@ -0,0 +1,84 @@
55.4 +/*
55.5 + * Copyright (c) 1995, 1996, Oracle and/or its affiliates. All rights reserved.
55.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55.7 + *
55.8 + * This code is free software; you can redistribute it and/or modify it
55.9 + * under the terms of the GNU General Public License version 2 only, as
55.10 + * published by the Free Software Foundation. Oracle designates this
55.11 + * particular file as subject to the "Classpath" exception as provided
55.12 + * by Oracle in the LICENSE file that accompanied this code.
55.13 + *
55.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
55.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
55.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
55.17 + * version 2 for more details (a copy is included in the LICENSE file that
55.18 + * accompanied this code).
55.19 + *
55.20 + * You should have received a copy of the GNU General Public License version
55.21 + * 2 along with this work; if not, write to the Free Software Foundation,
55.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
55.23 + *
55.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
55.25 + * or visit www.oracle.com if you need additional information or have any
55.26 + * questions.
55.27 + */
55.28 +
55.29 +package java.util.zip;
55.30 +
55.31 +/*
55.32 + * This class defines the constants that are used by the classes
55.33 + * which manipulate Zip64 files.
55.34 + */
55.35 +
55.36 +class ZipConstants64 {
55.37 +
55.38 + /*
55.39 + * ZIP64 constants
55.40 + */
55.41 + static final long ZIP64_ENDSIG = 0x06064b50L; // "PK\006\006"
55.42 + static final long ZIP64_LOCSIG = 0x07064b50L; // "PK\006\007"
55.43 + static final int ZIP64_ENDHDR = 56; // ZIP64 end header size
55.44 + static final int ZIP64_LOCHDR = 20; // ZIP64 end loc header size
55.45 + static final int ZIP64_EXTHDR = 24; // EXT header size
55.46 + static final int ZIP64_EXTID = 0x0001; // Extra field Zip64 header ID
55.47 +
55.48 + static final int ZIP64_MAGICCOUNT = 0xFFFF;
55.49 + static final long ZIP64_MAGICVAL = 0xFFFFFFFFL;
55.50 +
55.51 + /*
55.52 + * Zip64 End of central directory (END) header field offsets
55.53 + */
55.54 + static final int ZIP64_ENDLEN = 4; // size of zip64 end of central dir
55.55 + static final int ZIP64_ENDVEM = 12; // version made by
55.56 + static final int ZIP64_ENDVER = 14; // version needed to extract
55.57 + static final int ZIP64_ENDNMD = 16; // number of this disk
55.58 + static final int ZIP64_ENDDSK = 20; // disk number of start
55.59 + static final int ZIP64_ENDTOD = 24; // total number of entries on this disk
55.60 + static final int ZIP64_ENDTOT = 32; // total number of entries
55.61 + static final int ZIP64_ENDSIZ = 40; // central directory size in bytes
55.62 + static final int ZIP64_ENDOFF = 48; // offset of first CEN header
55.63 + static final int ZIP64_ENDEXT = 56; // zip64 extensible data sector
55.64 +
55.65 + /*
55.66 + * Zip64 End of central directory locator field offsets
55.67 + */
55.68 + static final int ZIP64_LOCDSK = 4; // disk number start
55.69 + static final int ZIP64_LOCOFF = 8; // offset of zip64 end
55.70 + static final int ZIP64_LOCTOT = 16; // total number of disks
55.71 +
55.72 + /*
55.73 + * Zip64 Extra local (EXT) header field offsets
55.74 + */
55.75 + static final int ZIP64_EXTCRC = 4; // uncompressed file crc-32 value
55.76 + static final int ZIP64_EXTSIZ = 8; // compressed size, 8-byte
55.77 + static final int ZIP64_EXTLEN = 16; // uncompressed size, 8-byte
55.78 +
55.79 + /*
55.80 + * Language encoding flag EFS
55.81 + */
55.82 + static final int EFS = 0x800; // If this bit is set the filename and
55.83 + // comment fields for this file must be
55.84 + // encoded using UTF-8.
55.85 +
55.86 + private ZipConstants64() {}
55.87 +}
56.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
56.2 +++ b/emul/mini/src/main/java/java/util/zip/ZipEntry.java Fri Feb 01 16:35:42 2013 +0100
56.3 @@ -0,0 +1,327 @@
56.4 +/*
56.5 + * Copyright (c) 1995, 2011, 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 +import java.util.Date;
56.32 +
56.33 +/**
56.34 + * This class is used to represent a ZIP file entry.
56.35 + *
56.36 + * @author David Connelly
56.37 + */
56.38 +public
56.39 +class ZipEntry implements ZipConstants, Cloneable {
56.40 + String name; // entry name
56.41 + long time = -1; // modification time (in DOS time)
56.42 + long crc = -1; // crc-32 of entry data
56.43 + long size = -1; // uncompressed size of entry data
56.44 + long csize = -1; // compressed size of entry data
56.45 + int method = -1; // compression method
56.46 + int flag = 0; // general purpose flag
56.47 + byte[] extra; // optional extra field data for entry
56.48 + String comment; // optional comment string for entry
56.49 +
56.50 + /**
56.51 + * Compression method for uncompressed entries.
56.52 + */
56.53 + public static final int STORED = 0;
56.54 +
56.55 + /**
56.56 + * Compression method for compressed (deflated) entries.
56.57 + */
56.58 + public static final int DEFLATED = 8;
56.59 +
56.60 + /**
56.61 + * Creates a new zip entry with the specified name.
56.62 + *
56.63 + * @param name the entry name
56.64 + * @exception NullPointerException if the entry name is null
56.65 + * @exception IllegalArgumentException if the entry name is longer than
56.66 + * 0xFFFF bytes
56.67 + */
56.68 + public ZipEntry(String name) {
56.69 + if (name == null) {
56.70 + throw new NullPointerException();
56.71 + }
56.72 + if (name.length() > 0xFFFF) {
56.73 + throw new IllegalArgumentException("entry name too long");
56.74 + }
56.75 + this.name = name;
56.76 + }
56.77 +
56.78 + /**
56.79 + * Creates a new zip entry with fields taken from the specified
56.80 + * zip entry.
56.81 + * @param e a zip Entry object
56.82 + */
56.83 + public ZipEntry(ZipEntry e) {
56.84 + name = e.name;
56.85 + time = e.time;
56.86 + crc = e.crc;
56.87 + size = e.size;
56.88 + csize = e.csize;
56.89 + method = e.method;
56.90 + flag = e.flag;
56.91 + extra = e.extra;
56.92 + comment = e.comment;
56.93 + }
56.94 +
56.95 + /*
56.96 + * Creates a new un-initialized zip entry
56.97 + */
56.98 + ZipEntry() {}
56.99 +
56.100 + /**
56.101 + * Returns the name of the entry.
56.102 + * @return the name of the entry
56.103 + */
56.104 + public String getName() {
56.105 + return name;
56.106 + }
56.107 +
56.108 + /**
56.109 + * Sets the modification time of the entry.
56.110 + * @param time the entry modification time in number of milliseconds
56.111 + * since the epoch
56.112 + * @see #getTime()
56.113 + */
56.114 + public void setTime(long time) {
56.115 + this.time = javaToDosTime(time);
56.116 + }
56.117 +
56.118 + /**
56.119 + * Returns the modification time of the entry, or -1 if not specified.
56.120 + * @return the modification time of the entry, or -1 if not specified
56.121 + * @see #setTime(long)
56.122 + */
56.123 + public long getTime() {
56.124 + return time != -1 ? dosToJavaTime(time) : -1;
56.125 + }
56.126 +
56.127 + /**
56.128 + * Sets the uncompressed size of the entry data.
56.129 + * @param size the uncompressed size in bytes
56.130 + * @exception IllegalArgumentException if the specified size is less
56.131 + * than 0, is greater than 0xFFFFFFFF when
56.132 + * <a href="package-summary.html#zip64">ZIP64 format</a> is not supported,
56.133 + * or is less than 0 when ZIP64 is supported
56.134 + * @see #getSize()
56.135 + */
56.136 + public void setSize(long size) {
56.137 + if (size < 0) {
56.138 + throw new IllegalArgumentException("invalid entry size");
56.139 + }
56.140 + this.size = size;
56.141 + }
56.142 +
56.143 + /**
56.144 + * Returns the uncompressed size of the entry data, or -1 if not known.
56.145 + * @return the uncompressed size of the entry data, or -1 if not known
56.146 + * @see #setSize(long)
56.147 + */
56.148 + public long getSize() {
56.149 + return size;
56.150 + }
56.151 +
56.152 + /**
56.153 + * Returns the size of the compressed entry data, or -1 if not known.
56.154 + * In the case of a stored entry, the compressed size will be the same
56.155 + * as the uncompressed size of the entry.
56.156 + * @return the size of the compressed entry data, or -1 if not known
56.157 + * @see #setCompressedSize(long)
56.158 + */
56.159 + public long getCompressedSize() {
56.160 + return csize;
56.161 + }
56.162 +
56.163 + /**
56.164 + * Sets the size of the compressed entry data.
56.165 + * @param csize the compressed size to set to
56.166 + * @see #getCompressedSize()
56.167 + */
56.168 + public void setCompressedSize(long csize) {
56.169 + this.csize = csize;
56.170 + }
56.171 +
56.172 + /**
56.173 + * Sets the CRC-32 checksum of the uncompressed entry data.
56.174 + * @param crc the CRC-32 value
56.175 + * @exception IllegalArgumentException if the specified CRC-32 value is
56.176 + * less than 0 or greater than 0xFFFFFFFF
56.177 + * @see #getCrc()
56.178 + */
56.179 + public void setCrc(long crc) {
56.180 + if (crc < 0 || crc > 0xFFFFFFFFL) {
56.181 + throw new IllegalArgumentException("invalid entry crc-32");
56.182 + }
56.183 + this.crc = crc;
56.184 + }
56.185 +
56.186 + /**
56.187 + * Returns the CRC-32 checksum of the uncompressed entry data, or -1 if
56.188 + * not known.
56.189 + * @return the CRC-32 checksum of the uncompressed entry data, or -1 if
56.190 + * not known
56.191 + * @see #setCrc(long)
56.192 + */
56.193 + public long getCrc() {
56.194 + return crc;
56.195 + }
56.196 +
56.197 + /**
56.198 + * Sets the compression method for the entry.
56.199 + * @param method the compression method, either STORED or DEFLATED
56.200 + * @exception IllegalArgumentException if the specified compression
56.201 + * method is invalid
56.202 + * @see #getMethod()
56.203 + */
56.204 + public void setMethod(int method) {
56.205 + if (method != STORED && method != DEFLATED) {
56.206 + throw new IllegalArgumentException("invalid compression method");
56.207 + }
56.208 + this.method = method;
56.209 + }
56.210 +
56.211 + /**
56.212 + * Returns the compression method of the entry, or -1 if not specified.
56.213 + * @return the compression method of the entry, or -1 if not specified
56.214 + * @see #setMethod(int)
56.215 + */
56.216 + public int getMethod() {
56.217 + return method;
56.218 + }
56.219 +
56.220 + /**
56.221 + * Sets the optional extra field data for the entry.
56.222 + * @param extra the extra field data bytes
56.223 + * @exception IllegalArgumentException if the length of the specified
56.224 + * extra field data is greater than 0xFFFF bytes
56.225 + * @see #getExtra()
56.226 + */
56.227 + public void setExtra(byte[] extra) {
56.228 + if (extra != null && extra.length > 0xFFFF) {
56.229 + throw new IllegalArgumentException("invalid extra field length");
56.230 + }
56.231 + this.extra = extra;
56.232 + }
56.233 +
56.234 + /**
56.235 + * Returns the extra field data for the entry, or null if none.
56.236 + * @return the extra field data for the entry, or null if none
56.237 + * @see #setExtra(byte[])
56.238 + */
56.239 + public byte[] getExtra() {
56.240 + return extra;
56.241 + }
56.242 +
56.243 + /**
56.244 + * Sets the optional comment string for the entry.
56.245 + *
56.246 + * <p>ZIP entry comments have maximum length of 0xffff. If the length of the
56.247 + * specified comment string is greater than 0xFFFF bytes after encoding, only
56.248 + * the first 0xFFFF bytes are output to the ZIP file entry.
56.249 + *
56.250 + * @param comment the comment string
56.251 + *
56.252 + * @see #getComment()
56.253 + */
56.254 + public void setComment(String comment) {
56.255 + this.comment = comment;
56.256 + }
56.257 +
56.258 + /**
56.259 + * Returns the comment string for the entry, or null if none.
56.260 + * @return the comment string for the entry, or null if none
56.261 + * @see #setComment(String)
56.262 + */
56.263 + public String getComment() {
56.264 + return comment;
56.265 + }
56.266 +
56.267 + /**
56.268 + * Returns true if this is a directory entry. A directory entry is
56.269 + * defined to be one whose name ends with a '/'.
56.270 + * @return true if this is a directory entry
56.271 + */
56.272 + public boolean isDirectory() {
56.273 + return name.endsWith("/");
56.274 + }
56.275 +
56.276 + /**
56.277 + * Returns a string representation of the ZIP entry.
56.278 + */
56.279 + public String toString() {
56.280 + return getName();
56.281 + }
56.282 +
56.283 + /*
56.284 + * Converts DOS time to Java time (number of milliseconds since epoch).
56.285 + */
56.286 + private static long dosToJavaTime(long dtime) {
56.287 + Date d = new Date((int)(((dtime >> 25) & 0x7f) + 80),
56.288 + (int)(((dtime >> 21) & 0x0f) - 1),
56.289 + (int)((dtime >> 16) & 0x1f),
56.290 + (int)((dtime >> 11) & 0x1f),
56.291 + (int)((dtime >> 5) & 0x3f),
56.292 + (int)((dtime << 1) & 0x3e));
56.293 + return d.getTime();
56.294 + }
56.295 +
56.296 + /*
56.297 + * Converts Java time to DOS time.
56.298 + */
56.299 + private static long javaToDosTime(long time) {
56.300 + Date d = new Date(time);
56.301 + int year = d.getYear() + 1900;
56.302 + if (year < 1980) {
56.303 + return (1 << 21) | (1 << 16);
56.304 + }
56.305 + return (year - 1980) << 25 | (d.getMonth() + 1) << 21 |
56.306 + d.getDate() << 16 | d.getHours() << 11 | d.getMinutes() << 5 |
56.307 + d.getSeconds() >> 1;
56.308 + }
56.309 +
56.310 + /**
56.311 + * Returns the hash code value for this entry.
56.312 + */
56.313 + public int hashCode() {
56.314 + return name.hashCode();
56.315 + }
56.316 +
56.317 + /**
56.318 + * Returns a copy of this entry.
56.319 + */
56.320 + public Object clone() {
56.321 + try {
56.322 + ZipEntry e = (ZipEntry)super.clone();
56.323 + e.extra = (extra == null) ? null : extra.clone();
56.324 + return e;
56.325 + } catch (CloneNotSupportedException e) {
56.326 + // This should never happen, since we are Cloneable
56.327 + throw new InternalError();
56.328 + }
56.329 + }
56.330 +}
57.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
57.2 +++ b/emul/mini/src/main/java/java/util/zip/ZipException.java Fri Feb 01 16:35:42 2013 +0100
57.3 @@ -0,0 +1,60 @@
57.4 +/*
57.5 + * Copyright (c) 1995, 2010, 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 +import java.io.IOException;
57.32 +
57.33 +/**
57.34 + * Signals that a Zip exception of some sort has occurred.
57.35 + *
57.36 + * @author unascribed
57.37 + * @see java.io.IOException
57.38 + * @since JDK1.0
57.39 + */
57.40 +
57.41 +public
57.42 +class ZipException extends IOException {
57.43 + private static final long serialVersionUID = 8000196834066748623L;
57.44 +
57.45 + /**
57.46 + * Constructs a <code>ZipException</code> with <code>null</code>
57.47 + * as its error detail message.
57.48 + */
57.49 + public ZipException() {
57.50 + super();
57.51 + }
57.52 +
57.53 + /**
57.54 + * Constructs a <code>ZipException</code> with the specified detail
57.55 + * message.
57.56 + *
57.57 + * @param s the detail message.
57.58 + */
57.59 +
57.60 + public ZipException(String s) {
57.61 + super(s);
57.62 + }
57.63 +}
58.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
58.2 +++ b/emul/mini/src/main/java/java/util/zip/ZipInputStream.java Fri Feb 01 16:35:42 2013 +0100
58.3 @@ -0,0 +1,456 @@
58.4 +/*
58.5 + * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
58.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
58.7 + *
58.8 + * This code is free software; you can redistribute it and/or modify it
58.9 + * under the terms of the GNU General Public License version 2 only, as
58.10 + * published by the Free Software Foundation. Oracle designates this
58.11 + * particular file as subject to the "Classpath" exception as provided
58.12 + * by Oracle in the LICENSE file that accompanied this code.
58.13 + *
58.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
58.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
58.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
58.17 + * version 2 for more details (a copy is included in the LICENSE file that
58.18 + * accompanied this code).
58.19 + *
58.20 + * You should have received a copy of the GNU General Public License version
58.21 + * 2 along with this work; if not, write to the Free Software Foundation,
58.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
58.23 + *
58.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
58.25 + * or visit www.oracle.com if you need additional information or have any
58.26 + * questions.
58.27 + */
58.28 +
58.29 +package java.util.zip;
58.30 +
58.31 +import java.io.InputStream;
58.32 +import java.io.IOException;
58.33 +import java.io.EOFException;
58.34 +import java.io.PushbackInputStream;
58.35 +import java.nio.charset.Charset;
58.36 +import java.nio.charset.StandardCharsets;
58.37 +import static java.util.zip.ZipConstants64.*;
58.38 +
58.39 +/**
58.40 + * This class implements an input stream filter for reading files in the
58.41 + * ZIP file format. Includes support for both compressed and uncompressed
58.42 + * entries.
58.43 + *
58.44 + * @author David Connelly
58.45 + */
58.46 +public
58.47 +class ZipInputStream extends InflaterInputStream implements ZipConstants {
58.48 + private ZipEntry entry;
58.49 + private int flag;
58.50 + private CRC32 crc = new CRC32();
58.51 + private long remaining;
58.52 + private byte[] tmpbuf = new byte[512];
58.53 +
58.54 + private static final int STORED = ZipEntry.STORED;
58.55 + private static final int DEFLATED = ZipEntry.DEFLATED;
58.56 +
58.57 + private boolean closed = false;
58.58 + // this flag is set to true after EOF has reached for
58.59 + // one entry
58.60 + private boolean entryEOF = false;
58.61 +
58.62 + private ZipCoder zc;
58.63 +
58.64 + /**
58.65 + * Check to make sure that this stream has not been closed
58.66 + */
58.67 + private void ensureOpen() throws IOException {
58.68 + if (closed) {
58.69 + throw new IOException("Stream closed");
58.70 + }
58.71 + }
58.72 +
58.73 + /**
58.74 + * Creates a new ZIP input stream.
58.75 + *
58.76 + * <p>The UTF-8 {@link java.nio.charset.Charset charset} is used to
58.77 + * decode the entry names.
58.78 + *
58.79 + * @param in the actual input stream
58.80 + */
58.81 + public ZipInputStream(InputStream in) {
58.82 + this(in, StandardCharsets.UTF_8);
58.83 + }
58.84 +
58.85 + /**
58.86 + * Creates a new ZIP input stream.
58.87 + *
58.88 + * @param in the actual input stream
58.89 + *
58.90 + * @param charset
58.91 + * The {@linkplain java.nio.charset.Charset charset} to be
58.92 + * used to decode the ZIP entry name (ignored if the
58.93 + * <a href="package-summary.html#lang_encoding"> language
58.94 + * encoding bit</a> of the ZIP entry's general purpose bit
58.95 + * flag is set).
58.96 + *
58.97 + * @since 1.7
58.98 + */
58.99 + public ZipInputStream(InputStream in, Charset charset) {
58.100 + super(new PushbackInputStream(in, 512), new Inflater(true), 512);
58.101 + usesDefaultInflater = true;
58.102 + if(in == null) {
58.103 + throw new NullPointerException("in is null");
58.104 + }
58.105 + if (charset == null)
58.106 + throw new NullPointerException("charset is null");
58.107 + this.zc = ZipCoder.get(charset);
58.108 + }
58.109 +
58.110 + /**
58.111 + * Reads the next ZIP file entry and positions the stream at the
58.112 + * beginning of the entry data.
58.113 + * @return the next ZIP file entry, or null if there are no more entries
58.114 + * @exception ZipException if a ZIP file error has occurred
58.115 + * @exception IOException if an I/O error has occurred
58.116 + */
58.117 + public ZipEntry getNextEntry() throws IOException {
58.118 + ensureOpen();
58.119 + if (entry != null) {
58.120 + closeEntry();
58.121 + }
58.122 + crc.reset();
58.123 + inf.reset();
58.124 + if ((entry = readLOC()) == null) {
58.125 + return null;
58.126 + }
58.127 + if (entry.method == STORED) {
58.128 + remaining = entry.size;
58.129 + }
58.130 + entryEOF = false;
58.131 + return entry;
58.132 + }
58.133 +
58.134 + /**
58.135 + * Closes the current ZIP entry and positions the stream for reading the
58.136 + * next entry.
58.137 + * @exception ZipException if a ZIP file error has occurred
58.138 + * @exception IOException if an I/O error has occurred
58.139 + */
58.140 + public void closeEntry() throws IOException {
58.141 + ensureOpen();
58.142 + while (read(tmpbuf, 0, tmpbuf.length) != -1) ;
58.143 + entryEOF = true;
58.144 + }
58.145 +
58.146 + /**
58.147 + * Returns 0 after EOF has reached for the current entry data,
58.148 + * otherwise always return 1.
58.149 + * <p>
58.150 + * Programs should not count on this method to return the actual number
58.151 + * of bytes that could be read without blocking.
58.152 + *
58.153 + * @return 1 before EOF and 0 after EOF has reached for current entry.
58.154 + * @exception IOException if an I/O error occurs.
58.155 + *
58.156 + */
58.157 + public int available() throws IOException {
58.158 + ensureOpen();
58.159 + if (entryEOF) {
58.160 + return 0;
58.161 + } else {
58.162 + return 1;
58.163 + }
58.164 + }
58.165 +
58.166 + /**
58.167 + * Reads from the current ZIP entry into an array of bytes.
58.168 + * If <code>len</code> is not zero, the method
58.169 + * blocks until some input is available; otherwise, no
58.170 + * bytes are read and <code>0</code> is returned.
58.171 + * @param b the buffer into which the data is read
58.172 + * @param off the start offset in the destination array <code>b</code>
58.173 + * @param len the maximum number of bytes read
58.174 + * @return the actual number of bytes read, or -1 if the end of the
58.175 + * entry is reached
58.176 + * @exception NullPointerException if <code>b</code> is <code>null</code>.
58.177 + * @exception IndexOutOfBoundsException if <code>off</code> is negative,
58.178 + * <code>len</code> is negative, or <code>len</code> is greater than
58.179 + * <code>b.length - off</code>
58.180 + * @exception ZipException if a ZIP file error has occurred
58.181 + * @exception IOException if an I/O error has occurred
58.182 + */
58.183 + public int read(byte[] b, int off, int len) throws IOException {
58.184 + ensureOpen();
58.185 + if (off < 0 || len < 0 || off > b.length - len) {
58.186 + throw new IndexOutOfBoundsException();
58.187 + } else if (len == 0) {
58.188 + return 0;
58.189 + }
58.190 +
58.191 + if (entry == null) {
58.192 + return -1;
58.193 + }
58.194 + switch (entry.method) {
58.195 + case DEFLATED:
58.196 + len = super.read(b, off, len);
58.197 + if (len == -1) {
58.198 + readEnd(entry);
58.199 + entryEOF = true;
58.200 + entry = null;
58.201 + } else {
58.202 + crc.update(b, off, len);
58.203 + }
58.204 + return len;
58.205 + case STORED:
58.206 + if (remaining <= 0) {
58.207 + entryEOF = true;
58.208 + entry = null;
58.209 + return -1;
58.210 + }
58.211 + if (len > remaining) {
58.212 + len = (int)remaining;
58.213 + }
58.214 + len = in.read(b, off, len);
58.215 + if (len == -1) {
58.216 + throw new ZipException("unexpected EOF");
58.217 + }
58.218 + crc.update(b, off, len);
58.219 + remaining -= len;
58.220 + if (remaining == 0 && entry.crc != crc.getValue()) {
58.221 + throw new ZipException(
58.222 + "invalid entry CRC (expected 0x" + Long.toHexString(entry.crc) +
58.223 + " but got 0x" + Long.toHexString(crc.getValue()) + ")");
58.224 + }
58.225 + return len;
58.226 + default:
58.227 + throw new ZipException("invalid compression method");
58.228 + }
58.229 + }
58.230 +
58.231 + /**
58.232 + * Skips specified number of bytes in the current ZIP entry.
58.233 + * @param n the number of bytes to skip
58.234 + * @return the actual number of bytes skipped
58.235 + * @exception ZipException if a ZIP file error has occurred
58.236 + * @exception IOException if an I/O error has occurred
58.237 + * @exception IllegalArgumentException if n < 0
58.238 + */
58.239 + public long skip(long n) throws IOException {
58.240 + if (n < 0) {
58.241 + throw new IllegalArgumentException("negative skip length");
58.242 + }
58.243 + ensureOpen();
58.244 + int max = (int)Math.min(n, Integer.MAX_VALUE);
58.245 + int total = 0;
58.246 + while (total < max) {
58.247 + int len = max - total;
58.248 + if (len > tmpbuf.length) {
58.249 + len = tmpbuf.length;
58.250 + }
58.251 + len = read(tmpbuf, 0, len);
58.252 + if (len == -1) {
58.253 + entryEOF = true;
58.254 + break;
58.255 + }
58.256 + total += len;
58.257 + }
58.258 + return total;
58.259 + }
58.260 +
58.261 + /**
58.262 + * Closes this input stream and releases any system resources associated
58.263 + * with the stream.
58.264 + * @exception IOException if an I/O error has occurred
58.265 + */
58.266 + public void close() throws IOException {
58.267 + if (!closed) {
58.268 + super.close();
58.269 + closed = true;
58.270 + }
58.271 + }
58.272 +
58.273 + private byte[] b = new byte[256];
58.274 +
58.275 + /*
58.276 + * Reads local file (LOC) header for next entry.
58.277 + */
58.278 + private ZipEntry readLOC() throws IOException {
58.279 + try {
58.280 + readFully(tmpbuf, 0, LOCHDR);
58.281 + } catch (EOFException e) {
58.282 + return null;
58.283 + }
58.284 + if (get32(tmpbuf, 0) != LOCSIG) {
58.285 + return null;
58.286 + }
58.287 + // get flag first, we need check EFS.
58.288 + flag = get16(tmpbuf, LOCFLG);
58.289 + // get the entry name and create the ZipEntry first
58.290 + int len = get16(tmpbuf, LOCNAM);
58.291 + int blen = b.length;
58.292 + if (len > blen) {
58.293 + do
58.294 + blen = blen * 2;
58.295 + while (len > blen);
58.296 + b = new byte[blen];
58.297 + }
58.298 + readFully(b, 0, len);
58.299 + // Force to use UTF-8 if the EFS bit is ON, even the cs is NOT UTF-8
58.300 + ZipEntry e = createZipEntry(((flag & EFS) != 0)
58.301 + ? zc.toStringUTF8(b, len)
58.302 + : zc.toString(b, len));
58.303 + // now get the remaining fields for the entry
58.304 + if ((flag & 1) == 1) {
58.305 + throw new ZipException("encrypted ZIP entry not supported");
58.306 + }
58.307 + e.method = get16(tmpbuf, LOCHOW);
58.308 + e.time = get32(tmpbuf, LOCTIM);
58.309 + if ((flag & 8) == 8) {
58.310 + /* "Data Descriptor" present */
58.311 + if (e.method != DEFLATED) {
58.312 + throw new ZipException(
58.313 + "only DEFLATED entries can have EXT descriptor");
58.314 + }
58.315 + } else {
58.316 + e.crc = get32(tmpbuf, LOCCRC);
58.317 + e.csize = get32(tmpbuf, LOCSIZ);
58.318 + e.size = get32(tmpbuf, LOCLEN);
58.319 + }
58.320 + len = get16(tmpbuf, LOCEXT);
58.321 + if (len > 0) {
58.322 + byte[] bb = new byte[len];
58.323 + readFully(bb, 0, len);
58.324 + e.setExtra(bb);
58.325 + // extra fields are in "HeaderID(2)DataSize(2)Data... format
58.326 + if (e.csize == ZIP64_MAGICVAL || e.size == ZIP64_MAGICVAL) {
58.327 + int off = 0;
58.328 + while (off + 4 < len) {
58.329 + int sz = get16(bb, off + 2);
58.330 + if (get16(bb, off) == ZIP64_EXTID) {
58.331 + off += 4;
58.332 + // LOC extra zip64 entry MUST include BOTH original and
58.333 + // compressed file size fields
58.334 + if (sz < 16 || (off + sz) > len ) {
58.335 + // Invalid zip64 extra fields, simply skip. Even it's
58.336 + // rare, it's possible the entry size happens to be
58.337 + // the magic value and it "accidnetly" has some bytes
58.338 + // in extra match the id.
58.339 + return e;
58.340 + }
58.341 + e.size = get64(bb, off);
58.342 + e.csize = get64(bb, off + 8);
58.343 + break;
58.344 + }
58.345 + off += (sz + 4);
58.346 + }
58.347 + }
58.348 + }
58.349 + return e;
58.350 + }
58.351 +
58.352 + /**
58.353 + * Creates a new <code>ZipEntry</code> object for the specified
58.354 + * entry name.
58.355 + *
58.356 + * @param name the ZIP file entry name
58.357 + * @return the ZipEntry just created
58.358 + */
58.359 + protected ZipEntry createZipEntry(String name) {
58.360 + return new ZipEntry(name);
58.361 + }
58.362 +
58.363 + /*
58.364 + * Reads end of deflated entry as well as EXT descriptor if present.
58.365 + */
58.366 + private void readEnd(ZipEntry e) throws IOException {
58.367 + int n = inf.getRemaining();
58.368 + if (n > 0) {
58.369 + ((PushbackInputStream)in).unread(buf, len - n, n);
58.370 + }
58.371 + if ((flag & 8) == 8) {
58.372 + /* "Data Descriptor" present */
58.373 + if (inf.getBytesWritten() > ZIP64_MAGICVAL ||
58.374 + inf.getBytesRead() > ZIP64_MAGICVAL) {
58.375 + // ZIP64 format
58.376 + readFully(tmpbuf, 0, ZIP64_EXTHDR);
58.377 + long sig = get32(tmpbuf, 0);
58.378 + if (sig != EXTSIG) { // no EXTSIG present
58.379 + e.crc = sig;
58.380 + e.csize = get64(tmpbuf, ZIP64_EXTSIZ - ZIP64_EXTCRC);
58.381 + e.size = get64(tmpbuf, ZIP64_EXTLEN - ZIP64_EXTCRC);
58.382 + ((PushbackInputStream)in).unread(
58.383 + tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC - 1, ZIP64_EXTCRC);
58.384 + } else {
58.385 + e.crc = get32(tmpbuf, ZIP64_EXTCRC);
58.386 + e.csize = get64(tmpbuf, ZIP64_EXTSIZ);
58.387 + e.size = get64(tmpbuf, ZIP64_EXTLEN);
58.388 + }
58.389 + } else {
58.390 + readFully(tmpbuf, 0, EXTHDR);
58.391 + long sig = get32(tmpbuf, 0);
58.392 + if (sig != EXTSIG) { // no EXTSIG present
58.393 + e.crc = sig;
58.394 + e.csize = get32(tmpbuf, EXTSIZ - EXTCRC);
58.395 + e.size = get32(tmpbuf, EXTLEN - EXTCRC);
58.396 + ((PushbackInputStream)in).unread(
58.397 + tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC);
58.398 + } else {
58.399 + e.crc = get32(tmpbuf, EXTCRC);
58.400 + e.csize = get32(tmpbuf, EXTSIZ);
58.401 + e.size = get32(tmpbuf, EXTLEN);
58.402 + }
58.403 + }
58.404 + }
58.405 + if (e.size != inf.getBytesWritten()) {
58.406 + throw new ZipException(
58.407 + "invalid entry size (expected " + e.size +
58.408 + " but got " + inf.getBytesWritten() + " bytes)");
58.409 + }
58.410 + if (e.csize != inf.getBytesRead()) {
58.411 + throw new ZipException(
58.412 + "invalid entry compressed size (expected " + e.csize +
58.413 + " but got " + inf.getBytesRead() + " bytes)");
58.414 + }
58.415 + if (e.crc != crc.getValue()) {
58.416 + throw new ZipException(
58.417 + "invalid entry CRC (expected 0x" + Long.toHexString(e.crc) +
58.418 + " but got 0x" + Long.toHexString(crc.getValue()) + ")");
58.419 + }
58.420 + }
58.421 +
58.422 + /*
58.423 + * Reads bytes, blocking until all bytes are read.
58.424 + */
58.425 + private void readFully(byte[] b, int off, int len) throws IOException {
58.426 + while (len > 0) {
58.427 + int n = in.read(b, off, len);
58.428 + if (n == -1) {
58.429 + throw new EOFException();
58.430 + }
58.431 + off += n;
58.432 + len -= n;
58.433 + }
58.434 + }
58.435 +
58.436 + /*
58.437 + * Fetches unsigned 16-bit value from byte array at specified offset.
58.438 + * The bytes are assumed to be in Intel (little-endian) byte order.
58.439 + */
58.440 + private static final int get16(byte b[], int off) {
58.441 + return (b[off] & 0xff) | ((b[off+1] & 0xff) << 8);
58.442 + }
58.443 +
58.444 + /*
58.445 + * Fetches unsigned 32-bit value from byte array at specified offset.
58.446 + * The bytes are assumed to be in Intel (little-endian) byte order.
58.447 + */
58.448 + private static final long get32(byte b[], int off) {
58.449 + return (get16(b, off) | ((long)get16(b, off+2) << 16)) & 0xffffffffL;
58.450 + }
58.451 +
58.452 + /*
58.453 + * Fetches signed 64-bit value from byte array at specified offset.
58.454 + * The bytes are assumed to be in Intel (little-endian) byte order.
58.455 + */
58.456 + private static final long get64(byte b[], int off) {
58.457 + return get32(b, off) | (get32(b, off+4) << 32);
58.458 + }
58.459 +}
59.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
59.2 +++ b/emul/mini/src/main/java/java/util/zip/package.html Fri Feb 01 16:35:42 2013 +0100
59.3 @@ -0,0 +1,98 @@
59.4 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
59.5 +<html>
59.6 +<head>
59.7 +<!--
59.8 +Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
59.9 +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
59.10 +
59.11 +This code is free software; you can redistribute it and/or modify it
59.12 +under the terms of the GNU General Public License version 2 only, as
59.13 +published by the Free Software Foundation. Oracle designates this
59.14 +particular file as subject to the "Classpath" exception as provided
59.15 +by Oracle in the LICENSE file that accompanied this code.
59.16 +
59.17 +This code is distributed in the hope that it will be useful, but WITHOUT
59.18 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
59.19 +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
59.20 +version 2 for more details (a copy is included in the LICENSE file that
59.21 +accompanied this code).
59.22 +
59.23 +You should have received a copy of the GNU General Public License version
59.24 +2 along with this work; if not, write to the Free Software Foundation,
59.25 +Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
59.26 +
59.27 +Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
59.28 +or visit www.oracle.com if you need additional information or have any
59.29 +questions.
59.30 +-->
59.31 +
59.32 +</head>
59.33 +<body bgcolor="white">
59.34 +
59.35 +Provides classes for reading and writing the standard ZIP and GZIP
59.36 +file formats. Also includes classes for compressing and decompressing
59.37 +data using the DEFLATE compression algorithm, which is used by the
59.38 +ZIP and GZIP file formats. Additionally, there are utility classes
59.39 +for computing the CRC-32 and Adler-32 checksums of arbitrary
59.40 +input streams.
59.41 +
59.42 +
59.43 +<h2>Package Specification</h2>
59.44 +
59.45 +</a>
59.46 +<ul>
59.47 + <li><a href="ftp://ftp.uu.net/pub/archiving/zip/doc/appnote-970311-iz.zip">
59.48 + Info-ZIP Application Note 970311
59.49 + </a> - a detailed description of the Info-ZIP format upon which
59.50 + the <code>java.util.zip</code> classes are based.
59.51 +<p>
59.52 + <a name="zip64">
59.53 + <li>An implementation may optionally support the ZIP64(tm) format extensions
59.54 + defined by the
59.55 + <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">
59.56 + PKWARE ZIP File Format Specification</a>. The ZIP64(tm) format extensions
59.57 + are used to overcome the size limitations of the original ZIP format.
59.58 +<p>
59.59 + <a name="lang_encoding">
59.60 + <li>APPENDIX D of <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">
59.61 + PKWARE ZIP File Format Specification</a> - Language Encoding Flag (EFS) to
59.62 + encode ZIP entry filename and comment fields using UTF-8.
59.63 +<p>
59.64 + <li><a href="http://www.ietf.org/rfc/rfc1950.txt">
59.65 + ZLIB Compressed Data Format Specification version 3.3</a>
59.66 +
59.67 + <a href="http://www.ietf.org/rfc/rfc1950.txt.pdf">(pdf)</a>
59.68 + (RFC 1950)
59.69 +<p>
59.70 + <li><a href="http://www.ietf.org/rfc/rfc1951.txt">
59.71 + DEFLATE Compressed Data Format Specification version 1.3</a>
59.72 +
59.73 + <a href="http://www.ietf.org/rfc/rfc1951.txt.pdf">(pdf)</a>
59.74 + (RFC 1951)
59.75 +<p>
59.76 + <li><a href="http://www.ietf.org/rfc/rfc1952.txt">
59.77 + GZIP file format specification version 4.3</a>
59.78 +
59.79 + <a href="http://www.ietf.org/rfc/rfc1952.txt.pdf">(pdf)</a>
59.80 + (RFC 1952)
59.81 +<p>
59.82 + <li>CRC-32 checksum is described in RFC 1952 (above)
59.83 +<p>
59.84 + <li>Adler-32 checksum is described in RFC 1950 (above)
59.85 +</ul>
59.86 +
59.87 +
59.88 +<!--
59.89 +<h2>Related Documentation</h2>
59.90 +
59.91 +For overviews, tutorials, examples, guides, and tool documentation, please see:
59.92 +<ul>
59.93 + <li><a href="">##### REFER TO NON-SPEC DOCUMENTATION HERE #####</a>
59.94 +</ul>
59.95 +-->
59.96 +
59.97 +@since JDK1.1
59.98 +</body>
59.99 +</html>
59.100 +
59.101 +