1.1 --- a/core/pom.xml Tue Feb 05 16:40:01 2013 +0100
1.2 +++ b/core/pom.xml Tue Feb 05 17:04:22 2013 +0100
1.3 @@ -38,6 +38,7 @@
1.4 <dependency>
1.5 <groupId>org.netbeans.api</groupId>
1.6 <artifactId>org-openide-util-lookup</artifactId>
1.7 + <scope>provided</scope>
1.8 </dependency>
1.9 </dependencies>
1.10 <description>Contains esential annotations for associating JavaScript code with
2.1 --- a/emul/compact/pom.xml Tue Feb 05 16:40:01 2013 +0100
2.2 +++ b/emul/compact/pom.xml Tue Feb 05 17:04:22 2013 +0100
2.3 @@ -27,6 +27,11 @@
2.4 <version>${project.version}</version>
2.5 <scope>test</scope>
2.6 </dependency>
2.7 + <dependency>
2.8 + <groupId>org.netbeans.api</groupId>
2.9 + <artifactId>org-openide-util-lookup</artifactId>
2.10 + <scope>test</scope>
2.11 + </dependency>
2.12 </dependencies>
2.13 <build>
2.14 <plugins>
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/emul/compact/src/main/java/java/beans/ChangeListenerMap.java Tue Feb 05 17:04:22 2013 +0100
3.3 @@ -0,0 +1,248 @@
3.4 +/*
3.5 + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3.7 + *
3.8 + * This code is free software; you can redistribute it and/or modify it
3.9 + * under the terms of the GNU General Public License version 2 only, as
3.10 + * published by the Free Software Foundation. Oracle designates this
3.11 + * particular file as subject to the "Classpath" exception as provided
3.12 + * by Oracle in the LICENSE file that accompanied this code.
3.13 + *
3.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
3.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
3.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
3.17 + * version 2 for more details (a copy is included in the LICENSE file that
3.18 + * accompanied this code).
3.19 + *
3.20 + * You should have received a copy of the GNU General Public License version
3.21 + * 2 along with this work; if not, write to the Free Software Foundation,
3.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
3.23 + *
3.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
3.25 + * or visit www.oracle.com if you need additional information or have any
3.26 + * questions.
3.27 + */
3.28 +package java.beans;
3.29 +
3.30 +import java.util.ArrayList;
3.31 +import java.util.Collections;
3.32 +import java.util.EventListener;
3.33 +import java.util.EventListenerProxy;
3.34 +import java.util.HashMap;
3.35 +import java.util.List;
3.36 +import java.util.Map;
3.37 +import java.util.Map.Entry;
3.38 +import java.util.Set;
3.39 +import org.apidesign.bck2brwsr.emul.lang.System;
3.40 +
3.41 +/**
3.42 + * This is an abstract class that provides base functionality
3.43 + * for the {@link PropertyChangeSupport PropertyChangeSupport} class
3.44 + * and the {@link VetoableChangeSupport VetoableChangeSupport} class.
3.45 + *
3.46 + * @see PropertyChangeListenerMap
3.47 + * @see VetoableChangeListenerMap
3.48 + *
3.49 + * @author Sergey A. Malenkov
3.50 + */
3.51 +abstract class ChangeListenerMap<L extends EventListener> {
3.52 + private Map<String, L[]> map;
3.53 +
3.54 + /**
3.55 + * Creates an array of listeners.
3.56 + * This method can be optimized by using
3.57 + * the same instance of the empty array
3.58 + * when {@code length} is equal to {@code 0}.
3.59 + *
3.60 + * @param length the array length
3.61 + * @return an array with specified length
3.62 + */
3.63 + protected abstract L[] newArray(int length);
3.64 +
3.65 + /**
3.66 + * Creates a proxy listener for the specified property.
3.67 + *
3.68 + * @param name the name of the property to listen on
3.69 + * @param listener the listener to process events
3.70 + * @return a proxy listener
3.71 + */
3.72 + protected abstract L newProxy(String name, L listener);
3.73 +
3.74 + /**
3.75 + * Adds a listener to the list of listeners for the specified property.
3.76 + * This listener is called as many times as it was added.
3.77 + *
3.78 + * @param name the name of the property to listen on
3.79 + * @param listener the listener to process events
3.80 + */
3.81 + public final synchronized void add(String name, L listener) {
3.82 + if (this.map == null) {
3.83 + this.map = new HashMap<String, L[]>();
3.84 + }
3.85 + L[] array = this.map.get(name);
3.86 + int size = (array != null)
3.87 + ? array.length
3.88 + : 0;
3.89 +
3.90 + L[] clone = newArray(size + 1);
3.91 + clone[size] = listener;
3.92 + if (array != null) {
3.93 + System.arraycopy(array, 0, clone, 0, size);
3.94 + }
3.95 + this.map.put(name, clone);
3.96 + }
3.97 +
3.98 + /**
3.99 + * Removes a listener from the list of listeners for the specified property.
3.100 + * If the listener was added more than once to the same event source,
3.101 + * this listener will be notified one less time after being removed.
3.102 + *
3.103 + * @param name the name of the property to listen on
3.104 + * @param listener the listener to process events
3.105 + */
3.106 + public final synchronized void remove(String name, L listener) {
3.107 + if (this.map != null) {
3.108 + L[] array = this.map.get(name);
3.109 + if (array != null) {
3.110 + for (int i = 0; i < array.length; i++) {
3.111 + if (listener.equals(array[i])) {
3.112 + int size = array.length - 1;
3.113 + if (size > 0) {
3.114 + L[] clone = newArray(size);
3.115 + System.arraycopy(array, 0, clone, 0, i);
3.116 + System.arraycopy(array, i + 1, clone, i, size - i);
3.117 + this.map.put(name, clone);
3.118 + }
3.119 + else {
3.120 + this.map.remove(name);
3.121 + if (this.map.isEmpty()) {
3.122 + this.map = null;
3.123 + }
3.124 + }
3.125 + break;
3.126 + }
3.127 + }
3.128 + }
3.129 + }
3.130 + }
3.131 +
3.132 + /**
3.133 + * Returns the list of listeners for the specified property.
3.134 + *
3.135 + * @param name the name of the property
3.136 + * @return the corresponding list of listeners
3.137 + */
3.138 + public final synchronized L[] get(String name) {
3.139 + return (this.map != null)
3.140 + ? this.map.get(name)
3.141 + : null;
3.142 + }
3.143 +
3.144 + /**
3.145 + * Sets new list of listeners for the specified property.
3.146 + *
3.147 + * @param name the name of the property
3.148 + * @param listeners new list of listeners
3.149 + */
3.150 + public final void set(String name, L[] listeners) {
3.151 + if (listeners != null) {
3.152 + if (this.map == null) {
3.153 + this.map = new HashMap<String, L[]>();
3.154 + }
3.155 + this.map.put(name, listeners);
3.156 + }
3.157 + else if (this.map != null) {
3.158 + this.map.remove(name);
3.159 + if (this.map.isEmpty()) {
3.160 + this.map = null;
3.161 + }
3.162 + }
3.163 + }
3.164 +
3.165 + /**
3.166 + * Returns all listeners in the map.
3.167 + *
3.168 + * @return an array of all listeners
3.169 + */
3.170 + public final synchronized L[] getListeners() {
3.171 + if (this.map == null) {
3.172 + return newArray(0);
3.173 + }
3.174 + List<L> list = new ArrayList<L>();
3.175 +
3.176 + L[] listeners = this.map.get(null);
3.177 + if (listeners != null) {
3.178 + for (L listener : listeners) {
3.179 + list.add(listener);
3.180 + }
3.181 + }
3.182 + for (Entry<String, L[]> entry : this.map.entrySet()) {
3.183 + String name = entry.getKey();
3.184 + if (name != null) {
3.185 + for (L listener : entry.getValue()) {
3.186 + list.add(newProxy(name, listener));
3.187 + }
3.188 + }
3.189 + }
3.190 + return list.toArray(newArray(list.size()));
3.191 + }
3.192 +
3.193 + /**
3.194 + * Returns listeners that have been associated with the named property.
3.195 + *
3.196 + * @param name the name of the property
3.197 + * @return an array of listeners for the named property
3.198 + */
3.199 + public final L[] getListeners(String name) {
3.200 + if (name != null) {
3.201 + L[] listeners = get(name);
3.202 + if (listeners != null) {
3.203 + return listeners.clone();
3.204 + }
3.205 + }
3.206 + return newArray(0);
3.207 + }
3.208 +
3.209 + /**
3.210 + * Indicates whether the map contains
3.211 + * at least one listener to be notified.
3.212 + *
3.213 + * @param name the name of the property
3.214 + * @return {@code true} if at least one listener exists or
3.215 + * {@code false} otherwise
3.216 + */
3.217 + public final synchronized boolean hasListeners(String name) {
3.218 + if (this.map == null) {
3.219 + return false;
3.220 + }
3.221 + L[] array = this.map.get(null);
3.222 + return (array != null) || ((name != null) && (null != this.map.get(name)));
3.223 + }
3.224 +
3.225 + /**
3.226 + * Returns a set of entries from the map.
3.227 + * Each entry is a pair consisted of the property name
3.228 + * and the corresponding list of listeners.
3.229 + *
3.230 + * @return a set of entries from the map
3.231 + */
3.232 + public final Set<Entry<String, L[]>> getEntries() {
3.233 + return (this.map != null)
3.234 + ? this.map.entrySet()
3.235 + : Collections.<Entry<String, L[]>>emptySet();
3.236 + }
3.237 +
3.238 + /**
3.239 + * Extracts a real listener from the proxy listener.
3.240 + * It is necessary because default proxy class is not serializable.
3.241 + *
3.242 + * @return a real listener
3.243 + */
3.244 + public final L extract(L listener) {
3.245 + while (listener instanceof EventListenerProxy) {
3.246 + EventListenerProxy<L> proxy = (EventListenerProxy<L>) listener;
3.247 + listener = proxy.getListener();
3.248 + }
3.249 + return listener;
3.250 + }
3.251 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/emul/compact/src/main/java/java/beans/IndexedPropertyChangeEvent.java Tue Feb 05 17:04:22 2013 +0100
4.3 @@ -0,0 +1,78 @@
4.4 +/*
4.5 + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4.7 + *
4.8 + * This code is free software; you can redistribute it and/or modify it
4.9 + * under the terms of the GNU General Public License version 2 only, as
4.10 + * published by the Free Software Foundation. Oracle designates this
4.11 + * particular file as subject to the "Classpath" exception as provided
4.12 + * by Oracle in the LICENSE file that accompanied this code.
4.13 + *
4.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
4.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
4.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
4.17 + * version 2 for more details (a copy is included in the LICENSE file that
4.18 + * accompanied this code).
4.19 + *
4.20 + * You should have received a copy of the GNU General Public License version
4.21 + * 2 along with this work; if not, write to the Free Software Foundation,
4.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
4.23 + *
4.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
4.25 + * or visit www.oracle.com if you need additional information or have any
4.26 + * questions.
4.27 + */
4.28 +package java.beans;
4.29 +
4.30 +/**
4.31 + * An "IndexedPropertyChange" event gets delivered whenever a component that
4.32 + * conforms to the JavaBeans™ specification (a "bean") changes a bound
4.33 + * indexed property. This class is an extension of <code>PropertyChangeEvent</code>
4.34 + * but contains the index of the property that has changed.
4.35 + * <P>
4.36 + * Null values may be provided for the old and the new values if their
4.37 + * true values are not known.
4.38 + * <P>
4.39 + * An event source may send a null object as the name to indicate that an
4.40 + * arbitrary set of if its properties have changed. In this case the
4.41 + * old and new values should also be null.
4.42 + *
4.43 + * @since 1.5
4.44 + * @author Mark Davidson
4.45 + */
4.46 +public class IndexedPropertyChangeEvent extends PropertyChangeEvent {
4.47 + private static final long serialVersionUID = -320227448495806870L;
4.48 +
4.49 + private int index;
4.50 +
4.51 + /**
4.52 + * Constructs a new <code>IndexedPropertyChangeEvent</code> object.
4.53 + *
4.54 + * @param source The bean that fired the event.
4.55 + * @param propertyName The programmatic name of the property that
4.56 + * was changed.
4.57 + * @param oldValue The old value of the property.
4.58 + * @param newValue The new value of the property.
4.59 + * @param index index of the property element that was changed.
4.60 + */
4.61 + public IndexedPropertyChangeEvent(Object source, String propertyName,
4.62 + Object oldValue, Object newValue,
4.63 + int index) {
4.64 + super (source, propertyName, oldValue, newValue);
4.65 + this.index = index;
4.66 + }
4.67 +
4.68 + /**
4.69 + * Gets the index of the property that was changed.
4.70 + *
4.71 + * @return The index specifying the property element that was
4.72 + * changed.
4.73 + */
4.74 + public int getIndex() {
4.75 + return index;
4.76 + }
4.77 +
4.78 + void appendTo(StringBuilder sb) {
4.79 + sb.append("; index=").append(getIndex());
4.80 + }
4.81 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/emul/compact/src/main/java/java/beans/PropertyChangeEvent.java Tue Feb 05 17:04:22 2013 +0100
5.3 @@ -0,0 +1,164 @@
5.4 +/*
5.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5.7 + *
5.8 + * This code is free software; you can redistribute it and/or modify it
5.9 + * under the terms of the GNU General Public License version 2 only, as
5.10 + * published by the Free Software Foundation. Oracle designates this
5.11 + * particular file as subject to the "Classpath" exception as provided
5.12 + * by Oracle in the LICENSE file that accompanied this code.
5.13 + *
5.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
5.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
5.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
5.17 + * version 2 for more details (a copy is included in the LICENSE file that
5.18 + * accompanied this code).
5.19 + *
5.20 + * You should have received a copy of the GNU General Public License version
5.21 + * 2 along with this work; if not, write to the Free Software Foundation,
5.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
5.23 + *
5.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
5.25 + * or visit www.oracle.com if you need additional information or have any
5.26 + * questions.
5.27 + */
5.28 +
5.29 +package java.beans;
5.30 +
5.31 +/**
5.32 + * A "PropertyChange" event gets delivered whenever a bean changes a "bound"
5.33 + * or "constrained" property. A PropertyChangeEvent object is sent as an
5.34 + * argument to the PropertyChangeListener and VetoableChangeListener methods.
5.35 + * <P>
5.36 + * Normally PropertyChangeEvents are accompanied by the name and the old
5.37 + * and new value of the changed property. If the new value is a primitive
5.38 + * type (such as int or boolean) it must be wrapped as the
5.39 + * corresponding java.lang.* Object type (such as Integer or Boolean).
5.40 + * <P>
5.41 + * Null values may be provided for the old and the new values if their
5.42 + * true values are not known.
5.43 + * <P>
5.44 + * An event source may send a null object as the name to indicate that an
5.45 + * arbitrary set of if its properties have changed. In this case the
5.46 + * old and new values should also be null.
5.47 + */
5.48 +
5.49 +public class PropertyChangeEvent extends java.util.EventObject {
5.50 + private static final long serialVersionUID = 7042693688939648123L;
5.51 +
5.52 + /**
5.53 + * Constructs a new <code>PropertyChangeEvent</code>.
5.54 + *
5.55 + * @param source The bean that fired the event.
5.56 + * @param propertyName The programmatic name of the property
5.57 + * that was changed.
5.58 + * @param oldValue The old value of the property.
5.59 + * @param newValue The new value of the property.
5.60 + */
5.61 + public PropertyChangeEvent(Object source, String propertyName,
5.62 + Object oldValue, Object newValue) {
5.63 + super(source);
5.64 + this.propertyName = propertyName;
5.65 + this.newValue = newValue;
5.66 + this.oldValue = oldValue;
5.67 + }
5.68 +
5.69 + /**
5.70 + * Gets the programmatic name of the property that was changed.
5.71 + *
5.72 + * @return The programmatic name of the property that was changed.
5.73 + * May be null if multiple properties have changed.
5.74 + */
5.75 + public String getPropertyName() {
5.76 + return propertyName;
5.77 + }
5.78 +
5.79 + /**
5.80 + * Gets the new value for the property, expressed as an Object.
5.81 + *
5.82 + * @return The new value for the property, expressed as an Object.
5.83 + * May be null if multiple properties have changed.
5.84 + */
5.85 + public Object getNewValue() {
5.86 + return newValue;
5.87 + }
5.88 +
5.89 + /**
5.90 + * Gets the old value for the property, expressed as an Object.
5.91 + *
5.92 + * @return The old value for the property, expressed as an Object.
5.93 + * May be null if multiple properties have changed.
5.94 + */
5.95 + public Object getOldValue() {
5.96 + return oldValue;
5.97 + }
5.98 +
5.99 + /**
5.100 + * Sets the propagationId object for the event.
5.101 + *
5.102 + * @param propagationId The propagationId object for the event.
5.103 + */
5.104 + public void setPropagationId(Object propagationId) {
5.105 + this.propagationId = propagationId;
5.106 + }
5.107 +
5.108 + /**
5.109 + * The "propagationId" field is reserved for future use. In Beans 1.0
5.110 + * the sole requirement is that if a listener catches a PropertyChangeEvent
5.111 + * and then fires a PropertyChangeEvent of its own, then it should
5.112 + * make sure that it propagates the propagationId field from its
5.113 + * incoming event to its outgoing event.
5.114 + *
5.115 + * @return the propagationId object associated with a bound/constrained
5.116 + * property update.
5.117 + */
5.118 + public Object getPropagationId() {
5.119 + return propagationId;
5.120 + }
5.121 +
5.122 + /**
5.123 + * name of the property that changed. May be null, if not known.
5.124 + * @serial
5.125 + */
5.126 + private String propertyName;
5.127 +
5.128 + /**
5.129 + * New value for property. May be null if not known.
5.130 + * @serial
5.131 + */
5.132 + private Object newValue;
5.133 +
5.134 + /**
5.135 + * Previous value for property. May be null if not known.
5.136 + * @serial
5.137 + */
5.138 + private Object oldValue;
5.139 +
5.140 + /**
5.141 + * Propagation ID. May be null.
5.142 + * @serial
5.143 + * @see #getPropagationId
5.144 + */
5.145 + private Object propagationId;
5.146 +
5.147 + /**
5.148 + * Returns a string representation of the object.
5.149 + *
5.150 + * @return a string representation of the object
5.151 + *
5.152 + * @since 1.7
5.153 + */
5.154 + public String toString() {
5.155 + StringBuilder sb = new StringBuilder(getClass().getName());
5.156 + sb.append("[propertyName=").append(getPropertyName());
5.157 + appendTo(sb);
5.158 + sb.append("; oldValue=").append(getOldValue());
5.159 + sb.append("; newValue=").append(getNewValue());
5.160 + sb.append("; propagationId=").append(getPropagationId());
5.161 + sb.append("; source=").append(getSource());
5.162 + return sb.append("]").toString();
5.163 + }
5.164 +
5.165 + void appendTo(StringBuilder sb) {
5.166 + }
5.167 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/emul/compact/src/main/java/java/beans/PropertyChangeListener.java Tue Feb 05 17:04:22 2013 +0100
6.3 @@ -0,0 +1,44 @@
6.4 +/*
6.5 + * Copyright (c) 1996, Oracle and/or its affiliates. All rights reserved.
6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6.7 + *
6.8 + * This code is free software; you can redistribute it and/or modify it
6.9 + * under the terms of the GNU General Public License version 2 only, as
6.10 + * published by the Free Software Foundation. Oracle designates this
6.11 + * particular file as subject to the "Classpath" exception as provided
6.12 + * by Oracle in the LICENSE file that accompanied this code.
6.13 + *
6.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
6.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
6.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
6.17 + * version 2 for more details (a copy is included in the LICENSE file that
6.18 + * accompanied this code).
6.19 + *
6.20 + * You should have received a copy of the GNU General Public License version
6.21 + * 2 along with this work; if not, write to the Free Software Foundation,
6.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
6.23 + *
6.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
6.25 + * or visit www.oracle.com if you need additional information or have any
6.26 + * questions.
6.27 + */
6.28 +
6.29 +package java.beans;
6.30 +
6.31 +/**
6.32 + * A "PropertyChange" event gets fired whenever a bean changes a "bound"
6.33 + * property. You can register a PropertyChangeListener with a source
6.34 + * bean so as to be notified of any bound property updates.
6.35 + */
6.36 +
6.37 +public interface PropertyChangeListener extends java.util.EventListener {
6.38 +
6.39 + /**
6.40 + * This method gets called when a bound property is changed.
6.41 + * @param evt A PropertyChangeEvent object describing the event source
6.42 + * and the property that has changed.
6.43 + */
6.44 +
6.45 + void propertyChange(PropertyChangeEvent evt);
6.46 +
6.47 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/emul/compact/src/main/java/java/beans/PropertyChangeListenerProxy.java Tue Feb 05 17:04:22 2013 +0100
7.3 @@ -0,0 +1,81 @@
7.4 +/*
7.5 + * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
7.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7.7 + *
7.8 + * This code is free software; you can redistribute it and/or modify it
7.9 + * under the terms of the GNU General Public License version 2 only, as
7.10 + * published by the Free Software Foundation. Oracle designates this
7.11 + * particular file as subject to the "Classpath" exception as provided
7.12 + * by Oracle in the LICENSE file that accompanied this code.
7.13 + *
7.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
7.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7.17 + * version 2 for more details (a copy is included in the LICENSE file that
7.18 + * accompanied this code).
7.19 + *
7.20 + * You should have received a copy of the GNU General Public License version
7.21 + * 2 along with this work; if not, write to the Free Software Foundation,
7.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7.23 + *
7.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7.25 + * or visit www.oracle.com if you need additional information or have any
7.26 + * questions.
7.27 + */
7.28 +
7.29 +package java.beans;
7.30 +
7.31 +import java.util.EventListenerProxy;
7.32 +
7.33 +/**
7.34 + * A class which extends the {@code EventListenerProxy}
7.35 + * specifically for adding a {@code PropertyChangeListener}
7.36 + * with a "bound" property.
7.37 + * Instances of this class can be added
7.38 + * as {@code PropertyChangeListener}s to a bean
7.39 + * which supports firing property change events.
7.40 + * <p>
7.41 + * If the object has a {@code getPropertyChangeListeners} method
7.42 + * then the array returned could be a mixture of {@code PropertyChangeListener}
7.43 + * and {@code PropertyChangeListenerProxy} objects.
7.44 + *
7.45 + * @see java.util.EventListenerProxy
7.46 + * @see PropertyChangeSupport#getPropertyChangeListeners
7.47 + * @since 1.4
7.48 + */
7.49 +public class PropertyChangeListenerProxy
7.50 + extends EventListenerProxy<PropertyChangeListener>
7.51 + implements PropertyChangeListener {
7.52 +
7.53 + private final String propertyName;
7.54 +
7.55 + /**
7.56 + * Constructor which binds the {@code PropertyChangeListener}
7.57 + * to a specific property.
7.58 + *
7.59 + * @param propertyName the name of the property to listen on
7.60 + * @param listener the listener object
7.61 + */
7.62 + public PropertyChangeListenerProxy(String propertyName, PropertyChangeListener listener) {
7.63 + super(listener);
7.64 + this.propertyName = propertyName;
7.65 + }
7.66 +
7.67 + /**
7.68 + * Forwards the property change event to the listener delegate.
7.69 + *
7.70 + * @param event the property change event
7.71 + */
7.72 + public void propertyChange(PropertyChangeEvent event) {
7.73 + getListener().propertyChange(event);
7.74 + }
7.75 +
7.76 + /**
7.77 + * Returns the name of the named property associated with the listener.
7.78 + *
7.79 + * @return the name of the named property associated with the listener
7.80 + */
7.81 + public String getPropertyName() {
7.82 + return this.propertyName;
7.83 + }
7.84 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/emul/compact/src/main/java/java/beans/PropertyChangeSupport.java Tue Feb 05 17:04:22 2013 +0100
8.3 @@ -0,0 +1,536 @@
8.4 +/*
8.5 + * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
8.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8.7 + *
8.8 + * This code is free software; you can redistribute it and/or modify it
8.9 + * under the terms of the GNU General Public License version 2 only, as
8.10 + * published by the Free Software Foundation. Oracle designates this
8.11 + * particular file as subject to the "Classpath" exception as provided
8.12 + * by Oracle in the LICENSE file that accompanied this code.
8.13 + *
8.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
8.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
8.17 + * version 2 for more details (a copy is included in the LICENSE file that
8.18 + * accompanied this code).
8.19 + *
8.20 + * You should have received a copy of the GNU General Public License version
8.21 + * 2 along with this work; if not, write to the Free Software Foundation,
8.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
8.23 + *
8.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
8.25 + * or visit www.oracle.com if you need additional information or have any
8.26 + * questions.
8.27 + */
8.28 +package java.beans;
8.29 +
8.30 +import java.io.Serializable;
8.31 +import java.io.ObjectStreamField;
8.32 +import java.io.ObjectOutputStream;
8.33 +import java.io.ObjectInputStream;
8.34 +import java.io.IOException;
8.35 +import java.util.Hashtable;
8.36 +import java.util.Map.Entry;
8.37 +
8.38 +/**
8.39 + * This is a utility class that can be used by beans that support bound
8.40 + * properties. It manages a list of listeners and dispatches
8.41 + * {@link PropertyChangeEvent}s to them. You can use an instance of this class
8.42 + * as a member field of your bean and delegate these types of work to it.
8.43 + * The {@link PropertyChangeListener} can be registered for all properties
8.44 + * or for a property specified by name.
8.45 + * <p>
8.46 + * Here is an example of {@code PropertyChangeSupport} usage that follows
8.47 + * the rules and recommendations laid out in the JavaBeans™ specification:
8.48 + * <pre>
8.49 + * public class MyBean {
8.50 + * private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
8.51 + *
8.52 + * public void addPropertyChangeListener(PropertyChangeListener listener) {
8.53 + * this.pcs.addPropertyChangeListener(listener);
8.54 + * }
8.55 + *
8.56 + * public void removePropertyChangeListener(PropertyChangeListener listener) {
8.57 + * this.pcs.removePropertyChangeListener(listener);
8.58 + * }
8.59 + *
8.60 + * private String value;
8.61 + *
8.62 + * public String getValue() {
8.63 + * return this.value;
8.64 + * }
8.65 + *
8.66 + * public void setValue(String newValue) {
8.67 + * String oldValue = this.value;
8.68 + * this.value = newValue;
8.69 + * this.pcs.firePropertyChange("value", oldValue, newValue);
8.70 + * }
8.71 + *
8.72 + * [...]
8.73 + * }
8.74 + * </pre>
8.75 + * <p>
8.76 + * A {@code PropertyChangeSupport} instance is thread-safe.
8.77 + * <p>
8.78 + * This class is serializable. When it is serialized it will save
8.79 + * (and restore) any listeners that are themselves serializable. Any
8.80 + * non-serializable listeners will be skipped during serialization.
8.81 + *
8.82 + * @see VetoableChangeSupport
8.83 + */
8.84 +public class PropertyChangeSupport implements Serializable {
8.85 + private PropertyChangeListenerMap map = new PropertyChangeListenerMap();
8.86 +
8.87 + /**
8.88 + * Constructs a <code>PropertyChangeSupport</code> object.
8.89 + *
8.90 + * @param sourceBean The bean to be given as the source for any events.
8.91 + */
8.92 + public PropertyChangeSupport(Object sourceBean) {
8.93 + if (sourceBean == null) {
8.94 + throw new NullPointerException();
8.95 + }
8.96 + source = sourceBean;
8.97 + }
8.98 +
8.99 + /**
8.100 + * Add a PropertyChangeListener to the listener list.
8.101 + * The listener is registered for all properties.
8.102 + * The same listener object may be added more than once, and will be called
8.103 + * as many times as it is added.
8.104 + * If <code>listener</code> is null, no exception is thrown and no action
8.105 + * is taken.
8.106 + *
8.107 + * @param listener The PropertyChangeListener to be added
8.108 + */
8.109 + public void addPropertyChangeListener(PropertyChangeListener listener) {
8.110 + if (listener == null) {
8.111 + return;
8.112 + }
8.113 + if (listener instanceof PropertyChangeListenerProxy) {
8.114 + PropertyChangeListenerProxy proxy =
8.115 + (PropertyChangeListenerProxy)listener;
8.116 + // Call two argument add method.
8.117 + addPropertyChangeListener(proxy.getPropertyName(),
8.118 + proxy.getListener());
8.119 + } else {
8.120 + this.map.add(null, listener);
8.121 + }
8.122 + }
8.123 +
8.124 + /**
8.125 + * Remove a PropertyChangeListener from the listener list.
8.126 + * This removes a PropertyChangeListener that was registered
8.127 + * for all properties.
8.128 + * If <code>listener</code> was added more than once to the same event
8.129 + * source, it will be notified one less time after being removed.
8.130 + * If <code>listener</code> is null, or was never added, no exception is
8.131 + * thrown and no action is taken.
8.132 + *
8.133 + * @param listener The PropertyChangeListener to be removed
8.134 + */
8.135 + public void removePropertyChangeListener(PropertyChangeListener listener) {
8.136 + if (listener == null) {
8.137 + return;
8.138 + }
8.139 + if (listener instanceof PropertyChangeListenerProxy) {
8.140 + PropertyChangeListenerProxy proxy =
8.141 + (PropertyChangeListenerProxy)listener;
8.142 + // Call two argument remove method.
8.143 + removePropertyChangeListener(proxy.getPropertyName(),
8.144 + proxy.getListener());
8.145 + } else {
8.146 + this.map.remove(null, listener);
8.147 + }
8.148 + }
8.149 +
8.150 + /**
8.151 + * Returns an array of all the listeners that were added to the
8.152 + * PropertyChangeSupport object with addPropertyChangeListener().
8.153 + * <p>
8.154 + * If some listeners have been added with a named property, then
8.155 + * the returned array will be a mixture of PropertyChangeListeners
8.156 + * and <code>PropertyChangeListenerProxy</code>s. If the calling
8.157 + * method is interested in distinguishing the listeners then it must
8.158 + * test each element to see if it's a
8.159 + * <code>PropertyChangeListenerProxy</code>, perform the cast, and examine
8.160 + * the parameter.
8.161 + *
8.162 + * <pre>
8.163 + * PropertyChangeListener[] listeners = bean.getPropertyChangeListeners();
8.164 + * for (int i = 0; i < listeners.length; i++) {
8.165 + * if (listeners[i] instanceof PropertyChangeListenerProxy) {
8.166 + * PropertyChangeListenerProxy proxy =
8.167 + * (PropertyChangeListenerProxy)listeners[i];
8.168 + * if (proxy.getPropertyName().equals("foo")) {
8.169 + * // proxy is a PropertyChangeListener which was associated
8.170 + * // with the property named "foo"
8.171 + * }
8.172 + * }
8.173 + * }
8.174 + *</pre>
8.175 + *
8.176 + * @see PropertyChangeListenerProxy
8.177 + * @return all of the <code>PropertyChangeListeners</code> added or an
8.178 + * empty array if no listeners have been added
8.179 + * @since 1.4
8.180 + */
8.181 + public PropertyChangeListener[] getPropertyChangeListeners() {
8.182 + return this.map.getListeners();
8.183 + }
8.184 +
8.185 + /**
8.186 + * Add a PropertyChangeListener for a specific property. The listener
8.187 + * will be invoked only when a call on firePropertyChange names that
8.188 + * specific property.
8.189 + * The same listener object may be added more than once. For each
8.190 + * property, the listener will be invoked the number of times it was added
8.191 + * for that property.
8.192 + * If <code>propertyName</code> or <code>listener</code> is null, no
8.193 + * exception is thrown and no action is taken.
8.194 + *
8.195 + * @param propertyName The name of the property to listen on.
8.196 + * @param listener The PropertyChangeListener to be added
8.197 + */
8.198 + public void addPropertyChangeListener(
8.199 + String propertyName,
8.200 + PropertyChangeListener listener) {
8.201 + if (listener == null || propertyName == null) {
8.202 + return;
8.203 + }
8.204 + listener = this.map.extract(listener);
8.205 + if (listener != null) {
8.206 + this.map.add(propertyName, listener);
8.207 + }
8.208 + }
8.209 +
8.210 + /**
8.211 + * Remove a PropertyChangeListener for a specific property.
8.212 + * If <code>listener</code> was added more than once to the same event
8.213 + * source for the specified property, it will be notified one less time
8.214 + * after being removed.
8.215 + * If <code>propertyName</code> is null, no exception is thrown and no
8.216 + * action is taken.
8.217 + * If <code>listener</code> is null, or was never added for the specified
8.218 + * property, no exception is thrown and no action is taken.
8.219 + *
8.220 + * @param propertyName The name of the property that was listened on.
8.221 + * @param listener The PropertyChangeListener to be removed
8.222 + */
8.223 + public void removePropertyChangeListener(
8.224 + String propertyName,
8.225 + PropertyChangeListener listener) {
8.226 + if (listener == null || propertyName == null) {
8.227 + return;
8.228 + }
8.229 + listener = this.map.extract(listener);
8.230 + if (listener != null) {
8.231 + this.map.remove(propertyName, listener);
8.232 + }
8.233 + }
8.234 +
8.235 + /**
8.236 + * Returns an array of all the listeners which have been associated
8.237 + * with the named property.
8.238 + *
8.239 + * @param propertyName The name of the property being listened to
8.240 + * @return all of the <code>PropertyChangeListeners</code> associated with
8.241 + * the named property. If no such listeners have been added,
8.242 + * or if <code>propertyName</code> is null, an empty array is
8.243 + * returned.
8.244 + * @since 1.4
8.245 + */
8.246 + public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
8.247 + return this.map.getListeners(propertyName);
8.248 + }
8.249 +
8.250 + /**
8.251 + * Reports a bound property update to listeners
8.252 + * that have been registered to track updates of
8.253 + * all properties or a property with the specified name.
8.254 + * <p>
8.255 + * No event is fired if old and new values are equal and non-null.
8.256 + * <p>
8.257 + * This is merely a convenience wrapper around the more general
8.258 + * {@link #firePropertyChange(PropertyChangeEvent)} method.
8.259 + *
8.260 + * @param propertyName the programmatic name of the property that was changed
8.261 + * @param oldValue the old value of the property
8.262 + * @param newValue the new value of the property
8.263 + */
8.264 + public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
8.265 + if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
8.266 + firePropertyChange(new PropertyChangeEvent(this.source, propertyName, oldValue, newValue));
8.267 + }
8.268 + }
8.269 +
8.270 + /**
8.271 + * Reports an integer bound property update to listeners
8.272 + * that have been registered to track updates of
8.273 + * all properties or a property with the specified name.
8.274 + * <p>
8.275 + * No event is fired if old and new values are equal.
8.276 + * <p>
8.277 + * This is merely a convenience wrapper around the more general
8.278 + * {@link #firePropertyChange(String, Object, Object)} method.
8.279 + *
8.280 + * @param propertyName the programmatic name of the property that was changed
8.281 + * @param oldValue the old value of the property
8.282 + * @param newValue the new value of the property
8.283 + */
8.284 + public void firePropertyChange(String propertyName, int oldValue, int newValue) {
8.285 + if (oldValue != newValue) {
8.286 + firePropertyChange(propertyName, Integer.valueOf(oldValue), Integer.valueOf(newValue));
8.287 + }
8.288 + }
8.289 +
8.290 + /**
8.291 + * Reports a boolean bound property update to listeners
8.292 + * that have been registered to track updates of
8.293 + * all properties or a property with the specified name.
8.294 + * <p>
8.295 + * No event is fired if old and new values are equal.
8.296 + * <p>
8.297 + * This is merely a convenience wrapper around the more general
8.298 + * {@link #firePropertyChange(String, Object, Object)} method.
8.299 + *
8.300 + * @param propertyName the programmatic name of the property that was changed
8.301 + * @param oldValue the old value of the property
8.302 + * @param newValue the new value of the property
8.303 + */
8.304 + public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {
8.305 + if (oldValue != newValue) {
8.306 + firePropertyChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
8.307 + }
8.308 + }
8.309 +
8.310 + /**
8.311 + * Fires a property change event to listeners
8.312 + * that have been registered to track updates of
8.313 + * all properties or a property with the specified name.
8.314 + * <p>
8.315 + * No event is fired if the given event's old and new values are equal and non-null.
8.316 + *
8.317 + * @param event the {@code PropertyChangeEvent} to be fired
8.318 + */
8.319 + public void firePropertyChange(PropertyChangeEvent event) {
8.320 + Object oldValue = event.getOldValue();
8.321 + Object newValue = event.getNewValue();
8.322 + if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
8.323 + String name = event.getPropertyName();
8.324 +
8.325 + PropertyChangeListener[] common = this.map.get(null);
8.326 + PropertyChangeListener[] named = (name != null)
8.327 + ? this.map.get(name)
8.328 + : null;
8.329 +
8.330 + fire(common, event);
8.331 + fire(named, event);
8.332 + }
8.333 + }
8.334 +
8.335 + private static void fire(PropertyChangeListener[] listeners, PropertyChangeEvent event) {
8.336 + if (listeners != null) {
8.337 + for (PropertyChangeListener listener : listeners) {
8.338 + listener.propertyChange(event);
8.339 + }
8.340 + }
8.341 + }
8.342 +
8.343 + /**
8.344 + * Reports a bound indexed property update to listeners
8.345 + * that have been registered to track updates of
8.346 + * all properties or a property with the specified name.
8.347 + * <p>
8.348 + * No event is fired if old and new values are equal and non-null.
8.349 + * <p>
8.350 + * This is merely a convenience wrapper around the more general
8.351 + * {@link #firePropertyChange(PropertyChangeEvent)} method.
8.352 + *
8.353 + * @param propertyName the programmatic name of the property that was changed
8.354 + * @param index the index of the property element that was changed
8.355 + * @param oldValue the old value of the property
8.356 + * @param newValue the new value of the property
8.357 + * @since 1.5
8.358 + */
8.359 + public void fireIndexedPropertyChange(String propertyName, int index, Object oldValue, Object newValue) {
8.360 + if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
8.361 + firePropertyChange(new IndexedPropertyChangeEvent(source, propertyName, oldValue, newValue, index));
8.362 + }
8.363 + }
8.364 +
8.365 + /**
8.366 + * Reports an integer bound indexed property update to listeners
8.367 + * that have been registered to track updates of
8.368 + * all properties or a property with the specified name.
8.369 + * <p>
8.370 + * No event is fired if old and new values are equal.
8.371 + * <p>
8.372 + * This is merely a convenience wrapper around the more general
8.373 + * {@link #fireIndexedPropertyChange(String, int, Object, Object)} method.
8.374 + *
8.375 + * @param propertyName the programmatic name of the property that was changed
8.376 + * @param index the index of the property element that was changed
8.377 + * @param oldValue the old value of the property
8.378 + * @param newValue the new value of the property
8.379 + * @since 1.5
8.380 + */
8.381 + public void fireIndexedPropertyChange(String propertyName, int index, int oldValue, int newValue) {
8.382 + if (oldValue != newValue) {
8.383 + fireIndexedPropertyChange(propertyName, index, Integer.valueOf(oldValue), Integer.valueOf(newValue));
8.384 + }
8.385 + }
8.386 +
8.387 + /**
8.388 + * Reports a boolean bound indexed property update to listeners
8.389 + * that have been registered to track updates of
8.390 + * all properties or a property with the specified name.
8.391 + * <p>
8.392 + * No event is fired if old and new values are equal.
8.393 + * <p>
8.394 + * This is merely a convenience wrapper around the more general
8.395 + * {@link #fireIndexedPropertyChange(String, int, Object, Object)} method.
8.396 + *
8.397 + * @param propertyName the programmatic name of the property that was changed
8.398 + * @param index the index of the property element that was changed
8.399 + * @param oldValue the old value of the property
8.400 + * @param newValue the new value of the property
8.401 + * @since 1.5
8.402 + */
8.403 + public void fireIndexedPropertyChange(String propertyName, int index, boolean oldValue, boolean newValue) {
8.404 + if (oldValue != newValue) {
8.405 + fireIndexedPropertyChange(propertyName, index, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
8.406 + }
8.407 + }
8.408 +
8.409 + /**
8.410 + * Check if there are any listeners for a specific property, including
8.411 + * those registered on all properties. If <code>propertyName</code>
8.412 + * is null, only check for listeners registered on all properties.
8.413 + *
8.414 + * @param propertyName the property name.
8.415 + * @return true if there are one or more listeners for the given property
8.416 + */
8.417 + public boolean hasListeners(String propertyName) {
8.418 + return this.map.hasListeners(propertyName);
8.419 + }
8.420 +
8.421 + /**
8.422 + * @serialData Null terminated list of <code>PropertyChangeListeners</code>.
8.423 + * <p>
8.424 + * At serialization time we skip non-serializable listeners and
8.425 + * only serialize the serializable listeners.
8.426 + */
8.427 + private void writeObject(ObjectOutputStream s) throws IOException {
8.428 + Hashtable<String, PropertyChangeSupport> children = null;
8.429 + PropertyChangeListener[] listeners = null;
8.430 + synchronized (this.map) {
8.431 + for (Entry<String, PropertyChangeListener[]> entry : this.map.getEntries()) {
8.432 + String property = entry.getKey();
8.433 + if (property == null) {
8.434 + listeners = entry.getValue();
8.435 + } else {
8.436 + if (children == null) {
8.437 + children = new Hashtable<String, PropertyChangeSupport>();
8.438 + }
8.439 + PropertyChangeSupport pcs = new PropertyChangeSupport(this.source);
8.440 + pcs.map.set(null, entry.getValue());
8.441 + children.put(property, pcs);
8.442 + }
8.443 + }
8.444 + }
8.445 + ObjectOutputStream.PutField fields = s.putFields();
8.446 + fields.put("children", children);
8.447 + fields.put("source", this.source);
8.448 + fields.put("propertyChangeSupportSerializedDataVersion", 2);
8.449 + s.writeFields();
8.450 +
8.451 + if (listeners != null) {
8.452 + for (PropertyChangeListener l : listeners) {
8.453 + if (l instanceof Serializable) {
8.454 + s.writeObject(l);
8.455 + }
8.456 + }
8.457 + }
8.458 + s.writeObject(null);
8.459 + }
8.460 +
8.461 + private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
8.462 + this.map = new PropertyChangeListenerMap();
8.463 +
8.464 + ObjectInputStream.GetField fields = s.readFields();
8.465 +
8.466 + Hashtable<String, PropertyChangeSupport> children = (Hashtable<String, PropertyChangeSupport>) fields.get("children", null);
8.467 + this.source = fields.get("source", null);
8.468 + fields.get("propertyChangeSupportSerializedDataVersion", 2);
8.469 +
8.470 + Object listenerOrNull;
8.471 + while (null != (listenerOrNull = s.readObject())) {
8.472 + this.map.add(null, (PropertyChangeListener)listenerOrNull);
8.473 + }
8.474 + if (children != null) {
8.475 + for (Entry<String, PropertyChangeSupport> entry : children.entrySet()) {
8.476 + for (PropertyChangeListener listener : entry.getValue().getPropertyChangeListeners()) {
8.477 + this.map.add(entry.getKey(), listener);
8.478 + }
8.479 + }
8.480 + }
8.481 + }
8.482 +
8.483 + /**
8.484 + * The object to be provided as the "source" for any generated events.
8.485 + */
8.486 + private Object source;
8.487 +
8.488 + /**
8.489 + * @serialField children Hashtable
8.490 + * @serialField source Object
8.491 + * @serialField propertyChangeSupportSerializedDataVersion int
8.492 + */
8.493 + private static final ObjectStreamField[] serialPersistentFields = {
8.494 + new ObjectStreamField("children", Hashtable.class),
8.495 + new ObjectStreamField("source", Object.class),
8.496 + new ObjectStreamField("propertyChangeSupportSerializedDataVersion", Integer.TYPE)
8.497 + };
8.498 +
8.499 + /**
8.500 + * Serialization version ID, so we're compatible with JDK 1.1
8.501 + */
8.502 + static final long serialVersionUID = 6401253773779951803L;
8.503 +
8.504 + /**
8.505 + * This is a {@link ChangeListenerMap ChangeListenerMap} implementation
8.506 + * that works with {@link PropertyChangeListener PropertyChangeListener} objects.
8.507 + */
8.508 + private static final class PropertyChangeListenerMap extends ChangeListenerMap<PropertyChangeListener> {
8.509 + private static final PropertyChangeListener[] EMPTY = {};
8.510 +
8.511 + /**
8.512 + * Creates an array of {@link PropertyChangeListener PropertyChangeListener} objects.
8.513 + * This method uses the same instance of the empty array
8.514 + * when {@code length} equals {@code 0}.
8.515 + *
8.516 + * @param length the array length
8.517 + * @return an array with specified length
8.518 + */
8.519 + @Override
8.520 + protected PropertyChangeListener[] newArray(int length) {
8.521 + return (0 < length)
8.522 + ? new PropertyChangeListener[length]
8.523 + : EMPTY;
8.524 + }
8.525 +
8.526 + /**
8.527 + * Creates a {@link PropertyChangeListenerProxy PropertyChangeListenerProxy}
8.528 + * object for the specified property.
8.529 + *
8.530 + * @param name the name of the property to listen on
8.531 + * @param listener the listener to process events
8.532 + * @return a {@code PropertyChangeListenerProxy} object
8.533 + */
8.534 + @Override
8.535 + protected PropertyChangeListener newProxy(String name, PropertyChangeListener listener) {
8.536 + return new PropertyChangeListenerProxy(name, listener);
8.537 + }
8.538 + }
8.539 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/emul/compact/src/main/java/java/beans/PropertyVetoException.java Tue Feb 05 17:04:22 2013 +0100
9.3 @@ -0,0 +1,64 @@
9.4 +/*
9.5 + * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
9.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
9.7 + *
9.8 + * This code is free software; you can redistribute it and/or modify it
9.9 + * under the terms of the GNU General Public License version 2 only, as
9.10 + * published by the Free Software Foundation. Oracle designates this
9.11 + * particular file as subject to the "Classpath" exception as provided
9.12 + * by Oracle in the LICENSE file that accompanied this code.
9.13 + *
9.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
9.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9.17 + * version 2 for more details (a copy is included in the LICENSE file that
9.18 + * accompanied this code).
9.19 + *
9.20 + * You should have received a copy of the GNU General Public License version
9.21 + * 2 along with this work; if not, write to the Free Software Foundation,
9.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
9.23 + *
9.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
9.25 + * or visit www.oracle.com if you need additional information or have any
9.26 + * questions.
9.27 + */
9.28 +
9.29 +package java.beans;
9.30 +
9.31 +
9.32 +/**
9.33 + * A PropertyVetoException is thrown when a proposed change to a
9.34 + * property represents an unacceptable value.
9.35 + */
9.36 +
9.37 +public
9.38 +class PropertyVetoException extends Exception {
9.39 + private static final long serialVersionUID = 129596057694162164L;
9.40 +
9.41 + /**
9.42 + * Constructs a <code>PropertyVetoException</code> with a
9.43 + * detailed message.
9.44 + *
9.45 + * @param mess Descriptive message
9.46 + * @param evt A PropertyChangeEvent describing the vetoed change.
9.47 + */
9.48 + public PropertyVetoException(String mess, PropertyChangeEvent evt) {
9.49 + super(mess);
9.50 + this.evt = evt;
9.51 + }
9.52 +
9.53 + /**
9.54 + * Gets the vetoed <code>PropertyChangeEvent</code>.
9.55 + *
9.56 + * @return A PropertyChangeEvent describing the vetoed change.
9.57 + */
9.58 + public PropertyChangeEvent getPropertyChangeEvent() {
9.59 + return evt;
9.60 + }
9.61 +
9.62 + /**
9.63 + * A PropertyChangeEvent describing the vetoed change.
9.64 + * @serial
9.65 + */
9.66 + private PropertyChangeEvent evt;
9.67 +}
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/emul/compact/src/main/java/java/beans/VetoableChangeListener.java Tue Feb 05 17:04:22 2013 +0100
10.3 @@ -0,0 +1,44 @@
10.4 +/*
10.5 + * Copyright (c) 1996, 1997, Oracle and/or its affiliates. All rights reserved.
10.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10.7 + *
10.8 + * This code is free software; you can redistribute it and/or modify it
10.9 + * under the terms of the GNU General Public License version 2 only, as
10.10 + * published by the Free Software Foundation. Oracle designates this
10.11 + * particular file as subject to the "Classpath" exception as provided
10.12 + * by Oracle in the LICENSE file that accompanied this code.
10.13 + *
10.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
10.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10.17 + * version 2 for more details (a copy is included in the LICENSE file that
10.18 + * accompanied this code).
10.19 + *
10.20 + * You should have received a copy of the GNU General Public License version
10.21 + * 2 along with this work; if not, write to the Free Software Foundation,
10.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
10.23 + *
10.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
10.25 + * or visit www.oracle.com if you need additional information or have any
10.26 + * questions.
10.27 + */
10.28 +
10.29 +package java.beans;
10.30 +
10.31 +/**
10.32 + * A VetoableChange event gets fired whenever a bean changes a "constrained"
10.33 + * property. You can register a VetoableChangeListener with a source bean
10.34 + * so as to be notified of any constrained property updates.
10.35 + */
10.36 +public interface VetoableChangeListener extends java.util.EventListener {
10.37 + /**
10.38 + * This method gets called when a constrained property is changed.
10.39 + *
10.40 + * @param evt a <code>PropertyChangeEvent</code> object describing the
10.41 + * event source and the property that has changed.
10.42 + * @exception PropertyVetoException if the recipient wishes the property
10.43 + * change to be rolled back.
10.44 + */
10.45 + void vetoableChange(PropertyChangeEvent evt)
10.46 + throws PropertyVetoException;
10.47 +}
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/emul/compact/src/main/java/java/beans/VetoableChangeListenerProxy.java Tue Feb 05 17:04:22 2013 +0100
11.3 @@ -0,0 +1,84 @@
11.4 +/*
11.5 + * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
11.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
11.7 + *
11.8 + * This code is free software; you can redistribute it and/or modify it
11.9 + * under the terms of the GNU General Public License version 2 only, as
11.10 + * published by the Free Software Foundation. Oracle designates this
11.11 + * particular file as subject to the "Classpath" exception as provided
11.12 + * by Oracle in the LICENSE file that accompanied this code.
11.13 + *
11.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
11.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11.17 + * version 2 for more details (a copy is included in the LICENSE file that
11.18 + * accompanied this code).
11.19 + *
11.20 + * You should have received a copy of the GNU General Public License version
11.21 + * 2 along with this work; if not, write to the Free Software Foundation,
11.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
11.23 + *
11.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
11.25 + * or visit www.oracle.com if you need additional information or have any
11.26 + * questions.
11.27 + */
11.28 +
11.29 +package java.beans;
11.30 +
11.31 +import java.util.EventListenerProxy;
11.32 +
11.33 +/**
11.34 + * A class which extends the {@code EventListenerProxy}
11.35 + * specifically for adding a {@code VetoableChangeListener}
11.36 + * with a "constrained" property.
11.37 + * Instances of this class can be added
11.38 + * as {@code VetoableChangeListener}s to a bean
11.39 + * which supports firing vetoable change events.
11.40 + * <p>
11.41 + * If the object has a {@code getVetoableChangeListeners} method
11.42 + * then the array returned could be a mixture of {@code VetoableChangeListener}
11.43 + * and {@code VetoableChangeListenerProxy} objects.
11.44 + *
11.45 + * @see java.util.EventListenerProxy
11.46 + * @see VetoableChangeSupport#getVetoableChangeListeners
11.47 + * @since 1.4
11.48 + */
11.49 +public class VetoableChangeListenerProxy
11.50 + extends EventListenerProxy<VetoableChangeListener>
11.51 + implements VetoableChangeListener {
11.52 +
11.53 + private final String propertyName;
11.54 +
11.55 + /**
11.56 + * Constructor which binds the {@code VetoableChangeListener}
11.57 + * to a specific property.
11.58 + *
11.59 + * @param propertyName the name of the property to listen on
11.60 + * @param listener the listener object
11.61 + */
11.62 + public VetoableChangeListenerProxy(String propertyName, VetoableChangeListener listener) {
11.63 + super(listener);
11.64 + this.propertyName = propertyName;
11.65 + }
11.66 +
11.67 + /**
11.68 + * Forwards the property change event to the listener delegate.
11.69 + *
11.70 + * @param event the property change event
11.71 + *
11.72 + * @exception PropertyVetoException if the recipient wishes the property
11.73 + * change to be rolled back
11.74 + */
11.75 + public void vetoableChange(PropertyChangeEvent event) throws PropertyVetoException{
11.76 + getListener().vetoableChange(event);
11.77 + }
11.78 +
11.79 + /**
11.80 + * Returns the name of the named property associated with the listener.
11.81 + *
11.82 + * @return the name of the named property associated with the listener
11.83 + */
11.84 + public String getPropertyName() {
11.85 + return this.propertyName;
11.86 + }
11.87 +}
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/emul/compact/src/main/java/java/beans/VetoableChangeSupport.java Tue Feb 05 17:04:22 2013 +0100
12.3 @@ -0,0 +1,526 @@
12.4 +/*
12.5 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
12.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
12.7 + *
12.8 + * This code is free software; you can redistribute it and/or modify it
12.9 + * under the terms of the GNU General Public License version 2 only, as
12.10 + * published by the Free Software Foundation. Oracle designates this
12.11 + * particular file as subject to the "Classpath" exception as provided
12.12 + * by Oracle in the LICENSE file that accompanied this code.
12.13 + *
12.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
12.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12.17 + * version 2 for more details (a copy is included in the LICENSE file that
12.18 + * accompanied this code).
12.19 + *
12.20 + * You should have received a copy of the GNU General Public License version
12.21 + * 2 along with this work; if not, write to the Free Software Foundation,
12.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
12.23 + *
12.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
12.25 + * or visit www.oracle.com if you need additional information or have any
12.26 + * questions.
12.27 + */
12.28 +package java.beans;
12.29 +
12.30 +import java.io.Serializable;
12.31 +import java.io.ObjectStreamField;
12.32 +import java.io.ObjectOutputStream;
12.33 +import java.io.ObjectInputStream;
12.34 +import java.io.IOException;
12.35 +import java.util.Hashtable;
12.36 +import java.util.Map.Entry;
12.37 +import org.apidesign.bck2brwsr.emul.lang.System;
12.38 +
12.39 +/**
12.40 + * This is a utility class that can be used by beans that support constrained
12.41 + * properties. It manages a list of listeners and dispatches
12.42 + * {@link PropertyChangeEvent}s to them. You can use an instance of this class
12.43 + * as a member field of your bean and delegate these types of work to it.
12.44 + * The {@link VetoableChangeListener} can be registered for all properties
12.45 + * or for a property specified by name.
12.46 + * <p>
12.47 + * Here is an example of {@code VetoableChangeSupport} usage that follows
12.48 + * the rules and recommendations laid out in the JavaBeans™ specification:
12.49 + * <pre>
12.50 + * public class MyBean {
12.51 + * private final VetoableChangeSupport vcs = new VetoableChangeSupport(this);
12.52 + *
12.53 + * public void addVetoableChangeListener(VetoableChangeListener listener) {
12.54 + * this.vcs.addVetoableChangeListener(listener);
12.55 + * }
12.56 + *
12.57 + * public void removeVetoableChangeListener(VetoableChangeListener listener) {
12.58 + * this.vcs.removeVetoableChangeListener(listener);
12.59 + * }
12.60 + *
12.61 + * private String value;
12.62 + *
12.63 + * public String getValue() {
12.64 + * return this.value;
12.65 + * }
12.66 + *
12.67 + * public void setValue(String newValue) throws PropertyVetoException {
12.68 + * String oldValue = this.value;
12.69 + * this.vcs.fireVetoableChange("value", oldValue, newValue);
12.70 + * this.value = newValue;
12.71 + * }
12.72 + *
12.73 + * [...]
12.74 + * }
12.75 + * </pre>
12.76 + * <p>
12.77 + * A {@code VetoableChangeSupport} instance is thread-safe.
12.78 + * <p>
12.79 + * This class is serializable. When it is serialized it will save
12.80 + * (and restore) any listeners that are themselves serializable. Any
12.81 + * non-serializable listeners will be skipped during serialization.
12.82 + *
12.83 + * @see PropertyChangeSupport
12.84 + */
12.85 +public class VetoableChangeSupport implements Serializable {
12.86 + private VetoableChangeListenerMap map = new VetoableChangeListenerMap();
12.87 +
12.88 + /**
12.89 + * Constructs a <code>VetoableChangeSupport</code> object.
12.90 + *
12.91 + * @param sourceBean The bean to be given as the source for any events.
12.92 + */
12.93 + public VetoableChangeSupport(Object sourceBean) {
12.94 + if (sourceBean == null) {
12.95 + throw new NullPointerException();
12.96 + }
12.97 + source = sourceBean;
12.98 + }
12.99 +
12.100 + /**
12.101 + * Add a VetoableChangeListener to the listener list.
12.102 + * The listener is registered for all properties.
12.103 + * The same listener object may be added more than once, and will be called
12.104 + * as many times as it is added.
12.105 + * If <code>listener</code> is null, no exception is thrown and no action
12.106 + * is taken.
12.107 + *
12.108 + * @param listener The VetoableChangeListener to be added
12.109 + */
12.110 + public void addVetoableChangeListener(VetoableChangeListener listener) {
12.111 + if (listener == null) {
12.112 + return;
12.113 + }
12.114 + if (listener instanceof VetoableChangeListenerProxy) {
12.115 + VetoableChangeListenerProxy proxy =
12.116 + (VetoableChangeListenerProxy)listener;
12.117 + // Call two argument add method.
12.118 + addVetoableChangeListener(proxy.getPropertyName(),
12.119 + proxy.getListener());
12.120 + } else {
12.121 + this.map.add(null, listener);
12.122 + }
12.123 + }
12.124 +
12.125 + /**
12.126 + * Remove a VetoableChangeListener from the listener list.
12.127 + * This removes a VetoableChangeListener that was registered
12.128 + * for all properties.
12.129 + * If <code>listener</code> was added more than once to the same event
12.130 + * source, it will be notified one less time after being removed.
12.131 + * If <code>listener</code> is null, or was never added, no exception is
12.132 + * thrown and no action is taken.
12.133 + *
12.134 + * @param listener The VetoableChangeListener to be removed
12.135 + */
12.136 + public void removeVetoableChangeListener(VetoableChangeListener listener) {
12.137 + if (listener == null) {
12.138 + return;
12.139 + }
12.140 + if (listener instanceof VetoableChangeListenerProxy) {
12.141 + VetoableChangeListenerProxy proxy =
12.142 + (VetoableChangeListenerProxy)listener;
12.143 + // Call two argument remove method.
12.144 + removeVetoableChangeListener(proxy.getPropertyName(),
12.145 + proxy.getListener());
12.146 + } else {
12.147 + this.map.remove(null, listener);
12.148 + }
12.149 + }
12.150 +
12.151 + /**
12.152 + * Returns an array of all the listeners that were added to the
12.153 + * VetoableChangeSupport object with addVetoableChangeListener().
12.154 + * <p>
12.155 + * If some listeners have been added with a named property, then
12.156 + * the returned array will be a mixture of VetoableChangeListeners
12.157 + * and <code>VetoableChangeListenerProxy</code>s. If the calling
12.158 + * method is interested in distinguishing the listeners then it must
12.159 + * test each element to see if it's a
12.160 + * <code>VetoableChangeListenerProxy</code>, perform the cast, and examine
12.161 + * the parameter.
12.162 + *
12.163 + * <pre>
12.164 + * VetoableChangeListener[] listeners = bean.getVetoableChangeListeners();
12.165 + * for (int i = 0; i < listeners.length; i++) {
12.166 + * if (listeners[i] instanceof VetoableChangeListenerProxy) {
12.167 + * VetoableChangeListenerProxy proxy =
12.168 + * (VetoableChangeListenerProxy)listeners[i];
12.169 + * if (proxy.getPropertyName().equals("foo")) {
12.170 + * // proxy is a VetoableChangeListener which was associated
12.171 + * // with the property named "foo"
12.172 + * }
12.173 + * }
12.174 + * }
12.175 + *</pre>
12.176 + *
12.177 + * @see VetoableChangeListenerProxy
12.178 + * @return all of the <code>VetoableChangeListeners</code> added or an
12.179 + * empty array if no listeners have been added
12.180 + * @since 1.4
12.181 + */
12.182 + public VetoableChangeListener[] getVetoableChangeListeners(){
12.183 + return this.map.getListeners();
12.184 + }
12.185 +
12.186 + /**
12.187 + * Add a VetoableChangeListener for a specific property. The listener
12.188 + * will be invoked only when a call on fireVetoableChange names that
12.189 + * specific property.
12.190 + * The same listener object may be added more than once. For each
12.191 + * property, the listener will be invoked the number of times it was added
12.192 + * for that property.
12.193 + * If <code>propertyName</code> or <code>listener</code> is null, no
12.194 + * exception is thrown and no action is taken.
12.195 + *
12.196 + * @param propertyName The name of the property to listen on.
12.197 + * @param listener The VetoableChangeListener to be added
12.198 + */
12.199 + public void addVetoableChangeListener(
12.200 + String propertyName,
12.201 + VetoableChangeListener listener) {
12.202 + if (listener == null || propertyName == null) {
12.203 + return;
12.204 + }
12.205 + listener = this.map.extract(listener);
12.206 + if (listener != null) {
12.207 + this.map.add(propertyName, listener);
12.208 + }
12.209 + }
12.210 +
12.211 + /**
12.212 + * Remove a VetoableChangeListener for a specific property.
12.213 + * If <code>listener</code> was added more than once to the same event
12.214 + * source for the specified property, it will be notified one less time
12.215 + * after being removed.
12.216 + * If <code>propertyName</code> is null, no exception is thrown and no
12.217 + * action is taken.
12.218 + * If <code>listener</code> is null, or was never added for the specified
12.219 + * property, no exception is thrown and no action is taken.
12.220 + *
12.221 + * @param propertyName The name of the property that was listened on.
12.222 + * @param listener The VetoableChangeListener to be removed
12.223 + */
12.224 + public void removeVetoableChangeListener(
12.225 + String propertyName,
12.226 + VetoableChangeListener listener) {
12.227 + if (listener == null || propertyName == null) {
12.228 + return;
12.229 + }
12.230 + listener = this.map.extract(listener);
12.231 + if (listener != null) {
12.232 + this.map.remove(propertyName, listener);
12.233 + }
12.234 + }
12.235 +
12.236 + /**
12.237 + * Returns an array of all the listeners which have been associated
12.238 + * with the named property.
12.239 + *
12.240 + * @param propertyName The name of the property being listened to
12.241 + * @return all the <code>VetoableChangeListeners</code> associated with
12.242 + * the named property. If no such listeners have been added,
12.243 + * or if <code>propertyName</code> is null, an empty array is
12.244 + * returned.
12.245 + * @since 1.4
12.246 + */
12.247 + public VetoableChangeListener[] getVetoableChangeListeners(String propertyName) {
12.248 + return this.map.getListeners(propertyName);
12.249 + }
12.250 +
12.251 + /**
12.252 + * Reports a constrained property update to listeners
12.253 + * that have been registered to track updates of
12.254 + * all properties or a property with the specified name.
12.255 + * <p>
12.256 + * Any listener can throw a {@code PropertyVetoException} to veto the update.
12.257 + * If one of the listeners vetoes the update, this method passes
12.258 + * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
12.259 + * to all listeners that already confirmed this update
12.260 + * and throws the {@code PropertyVetoException} again.
12.261 + * <p>
12.262 + * No event is fired if old and new values are equal and non-null.
12.263 + * <p>
12.264 + * This is merely a convenience wrapper around the more general
12.265 + * {@link #fireVetoableChange(PropertyChangeEvent)} method.
12.266 + *
12.267 + * @param propertyName the programmatic name of the property that is about to change
12.268 + * @param oldValue the old value of the property
12.269 + * @param newValue the new value of the property
12.270 + * @throws PropertyVetoException if one of listeners vetoes the property update
12.271 + */
12.272 + public void fireVetoableChange(String propertyName, Object oldValue, Object newValue)
12.273 + throws PropertyVetoException {
12.274 + if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
12.275 + fireVetoableChange(new PropertyChangeEvent(this.source, propertyName, oldValue, newValue));
12.276 + }
12.277 + }
12.278 +
12.279 + /**
12.280 + * Reports an integer constrained property update to listeners
12.281 + * that have been registered to track updates of
12.282 + * all properties or a property with the specified name.
12.283 + * <p>
12.284 + * Any listener can throw a {@code PropertyVetoException} to veto the update.
12.285 + * If one of the listeners vetoes the update, this method passes
12.286 + * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
12.287 + * to all listeners that already confirmed this update
12.288 + * and throws the {@code PropertyVetoException} again.
12.289 + * <p>
12.290 + * No event is fired if old and new values are equal.
12.291 + * <p>
12.292 + * This is merely a convenience wrapper around the more general
12.293 + * {@link #fireVetoableChange(String, Object, Object)} method.
12.294 + *
12.295 + * @param propertyName the programmatic name of the property that is about to change
12.296 + * @param oldValue the old value of the property
12.297 + * @param newValue the new value of the property
12.298 + * @throws PropertyVetoException if one of listeners vetoes the property update
12.299 + */
12.300 + public void fireVetoableChange(String propertyName, int oldValue, int newValue)
12.301 + throws PropertyVetoException {
12.302 + if (oldValue != newValue) {
12.303 + fireVetoableChange(propertyName, Integer.valueOf(oldValue), Integer.valueOf(newValue));
12.304 + }
12.305 + }
12.306 +
12.307 + /**
12.308 + * Reports a boolean constrained property update to listeners
12.309 + * that have been registered to track updates of
12.310 + * all properties or a property with the specified name.
12.311 + * <p>
12.312 + * Any listener can throw a {@code PropertyVetoException} to veto the update.
12.313 + * If one of the listeners vetoes the update, this method passes
12.314 + * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
12.315 + * to all listeners that already confirmed this update
12.316 + * and throws the {@code PropertyVetoException} again.
12.317 + * <p>
12.318 + * No event is fired if old and new values are equal.
12.319 + * <p>
12.320 + * This is merely a convenience wrapper around the more general
12.321 + * {@link #fireVetoableChange(String, Object, Object)} method.
12.322 + *
12.323 + * @param propertyName the programmatic name of the property that is about to change
12.324 + * @param oldValue the old value of the property
12.325 + * @param newValue the new value of the property
12.326 + * @throws PropertyVetoException if one of listeners vetoes the property update
12.327 + */
12.328 + public void fireVetoableChange(String propertyName, boolean oldValue, boolean newValue)
12.329 + throws PropertyVetoException {
12.330 + if (oldValue != newValue) {
12.331 + fireVetoableChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
12.332 + }
12.333 + }
12.334 +
12.335 + /**
12.336 + * Fires a property change event to listeners
12.337 + * that have been registered to track updates of
12.338 + * all properties or a property with the specified name.
12.339 + * <p>
12.340 + * Any listener can throw a {@code PropertyVetoException} to veto the update.
12.341 + * If one of the listeners vetoes the update, this method passes
12.342 + * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
12.343 + * to all listeners that already confirmed this update
12.344 + * and throws the {@code PropertyVetoException} again.
12.345 + * <p>
12.346 + * No event is fired if the given event's old and new values are equal and non-null.
12.347 + *
12.348 + * @param event the {@code PropertyChangeEvent} to be fired
12.349 + * @throws PropertyVetoException if one of listeners vetoes the property update
12.350 + */
12.351 + public void fireVetoableChange(PropertyChangeEvent event)
12.352 + throws PropertyVetoException {
12.353 + Object oldValue = event.getOldValue();
12.354 + Object newValue = event.getNewValue();
12.355 + if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
12.356 + String name = event.getPropertyName();
12.357 +
12.358 + VetoableChangeListener[] common = this.map.get(null);
12.359 + VetoableChangeListener[] named = (name != null)
12.360 + ? this.map.get(name)
12.361 + : null;
12.362 +
12.363 + VetoableChangeListener[] listeners;
12.364 + if (common == null) {
12.365 + listeners = named;
12.366 + }
12.367 + else if (named == null) {
12.368 + listeners = common;
12.369 + }
12.370 + else {
12.371 + listeners = new VetoableChangeListener[common.length + named.length];
12.372 + System.arraycopy(common, 0, listeners, 0, common.length);
12.373 + System.arraycopy(named, 0, listeners, common.length, named.length);
12.374 + }
12.375 + if (listeners != null) {
12.376 + int current = 0;
12.377 + try {
12.378 + while (current < listeners.length) {
12.379 + listeners[current].vetoableChange(event);
12.380 + current++;
12.381 + }
12.382 + }
12.383 + catch (PropertyVetoException veto) {
12.384 + event = new PropertyChangeEvent(this.source, name, newValue, oldValue);
12.385 + for (int i = 0; i < current; i++) {
12.386 + try {
12.387 + listeners[i].vetoableChange(event);
12.388 + }
12.389 + catch (PropertyVetoException exception) {
12.390 + // ignore exceptions that occur during rolling back
12.391 + }
12.392 + }
12.393 + throw veto; // rethrow the veto exception
12.394 + }
12.395 + }
12.396 + }
12.397 + }
12.398 +
12.399 + /**
12.400 + * Check if there are any listeners for a specific property, including
12.401 + * those registered on all properties. If <code>propertyName</code>
12.402 + * is null, only check for listeners registered on all properties.
12.403 + *
12.404 + * @param propertyName the property name.
12.405 + * @return true if there are one or more listeners for the given property
12.406 + */
12.407 + public boolean hasListeners(String propertyName) {
12.408 + return this.map.hasListeners(propertyName);
12.409 + }
12.410 +
12.411 + /**
12.412 + * @serialData Null terminated list of <code>VetoableChangeListeners</code>.
12.413 + * <p>
12.414 + * At serialization time we skip non-serializable listeners and
12.415 + * only serialize the serializable listeners.
12.416 + */
12.417 + private void writeObject(ObjectOutputStream s) throws IOException {
12.418 + Hashtable<String, VetoableChangeSupport> children = null;
12.419 + VetoableChangeListener[] listeners = null;
12.420 + synchronized (this.map) {
12.421 + for (Entry<String, VetoableChangeListener[]> entry : this.map.getEntries()) {
12.422 + String property = entry.getKey();
12.423 + if (property == null) {
12.424 + listeners = entry.getValue();
12.425 + } else {
12.426 + if (children == null) {
12.427 + children = new Hashtable<String, VetoableChangeSupport>();
12.428 + }
12.429 + VetoableChangeSupport vcs = new VetoableChangeSupport(this.source);
12.430 + vcs.map.set(null, entry.getValue());
12.431 + children.put(property, vcs);
12.432 + }
12.433 + }
12.434 + }
12.435 + ObjectOutputStream.PutField fields = s.putFields();
12.436 + fields.put("children", children);
12.437 + fields.put("source", this.source);
12.438 + fields.put("vetoableChangeSupportSerializedDataVersion", 2);
12.439 + s.writeFields();
12.440 +
12.441 + if (listeners != null) {
12.442 + for (VetoableChangeListener l : listeners) {
12.443 + if (l instanceof Serializable) {
12.444 + s.writeObject(l);
12.445 + }
12.446 + }
12.447 + }
12.448 + s.writeObject(null);
12.449 + }
12.450 +
12.451 + private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
12.452 + this.map = new VetoableChangeListenerMap();
12.453 +
12.454 + ObjectInputStream.GetField fields = s.readFields();
12.455 +
12.456 + Hashtable<String, VetoableChangeSupport> children = (Hashtable<String, VetoableChangeSupport>) fields.get("children", null);
12.457 + this.source = fields.get("source", null);
12.458 + fields.get("vetoableChangeSupportSerializedDataVersion", 2);
12.459 +
12.460 + Object listenerOrNull;
12.461 + while (null != (listenerOrNull = s.readObject())) {
12.462 + this.map.add(null, (VetoableChangeListener)listenerOrNull);
12.463 + }
12.464 + if (children != null) {
12.465 + for (Entry<String, VetoableChangeSupport> entry : children.entrySet()) {
12.466 + for (VetoableChangeListener listener : entry.getValue().getVetoableChangeListeners()) {
12.467 + this.map.add(entry.getKey(), listener);
12.468 + }
12.469 + }
12.470 + }
12.471 + }
12.472 +
12.473 + /**
12.474 + * The object to be provided as the "source" for any generated events.
12.475 + */
12.476 + private Object source;
12.477 +
12.478 + /**
12.479 + * @serialField children Hashtable
12.480 + * @serialField source Object
12.481 + * @serialField vetoableChangeSupportSerializedDataVersion int
12.482 + */
12.483 + private static final ObjectStreamField[] serialPersistentFields = {
12.484 + new ObjectStreamField("children", Hashtable.class),
12.485 + new ObjectStreamField("source", Object.class),
12.486 + new ObjectStreamField("vetoableChangeSupportSerializedDataVersion", Integer.TYPE)
12.487 + };
12.488 +
12.489 + /**
12.490 + * Serialization version ID, so we're compatible with JDK 1.1
12.491 + */
12.492 + static final long serialVersionUID = -5090210921595982017L;
12.493 +
12.494 + /**
12.495 + * This is a {@link ChangeListenerMap ChangeListenerMap} implementation
12.496 + * that works with {@link VetoableChangeListener VetoableChangeListener} objects.
12.497 + */
12.498 + private static final class VetoableChangeListenerMap extends ChangeListenerMap<VetoableChangeListener> {
12.499 + private static final VetoableChangeListener[] EMPTY = {};
12.500 +
12.501 + /**
12.502 + * Creates an array of {@link VetoableChangeListener VetoableChangeListener} objects.
12.503 + * This method uses the same instance of the empty array
12.504 + * when {@code length} equals {@code 0}.
12.505 + *
12.506 + * @param length the array length
12.507 + * @return an array with specified length
12.508 + */
12.509 + @Override
12.510 + protected VetoableChangeListener[] newArray(int length) {
12.511 + return (0 < length)
12.512 + ? new VetoableChangeListener[length]
12.513 + : EMPTY;
12.514 + }
12.515 +
12.516 + /**
12.517 + * Creates a {@link VetoableChangeListenerProxy VetoableChangeListenerProxy}
12.518 + * object for the specified property.
12.519 + *
12.520 + * @param name the name of the property to listen on
12.521 + * @param listener the listener to process events
12.522 + * @return a {@code VetoableChangeListenerProxy} object
12.523 + */
12.524 + @Override
12.525 + protected VetoableChangeListener newProxy(String name, VetoableChangeListener listener) {
12.526 + return new VetoableChangeListenerProxy(name, listener);
12.527 + }
12.528 + }
12.529 +}
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/emul/compact/src/main/java/java/io/Bits.java Tue Feb 05 17:04:22 2013 +0100
13.3 @@ -0,0 +1,123 @@
13.4 +/*
13.5 + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
13.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
13.7 + *
13.8 + * This code is free software; you can redistribute it and/or modify it
13.9 + * under the terms of the GNU General Public License version 2 only, as
13.10 + * published by the Free Software Foundation. Oracle designates this
13.11 + * particular file as subject to the "Classpath" exception as provided
13.12 + * by Oracle in the LICENSE file that accompanied this code.
13.13 + *
13.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
13.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13.17 + * version 2 for more details (a copy is included in the LICENSE file that
13.18 + * accompanied this code).
13.19 + *
13.20 + * You should have received a copy of the GNU General Public License version
13.21 + * 2 along with this work; if not, write to the Free Software Foundation,
13.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
13.23 + *
13.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
13.25 + * or visit www.oracle.com if you need additional information or have any
13.26 + * questions.
13.27 + */
13.28 +
13.29 +package java.io;
13.30 +
13.31 +/**
13.32 + * Utility methods for packing/unpacking primitive values in/out of byte arrays
13.33 + * using big-endian byte ordering.
13.34 + */
13.35 +class Bits {
13.36 +
13.37 + /*
13.38 + * Methods for unpacking primitive values from byte arrays starting at
13.39 + * given offsets.
13.40 + */
13.41 +
13.42 + static boolean getBoolean(byte[] b, int off) {
13.43 + return b[off] != 0;
13.44 + }
13.45 +
13.46 + static char getChar(byte[] b, int off) {
13.47 + return (char) ((b[off + 1] & 0xFF) +
13.48 + (b[off] << 8));
13.49 + }
13.50 +
13.51 + static short getShort(byte[] b, int off) {
13.52 + return (short) ((b[off + 1] & 0xFF) +
13.53 + (b[off] << 8));
13.54 + }
13.55 +
13.56 + static int getInt(byte[] b, int off) {
13.57 + return ((b[off + 3] & 0xFF) ) +
13.58 + ((b[off + 2] & 0xFF) << 8) +
13.59 + ((b[off + 1] & 0xFF) << 16) +
13.60 + ((b[off ] ) << 24);
13.61 + }
13.62 +
13.63 + static float getFloat(byte[] b, int off) {
13.64 + return Float.intBitsToFloat(getInt(b, off));
13.65 + }
13.66 +
13.67 + static long getLong(byte[] b, int off) {
13.68 + return ((b[off + 7] & 0xFFL) ) +
13.69 + ((b[off + 6] & 0xFFL) << 8) +
13.70 + ((b[off + 5] & 0xFFL) << 16) +
13.71 + ((b[off + 4] & 0xFFL) << 24) +
13.72 + ((b[off + 3] & 0xFFL) << 32) +
13.73 + ((b[off + 2] & 0xFFL) << 40) +
13.74 + ((b[off + 1] & 0xFFL) << 48) +
13.75 + (((long) b[off]) << 56);
13.76 + }
13.77 +
13.78 + static double getDouble(byte[] b, int off) {
13.79 + return Double.longBitsToDouble(getLong(b, off));
13.80 + }
13.81 +
13.82 + /*
13.83 + * Methods for packing primitive values into byte arrays starting at given
13.84 + * offsets.
13.85 + */
13.86 +
13.87 + static void putBoolean(byte[] b, int off, boolean val) {
13.88 + b[off] = (byte) (val ? 1 : 0);
13.89 + }
13.90 +
13.91 + static void putChar(byte[] b, int off, char val) {
13.92 + b[off + 1] = (byte) (val );
13.93 + b[off ] = (byte) (val >>> 8);
13.94 + }
13.95 +
13.96 + static void putShort(byte[] b, int off, short val) {
13.97 + b[off + 1] = (byte) (val );
13.98 + b[off ] = (byte) (val >>> 8);
13.99 + }
13.100 +
13.101 + static void putInt(byte[] b, int off, int val) {
13.102 + b[off + 3] = (byte) (val );
13.103 + b[off + 2] = (byte) (val >>> 8);
13.104 + b[off + 1] = (byte) (val >>> 16);
13.105 + b[off ] = (byte) (val >>> 24);
13.106 + }
13.107 +
13.108 + static void putFloat(byte[] b, int off, float val) {
13.109 + putInt(b, off, Float.floatToIntBits(val));
13.110 + }
13.111 +
13.112 + static void putLong(byte[] b, int off, long val) {
13.113 + b[off + 7] = (byte) (val );
13.114 + b[off + 6] = (byte) (val >>> 8);
13.115 + b[off + 5] = (byte) (val >>> 16);
13.116 + b[off + 4] = (byte) (val >>> 24);
13.117 + b[off + 3] = (byte) (val >>> 32);
13.118 + b[off + 2] = (byte) (val >>> 40);
13.119 + b[off + 1] = (byte) (val >>> 48);
13.120 + b[off ] = (byte) (val >>> 56);
13.121 + }
13.122 +
13.123 + static void putDouble(byte[] b, int off, double val) {
13.124 + putLong(b, off, Double.doubleToLongBits(val));
13.125 + }
13.126 +}
14.1 --- a/emul/compact/src/main/java/java/io/BufferedReader.java Tue Feb 05 16:40:01 2013 +0100
14.2 +++ b/emul/compact/src/main/java/java/io/BufferedReader.java Tue Feb 05 17:04:22 2013 +0100
14.3 @@ -25,7 +25,6 @@
14.4
14.5 package java.io;
14.6
14.7 -import org.apidesign.bck2brwsr.emul.lang.System;
14.8
14.9
14.10 /**
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/emul/compact/src/main/java/java/io/DataOutput.java Tue Feb 05 17:04:22 2013 +0100
15.3 @@ -0,0 +1,354 @@
15.4 +/*
15.5 + * Copyright (c) 1995, 2006, 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 + * The <code>DataOutput</code> interface provides
15.33 + * for converting data from any of the Java
15.34 + * primitive types to a series of bytes and
15.35 + * writing these bytes to a binary stream.
15.36 + * There is also a facility for converting
15.37 + * a <code>String</code> into
15.38 + * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
15.39 + * format and writing the resulting series
15.40 + * of bytes.
15.41 + * <p>
15.42 + * For all the methods in this interface that
15.43 + * write bytes, it is generally true that if
15.44 + * a byte cannot be written for any reason,
15.45 + * an <code>IOException</code> is thrown.
15.46 + *
15.47 + * @author Frank Yellin
15.48 + * @see java.io.DataInput
15.49 + * @see java.io.DataOutputStream
15.50 + * @since JDK1.0
15.51 + */
15.52 +public
15.53 +interface DataOutput {
15.54 + /**
15.55 + * Writes to the output stream the eight
15.56 + * low-order bits of the argument <code>b</code>.
15.57 + * The 24 high-order bits of <code>b</code>
15.58 + * are ignored.
15.59 + *
15.60 + * @param b the byte to be written.
15.61 + * @throws IOException if an I/O error occurs.
15.62 + */
15.63 + void write(int b) throws IOException;
15.64 +
15.65 + /**
15.66 + * Writes to the output stream all the bytes in array <code>b</code>.
15.67 + * If <code>b</code> is <code>null</code>,
15.68 + * a <code>NullPointerException</code> is thrown.
15.69 + * If <code>b.length</code> is zero, then
15.70 + * no bytes are written. Otherwise, the byte
15.71 + * <code>b[0]</code> is written first, then
15.72 + * <code>b[1]</code>, and so on; the last byte
15.73 + * written is <code>b[b.length-1]</code>.
15.74 + *
15.75 + * @param b the data.
15.76 + * @throws IOException if an I/O error occurs.
15.77 + */
15.78 + void write(byte b[]) throws IOException;
15.79 +
15.80 + /**
15.81 + * Writes <code>len</code> bytes from array
15.82 + * <code>b</code>, in order, to
15.83 + * the output stream. If <code>b</code>
15.84 + * is <code>null</code>, a <code>NullPointerException</code>
15.85 + * is thrown. If <code>off</code> is negative,
15.86 + * or <code>len</code> is negative, or <code>off+len</code>
15.87 + * is greater than the length of the array
15.88 + * <code>b</code>, then an <code>IndexOutOfBoundsException</code>
15.89 + * is thrown. If <code>len</code> is zero,
15.90 + * then no bytes are written. Otherwise, the
15.91 + * byte <code>b[off]</code> is written first,
15.92 + * then <code>b[off+1]</code>, and so on; the
15.93 + * last byte written is <code>b[off+len-1]</code>.
15.94 + *
15.95 + * @param b the data.
15.96 + * @param off the start offset in the data.
15.97 + * @param len the number of bytes to write.
15.98 + * @throws IOException if an I/O error occurs.
15.99 + */
15.100 + void write(byte b[], int off, int len) throws IOException;
15.101 +
15.102 + /**
15.103 + * Writes a <code>boolean</code> value to this output stream.
15.104 + * If the argument <code>v</code>
15.105 + * is <code>true</code>, the value <code>(byte)1</code>
15.106 + * is written; if <code>v</code> is <code>false</code>,
15.107 + * the value <code>(byte)0</code> is written.
15.108 + * The byte written by this method may
15.109 + * be read by the <code>readBoolean</code>
15.110 + * method of interface <code>DataInput</code>,
15.111 + * which will then return a <code>boolean</code>
15.112 + * equal to <code>v</code>.
15.113 + *
15.114 + * @param v the boolean to be written.
15.115 + * @throws IOException if an I/O error occurs.
15.116 + */
15.117 + void writeBoolean(boolean v) throws IOException;
15.118 +
15.119 + /**
15.120 + * Writes to the output stream the eight low-
15.121 + * order bits of the argument <code>v</code>.
15.122 + * The 24 high-order bits of <code>v</code>
15.123 + * are ignored. (This means that <code>writeByte</code>
15.124 + * does exactly the same thing as <code>write</code>
15.125 + * for an integer argument.) The byte written
15.126 + * by this method may be read by the <code>readByte</code>
15.127 + * method of interface <code>DataInput</code>,
15.128 + * which will then return a <code>byte</code>
15.129 + * equal to <code>(byte)v</code>.
15.130 + *
15.131 + * @param v the byte value to be written.
15.132 + * @throws IOException if an I/O error occurs.
15.133 + */
15.134 + void writeByte(int v) throws IOException;
15.135 +
15.136 + /**
15.137 + * Writes two bytes to the output
15.138 + * stream to represent the value of the argument.
15.139 + * The byte values to be written, in the order
15.140 + * shown, are: <p>
15.141 + * <pre><code>
15.142 + * (byte)(0xff & (v >> 8))
15.143 + * (byte)(0xff & v)
15.144 + * </code> </pre> <p>
15.145 + * The bytes written by this method may be
15.146 + * read by the <code>readShort</code> method
15.147 + * of interface <code>DataInput</code> , which
15.148 + * will then return a <code>short</code> equal
15.149 + * to <code>(short)v</code>.
15.150 + *
15.151 + * @param v the <code>short</code> value to be written.
15.152 + * @throws IOException if an I/O error occurs.
15.153 + */
15.154 + void writeShort(int v) throws IOException;
15.155 +
15.156 + /**
15.157 + * Writes a <code>char</code> value, which
15.158 + * is comprised of two bytes, to the
15.159 + * output stream.
15.160 + * The byte values to be written, in the order
15.161 + * shown, are:
15.162 + * <p><pre><code>
15.163 + * (byte)(0xff & (v >> 8))
15.164 + * (byte)(0xff & v)
15.165 + * </code></pre><p>
15.166 + * The bytes written by this method may be
15.167 + * read by the <code>readChar</code> method
15.168 + * of interface <code>DataInput</code> , which
15.169 + * will then return a <code>char</code> equal
15.170 + * to <code>(char)v</code>.
15.171 + *
15.172 + * @param v the <code>char</code> value to be written.
15.173 + * @throws IOException if an I/O error occurs.
15.174 + */
15.175 + void writeChar(int v) throws IOException;
15.176 +
15.177 + /**
15.178 + * Writes an <code>int</code> value, which is
15.179 + * comprised of four bytes, to the output stream.
15.180 + * The byte values to be written, in the order
15.181 + * shown, are:
15.182 + * <p><pre><code>
15.183 + * (byte)(0xff & (v >> 24))
15.184 + * (byte)(0xff & (v >> 16))
15.185 + * (byte)(0xff & (v >>    8))
15.186 + * (byte)(0xff & v)
15.187 + * </code></pre><p>
15.188 + * The bytes written by this method may be read
15.189 + * by the <code>readInt</code> method of interface
15.190 + * <code>DataInput</code> , which will then
15.191 + * return an <code>int</code> equal to <code>v</code>.
15.192 + *
15.193 + * @param v the <code>int</code> value to be written.
15.194 + * @throws IOException if an I/O error occurs.
15.195 + */
15.196 + void writeInt(int v) throws IOException;
15.197 +
15.198 + /**
15.199 + * Writes a <code>long</code> value, which is
15.200 + * comprised of eight bytes, to the output stream.
15.201 + * The byte values to be written, in the order
15.202 + * shown, are:
15.203 + * <p><pre><code>
15.204 + * (byte)(0xff & (v >> 56))
15.205 + * (byte)(0xff & (v >> 48))
15.206 + * (byte)(0xff & (v >> 40))
15.207 + * (byte)(0xff & (v >> 32))
15.208 + * (byte)(0xff & (v >> 24))
15.209 + * (byte)(0xff & (v >> 16))
15.210 + * (byte)(0xff & (v >> 8))
15.211 + * (byte)(0xff & v)
15.212 + * </code></pre><p>
15.213 + * The bytes written by this method may be
15.214 + * read by the <code>readLong</code> method
15.215 + * of interface <code>DataInput</code> , which
15.216 + * will then return a <code>long</code> equal
15.217 + * to <code>v</code>.
15.218 + *
15.219 + * @param v the <code>long</code> value to be written.
15.220 + * @throws IOException if an I/O error occurs.
15.221 + */
15.222 + void writeLong(long v) throws IOException;
15.223 +
15.224 + /**
15.225 + * Writes a <code>float</code> value,
15.226 + * which is comprised of four bytes, to the output stream.
15.227 + * It does this as if it first converts this
15.228 + * <code>float</code> value to an <code>int</code>
15.229 + * in exactly the manner of the <code>Float.floatToIntBits</code>
15.230 + * method and then writes the <code>int</code>
15.231 + * value in exactly the manner of the <code>writeInt</code>
15.232 + * method. The bytes written by this method
15.233 + * may be read by the <code>readFloat</code>
15.234 + * method of interface <code>DataInput</code>,
15.235 + * which will then return a <code>float</code>
15.236 + * equal to <code>v</code>.
15.237 + *
15.238 + * @param v the <code>float</code> value to be written.
15.239 + * @throws IOException if an I/O error occurs.
15.240 + */
15.241 + void writeFloat(float v) throws IOException;
15.242 +
15.243 + /**
15.244 + * Writes a <code>double</code> value,
15.245 + * which is comprised of eight bytes, to the output stream.
15.246 + * It does this as if it first converts this
15.247 + * <code>double</code> value to a <code>long</code>
15.248 + * in exactly the manner of the <code>Double.doubleToLongBits</code>
15.249 + * method and then writes the <code>long</code>
15.250 + * value in exactly the manner of the <code>writeLong</code>
15.251 + * method. The bytes written by this method
15.252 + * may be read by the <code>readDouble</code>
15.253 + * method of interface <code>DataInput</code>,
15.254 + * which will then return a <code>double</code>
15.255 + * equal to <code>v</code>.
15.256 + *
15.257 + * @param v the <code>double</code> value to be written.
15.258 + * @throws IOException if an I/O error occurs.
15.259 + */
15.260 + void writeDouble(double v) throws IOException;
15.261 +
15.262 + /**
15.263 + * Writes a string to the output stream.
15.264 + * For every character in the string
15.265 + * <code>s</code>, taken in order, one byte
15.266 + * is written to the output stream. If
15.267 + * <code>s</code> is <code>null</code>, a <code>NullPointerException</code>
15.268 + * is thrown.<p> If <code>s.length</code>
15.269 + * is zero, then no bytes are written. Otherwise,
15.270 + * the character <code>s[0]</code> is written
15.271 + * first, then <code>s[1]</code>, and so on;
15.272 + * the last character written is <code>s[s.length-1]</code>.
15.273 + * For each character, one byte is written,
15.274 + * the low-order byte, in exactly the manner
15.275 + * of the <code>writeByte</code> method . The
15.276 + * high-order eight bits of each character
15.277 + * in the string are ignored.
15.278 + *
15.279 + * @param s the string of bytes to be written.
15.280 + * @throws IOException if an I/O error occurs.
15.281 + */
15.282 + void writeBytes(String s) throws IOException;
15.283 +
15.284 + /**
15.285 + * Writes every character in the string <code>s</code>,
15.286 + * to the output stream, in order,
15.287 + * two bytes per character. If <code>s</code>
15.288 + * is <code>null</code>, a <code>NullPointerException</code>
15.289 + * is thrown. If <code>s.length</code>
15.290 + * is zero, then no characters are written.
15.291 + * Otherwise, the character <code>s[0]</code>
15.292 + * is written first, then <code>s[1]</code>,
15.293 + * and so on; the last character written is
15.294 + * <code>s[s.length-1]</code>. For each character,
15.295 + * two bytes are actually written, high-order
15.296 + * byte first, in exactly the manner of the
15.297 + * <code>writeChar</code> method.
15.298 + *
15.299 + * @param s the string value to be written.
15.300 + * @throws IOException if an I/O error occurs.
15.301 + */
15.302 + void writeChars(String s) throws IOException;
15.303 +
15.304 + /**
15.305 + * Writes two bytes of length information
15.306 + * to the output stream, followed
15.307 + * by the
15.308 + * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
15.309 + * representation
15.310 + * of every character in the string <code>s</code>.
15.311 + * If <code>s</code> is <code>null</code>,
15.312 + * a <code>NullPointerException</code> is thrown.
15.313 + * Each character in the string <code>s</code>
15.314 + * is converted to a group of one, two, or
15.315 + * three bytes, depending on the value of the
15.316 + * character.<p>
15.317 + * If a character <code>c</code>
15.318 + * is in the range <code>\u0001</code> through
15.319 + * <code>\u007f</code>, it is represented
15.320 + * by one byte:<p>
15.321 + * <pre>(byte)c </pre> <p>
15.322 + * If a character <code>c</code> is <code>\u0000</code>
15.323 + * or is in the range <code>\u0080</code>
15.324 + * through <code>\u07ff</code>, then it is
15.325 + * represented by two bytes, to be written
15.326 + * in the order shown:<p> <pre><code>
15.327 + * (byte)(0xc0 | (0x1f & (c >> 6)))
15.328 + * (byte)(0x80 | (0x3f & c))
15.329 + * </code></pre> <p> If a character
15.330 + * <code>c</code> is in the range <code>\u0800</code>
15.331 + * through <code>uffff</code>, then it is
15.332 + * represented by three bytes, to be written
15.333 + * in the order shown:<p> <pre><code>
15.334 + * (byte)(0xe0 | (0x0f & (c >> 12)))
15.335 + * (byte)(0x80 | (0x3f & (c >> 6)))
15.336 + * (byte)(0x80 | (0x3f & c))
15.337 + * </code></pre> <p> First,
15.338 + * the total number of bytes needed to represent
15.339 + * all the characters of <code>s</code> is
15.340 + * calculated. If this number is larger than
15.341 + * <code>65535</code>, then a <code>UTFDataFormatException</code>
15.342 + * is thrown. Otherwise, this length is written
15.343 + * to the output stream in exactly the manner
15.344 + * of the <code>writeShort</code> method;
15.345 + * after this, the one-, two-, or three-byte
15.346 + * representation of each character in the
15.347 + * string <code>s</code> is written.<p> The
15.348 + * bytes written by this method may be read
15.349 + * by the <code>readUTF</code> method of interface
15.350 + * <code>DataInput</code> , which will then
15.351 + * return a <code>String</code> equal to <code>s</code>.
15.352 + *
15.353 + * @param s the string value to be written.
15.354 + * @throws IOException if an I/O error occurs.
15.355 + */
15.356 + void writeUTF(String s) throws IOException;
15.357 +}
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/emul/compact/src/main/java/java/io/DataOutputStream.java Tue Feb 05 17:04:22 2013 +0100
16.3 @@ -0,0 +1,416 @@
16.4 +/*
16.5 + * Copyright (c) 1994, 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 +/**
16.32 + * A data output stream lets an application write primitive Java data
16.33 + * types to an output stream in a portable way. An application can
16.34 + * then use a data input stream to read the data back in.
16.35 + *
16.36 + * @author unascribed
16.37 + * @see java.io.DataInputStream
16.38 + * @since JDK1.0
16.39 + */
16.40 +public
16.41 +class DataOutputStream extends FilterOutputStream implements DataOutput {
16.42 + /**
16.43 + * The number of bytes written to the data output stream so far.
16.44 + * If this counter overflows, it will be wrapped to Integer.MAX_VALUE.
16.45 + */
16.46 + protected int written;
16.47 +
16.48 + /**
16.49 + * bytearr is initialized on demand by writeUTF
16.50 + */
16.51 + private byte[] bytearr = null;
16.52 +
16.53 + /**
16.54 + * Creates a new data output stream to write data to the specified
16.55 + * underlying output stream. The counter <code>written</code> is
16.56 + * set to zero.
16.57 + *
16.58 + * @param out the underlying output stream, to be saved for later
16.59 + * use.
16.60 + * @see java.io.FilterOutputStream#out
16.61 + */
16.62 + public DataOutputStream(OutputStream out) {
16.63 + super(out);
16.64 + }
16.65 +
16.66 + /**
16.67 + * Increases the written counter by the specified value
16.68 + * until it reaches Integer.MAX_VALUE.
16.69 + */
16.70 + private void incCount(int value) {
16.71 + int temp = written + value;
16.72 + if (temp < 0) {
16.73 + temp = Integer.MAX_VALUE;
16.74 + }
16.75 + written = temp;
16.76 + }
16.77 +
16.78 + /**
16.79 + * Writes the specified byte (the low eight bits of the argument
16.80 + * <code>b</code>) to the underlying output stream. If no exception
16.81 + * is thrown, the counter <code>written</code> is incremented by
16.82 + * <code>1</code>.
16.83 + * <p>
16.84 + * Implements the <code>write</code> method of <code>OutputStream</code>.
16.85 + *
16.86 + * @param b the <code>byte</code> to be written.
16.87 + * @exception IOException if an I/O error occurs.
16.88 + * @see java.io.FilterOutputStream#out
16.89 + */
16.90 + public synchronized void write(int b) throws IOException {
16.91 + out.write(b);
16.92 + incCount(1);
16.93 + }
16.94 +
16.95 + /**
16.96 + * Writes <code>len</code> bytes from the specified byte array
16.97 + * starting at offset <code>off</code> to the underlying output stream.
16.98 + * If no exception is thrown, the counter <code>written</code> is
16.99 + * incremented by <code>len</code>.
16.100 + *
16.101 + * @param b the data.
16.102 + * @param off the start offset in the data.
16.103 + * @param len the number of bytes to write.
16.104 + * @exception IOException if an I/O error occurs.
16.105 + * @see java.io.FilterOutputStream#out
16.106 + */
16.107 + public synchronized void write(byte b[], int off, int len)
16.108 + throws IOException
16.109 + {
16.110 + out.write(b, off, len);
16.111 + incCount(len);
16.112 + }
16.113 +
16.114 + /**
16.115 + * Flushes this data output stream. This forces any buffered output
16.116 + * bytes to be written out to the stream.
16.117 + * <p>
16.118 + * The <code>flush</code> method of <code>DataOutputStream</code>
16.119 + * calls the <code>flush</code> method of its underlying output stream.
16.120 + *
16.121 + * @exception IOException if an I/O error occurs.
16.122 + * @see java.io.FilterOutputStream#out
16.123 + * @see java.io.OutputStream#flush()
16.124 + */
16.125 + public void flush() throws IOException {
16.126 + out.flush();
16.127 + }
16.128 +
16.129 + /**
16.130 + * Writes a <code>boolean</code> to the underlying output stream as
16.131 + * a 1-byte value. The value <code>true</code> is written out as the
16.132 + * value <code>(byte)1</code>; the value <code>false</code> is
16.133 + * written out as the value <code>(byte)0</code>. If no exception is
16.134 + * thrown, the counter <code>written</code> is incremented by
16.135 + * <code>1</code>.
16.136 + *
16.137 + * @param v a <code>boolean</code> value to be written.
16.138 + * @exception IOException if an I/O error occurs.
16.139 + * @see java.io.FilterOutputStream#out
16.140 + */
16.141 + public final void writeBoolean(boolean v) throws IOException {
16.142 + out.write(v ? 1 : 0);
16.143 + incCount(1);
16.144 + }
16.145 +
16.146 + /**
16.147 + * Writes out a <code>byte</code> to the underlying output stream as
16.148 + * a 1-byte value. If no exception is thrown, the counter
16.149 + * <code>written</code> is incremented by <code>1</code>.
16.150 + *
16.151 + * @param v a <code>byte</code> value to be written.
16.152 + * @exception IOException if an I/O error occurs.
16.153 + * @see java.io.FilterOutputStream#out
16.154 + */
16.155 + public final void writeByte(int v) throws IOException {
16.156 + out.write(v);
16.157 + incCount(1);
16.158 + }
16.159 +
16.160 + /**
16.161 + * Writes a <code>short</code> to the underlying output stream as two
16.162 + * bytes, high byte first. If no exception is thrown, the counter
16.163 + * <code>written</code> is incremented by <code>2</code>.
16.164 + *
16.165 + * @param v a <code>short</code> to be written.
16.166 + * @exception IOException if an I/O error occurs.
16.167 + * @see java.io.FilterOutputStream#out
16.168 + */
16.169 + public final void writeShort(int v) throws IOException {
16.170 + out.write((v >>> 8) & 0xFF);
16.171 + out.write((v >>> 0) & 0xFF);
16.172 + incCount(2);
16.173 + }
16.174 +
16.175 + /**
16.176 + * Writes a <code>char</code> to the underlying output stream as a
16.177 + * 2-byte value, high byte first. If no exception is thrown, the
16.178 + * counter <code>written</code> is incremented by <code>2</code>.
16.179 + *
16.180 + * @param v a <code>char</code> value to be written.
16.181 + * @exception IOException if an I/O error occurs.
16.182 + * @see java.io.FilterOutputStream#out
16.183 + */
16.184 + public final void writeChar(int v) throws IOException {
16.185 + out.write((v >>> 8) & 0xFF);
16.186 + out.write((v >>> 0) & 0xFF);
16.187 + incCount(2);
16.188 + }
16.189 +
16.190 + /**
16.191 + * Writes an <code>int</code> to the underlying output stream as four
16.192 + * bytes, high byte first. If no exception is thrown, the counter
16.193 + * <code>written</code> is incremented by <code>4</code>.
16.194 + *
16.195 + * @param v an <code>int</code> to be written.
16.196 + * @exception IOException if an I/O error occurs.
16.197 + * @see java.io.FilterOutputStream#out
16.198 + */
16.199 + public final void writeInt(int v) throws IOException {
16.200 + out.write((v >>> 24) & 0xFF);
16.201 + out.write((v >>> 16) & 0xFF);
16.202 + out.write((v >>> 8) & 0xFF);
16.203 + out.write((v >>> 0) & 0xFF);
16.204 + incCount(4);
16.205 + }
16.206 +
16.207 + private byte writeBuffer[] = new byte[8];
16.208 +
16.209 + /**
16.210 + * Writes a <code>long</code> to the underlying output stream as eight
16.211 + * bytes, high byte first. In no exception is thrown, the counter
16.212 + * <code>written</code> is incremented by <code>8</code>.
16.213 + *
16.214 + * @param v a <code>long</code> to be written.
16.215 + * @exception IOException if an I/O error occurs.
16.216 + * @see java.io.FilterOutputStream#out
16.217 + */
16.218 + public final void writeLong(long v) throws IOException {
16.219 + writeBuffer[0] = (byte)(v >>> 56);
16.220 + writeBuffer[1] = (byte)(v >>> 48);
16.221 + writeBuffer[2] = (byte)(v >>> 40);
16.222 + writeBuffer[3] = (byte)(v >>> 32);
16.223 + writeBuffer[4] = (byte)(v >>> 24);
16.224 + writeBuffer[5] = (byte)(v >>> 16);
16.225 + writeBuffer[6] = (byte)(v >>> 8);
16.226 + writeBuffer[7] = (byte)(v >>> 0);
16.227 + out.write(writeBuffer, 0, 8);
16.228 + incCount(8);
16.229 + }
16.230 +
16.231 + /**
16.232 + * Converts the float argument to an <code>int</code> using the
16.233 + * <code>floatToIntBits</code> method in class <code>Float</code>,
16.234 + * and then writes that <code>int</code> value to the underlying
16.235 + * output stream as a 4-byte quantity, high byte first. If no
16.236 + * exception is thrown, the counter <code>written</code> is
16.237 + * incremented by <code>4</code>.
16.238 + *
16.239 + * @param v a <code>float</code> value to be written.
16.240 + * @exception IOException if an I/O error occurs.
16.241 + * @see java.io.FilterOutputStream#out
16.242 + * @see java.lang.Float#floatToIntBits(float)
16.243 + */
16.244 + public final void writeFloat(float v) throws IOException {
16.245 + writeInt(Float.floatToIntBits(v));
16.246 + }
16.247 +
16.248 + /**
16.249 + * Converts the double argument to a <code>long</code> using the
16.250 + * <code>doubleToLongBits</code> method in class <code>Double</code>,
16.251 + * and then writes that <code>long</code> value to the underlying
16.252 + * output stream as an 8-byte quantity, high byte first. If no
16.253 + * exception is thrown, the counter <code>written</code> is
16.254 + * incremented by <code>8</code>.
16.255 + *
16.256 + * @param v a <code>double</code> value to be written.
16.257 + * @exception IOException if an I/O error occurs.
16.258 + * @see java.io.FilterOutputStream#out
16.259 + * @see java.lang.Double#doubleToLongBits(double)
16.260 + */
16.261 + public final void writeDouble(double v) throws IOException {
16.262 + writeLong(Double.doubleToLongBits(v));
16.263 + }
16.264 +
16.265 + /**
16.266 + * Writes out the string to the underlying output stream as a
16.267 + * sequence of bytes. Each character in the string is written out, in
16.268 + * sequence, by discarding its high eight bits. If no exception is
16.269 + * thrown, the counter <code>written</code> is incremented by the
16.270 + * length of <code>s</code>.
16.271 + *
16.272 + * @param s a string of bytes to be written.
16.273 + * @exception IOException if an I/O error occurs.
16.274 + * @see java.io.FilterOutputStream#out
16.275 + */
16.276 + public final void writeBytes(String s) throws IOException {
16.277 + int len = s.length();
16.278 + for (int i = 0 ; i < len ; i++) {
16.279 + out.write((byte)s.charAt(i));
16.280 + }
16.281 + incCount(len);
16.282 + }
16.283 +
16.284 + /**
16.285 + * Writes a string to the underlying output stream as a sequence of
16.286 + * characters. Each character is written to the data output stream as
16.287 + * if by the <code>writeChar</code> method. If no exception is
16.288 + * thrown, the counter <code>written</code> is incremented by twice
16.289 + * the length of <code>s</code>.
16.290 + *
16.291 + * @param s a <code>String</code> value to be written.
16.292 + * @exception IOException if an I/O error occurs.
16.293 + * @see java.io.DataOutputStream#writeChar(int)
16.294 + * @see java.io.FilterOutputStream#out
16.295 + */
16.296 + public final void writeChars(String s) throws IOException {
16.297 + int len = s.length();
16.298 + for (int i = 0 ; i < len ; i++) {
16.299 + int v = s.charAt(i);
16.300 + out.write((v >>> 8) & 0xFF);
16.301 + out.write((v >>> 0) & 0xFF);
16.302 + }
16.303 + incCount(len * 2);
16.304 + }
16.305 +
16.306 + /**
16.307 + * Writes a string to the underlying output stream using
16.308 + * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
16.309 + * encoding in a machine-independent manner.
16.310 + * <p>
16.311 + * First, two bytes are written to the output stream as if by the
16.312 + * <code>writeShort</code> method giving the number of bytes to
16.313 + * follow. This value is the number of bytes actually written out,
16.314 + * not the length of the string. Following the length, each character
16.315 + * of the string is output, in sequence, using the modified UTF-8 encoding
16.316 + * for the character. If no exception is thrown, the counter
16.317 + * <code>written</code> is incremented by the total number of
16.318 + * bytes written to the output stream. This will be at least two
16.319 + * plus the length of <code>str</code>, and at most two plus
16.320 + * thrice the length of <code>str</code>.
16.321 + *
16.322 + * @param str a string to be written.
16.323 + * @exception IOException if an I/O error occurs.
16.324 + */
16.325 + public final void writeUTF(String str) throws IOException {
16.326 + writeUTF(str, this);
16.327 + }
16.328 +
16.329 + /**
16.330 + * Writes a string to the specified DataOutput using
16.331 + * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
16.332 + * encoding in a machine-independent manner.
16.333 + * <p>
16.334 + * First, two bytes are written to out as if by the <code>writeShort</code>
16.335 + * method giving the number of bytes to follow. This value is the number of
16.336 + * bytes actually written out, not the length of the string. Following the
16.337 + * length, each character of the string is output, in sequence, using the
16.338 + * modified UTF-8 encoding for the character. If no exception is thrown, the
16.339 + * counter <code>written</code> is incremented by the total number of
16.340 + * bytes written to the output stream. This will be at least two
16.341 + * plus the length of <code>str</code>, and at most two plus
16.342 + * thrice the length of <code>str</code>.
16.343 + *
16.344 + * @param str a string to be written.
16.345 + * @param out destination to write to
16.346 + * @return The number of bytes written out.
16.347 + * @exception IOException if an I/O error occurs.
16.348 + */
16.349 + static int writeUTF(String str, DataOutput out) throws IOException {
16.350 + int strlen = str.length();
16.351 + int utflen = 0;
16.352 + int c, count = 0;
16.353 +
16.354 + /* use charAt instead of copying String to char array */
16.355 + for (int i = 0; i < strlen; i++) {
16.356 + c = str.charAt(i);
16.357 + if ((c >= 0x0001) && (c <= 0x007F)) {
16.358 + utflen++;
16.359 + } else if (c > 0x07FF) {
16.360 + utflen += 3;
16.361 + } else {
16.362 + utflen += 2;
16.363 + }
16.364 + }
16.365 +
16.366 + if (utflen > 65535)
16.367 + throw new UTFDataFormatException(
16.368 + "encoded string too long: " + utflen + " bytes");
16.369 +
16.370 + byte[] bytearr = null;
16.371 + if (out instanceof DataOutputStream) {
16.372 + DataOutputStream dos = (DataOutputStream)out;
16.373 + if(dos.bytearr == null || (dos.bytearr.length < (utflen+2)))
16.374 + dos.bytearr = new byte[(utflen*2) + 2];
16.375 + bytearr = dos.bytearr;
16.376 + } else {
16.377 + bytearr = new byte[utflen+2];
16.378 + }
16.379 +
16.380 + bytearr[count++] = (byte) ((utflen >>> 8) & 0xFF);
16.381 + bytearr[count++] = (byte) ((utflen >>> 0) & 0xFF);
16.382 +
16.383 + int i=0;
16.384 + for (i=0; i<strlen; i++) {
16.385 + c = str.charAt(i);
16.386 + if (!((c >= 0x0001) && (c <= 0x007F))) break;
16.387 + bytearr[count++] = (byte) c;
16.388 + }
16.389 +
16.390 + for (;i < strlen; i++){
16.391 + c = str.charAt(i);
16.392 + if ((c >= 0x0001) && (c <= 0x007F)) {
16.393 + bytearr[count++] = (byte) c;
16.394 +
16.395 + } else if (c > 0x07FF) {
16.396 + bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
16.397 + bytearr[count++] = (byte) (0x80 | ((c >> 6) & 0x3F));
16.398 + bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
16.399 + } else {
16.400 + bytearr[count++] = (byte) (0xC0 | ((c >> 6) & 0x1F));
16.401 + bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
16.402 + }
16.403 + }
16.404 + out.write(bytearr, 0, utflen+2);
16.405 + return utflen + 2;
16.406 + }
16.407 +
16.408 + /**
16.409 + * Returns the current value of the counter <code>written</code>,
16.410 + * the number of bytes written to this data output stream so far.
16.411 + * If the counter overflows, it will be wrapped to Integer.MAX_VALUE.
16.412 + *
16.413 + * @return the value of the <code>written</code> field.
16.414 + * @see java.io.DataOutputStream#written
16.415 + */
16.416 + public final int size() {
16.417 + return written;
16.418 + }
16.419 +}
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/emul/compact/src/main/java/java/io/Externalizable.java Tue Feb 05 17:04:22 2013 +0100
17.3 @@ -0,0 +1,97 @@
17.4 +/*
17.5 + * Copyright (c) 1996, 2004, 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 +import java.io.ObjectOutput;
17.32 +import java.io.ObjectInput;
17.33 +
17.34 +/**
17.35 + * Only the identity of the class of an Externalizable instance is
17.36 + * written in the serialization stream and it is the responsibility
17.37 + * of the class to save and restore the contents of its instances.
17.38 + *
17.39 + * The writeExternal and readExternal methods of the Externalizable
17.40 + * interface are implemented by a class to give the class complete
17.41 + * control over the format and contents of the stream for an object
17.42 + * and its supertypes. These methods must explicitly
17.43 + * coordinate with the supertype to save its state. These methods supersede
17.44 + * customized implementations of writeObject and readObject methods.<br>
17.45 + *
17.46 + * Object Serialization uses the Serializable and Externalizable
17.47 + * interfaces. Object persistence mechanisms can use them as well. Each
17.48 + * object to be stored is tested for the Externalizable interface. If
17.49 + * the object supports Externalizable, the writeExternal method is called. If the
17.50 + * object does not support Externalizable and does implement
17.51 + * Serializable, the object is saved using
17.52 + * ObjectOutputStream. <br> When an Externalizable object is
17.53 + * reconstructed, an instance is created using the public no-arg
17.54 + * constructor, then the readExternal method called. Serializable
17.55 + * objects are restored by reading them from an ObjectInputStream.<br>
17.56 + *
17.57 + * An Externalizable instance can designate a substitution object via
17.58 + * the writeReplace and readResolve methods documented in the Serializable
17.59 + * interface.<br>
17.60 + *
17.61 + * @author unascribed
17.62 + * @see java.io.ObjectOutputStream
17.63 + * @see java.io.ObjectInputStream
17.64 + * @see java.io.ObjectOutput
17.65 + * @see java.io.ObjectInput
17.66 + * @see java.io.Serializable
17.67 + * @since JDK1.1
17.68 + */
17.69 +public interface Externalizable extends java.io.Serializable {
17.70 + /**
17.71 + * The object implements the writeExternal method to save its contents
17.72 + * by calling the methods of DataOutput for its primitive values or
17.73 + * calling the writeObject method of ObjectOutput for objects, strings,
17.74 + * and arrays.
17.75 + *
17.76 + * @serialData Overriding methods should use this tag to describe
17.77 + * the data layout of this Externalizable object.
17.78 + * List the sequence of element types and, if possible,
17.79 + * relate the element to a public/protected field and/or
17.80 + * method of this Externalizable class.
17.81 + *
17.82 + * @param out the stream to write the object to
17.83 + * @exception IOException Includes any I/O exceptions that may occur
17.84 + */
17.85 + void writeExternal(ObjectOutput out) throws IOException;
17.86 +
17.87 + /**
17.88 + * The object implements the readExternal method to restore its
17.89 + * contents by calling the methods of DataInput for primitive
17.90 + * types and readObject for objects, strings and arrays. The
17.91 + * readExternal method must read the values in the same sequence
17.92 + * and with the same types as were written by writeExternal.
17.93 + *
17.94 + * @param in the stream to read data from in order to restore the object
17.95 + * @exception IOException if I/O errors occur
17.96 + * @exception ClassNotFoundException If the class for an object being
17.97 + * restored cannot be found.
17.98 + */
17.99 + void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
17.100 +}
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
18.2 +++ b/emul/compact/src/main/java/java/io/FilterOutputStream.java Tue Feb 05 17:04:22 2013 +0100
18.3 @@ -0,0 +1,162 @@
18.4 +/*
18.5 + * Copyright (c) 1994, 2011, 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 + * This class is the superclass of all classes that filter output
18.33 + * streams. These streams sit on top of an already existing output
18.34 + * stream (the <i>underlying</i> output stream) which it uses as its
18.35 + * basic sink of data, but possibly transforming the data along the
18.36 + * way or providing additional functionality.
18.37 + * <p>
18.38 + * The class <code>FilterOutputStream</code> itself simply overrides
18.39 + * all methods of <code>OutputStream</code> with versions that pass
18.40 + * all requests to the underlying output stream. Subclasses of
18.41 + * <code>FilterOutputStream</code> may further override some of these
18.42 + * methods as well as provide additional methods and fields.
18.43 + *
18.44 + * @author Jonathan Payne
18.45 + * @since JDK1.0
18.46 + */
18.47 +public
18.48 +class FilterOutputStream extends OutputStream {
18.49 + /**
18.50 + * The underlying output stream to be filtered.
18.51 + */
18.52 + protected OutputStream out;
18.53 +
18.54 + /**
18.55 + * Creates an output stream filter built on top of the specified
18.56 + * underlying output stream.
18.57 + *
18.58 + * @param out the underlying output stream to be assigned to
18.59 + * the field <tt>this.out</tt> for later use, or
18.60 + * <code>null</code> if this instance is to be
18.61 + * created without an underlying stream.
18.62 + */
18.63 + public FilterOutputStream(OutputStream out) {
18.64 + this.out = out;
18.65 + }
18.66 +
18.67 + /**
18.68 + * Writes the specified <code>byte</code> to this output stream.
18.69 + * <p>
18.70 + * The <code>write</code> method of <code>FilterOutputStream</code>
18.71 + * calls the <code>write</code> method of its underlying output stream,
18.72 + * that is, it performs <tt>out.write(b)</tt>.
18.73 + * <p>
18.74 + * Implements the abstract <tt>write</tt> method of <tt>OutputStream</tt>.
18.75 + *
18.76 + * @param b the <code>byte</code>.
18.77 + * @exception IOException if an I/O error occurs.
18.78 + */
18.79 + public void write(int b) throws IOException {
18.80 + out.write(b);
18.81 + }
18.82 +
18.83 + /**
18.84 + * Writes <code>b.length</code> bytes to this output stream.
18.85 + * <p>
18.86 + * The <code>write</code> method of <code>FilterOutputStream</code>
18.87 + * calls its <code>write</code> method of three arguments with the
18.88 + * arguments <code>b</code>, <code>0</code>, and
18.89 + * <code>b.length</code>.
18.90 + * <p>
18.91 + * Note that this method does not call the one-argument
18.92 + * <code>write</code> method of its underlying stream with the single
18.93 + * argument <code>b</code>.
18.94 + *
18.95 + * @param b the data to be written.
18.96 + * @exception IOException if an I/O error occurs.
18.97 + * @see java.io.FilterOutputStream#write(byte[], int, int)
18.98 + */
18.99 + public void write(byte b[]) throws IOException {
18.100 + write(b, 0, b.length);
18.101 + }
18.102 +
18.103 + /**
18.104 + * Writes <code>len</code> bytes from the specified
18.105 + * <code>byte</code> array starting at offset <code>off</code> to
18.106 + * this output stream.
18.107 + * <p>
18.108 + * The <code>write</code> method of <code>FilterOutputStream</code>
18.109 + * calls the <code>write</code> method of one argument on each
18.110 + * <code>byte</code> to output.
18.111 + * <p>
18.112 + * Note that this method does not call the <code>write</code> method
18.113 + * of its underlying input stream with the same arguments. Subclasses
18.114 + * of <code>FilterOutputStream</code> should provide a more efficient
18.115 + * implementation of this method.
18.116 + *
18.117 + * @param b the data.
18.118 + * @param off the start offset in the data.
18.119 + * @param len the number of bytes to write.
18.120 + * @exception IOException if an I/O error occurs.
18.121 + * @see java.io.FilterOutputStream#write(int)
18.122 + */
18.123 + public void write(byte b[], int off, int len) throws IOException {
18.124 + if ((off | len | (b.length - (len + off)) | (off + len)) < 0)
18.125 + throw new IndexOutOfBoundsException();
18.126 +
18.127 + for (int i = 0 ; i < len ; i++) {
18.128 + write(b[off + i]);
18.129 + }
18.130 + }
18.131 +
18.132 + /**
18.133 + * Flushes this output stream and forces any buffered output bytes
18.134 + * to be written out to the stream.
18.135 + * <p>
18.136 + * The <code>flush</code> method of <code>FilterOutputStream</code>
18.137 + * calls the <code>flush</code> method of its underlying output stream.
18.138 + *
18.139 + * @exception IOException if an I/O error occurs.
18.140 + * @see java.io.FilterOutputStream#out
18.141 + */
18.142 + public void flush() throws IOException {
18.143 + out.flush();
18.144 + }
18.145 +
18.146 + /**
18.147 + * Closes this output stream and releases any system resources
18.148 + * associated with the stream.
18.149 + * <p>
18.150 + * The <code>close</code> method of <code>FilterOutputStream</code>
18.151 + * calls its <code>flush</code> method, and then calls the
18.152 + * <code>close</code> method of its underlying output stream.
18.153 + *
18.154 + * @exception IOException if an I/O error occurs.
18.155 + * @see java.io.FilterOutputStream#flush()
18.156 + * @see java.io.FilterOutputStream#out
18.157 + */
18.158 + public void close() throws IOException {
18.159 + try {
18.160 + flush();
18.161 + } catch (IOException ignored) {
18.162 + }
18.163 + out.close();
18.164 + }
18.165 +}
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
19.2 +++ b/emul/compact/src/main/java/java/io/Flushable.java Tue Feb 05 17:04:22 2013 +0100
19.3 @@ -0,0 +1,47 @@
19.4 +/*
19.5 + * Copyright (c) 2004, 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 +import java.io.IOException;
19.32 +
19.33 +/**
19.34 + * A <tt>Flushable</tt> is a destination of data that can be flushed. The
19.35 + * flush method is invoked to write any buffered output to the underlying
19.36 + * stream.
19.37 + *
19.38 + * @since 1.5
19.39 + */
19.40 +
19.41 +public interface Flushable {
19.42 +
19.43 + /**
19.44 + * Flushes this stream by writing any buffered output to the underlying
19.45 + * stream.
19.46 + *
19.47 + * @throws IOException If an I/O error occurs
19.48 + */
19.49 + void flush() throws IOException;
19.50 +}
20.1 --- a/emul/compact/src/main/java/java/io/InputStreamReader.java Tue Feb 05 16:40:01 2013 +0100
20.2 +++ b/emul/compact/src/main/java/java/io/InputStreamReader.java Tue Feb 05 17:04:22 2013 +0100
20.3 @@ -156,9 +156,39 @@
20.4 * @exception IOException If an I/O error occurs
20.5 */
20.6 public int read() throws IOException {
20.7 - return ((InputStream)lock).read();
20.8 + final InputStream is = (InputStream)lock;
20.9 + int c = is.read();
20.10 + if (c == -1) {
20.11 + return -1;
20.12 + }
20.13 + c = (int) c & 0xff;
20.14 + switch (c >> 4) {
20.15 + case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
20.16 + /* 0xxxxxxx*/
20.17 + return c;
20.18 + case 12: case 13: {
20.19 + /* 110x xxxx 10xx xxxx*/
20.20 + int char2 = (int) is.read();
20.21 + if ((char2 & 0xC0) != 0x80)
20.22 + throw new UTFDataFormatException("malformed input");
20.23 + return (((c & 0x1F) << 6) | (char2 & 0x3F));
20.24 + }
20.25 + case 14: {
20.26 + /* 1110 xxxx 10xx xxxx 10xx xxxx */
20.27 + int char2 = is.read();
20.28 + int char3 = is.read();
20.29 + if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
20.30 + throw new UTFDataFormatException("malformed input");
20.31 + return (((c & 0x0F) << 12) |
20.32 + ((char2 & 0x3F) << 6) |
20.33 + ((char3 & 0x3F) << 0));
20.34 + }
20.35 + default:
20.36 + /* 10xx xxxx, 1111 xxxx */
20.37 + throw new UTFDataFormatException("malformed input");
20.38 + }
20.39 }
20.40 -
20.41 +
20.42 /**
20.43 * Reads characters into a portion of an array.
20.44 *
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/emul/compact/src/main/java/java/io/InvalidClassException.java Tue Feb 05 17:04:22 2013 +0100
21.3 @@ -0,0 +1,81 @@
21.4 +/*
21.5 + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
21.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
21.7 + *
21.8 + * This code is free software; you can redistribute it and/or modify it
21.9 + * under the terms of the GNU General Public License version 2 only, as
21.10 + * published by the Free Software Foundation. Oracle designates this
21.11 + * particular file as subject to the "Classpath" exception as provided
21.12 + * by Oracle in the LICENSE file that accompanied this code.
21.13 + *
21.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
21.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21.17 + * version 2 for more details (a copy is included in the LICENSE file that
21.18 + * accompanied this code).
21.19 + *
21.20 + * You should have received a copy of the GNU General Public License version
21.21 + * 2 along with this work; if not, write to the Free Software Foundation,
21.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21.23 + *
21.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21.25 + * or visit www.oracle.com if you need additional information or have any
21.26 + * questions.
21.27 + */
21.28 +
21.29 +package java.io;
21.30 +
21.31 +/**
21.32 + * Thrown when the Serialization runtime detects one of the following
21.33 + * problems with a Class.
21.34 + * <UL>
21.35 + * <LI> The serial version of the class does not match that of the class
21.36 + * descriptor read from the stream
21.37 + * <LI> The class contains unknown datatypes
21.38 + * <LI> The class does not have an accessible no-arg constructor
21.39 + * </UL>
21.40 + *
21.41 + * @author unascribed
21.42 + * @since JDK1.1
21.43 + */
21.44 +public class InvalidClassException extends ObjectStreamException {
21.45 +
21.46 + private static final long serialVersionUID = -4333316296251054416L;
21.47 +
21.48 + /**
21.49 + * Name of the invalid class.
21.50 + *
21.51 + * @serial Name of the invalid class.
21.52 + */
21.53 + public String classname;
21.54 +
21.55 + /**
21.56 + * Report an InvalidClassException for the reason specified.
21.57 + *
21.58 + * @param reason String describing the reason for the exception.
21.59 + */
21.60 + public InvalidClassException(String reason) {
21.61 + super(reason);
21.62 + }
21.63 +
21.64 + /**
21.65 + * Constructs an InvalidClassException object.
21.66 + *
21.67 + * @param cname a String naming the invalid class.
21.68 + * @param reason a String describing the reason for the exception.
21.69 + */
21.70 + public InvalidClassException(String cname, String reason) {
21.71 + super(reason);
21.72 + classname = cname;
21.73 + }
21.74 +
21.75 + /**
21.76 + * Produce the message and include the classname, if present.
21.77 + */
21.78 + public String getMessage() {
21.79 + if (classname == null)
21.80 + return super.getMessage();
21.81 + else
21.82 + return classname + "; " + super.getMessage();
21.83 + }
21.84 +}
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
22.2 +++ b/emul/compact/src/main/java/java/io/InvalidObjectException.java Tue Feb 05 17:04:22 2013 +0100
22.3 @@ -0,0 +1,51 @@
22.4 +/*
22.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
22.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
22.7 + *
22.8 + * This code is free software; you can redistribute it and/or modify it
22.9 + * under the terms of the GNU General Public License version 2 only, as
22.10 + * published by the Free Software Foundation. Oracle designates this
22.11 + * particular file as subject to the "Classpath" exception as provided
22.12 + * by Oracle in the LICENSE file that accompanied this code.
22.13 + *
22.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
22.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22.17 + * version 2 for more details (a copy is included in the LICENSE file that
22.18 + * accompanied this code).
22.19 + *
22.20 + * You should have received a copy of the GNU General Public License version
22.21 + * 2 along with this work; if not, write to the Free Software Foundation,
22.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22.23 + *
22.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22.25 + * or visit www.oracle.com if you need additional information or have any
22.26 + * questions.
22.27 + */
22.28 +
22.29 +package java.io;
22.30 +
22.31 +/**
22.32 + * Indicates that one or more deserialized objects failed validation
22.33 + * tests. The argument should provide the reason for the failure.
22.34 + *
22.35 + * @see ObjectInputValidation
22.36 + * @since JDK1.1
22.37 + *
22.38 + * @author unascribed
22.39 + * @since JDK1.1
22.40 + */
22.41 +public class InvalidObjectException extends ObjectStreamException {
22.42 +
22.43 + private static final long serialVersionUID = 3233174318281839583L;
22.44 +
22.45 + /**
22.46 + * Constructs an <code>InvalidObjectException</code>.
22.47 + * @param reason Detailed message explaining the reason for the failure.
22.48 + *
22.49 + * @see ObjectInputValidation
22.50 + */
22.51 + public InvalidObjectException(String reason) {
22.52 + super(reason);
22.53 + }
22.54 +}
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
23.2 +++ b/emul/compact/src/main/java/java/io/NotActiveException.java Tue Feb 05 17:04:22 2013 +0100
23.3 @@ -0,0 +1,53 @@
23.4 +/*
23.5 + * Copyright (c) 1996, 2005, 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 + * Thrown when serialization or deserialization is not active.
23.33 + *
23.34 + * @author unascribed
23.35 + * @since JDK1.1
23.36 + */
23.37 +public class NotActiveException extends ObjectStreamException {
23.38 +
23.39 + private static final long serialVersionUID = -3893467273049808895L;
23.40 +
23.41 + /**
23.42 + * Constructor to create a new NotActiveException with the reason given.
23.43 + *
23.44 + * @param reason a String describing the reason for the exception.
23.45 + */
23.46 + public NotActiveException(String reason) {
23.47 + super(reason);
23.48 + }
23.49 +
23.50 + /**
23.51 + * Constructor to create a new NotActiveException without a reason.
23.52 + */
23.53 + public NotActiveException() {
23.54 + super();
23.55 + }
23.56 +}
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
24.2 +++ b/emul/compact/src/main/java/java/io/NotSerializableException.java Tue Feb 05 17:04:22 2013 +0100
24.3 @@ -0,0 +1,55 @@
24.4 +/*
24.5 + * Copyright (c) 1996, 2005, 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 + * Thrown when an instance is required to have a Serializable interface.
24.33 + * The serialization runtime or the class of the instance can throw
24.34 + * this exception. The argument should be the name of the class.
24.35 + *
24.36 + * @author unascribed
24.37 + * @since JDK1.1
24.38 + */
24.39 +public class NotSerializableException extends ObjectStreamException {
24.40 +
24.41 + private static final long serialVersionUID = 2906642554793891381L;
24.42 +
24.43 + /**
24.44 + * Constructs a NotSerializableException object with message string.
24.45 + *
24.46 + * @param classname Class of the instance being serialized/deserialized.
24.47 + */
24.48 + public NotSerializableException(String classname) {
24.49 + super(classname);
24.50 + }
24.51 +
24.52 + /**
24.53 + * Constructs a NotSerializableException object.
24.54 + */
24.55 + public NotSerializableException() {
24.56 + super();
24.57 + }
24.58 +}
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
25.2 +++ b/emul/compact/src/main/java/java/io/ObjectInput.java Tue Feb 05 17:04:22 2013 +0100
25.3 @@ -0,0 +1,107 @@
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 +/**
25.32 + * ObjectInput extends the DataInput interface to include the reading of
25.33 + * objects. DataInput includes methods for the input of primitive types,
25.34 + * ObjectInput extends that interface to include objects, arrays, and Strings.
25.35 + *
25.36 + * @author unascribed
25.37 + * @see java.io.InputStream
25.38 + * @see java.io.ObjectOutputStream
25.39 + * @see java.io.ObjectInputStream
25.40 + * @since JDK1.1
25.41 + */
25.42 +public interface ObjectInput extends DataInput, AutoCloseable {
25.43 + /**
25.44 + * Read and return an object. The class that implements this interface
25.45 + * defines where the object is "read" from.
25.46 + *
25.47 + * @return the object read from the stream
25.48 + * @exception java.lang.ClassNotFoundException If the class of a serialized
25.49 + * object cannot be found.
25.50 + * @exception IOException If any of the usual Input/Output
25.51 + * related exceptions occur.
25.52 + */
25.53 + public Object readObject()
25.54 + throws ClassNotFoundException, IOException;
25.55 +
25.56 + /**
25.57 + * Reads a byte of data. This method will block if no input is
25.58 + * available.
25.59 + * @return the byte read, or -1 if the end of the
25.60 + * stream is reached.
25.61 + * @exception IOException If an I/O error has occurred.
25.62 + */
25.63 + public int read() throws IOException;
25.64 +
25.65 + /**
25.66 + * Reads into an array of bytes. This method will
25.67 + * block until some input is available.
25.68 + * @param b the buffer into which the data is read
25.69 + * @return the actual number of bytes read, -1 is
25.70 + * returned when the end of the stream is reached.
25.71 + * @exception IOException If an I/O error has occurred.
25.72 + */
25.73 + public int read(byte b[]) throws IOException;
25.74 +
25.75 + /**
25.76 + * Reads into an array of bytes. This method will
25.77 + * block until some input is available.
25.78 + * @param b the buffer into which the data is read
25.79 + * @param off the start offset of the data
25.80 + * @param len the maximum number of bytes read
25.81 + * @return the actual number of bytes read, -1 is
25.82 + * returned when the end of the stream is reached.
25.83 + * @exception IOException If an I/O error has occurred.
25.84 + */
25.85 + public int read(byte b[], int off, int len) throws IOException;
25.86 +
25.87 + /**
25.88 + * Skips n bytes of input.
25.89 + * @param n the number of bytes to be skipped
25.90 + * @return the actual number of bytes skipped.
25.91 + * @exception IOException If an I/O error has occurred.
25.92 + */
25.93 + public long skip(long n) throws IOException;
25.94 +
25.95 + /**
25.96 + * Returns the number of bytes that can be read
25.97 + * without blocking.
25.98 + * @return the number of available bytes.
25.99 + * @exception IOException If an I/O error has occurred.
25.100 + */
25.101 + public int available() throws IOException;
25.102 +
25.103 + /**
25.104 + * Closes the input stream. Must be called
25.105 + * to release any resources associated with
25.106 + * the stream.
25.107 + * @exception IOException If an I/O error has occurred.
25.108 + */
25.109 + public void close() throws IOException;
25.110 +}
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
26.2 +++ b/emul/compact/src/main/java/java/io/ObjectInputStream.java Tue Feb 05 17:04:22 2013 +0100
26.3 @@ -0,0 +1,3357 @@
26.4 +/*
26.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
26.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
26.7 + *
26.8 + * This code is free software; you can redistribute it and/or modify it
26.9 + * under the terms of the GNU General Public License version 2 only, as
26.10 + * published by the Free Software Foundation. Oracle designates this
26.11 + * particular file as subject to the "Classpath" exception as provided
26.12 + * by Oracle in the LICENSE file that accompanied this code.
26.13 + *
26.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
26.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
26.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26.17 + * version 2 for more details (a copy is included in the LICENSE file that
26.18 + * accompanied this code).
26.19 + *
26.20 + * You should have received a copy of the GNU General Public License version
26.21 + * 2 along with this work; if not, write to the Free Software Foundation,
26.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26.23 + *
26.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
26.25 + * or visit www.oracle.com if you need additional information or have any
26.26 + * questions.
26.27 + */
26.28 +
26.29 +package java.io;
26.30 +
26.31 +import java.lang.reflect.Array;
26.32 +import java.lang.reflect.Modifier;
26.33 +import java.lang.reflect.Proxy;
26.34 +import java.util.Arrays;
26.35 +import java.util.HashMap;
26.36 +import org.apidesign.bck2brwsr.emul.lang.System;
26.37 +
26.38 +/**
26.39 + * An ObjectInputStream deserializes primitive data and objects previously
26.40 + * written using an ObjectOutputStream.
26.41 + *
26.42 + * <p>ObjectOutputStream and ObjectInputStream can provide an application with
26.43 + * persistent storage for graphs of objects when used with a FileOutputStream
26.44 + * and FileInputStream respectively. ObjectInputStream is used to recover
26.45 + * those objects previously serialized. Other uses include passing objects
26.46 + * between hosts using a socket stream or for marshaling and unmarshaling
26.47 + * arguments and parameters in a remote communication system.
26.48 + *
26.49 + * <p>ObjectInputStream ensures that the types of all objects in the graph
26.50 + * created from the stream match the classes present in the Java Virtual
26.51 + * Machine. Classes are loaded as required using the standard mechanisms.
26.52 + *
26.53 + * <p>Only objects that support the java.io.Serializable or
26.54 + * java.io.Externalizable interface can be read from streams.
26.55 + *
26.56 + * <p>The method <code>readObject</code> is used to read an object from the
26.57 + * stream. Java's safe casting should be used to get the desired type. In
26.58 + * Java, strings and arrays are objects and are treated as objects during
26.59 + * serialization. When read they need to be cast to the expected type.
26.60 + *
26.61 + * <p>Primitive data types can be read from the stream using the appropriate
26.62 + * method on DataInput.
26.63 + *
26.64 + * <p>The default deserialization mechanism for objects restores the contents
26.65 + * of each field to the value and type it had when it was written. Fields
26.66 + * declared as transient or static are ignored by the deserialization process.
26.67 + * References to other objects cause those objects to be read from the stream
26.68 + * as necessary. Graphs of objects are restored correctly using a reference
26.69 + * sharing mechanism. New objects are always allocated when deserializing,
26.70 + * which prevents existing objects from being overwritten.
26.71 + *
26.72 + * <p>Reading an object is analogous to running the constructors of a new
26.73 + * object. Memory is allocated for the object and initialized to zero (NULL).
26.74 + * No-arg constructors are invoked for the non-serializable classes and then
26.75 + * the fields of the serializable classes are restored from the stream starting
26.76 + * with the serializable class closest to java.lang.object and finishing with
26.77 + * the object's most specific class.
26.78 + *
26.79 + * <p>For example to read from a stream as written by the example in
26.80 + * ObjectOutputStream:
26.81 + * <br>
26.82 + * <pre>
26.83 + * FileInputStream fis = new FileInputStream("t.tmp");
26.84 + * ObjectInputStream ois = new ObjectInputStream(fis);
26.85 + *
26.86 + * int i = ois.readInt();
26.87 + * String today = (String) ois.readObject();
26.88 + * Date date = (Date) ois.readObject();
26.89 + *
26.90 + * ois.close();
26.91 + * </pre>
26.92 + *
26.93 + * <p>Classes control how they are serialized by implementing either the
26.94 + * java.io.Serializable or java.io.Externalizable interfaces.
26.95 + *
26.96 + * <p>Implementing the Serializable interface allows object serialization to
26.97 + * save and restore the entire state of the object and it allows classes to
26.98 + * evolve between the time the stream is written and the time it is read. It
26.99 + * automatically traverses references between objects, saving and restoring
26.100 + * entire graphs.
26.101 + *
26.102 + * <p>Serializable classes that require special handling during the
26.103 + * serialization and deserialization process should implement the following
26.104 + * methods:<p>
26.105 + *
26.106 + * <pre>
26.107 + * private void writeObject(java.io.ObjectOutputStream stream)
26.108 + * throws IOException;
26.109 + * private void readObject(java.io.ObjectInputStream stream)
26.110 + * throws IOException, ClassNotFoundException;
26.111 + * private void readObjectNoData()
26.112 + * throws ObjectStreamException;
26.113 + * </pre>
26.114 + *
26.115 + * <p>The readObject method is responsible for reading and restoring the state
26.116 + * of the object for its particular class using data written to the stream by
26.117 + * the corresponding writeObject method. The method does not need to concern
26.118 + * itself with the state belonging to its superclasses or subclasses. State is
26.119 + * restored by reading data from the ObjectInputStream for the individual
26.120 + * fields and making assignments to the appropriate fields of the object.
26.121 + * Reading primitive data types is supported by DataInput.
26.122 + *
26.123 + * <p>Any attempt to read object data which exceeds the boundaries of the
26.124 + * custom data written by the corresponding writeObject method will cause an
26.125 + * OptionalDataException to be thrown with an eof field value of true.
26.126 + * Non-object reads which exceed the end of the allotted data will reflect the
26.127 + * end of data in the same way that they would indicate the end of the stream:
26.128 + * bytewise reads will return -1 as the byte read or number of bytes read, and
26.129 + * primitive reads will throw EOFExceptions. If there is no corresponding
26.130 + * writeObject method, then the end of default serialized data marks the end of
26.131 + * the allotted data.
26.132 + *
26.133 + * <p>Primitive and object read calls issued from within a readExternal method
26.134 + * behave in the same manner--if the stream is already positioned at the end of
26.135 + * data written by the corresponding writeExternal method, object reads will
26.136 + * throw OptionalDataExceptions with eof set to true, bytewise reads will
26.137 + * return -1, and primitive reads will throw EOFExceptions. Note that this
26.138 + * behavior does not hold for streams written with the old
26.139 + * <code>ObjectStreamConstants.PROTOCOL_VERSION_1</code> protocol, in which the
26.140 + * end of data written by writeExternal methods is not demarcated, and hence
26.141 + * cannot be detected.
26.142 + *
26.143 + * <p>The readObjectNoData method is responsible for initializing the state of
26.144 + * the object for its particular class in the event that the serialization
26.145 + * stream does not list the given class as a superclass of the object being
26.146 + * deserialized. This may occur in cases where the receiving party uses a
26.147 + * different version of the deserialized instance's class than the sending
26.148 + * party, and the receiver's version extends classes that are not extended by
26.149 + * the sender's version. This may also occur if the serialization stream has
26.150 + * been tampered; hence, readObjectNoData is useful for initializing
26.151 + * deserialized objects properly despite a "hostile" or incomplete source
26.152 + * stream.
26.153 + *
26.154 + * <p>Serialization does not read or assign values to the fields of any object
26.155 + * that does not implement the java.io.Serializable interface. Subclasses of
26.156 + * Objects that are not serializable can be serializable. In this case the
26.157 + * non-serializable class must have a no-arg constructor to allow its fields to
26.158 + * be initialized. In this case it is the responsibility of the subclass to
26.159 + * save and restore the state of the non-serializable class. It is frequently
26.160 + * the case that the fields of that class are accessible (public, package, or
26.161 + * protected) or that there are get and set methods that can be used to restore
26.162 + * the state.
26.163 + *
26.164 + * <p>Any exception that occurs while deserializing an object will be caught by
26.165 + * the ObjectInputStream and abort the reading process.
26.166 + *
26.167 + * <p>Implementing the Externalizable interface allows the object to assume
26.168 + * complete control over the contents and format of the object's serialized
26.169 + * form. The methods of the Externalizable interface, writeExternal and
26.170 + * readExternal, are called to save and restore the objects state. When
26.171 + * implemented by a class they can write and read their own state using all of
26.172 + * the methods of ObjectOutput and ObjectInput. It is the responsibility of
26.173 + * the objects to handle any versioning that occurs.
26.174 + *
26.175 + * <p>Enum constants are deserialized differently than ordinary serializable or
26.176 + * externalizable objects. The serialized form of an enum constant consists
26.177 + * solely of its name; field values of the constant are not transmitted. To
26.178 + * deserialize an enum constant, ObjectInputStream reads the constant name from
26.179 + * the stream; the deserialized constant is then obtained by calling the static
26.180 + * method <code>Enum.valueOf(Class, String)</code> with the enum constant's
26.181 + * base type and the received constant name as arguments. Like other
26.182 + * serializable or externalizable objects, enum constants can function as the
26.183 + * targets of back references appearing subsequently in the serialization
26.184 + * stream. The process by which enum constants are deserialized cannot be
26.185 + * customized: any class-specific readObject, readObjectNoData, and readResolve
26.186 + * methods defined by enum types are ignored during deserialization.
26.187 + * Similarly, any serialPersistentFields or serialVersionUID field declarations
26.188 + * are also ignored--all enum types have a fixed serialVersionUID of 0L.
26.189 + *
26.190 + * @author Mike Warres
26.191 + * @author Roger Riggs
26.192 + * @see java.io.DataInput
26.193 + * @see java.io.ObjectOutputStream
26.194 + * @see java.io.Serializable
26.195 + * @see <a href="../../../platform/serialization/spec/input.html"> Object Serialization Specification, Section 3, Object Input Classes</a>
26.196 + * @since JDK1.1
26.197 + */
26.198 +public class ObjectInputStream
26.199 + extends InputStream implements ObjectInput, ObjectStreamConstants
26.200 +{
26.201 + /** handle value representing null */
26.202 + private static final int NULL_HANDLE = -1;
26.203 +
26.204 + /** marker for unshared objects in internal handle table */
26.205 + private static final Object unsharedMarker = new Object();
26.206 +
26.207 + /** table mapping primitive type names to corresponding class objects */
26.208 + private static final HashMap<String, Class<?>> primClasses
26.209 + = new HashMap<>(8, 1.0F);
26.210 + static {
26.211 + primClasses.put("boolean", boolean.class);
26.212 + primClasses.put("byte", byte.class);
26.213 + primClasses.put("char", char.class);
26.214 + primClasses.put("short", short.class);
26.215 + primClasses.put("int", int.class);
26.216 + primClasses.put("long", long.class);
26.217 + primClasses.put("float", float.class);
26.218 + primClasses.put("double", double.class);
26.219 + primClasses.put("void", void.class);
26.220 + }
26.221 +
26.222 + /** filter stream for handling block data conversion */
26.223 + private final BlockDataInputStream bin;
26.224 + /** validation callback list */
26.225 + private final ValidationList vlist;
26.226 + /** recursion depth */
26.227 + private int depth;
26.228 + /** whether stream is closed */
26.229 + private boolean closed;
26.230 +
26.231 + /** wire handle -> obj/exception map */
26.232 + private final HandleTable handles;
26.233 + /** scratch field for passing handle values up/down call stack */
26.234 + private int passHandle = NULL_HANDLE;
26.235 + /** flag set when at end of field value block with no TC_ENDBLOCKDATA */
26.236 + private boolean defaultDataEnd = false;
26.237 +
26.238 + /** buffer for reading primitive field values */
26.239 + private byte[] primVals;
26.240 +
26.241 + /** if true, invoke readObjectOverride() instead of readObject() */
26.242 + private final boolean enableOverride;
26.243 + /** if true, invoke resolveObject() */
26.244 + private boolean enableResolve;
26.245 +
26.246 + /**
26.247 + * Context during upcalls to class-defined readObject methods; holds
26.248 + * object currently being deserialized and descriptor for current class.
26.249 + * Null when not during readObject upcall.
26.250 + */
26.251 + private Object curContext;
26.252 +
26.253 + /**
26.254 + * Creates an ObjectInputStream that reads from the specified InputStream.
26.255 + * A serialization stream header is read from the stream and verified.
26.256 + * This constructor will block until the corresponding ObjectOutputStream
26.257 + * has written and flushed the header.
26.258 + *
26.259 + * <p>If a security manager is installed, this constructor will check for
26.260 + * the "enableSubclassImplementation" SerializablePermission when invoked
26.261 + * directly or indirectly by the constructor of a subclass which overrides
26.262 + * the ObjectInputStream.readFields or ObjectInputStream.readUnshared
26.263 + * methods.
26.264 + *
26.265 + * @param in input stream to read from
26.266 + * @throws StreamCorruptedException if the stream header is incorrect
26.267 + * @throws IOException if an I/O error occurs while reading stream header
26.268 + * @throws SecurityException if untrusted subclass illegally overrides
26.269 + * security-sensitive methods
26.270 + * @throws NullPointerException if <code>in</code> is <code>null</code>
26.271 + * @see ObjectInputStream#ObjectInputStream()
26.272 + * @see ObjectInputStream#readFields()
26.273 + * @see ObjectOutputStream#ObjectOutputStream(OutputStream)
26.274 + */
26.275 + public ObjectInputStream(InputStream in) throws IOException {
26.276 + verifySubclass();
26.277 + bin = new BlockDataInputStream(in);
26.278 + handles = new HandleTable(10);
26.279 + vlist = new ValidationList();
26.280 + enableOverride = false;
26.281 + readStreamHeader();
26.282 + bin.setBlockDataMode(true);
26.283 + }
26.284 +
26.285 + /**
26.286 + * Provide a way for subclasses that are completely reimplementing
26.287 + * ObjectInputStream to not have to allocate private data just used by this
26.288 + * implementation of ObjectInputStream.
26.289 + *
26.290 + * <p>If there is a security manager installed, this method first calls the
26.291 + * security manager's <code>checkPermission</code> method with the
26.292 + * <code>SerializablePermission("enableSubclassImplementation")</code>
26.293 + * permission to ensure it's ok to enable subclassing.
26.294 + *
26.295 + * @throws SecurityException if a security manager exists and its
26.296 + * <code>checkPermission</code> method denies enabling
26.297 + * subclassing.
26.298 + * @see SecurityManager#checkPermission
26.299 + * @see java.io.SerializablePermission
26.300 + */
26.301 + protected ObjectInputStream() throws IOException, SecurityException {
26.302 + throw new SecurityException();
26.303 + }
26.304 +
26.305 + /**
26.306 + * Read an object from the ObjectInputStream. The class of the object, the
26.307 + * signature of the class, and the values of the non-transient and
26.308 + * non-static fields of the class and all of its supertypes are read.
26.309 + * Default deserializing for a class can be overriden using the writeObject
26.310 + * and readObject methods. Objects referenced by this object are read
26.311 + * transitively so that a complete equivalent graph of objects is
26.312 + * reconstructed by readObject.
26.313 + *
26.314 + * <p>The root object is completely restored when all of its fields and the
26.315 + * objects it references are completely restored. At this point the object
26.316 + * validation callbacks are executed in order based on their registered
26.317 + * priorities. The callbacks are registered by objects (in the readObject
26.318 + * special methods) as they are individually restored.
26.319 + *
26.320 + * <p>Exceptions are thrown for problems with the InputStream and for
26.321 + * classes that should not be deserialized. All exceptions are fatal to
26.322 + * the InputStream and leave it in an indeterminate state; it is up to the
26.323 + * caller to ignore or recover the stream state.
26.324 + *
26.325 + * @throws ClassNotFoundException Class of a serialized object cannot be
26.326 + * found.
26.327 + * @throws InvalidClassException Something is wrong with a class used by
26.328 + * serialization.
26.329 + * @throws StreamCorruptedException Control information in the
26.330 + * stream is inconsistent.
26.331 + * @throws OptionalDataException Primitive data was found in the
26.332 + * stream instead of objects.
26.333 + * @throws IOException Any of the usual Input/Output related exceptions.
26.334 + */
26.335 + public final Object readObject()
26.336 + throws IOException, ClassNotFoundException
26.337 + {
26.338 + throw new IOException();
26.339 + }
26.340 +
26.341 + /**
26.342 + * This method is called by trusted subclasses of ObjectOutputStream that
26.343 + * constructed ObjectOutputStream using the protected no-arg constructor.
26.344 + * The subclass is expected to provide an override method with the modifier
26.345 + * "final".
26.346 + *
26.347 + * @return the Object read from the stream.
26.348 + * @throws ClassNotFoundException Class definition of a serialized object
26.349 + * cannot be found.
26.350 + * @throws OptionalDataException Primitive data was found in the stream
26.351 + * instead of objects.
26.352 + * @throws IOException if I/O errors occurred while reading from the
26.353 + * underlying stream
26.354 + * @see #ObjectInputStream()
26.355 + * @see #readObject()
26.356 + * @since 1.2
26.357 + */
26.358 + protected Object readObjectOverride()
26.359 + throws IOException, ClassNotFoundException
26.360 + {
26.361 + return null;
26.362 + }
26.363 +
26.364 + /**
26.365 + * Reads an "unshared" object from the ObjectInputStream. This method is
26.366 + * identical to readObject, except that it prevents subsequent calls to
26.367 + * readObject and readUnshared from returning additional references to the
26.368 + * deserialized instance obtained via this call. Specifically:
26.369 + * <ul>
26.370 + * <li>If readUnshared is called to deserialize a back-reference (the
26.371 + * stream representation of an object which has been written
26.372 + * previously to the stream), an ObjectStreamException will be
26.373 + * thrown.
26.374 + *
26.375 + * <li>If readUnshared returns successfully, then any subsequent attempts
26.376 + * to deserialize back-references to the stream handle deserialized
26.377 + * by readUnshared will cause an ObjectStreamException to be thrown.
26.378 + * </ul>
26.379 + * Deserializing an object via readUnshared invalidates the stream handle
26.380 + * associated with the returned object. Note that this in itself does not
26.381 + * always guarantee that the reference returned by readUnshared is unique;
26.382 + * the deserialized object may define a readResolve method which returns an
26.383 + * object visible to other parties, or readUnshared may return a Class
26.384 + * object or enum constant obtainable elsewhere in the stream or through
26.385 + * external means. If the deserialized object defines a readResolve method
26.386 + * and the invocation of that method returns an array, then readUnshared
26.387 + * returns a shallow clone of that array; this guarantees that the returned
26.388 + * array object is unique and cannot be obtained a second time from an
26.389 + * invocation of readObject or readUnshared on the ObjectInputStream,
26.390 + * even if the underlying data stream has been manipulated.
26.391 + *
26.392 + * <p>ObjectInputStream subclasses which override this method can only be
26.393 + * constructed in security contexts possessing the
26.394 + * "enableSubclassImplementation" SerializablePermission; any attempt to
26.395 + * instantiate such a subclass without this permission will cause a
26.396 + * SecurityException to be thrown.
26.397 + *
26.398 + * @return reference to deserialized object
26.399 + * @throws ClassNotFoundException if class of an object to deserialize
26.400 + * cannot be found
26.401 + * @throws StreamCorruptedException if control information in the stream
26.402 + * is inconsistent
26.403 + * @throws ObjectStreamException if object to deserialize has already
26.404 + * appeared in stream
26.405 + * @throws OptionalDataException if primitive data is next in stream
26.406 + * @throws IOException if an I/O error occurs during deserialization
26.407 + * @since 1.4
26.408 + */
26.409 + public Object readUnshared() throws IOException, ClassNotFoundException {
26.410 + // if nested read, passHandle contains handle of enclosing object
26.411 + int outerHandle = passHandle;
26.412 + try {
26.413 + Object obj = readObject0(true);
26.414 + handles.markDependency(outerHandle, passHandle);
26.415 + ClassNotFoundException ex = handles.lookupException(passHandle);
26.416 + if (ex != null) {
26.417 + throw ex;
26.418 + }
26.419 + if (depth == 0) {
26.420 + vlist.doCallbacks();
26.421 + }
26.422 + return obj;
26.423 + } finally {
26.424 + passHandle = outerHandle;
26.425 + if (closed && depth == 0) {
26.426 + clear();
26.427 + }
26.428 + }
26.429 + }
26.430 +
26.431 + /**
26.432 + * Read the non-static and non-transient fields of the current class from
26.433 + * this stream. This may only be called from the readObject method of the
26.434 + * class being deserialized. It will throw the NotActiveException if it is
26.435 + * called otherwise.
26.436 + *
26.437 + * @throws ClassNotFoundException if the class of a serialized object
26.438 + * could not be found.
26.439 + * @throws IOException if an I/O error occurs.
26.440 + * @throws NotActiveException if the stream is not currently reading
26.441 + * objects.
26.442 + */
26.443 + public void defaultReadObject()
26.444 + throws IOException, ClassNotFoundException
26.445 + {
26.446 + if (curContext == null) {
26.447 + throw new NotActiveException("not in call to readObject");
26.448 + }
26.449 + Object curObj = null; // curContext.getObj();
26.450 + ObjectStreamClass curDesc = null; // curContext.getDesc();
26.451 + bin.setBlockDataMode(false);
26.452 + defaultReadFields(curObj, curDesc);
26.453 + bin.setBlockDataMode(true);
26.454 + if (!curDesc.hasWriteObjectData()) {
26.455 + /*
26.456 + * Fix for 4360508: since stream does not contain terminating
26.457 + * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
26.458 + * knows to simulate end-of-custom-data behavior.
26.459 + */
26.460 + defaultDataEnd = true;
26.461 + }
26.462 + ClassNotFoundException ex = handles.lookupException(passHandle);
26.463 + if (ex != null) {
26.464 + throw ex;
26.465 + }
26.466 + }
26.467 +
26.468 + /**
26.469 + * Reads the persistent fields from the stream and makes them available by
26.470 + * name.
26.471 + *
26.472 + * @return the <code>GetField</code> object representing the persistent
26.473 + * fields of the object being deserialized
26.474 + * @throws ClassNotFoundException if the class of a serialized object
26.475 + * could not be found.
26.476 + * @throws IOException if an I/O error occurs.
26.477 + * @throws NotActiveException if the stream is not currently reading
26.478 + * objects.
26.479 + * @since 1.2
26.480 + */
26.481 + public ObjectInputStream.GetField readFields()
26.482 + throws IOException, ClassNotFoundException
26.483 + {
26.484 + if (curContext == null) {
26.485 + throw new NotActiveException("not in call to readObject");
26.486 + }
26.487 + Object curObj = null; // curContext.getObj();
26.488 + ObjectStreamClass curDesc = null; // curContext.getDesc();
26.489 + bin.setBlockDataMode(false);
26.490 + GetFieldImpl getField = new GetFieldImpl(curDesc);
26.491 + getField.readFields();
26.492 + bin.setBlockDataMode(true);
26.493 + if (!curDesc.hasWriteObjectData()) {
26.494 + /*
26.495 + * Fix for 4360508: since stream does not contain terminating
26.496 + * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
26.497 + * knows to simulate end-of-custom-data behavior.
26.498 + */
26.499 + defaultDataEnd = true;
26.500 + }
26.501 +
26.502 + return getField;
26.503 + }
26.504 +
26.505 + /**
26.506 + * Register an object to be validated before the graph is returned. While
26.507 + * similar to resolveObject these validations are called after the entire
26.508 + * graph has been reconstituted. Typically, a readObject method will
26.509 + * register the object with the stream so that when all of the objects are
26.510 + * restored a final set of validations can be performed.
26.511 + *
26.512 + * @param obj the object to receive the validation callback.
26.513 + * @param prio controls the order of callbacks;zero is a good default.
26.514 + * Use higher numbers to be called back earlier, lower numbers for
26.515 + * later callbacks. Within a priority, callbacks are processed in
26.516 + * no particular order.
26.517 + * @throws NotActiveException The stream is not currently reading objects
26.518 + * so it is invalid to register a callback.
26.519 + * @throws InvalidObjectException The validation object is null.
26.520 + */
26.521 + public void registerValidation(ObjectInputValidation obj, int prio)
26.522 + throws NotActiveException, InvalidObjectException
26.523 + {
26.524 + if (depth == 0) {
26.525 + throw new NotActiveException("stream inactive");
26.526 + }
26.527 + vlist.register(obj, prio);
26.528 + }
26.529 +
26.530 + /**
26.531 + * Load the local class equivalent of the specified stream class
26.532 + * description. Subclasses may implement this method to allow classes to
26.533 + * be fetched from an alternate source.
26.534 + *
26.535 + * <p>The corresponding method in <code>ObjectOutputStream</code> is
26.536 + * <code>annotateClass</code>. This method will be invoked only once for
26.537 + * each unique class in the stream. This method can be implemented by
26.538 + * subclasses to use an alternate loading mechanism but must return a
26.539 + * <code>Class</code> object. Once returned, if the class is not an array
26.540 + * class, its serialVersionUID is compared to the serialVersionUID of the
26.541 + * serialized class, and if there is a mismatch, the deserialization fails
26.542 + * and an {@link InvalidClassException} is thrown.
26.543 + *
26.544 + * <p>The default implementation of this method in
26.545 + * <code>ObjectInputStream</code> returns the result of calling
26.546 + * <pre>
26.547 + * Class.forName(desc.getName(), false, loader)
26.548 + * </pre>
26.549 + * where <code>loader</code> is determined as follows: if there is a
26.550 + * method on the current thread's stack whose declaring class was
26.551 + * defined by a user-defined class loader (and was not a generated to
26.552 + * implement reflective invocations), then <code>loader</code> is class
26.553 + * loader corresponding to the closest such method to the currently
26.554 + * executing frame; otherwise, <code>loader</code> is
26.555 + * <code>null</code>. If this call results in a
26.556 + * <code>ClassNotFoundException</code> and the name of the passed
26.557 + * <code>ObjectStreamClass</code> instance is the Java language keyword
26.558 + * for a primitive type or void, then the <code>Class</code> object
26.559 + * representing that primitive type or void will be returned
26.560 + * (e.g., an <code>ObjectStreamClass</code> with the name
26.561 + * <code>"int"</code> will be resolved to <code>Integer.TYPE</code>).
26.562 + * Otherwise, the <code>ClassNotFoundException</code> will be thrown to
26.563 + * the caller of this method.
26.564 + *
26.565 + * @param desc an instance of class <code>ObjectStreamClass</code>
26.566 + * @return a <code>Class</code> object corresponding to <code>desc</code>
26.567 + * @throws IOException any of the usual Input/Output exceptions.
26.568 + * @throws ClassNotFoundException if class of a serialized object cannot
26.569 + * be found.
26.570 + */
26.571 + protected Class<?> resolveClass(ObjectStreamClass desc)
26.572 + throws IOException, ClassNotFoundException
26.573 + {
26.574 + String name = desc.getName();
26.575 + try {
26.576 + return Class.forName(name, false, latestUserDefinedLoader());
26.577 + } catch (ClassNotFoundException ex) {
26.578 + Class<?> cl = primClasses.get(name);
26.579 + if (cl != null) {
26.580 + return cl;
26.581 + } else {
26.582 + throw ex;
26.583 + }
26.584 + }
26.585 + }
26.586 +
26.587 + /**
26.588 + * Returns a proxy class that implements the interfaces named in a proxy
26.589 + * class descriptor; subclasses may implement this method to read custom
26.590 + * data from the stream along with the descriptors for dynamic proxy
26.591 + * classes, allowing them to use an alternate loading mechanism for the
26.592 + * interfaces and the proxy class.
26.593 + *
26.594 + * <p>This method is called exactly once for each unique proxy class
26.595 + * descriptor in the stream.
26.596 + *
26.597 + * <p>The corresponding method in <code>ObjectOutputStream</code> is
26.598 + * <code>annotateProxyClass</code>. For a given subclass of
26.599 + * <code>ObjectInputStream</code> that overrides this method, the
26.600 + * <code>annotateProxyClass</code> method in the corresponding subclass of
26.601 + * <code>ObjectOutputStream</code> must write any data or objects read by
26.602 + * this method.
26.603 + *
26.604 + * <p>The default implementation of this method in
26.605 + * <code>ObjectInputStream</code> returns the result of calling
26.606 + * <code>Proxy.getProxyClass</code> with the list of <code>Class</code>
26.607 + * objects for the interfaces that are named in the <code>interfaces</code>
26.608 + * parameter. The <code>Class</code> object for each interface name
26.609 + * <code>i</code> is the value returned by calling
26.610 + * <pre>
26.611 + * Class.forName(i, false, loader)
26.612 + * </pre>
26.613 + * where <code>loader</code> is that of the first non-<code>null</code>
26.614 + * class loader up the execution stack, or <code>null</code> if no
26.615 + * non-<code>null</code> class loaders are on the stack (the same class
26.616 + * loader choice used by the <code>resolveClass</code> method). Unless any
26.617 + * of the resolved interfaces are non-public, this same value of
26.618 + * <code>loader</code> is also the class loader passed to
26.619 + * <code>Proxy.getProxyClass</code>; if non-public interfaces are present,
26.620 + * their class loader is passed instead (if more than one non-public
26.621 + * interface class loader is encountered, an
26.622 + * <code>IllegalAccessError</code> is thrown).
26.623 + * If <code>Proxy.getProxyClass</code> throws an
26.624 + * <code>IllegalArgumentException</code>, <code>resolveProxyClass</code>
26.625 + * will throw a <code>ClassNotFoundException</code> containing the
26.626 + * <code>IllegalArgumentException</code>.
26.627 + *
26.628 + * @param interfaces the list of interface names that were
26.629 + * deserialized in the proxy class descriptor
26.630 + * @return a proxy class for the specified interfaces
26.631 + * @throws IOException any exception thrown by the underlying
26.632 + * <code>InputStream</code>
26.633 + * @throws ClassNotFoundException if the proxy class or any of the
26.634 + * named interfaces could not be found
26.635 + * @see ObjectOutputStream#annotateProxyClass(Class)
26.636 + * @since 1.3
26.637 + */
26.638 + protected Class<?> resolveProxyClass(String[] interfaces)
26.639 + throws IOException, ClassNotFoundException
26.640 + {
26.641 + ClassLoader latestLoader = latestUserDefinedLoader();
26.642 + ClassLoader nonPublicLoader = null;
26.643 + boolean hasNonPublicInterface = false;
26.644 +
26.645 + // define proxy in class loader of non-public interface(s), if any
26.646 + Class[] classObjs = new Class[interfaces.length];
26.647 + for (int i = 0; i < interfaces.length; i++) {
26.648 + Class cl = Class.forName(interfaces[i], false, latestLoader);
26.649 + if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
26.650 + if (hasNonPublicInterface) {
26.651 + if (nonPublicLoader != cl.getClassLoader()) {
26.652 + throw new IllegalAccessError(
26.653 + "conflicting non-public interface class loaders");
26.654 + }
26.655 + } else {
26.656 + nonPublicLoader = cl.getClassLoader();
26.657 + hasNonPublicInterface = true;
26.658 + }
26.659 + }
26.660 + classObjs[i] = cl;
26.661 + }
26.662 + try {
26.663 + return Proxy.getProxyClass(
26.664 + hasNonPublicInterface ? nonPublicLoader : latestLoader,
26.665 + classObjs);
26.666 + } catch (IllegalArgumentException e) {
26.667 + throw new ClassNotFoundException(null, e);
26.668 + }
26.669 + }
26.670 +
26.671 + /**
26.672 + * This method will allow trusted subclasses of ObjectInputStream to
26.673 + * substitute one object for another during deserialization. Replacing
26.674 + * objects is disabled until enableResolveObject is called. The
26.675 + * enableResolveObject method checks that the stream requesting to resolve
26.676 + * object can be trusted. Every reference to serializable objects is passed
26.677 + * to resolveObject. To insure that the private state of objects is not
26.678 + * unintentionally exposed only trusted streams may use resolveObject.
26.679 + *
26.680 + * <p>This method is called after an object has been read but before it is
26.681 + * returned from readObject. The default resolveObject method just returns
26.682 + * the same object.
26.683 + *
26.684 + * <p>When a subclass is replacing objects it must insure that the
26.685 + * substituted object is compatible with every field where the reference
26.686 + * will be stored. Objects whose type is not a subclass of the type of the
26.687 + * field or array element abort the serialization by raising an exception
26.688 + * and the object is not be stored.
26.689 + *
26.690 + * <p>This method is called only once when each object is first
26.691 + * encountered. All subsequent references to the object will be redirected
26.692 + * to the new object.
26.693 + *
26.694 + * @param obj object to be substituted
26.695 + * @return the substituted object
26.696 + * @throws IOException Any of the usual Input/Output exceptions.
26.697 + */
26.698 + protected Object resolveObject(Object obj) throws IOException {
26.699 + return obj;
26.700 + }
26.701 +
26.702 + /**
26.703 + * Enable the stream to allow objects read from the stream to be replaced.
26.704 + * When enabled, the resolveObject method is called for every object being
26.705 + * deserialized.
26.706 + *
26.707 + * <p>If <i>enable</i> is true, and there is a security manager installed,
26.708 + * this method first calls the security manager's
26.709 + * <code>checkPermission</code> method with the
26.710 + * <code>SerializablePermission("enableSubstitution")</code> permission to
26.711 + * ensure it's ok to enable the stream to allow objects read from the
26.712 + * stream to be replaced.
26.713 + *
26.714 + * @param enable true for enabling use of <code>resolveObject</code> for
26.715 + * every object being deserialized
26.716 + * @return the previous setting before this method was invoked
26.717 + * @throws SecurityException if a security manager exists and its
26.718 + * <code>checkPermission</code> method denies enabling the stream
26.719 + * to allow objects read from the stream to be replaced.
26.720 + * @see SecurityManager#checkPermission
26.721 + * @see java.io.SerializablePermission
26.722 + */
26.723 + protected boolean enableResolveObject(boolean enable)
26.724 + throws SecurityException
26.725 + {
26.726 + throw new SecurityException();
26.727 + }
26.728 +
26.729 + /**
26.730 + * The readStreamHeader method is provided to allow subclasses to read and
26.731 + * verify their own stream headers. It reads and verifies the magic number
26.732 + * and version number.
26.733 + *
26.734 + * @throws IOException if there are I/O errors while reading from the
26.735 + * underlying <code>InputStream</code>
26.736 + * @throws StreamCorruptedException if control information in the stream
26.737 + * is inconsistent
26.738 + */
26.739 + protected void readStreamHeader()
26.740 + throws IOException, StreamCorruptedException
26.741 + {
26.742 + short s0 = bin.readShort();
26.743 + short s1 = bin.readShort();
26.744 + if (s0 != STREAM_MAGIC || s1 != STREAM_VERSION) {
26.745 + throw new StreamCorruptedException(
26.746 + String.format("invalid stream header: %04X%04X", s0, s1));
26.747 + }
26.748 + }
26.749 +
26.750 + /**
26.751 + * Read a class descriptor from the serialization stream. This method is
26.752 + * called when the ObjectInputStream expects a class descriptor as the next
26.753 + * item in the serialization stream. Subclasses of ObjectInputStream may
26.754 + * override this method to read in class descriptors that have been written
26.755 + * in non-standard formats (by subclasses of ObjectOutputStream which have
26.756 + * overridden the <code>writeClassDescriptor</code> method). By default,
26.757 + * this method reads class descriptors according to the format defined in
26.758 + * the Object Serialization specification.
26.759 + *
26.760 + * @return the class descriptor read
26.761 + * @throws IOException If an I/O error has occurred.
26.762 + * @throws ClassNotFoundException If the Class of a serialized object used
26.763 + * in the class descriptor representation cannot be found
26.764 + * @see java.io.ObjectOutputStream#writeClassDescriptor(java.io.ObjectStreamClass)
26.765 + * @since 1.3
26.766 + */
26.767 + protected ObjectStreamClass readClassDescriptor()
26.768 + throws IOException, ClassNotFoundException
26.769 + {
26.770 + ObjectStreamClass desc = new ObjectStreamClass();
26.771 + desc.readNonProxy(this);
26.772 + return desc;
26.773 + }
26.774 +
26.775 + /**
26.776 + * Reads a byte of data. This method will block if no input is available.
26.777 + *
26.778 + * @return the byte read, or -1 if the end of the stream is reached.
26.779 + * @throws IOException If an I/O error has occurred.
26.780 + */
26.781 + public int read() throws IOException {
26.782 + return bin.read();
26.783 + }
26.784 +
26.785 + /**
26.786 + * Reads into an array of bytes. This method will block until some input
26.787 + * is available. Consider using java.io.DataInputStream.readFully to read
26.788 + * exactly 'length' bytes.
26.789 + *
26.790 + * @param buf the buffer into which the data is read
26.791 + * @param off the start offset of the data
26.792 + * @param len the maximum number of bytes read
26.793 + * @return the actual number of bytes read, -1 is returned when the end of
26.794 + * the stream is reached.
26.795 + * @throws IOException If an I/O error has occurred.
26.796 + * @see java.io.DataInputStream#readFully(byte[],int,int)
26.797 + */
26.798 + public int read(byte[] buf, int off, int len) throws IOException {
26.799 + if (buf == null) {
26.800 + throw new NullPointerException();
26.801 + }
26.802 + int endoff = off + len;
26.803 + if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
26.804 + throw new IndexOutOfBoundsException();
26.805 + }
26.806 + return bin.read(buf, off, len, false);
26.807 + }
26.808 +
26.809 + /**
26.810 + * Returns the number of bytes that can be read without blocking.
26.811 + *
26.812 + * @return the number of available bytes.
26.813 + * @throws IOException if there are I/O errors while reading from the
26.814 + * underlying <code>InputStream</code>
26.815 + */
26.816 + public int available() throws IOException {
26.817 + return bin.available();
26.818 + }
26.819 +
26.820 + /**
26.821 + * Closes the input stream. Must be called to release any resources
26.822 + * associated with the stream.
26.823 + *
26.824 + * @throws IOException If an I/O error has occurred.
26.825 + */
26.826 + public void close() throws IOException {
26.827 + /*
26.828 + * Even if stream already closed, propagate redundant close to
26.829 + * underlying stream to stay consistent with previous implementations.
26.830 + */
26.831 + closed = true;
26.832 + if (depth == 0) {
26.833 + clear();
26.834 + }
26.835 + bin.close();
26.836 + }
26.837 +
26.838 + /**
26.839 + * Reads in a boolean.
26.840 + *
26.841 + * @return the boolean read.
26.842 + * @throws EOFException If end of file is reached.
26.843 + * @throws IOException If other I/O error has occurred.
26.844 + */
26.845 + public boolean readBoolean() throws IOException {
26.846 + return bin.readBoolean();
26.847 + }
26.848 +
26.849 + /**
26.850 + * Reads an 8 bit byte.
26.851 + *
26.852 + * @return the 8 bit byte read.
26.853 + * @throws EOFException If end of file is reached.
26.854 + * @throws IOException If other I/O error has occurred.
26.855 + */
26.856 + public byte readByte() throws IOException {
26.857 + return bin.readByte();
26.858 + }
26.859 +
26.860 + /**
26.861 + * Reads an unsigned 8 bit byte.
26.862 + *
26.863 + * @return the 8 bit byte read.
26.864 + * @throws EOFException If end of file is reached.
26.865 + * @throws IOException If other I/O error has occurred.
26.866 + */
26.867 + public int readUnsignedByte() throws IOException {
26.868 + return bin.readUnsignedByte();
26.869 + }
26.870 +
26.871 + /**
26.872 + * Reads a 16 bit char.
26.873 + *
26.874 + * @return the 16 bit char read.
26.875 + * @throws EOFException If end of file is reached.
26.876 + * @throws IOException If other I/O error has occurred.
26.877 + */
26.878 + public char readChar() throws IOException {
26.879 + return bin.readChar();
26.880 + }
26.881 +
26.882 + /**
26.883 + * Reads a 16 bit short.
26.884 + *
26.885 + * @return the 16 bit short read.
26.886 + * @throws EOFException If end of file is reached.
26.887 + * @throws IOException If other I/O error has occurred.
26.888 + */
26.889 + public short readShort() throws IOException {
26.890 + return bin.readShort();
26.891 + }
26.892 +
26.893 + /**
26.894 + * Reads an unsigned 16 bit short.
26.895 + *
26.896 + * @return the 16 bit short read.
26.897 + * @throws EOFException If end of file is reached.
26.898 + * @throws IOException If other I/O error has occurred.
26.899 + */
26.900 + public int readUnsignedShort() throws IOException {
26.901 + return bin.readUnsignedShort();
26.902 + }
26.903 +
26.904 + /**
26.905 + * Reads a 32 bit int.
26.906 + *
26.907 + * @return the 32 bit integer read.
26.908 + * @throws EOFException If end of file is reached.
26.909 + * @throws IOException If other I/O error has occurred.
26.910 + */
26.911 + public int readInt() throws IOException {
26.912 + return bin.readInt();
26.913 + }
26.914 +
26.915 + /**
26.916 + * Reads a 64 bit long.
26.917 + *
26.918 + * @return the read 64 bit long.
26.919 + * @throws EOFException If end of file is reached.
26.920 + * @throws IOException If other I/O error has occurred.
26.921 + */
26.922 + public long readLong() throws IOException {
26.923 + return bin.readLong();
26.924 + }
26.925 +
26.926 + /**
26.927 + * Reads a 32 bit float.
26.928 + *
26.929 + * @return the 32 bit float read.
26.930 + * @throws EOFException If end of file is reached.
26.931 + * @throws IOException If other I/O error has occurred.
26.932 + */
26.933 + public float readFloat() throws IOException {
26.934 + return bin.readFloat();
26.935 + }
26.936 +
26.937 + /**
26.938 + * Reads a 64 bit double.
26.939 + *
26.940 + * @return the 64 bit double read.
26.941 + * @throws EOFException If end of file is reached.
26.942 + * @throws IOException If other I/O error has occurred.
26.943 + */
26.944 + public double readDouble() throws IOException {
26.945 + return bin.readDouble();
26.946 + }
26.947 +
26.948 + /**
26.949 + * Reads bytes, blocking until all bytes are read.
26.950 + *
26.951 + * @param buf the buffer into which the data is read
26.952 + * @throws EOFException If end of file is reached.
26.953 + * @throws IOException If other I/O error has occurred.
26.954 + */
26.955 + public void readFully(byte[] buf) throws IOException {
26.956 + bin.readFully(buf, 0, buf.length, false);
26.957 + }
26.958 +
26.959 + /**
26.960 + * Reads bytes, blocking until all bytes are read.
26.961 + *
26.962 + * @param buf the buffer into which the data is read
26.963 + * @param off the start offset of the data
26.964 + * @param len the maximum number of bytes to read
26.965 + * @throws EOFException If end of file is reached.
26.966 + * @throws IOException If other I/O error has occurred.
26.967 + */
26.968 + public void readFully(byte[] buf, int off, int len) throws IOException {
26.969 + int endoff = off + len;
26.970 + if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
26.971 + throw new IndexOutOfBoundsException();
26.972 + }
26.973 + bin.readFully(buf, off, len, false);
26.974 + }
26.975 +
26.976 + /**
26.977 + * Skips bytes.
26.978 + *
26.979 + * @param len the number of bytes to be skipped
26.980 + * @return the actual number of bytes skipped.
26.981 + * @throws IOException If an I/O error has occurred.
26.982 + */
26.983 + public int skipBytes(int len) throws IOException {
26.984 + return bin.skipBytes(len);
26.985 + }
26.986 +
26.987 + /**
26.988 + * Reads in a line that has been terminated by a \n, \r, \r\n or EOF.
26.989 + *
26.990 + * @return a String copy of the line.
26.991 + * @throws IOException if there are I/O errors while reading from the
26.992 + * underlying <code>InputStream</code>
26.993 + * @deprecated This method does not properly convert bytes to characters.
26.994 + * see DataInputStream for the details and alternatives.
26.995 + */
26.996 + @Deprecated
26.997 + public String readLine() throws IOException {
26.998 + return bin.readLine();
26.999 + }
26.1000 +
26.1001 + /**
26.1002 + * Reads a String in
26.1003 + * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
26.1004 + * format.
26.1005 + *
26.1006 + * @return the String.
26.1007 + * @throws IOException if there are I/O errors while reading from the
26.1008 + * underlying <code>InputStream</code>
26.1009 + * @throws UTFDataFormatException if read bytes do not represent a valid
26.1010 + * modified UTF-8 encoding of a string
26.1011 + */
26.1012 + public String readUTF() throws IOException {
26.1013 + return bin.readUTF();
26.1014 + }
26.1015 +
26.1016 + /**
26.1017 + * Provide access to the persistent fields read from the input stream.
26.1018 + */
26.1019 + public static abstract class GetField {
26.1020 +
26.1021 + /**
26.1022 + * Get the ObjectStreamClass that describes the fields in the stream.
26.1023 + *
26.1024 + * @return the descriptor class that describes the serializable fields
26.1025 + */
26.1026 + public abstract ObjectStreamClass getObjectStreamClass();
26.1027 +
26.1028 + /**
26.1029 + * Return true if the named field is defaulted and has no value in this
26.1030 + * stream.
26.1031 + *
26.1032 + * @param name the name of the field
26.1033 + * @return true, if and only if the named field is defaulted
26.1034 + * @throws IOException if there are I/O errors while reading from
26.1035 + * the underlying <code>InputStream</code>
26.1036 + * @throws IllegalArgumentException if <code>name</code> does not
26.1037 + * correspond to a serializable field
26.1038 + */
26.1039 + public abstract boolean defaulted(String name) throws IOException;
26.1040 +
26.1041 + /**
26.1042 + * Get the value of the named boolean field from the persistent field.
26.1043 + *
26.1044 + * @param name the name of the field
26.1045 + * @param val the default value to use if <code>name</code> does not
26.1046 + * have a value
26.1047 + * @return the value of the named <code>boolean</code> field
26.1048 + * @throws IOException if there are I/O errors while reading from the
26.1049 + * underlying <code>InputStream</code>
26.1050 + * @throws IllegalArgumentException if type of <code>name</code> is
26.1051 + * not serializable or if the field type is incorrect
26.1052 + */
26.1053 + public abstract boolean get(String name, boolean val)
26.1054 + throws IOException;
26.1055 +
26.1056 + /**
26.1057 + * Get the value of the named byte field from the persistent field.
26.1058 + *
26.1059 + * @param name the name of the field
26.1060 + * @param val the default value to use if <code>name</code> does not
26.1061 + * have a value
26.1062 + * @return the value of the named <code>byte</code> field
26.1063 + * @throws IOException if there are I/O errors while reading from the
26.1064 + * underlying <code>InputStream</code>
26.1065 + * @throws IllegalArgumentException if type of <code>name</code> is
26.1066 + * not serializable or if the field type is incorrect
26.1067 + */
26.1068 + public abstract byte get(String name, byte val) throws IOException;
26.1069 +
26.1070 + /**
26.1071 + * Get the value of the named char field from the persistent field.
26.1072 + *
26.1073 + * @param name the name of the field
26.1074 + * @param val the default value to use if <code>name</code> does not
26.1075 + * have a value
26.1076 + * @return the value of the named <code>char</code> field
26.1077 + * @throws IOException if there are I/O errors while reading from the
26.1078 + * underlying <code>InputStream</code>
26.1079 + * @throws IllegalArgumentException if type of <code>name</code> is
26.1080 + * not serializable or if the field type is incorrect
26.1081 + */
26.1082 + public abstract char get(String name, char val) throws IOException;
26.1083 +
26.1084 + /**
26.1085 + * Get the value of the named short field from the persistent field.
26.1086 + *
26.1087 + * @param name the name of the field
26.1088 + * @param val the default value to use if <code>name</code> does not
26.1089 + * have a value
26.1090 + * @return the value of the named <code>short</code> field
26.1091 + * @throws IOException if there are I/O errors while reading from the
26.1092 + * underlying <code>InputStream</code>
26.1093 + * @throws IllegalArgumentException if type of <code>name</code> is
26.1094 + * not serializable or if the field type is incorrect
26.1095 + */
26.1096 + public abstract short get(String name, short val) throws IOException;
26.1097 +
26.1098 + /**
26.1099 + * Get the value of the named int field from the persistent field.
26.1100 + *
26.1101 + * @param name the name of the field
26.1102 + * @param val the default value to use if <code>name</code> does not
26.1103 + * have a value
26.1104 + * @return the value of the named <code>int</code> field
26.1105 + * @throws IOException if there are I/O errors while reading from the
26.1106 + * underlying <code>InputStream</code>
26.1107 + * @throws IllegalArgumentException if type of <code>name</code> is
26.1108 + * not serializable or if the field type is incorrect
26.1109 + */
26.1110 + public abstract int get(String name, int val) throws IOException;
26.1111 +
26.1112 + /**
26.1113 + * Get the value of the named long field from the persistent field.
26.1114 + *
26.1115 + * @param name the name of the field
26.1116 + * @param val the default value to use if <code>name</code> does not
26.1117 + * have a value
26.1118 + * @return the value of the named <code>long</code> field
26.1119 + * @throws IOException if there are I/O errors while reading from the
26.1120 + * underlying <code>InputStream</code>
26.1121 + * @throws IllegalArgumentException if type of <code>name</code> is
26.1122 + * not serializable or if the field type is incorrect
26.1123 + */
26.1124 + public abstract long get(String name, long val) throws IOException;
26.1125 +
26.1126 + /**
26.1127 + * Get the value of the named float field from the persistent field.
26.1128 + *
26.1129 + * @param name the name of the field
26.1130 + * @param val the default value to use if <code>name</code> does not
26.1131 + * have a value
26.1132 + * @return the value of the named <code>float</code> field
26.1133 + * @throws IOException if there are I/O errors while reading from the
26.1134 + * underlying <code>InputStream</code>
26.1135 + * @throws IllegalArgumentException if type of <code>name</code> is
26.1136 + * not serializable or if the field type is incorrect
26.1137 + */
26.1138 + public abstract float get(String name, float val) throws IOException;
26.1139 +
26.1140 + /**
26.1141 + * Get the value of the named double field from the persistent field.
26.1142 + *
26.1143 + * @param name the name of the field
26.1144 + * @param val the default value to use if <code>name</code> does not
26.1145 + * have a value
26.1146 + * @return the value of the named <code>double</code> field
26.1147 + * @throws IOException if there are I/O errors while reading from the
26.1148 + * underlying <code>InputStream</code>
26.1149 + * @throws IllegalArgumentException if type of <code>name</code> is
26.1150 + * not serializable or if the field type is incorrect
26.1151 + */
26.1152 + public abstract double get(String name, double val) throws IOException;
26.1153 +
26.1154 + /**
26.1155 + * Get the value of the named Object field from the persistent field.
26.1156 + *
26.1157 + * @param name the name of the field
26.1158 + * @param val the default value to use if <code>name</code> does not
26.1159 + * have a value
26.1160 + * @return the value of the named <code>Object</code> field
26.1161 + * @throws IOException if there are I/O errors while reading from the
26.1162 + * underlying <code>InputStream</code>
26.1163 + * @throws IllegalArgumentException if type of <code>name</code> is
26.1164 + * not serializable or if the field type is incorrect
26.1165 + */
26.1166 + public abstract Object get(String name, Object val) throws IOException;
26.1167 + }
26.1168 +
26.1169 + /**
26.1170 + * Verifies that this (possibly subclass) instance can be constructed
26.1171 + * without violating security constraints: the subclass must not override
26.1172 + * security-sensitive non-final methods, or else the
26.1173 + * "enableSubclassImplementation" SerializablePermission is checked.
26.1174 + */
26.1175 + private void verifySubclass() {
26.1176 + Class cl = getClass();
26.1177 + if (cl == ObjectInputStream.class) {
26.1178 + return;
26.1179 + }
26.1180 + throw new SecurityException();
26.1181 + }
26.1182 +
26.1183 + /**
26.1184 + * Clears internal data structures.
26.1185 + */
26.1186 + private void clear() {
26.1187 + handles.clear();
26.1188 + vlist.clear();
26.1189 + }
26.1190 +
26.1191 + /**
26.1192 + * Underlying readObject implementation.
26.1193 + */
26.1194 + private Object readObject0(boolean unshared) throws IOException {
26.1195 + boolean oldMode = bin.getBlockDataMode();
26.1196 + if (oldMode) {
26.1197 + int remain = bin.currentBlockRemaining();
26.1198 + if (remain > 0) {
26.1199 + throw new OptionalDataException(remain);
26.1200 + } else if (defaultDataEnd) {
26.1201 + /*
26.1202 + * Fix for 4360508: stream is currently at the end of a field
26.1203 + * value block written via default serialization; since there
26.1204 + * is no terminating TC_ENDBLOCKDATA tag, simulate
26.1205 + * end-of-custom-data behavior explicitly.
26.1206 + */
26.1207 + throw new OptionalDataException(true);
26.1208 + }
26.1209 + bin.setBlockDataMode(false);
26.1210 + }
26.1211 +
26.1212 + byte tc;
26.1213 + while ((tc = bin.peekByte()) == TC_RESET) {
26.1214 + bin.readByte();
26.1215 + handleReset();
26.1216 + }
26.1217 +
26.1218 + depth++;
26.1219 + try {
26.1220 + switch (tc) {
26.1221 + case TC_NULL:
26.1222 + return readNull();
26.1223 +
26.1224 + case TC_REFERENCE:
26.1225 + return readHandle(unshared);
26.1226 +
26.1227 + case TC_CLASS:
26.1228 + return readClass(unshared);
26.1229 +
26.1230 + case TC_CLASSDESC:
26.1231 + case TC_PROXYCLASSDESC:
26.1232 + return readClassDesc(unshared);
26.1233 +
26.1234 + case TC_STRING:
26.1235 + case TC_LONGSTRING:
26.1236 + return checkResolve(readString(unshared));
26.1237 +
26.1238 + case TC_ARRAY:
26.1239 + return checkResolve(readArray(unshared));
26.1240 +
26.1241 + case TC_ENUM:
26.1242 + return checkResolve(readEnum(unshared));
26.1243 +
26.1244 + case TC_OBJECT:
26.1245 + return checkResolve(readOrdinaryObject(unshared));
26.1246 +
26.1247 + case TC_EXCEPTION:
26.1248 + IOException ex = readFatalException();
26.1249 + throw new WriteAbortedException("writing aborted", ex);
26.1250 +
26.1251 + case TC_BLOCKDATA:
26.1252 + case TC_BLOCKDATALONG:
26.1253 + if (oldMode) {
26.1254 + bin.setBlockDataMode(true);
26.1255 + bin.peek(); // force header read
26.1256 + throw new OptionalDataException(
26.1257 + bin.currentBlockRemaining());
26.1258 + } else {
26.1259 + throw new StreamCorruptedException(
26.1260 + "unexpected block data");
26.1261 + }
26.1262 +
26.1263 + case TC_ENDBLOCKDATA:
26.1264 + if (oldMode) {
26.1265 + throw new OptionalDataException(true);
26.1266 + } else {
26.1267 + throw new StreamCorruptedException(
26.1268 + "unexpected end of block data");
26.1269 + }
26.1270 +
26.1271 + default:
26.1272 + throw new StreamCorruptedException(
26.1273 + String.format("invalid type code: %02X", tc));
26.1274 + }
26.1275 + } finally {
26.1276 + depth--;
26.1277 + bin.setBlockDataMode(oldMode);
26.1278 + }
26.1279 + }
26.1280 +
26.1281 + /**
26.1282 + * If resolveObject has been enabled and given object does not have an
26.1283 + * exception associated with it, calls resolveObject to determine
26.1284 + * replacement for object, and updates handle table accordingly. Returns
26.1285 + * replacement object, or echoes provided object if no replacement
26.1286 + * occurred. Expects that passHandle is set to given object's handle prior
26.1287 + * to calling this method.
26.1288 + */
26.1289 + private Object checkResolve(Object obj) throws IOException {
26.1290 + if (!enableResolve || handles.lookupException(passHandle) != null) {
26.1291 + return obj;
26.1292 + }
26.1293 + Object rep = resolveObject(obj);
26.1294 + if (rep != obj) {
26.1295 + handles.setObject(passHandle, rep);
26.1296 + }
26.1297 + return rep;
26.1298 + }
26.1299 +
26.1300 + /**
26.1301 + * Reads string without allowing it to be replaced in stream. Called from
26.1302 + * within ObjectStreamClass.read().
26.1303 + */
26.1304 + String readTypeString() throws IOException {
26.1305 + int oldHandle = passHandle;
26.1306 + try {
26.1307 + byte tc = bin.peekByte();
26.1308 + switch (tc) {
26.1309 + case TC_NULL:
26.1310 + return (String) readNull();
26.1311 +
26.1312 + case TC_REFERENCE:
26.1313 + return (String) readHandle(false);
26.1314 +
26.1315 + case TC_STRING:
26.1316 + case TC_LONGSTRING:
26.1317 + return readString(false);
26.1318 +
26.1319 + default:
26.1320 + throw new StreamCorruptedException(
26.1321 + String.format("invalid type code: %02X", tc));
26.1322 + }
26.1323 + } finally {
26.1324 + passHandle = oldHandle;
26.1325 + }
26.1326 + }
26.1327 +
26.1328 + /**
26.1329 + * Reads in null code, sets passHandle to NULL_HANDLE and returns null.
26.1330 + */
26.1331 + private Object readNull() throws IOException {
26.1332 + if (bin.readByte() != TC_NULL) {
26.1333 + throw new InternalError();
26.1334 + }
26.1335 + passHandle = NULL_HANDLE;
26.1336 + return null;
26.1337 + }
26.1338 +
26.1339 + /**
26.1340 + * Reads in object handle, sets passHandle to the read handle, and returns
26.1341 + * object associated with the handle.
26.1342 + */
26.1343 + private Object readHandle(boolean unshared) throws IOException {
26.1344 + if (bin.readByte() != TC_REFERENCE) {
26.1345 + throw new InternalError();
26.1346 + }
26.1347 + passHandle = bin.readInt() - baseWireHandle;
26.1348 + if (passHandle < 0 || passHandle >= handles.size()) {
26.1349 + throw new StreamCorruptedException(
26.1350 + String.format("invalid handle value: %08X", passHandle +
26.1351 + baseWireHandle));
26.1352 + }
26.1353 + if (unshared) {
26.1354 + // REMIND: what type of exception to throw here?
26.1355 + throw new InvalidObjectException(
26.1356 + "cannot read back reference as unshared");
26.1357 + }
26.1358 +
26.1359 + Object obj = handles.lookupObject(passHandle);
26.1360 + if (obj == unsharedMarker) {
26.1361 + // REMIND: what type of exception to throw here?
26.1362 + throw new InvalidObjectException(
26.1363 + "cannot read back reference to unshared object");
26.1364 + }
26.1365 + return obj;
26.1366 + }
26.1367 +
26.1368 + /**
26.1369 + * Reads in and returns class object. Sets passHandle to class object's
26.1370 + * assigned handle. Returns null if class is unresolvable (in which case a
26.1371 + * ClassNotFoundException will be associated with the class' handle in the
26.1372 + * handle table).
26.1373 + */
26.1374 + private Class readClass(boolean unshared) throws IOException {
26.1375 + if (bin.readByte() != TC_CLASS) {
26.1376 + throw new InternalError();
26.1377 + }
26.1378 + ObjectStreamClass desc = readClassDesc(false);
26.1379 + Class cl = desc.forClass();
26.1380 + passHandle = handles.assign(unshared ? unsharedMarker : cl);
26.1381 +
26.1382 + ClassNotFoundException resolveEx = desc.getResolveException();
26.1383 + if (resolveEx != null) {
26.1384 + handles.markException(passHandle, resolveEx);
26.1385 + }
26.1386 +
26.1387 + handles.finish(passHandle);
26.1388 + return cl;
26.1389 + }
26.1390 +
26.1391 + /**
26.1392 + * Reads in and returns (possibly null) class descriptor. Sets passHandle
26.1393 + * to class descriptor's assigned handle. If class descriptor cannot be
26.1394 + * resolved to a class in the local VM, a ClassNotFoundException is
26.1395 + * associated with the class descriptor's handle.
26.1396 + */
26.1397 + private ObjectStreamClass readClassDesc(boolean unshared)
26.1398 + throws IOException
26.1399 + {
26.1400 + byte tc = bin.peekByte();
26.1401 + switch (tc) {
26.1402 + case TC_NULL:
26.1403 + return (ObjectStreamClass) readNull();
26.1404 +
26.1405 + case TC_REFERENCE:
26.1406 + return (ObjectStreamClass) readHandle(unshared);
26.1407 +
26.1408 + case TC_PROXYCLASSDESC:
26.1409 + return readProxyDesc(unshared);
26.1410 +
26.1411 + case TC_CLASSDESC:
26.1412 + return readNonProxyDesc(unshared);
26.1413 +
26.1414 + default:
26.1415 + throw new StreamCorruptedException(
26.1416 + String.format("invalid type code: %02X", tc));
26.1417 + }
26.1418 + }
26.1419 +
26.1420 + /**
26.1421 + * Reads in and returns class descriptor for a dynamic proxy class. Sets
26.1422 + * passHandle to proxy class descriptor's assigned handle. If proxy class
26.1423 + * descriptor cannot be resolved to a class in the local VM, a
26.1424 + * ClassNotFoundException is associated with the descriptor's handle.
26.1425 + */
26.1426 + private ObjectStreamClass readProxyDesc(boolean unshared)
26.1427 + throws IOException
26.1428 + {
26.1429 + if (bin.readByte() != TC_PROXYCLASSDESC) {
26.1430 + throw new InternalError();
26.1431 + }
26.1432 +
26.1433 + ObjectStreamClass desc = new ObjectStreamClass();
26.1434 + int descHandle = handles.assign(unshared ? unsharedMarker : desc);
26.1435 + passHandle = NULL_HANDLE;
26.1436 +
26.1437 + int numIfaces = bin.readInt();
26.1438 + String[] ifaces = new String[numIfaces];
26.1439 + for (int i = 0; i < numIfaces; i++) {
26.1440 + ifaces[i] = bin.readUTF();
26.1441 + }
26.1442 +
26.1443 + Class cl = null;
26.1444 + ClassNotFoundException resolveEx = null;
26.1445 + bin.setBlockDataMode(true);
26.1446 + try {
26.1447 + if ((cl = resolveProxyClass(ifaces)) == null) {
26.1448 + resolveEx = new ClassNotFoundException("null class");
26.1449 + }
26.1450 + } catch (ClassNotFoundException ex) {
26.1451 + resolveEx = ex;
26.1452 + }
26.1453 + skipCustomData();
26.1454 +
26.1455 + desc.initProxy(cl, resolveEx, readClassDesc(false));
26.1456 +
26.1457 + handles.finish(descHandle);
26.1458 + passHandle = descHandle;
26.1459 + return desc;
26.1460 + }
26.1461 +
26.1462 + /**
26.1463 + * Reads in and returns class descriptor for a class that is not a dynamic
26.1464 + * proxy class. Sets passHandle to class descriptor's assigned handle. If
26.1465 + * class descriptor cannot be resolved to a class in the local VM, a
26.1466 + * ClassNotFoundException is associated with the descriptor's handle.
26.1467 + */
26.1468 + private ObjectStreamClass readNonProxyDesc(boolean unshared)
26.1469 + throws IOException
26.1470 + {
26.1471 + if (bin.readByte() != TC_CLASSDESC) {
26.1472 + throw new InternalError();
26.1473 + }
26.1474 +
26.1475 + ObjectStreamClass desc = new ObjectStreamClass();
26.1476 + int descHandle = handles.assign(unshared ? unsharedMarker : desc);
26.1477 + passHandle = NULL_HANDLE;
26.1478 +
26.1479 + ObjectStreamClass readDesc = null;
26.1480 + try {
26.1481 + readDesc = readClassDescriptor();
26.1482 + } catch (ClassNotFoundException ex) {
26.1483 + throw (IOException) new InvalidClassException(
26.1484 + "failed to read class descriptor").initCause(ex);
26.1485 + }
26.1486 +
26.1487 + Class cl = null;
26.1488 + ClassNotFoundException resolveEx = null;
26.1489 + bin.setBlockDataMode(true);
26.1490 + try {
26.1491 + if ((cl = resolveClass(readDesc)) == null) {
26.1492 + resolveEx = new ClassNotFoundException("null class");
26.1493 + }
26.1494 + } catch (ClassNotFoundException ex) {
26.1495 + resolveEx = ex;
26.1496 + }
26.1497 + skipCustomData();
26.1498 +
26.1499 + desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));
26.1500 +
26.1501 + handles.finish(descHandle);
26.1502 + passHandle = descHandle;
26.1503 + return desc;
26.1504 + }
26.1505 +
26.1506 + /**
26.1507 + * Reads in and returns new string. Sets passHandle to new string's
26.1508 + * assigned handle.
26.1509 + */
26.1510 + private String readString(boolean unshared) throws IOException {
26.1511 + String str;
26.1512 + byte tc = bin.readByte();
26.1513 + switch (tc) {
26.1514 + case TC_STRING:
26.1515 + str = bin.readUTF();
26.1516 + break;
26.1517 +
26.1518 + case TC_LONGSTRING:
26.1519 + str = bin.readLongUTF();
26.1520 + break;
26.1521 +
26.1522 + default:
26.1523 + throw new StreamCorruptedException(
26.1524 + String.format("invalid type code: %02X", tc));
26.1525 + }
26.1526 + passHandle = handles.assign(unshared ? unsharedMarker : str);
26.1527 + handles.finish(passHandle);
26.1528 + return str;
26.1529 + }
26.1530 +
26.1531 + /**
26.1532 + * Reads in and returns array object, or null if array class is
26.1533 + * unresolvable. Sets passHandle to array's assigned handle.
26.1534 + */
26.1535 + private Object readArray(boolean unshared) throws IOException {
26.1536 + if (bin.readByte() != TC_ARRAY) {
26.1537 + throw new InternalError();
26.1538 + }
26.1539 +
26.1540 + ObjectStreamClass desc = readClassDesc(false);
26.1541 + int len = bin.readInt();
26.1542 +
26.1543 + Object array = null;
26.1544 + Class cl, ccl = null;
26.1545 + if ((cl = desc.forClass()) != null) {
26.1546 + ccl = cl.getComponentType();
26.1547 + array = Array.newInstance(ccl, len);
26.1548 + }
26.1549 +
26.1550 + int arrayHandle = handles.assign(unshared ? unsharedMarker : array);
26.1551 + ClassNotFoundException resolveEx = desc.getResolveException();
26.1552 + if (resolveEx != null) {
26.1553 + handles.markException(arrayHandle, resolveEx);
26.1554 + }
26.1555 +
26.1556 + if (ccl == null) {
26.1557 + for (int i = 0; i < len; i++) {
26.1558 + readObject0(false);
26.1559 + }
26.1560 + } else if (ccl.isPrimitive()) {
26.1561 + if (ccl == Integer.TYPE) {
26.1562 + bin.readInts((int[]) array, 0, len);
26.1563 + } else if (ccl == Byte.TYPE) {
26.1564 + bin.readFully((byte[]) array, 0, len, true);
26.1565 + } else if (ccl == Long.TYPE) {
26.1566 + bin.readLongs((long[]) array, 0, len);
26.1567 + } else if (ccl == Float.TYPE) {
26.1568 + bin.readFloats((float[]) array, 0, len);
26.1569 + } else if (ccl == Double.TYPE) {
26.1570 + bin.readDoubles((double[]) array, 0, len);
26.1571 + } else if (ccl == Short.TYPE) {
26.1572 + bin.readShorts((short[]) array, 0, len);
26.1573 + } else if (ccl == Character.TYPE) {
26.1574 + bin.readChars((char[]) array, 0, len);
26.1575 + } else if (ccl == Boolean.TYPE) {
26.1576 + bin.readBooleans((boolean[]) array, 0, len);
26.1577 + } else {
26.1578 + throw new InternalError();
26.1579 + }
26.1580 + } else {
26.1581 + Object[] oa = (Object[]) array;
26.1582 + for (int i = 0; i < len; i++) {
26.1583 + oa[i] = readObject0(false);
26.1584 + handles.markDependency(arrayHandle, passHandle);
26.1585 + }
26.1586 + }
26.1587 +
26.1588 + handles.finish(arrayHandle);
26.1589 + passHandle = arrayHandle;
26.1590 + return array;
26.1591 + }
26.1592 +
26.1593 + /**
26.1594 + * Reads in and returns enum constant, or null if enum type is
26.1595 + * unresolvable. Sets passHandle to enum constant's assigned handle.
26.1596 + */
26.1597 + private Enum readEnum(boolean unshared) throws IOException {
26.1598 + if (bin.readByte() != TC_ENUM) {
26.1599 + throw new InternalError();
26.1600 + }
26.1601 +
26.1602 + ObjectStreamClass desc = readClassDesc(false);
26.1603 + if (!desc.isEnum()) {
26.1604 + throw new InvalidClassException("non-enum class: " + desc);
26.1605 + }
26.1606 +
26.1607 + int enumHandle = handles.assign(unshared ? unsharedMarker : null);
26.1608 + ClassNotFoundException resolveEx = desc.getResolveException();
26.1609 + if (resolveEx != null) {
26.1610 + handles.markException(enumHandle, resolveEx);
26.1611 + }
26.1612 +
26.1613 + String name = readString(false);
26.1614 + Enum en = null;
26.1615 + Class cl = desc.forClass();
26.1616 + if (cl != null) {
26.1617 + try {
26.1618 + en = Enum.valueOf(cl, name);
26.1619 + } catch (IllegalArgumentException ex) {
26.1620 + throw (IOException) new InvalidObjectException(
26.1621 + "enum constant " + name + " does not exist in " +
26.1622 + cl).initCause(ex);
26.1623 + }
26.1624 + if (!unshared) {
26.1625 + handles.setObject(enumHandle, en);
26.1626 + }
26.1627 + }
26.1628 +
26.1629 + handles.finish(enumHandle);
26.1630 + passHandle = enumHandle;
26.1631 + return en;
26.1632 + }
26.1633 +
26.1634 + /**
26.1635 + * Reads and returns "ordinary" (i.e., not a String, Class,
26.1636 + * ObjectStreamClass, array, or enum constant) object, or null if object's
26.1637 + * class is unresolvable (in which case a ClassNotFoundException will be
26.1638 + * associated with object's handle). Sets passHandle to object's assigned
26.1639 + * handle.
26.1640 + */
26.1641 + private Object readOrdinaryObject(boolean unshared)
26.1642 + throws IOException
26.1643 + {
26.1644 + if (bin.readByte() != TC_OBJECT) {
26.1645 + throw new InternalError();
26.1646 + }
26.1647 +
26.1648 + ObjectStreamClass desc = readClassDesc(false);
26.1649 + desc.checkDeserialize();
26.1650 +
26.1651 + Object obj;
26.1652 + try {
26.1653 + obj = desc.isInstantiable() ? desc.newInstance() : null;
26.1654 + } catch (Exception ex) {
26.1655 + throw (IOException) new InvalidClassException(
26.1656 + desc.forClass().getName(),
26.1657 + "unable to create instance").initCause(ex);
26.1658 + }
26.1659 +
26.1660 + passHandle = handles.assign(unshared ? unsharedMarker : obj);
26.1661 + ClassNotFoundException resolveEx = desc.getResolveException();
26.1662 + if (resolveEx != null) {
26.1663 + handles.markException(passHandle, resolveEx);
26.1664 + }
26.1665 +
26.1666 + if (desc.isExternalizable()) {
26.1667 + readExternalData((Externalizable) obj, desc);
26.1668 + } else {
26.1669 + readSerialData(obj, desc);
26.1670 + }
26.1671 +
26.1672 + handles.finish(passHandle);
26.1673 +
26.1674 + if (obj != null &&
26.1675 + handles.lookupException(passHandle) == null &&
26.1676 + desc.hasReadResolveMethod())
26.1677 + {
26.1678 + Object rep = desc.invokeReadResolve(obj);
26.1679 + if (unshared && rep.getClass().isArray()) {
26.1680 + rep = cloneArray(rep);
26.1681 + }
26.1682 + if (rep != obj) {
26.1683 + handles.setObject(passHandle, obj = rep);
26.1684 + }
26.1685 + }
26.1686 +
26.1687 + return obj;
26.1688 + }
26.1689 +
26.1690 + /**
26.1691 + * If obj is non-null, reads externalizable data by invoking readExternal()
26.1692 + * method of obj; otherwise, attempts to skip over externalizable data.
26.1693 + * Expects that passHandle is set to obj's handle before this method is
26.1694 + * called.
26.1695 + */
26.1696 + private void readExternalData(Externalizable obj, ObjectStreamClass desc)
26.1697 + throws IOException
26.1698 + {
26.1699 + Object oldContext = curContext;
26.1700 + curContext = null;
26.1701 + try {
26.1702 + boolean blocked = desc.hasBlockExternalData();
26.1703 + if (blocked) {
26.1704 + bin.setBlockDataMode(true);
26.1705 + }
26.1706 + if (obj != null) {
26.1707 + try {
26.1708 + obj.readExternal(this);
26.1709 + } catch (ClassNotFoundException ex) {
26.1710 + /*
26.1711 + * In most cases, the handle table has already propagated
26.1712 + * a CNFException to passHandle at this point; this mark
26.1713 + * call is included to address cases where the readExternal
26.1714 + * method has cons'ed and thrown a new CNFException of its
26.1715 + * own.
26.1716 + */
26.1717 + handles.markException(passHandle, ex);
26.1718 + }
26.1719 + }
26.1720 + if (blocked) {
26.1721 + skipCustomData();
26.1722 + }
26.1723 + } finally {
26.1724 + curContext = oldContext;
26.1725 + }
26.1726 + /*
26.1727 + * At this point, if the externalizable data was not written in
26.1728 + * block-data form and either the externalizable class doesn't exist
26.1729 + * locally (i.e., obj == null) or readExternal() just threw a
26.1730 + * CNFException, then the stream is probably in an inconsistent state,
26.1731 + * since some (or all) of the externalizable data may not have been
26.1732 + * consumed. Since there's no "correct" action to take in this case,
26.1733 + * we mimic the behavior of past serialization implementations and
26.1734 + * blindly hope that the stream is in sync; if it isn't and additional
26.1735 + * externalizable data remains in the stream, a subsequent read will
26.1736 + * most likely throw a StreamCorruptedException.
26.1737 + */
26.1738 + }
26.1739 +
26.1740 + /**
26.1741 + * Reads (or attempts to skip, if obj is null or is tagged with a
26.1742 + * ClassNotFoundException) instance data for each serializable class of
26.1743 + * object in stream, from superclass to subclass. Expects that passHandle
26.1744 + * is set to obj's handle before this method is called.
26.1745 + */
26.1746 + private void readSerialData(Object obj, ObjectStreamClass desc)
26.1747 + throws IOException
26.1748 + {
26.1749 + ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
26.1750 + for (int i = 0; i < slots.length; i++) {
26.1751 + ObjectStreamClass slotDesc = slots[i].desc;
26.1752 +
26.1753 + if (slots[i].hasData) {
26.1754 + if (obj != null &&
26.1755 + slotDesc.hasReadObjectMethod() &&
26.1756 + handles.lookupException(passHandle) == null)
26.1757 + {
26.1758 + Object oldContext = curContext;
26.1759 +
26.1760 + try {
26.1761 + curContext = null; //new SerialCallbackContext(obj, slotDesc);
26.1762 +
26.1763 + bin.setBlockDataMode(true);
26.1764 + slotDesc.invokeReadObject(obj, this);
26.1765 + } catch (ClassNotFoundException ex) {
26.1766 + /*
26.1767 + * In most cases, the handle table has already
26.1768 + * propagated a CNFException to passHandle at this
26.1769 + * point; this mark call is included to address cases
26.1770 + * where the custom readObject method has cons'ed and
26.1771 + * thrown a new CNFException of its own.
26.1772 + */
26.1773 + handles.markException(passHandle, ex);
26.1774 + } finally {
26.1775 + //curContext.setUsed();
26.1776 + curContext = oldContext;
26.1777 + }
26.1778 +
26.1779 + /*
26.1780 + * defaultDataEnd may have been set indirectly by custom
26.1781 + * readObject() method when calling defaultReadObject() or
26.1782 + * readFields(); clear it to restore normal read behavior.
26.1783 + */
26.1784 + defaultDataEnd = false;
26.1785 + } else {
26.1786 + defaultReadFields(obj, slotDesc);
26.1787 + }
26.1788 + if (slotDesc.hasWriteObjectData()) {
26.1789 + skipCustomData();
26.1790 + } else {
26.1791 + bin.setBlockDataMode(false);
26.1792 + }
26.1793 + } else {
26.1794 + if (obj != null &&
26.1795 + slotDesc.hasReadObjectNoDataMethod() &&
26.1796 + handles.lookupException(passHandle) == null)
26.1797 + {
26.1798 + slotDesc.invokeReadObjectNoData(obj);
26.1799 + }
26.1800 + }
26.1801 + }
26.1802 + }
26.1803 +
26.1804 + /**
26.1805 + * Skips over all block data and objects until TC_ENDBLOCKDATA is
26.1806 + * encountered.
26.1807 + */
26.1808 + private void skipCustomData() throws IOException {
26.1809 + int oldHandle = passHandle;
26.1810 + for (;;) {
26.1811 + if (bin.getBlockDataMode()) {
26.1812 + bin.skipBlockData();
26.1813 + bin.setBlockDataMode(false);
26.1814 + }
26.1815 + switch (bin.peekByte()) {
26.1816 + case TC_BLOCKDATA:
26.1817 + case TC_BLOCKDATALONG:
26.1818 + bin.setBlockDataMode(true);
26.1819 + break;
26.1820 +
26.1821 + case TC_ENDBLOCKDATA:
26.1822 + bin.readByte();
26.1823 + passHandle = oldHandle;
26.1824 + return;
26.1825 +
26.1826 + default:
26.1827 + readObject0(false);
26.1828 + break;
26.1829 + }
26.1830 + }
26.1831 + }
26.1832 +
26.1833 + /**
26.1834 + * Reads in values of serializable fields declared by given class
26.1835 + * descriptor. If obj is non-null, sets field values in obj. Expects that
26.1836 + * passHandle is set to obj's handle before this method is called.
26.1837 + */
26.1838 + private void defaultReadFields(Object obj, ObjectStreamClass desc)
26.1839 + throws IOException
26.1840 + {
26.1841 + // REMIND: is isInstance check necessary?
26.1842 + Class cl = desc.forClass();
26.1843 + if (cl != null && obj != null && !cl.isInstance(obj)) {
26.1844 + throw new ClassCastException();
26.1845 + }
26.1846 +
26.1847 + int primDataSize = desc.getPrimDataSize();
26.1848 + if (primVals == null || primVals.length < primDataSize) {
26.1849 + primVals = new byte[primDataSize];
26.1850 + }
26.1851 + bin.readFully(primVals, 0, primDataSize, false);
26.1852 + if (obj != null) {
26.1853 + desc.setPrimFieldValues(obj, primVals);
26.1854 + }
26.1855 +
26.1856 + int objHandle = passHandle;
26.1857 + ObjectStreamField[] fields = desc.getFields(false);
26.1858 + Object[] objVals = new Object[desc.getNumObjFields()];
26.1859 + int numPrimFields = fields.length - objVals.length;
26.1860 + for (int i = 0; i < objVals.length; i++) {
26.1861 + ObjectStreamField f = fields[numPrimFields + i];
26.1862 + objVals[i] = readObject0(f.isUnshared());
26.1863 + if (f.getField() != null) {
26.1864 + handles.markDependency(objHandle, passHandle);
26.1865 + }
26.1866 + }
26.1867 + if (obj != null) {
26.1868 + desc.setObjFieldValues(obj, objVals);
26.1869 + }
26.1870 + passHandle = objHandle;
26.1871 + }
26.1872 +
26.1873 + /**
26.1874 + * Reads in and returns IOException that caused serialization to abort.
26.1875 + * All stream state is discarded prior to reading in fatal exception. Sets
26.1876 + * passHandle to fatal exception's handle.
26.1877 + */
26.1878 + private IOException readFatalException() throws IOException {
26.1879 + if (bin.readByte() != TC_EXCEPTION) {
26.1880 + throw new InternalError();
26.1881 + }
26.1882 + clear();
26.1883 + return (IOException) readObject0(false);
26.1884 + }
26.1885 +
26.1886 + /**
26.1887 + * If recursion depth is 0, clears internal data structures; otherwise,
26.1888 + * throws a StreamCorruptedException. This method is called when a
26.1889 + * TC_RESET typecode is encountered.
26.1890 + */
26.1891 + private void handleReset() throws StreamCorruptedException {
26.1892 + if (depth > 0) {
26.1893 + throw new StreamCorruptedException(
26.1894 + "unexpected reset; recursion depth: " + depth);
26.1895 + }
26.1896 + clear();
26.1897 + }
26.1898 +
26.1899 + /**
26.1900 + * Converts specified span of bytes into float values.
26.1901 + */
26.1902 + // REMIND: remove once hotspot inlines Float.intBitsToFloat
26.1903 + private static native void bytesToFloats(byte[] src, int srcpos,
26.1904 + float[] dst, int dstpos,
26.1905 + int nfloats);
26.1906 +
26.1907 + /**
26.1908 + * Converts specified span of bytes into double values.
26.1909 + */
26.1910 + // REMIND: remove once hotspot inlines Double.longBitsToDouble
26.1911 + private static native void bytesToDoubles(byte[] src, int srcpos,
26.1912 + double[] dst, int dstpos,
26.1913 + int ndoubles);
26.1914 +
26.1915 + /**
26.1916 + * Returns the first non-null class loader (not counting class loaders of
26.1917 + * generated reflection implementation classes) up the execution stack, or
26.1918 + * null if only code from the null class loader is on the stack. This
26.1919 + * method is also called via reflection by the following RMI-IIOP class:
26.1920 + *
26.1921 + * com.sun.corba.se.internal.util.JDKClassLoader
26.1922 + *
26.1923 + * This method should not be removed or its signature changed without
26.1924 + * corresponding modifications to the above class.
26.1925 + */
26.1926 + // REMIND: change name to something more accurate?
26.1927 + private static native ClassLoader latestUserDefinedLoader();
26.1928 +
26.1929 + /**
26.1930 + * Default GetField implementation.
26.1931 + */
26.1932 + private class GetFieldImpl extends GetField {
26.1933 +
26.1934 + /** class descriptor describing serializable fields */
26.1935 + private final ObjectStreamClass desc;
26.1936 + /** primitive field values */
26.1937 + private final byte[] primVals;
26.1938 + /** object field values */
26.1939 + private final Object[] objVals;
26.1940 + /** object field value handles */
26.1941 + private final int[] objHandles;
26.1942 +
26.1943 + /**
26.1944 + * Creates GetFieldImpl object for reading fields defined in given
26.1945 + * class descriptor.
26.1946 + */
26.1947 + GetFieldImpl(ObjectStreamClass desc) {
26.1948 + this.desc = desc;
26.1949 + primVals = new byte[desc.getPrimDataSize()];
26.1950 + objVals = new Object[desc.getNumObjFields()];
26.1951 + objHandles = new int[objVals.length];
26.1952 + }
26.1953 +
26.1954 + public ObjectStreamClass getObjectStreamClass() {
26.1955 + return desc;
26.1956 + }
26.1957 +
26.1958 + public boolean defaulted(String name) throws IOException {
26.1959 + return (getFieldOffset(name, null) < 0);
26.1960 + }
26.1961 +
26.1962 + public boolean get(String name, boolean val) throws IOException {
26.1963 + int off = getFieldOffset(name, Boolean.TYPE);
26.1964 + return (off >= 0) ? Bits.getBoolean(primVals, off) : val;
26.1965 + }
26.1966 +
26.1967 + public byte get(String name, byte val) throws IOException {
26.1968 + int off = getFieldOffset(name, Byte.TYPE);
26.1969 + return (off >= 0) ? primVals[off] : val;
26.1970 + }
26.1971 +
26.1972 + public char get(String name, char val) throws IOException {
26.1973 + int off = getFieldOffset(name, Character.TYPE);
26.1974 + return (off >= 0) ? Bits.getChar(primVals, off) : val;
26.1975 + }
26.1976 +
26.1977 + public short get(String name, short val) throws IOException {
26.1978 + int off = getFieldOffset(name, Short.TYPE);
26.1979 + return (off >= 0) ? Bits.getShort(primVals, off) : val;
26.1980 + }
26.1981 +
26.1982 + public int get(String name, int val) throws IOException {
26.1983 + int off = getFieldOffset(name, Integer.TYPE);
26.1984 + return (off >= 0) ? Bits.getInt(primVals, off) : val;
26.1985 + }
26.1986 +
26.1987 + public float get(String name, float val) throws IOException {
26.1988 + int off = getFieldOffset(name, Float.TYPE);
26.1989 + return (off >= 0) ? Bits.getFloat(primVals, off) : val;
26.1990 + }
26.1991 +
26.1992 + public long get(String name, long val) throws IOException {
26.1993 + int off = getFieldOffset(name, Long.TYPE);
26.1994 + return (off >= 0) ? Bits.getLong(primVals, off) : val;
26.1995 + }
26.1996 +
26.1997 + public double get(String name, double val) throws IOException {
26.1998 + int off = getFieldOffset(name, Double.TYPE);
26.1999 + return (off >= 0) ? Bits.getDouble(primVals, off) : val;
26.2000 + }
26.2001 +
26.2002 + public Object get(String name, Object val) throws IOException {
26.2003 + int off = getFieldOffset(name, Object.class);
26.2004 + if (off >= 0) {
26.2005 + int objHandle = objHandles[off];
26.2006 + handles.markDependency(passHandle, objHandle);
26.2007 + return (handles.lookupException(objHandle) == null) ?
26.2008 + objVals[off] : null;
26.2009 + } else {
26.2010 + return val;
26.2011 + }
26.2012 + }
26.2013 +
26.2014 + /**
26.2015 + * Reads primitive and object field values from stream.
26.2016 + */
26.2017 + void readFields() throws IOException {
26.2018 + bin.readFully(primVals, 0, primVals.length, false);
26.2019 +
26.2020 + int oldHandle = passHandle;
26.2021 + ObjectStreamField[] fields = desc.getFields(false);
26.2022 + int numPrimFields = fields.length - objVals.length;
26.2023 + for (int i = 0; i < objVals.length; i++) {
26.2024 + objVals[i] =
26.2025 + readObject0(fields[numPrimFields + i].isUnshared());
26.2026 + objHandles[i] = passHandle;
26.2027 + }
26.2028 + passHandle = oldHandle;
26.2029 + }
26.2030 +
26.2031 + /**
26.2032 + * Returns offset of field with given name and type. A specified type
26.2033 + * of null matches all types, Object.class matches all non-primitive
26.2034 + * types, and any other non-null type matches assignable types only.
26.2035 + * If no matching field is found in the (incoming) class
26.2036 + * descriptor but a matching field is present in the associated local
26.2037 + * class descriptor, returns -1. Throws IllegalArgumentException if
26.2038 + * neither incoming nor local class descriptor contains a match.
26.2039 + */
26.2040 + private int getFieldOffset(String name, Class type) {
26.2041 + ObjectStreamField field = desc.getField(name, type);
26.2042 + if (field != null) {
26.2043 + return field.getOffset();
26.2044 + } else if (desc.getLocalDesc().getField(name, type) != null) {
26.2045 + return -1;
26.2046 + } else {
26.2047 + throw new IllegalArgumentException("no such field " + name +
26.2048 + " with type " + type);
26.2049 + }
26.2050 + }
26.2051 + }
26.2052 +
26.2053 + /**
26.2054 + * Prioritized list of callbacks to be performed once object graph has been
26.2055 + * completely deserialized.
26.2056 + */
26.2057 + private static class ValidationList {
26.2058 +
26.2059 +
26.2060 + /**
26.2061 + * Creates new (empty) ValidationList.
26.2062 + */
26.2063 + ValidationList() {
26.2064 + }
26.2065 +
26.2066 + /**
26.2067 + * Registers callback. Throws InvalidObjectException if callback
26.2068 + * object is null.
26.2069 + */
26.2070 + void register(ObjectInputValidation obj, int priority)
26.2071 + throws InvalidObjectException
26.2072 + {
26.2073 + if (obj == null) {
26.2074 + throw new InvalidObjectException("null callback");
26.2075 + }
26.2076 + throw new InvalidObjectException("Does not work.");
26.2077 + }
26.2078 +
26.2079 + /**
26.2080 + * Invokes all registered callbacks and clears the callback list.
26.2081 + * Callbacks with higher priorities are called first; those with equal
26.2082 + * priorities may be called in any order. If any of the callbacks
26.2083 + * throws an InvalidObjectException, the callback process is terminated
26.2084 + * and the exception propagated upwards.
26.2085 + */
26.2086 + void doCallbacks() throws InvalidObjectException {
26.2087 + }
26.2088 +
26.2089 + /**
26.2090 + * Resets the callback list to its initial (empty) state.
26.2091 + */
26.2092 + public void clear() {
26.2093 + }
26.2094 + }
26.2095 +
26.2096 + /**
26.2097 + * Input stream supporting single-byte peek operations.
26.2098 + */
26.2099 + private static class PeekInputStream extends InputStream {
26.2100 +
26.2101 + /** underlying stream */
26.2102 + private final InputStream in;
26.2103 + /** peeked byte */
26.2104 + private int peekb = -1;
26.2105 +
26.2106 + /**
26.2107 + * Creates new PeekInputStream on top of given underlying stream.
26.2108 + */
26.2109 + PeekInputStream(InputStream in) {
26.2110 + this.in = in;
26.2111 + }
26.2112 +
26.2113 + /**
26.2114 + * Peeks at next byte value in stream. Similar to read(), except
26.2115 + * that it does not consume the read value.
26.2116 + */
26.2117 + int peek() throws IOException {
26.2118 + return (peekb >= 0) ? peekb : (peekb = in.read());
26.2119 + }
26.2120 +
26.2121 + public int read() throws IOException {
26.2122 + if (peekb >= 0) {
26.2123 + int v = peekb;
26.2124 + peekb = -1;
26.2125 + return v;
26.2126 + } else {
26.2127 + return in.read();
26.2128 + }
26.2129 + }
26.2130 +
26.2131 + public int read(byte[] b, int off, int len) throws IOException {
26.2132 + if (len == 0) {
26.2133 + return 0;
26.2134 + } else if (peekb < 0) {
26.2135 + return in.read(b, off, len);
26.2136 + } else {
26.2137 + b[off++] = (byte) peekb;
26.2138 + len--;
26.2139 + peekb = -1;
26.2140 + int n = in.read(b, off, len);
26.2141 + return (n >= 0) ? (n + 1) : 1;
26.2142 + }
26.2143 + }
26.2144 +
26.2145 + void readFully(byte[] b, int off, int len) throws IOException {
26.2146 + int n = 0;
26.2147 + while (n < len) {
26.2148 + int count = read(b, off + n, len - n);
26.2149 + if (count < 0) {
26.2150 + throw new EOFException();
26.2151 + }
26.2152 + n += count;
26.2153 + }
26.2154 + }
26.2155 +
26.2156 + public long skip(long n) throws IOException {
26.2157 + if (n <= 0) {
26.2158 + return 0;
26.2159 + }
26.2160 + int skipped = 0;
26.2161 + if (peekb >= 0) {
26.2162 + peekb = -1;
26.2163 + skipped++;
26.2164 + n--;
26.2165 + }
26.2166 + return skipped + skip(n);
26.2167 + }
26.2168 +
26.2169 + public int available() throws IOException {
26.2170 + return in.available() + ((peekb >= 0) ? 1 : 0);
26.2171 + }
26.2172 +
26.2173 + public void close() throws IOException {
26.2174 + in.close();
26.2175 + }
26.2176 + }
26.2177 +
26.2178 + /**
26.2179 + * Input stream with two modes: in default mode, inputs data written in the
26.2180 + * same format as DataOutputStream; in "block data" mode, inputs data
26.2181 + * bracketed by block data markers (see object serialization specification
26.2182 + * for details). Buffering depends on block data mode: when in default
26.2183 + * mode, no data is buffered in advance; when in block data mode, all data
26.2184 + * for the current data block is read in at once (and buffered).
26.2185 + */
26.2186 + private class BlockDataInputStream
26.2187 + extends InputStream implements DataInput
26.2188 + {
26.2189 + /** maximum data block length */
26.2190 + private static final int MAX_BLOCK_SIZE = 1024;
26.2191 + /** maximum data block header length */
26.2192 + private static final int MAX_HEADER_SIZE = 5;
26.2193 + /** (tunable) length of char buffer (for reading strings) */
26.2194 + private static final int CHAR_BUF_SIZE = 256;
26.2195 + /** readBlockHeader() return value indicating header read may block */
26.2196 + private static final int HEADER_BLOCKED = -2;
26.2197 +
26.2198 + /** buffer for reading general/block data */
26.2199 + private final byte[] buf = new byte[MAX_BLOCK_SIZE];
26.2200 + /** buffer for reading block data headers */
26.2201 + private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
26.2202 + /** char buffer for fast string reads */
26.2203 + private final char[] cbuf = new char[CHAR_BUF_SIZE];
26.2204 +
26.2205 + /** block data mode */
26.2206 + private boolean blkmode = false;
26.2207 +
26.2208 + // block data state fields; values meaningful only when blkmode true
26.2209 + /** current offset into buf */
26.2210 + private int pos = 0;
26.2211 + /** end offset of valid data in buf, or -1 if no more block data */
26.2212 + private int end = -1;
26.2213 + /** number of bytes in current block yet to be read from stream */
26.2214 + private int unread = 0;
26.2215 +
26.2216 + /** underlying stream (wrapped in peekable filter stream) */
26.2217 + private final PeekInputStream in;
26.2218 + /** loopback stream (for data reads that span data blocks) */
26.2219 + private final DataInputStream din;
26.2220 +
26.2221 + /**
26.2222 + * Creates new BlockDataInputStream on top of given underlying stream.
26.2223 + * Block data mode is turned off by default.
26.2224 + */
26.2225 + BlockDataInputStream(InputStream in) {
26.2226 + this.in = new PeekInputStream(in);
26.2227 + din = new DataInputStream(this);
26.2228 + }
26.2229 +
26.2230 + /**
26.2231 + * Sets block data mode to the given mode (true == on, false == off)
26.2232 + * and returns the previous mode value. If the new mode is the same as
26.2233 + * the old mode, no action is taken. Throws IllegalStateException if
26.2234 + * block data mode is being switched from on to off while unconsumed
26.2235 + * block data is still present in the stream.
26.2236 + */
26.2237 + boolean setBlockDataMode(boolean newmode) throws IOException {
26.2238 + if (blkmode == newmode) {
26.2239 + return blkmode;
26.2240 + }
26.2241 + if (newmode) {
26.2242 + pos = 0;
26.2243 + end = 0;
26.2244 + unread = 0;
26.2245 + } else if (pos < end) {
26.2246 + throw new IllegalStateException("unread block data");
26.2247 + }
26.2248 + blkmode = newmode;
26.2249 + return !blkmode;
26.2250 + }
26.2251 +
26.2252 + /**
26.2253 + * Returns true if the stream is currently in block data mode, false
26.2254 + * otherwise.
26.2255 + */
26.2256 + boolean getBlockDataMode() {
26.2257 + return blkmode;
26.2258 + }
26.2259 +
26.2260 + /**
26.2261 + * If in block data mode, skips to the end of the current group of data
26.2262 + * blocks (but does not unset block data mode). If not in block data
26.2263 + * mode, throws an IllegalStateException.
26.2264 + */
26.2265 + void skipBlockData() throws IOException {
26.2266 + if (!blkmode) {
26.2267 + throw new IllegalStateException("not in block data mode");
26.2268 + }
26.2269 + while (end >= 0) {
26.2270 + refill();
26.2271 + }
26.2272 + }
26.2273 +
26.2274 + /**
26.2275 + * Attempts to read in the next block data header (if any). If
26.2276 + * canBlock is false and a full header cannot be read without possibly
26.2277 + * blocking, returns HEADER_BLOCKED, else if the next element in the
26.2278 + * stream is a block data header, returns the block data length
26.2279 + * specified by the header, else returns -1.
26.2280 + */
26.2281 + private int readBlockHeader(boolean canBlock) throws IOException {
26.2282 + if (defaultDataEnd) {
26.2283 + /*
26.2284 + * Fix for 4360508: stream is currently at the end of a field
26.2285 + * value block written via default serialization; since there
26.2286 + * is no terminating TC_ENDBLOCKDATA tag, simulate
26.2287 + * end-of-custom-data behavior explicitly.
26.2288 + */
26.2289 + return -1;
26.2290 + }
26.2291 + try {
26.2292 + for (;;) {
26.2293 + int avail = canBlock ? Integer.MAX_VALUE : in.available();
26.2294 + if (avail == 0) {
26.2295 + return HEADER_BLOCKED;
26.2296 + }
26.2297 +
26.2298 + int tc = in.peek();
26.2299 + switch (tc) {
26.2300 + case TC_BLOCKDATA:
26.2301 + if (avail < 2) {
26.2302 + return HEADER_BLOCKED;
26.2303 + }
26.2304 + in.readFully(hbuf, 0, 2);
26.2305 + return hbuf[1] & 0xFF;
26.2306 +
26.2307 + case TC_BLOCKDATALONG:
26.2308 + if (avail < 5) {
26.2309 + return HEADER_BLOCKED;
26.2310 + }
26.2311 + in.readFully(hbuf, 0, 5);
26.2312 + int len = Bits.getInt(hbuf, 1);
26.2313 + if (len < 0) {
26.2314 + throw new StreamCorruptedException(
26.2315 + "illegal block data header length: " +
26.2316 + len);
26.2317 + }
26.2318 + return len;
26.2319 +
26.2320 + /*
26.2321 + * TC_RESETs may occur in between data blocks.
26.2322 + * Unfortunately, this case must be parsed at a lower
26.2323 + * level than other typecodes, since primitive data
26.2324 + * reads may span data blocks separated by a TC_RESET.
26.2325 + */
26.2326 + case TC_RESET:
26.2327 + in.read();
26.2328 + handleReset();
26.2329 + break;
26.2330 +
26.2331 + default:
26.2332 + if (tc >= 0 && (tc < TC_BASE || tc > TC_MAX)) {
26.2333 + throw new StreamCorruptedException(
26.2334 + String.format("invalid type code: %02X",
26.2335 + tc));
26.2336 + }
26.2337 + return -1;
26.2338 + }
26.2339 + }
26.2340 + } catch (EOFException ex) {
26.2341 + throw new StreamCorruptedException(
26.2342 + "unexpected EOF while reading block data header");
26.2343 + }
26.2344 + }
26.2345 +
26.2346 + /**
26.2347 + * Refills internal buffer buf with block data. Any data in buf at the
26.2348 + * time of the call is considered consumed. Sets the pos, end, and
26.2349 + * unread fields to reflect the new amount of available block data; if
26.2350 + * the next element in the stream is not a data block, sets pos and
26.2351 + * unread to 0 and end to -1.
26.2352 + */
26.2353 + private void refill() throws IOException {
26.2354 + try {
26.2355 + do {
26.2356 + pos = 0;
26.2357 + if (unread > 0) {
26.2358 + int n =
26.2359 + in.read(buf, 0, Math.min(unread, MAX_BLOCK_SIZE));
26.2360 + if (n >= 0) {
26.2361 + end = n;
26.2362 + unread -= n;
26.2363 + } else {
26.2364 + throw new StreamCorruptedException(
26.2365 + "unexpected EOF in middle of data block");
26.2366 + }
26.2367 + } else {
26.2368 + int n = readBlockHeader(true);
26.2369 + if (n >= 0) {
26.2370 + end = 0;
26.2371 + unread = n;
26.2372 + } else {
26.2373 + end = -1;
26.2374 + unread = 0;
26.2375 + }
26.2376 + }
26.2377 + } while (pos == end);
26.2378 + } catch (IOException ex) {
26.2379 + pos = 0;
26.2380 + end = -1;
26.2381 + unread = 0;
26.2382 + throw ex;
26.2383 + }
26.2384 + }
26.2385 +
26.2386 + /**
26.2387 + * If in block data mode, returns the number of unconsumed bytes
26.2388 + * remaining in the current data block. If not in block data mode,
26.2389 + * throws an IllegalStateException.
26.2390 + */
26.2391 + int currentBlockRemaining() {
26.2392 + if (blkmode) {
26.2393 + return (end >= 0) ? (end - pos) + unread : 0;
26.2394 + } else {
26.2395 + throw new IllegalStateException();
26.2396 + }
26.2397 + }
26.2398 +
26.2399 + /**
26.2400 + * Peeks at (but does not consume) and returns the next byte value in
26.2401 + * the stream, or -1 if the end of the stream/block data (if in block
26.2402 + * data mode) has been reached.
26.2403 + */
26.2404 + int peek() throws IOException {
26.2405 + if (blkmode) {
26.2406 + if (pos == end) {
26.2407 + refill();
26.2408 + }
26.2409 + return (end >= 0) ? (buf[pos] & 0xFF) : -1;
26.2410 + } else {
26.2411 + return in.peek();
26.2412 + }
26.2413 + }
26.2414 +
26.2415 + /**
26.2416 + * Peeks at (but does not consume) and returns the next byte value in
26.2417 + * the stream, or throws EOFException if end of stream/block data has
26.2418 + * been reached.
26.2419 + */
26.2420 + byte peekByte() throws IOException {
26.2421 + int val = peek();
26.2422 + if (val < 0) {
26.2423 + throw new EOFException();
26.2424 + }
26.2425 + return (byte) val;
26.2426 + }
26.2427 +
26.2428 +
26.2429 + /* ----------------- generic input stream methods ------------------ */
26.2430 + /*
26.2431 + * The following methods are equivalent to their counterparts in
26.2432 + * InputStream, except that they interpret data block boundaries and
26.2433 + * read the requested data from within data blocks when in block data
26.2434 + * mode.
26.2435 + */
26.2436 +
26.2437 + public int read() throws IOException {
26.2438 + if (blkmode) {
26.2439 + if (pos == end) {
26.2440 + refill();
26.2441 + }
26.2442 + return (end >= 0) ? (buf[pos++] & 0xFF) : -1;
26.2443 + } else {
26.2444 + return in.read();
26.2445 + }
26.2446 + }
26.2447 +
26.2448 + public int read(byte[] b, int off, int len) throws IOException {
26.2449 + return read(b, off, len, false);
26.2450 + }
26.2451 +
26.2452 + public long skip(long len) throws IOException {
26.2453 + long remain = len;
26.2454 + while (remain > 0) {
26.2455 + if (blkmode) {
26.2456 + if (pos == end) {
26.2457 + refill();
26.2458 + }
26.2459 + if (end < 0) {
26.2460 + break;
26.2461 + }
26.2462 + int nread = (int) Math.min(remain, end - pos);
26.2463 + remain -= nread;
26.2464 + pos += nread;
26.2465 + } else {
26.2466 + int nread = (int) Math.min(remain, MAX_BLOCK_SIZE);
26.2467 + if ((nread = in.read(buf, 0, nread)) < 0) {
26.2468 + break;
26.2469 + }
26.2470 + remain -= nread;
26.2471 + }
26.2472 + }
26.2473 + return len - remain;
26.2474 + }
26.2475 +
26.2476 + public int available() throws IOException {
26.2477 + if (blkmode) {
26.2478 + if ((pos == end) && (unread == 0)) {
26.2479 + int n;
26.2480 + while ((n = readBlockHeader(false)) == 0) ;
26.2481 + switch (n) {
26.2482 + case HEADER_BLOCKED:
26.2483 + break;
26.2484 +
26.2485 + case -1:
26.2486 + pos = 0;
26.2487 + end = -1;
26.2488 + break;
26.2489 +
26.2490 + default:
26.2491 + pos = 0;
26.2492 + end = 0;
26.2493 + unread = n;
26.2494 + break;
26.2495 + }
26.2496 + }
26.2497 + // avoid unnecessary call to in.available() if possible
26.2498 + int unreadAvail = (unread > 0) ?
26.2499 + Math.min(in.available(), unread) : 0;
26.2500 + return (end >= 0) ? (end - pos) + unreadAvail : 0;
26.2501 + } else {
26.2502 + return in.available();
26.2503 + }
26.2504 + }
26.2505 +
26.2506 + public void close() throws IOException {
26.2507 + if (blkmode) {
26.2508 + pos = 0;
26.2509 + end = -1;
26.2510 + unread = 0;
26.2511 + }
26.2512 + in.close();
26.2513 + }
26.2514 +
26.2515 + /**
26.2516 + * Attempts to read len bytes into byte array b at offset off. Returns
26.2517 + * the number of bytes read, or -1 if the end of stream/block data has
26.2518 + * been reached. If copy is true, reads values into an intermediate
26.2519 + * buffer before copying them to b (to avoid exposing a reference to
26.2520 + * b).
26.2521 + */
26.2522 + int read(byte[] b, int off, int len, boolean copy) throws IOException {
26.2523 + if (len == 0) {
26.2524 + return 0;
26.2525 + } else if (blkmode) {
26.2526 + if (pos == end) {
26.2527 + refill();
26.2528 + }
26.2529 + if (end < 0) {
26.2530 + return -1;
26.2531 + }
26.2532 + int nread = Math.min(len, end - pos);
26.2533 + System.arraycopy(buf, pos, b, off, nread);
26.2534 + pos += nread;
26.2535 + return nread;
26.2536 + } else if (copy) {
26.2537 + int nread = in.read(buf, 0, Math.min(len, MAX_BLOCK_SIZE));
26.2538 + if (nread > 0) {
26.2539 + System.arraycopy(buf, 0, b, off, nread);
26.2540 + }
26.2541 + return nread;
26.2542 + } else {
26.2543 + return in.read(b, off, len);
26.2544 + }
26.2545 + }
26.2546 +
26.2547 + /* ----------------- primitive data input methods ------------------ */
26.2548 + /*
26.2549 + * The following methods are equivalent to their counterparts in
26.2550 + * DataInputStream, except that they interpret data block boundaries
26.2551 + * and read the requested data from within data blocks when in block
26.2552 + * data mode.
26.2553 + */
26.2554 +
26.2555 + public void readFully(byte[] b) throws IOException {
26.2556 + readFully(b, 0, b.length, false);
26.2557 + }
26.2558 +
26.2559 + public void readFully(byte[] b, int off, int len) throws IOException {
26.2560 + readFully(b, off, len, false);
26.2561 + }
26.2562 +
26.2563 + public void readFully(byte[] b, int off, int len, boolean copy)
26.2564 + throws IOException
26.2565 + {
26.2566 + while (len > 0) {
26.2567 + int n = read(b, off, len, copy);
26.2568 + if (n < 0) {
26.2569 + throw new EOFException();
26.2570 + }
26.2571 + off += n;
26.2572 + len -= n;
26.2573 + }
26.2574 + }
26.2575 +
26.2576 + public int skipBytes(int n) throws IOException {
26.2577 + return din.skipBytes(n);
26.2578 + }
26.2579 +
26.2580 + public boolean readBoolean() throws IOException {
26.2581 + int v = read();
26.2582 + if (v < 0) {
26.2583 + throw new EOFException();
26.2584 + }
26.2585 + return (v != 0);
26.2586 + }
26.2587 +
26.2588 + public byte readByte() throws IOException {
26.2589 + int v = read();
26.2590 + if (v < 0) {
26.2591 + throw new EOFException();
26.2592 + }
26.2593 + return (byte) v;
26.2594 + }
26.2595 +
26.2596 + public int readUnsignedByte() throws IOException {
26.2597 + int v = read();
26.2598 + if (v < 0) {
26.2599 + throw new EOFException();
26.2600 + }
26.2601 + return v;
26.2602 + }
26.2603 +
26.2604 + public char readChar() throws IOException {
26.2605 + if (!blkmode) {
26.2606 + pos = 0;
26.2607 + in.readFully(buf, 0, 2);
26.2608 + } else if (end - pos < 2) {
26.2609 + return din.readChar();
26.2610 + }
26.2611 + char v = Bits.getChar(buf, pos);
26.2612 + pos += 2;
26.2613 + return v;
26.2614 + }
26.2615 +
26.2616 + public short readShort() throws IOException {
26.2617 + if (!blkmode) {
26.2618 + pos = 0;
26.2619 + in.readFully(buf, 0, 2);
26.2620 + } else if (end - pos < 2) {
26.2621 + return din.readShort();
26.2622 + }
26.2623 + short v = Bits.getShort(buf, pos);
26.2624 + pos += 2;
26.2625 + return v;
26.2626 + }
26.2627 +
26.2628 + public int readUnsignedShort() throws IOException {
26.2629 + if (!blkmode) {
26.2630 + pos = 0;
26.2631 + in.readFully(buf, 0, 2);
26.2632 + } else if (end - pos < 2) {
26.2633 + return din.readUnsignedShort();
26.2634 + }
26.2635 + int v = Bits.getShort(buf, pos) & 0xFFFF;
26.2636 + pos += 2;
26.2637 + return v;
26.2638 + }
26.2639 +
26.2640 + public int readInt() throws IOException {
26.2641 + if (!blkmode) {
26.2642 + pos = 0;
26.2643 + in.readFully(buf, 0, 4);
26.2644 + } else if (end - pos < 4) {
26.2645 + return din.readInt();
26.2646 + }
26.2647 + int v = Bits.getInt(buf, pos);
26.2648 + pos += 4;
26.2649 + return v;
26.2650 + }
26.2651 +
26.2652 + public float readFloat() throws IOException {
26.2653 + if (!blkmode) {
26.2654 + pos = 0;
26.2655 + in.readFully(buf, 0, 4);
26.2656 + } else if (end - pos < 4) {
26.2657 + return din.readFloat();
26.2658 + }
26.2659 + float v = Bits.getFloat(buf, pos);
26.2660 + pos += 4;
26.2661 + return v;
26.2662 + }
26.2663 +
26.2664 + public long readLong() throws IOException {
26.2665 + if (!blkmode) {
26.2666 + pos = 0;
26.2667 + in.readFully(buf, 0, 8);
26.2668 + } else if (end - pos < 8) {
26.2669 + return din.readLong();
26.2670 + }
26.2671 + long v = Bits.getLong(buf, pos);
26.2672 + pos += 8;
26.2673 + return v;
26.2674 + }
26.2675 +
26.2676 + public double readDouble() throws IOException {
26.2677 + if (!blkmode) {
26.2678 + pos = 0;
26.2679 + in.readFully(buf, 0, 8);
26.2680 + } else if (end - pos < 8) {
26.2681 + return din.readDouble();
26.2682 + }
26.2683 + double v = Bits.getDouble(buf, pos);
26.2684 + pos += 8;
26.2685 + return v;
26.2686 + }
26.2687 +
26.2688 + public String readUTF() throws IOException {
26.2689 + return readUTFBody(readUnsignedShort());
26.2690 + }
26.2691 +
26.2692 + public String readLine() throws IOException {
26.2693 + return din.readLine(); // deprecated, not worth optimizing
26.2694 + }
26.2695 +
26.2696 + /* -------------- primitive data array input methods --------------- */
26.2697 + /*
26.2698 + * The following methods read in spans of primitive data values.
26.2699 + * Though equivalent to calling the corresponding primitive read
26.2700 + * methods repeatedly, these methods are optimized for reading groups
26.2701 + * of primitive data values more efficiently.
26.2702 + */
26.2703 +
26.2704 + void readBooleans(boolean[] v, int off, int len) throws IOException {
26.2705 + int stop, endoff = off + len;
26.2706 + while (off < endoff) {
26.2707 + if (!blkmode) {
26.2708 + int span = Math.min(endoff - off, MAX_BLOCK_SIZE);
26.2709 + in.readFully(buf, 0, span);
26.2710 + stop = off + span;
26.2711 + pos = 0;
26.2712 + } else if (end - pos < 1) {
26.2713 + v[off++] = din.readBoolean();
26.2714 + continue;
26.2715 + } else {
26.2716 + stop = Math.min(endoff, off + end - pos);
26.2717 + }
26.2718 +
26.2719 + while (off < stop) {
26.2720 + v[off++] = Bits.getBoolean(buf, pos++);
26.2721 + }
26.2722 + }
26.2723 + }
26.2724 +
26.2725 + void readChars(char[] v, int off, int len) throws IOException {
26.2726 + int stop, endoff = off + len;
26.2727 + while (off < endoff) {
26.2728 + if (!blkmode) {
26.2729 + int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
26.2730 + in.readFully(buf, 0, span << 1);
26.2731 + stop = off + span;
26.2732 + pos = 0;
26.2733 + } else if (end - pos < 2) {
26.2734 + v[off++] = din.readChar();
26.2735 + continue;
26.2736 + } else {
26.2737 + stop = Math.min(endoff, off + ((end - pos) >> 1));
26.2738 + }
26.2739 +
26.2740 + while (off < stop) {
26.2741 + v[off++] = Bits.getChar(buf, pos);
26.2742 + pos += 2;
26.2743 + }
26.2744 + }
26.2745 + }
26.2746 +
26.2747 + void readShorts(short[] v, int off, int len) throws IOException {
26.2748 + int stop, endoff = off + len;
26.2749 + while (off < endoff) {
26.2750 + if (!blkmode) {
26.2751 + int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
26.2752 + in.readFully(buf, 0, span << 1);
26.2753 + stop = off + span;
26.2754 + pos = 0;
26.2755 + } else if (end - pos < 2) {
26.2756 + v[off++] = din.readShort();
26.2757 + continue;
26.2758 + } else {
26.2759 + stop = Math.min(endoff, off + ((end - pos) >> 1));
26.2760 + }
26.2761 +
26.2762 + while (off < stop) {
26.2763 + v[off++] = Bits.getShort(buf, pos);
26.2764 + pos += 2;
26.2765 + }
26.2766 + }
26.2767 + }
26.2768 +
26.2769 + void readInts(int[] v, int off, int len) throws IOException {
26.2770 + int stop, endoff = off + len;
26.2771 + while (off < endoff) {
26.2772 + if (!blkmode) {
26.2773 + int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
26.2774 + in.readFully(buf, 0, span << 2);
26.2775 + stop = off + span;
26.2776 + pos = 0;
26.2777 + } else if (end - pos < 4) {
26.2778 + v[off++] = din.readInt();
26.2779 + continue;
26.2780 + } else {
26.2781 + stop = Math.min(endoff, off + ((end - pos) >> 2));
26.2782 + }
26.2783 +
26.2784 + while (off < stop) {
26.2785 + v[off++] = Bits.getInt(buf, pos);
26.2786 + pos += 4;
26.2787 + }
26.2788 + }
26.2789 + }
26.2790 +
26.2791 + void readFloats(float[] v, int off, int len) throws IOException {
26.2792 + int span, endoff = off + len;
26.2793 + while (off < endoff) {
26.2794 + if (!blkmode) {
26.2795 + span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
26.2796 + in.readFully(buf, 0, span << 2);
26.2797 + pos = 0;
26.2798 + } else if (end - pos < 4) {
26.2799 + v[off++] = din.readFloat();
26.2800 + continue;
26.2801 + } else {
26.2802 + span = Math.min(endoff - off, ((end - pos) >> 2));
26.2803 + }
26.2804 +
26.2805 + bytesToFloats(buf, pos, v, off, span);
26.2806 + off += span;
26.2807 + pos += span << 2;
26.2808 + }
26.2809 + }
26.2810 +
26.2811 + void readLongs(long[] v, int off, int len) throws IOException {
26.2812 + int stop, endoff = off + len;
26.2813 + while (off < endoff) {
26.2814 + if (!blkmode) {
26.2815 + int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
26.2816 + in.readFully(buf, 0, span << 3);
26.2817 + stop = off + span;
26.2818 + pos = 0;
26.2819 + } else if (end - pos < 8) {
26.2820 + v[off++] = din.readLong();
26.2821 + continue;
26.2822 + } else {
26.2823 + stop = Math.min(endoff, off + ((end - pos) >> 3));
26.2824 + }
26.2825 +
26.2826 + while (off < stop) {
26.2827 + v[off++] = Bits.getLong(buf, pos);
26.2828 + pos += 8;
26.2829 + }
26.2830 + }
26.2831 + }
26.2832 +
26.2833 + void readDoubles(double[] v, int off, int len) throws IOException {
26.2834 + int span, endoff = off + len;
26.2835 + while (off < endoff) {
26.2836 + if (!blkmode) {
26.2837 + span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
26.2838 + in.readFully(buf, 0, span << 3);
26.2839 + pos = 0;
26.2840 + } else if (end - pos < 8) {
26.2841 + v[off++] = din.readDouble();
26.2842 + continue;
26.2843 + } else {
26.2844 + span = Math.min(endoff - off, ((end - pos) >> 3));
26.2845 + }
26.2846 +
26.2847 + bytesToDoubles(buf, pos, v, off, span);
26.2848 + off += span;
26.2849 + pos += span << 3;
26.2850 + }
26.2851 + }
26.2852 +
26.2853 + /**
26.2854 + * Reads in string written in "long" UTF format. "Long" UTF format is
26.2855 + * identical to standard UTF, except that it uses an 8 byte header
26.2856 + * (instead of the standard 2 bytes) to convey the UTF encoding length.
26.2857 + */
26.2858 + String readLongUTF() throws IOException {
26.2859 + return readUTFBody(readLong());
26.2860 + }
26.2861 +
26.2862 + /**
26.2863 + * Reads in the "body" (i.e., the UTF representation minus the 2-byte
26.2864 + * or 8-byte length header) of a UTF encoding, which occupies the next
26.2865 + * utflen bytes.
26.2866 + */
26.2867 + private String readUTFBody(long utflen) throws IOException {
26.2868 + StringBuilder sbuf = new StringBuilder();
26.2869 + if (!blkmode) {
26.2870 + end = pos = 0;
26.2871 + }
26.2872 +
26.2873 + while (utflen > 0) {
26.2874 + int avail = end - pos;
26.2875 + if (avail >= 3 || (long) avail == utflen) {
26.2876 + utflen -= readUTFSpan(sbuf, utflen);
26.2877 + } else {
26.2878 + if (blkmode) {
26.2879 + // near block boundary, read one byte at a time
26.2880 + utflen -= readUTFChar(sbuf, utflen);
26.2881 + } else {
26.2882 + // shift and refill buffer manually
26.2883 + if (avail > 0) {
26.2884 + System.arraycopy(buf, pos, buf, 0, avail);
26.2885 + }
26.2886 + pos = 0;
26.2887 + end = (int) Math.min(MAX_BLOCK_SIZE, utflen);
26.2888 + in.readFully(buf, avail, end - avail);
26.2889 + }
26.2890 + }
26.2891 + }
26.2892 +
26.2893 + return sbuf.toString();
26.2894 + }
26.2895 +
26.2896 + /**
26.2897 + * Reads span of UTF-encoded characters out of internal buffer
26.2898 + * (starting at offset pos and ending at or before offset end),
26.2899 + * consuming no more than utflen bytes. Appends read characters to
26.2900 + * sbuf. Returns the number of bytes consumed.
26.2901 + */
26.2902 + private long readUTFSpan(StringBuilder sbuf, long utflen)
26.2903 + throws IOException
26.2904 + {
26.2905 + int cpos = 0;
26.2906 + int start = pos;
26.2907 + int avail = Math.min(end - pos, CHAR_BUF_SIZE);
26.2908 + // stop short of last char unless all of utf bytes in buffer
26.2909 + int stop = pos + ((utflen > avail) ? avail - 2 : (int) utflen);
26.2910 + boolean outOfBounds = false;
26.2911 +
26.2912 + try {
26.2913 + while (pos < stop) {
26.2914 + int b1, b2, b3;
26.2915 + b1 = buf[pos++] & 0xFF;
26.2916 + switch (b1 >> 4) {
26.2917 + case 0:
26.2918 + case 1:
26.2919 + case 2:
26.2920 + case 3:
26.2921 + case 4:
26.2922 + case 5:
26.2923 + case 6:
26.2924 + case 7: // 1 byte format: 0xxxxxxx
26.2925 + cbuf[cpos++] = (char) b1;
26.2926 + break;
26.2927 +
26.2928 + case 12:
26.2929 + case 13: // 2 byte format: 110xxxxx 10xxxxxx
26.2930 + b2 = buf[pos++];
26.2931 + if ((b2 & 0xC0) != 0x80) {
26.2932 + throw new UTFDataFormatException();
26.2933 + }
26.2934 + cbuf[cpos++] = (char) (((b1 & 0x1F) << 6) |
26.2935 + ((b2 & 0x3F) << 0));
26.2936 + break;
26.2937 +
26.2938 + case 14: // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
26.2939 + b3 = buf[pos + 1];
26.2940 + b2 = buf[pos + 0];
26.2941 + pos += 2;
26.2942 + if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
26.2943 + throw new UTFDataFormatException();
26.2944 + }
26.2945 + cbuf[cpos++] = (char) (((b1 & 0x0F) << 12) |
26.2946 + ((b2 & 0x3F) << 6) |
26.2947 + ((b3 & 0x3F) << 0));
26.2948 + break;
26.2949 +
26.2950 + default: // 10xx xxxx, 1111 xxxx
26.2951 + throw new UTFDataFormatException();
26.2952 + }
26.2953 + }
26.2954 + } catch (ArrayIndexOutOfBoundsException ex) {
26.2955 + outOfBounds = true;
26.2956 + } finally {
26.2957 + if (outOfBounds || (pos - start) > utflen) {
26.2958 + /*
26.2959 + * Fix for 4450867: if a malformed utf char causes the
26.2960 + * conversion loop to scan past the expected end of the utf
26.2961 + * string, only consume the expected number of utf bytes.
26.2962 + */
26.2963 + pos = start + (int) utflen;
26.2964 + throw new UTFDataFormatException();
26.2965 + }
26.2966 + }
26.2967 +
26.2968 + sbuf.append(cbuf, 0, cpos);
26.2969 + return pos - start;
26.2970 + }
26.2971 +
26.2972 + /**
26.2973 + * Reads in single UTF-encoded character one byte at a time, appends
26.2974 + * the character to sbuf, and returns the number of bytes consumed.
26.2975 + * This method is used when reading in UTF strings written in block
26.2976 + * data mode to handle UTF-encoded characters which (potentially)
26.2977 + * straddle block-data boundaries.
26.2978 + */
26.2979 + private int readUTFChar(StringBuilder sbuf, long utflen)
26.2980 + throws IOException
26.2981 + {
26.2982 + int b1, b2, b3;
26.2983 + b1 = readByte() & 0xFF;
26.2984 + switch (b1 >> 4) {
26.2985 + case 0:
26.2986 + case 1:
26.2987 + case 2:
26.2988 + case 3:
26.2989 + case 4:
26.2990 + case 5:
26.2991 + case 6:
26.2992 + case 7: // 1 byte format: 0xxxxxxx
26.2993 + sbuf.append((char) b1);
26.2994 + return 1;
26.2995 +
26.2996 + case 12:
26.2997 + case 13: // 2 byte format: 110xxxxx 10xxxxxx
26.2998 + if (utflen < 2) {
26.2999 + throw new UTFDataFormatException();
26.3000 + }
26.3001 + b2 = readByte();
26.3002 + if ((b2 & 0xC0) != 0x80) {
26.3003 + throw new UTFDataFormatException();
26.3004 + }
26.3005 + sbuf.append((char) (((b1 & 0x1F) << 6) |
26.3006 + ((b2 & 0x3F) << 0)));
26.3007 + return 2;
26.3008 +
26.3009 + case 14: // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
26.3010 + if (utflen < 3) {
26.3011 + if (utflen == 2) {
26.3012 + readByte(); // consume remaining byte
26.3013 + }
26.3014 + throw new UTFDataFormatException();
26.3015 + }
26.3016 + b2 = readByte();
26.3017 + b3 = readByte();
26.3018 + if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
26.3019 + throw new UTFDataFormatException();
26.3020 + }
26.3021 + sbuf.append((char) (((b1 & 0x0F) << 12) |
26.3022 + ((b2 & 0x3F) << 6) |
26.3023 + ((b3 & 0x3F) << 0)));
26.3024 + return 3;
26.3025 +
26.3026 + default: // 10xx xxxx, 1111 xxxx
26.3027 + throw new UTFDataFormatException();
26.3028 + }
26.3029 + }
26.3030 + }
26.3031 +
26.3032 + /**
26.3033 + * Unsynchronized table which tracks wire handle to object mappings, as
26.3034 + * well as ClassNotFoundExceptions associated with deserialized objects.
26.3035 + * This class implements an exception-propagation algorithm for
26.3036 + * determining which objects should have ClassNotFoundExceptions associated
26.3037 + * with them, taking into account cycles and discontinuities (e.g., skipped
26.3038 + * fields) in the object graph.
26.3039 + *
26.3040 + * <p>General use of the table is as follows: during deserialization, a
26.3041 + * given object is first assigned a handle by calling the assign method.
26.3042 + * This method leaves the assigned handle in an "open" state, wherein
26.3043 + * dependencies on the exception status of other handles can be registered
26.3044 + * by calling the markDependency method, or an exception can be directly
26.3045 + * associated with the handle by calling markException. When a handle is
26.3046 + * tagged with an exception, the HandleTable assumes responsibility for
26.3047 + * propagating the exception to any other objects which depend
26.3048 + * (transitively) on the exception-tagged object.
26.3049 + *
26.3050 + * <p>Once all exception information/dependencies for the handle have been
26.3051 + * registered, the handle should be "closed" by calling the finish method
26.3052 + * on it. The act of finishing a handle allows the exception propagation
26.3053 + * algorithm to aggressively prune dependency links, lessening the
26.3054 + * performance/memory impact of exception tracking.
26.3055 + *
26.3056 + * <p>Note that the exception propagation algorithm used depends on handles
26.3057 + * being assigned/finished in LIFO order; however, for simplicity as well
26.3058 + * as memory conservation, it does not enforce this constraint.
26.3059 + */
26.3060 + // REMIND: add full description of exception propagation algorithm?
26.3061 + private static class HandleTable {
26.3062 +
26.3063 + /* status codes indicating whether object has associated exception */
26.3064 + private static final byte STATUS_OK = 1;
26.3065 + private static final byte STATUS_UNKNOWN = 2;
26.3066 + private static final byte STATUS_EXCEPTION = 3;
26.3067 +
26.3068 + /** array mapping handle -> object status */
26.3069 + byte[] status;
26.3070 + /** array mapping handle -> object/exception (depending on status) */
26.3071 + Object[] entries;
26.3072 + /** array mapping handle -> list of dependent handles (if any) */
26.3073 + HandleList[] deps;
26.3074 + /** lowest unresolved dependency */
26.3075 + int lowDep = -1;
26.3076 + /** number of handles in table */
26.3077 + int size = 0;
26.3078 +
26.3079 + /**
26.3080 + * Creates handle table with the given initial capacity.
26.3081 + */
26.3082 + HandleTable(int initialCapacity) {
26.3083 + status = new byte[initialCapacity];
26.3084 + entries = new Object[initialCapacity];
26.3085 + deps = new HandleList[initialCapacity];
26.3086 + }
26.3087 +
26.3088 + /**
26.3089 + * Assigns next available handle to given object, and returns assigned
26.3090 + * handle. Once object has been completely deserialized (and all
26.3091 + * dependencies on other objects identified), the handle should be
26.3092 + * "closed" by passing it to finish().
26.3093 + */
26.3094 + int assign(Object obj) {
26.3095 + if (size >= entries.length) {
26.3096 + grow();
26.3097 + }
26.3098 + status[size] = STATUS_UNKNOWN;
26.3099 + entries[size] = obj;
26.3100 + return size++;
26.3101 + }
26.3102 +
26.3103 + /**
26.3104 + * Registers a dependency (in exception status) of one handle on
26.3105 + * another. The dependent handle must be "open" (i.e., assigned, but
26.3106 + * not finished yet). No action is taken if either dependent or target
26.3107 + * handle is NULL_HANDLE.
26.3108 + */
26.3109 + void markDependency(int dependent, int target) {
26.3110 + if (dependent == NULL_HANDLE || target == NULL_HANDLE) {
26.3111 + return;
26.3112 + }
26.3113 + switch (status[dependent]) {
26.3114 +
26.3115 + case STATUS_UNKNOWN:
26.3116 + switch (status[target]) {
26.3117 + case STATUS_OK:
26.3118 + // ignore dependencies on objs with no exception
26.3119 + break;
26.3120 +
26.3121 + case STATUS_EXCEPTION:
26.3122 + // eagerly propagate exception
26.3123 + markException(dependent,
26.3124 + (ClassNotFoundException) entries[target]);
26.3125 + break;
26.3126 +
26.3127 + case STATUS_UNKNOWN:
26.3128 + // add to dependency list of target
26.3129 + if (deps[target] == null) {
26.3130 + deps[target] = new HandleList();
26.3131 + }
26.3132 + deps[target].add(dependent);
26.3133 +
26.3134 + // remember lowest unresolved target seen
26.3135 + if (lowDep < 0 || lowDep > target) {
26.3136 + lowDep = target;
26.3137 + }
26.3138 + break;
26.3139 +
26.3140 + default:
26.3141 + throw new InternalError();
26.3142 + }
26.3143 + break;
26.3144 +
26.3145 + case STATUS_EXCEPTION:
26.3146 + break;
26.3147 +
26.3148 + default:
26.3149 + throw new InternalError();
26.3150 + }
26.3151 + }
26.3152 +
26.3153 + /**
26.3154 + * Associates a ClassNotFoundException (if one not already associated)
26.3155 + * with the currently active handle and propagates it to other
26.3156 + * referencing objects as appropriate. The specified handle must be
26.3157 + * "open" (i.e., assigned, but not finished yet).
26.3158 + */
26.3159 + void markException(int handle, ClassNotFoundException ex) {
26.3160 + switch (status[handle]) {
26.3161 + case STATUS_UNKNOWN:
26.3162 + status[handle] = STATUS_EXCEPTION;
26.3163 + entries[handle] = ex;
26.3164 +
26.3165 + // propagate exception to dependents
26.3166 + HandleList dlist = deps[handle];
26.3167 + if (dlist != null) {
26.3168 + int ndeps = dlist.size();
26.3169 + for (int i = 0; i < ndeps; i++) {
26.3170 + markException(dlist.get(i), ex);
26.3171 + }
26.3172 + deps[handle] = null;
26.3173 + }
26.3174 + break;
26.3175 +
26.3176 + case STATUS_EXCEPTION:
26.3177 + break;
26.3178 +
26.3179 + default:
26.3180 + throw new InternalError();
26.3181 + }
26.3182 + }
26.3183 +
26.3184 + /**
26.3185 + * Marks given handle as finished, meaning that no new dependencies
26.3186 + * will be marked for handle. Calls to the assign and finish methods
26.3187 + * must occur in LIFO order.
26.3188 + */
26.3189 + void finish(int handle) {
26.3190 + int end;
26.3191 + if (lowDep < 0) {
26.3192 + // no pending unknowns, only resolve current handle
26.3193 + end = handle + 1;
26.3194 + } else if (lowDep >= handle) {
26.3195 + // pending unknowns now clearable, resolve all upward handles
26.3196 + end = size;
26.3197 + lowDep = -1;
26.3198 + } else {
26.3199 + // unresolved backrefs present, can't resolve anything yet
26.3200 + return;
26.3201 + }
26.3202 +
26.3203 + // change STATUS_UNKNOWN -> STATUS_OK in selected span of handles
26.3204 + for (int i = handle; i < end; i++) {
26.3205 + switch (status[i]) {
26.3206 + case STATUS_UNKNOWN:
26.3207 + status[i] = STATUS_OK;
26.3208 + deps[i] = null;
26.3209 + break;
26.3210 +
26.3211 + case STATUS_OK:
26.3212 + case STATUS_EXCEPTION:
26.3213 + break;
26.3214 +
26.3215 + default:
26.3216 + throw new InternalError();
26.3217 + }
26.3218 + }
26.3219 + }
26.3220 +
26.3221 + /**
26.3222 + * Assigns a new object to the given handle. The object previously
26.3223 + * associated with the handle is forgotten. This method has no effect
26.3224 + * if the given handle already has an exception associated with it.
26.3225 + * This method may be called at any time after the handle is assigned.
26.3226 + */
26.3227 + void setObject(int handle, Object obj) {
26.3228 + switch (status[handle]) {
26.3229 + case STATUS_UNKNOWN:
26.3230 + case STATUS_OK:
26.3231 + entries[handle] = obj;
26.3232 + break;
26.3233 +
26.3234 + case STATUS_EXCEPTION:
26.3235 + break;
26.3236 +
26.3237 + default:
26.3238 + throw new InternalError();
26.3239 + }
26.3240 + }
26.3241 +
26.3242 + /**
26.3243 + * Looks up and returns object associated with the given handle.
26.3244 + * Returns null if the given handle is NULL_HANDLE, or if it has an
26.3245 + * associated ClassNotFoundException.
26.3246 + */
26.3247 + Object lookupObject(int handle) {
26.3248 + return (handle != NULL_HANDLE &&
26.3249 + status[handle] != STATUS_EXCEPTION) ?
26.3250 + entries[handle] : null;
26.3251 + }
26.3252 +
26.3253 + /**
26.3254 + * Looks up and returns ClassNotFoundException associated with the
26.3255 + * given handle. Returns null if the given handle is NULL_HANDLE, or
26.3256 + * if there is no ClassNotFoundException associated with the handle.
26.3257 + */
26.3258 + ClassNotFoundException lookupException(int handle) {
26.3259 + return (handle != NULL_HANDLE &&
26.3260 + status[handle] == STATUS_EXCEPTION) ?
26.3261 + (ClassNotFoundException) entries[handle] : null;
26.3262 + }
26.3263 +
26.3264 + /**
26.3265 + * Resets table to its initial state.
26.3266 + */
26.3267 + void clear() {
26.3268 + Arrays.fill(status, 0, size, (byte) 0);
26.3269 + Arrays.fill(entries, 0, size, null);
26.3270 + Arrays.fill(deps, 0, size, null);
26.3271 + lowDep = -1;
26.3272 + size = 0;
26.3273 + }
26.3274 +
26.3275 + /**
26.3276 + * Returns number of handles registered in table.
26.3277 + */
26.3278 + int size() {
26.3279 + return size;
26.3280 + }
26.3281 +
26.3282 + /**
26.3283 + * Expands capacity of internal arrays.
26.3284 + */
26.3285 + private void grow() {
26.3286 + int newCapacity = (entries.length << 1) + 1;
26.3287 +
26.3288 + byte[] newStatus = new byte[newCapacity];
26.3289 + Object[] newEntries = new Object[newCapacity];
26.3290 + HandleList[] newDeps = new HandleList[newCapacity];
26.3291 +
26.3292 + System.arraycopy(status, 0, newStatus, 0, size);
26.3293 + System.arraycopy(entries, 0, newEntries, 0, size);
26.3294 + System.arraycopy(deps, 0, newDeps, 0, size);
26.3295 +
26.3296 + status = newStatus;
26.3297 + entries = newEntries;
26.3298 + deps = newDeps;
26.3299 + }
26.3300 +
26.3301 + /**
26.3302 + * Simple growable list of (integer) handles.
26.3303 + */
26.3304 + private static class HandleList {
26.3305 + private int[] list = new int[4];
26.3306 + private int size = 0;
26.3307 +
26.3308 + public HandleList() {
26.3309 + }
26.3310 +
26.3311 + public void add(int handle) {
26.3312 + if (size >= list.length) {
26.3313 + int[] newList = new int[list.length << 1];
26.3314 + System.arraycopy(list, 0, newList, 0, list.length);
26.3315 + list = newList;
26.3316 + }
26.3317 + list[size++] = handle;
26.3318 + }
26.3319 +
26.3320 + public int get(int index) {
26.3321 + if (index >= size) {
26.3322 + throw new ArrayIndexOutOfBoundsException();
26.3323 + }
26.3324 + return list[index];
26.3325 + }
26.3326 +
26.3327 + public int size() {
26.3328 + return size;
26.3329 + }
26.3330 + }
26.3331 + }
26.3332 +
26.3333 + /**
26.3334 + * Method for cloning arrays in case of using unsharing reading
26.3335 + */
26.3336 + private static Object cloneArray(Object array) {
26.3337 + if (array instanceof Object[]) {
26.3338 + return ((Object[]) array).clone();
26.3339 + } else if (array instanceof boolean[]) {
26.3340 + return ((boolean[]) array).clone();
26.3341 + } else if (array instanceof byte[]) {
26.3342 + return ((byte[]) array).clone();
26.3343 + } else if (array instanceof char[]) {
26.3344 + return ((char[]) array).clone();
26.3345 + } else if (array instanceof double[]) {
26.3346 + return ((double[]) array).clone();
26.3347 + } else if (array instanceof float[]) {
26.3348 + return ((float[]) array).clone();
26.3349 + } else if (array instanceof int[]) {
26.3350 + return ((int[]) array).clone();
26.3351 + } else if (array instanceof long[]) {
26.3352 + return ((long[]) array).clone();
26.3353 + } else if (array instanceof short[]) {
26.3354 + return ((short[]) array).clone();
26.3355 + } else {
26.3356 + throw new AssertionError();
26.3357 + }
26.3358 + }
26.3359 +
26.3360 +}
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
27.2 +++ b/emul/compact/src/main/java/java/io/ObjectInputValidation.java Tue Feb 05 17:04:22 2013 +0100
27.3 @@ -0,0 +1,45 @@
27.4 +/*
27.5 + * Copyright (c) 1996, 1999, 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 + * Callback interface to allow validation of objects within a graph.
27.33 + * Allows an object to be called when a complete graph of objects has
27.34 + * been deserialized.
27.35 + *
27.36 + * @author unascribed
27.37 + * @see ObjectInputStream
27.38 + * @see ObjectInputStream#registerValidation(java.io.ObjectInputValidation, int)
27.39 + * @since JDK1.1
27.40 + */
27.41 +public interface ObjectInputValidation {
27.42 + /**
27.43 + * Validates the object.
27.44 + *
27.45 + * @exception InvalidObjectException If the object cannot validate itself.
27.46 + */
27.47 + public void validateObject() throws InvalidObjectException;
27.48 +}
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
28.2 +++ b/emul/compact/src/main/java/java/io/ObjectOutput.java Tue Feb 05 17:04:22 2013 +0100
28.3 @@ -0,0 +1,90 @@
28.4 +/*
28.5 + * Copyright (c) 1996, 2010, 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 + * ObjectOutput extends the DataOutput interface to include writing of objects.
28.33 + * DataOutput includes methods for output of primitive types, ObjectOutput
28.34 + * extends that interface to include objects, arrays, and Strings.
28.35 + *
28.36 + * @author unascribed
28.37 + * @see java.io.InputStream
28.38 + * @see java.io.ObjectOutputStream
28.39 + * @see java.io.ObjectInputStream
28.40 + * @since JDK1.1
28.41 + */
28.42 +public interface ObjectOutput extends DataOutput, AutoCloseable {
28.43 + /**
28.44 + * Write an object to the underlying storage or stream. The
28.45 + * class that implements this interface defines how the object is
28.46 + * written.
28.47 + *
28.48 + * @param obj the object to be written
28.49 + * @exception IOException Any of the usual Input/Output related exceptions.
28.50 + */
28.51 + public void writeObject(Object obj)
28.52 + throws IOException;
28.53 +
28.54 + /**
28.55 + * Writes a byte. This method will block until the byte is actually
28.56 + * written.
28.57 + * @param b the byte
28.58 + * @exception IOException If an I/O error has occurred.
28.59 + */
28.60 + public void write(int b) throws IOException;
28.61 +
28.62 + /**
28.63 + * Writes an array of bytes. This method will block until the bytes
28.64 + * are actually written.
28.65 + * @param b the data to be written
28.66 + * @exception IOException If an I/O error has occurred.
28.67 + */
28.68 + public void write(byte b[]) throws IOException;
28.69 +
28.70 + /**
28.71 + * Writes a sub array of bytes.
28.72 + * @param b the data to be written
28.73 + * @param off the start offset in the data
28.74 + * @param len the number of bytes that are written
28.75 + * @exception IOException If an I/O error has occurred.
28.76 + */
28.77 + public void write(byte b[], int off, int len) throws IOException;
28.78 +
28.79 + /**
28.80 + * Flushes the stream. This will write any buffered
28.81 + * output bytes.
28.82 + * @exception IOException If an I/O error has occurred.
28.83 + */
28.84 + public void flush() throws IOException;
28.85 +
28.86 + /**
28.87 + * Closes the stream. This method must be called
28.88 + * to release any resources associated with the
28.89 + * stream.
28.90 + * @exception IOException If an I/O error has occurred.
28.91 + */
28.92 + public void close() throws IOException;
28.93 +}
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
29.2 +++ b/emul/compact/src/main/java/java/io/ObjectOutputStream.java Tue Feb 05 17:04:22 2013 +0100
29.3 @@ -0,0 +1,2369 @@
29.4 +/*
29.5 + * Copyright (c) 1996, 2010, 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.util.ArrayList;
29.32 +import java.util.Arrays;
29.33 +import java.util.List;
29.34 +import org.apidesign.bck2brwsr.emul.lang.System;
29.35 +
29.36 +/**
29.37 + * An ObjectOutputStream writes primitive data types and graphs of Java objects
29.38 + * to an OutputStream. The objects can be read (reconstituted) using an
29.39 + * ObjectInputStream. Persistent storage of objects can be accomplished by
29.40 + * using a file for the stream. If the stream is a network socket stream, the
29.41 + * objects can be reconstituted on another host or in another process.
29.42 + *
29.43 + * <p>Only objects that support the java.io.Serializable interface can be
29.44 + * written to streams. The class of each serializable object is encoded
29.45 + * including the class name and signature of the class, the values of the
29.46 + * object's fields and arrays, and the closure of any other objects referenced
29.47 + * from the initial objects.
29.48 + *
29.49 + * <p>The method writeObject is used to write an object to the stream. Any
29.50 + * object, including Strings and arrays, is written with writeObject. Multiple
29.51 + * objects or primitives can be written to the stream. The objects must be
29.52 + * read back from the corresponding ObjectInputstream with the same types and
29.53 + * in the same order as they were written.
29.54 + *
29.55 + * <p>Primitive data types can also be written to the stream using the
29.56 + * appropriate methods from DataOutput. Strings can also be written using the
29.57 + * writeUTF method.
29.58 + *
29.59 + * <p>The default serialization mechanism for an object writes the class of the
29.60 + * object, the class signature, and the values of all non-transient and
29.61 + * non-static fields. References to other objects (except in transient or
29.62 + * static fields) cause those objects to be written also. Multiple references
29.63 + * to a single object are encoded using a reference sharing mechanism so that
29.64 + * graphs of objects can be restored to the same shape as when the original was
29.65 + * written.
29.66 + *
29.67 + * <p>For example to write an object that can be read by the example in
29.68 + * ObjectInputStream:
29.69 + * <br>
29.70 + * <pre>
29.71 + * FileOutputStream fos = new FileOutputStream("t.tmp");
29.72 + * ObjectOutputStream oos = new ObjectOutputStream(fos);
29.73 + *
29.74 + * oos.writeInt(12345);
29.75 + * oos.writeObject("Today");
29.76 + * oos.writeObject(new Date());
29.77 + *
29.78 + * oos.close();
29.79 + * </pre>
29.80 + *
29.81 + * <p>Classes that require special handling during the serialization and
29.82 + * deserialization process must implement special methods with these exact
29.83 + * signatures:
29.84 + * <br>
29.85 + * <pre>
29.86 + * private void readObject(java.io.ObjectInputStream stream)
29.87 + * throws IOException, ClassNotFoundException;
29.88 + * private void writeObject(java.io.ObjectOutputStream stream)
29.89 + * throws IOException
29.90 + * private void readObjectNoData()
29.91 + * throws ObjectStreamException;
29.92 + * </pre>
29.93 + *
29.94 + * <p>The writeObject method is responsible for writing the state of the object
29.95 + * for its particular class so that the corresponding readObject method can
29.96 + * restore it. The method does not need to concern itself with the state
29.97 + * belonging to the object's superclasses or subclasses. State is saved by
29.98 + * writing the individual fields to the ObjectOutputStream using the
29.99 + * writeObject method or by using the methods for primitive data types
29.100 + * supported by DataOutput.
29.101 + *
29.102 + * <p>Serialization does not write out the fields of any object that does not
29.103 + * implement the java.io.Serializable interface. Subclasses of Objects that
29.104 + * are not serializable can be serializable. In this case the non-serializable
29.105 + * class must have a no-arg constructor to allow its fields to be initialized.
29.106 + * In this case it is the responsibility of the subclass to save and restore
29.107 + * the state of the non-serializable class. It is frequently the case that the
29.108 + * fields of that class are accessible (public, package, or protected) or that
29.109 + * there are get and set methods that can be used to restore the state.
29.110 + *
29.111 + * <p>Serialization of an object can be prevented by implementing writeObject
29.112 + * and readObject methods that throw the NotSerializableException. The
29.113 + * exception will be caught by the ObjectOutputStream and abort the
29.114 + * serialization process.
29.115 + *
29.116 + * <p>Implementing the Externalizable interface allows the object to assume
29.117 + * complete control over the contents and format of the object's serialized
29.118 + * form. The methods of the Externalizable interface, writeExternal and
29.119 + * readExternal, are called to save and restore the objects state. When
29.120 + * implemented by a class they can write and read their own state using all of
29.121 + * the methods of ObjectOutput and ObjectInput. It is the responsibility of
29.122 + * the objects to handle any versioning that occurs.
29.123 + *
29.124 + * <p>Enum constants are serialized differently than ordinary serializable or
29.125 + * externalizable objects. The serialized form of an enum constant consists
29.126 + * solely of its name; field values of the constant are not transmitted. To
29.127 + * serialize an enum constant, ObjectOutputStream writes the string returned by
29.128 + * the constant's name method. Like other serializable or externalizable
29.129 + * objects, enum constants can function as the targets of back references
29.130 + * appearing subsequently in the serialization stream. The process by which
29.131 + * enum constants are serialized cannot be customized; any class-specific
29.132 + * writeObject and writeReplace methods defined by enum types are ignored
29.133 + * during serialization. Similarly, any serialPersistentFields or
29.134 + * serialVersionUID field declarations are also ignored--all enum types have a
29.135 + * fixed serialVersionUID of 0L.
29.136 + *
29.137 + * <p>Primitive data, excluding serializable fields and externalizable data, is
29.138 + * written to the ObjectOutputStream in block-data records. A block data record
29.139 + * is composed of a header and data. The block data header consists of a marker
29.140 + * and the number of bytes to follow the header. Consecutive primitive data
29.141 + * writes are merged into one block-data record. The blocking factor used for
29.142 + * a block-data record will be 1024 bytes. Each block-data record will be
29.143 + * filled up to 1024 bytes, or be written whenever there is a termination of
29.144 + * block-data mode. Calls to the ObjectOutputStream methods writeObject,
29.145 + * defaultWriteObject and writeFields initially terminate any existing
29.146 + * block-data record.
29.147 + *
29.148 + * @author Mike Warres
29.149 + * @author Roger Riggs
29.150 + * @see java.io.DataOutput
29.151 + * @see java.io.ObjectInputStream
29.152 + * @see java.io.Serializable
29.153 + * @see java.io.Externalizable
29.154 + * @see <a href="../../../platform/serialization/spec/output.html">Object Serialization Specification, Section 2, Object Output Classes</a>
29.155 + * @since JDK1.1
29.156 + */
29.157 +public class ObjectOutputStream
29.158 + extends OutputStream implements ObjectOutput, ObjectStreamConstants
29.159 +{
29.160 + /** filter stream for handling block data conversion */
29.161 + private final BlockDataOutputStream bout;
29.162 + /** obj -> wire handle map */
29.163 + private final HandleTable handles;
29.164 + /** obj -> replacement obj map */
29.165 + private final ReplaceTable subs;
29.166 + /** stream protocol version */
29.167 + private int protocol = PROTOCOL_VERSION_2;
29.168 + /** recursion depth */
29.169 + private int depth;
29.170 +
29.171 + /** buffer for writing primitive field values */
29.172 + private byte[] primVals;
29.173 +
29.174 + /** if true, invoke writeObjectOverride() instead of writeObject() */
29.175 + private final boolean enableOverride;
29.176 + /** if true, invoke replaceObject() */
29.177 + private boolean enableReplace;
29.178 +
29.179 + // values below valid only during upcalls to writeObject()/writeExternal()
29.180 + /**
29.181 + * Context during upcalls to class-defined writeObject methods; holds
29.182 + * object currently being serialized and descriptor for current class.
29.183 + * Null when not during writeObject upcall.
29.184 + */
29.185 + private Object curContext;
29.186 + /** current PutField object */
29.187 + private PutFieldImpl curPut;
29.188 +
29.189 + /** custom storage for debug trace info */
29.190 + private final DebugTraceInfoStack debugInfoStack;
29.191 +
29.192 + /**
29.193 + * value of "sun.io.serialization.extendedDebugInfo" property,
29.194 + * as true or false for extended information about exception's place
29.195 + */
29.196 + private static final boolean extendedDebugInfo = false;
29.197 +
29.198 + /**
29.199 + * Creates an ObjectOutputStream that writes to the specified OutputStream.
29.200 + * This constructor writes the serialization stream header to the
29.201 + * underlying stream; callers may wish to flush the stream immediately to
29.202 + * ensure that constructors for receiving ObjectInputStreams will not block
29.203 + * when reading the header.
29.204 + *
29.205 + * <p>If a security manager is installed, this constructor will check for
29.206 + * the "enableSubclassImplementation" SerializablePermission when invoked
29.207 + * directly or indirectly by the constructor of a subclass which overrides
29.208 + * the ObjectOutputStream.putFields or ObjectOutputStream.writeUnshared
29.209 + * methods.
29.210 + *
29.211 + * @param out output stream to write to
29.212 + * @throws IOException if an I/O error occurs while writing stream header
29.213 + * @throws SecurityException if untrusted subclass illegally overrides
29.214 + * security-sensitive methods
29.215 + * @throws NullPointerException if <code>out</code> is <code>null</code>
29.216 + * @since 1.4
29.217 + * @see ObjectOutputStream#ObjectOutputStream()
29.218 + * @see ObjectOutputStream#putFields()
29.219 + * @see ObjectInputStream#ObjectInputStream(InputStream)
29.220 + */
29.221 + public ObjectOutputStream(OutputStream out) throws IOException {
29.222 + verifySubclass();
29.223 + bout = new BlockDataOutputStream(out);
29.224 + handles = new HandleTable(10, (float) 3.00);
29.225 + subs = new ReplaceTable(10, (float) 3.00);
29.226 + enableOverride = false;
29.227 + writeStreamHeader();
29.228 + bout.setBlockDataMode(true);
29.229 + if (extendedDebugInfo) {
29.230 + debugInfoStack = new DebugTraceInfoStack();
29.231 + } else {
29.232 + debugInfoStack = null;
29.233 + }
29.234 + }
29.235 +
29.236 + /**
29.237 + * Provide a way for subclasses that are completely reimplementing
29.238 + * ObjectOutputStream to not have to allocate private data just used by
29.239 + * this implementation of ObjectOutputStream.
29.240 + *
29.241 + * <p>If there is a security manager installed, this method first calls the
29.242 + * security manager's <code>checkPermission</code> method with a
29.243 + * <code>SerializablePermission("enableSubclassImplementation")</code>
29.244 + * permission to ensure it's ok to enable subclassing.
29.245 + *
29.246 + * @throws SecurityException if a security manager exists and its
29.247 + * <code>checkPermission</code> method denies enabling
29.248 + * subclassing.
29.249 + * @see SecurityManager#checkPermission
29.250 + * @see java.io.SerializablePermission
29.251 + */
29.252 + protected ObjectOutputStream() throws IOException, SecurityException {
29.253 + throw new SecurityException();
29.254 + }
29.255 +
29.256 + /**
29.257 + * Specify stream protocol version to use when writing the stream.
29.258 + *
29.259 + * <p>This routine provides a hook to enable the current version of
29.260 + * Serialization to write in a format that is backwards compatible to a
29.261 + * previous version of the stream format.
29.262 + *
29.263 + * <p>Every effort will be made to avoid introducing additional
29.264 + * backwards incompatibilities; however, sometimes there is no
29.265 + * other alternative.
29.266 + *
29.267 + * @param version use ProtocolVersion from java.io.ObjectStreamConstants.
29.268 + * @throws IllegalStateException if called after any objects
29.269 + * have been serialized.
29.270 + * @throws IllegalArgumentException if invalid version is passed in.
29.271 + * @throws IOException if I/O errors occur
29.272 + * @see java.io.ObjectStreamConstants#PROTOCOL_VERSION_1
29.273 + * @see java.io.ObjectStreamConstants#PROTOCOL_VERSION_2
29.274 + * @since 1.2
29.275 + */
29.276 + public void useProtocolVersion(int version) throws IOException {
29.277 + if (handles.size() != 0) {
29.278 + // REMIND: implement better check for pristine stream?
29.279 + throw new IllegalStateException("stream non-empty");
29.280 + }
29.281 + switch (version) {
29.282 + case PROTOCOL_VERSION_1:
29.283 + case PROTOCOL_VERSION_2:
29.284 + protocol = version;
29.285 + break;
29.286 +
29.287 + default:
29.288 + throw new IllegalArgumentException(
29.289 + "unknown version: " + version);
29.290 + }
29.291 + }
29.292 +
29.293 + /**
29.294 + * Write the specified object to the ObjectOutputStream. The class of the
29.295 + * object, the signature of the class, and the values of the non-transient
29.296 + * and non-static fields of the class and all of its supertypes are
29.297 + * written. Default serialization for a class can be overridden using the
29.298 + * writeObject and the readObject methods. Objects referenced by this
29.299 + * object are written transitively so that a complete equivalent graph of
29.300 + * objects can be reconstructed by an ObjectInputStream.
29.301 + *
29.302 + * <p>Exceptions are thrown for problems with the OutputStream and for
29.303 + * classes that should not be serialized. All exceptions are fatal to the
29.304 + * OutputStream, which is left in an indeterminate state, and it is up to
29.305 + * the caller to ignore or recover the stream state.
29.306 + *
29.307 + * @throws InvalidClassException Something is wrong with a class used by
29.308 + * serialization.
29.309 + * @throws NotSerializableException Some object to be serialized does not
29.310 + * implement the java.io.Serializable interface.
29.311 + * @throws IOException Any exception thrown by the underlying
29.312 + * OutputStream.
29.313 + */
29.314 + public final void writeObject(Object obj) throws IOException {
29.315 + if (enableOverride) {
29.316 + writeObjectOverride(obj);
29.317 + return;
29.318 + }
29.319 + try {
29.320 + writeObject0(obj, false);
29.321 + } catch (IOException ex) {
29.322 + if (depth == 0) {
29.323 + writeFatalException(ex);
29.324 + }
29.325 + throw ex;
29.326 + }
29.327 + }
29.328 +
29.329 + /**
29.330 + * Method used by subclasses to override the default writeObject method.
29.331 + * This method is called by trusted subclasses of ObjectInputStream that
29.332 + * constructed ObjectInputStream using the protected no-arg constructor.
29.333 + * The subclass is expected to provide an override method with the modifier
29.334 + * "final".
29.335 + *
29.336 + * @param obj object to be written to the underlying stream
29.337 + * @throws IOException if there are I/O errors while writing to the
29.338 + * underlying stream
29.339 + * @see #ObjectOutputStream()
29.340 + * @see #writeObject(Object)
29.341 + * @since 1.2
29.342 + */
29.343 + protected void writeObjectOverride(Object obj) throws IOException {
29.344 + }
29.345 +
29.346 + /**
29.347 + * Writes an "unshared" object to the ObjectOutputStream. This method is
29.348 + * identical to writeObject, except that it always writes the given object
29.349 + * as a new, unique object in the stream (as opposed to a back-reference
29.350 + * pointing to a previously serialized instance). Specifically:
29.351 + * <ul>
29.352 + * <li>An object written via writeUnshared is always serialized in the
29.353 + * same manner as a newly appearing object (an object that has not
29.354 + * been written to the stream yet), regardless of whether or not the
29.355 + * object has been written previously.
29.356 + *
29.357 + * <li>If writeObject is used to write an object that has been previously
29.358 + * written with writeUnshared, the previous writeUnshared operation
29.359 + * is treated as if it were a write of a separate object. In other
29.360 + * words, ObjectOutputStream will never generate back-references to
29.361 + * object data written by calls to writeUnshared.
29.362 + * </ul>
29.363 + * While writing an object via writeUnshared does not in itself guarantee a
29.364 + * unique reference to the object when it is deserialized, it allows a
29.365 + * single object to be defined multiple times in a stream, so that multiple
29.366 + * calls to readUnshared by the receiver will not conflict. Note that the
29.367 + * rules described above only apply to the base-level object written with
29.368 + * writeUnshared, and not to any transitively referenced sub-objects in the
29.369 + * object graph to be serialized.
29.370 + *
29.371 + * <p>ObjectOutputStream subclasses which override this method can only be
29.372 + * constructed in security contexts possessing the
29.373 + * "enableSubclassImplementation" SerializablePermission; any attempt to
29.374 + * instantiate such a subclass without this permission will cause a
29.375 + * SecurityException to be thrown.
29.376 + *
29.377 + * @param obj object to write to stream
29.378 + * @throws NotSerializableException if an object in the graph to be
29.379 + * serialized does not implement the Serializable interface
29.380 + * @throws InvalidClassException if a problem exists with the class of an
29.381 + * object to be serialized
29.382 + * @throws IOException if an I/O error occurs during serialization
29.383 + * @since 1.4
29.384 + */
29.385 + public void writeUnshared(Object obj) throws IOException {
29.386 + try {
29.387 + writeObject0(obj, true);
29.388 + } catch (IOException ex) {
29.389 + if (depth == 0) {
29.390 + writeFatalException(ex);
29.391 + }
29.392 + throw ex;
29.393 + }
29.394 + }
29.395 +
29.396 + /**
29.397 + * Write the non-static and non-transient fields of the current class to
29.398 + * this stream. This may only be called from the writeObject method of the
29.399 + * class being serialized. It will throw the NotActiveException if it is
29.400 + * called otherwise.
29.401 + *
29.402 + * @throws IOException if I/O errors occur while writing to the underlying
29.403 + * <code>OutputStream</code>
29.404 + */
29.405 + public void defaultWriteObject() throws IOException {
29.406 + if ( curContext == null ) {
29.407 + throw new NotActiveException("not in call to writeObject");
29.408 + }
29.409 + Object curObj = null; // curContext.getObj();
29.410 + ObjectStreamClass curDesc = null; // curContext.getDesc();
29.411 + bout.setBlockDataMode(false);
29.412 + defaultWriteFields(curObj, curDesc);
29.413 + bout.setBlockDataMode(true);
29.414 + }
29.415 +
29.416 + /**
29.417 + * Retrieve the object used to buffer persistent fields to be written to
29.418 + * the stream. The fields will be written to the stream when writeFields
29.419 + * method is called.
29.420 + *
29.421 + * @return an instance of the class Putfield that holds the serializable
29.422 + * fields
29.423 + * @throws IOException if I/O errors occur
29.424 + * @since 1.2
29.425 + */
29.426 + public ObjectOutputStream.PutField putFields() throws IOException {
29.427 + if (curPut == null) {
29.428 + if (curContext == null) {
29.429 + throw new NotActiveException("not in call to writeObject");
29.430 + }
29.431 + Object curObj = null; // curContext.getObj();
29.432 + ObjectStreamClass curDesc = null; // curContext.getDesc();
29.433 + curPut = new PutFieldImpl(curDesc);
29.434 + }
29.435 + return curPut;
29.436 + }
29.437 +
29.438 + /**
29.439 + * Write the buffered fields to the stream.
29.440 + *
29.441 + * @throws IOException if I/O errors occur while writing to the underlying
29.442 + * stream
29.443 + * @throws NotActiveException Called when a classes writeObject method was
29.444 + * not called to write the state of the object.
29.445 + * @since 1.2
29.446 + */
29.447 + public void writeFields() throws IOException {
29.448 + if (curPut == null) {
29.449 + throw new NotActiveException("no current PutField object");
29.450 + }
29.451 + bout.setBlockDataMode(false);
29.452 + curPut.writeFields();
29.453 + bout.setBlockDataMode(true);
29.454 + }
29.455 +
29.456 + /**
29.457 + * Reset will disregard the state of any objects already written to the
29.458 + * stream. The state is reset to be the same as a new ObjectOutputStream.
29.459 + * The current point in the stream is marked as reset so the corresponding
29.460 + * ObjectInputStream will be reset at the same point. Objects previously
29.461 + * written to the stream will not be refered to as already being in the
29.462 + * stream. They will be written to the stream again.
29.463 + *
29.464 + * @throws IOException if reset() is invoked while serializing an object.
29.465 + */
29.466 + public void reset() throws IOException {
29.467 + if (depth != 0) {
29.468 + throw new IOException("stream active");
29.469 + }
29.470 + bout.setBlockDataMode(false);
29.471 + bout.writeByte(TC_RESET);
29.472 + clear();
29.473 + bout.setBlockDataMode(true);
29.474 + }
29.475 +
29.476 + /**
29.477 + * Subclasses may implement this method to allow class data to be stored in
29.478 + * the stream. By default this method does nothing. The corresponding
29.479 + * method in ObjectInputStream is resolveClass. This method is called
29.480 + * exactly once for each unique class in the stream. The class name and
29.481 + * signature will have already been written to the stream. This method may
29.482 + * make free use of the ObjectOutputStream to save any representation of
29.483 + * the class it deems suitable (for example, the bytes of the class file).
29.484 + * The resolveClass method in the corresponding subclass of
29.485 + * ObjectInputStream must read and use any data or objects written by
29.486 + * annotateClass.
29.487 + *
29.488 + * @param cl the class to annotate custom data for
29.489 + * @throws IOException Any exception thrown by the underlying
29.490 + * OutputStream.
29.491 + */
29.492 + protected void annotateClass(Class<?> cl) throws IOException {
29.493 + }
29.494 +
29.495 + /**
29.496 + * Subclasses may implement this method to store custom data in the stream
29.497 + * along with descriptors for dynamic proxy classes.
29.498 + *
29.499 + * <p>This method is called exactly once for each unique proxy class
29.500 + * descriptor in the stream. The default implementation of this method in
29.501 + * <code>ObjectOutputStream</code> does nothing.
29.502 + *
29.503 + * <p>The corresponding method in <code>ObjectInputStream</code> is
29.504 + * <code>resolveProxyClass</code>. For a given subclass of
29.505 + * <code>ObjectOutputStream</code> that overrides this method, the
29.506 + * <code>resolveProxyClass</code> method in the corresponding subclass of
29.507 + * <code>ObjectInputStream</code> must read any data or objects written by
29.508 + * <code>annotateProxyClass</code>.
29.509 + *
29.510 + * @param cl the proxy class to annotate custom data for
29.511 + * @throws IOException any exception thrown by the underlying
29.512 + * <code>OutputStream</code>
29.513 + * @see ObjectInputStream#resolveProxyClass(String[])
29.514 + * @since 1.3
29.515 + */
29.516 + protected void annotateProxyClass(Class<?> cl) throws IOException {
29.517 + }
29.518 +
29.519 + /**
29.520 + * This method will allow trusted subclasses of ObjectOutputStream to
29.521 + * substitute one object for another during serialization. Replacing
29.522 + * objects is disabled until enableReplaceObject is called. The
29.523 + * enableReplaceObject method checks that the stream requesting to do
29.524 + * replacement can be trusted. The first occurrence of each object written
29.525 + * into the serialization stream is passed to replaceObject. Subsequent
29.526 + * references to the object are replaced by the object returned by the
29.527 + * original call to replaceObject. To ensure that the private state of
29.528 + * objects is not unintentionally exposed, only trusted streams may use
29.529 + * replaceObject.
29.530 + *
29.531 + * <p>The ObjectOutputStream.writeObject method takes a parameter of type
29.532 + * Object (as opposed to type Serializable) to allow for cases where
29.533 + * non-serializable objects are replaced by serializable ones.
29.534 + *
29.535 + * <p>When a subclass is replacing objects it must insure that either a
29.536 + * complementary substitution must be made during deserialization or that
29.537 + * the substituted object is compatible with every field where the
29.538 + * reference will be stored. Objects whose type is not a subclass of the
29.539 + * type of the field or array element abort the serialization by raising an
29.540 + * exception and the object is not be stored.
29.541 + *
29.542 + * <p>This method is called only once when each object is first
29.543 + * encountered. All subsequent references to the object will be redirected
29.544 + * to the new object. This method should return the object to be
29.545 + * substituted or the original object.
29.546 + *
29.547 + * <p>Null can be returned as the object to be substituted, but may cause