Emulation of ZipInputStream seems to be in good shape. Merging, so David can use the latest achievements in main development line
1.1 --- a/core/pom.xml Fri Feb 01 16:34:51 2013 +0100
1.2 +++ b/core/pom.xml Mon Feb 04 09:37:56 2013 +0100
1.3 @@ -38,6 +38,7 @@
1.4 <dependency>
1.5 <groupId>org.netbeans.api</groupId>
1.6 <artifactId>org-openide-util-lookup</artifactId>
1.7 + <scope>provided</scope>
1.8 </dependency>
1.9 </dependencies>
1.10 <description>Contains esential annotations for associating JavaScript code with
2.1 --- a/emul/compact/pom.xml Fri Feb 01 16:34:51 2013 +0100
2.2 +++ b/emul/compact/pom.xml Mon Feb 04 09:37:56 2013 +0100
2.3 @@ -27,6 +27,11 @@
2.4 <version>${project.version}</version>
2.5 <scope>test</scope>
2.6 </dependency>
2.7 + <dependency>
2.8 + <groupId>org.netbeans.api</groupId>
2.9 + <artifactId>org-openide-util-lookup</artifactId>
2.10 + <scope>test</scope>
2.11 + </dependency>
2.12 </dependencies>
2.13 <build>
2.14 <plugins>
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/emul/compact/src/main/java/java/beans/ChangeListenerMap.java Mon Feb 04 09:37:56 2013 +0100
3.3 @@ -0,0 +1,248 @@
3.4 +/*
3.5 + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3.7 + *
3.8 + * This code is free software; you can redistribute it and/or modify it
3.9 + * under the terms of the GNU General Public License version 2 only, as
3.10 + * published by the Free Software Foundation. Oracle designates this
3.11 + * particular file as subject to the "Classpath" exception as provided
3.12 + * by Oracle in the LICENSE file that accompanied this code.
3.13 + *
3.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
3.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
3.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
3.17 + * version 2 for more details (a copy is included in the LICENSE file that
3.18 + * accompanied this code).
3.19 + *
3.20 + * You should have received a copy of the GNU General Public License version
3.21 + * 2 along with this work; if not, write to the Free Software Foundation,
3.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
3.23 + *
3.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
3.25 + * or visit www.oracle.com if you need additional information or have any
3.26 + * questions.
3.27 + */
3.28 +package java.beans;
3.29 +
3.30 +import java.util.ArrayList;
3.31 +import java.util.Collections;
3.32 +import java.util.EventListener;
3.33 +import java.util.EventListenerProxy;
3.34 +import java.util.HashMap;
3.35 +import java.util.List;
3.36 +import java.util.Map;
3.37 +import java.util.Map.Entry;
3.38 +import java.util.Set;
3.39 +import org.apidesign.bck2brwsr.emul.lang.System;
3.40 +
3.41 +/**
3.42 + * This is an abstract class that provides base functionality
3.43 + * for the {@link PropertyChangeSupport PropertyChangeSupport} class
3.44 + * and the {@link VetoableChangeSupport VetoableChangeSupport} class.
3.45 + *
3.46 + * @see PropertyChangeListenerMap
3.47 + * @see VetoableChangeListenerMap
3.48 + *
3.49 + * @author Sergey A. Malenkov
3.50 + */
3.51 +abstract class ChangeListenerMap<L extends EventListener> {
3.52 + private Map<String, L[]> map;
3.53 +
3.54 + /**
3.55 + * Creates an array of listeners.
3.56 + * This method can be optimized by using
3.57 + * the same instance of the empty array
3.58 + * when {@code length} is equal to {@code 0}.
3.59 + *
3.60 + * @param length the array length
3.61 + * @return an array with specified length
3.62 + */
3.63 + protected abstract L[] newArray(int length);
3.64 +
3.65 + /**
3.66 + * Creates a proxy listener for the specified property.
3.67 + *
3.68 + * @param name the name of the property to listen on
3.69 + * @param listener the listener to process events
3.70 + * @return a proxy listener
3.71 + */
3.72 + protected abstract L newProxy(String name, L listener);
3.73 +
3.74 + /**
3.75 + * Adds a listener to the list of listeners for the specified property.
3.76 + * This listener is called as many times as it was added.
3.77 + *
3.78 + * @param name the name of the property to listen on
3.79 + * @param listener the listener to process events
3.80 + */
3.81 + public final synchronized void add(String name, L listener) {
3.82 + if (this.map == null) {
3.83 + this.map = new HashMap<String, L[]>();
3.84 + }
3.85 + L[] array = this.map.get(name);
3.86 + int size = (array != null)
3.87 + ? array.length
3.88 + : 0;
3.89 +
3.90 + L[] clone = newArray(size + 1);
3.91 + clone[size] = listener;
3.92 + if (array != null) {
3.93 + System.arraycopy(array, 0, clone, 0, size);
3.94 + }
3.95 + this.map.put(name, clone);
3.96 + }
3.97 +
3.98 + /**
3.99 + * Removes a listener from the list of listeners for the specified property.
3.100 + * If the listener was added more than once to the same event source,
3.101 + * this listener will be notified one less time after being removed.
3.102 + *
3.103 + * @param name the name of the property to listen on
3.104 + * @param listener the listener to process events
3.105 + */
3.106 + public final synchronized void remove(String name, L listener) {
3.107 + if (this.map != null) {
3.108 + L[] array = this.map.get(name);
3.109 + if (array != null) {
3.110 + for (int i = 0; i < array.length; i++) {
3.111 + if (listener.equals(array[i])) {
3.112 + int size = array.length - 1;
3.113 + if (size > 0) {
3.114 + L[] clone = newArray(size);
3.115 + System.arraycopy(array, 0, clone, 0, i);
3.116 + System.arraycopy(array, i + 1, clone, i, size - i);
3.117 + this.map.put(name, clone);
3.118 + }
3.119 + else {
3.120 + this.map.remove(name);
3.121 + if (this.map.isEmpty()) {
3.122 + this.map = null;
3.123 + }
3.124 + }
3.125 + break;
3.126 + }
3.127 + }
3.128 + }
3.129 + }
3.130 + }
3.131 +
3.132 + /**
3.133 + * Returns the list of listeners for the specified property.
3.134 + *
3.135 + * @param name the name of the property
3.136 + * @return the corresponding list of listeners
3.137 + */
3.138 + public final synchronized L[] get(String name) {
3.139 + return (this.map != null)
3.140 + ? this.map.get(name)
3.141 + : null;
3.142 + }
3.143 +
3.144 + /**
3.145 + * Sets new list of listeners for the specified property.
3.146 + *
3.147 + * @param name the name of the property
3.148 + * @param listeners new list of listeners
3.149 + */
3.150 + public final void set(String name, L[] listeners) {
3.151 + if (listeners != null) {
3.152 + if (this.map == null) {
3.153 + this.map = new HashMap<String, L[]>();
3.154 + }
3.155 + this.map.put(name, listeners);
3.156 + }
3.157 + else if (this.map != null) {
3.158 + this.map.remove(name);
3.159 + if (this.map.isEmpty()) {
3.160 + this.map = null;
3.161 + }
3.162 + }
3.163 + }
3.164 +
3.165 + /**
3.166 + * Returns all listeners in the map.
3.167 + *
3.168 + * @return an array of all listeners
3.169 + */
3.170 + public final synchronized L[] getListeners() {
3.171 + if (this.map == null) {
3.172 + return newArray(0);
3.173 + }
3.174 + List<L> list = new ArrayList<L>();
3.175 +
3.176 + L[] listeners = this.map.get(null);
3.177 + if (listeners != null) {
3.178 + for (L listener : listeners) {
3.179 + list.add(listener);
3.180 + }
3.181 + }
3.182 + for (Entry<String, L[]> entry : this.map.entrySet()) {
3.183 + String name = entry.getKey();
3.184 + if (name != null) {
3.185 + for (L listener : entry.getValue()) {
3.186 + list.add(newProxy(name, listener));
3.187 + }
3.188 + }
3.189 + }
3.190 + return list.toArray(newArray(list.size()));
3.191 + }
3.192 +
3.193 + /**
3.194 + * Returns listeners that have been associated with the named property.
3.195 + *
3.196 + * @param name the name of the property
3.197 + * @return an array of listeners for the named property
3.198 + */
3.199 + public final L[] getListeners(String name) {
3.200 + if (name != null) {
3.201 + L[] listeners = get(name);
3.202 + if (listeners != null) {
3.203 + return listeners.clone();
3.204 + }
3.205 + }
3.206 + return newArray(0);
3.207 + }
3.208 +
3.209 + /**
3.210 + * Indicates whether the map contains
3.211 + * at least one listener to be notified.
3.212 + *
3.213 + * @param name the name of the property
3.214 + * @return {@code true} if at least one listener exists or
3.215 + * {@code false} otherwise
3.216 + */
3.217 + public final synchronized boolean hasListeners(String name) {
3.218 + if (this.map == null) {
3.219 + return false;
3.220 + }
3.221 + L[] array = this.map.get(null);
3.222 + return (array != null) || ((name != null) && (null != this.map.get(name)));
3.223 + }
3.224 +
3.225 + /**
3.226 + * Returns a set of entries from the map.
3.227 + * Each entry is a pair consisted of the property name
3.228 + * and the corresponding list of listeners.
3.229 + *
3.230 + * @return a set of entries from the map
3.231 + */
3.232 + public final Set<Entry<String, L[]>> getEntries() {
3.233 + return (this.map != null)
3.234 + ? this.map.entrySet()
3.235 + : Collections.<Entry<String, L[]>>emptySet();
3.236 + }
3.237 +
3.238 + /**
3.239 + * Extracts a real listener from the proxy listener.
3.240 + * It is necessary because default proxy class is not serializable.
3.241 + *
3.242 + * @return a real listener
3.243 + */
3.244 + public final L extract(L listener) {
3.245 + while (listener instanceof EventListenerProxy) {
3.246 + EventListenerProxy<L> proxy = (EventListenerProxy<L>) listener;
3.247 + listener = proxy.getListener();
3.248 + }
3.249 + return listener;
3.250 + }
3.251 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/emul/compact/src/main/java/java/beans/IndexedPropertyChangeEvent.java Mon Feb 04 09:37:56 2013 +0100
4.3 @@ -0,0 +1,78 @@
4.4 +/*
4.5 + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4.7 + *
4.8 + * This code is free software; you can redistribute it and/or modify it
4.9 + * under the terms of the GNU General Public License version 2 only, as
4.10 + * published by the Free Software Foundation. Oracle designates this
4.11 + * particular file as subject to the "Classpath" exception as provided
4.12 + * by Oracle in the LICENSE file that accompanied this code.
4.13 + *
4.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
4.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
4.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
4.17 + * version 2 for more details (a copy is included in the LICENSE file that
4.18 + * accompanied this code).
4.19 + *
4.20 + * You should have received a copy of the GNU General Public License version
4.21 + * 2 along with this work; if not, write to the Free Software Foundation,
4.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
4.23 + *
4.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
4.25 + * or visit www.oracle.com if you need additional information or have any
4.26 + * questions.
4.27 + */
4.28 +package java.beans;
4.29 +
4.30 +/**
4.31 + * An "IndexedPropertyChange" event gets delivered whenever a component that
4.32 + * conforms to the JavaBeans™ specification (a "bean") changes a bound
4.33 + * indexed property. This class is an extension of <code>PropertyChangeEvent</code>
4.34 + * but contains the index of the property that has changed.
4.35 + * <P>
4.36 + * Null values may be provided for the old and the new values if their
4.37 + * true values are not known.
4.38 + * <P>
4.39 + * An event source may send a null object as the name to indicate that an
4.40 + * arbitrary set of if its properties have changed. In this case the
4.41 + * old and new values should also be null.
4.42 + *
4.43 + * @since 1.5
4.44 + * @author Mark Davidson
4.45 + */
4.46 +public class IndexedPropertyChangeEvent extends PropertyChangeEvent {
4.47 + private static final long serialVersionUID = -320227448495806870L;
4.48 +
4.49 + private int index;
4.50 +
4.51 + /**
4.52 + * Constructs a new <code>IndexedPropertyChangeEvent</code> object.
4.53 + *
4.54 + * @param source The bean that fired the event.
4.55 + * @param propertyName The programmatic name of the property that
4.56 + * was changed.
4.57 + * @param oldValue The old value of the property.
4.58 + * @param newValue The new value of the property.
4.59 + * @param index index of the property element that was changed.
4.60 + */
4.61 + public IndexedPropertyChangeEvent(Object source, String propertyName,
4.62 + Object oldValue, Object newValue,
4.63 + int index) {
4.64 + super (source, propertyName, oldValue, newValue);
4.65 + this.index = index;
4.66 + }
4.67 +
4.68 + /**
4.69 + * Gets the index of the property that was changed.
4.70 + *
4.71 + * @return The index specifying the property element that was
4.72 + * changed.
4.73 + */
4.74 + public int getIndex() {
4.75 + return index;
4.76 + }
4.77 +
4.78 + void appendTo(StringBuilder sb) {
4.79 + sb.append("; index=").append(getIndex());
4.80 + }
4.81 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/emul/compact/src/main/java/java/beans/PropertyChangeEvent.java Mon Feb 04 09:37:56 2013 +0100
5.3 @@ -0,0 +1,164 @@
5.4 +/*
5.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5.7 + *
5.8 + * This code is free software; you can redistribute it and/or modify it
5.9 + * under the terms of the GNU General Public License version 2 only, as
5.10 + * published by the Free Software Foundation. Oracle designates this
5.11 + * particular file as subject to the "Classpath" exception as provided
5.12 + * by Oracle in the LICENSE file that accompanied this code.
5.13 + *
5.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
5.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
5.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
5.17 + * version 2 for more details (a copy is included in the LICENSE file that
5.18 + * accompanied this code).
5.19 + *
5.20 + * You should have received a copy of the GNU General Public License version
5.21 + * 2 along with this work; if not, write to the Free Software Foundation,
5.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
5.23 + *
5.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
5.25 + * or visit www.oracle.com if you need additional information or have any
5.26 + * questions.
5.27 + */
5.28 +
5.29 +package java.beans;
5.30 +
5.31 +/**
5.32 + * A "PropertyChange" event gets delivered whenever a bean changes a "bound"
5.33 + * or "constrained" property. A PropertyChangeEvent object is sent as an
5.34 + * argument to the PropertyChangeListener and VetoableChangeListener methods.
5.35 + * <P>
5.36 + * Normally PropertyChangeEvents are accompanied by the name and the old
5.37 + * and new value of the changed property. If the new value is a primitive
5.38 + * type (such as int or boolean) it must be wrapped as the
5.39 + * corresponding java.lang.* Object type (such as Integer or Boolean).
5.40 + * <P>
5.41 + * Null values may be provided for the old and the new values if their
5.42 + * true values are not known.
5.43 + * <P>
5.44 + * An event source may send a null object as the name to indicate that an
5.45 + * arbitrary set of if its properties have changed. In this case the
5.46 + * old and new values should also be null.
5.47 + */
5.48 +
5.49 +public class PropertyChangeEvent extends java.util.EventObject {
5.50 + private static final long serialVersionUID = 7042693688939648123L;
5.51 +
5.52 + /**
5.53 + * Constructs a new <code>PropertyChangeEvent</code>.
5.54 + *
5.55 + * @param source The bean that fired the event.
5.56 + * @param propertyName The programmatic name of the property
5.57 + * that was changed.
5.58 + * @param oldValue The old value of the property.
5.59 + * @param newValue The new value of the property.
5.60 + */
5.61 + public PropertyChangeEvent(Object source, String propertyName,
5.62 + Object oldValue, Object newValue) {
5.63 + super(source);
5.64 + this.propertyName = propertyName;
5.65 + this.newValue = newValue;
5.66 + this.oldValue = oldValue;
5.67 + }
5.68 +
5.69 + /**
5.70 + * Gets the programmatic name of the property that was changed.
5.71 + *
5.72 + * @return The programmatic name of the property that was changed.
5.73 + * May be null if multiple properties have changed.
5.74 + */
5.75 + public String getPropertyName() {
5.76 + return propertyName;
5.77 + }
5.78 +
5.79 + /**
5.80 + * Gets the new value for the property, expressed as an Object.
5.81 + *
5.82 + * @return The new value for the property, expressed as an Object.
5.83 + * May be null if multiple properties have changed.
5.84 + */
5.85 + public Object getNewValue() {
5.86 + return newValue;
5.87 + }
5.88 +
5.89 + /**
5.90 + * Gets the old value for the property, expressed as an Object.
5.91 + *
5.92 + * @return The old value for the property, expressed as an Object.
5.93 + * May be null if multiple properties have changed.
5.94 + */
5.95 + public Object getOldValue() {
5.96 + return oldValue;
5.97 + }
5.98 +
5.99 + /**
5.100 + * Sets the propagationId object for the event.
5.101 + *
5.102 + * @param propagationId The propagationId object for the event.
5.103 + */
5.104 + public void setPropagationId(Object propagationId) {
5.105 + this.propagationId = propagationId;
5.106 + }
5.107 +
5.108 + /**
5.109 + * The "propagationId" field is reserved for future use. In Beans 1.0
5.110 + * the sole requirement is that if a listener catches a PropertyChangeEvent
5.111 + * and then fires a PropertyChangeEvent of its own, then it should
5.112 + * make sure that it propagates the propagationId field from its
5.113 + * incoming event to its outgoing event.
5.114 + *
5.115 + * @return the propagationId object associated with a bound/constrained
5.116 + * property update.
5.117 + */
5.118 + public Object getPropagationId() {
5.119 + return propagationId;
5.120 + }
5.121 +
5.122 + /**
5.123 + * name of the property that changed. May be null, if not known.
5.124 + * @serial
5.125 + */
5.126 + private String propertyName;
5.127 +
5.128 + /**
5.129 + * New value for property. May be null if not known.
5.130 + * @serial
5.131 + */
5.132 + private Object newValue;
5.133 +
5.134 + /**
5.135 + * Previous value for property. May be null if not known.
5.136 + * @serial
5.137 + */
5.138 + private Object oldValue;
5.139 +
5.140 + /**
5.141 + * Propagation ID. May be null.
5.142 + * @serial
5.143 + * @see #getPropagationId
5.144 + */
5.145 + private Object propagationId;
5.146 +
5.147 + /**
5.148 + * Returns a string representation of the object.
5.149 + *
5.150 + * @return a string representation of the object
5.151 + *
5.152 + * @since 1.7
5.153 + */
5.154 + public String toString() {
5.155 + StringBuilder sb = new StringBuilder(getClass().getName());
5.156 + sb.append("[propertyName=").append(getPropertyName());
5.157 + appendTo(sb);
5.158 + sb.append("; oldValue=").append(getOldValue());
5.159 + sb.append("; newValue=").append(getNewValue());
5.160 + sb.append("; propagationId=").append(getPropagationId());
5.161 + sb.append("; source=").append(getSource());
5.162 + return sb.append("]").toString();
5.163 + }
5.164 +
5.165 + void appendTo(StringBuilder sb) {
5.166 + }
5.167 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/emul/compact/src/main/java/java/beans/PropertyChangeListener.java Mon Feb 04 09:37:56 2013 +0100
6.3 @@ -0,0 +1,44 @@
6.4 +/*
6.5 + * Copyright (c) 1996, Oracle and/or its affiliates. All rights reserved.
6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6.7 + *
6.8 + * This code is free software; you can redistribute it and/or modify it
6.9 + * under the terms of the GNU General Public License version 2 only, as
6.10 + * published by the Free Software Foundation. Oracle designates this
6.11 + * particular file as subject to the "Classpath" exception as provided
6.12 + * by Oracle in the LICENSE file that accompanied this code.
6.13 + *
6.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
6.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
6.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
6.17 + * version 2 for more details (a copy is included in the LICENSE file that
6.18 + * accompanied this code).
6.19 + *
6.20 + * You should have received a copy of the GNU General Public License version
6.21 + * 2 along with this work; if not, write to the Free Software Foundation,
6.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
6.23 + *
6.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
6.25 + * or visit www.oracle.com if you need additional information or have any
6.26 + * questions.
6.27 + */
6.28 +
6.29 +package java.beans;
6.30 +
6.31 +/**
6.32 + * A "PropertyChange" event gets fired whenever a bean changes a "bound"
6.33 + * property. You can register a PropertyChangeListener with a source
6.34 + * bean so as to be notified of any bound property updates.
6.35 + */
6.36 +
6.37 +public interface PropertyChangeListener extends java.util.EventListener {
6.38 +
6.39 + /**
6.40 + * This method gets called when a bound property is changed.
6.41 + * @param evt A PropertyChangeEvent object describing the event source
6.42 + * and the property that has changed.
6.43 + */
6.44 +
6.45 + void propertyChange(PropertyChangeEvent evt);
6.46 +
6.47 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/emul/compact/src/main/java/java/beans/PropertyChangeListenerProxy.java Mon Feb 04 09:37:56 2013 +0100
7.3 @@ -0,0 +1,81 @@
7.4 +/*
7.5 + * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
7.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7.7 + *
7.8 + * This code is free software; you can redistribute it and/or modify it
7.9 + * under the terms of the GNU General Public License version 2 only, as
7.10 + * published by the Free Software Foundation. Oracle designates this
7.11 + * particular file as subject to the "Classpath" exception as provided
7.12 + * by Oracle in the LICENSE file that accompanied this code.
7.13 + *
7.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
7.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7.17 + * version 2 for more details (a copy is included in the LICENSE file that
7.18 + * accompanied this code).
7.19 + *
7.20 + * You should have received a copy of the GNU General Public License version
7.21 + * 2 along with this work; if not, write to the Free Software Foundation,
7.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7.23 + *
7.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7.25 + * or visit www.oracle.com if you need additional information or have any
7.26 + * questions.
7.27 + */
7.28 +
7.29 +package java.beans;
7.30 +
7.31 +import java.util.EventListenerProxy;
7.32 +
7.33 +/**
7.34 + * A class which extends the {@code EventListenerProxy}
7.35 + * specifically for adding a {@code PropertyChangeListener}
7.36 + * with a "bound" property.
7.37 + * Instances of this class can be added
7.38 + * as {@code PropertyChangeListener}s to a bean
7.39 + * which supports firing property change events.
7.40 + * <p>
7.41 + * If the object has a {@code getPropertyChangeListeners} method
7.42 + * then the array returned could be a mixture of {@code PropertyChangeListener}
7.43 + * and {@code PropertyChangeListenerProxy} objects.
7.44 + *
7.45 + * @see java.util.EventListenerProxy
7.46 + * @see PropertyChangeSupport#getPropertyChangeListeners
7.47 + * @since 1.4
7.48 + */
7.49 +public class PropertyChangeListenerProxy
7.50 + extends EventListenerProxy<PropertyChangeListener>
7.51 + implements PropertyChangeListener {
7.52 +
7.53 + private final String propertyName;
7.54 +
7.55 + /**
7.56 + * Constructor which binds the {@code PropertyChangeListener}
7.57 + * to a specific property.
7.58 + *
7.59 + * @param propertyName the name of the property to listen on
7.60 + * @param listener the listener object
7.61 + */
7.62 + public PropertyChangeListenerProxy(String propertyName, PropertyChangeListener listener) {
7.63 + super(listener);
7.64 + this.propertyName = propertyName;
7.65 + }
7.66 +
7.67 + /**
7.68 + * Forwards the property change event to the listener delegate.
7.69 + *
7.70 + * @param event the property change event
7.71 + */
7.72 + public void propertyChange(PropertyChangeEvent event) {
7.73 + getListener().propertyChange(event);
7.74 + }
7.75 +
7.76 + /**
7.77 + * Returns the name of the named property associated with the listener.
7.78 + *
7.79 + * @return the name of the named property associated with the listener
7.80 + */
7.81 + public String getPropertyName() {
7.82 + return this.propertyName;
7.83 + }
7.84 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/emul/compact/src/main/java/java/beans/PropertyChangeSupport.java Mon Feb 04 09:37:56 2013 +0100
8.3 @@ -0,0 +1,536 @@
8.4 +/*
8.5 + * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
8.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8.7 + *
8.8 + * This code is free software; you can redistribute it and/or modify it
8.9 + * under the terms of the GNU General Public License version 2 only, as
8.10 + * published by the Free Software Foundation. Oracle designates this
8.11 + * particular file as subject to the "Classpath" exception as provided
8.12 + * by Oracle in the LICENSE file that accompanied this code.
8.13 + *
8.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
8.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
8.17 + * version 2 for more details (a copy is included in the LICENSE file that
8.18 + * accompanied this code).
8.19 + *
8.20 + * You should have received a copy of the GNU General Public License version
8.21 + * 2 along with this work; if not, write to the Free Software Foundation,
8.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
8.23 + *
8.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
8.25 + * or visit www.oracle.com if you need additional information or have any
8.26 + * questions.
8.27 + */
8.28 +package java.beans;
8.29 +
8.30 +import java.io.Serializable;
8.31 +import java.io.ObjectStreamField;
8.32 +import java.io.ObjectOutputStream;
8.33 +import java.io.ObjectInputStream;
8.34 +import java.io.IOException;
8.35 +import java.util.Hashtable;
8.36 +import java.util.Map.Entry;
8.37 +
8.38 +/**
8.39 + * This is a utility class that can be used by beans that support bound
8.40 + * properties. It manages a list of listeners and dispatches
8.41 + * {@link PropertyChangeEvent}s to them. You can use an instance of this class
8.42 + * as a member field of your bean and delegate these types of work to it.
8.43 + * The {@link PropertyChangeListener} can be registered for all properties
8.44 + * or for a property specified by name.
8.45 + * <p>
8.46 + * Here is an example of {@code PropertyChangeSupport} usage that follows
8.47 + * the rules and recommendations laid out in the JavaBeans™ specification:
8.48 + * <pre>
8.49 + * public class MyBean {
8.50 + * private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
8.51 + *
8.52 + * public void addPropertyChangeListener(PropertyChangeListener listener) {
8.53 + * this.pcs.addPropertyChangeListener(listener);
8.54 + * }
8.55 + *
8.56 + * public void removePropertyChangeListener(PropertyChangeListener listener) {
8.57 + * this.pcs.removePropertyChangeListener(listener);
8.58 + * }
8.59 + *
8.60 + * private String value;
8.61 + *
8.62 + * public String getValue() {
8.63 + * return this.value;
8.64 + * }
8.65 + *
8.66 + * public void setValue(String newValue) {
8.67 + * String oldValue = this.value;
8.68 + * this.value = newValue;
8.69 + * this.pcs.firePropertyChange("value", oldValue, newValue);
8.70 + * }
8.71 + *
8.72 + * [...]
8.73 + * }
8.74 + * </pre>
8.75 + * <p>
8.76 + * A {@code PropertyChangeSupport} instance is thread-safe.
8.77 + * <p>
8.78 + * This class is serializable. When it is serialized it will save
8.79 + * (and restore) any listeners that are themselves serializable. Any
8.80 + * non-serializable listeners will be skipped during serialization.
8.81 + *
8.82 + * @see VetoableChangeSupport
8.83 + */
8.84 +public class PropertyChangeSupport implements Serializable {
8.85 + private PropertyChangeListenerMap map = new PropertyChangeListenerMap();
8.86 +
8.87 + /**
8.88 + * Constructs a <code>PropertyChangeSupport</code> object.
8.89 + *
8.90 + * @param sourceBean The bean to be given as the source for any events.
8.91 + */
8.92 + public PropertyChangeSupport(Object sourceBean) {
8.93 + if (sourceBean == null) {
8.94 + throw new NullPointerException();
8.95 + }
8.96 + source = sourceBean;
8.97 + }
8.98 +
8.99 + /**
8.100 + * Add a PropertyChangeListener to the listener list.
8.101 + * The listener is registered for all properties.
8.102 + * The same listener object may be added more than once, and will be called
8.103 + * as many times as it is added.
8.104 + * If <code>listener</code> is null, no exception is thrown and no action
8.105 + * is taken.
8.106 + *
8.107 + * @param listener The PropertyChangeListener to be added
8.108 + */
8.109 + public void addPropertyChangeListener(PropertyChangeListener listener) {
8.110 + if (listener == null) {
8.111 + return;
8.112 + }
8.113 + if (listener instanceof PropertyChangeListenerProxy) {
8.114 + PropertyChangeListenerProxy proxy =
8.115 + (PropertyChangeListenerProxy)listener;
8.116 + // Call two argument add method.
8.117 + addPropertyChangeListener(proxy.getPropertyName(),
8.118 + proxy.getListener());
8.119 + } else {
8.120 + this.map.add(null, listener);
8.121 + }
8.122 + }
8.123 +
8.124 + /**
8.125 + * Remove a PropertyChangeListener from the listener list.
8.126 + * This removes a PropertyChangeListener that was registered
8.127 + * for all properties.
8.128 + * If <code>listener</code> was added more than once to the same event
8.129 + * source, it will be notified one less time after being removed.
8.130 + * If <code>listener</code> is null, or was never added, no exception is
8.131 + * thrown and no action is taken.
8.132 + *
8.133 + * @param listener The PropertyChangeListener to be removed
8.134 + */
8.135 + public void removePropertyChangeListener(PropertyChangeListener listener) {
8.136 + if (listener == null) {
8.137 + return;
8.138 + }
8.139 + if (listener instanceof PropertyChangeListenerProxy) {
8.140 + PropertyChangeListenerProxy proxy =
8.141 + (PropertyChangeListenerProxy)listener;
8.142 + // Call two argument remove method.
8.143 + removePropertyChangeListener(proxy.getPropertyName(),
8.144 + proxy.getListener());
8.145 + } else {
8.146 + this.map.remove(null, listener);
8.147 + }
8.148 + }
8.149 +
8.150 + /**
8.151 + * Returns an array of all the listeners that were added to the
8.152 + * PropertyChangeSupport object with addPropertyChangeListener().
8.153 + * <p>
8.154 + * If some listeners have been added with a named property, then
8.155 + * the returned array will be a mixture of PropertyChangeListeners
8.156 + * and <code>PropertyChangeListenerProxy</code>s. If the calling
8.157 + * method is interested in distinguishing the listeners then it must
8.158 + * test each element to see if it's a
8.159 + * <code>PropertyChangeListenerProxy</code>, perform the cast, and examine
8.160 + * the parameter.
8.161 + *
8.162 + * <pre>
8.163 + * PropertyChangeListener[] listeners = bean.getPropertyChangeListeners();
8.164 + * for (int i = 0; i < listeners.length; i++) {
8.165 + * if (listeners[i] instanceof PropertyChangeListenerProxy) {
8.166 + * PropertyChangeListenerProxy proxy =
8.167 + * (PropertyChangeListenerProxy)listeners[i];
8.168 + * if (proxy.getPropertyName().equals("foo")) {
8.169 + * // proxy is a PropertyChangeListener which was associated
8.170 + * // with the property named "foo"
8.171 + * }
8.172 + * }
8.173 + * }
8.174 + *</pre>
8.175 + *
8.176 + * @see PropertyChangeListenerProxy
8.177 + * @return all of the <code>PropertyChangeListeners</code> added or an
8.178 + * empty array if no listeners have been added
8.179 + * @since 1.4
8.180 + */
8.181 + public PropertyChangeListener[] getPropertyChangeListeners() {
8.182 + return this.map.getListeners();
8.183 + }
8.184 +
8.185 + /**
8.186 + * Add a PropertyChangeListener for a specific property. The listener
8.187 + * will be invoked only when a call on firePropertyChange names that
8.188 + * specific property.
8.189 + * The same listener object may be added more than once. For each
8.190 + * property, the listener will be invoked the number of times it was added
8.191 + * for that property.
8.192 + * If <code>propertyName</code> or <code>listener</code> is null, no
8.193 + * exception is thrown and no action is taken.
8.194 + *
8.195 + * @param propertyName The name of the property to listen on.
8.196 + * @param listener The PropertyChangeListener to be added
8.197 + */
8.198 + public void addPropertyChangeListener(
8.199 + String propertyName,
8.200 + PropertyChangeListener listener) {
8.201 + if (listener == null || propertyName == null) {
8.202 + return;
8.203 + }
8.204 + listener = this.map.extract(listener);
8.205 + if (listener != null) {
8.206 + this.map.add(propertyName, listener);
8.207 + }
8.208 + }
8.209 +
8.210 + /**
8.211 + * Remove a PropertyChangeListener for a specific property.
8.212 + * If <code>listener</code> was added more than once to the same event
8.213 + * source for the specified property, it will be notified one less time
8.214 + * after being removed.
8.215 + * If <code>propertyName</code> is null, no exception is thrown and no
8.216 + * action is taken.
8.217 + * If <code>listener</code> is null, or was never added for the specified
8.218 + * property, no exception is thrown and no action is taken.
8.219 + *
8.220 + * @param propertyName The name of the property that was listened on.
8.221 + * @param listener The PropertyChangeListener to be removed
8.222 + */
8.223 + public void removePropertyChangeListener(
8.224 + String propertyName,
8.225 + PropertyChangeListener listener) {
8.226 + if (listener == null || propertyName == null) {
8.227 + return;
8.228 + }
8.229 + listener = this.map.extract(listener);
8.230 + if (listener != null) {
8.231 + this.map.remove(propertyName, listener);
8.232 + }
8.233 + }
8.234 +
8.235 + /**
8.236 + * Returns an array of all the listeners which have been associated
8.237 + * with the named property.
8.238 + *
8.239 + * @param propertyName The name of the property being listened to
8.240 + * @return all of the <code>PropertyChangeListeners</code> associated with
8.241 + * the named property. If no such listeners have been added,
8.242 + * or if <code>propertyName</code> is null, an empty array is
8.243 + * returned.
8.244 + * @since 1.4
8.245 + */
8.246 + public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
8.247 + return this.map.getListeners(propertyName);
8.248 + }
8.249 +
8.250 + /**
8.251 + * Reports a bound property update to listeners
8.252 + * that have been registered to track updates of
8.253 + * all properties or a property with the specified name.
8.254 + * <p>
8.255 + * No event is fired if old and new values are equal and non-null.
8.256 + * <p>
8.257 + * This is merely a convenience wrapper around the more general
8.258 + * {@link #firePropertyChange(PropertyChangeEvent)} method.
8.259 + *
8.260 + * @param propertyName the programmatic name of the property that was changed
8.261 + * @param oldValue the old value of the property
8.262 + * @param newValue the new value of the property
8.263 + */
8.264 + public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
8.265 + if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
8.266 + firePropertyChange(new PropertyChangeEvent(this.source, propertyName, oldValue, newValue));
8.267 + }
8.268 + }
8.269 +
8.270 + /**
8.271 + * Reports an integer bound property update to listeners
8.272 + * that have been registered to track updates of
8.273 + * all properties or a property with the specified name.
8.274 + * <p>
8.275 + * No event is fired if old and new values are equal.
8.276 + * <p>
8.277 + * This is merely a convenience wrapper around the more general
8.278 + * {@link #firePropertyChange(String, Object, Object)} method.
8.279 + *
8.280 + * @param propertyName the programmatic name of the property that was changed
8.281 + * @param oldValue the old value of the property
8.282 + * @param newValue the new value of the property
8.283 + */
8.284 + public void firePropertyChange(String propertyName, int oldValue, int newValue) {
8.285 + if (oldValue != newValue) {
8.286 + firePropertyChange(propertyName, Integer.valueOf(oldValue), Integer.valueOf(newValue));
8.287 + }
8.288 + }
8.289 +
8.290 + /**
8.291 + * Reports a boolean bound property update to listeners
8.292 + * that have been registered to track updates of
8.293 + * all properties or a property with the specified name.
8.294 + * <p>
8.295 + * No event is fired if old and new values are equal.
8.296 + * <p>
8.297 + * This is merely a convenience wrapper around the more general
8.298 + * {@link #firePropertyChange(String, Object, Object)} method.
8.299 + *
8.300 + * @param propertyName the programmatic name of the property that was changed
8.301 + * @param oldValue the old value of the property
8.302 + * @param newValue the new value of the property
8.303 + */
8.304 + public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {
8.305 + if (oldValue != newValue) {
8.306 + firePropertyChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
8.307 + }
8.308 + }
8.309 +
8.310 + /**
8.311 + * Fires a property change event to listeners
8.312 + * that have been registered to track updates of
8.313 + * all properties or a property with the specified name.
8.314 + * <p>
8.315 + * No event is fired if the given event's old and new values are equal and non-null.
8.316 + *
8.317 + * @param event the {@code PropertyChangeEvent} to be fired
8.318 + */
8.319 + public void firePropertyChange(PropertyChangeEvent event) {
8.320 + Object oldValue = event.getOldValue();
8.321 + Object newValue = event.getNewValue();
8.322 + if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
8.323 + String name = event.getPropertyName();
8.324 +
8.325 + PropertyChangeListener[] common = this.map.get(null);
8.326 + PropertyChangeListener[] named = (name != null)
8.327 + ? this.map.get(name)
8.328 + : null;
8.329 +
8.330 + fire(common, event);
8.331 + fire(named, event);
8.332 + }
8.333 + }
8.334 +
8.335 + private static void fire(PropertyChangeListener[] listeners, PropertyChangeEvent event) {
8.336 + if (listeners != null) {
8.337 + for (PropertyChangeListener listener : listeners) {
8.338 + listener.propertyChange(event);
8.339 + }
8.340 + }
8.341 + }
8.342 +
8.343 + /**
8.344 + * Reports a bound indexed property update to listeners
8.345 + * that have been registered to track updates of
8.346 + * all properties or a property with the specified name.
8.347 + * <p>
8.348 + * No event is fired if old and new values are equal and non-null.
8.349 + * <p>
8.350 + * This is merely a convenience wrapper around the more general
8.351 + * {@link #firePropertyChange(PropertyChangeEvent)} method.
8.352 + *
8.353 + * @param propertyName the programmatic name of the property that was changed
8.354 + * @param index the index of the property element that was changed
8.355 + * @param oldValue the old value of the property
8.356 + * @param newValue the new value of the property
8.357 + * @since 1.5
8.358 + */
8.359 + public void fireIndexedPropertyChange(String propertyName, int index, Object oldValue, Object newValue) {
8.360 + if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
8.361 + firePropertyChange(new IndexedPropertyChangeEvent(source, propertyName, oldValue, newValue, index));
8.362 + }
8.363 + }
8.364 +
8.365 + /**
8.366 + * Reports an integer bound indexed property update to listeners
8.367 + * that have been registered to track updates of
8.368 + * all properties or a property with the specified name.
8.369 + * <p>
8.370 + * No event is fired if old and new values are equal.
8.371 + * <p>
8.372 + * This is merely a convenience wrapper around the more general
8.373 + * {@link #fireIndexedPropertyChange(String, int, Object, Object)} method.
8.374 + *
8.375 + * @param propertyName the programmatic name of the property that was changed
8.376 + * @param index the index of the property element that was changed
8.377 + * @param oldValue the old value of the property
8.378 + * @param newValue the new value of the property
8.379 + * @since 1.5
8.380 + */
8.381 + public void fireIndexedPropertyChange(String propertyName, int index, int oldValue, int newValue) {
8.382 + if (oldValue != newValue) {
8.383 + fireIndexedPropertyChange(propertyName, index, Integer.valueOf(oldValue), Integer.valueOf(newValue));
8.384 + }
8.385 + }
8.386 +
8.387 + /**
8.388 + * Reports a boolean bound indexed property update to listeners
8.389 + * that have been registered to track updates of
8.390 + * all properties or a property with the specified name.
8.391 + * <p>
8.392 + * No event is fired if old and new values are equal.
8.393 + * <p>
8.394 + * This is merely a convenience wrapper around the more general
8.395 + * {@link #fireIndexedPropertyChange(String, int, Object, Object)} method.
8.396 + *
8.397 + * @param propertyName the programmatic name of the property that was changed
8.398 + * @param index the index of the property element that was changed
8.399 + * @param oldValue the old value of the property
8.400 + * @param newValue the new value of the property
8.401 + * @since 1.5
8.402 + */
8.403 + public void fireIndexedPropertyChange(String propertyName, int index, boolean oldValue, boolean newValue) {
8.404 + if (oldValue != newValue) {
8.405 + fireIndexedPropertyChange(propertyName, index, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
8.406 + }
8.407 + }
8.408 +
8.409 + /**
8.410 + * Check if there are any listeners for a specific property, including
8.411 + * those registered on all properties. If <code>propertyName</code>
8.412 + * is null, only check for listeners registered on all properties.
8.413 + *
8.414 + * @param propertyName the property name.
8.415 + * @return true if there are one or more listeners for the given property
8.416 + */
8.417 + public boolean hasListeners(String propertyName) {
8.418 + return this.map.hasListeners(propertyName);
8.419 + }
8.420 +
8.421 + /**
8.422 + * @serialData Null terminated list of <code>PropertyChangeListeners</code>.
8.423 + * <p>
8.424 + * At serialization time we skip non-serializable listeners and
8.425 + * only serialize the serializable listeners.
8.426 + */
8.427 + private void writeObject(ObjectOutputStream s) throws IOException {
8.428 + Hashtable<String, PropertyChangeSupport> children = null;
8.429 + PropertyChangeListener[] listeners = null;
8.430 + synchronized (this.map) {
8.431 + for (Entry<String, PropertyChangeListener[]> entry : this.map.getEntries()) {
8.432 + String property = entry.getKey();
8.433 + if (property == null) {
8.434 + listeners = entry.getValue();
8.435 + } else {
8.436 + if (children == null) {
8.437 + children = new Hashtable<String, PropertyChangeSupport>();
8.438 + }
8.439 + PropertyChangeSupport pcs = new PropertyChangeSupport(this.source);
8.440 + pcs.map.set(null, entry.getValue());
8.441 + children.put(property, pcs);
8.442 + }
8.443 + }
8.444 + }
8.445 + ObjectOutputStream.PutField fields = s.putFields();
8.446 + fields.put("children", children);
8.447 + fields.put("source", this.source);
8.448 + fields.put("propertyChangeSupportSerializedDataVersion", 2);
8.449 + s.writeFields();
8.450 +
8.451 + if (listeners != null) {
8.452 + for (PropertyChangeListener l : listeners) {
8.453 + if (l instanceof Serializable) {
8.454 + s.writeObject(l);
8.455 + }
8.456 + }
8.457 + }
8.458 + s.writeObject(null);
8.459 + }
8.460 +
8.461 + private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
8.462 + this.map = new PropertyChangeListenerMap();
8.463 +
8.464 + ObjectInputStream.GetField fields = s.readFields();
8.465 +
8.466 + Hashtable<String, PropertyChangeSupport> children = (Hashtable<String, PropertyChangeSupport>) fields.get("children", null);
8.467 + this.source = fields.get("source", null);
8.468 + fields.get("propertyChangeSupportSerializedDataVersion", 2);
8.469 +
8.470 + Object listenerOrNull;
8.471 + while (null != (listenerOrNull = s.readObject())) {
8.472 + this.map.add(null, (PropertyChangeListener)listenerOrNull);
8.473 + }
8.474 + if (children != null) {
8.475 + for (Entry<String, PropertyChangeSupport> entry : children.entrySet()) {
8.476 + for (PropertyChangeListener listener : entry.getValue().getPropertyChangeListeners()) {
8.477 + this.map.add(entry.getKey(), listener);
8.478 + }
8.479 + }
8.480 + }
8.481 + }
8.482 +
8.483 + /**
8.484 + * The object to be provided as the "source" for any generated events.
8.485 + */
8.486 + private Object source;
8.487 +
8.488 + /**
8.489 + * @serialField children Hashtable
8.490 + * @serialField source Object
8.491 + * @serialField propertyChangeSupportSerializedDataVersion int
8.492 + */
8.493 + private static final ObjectStreamField[] serialPersistentFields = {
8.494 + new ObjectStreamField("children", Hashtable.class),
8.495 + new ObjectStreamField("source", Object.class),
8.496 + new ObjectStreamField("propertyChangeSupportSerializedDataVersion", Integer.TYPE)
8.497 + };
8.498 +
8.499 + /**
8.500 + * Serialization version ID, so we're compatible with JDK 1.1
8.501 + */
8.502 + static final long serialVersionUID = 6401253773779951803L;
8.503 +
8.504 + /**
8.505 + * This is a {@link ChangeListenerMap ChangeListenerMap} implementation
8.506 + * that works with {@link PropertyChangeListener PropertyChangeListener} objects.
8.507 + */
8.508 + private static final class PropertyChangeListenerMap extends ChangeListenerMap<PropertyChangeListener> {
8.509 + private static final PropertyChangeListener[] EMPTY = {};
8.510 +
8.511 + /**
8.512 + * Creates an array of {@link PropertyChangeListener PropertyChangeListener} objects.
8.513 + * This method uses the same instance of the empty array
8.514 + * when {@code length} equals {@code 0}.
8.515 + *
8.516 + * @param length the array length
8.517 + * @return an array with specified length
8.518 + */
8.519 + @Override
8.520 + protected PropertyChangeListener[] newArray(int length) {
8.521 + return (0 < length)
8.522 + ? new PropertyChangeListener[length]
8.523 + : EMPTY;
8.524 + }
8.525 +
8.526 + /**
8.527 + * Creates a {@link PropertyChangeListenerProxy PropertyChangeListenerProxy}
8.528 + * object for the specified property.
8.529 + *
8.530 + * @param name the name of the property to listen on
8.531 + * @param listener the listener to process events
8.532 + * @return a {@code PropertyChangeListenerProxy} object
8.533 + */
8.534 + @Override
8.535 + protected PropertyChangeListener newProxy(String name, PropertyChangeListener listener) {
8.536 + return new PropertyChangeListenerProxy(name, listener);
8.537 + }
8.538 + }
8.539 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/emul/compact/src/main/java/java/beans/PropertyVetoException.java Mon Feb 04 09:37:56 2013 +0100
9.3 @@ -0,0 +1,64 @@
9.4 +/*
9.5 + * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
9.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
9.7 + *
9.8 + * This code is free software; you can redistribute it and/or modify it
9.9 + * under the terms of the GNU General Public License version 2 only, as
9.10 + * published by the Free Software Foundation. Oracle designates this
9.11 + * particular file as subject to the "Classpath" exception as provided
9.12 + * by Oracle in the LICENSE file that accompanied this code.
9.13 + *
9.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
9.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9.17 + * version 2 for more details (a copy is included in the LICENSE file that
9.18 + * accompanied this code).
9.19 + *
9.20 + * You should have received a copy of the GNU General Public License version
9.21 + * 2 along with this work; if not, write to the Free Software Foundation,
9.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
9.23 + *
9.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
9.25 + * or visit www.oracle.com if you need additional information or have any
9.26 + * questions.
9.27 + */
9.28 +
9.29 +package java.beans;
9.30 +
9.31 +
9.32 +/**
9.33 + * A PropertyVetoException is thrown when a proposed change to a
9.34 + * property represents an unacceptable value.
9.35 + */
9.36 +
9.37 +public
9.38 +class PropertyVetoException extends Exception {
9.39 + private static final long serialVersionUID = 129596057694162164L;
9.40 +
9.41 + /**
9.42 + * Constructs a <code>PropertyVetoException</code> with a
9.43 + * detailed message.
9.44 + *
9.45 + * @param mess Descriptive message
9.46 + * @param evt A PropertyChangeEvent describing the vetoed change.
9.47 + */
9.48 + public PropertyVetoException(String mess, PropertyChangeEvent evt) {
9.49 + super(mess);
9.50 + this.evt = evt;
9.51 + }
9.52 +
9.53 + /**
9.54 + * Gets the vetoed <code>PropertyChangeEvent</code>.
9.55 + *
9.56 + * @return A PropertyChangeEvent describing the vetoed change.
9.57 + */
9.58 + public PropertyChangeEvent getPropertyChangeEvent() {
9.59 + return evt;
9.60 + }
9.61 +
9.62 + /**
9.63 + * A PropertyChangeEvent describing the vetoed change.
9.64 + * @serial
9.65 + */
9.66 + private PropertyChangeEvent evt;
9.67 +}
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/emul/compact/src/main/java/java/beans/VetoableChangeListener.java Mon Feb 04 09:37:56 2013 +0100
10.3 @@ -0,0 +1,44 @@
10.4 +/*
10.5 + * Copyright (c) 1996, 1997, Oracle and/or its affiliates. All rights reserved.
10.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10.7 + *
10.8 + * This code is free software; you can redistribute it and/or modify it
10.9 + * under the terms of the GNU General Public License version 2 only, as
10.10 + * published by the Free Software Foundation. Oracle designates this
10.11 + * particular file as subject to the "Classpath" exception as provided
10.12 + * by Oracle in the LICENSE file that accompanied this code.
10.13 + *
10.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
10.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10.17 + * version 2 for more details (a copy is included in the LICENSE file that
10.18 + * accompanied this code).
10.19 + *
10.20 + * You should have received a copy of the GNU General Public License version
10.21 + * 2 along with this work; if not, write to the Free Software Foundation,
10.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
10.23 + *
10.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
10.25 + * or visit www.oracle.com if you need additional information or have any
10.26 + * questions.
10.27 + */
10.28 +
10.29 +package java.beans;
10.30 +
10.31 +/**
10.32 + * A VetoableChange event gets fired whenever a bean changes a "constrained"
10.33 + * property. You can register a VetoableChangeListener with a source bean
10.34 + * so as to be notified of any constrained property updates.
10.35 + */
10.36 +public interface VetoableChangeListener extends java.util.EventListener {
10.37 + /**
10.38 + * This method gets called when a constrained property is changed.
10.39 + *
10.40 + * @param evt a <code>PropertyChangeEvent</code> object describing the
10.41 + * event source and the property that has changed.
10.42 + * @exception PropertyVetoException if the recipient wishes the property
10.43 + * change to be rolled back.
10.44 + */
10.45 + void vetoableChange(PropertyChangeEvent evt)
10.46 + throws PropertyVetoException;
10.47 +}
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/emul/compact/src/main/java/java/beans/VetoableChangeListenerProxy.java Mon Feb 04 09:37:56 2013 +0100
11.3 @@ -0,0 +1,84 @@
11.4 +/*
11.5 + * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
11.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
11.7 + *
11.8 + * This code is free software; you can redistribute it and/or modify it
11.9 + * under the terms of the GNU General Public License version 2 only, as
11.10 + * published by the Free Software Foundation. Oracle designates this
11.11 + * particular file as subject to the "Classpath" exception as provided
11.12 + * by Oracle in the LICENSE file that accompanied this code.
11.13 + *
11.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
11.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11.17 + * version 2 for more details (a copy is included in the LICENSE file that
11.18 + * accompanied this code).
11.19 + *
11.20 + * You should have received a copy of the GNU General Public License version
11.21 + * 2 along with this work; if not, write to the Free Software Foundation,
11.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
11.23 + *
11.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
11.25 + * or visit www.oracle.com if you need additional information or have any
11.26 + * questions.
11.27 + */
11.28 +
11.29 +package java.beans;
11.30 +
11.31 +import java.util.EventListenerProxy;
11.32 +
11.33 +/**
11.34 + * A class which extends the {@code EventListenerProxy}
11.35 + * specifically for adding a {@code VetoableChangeListener}
11.36 + * with a "constrained" property.
11.37 + * Instances of this class can be added
11.38 + * as {@code VetoableChangeListener}s to a bean
11.39 + * which supports firing vetoable change events.
11.40 + * <p>
11.41 + * If the object has a {@code getVetoableChangeListeners} method
11.42 + * then the array returned could be a mixture of {@code VetoableChangeListener}
11.43 + * and {@code VetoableChangeListenerProxy} objects.
11.44 + *
11.45 + * @see java.util.EventListenerProxy
11.46 + * @see VetoableChangeSupport#getVetoableChangeListeners
11.47 + * @since 1.4
11.48 + */
11.49 +public class VetoableChangeListenerProxy
11.50 + extends EventListenerProxy<VetoableChangeListener>
11.51 + implements VetoableChangeListener {
11.52 +
11.53 + private final String propertyName;
11.54 +
11.55 + /**
11.56 + * Constructor which binds the {@code VetoableChangeListener}
11.57 + * to a specific property.
11.58 + *
11.59 + * @param propertyName the name of the property to listen on
11.60 + * @param listener the listener object
11.61 + */
11.62 + public VetoableChangeListenerProxy(String propertyName, VetoableChangeListener listener) {
11.63 + super(listener);
11.64 + this.propertyName = propertyName;
11.65 + }
11.66 +
11.67 + /**
11.68 + * Forwards the property change event to the listener delegate.
11.69 + *
11.70 + * @param event the property change event
11.71 + *
11.72 + * @exception PropertyVetoException if the recipient wishes the property
11.73 + * change to be rolled back
11.74 + */
11.75 + public void vetoableChange(PropertyChangeEvent event) throws PropertyVetoException{
11.76 + getListener().vetoableChange(event);
11.77 + }
11.78 +
11.79 + /**
11.80 + * Returns the name of the named property associated with the listener.
11.81 + *
11.82 + * @return the name of the named property associated with the listener
11.83 + */
11.84 + public String getPropertyName() {
11.85 + return this.propertyName;
11.86 + }
11.87 +}
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/emul/compact/src/main/java/java/beans/VetoableChangeSupport.java Mon Feb 04 09:37:56 2013 +0100
12.3 @@ -0,0 +1,526 @@
12.4 +/*
12.5 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
12.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
12.7 + *
12.8 + * This code is free software; you can redistribute it and/or modify it
12.9 + * under the terms of the GNU General Public License version 2 only, as
12.10 + * published by the Free Software Foundation. Oracle designates this
12.11 + * particular file as subject to the "Classpath" exception as provided
12.12 + * by Oracle in the LICENSE file that accompanied this code.
12.13 + *
12.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
12.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12.17 + * version 2 for more details (a copy is included in the LICENSE file that
12.18 + * accompanied this code).
12.19 + *
12.20 + * You should have received a copy of the GNU General Public License version
12.21 + * 2 along with this work; if not, write to the Free Software Foundation,
12.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
12.23 + *
12.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
12.25 + * or visit www.oracle.com if you need additional information or have any
12.26 + * questions.
12.27 + */
12.28 +package java.beans;
12.29 +
12.30 +import java.io.Serializable;
12.31 +import java.io.ObjectStreamField;
12.32 +import java.io.ObjectOutputStream;
12.33 +import java.io.ObjectInputStream;
12.34 +import java.io.IOException;
12.35 +import java.util.Hashtable;
12.36 +import java.util.Map.Entry;
12.37 +import org.apidesign.bck2brwsr.emul.lang.System;
12.38 +
12.39 +/**
12.40 + * This is a utility class that can be used by beans that support constrained
12.41 + * properties. It manages a list of listeners and dispatches
12.42 + * {@link PropertyChangeEvent}s to them. You can use an instance of this class
12.43 + * as a member field of your bean and delegate these types of work to it.
12.44 + * The {@link VetoableChangeListener} can be registered for all properties
12.45 + * or for a property specified by name.
12.46 + * <p>
12.47 + * Here is an example of {@code VetoableChangeSupport} usage that follows
12.48 + * the rules and recommendations laid out in the JavaBeans™ specification:
12.49 + * <pre>
12.50 + * public class MyBean {
12.51 + * private final VetoableChangeSupport vcs = new VetoableChangeSupport(this);
12.52 + *
12.53 + * public void addVetoableChangeListener(VetoableChangeListener listener) {
12.54 + * this.vcs.addVetoableChangeListener(listener);
12.55 + * }
12.56 + *
12.57 + * public void removeVetoableChangeListener(VetoableChangeListener listener) {
12.58 + * this.vcs.removeVetoableChangeListener(listener);
12.59 + * }
12.60 + *
12.61 + * private String value;
12.62 + *
12.63 + * public String getValue() {
12.64 + * return this.value;
12.65 + * }
12.66 + *
12.67 + * public void setValue(String newValue) throws PropertyVetoException {
12.68 + * String oldValue = this.value;
12.69 + * this.vcs.fireVetoableChange("value", oldValue, newValue);
12.70 + * this.value = newValue;
12.71 + * }
12.72 + *
12.73 + * [...]
12.74 + * }
12.75 + * </pre>
12.76 + * <p>
12.77 + * A {@code VetoableChangeSupport} instance is thread-safe.
12.78 + * <p>
12.79 + * This class is serializable. When it is serialized it will save
12.80 + * (and restore) any listeners that are themselves serializable. Any
12.81 + * non-serializable listeners will be skipped during serialization.
12.82 + *
12.83 + * @see PropertyChangeSupport
12.84 + */
12.85 +public class VetoableChangeSupport implements Serializable {
12.86 + private VetoableChangeListenerMap map = new VetoableChangeListenerMap();
12.87 +
12.88 + /**
12.89 + * Constructs a <code>VetoableChangeSupport</code> object.
12.90 + *
12.91 + * @param sourceBean The bean to be given as the source for any events.
12.92 + */
12.93 + public VetoableChangeSupport(Object sourceBean) {
12.94 + if (sourceBean == null) {
12.95 + throw new NullPointerException();
12.96 + }
12.97 + source = sourceBean;
12.98 + }
12.99 +
12.100 + /**
12.101 + * Add a VetoableChangeListener to the listener list.
12.102 + * The listener is registered for all properties.
12.103 + * The same listener object may be added more than once, and will be called
12.104 + * as many times as it is added.
12.105 + * If <code>listener</code> is null, no exception is thrown and no action
12.106 + * is taken.
12.107 + *
12.108 + * @param listener The VetoableChangeListener to be added
12.109 + */
12.110 + public void addVetoableChangeListener(VetoableChangeListener listener) {
12.111 + if (listener == null) {
12.112 + return;
12.113 + }
12.114 + if (listener instanceof VetoableChangeListenerProxy) {
12.115 + VetoableChangeListenerProxy proxy =
12.116 + (VetoableChangeListenerProxy)listener;
12.117 + // Call two argument add method.
12.118 + addVetoableChangeListener(proxy.getPropertyName(),
12.119 + proxy.getListener());
12.120 + } else {
12.121 + this.map.add(null, listener);
12.122 + }
12.123 + }
12.124 +
12.125 + /**
12.126 + * Remove a VetoableChangeListener from the listener list.
12.127 + * This removes a VetoableChangeListener that was registered
12.128 + * for all properties.
12.129 + * If <code>listener</code> was added more than once to the same event
12.130 + * source, it will be notified one less time after being removed.
12.131 + * If <code>listener</code> is null, or was never added, no exception is
12.132 + * thrown and no action is taken.
12.133 + *
12.134 + * @param listener The VetoableChangeListener to be removed
12.135 + */
12.136 + public void removeVetoableChangeListener(VetoableChangeListener listener) {
12.137 + if (listener == null) {
12.138 + return;
12.139 + }
12.140 + if (listener instanceof VetoableChangeListenerProxy) {
12.141 + VetoableChangeListenerProxy proxy =
12.142 + (VetoableChangeListenerProxy)listener;
12.143 + // Call two argument remove method.
12.144 + removeVetoableChangeListener(proxy.getPropertyName(),
12.145 + proxy.getListener());
12.146 + } else {
12.147 + this.map.remove(null, listener);
12.148 + }
12.149 + }
12.150 +
12.151 + /**
12.152 + * Returns an array of all the listeners that were added to the
12.153 + * VetoableChangeSupport object with addVetoableChangeListener().
12.154 + * <p>
12.155 + * If some listeners have been added with a named property, then
12.156 + * the returned array will be a mixture of VetoableChangeListeners
12.157 + * and <code>VetoableChangeListenerProxy</code>s. If the calling
12.158 + * method is interested in distinguishing the listeners then it must
12.159 + * test each element to see if it's a
12.160 + * <code>VetoableChangeListenerProxy</code>, perform the cast, and examine
12.161 + * the parameter.
12.162 + *
12.163 + * <pre>
12.164 + * VetoableChangeListener[] listeners = bean.getVetoableChangeListeners();
12.165 + * for (int i = 0; i < listeners.length; i++) {
12.166 + * if (listeners[i] instanceof VetoableChangeListenerProxy) {
12.167 + * VetoableChangeListenerProxy proxy =
12.168 + * (VetoableChangeListenerProxy)listeners[i];
12.169 + * if (proxy.getPropertyName().equals("foo")) {
12.170 + * // proxy is a VetoableChangeListener which was associated
12.171 + * // with the property named "foo"
12.172 + * }
12.173 + * }
12.174 + * }
12.175 + *</pre>
12.176 + *
12.177 + * @see VetoableChangeListenerProxy
12.178 + * @return all of the <code>VetoableChangeListeners</code> added or an
12.179 + * empty array if no listeners have been added
12.180 + * @since 1.4
12.181 + */
12.182 + public VetoableChangeListener[] getVetoableChangeListeners(){
12.183 + return this.map.getListeners();
12.184 + }
12.185 +
12.186 + /**
12.187 + * Add a VetoableChangeListener for a specific property. The listener
12.188 + * will be invoked only when a call on fireVetoableChange names that
12.189 + * specific property.
12.190 + * The same listener object may be added more than once. For each
12.191 + * property, the listener will be invoked the number of times it was added
12.192 + * for that property.
12.193 + * If <code>propertyName</code> or <code>listener</code> is null, no
12.194 + * exception is thrown and no action is taken.
12.195 + *
12.196 + * @param propertyName The name of the property to listen on.
12.197 + * @param listener The VetoableChangeListener to be added
12.198 + */
12.199 + public void addVetoableChangeListener(
12.200 + String propertyName,
12.201 + VetoableChangeListener listener) {
12.202 + if (listener == null || propertyName == null) {
12.203 + return;
12.204 + }
12.205 + listener = this.map.extract(listener);
12.206 + if (listener != null) {
12.207 + this.map.add(propertyName, listener);
12.208 + }
12.209 + }
12.210 +
12.211 + /**
12.212 + * Remove a VetoableChangeListener for a specific property.
12.213 + * If <code>listener</code> was added more than once to the same event
12.214 + * source for the specified property, it will be notified one less time
12.215 + * after being removed.
12.216 + * If <code>propertyName</code> is null, no exception is thrown and no
12.217 + * action is taken.
12.218 + * If <code>listener</code> is null, or was never added for the specified
12.219 + * property, no exception is thrown and no action is taken.
12.220 + *
12.221 + * @param propertyName The name of the property that was listened on.
12.222 + * @param listener The VetoableChangeListener to be removed
12.223 + */
12.224 + public void removeVetoableChangeListener(
12.225 + String propertyName,
12.226 + VetoableChangeListener listener) {
12.227 + if (listener == null || propertyName == null) {
12.228 + return;
12.229 + }
12.230 + listener = this.map.extract(listener);
12.231 + if (listener != null) {
12.232 + this.map.remove(propertyName, listener);
12.233 + }
12.234 + }
12.235 +
12.236 + /**
12.237 + * Returns an array of all the listeners which have been associated
12.238 + * with the named property.
12.239 + *
12.240 + * @param propertyName The name of the property being listened to
12.241 + * @return all the <code>VetoableChangeListeners</code> associated with
12.242 + * the named property. If no such listeners have been added,
12.243 + * or if <code>propertyName</code> is null, an empty array is
12.244 + * returned.
12.245 + * @since 1.4
12.246 + */
12.247 + public VetoableChangeListener[] getVetoableChangeListeners(String propertyName) {
12.248 + return this.map.getListeners(propertyName);
12.249 + }
12.250 +
12.251 + /**
12.252 + * Reports a constrained property update to listeners
12.253 + * that have been registered to track updates of
12.254 + * all properties or a property with the specified name.
12.255 + * <p>
12.256 + * Any listener can throw a {@code PropertyVetoException} to veto the update.
12.257 + * If one of the listeners vetoes the update, this method passes
12.258 + * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
12.259 + * to all listeners that already confirmed this update
12.260 + * and throws the {@code PropertyVetoException} again.
12.261 + * <p>
12.262 + * No event is fired if old and new values are equal and non-null.
12.263 + * <p>
12.264 + * This is merely a convenience wrapper around the more general
12.265 + * {@link #fireVetoableChange(PropertyChangeEvent)} method.
12.266 + *
12.267 + * @param propertyName the programmatic name of the property that is about to change
12.268 + * @param oldValue the old value of the property
12.269 + * @param newValue the new value of the property
12.270 + * @throws PropertyVetoException if one of listeners vetoes the property update
12.271 + */
12.272 + public void fireVetoableChange(String propertyName, Object oldValue, Object newValue)
12.273 + throws PropertyVetoException {
12.274 + if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
12.275 + fireVetoableChange(new PropertyChangeEvent(this.source, propertyName, oldValue, newValue));
12.276 + }
12.277 + }
12.278 +
12.279 + /**
12.280 + * Reports an integer constrained property update to listeners
12.281 + * that have been registered to track updates of
12.282 + * all properties or a property with the specified name.
12.283 + * <p>
12.284 + * Any listener can throw a {@code PropertyVetoException} to veto the update.
12.285 + * If one of the listeners vetoes the update, this method passes
12.286 + * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
12.287 + * to all listeners that already confirmed this update
12.288 + * and throws the {@code PropertyVetoException} again.
12.289 + * <p>
12.290 + * No event is fired if old and new values are equal.
12.291 + * <p>
12.292 + * This is merely a convenience wrapper around the more general
12.293 + * {@link #fireVetoableChange(String, Object, Object)} method.
12.294 + *
12.295 + * @param propertyName the programmatic name of the property that is about to change
12.296 + * @param oldValue the old value of the property
12.297 + * @param newValue the new value of the property
12.298 + * @throws PropertyVetoException if one of listeners vetoes the property update
12.299 + */
12.300 + public void fireVetoableChange(String propertyName, int oldValue, int newValue)
12.301 + throws PropertyVetoException {
12.302 + if (oldValue != newValue) {
12.303 + fireVetoableChange(propertyName, Integer.valueOf(oldValue), Integer.valueOf(newValue));
12.304 + }
12.305 + }
12.306 +
12.307 + /**
12.308 + * Reports a boolean constrained property update to listeners
12.309 + * that have been registered to track updates of
12.310 + * all properties or a property with the specified name.
12.311 + * <p>
12.312 + * Any listener can throw a {@code PropertyVetoException} to veto the update.
12.313 + * If one of the listeners vetoes the update, this method passes
12.314 + * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
12.315 + * to all listeners that already confirmed this update
12.316 + * and throws the {@code PropertyVetoException} again.
12.317 + * <p>
12.318 + * No event is fired if old and new values are equal.
12.319 + * <p>
12.320 + * This is merely a convenience wrapper around the more general
12.321 + * {@link #fireVetoableChange(String, Object, Object)} method.
12.322 + *
12.323 + * @param propertyName the programmatic name of the property that is about to change
12.324 + * @param oldValue the old value of the property
12.325 + * @param newValue the new value of the property
12.326 + * @throws PropertyVetoException if one of listeners vetoes the property update
12.327 + */
12.328 + public void fireVetoableChange(String propertyName, boolean oldValue, boolean newValue)
12.329 + throws PropertyVetoException {
12.330 + if (oldValue != newValue) {
12.331 + fireVetoableChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
12.332 + }
12.333 + }
12.334 +
12.335 + /**
12.336 + * Fires a property change event to listeners
12.337 + * that have been registered to track updates of
12.338 + * all properties or a property with the specified name.
12.339 + * <p>
12.340 + * Any listener can throw a {@code PropertyVetoException} to veto the update.
12.341 + * If one of the listeners vetoes the update, this method passes
12.342 + * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
12.343 + * to all listeners that already confirmed this update
12.344 + * and throws the {@code PropertyVetoException} again.
12.345 + * <p>
12.346 + * No event is fired if the given event's old and new values are equal and non-null.
12.347 + *
12.348 + * @param event the {@code PropertyChangeEvent} to be fired
12.349 + * @throws PropertyVetoException if one of listeners vetoes the property update
12.350 + */
12.351 + public void fireVetoableChange(PropertyChangeEvent event)
12.352 + throws PropertyVetoException {
12.353 + Object oldValue = event.getOldValue();
12.354 + Object newValue = event.getNewValue();
12.355 + if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
12.356 + String name = event.getPropertyName();
12.357 +
12.358 + VetoableChangeListener[] common = this.map.get(null);
12.359 + VetoableChangeListener[] named = (name != null)
12.360 + ? this.map.get(name)
12.361 + : null;
12.362 +
12.363 + VetoableChangeListener[] listeners;
12.364 + if (common == null) {
12.365 + listeners = named;
12.366 + }
12.367 + else if (named == null) {
12.368 + listeners = common;
12.369 + }
12.370 + else {
12.371 + listeners = new VetoableChangeListener[common.length + named.length];
12.372 + System.arraycopy(common, 0, listeners, 0, common.length);
12.373 + System.arraycopy(named, 0, listeners, common.length, named.length);
12.374 + }
12.375 + if (listeners != null) {
12.376 + int current = 0;
12.377 + try {
12.378 + while (current < listeners.length) {
12.379 + listeners[current].vetoableChange(event);
12.380 + current++;
12.381 + }
12.382 + }
12.383 + catch (PropertyVetoException veto) {
12.384 + event = new PropertyChangeEvent(this.source, name, newValue, oldValue);
12.385 + for (int i = 0; i < current; i++) {
12.386 + try {
12.387 + listeners[i].vetoableChange(event);
12.388 + }
12.389 + catch (PropertyVetoException exception) {
12.390 + // ignore exceptions that occur during rolling back
12.391 + }
12.392 + }
12.393 + throw veto; // rethrow the veto exception
12.394 + }
12.395 + }
12.396 + }
12.397 + }
12.398 +
12.399 + /**
12.400 + * Check if there are any listeners for a specific property, including
12.401 + * those registered on all properties. If <code>propertyName</code>
12.402 + * is null, only check for listeners registered on all properties.
12.403 + *
12.404 + * @param propertyName the property name.
12.405 + * @return true if there are one or more listeners for the given property
12.406 + */
12.407 + public boolean hasListeners(String propertyName) {
12.408 + return this.map.hasListeners(propertyName);
12.409 + }
12.410 +
12.411 + /**
12.412 + * @serialData Null terminated list of <code>VetoableChangeListeners</code>.
12.413 + * <p>
12.414 + * At serialization time we skip non-serializable listeners and
12.415 + * only serialize the serializable listeners.
12.416 + */
12.417 + private void writeObject(ObjectOutputStream s) throws IOException {
12.418 + Hashtable<String, VetoableChangeSupport> children = null;
12.419 + VetoableChangeListener[] listeners = null;
12.420 + synchronized (this.map) {
12.421 + for (Entry<String, VetoableChangeListener[]> entry : this.map.getEntries()) {
12.422 + String property = entry.getKey();
12.423 + if (property == null) {
12.424 + listeners = entry.getValue();
12.425 + } else {
12.426 + if (children == null) {
12.427 + children = new Hashtable<String, VetoableChangeSupport>();
12.428 + }
12.429 + VetoableChangeSupport vcs = new VetoableChangeSupport(this.source);
12.430 + vcs.map.set(null, entry.getValue());
12.431 + children.put(property, vcs);
12.432 + }
12.433 + }
12.434 + }
12.435 + ObjectOutputStream.PutField fields = s.putFields();
12.436 + fields.put("children", children);
12.437 + fields.put("source", this.source);
12.438 + fields.put("vetoableChangeSupportSerializedDataVersion", 2);
12.439 + s.writeFields();
12.440 +
12.441 + if (listeners != null) {
12.442 + for (VetoableChangeListener l : listeners) {
12.443 + if (l instanceof Serializable) {
12.444 + s.writeObject(l);
12.445 + }
12.446 + }
12.447 + }
12.448 + s.writeObject(null);
12.449 + }
12.450 +
12.451 + private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
12.452 + this.map = new VetoableChangeListenerMap();
12.453 +
12.454 + ObjectInputStream.GetField fields = s.readFields();
12.455 +
12.456 + Hashtable<String, VetoableChangeSupport> children = (Hashtable<String, VetoableChangeSupport>) fields.get("children", null);
12.457 + this.source = fields.get("source", null);
12.458 + fields.get("vetoableChangeSupportSerializedDataVersion", 2);
12.459 +
12.460 + Object listenerOrNull;
12.461 + while (null != (listenerOrNull = s.readObject())) {
12.462 + this.map.add(null, (VetoableChangeListener)listenerOrNull);
12.463 + }
12.464 + if (children != null) {
12.465 + for (Entry<String, VetoableChangeSupport> entry : children.entrySet()) {
12.466 + for (VetoableChangeListener listener : entry.getValue().getVetoableChangeListeners()) {
12.467 + this.map.add(entry.getKey(), listener);
12.468 + }
12.469 + }
12.470 + }
12.471 + }
12.472 +
12.473 + /**
12.474 + * The object to be provided as the "source" for any generated events.
12.475 + */
12.476 + private Object source;
12.477 +
12.478 + /**
12.479 + * @serialField children Hashtable
12.480 + * @serialField source Object
12.481 + * @serialField vetoableChangeSupportSerializedDataVersion int
12.482 + */
12.483 + private static final ObjectStreamField[] serialPersistentFields = {
12.484 + new ObjectStreamField("children", Hashtable.class),
12.485 + new ObjectStreamField("source", Object.class),
12.486 + new ObjectStreamField("vetoableChangeSupportSerializedDataVersion", Integer.TYPE)
12.487 + };
12.488 +
12.489 + /**
12.490 + * Serialization version ID, so we're compatible with JDK 1.1
12.491 + */
12.492 + static final long serialVersionUID = -5090210921595982017L;
12.493 +
12.494 + /**
12.495 + * This is a {@link ChangeListenerMap ChangeListenerMap} implementation
12.496 + * that works with {@link VetoableChangeListener VetoableChangeListener} objects.
12.497 + */
12.498 + private static final class VetoableChangeListenerMap extends ChangeListenerMap<VetoableChangeListener> {
12.499 + private static final VetoableChangeListener[] EMPTY = {};
12.500 +
12.501 + /**
12.502 + * Creates an array of {@link VetoableChangeListener VetoableChangeListener} objects.
12.503 + * This method uses the same instance of the empty array
12.504 + * when {@code length} equals {@code 0}.
12.505 + *
12.506 + * @param length the array length
12.507 + * @return an array with specified length
12.508 + */
12.509 + @Override
12.510 + protected VetoableChangeListener[] newArray(int length) {
12.511 + return (0 < length)
12.512 + ? new VetoableChangeListener[length]
12.513 + : EMPTY;
12.514 + }
12.515 +
12.516 + /**
12.517 + * Creates a {@link VetoableChangeListenerProxy VetoableChangeListenerProxy}
12.518 + * object for the specified property.
12.519 + *
12.520 + * @param name the name of the property to listen on
12.521 + * @param listener the listener to process events
12.522 + * @return a {@code VetoableChangeListenerProxy} object
12.523 + */
12.524 + @Override
12.525 + protected VetoableChangeListener newProxy(String name, VetoableChangeListener listener) {
12.526 + return new VetoableChangeListenerProxy(name, listener);
12.527 + }
12.528 + }
12.529 +}
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/emul/compact/src/main/java/java/io/Bits.java Mon Feb 04 09:37:56 2013 +0100
13.3 @@ -0,0 +1,123 @@
13.4 +/*
13.5 + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
13.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
13.7 + *
13.8 + * This code is free software; you can redistribute it and/or modify it
13.9 + * under the terms of the GNU General Public License version 2 only, as
13.10 + * published by the Free Software Foundation. Oracle designates this
13.11 + * particular file as subject to the "Classpath" exception as provided
13.12 + * by Oracle in the LICENSE file that accompanied this code.
13.13 + *
13.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
13.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13.17 + * version 2 for more details (a copy is included in the LICENSE file that
13.18 + * accompanied this code).
13.19 + *
13.20 + * You should have received a copy of the GNU General Public License version
13.21 + * 2 along with this work; if not, write to the Free Software Foundation,
13.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
13.23 + *
13.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
13.25 + * or visit www.oracle.com if you need additional information or have any
13.26 + * questions.
13.27 + */
13.28 +
13.29 +package java.io;
13.30 +
13.31 +/**
13.32 + * Utility methods for packing/unpacking primitive values in/out of byte arrays
13.33 + * using big-endian byte ordering.
13.34 + */
13.35 +class Bits {
13.36 +
13.37 + /*
13.38 + * Methods for unpacking primitive values from byte arrays starting at
13.39 + * given offsets.
13.40 + */
13.41 +
13.42 + static boolean getBoolean(byte[] b, int off) {
13.43 + return b[off] != 0;
13.44 + }
13.45 +
13.46 + static char getChar(byte[] b, int off) {
13.47 + return (char) ((b[off + 1] & 0xFF) +
13.48 + (b[off] << 8));
13.49 + }
13.50 +
13.51 + static short getShort(byte[] b, int off) {
13.52 + return (short) ((b[off + 1] & 0xFF) +
13.53 + (b[off] << 8));
13.54 + }
13.55 +
13.56 + static int getInt(byte[] b, int off) {
13.57 + return ((b[off + 3] & 0xFF) ) +
13.58 + ((b[off + 2] & 0xFF) << 8) +
13.59 + ((b[off + 1] & 0xFF) << 16) +
13.60 + ((b[off ] ) << 24);
13.61 + }
13.62 +
13.63 + static float getFloat(byte[] b, int off) {
13.64 + return Float.intBitsToFloat(getInt(b, off));
13.65 + }
13.66 +
13.67 + static long getLong(byte[] b, int off) {
13.68 + return ((b[off + 7] & 0xFFL) ) +
13.69 + ((b[off + 6] & 0xFFL) << 8) +
13.70 + ((b[off + 5] & 0xFFL) << 16) +
13.71 + ((b[off + 4] & 0xFFL) << 24) +
13.72 + ((b[off + 3] & 0xFFL) << 32) +
13.73 + ((b[off + 2] & 0xFFL) << 40) +
13.74 + ((b[off + 1] & 0xFFL) << 48) +
13.75 + (((long) b[off]) << 56);
13.76 + }
13.77 +
13.78 + static double getDouble(byte[] b, int off) {
13.79 + return Double.longBitsToDouble(getLong(b, off));
13.80 + }
13.81 +
13.82 + /*
13.83 + * Methods for packing primitive values into byte arrays starting at given
13.84 + * offsets.
13.85 + */
13.86 +
13.87 + static void putBoolean(byte[] b, int off, boolean val) {
13.88 + b[off] = (byte) (val ? 1 : 0);
13.89 + }
13.90 +
13.91 + static void putChar(byte[] b, int off, char val) {
13.92 + b[off + 1] = (byte) (val );
13.93 + b[off ] = (byte) (val >>> 8);
13.94 + }
13.95 +
13.96 + static void putShort(byte[] b, int off, short val) {
13.97 + b[off + 1] = (byte) (val );
13.98 + b[off ] = (byte) (val >>> 8);
13.99 + }
13.100 +
13.101 + static void putInt(byte[] b, int off, int val) {
13.102 + b[off + 3] = (byte) (val );
13.103 + b[off + 2] = (byte) (val >>> 8);
13.104 + b[off + 1] = (byte) (val >>> 16);
13.105 + b[off ] = (byte) (val >>> 24);
13.106 + }
13.107 +
13.108 + static void putFloat(byte[] b, int off, float val) {
13.109 + putInt(b, off, Float.floatToIntBits(val));
13.110 + }
13.111 +
13.112 + static void putLong(byte[] b, int off, long val) {
13.113 + b[off + 7] = (byte) (val );
13.114 + b[off + 6] = (byte) (val >>> 8);
13.115 + b[off + 5] = (byte) (val >>> 16);
13.116 + b[off + 4] = (byte) (val >>> 24);
13.117 + b[off + 3] = (byte) (val >>> 32);
13.118 + b[off + 2] = (byte) (val >>> 40);
13.119 + b[off + 1] = (byte) (val >>> 48);
13.120 + b[off ] = (byte) (val >>> 56);
13.121 + }
13.122 +
13.123 + static void putDouble(byte[] b, int off, double val) {
13.124 + putLong(b, off, Double.doubleToLongBits(val));
13.125 + }
13.126 +}
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/emul/compact/src/main/java/java/io/DataOutput.java Mon Feb 04 09:37:56 2013 +0100
14.3 @@ -0,0 +1,354 @@
14.4 +/*
14.5 + * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved.
14.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
14.7 + *
14.8 + * This code is free software; you can redistribute it and/or modify it
14.9 + * under the terms of the GNU General Public License version 2 only, as
14.10 + * published by the Free Software Foundation. Oracle designates this
14.11 + * particular file as subject to the "Classpath" exception as provided
14.12 + * by Oracle in the LICENSE file that accompanied this code.
14.13 + *
14.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
14.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14.17 + * version 2 for more details (a copy is included in the LICENSE file that
14.18 + * accompanied this code).
14.19 + *
14.20 + * You should have received a copy of the GNU General Public License version
14.21 + * 2 along with this work; if not, write to the Free Software Foundation,
14.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
14.23 + *
14.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
14.25 + * or visit www.oracle.com if you need additional information or have any
14.26 + * questions.
14.27 + */
14.28 +
14.29 +package java.io;
14.30 +
14.31 +/**
14.32 + * The <code>DataOutput</code> interface provides
14.33 + * for converting data from any of the Java
14.34 + * primitive types to a series of bytes and
14.35 + * writing these bytes to a binary stream.
14.36 + * There is also a facility for converting
14.37 + * a <code>String</code> into
14.38 + * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
14.39 + * format and writing the resulting series
14.40 + * of bytes.
14.41 + * <p>
14.42 + * For all the methods in this interface that
14.43 + * write bytes, it is generally true that if
14.44 + * a byte cannot be written for any reason,
14.45 + * an <code>IOException</code> is thrown.
14.46 + *
14.47 + * @author Frank Yellin
14.48 + * @see java.io.DataInput
14.49 + * @see java.io.DataOutputStream
14.50 + * @since JDK1.0
14.51 + */
14.52 +public
14.53 +interface DataOutput {
14.54 + /**
14.55 + * Writes to the output stream the eight
14.56 + * low-order bits of the argument <code>b</code>.
14.57 + * The 24 high-order bits of <code>b</code>
14.58 + * are ignored.
14.59 + *
14.60 + * @param b the byte to be written.
14.61 + * @throws IOException if an I/O error occurs.
14.62 + */
14.63 + void write(int b) throws IOException;
14.64 +
14.65 + /**
14.66 + * Writes to the output stream all the bytes in array <code>b</code>.
14.67 + * If <code>b</code> is <code>null</code>,
14.68 + * a <code>NullPointerException</code> is thrown.
14.69 + * If <code>b.length</code> is zero, then
14.70 + * no bytes are written. Otherwise, the byte
14.71 + * <code>b[0]</code> is written first, then
14.72 + * <code>b[1]</code>, and so on; the last byte
14.73 + * written is <code>b[b.length-1]</code>.
14.74 + *
14.75 + * @param b the data.
14.76 + * @throws IOException if an I/O error occurs.
14.77 + */
14.78 + void write(byte b[]) throws IOException;
14.79 +
14.80 + /**
14.81 + * Writes <code>len</code> bytes from array
14.82 + * <code>b</code>, in order, to
14.83 + * the output stream. If <code>b</code>
14.84 + * is <code>null</code>, a <code>NullPointerException</code>
14.85 + * is thrown. If <code>off</code> is negative,
14.86 + * or <code>len</code> is negative, or <code>off+len</code>
14.87 + * is greater than the length of the array
14.88 + * <code>b</code>, then an <code>IndexOutOfBoundsException</code>
14.89 + * is thrown. If <code>len</code> is zero,
14.90 + * then no bytes are written. Otherwise, the
14.91 + * byte <code>b[off]</code> is written first,
14.92 + * then <code>b[off+1]</code>, and so on; the
14.93 + * last byte written is <code>b[off+len-1]</code>.
14.94 + *
14.95 + * @param b the data.
14.96 + * @param off the start offset in the data.
14.97 + * @param len the number of bytes to write.
14.98 + * @throws IOException if an I/O error occurs.
14.99 + */
14.100 + void write(byte b[], int off, int len) throws IOException;
14.101 +
14.102 + /**
14.103 + * Writes a <code>boolean</code> value to this output stream.
14.104 + * If the argument <code>v</code>
14.105 + * is <code>true</code>, the value <code>(byte)1</code>
14.106 + * is written; if <code>v</code> is <code>false</code>,
14.107 + * the value <code>(byte)0</code> is written.
14.108 + * The byte written by this method may
14.109 + * be read by the <code>readBoolean</code>
14.110 + * method of interface <code>DataInput</code>,
14.111 + * which will then return a <code>boolean</code>
14.112 + * equal to <code>v</code>.
14.113 + *
14.114 + * @param v the boolean to be written.
14.115 + * @throws IOException if an I/O error occurs.
14.116 + */
14.117 + void writeBoolean(boolean v) throws IOException;
14.118 +
14.119 + /**
14.120 + * Writes to the output stream the eight low-
14.121 + * order bits of the argument <code>v</code>.
14.122 + * The 24 high-order bits of <code>v</code>
14.123 + * are ignored. (This means that <code>writeByte</code>
14.124 + * does exactly the same thing as <code>write</code>
14.125 + * for an integer argument.) The byte written
14.126 + * by this method may be read by the <code>readByte</code>
14.127 + * method of interface <code>DataInput</code>,
14.128 + * which will then return a <code>byte</code>
14.129 + * equal to <code>(byte)v</code>.
14.130 + *
14.131 + * @param v the byte value to be written.
14.132 + * @throws IOException if an I/O error occurs.
14.133 + */
14.134 + void writeByte(int v) throws IOException;
14.135 +
14.136 + /**
14.137 + * Writes two bytes to the output
14.138 + * stream to represent the value of the argument.
14.139 + * The byte values to be written, in the order
14.140 + * shown, are: <p>
14.141 + * <pre><code>
14.142 + * (byte)(0xff & (v >> 8))
14.143 + * (byte)(0xff & v)
14.144 + * </code> </pre> <p>
14.145 + * The bytes written by this method may be
14.146 + * read by the <code>readShort</code> method
14.147 + * of interface <code>DataInput</code> , which
14.148 + * will then return a <code>short</code> equal
14.149 + * to <code>(short)v</code>.
14.150 + *
14.151 + * @param v the <code>short</code> value to be written.
14.152 + * @throws IOException if an I/O error occurs.
14.153 + */
14.154 + void writeShort(int v) throws IOException;
14.155 +
14.156 + /**
14.157 + * Writes a <code>char</code> value, which
14.158 + * is comprised of two bytes, to the
14.159 + * output stream.
14.160 + * The byte values to be written, in the order
14.161 + * shown, are:
14.162 + * <p><pre><code>
14.163 + * (byte)(0xff & (v >> 8))
14.164 + * (byte)(0xff & v)
14.165 + * </code></pre><p>
14.166 + * The bytes written by this method may be
14.167 + * read by the <code>readChar</code> method
14.168 + * of interface <code>DataInput</code> , which
14.169 + * will then return a <code>char</code> equal
14.170 + * to <code>(char)v</code>.
14.171 + *
14.172 + * @param v the <code>char</code> value to be written.
14.173 + * @throws IOException if an I/O error occurs.
14.174 + */
14.175 + void writeChar(int v) throws IOException;
14.176 +
14.177 + /**
14.178 + * Writes an <code>int</code> value, which is
14.179 + * comprised of four bytes, to the output stream.
14.180 + * The byte values to be written, in the order
14.181 + * shown, are:
14.182 + * <p><pre><code>
14.183 + * (byte)(0xff & (v >> 24))
14.184 + * (byte)(0xff & (v >> 16))
14.185 + * (byte)(0xff & (v >>    8))
14.186 + * (byte)(0xff & v)
14.187 + * </code></pre><p>
14.188 + * The bytes written by this method may be read
14.189 + * by the <code>readInt</code> method of interface
14.190 + * <code>DataInput</code> , which will then
14.191 + * return an <code>int</code> equal to <code>v</code>.
14.192 + *
14.193 + * @param v the <code>int</code> value to be written.
14.194 + * @throws IOException if an I/O error occurs.
14.195 + */
14.196 + void writeInt(int v) throws IOException;
14.197 +
14.198 + /**
14.199 + * Writes a <code>long</code> value, which is
14.200 + * comprised of eight bytes, to the output stream.
14.201 + * The byte values to be written, in the order
14.202 + * shown, are:
14.203 + * <p><pre><code>
14.204 + * (byte)(0xff & (v >> 56))
14.205 + * (byte)(0xff & (v >> 48))
14.206 + * (byte)(0xff & (v >> 40))
14.207 + * (byte)(0xff & (v >> 32))
14.208 + * (byte)(0xff & (v >> 24))
14.209 + * (byte)(0xff & (v >> 16))
14.210 + * (byte)(0xff & (v >> 8))
14.211 + * (byte)(0xff & v)
14.212 + * </code></pre><p>
14.213 + * The bytes written by this method may be
14.214 + * read by the <code>readLong</code> method
14.215 + * of interface <code>DataInput</code> , which
14.216 + * will then return a <code>long</code> equal
14.217 + * to <code>v</code>.
14.218 + *
14.219 + * @param v the <code>long</code> value to be written.
14.220 + * @throws IOException if an I/O error occurs.
14.221 + */
14.222 + void writeLong(long v) throws IOException;
14.223 +
14.224 + /**
14.225 + * Writes a <code>float</code> value,
14.226 + * which is comprised of four bytes, to the output stream.
14.227 + * It does this as if it first converts this
14.228 + * <code>float</code> value to an <code>int</code>
14.229 + * in exactly the manner of the <code>Float.floatToIntBits</code>
14.230 + * method and then writes the <code>int</code>
14.231 + * value in exactly the manner of the <code>writeInt</code>
14.232 + * method. The bytes written by this method
14.233 + * may be read by the <code>readFloat</code>
14.234 + * method of interface <code>DataInput</code>,
14.235 + * which will then return a <code>float</code>
14.236 + * equal to <code>v</code>.
14.237 + *
14.238 + * @param v the <code>float</code> value to be written.
14.239 + * @throws IOException if an I/O error occurs.
14.240 + */
14.241 + void writeFloat(float v) throws IOException;
14.242 +
14.243 + /**
14.244 + * Writes a <code>double</code> value,
14.245 + * which is comprised of eight bytes, to the output stream.
14.246 + * It does this as if it first converts this
14.247 + * <code>double</code> value to a <code>long</code>
14.248 + * in exactly the manner of the <code>Double.doubleToLongBits</code>
14.249 + * method and then writes the <code>long</code>
14.250 + * value in exactly the manner of the <code>writeLong</code>
14.251 + * method. The bytes written by this method
14.252 + * may be read by the <code>readDouble</code>
14.253 + * method of interface <code>DataInput</code>,
14.254 + * which will then return a <code>double</code>
14.255 + * equal to <code>v</code>.
14.256 + *
14.257 + * @param v the <code>double</code> value to be written.
14.258 + * @throws IOException if an I/O error occurs.
14.259 + */
14.260 + void writeDouble(double v) throws IOException;
14.261 +
14.262 + /**
14.263 + * Writes a string to the output stream.
14.264 + * For every character in the string
14.265 + * <code>s</code>, taken in order, one byte
14.266 + * is written to the output stream. If
14.267 + * <code>s</code> is <code>null</code>, a <code>NullPointerException</code>
14.268 + * is thrown.<p> If <code>s.length</code>
14.269 + * is zero, then no bytes are written. Otherwise,
14.270 + * the character <code>s[0]</code> is written
14.271 + * first, then <code>s[1]</code>, and so on;
14.272 + * the last character written is <code>s[s.length-1]</code>.
14.273 + * For each character, one byte is written,
14.274 + * the low-order byte, in exactly the manner
14.275 + * of the <code>writeByte</code> method . The
14.276 + * high-order eight bits of each character
14.277 + * in the string are ignored.
14.278 + *
14.279 + * @param s the string of bytes to be written.
14.280 + * @throws IOException if an I/O error occurs.
14.281 + */
14.282 + void writeBytes(String s) throws IOException;
14.283 +
14.284 + /**
14.285 + * Writes every character in the string <code>s</code>,
14.286 + * to the output stream, in order,
14.287 + * two bytes per character. If <code>s</code>
14.288 + * is <code>null</code>, a <code>NullPointerException</code>
14.289 + * is thrown. If <code>s.length</code>
14.290 + * is zero, then no characters are written.
14.291 + * Otherwise, the character <code>s[0]</code>
14.292 + * is written first, then <code>s[1]</code>,
14.293 + * and so on; the last character written is
14.294 + * <code>s[s.length-1]</code>. For each character,
14.295 + * two bytes are actually written, high-order
14.296 + * byte first, in exactly the manner of the
14.297 + * <code>writeChar</code> method.
14.298 + *
14.299 + * @param s the string value to be written.
14.300 + * @throws IOException if an I/O error occurs.
14.301 + */
14.302 + void writeChars(String s) throws IOException;
14.303 +
14.304 + /**
14.305 + * Writes two bytes of length information
14.306 + * to the output stream, followed
14.307 + * by the
14.308 + * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
14.309 + * representation
14.310 + * of every character in the string <code>s</code>.
14.311 + * If <code>s</code> is <code>null</code>,
14.312 + * a <code>NullPointerException</code> is thrown.
14.313 + * Each character in the string <code>s</code>
14.314 + * is converted to a group of one, two, or
14.315 + * three bytes, depending on the value of the
14.316 + * character.<p>
14.317 + * If a character <code>c</code>
14.318 + * is in the range <code>\u0001</code> through
14.319 + * <code>\u007f</code>, it is represented
14.320 + * by one byte:<p>
14.321 + * <pre>(byte)c </pre> <p>
14.322 + * If a character <code>c</code> is <code>\u0000</code>
14.323 + * or is in the range <code>\u0080</code>
14.324 + * through <code>\u07ff</code>, then it is
14.325 + * represented by two bytes, to be written
14.326 + * in the order shown:<p> <pre><code>
14.327 + * (byte)(0xc0 | (0x1f & (c >> 6)))
14.328 + * (byte)(0x80 | (0x3f & c))
14.329 + * </code></pre> <p> If a character
14.330 + * <code>c</code> is in the range <code>\u0800</code>
14.331 + * through <code>uffff</code>, then it is
14.332 + * represented by three bytes, to be written
14.333 + * in the order shown:<p> <pre><code>
14.334 + * (byte)(0xe0 | (0x0f & (c >> 12)))
14.335 + * (byte)(0x80 | (0x3f & (c >> 6)))
14.336 + * (byte)(0x80 | (0x3f & c))
14.337 + * </code></pre> <p> First,
14.338 + * the total number of bytes needed to represent
14.339 + * all the characters of <code>s</code> is
14.340 + * calculated. If this number is larger than
14.341 + * <code>65535</code>, then a <code>UTFDataFormatException</code>
14.342 + * is thrown. Otherwise, this length is written
14.343 + * to the output stream in exactly the manner
14.344 + * of the <code>writeShort</code> method;
14.345 + * after this, the one-, two-, or three-byte
14.346 + * representation of each character in the
14.347 + * string <code>s</code> is written.<p> The
14.348 + * bytes written by this method may be read
14.349 + * by the <code>readUTF</code> method of interface
14.350 + * <code>DataInput</code> , which will then
14.351 + * return a <code>String</code> equal to <code>s</code>.
14.352 + *
14.353 + * @param s the string value to be written.
14.354 + * @throws IOException if an I/O error occurs.
14.355 + */
14.356 + void writeUTF(String s) throws IOException;
14.357 +}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/emul/compact/src/main/java/java/io/DataOutputStream.java Mon Feb 04 09:37:56 2013 +0100
15.3 @@ -0,0 +1,416 @@
15.4 +/*
15.5 + * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.
15.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
15.7 + *
15.8 + * This code is free software; you can redistribute it and/or modify it
15.9 + * under the terms of the GNU General Public License version 2 only, as
15.10 + * published by the Free Software Foundation. Oracle designates this
15.11 + * particular file as subject to the "Classpath" exception as provided
15.12 + * by Oracle in the LICENSE file that accompanied this code.
15.13 + *
15.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
15.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15.17 + * version 2 for more details (a copy is included in the LICENSE file that
15.18 + * accompanied this code).
15.19 + *
15.20 + * You should have received a copy of the GNU General Public License version
15.21 + * 2 along with this work; if not, write to the Free Software Foundation,
15.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
15.23 + *
15.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
15.25 + * or visit www.oracle.com if you need additional information or have any
15.26 + * questions.
15.27 + */
15.28 +
15.29 +package java.io;
15.30 +
15.31 +/**
15.32 + * A data output stream lets an application write primitive Java data
15.33 + * types to an output stream in a portable way. An application can
15.34 + * then use a data input stream to read the data back in.
15.35 + *
15.36 + * @author unascribed
15.37 + * @see java.io.DataInputStream
15.38 + * @since JDK1.0
15.39 + */
15.40 +public
15.41 +class DataOutputStream extends FilterOutputStream implements DataOutput {
15.42 + /**
15.43 + * The number of bytes written to the data output stream so far.
15.44 + * If this counter overflows, it will be wrapped to Integer.MAX_VALUE.
15.45 + */
15.46 + protected int written;
15.47 +
15.48 + /**
15.49 + * bytearr is initialized on demand by writeUTF
15.50 + */
15.51 + private byte[] bytearr = null;
15.52 +
15.53 + /**
15.54 + * Creates a new data output stream to write data to the specified
15.55 + * underlying output stream. The counter <code>written</code> is
15.56 + * set to zero.
15.57 + *
15.58 + * @param out the underlying output stream, to be saved for later
15.59 + * use.
15.60 + * @see java.io.FilterOutputStream#out
15.61 + */
15.62 + public DataOutputStream(OutputStream out) {
15.63 + super(out);
15.64 + }
15.65 +
15.66 + /**
15.67 + * Increases the written counter by the specified value
15.68 + * until it reaches Integer.MAX_VALUE.
15.69 + */
15.70 + private void incCount(int value) {
15.71 + int temp = written + value;
15.72 + if (temp < 0) {
15.73 + temp = Integer.MAX_VALUE;
15.74 + }
15.75 + written = temp;
15.76 + }
15.77 +
15.78 + /**
15.79 + * Writes the specified byte (the low eight bits of the argument
15.80 + * <code>b</code>) to the underlying output stream. If no exception
15.81 + * is thrown, the counter <code>written</code> is incremented by
15.82 + * <code>1</code>.
15.83 + * <p>
15.84 + * Implements the <code>write</code> method of <code>OutputStream</code>.
15.85 + *
15.86 + * @param b the <code>byte</code> to be written.
15.87 + * @exception IOException if an I/O error occurs.
15.88 + * @see java.io.FilterOutputStream#out
15.89 + */
15.90 + public synchronized void write(int b) throws IOException {
15.91 + out.write(b);
15.92 + incCount(1);
15.93 + }
15.94 +
15.95 + /**
15.96 + * Writes <code>len</code> bytes from the specified byte array
15.97 + * starting at offset <code>off</code> to the underlying output stream.
15.98 + * If no exception is thrown, the counter <code>written</code> is
15.99 + * incremented by <code>len</code>.
15.100 + *
15.101 + * @param b the data.
15.102 + * @param off the start offset in the data.
15.103 + * @param len the number of bytes to write.
15.104 + * @exception IOException if an I/O error occurs.
15.105 + * @see java.io.FilterOutputStream#out
15.106 + */
15.107 + public synchronized void write(byte b[], int off, int len)
15.108 + throws IOException
15.109 + {
15.110 + out.write(b, off, len);
15.111 + incCount(len);
15.112 + }
15.113 +
15.114 + /**
15.115 + * Flushes this data output stream. This forces any buffered output
15.116 + * bytes to be written out to the stream.
15.117 + * <p>
15.118 + * The <code>flush</code> method of <code>DataOutputStream</code>
15.119 + * calls the <code>flush</code> method of its underlying output stream.
15.120 + *
15.121 + * @exception IOException if an I/O error occurs.
15.122 + * @see java.io.FilterOutputStream#out
15.123 + * @see java.io.OutputStream#flush()
15.124 + */
15.125 + public void flush() throws IOException {
15.126 + out.flush();
15.127 + }
15.128 +
15.129 + /**
15.130 + * Writes a <code>boolean</code> to the underlying output stream as
15.131 + * a 1-byte value. The value <code>true</code> is written out as the
15.132 + * value <code>(byte)1</code>; the value <code>false</code> is
15.133 + * written out as the value <code>(byte)0</code>. If no exception is
15.134 + * thrown, the counter <code>written</code> is incremented by
15.135 + * <code>1</code>.
15.136 + *
15.137 + * @param v a <code>boolean</code> value to be written.
15.138 + * @exception IOException if an I/O error occurs.
15.139 + * @see java.io.FilterOutputStream#out
15.140 + */
15.141 + public final void writeBoolean(boolean v) throws IOException {
15.142 + out.write(v ? 1 : 0);
15.143 + incCount(1);
15.144 + }
15.145 +
15.146 + /**
15.147 + * Writes out a <code>byte</code> to the underlying output stream as
15.148 + * a 1-byte value. If no exception is thrown, the counter
15.149 + * <code>written</code> is incremented by <code>1</code>.
15.150 + *
15.151 + * @param v a <code>byte</code> value to be written.
15.152 + * @exception IOException if an I/O error occurs.
15.153 + * @see java.io.FilterOutputStream#out
15.154 + */
15.155 + public final void writeByte(int v) throws IOException {
15.156 + out.write(v);
15.157 + incCount(1);
15.158 + }
15.159 +
15.160 + /**
15.161 + * Writes a <code>short</code> to the underlying output stream as two
15.162 + * bytes, high byte first. If no exception is thrown, the counter
15.163 + * <code>written</code> is incremented by <code>2</code>.
15.164 + *
15.165 + * @param v a <code>short</code> to be written.
15.166 + * @exception IOException if an I/O error occurs.
15.167 + * @see java.io.FilterOutputStream#out
15.168 + */
15.169 + public final void writeShort(int v) throws IOException {
15.170 + out.write((v >>> 8) & 0xFF);
15.171 + out.write((v >>> 0) & 0xFF);
15.172 + incCount(2);
15.173 + }
15.174 +
15.175 + /**
15.176 + * Writes a <code>char</code> to the underlying output stream as a
15.177 + * 2-byte value, high byte first. If no exception is thrown, the
15.178 + * counter <code>written</code> is incremented by <code>2</code>.
15.179 + *
15.180 + * @param v a <code>char</code> value to be written.
15.181 + * @exception IOException if an I/O error occurs.
15.182 + * @see java.io.FilterOutputStream#out
15.183 + */
15.184 + public final void writeChar(int v) throws IOException {
15.185 + out.write((v >>> 8) & 0xFF);
15.186 + out.write((v >>> 0) & 0xFF);
15.187 + incCount(2);
15.188 + }
15.189 +
15.190 + /**
15.191 + * Writes an <code>int</code> to the underlying output stream as four
15.192 + * bytes, high byte first. If no exception is thrown, the counter
15.193 + * <code>written</code> is incremented by <code>4</code>.
15.194 + *
15.195 + * @param v an <code>int</code> to be written.
15.196 + * @exception IOException if an I/O error occurs.
15.197 + * @see java.io.FilterOutputStream#out
15.198 + */
15.199 + public final void writeInt(int v) throws IOException {
15.200 + out.write((v >>> 24) & 0xFF);
15.201 + out.write((v >>> 16) & 0xFF);
15.202 + out.write((v >>> 8) & 0xFF);
15.203 + out.write((v >>> 0) & 0xFF);
15.204 + incCount(4);
15.205 + }
15.206 +
15.207 + private byte writeBuffer[] = new byte[8];
15.208 +
15.209 + /**
15.210 + * Writes a <code>long</code> to the underlying output stream as eight
15.211 + * bytes, high byte first. In no exception is thrown, the counter
15.212 + * <code>written</code> is incremented by <code>8</code>.
15.213 + *
15.214 + * @param v a <code>long</code> to be written.
15.215 + * @exception IOException if an I/O error occurs.
15.216 + * @see java.io.FilterOutputStream#out
15.217 + */
15.218 + public final void writeLong(long v) throws IOException {
15.219 + writeBuffer[0] = (byte)(v >>> 56);
15.220 + writeBuffer[1] = (byte)(v >>> 48);
15.221 + writeBuffer[2] = (byte)(v >>> 40);
15.222 + writeBuffer[3] = (byte)(v >>> 32);
15.223 + writeBuffer[4] = (byte)(v >>> 24);
15.224 + writeBuffer[5] = (byte)(v >>> 16);
15.225 + writeBuffer[6] = (byte)(v >>> 8);
15.226 + writeBuffer[7] = (byte)(v >>> 0);
15.227 + out.write(writeBuffer, 0, 8);
15.228 + incCount(8);
15.229 + }
15.230 +
15.231 + /**
15.232 + * Converts the float argument to an <code>int</code> using the
15.233 + * <code>floatToIntBits</code> method in class <code>Float</code>,
15.234 + * and then writes that <code>int</code> value to the underlying
15.235 + * output stream as a 4-byte quantity, high byte first. If no
15.236 + * exception is thrown, the counter <code>written</code> is
15.237 + * incremented by <code>4</code>.
15.238 + *
15.239 + * @param v a <code>float</code> value to be written.
15.240 + * @exception IOException if an I/O error occurs.
15.241 + * @see java.io.FilterOutputStream#out
15.242 + * @see java.lang.Float#floatToIntBits(float)
15.243 + */
15.244 + public final void writeFloat(float v) throws IOException {
15.245 + writeInt(Float.floatToIntBits(v));
15.246 + }
15.247 +
15.248 + /**
15.249 + * Converts the double argument to a <code>long</code> using the
15.250 + * <code>doubleToLongBits</code> method in class <code>Double</code>,
15.251 + * and then writes that <code>long</code> value to the underlying
15.252 + * output stream as an 8-byte quantity, high byte first. If no
15.253 + * exception is thrown, the counter <code>written</code> is
15.254 + * incremented by <code>8</code>.
15.255 + *
15.256 + * @param v a <code>double</code> value to be written.
15.257 + * @exception IOException if an I/O error occurs.
15.258 + * @see java.io.FilterOutputStream#out
15.259 + * @see java.lang.Double#doubleToLongBits(double)
15.260 + */
15.261 + public final void writeDouble(double v) throws IOException {
15.262 + writeLong(Double.doubleToLongBits(v));
15.263 + }
15.264 +
15.265 + /**
15.266 + * Writes out the string to the underlying output stream as a
15.267 + * sequence of bytes. Each character in the string is written out, in
15.268 + * sequence, by discarding its high eight bits. If no exception is
15.269 + * thrown, the counter <code>written</code> is incremented by the
15.270 + * length of <code>s</code>.
15.271 + *
15.272 + * @param s a string of bytes to be written.
15.273 + * @exception IOException if an I/O error occurs.
15.274 + * @see java.io.FilterOutputStream#out
15.275 + */
15.276 + public final void writeBytes(String s) throws IOException {
15.277 + int len = s.length();
15.278 + for (int i = 0 ; i < len ; i++) {
15.279 + out.write((byte)s.charAt(i));
15.280 + }
15.281 + incCount(len);
15.282 + }
15.283 +
15.284 + /**
15.285 + * Writes a string to the underlying output stream as a sequence of
15.286 + * characters. Each character is written to the data output stream as
15.287 + * if by the <code>writeChar</code> method. If no exception is
15.288 + * thrown, the counter <code>written</code> is incremented by twice
15.289 + * the length of <code>s</code>.
15.290 + *
15.291 + * @param s a <code>String</code> value to be written.
15.292 + * @exception IOException if an I/O error occurs.
15.293 + * @see java.io.DataOutputStream#writeChar(int)
15.294 + * @see java.io.FilterOutputStream#out
15.295 + */
15.296 + public final void writeChars(String s) throws IOException {
15.297 + int len = s.length();
15.298 + for (int i = 0 ; i < len ; i++) {
15.299 + int v = s.charAt(i);
15.300 + out.write((v >>> 8) & 0xFF);
15.301 + out.write((v >>> 0) & 0xFF);
15.302 + }
15.303 + incCount(len * 2);
15.304 + }
15.305 +
15.306 + /**
15.307 + * Writes a string to the underlying output stream using
15.308 + * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
15.309 + * encoding in a machine-independent manner.
15.310 + * <p>
15.311 + * First, two bytes are written to the output stream as if by the
15.312 + * <code>writeShort</code> method giving the number of bytes to
15.313 + * follow. This value is the number of bytes actually written out,
15.314 + * not the length of the string. Following the length, each character
15.315 + * of the string is output, in sequence, using the modified UTF-8 encoding
15.316 + * for the character. If no exception is thrown, the counter
15.317 + * <code>written</code> is incremented by the total number of
15.318 + * bytes written to the output stream. This will be at least two
15.319 + * plus the length of <code>str</code>, and at most two plus
15.320 + * thrice the length of <code>str</code>.
15.321 + *
15.322 + * @param str a string to be written.
15.323 + * @exception IOException if an I/O error occurs.
15.324 + */
15.325 + public final void writeUTF(String str) throws IOException {
15.326 + writeUTF(str, this);
15.327 + }
15.328 +
15.329 + /**
15.330 + * Writes a string to the specified DataOutput using
15.331 + * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
15.332 + * encoding in a machine-independent manner.
15.333 + * <p>
15.334 + * First, two bytes are written to out as if by the <code>writeShort</code>
15.335 + * method giving the number of bytes to follow. This value is the number of
15.336 + * bytes actually written out, not the length of the string. Following the
15.337 + * length, each character of the string is output, in sequence, using the
15.338 + * modified UTF-8 encoding for the character. If no exception is thrown, the
15.339 + * counter <code>written</code> is incremented by the total number of
15.340 + * bytes written to the output stream. This will be at least two
15.341 + * plus the length of <code>str</code>, and at most two plus
15.342 + * thrice the length of <code>str</code>.
15.343 + *
15.344 + * @param str a string to be written.
15.345 + * @param out destination to write to
15.346 + * @return The number of bytes written out.
15.347 + * @exception IOException if an I/O error occurs.
15.348 + */
15.349 + static int writeUTF(String str, DataOutput out) throws IOException {
15.350 + int strlen = str.length();
15.351 + int utflen = 0;
15.352 + int c, count = 0;
15.353 +
15.354 + /* use charAt instead of copying String to char array */
15.355 + for (int i = 0; i < strlen; i++) {
15.356 + c = str.charAt(i);
15.357 + if ((c >= 0x0001) && (c <= 0x007F)) {
15.358 + utflen++;
15.359 + } else if (c > 0x07FF) {
15.360 + utflen += 3;
15.361 + } else {
15.362 + utflen += 2;
15.363 + }
15.364 + }
15.365 +
15.366 + if (utflen > 65535)
15.367 + throw new UTFDataFormatException(
15.368 + "encoded string too long: " + utflen + " bytes");
15.369 +
15.370 + byte[] bytearr = null;
15.371 + if (out instanceof DataOutputStream) {
15.372 + DataOutputStream dos = (DataOutputStream)out;
15.373 + if(dos.bytearr == null || (dos.bytearr.length < (utflen+2)))
15.374 + dos.bytearr = new byte[(utflen*2) + 2];
15.375 + bytearr = dos.bytearr;
15.376 + } else {
15.377 + bytearr = new byte[utflen+2];
15.378 + }
15.379 +
15.380 + bytearr[count++] = (byte) ((utflen >>> 8) & 0xFF);
15.381 + bytearr[count++] = (byte) ((utflen >>> 0) & 0xFF);
15.382 +
15.383 + int i=0;
15.384 + for (i=0; i<strlen; i++) {
15.385 + c = str.charAt(i);
15.386 + if (!((c >= 0x0001) && (c <= 0x007F))) break;
15.387 + bytearr[count++] = (byte) c;
15.388 + }
15.389 +
15.390 + for (;i < strlen; i++){
15.391 + c = str.charAt(i);
15.392 + if ((c >= 0x0001) && (c <= 0x007F)) {
15.393 + bytearr[count++] = (byte) c;
15.394 +
15.395 + } else if (c > 0x07FF) {
15.396 + bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
15.397 + bytearr[count++] = (byte) (0x80 | ((c >> 6) & 0x3F));
15.398 + bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
15.399 + } else {
15.400 + bytearr[count++] = (byte) (0xC0 | ((c >> 6) & 0x1F));
15.401 + bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
15.402 + }
15.403 + }
15.404 + out.write(bytearr, 0, utflen+2);
15.405 + return utflen + 2;
15.406 + }
15.407 +
15.408 + /**
15.409 + * Returns the current value of the counter <code>written</code>,
15.410 + * the number of bytes written to this data output stream so far.
15.411 + * If the counter overflows, it will be wrapped to Integer.MAX_VALUE.
15.412 + *
15.413 + * @return the value of the <code>written</code> field.
15.414 + * @see java.io.DataOutputStream#written
15.415 + */
15.416 + public final int size() {
15.417 + return written;
15.418 + }
15.419 +}
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/emul/compact/src/main/java/java/io/Externalizable.java Mon Feb 04 09:37:56 2013 +0100
16.3 @@ -0,0 +1,97 @@
16.4 +/*
16.5 + * Copyright (c) 1996, 2004, Oracle and/or its affiliates. All rights reserved.
16.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
16.7 + *
16.8 + * This code is free software; you can redistribute it and/or modify it
16.9 + * under the terms of the GNU General Public License version 2 only, as
16.10 + * published by the Free Software Foundation. Oracle designates this
16.11 + * particular file as subject to the "Classpath" exception as provided
16.12 + * by Oracle in the LICENSE file that accompanied this code.
16.13 + *
16.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
16.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16.17 + * version 2 for more details (a copy is included in the LICENSE file that
16.18 + * accompanied this code).
16.19 + *
16.20 + * You should have received a copy of the GNU General Public License version
16.21 + * 2 along with this work; if not, write to the Free Software Foundation,
16.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
16.23 + *
16.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
16.25 + * or visit www.oracle.com if you need additional information or have any
16.26 + * questions.
16.27 + */
16.28 +
16.29 +package java.io;
16.30 +
16.31 +import java.io.ObjectOutput;
16.32 +import java.io.ObjectInput;
16.33 +
16.34 +/**
16.35 + * Only the identity of the class of an Externalizable instance is
16.36 + * written in the serialization stream and it is the responsibility
16.37 + * of the class to save and restore the contents of its instances.
16.38 + *
16.39 + * The writeExternal and readExternal methods of the Externalizable
16.40 + * interface are implemented by a class to give the class complete
16.41 + * control over the format and contents of the stream for an object
16.42 + * and its supertypes. These methods must explicitly
16.43 + * coordinate with the supertype to save its state. These methods supersede
16.44 + * customized implementations of writeObject and readObject methods.<br>
16.45 + *
16.46 + * Object Serialization uses the Serializable and Externalizable
16.47 + * interfaces. Object persistence mechanisms can use them as well. Each
16.48 + * object to be stored is tested for the Externalizable interface. If
16.49 + * the object supports Externalizable, the writeExternal method is called. If the
16.50 + * object does not support Externalizable and does implement
16.51 + * Serializable, the object is saved using
16.52 + * ObjectOutputStream. <br> When an Externalizable object is
16.53 + * reconstructed, an instance is created using the public no-arg
16.54 + * constructor, then the readExternal method called. Serializable
16.55 + * objects are restored by reading them from an ObjectInputStream.<br>
16.56 + *
16.57 + * An Externalizable instance can designate a substitution object via
16.58 + * the writeReplace and readResolve methods documented in the Serializable
16.59 + * interface.<br>
16.60 + *
16.61 + * @author unascribed
16.62 + * @see java.io.ObjectOutputStream
16.63 + * @see java.io.ObjectInputStream
16.64 + * @see java.io.ObjectOutput
16.65 + * @see java.io.ObjectInput
16.66 + * @see java.io.Serializable
16.67 + * @since JDK1.1
16.68 + */
16.69 +public interface Externalizable extends java.io.Serializable {
16.70 + /**
16.71 + * The object implements the writeExternal method to save its contents
16.72 + * by calling the methods of DataOutput for its primitive values or
16.73 + * calling the writeObject method of ObjectOutput for objects, strings,
16.74 + * and arrays.
16.75 + *
16.76 + * @serialData Overriding methods should use this tag to describe
16.77 + * the data layout of this Externalizable object.
16.78 + * List the sequence of element types and, if possible,
16.79 + * relate the element to a public/protected field and/or
16.80 + * method of this Externalizable class.
16.81 + *
16.82 + * @param out the stream to write the object to
16.83 + * @exception IOException Includes any I/O exceptions that may occur
16.84 + */
16.85 + void writeExternal(ObjectOutput out) throws IOException;
16.86 +
16.87 + /**
16.88 + * The object implements the readExternal method to restore its
16.89 + * contents by calling the methods of DataInput for primitive
16.90 + * types and readObject for objects, strings and arrays. The
16.91 + * readExternal method must read the values in the same sequence
16.92 + * and with the same types as were written by writeExternal.
16.93 + *
16.94 + * @param in the stream to read data from in order to restore the object
16.95 + * @exception IOException if I/O errors occur
16.96 + * @exception ClassNotFoundException If the class for an object being
16.97 + * restored cannot be found.
16.98 + */
16.99 + void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
16.100 +}
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/emul/compact/src/main/java/java/io/FilterOutputStream.java Mon Feb 04 09:37:56 2013 +0100
17.3 @@ -0,0 +1,162 @@
17.4 +/*
17.5 + * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
17.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
17.7 + *
17.8 + * This code is free software; you can redistribute it and/or modify it
17.9 + * under the terms of the GNU General Public License version 2 only, as
17.10 + * published by the Free Software Foundation. Oracle designates this
17.11 + * particular file as subject to the "Classpath" exception as provided
17.12 + * by Oracle in the LICENSE file that accompanied this code.
17.13 + *
17.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
17.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17.17 + * version 2 for more details (a copy is included in the LICENSE file that
17.18 + * accompanied this code).
17.19 + *
17.20 + * You should have received a copy of the GNU General Public License version
17.21 + * 2 along with this work; if not, write to the Free Software Foundation,
17.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17.23 + *
17.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
17.25 + * or visit www.oracle.com if you need additional information or have any
17.26 + * questions.
17.27 + */
17.28 +
17.29 +package java.io;
17.30 +
17.31 +/**
17.32 + * This class is the superclass of all classes that filter output
17.33 + * streams. These streams sit on top of an already existing output
17.34 + * stream (the <i>underlying</i> output stream) which it uses as its
17.35 + * basic sink of data, but possibly transforming the data along the
17.36 + * way or providing additional functionality.
17.37 + * <p>
17.38 + * The class <code>FilterOutputStream</code> itself simply overrides
17.39 + * all methods of <code>OutputStream</code> with versions that pass
17.40 + * all requests to the underlying output stream. Subclasses of
17.41 + * <code>FilterOutputStream</code> may further override some of these
17.42 + * methods as well as provide additional methods and fields.
17.43 + *
17.44 + * @author Jonathan Payne
17.45 + * @since JDK1.0
17.46 + */
17.47 +public
17.48 +class FilterOutputStream extends OutputStream {
17.49 + /**
17.50 + * The underlying output stream to be filtered.
17.51 + */
17.52 + protected OutputStream out;
17.53 +
17.54 + /**
17.55 + * Creates an output stream filter built on top of the specified
17.56 + * underlying output stream.
17.57 + *
17.58 + * @param out the underlying output stream to be assigned to
17.59 + * the field <tt>this.out</tt> for later use, or
17.60 + * <code>null</code> if this instance is to be
17.61 + * created without an underlying stream.
17.62 + */
17.63 + public FilterOutputStream(OutputStream out) {
17.64 + this.out = out;
17.65 + }
17.66 +
17.67 + /**
17.68 + * Writes the specified <code>byte</code> to this output stream.
17.69 + * <p>
17.70 + * The <code>write</code> method of <code>FilterOutputStream</code>
17.71 + * calls the <code>write</code> method of its underlying output stream,
17.72 + * that is, it performs <tt>out.write(b)</tt>.
17.73 + * <p>
17.74 + * Implements the abstract <tt>write</tt> method of <tt>OutputStream</tt>.
17.75 + *
17.76 + * @param b the <code>byte</code>.
17.77 + * @exception IOException if an I/O error occurs.
17.78 + */
17.79 + public void write(int b) throws IOException {
17.80 + out.write(b);
17.81 + }
17.82 +
17.83 + /**
17.84 + * Writes <code>b.length</code> bytes to this output stream.
17.85 + * <p>
17.86 + * The <code>write</code> method of <code>FilterOutputStream</code>
17.87 + * calls its <code>write</code> method of three arguments with the
17.88 + * arguments <code>b</code>, <code>0</code>, and
17.89 + * <code>b.length</code>.
17.90 + * <p>
17.91 + * Note that this method does not call the one-argument
17.92 + * <code>write</code> method of its underlying stream with the single
17.93 + * argument <code>b</code>.
17.94 + *
17.95 + * @param b the data to be written.
17.96 + * @exception IOException if an I/O error occurs.
17.97 + * @see java.io.FilterOutputStream#write(byte[], int, int)
17.98 + */
17.99 + public void write(byte b[]) throws IOException {
17.100 + write(b, 0, b.length);
17.101 + }
17.102 +
17.103 + /**
17.104 + * Writes <code>len</code> bytes from the specified
17.105 + * <code>byte</code> array starting at offset <code>off</code> to
17.106 + * this output stream.
17.107 + * <p>
17.108 + * The <code>write</code> method of <code>FilterOutputStream</code>
17.109 + * calls the <code>write</code> method of one argument on each
17.110 + * <code>byte</code> to output.
17.111 + * <p>
17.112 + * Note that this method does not call the <code>write</code> method
17.113 + * of its underlying input stream with the same arguments. Subclasses
17.114 + * of <code>FilterOutputStream</code> should provide a more efficient
17.115 + * implementation of this method.
17.116 + *
17.117 + * @param b the data.
17.118 + * @param off the start offset in the data.
17.119 + * @param len the number of bytes to write.
17.120 + * @exception IOException if an I/O error occurs.
17.121 + * @see java.io.FilterOutputStream#write(int)
17.122 + */
17.123 + public void write(byte b[], int off, int len) throws IOException {
17.124 + if ((off | len | (b.length - (len + off)) | (off + len)) < 0)
17.125 + throw new IndexOutOfBoundsException();
17.126 +
17.127 + for (int i = 0 ; i < len ; i++) {
17.128 + write(b[off + i]);
17.129 + }
17.130 + }
17.131 +
17.132 + /**
17.133 + * Flushes this output stream and forces any buffered output bytes
17.134 + * to be written out to the stream.
17.135 + * <p>
17.136 + * The <code>flush</code> method of <code>FilterOutputStream</code>
17.137 + * calls the <code>flush</code> method of its underlying output stream.
17.138 + *
17.139 + * @exception IOException if an I/O error occurs.
17.140 + * @see java.io.FilterOutputStream#out
17.141 + */
17.142 + public void flush() throws IOException {
17.143 + out.flush();
17.144 + }
17.145 +
17.146 + /**
17.147 + * Closes this output stream and releases any system resources
17.148 + * associated with the stream.
17.149 + * <p>
17.150 + * The <code>close</code> method of <code>FilterOutputStream</code>
17.151 + * calls its <code>flush</code> method, and then calls the
17.152 + * <code>close</code> method of its underlying output stream.
17.153 + *
17.154 + * @exception IOException if an I/O error occurs.
17.155 + * @see java.io.FilterOutputStream#flush()
17.156 + * @see java.io.FilterOutputStream#out
17.157 + */
17.158 + public void close() throws IOException {
17.159 + try {
17.160 + flush();
17.161 + } catch (IOException ignored) {
17.162 + }
17.163 + out.close();
17.164 + }
17.165 +}
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
18.2 +++ b/emul/compact/src/main/java/java/io/Flushable.java Mon Feb 04 09:37:56 2013 +0100
18.3 @@ -0,0 +1,47 @@
18.4 +/*
18.5 + * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
18.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
18.7 + *
18.8 + * This code is free software; you can redistribute it and/or modify it
18.9 + * under the terms of the GNU General Public License version 2 only, as
18.10 + * published by the Free Software Foundation. Oracle designates this
18.11 + * particular file as subject to the "Classpath" exception as provided
18.12 + * by Oracle in the LICENSE file that accompanied this code.
18.13 + *
18.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
18.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18.17 + * version 2 for more details (a copy is included in the LICENSE file that
18.18 + * accompanied this code).
18.19 + *
18.20 + * You should have received a copy of the GNU General Public License version
18.21 + * 2 along with this work; if not, write to the Free Software Foundation,
18.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18.23 + *
18.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
18.25 + * or visit www.oracle.com if you need additional information or have any
18.26 + * questions.
18.27 + */
18.28 +
18.29 +package java.io;
18.30 +
18.31 +import java.io.IOException;
18.32 +
18.33 +/**
18.34 + * A <tt>Flushable</tt> is a destination of data that can be flushed. The
18.35 + * flush method is invoked to write any buffered output to the underlying
18.36 + * stream.
18.37 + *
18.38 + * @since 1.5
18.39 + */
18.40 +
18.41 +public interface Flushable {
18.42 +
18.43 + /**
18.44 + * Flushes this stream by writing any buffered output to the underlying
18.45 + * stream.
18.46 + *
18.47 + * @throws IOException If an I/O error occurs
18.48 + */
18.49 + void flush() throws IOException;
18.50 +}
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
19.2 +++ b/emul/compact/src/main/java/java/io/InvalidClassException.java Mon Feb 04 09:37:56 2013 +0100
19.3 @@ -0,0 +1,81 @@
19.4 +/*
19.5 + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
19.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
19.7 + *
19.8 + * This code is free software; you can redistribute it and/or modify it
19.9 + * under the terms of the GNU General Public License version 2 only, as
19.10 + * published by the Free Software Foundation. Oracle designates this
19.11 + * particular file as subject to the "Classpath" exception as provided
19.12 + * by Oracle in the LICENSE file that accompanied this code.
19.13 + *
19.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
19.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19.17 + * version 2 for more details (a copy is included in the LICENSE file that
19.18 + * accompanied this code).
19.19 + *
19.20 + * You should have received a copy of the GNU General Public License version
19.21 + * 2 along with this work; if not, write to the Free Software Foundation,
19.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19.23 + *
19.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19.25 + * or visit www.oracle.com if you need additional information or have any
19.26 + * questions.
19.27 + */
19.28 +
19.29 +package java.io;
19.30 +
19.31 +/**
19.32 + * Thrown when the Serialization runtime detects one of the following
19.33 + * problems with a Class.
19.34 + * <UL>
19.35 + * <LI> The serial version of the class does not match that of the class
19.36 + * descriptor read from the stream
19.37 + * <LI> The class contains unknown datatypes
19.38 + * <LI> The class does not have an accessible no-arg constructor
19.39 + * </UL>
19.40 + *
19.41 + * @author unascribed
19.42 + * @since JDK1.1
19.43 + */
19.44 +public class InvalidClassException extends ObjectStreamException {
19.45 +
19.46 + private static final long serialVersionUID = -4333316296251054416L;
19.47 +
19.48 + /**
19.49 + * Name of the invalid class.
19.50 + *
19.51 + * @serial Name of the invalid class.
19.52 + */
19.53 + public String classname;
19.54 +
19.55 + /**
19.56 + * Report an InvalidClassException for the reason specified.
19.57 + *
19.58 + * @param reason String describing the reason for the exception.
19.59 + */
19.60 + public InvalidClassException(String reason) {
19.61 + super(reason);
19.62 + }
19.63 +
19.64 + /**
19.65 + * Constructs an InvalidClassException object.
19.66 + *
19.67 + * @param cname a String naming the invalid class.
19.68 + * @param reason a String describing the reason for the exception.
19.69 + */
19.70 + public InvalidClassException(String cname, String reason) {
19.71 + super(reason);
19.72 + classname = cname;
19.73 + }
19.74 +
19.75 + /**
19.76 + * Produce the message and include the classname, if present.
19.77 + */
19.78 + public String getMessage() {
19.79 + if (classname == null)
19.80 + return super.getMessage();
19.81 + else
19.82 + return classname + "; " + super.getMessage();
19.83 + }
19.84 +}
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
20.2 +++ b/emul/compact/src/main/java/java/io/InvalidObjectException.java Mon Feb 04 09:37:56 2013 +0100
20.3 @@ -0,0 +1,51 @@
20.4 +/*
20.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
20.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
20.7 + *
20.8 + * This code is free software; you can redistribute it and/or modify it
20.9 + * under the terms of the GNU General Public License version 2 only, as
20.10 + * published by the Free Software Foundation. Oracle designates this
20.11 + * particular file as subject to the "Classpath" exception as provided
20.12 + * by Oracle in the LICENSE file that accompanied this code.
20.13 + *
20.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
20.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20.17 + * version 2 for more details (a copy is included in the LICENSE file that
20.18 + * accompanied this code).
20.19 + *
20.20 + * You should have received a copy of the GNU General Public License version
20.21 + * 2 along with this work; if not, write to the Free Software Foundation,
20.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20.23 + *
20.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20.25 + * or visit www.oracle.com if you need additional information or have any
20.26 + * questions.
20.27 + */
20.28 +
20.29 +package java.io;
20.30 +
20.31 +/**
20.32 + * Indicates that one or more deserialized objects failed validation
20.33 + * tests. The argument should provide the reason for the failure.
20.34 + *
20.35 + * @see ObjectInputValidation
20.36 + * @since JDK1.1
20.37 + *
20.38 + * @author unascribed
20.39 + * @since JDK1.1
20.40 + */
20.41 +public class InvalidObjectException extends ObjectStreamException {
20.42 +
20.43 + private static final long serialVersionUID = 3233174318281839583L;
20.44 +
20.45 + /**
20.46 + * Constructs an <code>InvalidObjectException</code>.
20.47 + * @param reason Detailed message explaining the reason for the failure.
20.48 + *
20.49 + * @see ObjectInputValidation
20.50 + */
20.51 + public InvalidObjectException(String reason) {
20.52 + super(reason);
20.53 + }
20.54 +}
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/emul/compact/src/main/java/java/io/NotActiveException.java Mon Feb 04 09:37:56 2013 +0100
21.3 @@ -0,0 +1,53 @@
21.4 +/*
21.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
21.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
21.7 + *
21.8 + * This code is free software; you can redistribute it and/or modify it
21.9 + * under the terms of the GNU General Public License version 2 only, as
21.10 + * published by the Free Software Foundation. Oracle designates this
21.11 + * particular file as subject to the "Classpath" exception as provided
21.12 + * by Oracle in the LICENSE file that accompanied this code.
21.13 + *
21.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
21.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21.17 + * version 2 for more details (a copy is included in the LICENSE file that
21.18 + * accompanied this code).
21.19 + *
21.20 + * You should have received a copy of the GNU General Public License version
21.21 + * 2 along with this work; if not, write to the Free Software Foundation,
21.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21.23 + *
21.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21.25 + * or visit www.oracle.com if you need additional information or have any
21.26 + * questions.
21.27 + */
21.28 +
21.29 +package java.io;
21.30 +
21.31 +/**
21.32 + * Thrown when serialization or deserialization is not active.
21.33 + *
21.34 + * @author unascribed
21.35 + * @since JDK1.1
21.36 + */
21.37 +public class NotActiveException extends ObjectStreamException {
21.38 +
21.39 + private static final long serialVersionUID = -3893467273049808895L;
21.40 +
21.41 + /**
21.42 + * Constructor to create a new NotActiveException with the reason given.
21.43 + *
21.44 + * @param reason a String describing the reason for the exception.
21.45 + */
21.46 + public NotActiveException(String reason) {
21.47 + super(reason);
21.48 + }
21.49 +
21.50 + /**
21.51 + * Constructor to create a new NotActiveException without a reason.
21.52 + */
21.53 + public NotActiveException() {
21.54 + super();
21.55 + }
21.56 +}
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
22.2 +++ b/emul/compact/src/main/java/java/io/NotSerializableException.java Mon Feb 04 09:37:56 2013 +0100
22.3 @@ -0,0 +1,55 @@
22.4 +/*
22.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
22.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
22.7 + *
22.8 + * This code is free software; you can redistribute it and/or modify it
22.9 + * under the terms of the GNU General Public License version 2 only, as
22.10 + * published by the Free Software Foundation. Oracle designates this
22.11 + * particular file as subject to the "Classpath" exception as provided
22.12 + * by Oracle in the LICENSE file that accompanied this code.
22.13 + *
22.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
22.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22.17 + * version 2 for more details (a copy is included in the LICENSE file that
22.18 + * accompanied this code).
22.19 + *
22.20 + * You should have received a copy of the GNU General Public License version
22.21 + * 2 along with this work; if not, write to the Free Software Foundation,
22.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22.23 + *
22.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22.25 + * or visit www.oracle.com if you need additional information or have any
22.26 + * questions.
22.27 + */
22.28 +
22.29 +package java.io;
22.30 +
22.31 +/**
22.32 + * Thrown when an instance is required to have a Serializable interface.
22.33 + * The serialization runtime or the class of the instance can throw
22.34 + * this exception. The argument should be the name of the class.
22.35 + *
22.36 + * @author unascribed
22.37 + * @since JDK1.1
22.38 + */
22.39 +public class NotSerializableException extends ObjectStreamException {
22.40 +
22.41 + private static final long serialVersionUID = 2906642554793891381L;
22.42 +
22.43 + /**
22.44 + * Constructs a NotSerializableException object with message string.
22.45 + *
22.46 + * @param classname Class of the instance being serialized/deserialized.
22.47 + */
22.48 + public NotSerializableException(String classname) {
22.49 + super(classname);
22.50 + }
22.51 +
22.52 + /**
22.53 + * Constructs a NotSerializableException object.
22.54 + */
22.55 + public NotSerializableException() {
22.56 + super();
22.57 + }
22.58 +}
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
23.2 +++ b/emul/compact/src/main/java/java/io/ObjectInput.java Mon Feb 04 09:37:56 2013 +0100
23.3 @@ -0,0 +1,107 @@
23.4 +/*
23.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
23.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
23.7 + *
23.8 + * This code is free software; you can redistribute it and/or modify it
23.9 + * under the terms of the GNU General Public License version 2 only, as
23.10 + * published by the Free Software Foundation. Oracle designates this
23.11 + * particular file as subject to the "Classpath" exception as provided
23.12 + * by Oracle in the LICENSE file that accompanied this code.
23.13 + *
23.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
23.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23.17 + * version 2 for more details (a copy is included in the LICENSE file that
23.18 + * accompanied this code).
23.19 + *
23.20 + * You should have received a copy of the GNU General Public License version
23.21 + * 2 along with this work; if not, write to the Free Software Foundation,
23.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
23.23 + *
23.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23.25 + * or visit www.oracle.com if you need additional information or have any
23.26 + * questions.
23.27 + */
23.28 +
23.29 +package java.io;
23.30 +
23.31 +/**
23.32 + * ObjectInput extends the DataInput interface to include the reading of
23.33 + * objects. DataInput includes methods for the input of primitive types,
23.34 + * ObjectInput extends that interface to include objects, arrays, and Strings.
23.35 + *
23.36 + * @author unascribed
23.37 + * @see java.io.InputStream
23.38 + * @see java.io.ObjectOutputStream
23.39 + * @see java.io.ObjectInputStream
23.40 + * @since JDK1.1
23.41 + */
23.42 +public interface ObjectInput extends DataInput, AutoCloseable {
23.43 + /**
23.44 + * Read and return an object. The class that implements this interface
23.45 + * defines where the object is "read" from.
23.46 + *
23.47 + * @return the object read from the stream
23.48 + * @exception java.lang.ClassNotFoundException If the class of a serialized
23.49 + * object cannot be found.
23.50 + * @exception IOException If any of the usual Input/Output
23.51 + * related exceptions occur.
23.52 + */
23.53 + public Object readObject()
23.54 + throws ClassNotFoundException, IOException;
23.55 +
23.56 + /**
23.57 + * Reads a byte of data. This method will block if no input is
23.58 + * available.
23.59 + * @return the byte read, or -1 if the end of the
23.60 + * stream is reached.
23.61 + * @exception IOException If an I/O error has occurred.
23.62 + */
23.63 + public int read() throws IOException;
23.64 +
23.65 + /**
23.66 + * Reads into an array of bytes. This method will
23.67 + * block until some input is available.
23.68 + * @param b the buffer into which the data is read
23.69 + * @return the actual number of bytes read, -1 is
23.70 + * returned when the end of the stream is reached.
23.71 + * @exception IOException If an I/O error has occurred.
23.72 + */
23.73 + public int read(byte b[]) throws IOException;
23.74 +
23.75 + /**
23.76 + * Reads into an array of bytes. This method will
23.77 + * block until some input is available.
23.78 + * @param b the buffer into which the data is read
23.79 + * @param off the start offset of the data
23.80 + * @param len the maximum number of bytes read
23.81 + * @return the actual number of bytes read, -1 is
23.82 + * returned when the end of the stream is reached.
23.83 + * @exception IOException If an I/O error has occurred.
23.84 + */
23.85 + public int read(byte b[], int off, int len) throws IOException;
23.86 +
23.87 + /**
23.88 + * Skips n bytes of input.
23.89 + * @param n the number of bytes to be skipped
23.90 + * @return the actual number of bytes skipped.
23.91 + * @exception IOException If an I/O error has occurred.
23.92 + */
23.93 + public long skip(long n) throws IOException;
23.94 +
23.95 + /**
23.96 + * Returns the number of bytes that can be read
23.97 + * without blocking.
23.98 + * @return the number of available bytes.
23.99 + * @exception IOException If an I/O error has occurred.
23.100 + */
23.101 + public int available() throws IOException;
23.102 +
23.103 + /**
23.104 + * Closes the input stream. Must be called
23.105 + * to release any resources associated with
23.106 + * the stream.
23.107 + * @exception IOException If an I/O error has occurred.
23.108 + */
23.109 + public void close() throws IOException;
23.110 +}
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
24.2 +++ b/emul/compact/src/main/java/java/io/ObjectInputStream.java Mon Feb 04 09:37:56 2013 +0100
24.3 @@ -0,0 +1,3357 @@
24.4 +/*
24.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
24.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
24.7 + *
24.8 + * This code is free software; you can redistribute it and/or modify it
24.9 + * under the terms of the GNU General Public License version 2 only, as
24.10 + * published by the Free Software Foundation. Oracle designates this
24.11 + * particular file as subject to the "Classpath" exception as provided
24.12 + * by Oracle in the LICENSE file that accompanied this code.
24.13 + *
24.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
24.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
24.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24.17 + * version 2 for more details (a copy is included in the LICENSE file that
24.18 + * accompanied this code).
24.19 + *
24.20 + * You should have received a copy of the GNU General Public License version
24.21 + * 2 along with this work; if not, write to the Free Software Foundation,
24.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24.23 + *
24.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
24.25 + * or visit www.oracle.com if you need additional information or have any
24.26 + * questions.
24.27 + */
24.28 +
24.29 +package java.io;
24.30 +
24.31 +import java.lang.reflect.Array;
24.32 +import java.lang.reflect.Modifier;
24.33 +import java.lang.reflect.Proxy;
24.34 +import java.util.Arrays;
24.35 +import java.util.HashMap;
24.36 +import org.apidesign.bck2brwsr.emul.lang.System;
24.37 +
24.38 +/**
24.39 + * An ObjectInputStream deserializes primitive data and objects previously
24.40 + * written using an ObjectOutputStream.
24.41 + *
24.42 + * <p>ObjectOutputStream and ObjectInputStream can provide an application with
24.43 + * persistent storage for graphs of objects when used with a FileOutputStream
24.44 + * and FileInputStream respectively. ObjectInputStream is used to recover
24.45 + * those objects previously serialized. Other uses include passing objects
24.46 + * between hosts using a socket stream or for marshaling and unmarshaling
24.47 + * arguments and parameters in a remote communication system.
24.48 + *
24.49 + * <p>ObjectInputStream ensures that the types of all objects in the graph
24.50 + * created from the stream match the classes present in the Java Virtual
24.51 + * Machine. Classes are loaded as required using the standard mechanisms.
24.52 + *
24.53 + * <p>Only objects that support the java.io.Serializable or
24.54 + * java.io.Externalizable interface can be read from streams.
24.55 + *
24.56 + * <p>The method <code>readObject</code> is used to read an object from the
24.57 + * stream. Java's safe casting should be used to get the desired type. In
24.58 + * Java, strings and arrays are objects and are treated as objects during
24.59 + * serialization. When read they need to be cast to the expected type.
24.60 + *
24.61 + * <p>Primitive data types can be read from the stream using the appropriate
24.62 + * method on DataInput.
24.63 + *
24.64 + * <p>The default deserialization mechanism for objects restores the contents
24.65 + * of each field to the value and type it had when it was written. Fields
24.66 + * declared as transient or static are ignored by the deserialization process.
24.67 + * References to other objects cause those objects to be read from the stream
24.68 + * as necessary. Graphs of objects are restored correctly using a reference
24.69 + * sharing mechanism. New objects are always allocated when deserializing,
24.70 + * which prevents existing objects from being overwritten.
24.71 + *
24.72 + * <p>Reading an object is analogous to running the constructors of a new
24.73 + * object. Memory is allocated for the object and initialized to zero (NULL).
24.74 + * No-arg constructors are invoked for the non-serializable classes and then
24.75 + * the fields of the serializable classes are restored from the stream starting
24.76 + * with the serializable class closest to java.lang.object and finishing with
24.77 + * the object's most specific class.
24.78 + *
24.79 + * <p>For example to read from a stream as written by the example in
24.80 + * ObjectOutputStream:
24.81 + * <br>
24.82 + * <pre>
24.83 + * FileInputStream fis = new FileInputStream("t.tmp");
24.84 + * ObjectInputStream ois = new ObjectInputStream(fis);
24.85 + *
24.86 + * int i = ois.readInt();
24.87 + * String today = (String) ois.readObject();
24.88 + * Date date = (Date) ois.readObject();
24.89 + *
24.90 + * ois.close();
24.91 + * </pre>
24.92 + *
24.93 + * <p>Classes control how they are serialized by implementing either the
24.94 + * java.io.Serializable or java.io.Externalizable interfaces.
24.95 + *
24.96 + * <p>Implementing the Serializable interface allows object serialization to
24.97 + * save and restore the entire state of the object and it allows classes to
24.98 + * evolve between the time the stream is written and the time it is read. It
24.99 + * automatically traverses references between objects, saving and restoring
24.100 + * entire graphs.
24.101 + *
24.102 + * <p>Serializable classes that require special handling during the
24.103 + * serialization and deserialization process should implement the following
24.104 + * methods:<p>
24.105 + *
24.106 + * <pre>
24.107 + * private void writeObject(java.io.ObjectOutputStream stream)
24.108 + * throws IOException;
24.109 + * private void readObject(java.io.ObjectInputStream stream)
24.110 + * throws IOException, ClassNotFoundException;
24.111 + * private void readObjectNoData()
24.112 + * throws ObjectStreamException;
24.113 + * </pre>
24.114 + *
24.115 + * <p>The readObject method is responsible for reading and restoring the state
24.116 + * of the object for its particular class using data written to the stream by
24.117 + * the corresponding writeObject method. The method does not need to concern
24.118 + * itself with the state belonging to its superclasses or subclasses. State is
24.119 + * restored by reading data from the ObjectInputStream for the individual
24.120 + * fields and making assignments to the appropriate fields of the object.
24.121 + * Reading primitive data types is supported by DataInput.
24.122 + *
24.123 + * <p>Any attempt to read object data which exceeds the boundaries of the
24.124 + * custom data written by the corresponding writeObject method will cause an
24.125 + * OptionalDataException to be thrown with an eof field value of true.
24.126 + * Non-object reads which exceed the end of the allotted data will reflect the
24.127 + * end of data in the same way that they would indicate the end of the stream:
24.128 + * bytewise reads will return -1 as the byte read or number of bytes read, and
24.129 + * primitive reads will throw EOFExceptions. If there is no corresponding
24.130 + * writeObject method, then the end of default serialized data marks the end of
24.131 + * the allotted data.
24.132 + *
24.133 + * <p>Primitive and object read calls issued from within a readExternal method
24.134 + * behave in the same manner--if the stream is already positioned at the end of
24.135 + * data written by the corresponding writeExternal method, object reads will
24.136 + * throw OptionalDataExceptions with eof set to true, bytewise reads will
24.137 + * return -1, and primitive reads will throw EOFExceptions. Note that this
24.138 + * behavior does not hold for streams written with the old
24.139 + * <code>ObjectStreamConstants.PROTOCOL_VERSION_1</code> protocol, in which the
24.140 + * end of data written by writeExternal methods is not demarcated, and hence
24.141 + * cannot be detected.
24.142 + *
24.143 + * <p>The readObjectNoData method is responsible for initializing the state of
24.144 + * the object for its particular class in the event that the serialization
24.145 + * stream does not list the given class as a superclass of the object being
24.146 + * deserialized. This may occur in cases where the receiving party uses a
24.147 + * different version of the deserialized instance's class than the sending
24.148 + * party, and the receiver's version extends classes that are not extended by
24.149 + * the sender's version. This may also occur if the serialization stream has
24.150 + * been tampered; hence, readObjectNoData is useful for initializing
24.151 + * deserialized objects properly despite a "hostile" or incomplete source
24.152 + * stream.
24.153 + *
24.154 + * <p>Serialization does not read or assign values to the fields of any object
24.155 + * that does not implement the java.io.Serializable interface. Subclasses of
24.156 + * Objects that are not serializable can be serializable. In this case the
24.157 + * non-serializable class must have a no-arg constructor to allow its fields to
24.158 + * be initialized. In this case it is the responsibility of the subclass to
24.159 + * save and restore the state of the non-serializable class. It is frequently
24.160 + * the case that the fields of that class are accessible (public, package, or
24.161 + * protected) or that there are get and set methods that can be used to restore
24.162 + * the state.
24.163 + *
24.164 + * <p>Any exception that occurs while deserializing an object will be caught by
24.165 + * the ObjectInputStream and abort the reading process.
24.166 + *
24.167 + * <p>Implementing the Externalizable interface allows the object to assume
24.168 + * complete control over the contents and format of the object's serialized
24.169 + * form. The methods of the Externalizable interface, writeExternal and
24.170 + * readExternal, are called to save and restore the objects state. When
24.171 + * implemented by a class they can write and read their own state using all of
24.172 + * the methods of ObjectOutput and ObjectInput. It is the responsibility of
24.173 + * the objects to handle any versioning that occurs.
24.174 + *
24.175 + * <p>Enum constants are deserialized differently than ordinary serializable or
24.176 + * externalizable objects. The serialized form of an enum constant consists
24.177 + * solely of its name; field values of the constant are not transmitted. To
24.178 + * deserialize an enum constant, ObjectInputStream reads the constant name from
24.179 + * the stream; the deserialized constant is then obtained by calling the static
24.180 + * method <code>Enum.valueOf(Class, String)</code> with the enum constant's
24.181 + * base type and the received constant name as arguments. Like other
24.182 + * serializable or externalizable objects, enum constants can function as the
24.183 + * targets of back references appearing subsequently in the serialization
24.184 + * stream. The process by which enum constants are deserialized cannot be
24.185 + * customized: any class-specific readObject, readObjectNoData, and readResolve
24.186 + * methods defined by enum types are ignored during deserialization.
24.187 + * Similarly, any serialPersistentFields or serialVersionUID field declarations
24.188 + * are also ignored--all enum types have a fixed serialVersionUID of 0L.
24.189 + *
24.190 + * @author Mike Warres
24.191 + * @author Roger Riggs
24.192 + * @see java.io.DataInput
24.193 + * @see java.io.ObjectOutputStream
24.194 + * @see java.io.Serializable
24.195 + * @see <a href="../../../platform/serialization/spec/input.html"> Object Serialization Specification, Section 3, Object Input Classes</a>
24.196 + * @since JDK1.1
24.197 + */
24.198 +public class ObjectInputStream
24.199 + extends InputStream implements ObjectInput, ObjectStreamConstants
24.200 +{
24.201 + /** handle value representing null */
24.202 + private static final int NULL_HANDLE = -1;
24.203 +
24.204 + /** marker for unshared objects in internal handle table */
24.205 + private static final Object unsharedMarker = new Object();
24.206 +
24.207 + /** table mapping primitive type names to corresponding class objects */
24.208 + private static final HashMap<String, Class<?>> primClasses
24.209 + = new HashMap<>(8, 1.0F);
24.210 + static {
24.211 + primClasses.put("boolean", boolean.class);
24.212 + primClasses.put("byte", byte.class);
24.213 + primClasses.put("char", char.class);
24.214 + primClasses.put("short", short.class);
24.215 + primClasses.put("int", int.class);
24.216 + primClasses.put("long", long.class);
24.217 + primClasses.put("float", float.class);
24.218 + primClasses.put("double", double.class);
24.219 + primClasses.put("void", void.class);
24.220 + }
24.221 +
24.222 + /** filter stream for handling block data conversion */
24.223 + private final BlockDataInputStream bin;
24.224 + /** validation callback list */
24.225 + private final ValidationList vlist;
24.226 + /** recursion depth */
24.227 + private int depth;
24.228 + /** whether stream is closed */
24.229 + private boolean closed;
24.230 +
24.231 + /** wire handle -> obj/exception map */
24.232 + private final HandleTable handles;
24.233 + /** scratch field for passing handle values up/down call stack */
24.234 + private int passHandle = NULL_HANDLE;
24.235 + /** flag set when at end of field value block with no TC_ENDBLOCKDATA */
24.236 + private boolean defaultDataEnd = false;
24.237 +
24.238 + /** buffer for reading primitive field values */
24.239 + private byte[] primVals;
24.240 +
24.241 + /** if true, invoke readObjectOverride() instead of readObject() */
24.242 + private final boolean enableOverride;
24.243 + /** if true, invoke resolveObject() */
24.244 + private boolean enableResolve;
24.245 +
24.246 + /**
24.247 + * Context during upcalls to class-defined readObject methods; holds
24.248 + * object currently being deserialized and descriptor for current class.
24.249 + * Null when not during readObject upcall.
24.250 + */
24.251 + private Object curContext;
24.252 +
24.253 + /**
24.254 + * Creates an ObjectInputStream that reads from the specified InputStream.
24.255 + * A serialization stream header is read from the stream and verified.
24.256 + * This constructor will block until the corresponding ObjectOutputStream
24.257 + * has written and flushed the header.
24.258 + *
24.259 + * <p>If a security manager is installed, this constructor will check for
24.260 + * the "enableSubclassImplementation" SerializablePermission when invoked
24.261 + * directly or indirectly by the constructor of a subclass which overrides
24.262 + * the ObjectInputStream.readFields or ObjectInputStream.readUnshared
24.263 + * methods.
24.264 + *
24.265 + * @param in input stream to read from
24.266 + * @throws StreamCorruptedException if the stream header is incorrect
24.267 + * @throws IOException if an I/O error occurs while reading stream header
24.268 + * @throws SecurityException if untrusted subclass illegally overrides
24.269 + * security-sensitive methods
24.270 + * @throws NullPointerException if <code>in</code> is <code>null</code>
24.271 + * @see ObjectInputStream#ObjectInputStream()
24.272 + * @see ObjectInputStream#readFields()
24.273 + * @see ObjectOutputStream#ObjectOutputStream(OutputStream)
24.274 + */
24.275 + public ObjectInputStream(InputStream in) throws IOException {
24.276 + verifySubclass();
24.277 + bin = new BlockDataInputStream(in);
24.278 + handles = new HandleTable(10);
24.279 + vlist = new ValidationList();
24.280 + enableOverride = false;
24.281 + readStreamHeader();
24.282 + bin.setBlockDataMode(true);
24.283 + }
24.284 +
24.285 + /**
24.286 + * Provide a way for subclasses that are completely reimplementing
24.287 + * ObjectInputStream to not have to allocate private data just used by this
24.288 + * implementation of ObjectInputStream.
24.289 + *
24.290 + * <p>If there is a security manager installed, this method first calls the
24.291 + * security manager's <code>checkPermission</code> method with the
24.292 + * <code>SerializablePermission("enableSubclassImplementation")</code>
24.293 + * permission to ensure it's ok to enable subclassing.
24.294 + *
24.295 + * @throws SecurityException if a security manager exists and its
24.296 + * <code>checkPermission</code> method denies enabling
24.297 + * subclassing.
24.298 + * @see SecurityManager#checkPermission
24.299 + * @see java.io.SerializablePermission
24.300 + */
24.301 + protected ObjectInputStream() throws IOException, SecurityException {
24.302 + throw new SecurityException();
24.303 + }
24.304 +
24.305 + /**
24.306 + * Read an object from the ObjectInputStream. The class of the object, the
24.307 + * signature of the class, and the values of the non-transient and
24.308 + * non-static fields of the class and all of its supertypes are read.
24.309 + * Default deserializing for a class can be overriden using the writeObject
24.310 + * and readObject methods. Objects referenced by this object are read
24.311 + * transitively so that a complete equivalent graph of objects is
24.312 + * reconstructed by readObject.
24.313 + *
24.314 + * <p>The root object is completely restored when all of its fields and the
24.315 + * objects it references are completely restored. At this point the object
24.316 + * validation callbacks are executed in order based on their registered
24.317 + * priorities. The callbacks are registered by objects (in the readObject
24.318 + * special methods) as they are individually restored.
24.319 + *
24.320 + * <p>Exceptions are thrown for problems with the InputStream and for
24.321 + * classes that should not be deserialized. All exceptions are fatal to
24.322 + * the InputStream and leave it in an indeterminate state; it is up to the
24.323 + * caller to ignore or recover the stream state.
24.324 + *
24.325 + * @throws ClassNotFoundException Class of a serialized object cannot be
24.326 + * found.
24.327 + * @throws InvalidClassException Something is wrong with a class used by
24.328 + * serialization.
24.329 + * @throws StreamCorruptedException Control information in the
24.330 + * stream is inconsistent.
24.331 + * @throws OptionalDataException Primitive data was found in the
24.332 + * stream instead of objects.
24.333 + * @throws IOException Any of the usual Input/Output related exceptions.
24.334 + */
24.335 + public final Object readObject()
24.336 + throws IOException, ClassNotFoundException
24.337 + {
24.338 + throw new IOException();
24.339 + }
24.340 +
24.341 + /**
24.342 + * This method is called by trusted subclasses of ObjectOutputStream that
24.343 + * constructed ObjectOutputStream using the protected no-arg constructor.
24.344 + * The subclass is expected to provide an override method with the modifier
24.345 + * "final".
24.346 + *
24.347 + * @return the Object read from the stream.
24.348 + * @throws ClassNotFoundException Class definition of a serialized object
24.349 + * cannot be found.
24.350 + * @throws OptionalDataException Primitive data was found in the stream
24.351 + * instead of objects.
24.352 + * @throws IOException if I/O errors occurred while reading from the
24.353 + * underlying stream
24.354 + * @see #ObjectInputStream()
24.355 + * @see #readObject()
24.356 + * @since 1.2
24.357 + */
24.358 + protected Object readObjectOverride()
24.359 + throws IOException, ClassNotFoundException
24.360 + {
24.361 + return null;
24.362 + }
24.363 +
24.364 + /**
24.365 + * Reads an "unshared" object from the ObjectInputStream. This method is
24.366 + * identical to readObject, except that it prevents subsequent calls to
24.367 + * readObject and readUnshared from returning additional references to the
24.368 + * deserialized instance obtained via this call. Specifically:
24.369 + * <ul>
24.370 + * <li>If readUnshared is called to deserialize a back-reference (the
24.371 + * stream representation of an object which has been written
24.372 + * previously to the stream), an ObjectStreamException will be
24.373 + * thrown.
24.374 + *
24.375 + * <li>If readUnshared returns successfully, then any subsequent attempts
24.376 + * to deserialize back-references to the stream handle deserialized
24.377 + * by readUnshared will cause an ObjectStreamException to be thrown.
24.378 + * </ul>
24.379 + * Deserializing an object via readUnshared invalidates the stream handle
24.380 + * associated with the returned object. Note that this in itself does not
24.381 + * always guarantee that the reference returned by readUnshared is unique;
24.382 + * the deserialized object may define a readResolve method which returns an
24.383 + * object visible to other parties, or readUnshared may return a Class
24.384 + * object or enum constant obtainable elsewhere in the stream or through
24.385 + * external means. If the deserialized object defines a readResolve method
24.386 + * and the invocation of that method returns an array, then readUnshared
24.387 + * returns a shallow clone of that array; this guarantees that the returned
24.388 + * array object is unique and cannot be obtained a second time from an
24.389 + * invocation of readObject or readUnshared on the ObjectInputStream,
24.390 + * even if the underlying data stream has been manipulated.
24.391 + *
24.392 + * <p>ObjectInputStream subclasses which override this method can only be
24.393 + * constructed in security contexts possessing the
24.394 + * "enableSubclassImplementation" SerializablePermission; any attempt to
24.395 + * instantiate such a subclass without this permission will cause a
24.396 + * SecurityException to be thrown.
24.397 + *
24.398 + * @return reference to deserialized object
24.399 + * @throws ClassNotFoundException if class of an object to deserialize
24.400 + * cannot be found
24.401 + * @throws StreamCorruptedException if control information in the stream
24.402 + * is inconsistent
24.403 + * @throws ObjectStreamException if object to deserialize has already
24.404 + * appeared in stream
24.405 + * @throws OptionalDataException if primitive data is next in stream
24.406 + * @throws IOException if an I/O error occurs during deserialization
24.407 + * @since 1.4
24.408 + */
24.409 + public Object readUnshared() throws IOException, ClassNotFoundException {
24.410 + // if nested read, passHandle contains handle of enclosing object
24.411 + int outerHandle = passHandle;
24.412 + try {
24.413 + Object obj = readObject0(true);
24.414 + handles.markDependency(outerHandle, passHandle);
24.415 + ClassNotFoundException ex = handles.lookupException(passHandle);
24.416 + if (ex != null) {
24.417 + throw ex;
24.418 + }
24.419 + if (depth == 0) {
24.420 + vlist.doCallbacks();
24.421 + }
24.422 + return obj;
24.423 + } finally {
24.424 + passHandle = outerHandle;
24.425 + if (closed && depth == 0) {
24.426 + clear();
24.427 + }
24.428 + }
24.429 + }
24.430 +
24.431 + /**
24.432 + * Read the non-static and non-transient fields of the current class from
24.433 + * this stream. This may only be called from the readObject method of the
24.434 + * class being deserialized. It will throw the NotActiveException if it is
24.435 + * called otherwise.
24.436 + *
24.437 + * @throws ClassNotFoundException if the class of a serialized object
24.438 + * could not be found.
24.439 + * @throws IOException if an I/O error occurs.
24.440 + * @throws NotActiveException if the stream is not currently reading
24.441 + * objects.
24.442 + */
24.443 + public void defaultReadObject()
24.444 + throws IOException, ClassNotFoundException
24.445 + {
24.446 + if (curContext == null) {
24.447 + throw new NotActiveException("not in call to readObject");
24.448 + }
24.449 + Object curObj = null; // curContext.getObj();
24.450 + ObjectStreamClass curDesc = null; // curContext.getDesc();
24.451 + bin.setBlockDataMode(false);
24.452 + defaultReadFields(curObj, curDesc);
24.453 + bin.setBlockDataMode(true);
24.454 + if (!curDesc.hasWriteObjectData()) {
24.455 + /*
24.456 + * Fix for 4360508: since stream does not contain terminating
24.457 + * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
24.458 + * knows to simulate end-of-custom-data behavior.
24.459 + */
24.460 + defaultDataEnd = true;
24.461 + }
24.462 + ClassNotFoundException ex = handles.lookupException(passHandle);
24.463 + if (ex != null) {
24.464 + throw ex;
24.465 + }
24.466 + }
24.467 +
24.468 + /**
24.469 + * Reads the persistent fields from the stream and makes them available by
24.470 + * name.
24.471 + *
24.472 + * @return the <code>GetField</code> object representing the persistent
24.473 + * fields of the object being deserialized
24.474 + * @throws ClassNotFoundException if the class of a serialized object
24.475 + * could not be found.
24.476 + * @throws IOException if an I/O error occurs.
24.477 + * @throws NotActiveException if the stream is not currently reading
24.478 + * objects.
24.479 + * @since 1.2
24.480 + */
24.481 + public ObjectInputStream.GetField readFields()
24.482 + throws IOException, ClassNotFoundException
24.483 + {
24.484 + if (curContext == null) {
24.485 + throw new NotActiveException("not in call to readObject");
24.486 + }
24.487 + Object curObj = null; // curContext.getObj();
24.488 + ObjectStreamClass curDesc = null; // curContext.getDesc();
24.489 + bin.setBlockDataMode(false);
24.490 + GetFieldImpl getField = new GetFieldImpl(curDesc);
24.491 + getField.readFields();
24.492 + bin.setBlockDataMode(true);
24.493 + if (!curDesc.hasWriteObjectData()) {
24.494 + /*
24.495 + * Fix for 4360508: since stream does not contain terminating
24.496 + * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
24.497 + * knows to simulate end-of-custom-data behavior.
24.498 + */
24.499 + defaultDataEnd = true;
24.500 + }
24.501 +
24.502 + return getField;
24.503 + }
24.504 +
24.505 + /**
24.506 + * Register an object to be validated before the graph is returned. While
24.507 + * similar to resolveObject these validations are called after the entire
24.508 + * graph has been reconstituted. Typically, a readObject method will
24.509 + * register the object with the stream so that when all of the objects are
24.510 + * restored a final set of validations can be performed.
24.511 + *
24.512 + * @param obj the object to receive the validation callback.
24.513 + * @param prio controls the order of callbacks;zero is a good default.
24.514 + * Use higher numbers to be called back earlier, lower numbers for
24.515 + * later callbacks. Within a priority, callbacks are processed in
24.516 + * no particular order.
24.517 + * @throws NotActiveException The stream is not currently reading objects
24.518 + * so it is invalid to register a callback.
24.519 + * @throws InvalidObjectException The validation object is null.
24.520 + */
24.521 + public void registerValidation(ObjectInputValidation obj, int prio)
24.522 + throws NotActiveException, InvalidObjectException
24.523 + {
24.524 + if (depth == 0) {
24.525 + throw new NotActiveException("stream inactive");
24.526 + }
24.527 + vlist.register(obj, prio);
24.528 + }
24.529 +
24.530 + /**
24.531 + * Load the local class equivalent of the specified stream class
24.532 + * description. Subclasses may implement this method to allow classes to
24.533 + * be fetched from an alternate source.
24.534 + *
24.535 + * <p>The corresponding method in <code>ObjectOutputStream</code> is
24.536 + * <code>annotateClass</code>. This method will be invoked only once for
24.537 + * each unique class in the stream. This method can be implemented by
24.538 + * subclasses to use an alternate loading mechanism but must return a
24.539 + * <code>Class</code> object. Once returned, if the class is not an array
24.540 + * class, its serialVersionUID is compared to the serialVersionUID of the
24.541 + * serialized class, and if there is a mismatch, the deserialization fails
24.542 + * and an {@link InvalidClassException} is thrown.
24.543 + *
24.544 + * <p>The default implementation of this method in
24.545 + * <code>ObjectInputStream</code> returns the result of calling
24.546 + * <pre>
24.547 + * Class.forName(desc.getName(), false, loader)
24.548 + * </pre>
24.549 + * where <code>loader</code> is determined as follows: if there is a
24.550 + * method on the current thread's stack whose declaring class was
24.551 + * defined by a user-defined class loader (and was not a generated to
24.552 + * implement reflective invocations), then <code>loader</code> is class
24.553 + * loader corresponding to the closest such method to the currently
24.554 + * executing frame; otherwise, <code>loader</code> is
24.555 + * <code>null</code>. If this call results in a
24.556 + * <code>ClassNotFoundException</code> and the name of the passed
24.557 + * <code>ObjectStreamClass</code> instance is the Java language keyword
24.558 + * for a primitive type or void, then the <code>Class</code> object
24.559 + * representing that primitive type or void will be returned
24.560 + * (e.g., an <code>ObjectStreamClass</code> with the name
24.561 + * <code>"int"</code> will be resolved to <code>Integer.TYPE</code>).
24.562 + * Otherwise, the <code>ClassNotFoundException</code> will be thrown to
24.563 + * the caller of this method.
24.564 + *
24.565 + * @param desc an instance of class <code>ObjectStreamClass</code>
24.566 + * @return a <code>Class</code> object corresponding to <code>desc</code>
24.567 + * @throws IOException any of the usual Input/Output exceptions.
24.568 + * @throws ClassNotFoundException if class of a serialized object cannot
24.569 + * be found.
24.570 + */
24.571 + protected Class<?> resolveClass(ObjectStreamClass desc)
24.572 + throws IOException, ClassNotFoundException
24.573 + {
24.574 + String name = desc.getName();
24.575 + try {
24.576 + return Class.forName(name, false, latestUserDefinedLoader());
24.577 + } catch (ClassNotFoundException ex) {
24.578 + Class<?> cl = primClasses.get(name);
24.579 + if (cl != null) {
24.580 + return cl;
24.581 + } else {
24.582 + throw ex;
24.583 + }
24.584 + }
24.585 + }
24.586 +
24.587 + /**
24.588 + * Returns a proxy class that implements the interfaces named in a proxy
24.589 + * class descriptor; subclasses may implement this method to read custom
24.590 + * data from the stream along with the descriptors for dynamic proxy
24.591 + * classes, allowing them to use an alternate loading mechanism for the
24.592 + * interfaces and the proxy class.
24.593 + *
24.594 + * <p>This method is called exactly once for each unique proxy class
24.595 + * descriptor in the stream.
24.596 + *
24.597 + * <p>The corresponding method in <code>ObjectOutputStream</code> is
24.598 + * <code>annotateProxyClass</code>. For a given subclass of
24.599 + * <code>ObjectInputStream</code> that overrides this method, the
24.600 + * <code>annotateProxyClass</code> method in the corresponding subclass of
24.601 + * <code>ObjectOutputStream</code> must write any data or objects read by
24.602 + * this method.
24.603 + *
24.604 + * <p>The default implementation of this method in
24.605 + * <code>ObjectInputStream</code> returns the result of calling
24.606 + * <code>Proxy.getProxyClass</code> with the list of <code>Class</code>
24.607 + * objects for the interfaces that are named in the <code>interfaces</code>
24.608 + * parameter. The <code>Class</code> object for each interface name
24.609 + * <code>i</code> is the value returned by calling
24.610 + * <pre>
24.611 + * Class.forName(i, false, loader)
24.612 + * </pre>
24.613 + * where <code>loader</code> is that of the first non-<code>null</code>
24.614 + * class loader up the execution stack, or <code>null</code> if no
24.615 + * non-<code>null</code> class loaders are on the stack (the same class
24.616 + * loader choice used by the <code>resolveClass</code> method). Unless any
24.617 + * of the resolved interfaces are non-public, this same value of
24.618 + * <code>loader</code> is also the class loader passed to
24.619 + * <code>Proxy.getProxyClass</code>; if non-public interfaces are present,
24.620 + * their class loader is passed instead (if more than one non-public
24.621 + * interface class loader is encountered, an
24.622 + * <code>IllegalAccessError</code> is thrown).
24.623 + * If <code>Proxy.getProxyClass</code> throws an
24.624 + * <code>IllegalArgumentException</code>, <code>resolveProxyClass</code>
24.625 + * will throw a <code>ClassNotFoundException</code> containing the
24.626 + * <code>IllegalArgumentException</code>.
24.627 + *
24.628 + * @param interfaces the list of interface names that were
24.629 + * deserialized in the proxy class descriptor
24.630 + * @return a proxy class for the specified interfaces
24.631 + * @throws IOException any exception thrown by the underlying
24.632 + * <code>InputStream</code>
24.633 + * @throws ClassNotFoundException if the proxy class or any of the
24.634 + * named interfaces could not be found
24.635 + * @see ObjectOutputStream#annotateProxyClass(Class)
24.636 + * @since 1.3
24.637 + */
24.638 + protected Class<?> resolveProxyClass(String[] interfaces)
24.639 + throws IOException, ClassNotFoundException
24.640 + {
24.641 + ClassLoader latestLoader = latestUserDefinedLoader();
24.642 + ClassLoader nonPublicLoader = null;
24.643 + boolean hasNonPublicInterface = false;
24.644 +
24.645 + // define proxy in class loader of non-public interface(s), if any
24.646 + Class[] classObjs = new Class[interfaces.length];
24.647 + for (int i = 0; i < interfaces.length; i++) {
24.648 + Class cl = Class.forName(interfaces[i], false, latestLoader);
24.649 + if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
24.650 + if (hasNonPublicInterface) {
24.651 + if (nonPublicLoader != cl.getClassLoader()) {
24.652 + throw new IllegalAccessError(
24.653 + "conflicting non-public interface class loaders");
24.654 + }
24.655 + } else {
24.656 + nonPublicLoader = cl.getClassLoader();
24.657 + hasNonPublicInterface = true;
24.658 + }
24.659 + }
24.660 + classObjs[i] = cl;
24.661 + }
24.662 + try {
24.663 + return Proxy.getProxyClass(
24.664 + hasNonPublicInterface ? nonPublicLoader : latestLoader,
24.665 + classObjs);
24.666 + } catch (IllegalArgumentException e) {
24.667 + throw new ClassNotFoundException(null, e);
24.668 + }
24.669 + }
24.670 +
24.671 + /**
24.672 + * This method will allow trusted subclasses of ObjectInputStream to
24.673 + * substitute one object for another during deserialization. Replacing
24.674 + * objects is disabled until enableResolveObject is called. The
24.675 + * enableResolveObject method checks that the stream requesting to resolve
24.676 + * object can be trusted. Every reference to serializable objects is passed
24.677 + * to resolveObject. To insure that the private state of objects is not
24.678 + * unintentionally exposed only trusted streams may use resolveObject.
24.679 + *
24.680 + * <p>This method is called after an object has been read but before it is
24.681 + * returned from readObject. The default resolveObject method just returns
24.682 + * the same object.
24.683 + *
24.684 + * <p>When a subclass is replacing objects it must insure that the
24.685 + * substituted object is compatible with every field where the reference
24.686 + * will be stored. Objects whose type is not a subclass of the type of the
24.687 + * field or array element abort the serialization by raising an exception
24.688 + * and the object is not be stored.
24.689 + *
24.690 + * <p>This method is called only once when each object is first
24.691 + * encountered. All subsequent references to the object will be redirected
24.692 + * to the new object.
24.693 + *
24.694 + * @param obj object to be substituted
24.695 + * @return the substituted object
24.696 + * @throws IOException Any of the usual Input/Output exceptions.
24.697 + */
24.698 + protected Object resolveObject(Object obj) throws IOException {
24.699 + return obj;
24.700 + }
24.701 +
24.702 + /**
24.703 + * Enable the stream to allow objects read from the stream to be replaced.
24.704 + * When enabled, the resolveObject method is called for every object being
24.705 + * deserialized.
24.706 + *
24.707 + * <p>If <i>enable</i> is true, and there is a security manager installed,
24.708 + * this method first calls the security manager's
24.709 + * <code>checkPermission</code> method with the
24.710 + * <code>SerializablePermission("enableSubstitution")</code> permission to
24.711 + * ensure it's ok to enable the stream to allow objects read from the
24.712 + * stream to be replaced.
24.713 + *
24.714 + * @param enable true for enabling use of <code>resolveObject</code> for
24.715 + * every object being deserialized
24.716 + * @return the previous setting before this method was invoked
24.717 + * @throws SecurityException if a security manager exists and its
24.718 + * <code>checkPermission</code> method denies enabling the stream
24.719 + * to allow objects read from the stream to be replaced.
24.720 + * @see SecurityManager#checkPermission
24.721 + * @see java.io.SerializablePermission
24.722 + */
24.723 + protected boolean enableResolveObject(boolean enable)
24.724 + throws SecurityException
24.725 + {
24.726 + throw new SecurityException();
24.727 + }
24.728 +
24.729 + /**
24.730 + * The readStreamHeader method is provided to allow subclasses to read and
24.731 + * verify their own stream headers. It reads and verifies the magic number
24.732 + * and version number.
24.733 + *
24.734 + * @throws IOException if there are I/O errors while reading from the
24.735 + * underlying <code>InputStream</code>
24.736 + * @throws StreamCorruptedException if control information in the stream
24.737 + * is inconsistent
24.738 + */
24.739 + protected void readStreamHeader()
24.740 + throws IOException, StreamCorruptedException
24.741 + {
24.742 + short s0 = bin.readShort();
24.743 + short s1 = bin.readShort();
24.744 + if (s0 != STREAM_MAGIC || s1 != STREAM_VERSION) {
24.745 + throw new StreamCorruptedException(
24.746 + String.format("invalid stream header: %04X%04X", s0, s1));
24.747 + }
24.748 + }
24.749 +
24.750 + /**
24.751 + * Read a class descriptor from the serialization stream. This method is
24.752 + * called when the ObjectInputStream expects a class descriptor as the next
24.753 + * item in the serialization stream. Subclasses of ObjectInputStream may
24.754 + * override this method to read in class descriptors that have been written
24.755 + * in non-standard formats (by subclasses of ObjectOutputStream which have
24.756 + * overridden the <code>writeClassDescriptor</code> method). By default,
24.757 + * this method reads class descriptors according to the format defined in
24.758 + * the Object Serialization specification.
24.759 + *
24.760 + * @return the class descriptor read
24.761 + * @throws IOException If an I/O error has occurred.
24.762 + * @throws ClassNotFoundException If the Class of a serialized object used
24.763 + * in the class descriptor representation cannot be found
24.764 + * @see java.io.ObjectOutputStream#writeClassDescriptor(java.io.ObjectStreamClass)
24.765 + * @since 1.3
24.766 + */
24.767 + protected ObjectStreamClass readClassDescriptor()
24.768 + throws IOException, ClassNotFoundException
24.769 + {
24.770 + ObjectStreamClass desc = new ObjectStreamClass();
24.771 + desc.readNonProxy(this);
24.772 + return desc;
24.773 + }
24.774 +
24.775 + /**
24.776 + * Reads a byte of data. This method will block if no input is available.
24.777 + *
24.778 + * @return the byte read, or -1 if the end of the stream is reached.
24.779 + * @throws IOException If an I/O error has occurred.
24.780 + */
24.781 + public int read() throws IOException {
24.782 + return bin.read();
24.783 + }
24.784 +
24.785 + /**
24.786 + * Reads into an array of bytes. This method will block until some input
24.787 + * is available. Consider using java.io.DataInputStream.readFully to read
24.788 + * exactly 'length' bytes.
24.789 + *
24.790 + * @param buf the buffer into which the data is read
24.791 + * @param off the start offset of the data
24.792 + * @param len the maximum number of bytes read
24.793 + * @return the actual number of bytes read, -1 is returned when the end of
24.794 + * the stream is reached.
24.795 + * @throws IOException If an I/O error has occurred.
24.796 + * @see java.io.DataInputStream#readFully(byte[],int,int)
24.797 + */
24.798 + public int read(byte[] buf, int off, int len) throws IOException {
24.799 + if (buf == null) {
24.800 + throw new NullPointerException();
24.801 + }
24.802 + int endoff = off + len;
24.803 + if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
24.804 + throw new IndexOutOfBoundsException();
24.805 + }
24.806 + return bin.read(buf, off, len, false);
24.807 + }
24.808 +
24.809 + /**
24.810 + * Returns the number of bytes that can be read without blocking.
24.811 + *
24.812 + * @return the number of available bytes.
24.813 + * @throws IOException if there are I/O errors while reading from the
24.814 + * underlying <code>InputStream</code>
24.815 + */
24.816 + public int available() throws IOException {
24.817 + return bin.available();
24.818 + }
24.819 +
24.820 + /**
24.821 + * Closes the input stream. Must be called to release any resources
24.822 + * associated with the stream.
24.823 + *
24.824 + * @throws IOException If an I/O error has occurred.
24.825 + */
24.826 + public void close() throws IOException {
24.827 + /*
24.828 + * Even if stream already closed, propagate redundant close to
24.829 + * underlying stream to stay consistent with previous implementations.
24.830 + */
24.831 + closed = true;
24.832 + if (depth == 0) {
24.833 + clear();
24.834 + }
24.835 + bin.close();
24.836 + }
24.837 +
24.838 + /**
24.839 + * Reads in a boolean.
24.840 + *
24.841 + * @return the boolean read.
24.842 + * @throws EOFException If end of file is reached.
24.843 + * @throws IOException If other I/O error has occurred.
24.844 + */
24.845 + public boolean readBoolean() throws IOException {
24.846 + return bin.readBoolean();
24.847 + }
24.848 +
24.849 + /**
24.850 + * Reads an 8 bit byte.
24.851 + *
24.852 + * @return the 8 bit byte read.
24.853 + * @throws EOFException If end of file is reached.
24.854 + * @throws IOException If other I/O error has occurred.
24.855 + */
24.856 + public byte readByte() throws IOException {
24.857 + return bin.readByte();
24.858 + }
24.859 +
24.860 + /**
24.861 + * Reads an unsigned 8 bit byte.
24.862 + *
24.863 + * @return the 8 bit byte read.
24.864 + * @throws EOFException If end of file is reached.
24.865 + * @throws IOException If other I/O error has occurred.
24.866 + */
24.867 + public int readUnsignedByte() throws IOException {
24.868 + return bin.readUnsignedByte();
24.869 + }
24.870 +
24.871 + /**
24.872 + * Reads a 16 bit char.
24.873 + *
24.874 + * @return the 16 bit char read.
24.875 + * @throws EOFException If end of file is reached.
24.876 + * @throws IOException If other I/O error has occurred.
24.877 + */
24.878 + public char readChar() throws IOException {
24.879 + return bin.readChar();
24.880 + }
24.881 +
24.882 + /**
24.883 + * Reads a 16 bit short.
24.884 + *
24.885 + * @return the 16 bit short read.
24.886 + * @throws EOFException If end of file is reached.
24.887 + * @throws IOException If other I/O error has occurred.
24.888 + */
24.889 + public short readShort() throws IOException {
24.890 + return bin.readShort();
24.891 + }
24.892 +
24.893 + /**
24.894 + * Reads an unsigned 16 bit short.
24.895 + *
24.896 + * @return the 16 bit short read.
24.897 + * @throws EOFException If end of file is reached.
24.898 + * @throws IOException If other I/O error has occurred.
24.899 + */
24.900 + public int readUnsignedShort() throws IOException {
24.901 + return bin.readUnsignedShort();
24.902 + }
24.903 +
24.904 + /**
24.905 + * Reads a 32 bit int.
24.906 + *
24.907 + * @return the 32 bit integer read.
24.908 + * @throws EOFException If end of file is reached.
24.909 + * @throws IOException If other I/O error has occurred.
24.910 + */
24.911 + public int readInt() throws IOException {
24.912 + return bin.readInt();
24.913 + }
24.914 +
24.915 + /**
24.916 + * Reads a 64 bit long.
24.917 + *
24.918 + * @return the read 64 bit long.
24.919 + * @throws EOFException If end of file is reached.
24.920 + * @throws IOException If other I/O error has occurred.
24.921 + */
24.922 + public long readLong() throws IOException {
24.923 + return bin.readLong();
24.924 + }
24.925 +
24.926 + /**
24.927 + * Reads a 32 bit float.
24.928 + *
24.929 + * @return the 32 bit float read.
24.930 + * @throws EOFException If end of file is reached.
24.931 + * @throws IOException If other I/O error has occurred.
24.932 + */
24.933 + public float readFloat() throws IOException {
24.934 + return bin.readFloat();
24.935 + }
24.936 +
24.937 + /**
24.938 + * Reads a 64 bit double.
24.939 + *
24.940 + * @return the 64 bit double read.
24.941 + * @throws EOFException If end of file is reached.
24.942 + * @throws IOException If other I/O error has occurred.
24.943 + */
24.944 + public double readDouble() throws IOException {
24.945 + return bin.readDouble();
24.946 + }
24.947 +
24.948 + /**
24.949 + * Reads bytes, blocking until all bytes are read.
24.950 + *
24.951 + * @param buf the buffer into which the data is read
24.952 + * @throws EOFException If end of file is reached.
24.953 + * @throws IOException If other I/O error has occurred.
24.954 + */
24.955 + public void readFully(byte[] buf) throws IOException {
24.956 + bin.readFully(buf, 0, buf.length, false);
24.957 + }
24.958 +
24.959 + /**
24.960 + * Reads bytes, blocking until all bytes are read.
24.961 + *
24.962 + * @param buf the buffer into which the data is read
24.963 + * @param off the start offset of the data
24.964 + * @param len the maximum number of bytes to read
24.965 + * @throws EOFException If end of file is reached.
24.966 + * @throws IOException If other I/O error has occurred.
24.967 + */
24.968 + public void readFully(byte[] buf, int off, int len) throws IOException {
24.969 + int endoff = off + len;
24.970 + if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
24.971 + throw new IndexOutOfBoundsException();
24.972 + }
24.973 + bin.readFully(buf, off, len, false);
24.974 + }
24.975 +
24.976 + /**
24.977 + * Skips bytes.
24.978 + *
24.979 + * @param len the number of bytes to be skipped
24.980 + * @return the actual number of bytes skipped.
24.981 + * @throws IOException If an I/O error has occurred.
24.982 + */
24.983 + public int skipBytes(int len) throws IOException {
24.984 + return bin.skipBytes(len);
24.985 + }
24.986 +
24.987 + /**
24.988 + * Reads in a line that has been terminated by a \n, \r, \r\n or EOF.
24.989 + *
24.990 + * @return a String copy of the line.
24.991 + * @throws IOException if there are I/O errors while reading from the
24.992 + * underlying <code>InputStream</code>
24.993 + * @deprecated This method does not properly convert bytes to characters.
24.994 + * see DataInputStream for the details and alternatives.
24.995 + */
24.996 + @Deprecated
24.997 + public String readLine() throws IOException {
24.998 + return bin.readLine();
24.999 + }
24.1000 +
24.1001 + /**
24.1002 + * Reads a String in
24.1003 + * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
24.1004 + * format.
24.1005 + *
24.1006 + * @return the String.
24.1007 + * @throws IOException if there are I/O errors while reading from the
24.1008 + * underlying <code>InputStream</code>
24.1009 + * @throws UTFDataFormatException if read bytes do not represent a valid
24.1010 + * modified UTF-8 encoding of a string
24.1011 + */
24.1012 + public String readUTF() throws IOException {
24.1013 + return bin.readUTF();
24.1014 + }
24.1015 +
24.1016 + /**
24.1017 + * Provide access to the persistent fields read from the input stream.
24.1018 + */
24.1019 + public static abstract class GetField {
24.1020 +
24.1021 + /**
24.1022 + * Get the ObjectStreamClass that describes the fields in the stream.
24.1023 + *
24.1024 + * @return the descriptor class that describes the serializable fields
24.1025 + */
24.1026 + public abstract ObjectStreamClass getObjectStreamClass();
24.1027 +
24.1028 + /**
24.1029 + * Return true if the named field is defaulted and has no value in this
24.1030 + * stream.
24.1031 + *
24.1032 + * @param name the name of the field
24.1033 + * @return true, if and only if the named field is defaulted
24.1034 + * @throws IOException if there are I/O errors while reading from
24.1035 + * the underlying <code>InputStream</code>
24.1036 + * @throws IllegalArgumentException if <code>name</code> does not
24.1037 + * correspond to a serializable field
24.1038 + */
24.1039 + public abstract boolean defaulted(String name) throws IOException;
24.1040 +
24.1041 + /**
24.1042 + * Get the value of the named boolean field from the persistent field.
24.1043 + *
24.1044 + * @param name the name of the field
24.1045 + * @param val the default value to use if <code>name</code> does not
24.1046 + * have a value
24.1047 + * @return the value of the named <code>boolean</code> field
24.1048 + * @throws IOException if there are I/O errors while reading from the
24.1049 + * underlying <code>InputStream</code>
24.1050 + * @throws IllegalArgumentException if type of <code>name</code> is
24.1051 + * not serializable or if the field type is incorrect
24.1052 + */
24.1053 + public abstract boolean get(String name, boolean val)
24.1054 + throws IOException;
24.1055 +
24.1056 + /**
24.1057 + * Get the value of the named byte field from the persistent field.
24.1058 + *
24.1059 + * @param name the name of the field
24.1060 + * @param val the default value to use if <code>name</code> does not
24.1061 + * have a value
24.1062 + * @return the value of the named <code>byte</code> field
24.1063 + * @throws IOException if there are I/O errors while reading from the
24.1064 + * underlying <code>InputStream</code>
24.1065 + * @throws IllegalArgumentException if type of <code>name</code> is
24.1066 + * not serializable or if the field type is incorrect
24.1067 + */
24.1068 + public abstract byte get(String name, byte val) throws IOException;
24.1069 +
24.1070 + /**
24.1071 + * Get the value of the named char field from the persistent field.
24.1072 + *
24.1073 + * @param name the name of the field
24.1074 + * @param val the default value to use if <code>name</code> does not
24.1075 + * have a value
24.1076 + * @return the value of the named <code>char</code> field
24.1077 + * @throws IOException if there are I/O errors while reading from the
24.1078 + * underlying <code>InputStream</code>
24.1079 + * @throws IllegalArgumentException if type of <code>name</code> is
24.1080 + * not serializable or if the field type is incorrect
24.1081 + */
24.1082 + public abstract char get(String name, char val) throws IOException;
24.1083 +
24.1084 + /**
24.1085 + * Get the value of the named short field from the persistent field.
24.1086 + *
24.1087 + * @param name the name of the field
24.1088 + * @param val the default value to use if <code>name</code> does not
24.1089 + * have a value
24.1090 + * @return the value of the named <code>short</code> field
24.1091 + * @throws IOException if there are I/O errors while reading from the
24.1092 + * underlying <code>InputStream</code>
24.1093 + * @throws IllegalArgumentException if type of <code>name</code> is
24.1094 + * not serializable or if the field type is incorrect
24.1095 + */
24.1096 + public abstract short get(String name, short val) throws IOException;
24.1097 +
24.1098 + /**
24.1099 + * Get the value of the named int field from the persistent field.
24.1100 + *
24.1101 + * @param name the name of the field
24.1102 + * @param val the default value to use if <code>name</code> does not
24.1103 + * have a value
24.1104 + * @return the value of the named <code>int</code> field
24.1105 + * @throws IOException if there are I/O errors while reading from the
24.1106 + * underlying <code>InputStream</code>
24.1107 + * @throws IllegalArgumentException if type of <code>name</code> is
24.1108 + * not serializable or if the field type is incorrect
24.1109 + */
24.1110 + public abstract int get(String name, int val) throws IOException;
24.1111 +
24.1112 + /**
24.1113 + * Get the value of the named long field from the persistent field.
24.1114 + *
24.1115 + * @param name the name of the field
24.1116 + * @param val the default value to use if <code>name</code> does not
24.1117 + * have a value
24.1118 + * @return the value of the named <code>long</code> field
24.1119 + * @throws IOException if there are I/O errors while reading from the
24.1120 + * underlying <code>InputStream</code>
24.1121 + * @throws IllegalArgumentException if type of <code>name</code> is
24.1122 + * not serializable or if the field type is incorrect
24.1123 + */
24.1124 + public abstract long get(String name, long val) throws IOException;
24.1125 +
24.1126 + /**
24.1127 + * Get the value of the named float field from the persistent field.
24.1128 + *
24.1129 + * @param name the name of the field
24.1130 + * @param val the default value to use if <code>name</code> does not
24.1131 + * have a value
24.1132 + * @return the value of the named <code>float</code> field
24.1133 + * @throws IOException if there are I/O errors while reading from the
24.1134 + * underlying <code>InputStream</code>
24.1135 + * @throws IllegalArgumentException if type of <code>name</code> is
24.1136 + * not serializable or if the field type is incorrect
24.1137 + */
24.1138 + public abstract float get(String name, float val) throws IOException;
24.1139 +
24.1140 + /**
24.1141 + * Get the value of the named double field from the persistent field.
24.1142 + *
24.1143 + * @param name the name of the field
24.1144 + * @param val the default value to use if <code>name</code> does not
24.1145 + * have a value
24.1146 + * @return the value of the named <code>double</code> field
24.1147 + * @throws IOException if there are I/O errors while reading from the
24.1148 + * underlying <code>InputStream</code>
24.1149 + * @throws IllegalArgumentException if type of <code>name</code> is
24.1150 + * not serializable or if the field type is incorrect
24.1151 + */
24.1152 + public abstract double get(String name, double val) throws IOException;
24.1153 +
24.1154 + /**
24.1155 + * Get the value of the named Object field from the persistent field.
24.1156 + *
24.1157 + * @param name the name of the field
24.1158 + * @param val the default value to use if <code>name</code> does not
24.1159 + * have a value
24.1160 + * @return the value of the named <code>Object</code> field
24.1161 + * @throws IOException if there are I/O errors while reading from the
24.1162 + * underlying <code>InputStream</code>
24.1163 + * @throws IllegalArgumentException if type of <code>name</code> is
24.1164 + * not serializable or if the field type is incorrect
24.1165 + */
24.1166 + public abstract Object get(String name, Object val) throws IOException;
24.1167 + }
24.1168 +
24.1169 + /**
24.1170 + * Verifies that this (possibly subclass) instance can be constructed
24.1171 + * without violating security constraints: the subclass must not override
24.1172 + * security-sensitive non-final methods, or else the
24.1173 + * "enableSubclassImplementation" SerializablePermission is checked.
24.1174 + */
24.1175 + private void verifySubclass() {
24.1176 + Class cl = getClass();
24.1177 + if (cl == ObjectInputStream.class) {
24.1178 + return;
24.1179 + }
24.1180 + throw new SecurityException();
24.1181 + }
24.1182 +
24.1183 + /**
24.1184 + * Clears internal data structures.
24.1185 + */
24.1186 + private void clear() {
24.1187 + handles.clear();
24.1188 + vlist.clear();
24.1189 + }
24.1190 +
24.1191 + /**
24.1192 + * Underlying readObject implementation.
24.1193 + */
24.1194 + private Object readObject0(boolean unshared) throws IOException {
24.1195 + boolean oldMode = bin.getBlockDataMode();
24.1196 + if (oldMode) {
24.1197 + int remain = bin.currentBlockRemaining();
24.1198 + if (remain > 0) {
24.1199 + throw new OptionalDataException(remain);
24.1200 + } else if (defaultDataEnd) {
24.1201 + /*
24.1202 + * Fix for 4360508: stream is currently at the end of a field
24.1203 + * value block written via default serialization; since there
24.1204 + * is no terminating TC_ENDBLOCKDATA tag, simulate
24.1205 + * end-of-custom-data behavior explicitly.
24.1206 + */
24.1207 + throw new OptionalDataException(true);
24.1208 + }
24.1209 + bin.setBlockDataMode(false);
24.1210 + }
24.1211 +
24.1212 + byte tc;
24.1213 + while ((tc = bin.peekByte()) == TC_RESET) {
24.1214 + bin.readByte();
24.1215 + handleReset();
24.1216 + }
24.1217 +
24.1218 + depth++;
24.1219 + try {
24.1220 + switch (tc) {
24.1221 + case TC_NULL:
24.1222 + return readNull();
24.1223 +
24.1224 + case TC_REFERENCE:
24.1225 + return readHandle(unshared);
24.1226 +
24.1227 + case TC_CLASS:
24.1228 + return readClass(unshared);
24.1229 +
24.1230 + case TC_CLASSDESC:
24.1231 + case TC_PROXYCLASSDESC:
24.1232 + return readClassDesc(unshared);
24.1233 +
24.1234 + case TC_STRING:
24.1235 + case TC_LONGSTRING:
24.1236 + return checkResolve(readString(unshared));
24.1237 +
24.1238 + case TC_ARRAY:
24.1239 + return checkResolve(readArray(unshared));
24.1240 +
24.1241 + case TC_ENUM:
24.1242 + return checkResolve(readEnum(unshared));
24.1243 +
24.1244 + case TC_OBJECT:
24.1245 + return checkResolve(readOrdinaryObject(unshared));
24.1246 +
24.1247 + case TC_EXCEPTION:
24.1248 + IOException ex = readFatalException();
24.1249 + throw new WriteAbortedException("writing aborted", ex);
24.1250 +
24.1251 + case TC_BLOCKDATA:
24.1252 + case TC_BLOCKDATALONG:
24.1253 + if (oldMode) {
24.1254 + bin.setBlockDataMode(true);
24.1255 + bin.peek(); // force header read
24.1256 + throw new OptionalDataException(
24.1257 + bin.currentBlockRemaining());
24.1258 + } else {
24.1259 + throw new StreamCorruptedException(
24.1260 + "unexpected block data");
24.1261 + }
24.1262 +
24.1263 + case TC_ENDBLOCKDATA:
24.1264 + if (oldMode) {
24.1265 + throw new OptionalDataException(true);
24.1266 + } else {
24.1267 + throw new StreamCorruptedException(
24.1268 + "unexpected end of block data");
24.1269 + }
24.1270 +
24.1271 + default:
24.1272 + throw new StreamCorruptedException(
24.1273 + String.format("invalid type code: %02X", tc));
24.1274 + }
24.1275 + } finally {
24.1276 + depth--;
24.1277 + bin.setBlockDataMode(oldMode);
24.1278 + }
24.1279 + }
24.1280 +
24.1281 + /**
24.1282 + * If resolveObject has been enabled and given object does not have an
24.1283 + * exception associated with it, calls resolveObject to determine
24.1284 + * replacement for object, and updates handle table accordingly. Returns
24.1285 + * replacement object, or echoes provided object if no replacement
24.1286 + * occurred. Expects that passHandle is set to given object's handle prior
24.1287 + * to calling this method.
24.1288 + */
24.1289 + private Object checkResolve(Object obj) throws IOException {
24.1290 + if (!enableResolve || handles.lookupException(passHandle) != null) {
24.1291 + return obj;
24.1292 + }
24.1293 + Object rep = resolveObject(obj);
24.1294 + if (rep != obj) {
24.1295 + handles.setObject(passHandle, rep);
24.1296 + }
24.1297 + return rep;
24.1298 + }
24.1299 +
24.1300 + /**
24.1301 + * Reads string without allowing it to be replaced in stream. Called from
24.1302 + * within ObjectStreamClass.read().
24.1303 + */
24.1304 + String readTypeString() throws IOException {
24.1305 + int oldHandle = passHandle;
24.1306 + try {
24.1307 + byte tc = bin.peekByte();
24.1308 + switch (tc) {
24.1309 + case TC_NULL:
24.1310 + return (String) readNull();
24.1311 +
24.1312 + case TC_REFERENCE:
24.1313 + return (String) readHandle(false);
24.1314 +
24.1315 + case TC_STRING:
24.1316 + case TC_LONGSTRING:
24.1317 + return readString(false);
24.1318 +
24.1319 + default:
24.1320 + throw new StreamCorruptedException(
24.1321 + String.format("invalid type code: %02X", tc));
24.1322 + }
24.1323 + } finally {
24.1324 + passHandle = oldHandle;
24.1325 + }
24.1326 + }
24.1327 +
24.1328 + /**
24.1329 + * Reads in null code, sets passHandle to NULL_HANDLE and returns null.
24.1330 + */
24.1331 + private Object readNull() throws IOException {
24.1332 + if (bin.readByte() != TC_NULL) {
24.1333 + throw new InternalError();
24.1334 + }
24.1335 + passHandle = NULL_HANDLE;
24.1336 + return null;
24.1337 + }
24.1338 +
24.1339 + /**
24.1340 + * Reads in object handle, sets passHandle to the read handle, and returns
24.1341 + * object associated with the handle.
24.1342 + */
24.1343 + private Object readHandle(boolean unshared) throws IOException {
24.1344 + if (bin.readByte() != TC_REFERENCE) {
24.1345 + throw new InternalError();
24.1346 + }
24.1347 + passHandle = bin.readInt() - baseWireHandle;
24.1348 + if (passHandle < 0 || passHandle >= handles.size()) {
24.1349 + throw new StreamCorruptedException(
24.1350 + String.format("invalid handle value: %08X", passHandle +
24.1351 + baseWireHandle));
24.1352 + }
24.1353 + if (unshared) {
24.1354 + // REMIND: what type of exception to throw here?
24.1355 + throw new InvalidObjectException(
24.1356 + "cannot read back reference as unshared");
24.1357 + }
24.1358 +
24.1359 + Object obj = handles.lookupObject(passHandle);
24.1360 + if (obj == unsharedMarker) {
24.1361 + // REMIND: what type of exception to throw here?
24.1362 + throw new InvalidObjectException(
24.1363 + "cannot read back reference to unshared object");
24.1364 + }
24.1365 + return obj;
24.1366 + }
24.1367 +
24.1368 + /**
24.1369 + * Reads in and returns class object. Sets passHandle to class object's
24.1370 + * assigned handle. Returns null if class is unresolvable (in which case a
24.1371 + * ClassNotFoundException will be associated with the class' handle in the
24.1372 + * handle table).
24.1373 + */
24.1374 + private Class readClass(boolean unshared) throws IOException {
24.1375 + if (bin.readByte() != TC_CLASS) {
24.1376 + throw new InternalError();
24.1377 + }
24.1378 + ObjectStreamClass desc = readClassDesc(false);
24.1379 + Class cl = desc.forClass();
24.1380 + passHandle = handles.assign(unshared ? unsharedMarker : cl);
24.1381 +
24.1382 + ClassNotFoundException resolveEx = desc.getResolveException();
24.1383 + if (resolveEx != null) {
24.1384 + handles.markException(passHandle, resolveEx);
24.1385 + }
24.1386 +
24.1387 + handles.finish(passHandle);
24.1388 + return cl;
24.1389 + }
24.1390 +
24.1391 + /**
24.1392 + * Reads in and returns (possibly null) class descriptor. Sets passHandle
24.1393 + * to class descriptor's assigned handle. If class descriptor cannot be
24.1394 + * resolved to a class in the local VM, a ClassNotFoundException is
24.1395 + * associated with the class descriptor's handle.
24.1396 + */
24.1397 + private ObjectStreamClass readClassDesc(boolean unshared)
24.1398 + throws IOException
24.1399 + {
24.1400 + byte tc = bin.peekByte();
24.1401 + switch (tc) {
24.1402 + case TC_NULL:
24.1403 + return (ObjectStreamClass) readNull();
24.1404 +
24.1405 + case TC_REFERENCE:
24.1406 + return (ObjectStreamClass) readHandle(unshared);
24.1407 +
24.1408 + case TC_PROXYCLASSDESC:
24.1409 + return readProxyDesc(unshared);
24.1410 +
24.1411 + case TC_CLASSDESC:
24.1412 + return readNonProxyDesc(unshared);
24.1413 +
24.1414 + default:
24.1415 + throw new StreamCorruptedException(
24.1416 + String.format("invalid type code: %02X", tc));
24.1417 + }
24.1418 + }
24.1419 +
24.1420 + /**
24.1421 + * Reads in and returns class descriptor for a dynamic proxy class. Sets
24.1422 + * passHandle to proxy class descriptor's assigned handle. If proxy class
24.1423 + * descriptor cannot be resolved to a class in the local VM, a
24.1424 + * ClassNotFoundException is associated with the descriptor's handle.
24.1425 + */
24.1426 + private ObjectStreamClass readProxyDesc(boolean unshared)
24.1427 + throws IOException
24.1428 + {
24.1429 + if (bin.readByte() != TC_PROXYCLASSDESC) {
24.1430 + throw new InternalError();
24.1431 + }
24.1432 +
24.1433 + ObjectStreamClass desc = new ObjectStreamClass();
24.1434 + int descHandle = handles.assign(unshared ? unsharedMarker : desc);
24.1435 + passHandle = NULL_HANDLE;
24.1436 +
24.1437 + int numIfaces = bin.readInt();
24.1438 + String[] ifaces = new String[numIfaces];
24.1439 + for (int i = 0; i < numIfaces; i++) {
24.1440 + ifaces[i] = bin.readUTF();
24.1441 + }
24.1442 +
24.1443 + Class cl = null;
24.1444 + ClassNotFoundException resolveEx = null;
24.1445 + bin.setBlockDataMode(true);
24.1446 + try {
24.1447 + if ((cl = resolveProxyClass(ifaces)) == null) {
24.1448 + resolveEx = new ClassNotFoundException("null class");
24.1449 + }
24.1450 + } catch (ClassNotFoundException ex) {
24.1451 + resolveEx = ex;
24.1452 + }
24.1453 + skipCustomData();
24.1454 +
24.1455 + desc.initProxy(cl, resolveEx, readClassDesc(false));
24.1456 +
24.1457 + handles.finish(descHandle);
24.1458 + passHandle = descHandle;
24.1459 + return desc;
24.1460 + }
24.1461 +
24.1462 + /**
24.1463 + * Reads in and returns class descriptor for a class that is not a dynamic
24.1464 + * proxy class. Sets passHandle to class descriptor's assigned handle. If
24.1465 + * class descriptor cannot be resolved to a class in the local VM, a
24.1466 + * ClassNotFoundException is associated with the descriptor's handle.
24.1467 + */
24.1468 + private ObjectStreamClass readNonProxyDesc(boolean unshared)
24.1469 + throws IOException
24.1470 + {
24.1471 + if (bin.readByte() != TC_CLASSDESC) {
24.1472 + throw new InternalError();
24.1473 + }
24.1474 +
24.1475 + ObjectStreamClass desc = new ObjectStreamClass();
24.1476 + int descHandle = handles.assign(unshared ? unsharedMarker : desc);
24.1477 + passHandle = NULL_HANDLE;
24.1478 +
24.1479 + ObjectStreamClass readDesc = null;
24.1480 + try {
24.1481 + readDesc = readClassDescriptor();
24.1482 + } catch (ClassNotFoundException ex) {
24.1483 + throw (IOException) new InvalidClassException(
24.1484 + "failed to read class descriptor").initCause(ex);
24.1485 + }
24.1486 +
24.1487 + Class cl = null;
24.1488 + ClassNotFoundException resolveEx = null;
24.1489 + bin.setBlockDataMode(true);
24.1490 + try {
24.1491 + if ((cl = resolveClass(readDesc)) == null) {
24.1492 + resolveEx = new ClassNotFoundException("null class");
24.1493 + }
24.1494 + } catch (ClassNotFoundException ex) {
24.1495 + resolveEx = ex;
24.1496 + }
24.1497 + skipCustomData();
24.1498 +
24.1499 + desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));
24.1500 +
24.1501 + handles.finish(descHandle);
24.1502 + passHandle = descHandle;
24.1503 + return desc;
24.1504 + }
24.1505 +
24.1506 + /**
24.1507 + * Reads in and returns new string. Sets passHandle to new string's
24.1508 + * assigned handle.
24.1509 + */
24.1510 + private String readString(boolean unshared) throws IOException {
24.1511 + String str;
24.1512 + byte tc = bin.readByte();
24.1513 + switch (tc) {
24.1514 + case TC_STRING:
24.1515 + str = bin.readUTF();
24.1516 + break;
24.1517 +
24.1518 + case TC_LONGSTRING:
24.1519 + str = bin.readLongUTF();
24.1520 + break;
24.1521 +
24.1522 + default:
24.1523 + throw new StreamCorruptedException(
24.1524 + String.format("invalid type code: %02X", tc));
24.1525 + }
24.1526 + passHandle = handles.assign(unshared ? unsharedMarker : str);
24.1527 + handles.finish(passHandle);
24.1528 + return str;
24.1529 + }
24.1530 +
24.1531 + /**
24.1532 + * Reads in and returns array object, or null if array class is
24.1533 + * unresolvable. Sets passHandle to array's assigned handle.
24.1534 + */
24.1535 + private Object readArray(boolean unshared) throws IOException {
24.1536 + if (bin.readByte() != TC_ARRAY) {
24.1537 + throw new InternalError();
24.1538 + }
24.1539 +
24.1540 + ObjectStreamClass desc = readClassDesc(false);
24.1541 + int len = bin.readInt();
24.1542 +
24.1543 + Object array = null;
24.1544 + Class cl, ccl = null;
24.1545 + if ((cl = desc.forClass()) != null) {
24.1546 + ccl = cl.getComponentType();
24.1547 + array = Array.newInstance(ccl, len);
24.1548 + }
24.1549 +
24.1550 + int arrayHandle = handles.assign(unshared ? unsharedMarker : array);
24.1551 + ClassNotFoundException resolveEx = desc.getResolveException();
24.1552 + if (resolveEx != null) {
24.1553 + handles.markException(arrayHandle, resolveEx);
24.1554 + }
24.1555 +
24.1556 + if (ccl == null) {
24.1557 + for (int i = 0; i < len; i++) {
24.1558 + readObject0(false);
24.1559 + }
24.1560 + } else if (ccl.isPrimitive()) {
24.1561 + if (ccl == Integer.TYPE) {
24.1562 + bin.readInts((int[]) array, 0, len);
24.1563 + } else if (ccl == Byte.TYPE) {
24.1564 + bin.readFully((byte[]) array, 0, len, true);
24.1565 + } else if (ccl == Long.TYPE) {
24.1566 + bin.readLongs((long[]) array, 0, len);
24.1567 + } else if (ccl == Float.TYPE) {
24.1568 + bin.readFloats((float[]) array, 0, len);
24.1569 + } else if (ccl == Double.TYPE) {
24.1570 + bin.readDoubles((double[]) array, 0, len);
24.1571 + } else if (ccl == Short.TYPE) {
24.1572 + bin.readShorts((short[]) array, 0, len);
24.1573 + } else if (ccl == Character.TYPE) {
24.1574 + bin.readChars((char[]) array, 0, len);
24.1575 + } else if (ccl == Boolean.TYPE) {
24.1576 + bin.readBooleans((boolean[]) array, 0, len);
24.1577 + } else {
24.1578 + throw new InternalError();
24.1579 + }
24.1580 + } else {
24.1581 + Object[] oa = (Object[]) array;
24.1582 + for (int i = 0; i < len; i++) {
24.1583 + oa[i] = readObject0(false);
24.1584 + handles.markDependency(arrayHandle, passHandle);
24.1585 + }
24.1586 + }
24.1587 +
24.1588 + handles.finish(arrayHandle);
24.1589 + passHandle = arrayHandle;
24.1590 + return array;
24.1591 + }
24.1592 +
24.1593 + /**
24.1594 + * Reads in and returns enum constant, or null if enum type is
24.1595 + * unresolvable. Sets passHandle to enum constant's assigned handle.
24.1596 + */
24.1597 + private Enum readEnum(boolean unshared) throws IOException {
24.1598 + if (bin.readByte() != TC_ENUM) {
24.1599 + throw new InternalError();
24.1600 + }
24.1601 +
24.1602 + ObjectStreamClass desc = readClassDesc(false);
24.1603 + if (!desc.isEnum()) {
24.1604 + throw new InvalidClassException("non-enum class: " + desc);
24.1605 + }
24.1606 +
24.1607 + int enumHandle = handles.assign(unshared ? unsharedMarker : null);
24.1608 + ClassNotFoundException resolveEx = desc.getResolveException();
24.1609 + if (resolveEx != null) {
24.1610 + handles.markException(enumHandle, resolveEx);
24.1611 + }
24.1612 +
24.1613 + String name = readString(false);
24.1614 + Enum en = null;
24.1615 + Class cl = desc.forClass();
24.1616 + if (cl != null) {
24.1617 + try {
24.1618 + en = Enum.valueOf(cl, name);
24.1619 + } catch (IllegalArgumentException ex) {
24.1620 + throw (IOException) new InvalidObjectException(
24.1621 + "enum constant " + name + " does not exist in " +
24.1622 + cl).initCause(ex);
24.1623 + }
24.1624 + if (!unshared) {
24.1625 + handles.setObject(enumHandle, en);
24.1626 + }
24.1627 + }
24.1628 +
24.1629 + handles.finish(enumHandle);
24.1630 + passHandle = enumHandle;
24.1631 + return en;
24.1632 + }
24.1633 +
24.1634 + /**
24.1635 + * Reads and returns "ordinary" (i.e., not a String, Class,
24.1636 + * ObjectStreamClass, array, or enum constant) object, or null if object's
24.1637 + * class is unresolvable (in which case a ClassNotFoundException will be
24.1638 + * associated with object's handle). Sets passHandle to object's assigned
24.1639 + * handle.
24.1640 + */
24.1641 + private Object readOrdinaryObject(boolean unshared)
24.1642 + throws IOException
24.1643 + {
24.1644 + if (bin.readByte() != TC_OBJECT) {
24.1645 + throw new InternalError();
24.1646 + }
24.1647 +
24.1648 + ObjectStreamClass desc = readClassDesc(false);
24.1649 + desc.checkDeserialize();
24.1650 +
24.1651 + Object obj;
24.1652 + try {
24.1653 + obj = desc.isInstantiable() ? desc.newInstance() : null;
24.1654 + } catch (Exception ex) {
24.1655 + throw (IOException) new InvalidClassException(
24.1656 + desc.forClass().getName(),
24.1657 + "unable to create instance").initCause(ex);
24.1658 + }
24.1659 +
24.1660 + passHandle = handles.assign(unshared ? unsharedMarker : obj);
24.1661 + ClassNotFoundException resolveEx = desc.getResolveException();
24.1662 + if (resolveEx != null) {
24.1663 + handles.markException(passHandle, resolveEx);
24.1664 + }
24.1665 +
24.1666 + if (desc.isExternalizable()) {
24.1667 + readExternalData((Externalizable) obj, desc);
24.1668 + } else {
24.1669 + readSerialData(obj, desc);
24.1670 + }
24.1671 +
24.1672 + handles.finish(passHandle);
24.1673 +
24.1674 + if (obj != null &&
24.1675 + handles.lookupException(passHandle) == null &&
24.1676 + desc.hasReadResolveMethod())
24.1677 + {
24.1678 + Object rep = desc.invokeReadResolve(obj);
24.1679 + if (unshared && rep.getClass().isArray()) {
24.1680 + rep = cloneArray(rep);
24.1681 + }
24.1682 + if (rep != obj) {
24.1683 + handles.setObject(passHandle, obj = rep);
24.1684 + }
24.1685 + }
24.1686 +
24.1687 + return obj;
24.1688 + }
24.1689 +
24.1690 + /**
24.1691 + * If obj is non-null, reads externalizable data by invoking readExternal()
24.1692 + * method of obj; otherwise, attempts to skip over externalizable data.
24.1693 + * Expects that passHandle is set to obj's handle before this method is
24.1694 + * called.
24.1695 + */
24.1696 + private void readExternalData(Externalizable obj, ObjectStreamClass desc)
24.1697 + throws IOException
24.1698 + {
24.1699 + Object oldContext = curContext;
24.1700 + curContext = null;
24.1701 + try {
24.1702 + boolean blocked = desc.hasBlockExternalData();
24.1703 + if (blocked) {
24.1704 + bin.setBlockDataMode(true);
24.1705 + }
24.1706 + if (obj != null) {
24.1707 + try {
24.1708 + obj.readExternal(this);
24.1709 + } catch (ClassNotFoundException ex) {
24.1710 + /*
24.1711 + * In most cases, the handle table has already propagated
24.1712 + * a CNFException to passHandle at this point; this mark
24.1713 + * call is included to address cases where the readExternal
24.1714 + * method has cons'ed and thrown a new CNFException of its
24.1715 + * own.
24.1716 + */
24.1717 + handles.markException(passHandle, ex);
24.1718 + }
24.1719 + }
24.1720 + if (blocked) {
24.1721 + skipCustomData();
24.1722 + }
24.1723 + } finally {
24.1724 + curContext = oldContext;
24.1725 + }
24.1726 + /*
24.1727 + * At this point, if the externalizable data was not written in
24.1728 + * block-data form and either the externalizable class doesn't exist
24.1729 + * locally (i.e., obj == null) or readExternal() just threw a
24.1730 + * CNFException, then the stream is probably in an inconsistent state,
24.1731 + * since some (or all) of the externalizable data may not have been
24.1732 + * consumed. Since there's no "correct" action to take in this case,
24.1733 + * we mimic the behavior of past serialization implementations and
24.1734 + * blindly hope that the stream is in sync; if it isn't and additional
24.1735 + * externalizable data remains in the stream, a subsequent read will
24.1736 + * most likely throw a StreamCorruptedException.
24.1737 + */
24.1738 + }
24.1739 +
24.1740 + /**
24.1741 + * Reads (or attempts to skip, if obj is null or is tagged with a
24.1742 + * ClassNotFoundException) instance data for each serializable class of
24.1743 + * object in stream, from superclass to subclass. Expects that passHandle
24.1744 + * is set to obj's handle before this method is called.
24.1745 + */
24.1746 + private void readSerialData(Object obj, ObjectStreamClass desc)
24.1747 + throws IOException
24.1748 + {
24.1749 + ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
24.1750 + for (int i = 0; i < slots.length; i++) {
24.1751 + ObjectStreamClass slotDesc = slots[i].desc;
24.1752 +
24.1753 + if (slots[i].hasData) {
24.1754 + if (obj != null &&
24.1755 + slotDesc.hasReadObjectMethod() &&
24.1756 + handles.lookupException(passHandle) == null)
24.1757 + {
24.1758 + Object oldContext = curContext;
24.1759 +
24.1760 + try {
24.1761 + curContext = null; //new SerialCallbackContext(obj, slotDesc);
24.1762 +
24.1763 + bin.setBlockDataMode(true);
24.1764 + slotDesc.invokeReadObject(obj, this);
24.1765 + } catch (ClassNotFoundException ex) {
24.1766 + /*
24.1767 + * In most cases, the handle table has already
24.1768 + * propagated a CNFException to passHandle at this
24.1769 + * point; this mark call is included to address cases
24.1770 + * where the custom readObject method has cons'ed and
24.1771 + * thrown a new CNFException of its own.
24.1772 + */
24.1773 + handles.markException(passHandle, ex);
24.1774 + } finally {
24.1775 + //curContext.setUsed();
24.1776 + curContext = oldContext;
24.1777 + }
24.1778 +
24.1779 + /*
24.1780 + * defaultDataEnd may have been set indirectly by custom
24.1781 + * readObject() method when calling defaultReadObject() or
24.1782 + * readFields(); clear it to restore normal read behavior.
24.1783 + */
24.1784 + defaultDataEnd = false;
24.1785 + } else {
24.1786 + defaultReadFields(obj, slotDesc);
24.1787 + }
24.1788 + if (slotDesc.hasWriteObjectData()) {
24.1789 + skipCustomData();
24.1790 + } else {
24.1791 + bin.setBlockDataMode(false);
24.1792 + }
24.1793 + } else {
24.1794 + if (obj != null &&
24.1795 + slotDesc.hasReadObjectNoDataMethod() &&
24.1796 + handles.lookupException(passHandle) == null)
24.1797 + {
24.1798 + slotDesc.invokeReadObjectNoData(obj);
24.1799 + }
24.1800 + }
24.1801 + }
24.1802 + }
24.1803 +
24.1804 + /**
24.1805 + * Skips over all block data and objects until TC_ENDBLOCKDATA is
24.1806 + * encountered.
24.1807 + */
24.1808 + private void skipCustomData() throws IOException {
24.1809 + int oldHandle = passHandle;
24.1810 + for (;;) {
24.1811 + if (bin.getBlockDataMode()) {
24.1812 + bin.skipBlockData();
24.1813 + bin.setBlockDataMode(false);
24.1814 + }
24.1815 + switch (bin.peekByte()) {
24.1816 + case TC_BLOCKDATA:
24.1817 + case TC_BLOCKDATALONG:
24.1818 + bin.setBlockDataMode(true);
24.1819 + break;
24.1820 +
24.1821 + case TC_ENDBLOCKDATA:
24.1822 + bin.readByte();
24.1823 + passHandle = oldHandle;
24.1824 + return;
24.1825 +
24.1826 + default:
24.1827 + readObject0(false);
24.1828 + break;
24.1829 + }
24.1830 + }
24.1831 + }
24.1832 +
24.1833 + /**
24.1834 + * Reads in values of serializable fields declared by given class
24.1835 + * descriptor. If obj is non-null, sets field values in obj. Expects that
24.1836 + * passHandle is set to obj's handle before this method is called.
24.1837 + */
24.1838 + private void defaultReadFields(Object obj, ObjectStreamClass desc)
24.1839 + throws IOException
24.1840 + {
24.1841 + // REMIND: is isInstance check necessary?
24.1842 + Class cl = desc.forClass();
24.1843 + if (cl != null && obj != null && !cl.isInstance(obj)) {
24.1844 + throw new ClassCastException();
24.1845 + }
24.1846 +
24.1847 + int primDataSize = desc.getPrimDataSize();
24.1848 + if (primVals == null || primVals.length < primDataSize) {
24.1849 + primVals = new byte[primDataSize];
24.1850 + }
24.1851 + bin.readFully(primVals, 0, primDataSize, false);
24.1852 + if (obj != null) {
24.1853 + desc.setPrimFieldValues(obj, primVals);
24.1854 + }
24.1855 +
24.1856 + int objHandle = passHandle;
24.1857 + ObjectStreamField[] fields = desc.getFields(false);
24.1858 + Object[] objVals = new Object[desc.getNumObjFields()];
24.1859 + int numPrimFields = fields.length - objVals.length;
24.1860 + for (int i = 0; i < objVals.length; i++) {
24.1861 + ObjectStreamField f = fields[numPrimFields + i];
24.1862 + objVals[i] = readObject0(f.isUnshared());
24.1863 + if (f.getField() != null) {
24.1864 + handles.markDependency(objHandle, passHandle);
24.1865 + }
24.1866 + }
24.1867 + if (obj != null) {
24.1868 + desc.setObjFieldValues(obj, objVals);
24.1869 + }
24.1870 + passHandle = objHandle;
24.1871 + }
24.1872 +
24.1873 + /**
24.1874 + * Reads in and returns IOException that caused serialization to abort.
24.1875 + * All stream state is discarded prior to reading in fatal exception. Sets
24.1876 + * passHandle to fatal exception's handle.
24.1877 + */
24.1878 + private IOException readFatalException() throws IOException {
24.1879 + if (bin.readByte() != TC_EXCEPTION) {
24.1880 + throw new InternalError();
24.1881 + }
24.1882 + clear();
24.1883 + return (IOException) readObject0(false);
24.1884 + }
24.1885 +
24.1886 + /**
24.1887 + * If recursion depth is 0, clears internal data structures; otherwise,
24.1888 + * throws a StreamCorruptedException. This method is called when a
24.1889 + * TC_RESET typecode is encountered.
24.1890 + */
24.1891 + private void handleReset() throws StreamCorruptedException {
24.1892 + if (depth > 0) {
24.1893 + throw new StreamCorruptedException(
24.1894 + "unexpected reset; recursion depth: " + depth);
24.1895 + }
24.1896 + clear();
24.1897 + }
24.1898 +
24.1899 + /**
24.1900 + * Converts specified span of bytes into float values.
24.1901 + */
24.1902 + // REMIND: remove once hotspot inlines Float.intBitsToFloat
24.1903 + private static native void bytesToFloats(byte[] src, int srcpos,
24.1904 + float[] dst, int dstpos,
24.1905 + int nfloats);
24.1906 +
24.1907 + /**
24.1908 + * Converts specified span of bytes into double values.
24.1909 + */
24.1910 + // REMIND: remove once hotspot inlines Double.longBitsToDouble
24.1911 + private static native void bytesToDoubles(byte[] src, int srcpos,
24.1912 + double[] dst, int dstpos,
24.1913 + int ndoubles);
24.1914 +
24.1915 + /**
24.1916 + * Returns the first non-null class loader (not counting class loaders of
24.1917 + * generated reflection implementation classes) up the execution stack, or
24.1918 + * null if only code from the null class loader is on the stack. This
24.1919 + * method is also called via reflection by the following RMI-IIOP class:
24.1920 + *
24.1921 + * com.sun.corba.se.internal.util.JDKClassLoader
24.1922 + *
24.1923 + * This method should not be removed or its signature changed without
24.1924 + * corresponding modifications to the above class.
24.1925 + */
24.1926 + // REMIND: change name to something more accurate?
24.1927 + private static native ClassLoader latestUserDefinedLoader();
24.1928 +
24.1929 + /**
24.1930 + * Default GetField implementation.
24.1931 + */
24.1932 + private class GetFieldImpl extends GetField {
24.1933 +
24.1934 + /** class descriptor describing serializable fields */
24.1935 + private final ObjectStreamClass desc;
24.1936 + /** primitive field values */
24.1937 + private final byte[] primVals;
24.1938 + /** object field values */
24.1939 + private final Object[] objVals;
24.1940 + /** object field value handles */
24.1941 + private final int[] objHandles;
24.1942 +
24.1943 + /**
24.1944 + * Creates GetFieldImpl object for reading fields defined in given
24.1945 + * class descriptor.
24.1946 + */
24.1947 + GetFieldImpl(ObjectStreamClass desc) {
24.1948 + this.desc = desc;
24.1949 + primVals = new byte[desc.getPrimDataSize()];
24.1950 + objVals = new Object[desc.getNumObjFields()];
24.1951 + objHandles = new int[objVals.length];
24.1952 + }
24.1953 +
24.1954 + public ObjectStreamClass getObjectStreamClass() {
24.1955 + return desc;
24.1956 + }
24.1957 +
24.1958 + public boolean defaulted(String name) throws IOException {
24.1959 + return (getFieldOffset(name, null) < 0);
24.1960 + }
24.1961 +
24.1962 + public boolean get(String name, boolean val) throws IOException {
24.1963 + int off = getFieldOffset(name, Boolean.TYPE);
24.1964 + return (off >= 0) ? Bits.getBoolean(primVals, off) : val;
24.1965 + }
24.1966 +
24.1967 + public byte get(String name, byte val) throws IOException {
24.1968 + int off = getFieldOffset(name, Byte.TYPE);
24.1969 + return (off >= 0) ? primVals[off] : val;
24.1970 + }
24.1971 +
24.1972 + public char get(String name, char val) throws IOException {
24.1973 + int off = getFieldOffset(name, Character.TYPE);
24.1974 + return (off >= 0) ? Bits.getChar(primVals, off) : val;
24.1975 + }
24.1976 +
24.1977 + public short get(String name, short val) throws IOException {
24.1978 + int off = getFieldOffset(name, Short.TYPE);
24.1979 + return (off >= 0) ? Bits.getShort(primVals, off) : val;
24.1980 + }
24.1981 +
24.1982 + public int get(String name, int val) throws IOException {
24.1983 + int off = getFieldOffset(name, Integer.TYPE);
24.1984 + return (off >= 0) ? Bits.getInt(primVals, off) : val;
24.1985 + }
24.1986 +
24.1987 + public float get(String name, float val) throws IOException {
24.1988 + int off = getFieldOffset(name, Float.TYPE);
24.1989 + return (off >= 0) ? Bits.getFloat(primVals, off) : val;
24.1990 + }
24.1991 +
24.1992 + public long get(String name, long val) throws IOException {
24.1993 + int off = getFieldOffset(name, Long.TYPE);
24.1994 + return (off >= 0) ? Bits.getLong(primVals, off) : val;
24.1995 + }
24.1996 +
24.1997 + public double get(String name, double val) throws IOException {
24.1998 + int off = getFieldOffset(name, Double.TYPE);
24.1999 + return (off >= 0) ? Bits.getDouble(primVals, off) : val;
24.2000 + }
24.2001 +
24.2002 + public Object get(String name, Object val) throws IOException {
24.2003 + int off = getFieldOffset(name, Object.class);
24.2004 + if (off >= 0) {
24.2005 + int objHandle = objHandles[off];
24.2006 + handles.markDependency(passHandle, objHandle);
24.2007 + return (handles.lookupException(objHandle) == null) ?
24.2008 + objVals[off] : null;
24.2009 + } else {
24.2010 + return val;
24.2011 + }
24.2012 + }
24.2013 +
24.2014 + /**
24.2015 + * Reads primitive and object field values from stream.
24.2016 + */
24.2017 + void readFields() throws IOException {
24.2018 + bin.readFully(primVals, 0, primVals.length, false);
24.2019 +
24.2020 + int oldHandle = passHandle;
24.2021 + ObjectStreamField[] fields = desc.getFields(false);
24.2022 + int numPrimFields = fields.length - objVals.length;
24.2023 + for (int i = 0; i < objVals.length; i++) {
24.2024 + objVals[i] =
24.2025 + readObject0(fields[numPrimFields + i].isUnshared());
24.2026 + objHandles[i] = passHandle;
24.2027 + }
24.2028 + passHandle = oldHandle;
24.2029 + }
24.2030 +
24.2031 + /**
24.2032 + * Returns offset of field with given name and type. A specified type
24.2033 + * of null matches all types, Object.class matches all non-primitive
24.2034 + * types, and any other non-null type matches assignable types only.
24.2035 + * If no matching field is found in the (incoming) class
24.2036 + * descriptor but a matching field is present in the associated local
24.2037 + * class descriptor, returns -1. Throws IllegalArgumentException if
24.2038 + * neither incoming nor local class descriptor contains a match.
24.2039 + */
24.2040 + private int getFieldOffset(String name, Class type) {
24.2041 + ObjectStreamField field = desc.getField(name, type);
24.2042 + if (field != null) {
24.2043 + return field.getOffset();
24.2044 + } else if (desc.getLocalDesc().getField(name, type) != null) {
24.2045 + return -1;
24.2046 + } else {
24.2047 + throw new IllegalArgumentException("no such field " + name +
24.2048 + " with type " + type);
24.2049 + }
24.2050 + }
24.2051 + }
24.2052 +
24.2053 + /**
24.2054 + * Prioritized list of callbacks to be performed once object graph has been
24.2055 + * completely deserialized.
24.2056 + */
24.2057 + private static class ValidationList {
24.2058 +
24.2059 +
24.2060 + /**
24.2061 + * Creates new (empty) ValidationList.
24.2062 + */
24.2063 + ValidationList() {
24.2064 + }
24.2065 +
24.2066 + /**
24.2067 + * Registers callback. Throws InvalidObjectException if callback
24.2068 + * object is null.
24.2069 + */
24.2070 + void register(ObjectInputValidation obj, int priority)
24.2071 + throws InvalidObjectException
24.2072 + {
24.2073 + if (obj == null) {
24.2074 + throw new InvalidObjectException("null callback");
24.2075 + }
24.2076 + throw new InvalidObjectException("Does not work.");
24.2077 + }
24.2078 +
24.2079 + /**
24.2080 + * Invokes all registered callbacks and clears the callback list.
24.2081 + * Callbacks with higher priorities are called first; those with equal
24.2082 + * priorities may be called in any order. If any of the callbacks
24.2083 + * throws an InvalidObjectException, the callback process is terminated
24.2084 + * and the exception propagated upwards.
24.2085 + */
24.2086 + void doCallbacks() throws InvalidObjectException {
24.2087 + }
24.2088 +
24.2089 + /**
24.2090 + * Resets the callback list to its initial (empty) state.
24.2091 + */
24.2092 + public void clear() {
24.2093 + }
24.2094 + }
24.2095 +
24.2096 + /**
24.2097 + * Input stream supporting single-byte peek operations.
24.2098 + */
24.2099 + private static class PeekInputStream extends InputStream {
24.2100 +
24.2101 + /** underlying stream */
24.2102 + private final InputStream in;
24.2103 + /** peeked byte */
24.2104 + private int peekb = -1;
24.2105 +
24.2106 + /**
24.2107 + * Creates new PeekInputStream on top of given underlying stream.
24.2108 + */
24.2109 + PeekInputStream(InputStream in) {
24.2110 + this.in = in;
24.2111 + }
24.2112 +
24.2113 + /**
24.2114 + * Peeks at next byte value in stream. Similar to read(), except
24.2115 + * that it does not consume the read value.
24.2116 + */
24.2117 + int peek() throws IOException {
24.2118 + return (peekb >= 0) ? peekb : (peekb = in.read());
24.2119 + }
24.2120 +
24.2121 + public int read() throws IOException {
24.2122 + if (peekb >= 0) {
24.2123 + int v = peekb;
24.2124 + peekb = -1;
24.2125 + return v;
24.2126 + } else {
24.2127 + return in.read();
24.2128 + }
24.2129 + }
24.2130 +
24.2131 + public int read(byte[] b, int off, int len) throws IOException {
24.2132 + if (len == 0) {
24.2133 + return 0;
24.2134 + } else if (peekb < 0) {
24.2135 + return in.read(b, off, len);
24.2136 + } else {
24.2137 + b[off++] = (byte) peekb;
24.2138 + len--;
24.2139 + peekb = -1;
24.2140 + int n = in.read(b, off, len);
24.2141 + return (n >= 0) ? (n + 1) : 1;
24.2142 + }
24.2143 + }
24.2144 +
24.2145 + void readFully(byte[] b, int off, int len) throws IOException {
24.2146 + int n = 0;
24.2147 + while (n < len) {
24.2148 + int count = read(b, off + n, len - n);
24.2149 + if (count < 0) {
24.2150 + throw new EOFException();
24.2151 + }
24.2152 + n += count;
24.2153 + }
24.2154 + }
24.2155 +
24.2156 + public long skip(long n) throws IOException {
24.2157 + if (n <= 0) {
24.2158 + return 0;
24.2159 + }
24.2160 + int skipped = 0;
24.2161 + if (peekb >= 0) {
24.2162 + peekb = -1;
24.2163 + skipped++;
24.2164 + n--;
24.2165 + }
24.2166 + return skipped + skip(n);
24.2167 + }
24.2168 +
24.2169 + public int available() throws IOException {
24.2170 + return in.available() + ((peekb >= 0) ? 1 : 0);
24.2171 + }
24.2172 +
24.2173 + public void close() throws IOException {
24.2174 + in.close();
24.2175 + }
24.2176 + }
24.2177 +
24.2178 + /**
24.2179 + * Input stream with two modes: in default mode, inputs data written in the
24.2180 + * same format as DataOutputStream; in "block data" mode, inputs data
24.2181 + * bracketed by block data markers (see object serialization specification
24.2182 + * for details). Buffering depends on block data mode: when in default
24.2183 + * mode, no data is buffered in advance; when in block data mode, all data
24.2184 + * for the current data block is read in at once (and buffered).
24.2185 + */
24.2186 + private class BlockDataInputStream
24.2187 + extends InputStream implements DataInput
24.2188 + {
24.2189 + /** maximum data block length */
24.2190 + private static final int MAX_BLOCK_SIZE = 1024;
24.2191 + /** maximum data block header length */
24.2192 + private static final int MAX_HEADER_SIZE = 5;
24.2193 + /** (tunable) length of char buffer (for reading strings) */
24.2194 + private static final int CHAR_BUF_SIZE = 256;
24.2195 + /** readBlockHeader() return value indicating header read may block */
24.2196 + private static final int HEADER_BLOCKED = -2;
24.2197 +
24.2198 + /** buffer for reading general/block data */
24.2199 + private final byte[] buf = new byte[MAX_BLOCK_SIZE];
24.2200 + /** buffer for reading block data headers */
24.2201 + private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
24.2202 + /** char buffer for fast string reads */
24.2203 + private final char[] cbuf = new char[CHAR_BUF_SIZE];
24.2204 +
24.2205 + /** block data mode */
24.2206 + private boolean blkmode = false;
24.2207 +
24.2208 + // block data state fields; values meaningful only when blkmode true
24.2209 + /** current offset into buf */
24.2210 + private int pos = 0;
24.2211 + /** end offset of valid data in buf, or -1 if no more block data */
24.2212 + private int end = -1;
24.2213 + /** number of bytes in current block yet to be read from stream */
24.2214 + private int unread = 0;
24.2215 +
24.2216 + /** underlying stream (wrapped in peekable filter stream) */
24.2217 + private final PeekInputStream in;
24.2218 + /** loopback stream (for data reads that span data blocks) */
24.2219 + private final DataInputStream din;
24.2220 +
24.2221 + /**
24.2222 + * Creates new BlockDataInputStream on top of given underlying stream.
24.2223 + * Block data mode is turned off by default.
24.2224 + */
24.2225 + BlockDataInputStream(InputStream in) {
24.2226 + this.in = new PeekInputStream(in);
24.2227 + din = new DataInputStream(this);
24.2228 + }
24.2229 +
24.2230 + /**
24.2231 + * Sets block data mode to the given mode (true == on, false == off)
24.2232 + * and returns the previous mode value. If the new mode is the same as
24.2233 + * the old mode, no action is taken. Throws IllegalStateException if
24.2234 + * block data mode is being switched from on to off while unconsumed
24.2235 + * block data is still present in the stream.
24.2236 + */
24.2237 + boolean setBlockDataMode(boolean newmode) throws IOException {
24.2238 + if (blkmode == newmode) {
24.2239 + return blkmode;
24.2240 + }
24.2241 + if (newmode) {
24.2242 + pos = 0;
24.2243 + end = 0;
24.2244 + unread = 0;
24.2245 + } else if (pos < end) {
24.2246 + throw new IllegalStateException("unread block data");
24.2247 + }
24.2248 + blkmode = newmode;
24.2249 + return !blkmode;
24.2250 + }
24.2251 +
24.2252 + /**
24.2253 + * Returns true if the stream is currently in block data mode, false
24.2254 + * otherwise.
24.2255 + */
24.2256 + boolean getBlockDataMode() {
24.2257 + return blkmode;
24.2258 + }
24.2259 +
24.2260 + /**
24.2261 + * If in block data mode, skips to the end of the current group of data
24.2262 + * blocks (but does not unset block data mode). If not in block data
24.2263 + * mode, throws an IllegalStateException.
24.2264 + */
24.2265 + void skipBlockData() throws IOException {
24.2266 + if (!blkmode) {
24.2267 + throw new IllegalStateException("not in block data mode");
24.2268 + }
24.2269 + while (end >= 0) {
24.2270 + refill();
24.2271 + }
24.2272 + }
24.2273 +
24.2274 + /**
24.2275 + * Attempts to read in the next block data header (if any). If
24.2276 + * canBlock is false and a full header cannot be read without possibly
24.2277 + * blocking, returns HEADER_BLOCKED, else if the next element in the
24.2278 + * stream is a block data header, returns the block data length
24.2279 + * specified by the header, else returns -1.
24.2280 + */
24.2281 + private int readBlockHeader(boolean canBlock) throws IOException {
24.2282 + if (defaultDataEnd) {
24.2283 + /*
24.2284 + * Fix for 4360508: stream is currently at the end of a field
24.2285 + * value block written via default serialization; since there
24.2286 + * is no terminating TC_ENDBLOCKDATA tag, simulate
24.2287 + * end-of-custom-data behavior explicitly.
24.2288 + */
24.2289 + return -1;
24.2290 + }
24.2291 + try {
24.2292 + for (;;) {
24.2293 + int avail = canBlock ? Integer.MAX_VALUE : in.available();
24.2294 + if (avail == 0) {
24.2295 + return HEADER_BLOCKED;
24.2296 + }
24.2297 +
24.2298 + int tc = in.peek();
24.2299 + switch (tc) {
24.2300 + case TC_BLOCKDATA:
24.2301 + if (avail < 2) {
24.2302 + return HEADER_BLOCKED;
24.2303 + }
24.2304 + in.readFully(hbuf, 0, 2);
24.2305 + return hbuf[1] & 0xFF;
24.2306 +
24.2307 + case TC_BLOCKDATALONG:
24.2308 + if (avail < 5) {
24.2309 + return HEADER_BLOCKED;
24.2310 + }
24.2311 + in.readFully(hbuf, 0, 5);
24.2312 + int len = Bits.getInt(hbuf, 1);
24.2313 + if (len < 0) {
24.2314 + throw new StreamCorruptedException(
24.2315 + "illegal block data header length: " +
24.2316 + len);
24.2317 + }
24.2318 + return len;
24.2319 +
24.2320 + /*
24.2321 + * TC_RESETs may occur in between data blocks.
24.2322 + * Unfortunately, this case must be parsed at a lower
24.2323 + * level than other typecodes, since primitive data
24.2324 + * reads may span data blocks separated by a TC_RESET.
24.2325 + */
24.2326 + case TC_RESET:
24.2327 + in.read();
24.2328 + handleReset();
24.2329 + break;
24.2330 +
24.2331 + default:
24.2332 + if (tc >= 0 && (tc < TC_BASE || tc > TC_MAX)) {
24.2333 + throw new StreamCorruptedException(
24.2334 + String.format("invalid type code: %02X",
24.2335 + tc));
24.2336 + }
24.2337 + return -1;
24.2338 + }
24.2339 + }
24.2340 + } catch (EOFException ex) {
24.2341 + throw new StreamCorruptedException(
24.2342 + "unexpected EOF while reading block data header");
24.2343 + }
24.2344 + }
24.2345 +
24.2346 + /**
24.2347 + * Refills internal buffer buf with block data. Any data in buf at the
24.2348 + * time of the call is considered consumed. Sets the pos, end, and
24.2349 + * unread fields to reflect the new amount of available block data; if
24.2350 + * the next element in the stream is not a data block, sets pos and
24.2351 + * unread to 0 and end to -1.
24.2352 + */
24.2353 + private void refill() throws IOException {
24.2354 + try {
24.2355 + do {
24.2356 + pos = 0;
24.2357 + if (unread > 0) {
24.2358 + int n =
24.2359 + in.read(buf, 0, Math.min(unread, MAX_BLOCK_SIZE));
24.2360 + if (n >= 0) {
24.2361 + end = n;
24.2362 + unread -= n;
24.2363 + } else {
24.2364 + throw new StreamCorruptedException(
24.2365 + "unexpected EOF in middle of data block");
24.2366 + }
24.2367 + } else {
24.2368 + int n = readBlockHeader(true);
24.2369 + if (n >= 0) {
24.2370 + end = 0;
24.2371 + unread = n;
24.2372 + } else {
24.2373 + end = -1;
24.2374 + unread = 0;
24.2375 + }
24.2376 + }
24.2377 + } while (pos == end);
24.2378 + } catch (IOException ex) {
24.2379 + pos = 0;
24.2380 + end = -1;
24.2381 + unread = 0;
24.2382 + throw ex;
24.2383 + }
24.2384 + }
24.2385 +
24.2386 + /**
24.2387 + * If in block data mode, returns the number of unconsumed bytes
24.2388 + * remaining in the current data block. If not in block data mode,
24.2389 + * throws an IllegalStateException.
24.2390 + */
24.2391 + int currentBlockRemaining() {
24.2392 + if (blkmode) {
24.2393 + return (end >= 0) ? (end - pos) + unread : 0;
24.2394 + } else {
24.2395 + throw new IllegalStateException();
24.2396 + }
24.2397 + }
24.2398 +
24.2399 + /**
24.2400 + * Peeks at (but does not consume) and returns the next byte value in
24.2401 + * the stream, or -1 if the end of the stream/block data (if in block
24.2402 + * data mode) has been reached.
24.2403 + */
24.2404 + int peek() throws IOException {
24.2405 + if (blkmode) {
24.2406 + if (pos == end) {
24.2407 + refill();
24.2408 + }
24.2409 + return (end >= 0) ? (buf[pos] & 0xFF) : -1;
24.2410 + } else {
24.2411 + return in.peek();
24.2412 + }
24.2413 + }
24.2414 +
24.2415 + /**
24.2416 + * Peeks at (but does not consume) and returns the next byte value in
24.2417 + * the stream, or throws EOFException if end of stream/block data has
24.2418 + * been reached.
24.2419 + */
24.2420 + byte peekByte() throws IOException {
24.2421 + int val = peek();
24.2422 + if (val < 0) {
24.2423 + throw new EOFException();
24.2424 + }
24.2425 + return (byte) val;
24.2426 + }
24.2427 +
24.2428 +
24.2429 + /* ----------------- generic input stream methods ------------------ */
24.2430 + /*
24.2431 + * The following methods are equivalent to their counterparts in
24.2432 + * InputStream, except that they interpret data block boundaries and
24.2433 + * read the requested data from within data blocks when in block data
24.2434 + * mode.
24.2435 + */
24.2436 +
24.2437 + public int read() throws IOException {
24.2438 + if (blkmode) {
24.2439 + if (pos == end) {
24.2440 + refill();
24.2441 + }
24.2442 + return (end >= 0) ? (buf[pos++] & 0xFF) : -1;
24.2443 + } else {
24.2444 + return in.read();
24.2445 + }
24.2446 + }
24.2447 +
24.2448 + public int read(byte[] b, int off, int len) throws IOException {
24.2449 + return read(b, off, len, false);
24.2450 + }
24.2451 +
24.2452 + public long skip(long len) throws IOException {
24.2453 + long remain = len;
24.2454 + while (remain > 0) {
24.2455 + if (blkmode) {
24.2456 + if (pos == end) {
24.2457 + refill();
24.2458 + }
24.2459 + if (end < 0) {
24.2460 + break;
24.2461 + }
24.2462 + int nread = (int) Math.min(remain, end - pos);
24.2463 + remain -= nread;
24.2464 + pos += nread;
24.2465 + } else {
24.2466 + int nread = (int) Math.min(remain, MAX_BLOCK_SIZE);
24.2467 + if ((nread = in.read(buf, 0, nread)) < 0) {
24.2468 + break;
24.2469 + }
24.2470 + remain -= nread;
24.2471 + }
24.2472 + }
24.2473 + return len - remain;
24.2474 + }
24.2475 +
24.2476 + public int available() throws IOException {
24.2477 + if (blkmode) {
24.2478 + if ((pos == end) && (unread == 0)) {
24.2479 + int n;
24.2480 + while ((n = readBlockHeader(false)) == 0) ;
24.2481 + switch (n) {
24.2482 + case HEADER_BLOCKED:
24.2483 + break;
24.2484 +
24.2485 + case -1:
24.2486 + pos = 0;
24.2487 + end = -1;
24.2488 + break;
24.2489 +
24.2490 + default:
24.2491 + pos = 0;
24.2492 + end = 0;
24.2493 + unread = n;
24.2494 + break;
24.2495 + }
24.2496 + }
24.2497 + // avoid unnecessary call to in.available() if possible
24.2498 + int unreadAvail = (unread > 0) ?
24.2499 + Math.min(in.available(), unread) : 0;
24.2500 + return (end >= 0) ? (end - pos) + unreadAvail : 0;
24.2501 + } else {
24.2502 + return in.available();
24.2503 + }
24.2504 + }
24.2505 +
24.2506 + public void close() throws IOException {
24.2507 + if (blkmode) {
24.2508 + pos = 0;
24.2509 + end = -1;
24.2510 + unread = 0;
24.2511 + }
24.2512 + in.close();
24.2513 + }
24.2514 +
24.2515 + /**
24.2516 + * Attempts to read len bytes into byte array b at offset off. Returns
24.2517 + * the number of bytes read, or -1 if the end of stream/block data has
24.2518 + * been reached. If copy is true, reads values into an intermediate
24.2519 + * buffer before copying them to b (to avoid exposing a reference to
24.2520 + * b).
24.2521 + */
24.2522 + int read(byte[] b, int off, int len, boolean copy) throws IOException {
24.2523 + if (len == 0) {
24.2524 + return 0;
24.2525 + } else if (blkmode) {
24.2526 + if (pos == end) {
24.2527 + refill();
24.2528 + }
24.2529 + if (end < 0) {
24.2530 + return -1;
24.2531 + }
24.2532 + int nread = Math.min(len, end - pos);
24.2533 + System.arraycopy(buf, pos, b, off, nread);
24.2534 + pos += nread;
24.2535 + return nread;
24.2536 + } else if (copy) {
24.2537 + int nread = in.read(buf, 0, Math.min(len, MAX_BLOCK_SIZE));
24.2538 + if (nread > 0) {
24.2539 + System.arraycopy(buf, 0, b, off, nread);
24.2540 + }
24.2541 + return nread;
24.2542 + } else {
24.2543 + return in.read(b, off, len);
24.2544 + }
24.2545 + }
24.2546 +
24.2547 + /* ----------------- primitive data input methods ------------------ */
24.2548 + /*
24.2549 + * The following methods are equivalent to their counterparts in
24.2550 + * DataInputStream, except that they interpret data block boundaries
24.2551 + * and read the requested data from within data blocks when in block
24.2552 + * data mode.
24.2553 + */
24.2554 +
24.2555 + public void readFully(byte[] b) throws IOException {
24.2556 + readFully(b, 0, b.length, false);
24.2557 + }
24.2558 +
24.2559 + public void readFully(byte[] b, int off, int len) throws IOException {
24.2560 + readFully(b, off, len, false);
24.2561 + }
24.2562 +
24.2563 + public void readFully(byte[] b, int off, int len, boolean copy)
24.2564 + throws IOException
24.2565 + {
24.2566 + while (len > 0) {
24.2567 + int n = read(b, off, len, copy);
24.2568 + if (n < 0) {
24.2569 + throw new EOFException();
24.2570 + }
24.2571 + off += n;
24.2572 + len -= n;
24.2573 + }
24.2574 + }
24.2575 +
24.2576 + public int skipBytes(int n) throws IOException {
24.2577 + return din.skipBytes(n);
24.2578 + }
24.2579 +
24.2580 + public boolean readBoolean() throws IOException {
24.2581 + int v = read();
24.2582 + if (v < 0) {
24.2583 + throw new EOFException();
24.2584 + }
24.2585 + return (v != 0);
24.2586 + }
24.2587 +
24.2588 + public byte readByte() throws IOException {
24.2589 + int v = read();
24.2590 + if (v < 0) {
24.2591 + throw new EOFException();
24.2592 + }
24.2593 + return (byte) v;
24.2594 + }
24.2595 +
24.2596 + public int readUnsignedByte() throws IOException {
24.2597 + int v = read();
24.2598 + if (v < 0) {
24.2599 + throw new EOFException();
24.2600 + }
24.2601 + return v;
24.2602 + }
24.2603 +
24.2604 + public char readChar() throws IOException {
24.2605 + if (!blkmode) {
24.2606 + pos = 0;
24.2607 + in.readFully(buf, 0, 2);
24.2608 + } else if (end - pos < 2) {
24.2609 + return din.readChar();
24.2610 + }
24.2611 + char v = Bits.getChar(buf, pos);
24.2612 + pos += 2;
24.2613 + return v;
24.2614 + }
24.2615 +
24.2616 + public short readShort() throws IOException {
24.2617 + if (!blkmode) {
24.2618 + pos = 0;
24.2619 + in.readFully(buf, 0, 2);
24.2620 + } else if (end - pos < 2) {
24.2621 + return din.readShort();
24.2622 + }
24.2623 + short v = Bits.getShort(buf, pos);
24.2624 + pos += 2;
24.2625 + return v;
24.2626 + }
24.2627 +
24.2628 + public int readUnsignedShort() throws IOException {
24.2629 + if (!blkmode) {
24.2630 + pos = 0;
24.2631 + in.readFully(buf, 0, 2);
24.2632 + } else if (end - pos < 2) {
24.2633 + return din.readUnsignedShort();
24.2634 + }
24.2635 + int v = Bits.getShort(buf, pos) & 0xFFFF;
24.2636 + pos += 2;
24.2637 + return v;
24.2638 + }
24.2639 +
24.2640 + public int readInt() throws IOException {
24.2641 + if (!blkmode) {
24.2642 + pos = 0;
24.2643 + in.readFully(buf, 0, 4);
24.2644 + } else if (end - pos < 4) {
24.2645 + return din.readInt();
24.2646 + }
24.2647 + int v = Bits.getInt(buf, pos);
24.2648 + pos += 4;
24.2649 + return v;
24.2650 + }
24.2651 +
24.2652 + public float readFloat() throws IOException {
24.2653 + if (!blkmode) {
24.2654 + pos = 0;
24.2655 + in.readFully(buf, 0, 4);
24.2656 + } else if (end - pos < 4) {
24.2657 + return din.readFloat();
24.2658 + }
24.2659 + float v = Bits.getFloat(buf, pos);
24.2660 + pos += 4;
24.2661 + return v;
24.2662 + }
24.2663 +
24.2664 + public long readLong() throws IOException {
24.2665 + if (!blkmode) {
24.2666 + pos = 0;
24.2667 + in.readFully(buf, 0, 8);
24.2668 + } else if (end - pos < 8) {
24.2669 + return din.readLong();
24.2670 + }
24.2671 + long v = Bits.getLong(buf, pos);
24.2672 + pos += 8;
24.2673 + return v;
24.2674 + }
24.2675 +
24.2676 + public double readDouble() throws IOException {
24.2677 + if (!blkmode) {
24.2678 + pos = 0;
24.2679 + in.readFully(buf, 0, 8);
24.2680 + } else if (end - pos < 8) {
24.2681 + return din.readDouble();
24.2682 + }
24.2683 + double v = Bits.getDouble(buf, pos);
24.2684 + pos += 8;
24.2685 + return v;
24.2686 + }
24.2687 +
24.2688 + public String readUTF() throws IOException {
24.2689 + return readUTFBody(readUnsignedShort());
24.2690 + }
24.2691 +
24.2692 + public String readLine() throws IOException {
24.2693 + return din.readLine(); // deprecated, not worth optimizing
24.2694 + }
24.2695 +
24.2696 + /* -------------- primitive data array input methods --------------- */
24.2697 + /*
24.2698 + * The following methods read in spans of primitive data values.
24.2699 + * Though equivalent to calling the corresponding primitive read
24.2700 + * methods repeatedly, these methods are optimized for reading groups
24.2701 + * of primitive data values more efficiently.
24.2702 + */
24.2703 +
24.2704 + void readBooleans(boolean[] v, int off, int len) throws IOException {
24.2705 + int stop, endoff = off + len;
24.2706 + while (off < endoff) {
24.2707 + if (!blkmode) {
24.2708 + int span = Math.min(endoff - off, MAX_BLOCK_SIZE);
24.2709 + in.readFully(buf, 0, span);
24.2710 + stop = off + span;
24.2711 + pos = 0;
24.2712 + } else if (end - pos < 1) {
24.2713 + v[off++] = din.readBoolean();
24.2714 + continue;
24.2715 + } else {
24.2716 + stop = Math.min(endoff, off + end - pos);
24.2717 + }
24.2718 +
24.2719 + while (off < stop) {
24.2720 + v[off++] = Bits.getBoolean(buf, pos++);
24.2721 + }
24.2722 + }
24.2723 + }
24.2724 +
24.2725 + void readChars(char[] v, int off, int len) throws IOException {
24.2726 + int stop, endoff = off + len;
24.2727 + while (off < endoff) {
24.2728 + if (!blkmode) {
24.2729 + int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
24.2730 + in.readFully(buf, 0, span << 1);
24.2731 + stop = off + span;
24.2732 + pos = 0;
24.2733 + } else if (end - pos < 2) {
24.2734 + v[off++] = din.readChar();
24.2735 + continue;
24.2736 + } else {
24.2737 + stop = Math.min(endoff, off + ((end - pos) >> 1));
24.2738 + }
24.2739 +
24.2740 + while (off < stop) {
24.2741 + v[off++] = Bits.getChar(buf, pos);
24.2742 + pos += 2;
24.2743 + }
24.2744 + }
24.2745 + }
24.2746 +
24.2747 + void readShorts(short[] v, int off, int len) throws IOException {
24.2748 + int stop, endoff = off + len;
24.2749 + while (off < endoff) {
24.2750 + if (!blkmode) {
24.2751 + int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
24.2752 + in.readFully(buf, 0, span << 1);
24.2753 + stop = off + span;
24.2754 + pos = 0;
24.2755 + } else if (end - pos < 2) {
24.2756 + v[off++] = din.readShort();
24.2757 + continue;
24.2758 + } else {
24.2759 + stop = Math.min(endoff, off + ((end - pos) >> 1));
24.2760 + }
24.2761 +
24.2762 + while (off < stop) {
24.2763 + v[off++] = Bits.getShort(buf, pos);
24.2764 + pos += 2;
24.2765 + }
24.2766 + }
24.2767 + }
24.2768 +
24.2769 + void readInts(int[] v, int off, int len) throws IOException {
24.2770 + int stop, endoff = off + len;
24.2771 + while (off < endoff) {
24.2772 + if (!blkmode) {
24.2773 + int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
24.2774 + in.readFully(buf, 0, span << 2);
24.2775 + stop = off + span;
24.2776 + pos = 0;
24.2777 + } else if (end - pos < 4) {
24.2778 + v[off++] = din.readInt();
24.2779 + continue;
24.2780 + } else {
24.2781 + stop = Math.min(endoff, off + ((end - pos) >> 2));
24.2782 + }
24.2783 +
24.2784 + while (off < stop) {
24.2785 + v[off++] = Bits.getInt(buf, pos);
24.2786 + pos += 4;
24.2787 + }
24.2788 + }
24.2789 + }
24.2790 +
24.2791 + void readFloats(float[] v, int off, int len) throws IOException {
24.2792 + int span, endoff = off + len;
24.2793 + while (off < endoff) {
24.2794 + if (!blkmode) {
24.2795 + span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
24.2796 + in.readFully(buf, 0, span << 2);
24.2797 + pos = 0;
24.2798 + } else if (end - pos < 4) {
24.2799 + v[off++] = din.readFloat();
24.2800 + continue;
24.2801 + } else {
24.2802 + span = Math.min(endoff - off, ((end - pos) >> 2));
24.2803 + }
24.2804 +
24.2805 + bytesToFloats(buf, pos, v, off, span);
24.2806 + off += span;
24.2807 + pos += span << 2;
24.2808 + }
24.2809 + }
24.2810 +
24.2811 + void readLongs(long[] v, int off, int len) throws IOException {
24.2812 + int stop, endoff = off + len;
24.2813 + while (off < endoff) {
24.2814 + if (!blkmode) {
24.2815 + int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
24.2816 + in.readFully(buf, 0, span << 3);
24.2817 + stop = off + span;
24.2818 + pos = 0;
24.2819 + } else if (end - pos < 8) {
24.2820 + v[off++] = din.readLong();
24.2821 + continue;
24.2822 + } else {
24.2823 + stop = Math.min(endoff, off + ((end - pos) >> 3));
24.2824 + }
24.2825 +
24.2826 + while (off < stop) {
24.2827 + v[off++] = Bits.getLong(buf, pos);
24.2828 + pos += 8;
24.2829 + }
24.2830 + }
24.2831 + }
24.2832 +
24.2833 + void readDoubles(double[] v, int off, int len) throws IOException {
24.2834 + int span, endoff = off + len;
24.2835 + while (off < endoff) {
24.2836 + if (!blkmode) {
24.2837 + span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
24.2838 + in.readFully(buf, 0, span << 3);
24.2839 + pos = 0;
24.2840 + } else if (end - pos < 8) {
24.2841 + v[off++] = din.readDouble();
24.2842 + continue;
24.2843 + } else {
24.2844 + span = Math.min(endoff - off, ((end - pos) >> 3));
24.2845 + }
24.2846 +
24.2847 + bytesToDoubles(buf, pos, v, off, span);
24.2848 + off += span;
24.2849 + pos += span << 3;
24.2850 + }
24.2851 + }
24.2852 +
24.2853 + /**
24.2854 + * Reads in string written in "long" UTF format. "Long" UTF format is
24.2855 + * identical to standard UTF, except that it uses an 8 byte header
24.2856 + * (instead of the standard 2 bytes) to convey the UTF encoding length.
24.2857 + */
24.2858 + String readLongUTF() throws IOException {
24.2859 + return readUTFBody(readLong());
24.2860 + }
24.2861 +
24.2862 + /**
24.2863 + * Reads in the "body" (i.e., the UTF representation minus the 2-byte
24.2864 + * or 8-byte length header) of a UTF encoding, which occupies the next
24.2865 + * utflen bytes.
24.2866 + */
24.2867 + private String readUTFBody(long utflen) throws IOException {
24.2868 + StringBuilder sbuf = new StringBuilder();
24.2869 + if (!blkmode) {
24.2870 + end = pos = 0;
24.2871 + }
24.2872 +
24.2873 + while (utflen > 0) {
24.2874 + int avail = end - pos;
24.2875 + if (avail >= 3 || (long) avail == utflen) {
24.2876 + utflen -= readUTFSpan(sbuf, utflen);
24.2877 + } else {
24.2878 + if (blkmode) {
24.2879 + // near block boundary, read one byte at a time
24.2880 + utflen -= readUTFChar(sbuf, utflen);
24.2881 + } else {
24.2882 + // shift and refill buffer manually
24.2883 + if (avail > 0) {
24.2884 + System.arraycopy(buf, pos, buf, 0, avail);
24.2885 + }
24.2886 + pos = 0;
24.2887 + end = (int) Math.min(MAX_BLOCK_SIZE, utflen);
24.2888 + in.readFully(buf, avail, end - avail);
24.2889 + }
24.2890 + }
24.2891 + }
24.2892 +
24.2893 + return sbuf.toString();
24.2894 + }
24.2895 +
24.2896 + /**
24.2897 + * Reads span of UTF-encoded characters out of internal buffer
24.2898 + * (starting at offset pos and ending at or before offset end),
24.2899 + * consuming no more than utflen bytes. Appends read characters to
24.2900 + * sbuf. Returns the number of bytes consumed.
24.2901 + */
24.2902 + private long readUTFSpan(StringBuilder sbuf, long utflen)
24.2903 + throws IOException
24.2904 + {
24.2905 + int cpos = 0;
24.2906 + int start = pos;
24.2907 + int avail = Math.min(end - pos, CHAR_BUF_SIZE);
24.2908 + // stop short of last char unless all of utf bytes in buffer
24.2909 + int stop = pos + ((utflen > avail) ? avail - 2 : (int) utflen);
24.2910 + boolean outOfBounds = false;
24.2911 +
24.2912 + try {
24.2913 + while (pos < stop) {
24.2914 + int b1, b2, b3;
24.2915 + b1 = buf[pos++] & 0xFF;
24.2916 + switch (b1 >> 4) {
24.2917 + case 0:
24.2918 + case 1:
24.2919 + case 2:
24.2920 + case 3:
24.2921 + case 4:
24.2922 + case 5:
24.2923 + case 6:
24.2924 + case 7: // 1 byte format: 0xxxxxxx
24.2925 + cbuf[cpos++] = (char) b1;
24.2926 + break;
24.2927 +
24.2928 + case 12:
24.2929 + case 13: // 2 byte format: 110xxxxx 10xxxxxx
24.2930 + b2 = buf[pos++];
24.2931 + if ((b2 & 0xC0) != 0x80) {
24.2932 + throw new UTFDataFormatException();
24.2933 + }
24.2934 + cbuf[cpos++] = (char) (((b1 & 0x1F) << 6) |
24.2935 + ((b2 & 0x3F) << 0));
24.2936 + break;
24.2937 +
24.2938 + case 14: // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
24.2939 + b3 = buf[pos + 1];
24.2940 + b2 = buf[pos + 0];
24.2941 + pos += 2;
24.2942 + if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
24.2943 + throw new UTFDataFormatException();
24.2944 + }
24.2945 + cbuf[cpos++] = (char) (((b1 & 0x0F) << 12) |
24.2946 + ((b2 & 0x3F) << 6) |
24.2947 + ((b3 & 0x3F) << 0));
24.2948 + break;
24.2949 +
24.2950 + default: // 10xx xxxx, 1111 xxxx
24.2951 + throw new UTFDataFormatException();
24.2952 + }
24.2953 + }
24.2954 + } catch (ArrayIndexOutOfBoundsException ex) {
24.2955 + outOfBounds = true;
24.2956 + } finally {
24.2957 + if (outOfBounds || (pos - start) > utflen) {
24.2958 + /*
24.2959 + * Fix for 4450867: if a malformed utf char causes the
24.2960 + * conversion loop to scan past the expected end of the utf
24.2961 + * string, only consume the expected number of utf bytes.
24.2962 + */
24.2963 + pos = start + (int) utflen;
24.2964 + throw new UTFDataFormatException();
24.2965 + }
24.2966 + }
24.2967 +
24.2968 + sbuf.append(cbuf, 0, cpos);
24.2969 + return pos - start;
24.2970 + }
24.2971 +
24.2972 + /**
24.2973 + * Reads in single UTF-encoded character one byte at a time, appends
24.2974 + * the character to sbuf, and returns the number of bytes consumed.
24.2975 + * This method is used when reading in UTF strings written in block
24.2976 + * data mode to handle UTF-encoded characters which (potentially)
24.2977 + * straddle block-data boundaries.
24.2978 + */
24.2979 + private int readUTFChar(StringBuilder sbuf, long utflen)
24.2980 + throws IOException
24.2981 + {
24.2982 + int b1, b2, b3;
24.2983 + b1 = readByte() & 0xFF;
24.2984 + switch (b1 >> 4) {
24.2985 + case 0:
24.2986 + case 1:
24.2987 + case 2:
24.2988 + case 3:
24.2989 + case 4:
24.2990 + case 5:
24.2991 + case 6:
24.2992 + case 7: // 1 byte format: 0xxxxxxx
24.2993 + sbuf.append((char) b1);
24.2994 + return 1;
24.2995 +
24.2996 + case 12:
24.2997 + case 13: // 2 byte format: 110xxxxx 10xxxxxx
24.2998 + if (utflen < 2) {
24.2999 + throw new UTFDataFormatException();
24.3000 + }
24.3001 + b2 = readByte();
24.3002 + if ((b2 & 0xC0) != 0x80) {
24.3003 + throw new UTFDataFormatException();
24.3004 + }
24.3005 + sbuf.append((char) (((b1 & 0x1F) << 6) |
24.3006 + ((b2 & 0x3F) << 0)));
24.3007 + return 2;
24.3008 +
24.3009 + case 14: // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
24.3010 + if (utflen < 3) {
24.3011 + if (utflen == 2) {
24.3012 + readByte(); // consume remaining byte
24.3013 + }
24.3014 + throw new UTFDataFormatException();
24.3015 + }
24.3016 + b2 = readByte();
24.3017 + b3 = readByte();
24.3018 + if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
24.3019 + throw new UTFDataFormatException();
24.3020 + }
24.3021 + sbuf.append((char) (((b1 & 0x0F) << 12) |
24.3022 + ((b2 & 0x3F) << 6) |
24.3023 + ((b3 & 0x3F) << 0)));
24.3024 + return 3;
24.3025 +
24.3026 + default: // 10xx xxxx, 1111 xxxx
24.3027 + throw new UTFDataFormatException();
24.3028 + }
24.3029 + }
24.3030 + }
24.3031 +
24.3032 + /**
24.3033 + * Unsynchronized table which tracks wire handle to object mappings, as
24.3034 + * well as ClassNotFoundExceptions associated with deserialized objects.
24.3035 + * This class implements an exception-propagation algorithm for
24.3036 + * determining which objects should have ClassNotFoundExceptions associated
24.3037 + * with them, taking into account cycles and discontinuities (e.g., skipped
24.3038 + * fields) in the object graph.
24.3039 + *
24.3040 + * <p>General use of the table is as follows: during deserialization, a
24.3041 + * given object is first assigned a handle by calling the assign method.
24.3042 + * This method leaves the assigned handle in an "open" state, wherein
24.3043 + * dependencies on the exception status of other handles can be registered
24.3044 + * by calling the markDependency method, or an exception can be directly
24.3045 + * associated with the handle by calling markException. When a handle is
24.3046 + * tagged with an exception, the HandleTable assumes responsibility for
24.3047 + * propagating the exception to any other objects which depend
24.3048 + * (transitively) on the exception-tagged object.
24.3049 + *
24.3050 + * <p>Once all exception information/dependencies for the handle have been
24.3051 + * registered, the handle should be "closed" by calling the finish method
24.3052 + * on it. The act of finishing a handle allows the exception propagation
24.3053 + * algorithm to aggressively prune dependency links, lessening the
24.3054 + * performance/memory impact of exception tracking.
24.3055 + *
24.3056 + * <p>Note that the exception propagation algorithm used depends on handles
24.3057 + * being assigned/finished in LIFO order; however, for simplicity as well
24.3058 + * as memory conservation, it does not enforce this constraint.
24.3059 + */
24.3060 + // REMIND: add full description of exception propagation algorithm?
24.3061 + private static class HandleTable {
24.3062 +
24.3063 + /* status codes indicating whether object has associated exception */
24.3064 + private static final byte STATUS_OK = 1;
24.3065 + private static final byte STATUS_UNKNOWN = 2;
24.3066 + private static final byte STATUS_EXCEPTION = 3;
24.3067 +
24.3068 + /** array mapping handle -> object status */
24.3069 + byte[] status;
24.3070 + /** array mapping handle -> object/exception (depending on status) */
24.3071 + Object[] entries;
24.3072 + /** array mapping handle -> list of dependent handles (if any) */
24.3073 + HandleList[] deps;
24.3074 + /** lowest unresolved dependency */
24.3075 + int lowDep = -1;
24.3076 + /** number of handles in table */
24.3077 + int size = 0;
24.3078 +
24.3079 + /**
24.3080 + * Creates handle table with the given initial capacity.
24.3081 + */
24.3082 + HandleTable(int initialCapacity) {
24.3083 + status = new byte[initialCapacity];
24.3084 + entries = new Object[initialCapacity];
24.3085 + deps = new HandleList[initialCapacity];
24.3086 + }
24.3087 +
24.3088 + /**
24.3089 + * Assigns next available handle to given object, and returns assigned
24.3090 + * handle. Once object has been completely deserialized (and all
24.3091 + * dependencies on other objects identified), the handle should be
24.3092 + * "closed" by passing it to finish().
24.3093 + */
24.3094 + int assign(Object obj) {
24.3095 + if (size >= entries.length) {
24.3096 + grow();
24.3097 + }
24.3098 + status[size] = STATUS_UNKNOWN;
24.3099 + entries[size] = obj;
24.3100 + return size++;
24.3101 + }
24.3102 +
24.3103 + /**
24.3104 + * Registers a dependency (in exception status) of one handle on
24.3105 + * another. The dependent handle must be "open" (i.e., assigned, but
24.3106 + * not finished yet). No action is taken if either dependent or target
24.3107 + * handle is NULL_HANDLE.
24.3108 + */
24.3109 + void markDependency(int dependent, int target) {
24.3110 + if (dependent == NULL_HANDLE || target == NULL_HANDLE) {
24.3111 + return;
24.3112 + }
24.3113 + switch (status[dependent]) {
24.3114 +
24.3115 + case STATUS_UNKNOWN:
24.3116 + switch (status[target]) {
24.3117 + case STATUS_OK:
24.3118 + // ignore dependencies on objs with no exception
24.3119 + break;
24.3120 +
24.3121 + case STATUS_EXCEPTION:
24.3122 + // eagerly propagate exception
24.3123 + markException(dependent,
24.3124 + (ClassNotFoundException) entries[target]);
24.3125 + break;
24.3126 +
24.3127 + case STATUS_UNKNOWN:
24.3128 + // add to dependency list of target
24.3129 + if (deps[target] == null) {
24.3130 + deps[target] = new HandleList();
24.3131 + }
24.3132 + deps[target].add(dependent);
24.3133 +
24.3134 + // remember lowest unresolved target seen
24.3135 + if (lowDep < 0 || lowDep > target) {
24.3136 + lowDep = target;
24.3137 + }
24.3138 + break;
24.3139 +
24.3140 + default:
24.3141 + throw new InternalError();
24.3142 + }
24.3143 + break;
24.3144 +
24.3145 + case STATUS_EXCEPTION:
24.3146 + break;
24.3147 +
24.3148 + default:
24.3149 + throw new InternalError();
24.3150 + }
24.3151 + }
24.3152 +
24.3153 + /**
24.3154 + * Associates a ClassNotFoundException (if one not already associated)
24.3155 + * with the currently active handle and propagates it to other
24.3156 + * referencing objects as appropriate. The specified handle must be
24.3157 + * "open" (i.e., assigned, but not finished yet).
24.3158 + */
24.3159 + void markException(int handle, ClassNotFoundException ex) {
24.3160 + switch (status[handle]) {
24.3161 + case STATUS_UNKNOWN:
24.3162 + status[handle] = STATUS_EXCEPTION;
24.3163 + entries[handle] = ex;
24.3164 +
24.3165 + // propagate exception to dependents
24.3166 + HandleList dlist = deps[handle];
24.3167 + if (dlist != null) {
24.3168 + int ndeps = dlist.size();
24.3169 + for (int i = 0; i < ndeps; i++) {
24.3170 + markException(dlist.get(i), ex);
24.3171 + }
24.3172 + deps[handle] = null;
24.3173 + }
24.3174 + break;
24.3175 +
24.3176 + case STATUS_EXCEPTION:
24.3177 + break;
24.3178 +
24.3179 + default:
24.3180 + throw new InternalError();
24.3181 + }
24.3182 + }
24.3183 +
24.3184 + /**
24.3185 + * Marks given handle as finished, meaning that no new dependencies
24.3186 + * will be marked for handle. Calls to the assign and finish methods
24.3187 + * must occur in LIFO order.
24.3188 + */
24.3189 + void finish(int handle) {
24.3190 + int end;
24.3191 + if (lowDep < 0) {
24.3192 + // no pending unknowns, only resolve current handle
24.3193 + end = handle + 1;
24.3194 + } else if (lowDep >= handle) {
24.3195 + // pending unknowns now clearable, resolve all upward handles
24.3196 + end = size;
24.3197 + lowDep = -1;
24.3198 + } else {
24.3199 + // unresolved backrefs present, can't resolve anything yet
24.3200 + return;
24.3201 + }
24.3202 +
24.3203 + // change STATUS_UNKNOWN -> STATUS_OK in selected span of handles
24.3204 + for (int i = handle; i < end; i++) {
24.3205 + switch (status[i]) {
24.3206 + case STATUS_UNKNOWN:
24.3207 + status[i] = STATUS_OK;
24.3208 + deps[i] = null;
24.3209 + break;
24.3210 +
24.3211 + case STATUS_OK:
24.3212 + case STATUS_EXCEPTION:
24.3213 + break;
24.3214 +
24.3215 + default:
24.3216 + throw new InternalError();
24.3217 + }
24.3218 + }
24.3219 + }
24.3220 +
24.3221 + /**
24.3222 + * Assigns a new object to the given handle. The object previously
24.3223 + * associated with the handle is forgotten. This method has no effect
24.3224 + * if the given handle already has an exception associated with it.
24.3225 + * This method may be called at any time after the handle is assigned.
24.3226 + */
24.3227 + void setObject(int handle, Object obj) {
24.3228 + switch (status[handle]) {
24.3229 + case STATUS_UNKNOWN:
24.3230 + case STATUS_OK:
24.3231 + entries[handle] = obj;
24.3232 + break;
24.3233 +
24.3234 + case STATUS_EXCEPTION:
24.3235 + break;
24.3236 +
24.3237 + default:
24.3238 + throw new InternalError();
24.3239 + }
24.3240 + }
24.3241 +
24.3242 + /**
24.3243 + * Looks up and returns object associated with the given handle.
24.3244 + * Returns null if the given handle is NULL_HANDLE, or if it has an
24.3245 + * associated ClassNotFoundException.
24.3246 + */
24.3247 + Object lookupObject(int handle) {
24.3248 + return (handle != NULL_HANDLE &&
24.3249 + status[handle] != STATUS_EXCEPTION) ?
24.3250 + entries[handle] : null;
24.3251 + }
24.3252 +
24.3253 + /**
24.3254 + * Looks up and returns ClassNotFoundException associated with the
24.3255 + * given handle. Returns null if the given handle is NULL_HANDLE, or
24.3256 + * if there is no ClassNotFoundException associated with the handle.
24.3257 + */
24.3258 + ClassNotFoundException lookupException(int handle) {
24.3259 + return (handle != NULL_HANDLE &&
24.3260 + status[handle] == STATUS_EXCEPTION) ?
24.3261 + (ClassNotFoundException) entries[handle] : null;
24.3262 + }
24.3263 +
24.3264 + /**
24.3265 + * Resets table to its initial state.
24.3266 + */
24.3267 + void clear() {
24.3268 + Arrays.fill(status, 0, size, (byte) 0);
24.3269 + Arrays.fill(entries, 0, size, null);
24.3270 + Arrays.fill(deps, 0, size, null);
24.3271 + lowDep = -1;
24.3272 + size = 0;
24.3273 + }
24.3274 +
24.3275 + /**
24.3276 + * Returns number of handles registered in table.
24.3277 + */
24.3278 + int size() {
24.3279 + return size;
24.3280 + }
24.3281 +
24.3282 + /**
24.3283 + * Expands capacity of internal arrays.
24.3284 + */
24.3285 + private void grow() {
24.3286 + int newCapacity = (entries.length << 1) + 1;
24.3287 +
24.3288 + byte[] newStatus = new byte[newCapacity];
24.3289 + Object[] newEntries = new Object[newCapacity];
24.3290 + HandleList[] newDeps = new HandleList[newCapacity];
24.3291 +
24.3292 + System.arraycopy(status, 0, newStatus, 0, size);
24.3293 + System.arraycopy(entries, 0, newEntries, 0, size);
24.3294 + System.arraycopy(deps, 0, newDeps, 0, size);
24.3295 +
24.3296 + status = newStatus;
24.3297 + entries = newEntries;
24.3298 + deps = newDeps;
24.3299 + }
24.3300 +
24.3301 + /**
24.3302 + * Simple growable list of (integer) handles.
24.3303 + */
24.3304 + private static class HandleList {
24.3305 + private int[] list = new int[4];
24.3306 + private int size = 0;
24.3307 +
24.3308 + public HandleList() {
24.3309 + }
24.3310 +
24.3311 + public void add(int handle) {
24.3312 + if (size >= list.length) {
24.3313 + int[] newList = new int[list.length << 1];
24.3314 + System.arraycopy(list, 0, newList, 0, list.length);
24.3315 + list = newList;
24.3316 + }
24.3317 + list[size++] = handle;
24.3318 + }
24.3319 +
24.3320 + public int get(int index) {
24.3321 + if (index >= size) {
24.3322 + throw new ArrayIndexOutOfBoundsException();
24.3323 + }
24.3324 + return list[index];
24.3325 + }
24.3326 +
24.3327 + public int size() {
24.3328 + return size;
24.3329 + }
24.3330 + }
24.3331 + }
24.3332 +
24.3333 + /**
24.3334 + * Method for cloning arrays in case of using unsharing reading
24.3335 + */
24.3336 + private static Object cloneArray(Object array) {
24.3337 + if (array instanceof Object[]) {
24.3338 + return ((Object[]) array).clone();
24.3339 + } else if (array instanceof boolean[]) {
24.3340 + return ((boolean[]) array).clone();
24.3341 + } else if (array instanceof byte[]) {
24.3342 + return ((byte[]) array).clone();
24.3343 + } else if (array instanceof char[]) {
24.3344 + return ((char[]) array).clone();
24.3345 + } else if (array instanceof double[]) {
24.3346 + return ((double[]) array).clone();
24.3347 + } else if (array instanceof float[]) {
24.3348 + return ((float[]) array).clone();
24.3349 + } else if (array instanceof int[]) {
24.3350 + return ((int[]) array).clone();
24.3351 + } else if (array instanceof long[]) {
24.3352 + return ((long[]) array).clone();
24.3353 + } else if (array instanceof short[]) {
24.3354 + return ((short[]) array).clone();
24.3355 + } else {
24.3356 + throw new AssertionError();
24.3357 + }
24.3358 + }
24.3359 +
24.3360 +}
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
25.2 +++ b/emul/compact/src/main/java/java/io/ObjectInputValidation.java Mon Feb 04 09:37:56 2013 +0100
25.3 @@ -0,0 +1,45 @@
25.4 +/*
25.5 + * Copyright (c) 1996, 1999, Oracle and/or its affiliates. All rights reserved.
25.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
25.7 + *
25.8 + * This code is free software; you can redistribute it and/or modify it
25.9 + * under the terms of the GNU General Public License version 2 only, as
25.10 + * published by the Free Software Foundation. Oracle designates this
25.11 + * particular file as subject to the "Classpath" exception as provided
25.12 + * by Oracle in the LICENSE file that accompanied this code.
25.13 + *
25.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
25.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
25.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25.17 + * version 2 for more details (a copy is included in the LICENSE file that
25.18 + * accompanied this code).
25.19 + *
25.20 + * You should have received a copy of the GNU General Public License version
25.21 + * 2 along with this work; if not, write to the Free Software Foundation,
25.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
25.23 + *
25.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
25.25 + * or visit www.oracle.com if you need additional information or have any
25.26 + * questions.
25.27 + */
25.28 +
25.29 +package java.io;
25.30 +
25.31 +/**
25.32 + * Callback interface to allow validation of objects within a graph.
25.33 + * Allows an object to be called when a complete graph of objects has
25.34 + * been deserialized.
25.35 + *
25.36 + * @author unascribed
25.37 + * @see ObjectInputStream
25.38 + * @see ObjectInputStream#registerValidation(java.io.ObjectInputValidation, int)
25.39 + * @since JDK1.1
25.40 + */
25.41 +public interface ObjectInputValidation {
25.42 + /**
25.43 + * Validates the object.
25.44 + *
25.45 + * @exception InvalidObjectException If the object cannot validate itself.
25.46 + */
25.47 + public void validateObject() throws InvalidObjectException;
25.48 +}
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
26.2 +++ b/emul/compact/src/main/java/java/io/ObjectOutput.java Mon Feb 04 09:37:56 2013 +0100
26.3 @@ -0,0 +1,90 @@
26.4 +/*
26.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
26.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
26.7 + *
26.8 + * This code is free software; you can redistribute it and/or modify it
26.9 + * under the terms of the GNU General Public License version 2 only, as
26.10 + * published by the Free Software Foundation. Oracle designates this
26.11 + * particular file as subject to the "Classpath" exception as provided
26.12 + * by Oracle in the LICENSE file that accompanied this code.
26.13 + *
26.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
26.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
26.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26.17 + * version 2 for more details (a copy is included in the LICENSE file that
26.18 + * accompanied this code).
26.19 + *
26.20 + * You should have received a copy of the GNU General Public License version
26.21 + * 2 along with this work; if not, write to the Free Software Foundation,
26.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26.23 + *
26.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
26.25 + * or visit www.oracle.com if you need additional information or have any
26.26 + * questions.
26.27 + */
26.28 +
26.29 +package java.io;
26.30 +
26.31 +/**
26.32 + * ObjectOutput extends the DataOutput interface to include writing of objects.
26.33 + * DataOutput includes methods for output of primitive types, ObjectOutput
26.34 + * extends that interface to include objects, arrays, and Strings.
26.35 + *
26.36 + * @author unascribed
26.37 + * @see java.io.InputStream
26.38 + * @see java.io.ObjectOutputStream
26.39 + * @see java.io.ObjectInputStream
26.40 + * @since JDK1.1
26.41 + */
26.42 +public interface ObjectOutput extends DataOutput, AutoCloseable {
26.43 + /**
26.44 + * Write an object to the underlying storage or stream. The
26.45 + * class that implements this interface defines how the object is
26.46 + * written.
26.47 + *
26.48 + * @param obj the object to be written
26.49 + * @exception IOException Any of the usual Input/Output related exceptions.
26.50 + */
26.51 + public void writeObject(Object obj)
26.52 + throws IOException;
26.53 +
26.54 + /**
26.55 + * Writes a byte. This method will block until the byte is actually
26.56 + * written.
26.57 + * @param b the byte
26.58 + * @exception IOException If an I/O error has occurred.
26.59 + */
26.60 + public void write(int b) throws IOException;
26.61 +
26.62 + /**
26.63 + * Writes an array of bytes. This method will block until the bytes
26.64 + * are actually written.
26.65 + * @param b the data to be written
26.66 + * @exception IOException If an I/O error has occurred.
26.67 + */
26.68 + public void write(byte b[]) throws IOException;
26.69 +
26.70 + /**
26.71 + * Writes a sub array of bytes.
26.72 + * @param b the data to be written
26.73 + * @param off the start offset in the data
26.74 + * @param len the number of bytes that are written
26.75 + * @exception IOException If an I/O error has occurred.
26.76 + */
26.77 + public void write(byte b[], int off, int len) throws IOException;
26.78 +
26.79 + /**
26.80 + * Flushes the stream. This will write any buffered
26.81 + * output bytes.
26.82 + * @exception IOException If an I/O error has occurred.
26.83 + */
26.84 + public void flush() throws IOException;
26.85 +
26.86 + /**
26.87 + * Closes the stream. This method must be called
26.88 + * to release any resources associated with the
26.89 + * stream.
26.90 + * @exception IOException If an I/O error has occurred.
26.91 + */
26.92 + public void close() throws IOException;
26.93 +}
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
27.2 +++ b/emul/compact/src/main/java/java/io/ObjectOutputStream.java Mon Feb 04 09:37:56 2013 +0100
27.3 @@ -0,0 +1,2369 @@
27.4 +/*
27.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
27.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
27.7 + *
27.8 + * This code is free software; you can redistribute it and/or modify it
27.9 + * under the terms of the GNU General Public License version 2 only, as
27.10 + * published by the Free Software Foundation. Oracle designates this
27.11 + * particular file as subject to the "Classpath" exception as provided
27.12 + * by Oracle in the LICENSE file that accompanied this code.
27.13 + *
27.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
27.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
27.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
27.17 + * version 2 for more details (a copy is included in the LICENSE file that
27.18 + * accompanied this code).
27.19 + *
27.20 + * You should have received a copy of the GNU General Public License version
27.21 + * 2 along with this work; if not, write to the Free Software Foundation,
27.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
27.23 + *
27.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
27.25 + * or visit www.oracle.com if you need additional information or have any
27.26 + * questions.
27.27 + */
27.28 +
27.29 +package java.io;
27.30 +
27.31 +import java.util.ArrayList;
27.32 +import java.util.Arrays;
27.33 +import java.util.List;
27.34 +import org.apidesign.bck2brwsr.emul.lang.System;
27.35 +
27.36 +/**
27.37 + * An ObjectOutputStream writes primitive data types and graphs of Java objects
27.38 + * to an OutputStream. The objects can be read (reconstituted) using an
27.39 + * ObjectInputStream. Persistent storage of objects can be accomplished by
27.40 + * using a file for the stream. If the stream is a network socket stream, the
27.41 + * objects can be reconstituted on another host or in another process.
27.42 + *
27.43 + * <p>Only objects that support the java.io.Serializable interface can be
27.44 + * written to streams. The class of each serializable object is encoded
27.45 + * including the class name and signature of the class, the values of the
27.46 + * object's fields and arrays, and the closure of any other objects referenced
27.47 + * from the initial objects.
27.48 + *
27.49 + * <p>The method writeObject is used to write an object to the stream. Any
27.50 + * object, including Strings and arrays, is written with writeObject. Multiple
27.51 + * objects or primitives can be written to the stream. The objects must be
27.52 + * read back from the corresponding ObjectInputstream with the same types and
27.53 + * in the same order as they were written.
27.54 + *
27.55 + * <p>Primitive data types can also be written to the stream using the
27.56 + * appropriate methods from DataOutput. Strings can also be written using the
27.57 + * writeUTF method.
27.58 + *
27.59 + * <p>The default serialization mechanism for an object writes the class of the
27.60 + * object, the class signature, and the values of all non-transient and
27.61 + * non-static fields. References to other objects (except in transient or
27.62 + * static fields) cause those objects to be written also. Multiple references
27.63 + * to a single object are encoded using a reference sharing mechanism so that
27.64 + * graphs of objects can be restored to the same shape as when the original was
27.65 + * written.
27.66 + *
27.67 + * <p>For example to write an object that can be read by the example in
27.68 + * ObjectInputStream:
27.69 + * <br>
27.70 + * <pre>
27.71 + * FileOutputStream fos = new FileOutputStream("t.tmp");
27.72 + * ObjectOutputStream oos = new ObjectOutputStream(fos);
27.73 + *
27.74 + * oos.writeInt(12345);
27.75 + * oos.writeObject("Today");
27.76 + * oos.writeObject(new Date());
27.77 + *
27.78 + * oos.close();
27.79 + * </pre>
27.80 + *
27.81 + * <p>Classes that require special handling during the serialization and
27.82 + * deserialization process must implement special methods with these exact
27.83 + * signatures:
27.84 + * <br>
27.85 + * <pre>
27.86 + * private void readObject(java.io.ObjectInputStream stream)
27.87 + * throws IOException, ClassNotFoundException;
27.88 + * private void writeObject(java.io.ObjectOutputStream stream)
27.89 + * throws IOException
27.90 + * private void readObjectNoData()
27.91 + * throws ObjectStreamException;
27.92 + * </pre>
27.93 + *
27.94 + * <p>The writeObject method is responsible for writing the state of the object
27.95 + * for its particular class so that the corresponding readObject method can
27.96 + * restore it. The method does not need to concern itself with the state
27.97 + * belonging to the object's superclasses or subclasses. State is saved by
27.98 + * writing the individual fields to the ObjectOutputStream using the
27.99 + * writeObject method or by using the methods for primitive data types
27.100 + * supported by DataOutput.
27.101 + *
27.102 + * <p>Serialization does not write out the fields of any object that does not
27.103 + * implement the java.io.Serializable interface. Subclasses of Objects that
27.104 + * are not serializable can be serializable. In this case the non-serializable
27.105 + * class must have a no-arg constructor to allow its fields to be initialized.
27.106 + * In this case it is the responsibility of the subclass to save and restore
27.107 + * the state of the non-serializable class. It is frequently the case that the
27.108 + * fields of that class are accessible (public, package, or protected) or that
27.109 + * there are get and set methods that can be used to restore the state.
27.110 + *
27.111 + * <p>Serialization of an object can be prevented by implementing writeObject
27.112 + * and readObject methods that throw the NotSerializableException. The
27.113 + * exception will be caught by the ObjectOutputStream and abort the
27.114 + * serialization process.
27.115 + *
27.116 + * <p>Implementing the Externalizable interface allows the object to assume
27.117 + * complete control over the contents and format of the object's serialized
27.118 + * form. The methods of the Externalizable interface, writeExternal and
27.119 + * readExternal, are called to save and restore the objects state. When
27.120 + * implemented by a class they can write and read their own state using all of
27.121 + * the methods of ObjectOutput and ObjectInput. It is the responsibility of
27.122 + * the objects to handle any versioning that occurs.
27.123 + *
27.124 + * <p>Enum constants are serialized differently than ordinary serializable or
27.125 + * externalizable objects. The serialized form of an enum constant consists
27.126 + * solely of its name; field values of the constant are not transmitted. To
27.127 + * serialize an enum constant, ObjectOutputStream writes the string returned by
27.128 + * the constant's name method. Like other serializable or externalizable
27.129 + * objects, enum constants can function as the targets of back references
27.130 + * appearing subsequently in the serialization stream. The process by which
27.131 + * enum constants are serialized cannot be customized; any class-specific
27.132 + * writeObject and writeReplace methods defined by enum types are ignored
27.133 + * during serialization. Similarly, any serialPersistentFields or
27.134 + * serialVersionUID field declarations are also ignored--all enum types have a
27.135 + * fixed serialVersionUID of 0L.
27.136 + *
27.137 + * <p>Primitive data, excluding serializable fields and externalizable data, is
27.138 + * written to the ObjectOutputStream in block-data records. A block data record
27.139 + * is composed of a header and data. The block data header consists of a marker
27.140 + * and the number of bytes to follow the header. Consecutive primitive data
27.141 + * writes are merged into one block-data record. The blocking factor used for
27.142 + * a block-data record will be 1024 bytes. Each block-data record will be
27.143 + * filled up to 1024 bytes, or be written whenever there is a termination of
27.144 + * block-data mode. Calls to the ObjectOutputStream methods writeObject,
27.145 + * defaultWriteObject and writeFields initially terminate any existing
27.146 + * block-data record.
27.147 + *
27.148 + * @author Mike Warres
27.149 + * @author Roger Riggs
27.150 + * @see java.io.DataOutput
27.151 + * @see java.io.ObjectInputStream
27.152 + * @see java.io.Serializable
27.153 + * @see java.io.Externalizable
27.154 + * @see <a href="../../../platform/serialization/spec/output.html">Object Serialization Specification, Section 2, Object Output Classes</a>
27.155 + * @since JDK1.1
27.156 + */
27.157 +public class ObjectOutputStream
27.158 + extends OutputStream implements ObjectOutput, ObjectStreamConstants
27.159 +{
27.160 + /** filter stream for handling block data conversion */
27.161 + private final BlockDataOutputStream bout;
27.162 + /** obj -> wire handle map */
27.163 + private final HandleTable handles;
27.164 + /** obj -> replacement obj map */
27.165 + private final ReplaceTable subs;
27.166 + /** stream protocol version */
27.167 + private int protocol = PROTOCOL_VERSION_2;
27.168 + /** recursion depth */
27.169 + private int depth;
27.170 +
27.171 + /** buffer for writing primitive field values */
27.172 + private byte[] primVals;
27.173 +
27.174 + /** if true, invoke writeObjectOverride() instead of writeObject() */
27.175 + private final boolean enableOverride;
27.176 + /** if true, invoke replaceObject() */
27.177 + private boolean enableReplace;
27.178 +
27.179 + // values below valid only during upcalls to writeObject()/writeExternal()
27.180 + /**
27.181 + * Context during upcalls to class-defined writeObject methods; holds
27.182 + * object currently being serialized and descriptor for current class.
27.183 + * Null when not during writeObject upcall.
27.184 + */
27.185 + private Object curContext;
27.186 + /** current PutField object */
27.187 + private PutFieldImpl curPut;
27.188 +
27.189 + /** custom storage for debug trace info */
27.190 + private final DebugTraceInfoStack debugInfoStack;
27.191 +
27.192 + /**
27.193 + * value of "sun.io.serialization.extendedDebugInfo" property,
27.194 + * as true or false for extended information about exception's place
27.195 + */
27.196 + private static final boolean extendedDebugInfo = false;
27.197 +
27.198 + /**
27.199 + * Creates an ObjectOutputStream that writes to the specified OutputStream.
27.200 + * This constructor writes the serialization stream header to the
27.201 + * underlying stream; callers may wish to flush the stream immediately to
27.202 + * ensure that constructors for receiving ObjectInputStreams will not block
27.203 + * when reading the header.
27.204 + *
27.205 + * <p>If a security manager is installed, this constructor will check for
27.206 + * the "enableSubclassImplementation" SerializablePermission when invoked
27.207 + * directly or indirectly by the constructor of a subclass which overrides
27.208 + * the ObjectOutputStream.putFields or ObjectOutputStream.writeUnshared
27.209 + * methods.
27.210 + *
27.211 + * @param out output stream to write to
27.212 + * @throws IOException if an I/O error occurs while writing stream header
27.213 + * @throws SecurityException if untrusted subclass illegally overrides
27.214 + * security-sensitive methods
27.215 + * @throws NullPointerException if <code>out</code> is <code>null</code>
27.216 + * @since 1.4
27.217 + * @see ObjectOutputStream#ObjectOutputStream()
27.218 + * @see ObjectOutputStream#putFields()
27.219 + * @see ObjectInputStream#ObjectInputStream(InputStream)
27.220 + */
27.221 + public ObjectOutputStream(OutputStream out) throws IOException {
27.222 + verifySubclass();
27.223 + bout = new BlockDataOutputStream(out);
27.224 + handles = new HandleTable(10, (float) 3.00);
27.225 + subs = new ReplaceTable(10, (float) 3.00);
27.226 + enableOverride = false;
27.227 + writeStreamHeader();
27.228 + bout.setBlockDataMode(true);
27.229 + if (extendedDebugInfo) {
27.230 + debugInfoStack = new DebugTraceInfoStack();
27.231 + } else {
27.232 + debugInfoStack = null;
27.233 + }
27.234 + }
27.235 +
27.236 + /**
27.237 + * Provide a way for subclasses that are completely reimplementing
27.238 + * ObjectOutputStream to not have to allocate private data just used by
27.239 + * this implementation of ObjectOutputStream.
27.240 + *
27.241 + * <p>If there is a security manager installed, this method first calls the
27.242 + * security manager's <code>checkPermission</code> method with a
27.243 + * <code>SerializablePermission("enableSubclassImplementation")</code>
27.244 + * permission to ensure it's ok to enable subclassing.
27.245 + *
27.246 + * @throws SecurityException if a security manager exists and its
27.247 + * <code>checkPermission</code> method denies enabling
27.248 + * subclassing.
27.249 + * @see SecurityManager#checkPermission
27.250 + * @see java.io.SerializablePermission
27.251 + */
27.252 + protected ObjectOutputStream() throws IOException, SecurityException {
27.253 + throw new SecurityException();
27.254 + }
27.255 +
27.256 + /**
27.257 + * Specify stream protocol version to use when writing the stream.
27.258 + *
27.259 + * <p>This routine provides a hook to enable the current version of
27.260 + * Serialization to write in a format that is backwards compatible to a
27.261 + * previous version of the stream format.
27.262 + *
27.263 + * <p>Every effort will be made to avoid introducing additional
27.264 + * backwards incompatibilities; however, sometimes there is no
27.265 + * other alternative.
27.266 + *
27.267 + * @param version use ProtocolVersion from java.io.ObjectStreamConstants.
27.268 + * @throws IllegalStateException if called after any objects
27.269 + * have been serialized.
27.270 + * @throws IllegalArgumentException if invalid version is passed in.
27.271 + * @throws IOException if I/O errors occur
27.272 + * @see java.io.ObjectStreamConstants#PROTOCOL_VERSION_1
27.273 + * @see java.io.ObjectStreamConstants#PROTOCOL_VERSION_2
27.274 + * @since 1.2
27.275 + */
27.276 + public void useProtocolVersion(int version) throws IOException {
27.277 + if (handles.size() != 0) {
27.278 + // REMIND: implement better check for pristine stream?
27.279 + throw new IllegalStateException("stream non-empty");
27.280 + }
27.281 + switch (version) {
27.282 + case PROTOCOL_VERSION_1:
27.283 + case PROTOCOL_VERSION_2:
27.284 + protocol = version;
27.285 + break;
27.286 +
27.287 + default:
27.288 + throw new IllegalArgumentException(
27.289 + "unknown version: " + version);
27.290 + }
27.291 + }
27.292 +
27.293 + /**
27.294 + * Write the specified object to the ObjectOutputStream. The class of the
27.295 + * object, the signature of the class, and the values of the non-transient
27.296 + * and non-static fields of the class and all of its supertypes are
27.297 + * written. Default serialization for a class can be overridden using the
27.298 + * writeObject and the readObject methods. Objects referenced by this
27.299 + * object are written transitively so that a complete equivalent graph of
27.300 + * objects can be reconstructed by an ObjectInputStream.
27.301 + *
27.302 + * <p>Exceptions are thrown for problems with the OutputStream and for
27.303 + * classes that should not be serialized. All exceptions are fatal to the
27.304 + * OutputStream, which is left in an indeterminate state, and it is up to
27.305 + * the caller to ignore or recover the stream state.
27.306 + *
27.307 + * @throws InvalidClassException Something is wrong with a class used by
27.308 + * serialization.
27.309 + * @throws NotSerializableException Some object to be serialized does not
27.310 + * implement the java.io.Serializable interface.
27.311 + * @throws IOException Any exception thrown by the underlying
27.312 + * OutputStream.
27.313 + */
27.314 + public final void writeObject(Object obj) throws IOException {
27.315 + if (enableOverride) {
27.316 + writeObjectOverride(obj);
27.317 + return;
27.318 + }
27.319 + try {
27.320 + writeObject0(obj, false);
27.321 + } catch (IOException ex) {
27.322 + if (depth == 0) {
27.323 + writeFatalException(ex);
27.324 + }
27.325 + throw ex;
27.326 + }
27.327 + }
27.328 +
27.329 + /**
27.330 + * Method used by subclasses to override the default writeObject method.
27.331 + * This method is called by trusted subclasses of ObjectInputStream that
27.332 + * constructed ObjectInputStream using the protected no-arg constructor.
27.333 + * The subclass is expected to provide an override method with the modifier
27.334 + * "final".
27.335 + *
27.336 + * @param obj object to be written to the underlying stream
27.337 + * @throws IOException if there are I/O errors while writing to the
27.338 + * underlying stream
27.339 + * @see #ObjectOutputStream()
27.340 + * @see #writeObject(Object)
27.341 + * @since 1.2
27.342 + */
27.343 + protected void writeObjectOverride(Object obj) throws IOException {
27.344 + }
27.345 +
27.346 + /**
27.347 + * Writes an "unshared" object to the ObjectOutputStream. This method is
27.348 + * identical to writeObject, except that it always writes the given object
27.349 + * as a new, unique object in the stream (as opposed to a back-reference
27.350 + * pointing to a previously serialized instance). Specifically:
27.351 + * <ul>
27.352 + * <li>An object written via writeUnshared is always serialized in the
27.353 + * same manner as a newly appearing object (an object that has not
27.354 + * been written to the stream yet), regardless of whether or not the
27.355 + * object has been written previously.
27.356 + *
27.357 + * <li>If writeObject is used to write an object that has been previously
27.358 + * written with writeUnshared, the previous writeUnshared operation
27.359 + * is treated as if it were a write of a separate object. In other
27.360 + * words, ObjectOutputStream will never generate back-references to
27.361 + * object data written by calls to writeUnshared.
27.362 + * </ul>
27.363 + * While writing an object via writeUnshared does not in itself guarantee a
27.364 + * unique reference to the object when it is deserialized, it allows a
27.365 + * single object to be defined multiple times in a stream, so that multiple
27.366 + * calls to readUnshared by the receiver will not conflict. Note that the
27.367 + * rules described above only apply to the base-level object written with
27.368 + * writeUnshared, and not to any transitively referenced sub-objects in the
27.369 + * object graph to be serialized.
27.370 + *
27.371 + * <p>ObjectOutputStream subclasses which override this method can only be
27.372 + * constructed in security contexts possessing the
27.373 + * "enableSubclassImplementation" SerializablePermission; any attempt to
27.374 + * instantiate such a subclass without this permission will cause a
27.375 + * SecurityException to be thrown.
27.376 + *
27.377 + * @param obj object to write to stream
27.378 + * @throws NotSerializableException if an object in the graph to be
27.379 + * serialized does not implement the Serializable interface
27.380 + * @throws InvalidClassException if a problem exists with the class of an
27.381 + * object to be serialized
27.382 + * @throws IOException if an I/O error occurs during serialization
27.383 + * @since 1.4
27.384 + */
27.385 + public void writeUnshared(Object obj) throws IOException {
27.386 + try {
27.387 + writeObject0(obj, true);
27.388 + } catch (IOException ex) {
27.389 + if (depth == 0) {
27.390 + writeFatalException(ex);
27.391 + }
27.392 + throw ex;
27.393 + }
27.394 + }
27.395 +
27.396 + /**
27.397 + * Write the non-static and non-transient fields of the current class to
27.398 + * this stream. This may only be called from the writeObject method of the
27.399 + * class being serialized. It will throw the NotActiveException if it is
27.400 + * called otherwise.
27.401 + *
27.402 + * @throws IOException if I/O errors occur while writing to the underlying
27.403 + * <code>OutputStream</code>
27.404 + */
27.405 + public void defaultWriteObject() throws IOException {
27.406 + if ( curContext == null ) {
27.407 + throw new NotActiveException("not in call to writeObject");
27.408 + }
27.409 + Object curObj = null; // curContext.getObj();
27.410 + ObjectStreamClass curDesc = null; // curContext.getDesc();
27.411 + bout.setBlockDataMode(false);
27.412 + defaultWriteFields(curObj, curDesc);
27.413 + bout.setBlockDataMode(true);
27.414 + }
27.415 +
27.416 + /**
27.417 + * Retrieve the object used to buffer persistent fields to be written to
27.418 + * the stream. The fields will be written to the stream when writeFields
27.419 + * method is called.
27.420 + *
27.421 + * @return an instance of the class Putfield that holds the serializable
27.422 + * fields
27.423 + * @throws IOException if I/O errors occur
27.424 + * @since 1.2
27.425 + */
27.426 + public ObjectOutputStream.PutField putFields() throws IOException {
27.427 + if (curPut == null) {
27.428 + if (curContext == null) {
27.429 + throw new NotActiveException("not in call to writeObject");
27.430 + }
27.431 + Object curObj = null; // curContext.getObj();
27.432 + ObjectStreamClass curDesc = null; // curContext.getDesc();
27.433 + curPut = new PutFieldImpl(curDesc);
27.434 + }
27.435 + return curPut;
27.436 + }
27.437 +
27.438 + /**
27.439 + * Write the buffered fields to the stream.
27.440 + *
27.441 + * @throws IOException if I/O errors occur while writing to the underlying
27.442 + * stream
27.443 + * @throws NotActiveException Called when a classes writeObject method was
27.444 + * not called to write the state of the object.
27.445 + * @since 1.2
27.446 + */
27.447 + public void writeFields() throws IOException {
27.448 + if (curPut == null) {
27.449 + throw new NotActiveException("no current PutField object");
27.450 + }
27.451 + bout.setBlockDataMode(false);
27.452 + curPut.writeFields();
27.453 + bout.setBlockDataMode(true);
27.454 + }
27.455 +
27.456 + /**
27.457 + * Reset will disregard the state of any objects already written to the
27.458 + * stream. The state is reset to be the same as a new ObjectOutputStream.
27.459 + * The current point in the stream is marked as reset so the corresponding
27.460 + * ObjectInputStream will be reset at the same point. Objects previously
27.461 + * written to the stream will not be refered to as already being in the
27.462 + * stream. They will be written to the stream again.
27.463 + *
27.464 + * @throws IOException if reset() is invoked while serializing an object.
27.465 + */
27.466 + public void reset() throws IOException {
27.467 + if (depth != 0) {
27.468 + throw new IOException("stream active");
27.469 + }
27.470 + bout.setBlockDataMode(false);
27.471 + bout.writeByte(TC_RESET);
27.472 + clear();
27.473 + bout.setBlockDataMode(true);
27.474 + }
27.475 +
27.476 + /**
27.477 + * Subclasses may implement this method to allow class data to be stored in
27.478 + * the stream. By default this method does nothing. The corresponding
27.479 + * method in ObjectInputStream is resolveClass. This method is called
27.480 + * exactly once for each unique class in the stream. The class name and
27.481 + * signature will have already been written to the stream. This method may
27.482 + * make free use of the ObjectOutputStream to save any representation of
27.483 + * the class it deems suitable (for example, the bytes of the class file).
27.484 + * The resolveClass method in the corresponding subclass of
27.485 + * ObjectInputStream must read and use any data or objects written by
27.486 + * annotateClass.
27.487 + *
27.488 + * @param cl the class to annotate custom data for
27.489 + * @throws IOException Any exception thrown by the underlying
27.490 + * OutputStream.
27.491 + */
27.492 + protected void annotateClass(Class<?> cl) throws IOException {
27.493 + }
27.494 +
27.495 + /**
27.496 + * Subclasses may implement this method to store custom data in the stream
27.497 + * along with descriptors for dynamic proxy classes.
27.498 + *
27.499 + * <p>This method is called exactly once for each unique proxy class
27.500 + * descriptor in the stream. The default implementation of this method in
27.501 + * <code>ObjectOutputStream</code> does nothing.
27.502 + *
27.503 + * <p>The corresponding method in <code>ObjectInputStream</code> is
27.504 + * <code>resolveProxyClass</code>. For a given subclass of
27.505 + * <code>ObjectOutputStream</code> that overrides this method, the
27.506 + * <code>resolveProxyClass</code> method in the corresponding subclass of
27.507 + * <code>ObjectInputStream</code> must read any data or objects written by
27.508 + * <code>annotateProxyClass</code>.
27.509 + *
27.510 + * @param cl the proxy class to annotate custom data for
27.511 + * @throws IOException any exception thrown by the underlying
27.512 + * <code>OutputStream</code>
27.513 + * @see ObjectInputStream#resolveProxyClass(String[])
27.514 + * @since 1.3
27.515 + */
27.516 + protected void annotateProxyClass(Class<?> cl) throws IOException {
27.517 + }
27.518 +
27.519 + /**
27.520 + * This method will allow trusted subclasses of ObjectOutputStream to
27.521 + * substitute one object for another during serialization. Replacing
27.522 + * objects is disabled until enableReplaceObject is called. The
27.523 + * enableReplaceObject method checks that the stream requesting to do
27.524 + * replacement can be trusted. The first occurrence of each object written
27.525 + * into the serialization stream is passed to replaceObject. Subsequent
27.526 + * references to the object are replaced by the object returned by the
27.527 + * original call to replaceObject. To ensure that the private state of
27.528 + * objects is not unintentionally exposed, only trusted streams may use
27.529 + * replaceObject.
27.530 + *
27.531 + * <p>The ObjectOutputStream.writeObject method takes a parameter of type
27.532 + * Object (as opposed to type Serializable) to allow for cases where
27.533 + * non-serializable objects are replaced by serializable ones.
27.534 + *
27.535 + * <p>When a subclass is replacing objects it must insure that either a
27.536 + * complementary substitution must be made during deserialization or that
27.537 + * the substituted object is compatible with every field where the
27.538 + * reference will be stored. Objects whose type is not a subclass of the
27.539 + * type of the field or array element abort the serialization by raising an
27.540 + * exception and the object is not be stored.
27.541 + *
27.542 + * <p>This method is called only once when each object is first
27.543 + * encountered. All subsequent references to the object will be redirected
27.544 + * to the new object. This method should return the object to be
27.545 + * substituted or the original object.
27.546 + *
27.547 + * <p>Null can be returned as the object to be substituted, but may cause
27.548 + * NullReferenceException in classes that contain references to the
27.549 + * original object since they may be expecting an object instead of
27.550 + * null.
27.551 + *
27.552 + * @param obj the object to be replaced
27.553 + * @return the alternate object that replaced the specified one
27.554 + * @throws IOException Any exception thrown by the underlying
27.555 + * OutputStream.
27.556 + */
27.557 + protected Object replaceObject(Object obj) throws IOException {
27.558 + return obj;
27.559 + }
27.560 +
27.561 + /**
27.562 + * Enable the stream to do replacement of objects in the stream. When
27.563 + * enabled, the replaceObject method is called for every object being
27.564 + * serialized.
27.565 + *
27.566 + * <p>If <code>enable</code> is true, and there is a security manager
27.567 + * installed, this method first calls the security manager's
27.568 + * <code>checkPermission</code> method with a
27.569 + * <code>SerializablePermission("enableSubstitution")</code> permission to
27.570 + * ensure it's ok to enable the stream to do replacement of objects in the
27.571 + * stream.
27.572 + *
27.573 + * @param enable boolean parameter to enable replacement of objects
27.574 + * @return the previous setting before this method was invoked
27.575 + * @throws SecurityException if a security manager exists and its
27.576 + * <code>checkPermission</code> method denies enabling the stream
27.577 + * to do replacement of objects in the stream.
27.578 + * @see SecurityManager#checkPermission
27.579 + * @see java.io.SerializablePermission
27.580 + */
27.581 + protected boolean enableReplaceObject(boolean enable)
27.582 + throws SecurityException
27.583 + {
27.584 + throw new SecurityException();
27.585 + }
27.586 +
27.587 + /**
27.588 + * The writeStreamHeader method is provided so subclasses can append or
27.589 + * prepend their own header to the stream. It writes the magic number and
27.590 + * version to the stream.
27.591 + *
27.592 + * @throws IOException if I/O errors occur while writing to the underlying
27.593 + * stream
27.594 + */
27.595 + protected void writeStreamHeader() throws IOException {
27.596 + bout.writeShort(STREAM_MAGIC);
27.597 + bout.writeShort(STREAM_VERSION);
27.598 + }
27.599 +
27.600 + /**
27.601 + * Write the specified class descriptor to the ObjectOutputStream. Class
27.602 + * descriptors are used to identify the classes of objects written to the
27.603 + * stream. Subclasses of ObjectOutputStream may override this method to
27.604 + * customize the way in which class descriptors are written to the
27.605 + * serialization stream. The corresponding method in ObjectInputStream,
27.606 + * <code>readClassDescriptor</code>, should then be overridden to
27.607 + * reconstitute the class descriptor from its custom stream representation.
27.608 + * By default, this method writes class descriptors according to the format
27.609 + * defined in the Object Serialization specification.
27.610 + *
27.611 + * <p>Note that this method will only be called if the ObjectOutputStream
27.612 + * is not using the old serialization stream format (set by calling
27.613 + * ObjectOutputStream's <code>useProtocolVersion</code> method). If this
27.614 + * serialization stream is using the old format
27.615 + * (<code>PROTOCOL_VERSION_1</code>), the class descriptor will be written
27.616 + * internally in a manner that cannot be overridden or customized.
27.617 + *
27.618 + * @param desc class descriptor to write to the stream
27.619 + * @throws IOException If an I/O error has occurred.
27.620 + * @see java.io.ObjectInputStream#readClassDescriptor()
27.621 + * @see #useProtocolVersion(int)
27.622 + * @see java.io.ObjectStreamConstants#PROTOCOL_VERSION_1
27.623 + * @since 1.3
27.624 + */
27.625 + protected void writeClassDescriptor(ObjectStreamClass desc)
27.626 + throws IOException
27.627 + {
27.628 + desc.writeNonProxy(this);
27.629 + }
27.630 +
27.631 + /**
27.632 + * Writes a byte. This method will block until the byte is actually
27.633 + * written.
27.634 + *
27.635 + * @param val the byte to be written to the stream
27.636 + * @throws IOException If an I/O error has occurred.
27.637 + */
27.638 + public void write(int val) throws IOException {
27.639 + bout.write(val);
27.640 + }
27.641 +
27.642 + /**
27.643 + * Writes an array of bytes. This method will block until the bytes are
27.644 + * actually written.
27.645 + *
27.646 + * @param buf the data to be written
27.647 + * @throws IOException If an I/O error has occurred.
27.648 + */
27.649 + public void write(byte[] buf) throws IOException {
27.650 + bout.write(buf, 0, buf.length, false);
27.651 + }
27.652 +
27.653 + /**
27.654 + * Writes a sub array of bytes.
27.655 + *
27.656 + * @param buf the data to be written
27.657 + * @param off the start offset in the data
27.658 + * @param len the number of bytes that are written
27.659 + * @throws IOException If an I/O error has occurred.
27.660 + */
27.661 + public void write(byte[] buf, int off, int len) throws IOException {
27.662 + if (buf == null) {
27.663 + throw new NullPointerException();
27.664 + }
27.665 + int endoff = off + len;
27.666 + if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
27.667 + throw new IndexOutOfBoundsException();
27.668 + }
27.669 + bout.write(buf, off, len, false);
27.670 + }
27.671 +
27.672 + /**
27.673 + * Flushes the stream. This will write any buffered output bytes and flush
27.674 + * through to the underlying stream.
27.675 + *
27.676 + * @throws IOException If an I/O error has occurred.
27.677 + */
27.678 + public void flush() throws IOException {
27.679 + bout.flush();
27.680 + }
27.681 +
27.682 + /**
27.683 + * Drain any buffered data in ObjectOutputStream. Similar to flush but
27.684 + * does not propagate the flush to the underlying stream.
27.685 + *
27.686 + * @throws IOException if I/O errors occur while writing to the underlying
27.687 + * stream
27.688 + */
27.689 + protected void drain() throws IOException {
27.690 + bout.drain();
27.691 + }
27.692 +
27.693 + /**
27.694 + * Closes the stream. This method must be called to release any resources
27.695 + * associated with the stream.
27.696 + *
27.697 + * @throws IOException If an I/O error has occurred.
27.698 + */
27.699 + public void close() throws IOException {
27.700 + flush();
27.701 + clear();
27.702 + bout.close();
27.703 + }
27.704 +
27.705 + /**
27.706 + * Writes a boolean.
27.707 + *
27.708 + * @param val the boolean to be written
27.709 + * @throws IOException if I/O errors occur while writing to the underlying
27.710 + * stream
27.711 + */
27.712 + public void writeBoolean(boolean val) throws IOException {
27.713 + bout.writeBoolean(val);
27.714 + }
27.715 +
27.716 + /**
27.717 + * Writes an 8 bit byte.
27.718 + *
27.719 + * @param val the byte value to be written
27.720 + * @throws IOException if I/O errors occur while writing to the underlying
27.721 + * stream
27.722 + */
27.723 + public void writeByte(int val) throws IOException {
27.724 + bout.writeByte(val);
27.725 + }
27.726 +
27.727 + /**
27.728 + * Writes a 16 bit short.
27.729 + *
27.730 + * @param val the short value to be written
27.731 + * @throws IOException if I/O errors occur while writing to the underlying
27.732 + * stream
27.733 + */
27.734 + public void writeShort(int val) throws IOException {
27.735 + bout.writeShort(val);
27.736 + }
27.737 +
27.738 + /**
27.739 + * Writes a 16 bit char.
27.740 + *
27.741 + * @param val the char value to be written
27.742 + * @throws IOException if I/O errors occur while writing to the underlying
27.743 + * stream
27.744 + */
27.745 + public void writeChar(int val) throws IOException {
27.746 + bout.writeChar(val);
27.747 + }
27.748 +
27.749 + /**
27.750 + * Writes a 32 bit int.
27.751 + *
27.752 + * @param val the integer value to be written
27.753 + * @throws IOException if I/O errors occur while writing to the underlying
27.754 + * stream
27.755 + */
27.756 + public void writeInt(int val) throws IOException {
27.757 + bout.writeInt(val);
27.758 + }
27.759 +
27.760 + /**
27.761 + * Writes a 64 bit long.
27.762 + *
27.763 + * @param val the long value to be written
27.764 + * @throws IOException if I/O errors occur while writing to the underlying
27.765 + * stream
27.766 + */
27.767 + public void writeLong(long val) throws IOException {
27.768 + bout.writeLong(val);
27.769 + }
27.770 +
27.771 + /**
27.772 + * Writes a 32 bit float.
27.773 + *
27.774 + * @param val the float value to be written
27.775 + * @throws IOException if I/O errors occur while writing to the underlying
27.776 + * stream
27.777 + */
27.778 + public void writeFloat(float val) throws IOException {
27.779 + bout.writeFloat(val);
27.780 + }
27.781 +
27.782 + /**
27.783 + * Writes a 64 bit double.
27.784 + *
27.785 + * @param val the double value to be written
27.786 + * @throws IOException if I/O errors occur while writing to the underlying
27.787 + * stream
27.788 + */
27.789 + public void writeDouble(double val) throws IOException {
27.790 + bout.writeDouble(val);
27.791 + }
27.792 +
27.793 + /**
27.794 + * Writes a String as a sequence of bytes.
27.795 + *
27.796 + * @param str the String of bytes to be written
27.797 + * @throws IOException if I/O errors occur while writing to the underlying
27.798 + * stream
27.799 + */
27.800 + public void writeBytes(String str) throws IOException {
27.801 + bout.writeBytes(str);
27.802 + }
27.803 +
27.804 + /**
27.805 + * Writes a String as a sequence of chars.
27.806 + *
27.807 + * @param str the String of chars to be written
27.808 + * @throws IOException if I/O errors occur while writing to the underlying
27.809 + * stream
27.810 + */
27.811 + public void writeChars(String str) throws IOException {
27.812 + bout.writeChars(str);
27.813 + }
27.814 +
27.815 + /**
27.816 + * Primitive data write of this String in
27.817 + * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
27.818 + * format. Note that there is a
27.819 + * significant difference between writing a String into the stream as
27.820 + * primitive data or as an Object. A String instance written by writeObject
27.821 + * is written into the stream as a String initially. Future writeObject()
27.822 + * calls write references to the string into the stream.
27.823 + *
27.824 + * @param str the String to be written
27.825 + * @throws IOException if I/O errors occur while writing to the underlying
27.826 + * stream
27.827 + */
27.828 + public void writeUTF(String str) throws IOException {
27.829 + bout.writeUTF(str);
27.830 + }
27.831 +
27.832 + /**
27.833 + * Provide programmatic access to the persistent fields to be written
27.834 + * to ObjectOutput.
27.835 + *
27.836 + * @since 1.2
27.837 + */
27.838 + public static abstract class PutField {
27.839 +
27.840 + /**
27.841 + * Put the value of the named boolean field into the persistent field.
27.842 + *
27.843 + * @param name the name of the serializable field
27.844 + * @param val the value to assign to the field
27.845 + * @throws IllegalArgumentException if <code>name</code> does not
27.846 + * match the name of a serializable field for the class whose fields
27.847 + * are being written, or if the type of the named field is not
27.848 + * <code>boolean</code>
27.849 + */
27.850 + public abstract void put(String name, boolean val);
27.851 +
27.852 + /**
27.853 + * Put the value of the named byte field into the persistent field.
27.854 + *
27.855 + * @param name the name of the serializable field
27.856 + * @param val the value to assign to the field
27.857 + * @throws IllegalArgumentException if <code>name</code> does not
27.858 + * match the name of a serializable field for the class whose fields
27.859 + * are being written, or if the type of the named field is not
27.860 + * <code>byte</code>
27.861 + */
27.862 + public abstract void put(String name, byte val);
27.863 +
27.864 + /**
27.865 + * Put the value of the named char field into the persistent field.
27.866 + *
27.867 + * @param name the name of the serializable field
27.868 + * @param val the value to assign to the field
27.869 + * @throws IllegalArgumentException if <code>name</code> does not
27.870 + * match the name of a serializable field for the class whose fields
27.871 + * are being written, or if the type of the named field is not
27.872 + * <code>char</code>
27.873 + */
27.874 + public abstract void put(String name, char val);
27.875 +
27.876 + /**
27.877 + * Put the value of the named short field into the persistent field.
27.878 + *
27.879 + * @param name the name of the serializable field
27.880 + * @param val the value to assign to the field
27.881 + * @throws IllegalArgumentException if <code>name</code> does not
27.882 + * match the name of a serializable field for the class whose fields
27.883 + * are being written, or if the type of the named field is not
27.884 + * <code>short</code>
27.885 + */
27.886 + public abstract void put(String name, short val);
27.887 +
27.888 + /**
27.889 + * Put the value of the named int field into the persistent field.
27.890 + *
27.891 + * @param name the name of the serializable field
27.892 + * @param val the value to assign to the field
27.893 + * @throws IllegalArgumentException if <code>name</code> does not
27.894 + * match the name of a serializable field for the class whose fields
27.895 + * are being written, or if the type of the named field is not
27.896 + * <code>int</code>
27.897 + */
27.898 + public abstract void put(String name, int val);
27.899 +
27.900 + /**
27.901 + * Put the value of the named long field into the persistent field.
27.902 + *
27.903 + * @param name the name of the serializable field
27.904 + * @param val the value to assign to the field
27.905 + * @throws IllegalArgumentException if <code>name</code> does not
27.906 + * match the name of a serializable field for the class whose fields
27.907 + * are being written, or if the type of the named field is not
27.908 + * <code>long</code>
27.909 + */
27.910 + public abstract void put(String name, long val);
27.911 +
27.912 + /**
27.913 + * Put the value of the named float field into the persistent field.
27.914 + *
27.915 + * @param name the name of the serializable field
27.916 + * @param val the value to assign to the field
27.917 + * @throws IllegalArgumentException if <code>name</code> does not
27.918 + * match the name of a serializable field for the class whose fields
27.919 + * are being written, or if the type of the named field is not
27.920 + * <code>float</code>
27.921 + */
27.922 + public abstract void put(String name, float val);
27.923 +
27.924 + /**
27.925 + * Put the value of the named double field into the persistent field.
27.926 + *
27.927 + * @param name the name of the serializable field
27.928 + * @param val the value to assign to the field
27.929 + * @throws IllegalArgumentException if <code>name</code> does not
27.930 + * match the name of a serializable field for the class whose fields
27.931 + * are being written, or if the type of the named field is not
27.932 + * <code>double</code>
27.933 + */
27.934 + public abstract void put(String name, double val);
27.935 +
27.936 + /**
27.937 + * Put the value of the named Object field into the persistent field.
27.938 + *
27.939 + * @param name the name of the serializable field
27.940 + * @param val the value to assign to the field
27.941 + * (which may be <code>null</code>)
27.942 + * @throws IllegalArgumentException if <code>name</code> does not
27.943 + * match the name of a serializable field for the class whose fields
27.944 + * are being written, or if the type of the named field is not a
27.945 + * reference type
27.946 + */
27.947 + public abstract void put(String name, Object val);
27.948 +
27.949 + /**
27.950 + * Write the data and fields to the specified ObjectOutput stream,
27.951 + * which must be the same stream that produced this
27.952 + * <code>PutField</code> object.
27.953 + *
27.954 + * @param out the stream to write the data and fields to
27.955 + * @throws IOException if I/O errors occur while writing to the
27.956 + * underlying stream
27.957 + * @throws IllegalArgumentException if the specified stream is not
27.958 + * the same stream that produced this <code>PutField</code>
27.959 + * object
27.960 + * @deprecated This method does not write the values contained by this
27.961 + * <code>PutField</code> object in a proper format, and may
27.962 + * result in corruption of the serialization stream. The
27.963 + * correct way to write <code>PutField</code> data is by
27.964 + * calling the {@link java.io.ObjectOutputStream#writeFields()}
27.965 + * method.
27.966 + */
27.967 + @Deprecated
27.968 + public abstract void write(ObjectOutput out) throws IOException;
27.969 + }
27.970 +
27.971 +
27.972 + /**
27.973 + * Returns protocol version in use.
27.974 + */
27.975 + int getProtocolVersion() {
27.976 + return protocol;
27.977 + }
27.978 +
27.979 + /**
27.980 + * Writes string without allowing it to be replaced in stream. Used by
27.981 + * ObjectStreamClass to write class descriptor type strings.
27.982 + */
27.983 + void writeTypeString(String str) throws IOException {
27.984 + int handle;
27.985 + if (str == null) {
27.986 + writeNull();
27.987 + } else if ((handle = handles.lookup(str)) != -1) {
27.988 + writeHandle(handle);
27.989 + } else {
27.990 + writeString(str, false);
27.991 + }
27.992 + }
27.993 +
27.994 + /**
27.995 + * Verifies that this (possibly subclass) instance can be constructed
27.996 + * without violating security constraints: the subclass must not override
27.997 + * security-sensitive non-final methods, or else the
27.998 + * "enableSubclassImplementation" SerializablePermission is checked.
27.999 + */
27.1000 + private void verifySubclass() {
27.1001 + Class cl = getClass();
27.1002 + if (cl == ObjectOutputStream.class) {
27.1003 + return;
27.1004 + }
27.1005 + throw new SecurityException();
27.1006 + }
27.1007 +
27.1008 + /**
27.1009 + * Clears internal data structures.
27.1010 + */
27.1011 + private void clear() {
27.1012 + subs.clear();
27.1013 + handles.clear();
27.1014 + }
27.1015 +
27.1016 + /**
27.1017 + * Underlying writeObject/writeUnshared implementation.
27.1018 + */
27.1019 + private void writeObject0(Object obj, boolean unshared)
27.1020 + throws IOException
27.1021 + {
27.1022 + boolean oldMode = bout.setBlockDataMode(false);
27.1023 + depth++;
27.1024 + try {
27.1025 + // handle previously written and non-replaceable objects
27.1026 + int h;
27.1027 + if ((obj = subs.lookup(obj)) == null) {
27.1028 + writeNull();
27.1029 + return;
27.1030 + } else if (!unshared && (h = handles.lookup(obj)) != -1) {
27.1031 + writeHandle(h);
27.1032 + return;
27.1033 + } else if (obj instanceof Class) {
27.1034 + writeClass((Class) obj, unshared);
27.1035 + return;
27.1036 + } else if (obj instanceof ObjectStreamClass) {
27.1037 + writeClassDesc((ObjectStreamClass) obj, unshared);
27.1038 + return;
27.1039 + }
27.1040 +
27.1041 + // check for replacement object
27.1042 + Object orig = obj;
27.1043 + Class cl = obj.getClass();
27.1044 + ObjectStreamClass desc;
27.1045 + for (;;) {
27.1046 + // REMIND: skip this check for strings/arrays?
27.1047 + Class repCl;
27.1048 + desc = ObjectStreamClass.lookup(cl, true);
27.1049 + if (!desc.hasWriteReplaceMethod() ||
27.1050 + (obj = desc.invokeWriteReplace(obj)) == null ||
27.1051 + (repCl = obj.getClass()) == cl)
27.1052 + {
27.1053 + break;
27.1054 + }
27.1055 + cl = repCl;
27.1056 + }
27.1057 + if (enableReplace) {
27.1058 + Object rep = replaceObject(obj);
27.1059 + if (rep != obj && rep != null) {
27.1060 + cl = rep.getClass();
27.1061 + desc = ObjectStreamClass.lookup(cl, true);
27.1062 + }
27.1063 + obj = rep;
27.1064 + }
27.1065 +
27.1066 + // if object replaced, run through original checks a second time
27.1067 + if (obj != orig) {
27.1068 + subs.assign(orig, obj);
27.1069 + if (obj == null) {
27.1070 + writeNull();
27.1071 + return;
27.1072 + } else if (!unshared && (h = handles.lookup(obj)) != -1) {
27.1073 + writeHandle(h);
27.1074 + return;
27.1075 + } else if (obj instanceof Class) {
27.1076 + writeClass((Class) obj, unshared);
27.1077 + return;
27.1078 + } else if (obj instanceof ObjectStreamClass) {
27.1079 + writeClassDesc((ObjectStreamClass) obj, unshared);
27.1080 + return;
27.1081 + }
27.1082 + }
27.1083 +
27.1084 + // remaining cases
27.1085 + if (obj instanceof String) {
27.1086 + writeString((String) obj, unshared);
27.1087 + } else if (cl.isArray()) {
27.1088 + writeArray(obj, desc, unshared);
27.1089 + } else if (obj instanceof Enum) {
27.1090 + writeEnum((Enum) obj, desc, unshared);
27.1091 + } else if (obj instanceof Serializable) {
27.1092 + writeOrdinaryObject(obj, desc, unshared);
27.1093 + } else {
27.1094 + if (extendedDebugInfo) {
27.1095 + throw new NotSerializableException(
27.1096 + cl.getName() + "\n" + debugInfoStack.toString());
27.1097 + } else {
27.1098 + throw new NotSerializableException(cl.getName());
27.1099 + }
27.1100 + }
27.1101 + } finally {
27.1102 + depth--;
27.1103 + bout.setBlockDataMode(oldMode);
27.1104 + }
27.1105 + }
27.1106 +
27.1107 + /**
27.1108 + * Writes null code to stream.
27.1109 + */
27.1110 + private void writeNull() throws IOException {
27.1111 + bout.writeByte(TC_NULL);
27.1112 + }
27.1113 +
27.1114 + /**
27.1115 + * Writes given object handle to stream.
27.1116 + */
27.1117 + private void writeHandle(int handle) throws IOException {
27.1118 + bout.writeByte(TC_REFERENCE);
27.1119 + bout.writeInt(baseWireHandle + handle);
27.1120 + }
27.1121 +
27.1122 + /**
27.1123 + * Writes representation of given class to stream.
27.1124 + */
27.1125 + private void writeClass(Class cl, boolean unshared) throws IOException {
27.1126 + bout.writeByte(TC_CLASS);
27.1127 + writeClassDesc(ObjectStreamClass.lookup(cl, true), false);
27.1128 + handles.assign(unshared ? null : cl);
27.1129 + }
27.1130 +
27.1131 + /**
27.1132 + * Writes representation of given class descriptor to stream.
27.1133 + */
27.1134 + private void writeClassDesc(ObjectStreamClass desc, boolean unshared)
27.1135 + throws IOException
27.1136 + {
27.1137 + int handle;
27.1138 + if (desc == null) {
27.1139 + writeNull();
27.1140 + } else if (!unshared && (handle = handles.lookup(desc)) != -1) {
27.1141 + writeHandle(handle);
27.1142 + } else if (desc.isProxy()) {
27.1143 + writeProxyDesc(desc, unshared);
27.1144 + } else {
27.1145 + writeNonProxyDesc(desc, unshared);
27.1146 + }
27.1147 + }
27.1148 +
27.1149 + /**
27.1150 + * Writes class descriptor representing a dynamic proxy class to stream.
27.1151 + */
27.1152 + private void writeProxyDesc(ObjectStreamClass desc, boolean unshared)
27.1153 + throws IOException
27.1154 + {
27.1155 + bout.writeByte(TC_PROXYCLASSDESC);
27.1156 + handles.assign(unshared ? null : desc);
27.1157 +
27.1158 + Class cl = desc.forClass();
27.1159 + Class[] ifaces = cl.getInterfaces();
27.1160 + bout.writeInt(ifaces.length);
27.1161 + for (int i = 0; i < ifaces.length; i++) {
27.1162 + bout.writeUTF(ifaces[i].getName());
27.1163 + }
27.1164 +
27.1165 + bout.setBlockDataMode(true);
27.1166 + annotateProxyClass(cl);
27.1167 + bout.setBlockDataMode(false);
27.1168 + bout.writeByte(TC_ENDBLOCKDATA);
27.1169 +
27.1170 + writeClassDesc(desc.getSuperDesc(), false);
27.1171 + }
27.1172 +
27.1173 + /**
27.1174 + * Writes class descriptor representing a standard (i.e., not a dynamic
27.1175 + * proxy) class to stream.
27.1176 + */
27.1177 + private void writeNonProxyDesc(ObjectStreamClass desc, boolean unshared)
27.1178 + throws IOException
27.1179 + {
27.1180 + bout.writeByte(TC_CLASSDESC);
27.1181 + handles.assign(unshared ? null : desc);
27.1182 +
27.1183 + if (protocol == PROTOCOL_VERSION_1) {
27.1184 + // do not invoke class descriptor write hook with old protocol
27.1185 + desc.writeNonProxy(this);
27.1186 + } else {
27.1187 + writeClassDescriptor(desc);
27.1188 + }
27.1189 +
27.1190 + Class cl = desc.forClass();
27.1191 + bout.setBlockDataMode(true);
27.1192 + annotateClass(cl);
27.1193 + bout.setBlockDataMode(false);
27.1194 + bout.writeByte(TC_ENDBLOCKDATA);
27.1195 +
27.1196 + writeClassDesc(desc.getSuperDesc(), false);
27.1197 + }
27.1198 +
27.1199 + /**
27.1200 + * Writes given string to stream, using standard or long UTF format
27.1201 + * depending on string length.
27.1202 + */
27.1203 + private void writeString(String str, boolean unshared) throws IOException {
27.1204 + handles.assign(unshared ? null : str);
27.1205 + long utflen = bout.getUTFLength(str);
27.1206 + if (utflen <= 0xFFFF) {
27.1207 + bout.writeByte(TC_STRING);
27.1208 + bout.writeUTF(str, utflen);
27.1209 + } else {
27.1210 + bout.writeByte(TC_LONGSTRING);
27.1211 + bout.writeLongUTF(str, utflen);
27.1212 + }
27.1213 + }
27.1214 +
27.1215 + /**
27.1216 + * Writes given array object to stream.
27.1217 + */
27.1218 + private void writeArray(Object array,
27.1219 + ObjectStreamClass desc,
27.1220 + boolean unshared)
27.1221 + throws IOException
27.1222 + {
27.1223 + bout.writeByte(TC_ARRAY);
27.1224 + writeClassDesc(desc, false);
27.1225 + handles.assign(unshared ? null : array);
27.1226 +
27.1227 + Class ccl = desc.forClass().getComponentType();
27.1228 + if (ccl.isPrimitive()) {
27.1229 + if (ccl == Integer.TYPE) {
27.1230 + int[] ia = (int[]) array;
27.1231 + bout.writeInt(ia.length);
27.1232 + bout.writeInts(ia, 0, ia.length);
27.1233 + } else if (ccl == Byte.TYPE) {
27.1234 + byte[] ba = (byte[]) array;
27.1235 + bout.writeInt(ba.length);
27.1236 + bout.write(ba, 0, ba.length, true);
27.1237 + } else if (ccl == Long.TYPE) {
27.1238 + long[] ja = (long[]) array;
27.1239 + bout.writeInt(ja.length);
27.1240 + bout.writeLongs(ja, 0, ja.length);
27.1241 + } else if (ccl == Float.TYPE) {
27.1242 + float[] fa = (float[]) array;
27.1243 + bout.writeInt(fa.length);
27.1244 + bout.writeFloats(fa, 0, fa.length);
27.1245 + } else if (ccl == Double.TYPE) {
27.1246 + double[] da = (double[]) array;
27.1247 + bout.writeInt(da.length);
27.1248 + bout.writeDoubles(da, 0, da.length);
27.1249 + } else if (ccl == Short.TYPE) {
27.1250 + short[] sa = (short[]) array;
27.1251 + bout.writeInt(sa.length);
27.1252 + bout.writeShorts(sa, 0, sa.length);
27.1253 + } else if (ccl == Character.TYPE) {
27.1254 + char[] ca = (char[]) array;
27.1255 + bout.writeInt(ca.length);
27.1256 + bout.writeChars(ca, 0, ca.length);
27.1257 + } else if (ccl == Boolean.TYPE) {
27.1258 + boolean[] za = (boolean[]) array;
27.1259 + bout.writeInt(za.length);
27.1260 + bout.writeBooleans(za, 0, za.length);
27.1261 + } else {
27.1262 + throw new InternalError();
27.1263 + }
27.1264 + } else {
27.1265 + Object[] objs = (Object[]) array;
27.1266 + int len = objs.length;
27.1267 + bout.writeInt(len);
27.1268 + if (extendedDebugInfo) {
27.1269 + debugInfoStack.push(
27.1270 + "array (class \"" + array.getClass().getName() +
27.1271 + "\", size: " + len + ")");
27.1272 + }
27.1273 + try {
27.1274 + for (int i = 0; i < len; i++) {
27.1275 + if (extendedDebugInfo) {
27.1276 + debugInfoStack.push(
27.1277 + "element of array (index: " + i + ")");
27.1278 + }
27.1279 + try {
27.1280 + writeObject0(objs[i], false);
27.1281 + } finally {
27.1282 + if (extendedDebugInfo) {
27.1283 + debugInfoStack.pop();
27.1284 + }
27.1285 + }
27.1286 + }
27.1287 + } finally {
27.1288 + if (extendedDebugInfo) {
27.1289 + debugInfoStack.pop();
27.1290 + }
27.1291 + }
27.1292 + }
27.1293 + }
27.1294 +
27.1295 + /**
27.1296 + * Writes given enum constant to stream.
27.1297 + */
27.1298 + private void writeEnum(Enum en,
27.1299 + ObjectStreamClass desc,
27.1300 + boolean unshared)
27.1301 + throws IOException
27.1302 + {
27.1303 + bout.writeByte(TC_ENUM);
27.1304 + ObjectStreamClass sdesc = desc.getSuperDesc();
27.1305 + writeClassDesc((sdesc.forClass() == Enum.class) ? desc : sdesc, false);
27.1306 + handles.assign(unshared ? null : en);
27.1307 + writeString(en.name(), false);
27.1308 + }
27.1309 +
27.1310 + /**
27.1311 + * Writes representation of a "ordinary" (i.e., not a String, Class,
27.1312 + * ObjectStreamClass, array, or enum constant) serializable object to the
27.1313 + * stream.
27.1314 + */
27.1315 + private void writeOrdinaryObject(Object obj,
27.1316 + ObjectStreamClass desc,
27.1317 + boolean unshared)
27.1318 + throws IOException
27.1319 + {
27.1320 + if (extendedDebugInfo) {
27.1321 + debugInfoStack.push(
27.1322 + (depth == 1 ? "root " : "") + "object (class \"" +
27.1323 + obj.getClass().getName() + "\", " + obj.toString() + ")");
27.1324 + }
27.1325 + try {
27.1326 + desc.checkSerialize();
27.1327 +
27.1328 + bout.writeByte(TC_OBJECT);
27.1329 + writeClassDesc(desc, false);
27.1330 + handles.assign(unshared ? null : obj);
27.1331 + if (desc.isExternalizable() && !desc.isProxy()) {
27.1332 + writeExternalData((Externalizable) obj);
27.1333 + } else {
27.1334 + writeSerialData(obj, desc);
27.1335 + }
27.1336 + } finally {
27.1337 + if (extendedDebugInfo) {
27.1338 + debugInfoStack.pop();
27.1339 + }
27.1340 + }
27.1341 + }
27.1342 +
27.1343 + /**
27.1344 + * Writes externalizable data of given object by invoking its
27.1345 + * writeExternal() method.
27.1346 + */
27.1347 + private void writeExternalData(Externalizable obj) throws IOException {
27.1348 + PutFieldImpl oldPut = curPut;
27.1349 + curPut = null;
27.1350 +
27.1351 + if (extendedDebugInfo) {
27.1352 + debugInfoStack.push("writeExternal data");
27.1353 + }
27.1354 + Object oldContext = curContext;
27.1355 + try {
27.1356 + curContext = null;
27.1357 + if (protocol == PROTOCOL_VERSION_1) {
27.1358 + obj.writeExternal(this);
27.1359 + } else {
27.1360 + bout.setBlockDataMode(true);
27.1361 + obj.writeExternal(this);
27.1362 + bout.setBlockDataMode(false);
27.1363 + bout.writeByte(TC_ENDBLOCKDATA);
27.1364 + }
27.1365 + } finally {
27.1366 + curContext = oldContext;
27.1367 + if (extendedDebugInfo) {
27.1368 + debugInfoStack.pop();
27.1369 + }
27.1370 + }
27.1371 +
27.1372 + curPut = oldPut;
27.1373 + }
27.1374 +
27.1375 + /**
27.1376 + * Writes instance data for each serializable class of given object, from
27.1377 + * superclass to subclass.
27.1378 + */
27.1379 + private void writeSerialData(Object obj, ObjectStreamClass desc)
27.1380 + throws IOException
27.1381 + {
27.1382 + ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
27.1383 + for (int i = 0; i < slots.length; i++) {
27.1384 + ObjectStreamClass slotDesc = slots[i].desc;
27.1385 + if (slotDesc.hasWriteObjectMethod()) {
27.1386 + PutFieldImpl oldPut = curPut;
27.1387 + curPut = null;
27.1388 + Object oldContext = curContext;
27.1389 +
27.1390 + if (extendedDebugInfo) {
27.1391 + debugInfoStack.push(
27.1392 + "custom writeObject data (class \"" +
27.1393 + slotDesc.getName() + "\")");
27.1394 + }
27.1395 + try {
27.1396 + curContext = new Object(); //new SerialCallbackContext(obj, slotDesc);
27.1397 + bout.setBlockDataMode(true);
27.1398 + slotDesc.invokeWriteObject(obj, this);
27.1399 + bout.setBlockDataMode(false);
27.1400 + bout.writeByte(TC_ENDBLOCKDATA);
27.1401 + } finally {
27.1402 + //curContext.setUsed();
27.1403 + curContext = oldContext;
27.1404 + if (extendedDebugInfo) {
27.1405 + debugInfoStack.pop();
27.1406 + }
27.1407 + }
27.1408 +
27.1409 + curPut = oldPut;
27.1410 + } else {
27.1411 + defaultWriteFields(obj, slotDesc);
27.1412 + }
27.1413 + }
27.1414 + }
27.1415 +
27.1416 + /**
27.1417 + * Fetches and writes values of serializable fields of given object to
27.1418 + * stream. The given class descriptor specifies which field values to
27.1419 + * write, and in which order they should be written.
27.1420 + */
27.1421 + private void defaultWriteFields(Object obj, ObjectStreamClass desc)
27.1422 + throws IOException
27.1423 + {
27.1424 + // REMIND: perform conservative isInstance check here?
27.1425 + desc.checkDefaultSerialize();
27.1426 +
27.1427 + int primDataSize = desc.getPrimDataSize();
27.1428 + if (primVals == null || primVals.length < primDataSize) {
27.1429 + primVals = new byte[primDataSize];
27.1430 + }
27.1431 + desc.getPrimFieldValues(obj, primVals);
27.1432 + bout.write(primVals, 0, primDataSize, false);
27.1433 +
27.1434 + ObjectStreamField[] fields = desc.getFields(false);
27.1435 + Object[] objVals = new Object[desc.getNumObjFields()];
27.1436 + int numPrimFields = fields.length - objVals.length;
27.1437 + desc.getObjFieldValues(obj, objVals);
27.1438 + for (int i = 0; i < objVals.length; i++) {
27.1439 + if (extendedDebugInfo) {
27.1440 + debugInfoStack.push(
27.1441 + "field (class \"" + desc.getName() + "\", name: \"" +
27.1442 + fields[numPrimFields + i].getName() + "\", type: \"" +
27.1443 + fields[numPrimFields + i].getType() + "\")");
27.1444 + }
27.1445 + try {
27.1446 + writeObject0(objVals[i],
27.1447 + fields[numPrimFields + i].isUnshared());
27.1448 + } finally {
27.1449 + if (extendedDebugInfo) {
27.1450 + debugInfoStack.pop();
27.1451 + }
27.1452 + }
27.1453 + }
27.1454 + }
27.1455 +
27.1456 + /**
27.1457 + * Attempts to write to stream fatal IOException that has caused
27.1458 + * serialization to abort.
27.1459 + */
27.1460 + private void writeFatalException(IOException ex) throws IOException {
27.1461 + /*
27.1462 + * Note: the serialization specification states that if a second
27.1463 + * IOException occurs while attempting to serialize the original fatal
27.1464 + * exception to the stream, then a StreamCorruptedException should be
27.1465 + * thrown (section 2.1). However, due to a bug in previous
27.1466 + * implementations of serialization, StreamCorruptedExceptions were
27.1467 + * rarely (if ever) actually thrown--the "root" exceptions from
27.1468 + * underlying streams were thrown instead. This historical behavior is
27.1469 + * followed here for consistency.
27.1470 + */
27.1471 + clear();
27.1472 + boolean oldMode = bout.setBlockDataMode(false);
27.1473 + try {
27.1474 + bout.writeByte(TC_EXCEPTION);
27.1475 + writeObject0(ex, false);
27.1476 + clear();
27.1477 + } finally {
27.1478 + bout.setBlockDataMode(oldMode);
27.1479 + }
27.1480 + }
27.1481 +
27.1482 + /**
27.1483 + * Converts specified span of float values into byte values.
27.1484 + */
27.1485 + // REMIND: remove once hotspot inlines Float.floatToIntBits
27.1486 + private static native void floatsToBytes(float[] src, int srcpos,
27.1487 + byte[] dst, int dstpos,
27.1488 + int nfloats);
27.1489 +
27.1490 + /**
27.1491 + * Converts specified span of double values into byte values.
27.1492 + */
27.1493 + // REMIND: remove once hotspot inlines Double.doubleToLongBits
27.1494 + private static native void doublesToBytes(double[] src, int srcpos,
27.1495 + byte[] dst, int dstpos,
27.1496 + int ndoubles);
27.1497 +
27.1498 + /**
27.1499 + * Default PutField implementation.
27.1500 + */
27.1501 + private class PutFieldImpl extends PutField {
27.1502 +
27.1503 + /** class descriptor describing serializable fields */
27.1504 + private final ObjectStreamClass desc;
27.1505 + /** primitive field values */
27.1506 + private final byte[] primVals;
27.1507 + /** object field values */
27.1508 + private final Object[] objVals;
27.1509 +
27.1510 + /**
27.1511 + * Creates PutFieldImpl object for writing fields defined in given
27.1512 + * class descriptor.
27.1513 + */
27.1514 + PutFieldImpl(ObjectStreamClass desc) {
27.1515 + this.desc = desc;
27.1516 + primVals = new byte[desc.getPrimDataSize()];
27.1517 + objVals = new Object[desc.getNumObjFields()];
27.1518 + }
27.1519 +
27.1520 + public void put(String name, boolean val) {
27.1521 + Bits.putBoolean(primVals, getFieldOffset(name, Boolean.TYPE), val);
27.1522 + }
27.1523 +
27.1524 + public void put(String name, byte val) {
27.1525 + primVals[getFieldOffset(name, Byte.TYPE)] = val;
27.1526 + }
27.1527 +
27.1528 + public void put(String name, char val) {
27.1529 + Bits.putChar(primVals, getFieldOffset(name, Character.TYPE), val);
27.1530 + }
27.1531 +
27.1532 + public void put(String name, short val) {
27.1533 + Bits.putShort(primVals, getFieldOffset(name, Short.TYPE), val);
27.1534 + }
27.1535 +
27.1536 + public void put(String name, int val) {
27.1537 + Bits.putInt(primVals, getFieldOffset(name, Integer.TYPE), val);
27.1538 + }
27.1539 +
27.1540 + public void put(String name, float val) {
27.1541 + Bits.putFloat(primVals, getFieldOffset(name, Float.TYPE), val);
27.1542 + }
27.1543 +
27.1544 + public void put(String name, long val) {
27.1545 + Bits.putLong(primVals, getFieldOffset(name, Long.TYPE), val);
27.1546 + }
27.1547 +
27.1548 + public void put(String name, double val) {
27.1549 + Bits.putDouble(primVals, getFieldOffset(name, Double.TYPE), val);
27.1550 + }
27.1551 +
27.1552 + public void put(String name, Object val) {
27.1553 + objVals[getFieldOffset(name, Object.class)] = val;
27.1554 + }
27.1555 +
27.1556 + // deprecated in ObjectOutputStream.PutField
27.1557 + public void write(ObjectOutput out) throws IOException {
27.1558 + /*
27.1559 + * Applications should *not* use this method to write PutField
27.1560 + * data, as it will lead to stream corruption if the PutField
27.1561 + * object writes any primitive data (since block data mode is not
27.1562 + * unset/set properly, as is done in OOS.writeFields()). This
27.1563 + * broken implementation is being retained solely for behavioral
27.1564 + * compatibility, in order to support applications which use
27.1565 + * OOS.PutField.write() for writing only non-primitive data.
27.1566 + *
27.1567 + * Serialization of unshared objects is not implemented here since
27.1568 + * it is not necessary for backwards compatibility; also, unshared
27.1569 + * semantics may not be supported by the given ObjectOutput
27.1570 + * instance. Applications which write unshared objects using the
27.1571 + * PutField API must use OOS.writeFields().
27.1572 + */
27.1573 + if (ObjectOutputStream.this != out) {
27.1574 + throw new IllegalArgumentException("wrong stream");
27.1575 + }
27.1576 + out.write(primVals, 0, primVals.length);
27.1577 +
27.1578 + ObjectStreamField[] fields = desc.getFields(false);
27.1579 + int numPrimFields = fields.length - objVals.length;
27.1580 + // REMIND: warn if numPrimFields > 0?
27.1581 + for (int i = 0; i < objVals.length; i++) {
27.1582 + if (fields[numPrimFields + i].isUnshared()) {
27.1583 + throw new IOException("cannot write unshared object");
27.1584 + }
27.1585 + out.writeObject(objVals[i]);
27.1586 + }
27.1587 + }
27.1588 +
27.1589 + /**
27.1590 + * Writes buffered primitive data and object fields to stream.
27.1591 + */
27.1592 + void writeFields() throws IOException {
27.1593 + bout.write(primVals, 0, primVals.length, false);
27.1594 +
27.1595 + ObjectStreamField[] fields = desc.getFields(false);
27.1596 + int numPrimFields = fields.length - objVals.length;
27.1597 + for (int i = 0; i < objVals.length; i++) {
27.1598 + if (extendedDebugInfo) {
27.1599 + debugInfoStack.push(
27.1600 + "field (class \"" + desc.getName() + "\", name: \"" +
27.1601 + fields[numPrimFields + i].getName() + "\", type: \"" +
27.1602 + fields[numPrimFields + i].getType() + "\")");
27.1603 + }
27.1604 + try {
27.1605 + writeObject0(objVals[i],
27.1606 + fields[numPrimFields + i].isUnshared());
27.1607 + } finally {
27.1608 + if (extendedDebugInfo) {
27.1609 + debugInfoStack.pop();
27.1610 + }
27.1611 + }
27.1612 + }
27.1613 + }
27.1614 +
27.1615 + /**
27.1616 + * Returns offset of field with given name and type. A specified type
27.1617 + * of null matches all types, Object.class matches all non-primitive
27.1618 + * types, and any other non-null type matches assignable types only.
27.1619 + * Throws IllegalArgumentException if no matching field found.
27.1620 + */
27.1621 + private int getFieldOffset(String name, Class type) {
27.1622 + ObjectStreamField field = desc.getField(name, type);
27.1623 + if (field == null) {
27.1624 + throw new IllegalArgumentException("no such field " + name +
27.1625 + " with type " + type);
27.1626 + }
27.1627 + return field.getOffset();
27.1628 + }
27.1629 + }
27.1630 +
27.1631 + /**
27.1632 + * Buffered output stream with two modes: in default mode, outputs data in
27.1633 + * same format as DataOutputStream; in "block data" mode, outputs data
27.1634 + * bracketed by block data markers (see object serialization specification
27.1635 + * for details).
27.1636 + */
27.1637 + private static class BlockDataOutputStream
27.1638 + extends OutputStream implements DataOutput
27.1639 + {
27.1640 + /** maximum data block length */
27.1641 + private static final int MAX_BLOCK_SIZE = 1024;
27.1642 + /** maximum data block header length */
27.1643 + private static final int MAX_HEADER_SIZE = 5;
27.1644 + /** (tunable) length of char buffer (for writing strings) */
27.1645 + private static final int CHAR_BUF_SIZE = 256;
27.1646 +
27.1647 + /** buffer for writing general/block data */
27.1648 + private final byte[] buf = new byte[MAX_BLOCK_SIZE];
27.1649 + /** buffer for writing block data headers */
27.1650 + private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
27.1651 + /** char buffer for fast string writes */
27.1652 + private final char[] cbuf = new char[CHAR_BUF_SIZE];
27.1653 +
27.1654 + /** block data mode */
27.1655 + private boolean blkmode = false;
27.1656 + /** current offset into buf */
27.1657 + private int pos = 0;
27.1658 +
27.1659 + /** underlying output stream */
27.1660 + private final OutputStream out;
27.1661 + /** loopback stream (for data writes that span data blocks) */
27.1662 + private final DataOutputStream dout;
27.1663 +
27.1664 + /**
27.1665 + * Creates new BlockDataOutputStream on top of given underlying stream.
27.1666 + * Block data mode is turned off by default.
27.1667 + */
27.1668 + BlockDataOutputStream(OutputStream out) {
27.1669 + this.out = out;
27.1670 + dout = new DataOutputStream(this);
27.1671 + }
27.1672 +
27.1673 + /**
27.1674 + * Sets block data mode to the given mode (true == on, false == off)
27.1675 + * and returns the previous mode value. If the new mode is the same as
27.1676 + * the old mode, no action is taken. If the new mode differs from the
27.1677 + * old mode, any buffered data is flushed before switching to the new
27.1678 + * mode.
27.1679 + */
27.1680 + boolean setBlockDataMode(boolean mode) throws IOException {
27.1681 + if (blkmode == mode) {
27.1682 + return blkmode;
27.1683 + }
27.1684 + drain();
27.1685 + blkmode = mode;
27.1686 + return !blkmode;
27.1687 + }
27.1688 +
27.1689 + /**
27.1690 + * Returns true if the stream is currently in block data mode, false
27.1691 + * otherwise.
27.1692 + */
27.1693 + boolean getBlockDataMode() {
27.1694 + return blkmode;
27.1695 + }
27.1696 +
27.1697 + /* ----------------- generic output stream methods ----------------- */
27.1698 + /*
27.1699 + * The following methods are equivalent to their counterparts in
27.1700 + * OutputStream, except that they partition written data into data
27.1701 + * blocks when in block data mode.
27.1702 + */
27.1703 +
27.1704 + public void write(int b) throws IOException {
27.1705 + if (pos >= MAX_BLOCK_SIZE) {
27.1706 + drain();
27.1707 + }
27.1708 + buf[pos++] = (byte) b;
27.1709 + }
27.1710 +
27.1711 + public void write(byte[] b) throws IOException {
27.1712 + write(b, 0, b.length, false);
27.1713 + }
27.1714 +
27.1715 + public void write(byte[] b, int off, int len) throws IOException {
27.1716 + write(b, off, len, false);
27.1717 + }
27.1718 +
27.1719 + public void flush() throws IOException {
27.1720 + drain();
27.1721 + out.flush();
27.1722 + }
27.1723 +
27.1724 + public void close() throws IOException {
27.1725 + flush();
27.1726 + out.close();
27.1727 + }
27.1728 +
27.1729 + /**
27.1730 + * Writes specified span of byte values from given array. If copy is
27.1731 + * true, copies the values to an intermediate buffer before writing
27.1732 + * them to underlying stream (to avoid exposing a reference to the
27.1733 + * original byte array).
27.1734 + */
27.1735 + void write(byte[] b, int off, int len, boolean copy)
27.1736 + throws IOException
27.1737 + {
27.1738 + if (!(copy || blkmode)) { // write directly
27.1739 + drain();
27.1740 + out.write(b, off, len);
27.1741 + return;
27.1742 + }
27.1743 +
27.1744 + while (len > 0) {
27.1745 + if (pos >= MAX_BLOCK_SIZE) {
27.1746 + drain();
27.1747 + }
27.1748 + if (len >= MAX_BLOCK_SIZE && !copy && pos == 0) {
27.1749 + // avoid unnecessary copy
27.1750 + writeBlockHeader(MAX_BLOCK_SIZE);
27.1751 + out.write(b, off, MAX_BLOCK_SIZE);
27.1752 + off += MAX_BLOCK_SIZE;
27.1753 + len -= MAX_BLOCK_SIZE;
27.1754 + } else {
27.1755 + int wlen = Math.min(len, MAX_BLOCK_SIZE - pos);
27.1756 + System.arraycopy(b, off, buf, pos, wlen);
27.1757 + pos += wlen;
27.1758 + off += wlen;
27.1759 + len -= wlen;
27.1760 + }
27.1761 + }
27.1762 + }
27.1763 +
27.1764 + /**
27.1765 + * Writes all buffered data from this stream to the underlying stream,
27.1766 + * but does not flush underlying stream.
27.1767 + */
27.1768 + void drain() throws IOException {
27.1769 + if (pos == 0) {
27.1770 + return;
27.1771 + }
27.1772 + if (blkmode) {
27.1773 + writeBlockHeader(pos);
27.1774 + }
27.1775 + out.write(buf, 0, pos);
27.1776 + pos = 0;
27.1777 + }
27.1778 +
27.1779 + /**
27.1780 + * Writes block data header. Data blocks shorter than 256 bytes are
27.1781 + * prefixed with a 2-byte header; all others start with a 5-byte
27.1782 + * header.
27.1783 + */
27.1784 + private void writeBlockHeader(int len) throws IOException {
27.1785 + if (len <= 0xFF) {
27.1786 + hbuf[0] = TC_BLOCKDATA;
27.1787 + hbuf[1] = (byte) len;
27.1788 + out.write(hbuf, 0, 2);
27.1789 + } else {
27.1790 + hbuf[0] = TC_BLOCKDATALONG;
27.1791 + Bits.putInt(hbuf, 1, len);
27.1792 + out.write(hbuf, 0, 5);
27.1793 + }
27.1794 + }
27.1795 +
27.1796 +
27.1797 + /* ----------------- primitive data output methods ----------------- */
27.1798 + /*
27.1799 + * The following methods are equivalent to their counterparts in
27.1800 + * DataOutputStream, except that they partition written data into data
27.1801 + * blocks when in block data mode.
27.1802 + */
27.1803 +
27.1804 + public void writeBoolean(boolean v) throws IOException {
27.1805 + if (pos >= MAX_BLOCK_SIZE) {
27.1806 + drain();
27.1807 + }
27.1808 + Bits.putBoolean(buf, pos++, v);
27.1809 + }
27.1810 +
27.1811 + public void writeByte(int v) throws IOException {
27.1812 + if (pos >= MAX_BLOCK_SIZE) {
27.1813 + drain();
27.1814 + }
27.1815 + buf[pos++] = (byte) v;
27.1816 + }
27.1817 +
27.1818 + public void writeChar(int v) throws IOException {
27.1819 + if (pos + 2 <= MAX_BLOCK_SIZE) {
27.1820 + Bits.putChar(buf, pos, (char) v);
27.1821 + pos += 2;
27.1822 + } else {
27.1823 + dout.writeChar(v);
27.1824 + }
27.1825 + }
27.1826 +
27.1827 + public void writeShort(int v) throws IOException {
27.1828 + if (pos + 2 <= MAX_BLOCK_SIZE) {
27.1829 + Bits.putShort(buf, pos, (short) v);
27.1830 + pos += 2;
27.1831 + } else {
27.1832 + dout.writeShort(v);
27.1833 + }
27.1834 + }
27.1835 +
27.1836 + public void writeInt(int v) throws IOException {
27.1837 + if (pos + 4 <= MAX_BLOCK_SIZE) {
27.1838 + Bits.putInt(buf, pos, v);
27.1839 + pos += 4;
27.1840 + } else {
27.1841 + dout.writeInt(v);
27.1842 + }
27.1843 + }
27.1844 +
27.1845 + public void writeFloat(float v) throws IOException {
27.1846 + if (pos + 4 <= MAX_BLOCK_SIZE) {
27.1847 + Bits.putFloat(buf, pos, v);
27.1848 + pos += 4;
27.1849 + } else {
27.1850 + dout.writeFloat(v);
27.1851 + }
27.1852 + }
27.1853 +
27.1854 + public void writeLong(long v) throws IOException {
27.1855 + if (pos + 8 <= MAX_BLOCK_SIZE) {
27.1856 + Bits.putLong(buf, pos, v);
27.1857 + pos += 8;
27.1858 + } else {
27.1859 + dout.writeLong(v);
27.1860 + }
27.1861 + }
27.1862 +
27.1863 + public void writeDouble(double v) throws IOException {
27.1864 + if (pos + 8 <= MAX_BLOCK_SIZE) {
27.1865 + Bits.putDouble(buf, pos, v);
27.1866 + pos += 8;
27.1867 + } else {
27.1868 + dout.writeDouble(v);
27.1869 + }
27.1870 + }
27.1871 +
27.1872 + public void writeBytes(String s) throws IOException {
27.1873 + int endoff = s.length();
27.1874 + int cpos = 0;
27.1875 + int csize = 0;
27.1876 + for (int off = 0; off < endoff; ) {
27.1877 + if (cpos >= csize) {
27.1878 + cpos = 0;
27.1879 + csize = Math.min(endoff - off, CHAR_BUF_SIZE);
27.1880 + s.getChars(off, off + csize, cbuf, 0);
27.1881 + }
27.1882 + if (pos >= MAX_BLOCK_SIZE) {
27.1883 + drain();
27.1884 + }
27.1885 + int n = Math.min(csize - cpos, MAX_BLOCK_SIZE - pos);
27.1886 + int stop = pos + n;
27.1887 + while (pos < stop) {
27.1888 + buf[pos++] = (byte) cbuf[cpos++];
27.1889 + }
27.1890 + off += n;
27.1891 + }
27.1892 + }
27.1893 +
27.1894 + public void writeChars(String s) throws IOException {
27.1895 + int endoff = s.length();
27.1896 + for (int off = 0; off < endoff; ) {
27.1897 + int csize = Math.min(endoff - off, CHAR_BUF_SIZE);
27.1898 + s.getChars(off, off + csize, cbuf, 0);
27.1899 + writeChars(cbuf, 0, csize);
27.1900 + off += csize;
27.1901 + }
27.1902 + }
27.1903 +
27.1904 + public void writeUTF(String s) throws IOException {
27.1905 + writeUTF(s, getUTFLength(s));
27.1906 + }
27.1907 +
27.1908 +
27.1909 + /* -------------- primitive data array output methods -------------- */
27.1910 + /*
27.1911 + * The following methods write out spans of primitive data values.
27.1912 + * Though equivalent to calling the corresponding primitive write
27.1913 + * methods repeatedly, these methods are optimized for writing groups
27.1914 + * of primitive data values more efficiently.
27.1915 + */
27.1916 +
27.1917 + void writeBooleans(boolean[] v, int off, int len) throws IOException {
27.1918 + int endoff = off + len;
27.1919 + while (off < endoff) {
27.1920 + if (pos >= MAX_BLOCK_SIZE) {
27.1921 + drain();
27.1922 + }
27.1923 + int stop = Math.min(endoff, off + (MAX_BLOCK_SIZE - pos));
27.1924 + while (off < stop) {
27.1925 + Bits.putBoolean(buf, pos++, v[off++]);
27.1926 + }
27.1927 + }
27.1928 + }
27.1929 +
27.1930 + void writeChars(char[] v, int off, int len) throws IOException {
27.1931 + int limit = MAX_BLOCK_SIZE - 2;
27.1932 + int endoff = off + len;
27.1933 + while (off < endoff) {
27.1934 + if (pos <= limit) {
27.1935 + int avail = (MAX_BLOCK_SIZE - pos) >> 1;
27.1936 + int stop = Math.min(endoff, off + avail);
27.1937 + while (off < stop) {
27.1938 + Bits.putChar(buf, pos, v[off++]);
27.1939 + pos += 2;
27.1940 + }
27.1941 + } else {
27.1942 + dout.writeChar(v[off++]);
27.1943 + }
27.1944 + }
27.1945 + }
27.1946 +
27.1947 + void writeShorts(short[] v, int off, int len) throws IOException {
27.1948 + int limit = MAX_BLOCK_SIZE - 2;
27.1949 + int endoff = off + len;
27.1950 + while (off < endoff) {
27.1951 + if (pos <= limit) {
27.1952 + int avail = (MAX_BLOCK_SIZE - pos) >> 1;
27.1953 + int stop = Math.min(endoff, off + avail);
27.1954 + while (off < stop) {
27.1955 + Bits.putShort(buf, pos, v[off++]);
27.1956 + pos += 2;
27.1957 + }
27.1958 + } else {
27.1959 + dout.writeShort(v[off++]);
27.1960 + }
27.1961 + }
27.1962 + }
27.1963 +
27.1964 + void writeInts(int[] v, int off, int len) throws IOException {
27.1965 + int limit = MAX_BLOCK_SIZE - 4;
27.1966 + int endoff = off + len;
27.1967 + while (off < endoff) {
27.1968 + if (pos <= limit) {
27.1969 + int avail = (MAX_BLOCK_SIZE - pos) >> 2;
27.1970 + int stop = Math.min(endoff, off + avail);
27.1971 + while (off < stop) {
27.1972 + Bits.putInt(buf, pos, v[off++]);
27.1973 + pos += 4;
27.1974 + }
27.1975 + } else {
27.1976 + dout.writeInt(v[off++]);
27.1977 + }
27.1978 + }
27.1979 + }
27.1980 +
27.1981 + void writeFloats(float[] v, int off, int len) throws IOException {
27.1982 + int limit = MAX_BLOCK_SIZE - 4;
27.1983 + int endoff = off + len;
27.1984 + while (off < endoff) {
27.1985 + if (pos <= limit) {
27.1986 + int avail = (MAX_BLOCK_SIZE - pos) >> 2;
27.1987 + int chunklen = Math.min(endoff - off, avail);
27.1988 + floatsToBytes(v, off, buf, pos, chunklen);
27.1989 + off += chunklen;
27.1990 + pos += chunklen << 2;
27.1991 + } else {
27.1992 + dout.writeFloat(v[off++]);
27.1993 + }
27.1994 + }
27.1995 + }
27.1996 +
27.1997 + void writeLongs(long[] v, int off, int len) throws IOException {
27.1998 + int limit = MAX_BLOCK_SIZE - 8;
27.1999 + int endoff = off + len;
27.2000 + while (off < endoff) {
27.2001 + if (pos <= limit) {
27.2002 + int avail = (MAX_BLOCK_SIZE - pos) >> 3;
27.2003 + int stop = Math.min(endoff, off + avail);
27.2004 + while (off < stop) {
27.2005 + Bits.putLong(buf, pos, v[off++]);
27.2006 + pos += 8;
27.2007 + }
27.2008 + } else {
27.2009 + dout.writeLong(v[off++]);
27.2010 + }
27.2011 + }
27.2012 + }
27.2013 +
27.2014 + void writeDoubles(double[] v, int off, int len) throws IOException {
27.2015 + int limit = MAX_BLOCK_SIZE - 8;
27.2016 + int endoff = off + len;
27.2017 + while (off < endoff) {
27.2018 + if (pos <= limit) {
27.2019 + int avail = (MAX_BLOCK_SIZE - pos) >> 3;
27.2020 + int chunklen = Math.min(endoff - off, avail);
27.2021 + doublesToBytes(v, off, buf, pos, chunklen);
27.2022 + off += chunklen;
27.2023 + pos += chunklen << 3;
27.2024 + } else {
27.2025 + dout.writeDouble(v[off++]);
27.2026 + }
27.2027 + }
27.2028 + }
27.2029 +
27.2030 + /**
27.2031 + * Returns the length in bytes of the UTF encoding of the given string.
27.2032 + */
27.2033 + long getUTFLength(String s) {
27.2034 + int len = s.length();
27.2035 + long utflen = 0;
27.2036 + for (int off = 0; off < len; ) {
27.2037 + int csize = Math.min(len - off, CHAR_BUF_SIZE);
27.2038 + s.getChars(off, off + csize, cbuf, 0);
27.2039 + for (int cpos = 0; cpos < csize; cpos++) {
27.2040 + char c = cbuf[cpos];
27.2041 + if (c >= 0x0001 && c <= 0x007F) {
27.2042 + utflen++;
27.2043 + } else if (c > 0x07FF) {
27.2044 + utflen += 3;
27.2045 + } else {
27.2046 + utflen += 2;
27.2047 + }
27.2048 + }
27.2049 + off += csize;
27.2050 + }
27.2051 + return utflen;
27.2052 + }
27.2053 +
27.2054 + /**
27.2055 + * Writes the given string in UTF format. This method is used in
27.2056 + * situations where the UTF encoding length of the string is already
27.2057 + * known; specifying it explicitly avoids a prescan of the string to
27.2058 + * determine its UTF length.
27.2059 + */
27.2060 + void writeUTF(String s, long utflen) throws IOException {
27.2061 + if (utflen > 0xFFFFL) {
27.2062 + throw new UTFDataFormatException();
27.2063 + }
27.2064 + writeShort((int) utflen);
27.2065 + if (utflen == (long) s.length()) {
27.2066 + writeBytes(s);
27.2067 + } else {
27.2068 + writeUTFBody(s);
27.2069 + }
27.2070 + }
27.2071 +
27.2072 + /**
27.2073 + * Writes given string in "long" UTF format. "Long" UTF format is
27.2074 + * identical to standard UTF, except that it uses an 8 byte header
27.2075 + * (instead of the standard 2 bytes) to convey the UTF encoding length.
27.2076 + */
27.2077 + void writeLongUTF(String s) throws IOException {
27.2078 + writeLongUTF(s, getUTFLength(s));
27.2079 + }
27.2080 +
27.2081 + /**
27.2082 + * Writes given string in "long" UTF format, where the UTF encoding
27.2083 + * length of the string is already known.
27.2084 + */
27.2085 + void writeLongUTF(String s, long utflen) throws IOException {
27.2086 + writeLong(utflen);
27.2087 + if (utflen == (long) s.length()) {
27.2088 + writeBytes(s);
27.2089 + } else {
27.2090 + writeUTFBody(s);
27.2091 + }
27.2092 + }
27.2093 +
27.2094 + /**
27.2095 + * Writes the "body" (i.e., the UTF representation minus the 2-byte or
27.2096 + * 8-byte length header) of the UTF encoding for the given string.
27.2097 + */
27.2098 + private void writeUTFBody(String s) throws IOException {
27.2099 + int limit = MAX_BLOCK_SIZE - 3;
27.2100 + int len = s.length();
27.2101 + for (int off = 0; off < len; ) {
27.2102 + int csize = Math.min(len - off, CHAR_BUF_SIZE);
27.2103 + s.getChars(off, off + csize, cbuf, 0);
27.2104 + for (int cpos = 0; cpos < csize; cpos++) {
27.2105 + char c = cbuf[cpos];
27.2106 + if (pos <= limit) {
27.2107 + if (c <= 0x007F && c != 0) {
27.2108 + buf[pos++] = (byte) c;
27.2109 + } else if (c > 0x07FF) {
27.2110 + buf[pos + 2] = (byte) (0x80 | ((c >> 0) & 0x3F));
27.2111 + buf[pos + 1] = (byte) (0x80 | ((c >> 6) & 0x3F));
27.2112 + buf[pos + 0] = (byte) (0xE0 | ((c >> 12) & 0x0F));
27.2113 + pos += 3;
27.2114 + } else {
27.2115 + buf[pos + 1] = (byte) (0x80 | ((c >> 0) & 0x3F));
27.2116 + buf[pos + 0] = (byte) (0xC0 | ((c >> 6) & 0x1F));
27.2117 + pos += 2;
27.2118 + }
27.2119 + } else { // write one byte at a time to normalize block
27.2120 + if (c <= 0x007F && c != 0) {
27.2121 + write(c);
27.2122 + } else if (c > 0x07FF) {
27.2123 + write(0xE0 | ((c >> 12) & 0x0F));
27.2124 + write(0x80 | ((c >> 6) & 0x3F));
27.2125 + write(0x80 | ((c >> 0) & 0x3F));
27.2126 + } else {
27.2127 + write(0xC0 | ((c >> 6) & 0x1F));
27.2128 + write(0x80 | ((c >> 0) & 0x3F));
27.2129 + }
27.2130 + }
27.2131 + }
27.2132 + off += csize;
27.2133 + }
27.2134 + }
27.2135 + }
27.2136 +
27.2137 + /**
27.2138 + * Lightweight identity hash table which maps objects to integer handles,
27.2139 + * assigned in ascending order.
27.2140 + */
27.2141 + private static class HandleTable {
27.2142 +
27.2143 + /* number of mappings in table/next available handle */
27.2144 + private int size;
27.2145 + /* size threshold determining when to expand hash spine */
27.2146 + private int threshold;
27.2147 + /* factor for computing size threshold */
27.2148 + private final float loadFactor;
27.2149 + /* maps hash value -> candidate handle value */
27.2150 + private int[] spine;
27.2151 + /* maps handle value -> next candidate handle value */
27.2152 + private int[] next;
27.2153 + /* maps handle value -> associated object */
27.2154 + private Object[] objs;
27.2155 +
27.2156 + /**
27.2157 + * Creates new HandleTable with given capacity and load factor.
27.2158 + */
27.2159 + HandleTable(int initialCapacity, float loadFactor) {
27.2160 + this.loadFactor = loadFactor;
27.2161 + spine = new int[initialCapacity];
27.2162 + next = new int[initialCapacity];
27.2163 + objs = new Object[initialCapacity];
27.2164 + threshold = (int) (initialCapacity * loadFactor);
27.2165 + clear();
27.2166 + }
27.2167 +
27.2168 + /**
27.2169 + * Assigns next available handle to given object, and returns handle
27.2170 + * value. Handles are assigned in ascending order starting at 0.
27.2171 + */
27.2172 + int assign(Object obj) {
27.2173 + if (size >= next.length) {
27.2174 + growEntries();
27.2175 + }
27.2176 + if (size >= threshold) {
27.2177 + growSpine();
27.2178 + }
27.2179 + insert(obj, size);
27.2180 + return size++;
27.2181 + }
27.2182 +
27.2183 + /**
27.2184 + * Looks up and returns handle associated with given object, or -1 if
27.2185 + * no mapping found.
27.2186 + */
27.2187 + int lookup(Object obj) {
27.2188 + if (size == 0) {
27.2189 + return -1;
27.2190 + }
27.2191 + int index = hash(obj) % spine.length;
27.2192 + for (int i = spine[index]; i >= 0; i = next[i]) {
27.2193 + if (objs[i] == obj) {
27.2194 + return i;
27.2195 + }
27.2196 + }
27.2197 + return -1;
27.2198 + }
27.2199 +
27.2200 + /**
27.2201 + * Resets table to its initial (empty) state.
27.2202 + */
27.2203 + void clear() {
27.2204 + Arrays.fill(spine, -1);
27.2205 + Arrays.fill(objs, 0, size, null);
27.2206 + size = 0;
27.2207 + }
27.2208 +
27.2209 + /**
27.2210 + * Returns the number of mappings currently in table.
27.2211 + */
27.2212 + int size() {
27.2213 + return size;
27.2214 + }
27.2215 +
27.2216 + /**
27.2217 + * Inserts mapping object -> handle mapping into table. Assumes table
27.2218 + * is large enough to accommodate new mapping.
27.2219 + */
27.2220 + private void insert(Object obj, int handle) {
27.2221 + int index = hash(obj) % spine.length;
27.2222 + objs[handle] = obj;
27.2223 + next[handle] = spine[index];
27.2224 + spine[index] = handle;
27.2225 + }
27.2226 +
27.2227 + /**
27.2228 + * Expands the hash "spine" -- equivalent to increasing the number of
27.2229 + * buckets in a conventional hash table.
27.2230 + */
27.2231 + private void growSpine() {
27.2232 + spine = new int[(spine.length << 1) + 1];
27.2233 + threshold = (int) (spine.length * loadFactor);
27.2234 + Arrays.fill(spine, -1);
27.2235 + for (int i = 0; i < size; i++) {
27.2236 + insert(objs[i], i);
27.2237 + }
27.2238 + }
27.2239 +
27.2240 + /**
27.2241 + * Increases hash table capacity by lengthening entry arrays.
27.2242 + */
27.2243 + private void growEntries() {
27.2244 + int newLength = (next.length << 1) + 1;
27.2245 + int[] newNext = new int[newLength];
27.2246 + System.arraycopy(next, 0, newNext, 0, size);
27.2247 + next = newNext;
27.2248 +
27.2249 + Object[] newObjs = new Object[newLength];
27.2250 + System.arraycopy(objs, 0, newObjs, 0, size);
27.2251 + objs = newObjs;
27.2252 + }
27.2253 +
27.2254 + /**
27.2255 + * Returns hash value for given object.
27.2256 + */
27.2257 + private int hash(Object obj) {
27.2258 + return System.identityHashCode(obj) & 0x7FFFFFFF;
27.2259 + }
27.2260 + }
27.2261 +
27.2262 + /**
27.2263 + * Lightweight identity hash table which maps objects to replacement
27.2264 + * objects.
27.2265 + */
27.2266 + private static class ReplaceTable {
27.2267 +
27.2268 + /* maps object -> index */
27.2269 + private final HandleTable htab;
27.2270 + /* maps index -> replacement object */
27.2271 + private Object[] reps;
27.2272 +
27.2273 + /**
27.2274 + * Creates new ReplaceTable with given capacity and load factor.
27.2275 + */
27.2276 + ReplaceTable(int initialCapacity, float loadFactor) {
27.2277 + htab = new HandleTable(initialCapacity, loadFactor);
27.2278 + reps = new Object[initialCapacity];
27.2279 + }
27.2280 +
27.2281 + /**
27.2282 + * Enters mapping from object to replacement object.
27.2283 + */
27.2284 + void assign(Object obj, Object rep) {
27.2285 + int index = htab.assign(obj);
27.2286 + while (index >= reps.length) {
27.2287 + grow();
27.2288 + }
27.2289 + reps[index] = rep;
27.2290 + }
27.2291 +
27.2292 + /**
27.2293 + * Looks up and returns replacement for given object. If no
27.2294 + * replacement is found, returns the lookup object itself.
27.2295 + */
27.2296 + Object lookup(Object obj) {
27.2297 + int index = htab.lookup(obj);
27.2298 + return (index >= 0) ? reps[index] : obj;
27.2299 + }
27.2300 +
27.2301 + /**
27.2302 + * Resets table to its initial (empty) state.
27.2303 + */
27.2304 + void clear() {
27.2305 + Arrays.fill(reps, 0, htab.size(), null);
27.2306 + htab.clear();
27.2307 + }
27.2308 +
27.2309 + /**
27.2310 + * Returns the number of mappings currently in table.
27.2311 + */
27.2312 + int size() {
27.2313 + return htab.size();
27.2314 + }
27.2315 +
27.2316 + /**
27.2317 + * Increases table capacity.
27.2318 + */
27.2319 + private void grow() {
27.2320 + Object[] newReps = new Object[(reps.length << 1) + 1];
27.2321 + System.arraycopy(reps, 0, newReps, 0, reps.length);
27.2322 + reps = newReps;
27.2323 + }
27.2324 + }
27.2325 +
27.2326 + /**
27.2327 + * Stack to keep debug information about the state of the
27.2328 + * serialization process, for embedding in exception messages.
27.2329 + */
27.2330 + private static class DebugTraceInfoStack {
27.2331 + private final List<String> stack;
27.2332 +
27.2333 + DebugTraceInfoStack() {
27.2334 + stack = new ArrayList<>();
27.2335 + }
27.2336 +
27.2337 + /**
27.2338 + * Removes all of the elements from enclosed list.
27.2339 + */
27.2340 + void clear() {
27.2341 + stack.clear();
27.2342 + }
27.2343 +
27.2344 + /**
27.2345 + * Removes the object at the top of enclosed list.
27.2346 + */
27.2347 + void pop() {
27.2348 + stack.remove(stack.size()-1);
27.2349 + }
27.2350 +
27.2351 + /**
27.2352 + * Pushes a String onto the top of enclosed list.
27.2353 + */
27.2354 + void push(String entry) {
27.2355 + stack.add("\t- " + entry);
27.2356 + }
27.2357 +
27.2358 + /**
27.2359 + * Returns a string representation of this object
27.2360 + */
27.2361 + public String toString() {
27.2362 + StringBuilder buffer = new StringBuilder();
27.2363 + if (!stack.isEmpty()) {
27.2364 + for(int i = stack.size(); i > 0; i-- ) {
27.2365 + buffer.append(stack.get(i-1) + ((i != 1) ? "\n" : ""));
27.2366 + }
27.2367 + }
27.2368 + return buffer.toString();
27.2369 + }
27.2370 + }
27.2371 +
27.2372 +}
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
28.2 +++ b/emul/compact/src/main/java/java/io/ObjectStreamClass.java Mon Feb 04 09:37:56 2013 +0100
28.3 @@ -0,0 +1,1396 @@
28.4 +/*
28.5 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
28.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
28.7 + *
28.8 + * This code is free software; you can redistribute it and/or modify it
28.9 + * under the terms of the GNU General Public License version 2 only, as
28.10 + * published by the Free Software Foundation. Oracle designates this
28.11 + * particular file as subject to the "Classpath" exception as provided
28.12 + * by Oracle in the LICENSE file that accompanied this code.
28.13 + *
28.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
28.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
28.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
28.17 + * version 2 for more details (a copy is included in the LICENSE file that
28.18 + * accompanied this code).
28.19 + *
28.20 + * You should have received a copy of the GNU General Public License version
28.21 + * 2 along with this work; if not, write to the Free Software Foundation,
28.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
28.23 + *
28.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
28.25 + * or visit www.oracle.com if you need additional information or have any
28.26 + * questions.
28.27 + */
28.28 +
28.29 +package java.io;
28.30 +
28.31 +import java.lang.ref.Reference;
28.32 +import java.lang.ref.ReferenceQueue;
28.33 +import java.lang.ref.SoftReference;
28.34 +import java.lang.ref.WeakReference;
28.35 +import java.lang.reflect.Constructor;
28.36 +import java.lang.reflect.Field;
28.37 +import java.lang.reflect.InvocationTargetException;
28.38 +import java.lang.reflect.Member;
28.39 +import java.lang.reflect.Method;
28.40 +import java.lang.reflect.Modifier;
28.41 +import java.lang.reflect.Proxy;
28.42 +import java.util.ArrayList;
28.43 +import java.util.Arrays;
28.44 +import java.util.Collections;
28.45 +import java.util.Comparator;
28.46 +import java.util.HashSet;
28.47 +import java.util.Set;
28.48 +
28.49 +/**
28.50 + * Serialization's descriptor for classes. It contains the name and
28.51 + * serialVersionUID of the class. The ObjectStreamClass for a specific class
28.52 + * loaded in this Java VM can be found/created using the lookup method.
28.53 + *
28.54 + * <p>The algorithm to compute the SerialVersionUID is described in
28.55 + * <a href="../../../platform/serialization/spec/class.html#4100">Object
28.56 + * Serialization Specification, Section 4.6, Stream Unique Identifiers</a>.
28.57 + *
28.58 + * @author Mike Warres
28.59 + * @author Roger Riggs
28.60 + * @see ObjectStreamField
28.61 + * @see <a href="../../../platform/serialization/spec/class.html">Object Serialization Specification, Section 4, Class Descriptors</a>
28.62 + * @since JDK1.1
28.63 + */
28.64 +public class ObjectStreamClass implements Serializable {
28.65 +
28.66 + /** serialPersistentFields value indicating no serializable fields */
28.67 + public static final ObjectStreamField[] NO_FIELDS =
28.68 + new ObjectStreamField[0];
28.69 +
28.70 + private static final long serialVersionUID = -6120832682080437368L;
28.71 + private static final ObjectStreamField[] serialPersistentFields =
28.72 + NO_FIELDS;
28.73 +
28.74 +
28.75 + /** class associated with this descriptor (if any) */
28.76 + private Class<?> cl;
28.77 + /** name of class represented by this descriptor */
28.78 + private String name;
28.79 + /** serialVersionUID of represented class (null if not computed yet) */
28.80 + private volatile Long suid;
28.81 +
28.82 + /** true if represents dynamic proxy class */
28.83 + private boolean isProxy;
28.84 + /** true if represents enum type */
28.85 + private boolean isEnum;
28.86 + /** true if represented class implements Serializable */
28.87 + private boolean serializable;
28.88 + /** true if represented class implements Externalizable */
28.89 + private boolean externalizable;
28.90 + /** true if desc has data written by class-defined writeObject method */
28.91 + private boolean hasWriteObjectData;
28.92 + /**
28.93 + * true if desc has externalizable data written in block data format; this
28.94 + * must be true by default to accommodate ObjectInputStream subclasses which
28.95 + * override readClassDescriptor() to return class descriptors obtained from
28.96 + * ObjectStreamClass.lookup() (see 4461737)
28.97 + */
28.98 + private boolean hasBlockExternalData = true;
28.99 +
28.100 + /** exception (if any) thrown while attempting to resolve class */
28.101 + private ClassNotFoundException resolveEx;
28.102 + /** exception (if any) to throw if non-enum deserialization attempted */
28.103 + private InvalidClassException deserializeEx;
28.104 + /** exception (if any) to throw if non-enum serialization attempted */
28.105 + private InvalidClassException serializeEx;
28.106 + /** exception (if any) to throw if default serialization attempted */
28.107 + private InvalidClassException defaultSerializeEx;
28.108 +
28.109 + /** serializable fields */
28.110 + private ObjectStreamField[] fields;
28.111 + /** aggregate marshalled size of primitive fields */
28.112 + private int primDataSize;
28.113 + /** number of non-primitive fields */
28.114 + private int numObjFields;
28.115 + /** reflector for setting/getting serializable field values */
28.116 +// private FieldReflector fieldRefl;
28.117 + /** data layout of serialized objects described by this class desc */
28.118 + private volatile ClassDataSlot[] dataLayout;
28.119 +
28.120 + /** serialization-appropriate constructor, or null if none */
28.121 + private Constructor cons;
28.122 + /** class-defined writeObject method, or null if none */
28.123 + private Method writeObjectMethod;
28.124 + /** class-defined readObject method, or null if none */
28.125 + private Method readObjectMethod;
28.126 + /** class-defined readObjectNoData method, or null if none */
28.127 + private Method readObjectNoDataMethod;
28.128 + /** class-defined writeReplace method, or null if none */
28.129 + private Method writeReplaceMethod;
28.130 + /** class-defined readResolve method, or null if none */
28.131 + private Method readResolveMethod;
28.132 +
28.133 + /** local class descriptor for represented class (may point to self) */
28.134 + private ObjectStreamClass localDesc;
28.135 + /** superclass descriptor appearing in stream */
28.136 + private ObjectStreamClass superDesc;
28.137 +
28.138 + /**
28.139 + * Initializes native code.
28.140 + */
28.141 + private static native void initNative();
28.142 + static {
28.143 + initNative();
28.144 + }
28.145 +
28.146 + /**
28.147 + * Find the descriptor for a class that can be serialized. Creates an
28.148 + * ObjectStreamClass instance if one does not exist yet for class. Null is
28.149 + * returned if the specified class does not implement java.io.Serializable
28.150 + * or java.io.Externalizable.
28.151 + *
28.152 + * @param cl class for which to get the descriptor
28.153 + * @return the class descriptor for the specified class
28.154 + */
28.155 + public static ObjectStreamClass lookup(Class<?> cl) {
28.156 + return lookup(cl, false);
28.157 + }
28.158 +
28.159 + /**
28.160 + * Returns the descriptor for any class, regardless of whether it
28.161 + * implements {@link Serializable}.
28.162 + *
28.163 + * @param cl class for which to get the descriptor
28.164 + * @return the class descriptor for the specified class
28.165 + * @since 1.6
28.166 + */
28.167 + public static ObjectStreamClass lookupAny(Class<?> cl) {
28.168 + return lookup(cl, true);
28.169 + }
28.170 +
28.171 + /**
28.172 + * Returns the name of the class described by this descriptor.
28.173 + * This method returns the name of the class in the format that
28.174 + * is used by the {@link Class#getName} method.
28.175 + *
28.176 + * @return a string representing the name of the class
28.177 + */
28.178 + public String getName() {
28.179 + return name;
28.180 + }
28.181 +
28.182 + /**
28.183 + * Return the serialVersionUID for this class. The serialVersionUID
28.184 + * defines a set of classes all with the same name that have evolved from a
28.185 + * common root class and agree to be serialized and deserialized using a
28.186 + * common format. NonSerializable classes have a serialVersionUID of 0L.
28.187 + *
28.188 + * @return the SUID of the class described by this descriptor
28.189 + */
28.190 + public long getSerialVersionUID() {
28.191 + // REMIND: synchronize instead of relying on volatile?
28.192 + if (suid == null) {
28.193 + return computeDefaultSUID(cl);
28.194 + }
28.195 + return suid.longValue();
28.196 + }
28.197 +
28.198 + /**
28.199 + * Return the class in the local VM that this version is mapped to. Null
28.200 + * is returned if there is no corresponding local class.
28.201 + *
28.202 + * @return the <code>Class</code> instance that this descriptor represents
28.203 + */
28.204 + public Class<?> forClass() {
28.205 + return cl;
28.206 + }
28.207 +
28.208 + /**
28.209 + * Return an array of the fields of this serializable class.
28.210 + *
28.211 + * @return an array containing an element for each persistent field of
28.212 + * this class. Returns an array of length zero if there are no
28.213 + * fields.
28.214 + * @since 1.2
28.215 + */
28.216 + public ObjectStreamField[] getFields() {
28.217 + return getFields(true);
28.218 + }
28.219 +
28.220 + /**
28.221 + * Get the field of this class by name.
28.222 + *
28.223 + * @param name the name of the data field to look for
28.224 + * @return The ObjectStreamField object of the named field or null if
28.225 + * there is no such named field.
28.226 + */
28.227 + public ObjectStreamField getField(String name) {
28.228 + return getField(name, null);
28.229 + }
28.230 +
28.231 + /**
28.232 + * Return a string describing this ObjectStreamClass.
28.233 + */
28.234 + public String toString() {
28.235 + return name + ": static final long serialVersionUID = " +
28.236 + getSerialVersionUID() + "L;";
28.237 + }
28.238 +
28.239 + /**
28.240 + * Looks up and returns class descriptor for given class, or null if class
28.241 + * is non-serializable and "all" is set to false.
28.242 + *
28.243 + * @param cl class to look up
28.244 + * @param all if true, return descriptors for all classes; if false, only
28.245 + * return descriptors for serializable classes
28.246 + */
28.247 + static ObjectStreamClass lookup(Class<?> cl, boolean all) {
28.248 + if (!(all || Serializable.class.isAssignableFrom(cl))) {
28.249 + return null;
28.250 + }
28.251 + Object entry = null;
28.252 + EntryFuture future = null;
28.253 + if (entry == null) {
28.254 + EntryFuture newEntry = new EntryFuture();
28.255 + Reference<?> newRef = new SoftReference<>(newEntry);
28.256 + if (entry == null) {
28.257 + future = newEntry;
28.258 + }
28.259 + }
28.260 +
28.261 + if (entry instanceof ObjectStreamClass) { // check common case first
28.262 + return (ObjectStreamClass) entry;
28.263 + }
28.264 + if (entry instanceof EntryFuture) {
28.265 + future = (EntryFuture) entry;
28.266 + if (true) {
28.267 + /*
28.268 + * Handle nested call situation described by 4803747: waiting
28.269 + * for future value to be set by a lookup() call further up the
28.270 + * stack will result in deadlock, so calculate and set the
28.271 + * future value here instead.
28.272 + */
28.273 + entry = null;
28.274 + } else {
28.275 + entry = future.get();
28.276 + }
28.277 + }
28.278 + if (entry == null) {
28.279 + try {
28.280 + entry = new ObjectStreamClass(cl);
28.281 + } catch (Throwable th) {
28.282 + entry = th;
28.283 + }
28.284 + // nested lookup call already set future
28.285 + entry = future.get();
28.286 + }
28.287 +
28.288 + if (entry instanceof ObjectStreamClass) {
28.289 + return (ObjectStreamClass) entry;
28.290 + } else if (entry instanceof RuntimeException) {
28.291 + throw (RuntimeException) entry;
28.292 + } else if (entry instanceof Error) {
28.293 + throw (Error) entry;
28.294 + } else {
28.295 + throw new InternalError("unexpected entry: " + entry);
28.296 + }
28.297 + }
28.298 +
28.299 + /**
28.300 + * Placeholder used in class descriptor and field reflector lookup tables
28.301 + * for an entry in the process of being initialized. (Internal) callers
28.302 + * which receive an EntryFuture belonging to another thread as the result
28.303 + * of a lookup should call the get() method of the EntryFuture; this will
28.304 + * return the actual entry once it is ready for use and has been set(). To
28.305 + * conserve objects, EntryFutures synchronize on themselves.
28.306 + */
28.307 + private static class EntryFuture {
28.308 +
28.309 + private static final Object unset = new Object();
28.310 + private Object entry = unset;
28.311 +
28.312 + /**
28.313 + * Attempts to set the value contained by this EntryFuture. If the
28.314 + * EntryFuture's value has not been set already, then the value is
28.315 + * saved, any callers blocked in the get() method are notified, and
28.316 + * true is returned. If the value has already been set, then no saving
28.317 + * or notification occurs, and false is returned.
28.318 + */
28.319 + synchronized boolean set(Object entry) {
28.320 + if (this.entry != unset) {
28.321 + return false;
28.322 + }
28.323 + this.entry = entry;
28.324 + notifyAll();
28.325 + return true;
28.326 + }
28.327 +
28.328 + /**
28.329 + * Returns the value contained by this EntryFuture, blocking if
28.330 + * necessary until a value is set.
28.331 + */
28.332 + synchronized Object get() {
28.333 + boolean interrupted = false;
28.334 + while (entry == unset) {
28.335 + try {
28.336 + wait();
28.337 + } catch (InterruptedException ex) {
28.338 + interrupted = true;
28.339 + }
28.340 + }
28.341 + return entry;
28.342 + }
28.343 + }
28.344 +
28.345 + /**
28.346 + * Creates local class descriptor representing given class.
28.347 + */
28.348 + private ObjectStreamClass(final Class<?> cl) {
28.349 + this.cl = cl;
28.350 + name = cl.getName();
28.351 + isProxy = Proxy.isProxyClass(cl);
28.352 + isEnum = Enum.class.isAssignableFrom(cl);
28.353 + serializable = Serializable.class.isAssignableFrom(cl);
28.354 + externalizable = Externalizable.class.isAssignableFrom(cl);
28.355 +
28.356 + Class<?> superCl = cl.getSuperclass();
28.357 + superDesc = (superCl != null) ? lookup(superCl, false) : null;
28.358 + localDesc = this;
28.359 +
28.360 + suid = Long.valueOf(0);
28.361 + fields = NO_FIELDS;
28.362 +
28.363 +
28.364 + if (deserializeEx == null) {
28.365 + if (isEnum) {
28.366 + deserializeEx = new InvalidClassException(name, "enum type");
28.367 + } else if (cons == null) {
28.368 + deserializeEx = new InvalidClassException(
28.369 + name, "no valid constructor");
28.370 + }
28.371 + }
28.372 + for (int i = 0; i < fields.length; i++) {
28.373 + if (fields[i].getField() == null) {
28.374 + defaultSerializeEx = new InvalidClassException(
28.375 + name, "unmatched serializable field(s) declared");
28.376 + }
28.377 + }
28.378 + }
28.379 +
28.380 + /**
28.381 + * Creates blank class descriptor which should be initialized via a
28.382 + * subsequent call to initProxy(), initNonProxy() or readNonProxy().
28.383 + */
28.384 + ObjectStreamClass() {
28.385 + }
28.386 +
28.387 + /**
28.388 + * Initializes class descriptor representing a proxy class.
28.389 + */
28.390 + void initProxy(Class<?> cl,
28.391 + ClassNotFoundException resolveEx,
28.392 + ObjectStreamClass superDesc)
28.393 + throws InvalidClassException
28.394 + {
28.395 + this.cl = cl;
28.396 + this.resolveEx = resolveEx;
28.397 + this.superDesc = superDesc;
28.398 + isProxy = true;
28.399 + serializable = true;
28.400 + suid = Long.valueOf(0);
28.401 + fields = NO_FIELDS;
28.402 +
28.403 + if (cl != null) {
28.404 + localDesc = lookup(cl, true);
28.405 + if (!localDesc.isProxy) {
28.406 + throw new InvalidClassException(
28.407 + "cannot bind proxy descriptor to a non-proxy class");
28.408 + }
28.409 + name = localDesc.name;
28.410 + externalizable = localDesc.externalizable;
28.411 + cons = localDesc.cons;
28.412 + writeReplaceMethod = localDesc.writeReplaceMethod;
28.413 + readResolveMethod = localDesc.readResolveMethod;
28.414 + deserializeEx = localDesc.deserializeEx;
28.415 + }
28.416 + }
28.417 +
28.418 + /**
28.419 + * Initializes class descriptor representing a non-proxy class.
28.420 + */
28.421 + void initNonProxy(ObjectStreamClass model,
28.422 + Class<?> cl,
28.423 + ClassNotFoundException resolveEx,
28.424 + ObjectStreamClass superDesc)
28.425 + throws InvalidClassException
28.426 + {
28.427 + this.cl = cl;
28.428 + this.resolveEx = resolveEx;
28.429 + this.superDesc = superDesc;
28.430 + name = model.name;
28.431 + suid = Long.valueOf(model.getSerialVersionUID());
28.432 + isProxy = false;
28.433 + isEnum = model.isEnum;
28.434 + serializable = model.serializable;
28.435 + externalizable = model.externalizable;
28.436 + hasBlockExternalData = model.hasBlockExternalData;
28.437 + hasWriteObjectData = model.hasWriteObjectData;
28.438 + fields = model.fields;
28.439 + primDataSize = model.primDataSize;
28.440 + numObjFields = model.numObjFields;
28.441 +
28.442 + if (cl != null) {
28.443 + localDesc = lookup(cl, true);
28.444 + if (localDesc.isProxy) {
28.445 + throw new InvalidClassException(
28.446 + "cannot bind non-proxy descriptor to a proxy class");
28.447 + }
28.448 + if (isEnum != localDesc.isEnum) {
28.449 + throw new InvalidClassException(isEnum ?
28.450 + "cannot bind enum descriptor to a non-enum class" :
28.451 + "cannot bind non-enum descriptor to an enum class");
28.452 + }
28.453 +
28.454 + if (serializable == localDesc.serializable &&
28.455 + !cl.isArray() &&
28.456 + suid.longValue() != localDesc.getSerialVersionUID())
28.457 + {
28.458 + throw new InvalidClassException(localDesc.name,
28.459 + "local class incompatible: " +
28.460 + "stream classdesc serialVersionUID = " + suid +
28.461 + ", local class serialVersionUID = " +
28.462 + localDesc.getSerialVersionUID());
28.463 + }
28.464 +
28.465 + if (!classNamesEqual(name, localDesc.name)) {
28.466 + throw new InvalidClassException(localDesc.name,
28.467 + "local class name incompatible with stream class " +
28.468 + "name \"" + name + "\"");
28.469 + }
28.470 +
28.471 + if (!isEnum) {
28.472 + if ((serializable == localDesc.serializable) &&
28.473 + (externalizable != localDesc.externalizable))
28.474 + {
28.475 + throw new InvalidClassException(localDesc.name,
28.476 + "Serializable incompatible with Externalizable");
28.477 + }
28.478 +
28.479 + if ((serializable != localDesc.serializable) ||
28.480 + (externalizable != localDesc.externalizable) ||
28.481 + !(serializable || externalizable))
28.482 + {
28.483 + deserializeEx = new InvalidClassException(localDesc.name,
28.484 + "class invalid for deserialization");
28.485 + }
28.486 + }
28.487 +
28.488 + cons = localDesc.cons;
28.489 + writeObjectMethod = localDesc.writeObjectMethod;
28.490 + readObjectMethod = localDesc.readObjectMethod;
28.491 + readObjectNoDataMethod = localDesc.readObjectNoDataMethod;
28.492 + writeReplaceMethod = localDesc.writeReplaceMethod;
28.493 + readResolveMethod = localDesc.readResolveMethod;
28.494 + if (deserializeEx == null) {
28.495 + deserializeEx = localDesc.deserializeEx;
28.496 + }
28.497 + }
28.498 + // reassign to matched fields so as to reflect local unshared settings
28.499 + fields = null;
28.500 + }
28.501 +
28.502 + /**
28.503 + * Reads non-proxy class descriptor information from given input stream.
28.504 + * The resulting class descriptor is not fully functional; it can only be
28.505 + * used as input to the ObjectInputStream.resolveClass() and
28.506 + * ObjectStreamClass.initNonProxy() methods.
28.507 + */
28.508 + void readNonProxy(ObjectInputStream in)
28.509 + throws IOException, ClassNotFoundException
28.510 + {
28.511 + name = in.readUTF();
28.512 + suid = Long.valueOf(in.readLong());
28.513 + isProxy = false;
28.514 +
28.515 + byte flags = in.readByte();
28.516 + hasWriteObjectData =
28.517 + ((flags & ObjectStreamConstants.SC_WRITE_METHOD) != 0);
28.518 + hasBlockExternalData =
28.519 + ((flags & ObjectStreamConstants.SC_BLOCK_DATA) != 0);
28.520 + externalizable =
28.521 + ((flags & ObjectStreamConstants.SC_EXTERNALIZABLE) != 0);
28.522 + boolean sflag =
28.523 + ((flags & ObjectStreamConstants.SC_SERIALIZABLE) != 0);
28.524 + if (externalizable && sflag) {
28.525 + throw new InvalidClassException(
28.526 + name, "serializable and externalizable flags conflict");
28.527 + }
28.528 + serializable = externalizable || sflag;
28.529 + isEnum = ((flags & ObjectStreamConstants.SC_ENUM) != 0);
28.530 + if (isEnum && suid.longValue() != 0L) {
28.531 + throw new InvalidClassException(name,
28.532 + "enum descriptor has non-zero serialVersionUID: " + suid);
28.533 + }
28.534 +
28.535 + int numFields = in.readShort();
28.536 + if (isEnum && numFields != 0) {
28.537 + throw new InvalidClassException(name,
28.538 + "enum descriptor has non-zero field count: " + numFields);
28.539 + }
28.540 + fields = (numFields > 0) ?
28.541 + new ObjectStreamField[numFields] : NO_FIELDS;
28.542 + for (int i = 0; i < numFields; i++) {
28.543 + char tcode = (char) in.readByte();
28.544 + String fname = in.readUTF();
28.545 + String signature = ((tcode == 'L') || (tcode == '[')) ?
28.546 + in.readTypeString() : new String(new char[] { tcode });
28.547 + try {
28.548 + fields[i] = new ObjectStreamField(fname, signature, false);
28.549 + } catch (RuntimeException e) {
28.550 + throw (IOException) new InvalidClassException(name,
28.551 + "invalid descriptor for field " + fname).initCause(e);
28.552 + }
28.553 + }
28.554 + computeFieldOffsets();
28.555 + }
28.556 +
28.557 + /**
28.558 + * Writes non-proxy class descriptor information to given output stream.
28.559 + */
28.560 + void writeNonProxy(ObjectOutputStream out) throws IOException {
28.561 + out.writeUTF(name);
28.562 + out.writeLong(getSerialVersionUID());
28.563 +
28.564 + byte flags = 0;
28.565 + if (externalizable) {
28.566 + flags |= ObjectStreamConstants.SC_EXTERNALIZABLE;
28.567 + int protocol = out.getProtocolVersion();
28.568 + if (protocol != ObjectStreamConstants.PROTOCOL_VERSION_1) {
28.569 + flags |= ObjectStreamConstants.SC_BLOCK_DATA;
28.570 + }
28.571 + } else if (serializable) {
28.572 + flags |= ObjectStreamConstants.SC_SERIALIZABLE;
28.573 + }
28.574 + if (hasWriteObjectData) {
28.575 + flags |= ObjectStreamConstants.SC_WRITE_METHOD;
28.576 + }
28.577 + if (isEnum) {
28.578 + flags |= ObjectStreamConstants.SC_ENUM;
28.579 + }
28.580 + out.writeByte(flags);
28.581 +
28.582 + out.writeShort(fields.length);
28.583 + for (int i = 0; i < fields.length; i++) {
28.584 + ObjectStreamField f = fields[i];
28.585 + out.writeByte(f.getTypeCode());
28.586 + out.writeUTF(f.getName());
28.587 + if (!f.isPrimitive()) {
28.588 + out.writeTypeString(f.getTypeString());
28.589 + }
28.590 + }
28.591 + }
28.592 +
28.593 + /**
28.594 + * Returns ClassNotFoundException (if any) thrown while attempting to
28.595 + * resolve local class corresponding to this class descriptor.
28.596 + */
28.597 + ClassNotFoundException getResolveException() {
28.598 + return resolveEx;
28.599 + }
28.600 +
28.601 + /**
28.602 + * Throws an InvalidClassException if object instances referencing this
28.603 + * class descriptor should not be allowed to deserialize. This method does
28.604 + * not apply to deserialization of enum constants.
28.605 + */
28.606 + void checkDeserialize() throws InvalidClassException {
28.607 + if (deserializeEx != null) {
28.608 + InvalidClassException ice =
28.609 + new InvalidClassException(deserializeEx.classname,
28.610 + deserializeEx.getMessage());
28.611 + ice.initCause(deserializeEx);
28.612 + throw ice;
28.613 + }
28.614 + }
28.615 +
28.616 + /**
28.617 + * Throws an InvalidClassException if objects whose class is represented by
28.618 + * this descriptor should not be allowed to serialize. This method does
28.619 + * not apply to serialization of enum constants.
28.620 + */
28.621 + void checkSerialize() throws InvalidClassException {
28.622 + if (serializeEx != null) {
28.623 + InvalidClassException ice =
28.624 + new InvalidClassException(serializeEx.classname,
28.625 + serializeEx.getMessage());
28.626 + ice.initCause(serializeEx);
28.627 + throw ice;
28.628 + }
28.629 + }
28.630 +
28.631 + /**
28.632 + * Throws an InvalidClassException if objects whose class is represented by
28.633 + * this descriptor should not be permitted to use default serialization
28.634 + * (e.g., if the class declares serializable fields that do not correspond
28.635 + * to actual fields, and hence must use the GetField API). This method
28.636 + * does not apply to deserialization of enum constants.
28.637 + */
28.638 + void checkDefaultSerialize() throws InvalidClassException {
28.639 + if (defaultSerializeEx != null) {
28.640 + InvalidClassException ice =
28.641 + new InvalidClassException(defaultSerializeEx.classname,
28.642 + defaultSerializeEx.getMessage());
28.643 + ice.initCause(defaultSerializeEx);
28.644 + throw ice;
28.645 + }
28.646 + }
28.647 +
28.648 + /**
28.649 + * Returns superclass descriptor. Note that on the receiving side, the
28.650 + * superclass descriptor may be bound to a class that is not a superclass
28.651 + * of the subclass descriptor's bound class.
28.652 + */
28.653 + ObjectStreamClass getSuperDesc() {
28.654 + return superDesc;
28.655 + }
28.656 +
28.657 + /**
28.658 + * Returns the "local" class descriptor for the class associated with this
28.659 + * class descriptor (i.e., the result of
28.660 + * ObjectStreamClass.lookup(this.forClass())) or null if there is no class
28.661 + * associated with this descriptor.
28.662 + */
28.663 + ObjectStreamClass getLocalDesc() {
28.664 + return localDesc;
28.665 + }
28.666 +
28.667 + /**
28.668 + * Returns arrays of ObjectStreamFields representing the serializable
28.669 + * fields of the represented class. If copy is true, a clone of this class
28.670 + * descriptor's field array is returned, otherwise the array itself is
28.671 + * returned.
28.672 + */
28.673 + ObjectStreamField[] getFields(boolean copy) {
28.674 + return copy ? fields.clone() : fields;
28.675 + }
28.676 +
28.677 + /**
28.678 + * Looks up a serializable field of the represented class by name and type.
28.679 + * A specified type of null matches all types, Object.class matches all
28.680 + * non-primitive types, and any other non-null type matches assignable
28.681 + * types only. Returns matching field, or null if no match found.
28.682 + */
28.683 + ObjectStreamField getField(String name, Class<?> type) {
28.684 + for (int i = 0; i < fields.length; i++) {
28.685 + ObjectStreamField f = fields[i];
28.686 + if (f.getName().equals(name)) {
28.687 + if (type == null ||
28.688 + (type == Object.class && !f.isPrimitive()))
28.689 + {
28.690 + return f;
28.691 + }
28.692 + Class<?> ftype = f.getType();
28.693 + if (ftype != null && type.isAssignableFrom(ftype)) {
28.694 + return f;
28.695 + }
28.696 + }
28.697 + }
28.698 + return null;
28.699 + }
28.700 +
28.701 + /**
28.702 + * Returns true if class descriptor represents a dynamic proxy class, false
28.703 + * otherwise.
28.704 + */
28.705 + boolean isProxy() {
28.706 + return isProxy;
28.707 + }
28.708 +
28.709 + /**
28.710 + * Returns true if class descriptor represents an enum type, false
28.711 + * otherwise.
28.712 + */
28.713 + boolean isEnum() {
28.714 + return isEnum;
28.715 + }
28.716 +
28.717 + /**
28.718 + * Returns true if represented class implements Externalizable, false
28.719 + * otherwise.
28.720 + */
28.721 + boolean isExternalizable() {
28.722 + return externalizable;
28.723 + }
28.724 +
28.725 + /**
28.726 + * Returns true if represented class implements Serializable, false
28.727 + * otherwise.
28.728 + */
28.729 + boolean isSerializable() {
28.730 + return serializable;
28.731 + }
28.732 +
28.733 + /**
28.734 + * Returns true if class descriptor represents externalizable class that
28.735 + * has written its data in 1.2 (block data) format, false otherwise.
28.736 + */
28.737 + boolean hasBlockExternalData() {
28.738 + return hasBlockExternalData;
28.739 + }
28.740 +
28.741 + /**
28.742 + * Returns true if class descriptor represents serializable (but not
28.743 + * externalizable) class which has written its data via a custom
28.744 + * writeObject() method, false otherwise.
28.745 + */
28.746 + boolean hasWriteObjectData() {
28.747 + return hasWriteObjectData;
28.748 + }
28.749 +
28.750 + /**
28.751 + * Returns true if represented class is serializable/externalizable and can
28.752 + * be instantiated by the serialization runtime--i.e., if it is
28.753 + * externalizable and defines a public no-arg constructor, or if it is
28.754 + * non-externalizable and its first non-serializable superclass defines an
28.755 + * accessible no-arg constructor. Otherwise, returns false.
28.756 + */
28.757 + boolean isInstantiable() {
28.758 + return (cons != null);
28.759 + }
28.760 +
28.761 + /**
28.762 + * Returns true if represented class is serializable (but not
28.763 + * externalizable) and defines a conformant writeObject method. Otherwise,
28.764 + * returns false.
28.765 + */
28.766 + boolean hasWriteObjectMethod() {
28.767 + return (writeObjectMethod != null);
28.768 + }
28.769 +
28.770 + /**
28.771 + * Returns true if represented class is serializable (but not
28.772 + * externalizable) and defines a conformant readObject method. Otherwise,
28.773 + * returns false.
28.774 + */
28.775 + boolean hasReadObjectMethod() {
28.776 + return (readObjectMethod != null);
28.777 + }
28.778 +
28.779 + /**
28.780 + * Returns true if represented class is serializable (but not
28.781 + * externalizable) and defines a conformant readObjectNoData method.
28.782 + * Otherwise, returns false.
28.783 + */
28.784 + boolean hasReadObjectNoDataMethod() {
28.785 + return (readObjectNoDataMethod != null);
28.786 + }
28.787 +
28.788 + /**
28.789 + * Returns true if represented class is serializable or externalizable and
28.790 + * defines a conformant writeReplace method. Otherwise, returns false.
28.791 + */
28.792 + boolean hasWriteReplaceMethod() {
28.793 + return (writeReplaceMethod != null);
28.794 + }
28.795 +
28.796 + /**
28.797 + * Returns true if represented class is serializable or externalizable and
28.798 + * defines a conformant readResolve method. Otherwise, returns false.
28.799 + */
28.800 + boolean hasReadResolveMethod() {
28.801 + return (readResolveMethod != null);
28.802 + }
28.803 +
28.804 + /**
28.805 + * Creates a new instance of the represented class. If the class is
28.806 + * externalizable, invokes its public no-arg constructor; otherwise, if the
28.807 + * class is serializable, invokes the no-arg constructor of the first
28.808 + * non-serializable superclass. Throws UnsupportedOperationException if
28.809 + * this class descriptor is not associated with a class, if the associated
28.810 + * class is non-serializable or if the appropriate no-arg constructor is
28.811 + * inaccessible/unavailable.
28.812 + */
28.813 + Object newInstance()
28.814 + throws InstantiationException, InvocationTargetException,
28.815 + UnsupportedOperationException
28.816 + {
28.817 + if (cons != null) {
28.818 + try {
28.819 + return cons.newInstance();
28.820 + } catch (IllegalAccessException ex) {
28.821 + // should not occur, as access checks have been suppressed
28.822 + throw new InternalError();
28.823 + }
28.824 + } else {
28.825 + throw new UnsupportedOperationException();
28.826 + }
28.827 + }
28.828 +
28.829 + /**
28.830 + * Invokes the writeObject method of the represented serializable class.
28.831 + * Throws UnsupportedOperationException if this class descriptor is not
28.832 + * associated with a class, or if the class is externalizable,
28.833 + * non-serializable or does not define writeObject.
28.834 + */
28.835 + void invokeWriteObject(Object obj, ObjectOutputStream out)
28.836 + throws IOException, UnsupportedOperationException
28.837 + {
28.838 + if (writeObjectMethod != null) {
28.839 + try {
28.840 + writeObjectMethod.invoke(obj, new Object[]{ out });
28.841 + } catch (InvocationTargetException ex) {
28.842 + Throwable th = ex.getTargetException();
28.843 + if (th instanceof IOException) {
28.844 + throw (IOException) th;
28.845 + } else {
28.846 + throwMiscException(th);
28.847 + }
28.848 + } catch (IllegalAccessException ex) {
28.849 + // should not occur, as access checks have been suppressed
28.850 + throw new InternalError();
28.851 + }
28.852 + } else {
28.853 + throw new UnsupportedOperationException();
28.854 + }
28.855 + }
28.856 +
28.857 + /**
28.858 + * Invokes the readObject method of the represented serializable class.
28.859 + * Throws UnsupportedOperationException if this class descriptor is not
28.860 + * associated with a class, or if the class is externalizable,
28.861 + * non-serializable or does not define readObject.
28.862 + */
28.863 + void invokeReadObject(Object obj, ObjectInputStream in)
28.864 + throws ClassNotFoundException, IOException,
28.865 + UnsupportedOperationException
28.866 + {
28.867 + if (readObjectMethod != null) {
28.868 + try {
28.869 + readObjectMethod.invoke(obj, new Object[]{ in });
28.870 + } catch (InvocationTargetException ex) {
28.871 + Throwable th = ex.getTargetException();
28.872 + if (th instanceof ClassNotFoundException) {
28.873 + throw (ClassNotFoundException) th;
28.874 + } else if (th instanceof IOException) {
28.875 + throw (IOException) th;
28.876 + } else {
28.877 + throwMiscException(th);
28.878 + }
28.879 + } catch (IllegalAccessException ex) {
28.880 + // should not occur, as access checks have been suppressed
28.881 + throw new InternalError();
28.882 + }
28.883 + } else {
28.884 + throw new UnsupportedOperationException();
28.885 + }
28.886 + }
28.887 +
28.888 + /**
28.889 + * Invokes the readObjectNoData method of the represented serializable
28.890 + * class. Throws UnsupportedOperationException if this class descriptor is
28.891 + * not associated with a class, or if the class is externalizable,
28.892 + * non-serializable or does not define readObjectNoData.
28.893 + */
28.894 + void invokeReadObjectNoData(Object obj)
28.895 + throws IOException, UnsupportedOperationException
28.896 + {
28.897 + if (readObjectNoDataMethod != null) {
28.898 + try {
28.899 + readObjectNoDataMethod.invoke(obj, (Object[]) null);
28.900 + } catch (InvocationTargetException ex) {
28.901 + Throwable th = ex.getTargetException();
28.902 + if (th instanceof ObjectStreamException) {
28.903 + throw (ObjectStreamException) th;
28.904 + } else {
28.905 + throwMiscException(th);
28.906 + }
28.907 + } catch (IllegalAccessException ex) {
28.908 + // should not occur, as access checks have been suppressed
28.909 + throw new InternalError();
28.910 + }
28.911 + } else {
28.912 + throw new UnsupportedOperationException();
28.913 + }
28.914 + }
28.915 +
28.916 + /**
28.917 + * Invokes the writeReplace method of the represented serializable class and
28.918 + * returns the result. Throws UnsupportedOperationException if this class
28.919 + * descriptor is not associated with a class, or if the class is
28.920 + * non-serializable or does not define writeReplace.
28.921 + */
28.922 + Object invokeWriteReplace(Object obj)
28.923 + throws IOException, UnsupportedOperationException
28.924 + {
28.925 + if (writeReplaceMethod != null) {
28.926 + try {
28.927 + return writeReplaceMethod.invoke(obj, (Object[]) null);
28.928 + } catch (InvocationTargetException ex) {
28.929 + Throwable th = ex.getTargetException();
28.930 + if (th instanceof ObjectStreamException) {
28.931 + throw (ObjectStreamException) th;
28.932 + } else {
28.933 + throwMiscException(th);
28.934 + throw new InternalError(); // never reached
28.935 + }
28.936 + } catch (IllegalAccessException ex) {
28.937 + // should not occur, as access checks have been suppressed
28.938 + throw new InternalError();
28.939 + }
28.940 + } else {
28.941 + throw new UnsupportedOperationException();
28.942 + }
28.943 + }
28.944 +
28.945 + /**
28.946 + * Invokes the readResolve method of the represented serializable class and
28.947 + * returns the result. Throws UnsupportedOperationException if this class
28.948 + * descriptor is not associated with a class, or if the class is
28.949 + * non-serializable or does not define readResolve.
28.950 + */
28.951 + Object invokeReadResolve(Object obj)
28.952 + throws IOException, UnsupportedOperationException
28.953 + {
28.954 + if (readResolveMethod != null) {
28.955 + try {
28.956 + return readResolveMethod.invoke(obj, (Object[]) null);
28.957 + } catch (InvocationTargetException ex) {
28.958 + Throwable th = ex.getTargetException();
28.959 + if (th instanceof ObjectStreamException) {
28.960 + throw (ObjectStreamException) th;
28.961 + } else {
28.962 + throwMiscException(th);
28.963 + throw new InternalError(); // never reached
28.964 + }
28.965 + } catch (IllegalAccessException ex) {
28.966 + // should not occur, as access checks have been suppressed
28.967 + throw new InternalError();
28.968 + }
28.969 + } else {
28.970 + throw new UnsupportedOperationException();
28.971 + }
28.972 + }
28.973 +
28.974 + /**
28.975 + * Class representing the portion of an object's serialized form allotted
28.976 + * to data described by a given class descriptor. If "hasData" is false,
28.977 + * the object's serialized form does not contain data associated with the
28.978 + * class descriptor.
28.979 + */
28.980 + static class ClassDataSlot {
28.981 +
28.982 + /** class descriptor "occupying" this slot */
28.983 + final ObjectStreamClass desc;
28.984 + /** true if serialized form includes data for this slot's descriptor */
28.985 + final boolean hasData;
28.986 +
28.987 + ClassDataSlot(ObjectStreamClass desc, boolean hasData) {
28.988 + this.desc = desc;
28.989 + this.hasData = hasData;
28.990 + }
28.991 + }
28.992 +
28.993 + /**
28.994 + * Returns array of ClassDataSlot instances representing the data layout
28.995 + * (including superclass data) for serialized objects described by this
28.996 + * class descriptor. ClassDataSlots are ordered by inheritance with those
28.997 + * containing "higher" superclasses appearing first. The final
28.998 + * ClassDataSlot contains a reference to this descriptor.
28.999 + */
28.1000 + ClassDataSlot[] getClassDataLayout() throws InvalidClassException {
28.1001 + // REMIND: synchronize instead of relying on volatile?
28.1002 + if (dataLayout == null) {
28.1003 + dataLayout = getClassDataLayout0();
28.1004 + }
28.1005 + return dataLayout;
28.1006 + }
28.1007 +
28.1008 + private ClassDataSlot[] getClassDataLayout0()
28.1009 + throws InvalidClassException
28.1010 + {
28.1011 + ArrayList<ClassDataSlot> slots = new ArrayList<>();
28.1012 + Class<?> start = cl, end = cl;
28.1013 +
28.1014 + // locate closest non-serializable superclass
28.1015 + while (end != null && Serializable.class.isAssignableFrom(end)) {
28.1016 + end = end.getSuperclass();
28.1017 + }
28.1018 +
28.1019 + for (ObjectStreamClass d = this; d != null; d = d.superDesc) {
28.1020 +
28.1021 + // search up inheritance hierarchy for class with matching name
28.1022 + String searchName = (d.cl != null) ? d.cl.getName() : d.name;
28.1023 + Class<?> match = null;
28.1024 + for (Class<?> c = start; c != end; c = c.getSuperclass()) {
28.1025 + if (searchName.equals(c.getName())) {
28.1026 + match = c;
28.1027 + break;
28.1028 + }
28.1029 + }
28.1030 +
28.1031 + // add "no data" slot for each unmatched class below match
28.1032 + if (match != null) {
28.1033 + for (Class<?> c = start; c != match; c = c.getSuperclass()) {
28.1034 + slots.add(new ClassDataSlot(
28.1035 + ObjectStreamClass.lookup(c, true), false));
28.1036 + }
28.1037 + start = match.getSuperclass();
28.1038 + }
28.1039 +
28.1040 + // record descriptor/class pairing
28.1041 + slots.add(new ClassDataSlot(d.getVariantFor(match), true));
28.1042 + }
28.1043 +
28.1044 + // add "no data" slot for any leftover unmatched classes
28.1045 + for (Class<?> c = start; c != end; c = c.getSuperclass()) {
28.1046 + slots.add(new ClassDataSlot(
28.1047 + ObjectStreamClass.lookup(c, true), false));
28.1048 + }
28.1049 +
28.1050 + // order slots from superclass -> subclass
28.1051 + Collections.reverse(slots);
28.1052 + return slots.toArray(new ClassDataSlot[slots.size()]);
28.1053 + }
28.1054 +
28.1055 + /**
28.1056 + * Returns aggregate size (in bytes) of marshalled primitive field values
28.1057 + * for represented class.
28.1058 + */
28.1059 + int getPrimDataSize() {
28.1060 + return primDataSize;
28.1061 + }
28.1062 +
28.1063 + /**
28.1064 + * Returns number of non-primitive serializable fields of represented
28.1065 + * class.
28.1066 + */
28.1067 + int getNumObjFields() {
28.1068 + return numObjFields;
28.1069 + }
28.1070 +
28.1071 + /**
28.1072 + * Fetches the serializable primitive field values of object obj and
28.1073 + * marshals them into byte array buf starting at offset 0. It is the
28.1074 + * responsibility of the caller to ensure that obj is of the proper type if
28.1075 + * non-null.
28.1076 + */
28.1077 + void getPrimFieldValues(Object obj, byte[] buf) {
28.1078 + }
28.1079 +
28.1080 + /**
28.1081 + * Sets the serializable primitive fields of object obj using values
28.1082 + * unmarshalled from byte array buf starting at offset 0. It is the
28.1083 + * responsibility of the caller to ensure that obj is of the proper type if
28.1084 + * non-null.
28.1085 + */
28.1086 + void setPrimFieldValues(Object obj, byte[] buf) {
28.1087 + }
28.1088 +
28.1089 + /**
28.1090 + * Fetches the serializable object field values of object obj and stores
28.1091 + * them in array vals starting at offset 0. It is the responsibility of
28.1092 + * the caller to ensure that obj is of the proper type if non-null.
28.1093 + */
28.1094 + void getObjFieldValues(Object obj, Object[] vals) {
28.1095 + }
28.1096 +
28.1097 + /**
28.1098 + * Sets the serializable object fields of object obj using values from
28.1099 + * array vals starting at offset 0. It is the responsibility of the caller
28.1100 + * to ensure that obj is of the proper type if non-null.
28.1101 + */
28.1102 + void setObjFieldValues(Object obj, Object[] vals) {
28.1103 + }
28.1104 +
28.1105 + /**
28.1106 + * Calculates and sets serializable field offsets, as well as primitive
28.1107 + * data size and object field count totals. Throws InvalidClassException
28.1108 + * if fields are illegally ordered.
28.1109 + */
28.1110 + private void computeFieldOffsets() throws InvalidClassException {
28.1111 + primDataSize = 0;
28.1112 + numObjFields = 0;
28.1113 + int firstObjIndex = -1;
28.1114 +
28.1115 + for (int i = 0; i < fields.length; i++) {
28.1116 + ObjectStreamField f = fields[i];
28.1117 + switch (f.getTypeCode()) {
28.1118 + case 'Z':
28.1119 + case 'B':
28.1120 + f.setOffset(primDataSize++);
28.1121 + break;
28.1122 +
28.1123 + case 'C':
28.1124 + case 'S':
28.1125 + f.setOffset(primDataSize);
28.1126 + primDataSize += 2;
28.1127 + break;
28.1128 +
28.1129 + case 'I':
28.1130 + case 'F':
28.1131 + f.setOffset(primDataSize);
28.1132 + primDataSize += 4;
28.1133 + break;
28.1134 +
28.1135 + case 'J':
28.1136 + case 'D':
28.1137 + f.setOffset(primDataSize);
28.1138 + primDataSize += 8;
28.1139 + break;
28.1140 +
28.1141 + case '[':
28.1142 + case 'L':
28.1143 + f.setOffset(numObjFields++);
28.1144 + if (firstObjIndex == -1) {
28.1145 + firstObjIndex = i;
28.1146 + }
28.1147 + break;
28.1148 +
28.1149 + default:
28.1150 + throw new InternalError();
28.1151 + }
28.1152 + }
28.1153 + if (firstObjIndex != -1 &&
28.1154 + firstObjIndex + numObjFields != fields.length)
28.1155 + {
28.1156 + throw new InvalidClassException(name, "illegal field order");
28.1157 + }
28.1158 + }
28.1159 +
28.1160 + /**
28.1161 + * If given class is the same as the class associated with this class
28.1162 + * descriptor, returns reference to this class descriptor. Otherwise,
28.1163 + * returns variant of this class descriptor bound to given class.
28.1164 + */
28.1165 + private ObjectStreamClass getVariantFor(Class<?> cl)
28.1166 + throws InvalidClassException
28.1167 + {
28.1168 + if (this.cl == cl) {
28.1169 + return this;
28.1170 + }
28.1171 + ObjectStreamClass desc = new ObjectStreamClass();
28.1172 + if (isProxy) {
28.1173 + desc.initProxy(cl, null, superDesc);
28.1174 + } else {
28.1175 + desc.initNonProxy(this, cl, null, superDesc);
28.1176 + }
28.1177 + return desc;
28.1178 + }
28.1179 +
28.1180 + /**
28.1181 + * Returns public no-arg constructor of given class, or null if none found.
28.1182 + * Access checks are disabled on the returned constructor (if any), since
28.1183 + * the defining class may still be non-public.
28.1184 + */
28.1185 + private static Constructor getExternalizableConstructor(Class<?> cl) {
28.1186 + throw new SecurityException();
28.1187 + }
28.1188 +
28.1189 + /**
28.1190 + * Returns subclass-accessible no-arg constructor of first non-serializable
28.1191 + * superclass, or null if none found. Access checks are disabled on the
28.1192 + * returned constructor (if any).
28.1193 + */
28.1194 + private static Constructor getSerializableConstructor(Class<?> cl) {
28.1195 + Class<?> initCl = cl;
28.1196 + while (Serializable.class.isAssignableFrom(initCl)) {
28.1197 + if ((initCl = initCl.getSuperclass()) == null) {
28.1198 + return null;
28.1199 + }
28.1200 + }
28.1201 + throw new SecurityException();
28.1202 + }
28.1203 +
28.1204 + /**
28.1205 + * Returns non-static, non-abstract method with given signature provided it
28.1206 + * is defined by or accessible (via inheritance) by the given class, or
28.1207 + * null if no match found. Access checks are disabled on the returned
28.1208 + * method (if any).
28.1209 + */
28.1210 + private static Method getInheritableMethod(Class<?> cl, String name,
28.1211 + Class<?>[] argTypes,
28.1212 + Class<?> returnType)
28.1213 + {
28.1214 + throw new SecurityException();
28.1215 + }
28.1216 +
28.1217 + /**
28.1218 + * Returns non-static private method with given signature defined by given
28.1219 + * class, or null if none found. Access checks are disabled on the
28.1220 + * returned method (if any).
28.1221 + */
28.1222 + private static Method getPrivateMethod(Class<?> cl, String name,
28.1223 + Class<?>[] argTypes,
28.1224 + Class<?> returnType)
28.1225 + {
28.1226 + throw new SecurityException();
28.1227 + }
28.1228 +
28.1229 + /**
28.1230 + * Returns true if classes are defined in the same runtime package, false
28.1231 + * otherwise.
28.1232 + */
28.1233 + private static boolean packageEquals(Class<?> cl1, Class<?> cl2) {
28.1234 + return (cl1.getClassLoader() == cl2.getClassLoader() &&
28.1235 + getPackageName(cl1).equals(getPackageName(cl2)));
28.1236 + }
28.1237 +
28.1238 + /**
28.1239 + * Returns package name of given class.
28.1240 + */
28.1241 + private static String getPackageName(Class<?> cl) {
28.1242 + String s = cl.getName();
28.1243 + int i = s.lastIndexOf('[');
28.1244 + if (i >= 0) {
28.1245 + s = s.substring(i + 2);
28.1246 + }
28.1247 + i = s.lastIndexOf('.');
28.1248 + return (i >= 0) ? s.substring(0, i) : "";
28.1249 + }
28.1250 +
28.1251 + /**
28.1252 + * Compares class names for equality, ignoring package names. Returns true
28.1253 + * if class names equal, false otherwise.
28.1254 + */
28.1255 + private static boolean classNamesEqual(String name1, String name2) {
28.1256 + name1 = name1.substring(name1.lastIndexOf('.') + 1);
28.1257 + name2 = name2.substring(name2.lastIndexOf('.') + 1);
28.1258 + return name1.equals(name2);
28.1259 + }
28.1260 +
28.1261 + /**
28.1262 + * Returns JVM type signature for given class.
28.1263 + */
28.1264 + private static String getClassSignature(Class<?> cl) {
28.1265 + StringBuilder sbuf = new StringBuilder();
28.1266 + while (cl.isArray()) {
28.1267 + sbuf.append('[');
28.1268 + cl = cl.getComponentType();
28.1269 + }
28.1270 + if (cl.isPrimitive()) {
28.1271 + if (cl == Integer.TYPE) {
28.1272 + sbuf.append('I');
28.1273 + } else if (cl == Byte.TYPE) {
28.1274 + sbuf.append('B');
28.1275 + } else if (cl == Long.TYPE) {
28.1276 + sbuf.append('J');
28.1277 + } else if (cl == Float.TYPE) {
28.1278 + sbuf.append('F');
28.1279 + } else if (cl == Double.TYPE) {
28.1280 + sbuf.append('D');
28.1281 + } else if (cl == Short.TYPE) {
28.1282 + sbuf.append('S');
28.1283 + } else if (cl == Character.TYPE) {
28.1284 + sbuf.append('C');
28.1285 + } else if (cl == Boolean.TYPE) {
28.1286 + sbuf.append('Z');
28.1287 + } else if (cl == Void.TYPE) {
28.1288 + sbuf.append('V');
28.1289 + } else {
28.1290 + throw new InternalError();
28.1291 + }
28.1292 + } else {
28.1293 + sbuf.append('L' + cl.getName().replace('.', '/') + ';');
28.1294 + }
28.1295 + return sbuf.toString();
28.1296 + }
28.1297 +
28.1298 + /**
28.1299 + * Returns JVM type signature for given list of parameters and return type.
28.1300 + */
28.1301 + private static String getMethodSignature(Class<?>[] paramTypes,
28.1302 + Class<?> retType)
28.1303 + {
28.1304 + StringBuilder sbuf = new StringBuilder();
28.1305 + sbuf.append('(');
28.1306 + for (int i = 0; i < paramTypes.length; i++) {
28.1307 + sbuf.append(getClassSignature(paramTypes[i]));
28.1308 + }
28.1309 + sbuf.append(')');
28.1310 + sbuf.append(getClassSignature(retType));
28.1311 + return sbuf.toString();
28.1312 + }
28.1313 +
28.1314 + /**
28.1315 + * Convenience method for throwing an exception that is either a
28.1316 + * RuntimeException, Error, or of some unexpected type (in which case it is
28.1317 + * wrapped inside an IOException).
28.1318 + */
28.1319 + private static void throwMiscException(Throwable th) throws IOException {
28.1320 + if (th instanceof RuntimeException) {
28.1321 + throw (RuntimeException) th;
28.1322 + } else if (th instanceof Error) {
28.1323 + throw (Error) th;
28.1324 + } else {
28.1325 + IOException ex = new IOException("unexpected exception type");
28.1326 + ex.initCause(th);
28.1327 + throw ex;
28.1328 + }
28.1329 + }
28.1330 +
28.1331 + /**
28.1332 + * Returns ObjectStreamField array describing the serializable fields of
28.1333 + * the given class. Serializable fields backed by an actual field of the
28.1334 + * class are represented by ObjectStreamFields with corresponding non-null
28.1335 + * Field objects. Throws InvalidClassException if the (explicitly
28.1336 + * declared) serializable fields are invalid.
28.1337 + */
28.1338 + private static ObjectStreamField[] getSerialFields(Class<?> cl)
28.1339 + throws InvalidClassException
28.1340 + {
28.1341 + ObjectStreamField[] fields;
28.1342 + if (Serializable.class.isAssignableFrom(cl) &&
28.1343 + !Externalizable.class.isAssignableFrom(cl) &&
28.1344 + !Proxy.isProxyClass(cl) &&
28.1345 + !cl.isInterface())
28.1346 + {
28.1347 + if ((fields = getDeclaredSerialFields(cl)) == null) {
28.1348 + fields = getDefaultSerialFields(cl);
28.1349 + }
28.1350 + Arrays.sort(fields);
28.1351 + } else {
28.1352 + fields = NO_FIELDS;
28.1353 + }
28.1354 + return fields;
28.1355 + }
28.1356 +
28.1357 + /**
28.1358 + * Returns serializable fields of given class as defined explicitly by a
28.1359 + * "serialPersistentFields" field, or null if no appropriate
28.1360 + * "serialPersistentFields" field is defined. Serializable fields backed
28.1361 + * by an actual field of the class are represented by ObjectStreamFields
28.1362 + * with corresponding non-null Field objects. For compatibility with past
28.1363 + * releases, a "serialPersistentFields" field with a null value is
28.1364 + * considered equivalent to not declaring "serialPersistentFields". Throws
28.1365 + * InvalidClassException if the declared serializable fields are
28.1366 + * invalid--e.g., if multiple fields share the same name.
28.1367 + */
28.1368 + private static ObjectStreamField[] getDeclaredSerialFields(Class<?> cl)
28.1369 + throws InvalidClassException
28.1370 + {
28.1371 + throw new SecurityException();
28.1372 + }
28.1373 +
28.1374 + /**
28.1375 + * Returns array of ObjectStreamFields corresponding to all non-static
28.1376 + * non-transient fields declared by given class. Each ObjectStreamField
28.1377 + * contains a Field object for the field it represents. If no default
28.1378 + * serializable fields exist, NO_FIELDS is returned.
28.1379 + */
28.1380 + private static ObjectStreamField[] getDefaultSerialFields(Class<?> cl) {
28.1381 + throw new SecurityException();
28.1382 + }
28.1383 +
28.1384 + /**
28.1385 + * Returns explicit serial version UID value declared by given class, or
28.1386 + * null if none.
28.1387 + */
28.1388 + private static Long getDeclaredSUID(Class<?> cl) {
28.1389 + return null;
28.1390 + }
28.1391 +
28.1392 + /**
28.1393 + * Computes the default serial version UID value for the given class.
28.1394 + */
28.1395 + private static long computeDefaultSUID(Class<?> cl) {
28.1396 + throw new SecurityException();
28.1397 + }
28.1398 +
28.1399 +}
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
29.2 +++ b/emul/compact/src/main/java/java/io/ObjectStreamConstants.java Mon Feb 04 09:37:56 2013 +0100
29.3 @@ -0,0 +1,215 @@
29.4 +/*
29.5 + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
29.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
29.7 + *
29.8 + * This code is free software; you can redistribute it and/or modify it
29.9 + * under the terms of the GNU General Public License version 2 only, as
29.10 + * published by the Free Software Foundation. Oracle designates this
29.11 + * particular file as subject to the "Classpath" exception as provided
29.12 + * by Oracle in the LICENSE file that accompanied this code.
29.13 + *
29.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
29.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
29.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
29.17 + * version 2 for more details (a copy is included in the LICENSE file that
29.18 + * accompanied this code).
29.19 + *
29.20 + * You should have received a copy of the GNU General Public License version
29.21 + * 2 along with this work; if not, write to the Free Software Foundation,
29.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
29.23 + *
29.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
29.25 + * or visit www.oracle.com if you need additional information or have any
29.26 + * questions.
29.27 + */
29.28 +
29.29 +package java.io;
29.30 +
29.31 +/**
29.32 + * Constants written into the Object Serialization Stream.
29.33 + *
29.34 + * @author unascribed
29.35 + * @since JDK 1.1
29.36 + */
29.37 +public interface ObjectStreamConstants {
29.38 +
29.39 + /**
29.40 + * Magic number that is written to the stream header.
29.41 + */
29.42 + final static short STREAM_MAGIC = (short)0xaced;
29.43 +
29.44 + /**
29.45 + * Version number that is written to the stream header.
29.46 + */
29.47 + final static short STREAM_VERSION = 5;
29.48 +
29.49 + /* Each item in the stream is preceded by a tag
29.50 + */
29.51 +
29.52 + /**
29.53 + * First tag value.
29.54 + */
29.55 + final static byte TC_BASE = 0x70;
29.56 +
29.57 + /**
29.58 + * Null object reference.
29.59 + */
29.60 + final static byte TC_NULL = (byte)0x70;
29.61 +
29.62 + /**
29.63 + * Reference to an object already written into the stream.
29.64 + */
29.65 + final static byte TC_REFERENCE = (byte)0x71;
29.66 +
29.67 + /**
29.68 + * new Class Descriptor.
29.69 + */
29.70 + final static byte TC_CLASSDESC = (byte)0x72;
29.71 +
29.72 + /**
29.73 + * new Object.
29.74 + */
29.75 + final static byte TC_OBJECT = (byte)0x73;
29.76 +
29.77 + /**
29.78 + * new String.
29.79 + */
29.80 + final static byte TC_STRING = (byte)0x74;
29.81 +
29.82 + /**
29.83 + * new Array.
29.84 + */
29.85 + final static byte TC_ARRAY = (byte)0x75;
29.86 +
29.87 + /**
29.88 + * Reference to Class.
29.89 + */
29.90 + final static byte TC_CLASS = (byte)0x76;
29.91 +
29.92 + /**
29.93 + * Block of optional data. Byte following tag indicates number
29.94 + * of bytes in this block data.
29.95 + */
29.96 + final static byte TC_BLOCKDATA = (byte)0x77;
29.97 +
29.98 + /**
29.99 + * End of optional block data blocks for an object.
29.100 + */
29.101 + final static byte TC_ENDBLOCKDATA = (byte)0x78;
29.102 +
29.103 + /**
29.104 + * Reset stream context. All handles written into stream are reset.
29.105 + */
29.106 + final static byte TC_RESET = (byte)0x79;
29.107 +
29.108 + /**
29.109 + * long Block data. The long following the tag indicates the
29.110 + * number of bytes in this block data.
29.111 + */
29.112 + final static byte TC_BLOCKDATALONG= (byte)0x7A;
29.113 +
29.114 + /**
29.115 + * Exception during write.
29.116 + */
29.117 + final static byte TC_EXCEPTION = (byte)0x7B;
29.118 +
29.119 + /**
29.120 + * Long string.
29.121 + */
29.122 + final static byte TC_LONGSTRING = (byte)0x7C;
29.123 +
29.124 + /**
29.125 + * new Proxy Class Descriptor.
29.126 + */
29.127 + final static byte TC_PROXYCLASSDESC = (byte)0x7D;
29.128 +
29.129 + /**
29.130 + * new Enum constant.
29.131 + * @since 1.5
29.132 + */
29.133 + final static byte TC_ENUM = (byte)0x7E;
29.134 +
29.135 + /**
29.136 + * Last tag value.
29.137 + */
29.138 + final static byte TC_MAX = (byte)0x7E;
29.139 +
29.140 + /**
29.141 + * First wire handle to be assigned.
29.142 + */
29.143 + final static int baseWireHandle = 0x7e0000;
29.144 +
29.145 +
29.146 + /******************************************************/
29.147 + /* Bit masks for ObjectStreamClass flag.*/
29.148 +
29.149 + /**
29.150 + * Bit mask for ObjectStreamClass flag. Indicates a Serializable class
29.151 + * defines its own writeObject method.
29.152 + */
29.153 + final static byte SC_WRITE_METHOD = 0x01;
29.154 +
29.155 + /**
29.156 + * Bit mask for ObjectStreamClass flag. Indicates Externalizable data
29.157 + * written in Block Data mode.
29.158 + * Added for PROTOCOL_VERSION_2.
29.159 + *
29.160 + * @see #PROTOCOL_VERSION_2
29.161 + * @since 1.2
29.162 + */
29.163 + final static byte SC_BLOCK_DATA = 0x08;
29.164 +
29.165 + /**
29.166 + * Bit mask for ObjectStreamClass flag. Indicates class is Serializable.
29.167 + */
29.168 + final static byte SC_SERIALIZABLE = 0x02;
29.169 +
29.170 + /**
29.171 + * Bit mask for ObjectStreamClass flag. Indicates class is Externalizable.
29.172 + */
29.173 + final static byte SC_EXTERNALIZABLE = 0x04;
29.174 +
29.175 + /**
29.176 + * Bit mask for ObjectStreamClass flag. Indicates class is an enum type.
29.177 + * @since 1.5
29.178 + */
29.179 + final static byte SC_ENUM = 0x10;
29.180 +
29.181 +
29.182 + /* *******************************************************************/
29.183 + /* Security permissions */
29.184 +
29.185 + /**
29.186 + * A Stream Protocol Version. <p>
29.187 + *
29.188 + * All externalizable data is written in JDK 1.1 external data
29.189 + * format after calling this method. This version is needed to write
29.190 + * streams containing Externalizable data that can be read by
29.191 + * pre-JDK 1.1.6 JVMs.
29.192 + *
29.193 + * @see java.io.ObjectOutputStream#useProtocolVersion(int)
29.194 + * @since 1.2
29.195 + */
29.196 + public final static int PROTOCOL_VERSION_1 = 1;
29.197 +
29.198 +
29.199 + /**
29.200 + * A Stream Protocol Version. <p>
29.201 + *
29.202 + * This protocol is written by JVM 1.2.
29.203 + *
29.204 + * Externalizable data is written in block data mode and is
29.205 + * terminated with TC_ENDBLOCKDATA. Externalizable classdescriptor
29.206 + * flags has SC_BLOCK_DATA enabled. JVM 1.1.6 and greater can
29.207 + * read this format change.
29.208 + *
29.209 + * Enables writing a nonSerializable class descriptor into the
29.210 + * stream. The serialVersionUID of a nonSerializable class is
29.211 + * set to 0L.
29.212 + *
29.213 + * @see java.io.ObjectOutputStream#useProtocolVersion(int)
29.214 + * @see #SC_BLOCK_DATA
29.215 + * @since 1.2
29.216 + */
29.217 + public final static int PROTOCOL_VERSION_2 = 2;
29.218 +}
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
30.2 +++ b/emul/compact/src/main/java/java/io/ObjectStreamException.java Mon Feb 04 09:37:56 2013 +0100
30.3 @@ -0,0 +1,53 @@
30.4 +/*
30.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
30.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
30.7 + *
30.8 + * This code is free software; you can redistribute it and/or modify it
30.9 + * under the terms of the GNU General Public License version 2 only, as
30.10 + * published by the Free Software Foundation. Oracle designates this
30.11 + * particular file as subject to the "Classpath" exception as provided
30.12 + * by Oracle in the LICENSE file that accompanied this code.
30.13 + *
30.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
30.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
30.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
30.17 + * version 2 for more details (a copy is included in the LICENSE file that
30.18 + * accompanied this code).
30.19 + *
30.20 + * You should have received a copy of the GNU General Public License version
30.21 + * 2 along with this work; if not, write to the Free Software Foundation,
30.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
30.23 + *
30.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
30.25 + * or visit www.oracle.com if you need additional information or have any
30.26 + * questions.
30.27 + */
30.28 +
30.29 +package java.io;
30.30 +
30.31 +/**
30.32 + * Superclass of all exceptions specific to Object Stream classes.
30.33 + *
30.34 + * @author unascribed
30.35 + * @since JDK1.1
30.36 + */
30.37 +public abstract class ObjectStreamException extends IOException {
30.38 +
30.39 + private static final long serialVersionUID = 7260898174833392607L;
30.40 +
30.41 + /**
30.42 + * Create an ObjectStreamException with the specified argument.
30.43 + *
30.44 + * @param classname the detailed message for the exception
30.45 + */
30.46 + protected ObjectStreamException(String classname) {
30.47 + super(classname);
30.48 + }
30.49 +
30.50 + /**
30.51 + * Create an ObjectStreamException.
30.52 + */
30.53 + protected ObjectStreamException() {
30.54 + super();
30.55 + }
30.56 +}
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
31.2 +++ b/emul/compact/src/main/java/java/io/ObjectStreamField.java Mon Feb 04 09:37:56 2013 +0100
31.3 @@ -0,0 +1,314 @@
31.4 +/*
31.5 + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
31.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
31.7 + *
31.8 + * This code is free software; you can redistribute it and/or modify it
31.9 + * under the terms of the GNU General Public License version 2 only, as
31.10 + * published by the Free Software Foundation. Oracle designates this
31.11 + * particular file as subject to the "Classpath" exception as provided
31.12 + * by Oracle in the LICENSE file that accompanied this code.
31.13 + *
31.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
31.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
31.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
31.17 + * version 2 for more details (a copy is included in the LICENSE file that
31.18 + * accompanied this code).
31.19 + *
31.20 + * You should have received a copy of the GNU General Public License version
31.21 + * 2 along with this work; if not, write to the Free Software Foundation,
31.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
31.23 + *
31.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
31.25 + * or visit www.oracle.com if you need additional information or have any
31.26 + * questions.
31.27 + */
31.28 +
31.29 +package java.io;
31.30 +
31.31 +import java.lang.reflect.Field;
31.32 +
31.33 +/**
31.34 + * A description of a Serializable field from a Serializable class. An array
31.35 + * of ObjectStreamFields is used to declare the Serializable fields of a class.
31.36 + *
31.37 + * @author Mike Warres
31.38 + * @author Roger Riggs
31.39 + * @see ObjectStreamClass
31.40 + * @since 1.2
31.41 + */
31.42 +public class ObjectStreamField
31.43 + implements Comparable<Object>
31.44 +{
31.45 +
31.46 + /** field name */
31.47 + private final String name;
31.48 + /** canonical JVM signature of field type */
31.49 + private final String signature;
31.50 + /** field type (Object.class if unknown non-primitive type) */
31.51 + private final Class<?> type;
31.52 + /** whether or not to (de)serialize field values as unshared */
31.53 + private final boolean unshared;
31.54 + /** corresponding reflective field object, if any */
31.55 + private final Field field;
31.56 + /** offset of field value in enclosing field group */
31.57 + private int offset = 0;
31.58 +
31.59 + /**
31.60 + * Create a Serializable field with the specified type. This field should
31.61 + * be documented with a <code>serialField</code> tag.
31.62 + *
31.63 + * @param name the name of the serializable field
31.64 + * @param type the <code>Class</code> object of the serializable field
31.65 + */
31.66 + public ObjectStreamField(String name, Class<?> type) {
31.67 + this(name, type, false);
31.68 + }
31.69 +
31.70 + /**
31.71 + * Creates an ObjectStreamField representing a serializable field with the
31.72 + * given name and type. If unshared is false, values of the represented
31.73 + * field are serialized and deserialized in the default manner--if the
31.74 + * field is non-primitive, object values are serialized and deserialized as
31.75 + * if they had been written and read by calls to writeObject and
31.76 + * readObject. If unshared is true, values of the represented field are
31.77 + * serialized and deserialized as if they had been written and read by
31.78 + * calls to writeUnshared and readUnshared.
31.79 + *
31.80 + * @param name field name
31.81 + * @param type field type
31.82 + * @param unshared if false, write/read field values in the same manner
31.83 + * as writeObject/readObject; if true, write/read in the same
31.84 + * manner as writeUnshared/readUnshared
31.85 + * @since 1.4
31.86 + */
31.87 + public ObjectStreamField(String name, Class<?> type, boolean unshared) {
31.88 + if (name == null) {
31.89 + throw new NullPointerException();
31.90 + }
31.91 + this.name = name;
31.92 + this.type = type;
31.93 + this.unshared = unshared;
31.94 + signature = getClassSignature(type).intern();
31.95 + field = null;
31.96 + }
31.97 +
31.98 + /**
31.99 + * Creates an ObjectStreamField representing a field with the given name,
31.100 + * signature and unshared setting.
31.101 + */
31.102 + ObjectStreamField(String name, String signature, boolean unshared) {
31.103 + if (name == null) {
31.104 + throw new NullPointerException();
31.105 + }
31.106 + this.name = name;
31.107 + this.signature = signature.intern();
31.108 + this.unshared = unshared;
31.109 + field = null;
31.110 +
31.111 + switch (signature.charAt(0)) {
31.112 + case 'Z': type = Boolean.TYPE; break;
31.113 + case 'B': type = Byte.TYPE; break;
31.114 + case 'C': type = Character.TYPE; break;
31.115 + case 'S': type = Short.TYPE; break;
31.116 + case 'I': type = Integer.TYPE; break;
31.117 + case 'J': type = Long.TYPE; break;
31.118 + case 'F': type = Float.TYPE; break;
31.119 + case 'D': type = Double.TYPE; break;
31.120 + case 'L':
31.121 + case '[': type = Object.class; break;
31.122 + default: throw new IllegalArgumentException("illegal signature");
31.123 + }
31.124 + }
31.125 +
31.126 + /**
31.127 + * Creates an ObjectStreamField representing the given field with the
31.128 + * specified unshared setting. For compatibility with the behavior of
31.129 + * earlier serialization implementations, a "showType" parameter is
31.130 + * necessary to govern whether or not a getType() call on this
31.131 + * ObjectStreamField (if non-primitive) will return Object.class (as
31.132 + * opposed to a more specific reference type).
31.133 + */
31.134 + ObjectStreamField(Field field, boolean unshared, boolean showType) {
31.135 + this.field = field;
31.136 + this.unshared = unshared;
31.137 + name = field.getName();
31.138 + Class<?> ftype = field.getType();
31.139 + type = (showType || ftype.isPrimitive()) ? ftype : Object.class;
31.140 + signature = getClassSignature(ftype).intern();
31.141 + }
31.142 +
31.143 + /**
31.144 + * Get the name of this field.
31.145 + *
31.146 + * @return a <code>String</code> representing the name of the serializable
31.147 + * field
31.148 + */
31.149 + public String getName() {
31.150 + return name;
31.151 + }
31.152 +
31.153 + /**
31.154 + * Get the type of the field. If the type is non-primitive and this
31.155 + * <code>ObjectStreamField</code> was obtained from a deserialized {@link
31.156 + * ObjectStreamClass} instance, then <code>Object.class</code> is returned.
31.157 + * Otherwise, the <code>Class</code> object for the type of the field is
31.158 + * returned.
31.159 + *
31.160 + * @return a <code>Class</code> object representing the type of the
31.161 + * serializable field
31.162 + */
31.163 + public Class<?> getType() {
31.164 + return type;
31.165 + }
31.166 +
31.167 + /**
31.168 + * Returns character encoding of field type. The encoding is as follows:
31.169 + * <blockquote><pre>
31.170 + * B byte
31.171 + * C char
31.172 + * D double
31.173 + * F float
31.174 + * I int
31.175 + * J long
31.176 + * L class or interface
31.177 + * S short
31.178 + * Z boolean
31.179 + * [ array
31.180 + * </pre></blockquote>
31.181 + *
31.182 + * @return the typecode of the serializable field
31.183 + */
31.184 + // REMIND: deprecate?
31.185 + public char getTypeCode() {
31.186 + return signature.charAt(0);
31.187 + }
31.188 +
31.189 + /**
31.190 + * Return the JVM type signature.
31.191 + *
31.192 + * @return null if this field has a primitive type.
31.193 + */
31.194 + // REMIND: deprecate?
31.195 + public String getTypeString() {
31.196 + return isPrimitive() ? null : signature;
31.197 + }
31.198 +
31.199 + /**
31.200 + * Offset of field within instance data.
31.201 + *
31.202 + * @return the offset of this field
31.203 + * @see #setOffset
31.204 + */
31.205 + // REMIND: deprecate?
31.206 + public int getOffset() {
31.207 + return offset;
31.208 + }
31.209 +
31.210 + /**
31.211 + * Offset within instance data.
31.212 + *
31.213 + * @param offset the offset of the field
31.214 + * @see #getOffset
31.215 + */
31.216 + // REMIND: deprecate?
31.217 + protected void setOffset(int offset) {
31.218 + this.offset = offset;
31.219 + }
31.220 +
31.221 + /**
31.222 + * Return true if this field has a primitive type.
31.223 + *
31.224 + * @return true if and only if this field corresponds to a primitive type
31.225 + */
31.226 + // REMIND: deprecate?
31.227 + public boolean isPrimitive() {
31.228 + char tcode = signature.charAt(0);
31.229 + return ((tcode != 'L') && (tcode != '['));
31.230 + }
31.231 +
31.232 + /**
31.233 + * Returns boolean value indicating whether or not the serializable field
31.234 + * represented by this ObjectStreamField instance is unshared.
31.235 + *
31.236 + * @since 1.4
31.237 + */
31.238 + public boolean isUnshared() {
31.239 + return unshared;
31.240 + }
31.241 +
31.242 + /**
31.243 + * Compare this field with another <code>ObjectStreamField</code>. Return
31.244 + * -1 if this is smaller, 0 if equal, 1 if greater. Types that are
31.245 + * primitives are "smaller" than object types. If equal, the field names
31.246 + * are compared.
31.247 + */
31.248 + // REMIND: deprecate?
31.249 + public int compareTo(Object obj) {
31.250 + ObjectStreamField other = (ObjectStreamField) obj;
31.251 + boolean isPrim = isPrimitive();
31.252 + if (isPrim != other.isPrimitive()) {
31.253 + return isPrim ? -1 : 1;
31.254 + }
31.255 + return name.compareTo(other.name);
31.256 + }
31.257 +
31.258 + /**
31.259 + * Return a string that describes this field.
31.260 + */
31.261 + public String toString() {
31.262 + return signature + ' ' + name;
31.263 + }
31.264 +
31.265 + /**
31.266 + * Returns field represented by this ObjectStreamField, or null if
31.267 + * ObjectStreamField is not associated with an actual field.
31.268 + */
31.269 + Field getField() {
31.270 + return field;
31.271 + }
31.272 +
31.273 + /**
31.274 + * Returns JVM type signature of field (similar to getTypeString, except
31.275 + * that signature strings are returned for primitive fields as well).
31.276 + */
31.277 + String getSignature() {
31.278 + return signature;
31.279 + }
31.280 +
31.281 + /**
31.282 + * Returns JVM type signature for given class.
31.283 + */
31.284 + private static String getClassSignature(Class<?> cl) {
31.285 + StringBuilder sbuf = new StringBuilder();
31.286 + while (cl.isArray()) {
31.287 + sbuf.append('[');
31.288 + cl = cl.getComponentType();
31.289 + }
31.290 + if (cl.isPrimitive()) {
31.291 + if (cl == Integer.TYPE) {
31.292 + sbuf.append('I');
31.293 + } else if (cl == Byte.TYPE) {
31.294 + sbuf.append('B');
31.295 + } else if (cl == Long.TYPE) {
31.296 + sbuf.append('J');
31.297 + } else if (cl == Float.TYPE) {
31.298 + sbuf.append('F');
31.299 + } else if (cl == Double.TYPE) {
31.300 + sbuf.append('D');
31.301 + } else if (cl == Short.TYPE) {
31.302 + sbuf.append('S');
31.303 + } else if (cl == Character.TYPE) {
31.304 + sbuf.append('C');
31.305 + } else if (cl == Boolean.TYPE) {
31.306 + sbuf.append('Z');
31.307 + } else if (cl == Void.TYPE) {
31.308 + sbuf.append('V');
31.309 + } else {
31.310 + throw new InternalError();
31.311 + }
31.312 + } else {
31.313 + sbuf.append('L' + cl.getName().replace('.', '/') + ';');
31.314 + }
31.315 + return sbuf.toString();
31.316 + }
31.317 +}
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
32.2 +++ b/emul/compact/src/main/java/java/io/OptionalDataException.java Mon Feb 04 09:37:56 2013 +0100
32.3 @@ -0,0 +1,83 @@
32.4 +/*
32.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
32.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
32.7 + *
32.8 + * This code is free software; you can redistribute it and/or modify it
32.9 + * under the terms of the GNU General Public License version 2 only, as
32.10 + * published by the Free Software Foundation. Oracle designates this
32.11 + * particular file as subject to the "Classpath" exception as provided
32.12 + * by Oracle in the LICENSE file that accompanied this code.
32.13 + *
32.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
32.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
32.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
32.17 + * version 2 for more details (a copy is included in the LICENSE file that
32.18 + * accompanied this code).
32.19 + *
32.20 + * You should have received a copy of the GNU General Public License version
32.21 + * 2 along with this work; if not, write to the Free Software Foundation,
32.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
32.23 + *
32.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
32.25 + * or visit www.oracle.com if you need additional information or have any
32.26 + * questions.
32.27 + */
32.28 +package java.io;
32.29 +
32.30 +/**
32.31 + * Exception indicating the failure of an object read operation due to
32.32 + * unread primitive data, or the end of data belonging to a serialized
32.33 + * object in the stream. This exception may be thrown in two cases:
32.34 + *
32.35 + * <ul>
32.36 + * <li>An attempt was made to read an object when the next element in the
32.37 + * stream is primitive data. In this case, the OptionalDataException's
32.38 + * length field is set to the number of bytes of primitive data
32.39 + * immediately readable from the stream, and the eof field is set to
32.40 + * false.
32.41 + *
32.42 + * <li>An attempt was made to read past the end of data consumable by a
32.43 + * class-defined readObject or readExternal method. In this case, the
32.44 + * OptionalDataException's eof field is set to true, and the length field
32.45 + * is set to 0.
32.46 + * </ul>
32.47 + *
32.48 + * @author unascribed
32.49 + * @since JDK1.1
32.50 + */
32.51 +public class OptionalDataException extends ObjectStreamException {
32.52 +
32.53 + private static final long serialVersionUID = -8011121865681257820L;
32.54 +
32.55 + /*
32.56 + * Create an <code>OptionalDataException</code> with a length.
32.57 + */
32.58 + OptionalDataException(int len) {
32.59 + eof = false;
32.60 + length = len;
32.61 + }
32.62 +
32.63 + /*
32.64 + * Create an <code>OptionalDataException</code> signifying no
32.65 + * more primitive data is available.
32.66 + */
32.67 + OptionalDataException(boolean end) {
32.68 + length = 0;
32.69 + eof = end;
32.70 + }
32.71 +
32.72 + /**
32.73 + * The number of bytes of primitive data available to be read
32.74 + * in the current buffer.
32.75 + *
32.76 + * @serial
32.77 + */
32.78 + public int length;
32.79 +
32.80 + /**
32.81 + * True if there is no more data in the buffered part of the stream.
32.82 + *
32.83 + * @serial
32.84 + */
32.85 + public boolean eof;
32.86 +}
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
33.2 +++ b/emul/compact/src/main/java/java/io/OutputStream.java Mon Feb 04 09:37:56 2013 +0100
33.3 @@ -0,0 +1,154 @@
33.4 +/*
33.5 + * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.
33.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33.7 + *
33.8 + * This code is free software; you can redistribute it and/or modify it
33.9 + * under the terms of the GNU General Public License version 2 only, as
33.10 + * published by the Free Software Foundation. Oracle designates this
33.11 + * particular file as subject to the "Classpath" exception as provided
33.12 + * by Oracle in the LICENSE file that accompanied this code.
33.13 + *
33.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
33.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
33.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
33.17 + * version 2 for more details (a copy is included in the LICENSE file that
33.18 + * accompanied this code).
33.19 + *
33.20 + * You should have received a copy of the GNU General Public License version
33.21 + * 2 along with this work; if not, write to the Free Software Foundation,
33.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
33.23 + *
33.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
33.25 + * or visit www.oracle.com if you need additional information or have any
33.26 + * questions.
33.27 + */
33.28 +
33.29 +package java.io;
33.30 +
33.31 +/**
33.32 + * This abstract class is the superclass of all classes representing
33.33 + * an output stream of bytes. An output stream accepts output bytes
33.34 + * and sends them to some sink.
33.35 + * <p>
33.36 + * Applications that need to define a subclass of
33.37 + * <code>OutputStream</code> must always provide at least a method
33.38 + * that writes one byte of output.
33.39 + *
33.40 + * @author Arthur van Hoff
33.41 + * @see java.io.BufferedOutputStream
33.42 + * @see java.io.ByteArrayOutputStream
33.43 + * @see java.io.DataOutputStream
33.44 + * @see java.io.FilterOutputStream
33.45 + * @see java.io.InputStream
33.46 + * @see java.io.OutputStream#write(int)
33.47 + * @since JDK1.0
33.48 + */
33.49 +public abstract class OutputStream implements Closeable, Flushable {
33.50 + /**
33.51 + * Writes the specified byte to this output stream. The general
33.52 + * contract for <code>write</code> is that one byte is written
33.53 + * to the output stream. The byte to be written is the eight
33.54 + * low-order bits of the argument <code>b</code>. The 24
33.55 + * high-order bits of <code>b</code> are ignored.
33.56 + * <p>
33.57 + * Subclasses of <code>OutputStream</code> must provide an
33.58 + * implementation for this method.
33.59 + *
33.60 + * @param b the <code>byte</code>.
33.61 + * @exception IOException if an I/O error occurs. In particular,
33.62 + * an <code>IOException</code> may be thrown if the
33.63 + * output stream has been closed.
33.64 + */
33.65 + public abstract void write(int b) throws IOException;
33.66 +
33.67 + /**
33.68 + * Writes <code>b.length</code> bytes from the specified byte array
33.69 + * to this output stream. The general contract for <code>write(b)</code>
33.70 + * is that it should have exactly the same effect as the call
33.71 + * <code>write(b, 0, b.length)</code>.
33.72 + *
33.73 + * @param b the data.
33.74 + * @exception IOException if an I/O error occurs.
33.75 + * @see java.io.OutputStream#write(byte[], int, int)
33.76 + */
33.77 + public void write(byte b[]) throws IOException {
33.78 + write(b, 0, b.length);
33.79 + }
33.80 +
33.81 + /**
33.82 + * Writes <code>len</code> bytes from the specified byte array
33.83 + * starting at offset <code>off</code> to this output stream.
33.84 + * The general contract for <code>write(b, off, len)</code> is that
33.85 + * some of the bytes in the array <code>b</code> are written to the
33.86 + * output stream in order; element <code>b[off]</code> is the first
33.87 + * byte written and <code>b[off+len-1]</code> is the last byte written
33.88 + * by this operation.
33.89 + * <p>
33.90 + * The <code>write</code> method of <code>OutputStream</code> calls
33.91 + * the write method of one argument on each of the bytes to be
33.92 + * written out. Subclasses are encouraged to override this method and
33.93 + * provide a more efficient implementation.
33.94 + * <p>
33.95 + * If <code>b</code> is <code>null</code>, a
33.96 + * <code>NullPointerException</code> is thrown.
33.97 + * <p>
33.98 + * If <code>off</code> is negative, or <code>len</code> is negative, or
33.99 + * <code>off+len</code> is greater than the length of the array
33.100 + * <code>b</code>, then an <tt>IndexOutOfBoundsException</tt> is thrown.
33.101 + *
33.102 + * @param b the data.
33.103 + * @param off the start offset in the data.
33.104 + * @param len the number of bytes to write.
33.105 + * @exception IOException if an I/O error occurs. In particular,
33.106 + * an <code>IOException</code> is thrown if the output
33.107 + * stream is closed.
33.108 + */
33.109 + public void write(byte b[], int off, int len) throws IOException {
33.110 + if (b == null) {
33.111 + throw new NullPointerException();
33.112 + } else if ((off < 0) || (off > b.length) || (len < 0) ||
33.113 + ((off + len) > b.length) || ((off + len) < 0)) {
33.114 + throw new IndexOutOfBoundsException();
33.115 + } else if (len == 0) {
33.116 + return;
33.117 + }
33.118 + for (int i = 0 ; i < len ; i++) {
33.119 + write(b[off + i]);
33.120 + }
33.121 + }
33.122 +
33.123 + /**
33.124 + * Flushes this output stream and forces any buffered output bytes
33.125 + * to be written out. The general contract of <code>flush</code> is
33.126 + * that calling it is an indication that, if any bytes previously
33.127 + * written have been buffered by the implementation of the output
33.128 + * stream, such bytes should immediately be written to their
33.129 + * intended destination.
33.130 + * <p>
33.131 + * If the intended destination of this stream is an abstraction provided by
33.132 + * the underlying operating system, for example a file, then flushing the
33.133 + * stream guarantees only that bytes previously written to the stream are
33.134 + * passed to the operating system for writing; it does not guarantee that
33.135 + * they are actually written to a physical device such as a disk drive.
33.136 + * <p>
33.137 + * The <code>flush</code> method of <code>OutputStream</code> does nothing.
33.138 + *
33.139 + * @exception IOException if an I/O error occurs.
33.140 + */
33.141 + public void flush() throws IOException {
33.142 + }
33.143 +
33.144 + /**
33.145 + * Closes this output stream and releases any system resources
33.146 + * associated with this stream. The general contract of <code>close</code>
33.147 + * is that it closes the output stream. A closed stream cannot perform
33.148 + * output operations and cannot be reopened.
33.149 + * <p>
33.150 + * The <code>close</code> method of <code>OutputStream</code> does nothing.
33.151 + *
33.152 + * @exception IOException if an I/O error occurs.
33.153 + */
33.154 + public void close() throws IOException {
33.155 + }
33.156 +
33.157 +}
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
34.2 +++ b/emul/compact/src/main/java/java/io/StreamCorruptedException.java Mon Feb 04 09:37:56 2013 +0100
34.3 @@ -0,0 +1,54 @@
34.4 +/*
34.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
34.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
34.7 + *
34.8 + * This code is free software; you can redistribute it and/or modify it
34.9 + * under the terms of the GNU General Public License version 2 only, as
34.10 + * published by the Free Software Foundation. Oracle designates this
34.11 + * particular file as subject to the "Classpath" exception as provided
34.12 + * by Oracle in the LICENSE file that accompanied this code.
34.13 + *
34.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
34.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
34.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
34.17 + * version 2 for more details (a copy is included in the LICENSE file that
34.18 + * accompanied this code).
34.19 + *
34.20 + * You should have received a copy of the GNU General Public License version
34.21 + * 2 along with this work; if not, write to the Free Software Foundation,
34.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
34.23 + *
34.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
34.25 + * or visit www.oracle.com if you need additional information or have any
34.26 + * questions.
34.27 + */
34.28 +
34.29 +package java.io;
34.30 +
34.31 +/**
34.32 + * Thrown when control information that was read from an object stream
34.33 + * violates internal consistency checks.
34.34 + *
34.35 + * @author unascribed
34.36 + * @since JDK1.1
34.37 + */
34.38 +public class StreamCorruptedException extends ObjectStreamException {
34.39 +
34.40 + private static final long serialVersionUID = 8983558202217591746L;
34.41 +
34.42 + /**
34.43 + * Create a StreamCorruptedException and list a reason why thrown.
34.44 + *
34.45 + * @param reason String describing the reason for the exception.
34.46 + */
34.47 + public StreamCorruptedException(String reason) {
34.48 + super(reason);
34.49 + }
34.50 +
34.51 + /**
34.52 + * Create a StreamCorruptedException and list no reason why thrown.
34.53 + */
34.54 + public StreamCorruptedException() {
34.55 + super();
34.56 + }
34.57 +}
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
35.2 +++ b/emul/compact/src/main/java/java/io/WriteAbortedException.java Mon Feb 04 09:37:56 2013 +0100
35.3 @@ -0,0 +1,93 @@
35.4 +/*
35.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
35.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
35.7 + *
35.8 + * This code is free software; you can redistribute it and/or modify it
35.9 + * under the terms of the GNU General Public License version 2 only, as
35.10 + * published by the Free Software Foundation. Oracle designates this
35.11 + * particular file as subject to the "Classpath" exception as provided
35.12 + * by Oracle in the LICENSE file that accompanied this code.
35.13 + *
35.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
35.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
35.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
35.17 + * version 2 for more details (a copy is included in the LICENSE file that
35.18 + * accompanied this code).
35.19 + *
35.20 + * You should have received a copy of the GNU General Public License version
35.21 + * 2 along with this work; if not, write to the Free Software Foundation,
35.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
35.23 + *
35.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
35.25 + * or visit www.oracle.com if you need additional information or have any
35.26 + * questions.
35.27 + */
35.28 +
35.29 +package java.io;
35.30 +
35.31 +/**
35.32 + * Signals that one of the ObjectStreamExceptions was thrown during a
35.33 + * write operation. Thrown during a read operation when one of the
35.34 + * ObjectStreamExceptions was thrown during a write operation. The
35.35 + * exception that terminated the write can be found in the detail
35.36 + * field. The stream is reset to it's initial state and all references
35.37 + * to objects already deserialized are discarded.
35.38 + *
35.39 + * <p>As of release 1.4, this exception has been retrofitted to conform to
35.40 + * the general purpose exception-chaining mechanism. The "exception causing
35.41 + * the abort" that is provided at construction time and
35.42 + * accessed via the public {@link #detail} field is now known as the
35.43 + * <i>cause</i>, and may be accessed via the {@link Throwable#getCause()}
35.44 + * method, as well as the aforementioned "legacy field."
35.45 + *
35.46 + * @author unascribed
35.47 + * @since JDK1.1
35.48 + */
35.49 +public class WriteAbortedException extends ObjectStreamException {
35.50 + private static final long serialVersionUID = -3326426625597282442L;
35.51 +
35.52 + /**
35.53 + * Exception that was caught while writing the ObjectStream.
35.54 + *
35.55 + * <p>This field predates the general-purpose exception chaining facility.
35.56 + * The {@link Throwable#getCause()} method is now the preferred means of
35.57 + * obtaining this information.
35.58 + *
35.59 + * @serial
35.60 + */
35.61 + public Exception detail;
35.62 +
35.63 + /**
35.64 + * Constructs a WriteAbortedException with a string describing
35.65 + * the exception and the exception causing the abort.
35.66 + * @param s String describing the exception.
35.67 + * @param ex Exception causing the abort.
35.68 + */
35.69 + public WriteAbortedException(String s, Exception ex) {
35.70 + super(s);
35.71 + initCause(null); // Disallow subsequent initCause
35.72 + detail = ex;
35.73 + }
35.74 +
35.75 + /**
35.76 + * Produce the message and include the message from the nested
35.77 + * exception, if there is one.
35.78 + */
35.79 + public String getMessage() {
35.80 + if (detail == null)
35.81 + return super.getMessage();
35.82 + else
35.83 + return super.getMessage() + "; " + detail.toString();
35.84 + }
35.85 +
35.86 + /**
35.87 + * Returns the exception that terminated the operation (the <i>cause</i>).
35.88 + *
35.89 + * @return the exception that terminated the operation (the <i>cause</i>),
35.90 + * which may be null.
35.91 + * @since 1.4
35.92 + */
35.93 + public Throwable getCause() {
35.94 + return detail;
35.95 + }
35.96 +}
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
36.2 +++ b/emul/compact/src/main/java/java/lang/ref/PhantomReference.java Mon Feb 04 09:37:56 2013 +0100
36.3 @@ -0,0 +1,83 @@
36.4 +/*
36.5 + * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
36.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
36.7 + *
36.8 + * This code is free software; you can redistribute it and/or modify it
36.9 + * under the terms of the GNU General Public License version 2 only, as
36.10 + * published by the Free Software Foundation. Oracle designates this
36.11 + * particular file as subject to the "Classpath" exception as provided
36.12 + * by Oracle in the LICENSE file that accompanied this code.
36.13 + *
36.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
36.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
36.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
36.17 + * version 2 for more details (a copy is included in the LICENSE file that
36.18 + * accompanied this code).
36.19 + *
36.20 + * You should have received a copy of the GNU General Public License version
36.21 + * 2 along with this work; if not, write to the Free Software Foundation,
36.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
36.23 + *
36.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
36.25 + * or visit www.oracle.com if you need additional information or have any
36.26 + * questions.
36.27 + */
36.28 +
36.29 +package java.lang.ref;
36.30 +
36.31 +
36.32 +/**
36.33 + * Phantom reference objects, which are enqueued after the collector
36.34 + * determines that their referents may otherwise be reclaimed. Phantom
36.35 + * references are most often used for scheduling pre-mortem cleanup actions in
36.36 + * a more flexible way than is possible with the Java finalization mechanism.
36.37 + *
36.38 + * <p> If the garbage collector determines at a certain point in time that the
36.39 + * referent of a phantom reference is <a
36.40 + * href="package-summary.html#reachability">phantom reachable</a>, then at that
36.41 + * time or at some later time it will enqueue the reference.
36.42 + *
36.43 + * <p> In order to ensure that a reclaimable object remains so, the referent of
36.44 + * a phantom reference may not be retrieved: The <code>get</code> method of a
36.45 + * phantom reference always returns <code>null</code>.
36.46 + *
36.47 + * <p> Unlike soft and weak references, phantom references are not
36.48 + * automatically cleared by the garbage collector as they are enqueued. An
36.49 + * object that is reachable via phantom references will remain so until all
36.50 + * such references are cleared or themselves become unreachable.
36.51 + *
36.52 + * @author Mark Reinhold
36.53 + * @since 1.2
36.54 + */
36.55 +
36.56 +public class PhantomReference<T> extends Reference<T> {
36.57 +
36.58 + /**
36.59 + * Returns this reference object's referent. Because the referent of a
36.60 + * phantom reference is always inaccessible, this method always returns
36.61 + * <code>null</code>.
36.62 + *
36.63 + * @return <code>null</code>
36.64 + */
36.65 + public T get() {
36.66 + return null;
36.67 + }
36.68 +
36.69 + /**
36.70 + * Creates a new phantom reference that refers to the given object and
36.71 + * is registered with the given queue.
36.72 + *
36.73 + * <p> It is possible to create a phantom reference with a <tt>null</tt>
36.74 + * queue, but such a reference is completely useless: Its <tt>get</tt>
36.75 + * method will always return null and, since it does not have a queue, it
36.76 + * will never be enqueued.
36.77 + *
36.78 + * @param referent the object the new phantom reference will refer to
36.79 + * @param q the queue with which the reference is to be registered,
36.80 + * or <tt>null</tt> if registration is not required
36.81 + */
36.82 + public PhantomReference(T referent, ReferenceQueue<? super T> q) {
36.83 + super(referent, q);
36.84 + }
36.85 +
36.86 +}
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
37.2 +++ b/emul/compact/src/main/java/java/lang/ref/Reference.java Mon Feb 04 09:37:56 2013 +0100
37.3 @@ -0,0 +1,185 @@
37.4 +/*
37.5 + * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
37.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
37.7 + *
37.8 + * This code is free software; you can redistribute it and/or modify it
37.9 + * under the terms of the GNU General Public License version 2 only, as
37.10 + * published by the Free Software Foundation. Oracle designates this
37.11 + * particular file as subject to the "Classpath" exception as provided
37.12 + * by Oracle in the LICENSE file that accompanied this code.
37.13 + *
37.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
37.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
37.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
37.17 + * version 2 for more details (a copy is included in the LICENSE file that
37.18 + * accompanied this code).
37.19 + *
37.20 + * You should have received a copy of the GNU General Public License version
37.21 + * 2 along with this work; if not, write to the Free Software Foundation,
37.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
37.23 + *
37.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
37.25 + * or visit www.oracle.com if you need additional information or have any
37.26 + * questions.
37.27 + */
37.28 +
37.29 +package java.lang.ref;
37.30 +
37.31 +
37.32 +/**
37.33 + * Abstract base class for reference objects. This class defines the
37.34 + * operations common to all reference objects. Because reference objects are
37.35 + * implemented in close cooperation with the garbage collector, this class may
37.36 + * not be subclassed directly.
37.37 + *
37.38 + * @author Mark Reinhold
37.39 + * @since 1.2
37.40 + */
37.41 +
37.42 +public abstract class Reference<T> {
37.43 +
37.44 + /* A Reference instance is in one of four possible internal states:
37.45 + *
37.46 + * Active: Subject to special treatment by the garbage collector. Some
37.47 + * time after the collector detects that the reachability of the
37.48 + * referent has changed to the appropriate state, it changes the
37.49 + * instance's state to either Pending or Inactive, depending upon
37.50 + * whether or not the instance was registered with a queue when it was
37.51 + * created. In the former case it also adds the instance to the
37.52 + * pending-Reference list. Newly-created instances are Active.
37.53 + *
37.54 + * Pending: An element of the pending-Reference list, waiting to be
37.55 + * enqueued by the Reference-handler thread. Unregistered instances
37.56 + * are never in this state.
37.57 + *
37.58 + * Enqueued: An element of the queue with which the instance was
37.59 + * registered when it was created. When an instance is removed from
37.60 + * its ReferenceQueue, it is made Inactive. Unregistered instances are
37.61 + * never in this state.
37.62 + *
37.63 + * Inactive: Nothing more to do. Once an instance becomes Inactive its
37.64 + * state will never change again.
37.65 + *
37.66 + * The state is encoded in the queue and next fields as follows:
37.67 + *
37.68 + * Active: queue = ReferenceQueue with which instance is registered, or
37.69 + * ReferenceQueue.NULL if it was not registered with a queue; next =
37.70 + * null.
37.71 + *
37.72 + * Pending: queue = ReferenceQueue with which instance is registered;
37.73 + * next = Following instance in queue, or this if at end of list.
37.74 + *
37.75 + * Enqueued: queue = ReferenceQueue.ENQUEUED; next = Following instance
37.76 + * in queue, or this if at end of list.
37.77 + *
37.78 + * Inactive: queue = ReferenceQueue.NULL; next = this.
37.79 + *
37.80 + * With this scheme the collector need only examine the next field in order
37.81 + * to determine whether a Reference instance requires special treatment: If
37.82 + * the next field is null then the instance is active; if it is non-null,
37.83 + * then the collector should treat the instance normally.
37.84 + *
37.85 + * To ensure that concurrent collector can discover active Reference
37.86 + * objects without interfering with application threads that may apply
37.87 + * the enqueue() method to those objects, collectors should link
37.88 + * discovered objects through the discovered field.
37.89 + */
37.90 +
37.91 + private T referent; /* Treated specially by GC */
37.92 +
37.93 + ReferenceQueue<? super T> queue;
37.94 +
37.95 + Reference next;
37.96 + transient private Reference<T> discovered; /* used by VM */
37.97 +
37.98 +
37.99 + /* Object used to synchronize with the garbage collector. The collector
37.100 + * must acquire this lock at the beginning of each collection cycle. It is
37.101 + * therefore critical that any code holding this lock complete as quickly
37.102 + * as possible, allocate no new objects, and avoid calling user code.
37.103 + */
37.104 + static private class Lock { };
37.105 + private static Lock lock = new Lock();
37.106 +
37.107 +
37.108 + /* List of References waiting to be enqueued. The collector adds
37.109 + * References to this list, while the Reference-handler thread removes
37.110 + * them. This list is protected by the above lock object.
37.111 + */
37.112 + private static Reference pending = null;
37.113 +
37.114 +
37.115 +
37.116 + /* -- Referent accessor and setters -- */
37.117 +
37.118 + /**
37.119 + * Returns this reference object's referent. If this reference object has
37.120 + * been cleared, either by the program or by the garbage collector, then
37.121 + * this method returns <code>null</code>.
37.122 + *
37.123 + * @return The object to which this reference refers, or
37.124 + * <code>null</code> if this reference object has been cleared
37.125 + */
37.126 + public T get() {
37.127 + return this.referent;
37.128 + }
37.129 +
37.130 + /**
37.131 + * Clears this reference object. Invoking this method will not cause this
37.132 + * object to be enqueued.
37.133 + *
37.134 + * <p> This method is invoked only by Java code; when the garbage collector
37.135 + * clears references it does so directly, without invoking this method.
37.136 + */
37.137 + public void clear() {
37.138 + this.referent = null;
37.139 + }
37.140 +
37.141 +
37.142 + /* -- Queue operations -- */
37.143 +
37.144 + /**
37.145 + * Tells whether or not this reference object has been enqueued, either by
37.146 + * the program or by the garbage collector. If this reference object was
37.147 + * not registered with a queue when it was created, then this method will
37.148 + * always return <code>false</code>.
37.149 + *
37.150 + * @return <code>true</code> if and only if this reference object has
37.151 + * been enqueued
37.152 + */
37.153 + public boolean isEnqueued() {
37.154 + /* In terms of the internal states, this predicate actually tests
37.155 + whether the instance is either Pending or Enqueued */
37.156 + synchronized (this) {
37.157 + return (this.queue != ReferenceQueue.NULL) && (this.next != null);
37.158 + }
37.159 + }
37.160 +
37.161 + /**
37.162 + * Adds this reference object to the queue with which it is registered,
37.163 + * if any.
37.164 + *
37.165 + * <p> This method is invoked only by Java code; when the garbage collector
37.166 + * enqueues references it does so directly, without invoking this method.
37.167 + *
37.168 + * @return <code>true</code> if this reference object was successfully
37.169 + * enqueued; <code>false</code> if it was already enqueued or if
37.170 + * it was not registered with a queue when it was created
37.171 + */
37.172 + public boolean enqueue() {
37.173 + return this.queue.enqueue(this);
37.174 + }
37.175 +
37.176 +
37.177 + /* -- Constructors -- */
37.178 +
37.179 + Reference(T referent) {
37.180 + this(referent, null);
37.181 + }
37.182 +
37.183 + Reference(T referent, ReferenceQueue<? super T> queue) {
37.184 + this.referent = referent;
37.185 + this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
37.186 + }
37.187 +
37.188 +}
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
38.2 +++ b/emul/compact/src/main/java/java/lang/ref/ReferenceQueue.java Mon Feb 04 09:37:56 2013 +0100
38.3 @@ -0,0 +1,148 @@
38.4 +/*
38.5 + * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved.
38.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
38.7 + *
38.8 + * This code is free software; you can redistribute it and/or modify it
38.9 + * under the terms of the GNU General Public License version 2 only, as
38.10 + * published by the Free Software Foundation. Oracle designates this
38.11 + * particular file as subject to the "Classpath" exception as provided
38.12 + * by Oracle in the LICENSE file that accompanied this code.
38.13 + *
38.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
38.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
38.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
38.17 + * version 2 for more details (a copy is included in the LICENSE file that
38.18 + * accompanied this code).
38.19 + *
38.20 + * You should have received a copy of the GNU General Public License version
38.21 + * 2 along with this work; if not, write to the Free Software Foundation,
38.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
38.23 + *
38.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
38.25 + * or visit www.oracle.com if you need additional information or have any
38.26 + * questions.
38.27 + */
38.28 +
38.29 +package java.lang.ref;
38.30 +
38.31 +/**
38.32 + * Reference queues, to which registered reference objects are appended by the
38.33 + * garbage collector after the appropriate reachability changes are detected.
38.34 + *
38.35 + * @author Mark Reinhold
38.36 + * @since 1.2
38.37 + */
38.38 +
38.39 +public class ReferenceQueue<T> {
38.40 +
38.41 + /**
38.42 + * Constructs a new reference-object queue.
38.43 + */
38.44 + public ReferenceQueue() { }
38.45 +
38.46 + private static class Null extends ReferenceQueue {
38.47 + boolean enqueue(Reference r) {
38.48 + return false;
38.49 + }
38.50 + }
38.51 +
38.52 + static ReferenceQueue NULL = new Null();
38.53 + static ReferenceQueue ENQUEUED = new Null();
38.54 +
38.55 + static private class Lock { };
38.56 + private Lock lock = new Lock();
38.57 + private volatile Reference<? extends T> head = null;
38.58 + private long queueLength = 0;
38.59 +
38.60 + boolean enqueue(Reference<? extends T> r) { /* Called only by Reference class */
38.61 + synchronized (r) {
38.62 + if (r.queue == ENQUEUED) return false;
38.63 + synchronized (lock) {
38.64 + r.queue = ENQUEUED;
38.65 + r.next = (head == null) ? r : head;
38.66 + head = r;
38.67 + queueLength++;
38.68 + lock.notifyAll();
38.69 + return true;
38.70 + }
38.71 + }
38.72 + }
38.73 +
38.74 + private Reference<? extends T> reallyPoll() { /* Must hold lock */
38.75 + if (head != null) {
38.76 + Reference<? extends T> r = head;
38.77 + head = (r.next == r) ? null : r.next;
38.78 + r.queue = NULL;
38.79 + r.next = r;
38.80 + queueLength--;
38.81 + return r;
38.82 + }
38.83 + return null;
38.84 + }
38.85 +
38.86 + /**
38.87 + * Polls this queue to see if a reference object is available. If one is
38.88 + * available without further delay then it is removed from the queue and
38.89 + * returned. Otherwise this method immediately returns <tt>null</tt>.
38.90 + *
38.91 + * @return A reference object, if one was immediately available,
38.92 + * otherwise <code>null</code>
38.93 + */
38.94 + public Reference<? extends T> poll() {
38.95 + if (head == null)
38.96 + return null;
38.97 + synchronized (lock) {
38.98 + return reallyPoll();
38.99 + }
38.100 + }
38.101 +
38.102 + /**
38.103 + * Removes the next reference object in this queue, blocking until either
38.104 + * one becomes available or the given timeout period expires.
38.105 + *
38.106 + * <p> This method does not offer real-time guarantees: It schedules the
38.107 + * timeout as if by invoking the {@link Object#wait(long)} method.
38.108 + *
38.109 + * @param timeout If positive, block for up to <code>timeout</code>
38.110 + * milliseconds while waiting for a reference to be
38.111 + * added to this queue. If zero, block indefinitely.
38.112 + *
38.113 + * @return A reference object, if one was available within the specified
38.114 + * timeout period, otherwise <code>null</code>
38.115 + *
38.116 + * @throws IllegalArgumentException
38.117 + * If the value of the timeout argument is negative
38.118 + *
38.119 + * @throws InterruptedException
38.120 + * If the timeout wait is interrupted
38.121 + */
38.122 + public Reference<? extends T> remove(long timeout)
38.123 + throws IllegalArgumentException, InterruptedException
38.124 + {
38.125 + if (timeout < 0) {
38.126 + throw new IllegalArgumentException("Negative timeout value");
38.127 + }
38.128 + synchronized (lock) {
38.129 + Reference<? extends T> r = reallyPoll();
38.130 + if (r != null) return r;
38.131 + for (;;) {
38.132 + lock.wait(timeout);
38.133 + r = reallyPoll();
38.134 + if (r != null) return r;
38.135 + if (timeout != 0) return null;
38.136 + }
38.137 + }
38.138 + }
38.139 +
38.140 + /**
38.141 + * Removes the next reference object in this queue, blocking until one
38.142 + * becomes available.
38.143 + *
38.144 + * @return A reference object, blocking until one becomes available
38.145 + * @throws InterruptedException If the wait is interrupted
38.146 + */
38.147 + public Reference<? extends T> remove() throws InterruptedException {
38.148 + return remove(0);
38.149 + }
38.150 +
38.151 +}
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
39.2 +++ b/emul/compact/src/main/java/java/lang/ref/SoftReference.java Mon Feb 04 09:37:56 2013 +0100
39.3 @@ -0,0 +1,118 @@
39.4 +/*
39.5 + * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
39.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
39.7 + *
39.8 + * This code is free software; you can redistribute it and/or modify it
39.9 + * under the terms of the GNU General Public License version 2 only, as
39.10 + * published by the Free Software Foundation. Oracle designates this
39.11 + * particular file as subject to the "Classpath" exception as provided
39.12 + * by Oracle in the LICENSE file that accompanied this code.
39.13 + *
39.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
39.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
39.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
39.17 + * version 2 for more details (a copy is included in the LICENSE file that
39.18 + * accompanied this code).
39.19 + *
39.20 + * You should have received a copy of the GNU General Public License version
39.21 + * 2 along with this work; if not, write to the Free Software Foundation,
39.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
39.23 + *
39.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
39.25 + * or visit www.oracle.com if you need additional information or have any
39.26 + * questions.
39.27 + */
39.28 +
39.29 +package java.lang.ref;
39.30 +
39.31 +
39.32 +/**
39.33 + * Soft reference objects, which are cleared at the discretion of the garbage
39.34 + * collector in response to memory demand. Soft references are most often used
39.35 + * to implement memory-sensitive caches.
39.36 + *
39.37 + * <p> Suppose that the garbage collector determines at a certain point in time
39.38 + * that an object is <a href="package-summary.html#reachability">softly
39.39 + * reachable</a>. At that time it may choose to clear atomically all soft
39.40 + * references to that object and all soft references to any other
39.41 + * softly-reachable objects from which that object is reachable through a chain
39.42 + * of strong references. At the same time or at some later time it will
39.43 + * enqueue those newly-cleared soft references that are registered with
39.44 + * reference queues.
39.45 + *
39.46 + * <p> All soft references to softly-reachable objects are guaranteed to have
39.47 + * been cleared before the virtual machine throws an
39.48 + * <code>OutOfMemoryError</code>. Otherwise no constraints are placed upon the
39.49 + * time at which a soft reference will be cleared or the order in which a set
39.50 + * of such references to different objects will be cleared. Virtual machine
39.51 + * implementations are, however, encouraged to bias against clearing
39.52 + * recently-created or recently-used soft references.
39.53 + *
39.54 + * <p> Direct instances of this class may be used to implement simple caches;
39.55 + * this class or derived subclasses may also be used in larger data structures
39.56 + * to implement more sophisticated caches. As long as the referent of a soft
39.57 + * reference is strongly reachable, that is, is actually in use, the soft
39.58 + * reference will not be cleared. Thus a sophisticated cache can, for example,
39.59 + * prevent its most recently used entries from being discarded by keeping
39.60 + * strong referents to those entries, leaving the remaining entries to be
39.61 + * discarded at the discretion of the garbage collector.
39.62 + *
39.63 + * @author Mark Reinhold
39.64 + * @since 1.2
39.65 + */
39.66 +
39.67 +public class SoftReference<T> extends Reference<T> {
39.68 +
39.69 + /**
39.70 + * Timestamp clock, updated by the garbage collector
39.71 + */
39.72 + static private long clock;
39.73 +
39.74 + /**
39.75 + * Timestamp updated by each invocation of the get method. The VM may use
39.76 + * this field when selecting soft references to be cleared, but it is not
39.77 + * required to do so.
39.78 + */
39.79 + private long timestamp;
39.80 +
39.81 + /**
39.82 + * Creates a new soft reference that refers to the given object. The new
39.83 + * reference is not registered with any queue.
39.84 + *
39.85 + * @param referent object the new soft reference will refer to
39.86 + */
39.87 + public SoftReference(T referent) {
39.88 + super(referent);
39.89 + this.timestamp = clock;
39.90 + }
39.91 +
39.92 + /**
39.93 + * Creates a new soft reference that refers to the given object and is
39.94 + * registered with the given queue.
39.95 + *
39.96 + * @param referent object the new soft reference will refer to
39.97 + * @param q the queue with which the reference is to be registered,
39.98 + * or <tt>null</tt> if registration is not required
39.99 + *
39.100 + */
39.101 + public SoftReference(T referent, ReferenceQueue<? super T> q) {
39.102 + super(referent, q);
39.103 + this.timestamp = clock;
39.104 + }
39.105 +
39.106 + /**
39.107 + * Returns this reference object's referent. If this reference object has
39.108 + * been cleared, either by the program or by the garbage collector, then
39.109 + * this method returns <code>null</code>.
39.110 + *
39.111 + * @return The object to which this reference refers, or
39.112 + * <code>null</code> if this reference object has been cleared
39.113 + */
39.114 + public T get() {
39.115 + T o = super.get();
39.116 + if (o != null && this.timestamp != clock)
39.117 + this.timestamp = clock;
39.118 + return o;
39.119 + }
39.120 +
39.121 +}
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
40.2 +++ b/emul/compact/src/main/java/java/lang/ref/WeakReference.java Mon Feb 04 09:37:56 2013 +0100
40.3 @@ -0,0 +1,72 @@
40.4 +/*
40.5 + * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
40.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
40.7 + *
40.8 + * This code is free software; you can redistribute it and/or modify it
40.9 + * under the terms of the GNU General Public License version 2 only, as
40.10 + * published by the Free Software Foundation. Oracle designates this
40.11 + * particular file as subject to the "Classpath" exception as provided
40.12 + * by Oracle in the LICENSE file that accompanied this code.
40.13 + *
40.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
40.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
40.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
40.17 + * version 2 for more details (a copy is included in the LICENSE file that
40.18 + * accompanied this code).
40.19 + *
40.20 + * You should have received a copy of the GNU General Public License version
40.21 + * 2 along with this work; if not, write to the Free Software Foundation,
40.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
40.23 + *
40.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
40.25 + * or visit www.oracle.com if you need additional information or have any
40.26 + * questions.
40.27 + */
40.28 +
40.29 +package java.lang.ref;
40.30 +
40.31 +
40.32 +/**
40.33 + * Weak reference objects, which do not prevent their referents from being
40.34 + * made finalizable, finalized, and then reclaimed. Weak references are most
40.35 + * often used to implement canonicalizing mappings.
40.36 + *
40.37 + * <p> Suppose that the garbage collector determines at a certain point in time
40.38 + * that an object is <a href="package-summary.html#reachability">weakly
40.39 + * reachable</a>. At that time it will atomically clear all weak references to
40.40 + * that object and all weak references to any other weakly-reachable objects
40.41 + * from which that object is reachable through a chain of strong and soft
40.42 + * references. At the same time it will declare all of the formerly
40.43 + * weakly-reachable objects to be finalizable. At the same time or at some
40.44 + * later time it will enqueue those newly-cleared weak references that are
40.45 + * registered with reference queues.
40.46 + *
40.47 + * @author Mark Reinhold
40.48 + * @since 1.2
40.49 + */
40.50 +
40.51 +public class WeakReference<T> extends Reference<T> {
40.52 +
40.53 + /**
40.54 + * Creates a new weak reference that refers to the given object. The new
40.55 + * reference is not registered with any queue.
40.56 + *
40.57 + * @param referent object the new weak reference will refer to
40.58 + */
40.59 + public WeakReference(T referent) {
40.60 + super(referent);
40.61 + }
40.62 +
40.63 + /**
40.64 + * Creates a new weak reference that refers to the given object and is
40.65 + * registered with the given queue.
40.66 + *
40.67 + * @param referent object the new weak reference will refer to
40.68 + * @param q the queue with which the reference is to be registered,
40.69 + * or <tt>null</tt> if registration is not required
40.70 + */
40.71 + public WeakReference(T referent, ReferenceQueue<? super T> q) {
40.72 + super(referent, q);
40.73 + }
40.74 +
40.75 +}
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
41.2 +++ b/emul/compact/src/main/java/java/lang/ref/package.html Mon Feb 04 09:37:56 2013 +0100
41.3 @@ -0,0 +1,147 @@
41.4 +<!--
41.5 + Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved.
41.6 + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
41.7 +
41.8 + This code is free software; you can redistribute it and/or modify it
41.9 + under the terms of the GNU General Public License version 2 only, as
41.10 + published by the Free Software Foundation. Oracle designates this
41.11 + particular file as subject to the "Classpath" exception as provided
41.12 + by Oracle in the LICENSE file that accompanied this code.
41.13 +
41.14 + This code is distributed in the hope that it will be useful, but WITHOUT
41.15 + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
41.16 + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
41.17 + version 2 for more details (a copy is included in the LICENSE file that
41.18 + accompanied this code).
41.19 +
41.20 + You should have received a copy of the GNU General Public License version
41.21 + 2 along with this work; if not, write to the Free Software Foundation,
41.22 + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
41.23 +
41.24 + Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
41.25 + or visit www.oracle.com if you need additional information or have any
41.26 + questions.
41.27 +-->
41.28 +
41.29 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
41.30 +<html>
41.31 +<body bgcolor="white">
41.32 +
41.33 +
41.34 +Provides reference-object classes, which support a limited degree of
41.35 +interaction with the garbage collector. A program may use a reference object
41.36 +to maintain a reference to some other object in such a way that the latter
41.37 +object may still be reclaimed by the collector. A program may also arrange to
41.38 +be notified some time after the collector has determined that the reachability
41.39 +of a given object has changed.
41.40 +
41.41 +
41.42 +<h2>Package Specification</h2>
41.43 +
41.44 +A <em>reference object</em> encapsulates a reference to some other object so
41.45 +that the reference itself may be examined and manipulated like any other
41.46 +object. Three types of reference objects are provided, each weaker than the
41.47 +last: <em>soft</em>, <em>weak</em>, and <em>phantom</em>. Each type
41.48 +corresponds to a different level of reachability, as defined below. Soft
41.49 +references are for implementing memory-sensitive caches, weak references are
41.50 +for implementing canonicalizing mappings that do not prevent their keys (or
41.51 +values) from being reclaimed, and phantom references are for scheduling
41.52 +pre-mortem cleanup actions in a more flexible way than is possible with the
41.53 +Java finalization mechanism.
41.54 +
41.55 +<p> Each reference-object type is implemented by a subclass of the abstract
41.56 +base <code>{@link java.lang.ref.Reference}</code> class. An instance of one of
41.57 +these subclasses encapsulates a single reference to a particular object, called
41.58 +the <em>referent</em>. Every reference object provides methods for getting and
41.59 +clearing the reference. Aside from the clearing operation reference objects
41.60 +are otherwise immutable, so no <code>set</code> operation is provided. A
41.61 +program may further subclass these subclasses, adding whatever fields and
41.62 +methods are required for its purposes, or it may use these subclasses without
41.63 +change.
41.64 +
41.65 +
41.66 +<h3>Notification</h3>
41.67 +
41.68 +A program may request to be notified of changes in an object's reachability by
41.69 +<em>registering</em> an appropriate reference object with a <em>reference
41.70 +queue</em> at the time the reference object is created. Some time after the
41.71 +garbage collector determines that the reachability of the referent has changed
41.72 +to the value corresponding to the type of the reference, it will add the
41.73 +reference to the associated queue. At this point, the reference is considered
41.74 +to be <em>enqueued</em>. The program may remove references from a queue either
41.75 +by polling or by blocking until a reference becomes available. Reference
41.76 +queues are implemented by the <code>{@link java.lang.ref.ReferenceQueue}</code>
41.77 +class.
41.78 +
41.79 +<p> The relationship between a registered reference object and its queue is
41.80 +one-sided. That is, a queue does not keep track of the references that are
41.81 +registered with it. If a registered reference becomes unreachable itself, then
41.82 +it will never be enqueued. It is the responsibility of the program using
41.83 +reference objects to ensure that the objects remain reachable for as long as
41.84 +the program is interested in their referents.
41.85 +
41.86 +<p> While some programs will choose to dedicate a thread to removing reference
41.87 +objects from one or more queues and processing them, this is by no means
41.88 +necessary. A tactic that often works well is to examine a reference queue in
41.89 +the course of performing some other fairly-frequent action. For example, a
41.90 +hashtable that uses weak references to implement weak keys could poll its
41.91 +reference queue each time the table is accessed. This is how the <code>{@link
41.92 +java.util.WeakHashMap}</code> class works. Because the <code>{@link
41.93 +java.lang.ref.ReferenceQueue#poll ReferenceQueue.poll}</code> method simply
41.94 +checks an internal data structure, this check will add little overhead to the
41.95 +hashtable access methods.
41.96 +
41.97 +
41.98 +<h3>Automatically-cleared references</h3>
41.99 +
41.100 +Soft and weak references are automatically cleared by the collector before
41.101 +being added to the queues with which they are registered, if any. Therefore
41.102 +soft and weak references need not be registered with a queue in order to be
41.103 +useful, while phantom references do. An object that is reachable via phantom
41.104 +references will remain so until all such references are cleared or themselves
41.105 +become unreachable.
41.106 +
41.107 +
41.108 +<a name="reachability"></a>
41.109 +<h3>Reachability</h3>
41.110 +
41.111 +Going from strongest to weakest, the different levels of reachability reflect
41.112 +the life cycle of an object. They are operationally defined as follows:
41.113 +
41.114 +<ul>
41.115 +
41.116 +<li> An object is <em>strongly reachable</em> if it can be reached by some
41.117 +thread without traversing any reference objects. A newly-created object is
41.118 +strongly reachable by the thread that created it.
41.119 +
41.120 +<li> An object is <em>softly reachable</em> if it is not strongly reachable but
41.121 +can be reached by traversing a soft reference.
41.122 +
41.123 +<li> An object is <em>weakly reachable</em> if it is neither strongly nor
41.124 +softly reachable but can be reached by traversing a weak reference. When the
41.125 +weak references to a weakly-reachable object are cleared, the object becomes
41.126 +eligible for finalization.
41.127 +
41.128 +<li> An object is <em>phantom reachable</em> if it is neither strongly, softly,
41.129 +nor weakly reachable, it has been finalized, and some phantom reference refers
41.130 +to it.
41.131 +
41.132 +<li> Finally, an object is <em>unreachable</em>, and therefore eligible for
41.133 +reclamation, when it is not reachable in any of the above ways.
41.134 +
41.135 +</ul>
41.136 +
41.137 +
41.138 +@author Mark Reinhold
41.139 +@since 1.2
41.140 +
41.141 +<!--
41.142 +<h2>Related Documentation</h2>
41.143 +
41.144 +For overviews, tutorials, examples, guides, and tool documentation, please see:
41.145 +<ul>
41.146 + <li><a href="">##### REFER TO NON-SPEC DOCUMENTATION HERE #####</a>
41.147 +</ul>
41.148 +-->
41.149 +</body>
41.150 +</html>
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
42.2 +++ b/emul/compact/src/main/java/java/util/EventListenerProxy.java Mon Feb 04 09:37:56 2013 +0100
42.3 @@ -0,0 +1,75 @@
42.4 +/*
42.5 + * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved.
42.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
42.7 + *
42.8 + * This code is free software; you can redistribute it and/or modify it
42.9 + * under the terms of the GNU General Public License version 2 only, as
42.10 + * published by the Free Software Foundation. Oracle designates this
42.11 + * particular file as subject to the "Classpath" exception as provided
42.12 + * by Oracle in the LICENSE file that accompanied this code.
42.13 + *
42.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
42.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
42.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
42.17 + * version 2 for more details (a copy is included in the LICENSE file that
42.18 + * accompanied this code).
42.19 + *
42.20 + * You should have received a copy of the GNU General Public License version
42.21 + * 2 along with this work; if not, write to the Free Software Foundation,
42.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
42.23 + *
42.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
42.25 + * or visit www.oracle.com if you need additional information or have any
42.26 + * questions.
42.27 + */
42.28 +
42.29 +package java.util;
42.30 +
42.31 +/**
42.32 + * An abstract wrapper class for an {@code EventListener} class
42.33 + * which associates a set of additional parameters with the listener.
42.34 + * Subclasses must provide the storage and accessor methods
42.35 + * for the additional arguments or parameters.
42.36 + * <p>
42.37 + * For example, a bean which supports named properties
42.38 + * would have a two argument method signature for adding
42.39 + * a {@code PropertyChangeListener} for a property:
42.40 + * <pre>
42.41 + * public void addPropertyChangeListener(String propertyName,
42.42 + * PropertyChangeListener listener)
42.43 + * </pre>
42.44 + * If the bean also implemented the zero argument get listener method:
42.45 + * <pre>
42.46 + * public PropertyChangeListener[] getPropertyChangeListeners()
42.47 + * </pre>
42.48 + * then the array may contain inner {@code PropertyChangeListeners}
42.49 + * which are also {@code PropertyChangeListenerProxy} objects.
42.50 + * <p>
42.51 + * If the calling method is interested in retrieving the named property
42.52 + * then it would have to test the element to see if it is a proxy class.
42.53 + *
42.54 + * @since 1.4
42.55 + */
42.56 +public abstract class EventListenerProxy<T extends EventListener>
42.57 + implements EventListener {
42.58 +
42.59 + private final T listener;
42.60 +
42.61 + /**
42.62 + * Creates a proxy for the specified listener.
42.63 + *
42.64 + * @param listener the listener object
42.65 + */
42.66 + public EventListenerProxy(T listener) {
42.67 + this.listener = listener;
42.68 + }
42.69 +
42.70 + /**
42.71 + * Returns the listener associated with the proxy.
42.72 + *
42.73 + * @return the listener associated with the proxy
42.74 + */
42.75 + public T getListener() {
42.76 + return this.listener;
42.77 + }
42.78 +}
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
43.2 +++ b/emul/compact/src/main/java/java/util/concurrent/Callable.java Mon Feb 04 09:37:56 2013 +0100
43.3 @@ -0,0 +1,65 @@
43.4 +/*
43.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
43.6 + *
43.7 + * This code is free software; you can redistribute it and/or modify it
43.8 + * under the terms of the GNU General Public License version 2 only, as
43.9 + * published by the Free Software Foundation. Oracle designates this
43.10 + * particular file as subject to the "Classpath" exception as provided
43.11 + * by Oracle in the LICENSE file that accompanied this code.
43.12 + *
43.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
43.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
43.15 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
43.16 + * version 2 for more details (a copy is included in the LICENSE file that
43.17 + * accompanied this code).
43.18 + *
43.19 + * You should have received a copy of the GNU General Public License version
43.20 + * 2 along with this work; if not, write to the Free Software Foundation,
43.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
43.22 + *
43.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
43.24 + * or visit www.oracle.com if you need additional information or have any
43.25 + * questions.
43.26 + */
43.27 +
43.28 +/*
43.29 + * This file is available under and governed by the GNU General Public
43.30 + * License version 2 only, as published by the Free Software Foundation.
43.31 + * However, the following notice accompanied the original version of this
43.32 + * file:
43.33 + *
43.34 + * Written by Doug Lea with assistance from members of JCP JSR-166
43.35 + * Expert Group and released to the public domain, as explained at
43.36 + * http://creativecommons.org/publicdomain/zero/1.0/
43.37 + */
43.38 +
43.39 +package java.util.concurrent;
43.40 +
43.41 +/**
43.42 + * A task that returns a result and may throw an exception.
43.43 + * Implementors define a single method with no arguments called
43.44 + * <tt>call</tt>.
43.45 + *
43.46 + * <p>The <tt>Callable</tt> interface is similar to {@link
43.47 + * java.lang.Runnable}, in that both are designed for classes whose
43.48 + * instances are potentially executed by another thread. A
43.49 + * <tt>Runnable</tt>, however, does not return a result and cannot
43.50 + * throw a checked exception.
43.51 + *
43.52 + * <p> The {@link Executors} class contains utility methods to
43.53 + * convert from other common forms to <tt>Callable</tt> classes.
43.54 + *
43.55 + * @see Executor
43.56 + * @since 1.5
43.57 + * @author Doug Lea
43.58 + * @param <V> the result type of method <tt>call</tt>
43.59 + */
43.60 +public interface Callable<V> {
43.61 + /**
43.62 + * Computes a result, or throws an exception if unable to do so.
43.63 + *
43.64 + * @return computed result
43.65 + * @throws Exception if unable to compute a result
43.66 + */
43.67 + V call() throws Exception;
43.68 +}
44.1 --- a/emul/mini/src/main/java/java/lang/Class.java Fri Feb 01 16:34:51 2013 +0100
44.2 +++ b/emul/mini/src/main/java/java/lang/Class.java Mon Feb 04 09:37:56 2013 +0100
44.3 @@ -347,6 +347,9 @@
44.4 * @since JDK1.1
44.5 */
44.6 public boolean isInstance(Object obj) {
44.7 + if (obj == null) {
44.8 + return false;
44.9 + }
44.10 if (isArray()) {
44.11 return isAssignableFrom(obj.getClass());
44.12 }
44.13 @@ -909,7 +912,50 @@
44.14 }
44.15 return m;
44.16 }
44.17 -
44.18 +
44.19 + /**
44.20 + * Returns an array of {@code Method} objects reflecting all the
44.21 + * methods declared by the class or interface represented by this
44.22 + * {@code Class} object. This includes public, protected, default
44.23 + * (package) access, and private methods, but excludes inherited methods.
44.24 + * The elements in the array returned are not sorted and are not in any
44.25 + * particular order. This method returns an array of length 0 if the class
44.26 + * or interface declares no methods, or if this {@code Class} object
44.27 + * represents a primitive type, an array class, or void. The class
44.28 + * initialization method {@code <clinit>} is not included in the
44.29 + * returned array. If the class declares multiple public member methods
44.30 + * with the same parameter types, they are all included in the returned
44.31 + * array.
44.32 + *
44.33 + * <p> See <em>The Java Language Specification</em>, section 8.2.
44.34 + *
44.35 + * @return the array of {@code Method} objects representing all the
44.36 + * declared methods of this class
44.37 + * @exception SecurityException
44.38 + * If a security manager, <i>s</i>, is present and any of the
44.39 + * following conditions is met:
44.40 + *
44.41 + * <ul>
44.42 + *
44.43 + * <li> invocation of
44.44 + * {@link SecurityManager#checkMemberAccess
44.45 + * s.checkMemberAccess(this, Member.DECLARED)} denies
44.46 + * access to the declared methods within this class
44.47 + *
44.48 + * <li> the caller's class loader is not the same as or an
44.49 + * ancestor of the class loader for the current class and
44.50 + * invocation of {@link SecurityManager#checkPackageAccess
44.51 + * s.checkPackageAccess()} denies access to the package
44.52 + * of this class
44.53 + *
44.54 + * </ul>
44.55 + *
44.56 + * @since JDK1.1
44.57 + */
44.58 + public Method[] getDeclaredMethods() throws SecurityException {
44.59 + throw new SecurityException();
44.60 + }
44.61 +
44.62 /**
44.63 * Character.isDigit answers {@code true} to some non-ascii
44.64 * digits. This one does not.
44.65 @@ -1096,6 +1142,48 @@
44.66 public ClassLoader getClassLoader() {
44.67 throw new SecurityException();
44.68 }
44.69 +
44.70 + /**
44.71 + * Determines the interfaces implemented by the class or interface
44.72 + * represented by this object.
44.73 + *
44.74 + * <p> If this object represents a class, the return value is an array
44.75 + * containing objects representing all interfaces implemented by the
44.76 + * class. The order of the interface objects in the array corresponds to
44.77 + * the order of the interface names in the {@code implements} clause
44.78 + * of the declaration of the class represented by this object. For
44.79 + * example, given the declaration:
44.80 + * <blockquote>
44.81 + * {@code class Shimmer implements FloorWax, DessertTopping { ... }}
44.82 + * </blockquote>
44.83 + * suppose the value of {@code s} is an instance of
44.84 + * {@code Shimmer}; the value of the expression:
44.85 + * <blockquote>
44.86 + * {@code s.getClass().getInterfaces()[0]}
44.87 + * </blockquote>
44.88 + * is the {@code Class} object that represents interface
44.89 + * {@code FloorWax}; and the value of:
44.90 + * <blockquote>
44.91 + * {@code s.getClass().getInterfaces()[1]}
44.92 + * </blockquote>
44.93 + * is the {@code Class} object that represents interface
44.94 + * {@code DessertTopping}.
44.95 + *
44.96 + * <p> If this object represents an interface, the array contains objects
44.97 + * representing all interfaces extended by the interface. The order of the
44.98 + * interface objects in the array corresponds to the order of the interface
44.99 + * names in the {@code extends} clause of the declaration of the
44.100 + * interface represented by this object.
44.101 + *
44.102 + * <p> If this object represents a class or interface that implements no
44.103 + * interfaces, the method returns an array of length 0.
44.104 + *
44.105 + * <p> If this object represents a primitive type or void, the method
44.106 + * returns an array of length 0.
44.107 + *
44.108 + * @return an array of interfaces implemented by this class.
44.109 + */
44.110 + public native Class<?>[] getInterfaces();
44.111
44.112 /**
44.113 * Returns the {@code Class} representing the component type of an
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
45.2 +++ b/emul/mini/src/main/java/java/lang/Cloneable.java Mon Feb 04 09:37:56 2013 +0100
45.3 @@ -0,0 +1,54 @@
45.4 +/*
45.5 + * Copyright (c) 1995, 2004, Oracle and/or its affiliates. All rights reserved.
45.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
45.7 + *
45.8 + * This code is free software; you can redistribute it and/or modify it
45.9 + * under the terms of the GNU General Public License version 2 only, as
45.10 + * published by the Free Software Foundation. Oracle designates this
45.11 + * particular file as subject to the "Classpath" exception as provided
45.12 + * by Oracle in the LICENSE file that accompanied this code.
45.13 + *
45.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
45.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
45.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
45.17 + * version 2 for more details (a copy is included in the LICENSE file that
45.18 + * accompanied this code).
45.19 + *
45.20 + * You should have received a copy of the GNU General Public License version
45.21 + * 2 along with this work; if not, write to the Free Software Foundation,
45.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
45.23 + *
45.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
45.25 + * or visit www.oracle.com if you need additional information or have any
45.26 + * questions.
45.27 + */
45.28 +
45.29 +package java.lang;
45.30 +
45.31 +/**
45.32 + * A class implements the <code>Cloneable</code> interface to
45.33 + * indicate to the {@link java.lang.Object#clone()} method that it
45.34 + * is legal for that method to make a
45.35 + * field-for-field copy of instances of that class.
45.36 + * <p>
45.37 + * Invoking Object's clone method on an instance that does not implement the
45.38 + * <code>Cloneable</code> interface results in the exception
45.39 + * <code>CloneNotSupportedException</code> being thrown.
45.40 + * <p>
45.41 + * By convention, classes that implement this interface should override
45.42 + * <tt>Object.clone</tt> (which is protected) with a public method.
45.43 + * See {@link java.lang.Object#clone()} for details on overriding this
45.44 + * method.
45.45 + * <p>
45.46 + * Note that this interface does <i>not</i> contain the <tt>clone</tt> method.
45.47 + * Therefore, it is not possible to clone an object merely by virtue of the
45.48 + * fact that it implements this interface. Even if the clone method is invoked
45.49 + * reflectively, there is no guarantee that it will succeed.
45.50 + *
45.51 + * @author unascribed
45.52 + * @see java.lang.CloneNotSupportedException
45.53 + * @see java.lang.Object#clone()
45.54 + * @since JDK1.0
45.55 + */
45.56 +public interface Cloneable {
45.57 +}
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
46.2 +++ b/emul/mini/src/main/java/java/lang/IllegalAccessError.java Mon Feb 04 09:37:56 2013 +0100
46.3 @@ -0,0 +1,58 @@
46.4 +/*
46.5 + * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
46.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
46.7 + *
46.8 + * This code is free software; you can redistribute it and/or modify it
46.9 + * under the terms of the GNU General Public License version 2 only, as
46.10 + * published by the Free Software Foundation. Oracle designates this
46.11 + * particular file as subject to the "Classpath" exception as provided
46.12 + * by Oracle in the LICENSE file that accompanied this code.
46.13 + *
46.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
46.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
46.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
46.17 + * version 2 for more details (a copy is included in the LICENSE file that
46.18 + * accompanied this code).
46.19 + *
46.20 + * You should have received a copy of the GNU General Public License version
46.21 + * 2 along with this work; if not, write to the Free Software Foundation,
46.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
46.23 + *
46.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
46.25 + * or visit www.oracle.com if you need additional information or have any
46.26 + * questions.
46.27 + */
46.28 +
46.29 +package java.lang;
46.30 +
46.31 +/**
46.32 + * Thrown if an application attempts to access or modify a field, or
46.33 + * to call a method that it does not have access to.
46.34 + * <p>
46.35 + * Normally, this error is caught by the compiler; this error can
46.36 + * only occur at run time if the definition of a class has
46.37 + * incompatibly changed.
46.38 + *
46.39 + * @author unascribed
46.40 + * @since JDK1.0
46.41 + */
46.42 +public class IllegalAccessError extends IncompatibleClassChangeError {
46.43 + private static final long serialVersionUID = -8988904074992417891L;
46.44 +
46.45 + /**
46.46 + * Constructs an <code>IllegalAccessError</code> with no detail message.
46.47 + */
46.48 + public IllegalAccessError() {
46.49 + super();
46.50 + }
46.51 +
46.52 + /**
46.53 + * Constructs an <code>IllegalAccessError</code> with the specified
46.54 + * detail message.
46.55 + *
46.56 + * @param s the detail message.
46.57 + */
46.58 + public IllegalAccessError(String s) {
46.59 + super(s);
46.60 + }
46.61 +}
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
47.2 +++ b/emul/mini/src/main/java/java/lang/IncompatibleClassChangeError.java Mon Feb 04 09:37:56 2013 +0100
47.3 @@ -0,0 +1,57 @@
47.4 +/*
47.5 + * Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved.
47.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
47.7 + *
47.8 + * This code is free software; you can redistribute it and/or modify it
47.9 + * under the terms of the GNU General Public License version 2 only, as
47.10 + * published by the Free Software Foundation. Oracle designates this
47.11 + * particular file as subject to the "Classpath" exception as provided
47.12 + * by Oracle in the LICENSE file that accompanied this code.
47.13 + *
47.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
47.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
47.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
47.17 + * version 2 for more details (a copy is included in the LICENSE file that
47.18 + * accompanied this code).
47.19 + *
47.20 + * You should have received a copy of the GNU General Public License version
47.21 + * 2 along with this work; if not, write to the Free Software Foundation,
47.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
47.23 + *
47.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
47.25 + * or visit www.oracle.com if you need additional information or have any
47.26 + * questions.
47.27 + */
47.28 +
47.29 +package java.lang;
47.30 +
47.31 +/**
47.32 + * Thrown when an incompatible class change has occurred to some class
47.33 + * definition. The definition of some class, on which the currently
47.34 + * executing method depends, has since changed.
47.35 + *
47.36 + * @author unascribed
47.37 + * @since JDK1.0
47.38 + */
47.39 +public
47.40 +class IncompatibleClassChangeError extends LinkageError {
47.41 + private static final long serialVersionUID = -4914975503642802119L;
47.42 +
47.43 + /**
47.44 + * Constructs an <code>IncompatibleClassChangeError</code> with no
47.45 + * detail message.
47.46 + */
47.47 + public IncompatibleClassChangeError () {
47.48 + super();
47.49 + }
47.50 +
47.51 + /**
47.52 + * Constructs an <code>IncompatibleClassChangeError</code> with the
47.53 + * specified detail message.
47.54 + *
47.55 + * @param s the detail message.
47.56 + */
47.57 + public IncompatibleClassChangeError(String s) {
47.58 + super(s);
47.59 + }
47.60 +}
48.1 --- a/emul/mini/src/main/java/java/lang/String.java Fri Feb 01 16:34:51 2013 +0100
48.2 +++ b/emul/mini/src/main/java/java/lang/String.java Mon Feb 04 09:37:56 2013 +0100
48.3 @@ -25,6 +25,7 @@
48.4
48.5 package java.lang;
48.6
48.7 +import java.io.UnsupportedEncodingException;
48.8 import java.util.Comparator;
48.9 import org.apidesign.bck2brwsr.core.ExtraJavaScript;
48.10 import org.apidesign.bck2brwsr.core.JavaScriptBody;
48.11 @@ -200,6 +201,10 @@
48.12 * If the {@code offset} and {@code count} arguments index
48.13 * characters outside the bounds of the {@code value} array
48.14 */
48.15 + public String(char value[], int offset, int count) {
48.16 + initFromCharArray(value, offset, count);
48.17 + }
48.18 +
48.19 @JavaScriptBody(args = { "charArr", "off", "cnt" }, body =
48.20 "var up = off + cnt;\n" +
48.21 "for (var i = off; i < up; i++) {\n" +
48.22 @@ -207,8 +212,7 @@
48.23 "}\n" +
48.24 "this._r(charArr.slice(off, up).join(\"\"));\n"
48.25 )
48.26 - public String(char value[], int offset, int count) {
48.27 - }
48.28 + private native void initFromCharArray(char value[], int offset, int count);
48.29
48.30 /**
48.31 * Allocates a new {@code String} that contains characters from a subarray
48.32 @@ -415,17 +419,11 @@
48.33 *
48.34 * @since JDK1.1
48.35 */
48.36 -// public String(byte bytes[], int offset, int length, String charsetName)
48.37 -// throws UnsupportedEncodingException
48.38 -// {
48.39 -// if (charsetName == null)
48.40 -// throw new NullPointerException("charsetName");
48.41 -// checkBounds(bytes, offset, length);
48.42 -// char[] v = StringCoding.decode(charsetName, bytes, offset, length);
48.43 -// this.offset = 0;
48.44 -// this.count = v.length;
48.45 -// this.value = v;
48.46 -// }
48.47 + public String(byte bytes[], int offset, int length, String charsetName)
48.48 + throws UnsupportedEncodingException
48.49 + {
48.50 + this(checkUTF8(bytes, charsetName), offset, length);
48.51 + }
48.52
48.53 /**
48.54 * Constructs a new {@code String} by decoding the specified subarray of
48.55 @@ -492,11 +490,11 @@
48.56 *
48.57 * @since JDK1.1
48.58 */
48.59 -// public String(byte bytes[], String charsetName)
48.60 -// throws UnsupportedEncodingException
48.61 -// {
48.62 -// this(bytes, 0, bytes.length, charsetName);
48.63 -// }
48.64 + public String(byte bytes[], String charsetName)
48.65 + throws UnsupportedEncodingException
48.66 + {
48.67 + this(bytes, 0, bytes.length, charsetName);
48.68 + }
48.69
48.70 /**
48.71 * Constructs a new {@code String} by decoding the specified array of
48.72 @@ -553,10 +551,14 @@
48.73 public String(byte bytes[], int offset, int length) {
48.74 checkBounds(bytes, offset, length);
48.75 char[] v = new char[length];
48.76 - for (int i = 0; i < length; i++) {
48.77 - v[i] = (char)bytes[offset++];
48.78 + int[] at = { offset };
48.79 + int end = offset + length;
48.80 + int chlen = 0;
48.81 + while (at[0] < end) {
48.82 + int ch = nextChar(bytes, at);
48.83 + v[chlen++] = (char)ch;
48.84 }
48.85 - this.r = new String(v, 0, v.length);
48.86 + initFromCharArray(v, 0, chlen);
48.87 }
48.88
48.89 /**
48.90 @@ -925,12 +927,12 @@
48.91 *
48.92 * @since JDK1.1
48.93 */
48.94 -// public byte[] getBytes(String charsetName)
48.95 -// throws UnsupportedEncodingException
48.96 -// {
48.97 -// if (charsetName == null) throw new NullPointerException();
48.98 -// return StringCoding.encode(charsetName, value, offset, count);
48.99 -// }
48.100 + public byte[] getBytes(String charsetName)
48.101 + throws UnsupportedEncodingException
48.102 + {
48.103 + checkUTF8(null, charsetName);
48.104 + return getBytes();
48.105 + }
48.106
48.107 /**
48.108 * Encodes this {@code String} into a sequence of bytes using the given
48.109 @@ -1224,7 +1226,7 @@
48.110 private static int offset() {
48.111 return 0;
48.112 }
48.113 -
48.114 +
48.115 private static class CaseInsensitiveComparator
48.116 implements Comparator<String>, java.io.Serializable {
48.117 // use serialVersionUID from JDK 1.2.2 for interoperability
48.118 @@ -3021,4 +3023,57 @@
48.119 * guaranteed to be from a pool of unique strings.
48.120 */
48.121 public native String intern();
48.122 +
48.123 +
48.124 + private static <T> T checkUTF8(T data, String charsetName)
48.125 + throws UnsupportedEncodingException {
48.126 + if (charsetName == null) {
48.127 + throw new NullPointerException("charsetName");
48.128 + }
48.129 + if (!charsetName.equalsIgnoreCase("UTF-8")
48.130 + && !charsetName.equalsIgnoreCase("UTF8")) {
48.131 + throw new UnsupportedEncodingException(charsetName);
48.132 + }
48.133 + return data;
48.134 + }
48.135 +
48.136 + private static int nextChar(byte[] arr, int[] index) throws IndexOutOfBoundsException {
48.137 + int c = arr[index[0]++] & 0xff;
48.138 + switch (c >> 4) {
48.139 + case 0:
48.140 + case 1:
48.141 + case 2:
48.142 + case 3:
48.143 + case 4:
48.144 + case 5:
48.145 + case 6:
48.146 + case 7:
48.147 + /* 0xxxxxxx*/
48.148 + return c;
48.149 + case 12:
48.150 + case 13: {
48.151 + /* 110x xxxx 10xx xxxx*/
48.152 + int char2 = (int) arr[index[0]++];
48.153 + if ((char2 & 0xC0) != 0x80) {
48.154 + throw new IndexOutOfBoundsException("malformed input");
48.155 + }
48.156 + return (((c & 0x1F) << 6) | (char2 & 0x3F));
48.157 + }
48.158 + case 14: {
48.159 + /* 1110 xxxx 10xx xxxx 10xx xxxx */
48.160 + int char2 = arr[index[0]++];
48.161 + int char3 = arr[index[0]++];
48.162 + if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80)) {
48.163 + throw new IndexOutOfBoundsException("malformed input");
48.164 + }
48.165 + return (((c & 0x0F) << 12)
48.166 + | ((char2 & 0x3F) << 6)
48.167 + | ((char3 & 0x3F) << 0));
48.168 + }
48.169 + default:
48.170 + /* 10xx xxxx, 1111 xxxx */
48.171 + throw new IndexOutOfBoundsException("malformed input");
48.172 + }
48.173 +
48.174 + }
48.175 }
49.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
49.2 +++ b/emul/mini/src/main/java/java/lang/reflect/Constructor.java Mon Feb 04 09:37:56 2013 +0100
49.3 @@ -0,0 +1,567 @@
49.4 +/*
49.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
49.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
49.7 + *
49.8 + * This code is free software; you can redistribute it and/or modify it
49.9 + * under the terms of the GNU General Public License version 2 only, as
49.10 + * published by the Free Software Foundation. Oracle designates this
49.11 + * particular file as subject to the "Classpath" exception as provided
49.12 + * by Oracle in the LICENSE file that accompanied this code.
49.13 + *
49.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
49.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
49.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
49.17 + * version 2 for more details (a copy is included in the LICENSE file that
49.18 + * accompanied this code).
49.19 + *
49.20 + * You should have received a copy of the GNU General Public License version
49.21 + * 2 along with this work; if not, write to the Free Software Foundation,
49.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
49.23 + *
49.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
49.25 + * or visit www.oracle.com if you need additional information or have any
49.26 + * questions.
49.27 + */
49.28 +
49.29 +package java.lang.reflect;
49.30 +
49.31 +import java.lang.annotation.Annotation;
49.32 +import org.apidesign.bck2brwsr.emul.reflect.TypeProvider;
49.33 +
49.34 +/**
49.35 + * {@code Constructor} provides information about, and access to, a single
49.36 + * constructor for a class.
49.37 + *
49.38 + * <p>{@code Constructor} permits widening conversions to occur when matching the
49.39 + * actual parameters to newInstance() with the underlying
49.40 + * constructor's formal parameters, but throws an
49.41 + * {@code IllegalArgumentException} if a narrowing conversion would occur.
49.42 + *
49.43 + * @param <T> the class in which the constructor is declared
49.44 + *
49.45 + * @see Member
49.46 + * @see java.lang.Class
49.47 + * @see java.lang.Class#getConstructors()
49.48 + * @see java.lang.Class#getConstructor(Class[])
49.49 + * @see java.lang.Class#getDeclaredConstructors()
49.50 + *
49.51 + * @author Kenneth Russell
49.52 + * @author Nakul Saraiya
49.53 + */
49.54 +public final
49.55 + class Constructor<T> extends AccessibleObject implements
49.56 + GenericDeclaration,
49.57 + Member {
49.58 +
49.59 + private Class<T> clazz;
49.60 + private int slot;
49.61 + private Class<?>[] parameterTypes;
49.62 + private Class<?>[] exceptionTypes;
49.63 + private int modifiers;
49.64 + // Generics and annotations support
49.65 + private transient String signature;
49.66 + private byte[] annotations;
49.67 + private byte[] parameterAnnotations;
49.68 +
49.69 +
49.70 + // For sharing of ConstructorAccessors. This branching structure
49.71 + // is currently only two levels deep (i.e., one root Constructor
49.72 + // and potentially many Constructor objects pointing to it.)
49.73 + private Constructor<T> root;
49.74 +
49.75 + /**
49.76 + * Package-private constructor used by ReflectAccess to enable
49.77 + * instantiation of these objects in Java code from the java.lang
49.78 + * package via sun.reflect.LangReflectAccess.
49.79 + */
49.80 + Constructor(Class<T> declaringClass,
49.81 + Class<?>[] parameterTypes,
49.82 + Class<?>[] checkedExceptions,
49.83 + int modifiers,
49.84 + int slot,
49.85 + String signature,
49.86 + byte[] annotations,
49.87 + byte[] parameterAnnotations)
49.88 + {
49.89 + this.clazz = declaringClass;
49.90 + this.parameterTypes = parameterTypes;
49.91 + this.exceptionTypes = checkedExceptions;
49.92 + this.modifiers = modifiers;
49.93 + this.slot = slot;
49.94 + this.signature = signature;
49.95 + this.annotations = annotations;
49.96 + this.parameterAnnotations = parameterAnnotations;
49.97 + }
49.98 +
49.99 + /**
49.100 + * Package-private routine (exposed to java.lang.Class via
49.101 + * ReflectAccess) which returns a copy of this Constructor. The copy's
49.102 + * "root" field points to this Constructor.
49.103 + */
49.104 + Constructor<T> copy() {
49.105 + return this;
49.106 + }
49.107 +
49.108 + /**
49.109 + * Returns the {@code Class} object representing the class that declares
49.110 + * the constructor represented by this {@code Constructor} object.
49.111 + */
49.112 + public Class<T> getDeclaringClass() {
49.113 + return clazz;
49.114 + }
49.115 +
49.116 + /**
49.117 + * Returns the name of this constructor, as a string. This is
49.118 + * the binary name of the constructor's declaring class.
49.119 + */
49.120 + public String getName() {
49.121 + return getDeclaringClass().getName();
49.122 + }
49.123 +
49.124 + /**
49.125 + * Returns the Java language modifiers for the constructor
49.126 + * represented by this {@code Constructor} object, as an integer. The
49.127 + * {@code Modifier} class should be used to decode the modifiers.
49.128 + *
49.129 + * @see Modifier
49.130 + */
49.131 + public int getModifiers() {
49.132 + return modifiers;
49.133 + }
49.134 +
49.135 + /**
49.136 + * Returns an array of {@code TypeVariable} objects that represent the
49.137 + * type variables declared by the generic declaration represented by this
49.138 + * {@code GenericDeclaration} object, in declaration order. Returns an
49.139 + * array of length 0 if the underlying generic declaration declares no type
49.140 + * variables.
49.141 + *
49.142 + * @return an array of {@code TypeVariable} objects that represent
49.143 + * the type variables declared by this generic declaration
49.144 + * @throws GenericSignatureFormatError if the generic
49.145 + * signature of this generic declaration does not conform to
49.146 + * the format specified in
49.147 + * <cite>The Java™ Virtual Machine Specification</cite>
49.148 + * @since 1.5
49.149 + */
49.150 + public TypeVariable<Constructor<T>>[] getTypeParameters() {
49.151 + return TypeProvider.getDefault().getTypeParameters(this);
49.152 + }
49.153 +
49.154 +
49.155 + /**
49.156 + * Returns an array of {@code Class} objects that represent the formal
49.157 + * parameter types, in declaration order, of the constructor
49.158 + * represented by this {@code Constructor} object. Returns an array of
49.159 + * length 0 if the underlying constructor takes no parameters.
49.160 + *
49.161 + * @return the parameter types for the constructor this object
49.162 + * represents
49.163 + */
49.164 + public Class<?>[] getParameterTypes() {
49.165 + return (Class<?>[]) parameterTypes.clone();
49.166 + }
49.167 +
49.168 +
49.169 + /**
49.170 + * Returns an array of {@code Type} objects that represent the formal
49.171 + * parameter types, in declaration order, of the method represented by
49.172 + * this {@code Constructor} object. Returns an array of length 0 if the
49.173 + * underlying method takes no parameters.
49.174 + *
49.175 + * <p>If a formal parameter type is a parameterized type,
49.176 + * the {@code Type} object returned for it must accurately reflect
49.177 + * the actual type parameters used in the source code.
49.178 + *
49.179 + * <p>If a formal parameter type is a type variable or a parameterized
49.180 + * type, it is created. Otherwise, it is resolved.
49.181 + *
49.182 + * @return an array of {@code Type}s that represent the formal
49.183 + * parameter types of the underlying method, in declaration order
49.184 + * @throws GenericSignatureFormatError
49.185 + * if the generic method signature does not conform to the format
49.186 + * specified in
49.187 + * <cite>The Java™ Virtual Machine Specification</cite>
49.188 + * @throws TypeNotPresentException if any of the parameter
49.189 + * types of the underlying method refers to a non-existent type
49.190 + * declaration
49.191 + * @throws MalformedParameterizedTypeException if any of
49.192 + * the underlying method's parameter types refer to a parameterized
49.193 + * type that cannot be instantiated for any reason
49.194 + * @since 1.5
49.195 + */
49.196 + public Type[] getGenericParameterTypes() {
49.197 + return TypeProvider.getDefault().getGenericParameterTypes(this);
49.198 + }
49.199 +
49.200 +
49.201 + /**
49.202 + * Returns an array of {@code Class} objects that represent the types
49.203 + * of exceptions declared to be thrown by the underlying constructor
49.204 + * represented by this {@code Constructor} object. Returns an array of
49.205 + * length 0 if the constructor declares no exceptions in its {@code throws} clause.
49.206 + *
49.207 + * @return the exception types declared as being thrown by the
49.208 + * constructor this object represents
49.209 + */
49.210 + public Class<?>[] getExceptionTypes() {
49.211 + return (Class<?>[])exceptionTypes.clone();
49.212 + }
49.213 +
49.214 +
49.215 + /**
49.216 + * Returns an array of {@code Type} objects that represent the
49.217 + * exceptions declared to be thrown by this {@code Constructor} object.
49.218 + * Returns an array of length 0 if the underlying method declares
49.219 + * no exceptions in its {@code throws} clause.
49.220 + *
49.221 + * <p>If an exception type is a type variable or a parameterized
49.222 + * type, it is created. Otherwise, it is resolved.
49.223 + *
49.224 + * @return an array of Types that represent the exception types
49.225 + * thrown by the underlying method
49.226 + * @throws GenericSignatureFormatError
49.227 + * if the generic method signature does not conform to the format
49.228 + * specified in
49.229 + * <cite>The Java™ Virtual Machine Specification</cite>
49.230 + * @throws TypeNotPresentException if the underlying method's
49.231 + * {@code throws} clause refers to a non-existent type declaration
49.232 + * @throws MalformedParameterizedTypeException if
49.233 + * the underlying method's {@code throws} clause refers to a
49.234 + * parameterized type that cannot be instantiated for any reason
49.235 + * @since 1.5
49.236 + */
49.237 + public Type[] getGenericExceptionTypes() {
49.238 + return TypeProvider.getDefault().getGenericExceptionTypes(this);
49.239 + }
49.240 +
49.241 + /**
49.242 + * Compares this {@code Constructor} against the specified object.
49.243 + * Returns true if the objects are the same. Two {@code Constructor} objects are
49.244 + * the same if they were declared by the same class and have the
49.245 + * same formal parameter types.
49.246 + */
49.247 + public boolean equals(Object obj) {
49.248 + if (obj != null && obj instanceof Constructor) {
49.249 + Constructor<?> other = (Constructor<?>)obj;
49.250 + if (getDeclaringClass() == other.getDeclaringClass()) {
49.251 + /* Avoid unnecessary cloning */
49.252 + Class<?>[] params1 = parameterTypes;
49.253 + Class<?>[] params2 = other.parameterTypes;
49.254 + if (params1.length == params2.length) {
49.255 + for (int i = 0; i < params1.length; i++) {
49.256 + if (params1[i] != params2[i])
49.257 + return false;
49.258 + }
49.259 + return true;
49.260 + }
49.261 + }
49.262 + }
49.263 + return false;
49.264 + }
49.265 +
49.266 + /**
49.267 + * Returns a hashcode for this {@code Constructor}. The hashcode is
49.268 + * the same as the hashcode for the underlying constructor's
49.269 + * declaring class name.
49.270 + */
49.271 + public int hashCode() {
49.272 + return getDeclaringClass().getName().hashCode();
49.273 + }
49.274 +
49.275 + /**
49.276 + * Returns a string describing this {@code Constructor}. The string is
49.277 + * formatted as the constructor access modifiers, if any,
49.278 + * followed by the fully-qualified name of the declaring class,
49.279 + * followed by a parenthesized, comma-separated list of the
49.280 + * constructor's formal parameter types. For example:
49.281 + * <pre>
49.282 + * public java.util.Hashtable(int,float)
49.283 + * </pre>
49.284 + *
49.285 + * <p>The only possible modifiers for constructors are the access
49.286 + * modifiers {@code public}, {@code protected} or
49.287 + * {@code private}. Only one of these may appear, or none if the
49.288 + * constructor has default (package) access.
49.289 + */
49.290 + public String toString() {
49.291 + try {
49.292 + StringBuffer sb = new StringBuffer();
49.293 + int mod = getModifiers() & Modifier.constructorModifiers();
49.294 + if (mod != 0) {
49.295 + sb.append(Modifier.toString(mod) + " ");
49.296 + }
49.297 + sb.append(Field.getTypeName(getDeclaringClass()));
49.298 + sb.append("(");
49.299 + Class<?>[] params = parameterTypes; // avoid clone
49.300 + for (int j = 0; j < params.length; j++) {
49.301 + sb.append(Field.getTypeName(params[j]));
49.302 + if (j < (params.length - 1))
49.303 + sb.append(",");
49.304 + }
49.305 + sb.append(")");
49.306 + Class<?>[] exceptions = exceptionTypes; // avoid clone
49.307 + if (exceptions.length > 0) {
49.308 + sb.append(" throws ");
49.309 + for (int k = 0; k < exceptions.length; k++) {
49.310 + sb.append(exceptions[k].getName());
49.311 + if (k < (exceptions.length - 1))
49.312 + sb.append(",");
49.313 + }
49.314 + }
49.315 + return sb.toString();
49.316 + } catch (Exception e) {
49.317 + return "<" + e + ">";
49.318 + }
49.319 + }
49.320 +
49.321 + /**
49.322 + * Returns a string describing this {@code Constructor},
49.323 + * including type parameters. The string is formatted as the
49.324 + * constructor access modifiers, if any, followed by an
49.325 + * angle-bracketed comma separated list of the constructor's type
49.326 + * parameters, if any, followed by the fully-qualified name of the
49.327 + * declaring class, followed by a parenthesized, comma-separated
49.328 + * list of the constructor's generic formal parameter types.
49.329 + *
49.330 + * If this constructor was declared to take a variable number of
49.331 + * arguments, instead of denoting the last parameter as
49.332 + * "<tt><i>Type</i>[]</tt>", it is denoted as
49.333 + * "<tt><i>Type</i>...</tt>".
49.334 + *
49.335 + * A space is used to separate access modifiers from one another
49.336 + * and from the type parameters or return type. If there are no
49.337 + * type parameters, the type parameter list is elided; if the type
49.338 + * parameter list is present, a space separates the list from the
49.339 + * class name. If the constructor is declared to throw
49.340 + * exceptions, the parameter list is followed by a space, followed
49.341 + * by the word "{@code throws}" followed by a
49.342 + * comma-separated list of the thrown exception types.
49.343 + *
49.344 + * <p>The only possible modifiers for constructors are the access
49.345 + * modifiers {@code public}, {@code protected} or
49.346 + * {@code private}. Only one of these may appear, or none if the
49.347 + * constructor has default (package) access.
49.348 + *
49.349 + * @return a string describing this {@code Constructor},
49.350 + * include type parameters
49.351 + *
49.352 + * @since 1.5
49.353 + */
49.354 + public String toGenericString() {
49.355 + try {
49.356 + StringBuilder sb = new StringBuilder();
49.357 + int mod = getModifiers() & Modifier.constructorModifiers();
49.358 + if (mod != 0) {
49.359 + sb.append(Modifier.toString(mod) + " ");
49.360 + }
49.361 + TypeVariable<?>[] typeparms = getTypeParameters();
49.362 + if (typeparms.length > 0) {
49.363 + boolean first = true;
49.364 + sb.append("<");
49.365 + for(TypeVariable<?> typeparm: typeparms) {
49.366 + if (!first)
49.367 + sb.append(",");
49.368 + // Class objects can't occur here; no need to test
49.369 + // and call Class.getName().
49.370 + sb.append(typeparm.toString());
49.371 + first = false;
49.372 + }
49.373 + sb.append("> ");
49.374 + }
49.375 + sb.append(Field.getTypeName(getDeclaringClass()));
49.376 + sb.append("(");
49.377 + Type[] params = getGenericParameterTypes();
49.378 + for (int j = 0; j < params.length; j++) {
49.379 + String param = (params[j] instanceof Class<?>)?
49.380 + Field.getTypeName((Class<?>)params[j]):
49.381 + (params[j].toString());
49.382 + if (isVarArgs() && (j == params.length - 1)) // replace T[] with T...
49.383 + param = param.replaceFirst("\\[\\]$", "...");
49.384 + sb.append(param);
49.385 + if (j < (params.length - 1))
49.386 + sb.append(",");
49.387 + }
49.388 + sb.append(")");
49.389 + Type[] exceptions = getGenericExceptionTypes();
49.390 + if (exceptions.length > 0) {
49.391 + sb.append(" throws ");
49.392 + for (int k = 0; k < exceptions.length; k++) {
49.393 + sb.append((exceptions[k] instanceof Class)?
49.394 + ((Class<?>)exceptions[k]).getName():
49.395 + exceptions[k].toString());
49.396 + if (k < (exceptions.length - 1))
49.397 + sb.append(",");
49.398 + }
49.399 + }
49.400 + return sb.toString();
49.401 + } catch (Exception e) {
49.402 + return "<" + e + ">";
49.403 + }
49.404 + }
49.405 +
49.406 + /**
49.407 + * Uses the constructor represented by this {@code Constructor} object to
49.408 + * create and initialize a new instance of the constructor's
49.409 + * declaring class, with the specified initialization parameters.
49.410 + * Individual parameters are automatically unwrapped to match
49.411 + * primitive formal parameters, and both primitive and reference
49.412 + * parameters are subject to method invocation conversions as necessary.
49.413 + *
49.414 + * <p>If the number of formal parameters required by the underlying constructor
49.415 + * is 0, the supplied {@code initargs} array may be of length 0 or null.
49.416 + *
49.417 + * <p>If the constructor's declaring class is an inner class in a
49.418 + * non-static context, the first argument to the constructor needs
49.419 + * to be the enclosing instance; see section 15.9.3 of
49.420 + * <cite>The Java™ Language Specification</cite>.
49.421 + *
49.422 + * <p>If the required access and argument checks succeed and the
49.423 + * instantiation will proceed, the constructor's declaring class
49.424 + * is initialized if it has not already been initialized.
49.425 + *
49.426 + * <p>If the constructor completes normally, returns the newly
49.427 + * created and initialized instance.
49.428 + *
49.429 + * @param initargs array of objects to be passed as arguments to
49.430 + * the constructor call; values of primitive types are wrapped in
49.431 + * a wrapper object of the appropriate type (e.g. a {@code float}
49.432 + * in a {@link java.lang.Float Float})
49.433 + *
49.434 + * @return a new object created by calling the constructor
49.435 + * this object represents
49.436 + *
49.437 + * @exception IllegalAccessException if this {@code Constructor} object
49.438 + * is enforcing Java language access control and the underlying
49.439 + * constructor is inaccessible.
49.440 + * @exception IllegalArgumentException if the number of actual
49.441 + * and formal parameters differ; if an unwrapping
49.442 + * conversion for primitive arguments fails; or if,
49.443 + * after possible unwrapping, a parameter value
49.444 + * cannot be converted to the corresponding formal
49.445 + * parameter type by a method invocation conversion; if
49.446 + * this constructor pertains to an enum type.
49.447 + * @exception InstantiationException if the class that declares the
49.448 + * underlying constructor represents an abstract class.
49.449 + * @exception InvocationTargetException if the underlying constructor
49.450 + * throws an exception.
49.451 + * @exception ExceptionInInitializerError if the initialization provoked
49.452 + * by this method fails.
49.453 + */
49.454 + public T newInstance(Object ... initargs)
49.455 + throws InstantiationException, IllegalAccessException,
49.456 + IllegalArgumentException, InvocationTargetException
49.457 + {
49.458 + throw new SecurityException();
49.459 + }
49.460 +
49.461 + /**
49.462 + * Returns {@code true} if this constructor was declared to take
49.463 + * a variable number of arguments; returns {@code false}
49.464 + * otherwise.
49.465 + *
49.466 + * @return {@code true} if an only if this constructor was declared to
49.467 + * take a variable number of arguments.
49.468 + * @since 1.5
49.469 + */
49.470 + public boolean isVarArgs() {
49.471 + return (getModifiers() & Modifier.VARARGS) != 0;
49.472 + }
49.473 +
49.474 + /**
49.475 + * Returns {@code true} if this constructor is a synthetic
49.476 + * constructor; returns {@code false} otherwise.
49.477 + *
49.478 + * @return true if and only if this constructor is a synthetic
49.479 + * constructor as defined by
49.480 + * <cite>The Java™ Language Specification</cite>.
49.481 + * @since 1.5
49.482 + */
49.483 + public boolean isSynthetic() {
49.484 + return Modifier.isSynthetic(getModifiers());
49.485 + }
49.486 +
49.487 + int getSlot() {
49.488 + return slot;
49.489 + }
49.490 +
49.491 + String getSignature() {
49.492 + return signature;
49.493 + }
49.494 +
49.495 + byte[] getRawAnnotations() {
49.496 + return annotations;
49.497 + }
49.498 +
49.499 + byte[] getRawParameterAnnotations() {
49.500 + return parameterAnnotations;
49.501 + }
49.502 +
49.503 + /**
49.504 + * @throws NullPointerException {@inheritDoc}
49.505 + * @since 1.5
49.506 + */
49.507 + public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
49.508 + if (annotationClass == null)
49.509 + throw new NullPointerException();
49.510 +
49.511 + return null; // XXX (T) declaredAnnotations().get(annotationClass);
49.512 + }
49.513 +
49.514 + /**
49.515 + * @since 1.5
49.516 + */
49.517 + public Annotation[] getDeclaredAnnotations() {
49.518 + return new Annotation[0]; // XXX AnnotationParser.toArray(declaredAnnotations());
49.519 + }
49.520 +
49.521 + /**
49.522 + * Returns an array of arrays that represent the annotations on the formal
49.523 + * parameters, in declaration order, of the method represented by
49.524 + * this {@code Constructor} object. (Returns an array of length zero if the
49.525 + * underlying method is parameterless. If the method has one or more
49.526 + * parameters, a nested array of length zero is returned for each parameter
49.527 + * with no annotations.) The annotation objects contained in the returned
49.528 + * arrays are serializable. The caller of this method is free to modify
49.529 + * the returned arrays; it will have no effect on the arrays returned to
49.530 + * other callers.
49.531 + *
49.532 + * @return an array of arrays that represent the annotations on the formal
49.533 + * parameters, in declaration order, of the method represented by this
49.534 + * Constructor object
49.535 + * @since 1.5
49.536 + */
49.537 + public Annotation[][] getParameterAnnotations() {
49.538 + int numParameters = parameterTypes.length;
49.539 + if (parameterAnnotations == null)
49.540 + return new Annotation[numParameters][0];
49.541 +
49.542 + return new Annotation[numParameters][0]; // XXX
49.543 +/*
49.544 + Annotation[][] result = AnnotationParser.parseParameterAnnotations(
49.545 + parameterAnnotations,
49.546 + sun.misc.SharedSecrets.getJavaLangAccess().
49.547 + getConstantPool(getDeclaringClass()),
49.548 + getDeclaringClass());
49.549 + if (result.length != numParameters) {
49.550 + Class<?> declaringClass = getDeclaringClass();
49.551 + if (declaringClass.isEnum() ||
49.552 + declaringClass.isAnonymousClass() ||
49.553 + declaringClass.isLocalClass() )
49.554 + ; // Can't do reliable parameter counting
49.555 + else {
49.556 + if (!declaringClass.isMemberClass() || // top-level
49.557 + // Check for the enclosing instance parameter for
49.558 + // non-static member classes
49.559 + (declaringClass.isMemberClass() &&
49.560 + ((declaringClass.getModifiers() & Modifier.STATIC) == 0) &&
49.561 + result.length + 1 != numParameters) ) {
49.562 + throw new AnnotationFormatError(
49.563 + "Parameter annotations don't match number of parameters");
49.564 + }
49.565 + }
49.566 + }
49.567 + return result;
49.568 + */
49.569 + }
49.570 +}
50.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
50.2 +++ b/emul/mini/src/main/java/java/lang/reflect/InvocationHandler.java Mon Feb 04 09:37:56 2013 +0100
50.3 @@ -0,0 +1,95 @@
50.4 +/*
50.5 + * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved.
50.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
50.7 + *
50.8 + * This code is free software; you can redistribute it and/or modify it
50.9 + * under the terms of the GNU General Public License version 2 only, as
50.10 + * published by the Free Software Foundation. Oracle designates this
50.11 + * particular file as subject to the "Classpath" exception as provided
50.12 + * by Oracle in the LICENSE file that accompanied this code.
50.13 + *
50.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
50.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
50.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
50.17 + * version 2 for more details (a copy is included in the LICENSE file that
50.18 + * accompanied this code).
50.19 + *
50.20 + * You should have received a copy of the GNU General Public License version
50.21 + * 2 along with this work; if not, write to the Free Software Foundation,
50.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
50.23 + *
50.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
50.25 + * or visit www.oracle.com if you need additional information or have any
50.26 + * questions.
50.27 + */
50.28 +
50.29 +package java.lang.reflect;
50.30 +
50.31 +/**
50.32 + * {@code InvocationHandler} is the interface implemented by
50.33 + * the <i>invocation handler</i> of a proxy instance.
50.34 + *
50.35 + * <p>Each proxy instance has an associated invocation handler.
50.36 + * When a method is invoked on a proxy instance, the method
50.37 + * invocation is encoded and dispatched to the {@code invoke}
50.38 + * method of its invocation handler.
50.39 + *
50.40 + * @author Peter Jones
50.41 + * @see Proxy
50.42 + * @since 1.3
50.43 + */
50.44 +public interface InvocationHandler {
50.45 +
50.46 + /**
50.47 + * Processes a method invocation on a proxy instance and returns
50.48 + * the result. This method will be invoked on an invocation handler
50.49 + * when a method is invoked on a proxy instance that it is
50.50 + * associated with.
50.51 + *
50.52 + * @param proxy the proxy instance that the method was invoked on
50.53 + *
50.54 + * @param method the {@code Method} instance corresponding to
50.55 + * the interface method invoked on the proxy instance. The declaring
50.56 + * class of the {@code Method} object will be the interface that
50.57 + * the method was declared in, which may be a superinterface of the
50.58 + * proxy interface that the proxy class inherits the method through.
50.59 + *
50.60 + * @param args an array of objects containing the values of the
50.61 + * arguments passed in the method invocation on the proxy instance,
50.62 + * or {@code null} if interface method takes no arguments.
50.63 + * Arguments of primitive types are wrapped in instances of the
50.64 + * appropriate primitive wrapper class, such as
50.65 + * {@code java.lang.Integer} or {@code java.lang.Boolean}.
50.66 + *
50.67 + * @return the value to return from the method invocation on the
50.68 + * proxy instance. If the declared return type of the interface
50.69 + * method is a primitive type, then the value returned by
50.70 + * this method must be an instance of the corresponding primitive
50.71 + * wrapper class; otherwise, it must be a type assignable to the
50.72 + * declared return type. If the value returned by this method is
50.73 + * {@code null} and the interface method's return type is
50.74 + * primitive, then a {@code NullPointerException} will be
50.75 + * thrown by the method invocation on the proxy instance. If the
50.76 + * value returned by this method is otherwise not compatible with
50.77 + * the interface method's declared return type as described above,
50.78 + * a {@code ClassCastException} will be thrown by the method
50.79 + * invocation on the proxy instance.
50.80 + *
50.81 + * @throws Throwable the exception to throw from the method
50.82 + * invocation on the proxy instance. The exception's type must be
50.83 + * assignable either to any of the exception types declared in the
50.84 + * {@code throws} clause of the interface method or to the
50.85 + * unchecked exception types {@code java.lang.RuntimeException}
50.86 + * or {@code java.lang.Error}. If a checked exception is
50.87 + * thrown by this method that is not assignable to any of the
50.88 + * exception types declared in the {@code throws} clause of
50.89 + * the interface method, then an
50.90 + * {@link UndeclaredThrowableException} containing the
50.91 + * exception that was thrown by this method will be thrown by the
50.92 + * method invocation on the proxy instance.
50.93 + *
50.94 + * @see UndeclaredThrowableException
50.95 + */
50.96 + public Object invoke(Object proxy, Method method, Object[] args)
50.97 + throws Throwable;
50.98 +}
51.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
51.2 +++ b/emul/mini/src/main/java/java/lang/reflect/Proxy.java Mon Feb 04 09:37:56 2013 +0100
51.3 @@ -0,0 +1,407 @@
51.4 +/*
51.5 + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
51.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
51.7 + *
51.8 + * This code is free software; you can redistribute it and/or modify it
51.9 + * under the terms of the GNU General Public License version 2 only, as
51.10 + * published by the Free Software Foundation. Oracle designates this
51.11 + * particular file as subject to the "Classpath" exception as provided
51.12 + * by Oracle in the LICENSE file that accompanied this code.
51.13 + *
51.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
51.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
51.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
51.17 + * version 2 for more details (a copy is included in the LICENSE file that
51.18 + * accompanied this code).
51.19 + *
51.20 + * You should have received a copy of the GNU General Public License version
51.21 + * 2 along with this work; if not, write to the Free Software Foundation,
51.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
51.23 + *
51.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
51.25 + * or visit www.oracle.com if you need additional information or have any
51.26 + * questions.
51.27 + */
51.28 +
51.29 +package java.lang.reflect;
51.30 +
51.31 +
51.32 +/**
51.33 + * {@code Proxy} provides static methods for creating dynamic proxy
51.34 + * classes and instances, and it is also the superclass of all
51.35 + * dynamic proxy classes created by those methods.
51.36 + *
51.37 + * <p>To create a proxy for some interface {@code Foo}:
51.38 + * <pre>
51.39 + * InvocationHandler handler = new MyInvocationHandler(...);
51.40 + * Class proxyClass = Proxy.getProxyClass(
51.41 + * Foo.class.getClassLoader(), new Class[] { Foo.class });
51.42 + * Foo f = (Foo) proxyClass.
51.43 + * getConstructor(new Class[] { InvocationHandler.class }).
51.44 + * newInstance(new Object[] { handler });
51.45 + * </pre>
51.46 + * or more simply:
51.47 + * <pre>
51.48 + * Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
51.49 + * new Class[] { Foo.class },
51.50 + * handler);
51.51 + * </pre>
51.52 + *
51.53 + * <p>A <i>dynamic proxy class</i> (simply referred to as a <i>proxy
51.54 + * class</i> below) is a class that implements a list of interfaces
51.55 + * specified at runtime when the class is created, with behavior as
51.56 + * described below.
51.57 + *
51.58 + * A <i>proxy interface</i> is such an interface that is implemented
51.59 + * by a proxy class.
51.60 + *
51.61 + * A <i>proxy instance</i> is an instance of a proxy class.
51.62 + *
51.63 + * Each proxy instance has an associated <i>invocation handler</i>
51.64 + * object, which implements the interface {@link InvocationHandler}.
51.65 + * A method invocation on a proxy instance through one of its proxy
51.66 + * interfaces will be dispatched to the {@link InvocationHandler#invoke
51.67 + * invoke} method of the instance's invocation handler, passing the proxy
51.68 + * instance, a {@code java.lang.reflect.Method} object identifying
51.69 + * the method that was invoked, and an array of type {@code Object}
51.70 + * containing the arguments. The invocation handler processes the
51.71 + * encoded method invocation as appropriate and the result that it
51.72 + * returns will be returned as the result of the method invocation on
51.73 + * the proxy instance.
51.74 + *
51.75 + * <p>A proxy class has the following properties:
51.76 + *
51.77 + * <ul>
51.78 + * <li>Proxy classes are public, final, and not abstract.
51.79 + *
51.80 + * <li>The unqualified name of a proxy class is unspecified. The space
51.81 + * of class names that begin with the string {@code "$Proxy"}
51.82 + * should be, however, reserved for proxy classes.
51.83 + *
51.84 + * <li>A proxy class extends {@code java.lang.reflect.Proxy}.
51.85 + *
51.86 + * <li>A proxy class implements exactly the interfaces specified at its
51.87 + * creation, in the same order.
51.88 + *
51.89 + * <li>If a proxy class implements a non-public interface, then it will
51.90 + * be defined in the same package as that interface. Otherwise, the
51.91 + * package of a proxy class is also unspecified. Note that package
51.92 + * sealing will not prevent a proxy class from being successfully defined
51.93 + * in a particular package at runtime, and neither will classes already
51.94 + * defined by the same class loader and the same package with particular
51.95 + * signers.
51.96 + *
51.97 + * <li>Since a proxy class implements all of the interfaces specified at
51.98 + * its creation, invoking {@code getInterfaces} on its
51.99 + * {@code Class} object will return an array containing the same
51.100 + * list of interfaces (in the order specified at its creation), invoking
51.101 + * {@code getMethods} on its {@code Class} object will return
51.102 + * an array of {@code Method} objects that include all of the
51.103 + * methods in those interfaces, and invoking {@code getMethod} will
51.104 + * find methods in the proxy interfaces as would be expected.
51.105 + *
51.106 + * <li>The {@link Proxy#isProxyClass Proxy.isProxyClass} method will
51.107 + * return true if it is passed a proxy class-- a class returned by
51.108 + * {@code Proxy.getProxyClass} or the class of an object returned by
51.109 + * {@code Proxy.newProxyInstance}-- and false otherwise.
51.110 + *
51.111 + * <li>The {@code java.security.ProtectionDomain} of a proxy class
51.112 + * is the same as that of system classes loaded by the bootstrap class
51.113 + * loader, such as {@code java.lang.Object}, because the code for a
51.114 + * proxy class is generated by trusted system code. This protection
51.115 + * domain will typically be granted
51.116 + * {@code java.security.AllPermission}.
51.117 + *
51.118 + * <li>Each proxy class has one public constructor that takes one argument,
51.119 + * an implementation of the interface {@link InvocationHandler}, to set
51.120 + * the invocation handler for a proxy instance. Rather than having to use
51.121 + * the reflection API to access the public constructor, a proxy instance
51.122 + * can be also be created by calling the {@link Proxy#newProxyInstance
51.123 + * Proxy.newProxyInstance} method, which combines the actions of calling
51.124 + * {@link Proxy#getProxyClass Proxy.getProxyClass} with invoking the
51.125 + * constructor with an invocation handler.
51.126 + * </ul>
51.127 + *
51.128 + * <p>A proxy instance has the following properties:
51.129 + *
51.130 + * <ul>
51.131 + * <li>Given a proxy instance {@code proxy} and one of the
51.132 + * interfaces implemented by its proxy class {@code Foo}, the
51.133 + * following expression will return true:
51.134 + * <pre>
51.135 + * {@code proxy instanceof Foo}
51.136 + * </pre>
51.137 + * and the following cast operation will succeed (rather than throwing
51.138 + * a {@code ClassCastException}):
51.139 + * <pre>
51.140 + * {@code (Foo) proxy}
51.141 + * </pre>
51.142 + *
51.143 + * <li>Each proxy instance has an associated invocation handler, the one
51.144 + * that was passed to its constructor. The static
51.145 + * {@link Proxy#getInvocationHandler Proxy.getInvocationHandler} method
51.146 + * will return the invocation handler associated with the proxy instance
51.147 + * passed as its argument.
51.148 + *
51.149 + * <li>An interface method invocation on a proxy instance will be
51.150 + * encoded and dispatched to the invocation handler's {@link
51.151 + * InvocationHandler#invoke invoke} method as described in the
51.152 + * documentation for that method.
51.153 + *
51.154 + * <li>An invocation of the {@code hashCode},
51.155 + * {@code equals}, or {@code toString} methods declared in
51.156 + * {@code java.lang.Object} on a proxy instance will be encoded and
51.157 + * dispatched to the invocation handler's {@code invoke} method in
51.158 + * the same manner as interface method invocations are encoded and
51.159 + * dispatched, as described above. The declaring class of the
51.160 + * {@code Method} object passed to {@code invoke} will be
51.161 + * {@code java.lang.Object}. Other public methods of a proxy
51.162 + * instance inherited from {@code java.lang.Object} are not
51.163 + * overridden by a proxy class, so invocations of those methods behave
51.164 + * like they do for instances of {@code java.lang.Object}.
51.165 + * </ul>
51.166 + *
51.167 + * <h3>Methods Duplicated in Multiple Proxy Interfaces</h3>
51.168 + *
51.169 + * <p>When two or more interfaces of a proxy class contain a method with
51.170 + * the same name and parameter signature, the order of the proxy class's
51.171 + * interfaces becomes significant. When such a <i>duplicate method</i>
51.172 + * is invoked on a proxy instance, the {@code Method} object passed
51.173 + * to the invocation handler will not necessarily be the one whose
51.174 + * declaring class is assignable from the reference type of the interface
51.175 + * that the proxy's method was invoked through. This limitation exists
51.176 + * because the corresponding method implementation in the generated proxy
51.177 + * class cannot determine which interface it was invoked through.
51.178 + * Therefore, when a duplicate method is invoked on a proxy instance,
51.179 + * the {@code Method} object for the method in the foremost interface
51.180 + * that contains the method (either directly or inherited through a
51.181 + * superinterface) in the proxy class's list of interfaces is passed to
51.182 + * the invocation handler's {@code invoke} method, regardless of the
51.183 + * reference type through which the method invocation occurred.
51.184 + *
51.185 + * <p>If a proxy interface contains a method with the same name and
51.186 + * parameter signature as the {@code hashCode}, {@code equals},
51.187 + * or {@code toString} methods of {@code java.lang.Object},
51.188 + * when such a method is invoked on a proxy instance, the
51.189 + * {@code Method} object passed to the invocation handler will have
51.190 + * {@code java.lang.Object} as its declaring class. In other words,
51.191 + * the public, non-final methods of {@code java.lang.Object}
51.192 + * logically precede all of the proxy interfaces for the determination of
51.193 + * which {@code Method} object to pass to the invocation handler.
51.194 + *
51.195 + * <p>Note also that when a duplicate method is dispatched to an
51.196 + * invocation handler, the {@code invoke} method may only throw
51.197 + * checked exception types that are assignable to one of the exception
51.198 + * types in the {@code throws} clause of the method in <i>all</i> of
51.199 + * the proxy interfaces that it can be invoked through. If the
51.200 + * {@code invoke} method throws a checked exception that is not
51.201 + * assignable to any of the exception types declared by the method in one
51.202 + * of the proxy interfaces that it can be invoked through, then an
51.203 + * unchecked {@code UndeclaredThrowableException} will be thrown by
51.204 + * the invocation on the proxy instance. This restriction means that not
51.205 + * all of the exception types returned by invoking
51.206 + * {@code getExceptionTypes} on the {@code Method} object
51.207 + * passed to the {@code invoke} method can necessarily be thrown
51.208 + * successfully by the {@code invoke} method.
51.209 + *
51.210 + * @author Peter Jones
51.211 + * @see InvocationHandler
51.212 + * @since 1.3
51.213 + */
51.214 +public class Proxy implements java.io.Serializable {
51.215 +
51.216 + private static final long serialVersionUID = -2222568056686623797L;
51.217 +
51.218 +
51.219 +
51.220 + /**
51.221 + * the invocation handler for this proxy instance.
51.222 + * @serial
51.223 + */
51.224 + protected InvocationHandler h;
51.225 +
51.226 + /**
51.227 + * Prohibits instantiation.
51.228 + */
51.229 + private Proxy() {
51.230 + }
51.231 +
51.232 + /**
51.233 + * Constructs a new {@code Proxy} instance from a subclass
51.234 + * (typically, a dynamic proxy class) with the specified value
51.235 + * for its invocation handler.
51.236 + *
51.237 + * @param h the invocation handler for this proxy instance
51.238 + */
51.239 + protected Proxy(InvocationHandler h) {
51.240 + this.h = h;
51.241 + }
51.242 +
51.243 + /**
51.244 + * Returns the {@code java.lang.Class} object for a proxy class
51.245 + * given a class loader and an array of interfaces. The proxy class
51.246 + * will be defined by the specified class loader and will implement
51.247 + * all of the supplied interfaces. If a proxy class for the same
51.248 + * permutation of interfaces has already been defined by the class
51.249 + * loader, then the existing proxy class will be returned; otherwise,
51.250 + * a proxy class for those interfaces will be generated dynamically
51.251 + * and defined by the class loader.
51.252 + *
51.253 + * <p>There are several restrictions on the parameters that may be
51.254 + * passed to {@code Proxy.getProxyClass}:
51.255 + *
51.256 + * <ul>
51.257 + * <li>All of the {@code Class} objects in the
51.258 + * {@code interfaces} array must represent interfaces, not
51.259 + * classes or primitive types.
51.260 + *
51.261 + * <li>No two elements in the {@code interfaces} array may
51.262 + * refer to identical {@code Class} objects.
51.263 + *
51.264 + * <li>All of the interface types must be visible by name through the
51.265 + * specified class loader. In other words, for class loader
51.266 + * {@code cl} and every interface {@code i}, the following
51.267 + * expression must be true:
51.268 + * <pre>
51.269 + * Class.forName(i.getName(), false, cl) == i
51.270 + * </pre>
51.271 + *
51.272 + * <li>All non-public interfaces must be in the same package;
51.273 + * otherwise, it would not be possible for the proxy class to
51.274 + * implement all of the interfaces, regardless of what package it is
51.275 + * defined in.
51.276 + *
51.277 + * <li>For any set of member methods of the specified interfaces
51.278 + * that have the same signature:
51.279 + * <ul>
51.280 + * <li>If the return type of any of the methods is a primitive
51.281 + * type or void, then all of the methods must have that same
51.282 + * return type.
51.283 + * <li>Otherwise, one of the methods must have a return type that
51.284 + * is assignable to all of the return types of the rest of the
51.285 + * methods.
51.286 + * </ul>
51.287 + *
51.288 + * <li>The resulting proxy class must not exceed any limits imposed
51.289 + * on classes by the virtual machine. For example, the VM may limit
51.290 + * the number of interfaces that a class may implement to 65535; in
51.291 + * that case, the size of the {@code interfaces} array must not
51.292 + * exceed 65535.
51.293 + * </ul>
51.294 + *
51.295 + * <p>If any of these restrictions are violated,
51.296 + * {@code Proxy.getProxyClass} will throw an
51.297 + * {@code IllegalArgumentException}. If the {@code interfaces}
51.298 + * array argument or any of its elements are {@code null}, a
51.299 + * {@code NullPointerException} will be thrown.
51.300 + *
51.301 + * <p>Note that the order of the specified proxy interfaces is
51.302 + * significant: two requests for a proxy class with the same combination
51.303 + * of interfaces but in a different order will result in two distinct
51.304 + * proxy classes.
51.305 + *
51.306 + * @param loader the class loader to define the proxy class
51.307 + * @param interfaces the list of interfaces for the proxy class
51.308 + * to implement
51.309 + * @return a proxy class that is defined in the specified class loader
51.310 + * and that implements the specified interfaces
51.311 + * @throws IllegalArgumentException if any of the restrictions on the
51.312 + * parameters that may be passed to {@code getProxyClass}
51.313 + * are violated
51.314 + * @throws NullPointerException if the {@code interfaces} array
51.315 + * argument or any of its elements are {@code null}
51.316 + */
51.317 + public static Class<?> getProxyClass(ClassLoader loader,
51.318 + Class<?>... interfaces)
51.319 + throws IllegalArgumentException
51.320 + {
51.321 + throw new IllegalArgumentException();
51.322 + }
51.323 +
51.324 + /**
51.325 + * Returns an instance of a proxy class for the specified interfaces
51.326 + * that dispatches method invocations to the specified invocation
51.327 + * handler. This method is equivalent to:
51.328 + * <pre>
51.329 + * Proxy.getProxyClass(loader, interfaces).
51.330 + * getConstructor(new Class[] { InvocationHandler.class }).
51.331 + * newInstance(new Object[] { handler });
51.332 + * </pre>
51.333 + *
51.334 + * <p>{@code Proxy.newProxyInstance} throws
51.335 + * {@code IllegalArgumentException} for the same reasons that
51.336 + * {@code Proxy.getProxyClass} does.
51.337 + *
51.338 + * @param loader the class loader to define the proxy class
51.339 + * @param interfaces the list of interfaces for the proxy class
51.340 + * to implement
51.341 + * @param h the invocation handler to dispatch method invocations to
51.342 + * @return a proxy instance with the specified invocation handler of a
51.343 + * proxy class that is defined by the specified class loader
51.344 + * and that implements the specified interfaces
51.345 + * @throws IllegalArgumentException if any of the restrictions on the
51.346 + * parameters that may be passed to {@code getProxyClass}
51.347 + * are violated
51.348 + * @throws NullPointerException if the {@code interfaces} array
51.349 + * argument or any of its elements are {@code null}, or
51.350 + * if the invocation handler, {@code h}, is
51.351 + * {@code null}
51.352 + */
51.353 + public static Object newProxyInstance(ClassLoader loader,
51.354 + Class<?>[] interfaces,
51.355 + InvocationHandler h)
51.356 + throws IllegalArgumentException
51.357 + {
51.358 + if (h == null) {
51.359 + throw new NullPointerException();
51.360 + }
51.361 + throw new IllegalArgumentException();
51.362 + }
51.363 +
51.364 + /**
51.365 + * Returns true if and only if the specified class was dynamically
51.366 + * generated to be a proxy class using the {@code getProxyClass}
51.367 + * method or the {@code newProxyInstance} method.
51.368 + *
51.369 + * <p>The reliability of this method is important for the ability
51.370 + * to use it to make security decisions, so its implementation should
51.371 + * not just test if the class in question extends {@code Proxy}.
51.372 + *
51.373 + * @param cl the class to test
51.374 + * @return {@code true} if the class is a proxy class and
51.375 + * {@code false} otherwise
51.376 + * @throws NullPointerException if {@code cl} is {@code null}
51.377 + */
51.378 + public static boolean isProxyClass(Class<?> cl) {
51.379 + if (cl == null) {
51.380 + throw new NullPointerException();
51.381 + }
51.382 +
51.383 + return false;
51.384 + }
51.385 +
51.386 + /**
51.387 + * Returns the invocation handler for the specified proxy instance.
51.388 + *
51.389 + * @param proxy the proxy instance to return the invocation handler for
51.390 + * @return the invocation handler for the proxy instance
51.391 + * @throws IllegalArgumentException if the argument is not a
51.392 + * proxy instance
51.393 + */
51.394 + public static InvocationHandler getInvocationHandler(Object proxy)
51.395 + throws IllegalArgumentException
51.396 + {
51.397 + /*
51.398 + * Verify that the object is actually a proxy instance.
51.399 + */
51.400 + if (!isProxyClass(proxy.getClass())) {
51.401 + throw new IllegalArgumentException("not a proxy instance");
51.402 + }
51.403 +
51.404 + Proxy p = (Proxy) proxy;
51.405 + return p.h;
51.406 + }
51.407 +
51.408 + private static native Class defineClass0(ClassLoader loader, String name,
51.409 + byte[] b, int off, int len);
51.410 +}
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
52.2 +++ b/emul/mini/src/main/java/java/lang/reflect/UndeclaredThrowableException.java Mon Feb 04 09:37:56 2013 +0100
52.3 @@ -0,0 +1,119 @@
52.4 +/*
52.5 + * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved.
52.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
52.7 + *
52.8 + * This code is free software; you can redistribute it and/or modify it
52.9 + * under the terms of the GNU General Public License version 2 only, as
52.10 + * published by the Free Software Foundation. Oracle designates this
52.11 + * particular file as subject to the "Classpath" exception as provided
52.12 + * by Oracle in the LICENSE file that accompanied this code.
52.13 + *
52.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
52.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
52.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
52.17 + * version 2 for more details (a copy is included in the LICENSE file that
52.18 + * accompanied this code).
52.19 + *
52.20 + * You should have received a copy of the GNU General Public License version
52.21 + * 2 along with this work; if not, write to the Free Software Foundation,
52.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
52.23 + *
52.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
52.25 + * or visit www.oracle.com if you need additional information or have any
52.26 + * questions.
52.27 + */
52.28 +
52.29 +package java.lang.reflect;
52.30 +
52.31 +/**
52.32 + * Thrown by a method invocation on a proxy instance if its invocation
52.33 + * handler's {@link InvocationHandler#invoke invoke} method throws a
52.34 + * checked exception (a {@code Throwable} that is not assignable
52.35 + * to {@code RuntimeException} or {@code Error}) that
52.36 + * is not assignable to any of the exception types declared in the
52.37 + * {@code throws} clause of the method that was invoked on the
52.38 + * proxy instance and dispatched to the invocation handler.
52.39 + *
52.40 + * <p>An {@code UndeclaredThrowableException} instance contains
52.41 + * the undeclared checked exception that was thrown by the invocation
52.42 + * handler, and it can be retrieved with the
52.43 + * {@code getUndeclaredThrowable()} method.
52.44 + * {@code UndeclaredThrowableException} extends
52.45 + * {@code RuntimeException}, so it is an unchecked exception
52.46 + * that wraps a checked exception.
52.47 + *
52.48 + * <p>As of release 1.4, this exception has been retrofitted to
52.49 + * conform to the general purpose exception-chaining mechanism. The
52.50 + * "undeclared checked exception that was thrown by the invocation
52.51 + * handler" that may be provided at construction time and accessed via
52.52 + * the {@link #getUndeclaredThrowable()} method is now known as the
52.53 + * <i>cause</i>, and may be accessed via the {@link
52.54 + * Throwable#getCause()} method, as well as the aforementioned "legacy
52.55 + * method."
52.56 + *
52.57 + * @author Peter Jones
52.58 + * @see InvocationHandler
52.59 + * @since 1.3
52.60 + */
52.61 +public class UndeclaredThrowableException extends RuntimeException {
52.62 + static final long serialVersionUID = 330127114055056639L;
52.63 +
52.64 + /**
52.65 + * the undeclared checked exception that was thrown
52.66 + * @serial
52.67 + */
52.68 + private Throwable undeclaredThrowable;
52.69 +
52.70 + /**
52.71 + * Constructs an {@code UndeclaredThrowableException} with the
52.72 + * specified {@code Throwable}.
52.73 + *
52.74 + * @param undeclaredThrowable the undeclared checked exception
52.75 + * that was thrown
52.76 + */
52.77 + public UndeclaredThrowableException(Throwable undeclaredThrowable) {
52.78 + super((Throwable) null); // Disallow initCause
52.79 + this.undeclaredThrowable = undeclaredThrowable;
52.80 + }
52.81 +
52.82 + /**
52.83 + * Constructs an {@code UndeclaredThrowableException} with the
52.84 + * specified {@code Throwable} and a detail message.
52.85 + *
52.86 + * @param undeclaredThrowable the undeclared checked exception
52.87 + * that was thrown
52.88 + * @param s the detail message
52.89 + */
52.90 + public UndeclaredThrowableException(Throwable undeclaredThrowable,
52.91 + String s)
52.92 + {
52.93 + super(s, null); // Disallow initCause
52.94 + this.undeclaredThrowable = undeclaredThrowable;
52.95 + }
52.96 +
52.97 + /**
52.98 + * Returns the {@code Throwable} instance wrapped in this
52.99 + * {@code UndeclaredThrowableException}, which may be {@code null}.
52.100 + *
52.101 + * <p>This method predates the general-purpose exception chaining facility.
52.102 + * The {@link Throwable#getCause()} method is now the preferred means of
52.103 + * obtaining this information.
52.104 + *
52.105 + * @return the undeclared checked exception that was thrown
52.106 + */
52.107 + public Throwable getUndeclaredThrowable() {
52.108 + return undeclaredThrowable;
52.109 + }
52.110 +
52.111 + /**
52.112 + * Returns the cause of this exception (the {@code Throwable}
52.113 + * instance wrapped in this {@code UndeclaredThrowableException},
52.114 + * which may be {@code null}).
52.115 + *
52.116 + * @return the cause of this exception.
52.117 + * @since 1.4
52.118 + */
52.119 + public Throwable getCause() {
52.120 + return undeclaredThrowable;
52.121 + }
52.122 +}
53.1 --- a/emul/mini/src/main/java/java/net/URL.java Fri Feb 01 16:34:51 2013 +0100
53.2 +++ b/emul/mini/src/main/java/java/net/URL.java Mon Feb 04 09:37:56 2013 +0100
53.3 @@ -25,6 +25,7 @@
53.4
53.5 package java.net;
53.6
53.7 +import java.io.ByteArrayInputStream;
53.8 import java.io.IOException;
53.9 import java.io.InputStream;
53.10 import org.apidesign.bck2brwsr.core.JavaScriptBody;
53.11 @@ -505,6 +506,17 @@
53.12 public URL(URL context, String spec, URLStreamHandler handler)
53.13 throws MalformedURLException
53.14 {
53.15 + this(findContext(context), spec, handler != null);
53.16 + }
53.17 +
53.18 + private URL(URL context, String spec, boolean ishandler)
53.19 + throws MalformedURLException {
53.20 + // Check for permission to specify a handler
53.21 + if (ishandler) {
53.22 + throw new SecurityException();
53.23 + }
53.24 + URLStreamHandler handler = null;
53.25 +
53.26 String original = spec;
53.27 int i, limit, c;
53.28 int start = 0;
53.29 @@ -512,10 +524,6 @@
53.30 boolean aRef=false;
53.31 boolean isRelative = false;
53.32
53.33 - // Check for permission to specify a handler
53.34 - if (handler != null) {
53.35 - throw new SecurityException();
53.36 - }
53.37
53.38 try {
53.39 limit = spec.length();
53.40 @@ -962,7 +970,11 @@
53.41 if (is != null) {
53.42 return is;
53.43 }
53.44 - throw new IOException();
53.45 + byte[] arr = (byte[]) getContent(new Class[] { byte[].class });
53.46 + if (arr == null) {
53.47 + throw new IOException();
53.48 + }
53.49 + return new ByteArrayInputStream(arr);
53.50 }
53.51
53.52 /**
53.53 @@ -987,6 +999,17 @@
53.54 )
53.55 private static native String loadText(String url) throws IOException;
53.56
53.57 + @JavaScriptBody(args = { "url", "arr" }, body = ""
53.58 + + "var request = new XMLHttpRequest();\n"
53.59 + + "request.open('GET', url, false);\n"
53.60 + + "request.overrideMimeType('text\\/plain; charset=x-user-defined');\n"
53.61 + + "request.send();\n"
53.62 + + "var t = request.responseText;\n"
53.63 + + "for (var i = 0; i < t.length; i++) arr.push(t.charCodeAt(i) & 0xff);\n"
53.64 + + "return arr;\n"
53.65 + )
53.66 + private static native Object loadBytes(String url, byte[] arr) throws IOException;
53.67 +
53.68 /**
53.69 * Gets the contents of this URL. This method is a shorthand for:
53.70 * <blockquote><pre>
53.71 @@ -1005,7 +1028,10 @@
53.72 throws java.io.IOException {
53.73 for (Class<?> c : classes) {
53.74 if (c == String.class) {
53.75 - return getContent();
53.76 + return loadText(toExternalForm());
53.77 + }
53.78 + if (c == byte[].class) {
53.79 + return loadBytes(toExternalForm(), new byte[0]);
53.80 }
53.81 }
53.82 return null;
53.83 @@ -1016,6 +1042,23 @@
53.84 return universal;
53.85 }
53.86
53.87 + private static URL findContext(URL context) throws MalformedURLException {
53.88 + if (context == null) {
53.89 + String base = findBaseURL();
53.90 + if (base != null) {
53.91 + context = new URL(null, base, false);
53.92 + }
53.93 + }
53.94 + return context;
53.95 + }
53.96 +
53.97 + @JavaScriptBody(args = {}, body =
53.98 + "if (typeof window !== 'object') return null;\n"
53.99 + + "if (!window.location) return null;\n"
53.100 + + "if (!window.location.href) return null;\n"
53.101 + + "return window.location.href;\n"
53.102 + )
53.103 + private static native String findBaseURL();
53.104 }
53.105 class Parts {
53.106 String path, query, ref;
54.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
54.2 +++ b/emul/mini/src/main/java/java/util/zip/Adler32.java Mon Feb 04 09:37:56 2013 +0100
54.3 @@ -0,0 +1,205 @@
54.4 +/* Adler32.java - Computes Adler32 data checksum of a data stream
54.5 + Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
54.6 +
54.7 +This file is part of GNU Classpath.
54.8 +
54.9 +GNU Classpath is free software; you can redistribute it and/or modify
54.10 +it under the terms of the GNU General Public License as published by
54.11 +the Free Software Foundation; either version 2, or (at your option)
54.12 +any later version.
54.13 +
54.14 +GNU Classpath is distributed in the hope that it will be useful, but
54.15 +WITHOUT ANY WARRANTY; without even the implied warranty of
54.16 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
54.17 +General Public License for more details.
54.18 +
54.19 +You should have received a copy of the GNU General Public License
54.20 +along with GNU Classpath; see the file COPYING. If not, write to the
54.21 +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
54.22 +02111-1307 USA.
54.23 +
54.24 +Linking this library statically or dynamically with other modules is
54.25 +making a combined work based on this library. Thus, the terms and
54.26 +conditions of the GNU General Public License cover the whole
54.27 +combination.
54.28 +
54.29 +As a special exception, the copyright holders of this library give you
54.30 +permission to link this library with independent modules to produce an
54.31 +executable, regardless of the license terms of these independent
54.32 +modules, and to copy and distribute the resulting executable under
54.33 +terms of your choice, provided that you also meet, for each linked
54.34 +independent module, the terms and conditions of the license of that
54.35 +module. An independent module is a module which is not derived from
54.36 +or based on this library. If you modify this library, you may extend
54.37 +this exception to your version of the library, but you are not
54.38 +obligated to do so. If you do not wish to do so, delete this
54.39 +exception statement from your version. */
54.40 +
54.41 +package java.util.zip;
54.42 +
54.43 +/*
54.44 + * Written using on-line Java Platform 1.2 API Specification, as well
54.45 + * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
54.46 + * The actual Adler32 algorithm is taken from RFC 1950.
54.47 + * Status: Believed complete and correct.
54.48 + */
54.49 +
54.50 +/**
54.51 + * Computes Adler32 checksum for a stream of data. An Adler32
54.52 + * checksum is not as reliable as a CRC32 checksum, but a lot faster to
54.53 + * compute.
54.54 + *<p>
54.55 + * The specification for Adler32 may be found in RFC 1950.
54.56 + * (ZLIB Compressed Data Format Specification version 3.3)
54.57 + *<p>
54.58 + *<p>
54.59 + * From that document:
54.60 + *<p>
54.61 + * "ADLER32 (Adler-32 checksum)
54.62 + * This contains a checksum value of the uncompressed data
54.63 + * (excluding any dictionary data) computed according to Adler-32
54.64 + * algorithm. This algorithm is a 32-bit extension and improvement
54.65 + * of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073
54.66 + * standard.
54.67 + *<p>
54.68 + * Adler-32 is composed of two sums accumulated per byte: s1 is
54.69 + * the sum of all bytes, s2 is the sum of all s1 values. Both sums
54.70 + * are done modulo 65521. s1 is initialized to 1, s2 to zero. The
54.71 + * Adler-32 checksum is stored as s2*65536 + s1 in most-
54.72 + * significant-byte first (network) order."
54.73 + *<p>
54.74 + * "8.2. The Adler-32 algorithm
54.75 + *<p>
54.76 + * The Adler-32 algorithm is much faster than the CRC32 algorithm yet
54.77 + * still provides an extremely low probability of undetected errors.
54.78 + *<p>
54.79 + * The modulo on unsigned long accumulators can be delayed for 5552
54.80 + * bytes, so the modulo operation time is negligible. If the bytes
54.81 + * are a, b, c, the second sum is 3a + 2b + c + 3, and so is position
54.82 + * and order sensitive, unlike the first sum, which is just a
54.83 + * checksum. That 65521 is prime is important to avoid a possible
54.84 + * large class of two-byte errors that leave the check unchanged.
54.85 + * (The Fletcher checksum uses 255, which is not prime and which also
54.86 + * makes the Fletcher check insensitive to single byte changes 0 <->
54.87 + * 255.)
54.88 + *<p>
54.89 + * The sum s1 is initialized to 1 instead of zero to make the length
54.90 + * of the sequence part of s2, so that the length does not have to be
54.91 + * checked separately. (Any sequence of zeroes has a Fletcher
54.92 + * checksum of zero.)"
54.93 + *
54.94 + * @author John Leuner, Per Bothner
54.95 + * @since JDK 1.1
54.96 + *
54.97 + * @see InflaterInputStream
54.98 + * @see DeflaterOutputStream
54.99 + */
54.100 +public class Adler32 implements Checksum
54.101 +{
54.102 +
54.103 + /** largest prime smaller than 65536 */
54.104 + private static final int BASE = 65521;
54.105 +
54.106 + private int checksum; //we do all in int.
54.107 +
54.108 + //Note that java doesn't have unsigned integers,
54.109 + //so we have to be careful with what arithmetic
54.110 + //we do. We return the checksum as a long to
54.111 + //avoid sign confusion.
54.112 +
54.113 + /**
54.114 + * Creates a new instance of the <code>Adler32</code> class.
54.115 + * The checksum starts off with a value of 1.
54.116 + */
54.117 + public Adler32 ()
54.118 + {
54.119 + reset();
54.120 + }
54.121 +
54.122 + /**
54.123 + * Resets the Adler32 checksum to the initial value.
54.124 + */
54.125 + public void reset ()
54.126 + {
54.127 + checksum = 1; //Initialize to 1
54.128 + }
54.129 +
54.130 + /**
54.131 + * Updates the checksum with the byte b.
54.132 + *
54.133 + * @param bval the data value to add. The high byte of the int is ignored.
54.134 + */
54.135 + public void update (int bval)
54.136 + {
54.137 + //We could make a length 1 byte array and call update again, but I
54.138 + //would rather not have that overhead
54.139 + int s1 = checksum & 0xffff;
54.140 + int s2 = checksum >>> 16;
54.141 +
54.142 + s1 = (s1 + (bval & 0xFF)) % BASE;
54.143 + s2 = (s1 + s2) % BASE;
54.144 +
54.145 + checksum = (s2 << 16) + s1;
54.146 + }
54.147 +
54.148 + /**
54.149 + * Updates the checksum with the bytes taken from the array.
54.150 + *
54.151 + * @param buffer an array of bytes
54.152 + */
54.153 + public void update (byte[] buffer)
54.154 + {
54.155 + update(buffer, 0, buffer.length);
54.156 + }
54.157 +
54.158 + /**
54.159 + * Updates the checksum with the bytes taken from the array.
54.160 + *
54.161 + * @param buf an array of bytes
54.162 + * @param off the start of the data used for this update
54.163 + * @param len the number of bytes to use for this update
54.164 + */
54.165 + public void update (byte[] buf, int off, int len)
54.166 + {
54.167 + //(By Per Bothner)
54.168 + int s1 = checksum & 0xffff;
54.169 + int s2 = checksum >>> 16;
54.170 +
54.171 + while (len > 0)
54.172 + {
54.173 + // We can defer the modulo operation:
54.174 + // s1 maximally grows from 65521 to 65521 + 255 * 3800
54.175 + // s2 maximally grows by 3800 * median(s1) = 2090079800 < 2^31
54.176 + int n = 3800;
54.177 + if (n > len)
54.178 + n = len;
54.179 + len -= n;
54.180 + while (--n >= 0)
54.181 + {
54.182 + s1 = s1 + (buf[off++] & 0xFF);
54.183 + s2 = s2 + s1;
54.184 + }
54.185 + s1 %= BASE;
54.186 + s2 %= BASE;
54.187 + }
54.188 +
54.189 + /*Old implementation, borrowed from somewhere:
54.190 + int n;
54.191 +
54.192 + while (len-- > 0) {
54.193 +
54.194 + s1 = (s1 + (bs[offset++] & 0xff)) % BASE;
54.195 + s2 = (s2 + s1) % BASE;
54.196 + }*/
54.197 +
54.198 + checksum = (s2 << 16) | s1;
54.199 + }
54.200 +
54.201 + /**
54.202 + * Returns the Adler32 data checksum computed so far.
54.203 + */
54.204 + public long getValue()
54.205 + {
54.206 + return (long) checksum & 0xffffffffL;
54.207 + }
54.208 +}
55.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
55.2 +++ b/emul/mini/src/main/java/java/util/zip/CRC32.java Mon Feb 04 09:37:56 2013 +0100
55.3 @@ -0,0 +1,132 @@
55.4 +/* CRC32.java - Computes CRC32 data checksum of a data stream
55.5 + Copyright (C) 1999. 2000, 2001 Free Software Foundation, Inc.
55.6 +
55.7 +This file is part of GNU Classpath.
55.8 +
55.9 +GNU Classpath is free software; you can redistribute it and/or modify
55.10 +it under the terms of the GNU General Public License as published by
55.11 +the Free Software Foundation; either version 2, or (at your option)
55.12 +any later version.
55.13 +
55.14 +GNU Classpath is distributed in the hope that it will be useful, but
55.15 +WITHOUT ANY WARRANTY; without even the implied warranty of
55.16 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
55.17 +General Public License for more details.
55.18 +
55.19 +You should have received a copy of the GNU General Public License
55.20 +along with GNU Classpath; see the file COPYING. If not, write to the
55.21 +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
55.22 +02111-1307 USA.
55.23 +
55.24 +Linking this library statically or dynamically with other modules is
55.25 +making a combined work based on this library. Thus, the terms and
55.26 +conditions of the GNU General Public License cover the whole
55.27 +combination.
55.28 +
55.29 +As a special exception, the copyright holders of this library give you
55.30 +permission to link this library with independent modules to produce an
55.31 +executable, regardless of the license terms of these independent
55.32 +modules, and to copy and distribute the resulting executable under
55.33 +terms of your choice, provided that you also meet, for each linked
55.34 +independent module, the terms and conditions of the license of that
55.35 +module. An independent module is a module which is not derived from
55.36 +or based on this library. If you modify this library, you may extend
55.37 +this exception to your version of the library, but you are not
55.38 +obligated to do so. If you do not wish to do so, delete this
55.39 +exception statement from your version. */
55.40 +
55.41 +package java.util.zip;
55.42 +
55.43 +/*
55.44 + * Written using on-line Java Platform 1.2 API Specification, as well
55.45 + * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
55.46 + * The actual CRC32 algorithm is taken from RFC 1952.
55.47 + * Status: Believed complete and correct.
55.48 + */
55.49 +
55.50 +/**
55.51 + * Computes CRC32 data checksum of a data stream.
55.52 + * The actual CRC32 algorithm is described in RFC 1952
55.53 + * (GZIP file format specification version 4.3).
55.54 + * Can be used to get the CRC32 over a stream if used with checked input/output
55.55 + * streams.
55.56 + *
55.57 + * @see InflaterInputStream
55.58 + * @see DeflaterOutputStream
55.59 + *
55.60 + * @author Per Bothner
55.61 + * @date April 1, 1999.
55.62 + */
55.63 +public class CRC32 implements Checksum
55.64 +{
55.65 + /** The crc data checksum so far. */
55.66 + private int crc = 0;
55.67 +
55.68 + /** The fast CRC table. Computed once when the CRC32 class is loaded. */
55.69 + private static int[] crc_table = make_crc_table();
55.70 +
55.71 + /** Make the table for a fast CRC. */
55.72 + private static int[] make_crc_table ()
55.73 + {
55.74 + int[] crc_table = new int[256];
55.75 + for (int n = 0; n < 256; n++)
55.76 + {
55.77 + int c = n;
55.78 + for (int k = 8; --k >= 0; )
55.79 + {
55.80 + if ((c & 1) != 0)
55.81 + c = 0xedb88320 ^ (c >>> 1);
55.82 + else
55.83 + c = c >>> 1;
55.84 + }
55.85 + crc_table[n] = c;
55.86 + }
55.87 + return crc_table;
55.88 + }
55.89 +
55.90 + /**
55.91 + * Returns the CRC32 data checksum computed so far.
55.92 + */
55.93 + public long getValue ()
55.94 + {
55.95 + return (long) crc & 0xffffffffL;
55.96 + }
55.97 +
55.98 + /**
55.99 + * Resets the CRC32 data checksum as if no update was ever called.
55.100 + */
55.101 + public void reset () { crc = 0; }
55.102 +
55.103 + /**
55.104 + * Updates the checksum with the int bval.
55.105 + *
55.106 + * @param bval (the byte is taken as the lower 8 bits of bval)
55.107 + */
55.108 +
55.109 + public void update (int bval)
55.110 + {
55.111 + int c = ~crc;
55.112 + c = crc_table[(c ^ bval) & 0xff] ^ (c >>> 8);
55.113 + crc = ~c;
55.114 + }
55.115 +
55.116 + /**
55.117 + * Adds the byte array to the data checksum.
55.118 + *
55.119 + * @param buf the buffer which contains the data
55.120 + * @param off the offset in the buffer where the data starts
55.121 + * @param len the length of the data
55.122 + */
55.123 + public void update (byte[] buf, int off, int len)
55.124 + {
55.125 + int c = ~crc;
55.126 + while (--len >= 0)
55.127 + c = crc_table[(c ^ buf[off++]) & 0xff] ^ (c >>> 8);
55.128 + crc = ~c;
55.129 + }
55.130 +
55.131 + /**
55.132 + * Adds the complete byte array to the data checksum.
55.133 + */
55.134 + public void update (byte[] buf) { update(buf, 0, buf.length); }
55.135 +}
56.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
56.2 +++ b/emul/mini/src/main/java/java/util/zip/Checksum.java Mon Feb 04 09:37:56 2013 +0100
56.3 @@ -0,0 +1,60 @@
56.4 +/*
56.5 + * Copyright (c) 1996, 1999, Oracle and/or its affiliates. All rights reserved.
56.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
56.7 + *
56.8 + * This code is free software; you can redistribute it and/or modify it
56.9 + * under the terms of the GNU General Public License version 2 only, as
56.10 + * published by the Free Software Foundation. Oracle designates this
56.11 + * particular file as subject to the "Classpath" exception as provided
56.12 + * by Oracle in the LICENSE file that accompanied this code.
56.13 + *
56.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
56.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
56.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
56.17 + * version 2 for more details (a copy is included in the LICENSE file that
56.18 + * accompanied this code).
56.19 + *
56.20 + * You should have received a copy of the GNU General Public License version
56.21 + * 2 along with this work; if not, write to the Free Software Foundation,
56.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
56.23 + *
56.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
56.25 + * or visit www.oracle.com if you need additional information or have any
56.26 + * questions.
56.27 + */
56.28 +
56.29 +package java.util.zip;
56.30 +
56.31 +/**
56.32 + * An interface representing a data checksum.
56.33 + *
56.34 + * @author David Connelly
56.35 + */
56.36 +public
56.37 +interface Checksum {
56.38 + /**
56.39 + * Updates the current checksum with the specified byte.
56.40 + *
56.41 + * @param b the byte to update the checksum with
56.42 + */
56.43 + public void update(int b);
56.44 +
56.45 + /**
56.46 + * Updates the current checksum with the specified array of bytes.
56.47 + * @param b the byte array to update the checksum with
56.48 + * @param off the start offset of the data
56.49 + * @param len the number of bytes to use for the update
56.50 + */
56.51 + public void update(byte[] b, int off, int len);
56.52 +
56.53 + /**
56.54 + * Returns the current checksum value.
56.55 + * @return the current checksum value
56.56 + */
56.57 + public long getValue();
56.58 +
56.59 + /**
56.60 + * Resets the checksum to its initial value.
56.61 + */
56.62 + public void reset();
56.63 +}
57.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
57.2 +++ b/emul/mini/src/main/java/java/util/zip/DataFormatException.java Mon Feb 04 09:37:56 2013 +0100
57.3 @@ -0,0 +1,52 @@
57.4 +/*
57.5 + * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
57.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
57.7 + *
57.8 + * This code is free software; you can redistribute it and/or modify it
57.9 + * under the terms of the GNU General Public License version 2 only, as
57.10 + * published by the Free Software Foundation. Oracle designates this
57.11 + * particular file as subject to the "Classpath" exception as provided
57.12 + * by Oracle in the LICENSE file that accompanied this code.
57.13 + *
57.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
57.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
57.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
57.17 + * version 2 for more details (a copy is included in the LICENSE file that
57.18 + * accompanied this code).
57.19 + *
57.20 + * You should have received a copy of the GNU General Public License version
57.21 + * 2 along with this work; if not, write to the Free Software Foundation,
57.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
57.23 + *
57.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
57.25 + * or visit www.oracle.com if you need additional information or have any
57.26 + * questions.
57.27 + */
57.28 +
57.29 +package java.util.zip;
57.30 +
57.31 +/**
57.32 + * Signals that a data format error has occurred.
57.33 + *
57.34 + * @author David Connelly
57.35 + */
57.36 +public
57.37 +class DataFormatException extends Exception {
57.38 + private static final long serialVersionUID = 2219632870893641452L;
57.39 +
57.40 + /**
57.41 + * Constructs a DataFormatException with no detail message.
57.42 + */
57.43 + public DataFormatException() {
57.44 + super();
57.45 + }
57.46 +
57.47 + /**
57.48 + * Constructs a DataFormatException with the specified detail message.
57.49 + * A detail message is a String that describes this particular exception.
57.50 + * @param s the String containing a detail message
57.51 + */
57.52 + public DataFormatException(String s) {
57.53 + super(s);
57.54 + }
57.55 +}
58.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
58.2 +++ b/emul/mini/src/main/java/java/util/zip/Inflater.java Mon Feb 04 09:37:56 2013 +0100
58.3 @@ -0,0 +1,1475 @@
58.4 +/* Inflater.java - Decompress a data stream
58.5 + Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
58.6 +
58.7 +This file is part of GNU Classpath.
58.8 +
58.9 +GNU Classpath is free software; you can redistribute it and/or modify
58.10 +it under the terms of the GNU General Public License as published by
58.11 +the Free Software Foundation; either version 2, or (at your option)
58.12 +any later version.
58.13 +
58.14 +GNU Classpath is distributed in the hope that it will be useful, but
58.15 +WITHOUT ANY WARRANTY; without even the implied warranty of
58.16 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
58.17 +General Public License for more details.
58.18 +
58.19 +You should have received a copy of the GNU General Public License
58.20 +along with GNU Classpath; see the file COPYING. If not, write to the
58.21 +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
58.22 +02111-1307 USA.
58.23 +
58.24 +Linking this library statically or dynamically with other modules is
58.25 +making a combined work based on this library. Thus, the terms and
58.26 +conditions of the GNU General Public License cover the whole
58.27 +combination.
58.28 +
58.29 +As a special exception, the copyright holders of this library give you
58.30 +permission to link this library with independent modules to produce an
58.31 +executable, regardless of the license terms of these independent
58.32 +modules, and to copy and distribute the resulting executable under
58.33 +terms of your choice, provided that you also meet, for each linked
58.34 +independent module, the terms and conditions of the license of that
58.35 +module. An independent module is a module which is not derived from
58.36 +or based on this library. If you modify this library, you may extend
58.37 +this exception to your version of the library, but you are not
58.38 +obligated to do so. If you do not wish to do so, delete this
58.39 +exception statement from your version. */
58.40 +
58.41 +package java.util.zip;
58.42 +
58.43 +import org.apidesign.bck2brwsr.emul.lang.System;
58.44 +
58.45 +/**
58.46 + * This class provides support for general purpose decompression using the
58.47 + * popular ZLIB compression library. The ZLIB compression library was
58.48 + * initially developed as part of the PNG graphics standard and is not
58.49 + * protected by patents. It is fully described in the specifications at
58.50 + * the <a href="package-summary.html#package_description">java.util.zip
58.51 + * package description</a>.
58.52 + *
58.53 + * <p>The following code fragment demonstrates a trivial compression
58.54 + * and decompression of a string using <tt>Deflater</tt> and
58.55 + * <tt>Inflater</tt>.
58.56 + *
58.57 + * <blockquote><pre>
58.58 + * try {
58.59 + * // Encode a String into bytes
58.60 + * String inputString = "blahblahblah\u20AC\u20AC";
58.61 + * byte[] input = inputString.getBytes("UTF-8");
58.62 + *
58.63 + * // Compress the bytes
58.64 + * byte[] output = new byte[100];
58.65 + * Deflater compresser = new Deflater();
58.66 + * compresser.setInput(input);
58.67 + * compresser.finish();
58.68 + * int compressedDataLength = compresser.deflate(output);
58.69 + *
58.70 + * // Decompress the bytes
58.71 + * Inflater decompresser = new Inflater();
58.72 + * decompresser.setInput(output, 0, compressedDataLength);
58.73 + * byte[] result = new byte[100];
58.74 + * int resultLength = decompresser.inflate(result);
58.75 + * decompresser.end();
58.76 + *
58.77 + * // Decode the bytes into a String
58.78 + * String outputString = new String(result, 0, resultLength, "UTF-8");
58.79 + * } catch(java.io.UnsupportedEncodingException ex) {
58.80 + * // handle
58.81 + * } catch (java.util.zip.DataFormatException ex) {
58.82 + * // handle
58.83 + * }
58.84 + * </pre></blockquote>
58.85 + *
58.86 + * @see Deflater
58.87 + * @author David Connelly
58.88 + *
58.89 + */
58.90 +
58.91 +/* Written using on-line Java Platform 1.2 API Specification
58.92 + * and JCL book.
58.93 + * Believed complete and correct.
58.94 + */
58.95 +
58.96 +/**
58.97 + * Inflater is used to decompress data that has been compressed according
58.98 + * to the "deflate" standard described in rfc1950.
58.99 + *
58.100 + * The usage is as following. First you have to set some input with
58.101 + * <code>setInput()</code>, then inflate() it. If inflate doesn't
58.102 + * inflate any bytes there may be three reasons:
58.103 + * <ul>
58.104 + * <li>needsInput() returns true because the input buffer is empty.
58.105 + * You have to provide more input with <code>setInput()</code>.
58.106 + * NOTE: needsInput() also returns true when, the stream is finished.
58.107 + * </li>
58.108 + * <li>needsDictionary() returns true, you have to provide a preset
58.109 + * dictionary with <code>setDictionary()</code>.</li>
58.110 + * <li>finished() returns true, the inflater has finished.</li>
58.111 + * </ul>
58.112 + * Once the first output byte is produced, a dictionary will not be
58.113 + * needed at a later stage.
58.114 + *
58.115 + * @author John Leuner, Jochen Hoenicke
58.116 + * @author Tom Tromey
58.117 + * @date May 17, 1999
58.118 + * @since JDK 1.1
58.119 + */
58.120 +public class Inflater
58.121 +{
58.122 + /* Copy lengths for literal codes 257..285 */
58.123 + private static final int CPLENS[] =
58.124 + {
58.125 + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
58.126 + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
58.127 + };
58.128 +
58.129 + /* Extra bits for literal codes 257..285 */
58.130 + private static final int CPLEXT[] =
58.131 + {
58.132 + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
58.133 + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
58.134 + };
58.135 +
58.136 + /* Copy offsets for distance codes 0..29 */
58.137 + private static final int CPDIST[] = {
58.138 + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
58.139 + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
58.140 + 8193, 12289, 16385, 24577
58.141 + };
58.142 +
58.143 + /* Extra bits for distance codes */
58.144 + private static final int CPDEXT[] = {
58.145 + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
58.146 + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
58.147 + 12, 12, 13, 13
58.148 + };
58.149 +
58.150 + /* This are the state in which the inflater can be. */
58.151 + private static final int DECODE_HEADER = 0;
58.152 + private static final int DECODE_DICT = 1;
58.153 + private static final int DECODE_BLOCKS = 2;
58.154 + private static final int DECODE_STORED_LEN1 = 3;
58.155 + private static final int DECODE_STORED_LEN2 = 4;
58.156 + private static final int DECODE_STORED = 5;
58.157 + private static final int DECODE_DYN_HEADER = 6;
58.158 + private static final int DECODE_HUFFMAN = 7;
58.159 + private static final int DECODE_HUFFMAN_LENBITS = 8;
58.160 + private static final int DECODE_HUFFMAN_DIST = 9;
58.161 + private static final int DECODE_HUFFMAN_DISTBITS = 10;
58.162 + private static final int DECODE_CHKSUM = 11;
58.163 + private static final int FINISHED = 12;
58.164 +
58.165 + /** This variable contains the current state. */
58.166 + private int mode;
58.167 +
58.168 + /**
58.169 + * The adler checksum of the dictionary or of the decompressed
58.170 + * stream, as it is written in the header resp. footer of the
58.171 + * compressed stream. <br>
58.172 + *
58.173 + * Only valid if mode is DECODE_DICT or DECODE_CHKSUM.
58.174 + */
58.175 + private int readAdler;
58.176 + /**
58.177 + * The number of bits needed to complete the current state. This
58.178 + * is valid, if mode is DECODE_DICT, DECODE_CHKSUM,
58.179 + * DECODE_HUFFMAN_LENBITS or DECODE_HUFFMAN_DISTBITS.
58.180 + */
58.181 + private int neededBits;
58.182 + private int repLength, repDist;
58.183 + private int uncomprLen;
58.184 + /**
58.185 + * True, if the last block flag was set in the last block of the
58.186 + * inflated stream. This means that the stream ends after the
58.187 + * current block.
58.188 + */
58.189 + private boolean isLastBlock;
58.190 +
58.191 + /**
58.192 + * The total number of inflated bytes.
58.193 + */
58.194 + private long totalOut;
58.195 + /**
58.196 + * The total number of bytes set with setInput(). This is not the
58.197 + * value returned by getTotalIn(), since this also includes the
58.198 + * unprocessed input.
58.199 + */
58.200 + private long totalIn;
58.201 + /**
58.202 + * This variable stores the nowrap flag that was given to the constructor.
58.203 + * True means, that the inflated stream doesn't contain a header nor the
58.204 + * checksum in the footer.
58.205 + */
58.206 + private boolean nowrap;
58.207 +
58.208 + private StreamManipulator input;
58.209 + private OutputWindow outputWindow;
58.210 + private InflaterDynHeader dynHeader;
58.211 + private InflaterHuffmanTree litlenTree, distTree;
58.212 + private Adler32 adler;
58.213 +
58.214 + /**
58.215 + * Creates a new inflater.
58.216 + */
58.217 + public Inflater ()
58.218 + {
58.219 + this (false);
58.220 + }
58.221 +
58.222 + /**
58.223 + * Creates a new inflater.
58.224 + * @param nowrap true if no header and checksum field appears in the
58.225 + * stream. This is used for GZIPed input. For compatibility with
58.226 + * Sun JDK you should provide one byte of input more than needed in
58.227 + * this case.
58.228 + */
58.229 + public Inflater (boolean nowrap)
58.230 + {
58.231 + this.nowrap = nowrap;
58.232 + this.adler = new Adler32();
58.233 + input = new StreamManipulator();
58.234 + outputWindow = new OutputWindow();
58.235 + mode = nowrap ? DECODE_BLOCKS : DECODE_HEADER;
58.236 + }
58.237 +
58.238 + /**
58.239 + * Finalizes this object.
58.240 + */
58.241 + protected void finalize ()
58.242 + {
58.243 + /* Exists only for compatibility */
58.244 + }
58.245 +
58.246 + /**
58.247 + * Frees all objects allocated by the inflater. There's no reason
58.248 + * to call this, since you can just rely on garbage collection (even
58.249 + * for the Sun implementation). Exists only for compatibility
58.250 + * with Sun's JDK, where the compressor allocates native memory.
58.251 + * If you call any method (even reset) afterwards the behaviour is
58.252 + * <i>undefined</i>.
58.253 + * @deprecated Just clear all references to inflater instead.
58.254 + */
58.255 + public void end ()
58.256 + {
58.257 + outputWindow = null;
58.258 + input = null;
58.259 + dynHeader = null;
58.260 + litlenTree = null;
58.261 + distTree = null;
58.262 + adler = null;
58.263 + }
58.264 +
58.265 + /**
58.266 + * Returns true, if the inflater has finished. This means, that no
58.267 + * input is needed and no output can be produced.
58.268 + */
58.269 + public boolean finished()
58.270 + {
58.271 + return mode == FINISHED && outputWindow.getAvailable() == 0;
58.272 + }
58.273 +
58.274 + /**
58.275 + * Gets the adler checksum. This is either the checksum of all
58.276 + * uncompressed bytes returned by inflate(), or if needsDictionary()
58.277 + * returns true (and thus no output was yet produced) this is the
58.278 + * adler checksum of the expected dictionary.
58.279 + * @returns the adler checksum.
58.280 + */
58.281 + public int getAdler()
58.282 + {
58.283 + return needsDictionary() ? readAdler : (int) adler.getValue();
58.284 + }
58.285 +
58.286 + /**
58.287 + * Gets the number of unprocessed input. Useful, if the end of the
58.288 + * stream is reached and you want to further process the bytes after
58.289 + * the deflate stream.
58.290 + * @return the number of bytes of the input which were not processed.
58.291 + */
58.292 + public int getRemaining()
58.293 + {
58.294 + return input.getAvailableBytes();
58.295 + }
58.296 +
58.297 + /**
58.298 + * Gets the total number of processed compressed input bytes.
58.299 + * @return the total number of bytes of processed input bytes.
58.300 + */
58.301 + public int getTotalIn()
58.302 + {
58.303 + return (int)getBytesRead();
58.304 + }
58.305 +
58.306 + /**
58.307 + * Gets the total number of output bytes returned by inflate().
58.308 + * @return the total number of output bytes.
58.309 + */
58.310 + public int getTotalOut()
58.311 + {
58.312 + return (int)totalOut;
58.313 + }
58.314 +
58.315 + public long getBytesWritten() {
58.316 + return totalOut;
58.317 + }
58.318 +
58.319 + public long getBytesRead() {
58.320 + return totalIn - getRemaining();
58.321 + }
58.322 +
58.323 +
58.324 + /**
58.325 + * Inflates the compressed stream to the output buffer. If this
58.326 + * returns 0, you should check, whether needsDictionary(),
58.327 + * needsInput() or finished() returns true, to determine why no
58.328 + * further output is produced.
58.329 + * @param buffer the output buffer.
58.330 + * @return the number of bytes written to the buffer, 0 if no further
58.331 + * output can be produced.
58.332 + * @exception DataFormatException if deflated stream is invalid.
58.333 + * @exception IllegalArgumentException if buf has length 0.
58.334 + */
58.335 + public int inflate (byte[] buf) throws DataFormatException
58.336 + {
58.337 + return inflate (buf, 0, buf.length);
58.338 + }
58.339 +
58.340 + /**
58.341 + * Inflates the compressed stream to the output buffer. If this
58.342 + * returns 0, you should check, whether needsDictionary(),
58.343 + * needsInput() or finished() returns true, to determine why no
58.344 + * further output is produced.
58.345 + * @param buffer the output buffer.
58.346 + * @param off the offset into buffer where the output should start.
58.347 + * @param len the maximum length of the output.
58.348 + * @return the number of bytes written to the buffer, 0 if no further
58.349 + * output can be produced.
58.350 + * @exception DataFormatException if deflated stream is invalid.
58.351 + * @exception IndexOutOfBoundsException if the off and/or len are wrong.
58.352 + */
58.353 + public int inflate (byte[] buf, int off, int len) throws DataFormatException
58.354 + {
58.355 + /* Special case: len may be zero */
58.356 + if (len == 0)
58.357 + return 0;
58.358 + /* Check for correct buff, off, len triple */
58.359 + if (0 > off || off > off + len || off + len > buf.length)
58.360 + throw new ArrayIndexOutOfBoundsException();
58.361 + int count = 0;
58.362 + int more;
58.363 + do
58.364 + {
58.365 + if (mode != DECODE_CHKSUM)
58.366 + {
58.367 + /* Don't give away any output, if we are waiting for the
58.368 + * checksum in the input stream.
58.369 + *
58.370 + * With this trick we have always:
58.371 + * needsInput() and not finished()
58.372 + * implies more output can be produced.
58.373 + */
58.374 + more = outputWindow.copyOutput(buf, off, len);
58.375 + adler.update(buf, off, more);
58.376 + off += more;
58.377 + count += more;
58.378 + totalOut += more;
58.379 + len -= more;
58.380 + if (len == 0)
58.381 + return count;
58.382 + }
58.383 + }
58.384 + while (decode() || (outputWindow.getAvailable() > 0
58.385 + && mode != DECODE_CHKSUM));
58.386 + return count;
58.387 + }
58.388 +
58.389 + /**
58.390 + * Returns true, if a preset dictionary is needed to inflate the input.
58.391 + */
58.392 + public boolean needsDictionary ()
58.393 + {
58.394 + return mode == DECODE_DICT && neededBits == 0;
58.395 + }
58.396 +
58.397 + /**
58.398 + * Returns true, if the input buffer is empty.
58.399 + * You should then call setInput(). <br>
58.400 + *
58.401 + * <em>NOTE</em>: This method also returns true when the stream is finished.
58.402 + */
58.403 + public boolean needsInput ()
58.404 + {
58.405 + return input.needsInput ();
58.406 + }
58.407 +
58.408 + /**
58.409 + * Resets the inflater so that a new stream can be decompressed. All
58.410 + * pending input and output will be discarded.
58.411 + */
58.412 + public void reset ()
58.413 + {
58.414 + mode = nowrap ? DECODE_BLOCKS : DECODE_HEADER;
58.415 + totalIn = totalOut = 0;
58.416 + input.reset();
58.417 + outputWindow.reset();
58.418 + dynHeader = null;
58.419 + litlenTree = null;
58.420 + distTree = null;
58.421 + isLastBlock = false;
58.422 + adler.reset();
58.423 + }
58.424 +
58.425 + /**
58.426 + * Sets the preset dictionary. This should only be called, if
58.427 + * needsDictionary() returns true and it should set the same
58.428 + * dictionary, that was used for deflating. The getAdler()
58.429 + * function returns the checksum of the dictionary needed.
58.430 + * @param buffer the dictionary.
58.431 + * @exception IllegalStateException if no dictionary is needed.
58.432 + * @exception IllegalArgumentException if the dictionary checksum is
58.433 + * wrong.
58.434 + */
58.435 + public void setDictionary (byte[] buffer)
58.436 + {
58.437 + setDictionary(buffer, 0, buffer.length);
58.438 + }
58.439 +
58.440 + /**
58.441 + * Sets the preset dictionary. This should only be called, if
58.442 + * needsDictionary() returns true and it should set the same
58.443 + * dictionary, that was used for deflating. The getAdler()
58.444 + * function returns the checksum of the dictionary needed.
58.445 + * @param buffer the dictionary.
58.446 + * @param off the offset into buffer where the dictionary starts.
58.447 + * @param len the length of the dictionary.
58.448 + * @exception IllegalStateException if no dictionary is needed.
58.449 + * @exception IllegalArgumentException if the dictionary checksum is
58.450 + * wrong.
58.451 + * @exception IndexOutOfBoundsException if the off and/or len are wrong.
58.452 + */
58.453 + public void setDictionary (byte[] buffer, int off, int len)
58.454 + {
58.455 + if (!needsDictionary())
58.456 + throw new IllegalStateException();
58.457 +
58.458 + adler.update(buffer, off, len);
58.459 + if ((int) adler.getValue() != readAdler)
58.460 + throw new IllegalArgumentException("Wrong adler checksum");
58.461 + adler.reset();
58.462 + outputWindow.copyDict(buffer, off, len);
58.463 + mode = DECODE_BLOCKS;
58.464 + }
58.465 +
58.466 + /**
58.467 + * Sets the input. This should only be called, if needsInput()
58.468 + * returns true.
58.469 + * @param buffer the input.
58.470 + * @exception IllegalStateException if no input is needed.
58.471 + */
58.472 + public void setInput (byte[] buf)
58.473 + {
58.474 + setInput (buf, 0, buf.length);
58.475 + }
58.476 +
58.477 + /**
58.478 + * Sets the input. This should only be called, if needsInput()
58.479 + * returns true.
58.480 + * @param buffer the input.
58.481 + * @param off the offset into buffer where the input starts.
58.482 + * @param len the length of the input.
58.483 + * @exception IllegalStateException if no input is needed.
58.484 + * @exception IndexOutOfBoundsException if the off and/or len are wrong.
58.485 + */
58.486 + public void setInput (byte[] buf, int off, int len)
58.487 + {
58.488 + input.setInput (buf, off, len);
58.489 + totalIn += len;
58.490 + }
58.491 + private static final int DEFLATED = 8;
58.492 + /**
58.493 + * Decodes the deflate header.
58.494 + * @return false if more input is needed.
58.495 + * @exception DataFormatException if header is invalid.
58.496 + */
58.497 + private boolean decodeHeader () throws DataFormatException
58.498 + {
58.499 + int header = input.peekBits(16);
58.500 + if (header < 0)
58.501 + return false;
58.502 + input.dropBits(16);
58.503 +
58.504 + /* The header is written in "wrong" byte order */
58.505 + header = ((header << 8) | (header >> 8)) & 0xffff;
58.506 + if (header % 31 != 0)
58.507 + throw new DataFormatException("Header checksum illegal");
58.508 +
58.509 + if ((header & 0x0f00) != (DEFLATED << 8))
58.510 + throw new DataFormatException("Compression Method unknown");
58.511 +
58.512 + /* Maximum size of the backwards window in bits.
58.513 + * We currently ignore this, but we could use it to make the
58.514 + * inflater window more space efficient. On the other hand the
58.515 + * full window (15 bits) is needed most times, anyway.
58.516 + int max_wbits = ((header & 0x7000) >> 12) + 8;
58.517 + */
58.518 +
58.519 + if ((header & 0x0020) == 0) // Dictionary flag?
58.520 + {
58.521 + mode = DECODE_BLOCKS;
58.522 + }
58.523 + else
58.524 + {
58.525 + mode = DECODE_DICT;
58.526 + neededBits = 32;
58.527 + }
58.528 + return true;
58.529 + }
58.530 +
58.531 + /**
58.532 + * Decodes the dictionary checksum after the deflate header.
58.533 + * @return false if more input is needed.
58.534 + */
58.535 + private boolean decodeDict ()
58.536 + {
58.537 + while (neededBits > 0)
58.538 + {
58.539 + int dictByte = input.peekBits(8);
58.540 + if (dictByte < 0)
58.541 + return false;
58.542 + input.dropBits(8);
58.543 + readAdler = (readAdler << 8) | dictByte;
58.544 + neededBits -= 8;
58.545 + }
58.546 + return false;
58.547 + }
58.548 +
58.549 + /**
58.550 + * Decodes the huffman encoded symbols in the input stream.
58.551 + * @return false if more input is needed, true if output window is
58.552 + * full or the current block ends.
58.553 + * @exception DataFormatException if deflated stream is invalid.
58.554 + */
58.555 + private boolean decodeHuffman () throws DataFormatException
58.556 + {
58.557 + int free = outputWindow.getFreeSpace();
58.558 + while (free >= 258)
58.559 + {
58.560 + int symbol;
58.561 + switch (mode)
58.562 + {
58.563 + case DECODE_HUFFMAN:
58.564 + /* This is the inner loop so it is optimized a bit */
58.565 + while (((symbol = litlenTree.getSymbol(input)) & ~0xff) == 0)
58.566 + {
58.567 + outputWindow.write(symbol);
58.568 + if (--free < 258)
58.569 + return true;
58.570 + }
58.571 + if (symbol < 257)
58.572 + {
58.573 + if (symbol < 0)
58.574 + return false;
58.575 + else
58.576 + {
58.577 + /* symbol == 256: end of block */
58.578 + distTree = null;
58.579 + litlenTree = null;
58.580 + mode = DECODE_BLOCKS;
58.581 + return true;
58.582 + }
58.583 + }
58.584 +
58.585 + try
58.586 + {
58.587 + repLength = CPLENS[symbol - 257];
58.588 + neededBits = CPLEXT[symbol - 257];
58.589 + }
58.590 + catch (ArrayIndexOutOfBoundsException ex)
58.591 + {
58.592 + throw new DataFormatException("Illegal rep length code");
58.593 + }
58.594 + /* fall through */
58.595 + case DECODE_HUFFMAN_LENBITS:
58.596 + if (neededBits > 0)
58.597 + {
58.598 + mode = DECODE_HUFFMAN_LENBITS;
58.599 + int i = input.peekBits(neededBits);
58.600 + if (i < 0)
58.601 + return false;
58.602 + input.dropBits(neededBits);
58.603 + repLength += i;
58.604 + }
58.605 + mode = DECODE_HUFFMAN_DIST;
58.606 + /* fall through */
58.607 + case DECODE_HUFFMAN_DIST:
58.608 + symbol = distTree.getSymbol(input);
58.609 + if (symbol < 0)
58.610 + return false;
58.611 + try
58.612 + {
58.613 + repDist = CPDIST[symbol];
58.614 + neededBits = CPDEXT[symbol];
58.615 + }
58.616 + catch (ArrayIndexOutOfBoundsException ex)
58.617 + {
58.618 + throw new DataFormatException("Illegal rep dist code");
58.619 + }
58.620 + /* fall through */
58.621 + case DECODE_HUFFMAN_DISTBITS:
58.622 + if (neededBits > 0)
58.623 + {
58.624 + mode = DECODE_HUFFMAN_DISTBITS;
58.625 + int i = input.peekBits(neededBits);
58.626 + if (i < 0)
58.627 + return false;
58.628 + input.dropBits(neededBits);
58.629 + repDist += i;
58.630 + }
58.631 + outputWindow.repeat(repLength, repDist);
58.632 + free -= repLength;
58.633 + mode = DECODE_HUFFMAN;
58.634 + break;
58.635 + default:
58.636 + throw new IllegalStateException();
58.637 + }
58.638 + }
58.639 + return true;
58.640 + }
58.641 +
58.642 + /**
58.643 + * Decodes the adler checksum after the deflate stream.
58.644 + * @return false if more input is needed.
58.645 + * @exception DataFormatException if checksum doesn't match.
58.646 + */
58.647 + private boolean decodeChksum () throws DataFormatException
58.648 + {
58.649 + while (neededBits > 0)
58.650 + {
58.651 + int chkByte = input.peekBits(8);
58.652 + if (chkByte < 0)
58.653 + return false;
58.654 + input.dropBits(8);
58.655 + readAdler = (readAdler << 8) | chkByte;
58.656 + neededBits -= 8;
58.657 + }
58.658 + if ((int) adler.getValue() != readAdler)
58.659 + throw new DataFormatException("Adler chksum doesn't match: "
58.660 + +Integer.toHexString((int)adler.getValue())
58.661 + +" vs. "+Integer.toHexString(readAdler));
58.662 + mode = FINISHED;
58.663 + return false;
58.664 + }
58.665 +
58.666 + /**
58.667 + * Decodes the deflated stream.
58.668 + * @return false if more input is needed, or if finished.
58.669 + * @exception DataFormatException if deflated stream is invalid.
58.670 + */
58.671 + private boolean decode () throws DataFormatException
58.672 + {
58.673 + switch (mode)
58.674 + {
58.675 + case DECODE_HEADER:
58.676 + return decodeHeader();
58.677 + case DECODE_DICT:
58.678 + return decodeDict();
58.679 + case DECODE_CHKSUM:
58.680 + return decodeChksum();
58.681 +
58.682 + case DECODE_BLOCKS:
58.683 + if (isLastBlock)
58.684 + {
58.685 + if (nowrap)
58.686 + {
58.687 + mode = FINISHED;
58.688 + return false;
58.689 + }
58.690 + else
58.691 + {
58.692 + input.skipToByteBoundary();
58.693 + neededBits = 32;
58.694 + mode = DECODE_CHKSUM;
58.695 + return true;
58.696 + }
58.697 + }
58.698 +
58.699 + int type = input.peekBits(3);
58.700 + if (type < 0)
58.701 + return false;
58.702 + input.dropBits(3);
58.703 +
58.704 + if ((type & 1) != 0)
58.705 + isLastBlock = true;
58.706 + switch (type >> 1)
58.707 + {
58.708 + case DeflaterConstants.STORED_BLOCK:
58.709 + input.skipToByteBoundary();
58.710 + mode = DECODE_STORED_LEN1;
58.711 + break;
58.712 + case DeflaterConstants.STATIC_TREES:
58.713 + litlenTree = InflaterHuffmanTree.defLitLenTree;
58.714 + distTree = InflaterHuffmanTree.defDistTree;
58.715 + mode = DECODE_HUFFMAN;
58.716 + break;
58.717 + case DeflaterConstants.DYN_TREES:
58.718 + dynHeader = new InflaterDynHeader();
58.719 + mode = DECODE_DYN_HEADER;
58.720 + break;
58.721 + default:
58.722 + throw new DataFormatException("Unknown block type "+type);
58.723 + }
58.724 + return true;
58.725 +
58.726 + case DECODE_STORED_LEN1:
58.727 + {
58.728 + if ((uncomprLen = input.peekBits(16)) < 0)
58.729 + return false;
58.730 + input.dropBits(16);
58.731 + mode = DECODE_STORED_LEN2;
58.732 + }
58.733 + /* fall through */
58.734 + case DECODE_STORED_LEN2:
58.735 + {
58.736 + int nlen = input.peekBits(16);
58.737 + if (nlen < 0)
58.738 + return false;
58.739 + input.dropBits(16);
58.740 + if (nlen != (uncomprLen ^ 0xffff))
58.741 + throw new DataFormatException("broken uncompressed block");
58.742 + mode = DECODE_STORED;
58.743 + }
58.744 + /* fall through */
58.745 + case DECODE_STORED:
58.746 + {
58.747 + int more = outputWindow.copyStored(input, uncomprLen);
58.748 + uncomprLen -= more;
58.749 + if (uncomprLen == 0)
58.750 + {
58.751 + mode = DECODE_BLOCKS;
58.752 + return true;
58.753 + }
58.754 + return !input.needsInput();
58.755 + }
58.756 +
58.757 + case DECODE_DYN_HEADER:
58.758 + if (!dynHeader.decode(input))
58.759 + return false;
58.760 + litlenTree = dynHeader.buildLitLenTree();
58.761 + distTree = dynHeader.buildDistTree();
58.762 + mode = DECODE_HUFFMAN;
58.763 + /* fall through */
58.764 + case DECODE_HUFFMAN:
58.765 + case DECODE_HUFFMAN_LENBITS:
58.766 + case DECODE_HUFFMAN_DIST:
58.767 + case DECODE_HUFFMAN_DISTBITS:
58.768 + return decodeHuffman();
58.769 + case FINISHED:
58.770 + return false;
58.771 + default:
58.772 + throw new IllegalStateException();
58.773 + }
58.774 + }
58.775 +
58.776 +
58.777 + interface DeflaterConstants {
58.778 + final static boolean DEBUGGING = false;
58.779 +
58.780 + final static int STORED_BLOCK = 0;
58.781 + final static int STATIC_TREES = 1;
58.782 + final static int DYN_TREES = 2;
58.783 + final static int PRESET_DICT = 0x20;
58.784 +
58.785 + final static int DEFAULT_MEM_LEVEL = 8;
58.786 +
58.787 + final static int MAX_MATCH = 258;
58.788 + final static int MIN_MATCH = 3;
58.789 +
58.790 + final static int MAX_WBITS = 15;
58.791 + final static int WSIZE = 1 << MAX_WBITS;
58.792 + final static int WMASK = WSIZE - 1;
58.793 +
58.794 + final static int HASH_BITS = DEFAULT_MEM_LEVEL + 7;
58.795 + final static int HASH_SIZE = 1 << HASH_BITS;
58.796 + final static int HASH_MASK = HASH_SIZE - 1;
58.797 + final static int HASH_SHIFT = (HASH_BITS + MIN_MATCH - 1) / MIN_MATCH;
58.798 +
58.799 + final static int MIN_LOOKAHEAD = MAX_MATCH + MIN_MATCH + 1;
58.800 + final static int MAX_DIST = WSIZE - MIN_LOOKAHEAD;
58.801 +
58.802 + final static int PENDING_BUF_SIZE = 1 << (DEFAULT_MEM_LEVEL + 8);
58.803 + final static int MAX_BLOCK_SIZE = Math.min(65535, PENDING_BUF_SIZE-5);
58.804 +
58.805 + final static int DEFLATE_STORED = 0;
58.806 + final static int DEFLATE_FAST = 1;
58.807 + final static int DEFLATE_SLOW = 2;
58.808 +
58.809 + final static int GOOD_LENGTH[] = { 0,4, 4, 4, 4, 8, 8, 8, 32, 32 };
58.810 + final static int MAX_LAZY[] = { 0,4, 5, 6, 4,16, 16, 32, 128, 258 };
58.811 + final static int NICE_LENGTH[] = { 0,8,16,32,16,32,128,128, 258, 258 };
58.812 + final static int MAX_CHAIN[] = { 0,4, 8,32,16,32,128,256,1024,4096 };
58.813 + final static int COMPR_FUNC[] = { 0,1, 1, 1, 1, 2, 2, 2, 2, 2 };
58.814 + }
58.815 + private static class InflaterHuffmanTree {
58.816 + private final static int MAX_BITLEN = 15;
58.817 + private short[] tree;
58.818 +
58.819 + public static InflaterHuffmanTree defLitLenTree, defDistTree;
58.820 +
58.821 + static
58.822 + {
58.823 + try
58.824 + {
58.825 + byte[] codeLengths = new byte[288];
58.826 + int i = 0;
58.827 + while (i < 144)
58.828 + codeLengths[i++] = 8;
58.829 + while (i < 256)
58.830 + codeLengths[i++] = 9;
58.831 + while (i < 280)
58.832 + codeLengths[i++] = 7;
58.833 + while (i < 288)
58.834 + codeLengths[i++] = 8;
58.835 + defLitLenTree = new InflaterHuffmanTree(codeLengths);
58.836 +
58.837 + codeLengths = new byte[32];
58.838 + i = 0;
58.839 + while (i < 32)
58.840 + codeLengths[i++] = 5;
58.841 + defDistTree = new InflaterHuffmanTree(codeLengths);
58.842 + }
58.843 + catch (DataFormatException ex)
58.844 + {
58.845 + throw new IllegalStateException
58.846 + ("InflaterHuffmanTree: static tree length illegal");
58.847 + }
58.848 + }
58.849 +
58.850 + /**
58.851 + * Constructs a Huffman tree from the array of code lengths.
58.852 + *
58.853 + * @param codeLengths the array of code lengths
58.854 + */
58.855 + public InflaterHuffmanTree(byte[] codeLengths) throws DataFormatException
58.856 + {
58.857 + buildTree(codeLengths);
58.858 + }
58.859 +
58.860 + private void buildTree(byte[] codeLengths) throws DataFormatException
58.861 + {
58.862 + int[] blCount = new int[MAX_BITLEN+1];
58.863 + int[] nextCode = new int[MAX_BITLEN+1];
58.864 + for (int i = 0; i < codeLengths.length; i++)
58.865 + {
58.866 + int bits = codeLengths[i];
58.867 + if (bits > 0)
58.868 + blCount[bits]++;
58.869 + }
58.870 +
58.871 + int code = 0;
58.872 + int treeSize = 512;
58.873 + for (int bits = 1; bits <= MAX_BITLEN; bits++)
58.874 + {
58.875 + nextCode[bits] = code;
58.876 + code += blCount[bits] << (16 - bits);
58.877 + if (bits >= 10)
58.878 + {
58.879 + /* We need an extra table for bit lengths >= 10. */
58.880 + int start = nextCode[bits] & 0x1ff80;
58.881 + int end = code & 0x1ff80;
58.882 + treeSize += (end - start) >> (16 - bits);
58.883 + }
58.884 + }
58.885 + if (code != 65536)
58.886 + throw new DataFormatException("Code lengths don't add up properly.");
58.887 +
58.888 + /* Now create and fill the extra tables from longest to shortest
58.889 + * bit len. This way the sub trees will be aligned.
58.890 + */
58.891 + tree = new short[treeSize];
58.892 + int treePtr = 512;
58.893 + for (int bits = MAX_BITLEN; bits >= 10; bits--)
58.894 + {
58.895 + int end = code & 0x1ff80;
58.896 + code -= blCount[bits] << (16 - bits);
58.897 + int start = code & 0x1ff80;
58.898 + for (int i = start; i < end; i += 1 << 7)
58.899 + {
58.900 + tree[bitReverse(i)]
58.901 + = (short) ((-treePtr << 4) | bits);
58.902 + treePtr += 1 << (bits-9);
58.903 + }
58.904 + }
58.905 +
58.906 + for (int i = 0; i < codeLengths.length; i++)
58.907 + {
58.908 + int bits = codeLengths[i];
58.909 + if (bits == 0)
58.910 + continue;
58.911 + code = nextCode[bits];
58.912 + int revcode = bitReverse(code);
58.913 + if (bits <= 9)
58.914 + {
58.915 + do
58.916 + {
58.917 + tree[revcode] = (short) ((i << 4) | bits);
58.918 + revcode += 1 << bits;
58.919 + }
58.920 + while (revcode < 512);
58.921 + }
58.922 + else
58.923 + {
58.924 + int subTree = tree[revcode & 511];
58.925 + int treeLen = 1 << (subTree & 15);
58.926 + subTree = -(subTree >> 4);
58.927 + do
58.928 + {
58.929 + tree[subTree | (revcode >> 9)] = (short) ((i << 4) | bits);
58.930 + revcode += 1 << bits;
58.931 + }
58.932 + while (revcode < treeLen);
58.933 + }
58.934 + nextCode[bits] = code + (1 << (16 - bits));
58.935 + }
58.936 + }
58.937 + private final static String bit4Reverse =
58.938 + "\000\010\004\014\002\012\006\016\001\011\005\015\003\013\007\017";
58.939 + static short bitReverse(int value) {
58.940 + return (short) (bit4Reverse.charAt(value & 0xf) << 12
58.941 + | bit4Reverse.charAt((value >> 4) & 0xf) << 8
58.942 + | bit4Reverse.charAt((value >> 8) & 0xf) << 4
58.943 + | bit4Reverse.charAt(value >> 12));
58.944 + }
58.945 +
58.946 + /**
58.947 + * Reads the next symbol from input. The symbol is encoded using the
58.948 + * huffman tree.
58.949 + * @param input the input source.
58.950 + * @return the next symbol, or -1 if not enough input is available.
58.951 + */
58.952 + public int getSymbol(StreamManipulator input) throws DataFormatException
58.953 + {
58.954 + int lookahead, symbol;
58.955 + if ((lookahead = input.peekBits(9)) >= 0)
58.956 + {
58.957 + if ((symbol = tree[lookahead]) >= 0)
58.958 + {
58.959 + input.dropBits(symbol & 15);
58.960 + return symbol >> 4;
58.961 + }
58.962 + int subtree = -(symbol >> 4);
58.963 + int bitlen = symbol & 15;
58.964 + if ((lookahead = input.peekBits(bitlen)) >= 0)
58.965 + {
58.966 + symbol = tree[subtree | (lookahead >> 9)];
58.967 + input.dropBits(symbol & 15);
58.968 + return symbol >> 4;
58.969 + }
58.970 + else
58.971 + {
58.972 + int bits = input.getAvailableBits();
58.973 + lookahead = input.peekBits(bits);
58.974 + symbol = tree[subtree | (lookahead >> 9)];
58.975 + if ((symbol & 15) <= bits)
58.976 + {
58.977 + input.dropBits(symbol & 15);
58.978 + return symbol >> 4;
58.979 + }
58.980 + else
58.981 + return -1;
58.982 + }
58.983 + }
58.984 + else
58.985 + {
58.986 + int bits = input.getAvailableBits();
58.987 + lookahead = input.peekBits(bits);
58.988 + symbol = tree[lookahead];
58.989 + if (symbol >= 0 && (symbol & 15) <= bits)
58.990 + {
58.991 + input.dropBits(symbol & 15);
58.992 + return symbol >> 4;
58.993 + }
58.994 + else
58.995 + return -1;
58.996 + }
58.997 + }
58.998 + }
58.999 + private static class InflaterDynHeader
58.1000 + {
58.1001 + private static final int LNUM = 0;
58.1002 + private static final int DNUM = 1;
58.1003 + private static final int BLNUM = 2;
58.1004 + private static final int BLLENS = 3;
58.1005 + private static final int LENS = 4;
58.1006 + private static final int REPS = 5;
58.1007 +
58.1008 + private static final int repMin[] = { 3, 3, 11 };
58.1009 + private static final int repBits[] = { 2, 3, 7 };
58.1010 +
58.1011 +
58.1012 + private byte[] blLens;
58.1013 + private byte[] litdistLens;
58.1014 +
58.1015 + private InflaterHuffmanTree blTree;
58.1016 +
58.1017 + private int mode;
58.1018 + private int lnum, dnum, blnum, num;
58.1019 + private int repSymbol;
58.1020 + private byte lastLen;
58.1021 + private int ptr;
58.1022 +
58.1023 + private static final int[] BL_ORDER =
58.1024 + { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
58.1025 +
58.1026 + public InflaterDynHeader()
58.1027 + {
58.1028 + }
58.1029 +
58.1030 + public boolean decode(StreamManipulator input) throws DataFormatException
58.1031 + {
58.1032 + decode_loop:
58.1033 + for (;;)
58.1034 + {
58.1035 + switch (mode)
58.1036 + {
58.1037 + case LNUM:
58.1038 + lnum = input.peekBits(5);
58.1039 + if (lnum < 0)
58.1040 + return false;
58.1041 + lnum += 257;
58.1042 + input.dropBits(5);
58.1043 + // System.err.println("LNUM: "+lnum);
58.1044 + mode = DNUM;
58.1045 + /* fall through */
58.1046 + case DNUM:
58.1047 + dnum = input.peekBits(5);
58.1048 + if (dnum < 0)
58.1049 + return false;
58.1050 + dnum++;
58.1051 + input.dropBits(5);
58.1052 + // System.err.println("DNUM: "+dnum);
58.1053 + num = lnum+dnum;
58.1054 + litdistLens = new byte[num];
58.1055 + mode = BLNUM;
58.1056 + /* fall through */
58.1057 + case BLNUM:
58.1058 + blnum = input.peekBits(4);
58.1059 + if (blnum < 0)
58.1060 + return false;
58.1061 + blnum += 4;
58.1062 + input.dropBits(4);
58.1063 + blLens = new byte[19];
58.1064 + ptr = 0;
58.1065 + // System.err.println("BLNUM: "+blnum);
58.1066 + mode = BLLENS;
58.1067 + /* fall through */
58.1068 + case BLLENS:
58.1069 + while (ptr < blnum)
58.1070 + {
58.1071 + int len = input.peekBits(3);
58.1072 + if (len < 0)
58.1073 + return false;
58.1074 + input.dropBits(3);
58.1075 + // System.err.println("blLens["+BL_ORDER[ptr]+"]: "+len);
58.1076 + blLens[BL_ORDER[ptr]] = (byte) len;
58.1077 + ptr++;
58.1078 + }
58.1079 + blTree = new InflaterHuffmanTree(blLens);
58.1080 + blLens = null;
58.1081 + ptr = 0;
58.1082 + mode = LENS;
58.1083 + /* fall through */
58.1084 + case LENS:
58.1085 + {
58.1086 + int symbol;
58.1087 + while (((symbol = blTree.getSymbol(input)) & ~15) == 0)
58.1088 + {
58.1089 + /* Normal case: symbol in [0..15] */
58.1090 +
58.1091 + // System.err.println("litdistLens["+ptr+"]: "+symbol);
58.1092 + litdistLens[ptr++] = lastLen = (byte) symbol;
58.1093 +
58.1094 + if (ptr == num)
58.1095 + {
58.1096 + /* Finished */
58.1097 + return true;
58.1098 + }
58.1099 + }
58.1100 +
58.1101 + /* need more input ? */
58.1102 + if (symbol < 0)
58.1103 + return false;
58.1104 +
58.1105 + /* otherwise repeat code */
58.1106 + if (symbol >= 17)
58.1107 + {
58.1108 + /* repeat zero */
58.1109 + // System.err.println("repeating zero");
58.1110 + lastLen = 0;
58.1111 + }
58.1112 + else
58.1113 + {
58.1114 + if (ptr == 0)
58.1115 + throw new DataFormatException();
58.1116 + }
58.1117 + repSymbol = symbol-16;
58.1118 + mode = REPS;
58.1119 + }
58.1120 + /* fall through */
58.1121 +
58.1122 + case REPS:
58.1123 + {
58.1124 + int bits = repBits[repSymbol];
58.1125 + int count = input.peekBits(bits);
58.1126 + if (count < 0)
58.1127 + return false;
58.1128 + input.dropBits(bits);
58.1129 + count += repMin[repSymbol];
58.1130 + // System.err.println("litdistLens repeated: "+count);
58.1131 +
58.1132 + if (ptr + count > num)
58.1133 + throw new DataFormatException();
58.1134 + while (count-- > 0)
58.1135 + litdistLens[ptr++] = lastLen;
58.1136 +
58.1137 + if (ptr == num)
58.1138 + {
58.1139 + /* Finished */
58.1140 + return true;
58.1141 + }
58.1142 + }
58.1143 + mode = LENS;
58.1144 + continue decode_loop;
58.1145 + }
58.1146 + }
58.1147 + }
58.1148 +
58.1149 + public InflaterHuffmanTree buildLitLenTree() throws DataFormatException
58.1150 + {
58.1151 + byte[] litlenLens = new byte[lnum];
58.1152 + System.arraycopy(litdistLens, 0, litlenLens, 0, lnum);
58.1153 + return new InflaterHuffmanTree(litlenLens);
58.1154 + }
58.1155 +
58.1156 + public InflaterHuffmanTree buildDistTree() throws DataFormatException
58.1157 + {
58.1158 + byte[] distLens = new byte[dnum];
58.1159 + System.arraycopy(litdistLens, lnum, distLens, 0, dnum);
58.1160 + return new InflaterHuffmanTree(distLens);
58.1161 + }
58.1162 + }
58.1163 + /**
58.1164 + * This class allows us to retrieve a specified amount of bits from
58.1165 + * the input buffer, as well as copy big byte blocks.
58.1166 + *
58.1167 + * It uses an int buffer to store up to 31 bits for direct
58.1168 + * manipulation. This guarantees that we can get at least 16 bits,
58.1169 + * but we only need at most 15, so this is all safe.
58.1170 + *
58.1171 + * There are some optimizations in this class, for example, you must
58.1172 + * never peek more then 8 bits more than needed, and you must first
58.1173 + * peek bits before you may drop them. This is not a general purpose
58.1174 + * class but optimized for the behaviour of the Inflater.
58.1175 + *
58.1176 + * @author John Leuner, Jochen Hoenicke
58.1177 + */
58.1178 +
58.1179 + private static class StreamManipulator
58.1180 + {
58.1181 + private byte[] window;
58.1182 + private int window_start = 0;
58.1183 + private int window_end = 0;
58.1184 +
58.1185 + private int buffer = 0;
58.1186 + private int bits_in_buffer = 0;
58.1187 +
58.1188 + /**
58.1189 + * Get the next n bits but don't increase input pointer. n must be
58.1190 + * less or equal 16 and if you if this call succeeds, you must drop
58.1191 + * at least n-8 bits in the next call.
58.1192 + *
58.1193 + * @return the value of the bits, or -1 if not enough bits available. */
58.1194 + public final int peekBits(int n)
58.1195 + {
58.1196 + if (bits_in_buffer < n)
58.1197 + {
58.1198 + if (window_start == window_end)
58.1199 + return -1;
58.1200 + buffer |= (window[window_start++] & 0xff
58.1201 + | (window[window_start++] & 0xff) << 8) << bits_in_buffer;
58.1202 + bits_in_buffer += 16;
58.1203 + }
58.1204 + return buffer & ((1 << n) - 1);
58.1205 + }
58.1206 +
58.1207 + /* Drops the next n bits from the input. You should have called peekBits
58.1208 + * with a bigger or equal n before, to make sure that enough bits are in
58.1209 + * the bit buffer.
58.1210 + */
58.1211 + public final void dropBits(int n)
58.1212 + {
58.1213 + buffer >>>= n;
58.1214 + bits_in_buffer -= n;
58.1215 + }
58.1216 +
58.1217 + /**
58.1218 + * Gets the next n bits and increases input pointer. This is equivalent
58.1219 + * to peekBits followed by dropBits, except for correct error handling.
58.1220 + * @return the value of the bits, or -1 if not enough bits available.
58.1221 + */
58.1222 + public final int getBits(int n)
58.1223 + {
58.1224 + int bits = peekBits(n);
58.1225 + if (bits >= 0)
58.1226 + dropBits(n);
58.1227 + return bits;
58.1228 + }
58.1229 + /**
58.1230 + * Gets the number of bits available in the bit buffer. This must be
58.1231 + * only called when a previous peekBits() returned -1.
58.1232 + * @return the number of bits available.
58.1233 + */
58.1234 + public final int getAvailableBits()
58.1235 + {
58.1236 + return bits_in_buffer;
58.1237 + }
58.1238 +
58.1239 + /**
58.1240 + * Gets the number of bytes available.
58.1241 + * @return the number of bytes available.
58.1242 + */
58.1243 + public final int getAvailableBytes()
58.1244 + {
58.1245 + return window_end - window_start + (bits_in_buffer >> 3);
58.1246 + }
58.1247 +
58.1248 + /**
58.1249 + * Skips to the next byte boundary.
58.1250 + */
58.1251 + public void skipToByteBoundary()
58.1252 + {
58.1253 + buffer >>= (bits_in_buffer & 7);
58.1254 + bits_in_buffer &= ~7;
58.1255 + }
58.1256 +
58.1257 + public final boolean needsInput() {
58.1258 + return window_start == window_end;
58.1259 + }
58.1260 +
58.1261 +
58.1262 + /* Copies length bytes from input buffer to output buffer starting
58.1263 + * at output[offset]. You have to make sure, that the buffer is
58.1264 + * byte aligned. If not enough bytes are available, copies fewer
58.1265 + * bytes.
58.1266 + * @param length the length to copy, 0 is allowed.
58.1267 + * @return the number of bytes copied, 0 if no byte is available.
58.1268 + */
58.1269 + public int copyBytes(byte[] output, int offset, int length)
58.1270 + {
58.1271 + if (length < 0)
58.1272 + throw new IllegalArgumentException("length negative");
58.1273 + if ((bits_in_buffer & 7) != 0)
58.1274 + /* bits_in_buffer may only be 0 or 8 */
58.1275 + throw new IllegalStateException("Bit buffer is not aligned!");
58.1276 +
58.1277 + int count = 0;
58.1278 + while (bits_in_buffer > 0 && length > 0)
58.1279 + {
58.1280 + output[offset++] = (byte) buffer;
58.1281 + buffer >>>= 8;
58.1282 + bits_in_buffer -= 8;
58.1283 + length--;
58.1284 + count++;
58.1285 + }
58.1286 + if (length == 0)
58.1287 + return count;
58.1288 +
58.1289 + int avail = window_end - window_start;
58.1290 + if (length > avail)
58.1291 + length = avail;
58.1292 + System.arraycopy(window, window_start, output, offset, length);
58.1293 + window_start += length;
58.1294 +
58.1295 + if (((window_start - window_end) & 1) != 0)
58.1296 + {
58.1297 + /* We always want an even number of bytes in input, see peekBits */
58.1298 + buffer = (window[window_start++] & 0xff);
58.1299 + bits_in_buffer = 8;
58.1300 + }
58.1301 + return count + length;
58.1302 + }
58.1303 +
58.1304 + public StreamManipulator()
58.1305 + {
58.1306 + }
58.1307 +
58.1308 + public void reset()
58.1309 + {
58.1310 + window_start = window_end = buffer = bits_in_buffer = 0;
58.1311 + }
58.1312 +
58.1313 + public void setInput(byte[] buf, int off, int len)
58.1314 + {
58.1315 + if (window_start < window_end)
58.1316 + throw new IllegalStateException
58.1317 + ("Old input was not completely processed");
58.1318 +
58.1319 + int end = off + len;
58.1320 +
58.1321 + /* We want to throw an ArrayIndexOutOfBoundsException early. The
58.1322 + * check is very tricky: it also handles integer wrap around.
58.1323 + */
58.1324 + if (0 > off || off > end || end > buf.length)
58.1325 + throw new ArrayIndexOutOfBoundsException();
58.1326 +
58.1327 + if ((len & 1) != 0)
58.1328 + {
58.1329 + /* We always want an even number of bytes in input, see peekBits */
58.1330 + buffer |= (buf[off++] & 0xff) << bits_in_buffer;
58.1331 + bits_in_buffer += 8;
58.1332 + }
58.1333 +
58.1334 + window = buf;
58.1335 + window_start = off;
58.1336 + window_end = end;
58.1337 + }
58.1338 + }
58.1339 + /*
58.1340 + * Contains the output from the Inflation process.
58.1341 + *
58.1342 + * We need to have a window so that we can refer backwards into the output stream
58.1343 + * to repeat stuff.
58.1344 + *
58.1345 + * @author John Leuner
58.1346 + * @since JDK 1.1
58.1347 + */
58.1348 +
58.1349 + private static class OutputWindow
58.1350 + {
58.1351 + private final int WINDOW_SIZE = 1 << 15;
58.1352 + private final int WINDOW_MASK = WINDOW_SIZE - 1;
58.1353 +
58.1354 + private byte[] window = new byte[WINDOW_SIZE]; //The window is 2^15 bytes
58.1355 + private int window_end = 0;
58.1356 + private int window_filled = 0;
58.1357 +
58.1358 + public void write(int abyte)
58.1359 + {
58.1360 + if (window_filled++ == WINDOW_SIZE)
58.1361 + throw new IllegalStateException("Window full");
58.1362 + window[window_end++] = (byte) abyte;
58.1363 + window_end &= WINDOW_MASK;
58.1364 + }
58.1365 +
58.1366 +
58.1367 + private final void slowRepeat(int rep_start, int len, int dist)
58.1368 + {
58.1369 + while (len-- > 0)
58.1370 + {
58.1371 + window[window_end++] = window[rep_start++];
58.1372 + window_end &= WINDOW_MASK;
58.1373 + rep_start &= WINDOW_MASK;
58.1374 + }
58.1375 + }
58.1376 +
58.1377 + public void repeat(int len, int dist)
58.1378 + {
58.1379 + if ((window_filled += len) > WINDOW_SIZE)
58.1380 + throw new IllegalStateException("Window full");
58.1381 +
58.1382 + int rep_start = (window_end - dist) & WINDOW_MASK;
58.1383 + int border = WINDOW_SIZE - len;
58.1384 + if (rep_start <= border && window_end < border)
58.1385 + {
58.1386 + if (len <= dist)
58.1387 + {
58.1388 + System.arraycopy(window, rep_start, window, window_end, len);
58.1389 + window_end += len;
58.1390 + }
58.1391 + else
58.1392 + {
58.1393 + /* We have to copy manually, since the repeat pattern overlaps.
58.1394 + */
58.1395 + while (len-- > 0)
58.1396 + window[window_end++] = window[rep_start++];
58.1397 + }
58.1398 + }
58.1399 + else
58.1400 + slowRepeat(rep_start, len, dist);
58.1401 + }
58.1402 +
58.1403 + public int copyStored(StreamManipulator input, int len)
58.1404 + {
58.1405 + len = Math.min(Math.min(len, WINDOW_SIZE - window_filled),
58.1406 + input.getAvailableBytes());
58.1407 + int copied;
58.1408 +
58.1409 + int tailLen = WINDOW_SIZE - window_end;
58.1410 + if (len > tailLen)
58.1411 + {
58.1412 + copied = input.copyBytes(window, window_end, tailLen);
58.1413 + if (copied == tailLen)
58.1414 + copied += input.copyBytes(window, 0, len - tailLen);
58.1415 + }
58.1416 + else
58.1417 + copied = input.copyBytes(window, window_end, len);
58.1418 +
58.1419 + window_end = (window_end + copied) & WINDOW_MASK;
58.1420 + window_filled += copied;
58.1421 + return copied;
58.1422 + }
58.1423 +
58.1424 + public void copyDict(byte[] dict, int offset, int len)
58.1425 + {
58.1426 + if (window_filled > 0)
58.1427 + throw new IllegalStateException();
58.1428 +
58.1429 + if (len > WINDOW_SIZE)
58.1430 + {
58.1431 + offset += len - WINDOW_SIZE;
58.1432 + len = WINDOW_SIZE;
58.1433 + }
58.1434 + System.arraycopy(dict, offset, window, 0, len);
58.1435 + window_end = len & WINDOW_MASK;
58.1436 + }
58.1437 +
58.1438 + public int getFreeSpace()
58.1439 + {
58.1440 + return WINDOW_SIZE - window_filled;
58.1441 + }
58.1442 +
58.1443 + public int getAvailable()
58.1444 + {
58.1445 + return window_filled;
58.1446 + }
58.1447 +
58.1448 + public int copyOutput(byte[] output, int offset, int len)
58.1449 + {
58.1450 + int copy_end = window_end;
58.1451 + if (len > window_filled)
58.1452 + len = window_filled;
58.1453 + else
58.1454 + copy_end = (window_end - window_filled + len) & WINDOW_MASK;
58.1455 +
58.1456 + int copied = len;
58.1457 + int tailLen = len - copy_end;
58.1458 +
58.1459 + if (tailLen > 0)
58.1460 + {
58.1461 + System.arraycopy(window, WINDOW_SIZE - tailLen,
58.1462 + output, offset, tailLen);
58.1463 + offset += tailLen;
58.1464 + len = copy_end;
58.1465 + }
58.1466 + System.arraycopy(window, copy_end - len, output, offset, len);
58.1467 + window_filled -= copied;
58.1468 + if (window_filled < 0)
58.1469 + throw new IllegalStateException();
58.1470 + return copied;
58.1471 + }
58.1472 +
58.1473 + public void reset() {
58.1474 + window_filled = window_end = 0;
58.1475 + }
58.1476 + }
58.1477 +
58.1478 +}
59.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
59.2 +++ b/emul/mini/src/main/java/java/util/zip/InflaterInputStream.java Mon Feb 04 09:37:56 2013 +0100
59.3 @@ -0,0 +1,288 @@
59.4 +/*
59.5 + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
59.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
59.7 + *
59.8 + * This code is free software; you can redistribute it and/or modify it
59.9 + * under the terms of the GNU General Public License version 2 only, as
59.10 + * published by the Free Software Foundation. Oracle designates this
59.11 + * particular file as subject to the "Classpath" exception as provided
59.12 + * by Oracle in the LICENSE file that accompanied this code.
59.13 + *
59.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
59.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
59.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
59.17 + * version 2 for more details (a copy is included in the LICENSE file that
59.18 + * accompanied this code).
59.19 + *
59.20 + * You should have received a copy of the GNU General Public License version
59.21 + * 2 along with this work; if not, write to the Free Software Foundation,
59.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
59.23 + *
59.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
59.25 + * or visit www.oracle.com if you need additional information or have any
59.26 + * questions.
59.27 + */
59.28 +
59.29 +package java.util.zip;
59.30 +
59.31 +import java.io.FilterInputStream;
59.32 +import java.io.InputStream;
59.33 +import java.io.IOException;
59.34 +import java.io.EOFException;
59.35 +
59.36 +/**
59.37 + * This class implements a stream filter for uncompressing data in the
59.38 + * "deflate" compression format. It is also used as the basis for other
59.39 + * decompression filters, such as GZIPInputStream.
59.40 + *
59.41 + * @see Inflater
59.42 + * @author David Connelly
59.43 + */
59.44 +public
59.45 +class InflaterInputStream extends FilterInputStream {
59.46 + /**
59.47 + * Decompressor for this stream.
59.48 + */
59.49 + protected Inflater inf;
59.50 +
59.51 + /**
59.52 + * Input buffer for decompression.
59.53 + */
59.54 + protected byte[] buf;
59.55 +
59.56 + /**
59.57 + * Length of input buffer.
59.58 + */
59.59 + protected int len;
59.60 +
59.61 + private boolean closed = false;
59.62 + // this flag is set to true after EOF has reached
59.63 + private boolean reachEOF = false;
59.64 +
59.65 + /**
59.66 + * Check to make sure that this stream has not been closed
59.67 + */
59.68 + private void ensureOpen() throws IOException {
59.69 + if (closed) {
59.70 + throw new IOException("Stream closed");
59.71 + }
59.72 + }
59.73 +
59.74 +
59.75 + /**
59.76 + * Creates a new input stream with the specified decompressor and
59.77 + * buffer size.
59.78 + * @param in the input stream
59.79 + * @param inf the decompressor ("inflater")
59.80 + * @param size the input buffer size
59.81 + * @exception IllegalArgumentException if size is <= 0
59.82 + */
59.83 + public InflaterInputStream(InputStream in, Inflater inf, int size) {
59.84 + super(in);
59.85 + if (in == null || inf == null) {
59.86 + throw new NullPointerException();
59.87 + } else if (size <= 0) {
59.88 + throw new IllegalArgumentException("buffer size <= 0");
59.89 + }
59.90 + this.inf = inf;
59.91 + buf = new byte[size];
59.92 + }
59.93 +
59.94 + /**
59.95 + * Creates a new input stream with the specified decompressor and a
59.96 + * default buffer size.
59.97 + * @param in the input stream
59.98 + * @param inf the decompressor ("inflater")
59.99 + */
59.100 + public InflaterInputStream(InputStream in, Inflater inf) {
59.101 + this(in, inf, 512);
59.102 + }
59.103 +
59.104 + boolean usesDefaultInflater = false;
59.105 +
59.106 + /**
59.107 + * Creates a new input stream with a default decompressor and buffer size.
59.108 + * @param in the input stream
59.109 + */
59.110 + public InflaterInputStream(InputStream in) {
59.111 + this(in, new Inflater());
59.112 + usesDefaultInflater = true;
59.113 + }
59.114 +
59.115 + private byte[] singleByteBuf = new byte[1];
59.116 +
59.117 + /**
59.118 + * Reads a byte of uncompressed data. This method will block until
59.119 + * enough input is available for decompression.
59.120 + * @return the byte read, or -1 if end of compressed input is reached
59.121 + * @exception IOException if an I/O error has occurred
59.122 + */
59.123 + public int read() throws IOException {
59.124 + ensureOpen();
59.125 + return read(singleByteBuf, 0, 1) == -1 ? -1 : singleByteBuf[0] & 0xff;
59.126 + }
59.127 +
59.128 + /**
59.129 + * Reads uncompressed data into an array of bytes. If <code>len</code> is not
59.130 + * zero, the method will block until some input can be decompressed; otherwise,
59.131 + * no bytes are read and <code>0</code> is returned.
59.132 + * @param b the buffer into which the data is read
59.133 + * @param off the start offset in the destination array <code>b</code>
59.134 + * @param len the maximum number of bytes read
59.135 + * @return the actual number of bytes read, or -1 if the end of the
59.136 + * compressed input is reached or a preset dictionary is needed
59.137 + * @exception NullPointerException If <code>b</code> is <code>null</code>.
59.138 + * @exception IndexOutOfBoundsException If <code>off</code> is negative,
59.139 + * <code>len</code> is negative, or <code>len</code> is greater than
59.140 + * <code>b.length - off</code>
59.141 + * @exception ZipException if a ZIP format error has occurred
59.142 + * @exception IOException if an I/O error has occurred
59.143 + */
59.144 + public int read(byte[] b, int off, int len) throws IOException {
59.145 + ensureOpen();
59.146 + if (b == null) {
59.147 + throw new NullPointerException();
59.148 + } else if (off < 0 || len < 0 || len > b.length - off) {
59.149 + throw new IndexOutOfBoundsException();
59.150 + } else if (len == 0) {
59.151 + return 0;
59.152 + }
59.153 + try {
59.154 + int n;
59.155 + while ((n = inf.inflate(b, off, len)) == 0) {
59.156 + if (inf.finished() || inf.needsDictionary()) {
59.157 + reachEOF = true;
59.158 + return -1;
59.159 + }
59.160 + if (inf.needsInput()) {
59.161 + fill();
59.162 + }
59.163 + }
59.164 + return n;
59.165 + } catch (DataFormatException e) {
59.166 + String s = e.getMessage();
59.167 + throw new ZipException(s != null ? s : "Invalid ZLIB data format");
59.168 + }
59.169 + }
59.170 +
59.171 + /**
59.172 + * Returns 0 after EOF has been reached, otherwise always return 1.
59.173 + * <p>
59.174 + * Programs should not count on this method to return the actual number
59.175 + * of bytes that could be read without blocking.
59.176 + *
59.177 + * @return 1 before EOF and 0 after EOF.
59.178 + * @exception IOException if an I/O error occurs.
59.179 + *
59.180 + */
59.181 + public int available() throws IOException {
59.182 + ensureOpen();
59.183 + if (reachEOF) {
59.184 + return 0;
59.185 + } else {
59.186 + return 1;
59.187 + }
59.188 + }
59.189 +
59.190 + private byte[] b = new byte[512];
59.191 +
59.192 + /**
59.193 + * Skips specified number of bytes of uncompressed data.
59.194 + * @param n the number of bytes to skip
59.195 + * @return the actual number of bytes skipped.
59.196 + * @exception IOException if an I/O error has occurred
59.197 + * @exception IllegalArgumentException if n < 0
59.198 + */
59.199 + public long skip(long n) throws IOException {
59.200 + if (n < 0) {
59.201 + throw new IllegalArgumentException("negative skip length");
59.202 + }
59.203 + ensureOpen();
59.204 + int max = (int)Math.min(n, Integer.MAX_VALUE);
59.205 + int total = 0;
59.206 + while (total < max) {
59.207 + int len = max - total;
59.208 + if (len > b.length) {
59.209 + len = b.length;
59.210 + }
59.211 + len = read(b, 0, len);
59.212 + if (len == -1) {
59.213 + reachEOF = true;
59.214 + break;
59.215 + }
59.216 + total += len;
59.217 + }
59.218 + return total;
59.219 + }
59.220 +
59.221 + /**
59.222 + * Closes this input stream and releases any system resources associated
59.223 + * with the stream.
59.224 + * @exception IOException if an I/O error has occurred
59.225 + */
59.226 + public void close() throws IOException {
59.227 + if (!closed) {
59.228 + if (usesDefaultInflater)
59.229 + inf.end();
59.230 + in.close();
59.231 + closed = true;
59.232 + }
59.233 + }
59.234 +
59.235 + /**
59.236 + * Fills input buffer with more data to decompress.
59.237 + * @exception IOException if an I/O error has occurred
59.238 + */
59.239 + protected void fill() throws IOException {
59.240 + ensureOpen();
59.241 + len = in.read(buf, 0, buf.length);
59.242 + if (len == -1) {
59.243 + throw new EOFException("Unexpected end of ZLIB input stream");
59.244 + }
59.245 + inf.setInput(buf, 0, len);
59.246 + }
59.247 +
59.248 + /**
59.249 + * Tests if this input stream supports the <code>mark</code> and
59.250 + * <code>reset</code> methods. The <code>markSupported</code>
59.251 + * method of <code>InflaterInputStream</code> returns
59.252 + * <code>false</code>.
59.253 + *
59.254 + * @return a <code>boolean</code> indicating if this stream type supports
59.255 + * the <code>mark</code> and <code>reset</code> methods.
59.256 + * @see java.io.InputStream#mark(int)
59.257 + * @see java.io.InputStream#reset()
59.258 + */
59.259 + public boolean markSupported() {
59.260 + return false;
59.261 + }
59.262 +
59.263 + /**
59.264 + * Marks the current position in this input stream.
59.265 + *
59.266 + * <p> The <code>mark</code> method of <code>InflaterInputStream</code>
59.267 + * does nothing.
59.268 + *
59.269 + * @param readlimit the maximum limit of bytes that can be read before
59.270 + * the mark position becomes invalid.
59.271 + * @see java.io.InputStream#reset()
59.272 + */
59.273 + public synchronized void mark(int readlimit) {
59.274 + }
59.275 +
59.276 + /**
59.277 + * Repositions this stream to the position at the time the
59.278 + * <code>mark</code> method was last called on this input stream.
59.279 + *
59.280 + * <p> The method <code>reset</code> for class
59.281 + * <code>InflaterInputStream</code> does nothing except throw an
59.282 + * <code>IOException</code>.
59.283 + *
59.284 + * @exception IOException if this method is invoked.
59.285 + * @see java.io.InputStream#mark(int)
59.286 + * @see java.io.IOException
59.287 + */
59.288 + public synchronized void reset() throws IOException {
59.289 + throw new IOException("mark/reset not supported");
59.290 + }
59.291 +}
60.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
60.2 +++ b/emul/mini/src/main/java/java/util/zip/ZStreamRef.java Mon Feb 04 09:37:56 2013 +0100
60.3 @@ -0,0 +1,46 @@
60.4 +/*
60.5 + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
60.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
60.7 + *
60.8 + * This code is free software; you can redistribute it and/or modify it
60.9 + * under the terms of the GNU General Public License version 2 only, as
60.10 + * published by the Free Software Foundation. Oracle designates this
60.11 + * particular file as subject to the "Classpath" exception as provided
60.12 + * by Oracle in the LICENSE file that accompanied this code.
60.13 + *
60.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
60.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
60.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
60.17 + * version 2 for more details (a copy is included in the LICENSE file that
60.18 + * accompanied this code).
60.19 + *
60.20 + * You should have received a copy of the GNU General Public License version
60.21 + * 2 along with this work; if not, write to the Free Software Foundation,
60.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
60.23 + *
60.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
60.25 + * or visit www.oracle.com if you need additional information or have any
60.26 + * questions.
60.27 + */
60.28 +
60.29 +package java.util.zip;
60.30 +
60.31 +/**
60.32 + * A reference to the native zlib's z_stream structure.
60.33 + */
60.34 +
60.35 +class ZStreamRef {
60.36 +
60.37 + private long address;
60.38 + ZStreamRef (long address) {
60.39 + this.address = address;
60.40 + }
60.41 +
60.42 + long address() {
60.43 + return address;
60.44 + }
60.45 +
60.46 + void clear() {
60.47 + address = 0;
60.48 + }
60.49 +}
61.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
61.2 +++ b/emul/mini/src/main/java/java/util/zip/ZipConstants.java Mon Feb 04 09:37:56 2013 +0100
61.3 @@ -0,0 +1,98 @@
61.4 +/*
61.5 + * Copyright (c) 1995, 1996, Oracle and/or its affiliates. All rights reserved.
61.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
61.7 + *
61.8 + * This code is free software; you can redistribute it and/or modify it
61.9 + * under the terms of the GNU General Public License version 2 only, as
61.10 + * published by the Free Software Foundation. Oracle designates this
61.11 + * particular file as subject to the "Classpath" exception as provided
61.12 + * by Oracle in the LICENSE file that accompanied this code.
61.13 + *
61.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
61.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
61.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
61.17 + * version 2 for more details (a copy is included in the LICENSE file that
61.18 + * accompanied this code).
61.19 + *
61.20 + * You should have received a copy of the GNU General Public License version
61.21 + * 2 along with this work; if not, write to the Free Software Foundation,
61.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
61.23 + *
61.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
61.25 + * or visit www.oracle.com if you need additional information or have any
61.26 + * questions.
61.27 + */
61.28 +
61.29 +package java.util.zip;
61.30 +
61.31 +/*
61.32 + * This interface defines the constants that are used by the classes
61.33 + * which manipulate ZIP files.
61.34 + *
61.35 + * @author David Connelly
61.36 + */
61.37 +interface ZipConstants {
61.38 + /*
61.39 + * Header signatures
61.40 + */
61.41 + static long LOCSIG = 0x04034b50L; // "PK\003\004"
61.42 + static long EXTSIG = 0x08074b50L; // "PK\007\008"
61.43 + static long CENSIG = 0x02014b50L; // "PK\001\002"
61.44 + static long ENDSIG = 0x06054b50L; // "PK\005\006"
61.45 +
61.46 + /*
61.47 + * Header sizes in bytes (including signatures)
61.48 + */
61.49 + static final int LOCHDR = 30; // LOC header size
61.50 + static final int EXTHDR = 16; // EXT header size
61.51 + static final int CENHDR = 46; // CEN header size
61.52 + static final int ENDHDR = 22; // END header size
61.53 +
61.54 + /*
61.55 + * Local file (LOC) header field offsets
61.56 + */
61.57 + static final int LOCVER = 4; // version needed to extract
61.58 + static final int LOCFLG = 6; // general purpose bit flag
61.59 + static final int LOCHOW = 8; // compression method
61.60 + static final int LOCTIM = 10; // modification time
61.61 + static final int LOCCRC = 14; // uncompressed file crc-32 value
61.62 + static final int LOCSIZ = 18; // compressed size
61.63 + static final int LOCLEN = 22; // uncompressed size
61.64 + static final int LOCNAM = 26; // filename length
61.65 + static final int LOCEXT = 28; // extra field length
61.66 +
61.67 + /*
61.68 + * Extra local (EXT) header field offsets
61.69 + */
61.70 + static final int EXTCRC = 4; // uncompressed file crc-32 value
61.71 + static final int EXTSIZ = 8; // compressed size
61.72 + static final int EXTLEN = 12; // uncompressed size
61.73 +
61.74 + /*
61.75 + * Central directory (CEN) header field offsets
61.76 + */
61.77 + static final int CENVEM = 4; // version made by
61.78 + static final int CENVER = 6; // version needed to extract
61.79 + static final int CENFLG = 8; // encrypt, decrypt flags
61.80 + static final int CENHOW = 10; // compression method
61.81 + static final int CENTIM = 12; // modification time
61.82 + static final int CENCRC = 16; // uncompressed file crc-32 value
61.83 + static final int CENSIZ = 20; // compressed size
61.84 + static final int CENLEN = 24; // uncompressed size
61.85 + static final int CENNAM = 28; // filename length
61.86 + static final int CENEXT = 30; // extra field length
61.87 + static final int CENCOM = 32; // comment length
61.88 + static final int CENDSK = 34; // disk number start
61.89 + static final int CENATT = 36; // internal file attributes
61.90 + static final int CENATX = 38; // external file attributes
61.91 + static final int CENOFF = 42; // LOC header offset
61.92 +
61.93 + /*
61.94 + * End of central directory (END) header field offsets
61.95 + */
61.96 + static final int ENDSUB = 8; // number of entries on this disk
61.97 + static final int ENDTOT = 10; // total number of entries
61.98 + static final int ENDSIZ = 12; // central directory size in bytes
61.99 + static final int ENDOFF = 16; // offset of first CEN header
61.100 + static final int ENDCOM = 20; // zip file comment length
61.101 +}
62.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
62.2 +++ b/emul/mini/src/main/java/java/util/zip/ZipConstants64.java Mon Feb 04 09:37:56 2013 +0100
62.3 @@ -0,0 +1,84 @@
62.4 +/*
62.5 + * Copyright (c) 1995, 1996, Oracle and/or its affiliates. All rights reserved.
62.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
62.7 + *
62.8 + * This code is free software; you can redistribute it and/or modify it
62.9 + * under the terms of the GNU General Public License version 2 only, as
62.10 + * published by the Free Software Foundation. Oracle designates this
62.11 + * particular file as subject to the "Classpath" exception as provided
62.12 + * by Oracle in the LICENSE file that accompanied this code.
62.13 + *
62.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
62.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
62.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
62.17 + * version 2 for more details (a copy is included in the LICENSE file that
62.18 + * accompanied this code).
62.19 + *
62.20 + * You should have received a copy of the GNU General Public License version
62.21 + * 2 along with this work; if not, write to the Free Software Foundation,
62.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
62.23 + *
62.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
62.25 + * or visit www.oracle.com if you need additional information or have any
62.26 + * questions.
62.27 + */
62.28 +
62.29 +package java.util.zip;
62.30 +
62.31 +/*
62.32 + * This class defines the constants that are used by the classes
62.33 + * which manipulate Zip64 files.
62.34 + */
62.35 +
62.36 +class ZipConstants64 {
62.37 +
62.38 + /*
62.39 + * ZIP64 constants
62.40 + */
62.41 + static final long ZIP64_ENDSIG = 0x06064b50L; // "PK\006\006"
62.42 + static final long ZIP64_LOCSIG = 0x07064b50L; // "PK\006\007"
62.43 + static final int ZIP64_ENDHDR = 56; // ZIP64 end header size
62.44 + static final int ZIP64_LOCHDR = 20; // ZIP64 end loc header size
62.45 + static final int ZIP64_EXTHDR = 24; // EXT header size
62.46 + static final int ZIP64_EXTID = 0x0001; // Extra field Zip64 header ID
62.47 +
62.48 + static final int ZIP64_MAGICCOUNT = 0xFFFF;
62.49 + static final long ZIP64_MAGICVAL = 0xFFFFFFFFL;
62.50 +
62.51 + /*
62.52 + * Zip64 End of central directory (END) header field offsets
62.53 + */
62.54 + static final int ZIP64_ENDLEN = 4; // size of zip64 end of central dir
62.55 + static final int ZIP64_ENDVEM = 12; // version made by
62.56 + static final int ZIP64_ENDVER = 14; // version needed to extract
62.57 + static final int ZIP64_ENDNMD = 16; // number of this disk
62.58 + static final int ZIP64_ENDDSK = 20; // disk number of start
62.59 + static final int ZIP64_ENDTOD = 24; // total number of entries on this disk
62.60 + static final int ZIP64_ENDTOT = 32; // total number of entries
62.61 + static final int ZIP64_ENDSIZ = 40; // central directory size in bytes
62.62 + static final int ZIP64_ENDOFF = 48; // offset of first CEN header
62.63 + static final int ZIP64_ENDEXT = 56; // zip64 extensible data sector
62.64 +
62.65 + /*
62.66 + * Zip64 End of central directory locator field offsets
62.67 + */
62.68 + static final int ZIP64_LOCDSK = 4; // disk number start
62.69 + static final int ZIP64_LOCOFF = 8; // offset of zip64 end
62.70 + static final int ZIP64_LOCTOT = 16; // total number of disks
62.71 +
62.72 + /*
62.73 + * Zip64 Extra local (EXT) header field offsets
62.74 + */
62.75 + static final int ZIP64_EXTCRC = 4; // uncompressed file crc-32 value
62.76 + static final int ZIP64_EXTSIZ = 8; // compressed size, 8-byte
62.77 + static final int ZIP64_EXTLEN = 16; // uncompressed size, 8-byte
62.78 +
62.79 + /*
62.80 + * Language encoding flag EFS
62.81 + */
62.82 + static final int EFS = 0x800; // If this bit is set the filename and
62.83 + // comment fields for this file must be
62.84 + // encoded using UTF-8.
62.85 +
62.86 + private ZipConstants64() {}
62.87 +}
63.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
63.2 +++ b/emul/mini/src/main/java/java/util/zip/ZipEntry.java Mon Feb 04 09:37:56 2013 +0100
63.3 @@ -0,0 +1,331 @@
63.4 +/*
63.5 + * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
63.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
63.7 + *
63.8 + * This code is free software; you can redistribute it and/or modify it
63.9 + * under the terms of the GNU General Public License version 2 only, as
63.10 + * published by the Free Software Foundation. Oracle designates this
63.11 + * particular file as subject to the "Classpath" exception as provided
63.12 + * by Oracle in the LICENSE file that accompanied this code.
63.13 + *
63.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
63.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
63.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
63.17 + * version 2 for more details (a copy is included in the LICENSE file that
63.18 + * accompanied this code).
63.19 + *
63.20 + * You should have received a copy of the GNU General Public License version
63.21 + * 2 along with this work; if not, write to the Free Software Foundation,
63.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
63.23 + *
63.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
63.25 + * or visit www.oracle.com if you need additional information or have any
63.26 + * questions.
63.27 + */
63.28 +
63.29 +package java.util.zip;
63.30 +
63.31 +/**
63.32 + * This class is used to represent a ZIP file entry.
63.33 + *
63.34 + * @author David Connelly
63.35 + */
63.36 +public
63.37 +class ZipEntry implements ZipConstants, Cloneable {
63.38 + String name; // entry name
63.39 + long time = -1; // modification time (in DOS time)
63.40 + long crc = -1; // crc-32 of entry data
63.41 + long size = -1; // uncompressed size of entry data
63.42 + long csize = -1; // compressed size of entry data
63.43 + int method = -1; // compression method
63.44 + int flag = 0; // general purpose flag
63.45 + byte[] extra; // optional extra field data for entry
63.46 + String comment; // optional comment string for entry
63.47 +
63.48 + /**
63.49 + * Compression method for uncompressed entries.
63.50 + */
63.51 + public static final int STORED = 0;
63.52 +
63.53 + /**
63.54 + * Compression method for compressed (deflated) entries.
63.55 + */
63.56 + public static final int DEFLATED = 8;
63.57 +
63.58 + /**
63.59 + * Creates a new zip entry with the specified name.
63.60 + *
63.61 + * @param name the entry name
63.62 + * @exception NullPointerException if the entry name is null
63.63 + * @exception IllegalArgumentException if the entry name is longer than
63.64 + * 0xFFFF bytes
63.65 + */
63.66 + public ZipEntry(String name) {
63.67 + if (name == null) {
63.68 + throw new NullPointerException();
63.69 + }
63.70 + if (name.length() > 0xFFFF) {
63.71 + throw new IllegalArgumentException("entry name too long");
63.72 + }
63.73 + this.name = name;
63.74 + }
63.75 +
63.76 + /**
63.77 + * Creates a new zip entry with fields taken from the specified
63.78 + * zip entry.
63.79 + * @param e a zip Entry object
63.80 + */
63.81 + public ZipEntry(ZipEntry e) {
63.82 + name = e.name;
63.83 + time = e.time;
63.84 + crc = e.crc;
63.85 + size = e.size;
63.86 + csize = e.csize;
63.87 + method = e.method;
63.88 + flag = e.flag;
63.89 + extra = e.extra;
63.90 + comment = e.comment;
63.91 + }
63.92 +
63.93 + /*
63.94 + * Creates a new un-initialized zip entry
63.95 + */
63.96 + ZipEntry() {}
63.97 +
63.98 + /**
63.99 + * Returns the name of the entry.
63.100 + * @return the name of the entry
63.101 + */
63.102 + public String getName() {
63.103 + return name;
63.104 + }
63.105 +
63.106 + /**
63.107 + * Sets the modification time of the entry.
63.108 + * @param time the entry modification time in number of milliseconds
63.109 + * since the epoch
63.110 + * @see #getTime()
63.111 + */
63.112 + public void setTime(long time) {
63.113 + this.time = javaToDosTime(time);
63.114 + }
63.115 +
63.116 + /**
63.117 + * Returns the modification time of the entry, or -1 if not specified.
63.118 + * @return the modification time of the entry, or -1 if not specified
63.119 + * @see #setTime(long)
63.120 + */
63.121 + public long getTime() {
63.122 + return time != -1 ? dosToJavaTime(time) : -1;
63.123 + }
63.124 +
63.125 + /**
63.126 + * Sets the uncompressed size of the entry data.
63.127 + * @param size the uncompressed size in bytes
63.128 + * @exception IllegalArgumentException if the specified size is less
63.129 + * than 0, is greater than 0xFFFFFFFF when
63.130 + * <a href="package-summary.html#zip64">ZIP64 format</a> is not supported,
63.131 + * or is less than 0 when ZIP64 is supported
63.132 + * @see #getSize()
63.133 + */
63.134 + public void setSize(long size) {
63.135 + if (size < 0) {
63.136 + throw new IllegalArgumentException("invalid entry size");
63.137 + }
63.138 + this.size = size;
63.139 + }
63.140 +
63.141 + /**
63.142 + * Returns the uncompressed size of the entry data, or -1 if not known.
63.143 + * @return the uncompressed size of the entry data, or -1 if not known
63.144 + * @see #setSize(long)
63.145 + */
63.146 + public long getSize() {
63.147 + return size;
63.148 + }
63.149 +
63.150 + /**
63.151 + * Returns the size of the compressed entry data, or -1 if not known.
63.152 + * In the case of a stored entry, the compressed size will be the same
63.153 + * as the uncompressed size of the entry.
63.154 + * @return the size of the compressed entry data, or -1 if not known
63.155 + * @see #setCompressedSize(long)
63.156 + */
63.157 + public long getCompressedSize() {
63.158 + return csize;
63.159 + }
63.160 +
63.161 + /**
63.162 + * Sets the size of the compressed entry data.
63.163 + * @param csize the compressed size to set to
63.164 + * @see #getCompressedSize()
63.165 + */
63.166 + public void setCompressedSize(long csize) {
63.167 + this.csize = csize;
63.168 + }
63.169 +
63.170 + /**
63.171 + * Sets the CRC-32 checksum of the uncompressed entry data.
63.172 + * @param crc the CRC-32 value
63.173 + * @exception IllegalArgumentException if the specified CRC-32 value is
63.174 + * less than 0 or greater than 0xFFFFFFFF
63.175 + * @see #getCrc()
63.176 + */
63.177 + public void setCrc(long crc) {
63.178 + if (crc < 0 || crc > 0xFFFFFFFFL) {
63.179 + throw new IllegalArgumentException("invalid entry crc-32");
63.180 + }
63.181 + this.crc = crc;
63.182 + }
63.183 +
63.184 + /**
63.185 + * Returns the CRC-32 checksum of the uncompressed entry data, or -1 if
63.186 + * not known.
63.187 + * @return the CRC-32 checksum of the uncompressed entry data, or -1 if
63.188 + * not known
63.189 + * @see #setCrc(long)
63.190 + */
63.191 + public long getCrc() {
63.192 + return crc;
63.193 + }
63.194 +
63.195 + /**
63.196 + * Sets the compression method for the entry.
63.197 + * @param method the compression method, either STORED or DEFLATED
63.198 + * @exception IllegalArgumentException if the specified compression
63.199 + * method is invalid
63.200 + * @see #getMethod()
63.201 + */
63.202 + public void setMethod(int method) {
63.203 + if (method != STORED && method != DEFLATED) {
63.204 + throw new IllegalArgumentException("invalid compression method");
63.205 + }
63.206 + this.method = method;
63.207 + }
63.208 +
63.209 + /**
63.210 + * Returns the compression method of the entry, or -1 if not specified.
63.211 + * @return the compression method of the entry, or -1 if not specified
63.212 + * @see #setMethod(int)
63.213 + */
63.214 + public int getMethod() {
63.215 + return method;
63.216 + }
63.217 +
63.218 + /**
63.219 + * Sets the optional extra field data for the entry.
63.220 + * @param extra the extra field data bytes
63.221 + * @exception IllegalArgumentException if the length of the specified
63.222 + * extra field data is greater than 0xFFFF bytes
63.223 + * @see #getExtra()
63.224 + */
63.225 + public void setExtra(byte[] extra) {
63.226 + if (extra != null && extra.length > 0xFFFF) {
63.227 + throw new IllegalArgumentException("invalid extra field length");
63.228 + }
63.229 + this.extra = extra;
63.230 + }
63.231 +
63.232 + /**
63.233 + * Returns the extra field data for the entry, or null if none.
63.234 + * @return the extra field data for the entry, or null if none
63.235 + * @see #setExtra(byte[])
63.236 + */
63.237 + public byte[] getExtra() {
63.238 + return extra;
63.239 + }
63.240 +
63.241 + /**
63.242 + * Sets the optional comment string for the entry.
63.243 + *
63.244 + * <p>ZIP entry comments have maximum length of 0xffff. If the length of the
63.245 + * specified comment string is greater than 0xFFFF bytes after encoding, only
63.246 + * the first 0xFFFF bytes are output to the ZIP file entry.
63.247 + *
63.248 + * @param comment the comment string
63.249 + *
63.250 + * @see #getComment()
63.251 + */
63.252 + public void setComment(String comment) {
63.253 + this.comment = comment;
63.254 + }
63.255 +
63.256 + /**
63.257 + * Returns the comment string for the entry, or null if none.
63.258 + * @return the comment string for the entry, or null if none
63.259 + * @see #setComment(String)
63.260 + */
63.261 + public String getComment() {
63.262 + return comment;
63.263 + }
63.264 +
63.265 + /**
63.266 + * Returns true if this is a directory entry. A directory entry is
63.267 + * defined to be one whose name ends with a '/'.
63.268 + * @return true if this is a directory entry
63.269 + */
63.270 + public boolean isDirectory() {
63.271 + return name.endsWith("/");
63.272 + }
63.273 +
63.274 + /**
63.275 + * Returns a string representation of the ZIP entry.
63.276 + */
63.277 + public String toString() {
63.278 + return getName();
63.279 + }
63.280 +
63.281 + /*
63.282 + * Converts DOS time to Java time (number of milliseconds since epoch).
63.283 + */
63.284 + private static long dosToJavaTime(long dtime) {
63.285 + return dtime;
63.286 + /* XXX:
63.287 + Date d = new Date((int)(((dtime >> 25) & 0x7f) + 80),
63.288 + (int)(((dtime >> 21) & 0x0f) - 1),
63.289 + (int)((dtime >> 16) & 0x1f),
63.290 + (int)((dtime >> 11) & 0x1f),
63.291 + (int)((dtime >> 5) & 0x3f),
63.292 + (int)((dtime << 1) & 0x3e));
63.293 + return d.getTime();
63.294 + */
63.295 + }
63.296 +
63.297 + /*
63.298 + * Converts Java time to DOS time.
63.299 + */
63.300 + private static long javaToDosTime(long time) {
63.301 + return time;
63.302 + /* XXX:
63.303 + Date d = new Date(time);
63.304 + int year = d.getYear() + 1900;
63.305 + if (year < 1980) {
63.306 + return (1 << 21) | (1 << 16);
63.307 + }
63.308 + return (year - 1980) << 25 | (d.getMonth() + 1) << 21 |
63.309 + d.getDate() << 16 | d.getHours() << 11 | d.getMinutes() << 5 |
63.310 + d.getSeconds() >> 1;
63.311 + */
63.312 + }
63.313 +
63.314 + /**
63.315 + * Returns the hash code value for this entry.
63.316 + */
63.317 + public int hashCode() {
63.318 + return name.hashCode();
63.319 + }
63.320 +
63.321 + /**
63.322 + * Returns a copy of this entry.
63.323 + */
63.324 + public Object clone() {
63.325 + try {
63.326 + ZipEntry e = (ZipEntry)super.clone();
63.327 + e.extra = (extra == null) ? null : extra.clone();
63.328 + return e;
63.329 + } catch (CloneNotSupportedException e) {
63.330 + // This should never happen, since we are Cloneable
63.331 + throw new IllegalStateException();
63.332 + }
63.333 + }
63.334 +}
64.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
64.2 +++ b/emul/mini/src/main/java/java/util/zip/ZipException.java Mon Feb 04 09:37:56 2013 +0100
64.3 @@ -0,0 +1,60 @@
64.4 +/*
64.5 + * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
64.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
64.7 + *
64.8 + * This code is free software; you can redistribute it and/or modify it
64.9 + * under the terms of the GNU General Public License version 2 only, as
64.10 + * published by the Free Software Foundation. Oracle designates this
64.11 + * particular file as subject to the "Classpath" exception as provided
64.12 + * by Oracle in the LICENSE file that accompanied this code.
64.13 + *
64.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
64.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
64.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
64.17 + * version 2 for more details (a copy is included in the LICENSE file that
64.18 + * accompanied this code).
64.19 + *
64.20 + * You should have received a copy of the GNU General Public License version
64.21 + * 2 along with this work; if not, write to the Free Software Foundation,
64.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
64.23 + *
64.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
64.25 + * or visit www.oracle.com if you need additional information or have any
64.26 + * questions.
64.27 + */
64.28 +
64.29 +package java.util.zip;
64.30 +
64.31 +import java.io.IOException;
64.32 +
64.33 +/**
64.34 + * Signals that a Zip exception of some sort has occurred.
64.35 + *
64.36 + * @author unascribed
64.37 + * @see java.io.IOException
64.38 + * @since JDK1.0
64.39 + */
64.40 +
64.41 +public
64.42 +class ZipException extends IOException {
64.43 + private static final long serialVersionUID = 8000196834066748623L;
64.44 +
64.45 + /**
64.46 + * Constructs a <code>ZipException</code> with <code>null</code>
64.47 + * as its error detail message.
64.48 + */
64.49 + public ZipException() {
64.50 + super();
64.51 + }
64.52 +
64.53 + /**
64.54 + * Constructs a <code>ZipException</code> with the specified detail
64.55 + * message.
64.56 + *
64.57 + * @param s the detail message.
64.58 + */
64.59 +
64.60 + public ZipException(String s) {
64.61 + super(s);
64.62 + }
64.63 +}
65.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
65.2 +++ b/emul/mini/src/main/java/java/util/zip/ZipInputStream.java Mon Feb 04 09:37:56 2013 +0100
65.3 @@ -0,0 +1,467 @@
65.4 +/*
65.5 + * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
65.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
65.7 + *
65.8 + * This code is free software; you can redistribute it and/or modify it
65.9 + * under the terms of the GNU General Public License version 2 only, as
65.10 + * published by the Free Software Foundation. Oracle designates this
65.11 + * particular file as subject to the "Classpath" exception as provided
65.12 + * by Oracle in the LICENSE file that accompanied this code.
65.13 + *
65.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
65.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
65.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
65.17 + * version 2 for more details (a copy is included in the LICENSE file that
65.18 + * accompanied this code).
65.19 + *
65.20 + * You should have received a copy of the GNU General Public License version
65.21 + * 2 along with this work; if not, write to the Free Software Foundation,
65.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
65.23 + *
65.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
65.25 + * or visit www.oracle.com if you need additional information or have any
65.26 + * questions.
65.27 + */
65.28 +
65.29 +package java.util.zip;
65.30 +
65.31 +import java.io.InputStream;
65.32 +import java.io.IOException;
65.33 +import java.io.EOFException;
65.34 +import java.io.PushbackInputStream;
65.35 +import static java.util.zip.ZipConstants64.*;
65.36 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
65.37 +
65.38 +/**
65.39 + * This class implements an input stream filter for reading files in the
65.40 + * ZIP file format. Includes support for both compressed and uncompressed
65.41 + * entries.
65.42 + *
65.43 + * @author David Connelly
65.44 + */
65.45 +public
65.46 +class ZipInputStream extends InflaterInputStream implements ZipConstants {
65.47 + private ZipEntry entry;
65.48 + private int flag;
65.49 + private CRC32 crc = new CRC32();
65.50 + private long remaining;
65.51 + private byte[] tmpbuf = new byte[512];
65.52 +
65.53 + private static final int STORED = ZipEntry.STORED;
65.54 + private static final int DEFLATED = ZipEntry.DEFLATED;
65.55 +
65.56 + private boolean closed = false;
65.57 + // this flag is set to true after EOF has reached for
65.58 + // one entry
65.59 + private boolean entryEOF = false;
65.60 +
65.61 + /**
65.62 + * Check to make sure that this stream has not been closed
65.63 + */
65.64 + private void ensureOpen() throws IOException {
65.65 + if (closed) {
65.66 + throw new IOException("Stream closed");
65.67 + }
65.68 + }
65.69 +
65.70 + /**
65.71 + * Creates a new ZIP input stream.
65.72 + *
65.73 + * <p>The UTF-8 {@link java.nio.charset.Charset charset} is used to
65.74 + * decode the entry names.
65.75 + *
65.76 + * @param in the actual input stream
65.77 + */
65.78 + public ZipInputStream(InputStream in) {
65.79 +// this(in, "UTF-8");
65.80 + super(new PushbackInputStream(in, 512), new Inflater(true), 512);
65.81 + usesDefaultInflater = true;
65.82 + if(in == null) {
65.83 + throw new NullPointerException("in is null");
65.84 + }
65.85 + }
65.86 +
65.87 + /**
65.88 + * Creates a new ZIP input stream.
65.89 + *
65.90 + * @param in the actual input stream
65.91 + *
65.92 + * @param charset
65.93 + * The {@linkplain java.nio.charset.Charset charset} to be
65.94 + * used to decode the ZIP entry name (ignored if the
65.95 + * <a href="package-summary.html#lang_encoding"> language
65.96 + * encoding bit</a> of the ZIP entry's general purpose bit
65.97 + * flag is set).
65.98 + *
65.99 + * @since 1.7
65.100 + *
65.101 + public ZipInputStream(InputStream in, Charset charset) {
65.102 + super(new PushbackInputStream(in, 512), new Inflater(true), 512);
65.103 + usesDefaultInflater = true;
65.104 + if(in == null) {
65.105 + throw new NullPointerException("in is null");
65.106 + }
65.107 + if (charset == null)
65.108 + throw new NullPointerException("charset is null");
65.109 + this.zc = ZipCoder.get(charset);
65.110 + }
65.111 + */
65.112 +
65.113 + /**
65.114 + * Reads the next ZIP file entry and positions the stream at the
65.115 + * beginning of the entry data.
65.116 + * @return the next ZIP file entry, or null if there are no more entries
65.117 + * @exception ZipException if a ZIP file error has occurred
65.118 + * @exception IOException if an I/O error has occurred
65.119 + */
65.120 + public ZipEntry getNextEntry() throws IOException {
65.121 + ensureOpen();
65.122 + if (entry != null) {
65.123 + closeEntry();
65.124 + }
65.125 + crc.reset();
65.126 + inf.reset();
65.127 + if ((entry = readLOC()) == null) {
65.128 + return null;
65.129 + }
65.130 + if (entry.method == STORED) {
65.131 + remaining = entry.size;
65.132 + }
65.133 + entryEOF = false;
65.134 + return entry;
65.135 + }
65.136 +
65.137 + /**
65.138 + * Closes the current ZIP entry and positions the stream for reading the
65.139 + * next entry.
65.140 + * @exception ZipException if a ZIP file error has occurred
65.141 + * @exception IOException if an I/O error has occurred
65.142 + */
65.143 + public void closeEntry() throws IOException {
65.144 + ensureOpen();
65.145 + while (read(tmpbuf, 0, tmpbuf.length) != -1) ;
65.146 + entryEOF = true;
65.147 + }
65.148 +
65.149 + /**
65.150 + * Returns 0 after EOF has reached for the current entry data,
65.151 + * otherwise always return 1.
65.152 + * <p>
65.153 + * Programs should not count on this method to return the actual number
65.154 + * of bytes that could be read without blocking.
65.155 + *
65.156 + * @return 1 before EOF and 0 after EOF has reached for current entry.
65.157 + * @exception IOException if an I/O error occurs.
65.158 + *
65.159 + */
65.160 + public int available() throws IOException {
65.161 + ensureOpen();
65.162 + if (entryEOF) {
65.163 + return 0;
65.164 + } else {
65.165 + return 1;
65.166 + }
65.167 + }
65.168 +
65.169 + /**
65.170 + * Reads from the current ZIP entry into an array of bytes.
65.171 + * If <code>len</code> is not zero, the method
65.172 + * blocks until some input is available; otherwise, no
65.173 + * bytes are read and <code>0</code> is returned.
65.174 + * @param b the buffer into which the data is read
65.175 + * @param off the start offset in the destination array <code>b</code>
65.176 + * @param len the maximum number of bytes read
65.177 + * @return the actual number of bytes read, or -1 if the end of the
65.178 + * entry is reached
65.179 + * @exception NullPointerException if <code>b</code> is <code>null</code>.
65.180 + * @exception IndexOutOfBoundsException if <code>off</code> is negative,
65.181 + * <code>len</code> is negative, or <code>len</code> is greater than
65.182 + * <code>b.length - off</code>
65.183 + * @exception ZipException if a ZIP file error has occurred
65.184 + * @exception IOException if an I/O error has occurred
65.185 + */
65.186 + public int read(byte[] b, int off, int len) throws IOException {
65.187 + ensureOpen();
65.188 + if (off < 0 || len < 0 || off > b.length - len) {
65.189 + throw new IndexOutOfBoundsException();
65.190 + } else if (len == 0) {
65.191 + return 0;
65.192 + }
65.193 +
65.194 + if (entry == null) {
65.195 + return -1;
65.196 + }
65.197 + switch (entry.method) {
65.198 + case DEFLATED:
65.199 + len = super.read(b, off, len);
65.200 + if (len == -1) {
65.201 + readEnd(entry);
65.202 + entryEOF = true;
65.203 + entry = null;
65.204 + } else {
65.205 + crc.update(b, off, len);
65.206 + }
65.207 + return len;
65.208 + case STORED:
65.209 + if (remaining <= 0) {
65.210 + entryEOF = true;
65.211 + entry = null;
65.212 + return -1;
65.213 + }
65.214 + if (len > remaining) {
65.215 + len = (int)remaining;
65.216 + }
65.217 + len = in.read(b, off, len);
65.218 + if (len == -1) {
65.219 + throw new ZipException("unexpected EOF");
65.220 + }
65.221 + crc.update(b, off, len);
65.222 + remaining -= len;
65.223 + if (remaining == 0 && entry.crc != crc.getValue()) {
65.224 + throw new ZipException(
65.225 + "invalid entry CRC (expected 0x" + Long.toHexString(entry.crc) +
65.226 + " but got 0x" + Long.toHexString(crc.getValue()) + ")");
65.227 + }
65.228 + return len;
65.229 + default:
65.230 + throw new ZipException("invalid compression method");
65.231 + }
65.232 + }
65.233 +
65.234 + /**
65.235 + * Skips specified number of bytes in the current ZIP entry.
65.236 + * @param n the number of bytes to skip
65.237 + * @return the actual number of bytes skipped
65.238 + * @exception ZipException if a ZIP file error has occurred
65.239 + * @exception IOException if an I/O error has occurred
65.240 + * @exception IllegalArgumentException if n < 0
65.241 + */
65.242 + public long skip(long n) throws IOException {
65.243 + if (n < 0) {
65.244 + throw new IllegalArgumentException("negative skip length");
65.245 + }
65.246 + ensureOpen();
65.247 + int max = (int)Math.min(n, Integer.MAX_VALUE);
65.248 + int total = 0;
65.249 + while (total < max) {
65.250 + int len = max - total;
65.251 + if (len > tmpbuf.length) {
65.252 + len = tmpbuf.length;
65.253 + }
65.254 + len = read(tmpbuf, 0, len);
65.255 + if (len == -1) {
65.256 + entryEOF = true;
65.257 + break;
65.258 + }
65.259 + total += len;
65.260 + }
65.261 + return total;
65.262 + }
65.263 +
65.264 + /**
65.265 + * Closes this input stream and releases any system resources associated
65.266 + * with the stream.
65.267 + * @exception IOException if an I/O error has occurred
65.268 + */
65.269 + public void close() throws IOException {
65.270 + if (!closed) {
65.271 + super.close();
65.272 + closed = true;
65.273 + }
65.274 + }
65.275 +
65.276 + private byte[] b = new byte[256];
65.277 +
65.278 + /*
65.279 + * Reads local file (LOC) header for next entry.
65.280 + */
65.281 + private ZipEntry readLOC() throws IOException {
65.282 + try {
65.283 + readFully(tmpbuf, 0, LOCHDR);
65.284 + } catch (EOFException e) {
65.285 + return null;
65.286 + }
65.287 + if (get32(tmpbuf, 0) != LOCSIG) {
65.288 + return null;
65.289 + }
65.290 + // get flag first, we need check EFS.
65.291 + flag = get16(tmpbuf, LOCFLG);
65.292 + // get the entry name and create the ZipEntry first
65.293 + int len = get16(tmpbuf, LOCNAM);
65.294 + int blen = b.length;
65.295 + if (len > blen) {
65.296 + do
65.297 + blen = blen * 2;
65.298 + while (len > blen);
65.299 + b = new byte[blen];
65.300 + }
65.301 + readFully(b, 0, len);
65.302 + // Force to use UTF-8 if the EFS bit is ON, even the cs is NOT UTF-8
65.303 + ZipEntry e = createZipEntry(((flag & EFS) != 0)
65.304 + ? toStringUTF8(b, len)
65.305 + : toString(b, len));
65.306 + // now get the remaining fields for the entry
65.307 + if ((flag & 1) == 1) {
65.308 + throw new ZipException("encrypted ZIP entry not supported");
65.309 + }
65.310 + e.method = get16(tmpbuf, LOCHOW);
65.311 + e.time = get32(tmpbuf, LOCTIM);
65.312 + if ((flag & 8) == 8) {
65.313 + /* "Data Descriptor" present */
65.314 + if (e.method != DEFLATED) {
65.315 + throw new ZipException(
65.316 + "only DEFLATED entries can have EXT descriptor");
65.317 + }
65.318 + } else {
65.319 + e.crc = get32(tmpbuf, LOCCRC);
65.320 + e.csize = get32(tmpbuf, LOCSIZ);
65.321 + e.size = get32(tmpbuf, LOCLEN);
65.322 + }
65.323 + len = get16(tmpbuf, LOCEXT);
65.324 + if (len > 0) {
65.325 + byte[] bb = new byte[len];
65.326 + readFully(bb, 0, len);
65.327 + e.setExtra(bb);
65.328 + // extra fields are in "HeaderID(2)DataSize(2)Data... format
65.329 + if (e.csize == ZIP64_MAGICVAL || e.size == ZIP64_MAGICVAL) {
65.330 + int off = 0;
65.331 + while (off + 4 < len) {
65.332 + int sz = get16(bb, off + 2);
65.333 + if (get16(bb, off) == ZIP64_EXTID) {
65.334 + off += 4;
65.335 + // LOC extra zip64 entry MUST include BOTH original and
65.336 + // compressed file size fields
65.337 + if (sz < 16 || (off + sz) > len ) {
65.338 + // Invalid zip64 extra fields, simply skip. Even it's
65.339 + // rare, it's possible the entry size happens to be
65.340 + // the magic value and it "accidnetly" has some bytes
65.341 + // in extra match the id.
65.342 + return e;
65.343 + }
65.344 + e.size = get64(bb, off);
65.345 + e.csize = get64(bb, off + 8);
65.346 + break;
65.347 + }
65.348 + off += (sz + 4);
65.349 + }
65.350 + }
65.351 + }
65.352 + return e;
65.353 + }
65.354 +
65.355 + /**
65.356 + * Creates a new <code>ZipEntry</code> object for the specified
65.357 + * entry name.
65.358 + *
65.359 + * @param name the ZIP file entry name
65.360 + * @return the ZipEntry just created
65.361 + */
65.362 + protected ZipEntry createZipEntry(String name) {
65.363 + return new ZipEntry(name);
65.364 + }
65.365 +
65.366 + /*
65.367 + * Reads end of deflated entry as well as EXT descriptor if present.
65.368 + */
65.369 + private void readEnd(ZipEntry e) throws IOException {
65.370 + int n = inf.getRemaining();
65.371 + if (n > 0) {
65.372 + ((PushbackInputStream)in).unread(buf, len - n, n);
65.373 + }
65.374 + if ((flag & 8) == 8) {
65.375 + /* "Data Descriptor" present */
65.376 + if (inf.getBytesWritten() > ZIP64_MAGICVAL ||
65.377 + inf.getBytesRead() > ZIP64_MAGICVAL) {
65.378 + // ZIP64 format
65.379 + readFully(tmpbuf, 0, ZIP64_EXTHDR);
65.380 + long sig = get32(tmpbuf, 0);
65.381 + if (sig != EXTSIG) { // no EXTSIG present
65.382 + e.crc = sig;
65.383 + e.csize = get64(tmpbuf, ZIP64_EXTSIZ - ZIP64_EXTCRC);
65.384 + e.size = get64(tmpbuf, ZIP64_EXTLEN - ZIP64_EXTCRC);
65.385 + ((PushbackInputStream)in).unread(
65.386 + tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC - 1, ZIP64_EXTCRC);
65.387 + } else {
65.388 + e.crc = get32(tmpbuf, ZIP64_EXTCRC);
65.389 + e.csize = get64(tmpbuf, ZIP64_EXTSIZ);
65.390 + e.size = get64(tmpbuf, ZIP64_EXTLEN);
65.391 + }
65.392 + } else {
65.393 + readFully(tmpbuf, 0, EXTHDR);
65.394 + long sig = get32(tmpbuf, 0);
65.395 + if (sig != EXTSIG) { // no EXTSIG present
65.396 + e.crc = sig;
65.397 + e.csize = get32(tmpbuf, EXTSIZ - EXTCRC);
65.398 + e.size = get32(tmpbuf, EXTLEN - EXTCRC);
65.399 + ((PushbackInputStream)in).unread(
65.400 + tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC);
65.401 + } else {
65.402 + e.crc = get32(tmpbuf, EXTCRC);
65.403 + e.csize = get32(tmpbuf, EXTSIZ);
65.404 + e.size = get32(tmpbuf, EXTLEN);
65.405 + }
65.406 + }
65.407 + }
65.408 + if (e.size != inf.getBytesWritten()) {
65.409 + throw new ZipException(
65.410 + "invalid entry size (expected " + e.size +
65.411 + " but got " + inf.getBytesWritten() + " bytes)");
65.412 + }
65.413 + if (e.csize != inf.getBytesRead()) {
65.414 + throw new ZipException(
65.415 + "invalid entry compressed size (expected " + e.csize +
65.416 + " but got " + inf.getBytesRead() + " bytes)");
65.417 + }
65.418 + if (e.crc != crc.getValue()) {
65.419 + throw new ZipException(
65.420 + "invalid entry CRC (expected 0x" + Long.toHexString(e.crc) +
65.421 + " but got 0x" + Long.toHexString(crc.getValue()) + ")");
65.422 + }
65.423 + }
65.424 +
65.425 + /*
65.426 + * Reads bytes, blocking until all bytes are read.
65.427 + */
65.428 + private void readFully(byte[] b, int off, int len) throws IOException {
65.429 + while (len > 0) {
65.430 + int n = in.read(b, off, len);
65.431 + if (n == -1) {
65.432 + throw new EOFException();
65.433 + }
65.434 + off += n;
65.435 + len -= n;
65.436 + }
65.437 + }
65.438 +
65.439 + /*
65.440 + * Fetches unsigned 16-bit value from byte array at specified offset.
65.441 + * The bytes are assumed to be in Intel (little-endian) byte order.
65.442 + */
65.443 + private static final int get16(byte b[], int off) {
65.444 + return (b[off] & 0xff) | ((b[off+1] & 0xff) << 8);
65.445 + }
65.446 +
65.447 + /*
65.448 + * Fetches unsigned 32-bit value from byte array at specified offset.
65.449 + * The bytes are assumed to be in Intel (little-endian) byte order.
65.450 + */
65.451 + private static final long get32(byte b[], int off) {
65.452 + return (get16(b, off) | ((long)get16(b, off+2) << 16)) & 0xffffffffL;
65.453 + }
65.454 +
65.455 + /*
65.456 + * Fetches signed 64-bit value from byte array at specified offset.
65.457 + * The bytes are assumed to be in Intel (little-endian) byte order.
65.458 + */
65.459 + private static final long get64(byte b[], int off) {
65.460 + return get32(b, off) | (get32(b, off+4) << 32);
65.461 + }
65.462 +
65.463 + private static String toStringUTF8(byte[] arr, int len) {
65.464 + return new String(arr, 0, len);
65.465 + }
65.466 +
65.467 + private static String toString(byte[] b, int len) {
65.468 + return new String(b, 0, len);
65.469 + }
65.470 +}
66.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
66.2 +++ b/emul/mini/src/main/java/java/util/zip/package.html Mon Feb 04 09:37:56 2013 +0100
66.3 @@ -0,0 +1,98 @@
66.4 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
66.5 +<html>
66.6 +<head>
66.7 +<!--
66.8 +Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
66.9 +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
66.10 +
66.11 +This code is free software; you can redistribute it and/or modify it
66.12 +under the terms of the GNU General Public License version 2 only, as
66.13 +published by the Free Software Foundation. Oracle designates this
66.14 +particular file as subject to the "Classpath" exception as provided
66.15 +by Oracle in the LICENSE file that accompanied this code.
66.16 +
66.17 +This code is distributed in the hope that it will be useful, but WITHOUT
66.18 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
66.19 +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
66.20 +version 2 for more details (a copy is included in the LICENSE file that
66.21 +accompanied this code).
66.22 +
66.23 +You should have received a copy of the GNU General Public License version
66.24 +2 along with this work; if not, write to the Free Software Foundation,
66.25 +Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
66.26 +
66.27 +Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
66.28 +or visit www.oracle.com if you need additional information or have any
66.29 +questions.
66.30 +-->
66.31 +
66.32 +</head>
66.33 +<body bgcolor="white">
66.34 +
66.35 +Provides classes for reading and writing the standard ZIP and GZIP
66.36 +file formats. Also includes classes for compressing and decompressing
66.37 +data using the DEFLATE compression algorithm, which is used by the
66.38 +ZIP and GZIP file formats. Additionally, there are utility classes
66.39 +for computing the CRC-32 and Adler-32 checksums of arbitrary
66.40 +input streams.
66.41 +
66.42 +
66.43 +<h2>Package Specification</h2>
66.44 +
66.45 +</a>
66.46 +<ul>
66.47 + <li><a href="ftp://ftp.uu.net/pub/archiving/zip/doc/appnote-970311-iz.zip">
66.48 + Info-ZIP Application Note 970311
66.49 + </a> - a detailed description of the Info-ZIP format upon which
66.50 + the <code>java.util.zip</code> classes are based.
66.51 +<p>
66.52 + <a name="zip64">
66.53 + <li>An implementation may optionally support the ZIP64(tm) format extensions
66.54 + defined by the
66.55 + <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">
66.56 + PKWARE ZIP File Format Specification</a>. The ZIP64(tm) format extensions
66.57 + are used to overcome the size limitations of the original ZIP format.
66.58 +<p>
66.59 + <a name="lang_encoding">
66.60 + <li>APPENDIX D of <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">
66.61 + PKWARE ZIP File Format Specification</a> - Language Encoding Flag (EFS) to
66.62 + encode ZIP entry filename and comment fields using UTF-8.
66.63 +<p>
66.64 + <li><a href="http://www.ietf.org/rfc/rfc1950.txt">
66.65 + ZLIB Compressed Data Format Specification version 3.3</a>
66.66 +
66.67 + <a href="http://www.ietf.org/rfc/rfc1950.txt.pdf">(pdf)</a>
66.68 + (RFC 1950)
66.69 +<p>
66.70 + <li><a href="http://www.ietf.org/rfc/rfc1951.txt">
66.71 + DEFLATE Compressed Data Format Specification version 1.3</a>
66.72 +
66.73 + <a href="http://www.ietf.org/rfc/rfc1951.txt.pdf">(pdf)</a>
66.74 + (RFC 1951)
66.75 +<p>
66.76 + <li><a href="http://www.ietf.org/rfc/rfc1952.txt">
66.77 + GZIP file format specification version 4.3</a>
66.78 +
66.79 + <a href="http://www.ietf.org/rfc/rfc1952.txt.pdf">(pdf)</a>
66.80 + (RFC 1952)
66.81 +<p>
66.82 + <li>CRC-32 checksum is described in RFC 1952 (above)
66.83 +<p>
66.84 + <li>Adler-32 checksum is described in RFC 1950 (above)
66.85 +</ul>
66.86 +
66.87 +
66.88 +<!--
66.89 +<h2>Related Documentation</h2>
66.90 +
66.91 +For overviews, tutorials, examples, guides, and tool documentation, please see:
66.92 +<ul>
66.93 + <li><a href="">##### REFER TO NON-SPEC DOCUMENTATION HERE #####</a>
66.94 +</ul>
66.95 +-->
66.96 +
66.97 +@since JDK1.1
66.98 +</body>
66.99 +</html>
66.100 +
66.101 +
67.1 --- a/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/System.java Fri Feb 01 16:34:51 2013 +0100
67.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/System.java Mon Feb 04 09:37:56 2013 +0100
67.3 @@ -51,4 +51,7 @@
67.4 public static long nanoTime() {
67.5 return 1000L * currentTimeMillis();
67.6 }
67.7 + @JavaScriptBody(args = { "obj" }, body="return vm.java_lang_Object(false).hashCode__I.call(obj);")
67.8 + public static native int identityHashCode(Object obj);
67.9 +
67.10 }
68.1 --- a/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/MethodImpl.java Fri Feb 01 16:34:51 2013 +0100
68.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/MethodImpl.java Mon Feb 04 09:37:56 2013 +0100
68.3 @@ -1,26 +1,19 @@
68.4 -/*
68.5 - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
68.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
68.7 +/**
68.8 + * Back 2 Browser Bytecode Translator
68.9 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
68.10 *
68.11 - * This code is free software; you can redistribute it and/or modify it
68.12 - * under the terms of the GNU General Public License version 2 only, as
68.13 - * published by the Free Software Foundation. Oracle designates this
68.14 - * particular file as subject to the "Classpath" exception as provided
68.15 - * by Oracle in the LICENSE file that accompanied this code.
68.16 + * This program is free software: you can redistribute it and/or modify
68.17 + * it under the terms of the GNU General Public License as published by
68.18 + * the Free Software Foundation, version 2 of the License.
68.19 *
68.20 - * This code is distributed in the hope that it will be useful, but WITHOUT
68.21 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
68.22 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
68.23 - * version 2 for more details (a copy is included in the LICENSE file that
68.24 - * accompanied this code).
68.25 + * This program is distributed in the hope that it will be useful,
68.26 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
68.27 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
68.28 + * GNU General Public License for more details.
68.29 *
68.30 - * You should have received a copy of the GNU General Public License version
68.31 - * 2 along with this work; if not, write to the Free Software Foundation,
68.32 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
68.33 - *
68.34 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
68.35 - * or visit www.oracle.com if you need additional information or have any
68.36 - * questions.
68.37 + * You should have received a copy of the GNU General Public License
68.38 + * along with this program. Look for COPYING file in the top folder.
68.39 + * If not, see http://opensource.org/licenses/GPL-2.0.
68.40 */
68.41 package org.apidesign.bck2brwsr.emul.reflect;
68.42
69.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
69.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/TypeProvider.java Mon Feb 04 09:37:56 2013 +0100
69.3 @@ -0,0 +1,40 @@
69.4 +/**
69.5 + * Back 2 Browser Bytecode Translator
69.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
69.7 + *
69.8 + * This program is free software: you can redistribute it and/or modify
69.9 + * it under the terms of the GNU General Public License as published by
69.10 + * the Free Software Foundation, version 2 of the License.
69.11 + *
69.12 + * This program is distributed in the hope that it will be useful,
69.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
69.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
69.15 + * GNU General Public License for more details.
69.16 + *
69.17 + * You should have received a copy of the GNU General Public License
69.18 + * along with this program. Look for COPYING file in the top folder.
69.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
69.20 + */
69.21 +package org.apidesign.bck2brwsr.emul.reflect;
69.22 +
69.23 +import java.lang.reflect.Constructor;
69.24 +import java.lang.reflect.Type;
69.25 +import java.lang.reflect.TypeVariable;
69.26 +
69.27 +/**
69.28 + *
69.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
69.30 + */
69.31 +public abstract class TypeProvider {
69.32 + private TypeProvider() {
69.33 + }
69.34 +
69.35 + public static TypeProvider getDefault() {
69.36 + return null;
69.37 + }
69.38 +
69.39 + public abstract <T> TypeVariable<Constructor<T>>[] getTypeParameters(Constructor<T> c);
69.40 + public abstract <T> Type[] getGenericParameterTypes(Constructor<T> c);
69.41 + public abstract <T> Type[] getGenericExceptionTypes(Constructor<T> c);
69.42 +
69.43 +}
70.1 --- a/javaquery/api/pom.xml Fri Feb 01 16:34:51 2013 +0100
70.2 +++ b/javaquery/api/pom.xml Mon Feb 04 09:37:56 2013 +0100
70.3 @@ -43,6 +43,7 @@
70.4 <dependency>
70.5 <groupId>org.netbeans.api</groupId>
70.6 <artifactId>org-openide-util-lookup</artifactId>
70.7 + <scope>provided</scope>
70.8 </dependency>
70.9 <dependency>
70.10 <groupId>org.apidesign.bck2brwsr</groupId>
71.1 --- a/javaquery/demo-calculator/nbactions.xml Fri Feb 01 16:34:51 2013 +0100
71.2 +++ b/javaquery/demo-calculator/nbactions.xml Mon Feb 04 09:37:56 2013 +0100
71.3 @@ -23,7 +23,7 @@
71.4 <actionName>run</actionName>
71.5 <goals>
71.6 <goal>process-classes</goal>
71.7 - <goal>org.codehaus.mojo:exec-maven-plugin:1.2.1:exec</goal>
71.8 + <goal>org.apidesign.bck2brwsr:mojo:0.3-SNAPSHOT:brwsr</goal>
71.9 </goals>
71.10 </action>
71.11 </actions>
72.1 --- a/javaquery/demo-calculator/pom.xml Fri Feb 01 16:34:51 2013 +0100
72.2 +++ b/javaquery/demo-calculator/pom.xml Mon Feb 04 09:37:56 2013 +0100
72.3 @@ -16,34 +16,21 @@
72.4 </properties>
72.5 <build>
72.6 <plugins>
72.7 - <plugin>
72.8 - <groupId>org.apidesign.bck2brwsr</groupId>
72.9 - <artifactId>mojo</artifactId>
72.10 - <version>0.3-SNAPSHOT</version>
72.11 - <executions>
72.12 - <execution>
72.13 - <goals>
72.14 - <goal>j2js</goal>
72.15 - </goals>
72.16 - </execution>
72.17 - </executions>
72.18 - </plugin>
72.19 <plugin>
72.20 - <groupId>org.codehaus.mojo</groupId>
72.21 - <artifactId>exec-maven-plugin</artifactId>
72.22 - <version>1.2.1</version>
72.23 + <groupId>org.apidesign.bck2brwsr</groupId>
72.24 + <artifactId>mojo</artifactId>
72.25 + <version>0.3-SNAPSHOT</version>
72.26 <executions>
72.27 <execution>
72.28 <goals>
72.29 - <goal>exec</goal>
72.30 + <goal>j2js</goal>
72.31 + <goal>brwsr</goal>
72.32 </goals>
72.33 </execution>
72.34 </executions>
72.35 <configuration>
72.36 - <executable>xdg-open</executable>
72.37 - <arguments>
72.38 - <argument>${project.build.directory}/classes/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml</argument>
72.39 - </arguments>
72.40 + <directory>${project.build.directory}/${project.build.finalName}-bck2brwsr/public_html/</directory>
72.41 + <startpage>index.xhtml</startpage>
72.42 </configuration>
72.43 </plugin>
72.44 <plugin>
72.45 @@ -55,6 +42,24 @@
72.46 <target>1.7</target>
72.47 </configuration>
72.48 </plugin>
72.49 + <plugin>
72.50 + <artifactId>maven-assembly-plugin</artifactId>
72.51 + <version>2.4</version>
72.52 + <executions>
72.53 + <execution>
72.54 + <id>distro-assembly</id>
72.55 + <phase>package</phase>
72.56 + <goals>
72.57 + <goal>single</goal>
72.58 + </goals>
72.59 + <configuration>
72.60 + <descriptors>
72.61 + <descriptor>src/main/assembly/bck2brwsr.xml</descriptor>
72.62 + </descriptors>
72.63 + </configuration>
72.64 + </execution>
72.65 + </executions>
72.66 + </plugin>
72.67 </plugins>
72.68 </build>
72.69
73.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
73.2 +++ b/javaquery/demo-calculator/src/main/assembly/bck2brwsr.xml Mon Feb 04 09:37:56 2013 +0100
73.3 @@ -0,0 +1,54 @@
73.4 +<?xml version="1.0"?>
73.5 +<!--
73.6 +
73.7 + Back 2 Browser Bytecode Translator
73.8 + Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
73.9 +
73.10 + This program is free software: you can redistribute it and/or modify
73.11 + it under the terms of the GNU General Public License as published by
73.12 + the Free Software Foundation, version 2 of the License.
73.13 +
73.14 + This program is distributed in the hope that it will be useful,
73.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of
73.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
73.17 + GNU General Public License for more details.
73.18 +
73.19 + You should have received a copy of the GNU General Public License
73.20 + along with this program. Look for COPYING file in the top folder.
73.21 + If not, see http://opensource.org/licenses/GPL-2.0.
73.22 +
73.23 +-->
73.24 +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
73.25 + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
73.26 +
73.27 + <id>bck2brwsr</id>
73.28 + <formats>
73.29 + <format>zip</format>
73.30 + <format>dir</format>
73.31 + </formats>
73.32 + <baseDirectory>public_html</baseDirectory>
73.33 + <dependencySets>
73.34 + <dependencySet>
73.35 + <useProjectArtifact>false</useProjectArtifact>
73.36 + <scope>runtime</scope>
73.37 + <outputDirectory>lib</outputDirectory>
73.38 + </dependencySet>
73.39 + </dependencySets>
73.40 + <files>
73.41 + <file>
73.42 + <source>${project.build.directory}/${project.build.finalName}.jar</source>
73.43 + <outputDirectory>/</outputDirectory>
73.44 + </file>
73.45 + <file>
73.46 + <source>${project.build.directory}/classes/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml</source>
73.47 + <outputDirectory>/</outputDirectory>
73.48 + <destName>index.xhtml</destName>
73.49 + </file>
73.50 + <file>
73.51 + <source>${project.build.directory}/classes/org/apidesign/bck2brwsr/demo/calc/staticcompilation/bootjava.js</source>
73.52 + <outputDirectory>/</outputDirectory>
73.53 + <destName>bck2brwsr.js</destName>
73.54 + </file>
73.55 + </files>
73.56 +
73.57 +</assembly>
73.58 \ No newline at end of file
74.1 --- a/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml Fri Feb 01 16:34:51 2013 +0100
74.2 +++ b/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml Mon Feb 04 09:37:56 2013 +0100
74.3 @@ -77,78 +77,6 @@
74.4 </tbody>
74.5 </table>
74.6 <div data-bind="text: displayPreview"></div>
74.7 - <script src="bootjava.js"/>
74.8 -
74.9 - <hr/>
74.10 - <pre>
74.11 - <span class="keyword-directive">package</span> org.apidesign.bck2brwsr.mavenhtml;
74.12 -
74.13 - <span class="keyword-directive">import</span> org.apidesign.bck2brwsr.htmlpage.api.OnClick;
74.14 - <span class="keyword-directive">import</span> org.apidesign.bck2brwsr.htmlpage.api.Page;
74.15 -
74.16 - <span class="comment">/**</span> <span class="comment">HTML5</span><span class="comment"> & </span><span class="comment">Java</span> <span class="comment">demo</span> <span class="comment">showing</span> <span class="comment">the</span> <span class="comment">power</span> <span class="comment">of</span> <a href="http://wiki.apidesign.org/wiki/AnnotationProcessor">annotation processors</a>
74.17 - <span class="comment"> * </span><span class="comment">as</span> <span class="comment">well</span> <span class="comment">as</span> <span class="comment">other</span> <span class="comment">goodies</span><span class="comment">, including type-safe association between</span>
74.18 - <span class="comment"> * </span><span class="comment">an XHTML page and Java.</span>
74.19 - <span class="comment"> * </span>
74.20 - <span class="comment"> * </span><span class="ST1">@author</span> <span class="comment">Jaroslav</span> <span class="comment">Tulach</span> <span class="ST0"><jaroslav.tulach@apidesign.org></span>
74.21 - <span class="comment">*/</span>
74.22 - @Page(xhtml=<span class="string">"</span><span class="string">Calculator.xhtml</span><span class="string">"</span>)
74.23 - <span class="keyword-directive">public</span> <span class="keyword-directive">class</span> App {
74.24 - <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> <span class="keyword-directive">double</span> memory;
74.25 - <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> String operation;
74.26 -
74.27 - @OnClick(id=<span class="string">"</span><span class="string">clear</span><span class="string">"</span>)
74.28 - <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> clear() {
74.29 - memory = <span class="number">0</span>;
74.30 - operation = <span class="keyword-directive">null</span>;
74.31 - Calculator.DISPLAY.setValue(<span class="string">"</span><span class="string">0</span><span class="string">"</span>);
74.32 - }
74.33 -
74.34 - @OnClick(id= { <span class="string">"</span><span class="string">plus</span><span class="string">"</span>, <span class="string">"</span><span class="string">minus</span><span class="string">"</span>, <span class="string">"</span><span class="string">mul</span><span class="string">"</span>, <span class="string">"</span><span class="string">div</span><span class="string">"</span> })
74.35 - <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> applyOp(String op) {
74.36 - memory = getValue();
74.37 - operation = op;
74.38 - Calculator.DISPLAY.setValue(<span class="string">"</span><span class="string">0</span><span class="string">"</span>);
74.39 - }
74.40 -
74.41 - @OnClick(id=<span class="string">"</span><span class="string">result</span><span class="string">"</span>)
74.42 - <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> computeTheValue() {
74.43 - <span class="keyword-directive">switch</span> (operation) {
74.44 - <span class="keyword-directive">case</span> <span class="string">"</span><span class="string">plus</span><span class="string">"</span>: setValue(memory + getValue()); <span class="keyword-directive">break</span>;
74.45 - <span class="keyword-directive">case</span> <span class="string">"</span><span class="string">minus</span><span class="string">"</span>: setValue(memory - getValue()); <span class="keyword-directive">break</span>;
74.46 - <span class="keyword-directive">case</span> <span class="string">"</span><span class="string">mul</span><span class="string">"</span>: setValue(memory * getValue()); <span class="keyword-directive">break</span>;
74.47 - <span class="keyword-directive">case</span> <span class="string">"</span><span class="string">div</span><span class="string">"</span>: setValue(memory / getValue()); <span class="keyword-directive">break</span>;
74.48 - <span class="keyword-directive">default</span>: <span class="keyword-directive">throw</span> <span class="keyword-directive">new</span> IllegalStateException(operation);
74.49 - }
74.50 - }
74.51 -
74.52 - @OnClick(id={<span class="string">"</span><span class="string">n0</span><span class="string">"</span>, <span class="string">"</span><span class="string">n1</span><span class="string">"</span>, <span class="string">"</span><span class="string">n2</span><span class="string">"</span>, <span class="string">"</span><span class="string">n3</span><span class="string">"</span>, <span class="string">"</span><span class="string">n4</span><span class="string">"</span>, <span class="string">"</span><span class="string">n5</span><span class="string">"</span>, <span class="string">"</span><span class="string">n6</span><span class="string">"</span>, <span class="string">"</span><span class="string">n7</span><span class="string">"</span>, <span class="string">"</span><span class="string">n8</span><span class="string">"</span>, <span class="string">"</span><span class="string">n9</span><span class="string">"</span>})
74.53 - <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> addDigit(String digit) {
74.54 - digit = digit.substring(<span class="number">1</span>);
74.55 - String v = Calculator.DISPLAY.getValue();
74.56 - <span class="keyword-directive">if</span> (getValue() == <span class="number">0.0</span>) {
74.57 - Calculator.DISPLAY.setValue(digit);
74.58 - } <span class="keyword-directive">else</span> {
74.59 - Calculator.DISPLAY.setValue(v + digit);
74.60 - }
74.61 - }
74.62 -
74.63 - <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> setValue(<span class="keyword-directive">double</span> v) {
74.64 - StringBuilder sb = <span class="keyword-directive">new</span> StringBuilder();
74.65 - sb.append(v);
74.66 - Calculator.DISPLAY.setValue(sb.toString());
74.67 - }
74.68 -
74.69 - <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> <span class="keyword-directive">double</span> getValue() {
74.70 - <span class="keyword-directive">try</span> {
74.71 - <span class="keyword-directive">return</span> Double.parseDouble(Calculator.DISPLAY.getValue());
74.72 - } <span class="keyword-directive">catch</span> (NumberFormatException ex) {
74.73 - Calculator.DISPLAY.setValue(<span class="string">"</span><span class="string">err</span><span class="string">"</span>);
74.74 - <span class="keyword-directive">return</span> <span class="number">0.0</span>;
74.75 - }
74.76 - }
74.77 - }
74.78 -
74.79 - </pre>
74.80 + <script src="bck2brwsr.js"/>
74.81 </body>
74.82 </html>
75.1 --- a/launcher/pom.xml Fri Feb 01 16:34:51 2013 +0100
75.2 +++ b/launcher/pom.xml Mon Feb 04 09:37:56 2013 +0100
75.3 @@ -23,6 +23,14 @@
75.4 <target>1.7</target>
75.5 </configuration>
75.6 </plugin>
75.7 + <plugin>
75.8 + <groupId>org.apache.maven.plugins</groupId>
75.9 + <artifactId>maven-javadoc-plugin</artifactId>
75.10 + <version>2.8.1</version>
75.11 + <configuration>
75.12 + <excludePackageNames>org.apidesign.bck2brwsr.launcher.impl</excludePackageNames>
75.13 + </configuration>
75.14 + </plugin>
75.15 </plugins>
75.16 </build>
75.17 <properties>
76.1 --- a/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java Fri Feb 01 16:34:51 2013 +0100
76.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java Mon Feb 04 09:37:56 2013 +0100
76.3 @@ -55,24 +55,23 @@
76.4 */
76.5 final class Bck2BrwsrLauncher extends Launcher implements Closeable {
76.6 private static final Logger LOG = Logger.getLogger(Bck2BrwsrLauncher.class.getName());
76.7 - private static final MethodInvocation END = new MethodInvocation(null, null, null);
76.8 - private Set<ClassLoader> loaders = new LinkedHashSet<>();
76.9 - private BlockingQueue<MethodInvocation> methods = new LinkedBlockingQueue<>();
76.10 + private static final InvocationContext END = new InvocationContext(null, null, null);
76.11 + private final Set<ClassLoader> loaders = new LinkedHashSet<>();
76.12 + private final BlockingQueue<InvocationContext> methods = new LinkedBlockingQueue<>();
76.13 private long timeOut;
76.14 private final Res resources = new Res();
76.15 private final String cmd;
76.16 private Object[] brwsr;
76.17 private HttpServer server;
76.18 private CountDownLatch wait;
76.19 -
76.20 +
76.21 public Bck2BrwsrLauncher(String cmd) {
76.22 this.cmd = cmd;
76.23 }
76.24
76.25 @Override
76.26 - MethodInvocation addMethod(Class<?> clazz, String method, String html) throws IOException {
76.27 - loaders.add(clazz.getClassLoader());
76.28 - MethodInvocation c = new MethodInvocation(clazz.getName(), method, html);
76.29 + InvocationContext runMethod(InvocationContext c) throws IOException {
76.30 + loaders.add(c.clazz.getClassLoader());
76.31 methods.add(c);
76.32 try {
76.33 c.await(timeOut);
76.34 @@ -94,7 +93,7 @@
76.35 if (!startpage.startsWith("/")) {
76.36 startpage = "/" + startpage;
76.37 }
76.38 - HttpServer s = initServer();
76.39 + HttpServer s = initServer(".", true);
76.40 s.getServerConfiguration().addHttpHandler(new Page(resources, null), "/");
76.41 try {
76.42 launchServerAndBrwsr(s, startpage);
76.43 @@ -103,6 +102,18 @@
76.44 }
76.45 }
76.46
76.47 + void showDirectory(File dir, String startpage) throws IOException {
76.48 + if (!startpage.startsWith("/")) {
76.49 + startpage = "/" + startpage;
76.50 + }
76.51 + HttpServer s = initServer(dir.getPath(), false);
76.52 + try {
76.53 + launchServerAndBrwsr(s, startpage);
76.54 + } catch (URISyntaxException | InterruptedException ex) {
76.55 + throw new IOException(ex);
76.56 + }
76.57 + }
76.58 +
76.59 @Override
76.60 public void initialize() throws IOException {
76.61 try {
76.62 @@ -122,25 +133,54 @@
76.63 }
76.64 }
76.65
76.66 - private HttpServer initServer() throws IOException {
76.67 - HttpServer s = HttpServer.createSimpleServer(".", new PortRange(8080, 65535));
76.68 + private HttpServer initServer(String path, boolean addClasses) throws IOException {
76.69 + HttpServer s = HttpServer.createSimpleServer(path, new PortRange(8080, 65535));
76.70
76.71 final ServerConfiguration conf = s.getServerConfiguration();
76.72 - conf.addHttpHandler(new VM(resources), "/vm.js");
76.73 - conf.addHttpHandler(new Classes(resources), "/classes/");
76.74 + if (addClasses) {
76.75 + conf.addHttpHandler(new VM(resources), "/vm.js");
76.76 + conf.addHttpHandler(new Classes(resources), "/classes/");
76.77 + }
76.78 return s;
76.79 }
76.80
76.81 private void executeInBrowser() throws InterruptedException, URISyntaxException, IOException {
76.82 wait = new CountDownLatch(1);
76.83 - server = initServer();
76.84 - ServerConfiguration conf = server.getServerConfiguration();
76.85 + server = initServer(".", true);
76.86 + final ServerConfiguration conf = server.getServerConfiguration();
76.87 +
76.88 + class DynamicResourceHandler extends HttpHandler {
76.89 + private final InvocationContext ic;
76.90 + public DynamicResourceHandler(InvocationContext ic) {
76.91 + if (ic == null || ic.httpPath == null) {
76.92 + throw new NullPointerException();
76.93 + }
76.94 + this.ic = ic;
76.95 + conf.addHttpHandler(this, ic.httpPath);
76.96 + }
76.97 +
76.98 + public void close() {
76.99 + conf.removeHttpHandler(this);
76.100 + }
76.101 +
76.102 + @Override
76.103 + public void service(Request request, Response response) throws Exception {
76.104 + if (ic.httpPath.equals(request.getRequestURI())) {
76.105 + LOG.log(Level.INFO, "Serving HttpResource for {0}", request.getRequestURI());
76.106 + response.setContentType(ic.httpType);
76.107 + copyStream(ic.httpContent, response.getOutputStream(), null);
76.108 + }
76.109 + }
76.110 + }
76.111 +
76.112 conf.addHttpHandler(new Page(resources,
76.113 "org/apidesign/bck2brwsr/launcher/harness.xhtml"
76.114 ), "/execute");
76.115 +
76.116 conf.addHttpHandler(new HttpHandler() {
76.117 int cnt;
76.118 - List<MethodInvocation> cases = new ArrayList<>();
76.119 + List<InvocationContext> cases = new ArrayList<>();
76.120 + DynamicResourceHandler prev;
76.121 @Override
76.122 public void service(Request request, Response response) throws Exception {
76.123 String id = request.getParameter("request");
76.124 @@ -152,7 +192,12 @@
76.125 cases.get(Integer.parseInt(id)).result(value, null);
76.126 }
76.127
76.128 - MethodInvocation mi = methods.take();
76.129 + if (prev != null) {
76.130 + prev.close();
76.131 + prev = null;
76.132 + }
76.133 +
76.134 + InvocationContext mi = methods.take();
76.135 if (mi == END) {
76.136 response.getWriter().write("");
76.137 wait.countDown();
76.138 @@ -161,8 +206,12 @@
76.139 return;
76.140 }
76.141
76.142 + if (mi.httpPath != null) {
76.143 + prev = new DynamicResourceHandler(mi);
76.144 + }
76.145 +
76.146 cases.add(mi);
76.147 - final String cn = mi.className;
76.148 + final String cn = mi.clazz.getName();
76.149 final String mn = mi.methodName;
76.150 LOG.log(Level.INFO, "Request for {0} case. Sending {1}.{2}", new Object[]{cnt, cn, mn});
76.151 response.getWriter().write("{"
77.1 --- a/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Console.java Fri Feb 01 16:34:51 2013 +0100
77.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
77.3 @@ -1,253 +0,0 @@
77.4 -/**
77.5 - * Back 2 Browser Bytecode Translator
77.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
77.7 - *
77.8 - * This program is free software: you can redistribute it and/or modify
77.9 - * it under the terms of the GNU General Public License as published by
77.10 - * the Free Software Foundation, version 2 of the License.
77.11 - *
77.12 - * This program is distributed in the hope that it will be useful,
77.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
77.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
77.15 - * GNU General Public License for more details.
77.16 - *
77.17 - * You should have received a copy of the GNU General Public License
77.18 - * along with this program. Look for COPYING file in the top folder.
77.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
77.20 - */
77.21 -package org.apidesign.bck2brwsr.launcher;
77.22 -
77.23 -import java.io.IOException;
77.24 -import java.io.InputStream;
77.25 -import java.lang.reflect.InvocationTargetException;
77.26 -import java.lang.reflect.Method;
77.27 -import java.lang.reflect.Modifier;
77.28 -import java.net.URL;
77.29 -import java.util.Enumeration;
77.30 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
77.31 -
77.32 -/**
77.33 - *
77.34 - * @author Jaroslav Tulach <jtulach@netbeans.org>
77.35 - */
77.36 -public class Console {
77.37 - static {
77.38 - turnAssetionStatusOn();
77.39 - }
77.40 -
77.41 - @JavaScriptBody(args = {"id", "attr"}, body =
77.42 - "return window.document.getElementById(id)[attr].toString();")
77.43 - private static native Object getAttr(String id, String attr);
77.44 -
77.45 - @JavaScriptBody(args = {"id", "attr", "value"}, body =
77.46 - "window.document.getElementById(id)[attr] = value;")
77.47 - private static native void setAttr(String id, String attr, Object value);
77.48 -
77.49 - @JavaScriptBody(args = {}, body = "return; window.close();")
77.50 - private static native void closeWindow();
77.51 -
77.52 - private static void log(String newText) {
77.53 - String id = "bck2brwsr.result";
77.54 - String attr = "value";
77.55 - setAttr(id, attr, getAttr(id, attr) + "\n" + newText);
77.56 - setAttr(id, "scrollTop", getAttr(id, "scrollHeight"));
77.57 - }
77.58 -
77.59 - public static void execute() throws Exception {
77.60 - String clazz = (String) getAttr("clazz", "value");
77.61 - String method = (String) getAttr("method", "value");
77.62 - Object res = invokeMethod(clazz, method);
77.63 - setAttr("bck2brwsr.result", "value", res);
77.64 - }
77.65 -
77.66 - @JavaScriptBody(args = { "url", "callback", "arr" }, body = ""
77.67 - + "var request = new XMLHttpRequest();\n"
77.68 - + "request.open('GET', url, true);\n"
77.69 - + "request.onreadystatechange = function() {\n"
77.70 - + " if (this.readyState!==4) return;\n"
77.71 - + " arr[0] = this.responseText;\n"
77.72 - + " callback.run__V();\n"
77.73 - + "};"
77.74 - + "request.send();"
77.75 - )
77.76 - private static native void loadText(String url, Runnable callback, String[] arr) throws IOException;
77.77 -
77.78 - public static void harness(String url) throws IOException {
77.79 - log("Connecting to " + url);
77.80 - Request r = new Request(url);
77.81 - }
77.82 -
77.83 - private static class Request implements Runnable {
77.84 - private final String[] arr = { null };
77.85 - private final String url;
77.86 -
77.87 - private Request(String url) throws IOException {
77.88 - this.url = url;
77.89 - loadText(url, this, arr);
77.90 - }
77.91 -
77.92 - @Override
77.93 - public void run() {
77.94 - try {
77.95 - String data = arr[0];
77.96 - log("\nGot \"" + data + "\"");
77.97 -
77.98 - if (data == null) {
77.99 - log("Some error exiting");
77.100 - closeWindow();
77.101 - return;
77.102 - }
77.103 -
77.104 - if (data.isEmpty()) {
77.105 - log("No data, exiting");
77.106 - closeWindow();
77.107 - return;
77.108 - }
77.109 -
77.110 - Case c = Case.parseData(data);
77.111 - if (c.getHtmlFragment() != null) {
77.112 - setAttr("bck2brwsr.fragment", "innerHTML", c.getHtmlFragment());
77.113 - }
77.114 - log("Invoking " + c.getClassName() + '.' + c.getMethodName() + " as request: " + c.getRequestId());
77.115 -
77.116 - Object result = invokeMethod(c.getClassName(), c.getMethodName());
77.117 -
77.118 - setAttr("bck2brwsr.fragment", "innerHTML", "");
77.119 - log("Result: " + result);
77.120 -
77.121 - result = encodeURL("" + result);
77.122 -
77.123 - log("Sending back: " + url + "?request=" + c.getRequestId() + "&result=" + result);
77.124 - String u = url + "?request=" + c.getRequestId() + "&result=" + result;
77.125 -
77.126 - loadText(u, this, arr);
77.127 -
77.128 - } catch (Exception ex) {
77.129 - log(ex.getMessage());
77.130 - }
77.131 - }
77.132 - }
77.133 -
77.134 - private static String encodeURL(String r) {
77.135 - StringBuilder sb = new StringBuilder();
77.136 - for (int i = 0; i < r.length(); i++) {
77.137 - int ch = r.charAt(i);
77.138 - if (ch < 32 || ch == '%' || ch == '+') {
77.139 - sb.append("%").append(("0" + Integer.toHexString(ch)).substring(0, 2));
77.140 - } else {
77.141 - if (ch == 32) {
77.142 - sb.append("+");
77.143 - } else {
77.144 - sb.append((char)ch);
77.145 - }
77.146 - }
77.147 - }
77.148 - return sb.toString();
77.149 - }
77.150 -
77.151 - static String invoke(String clazz, String method) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException, InstantiationException {
77.152 - final Object r = invokeMethod(clazz, method);
77.153 - return r == null ? "null" : r.toString().toString();
77.154 - }
77.155 -
77.156 - /** Helper method that inspects the classpath and loads given resource
77.157 - * (usually a class file). Used while running tests in Rhino.
77.158 - *
77.159 - * @param name resource name to find
77.160 - * @return the array of bytes in the given resource
77.161 - * @throws IOException I/O in case something goes wrong
77.162 - */
77.163 - public static byte[] read(String name) throws IOException {
77.164 - URL u = null;
77.165 - Enumeration<URL> en = Console.class.getClassLoader().getResources(name);
77.166 - while (en.hasMoreElements()) {
77.167 - u = en.nextElement();
77.168 - }
77.169 - if (u == null) {
77.170 - throw new IOException("Can't find " + name);
77.171 - }
77.172 - try (InputStream is = u.openStream()) {
77.173 - byte[] arr;
77.174 - arr = new byte[is.available()];
77.175 - int offset = 0;
77.176 - while (offset < arr.length) {
77.177 - int len = is.read(arr, offset, arr.length - offset);
77.178 - if (len == -1) {
77.179 - throw new IOException("Can't read " + name);
77.180 - }
77.181 - offset += len;
77.182 - }
77.183 - return arr;
77.184 - }
77.185 - }
77.186 -
77.187 - private static Object invokeMethod(String clazz, String method)
77.188 - throws ClassNotFoundException, InvocationTargetException,
77.189 - SecurityException, IllegalAccessException, IllegalArgumentException,
77.190 - InstantiationException {
77.191 - Method found = null;
77.192 - Class<?> c = Class.forName(clazz);
77.193 - for (Method m : c.getMethods()) {
77.194 - if (m.getName().equals(method)) {
77.195 - found = m;
77.196 - }
77.197 - }
77.198 - Object res;
77.199 - if (found != null) {
77.200 - try {
77.201 - if ((found.getModifiers() & Modifier.STATIC) != 0) {
77.202 - res = found.invoke(null);
77.203 - } else {
77.204 - res = found.invoke(c.newInstance());
77.205 - }
77.206 - } catch (Throwable ex) {
77.207 - res = ex.getClass().getName() + ":" + ex.getMessage();
77.208 - }
77.209 - } else {
77.210 - res = "Can't find method " + method + " in " + clazz;
77.211 - }
77.212 - return res;
77.213 - }
77.214 -
77.215 - @JavaScriptBody(args = {}, body = "vm.desiredAssertionStatus = true;")
77.216 - private static void turnAssetionStatusOn() {
77.217 - }
77.218 -
77.219 - private static final class Case {
77.220 - private final Object data;
77.221 -
77.222 - private Case(Object data) {
77.223 - this.data = data;
77.224 - }
77.225 -
77.226 - public static Case parseData(String s) {
77.227 - return new Case(toJSON(s));
77.228 - }
77.229 -
77.230 - public String getMethodName() {
77.231 - return value("methodName", data);
77.232 - }
77.233 -
77.234 - public String getClassName() {
77.235 - return value("className", data);
77.236 - }
77.237 -
77.238 - public String getRequestId() {
77.239 - return value("request", data);
77.240 - }
77.241 -
77.242 - public String getHtmlFragment() {
77.243 - return value("html", data);
77.244 - }
77.245 -
77.246 - @JavaScriptBody(args = "s", body = "return eval('(' + s + ')');")
77.247 - private static native Object toJSON(String s);
77.248 -
77.249 - @JavaScriptBody(args = {"p", "d"}, body =
77.250 - "var v = d[p];\n"
77.251 - + "if (typeof v === 'undefined') return null;\n"
77.252 - + "return v.toString();"
77.253 - )
77.254 - private static native String value(String p, Object d);
77.255 - }
77.256 -}
78.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
78.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/InvocationContext.java Mon Feb 04 09:37:56 2013 +0100
78.3 @@ -0,0 +1,101 @@
78.4 +/**
78.5 + * Back 2 Browser Bytecode Translator
78.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
78.7 + *
78.8 + * This program is free software: you can redistribute it and/or modify
78.9 + * it under the terms of the GNU General Public License as published by
78.10 + * the Free Software Foundation, version 2 of the License.
78.11 + *
78.12 + * This program is distributed in the hope that it will be useful,
78.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
78.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
78.15 + * GNU General Public License for more details.
78.16 + *
78.17 + * You should have received a copy of the GNU General Public License
78.18 + * along with this program. Look for COPYING file in the top folder.
78.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
78.20 + */
78.21 +package org.apidesign.bck2brwsr.launcher;
78.22 +
78.23 +import java.io.IOException;
78.24 +import java.io.InputStream;
78.25 +import java.util.concurrent.CountDownLatch;
78.26 +import java.util.concurrent.TimeUnit;
78.27 +
78.28 +/** Represents individual method invocation, its context and its result.
78.29 + *
78.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
78.31 + */
78.32 +public final class InvocationContext {
78.33 + final CountDownLatch wait = new CountDownLatch(1);
78.34 + final Class<?> clazz;
78.35 + final String methodName;
78.36 + private final Launcher launcher;
78.37 + private String result;
78.38 + private Throwable exception;
78.39 + String html;
78.40 + InputStream httpContent;
78.41 + String httpType;
78.42 + String httpPath;
78.43 +
78.44 + InvocationContext(Launcher launcher, Class<?> clazz, String methodName) {
78.45 + this.launcher = launcher;
78.46 + this.clazz = clazz;
78.47 + this.methodName = methodName;
78.48 + }
78.49 +
78.50 + /** An HTML fragment to be available for the execution. Useful primarily when
78.51 + * executing in a browser via {@link Launcher#createBrowser(java.lang.String)}.
78.52 + * @param html the html fragment
78.53 + */
78.54 + public void setHtmlFragment(String html) {
78.55 + this.html = html;
78.56 + }
78.57 +
78.58 + /** HTTP resource to be available during execution. An invocation may
78.59 + * perform an HTTP query and obtain a resource relative to the page.
78.60 + */
78.61 + public void setHttpResource(String relativePath, String mimeType, InputStream content) {
78.62 + if (relativePath == null || mimeType == null || content == null) {
78.63 + throw new NullPointerException();
78.64 + }
78.65 + this.httpPath = relativePath;
78.66 + this.httpType = mimeType;
78.67 + this.httpContent = content;
78.68 + }
78.69 +
78.70 + /** Invokes the associated method.
78.71 + * @return the textual result of the invocation
78.72 + */
78.73 + public String invoke() throws IOException {
78.74 + launcher.runMethod(this);
78.75 + return toString();
78.76 + }
78.77 +
78.78 + /** Obtains textual result of the invocation.
78.79 + * @return text representing the exception or result value
78.80 + */
78.81 + @Override
78.82 + public String toString() {
78.83 + if (exception != null) {
78.84 + return exception.toString();
78.85 + }
78.86 + return result;
78.87 + }
78.88 +
78.89 + /**
78.90 + * @param timeOut
78.91 + * @throws InterruptedException
78.92 + */
78.93 + void await(long timeOut) throws InterruptedException {
78.94 + wait.await(timeOut, TimeUnit.MILLISECONDS);
78.95 + }
78.96 +
78.97 + void result(String r, Throwable e) {
78.98 + this.result = r;
78.99 + this.exception = e;
78.100 + wait.countDown();
78.101 + }
78.102 +
78.103 +
78.104 +}
79.1 --- a/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/JSLauncher.java Fri Feb 01 16:34:51 2013 +0100
79.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/JSLauncher.java Mon Feb 04 09:37:56 2013 +0100
79.3 @@ -17,6 +17,7 @@
79.4 */
79.5 package org.apidesign.bck2brwsr.launcher;
79.6
79.7 +import org.apidesign.bck2brwsr.launcher.impl.Console;
79.8 import java.io.IOException;
79.9 import java.io.InputStream;
79.10 import java.net.URL;
79.11 @@ -43,18 +44,17 @@
79.12 private Object console;
79.13
79.14
79.15 - @Override MethodInvocation addMethod(Class<?> clazz, String method, String html) {
79.16 - loaders.add(clazz.getClassLoader());
79.17 - MethodInvocation mi = new MethodInvocation(clazz.getName(), method, html);
79.18 + @Override InvocationContext runMethod(InvocationContext mi) {
79.19 + loaders.add(mi.clazz.getClassLoader());
79.20 try {
79.21 long time = System.currentTimeMillis();
79.22 - LOG.log(Level.FINE, "Invoking {0}.{1}", new Object[]{mi.className, mi.methodName});
79.23 + LOG.log(Level.FINE, "Invoking {0}.{1}", new Object[]{mi.clazz.getName(), mi.methodName});
79.24 String res = code.invokeMethod(
79.25 console,
79.26 "invoke__Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2",
79.27 - mi.className, mi.methodName).toString();
79.28 + mi.clazz.getName(), mi.methodName).toString();
79.29 time = System.currentTimeMillis() - time;
79.30 - LOG.log(Level.FINE, "Resut of {0}.{1} = {2} in {3} ms", new Object[]{mi.className, mi.methodName, res, time});
79.31 + LOG.log(Level.FINE, "Resut of {0}.{1} = {2} in {3} ms", new Object[]{mi.clazz.getName(), mi.methodName, res, time});
79.32 mi.result(res, null);
79.33 } catch (ScriptException | NoSuchMethodException ex) {
79.34 mi.result(null, ex);
79.35 @@ -89,7 +89,7 @@
79.36 ScriptEngine mach = sem.getEngineByExtension("js");
79.37
79.38 sb.append(
79.39 - "\nvar vm = new bck2brwsr(org.apidesign.bck2brwsr.launcher.Console.read);"
79.40 + "\nvar vm = new bck2brwsr(org.apidesign.bck2brwsr.launcher.impl.Console.read);"
79.41 + "\nfunction initVM() { return vm; };"
79.42 + "\n");
79.43
80.1 --- a/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java Fri Feb 01 16:34:51 2013 +0100
80.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java Mon Feb 04 09:37:56 2013 +0100
80.3 @@ -18,12 +18,14 @@
80.4 package org.apidesign.bck2brwsr.launcher;
80.5
80.6 import java.io.Closeable;
80.7 +import java.io.File;
80.8 import java.io.IOException;
80.9 import java.net.URLClassLoader;
80.10 import org.apidesign.vm4brwsr.Bck2Brwsr;
80.11
80.12 /** An abstraction for executing tests in a Bck2Brwsr virtual machine.
80.13 - * Either in JavaScript engine, or in external browser.
80.14 + * Either in {@linkm Launcher#createJavaScript JavaScript engine},
80.15 + * or in {@linkm Launcher#createBrowser external browser}.
80.16 *
80.17 * @author Jaroslav Tulach <jtulach@netbeans.org>
80.18 */
80.19 @@ -31,33 +33,83 @@
80.20
80.21 Launcher() {
80.22 }
80.23 +
80.24 + /** Initializes the launcher. This may mean starting a web browser or
80.25 + * initializing execution engine.
80.26 + * @throws IOException if something goes wrong
80.27 + */
80.28 + public abstract void initialize() throws IOException;
80.29
80.30 - abstract MethodInvocation addMethod(Class<?> clazz, String method, String html) throws IOException;
80.31 -
80.32 - public abstract void initialize() throws IOException;
80.33 + /** Shuts down the launcher.
80.34 + * @throws IOException if something goes wrong
80.35 + */
80.36 public abstract void shutdown() throws IOException;
80.37 - public MethodInvocation invokeMethod(Class<?> clazz, String method, String html) throws IOException {
80.38 - return addMethod(clazz, method, html);
80.39 +
80.40 +
80.41 + /** Builds an invocation context. The context can later be customized
80.42 + * and {@link InvocationContext#invoke() invoked}.
80.43 + *
80.44 + * @param clazz the class to execute method from
80.45 + * @param method the method to execute
80.46 + * @return the context pointing to the selected method
80.47 + */
80.48 + public InvocationContext createInvocation(Class<?> clazz, String method) {
80.49 + return new InvocationContext(this, clazz, method);
80.50 }
80.51
80.52 -
80.53
80.54 + /** Creates launcher that uses internal JavaScript engine (Rhino).
80.55 + * @return the launcher
80.56 + */
80.57 public static Launcher createJavaScript() {
80.58 final JSLauncher l = new JSLauncher();
80.59 l.addClassLoader(Bck2Brwsr.class.getClassLoader());
80.60 return l;
80.61 }
80.62
80.63 + /** Creates launcher that is using external browser.
80.64 + *
80.65 + * @param cmd <code>null</code> to use <code>java.awt.Desktop</code> to show the launcher
80.66 + * or a string to execute in an external process (with a parameter to the URL)
80.67 + * @return launcher executing in external browser.
80.68 + */
80.69 public static Launcher createBrowser(String cmd) {
80.70 final Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(cmd);
80.71 l.addClassLoader(Bck2Brwsr.class.getClassLoader());
80.72 l.setTimeout(180000);
80.73 return l;
80.74 }
80.75 +
80.76 + /** Starts an HTTP server which provides access to classes and resources
80.77 + * available in the <code>classes</code> URL and shows a start page
80.78 + * available as {@link ClassLoader#getResource(java.lang.String)} from the
80.79 + * provide classloader. Opens a browser with URL showing the start page.
80.80 + *
80.81 + * @param classes classloader offering access to classes and resources
80.82 + * @param startpage page to show in the browser
80.83 + * @return interface that allows one to stop the server
80.84 + * @throws IOException if something goes wrong
80.85 + */
80.86 public static Closeable showURL(URLClassLoader classes, String startpage) throws IOException {
80.87 Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(null);
80.88 l.addClassLoader(classes);
80.89 l.showURL(startpage);
80.90 return l;
80.91 }
80.92 + /** Starts an HTTP server which provides access to certain directory.
80.93 + * The <code>startpage</code> should be relative location inside the root
80.94 + * driecotry
80.95 + * Opens a browser with URL showing the start page.
80.96 + *
80.97 + * @param directory the root directory on disk
80.98 + * @praam startpage relative path from the root to the page
80.99 + * @exception IOException if something goes wrong.
80.100 + */
80.101 + public static Closeable showDir(File directory, String startpage) throws IOException {
80.102 + Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(null);
80.103 + l.showDirectory(directory, startpage);
80.104 + return l;
80.105 + }
80.106 +
80.107 + abstract InvocationContext runMethod(InvocationContext c) throws IOException;
80.108 }
81.1 --- a/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/MethodInvocation.java Fri Feb 01 16:34:51 2013 +0100
81.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
81.3 @@ -1,59 +0,0 @@
81.4 -/**
81.5 - * Back 2 Browser Bytecode Translator
81.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
81.7 - *
81.8 - * This program is free software: you can redistribute it and/or modify
81.9 - * it under the terms of the GNU General Public License as published by
81.10 - * the Free Software Foundation, version 2 of the License.
81.11 - *
81.12 - * This program is distributed in the hope that it will be useful,
81.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
81.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
81.15 - * GNU General Public License for more details.
81.16 - *
81.17 - * You should have received a copy of the GNU General Public License
81.18 - * along with this program. Look for COPYING file in the top folder.
81.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
81.20 - */
81.21 -package org.apidesign.bck2brwsr.launcher;
81.22 -
81.23 -import java.util.concurrent.CountDownLatch;
81.24 -import java.util.concurrent.TimeUnit;
81.25 -
81.26 -/**
81.27 - *
81.28 - * @author Jaroslav Tulach <jtulach@netbeans.org>
81.29 - */
81.30 -public final class MethodInvocation {
81.31 - final CountDownLatch wait = new CountDownLatch(1);
81.32 - final String className;
81.33 - final String methodName;
81.34 - final String html;
81.35 - private String result;
81.36 - private Throwable exception;
81.37 -
81.38 - MethodInvocation(String className, String methodName, String html) {
81.39 - this.className = className;
81.40 - this.methodName = methodName;
81.41 - this.html = html;
81.42 - }
81.43 -
81.44 - void await(long timeOut) throws InterruptedException {
81.45 - wait.await(timeOut, TimeUnit.MILLISECONDS);
81.46 - }
81.47 -
81.48 - void result(String r, Throwable e) {
81.49 - this.result = r;
81.50 - this.exception = e;
81.51 - wait.countDown();
81.52 - }
81.53 -
81.54 - @Override
81.55 - public String toString() {
81.56 - if (exception != null) {
81.57 - return exception.toString();
81.58 - }
81.59 - return result;
81.60 - }
81.61 -
81.62 -}
82.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
82.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/impl/Console.java Mon Feb 04 09:37:56 2013 +0100
82.3 @@ -0,0 +1,255 @@
82.4 +/**
82.5 + * Back 2 Browser Bytecode Translator
82.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
82.7 + *
82.8 + * This program is free software: you can redistribute it and/or modify
82.9 + * it under the terms of the GNU General Public License as published by
82.10 + * the Free Software Foundation, version 2 of the License.
82.11 + *
82.12 + * This program is distributed in the hope that it will be useful,
82.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
82.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
82.15 + * GNU General Public License for more details.
82.16 + *
82.17 + * You should have received a copy of the GNU General Public License
82.18 + * along with this program. Look for COPYING file in the top folder.
82.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
82.20 + */
82.21 +package org.apidesign.bck2brwsr.launcher.impl;
82.22 +
82.23 +import java.io.IOException;
82.24 +import java.io.InputStream;
82.25 +import java.lang.reflect.InvocationTargetException;
82.26 +import java.lang.reflect.Method;
82.27 +import java.lang.reflect.Modifier;
82.28 +import java.net.URL;
82.29 +import java.util.Enumeration;
82.30 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
82.31 +
82.32 +/**
82.33 + *
82.34 + * @author Jaroslav Tulach <jtulach@netbeans.org>
82.35 + */
82.36 +public class Console {
82.37 + private Console() {
82.38 + }
82.39 + static {
82.40 + turnAssetionStatusOn();
82.41 + }
82.42 +
82.43 + @JavaScriptBody(args = {"id", "attr"}, body =
82.44 + "return window.document.getElementById(id)[attr].toString();")
82.45 + private static native Object getAttr(String id, String attr);
82.46 +
82.47 + @JavaScriptBody(args = {"id", "attr", "value"}, body =
82.48 + "window.document.getElementById(id)[attr] = value;")
82.49 + private static native void setAttr(String id, String attr, Object value);
82.50 +
82.51 + @JavaScriptBody(args = {}, body = "return; window.close();")
82.52 + private static native void closeWindow();
82.53 +
82.54 + private static void log(String newText) {
82.55 + String id = "bck2brwsr.result";
82.56 + String attr = "value";
82.57 + setAttr(id, attr, getAttr(id, attr) + "\n" + newText);
82.58 + setAttr(id, "scrollTop", getAttr(id, "scrollHeight"));
82.59 + }
82.60 +
82.61 + public static void execute() throws Exception {
82.62 + String clazz = (String) getAttr("clazz", "value");
82.63 + String method = (String) getAttr("method", "value");
82.64 + Object res = invokeMethod(clazz, method);
82.65 + setAttr("bck2brwsr.result", "value", res);
82.66 + }
82.67 +
82.68 + @JavaScriptBody(args = { "url", "callback", "arr" }, body = ""
82.69 + + "var request = new XMLHttpRequest();\n"
82.70 + + "request.open('GET', url, true);\n"
82.71 + + "request.onreadystatechange = function() {\n"
82.72 + + " if (this.readyState!==4) return;\n"
82.73 + + " arr[0] = this.responseText;\n"
82.74 + + " callback.run__V();\n"
82.75 + + "};"
82.76 + + "request.send();"
82.77 + )
82.78 + private static native void loadText(String url, Runnable callback, String[] arr) throws IOException;
82.79 +
82.80 + public static void harness(String url) throws IOException {
82.81 + log("Connecting to " + url);
82.82 + Request r = new Request(url);
82.83 + }
82.84 +
82.85 + private static class Request implements Runnable {
82.86 + private final String[] arr = { null };
82.87 + private final String url;
82.88 +
82.89 + private Request(String url) throws IOException {
82.90 + this.url = url;
82.91 + loadText(url, this, arr);
82.92 + }
82.93 +
82.94 + @Override
82.95 + public void run() {
82.96 + try {
82.97 + String data = arr[0];
82.98 + log("\nGot \"" + data + "\"");
82.99 +
82.100 + if (data == null) {
82.101 + log("Some error exiting");
82.102 + closeWindow();
82.103 + return;
82.104 + }
82.105 +
82.106 + if (data.isEmpty()) {
82.107 + log("No data, exiting");
82.108 + closeWindow();
82.109 + return;
82.110 + }
82.111 +
82.112 + Case c = Case.parseData(data);
82.113 + if (c.getHtmlFragment() != null) {
82.114 + setAttr("bck2brwsr.fragment", "innerHTML", c.getHtmlFragment());
82.115 + }
82.116 + log("Invoking " + c.getClassName() + '.' + c.getMethodName() + " as request: " + c.getRequestId());
82.117 +
82.118 + Object result = invokeMethod(c.getClassName(), c.getMethodName());
82.119 +
82.120 + setAttr("bck2brwsr.fragment", "innerHTML", "");
82.121 + log("Result: " + result);
82.122 +
82.123 + result = encodeURL("" + result);
82.124 +
82.125 + log("Sending back: " + url + "?request=" + c.getRequestId() + "&result=" + result);
82.126 + String u = url + "?request=" + c.getRequestId() + "&result=" + result;
82.127 +
82.128 + loadText(u, this, arr);
82.129 +
82.130 + } catch (Exception ex) {
82.131 + log(ex.getMessage());
82.132 + }
82.133 + }
82.134 + }
82.135 +
82.136 + private static String encodeURL(String r) {
82.137 + StringBuilder sb = new StringBuilder();
82.138 + for (int i = 0; i < r.length(); i++) {
82.139 + int ch = r.charAt(i);
82.140 + if (ch < 32 || ch == '%' || ch == '+') {
82.141 + sb.append("%").append(("0" + Integer.toHexString(ch)).substring(0, 2));
82.142 + } else {
82.143 + if (ch == 32) {
82.144 + sb.append("+");
82.145 + } else {
82.146 + sb.append((char)ch);
82.147 + }
82.148 + }
82.149 + }
82.150 + return sb.toString();
82.151 + }
82.152 +
82.153 + static String invoke(String clazz, String method) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException, InstantiationException {
82.154 + final Object r = invokeMethod(clazz, method);
82.155 + return r == null ? "null" : r.toString().toString();
82.156 + }
82.157 +
82.158 + /** Helper method that inspects the classpath and loads given resource
82.159 + * (usually a class file). Used while running tests in Rhino.
82.160 + *
82.161 + * @param name resource name to find
82.162 + * @return the array of bytes in the given resource
82.163 + * @throws IOException I/O in case something goes wrong
82.164 + */
82.165 + public static byte[] read(String name) throws IOException {
82.166 + URL u = null;
82.167 + Enumeration<URL> en = Console.class.getClassLoader().getResources(name);
82.168 + while (en.hasMoreElements()) {
82.169 + u = en.nextElement();
82.170 + }
82.171 + if (u == null) {
82.172 + throw new IOException("Can't find " + name);
82.173 + }
82.174 + try (InputStream is = u.openStream()) {
82.175 + byte[] arr;
82.176 + arr = new byte[is.available()];
82.177 + int offset = 0;
82.178 + while (offset < arr.length) {
82.179 + int len = is.read(arr, offset, arr.length - offset);
82.180 + if (len == -1) {
82.181 + throw new IOException("Can't read " + name);
82.182 + }
82.183 + offset += len;
82.184 + }
82.185 + return arr;
82.186 + }
82.187 + }
82.188 +
82.189 + private static Object invokeMethod(String clazz, String method)
82.190 + throws ClassNotFoundException, InvocationTargetException,
82.191 + SecurityException, IllegalAccessException, IllegalArgumentException,
82.192 + InstantiationException {
82.193 + Method found = null;
82.194 + Class<?> c = Class.forName(clazz);
82.195 + for (Method m : c.getMethods()) {
82.196 + if (m.getName().equals(method)) {
82.197 + found = m;
82.198 + }
82.199 + }
82.200 + Object res;
82.201 + if (found != null) {
82.202 + try {
82.203 + if ((found.getModifiers() & Modifier.STATIC) != 0) {
82.204 + res = found.invoke(null);
82.205 + } else {
82.206 + res = found.invoke(c.newInstance());
82.207 + }
82.208 + } catch (Throwable ex) {
82.209 + res = ex.getClass().getName() + ":" + ex.getMessage();
82.210 + }
82.211 + } else {
82.212 + res = "Can't find method " + method + " in " + clazz;
82.213 + }
82.214 + return res;
82.215 + }
82.216 +
82.217 + @JavaScriptBody(args = {}, body = "vm.desiredAssertionStatus = true;")
82.218 + private static void turnAssetionStatusOn() {
82.219 + }
82.220 +
82.221 + private static final class Case {
82.222 + private final Object data;
82.223 +
82.224 + private Case(Object data) {
82.225 + this.data = data;
82.226 + }
82.227 +
82.228 + public static Case parseData(String s) {
82.229 + return new Case(toJSON(s));
82.230 + }
82.231 +
82.232 + public String getMethodName() {
82.233 + return value("methodName", data);
82.234 + }
82.235 +
82.236 + public String getClassName() {
82.237 + return value("className", data);
82.238 + }
82.239 +
82.240 + public String getRequestId() {
82.241 + return value("request", data);
82.242 + }
82.243 +
82.244 + public String getHtmlFragment() {
82.245 + return value("html", data);
82.246 + }
82.247 +
82.248 + @JavaScriptBody(args = "s", body = "return eval('(' + s + ')');")
82.249 + private static native Object toJSON(String s);
82.250 +
82.251 + @JavaScriptBody(args = {"p", "d"}, body =
82.252 + "var v = d[p];\n"
82.253 + + "if (typeof v === 'undefined') return null;\n"
82.254 + + "return v.toString();"
82.255 + )
82.256 + private static native String value(String p, Object d);
82.257 + }
82.258 +}
83.1 --- a/launcher/src/main/resources/org/apidesign/bck2brwsr/launcher/harness.xhtml Fri Feb 01 16:34:51 2013 +0100
83.2 +++ b/launcher/src/main/resources/org/apidesign/bck2brwsr/launcher/harness.xhtml Mon Feb 04 09:37:56 2013 +0100
83.3 @@ -34,7 +34,7 @@
83.4 <div id="bck2brwsr.fragment"/>
83.5
83.6 <script type="text/javascript">
83.7 - vm.loadClass('org.apidesign.bck2brwsr.launcher.Console').harness__VLjava_lang_String_2('$U/../data');
83.8 + vm.loadClass('org.apidesign.bck2brwsr.launcher.impl.Console').harness__VLjava_lang_String_2('$U/../data');
83.9 </script>
83.10 </body>
83.11 </html>
84.1 --- a/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrswrMojo.java Fri Feb 01 16:34:51 2013 +0100
84.2 +++ b/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrswrMojo.java Mon Feb 04 09:37:56 2013 +0100
84.3 @@ -51,21 +51,28 @@
84.4 /** Root of the class files */
84.5 @Parameter(defaultValue="${project.build.directory}/classes")
84.6 private File classes;
84.7 +
84.8 + /** Root of all pages, and files, etc. */
84.9 + @Parameter
84.10 + private File directory;
84.11
84.12 @Override
84.13 public void execute() throws MojoExecutionException {
84.14 if (startpage == null) {
84.15 throw new MojoExecutionException("You have to provide a start page");
84.16 }
84.17 -
84.18 +
84.19 try {
84.20 - URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts());
84.21 -
84.22 Closeable httpServer;
84.23 - try {
84.24 - httpServer = Launcher.showURL(url, startpage());
84.25 - } catch (Exception ex) {
84.26 - throw new MojoExecutionException("Can't open " + startpage(), ex);
84.27 + if (directory != null) {
84.28 + httpServer = Launcher.showDir(directory, startpage);
84.29 + } else {
84.30 + URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts());
84.31 + try {
84.32 + httpServer = Launcher.showURL(url, startpage());
84.33 + } catch (Exception ex) {
84.34 + throw new MojoExecutionException("Can't open " + startpage(), ex);
84.35 + }
84.36 }
84.37 System.in.read();
84.38 httpServer.close();
85.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Fri Feb 01 16:34:51 2013 +0100
85.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Mon Feb 04 09:37:56 2013 +0100
85.3 @@ -1269,7 +1269,7 @@
85.4 int indx = readIntArg(byteCodes, i);
85.5 final String type = jc.getClassName(indx);
85.6 if (!type.startsWith("[")) {
85.7 - emit(out, "var @2 = @1.$instOf_@3 ? 1 : 0;",
85.8 + emit(out, "var @2 = @1 != null && @1.$instOf_@3 ? 1 : 0;",
85.9 smapper.popA(), smapper.pushI(),
85.10 type.replace('/', '_'));
85.11 } else {
86.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Fri Feb 01 16:34:51 2013 +0100
86.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Mon Feb 04 09:37:56 2013 +0100
86.3 @@ -32,6 +32,7 @@
86.4 static {
86.5 // uses VMLazy to load dynamic classes
86.6 VMLazy.init();
86.7 + Zips.init();
86.8 }
86.9
86.10 @Override
86.11 @@ -116,6 +117,12 @@
86.12 + " var args = arguments;\n"
86.13 + " var loader = {};\n"
86.14 + " loader.vm = vm;\n"
86.15 + + " if (args.length == 1 && typeof args[0] !== 'function') {;\n"
86.16 + + " var classpath = args[0];\n"
86.17 + + " args[0] = function(name) {\n"
86.18 + + " return vm.org_apidesign_vm4brwsr_Zips(false).loadFromCp___3B_3Ljava_lang_Object_2Ljava_lang_String_2(classpath, name);\n"
86.19 + + " };\n"
86.20 + + " };\n"
86.21 + " loader.loadClass = function(name) {\n"
86.22 + " var attr = name.replace__Ljava_lang_String_2CC('.','_');\n"
86.23 + " var fn = vm[attr];\n"
87.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
87.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/Zips.java Mon Feb 04 09:37:56 2013 +0100
87.3 @@ -0,0 +1,97 @@
87.4 +/**
87.5 + * Back 2 Browser Bytecode Translator
87.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
87.7 + *
87.8 + * This program is free software: you can redistribute it and/or modify
87.9 + * it under the terms of the GNU General Public License as published by
87.10 + * the Free Software Foundation, version 2 of the License.
87.11 + *
87.12 + * This program is distributed in the hope that it will be useful,
87.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
87.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
87.15 + * GNU General Public License for more details.
87.16 + *
87.17 + * You should have received a copy of the GNU General Public License
87.18 + * along with this program. Look for COPYING file in the top folder.
87.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
87.20 + */
87.21 +package org.apidesign.vm4brwsr;
87.22 +
87.23 +import java.io.IOException;
87.24 +import java.net.URL;
87.25 +import java.util.zip.ZipEntry;
87.26 +import java.util.zip.ZipInputStream;
87.27 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
87.28 +
87.29 +/** Conversion from classpath to load function.
87.30 + *
87.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
87.32 + */
87.33 +final class Zips {
87.34 + private Zips() {
87.35 + }
87.36 +
87.37 + public static void init() {
87.38 + }
87.39 +
87.40 + public static byte[] loadFromCp(Object[] classpath, String res) {
87.41 + for (int i = 0; i < classpath.length; i++) {
87.42 + Object c = classpath[i];
87.43 + if (c instanceof String) {
87.44 + try {
87.45 + c = classpath[i] = toZip((String)c);
87.46 + } catch (IOException ex) {
87.47 + classpath[i] = ex;
87.48 + }
87.49 + }
87.50 + if (c instanceof Zips) {
87.51 + Object checkRes = ((Zips)c).findRes(res);
87.52 + if (checkRes instanceof byte[]) {
87.53 + return (byte[])checkRes;
87.54 + }
87.55 + }
87.56 + }
87.57 + return null;
87.58 + }
87.59 +
87.60 + @JavaScriptBody(args = { "res" }, body = "var r = this[res]; return r ? r : null;")
87.61 + private native byte[] findRes(String res);
87.62 +
87.63 + @JavaScriptBody(args = { "res", "arr" }, body = "this[res] = arr;")
87.64 + private native void putRes(String res, byte[] arr);
87.65 +
87.66 + private static Zips toZip(String path) throws IOException {
87.67 + URL u = new URL(path);
87.68 + ZipInputStream zip = new ZipInputStream(u.openStream());
87.69 + Zips z = new Zips();
87.70 + for (;;) {
87.71 + ZipEntry entry = zip.getNextEntry();
87.72 + if (entry == null) {
87.73 + break;
87.74 + }
87.75 + byte[] arr = new byte[4096];
87.76 + int offset = 0;
87.77 + for (;;) {
87.78 + int len = zip.read(arr, offset, arr.length - offset);
87.79 + if (len == -1) {
87.80 + break;
87.81 + }
87.82 + offset += len;
87.83 + if (offset == arr.length) {
87.84 + enlargeArray(arr, arr.length + 4096);
87.85 + }
87.86 + }
87.87 + sliceArray(arr, offset);
87.88 + z.putRes(entry.getName(), arr);
87.89 + }
87.90 + return z;
87.91 + }
87.92 +
87.93 + @JavaScriptBody(args = { "arr", "len" }, body = "while (arr.length < len) arr.push(0);")
87.94 + private static native void enlargeArray(byte[] arr, int len);
87.95 +
87.96 + @JavaScriptBody(args = { "arr", "len" }, body = "arr.splice(len, arr.length - len);")
87.97 + private static native void sliceArray(byte[] arr, int len);
87.98 +
87.99 +
87.100 +}
88.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/Instance.java Fri Feb 01 16:34:51 2013 +0100
88.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Instance.java Mon Feb 04 09:37:56 2013 +0100
88.3 @@ -68,12 +68,12 @@
88.4 GetByte i = new InstanceSub(7, 2.2d);
88.5 return i.getByte();
88.6 }
88.7 - public static boolean instanceOf(boolean sub) {
88.8 + public static boolean instanceOf(int sub) {
88.9 Instance i = createInstance(sub);
88.10 return isInstanceSubOf(i);
88.11 }
88.12 public static int castsWork(boolean interfc) {
88.13 - Instance i = createInstance(true);
88.14 + Instance i = createInstance(2);
88.15 if (interfc) {
88.16 GetByte b = (GetByte)i;
88.17 } else {
88.18 @@ -85,11 +85,16 @@
88.19 private static boolean isInstanceSubOf(Instance instance) {
88.20 return instance instanceof InstanceSub;
88.21 }
88.22 - private static Instance createInstance(boolean sub) {
88.23 - return sub ? new InstanceSub(3, 0) : new Instance();
88.24 + private static Instance createInstance(int type) {
88.25 + switch (type) {
88.26 + case 0: return null;
88.27 + case 1: return new Instance();
88.28 + case 2: return new InstanceSub(3, 0);
88.29 + }
88.30 + throw new IllegalArgumentException();
88.31 }
88.32 private static boolean isNull() {
88.33 - return createInstance(true) == null;
88.34 + return createInstance(2) == null;
88.35 }
88.36
88.37 @JavaScriptBody(args = "obj", body = "return obj.constructor;")
89.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/InstanceTest.java Fri Feb 01 16:34:51 2013 +0100
89.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/InstanceTest.java Mon Feb 04 09:37:56 2013 +0100
89.3 @@ -80,16 +80,23 @@
89.4 @Test public void isInstanceOf() throws Exception {
89.5 assertExec(
89.6 "Yes, we are instance",
89.7 - Instance.class, "instanceOf__ZZ",
89.8 - Double.valueOf(1.0), true
89.9 + Instance.class, "instanceOf__ZI",
89.10 + Double.valueOf(1.0), 2
89.11 );
89.12 }
89.13
89.14 @Test public void notInstanceOf() throws Exception {
89.15 assertExec(
89.16 "No, we are not an instance",
89.17 - Instance.class, "instanceOf__ZZ",
89.18 - Double.valueOf(0.0), false
89.19 + Instance.class, "instanceOf__ZI",
89.20 + Double.valueOf(0.0), 1
89.21 + );
89.22 + }
89.23 + @Test public void nullInstanceOf() throws Exception {
89.24 + assertExec(
89.25 + "No, null is not an instance",
89.26 + Instance.class, "instanceOf__ZI",
89.27 + Double.valueOf(0.0), 0
89.28 );
89.29 }
89.30
90.1 --- a/vmtest/pom.xml Fri Feb 01 16:34:51 2013 +0100
90.2 +++ b/vmtest/pom.xml Mon Feb 04 09:37:56 2013 +0100
90.3 @@ -58,5 +58,10 @@
90.4 <artifactId>launcher</artifactId>
90.5 <version>${project.version}</version>
90.6 </dependency>
90.7 + <dependency>
90.8 + <groupId>org.netbeans.api</groupId>
90.9 + <artifactId>org-openide-util-lookup</artifactId>
90.10 + <scope>provided</scope>
90.11 + </dependency>
90.12 </dependencies>
90.13 </project>
91.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
91.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/HttpResource.java Mon Feb 04 09:37:56 2013 +0100
91.3 @@ -0,0 +1,43 @@
91.4 +/**
91.5 + * Back 2 Browser Bytecode Translator
91.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
91.7 + *
91.8 + * This program is free software: you can redistribute it and/or modify
91.9 + * it under the terms of the GNU General Public License as published by
91.10 + * the Free Software Foundation, version 2 of the License.
91.11 + *
91.12 + * This program is distributed in the hope that it will be useful,
91.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
91.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
91.15 + * GNU General Public License for more details.
91.16 + *
91.17 + * You should have received a copy of the GNU General Public License
91.18 + * along with this program. Look for COPYING file in the top folder.
91.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
91.20 + */
91.21 +package org.apidesign.bck2brwsr.vmtest;
91.22 +
91.23 +import java.lang.annotation.ElementType;
91.24 +import java.lang.annotation.Retention;
91.25 +import java.lang.annotation.RetentionPolicy;
91.26 +import java.lang.annotation.Target;
91.27 +
91.28 +/** Exposes an HTTP page to the running {@link BrwsrTest}, so it can access
91.29 + * under the relative path.
91.30 + *
91.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
91.32 + */
91.33 +@Retention(RetentionPolicy.RUNTIME)
91.34 +@Target({ ElementType.METHOD, ElementType.TYPE})
91.35 +public @interface HttpResource {
91.36 + /** path on the server that the test can use to access the exposed resource */
91.37 + String path();
91.38 + /** the content of the HttpResource */
91.39 + String content();
91.40 + /** resource relative to the class that should be used instead of <code>content</code>.
91.41 + * Leave content equal to empty string.
91.42 + */
91.43 + String resource() default "";
91.44 + /** mime type of the resource */
91.45 + String mimeType();
91.46 +}
92.1 --- a/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java Fri Feb 01 16:34:51 2013 +0100
92.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java Mon Feb 04 09:37:56 2013 +0100
92.3 @@ -17,14 +17,18 @@
92.4 */
92.5 package org.apidesign.bck2brwsr.vmtest.impl;
92.6
92.7 +import java.io.ByteArrayInputStream;
92.8 import java.io.File;
92.9 import java.io.FileWriter;
92.10 import java.io.IOException;
92.11 +import java.io.InputStream;
92.12 import java.lang.reflect.Constructor;
92.13 import java.lang.reflect.InvocationTargetException;
92.14 import java.lang.reflect.Method;
92.15 import org.apidesign.bck2brwsr.launcher.Launcher;
92.16 -import org.apidesign.bck2brwsr.launcher.MethodInvocation;
92.17 +import org.apidesign.bck2brwsr.launcher.InvocationContext;
92.18 +import org.apidesign.bck2brwsr.vmtest.HtmlFragment;
92.19 +import org.apidesign.bck2brwsr.vmtest.HttpResource;
92.20 import org.testng.ITest;
92.21 import org.testng.annotations.Test;
92.22
92.23 @@ -37,22 +41,36 @@
92.24 private final Launcher l;
92.25 private final String type;
92.26 private final boolean fail;
92.27 + private final HtmlFragment html;
92.28 + private final HttpResource http;
92.29 Object value;
92.30 - private final String html;
92.31
92.32 - Bck2BrwsrCase(Method m, String type, Launcher l, boolean fail, String html) {
92.33 + Bck2BrwsrCase(Method m, String type, Launcher l, boolean fail, HtmlFragment html, HttpResource http) {
92.34 this.l = l;
92.35 this.m = m;
92.36 this.type = type;
92.37 this.fail = fail;
92.38 this.html = html;
92.39 + this.http = http;
92.40 }
92.41
92.42 @Test(groups = "run")
92.43 public void executeCode() throws Throwable {
92.44 if (l != null) {
92.45 - MethodInvocation c = l.invokeMethod(m.getDeclaringClass(), m.getName(), html);
92.46 - String res = c.toString();
92.47 + InvocationContext c = l.createInvocation(m.getDeclaringClass(), m.getName());
92.48 + if (html != null) {
92.49 + c.setHtmlFragment(html.value());
92.50 + }
92.51 + if (http != null) {
92.52 + if (!http.content().isEmpty()) {
92.53 + InputStream is = new ByteArrayInputStream(http.content().getBytes("UTF-8"));
92.54 + c.setHttpResource(http.path(), http.mimeType(), is);
92.55 + } else {
92.56 + InputStream is = m.getDeclaringClass().getResourceAsStream(http.resource());
92.57 + c.setHttpResource(http.path(), http.mimeType(), is);
92.58 + }
92.59 + }
92.60 + String res = c.invoke();
92.61 value = res;
92.62 if (fail) {
92.63 int idx = res.indexOf(':');
92.64 @@ -92,6 +110,9 @@
92.65 } catch (InvocationTargetException ex) {
92.66 Throwable t = ex.getTargetException();
92.67 value = t.getClass().getName() + ":" + t.getMessage();
92.68 + if (t instanceof AssertionError) {
92.69 + throw t;
92.70 + }
92.71 }
92.72 }
92.73 }
93.1 --- a/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java Fri Feb 01 16:34:51 2013 +0100
93.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java Mon Feb 04 09:37:56 2013 +0100
93.3 @@ -111,17 +111,17 @@
93.4 if (c == null) {
93.5 return;
93.6 }
93.7 - final Bck2BrwsrCase real = new Bck2BrwsrCase(m, "Java", null, false, null);
93.8 + final Bck2BrwsrCase real = new Bck2BrwsrCase(m, "Java", null, false, null, null);
93.9 ret.add(real);
93.10 if (c.scripting()) {
93.11 - final Bck2BrwsrCase js = new Bck2BrwsrCase(m, "JavaScript", l.javaScript(), false, null);
93.12 + final Bck2BrwsrCase js = new Bck2BrwsrCase(m, "JavaScript", l.javaScript(), false, null, null);
93.13 ret.add(js);
93.14 ret.add(new CompareCase(m, real, js));
93.15 }
93.16 for (String b : brwsr) {
93.17 final Launcher s = l.brwsr(b);
93.18 ret.add(s);
93.19 - final Bck2BrwsrCase cse = new Bck2BrwsrCase(m, b, s, false, null);
93.20 + final Bck2BrwsrCase cse = new Bck2BrwsrCase(m, b, s, false, null, null);
93.21 ret.add(cse);
93.22 ret.add(new CompareCase(m, real, cse));
93.23 }
93.24 @@ -135,16 +135,19 @@
93.25 if (f == null) {
93.26 f = m.getDeclaringClass().getAnnotation(HtmlFragment.class);
93.27 }
93.28 - String html = f == null ? null : f.value();
93.29 + HttpResource r = m.getAnnotation(HttpResource.class);
93.30 + if (r == null) {
93.31 + r = m.getDeclaringClass().getAnnotation(HttpResource.class);
93.32 + }
93.33 if (brwsr.length == 0) {
93.34 final Launcher s = l.brwsr(null);
93.35 ret.add(s);
93.36 - ret.add(new Bck2BrwsrCase(m, "Brwsr", s, true, html));
93.37 + ret.add(new Bck2BrwsrCase(m, "Brwsr", s, true, f, r));
93.38 } else {
93.39 for (String b : brwsr) {
93.40 final Launcher s = l.brwsr(b);
93.41 ret.add(s);
93.42 - ret.add(new Bck2BrwsrCase(m, b, s, true, html));
93.43 + ret.add(new Bck2BrwsrCase(m, b, s, true, f, r));
93.44 }
93.45 }
93.46 }
94.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
94.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/GenerateZip.java Mon Feb 04 09:37:56 2013 +0100
94.3 @@ -0,0 +1,36 @@
94.4 +/**
94.5 + * Back 2 Browser Bytecode Translator
94.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
94.7 + *
94.8 + * This program is free software: you can redistribute it and/or modify
94.9 + * it under the terms of the GNU General Public License as published by
94.10 + * the Free Software Foundation, version 2 of the License.
94.11 + *
94.12 + * This program is distributed in the hope that it will be useful,
94.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
94.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
94.15 + * GNU General Public License for more details.
94.16 + *
94.17 + * You should have received a copy of the GNU General Public License
94.18 + * along with this program. Look for COPYING file in the top folder.
94.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
94.20 + */
94.21 +package org.apidesign.bck2brwsr.vmtest.impl;
94.22 +
94.23 +import java.lang.annotation.Retention;
94.24 +import java.lang.annotation.RetentionPolicy;
94.25 +
94.26 +/** Annotation to generate a ZIP or JAR file during build.
94.27 + *
94.28 + * @author Jaroslav Tulach <jtulach@netbeans.org>
94.29 + */
94.30 +@Retention(RetentionPolicy.SOURCE)
94.31 +@interface GenerateZip {
94.32 + String name();
94.33 +
94.34 + /** manifest for the file */
94.35 + String manifest() default "";
94.36 +
94.37 + /** Array of names (at odd positions) and their content (on even) */
94.38 + String[] contents();
94.39 +}
95.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
95.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/GenerateZipProcessor.java Mon Feb 04 09:37:56 2013 +0100
95.3 @@ -0,0 +1,98 @@
95.4 +/**
95.5 + * Back 2 Browser Bytecode Translator
95.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
95.7 + *
95.8 + * This program is free software: you can redistribute it and/or modify
95.9 + * it under the terms of the GNU General Public License as published by
95.10 + * the Free Software Foundation, version 2 of the License.
95.11 + *
95.12 + * This program is distributed in the hope that it will be useful,
95.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
95.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
95.15 + * GNU General Public License for more details.
95.16 + *
95.17 + * You should have received a copy of the GNU General Public License
95.18 + * along with this program. Look for COPYING file in the top folder.
95.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
95.20 + */
95.21 +package org.apidesign.bck2brwsr.vmtest.impl;
95.22 +
95.23 +import java.io.ByteArrayInputStream;
95.24 +import java.io.IOException;
95.25 +import java.io.OutputStream;
95.26 +import java.util.Set;
95.27 +import java.util.jar.JarEntry;
95.28 +import java.util.jar.JarOutputStream;
95.29 +import java.util.jar.Manifest;
95.30 +import javax.annotation.processing.AbstractProcessor;
95.31 +import javax.annotation.processing.Processor;
95.32 +import javax.annotation.processing.RoundEnvironment;
95.33 +import javax.annotation.processing.SupportedAnnotationTypes;
95.34 +import javax.lang.model.element.Element;
95.35 +import javax.lang.model.element.ElementKind;
95.36 +import javax.lang.model.element.PackageElement;
95.37 +import javax.lang.model.element.TypeElement;
95.38 +import javax.tools.Diagnostic;
95.39 +import javax.tools.FileObject;
95.40 +import javax.tools.StandardLocation;
95.41 +import org.openide.util.lookup.ServiceProvider;
95.42 +
95.43 +/**
95.44 + *
95.45 + * @author Jaroslav Tulach <jtulach@netbeans.org>
95.46 + */
95.47 +@ServiceProvider(service = Processor.class)
95.48 +@SupportedAnnotationTypes("org.apidesign.bck2brwsr.vmtest.impl.GenerateZip")
95.49 +public class GenerateZipProcessor extends AbstractProcessor {
95.50 +
95.51 + @Override
95.52 + public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
95.53 + for (Element e : roundEnv.getElementsAnnotatedWith(GenerateZip.class)) {
95.54 + GenerateZip gz = e.getAnnotation(GenerateZip.class);
95.55 + if (gz == null) {
95.56 + continue;
95.57 + }
95.58 + PackageElement pe = findPackage(e);
95.59 + try {
95.60 + generateJar(pe, gz, e);
95.61 + } catch (IOException ex) {
95.62 + processingEnv.getMessager().printMessage(
95.63 + Diagnostic.Kind.ERROR,
95.64 + "Can't generate JAR " + gz.name() + ": " + ex.getMessage()
95.65 + );
95.66 + }
95.67 + }
95.68 + return true;
95.69 + }
95.70 +
95.71 + private static PackageElement findPackage(Element e) {
95.72 + while (e.getKind() != ElementKind.PACKAGE) {
95.73 + e = e.getEnclosingElement();
95.74 + }
95.75 + return (PackageElement)e;
95.76 + }
95.77 +
95.78 + private void generateJar(PackageElement pe, GenerateZip gz, Element e) throws IOException {
95.79 + FileObject res = processingEnv.getFiler().createResource(
95.80 + StandardLocation.CLASS_OUTPUT,
95.81 + pe.getQualifiedName().toString(),
95.82 + gz.name(), e
95.83 + );
95.84 + OutputStream os = res.openOutputStream();
95.85 + JarOutputStream jar;
95.86 + if (gz.manifest().isEmpty()) {
95.87 + jar = new JarOutputStream(os);
95.88 + } else {
95.89 + Manifest mf = new Manifest(new ByteArrayInputStream(gz.manifest().getBytes("UTF-8")));
95.90 + jar = new JarOutputStream(os, mf);
95.91 + }
95.92 + String[] arr = gz.contents();
95.93 + for (int i = 0; i < arr.length; i += 2) {
95.94 + JarEntry je = new JarEntry(arr[i]);
95.95 + jar.putNextEntry(je);
95.96 + jar.write(arr[i + 1].getBytes("UTF-8"));
95.97 + jar.closeEntry();
95.98 + }
95.99 + }
95.100 +
95.101 +}
96.1 --- a/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/AssertionTest.java Fri Feb 01 16:34:51 2013 +0100
96.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/AssertionTest.java Mon Feb 04 09:37:56 2013 +0100
96.3 @@ -28,8 +28,12 @@
96.4 public class AssertionTest {
96.5
96.6 @Compare public Object checkAssert() throws ClassNotFoundException {
96.7 - assert false : "Is assertion status on?";
96.8 - return null;
96.9 + try {
96.10 + assert false : "Is assertion status on?";
96.11 + return null;
96.12 + } catch (AssertionError ex) {
96.13 + return ex.getClass().getName();
96.14 + }
96.15 }
96.16
96.17 @Factory
97.1 --- a/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java Fri Feb 01 16:34:51 2013 +0100
97.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java Mon Feb 04 09:37:56 2013 +0100
97.3 @@ -17,6 +17,7 @@
97.4 */
97.5 package org.apidesign.bck2brwsr.tck;
97.6
97.7 +import java.io.UnsupportedEncodingException;
97.8 import java.net.MalformedURLException;
97.9 import java.net.URL;
97.10 import org.apidesign.bck2brwsr.vmtest.Compare;
97.11 @@ -120,6 +121,21 @@
97.12 NullField nf = new NullField();
97.13 return ("" + nf.name).toString();
97.14 }
97.15 + @Compare
97.16 + public String toUTFString() throws UnsupportedEncodingException {
97.17 + byte[] arr = {
97.18 + (byte) -59, (byte) -67, (byte) 108, (byte) 117, (byte) -59, (byte) -91,
97.19 + (byte) 111, (byte) 117, (byte) -60, (byte) -115, (byte) 107, (byte) -61,
97.20 + (byte) -67, (byte) 32, (byte) 107, (byte) -59, (byte) -81, (byte) -59,
97.21 + (byte) -120
97.22 + };
97.23 + return new String(arr, "utf-8");
97.24 + }
97.25 +
97.26 + @Compare
97.27 + public int stringToBytesLenght() throws UnsupportedEncodingException {
97.28 + return "Žluťoučký kůň".getBytes("utf8").length;
97.29 + }
97.30
97.31 @Factory
97.32 public static Object[] create() {
98.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
98.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/HttpResourceTest.java Mon Feb 04 09:37:56 2013 +0100
98.3 @@ -0,0 +1,94 @@
98.4 +/**
98.5 + * Back 2 Browser Bytecode Translator
98.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
98.7 + *
98.8 + * This program is free software: you can redistribute it and/or modify
98.9 + * it under the terms of the GNU General Public License as published by
98.10 + * the Free Software Foundation, version 2 of the License.
98.11 + *
98.12 + * This program is distributed in the hope that it will be useful,
98.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
98.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
98.15 + * GNU General Public License for more details.
98.16 + *
98.17 + * You should have received a copy of the GNU General Public License
98.18 + * along with this program. Look for COPYING file in the top folder.
98.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
98.20 + */
98.21 +package org.apidesign.bck2brwsr.tck;
98.22 +
98.23 +import java.io.InputStream;
98.24 +import java.net.URL;
98.25 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
98.26 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
98.27 +import org.apidesign.bck2brwsr.vmtest.HttpResource;
98.28 +import org.apidesign.bck2brwsr.vmtest.VMTest;
98.29 +import org.testng.annotations.Factory;
98.30 +
98.31 +/**
98.32 + *
98.33 + * @author Jaroslav Tulach <jtulach@netbeans.org>
98.34 + */
98.35 +public class HttpResourceTest {
98.36 +
98.37 + @HttpResource(path = "/xhr", content = "Hello Brwsr!", mimeType = "text/plain")
98.38 + @BrwsrTest
98.39 + public String testReadContentViaXHR() throws Exception {
98.40 + String msg = read("/xhr");
98.41 + assert "Hello Brwsr!".equals(msg) : "The message was " + msg;
98.42 + return msg;
98.43 + }
98.44 +
98.45 + @HttpResource(path = "/url", content = "Hello via URL!", mimeType = "text/plain")
98.46 + @BrwsrTest
98.47 + public String testReadContentViaURL() throws Exception {
98.48 + URL url = new URL("http:/url");
98.49 + String msg = (String) url.getContent();
98.50 + assert "Hello via URL!".equals(msg) : "The message was " + msg;
98.51 + return msg;
98.52 + }
98.53 + @HttpResource(path = "/url", content = "Hello via URL!", mimeType = "text/plain")
98.54 + @BrwsrTest
98.55 + public String testReadContentViaURLWithStringParam() throws Exception {
98.56 + URL url = new URL("http:/url");
98.57 + String msg = (String) url.getContent(new Class[] { String.class });
98.58 + assert "Hello via URL!".equals(msg) : "The message was " + msg;
98.59 + return msg;
98.60 + }
98.61 +
98.62 + @HttpResource(path = "/bytes", content = "", resource = "0xfe", mimeType = "x-application/binary")
98.63 + @BrwsrTest
98.64 + public void testReadByte() throws Exception {
98.65 + URL url = new URL("http:/bytes");
98.66 + final Object res = url.getContent(new Class[] { byte[].class });
98.67 + assert res instanceof byte[] : "Expecting byte[]: " + res;
98.68 + byte[] arr = (byte[]) res;
98.69 + assert arr.length == 1 : "One byte " + arr.length;
98.70 + assert arr[0] == 0xfe : "It is 0xfe: " + Integer.toHexString(arr[0]);
98.71 + }
98.72 +
98.73 + @HttpResource(path = "/bytes", content = "", resource = "0xfe", mimeType = "x-application/binary")
98.74 + @BrwsrTest
98.75 + public void testReadByteViaInputStream() throws Exception {
98.76 + URL url = new URL("http:/bytes");
98.77 + InputStream is = url.openStream();
98.78 + byte[] arr = new byte[10];
98.79 + int len = is.read(arr);
98.80 + assert len == 1 : "One byte " + len;
98.81 + assert arr[0] == 0xfe : "It is 0xfe: " + Integer.toHexString(arr[0]);
98.82 + }
98.83 +
98.84 + @JavaScriptBody(args = { "url" }, body =
98.85 + "var req = new XMLHttpRequest();\n"
98.86 + + "req.open('GET', url, false);\n"
98.87 + + "req.send();\n"
98.88 + + "return req.responseText;"
98.89 + )
98.90 + private static native String read(String url);
98.91 +
98.92 +
98.93 + @Factory
98.94 + public static Object[] create() {
98.95 + return VMTest.create(HttpResourceTest.class);
98.96 + }
98.97 +}
99.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
99.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/CRC32Test.java Mon Feb 04 09:37:56 2013 +0100
99.3 @@ -0,0 +1,41 @@
99.4 +/**
99.5 + * Back 2 Browser Bytecode Translator
99.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
99.7 + *
99.8 + * This program is free software: you can redistribute it and/or modify
99.9 + * it under the terms of the GNU General Public License as published by
99.10 + * the Free Software Foundation, version 2 of the License.
99.11 + *
99.12 + * This program is distributed in the hope that it will be useful,
99.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
99.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
99.15 + * GNU General Public License for more details.
99.16 + *
99.17 + * You should have received a copy of the GNU General Public License
99.18 + * along with this program. Look for COPYING file in the top folder.
99.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
99.20 + */
99.21 +package org.apidesign.bck2brwsr.vmtest.impl;
99.22 +
99.23 +import java.io.UnsupportedEncodingException;
99.24 +import java.util.zip.CRC32;
99.25 +import org.apidesign.bck2brwsr.vmtest.Compare;
99.26 +import org.apidesign.bck2brwsr.vmtest.VMTest;
99.27 +import org.testng.annotations.Factory;
99.28 +
99.29 +/**
99.30 + *
99.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
99.32 + */
99.33 +public class CRC32Test {
99.34 +
99.35 + @Compare public long crc1() throws UnsupportedEncodingException {
99.36 + CRC32 crc = new CRC32();
99.37 + crc.update("Hello World!".getBytes("UTF-8"));
99.38 + return crc.getValue();
99.39 + }
99.40 +
99.41 + @Factory public static Object[] create() {
99.42 + return VMTest.create(CRC32Test.class);
99.43 + }
99.44 +}
100.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
100.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java Mon Feb 04 09:37:56 2013 +0100
100.3 @@ -0,0 +1,84 @@
100.4 +/**
100.5 + * Back 2 Browser Bytecode Translator
100.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
100.7 + *
100.8 + * This program is free software: you can redistribute it and/or modify
100.9 + * it under the terms of the GNU General Public License as published by
100.10 + * the Free Software Foundation, version 2 of the License.
100.11 + *
100.12 + * This program is distributed in the hope that it will be useful,
100.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
100.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
100.15 + * GNU General Public License for more details.
100.16 + *
100.17 + * You should have received a copy of the GNU General Public License
100.18 + * along with this program. Look for COPYING file in the top folder.
100.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
100.20 + */
100.21 +package org.apidesign.bck2brwsr.vmtest.impl;
100.22 +
100.23 +import java.io.IOException;
100.24 +import java.io.InputStream;
100.25 +import java.util.Objects;
100.26 +import java.util.zip.ZipEntry;
100.27 +import java.util.zip.ZipInputStream;
100.28 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
100.29 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
100.30 +import org.apidesign.bck2brwsr.vmtest.Compare;
100.31 +import org.apidesign.bck2brwsr.vmtest.HttpResource;
100.32 +import org.apidesign.bck2brwsr.vmtest.VMTest;
100.33 +import org.testng.annotations.Factory;
100.34 +
100.35 +/**
100.36 + *
100.37 + * @author Jaroslav Tulach <jtulach@netbeans.org>
100.38 + */
100.39 +@GenerateZip(name = "readAnEntry.zip", contents = {
100.40 + "my/main/file.txt", "Hello World!"
100.41 +})
100.42 +public class ZipFileTest {
100.43 +
100.44 + @Compare public String readAnEntry() throws IOException {
100.45 + InputStream is = ZipFileTest.class.getResourceAsStream("readAnEntry.zip");
100.46 + ZipInputStream zip = new ZipInputStream(is);
100.47 + ZipEntry entry = zip.getNextEntry();
100.48 + assertEquals(entry.getName(), "my/main/file.txt", "Correct entry");
100.49 +
100.50 + byte[] arr = new byte[4096];
100.51 + int len = zip.read(arr);
100.52 +
100.53 + assertEquals(zip.getNextEntry(), null, "No next entry");
100.54 +
100.55 + final String ret = new String(arr, 0, len, "UTF-8");
100.56 + return ret;
100.57 + }
100.58 +
100.59 + @JavaScriptBody(args = { "res", "path" }, body =
100.60 + "var myvm = new bck2brwsr(path);\n"
100.61 + + "var cls = myvm.loadClass('java.lang.String');\n"
100.62 + + "return cls.getClass__Ljava_lang_Class_2().getResourceAsStream__Ljava_io_InputStream_2Ljava_lang_String_2(res);\n"
100.63 + )
100.64 + private static native Object loadVMResource(String res, String...path);
100.65 +
100.66 + @HttpResource(path = "/readAnEntry.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip")
100.67 + @BrwsrTest public void canVmLoadResourceFromZip() throws IOException {
100.68 + Object res = loadVMResource("/my/main/file.txt", "/readAnEntry.jar");
100.69 + assert res instanceof InputStream : "Got array of bytes: " + res;
100.70 + InputStream is = (InputStream)res;
100.71 +
100.72 + byte[] arr = new byte[4096];
100.73 + int len = is.read(arr);
100.74 +
100.75 + final String ret = new String(arr, 0, len, "UTF-8");
100.76 +
100.77 + assertEquals(ret, "Hello World!", "Can read the bytes");
100.78 + }
100.79 +
100.80 + private static void assertEquals(Object real, Object exp, String msg) {
100.81 + assert Objects.equals(exp, real) : msg + " exp: " + exp + " real: " + real;
100.82 + }
100.83 +
100.84 + @Factory public static Object[] create() {
100.85 + return VMTest.create(ZipFileTest.class);
100.86 + }
100.87 +}
101.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
101.2 +++ b/vmtest/src/test/resources/org/apidesign/bck2brwsr/tck/0xfe Mon Feb 04 09:37:56 2013 +0100
101.3 @@ -0,0 +1,1 @@
101.4 +
101.5 \ No newline at end of file