1.1 --- a/benchmarks/matrix-multiplication/pom.xml Fri Jan 25 15:08:24 2013 +0100
1.2 +++ b/benchmarks/matrix-multiplication/pom.xml Sun Feb 17 17:58:34 2013 +0100
1.3 @@ -7,6 +7,11 @@
1.4 <artifactId>matrix.multiplication</artifactId>
1.5 <version>0.3-SNAPSHOT</version>
1.6 <packaging>jar</packaging>
1.7 + <parent>
1.8 + <artifactId>benchmarks</artifactId>
1.9 + <groupId>org.apidesign.bck2brwsr</groupId>
1.10 + <version>0.3-SNAPSHOT</version>
1.11 + </parent>
1.12
1.13 <name>Matrix multiplication</name>
1.14
1.15 @@ -25,6 +30,14 @@
1.16 <target>1.7</target>
1.17 </configuration>
1.18 </plugin>
1.19 + <plugin>
1.20 + <groupId>org.apache.maven.plugins</groupId>
1.21 + <artifactId>maven-deploy-plugin</artifactId>
1.22 + <version>2.7</version>
1.23 + <configuration>
1.24 + <skip>true</skip>
1.25 + </configuration>
1.26 + </plugin>
1.27 </plugins>
1.28 </build>
1.29
2.1 --- a/core/pom.xml Fri Jan 25 15:08:24 2013 +0100
2.2 +++ b/core/pom.xml Sun Feb 17 17:58:34 2013 +0100
2.3 @@ -38,6 +38,7 @@
2.4 <dependency>
2.5 <groupId>org.netbeans.api</groupId>
2.6 <artifactId>org-openide-util-lookup</artifactId>
2.7 + <scope>provided</scope>
2.8 </dependency>
2.9 </dependencies>
2.10 <description>Contains esential annotations for associating JavaScript code with
3.1 --- a/dew/src/main/java/org/apidesign/bck2brwsr/dew/Dew.java Fri Jan 25 15:08:24 2013 +0100
3.2 +++ b/dew/src/main/java/org/apidesign/bck2brwsr/dew/Dew.java Sun Feb 17 17:58:34 2013 +0100
3.3 @@ -96,7 +96,9 @@
3.4 }
3.5 if (r.equals("/result.html")) {
3.6 response.setContentType("text/html");
3.7 - response.getOutputBuffer().write(data.getHtml());
3.8 + if (data != null) {
3.9 + response.getOutputBuffer().write(data.getHtml());
3.10 + }
3.11 response.setStatus(HttpStatus.OK_200);
3.12 return;
3.13 }
4.1 --- a/dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/app.js Fri Jan 25 15:08:24 2013 +0100
4.2 +++ b/dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/app.js Sun Feb 17 17:58:34 2013 +0100
4.3 @@ -112,7 +112,7 @@
4.4 " var arr = eval('(' + request.responseText + ')');\n" +
4.5 " return arr;\n" +
4.6 " }\n" +
4.7 -" var vm = new bck2brwsr(ldCls);\n" +
4.8 +" var vm = bck2brwsr(ldCls);\n" +
4.9 " vm.loadClass('${fqn}');\n" +
4.10 " </script>\n" +
4.11 "</body></html>";
5.1 --- a/emul/compact/pom.xml Fri Jan 25 15:08:24 2013 +0100
5.2 +++ b/emul/compact/pom.xml Sun Feb 17 17:58:34 2013 +0100
5.3 @@ -10,7 +10,7 @@
5.4 <groupId>org.apidesign.bck2brwsr</groupId>
5.5 <artifactId>emul</artifactId>
5.6 <version>0.3-SNAPSHOT</version>
5.7 - <name>Compact API Profile</name>
5.8 + <name>Bck2Brwsr API Profile</name>
5.9 <url>http://maven.apache.org</url>
5.10 <properties>
5.11 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
5.12 @@ -20,6 +20,7 @@
5.13 <groupId>${project.groupId}</groupId>
5.14 <artifactId>emul.mini</artifactId>
5.15 <version>${project.version}</version>
5.16 + <scope>provided</scope>
5.17 </dependency>
5.18 <dependency>
5.19 <groupId>${project.groupId}</groupId>
5.20 @@ -27,6 +28,11 @@
5.21 <version>${project.version}</version>
5.22 <scope>test</scope>
5.23 </dependency>
5.24 + <dependency>
5.25 + <groupId>org.netbeans.api</groupId>
5.26 + <artifactId>org-openide-util-lookup</artifactId>
5.27 + <scope>test</scope>
5.28 + </dependency>
5.29 </dependencies>
5.30 <build>
5.31 <plugins>
5.32 @@ -42,6 +48,25 @@
5.33 <target>1.7</target>
5.34 </configuration>
5.35 </plugin>
5.36 + <plugin>
5.37 + <artifactId>maven-assembly-plugin</artifactId>
5.38 + <version>2.4</version>
5.39 + <executions>
5.40 + <execution>
5.41 + <id>rt</id>
5.42 + <phase>package</phase>
5.43 + <goals>
5.44 + <goal>single</goal>
5.45 + </goals>
5.46 + <configuration>
5.47 + <descriptors>
5.48 + <descriptor>src/main/assembly/rt.xml</descriptor>
5.49 + </descriptors>
5.50 + <finalName>bck2brwsr-${project.version}</finalName>
5.51 + </configuration>
5.52 + </execution>
5.53 + </executions>
5.54 + </plugin>
5.55 </plugins>
5.56 </build>
5.57 </project>
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/emul/compact/src/main/assembly/rt.xml Sun Feb 17 17:58:34 2013 +0100
6.3 @@ -0,0 +1,26 @@
6.4 +<?xml version="1.0"?>
6.5 +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
6.6 + <id>rt</id>
6.7 + <formats>
6.8 + <format>jar</format>
6.9 + </formats>
6.10 + <includeBaseDirectory>false</includeBaseDirectory>
6.11 + <dependencySets>
6.12 + <dependencySet>
6.13 + <useProjectArtifact>true</useProjectArtifact>
6.14 + <unpack>true</unpack>
6.15 + <scope>provided</scope>
6.16 + <unpackOptions>
6.17 + <excludes>
6.18 + <exclude>META-INF/maven/**</exclude>
6.19 + </excludes>
6.20 + </unpackOptions>
6.21 + </dependencySet>
6.22 + </dependencySets>
6.23 + <fileSets>
6.24 + <fileSet>
6.25 + <directory>${project.build.outputDirectory}</directory>
6.26 + <outputDirectory>/</outputDirectory>
6.27 + </fileSet>
6.28 + </fileSets>
6.29 +</assembly>
6.30 \ No newline at end of file
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/emul/compact/src/main/java/java/beans/ChangeListenerMap.java Sun Feb 17 17:58:34 2013 +0100
7.3 @@ -0,0 +1,248 @@
7.4 +/*
7.5 + * Copyright (c) 2007, 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 +package java.beans;
7.29 +
7.30 +import java.util.ArrayList;
7.31 +import java.util.Collections;
7.32 +import java.util.EventListener;
7.33 +import java.util.EventListenerProxy;
7.34 +import java.util.HashMap;
7.35 +import java.util.List;
7.36 +import java.util.Map;
7.37 +import java.util.Map.Entry;
7.38 +import java.util.Set;
7.39 +import org.apidesign.bck2brwsr.emul.lang.System;
7.40 +
7.41 +/**
7.42 + * This is an abstract class that provides base functionality
7.43 + * for the {@link PropertyChangeSupport PropertyChangeSupport} class
7.44 + * and the {@link VetoableChangeSupport VetoableChangeSupport} class.
7.45 + *
7.46 + * @see PropertyChangeListenerMap
7.47 + * @see VetoableChangeListenerMap
7.48 + *
7.49 + * @author Sergey A. Malenkov
7.50 + */
7.51 +abstract class ChangeListenerMap<L extends EventListener> {
7.52 + private Map<String, L[]> map;
7.53 +
7.54 + /**
7.55 + * Creates an array of listeners.
7.56 + * This method can be optimized by using
7.57 + * the same instance of the empty array
7.58 + * when {@code length} is equal to {@code 0}.
7.59 + *
7.60 + * @param length the array length
7.61 + * @return an array with specified length
7.62 + */
7.63 + protected abstract L[] newArray(int length);
7.64 +
7.65 + /**
7.66 + * Creates a proxy listener for the specified property.
7.67 + *
7.68 + * @param name the name of the property to listen on
7.69 + * @param listener the listener to process events
7.70 + * @return a proxy listener
7.71 + */
7.72 + protected abstract L newProxy(String name, L listener);
7.73 +
7.74 + /**
7.75 + * Adds a listener to the list of listeners for the specified property.
7.76 + * This listener is called as many times as it was added.
7.77 + *
7.78 + * @param name the name of the property to listen on
7.79 + * @param listener the listener to process events
7.80 + */
7.81 + public final synchronized void add(String name, L listener) {
7.82 + if (this.map == null) {
7.83 + this.map = new HashMap<String, L[]>();
7.84 + }
7.85 + L[] array = this.map.get(name);
7.86 + int size = (array != null)
7.87 + ? array.length
7.88 + : 0;
7.89 +
7.90 + L[] clone = newArray(size + 1);
7.91 + clone[size] = listener;
7.92 + if (array != null) {
7.93 + System.arraycopy(array, 0, clone, 0, size);
7.94 + }
7.95 + this.map.put(name, clone);
7.96 + }
7.97 +
7.98 + /**
7.99 + * Removes a listener from the list of listeners for the specified property.
7.100 + * If the listener was added more than once to the same event source,
7.101 + * this listener will be notified one less time after being removed.
7.102 + *
7.103 + * @param name the name of the property to listen on
7.104 + * @param listener the listener to process events
7.105 + */
7.106 + public final synchronized void remove(String name, L listener) {
7.107 + if (this.map != null) {
7.108 + L[] array = this.map.get(name);
7.109 + if (array != null) {
7.110 + for (int i = 0; i < array.length; i++) {
7.111 + if (listener.equals(array[i])) {
7.112 + int size = array.length - 1;
7.113 + if (size > 0) {
7.114 + L[] clone = newArray(size);
7.115 + System.arraycopy(array, 0, clone, 0, i);
7.116 + System.arraycopy(array, i + 1, clone, i, size - i);
7.117 + this.map.put(name, clone);
7.118 + }
7.119 + else {
7.120 + this.map.remove(name);
7.121 + if (this.map.isEmpty()) {
7.122 + this.map = null;
7.123 + }
7.124 + }
7.125 + break;
7.126 + }
7.127 + }
7.128 + }
7.129 + }
7.130 + }
7.131 +
7.132 + /**
7.133 + * Returns the list of listeners for the specified property.
7.134 + *
7.135 + * @param name the name of the property
7.136 + * @return the corresponding list of listeners
7.137 + */
7.138 + public final synchronized L[] get(String name) {
7.139 + return (this.map != null)
7.140 + ? this.map.get(name)
7.141 + : null;
7.142 + }
7.143 +
7.144 + /**
7.145 + * Sets new list of listeners for the specified property.
7.146 + *
7.147 + * @param name the name of the property
7.148 + * @param listeners new list of listeners
7.149 + */
7.150 + public final void set(String name, L[] listeners) {
7.151 + if (listeners != null) {
7.152 + if (this.map == null) {
7.153 + this.map = new HashMap<String, L[]>();
7.154 + }
7.155 + this.map.put(name, listeners);
7.156 + }
7.157 + else if (this.map != null) {
7.158 + this.map.remove(name);
7.159 + if (this.map.isEmpty()) {
7.160 + this.map = null;
7.161 + }
7.162 + }
7.163 + }
7.164 +
7.165 + /**
7.166 + * Returns all listeners in the map.
7.167 + *
7.168 + * @return an array of all listeners
7.169 + */
7.170 + public final synchronized L[] getListeners() {
7.171 + if (this.map == null) {
7.172 + return newArray(0);
7.173 + }
7.174 + List<L> list = new ArrayList<L>();
7.175 +
7.176 + L[] listeners = this.map.get(null);
7.177 + if (listeners != null) {
7.178 + for (L listener : listeners) {
7.179 + list.add(listener);
7.180 + }
7.181 + }
7.182 + for (Entry<String, L[]> entry : this.map.entrySet()) {
7.183 + String name = entry.getKey();
7.184 + if (name != null) {
7.185 + for (L listener : entry.getValue()) {
7.186 + list.add(newProxy(name, listener));
7.187 + }
7.188 + }
7.189 + }
7.190 + return list.toArray(newArray(list.size()));
7.191 + }
7.192 +
7.193 + /**
7.194 + * Returns listeners that have been associated with the named property.
7.195 + *
7.196 + * @param name the name of the property
7.197 + * @return an array of listeners for the named property
7.198 + */
7.199 + public final L[] getListeners(String name) {
7.200 + if (name != null) {
7.201 + L[] listeners = get(name);
7.202 + if (listeners != null) {
7.203 + return listeners.clone();
7.204 + }
7.205 + }
7.206 + return newArray(0);
7.207 + }
7.208 +
7.209 + /**
7.210 + * Indicates whether the map contains
7.211 + * at least one listener to be notified.
7.212 + *
7.213 + * @param name the name of the property
7.214 + * @return {@code true} if at least one listener exists or
7.215 + * {@code false} otherwise
7.216 + */
7.217 + public final synchronized boolean hasListeners(String name) {
7.218 + if (this.map == null) {
7.219 + return false;
7.220 + }
7.221 + L[] array = this.map.get(null);
7.222 + return (array != null) || ((name != null) && (null != this.map.get(name)));
7.223 + }
7.224 +
7.225 + /**
7.226 + * Returns a set of entries from the map.
7.227 + * Each entry is a pair consisted of the property name
7.228 + * and the corresponding list of listeners.
7.229 + *
7.230 + * @return a set of entries from the map
7.231 + */
7.232 + public final Set<Entry<String, L[]>> getEntries() {
7.233 + return (this.map != null)
7.234 + ? this.map.entrySet()
7.235 + : Collections.<Entry<String, L[]>>emptySet();
7.236 + }
7.237 +
7.238 + /**
7.239 + * Extracts a real listener from the proxy listener.
7.240 + * It is necessary because default proxy class is not serializable.
7.241 + *
7.242 + * @return a real listener
7.243 + */
7.244 + public final L extract(L listener) {
7.245 + while (listener instanceof EventListenerProxy) {
7.246 + EventListenerProxy<L> proxy = (EventListenerProxy<L>) listener;
7.247 + listener = proxy.getListener();
7.248 + }
7.249 + return listener;
7.250 + }
7.251 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/emul/compact/src/main/java/java/beans/IndexedPropertyChangeEvent.java Sun Feb 17 17:58:34 2013 +0100
8.3 @@ -0,0 +1,78 @@
8.4 +/*
8.5 + * Copyright (c) 2003, 2011, 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 +/**
8.31 + * An "IndexedPropertyChange" event gets delivered whenever a component that
8.32 + * conforms to the JavaBeans™ specification (a "bean") changes a bound
8.33 + * indexed property. This class is an extension of <code>PropertyChangeEvent</code>
8.34 + * but contains the index of the property that has changed.
8.35 + * <P>
8.36 + * Null values may be provided for the old and the new values if their
8.37 + * true values are not known.
8.38 + * <P>
8.39 + * An event source may send a null object as the name to indicate that an
8.40 + * arbitrary set of if its properties have changed. In this case the
8.41 + * old and new values should also be null.
8.42 + *
8.43 + * @since 1.5
8.44 + * @author Mark Davidson
8.45 + */
8.46 +public class IndexedPropertyChangeEvent extends PropertyChangeEvent {
8.47 + private static final long serialVersionUID = -320227448495806870L;
8.48 +
8.49 + private int index;
8.50 +
8.51 + /**
8.52 + * Constructs a new <code>IndexedPropertyChangeEvent</code> object.
8.53 + *
8.54 + * @param source The bean that fired the event.
8.55 + * @param propertyName The programmatic name of the property that
8.56 + * was changed.
8.57 + * @param oldValue The old value of the property.
8.58 + * @param newValue The new value of the property.
8.59 + * @param index index of the property element that was changed.
8.60 + */
8.61 + public IndexedPropertyChangeEvent(Object source, String propertyName,
8.62 + Object oldValue, Object newValue,
8.63 + int index) {
8.64 + super (source, propertyName, oldValue, newValue);
8.65 + this.index = index;
8.66 + }
8.67 +
8.68 + /**
8.69 + * Gets the index of the property that was changed.
8.70 + *
8.71 + * @return The index specifying the property element that was
8.72 + * changed.
8.73 + */
8.74 + public int getIndex() {
8.75 + return index;
8.76 + }
8.77 +
8.78 + void appendTo(StringBuilder sb) {
8.79 + sb.append("; index=").append(getIndex());
8.80 + }
8.81 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/emul/compact/src/main/java/java/beans/PropertyChangeEvent.java Sun Feb 17 17:58:34 2013 +0100
9.3 @@ -0,0 +1,164 @@
9.4 +/*
9.5 + * Copyright (c) 1996, 2010, 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 + * A "PropertyChange" event gets delivered whenever a bean changes a "bound"
9.33 + * or "constrained" property. A PropertyChangeEvent object is sent as an
9.34 + * argument to the PropertyChangeListener and VetoableChangeListener methods.
9.35 + * <P>
9.36 + * Normally PropertyChangeEvents are accompanied by the name and the old
9.37 + * and new value of the changed property. If the new value is a primitive
9.38 + * type (such as int or boolean) it must be wrapped as the
9.39 + * corresponding java.lang.* Object type (such as Integer or Boolean).
9.40 + * <P>
9.41 + * Null values may be provided for the old and the new values if their
9.42 + * true values are not known.
9.43 + * <P>
9.44 + * An event source may send a null object as the name to indicate that an
9.45 + * arbitrary set of if its properties have changed. In this case the
9.46 + * old and new values should also be null.
9.47 + */
9.48 +
9.49 +public class PropertyChangeEvent extends java.util.EventObject {
9.50 + private static final long serialVersionUID = 7042693688939648123L;
9.51 +
9.52 + /**
9.53 + * Constructs a new <code>PropertyChangeEvent</code>.
9.54 + *
9.55 + * @param source The bean that fired the event.
9.56 + * @param propertyName The programmatic name of the property
9.57 + * that was changed.
9.58 + * @param oldValue The old value of the property.
9.59 + * @param newValue The new value of the property.
9.60 + */
9.61 + public PropertyChangeEvent(Object source, String propertyName,
9.62 + Object oldValue, Object newValue) {
9.63 + super(source);
9.64 + this.propertyName = propertyName;
9.65 + this.newValue = newValue;
9.66 + this.oldValue = oldValue;
9.67 + }
9.68 +
9.69 + /**
9.70 + * Gets the programmatic name of the property that was changed.
9.71 + *
9.72 + * @return The programmatic name of the property that was changed.
9.73 + * May be null if multiple properties have changed.
9.74 + */
9.75 + public String getPropertyName() {
9.76 + return propertyName;
9.77 + }
9.78 +
9.79 + /**
9.80 + * Gets the new value for the property, expressed as an Object.
9.81 + *
9.82 + * @return The new value for the property, expressed as an Object.
9.83 + * May be null if multiple properties have changed.
9.84 + */
9.85 + public Object getNewValue() {
9.86 + return newValue;
9.87 + }
9.88 +
9.89 + /**
9.90 + * Gets the old value for the property, expressed as an Object.
9.91 + *
9.92 + * @return The old value for the property, expressed as an Object.
9.93 + * May be null if multiple properties have changed.
9.94 + */
9.95 + public Object getOldValue() {
9.96 + return oldValue;
9.97 + }
9.98 +
9.99 + /**
9.100 + * Sets the propagationId object for the event.
9.101 + *
9.102 + * @param propagationId The propagationId object for the event.
9.103 + */
9.104 + public void setPropagationId(Object propagationId) {
9.105 + this.propagationId = propagationId;
9.106 + }
9.107 +
9.108 + /**
9.109 + * The "propagationId" field is reserved for future use. In Beans 1.0
9.110 + * the sole requirement is that if a listener catches a PropertyChangeEvent
9.111 + * and then fires a PropertyChangeEvent of its own, then it should
9.112 + * make sure that it propagates the propagationId field from its
9.113 + * incoming event to its outgoing event.
9.114 + *
9.115 + * @return the propagationId object associated with a bound/constrained
9.116 + * property update.
9.117 + */
9.118 + public Object getPropagationId() {
9.119 + return propagationId;
9.120 + }
9.121 +
9.122 + /**
9.123 + * name of the property that changed. May be null, if not known.
9.124 + * @serial
9.125 + */
9.126 + private String propertyName;
9.127 +
9.128 + /**
9.129 + * New value for property. May be null if not known.
9.130 + * @serial
9.131 + */
9.132 + private Object newValue;
9.133 +
9.134 + /**
9.135 + * Previous value for property. May be null if not known.
9.136 + * @serial
9.137 + */
9.138 + private Object oldValue;
9.139 +
9.140 + /**
9.141 + * Propagation ID. May be null.
9.142 + * @serial
9.143 + * @see #getPropagationId
9.144 + */
9.145 + private Object propagationId;
9.146 +
9.147 + /**
9.148 + * Returns a string representation of the object.
9.149 + *
9.150 + * @return a string representation of the object
9.151 + *
9.152 + * @since 1.7
9.153 + */
9.154 + public String toString() {
9.155 + StringBuilder sb = new StringBuilder(getClass().getName());
9.156 + sb.append("[propertyName=").append(getPropertyName());
9.157 + appendTo(sb);
9.158 + sb.append("; oldValue=").append(getOldValue());
9.159 + sb.append("; newValue=").append(getNewValue());
9.160 + sb.append("; propagationId=").append(getPropagationId());
9.161 + sb.append("; source=").append(getSource());
9.162 + return sb.append("]").toString();
9.163 + }
9.164 +
9.165 + void appendTo(StringBuilder sb) {
9.166 + }
9.167 +}
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/emul/compact/src/main/java/java/beans/PropertyChangeListener.java Sun Feb 17 17:58:34 2013 +0100
10.3 @@ -0,0 +1,44 @@
10.4 +/*
10.5 + * Copyright (c) 1996, 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 "PropertyChange" event gets fired whenever a bean changes a "bound"
10.33 + * property. You can register a PropertyChangeListener with a source
10.34 + * bean so as to be notified of any bound property updates.
10.35 + */
10.36 +
10.37 +public interface PropertyChangeListener extends java.util.EventListener {
10.38 +
10.39 + /**
10.40 + * This method gets called when a bound property is changed.
10.41 + * @param evt A PropertyChangeEvent object describing the event source
10.42 + * and the property that has changed.
10.43 + */
10.44 +
10.45 + void propertyChange(PropertyChangeEvent evt);
10.46 +
10.47 +}
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/emul/compact/src/main/java/java/beans/PropertyChangeListenerProxy.java Sun Feb 17 17:58:34 2013 +0100
11.3 @@ -0,0 +1,81 @@
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 PropertyChangeListener}
11.36 + * with a "bound" property.
11.37 + * Instances of this class can be added
11.38 + * as {@code PropertyChangeListener}s to a bean
11.39 + * which supports firing property change events.
11.40 + * <p>
11.41 + * If the object has a {@code getPropertyChangeListeners} method
11.42 + * then the array returned could be a mixture of {@code PropertyChangeListener}
11.43 + * and {@code PropertyChangeListenerProxy} objects.
11.44 + *
11.45 + * @see java.util.EventListenerProxy
11.46 + * @see PropertyChangeSupport#getPropertyChangeListeners
11.47 + * @since 1.4
11.48 + */
11.49 +public class PropertyChangeListenerProxy
11.50 + extends EventListenerProxy<PropertyChangeListener>
11.51 + implements PropertyChangeListener {
11.52 +
11.53 + private final String propertyName;
11.54 +
11.55 + /**
11.56 + * Constructor which binds the {@code PropertyChangeListener}
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 PropertyChangeListenerProxy(String propertyName, PropertyChangeListener 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 + public void propertyChange(PropertyChangeEvent event) {
11.73 + getListener().propertyChange(event);
11.74 + }
11.75 +
11.76 + /**
11.77 + * Returns the name of the named property associated with the listener.
11.78 + *
11.79 + * @return the name of the named property associated with the listener
11.80 + */
11.81 + public String getPropertyName() {
11.82 + return this.propertyName;
11.83 + }
11.84 +}
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/emul/compact/src/main/java/java/beans/PropertyChangeSupport.java Sun Feb 17 17:58:34 2013 +0100
12.3 @@ -0,0 +1,536 @@
12.4 +/*
12.5 + * Copyright (c) 1996, 2008, 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 +
12.38 +/**
12.39 + * This is a utility class that can be used by beans that support bound
12.40 + * properties. It manages a list of listeners and dispatches
12.41 + * {@link PropertyChangeEvent}s to them. You can use an instance of this class
12.42 + * as a member field of your bean and delegate these types of work to it.
12.43 + * The {@link PropertyChangeListener} can be registered for all properties
12.44 + * or for a property specified by name.
12.45 + * <p>
12.46 + * Here is an example of {@code PropertyChangeSupport} usage that follows
12.47 + * the rules and recommendations laid out in the JavaBeans™ specification:
12.48 + * <pre>
12.49 + * public class MyBean {
12.50 + * private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
12.51 + *
12.52 + * public void addPropertyChangeListener(PropertyChangeListener listener) {
12.53 + * this.pcs.addPropertyChangeListener(listener);
12.54 + * }
12.55 + *
12.56 + * public void removePropertyChangeListener(PropertyChangeListener listener) {
12.57 + * this.pcs.removePropertyChangeListener(listener);
12.58 + * }
12.59 + *
12.60 + * private String value;
12.61 + *
12.62 + * public String getValue() {
12.63 + * return this.value;
12.64 + * }
12.65 + *
12.66 + * public void setValue(String newValue) {
12.67 + * String oldValue = this.value;
12.68 + * this.value = newValue;
12.69 + * this.pcs.firePropertyChange("value", oldValue, newValue);
12.70 + * }
12.71 + *
12.72 + * [...]
12.73 + * }
12.74 + * </pre>
12.75 + * <p>
12.76 + * A {@code PropertyChangeSupport} instance is thread-safe.
12.77 + * <p>
12.78 + * This class is serializable. When it is serialized it will save
12.79 + * (and restore) any listeners that are themselves serializable. Any
12.80 + * non-serializable listeners will be skipped during serialization.
12.81 + *
12.82 + * @see VetoableChangeSupport
12.83 + */
12.84 +public class PropertyChangeSupport implements Serializable {
12.85 + private PropertyChangeListenerMap map = new PropertyChangeListenerMap();
12.86 +
12.87 + /**
12.88 + * Constructs a <code>PropertyChangeSupport</code> object.
12.89 + *
12.90 + * @param sourceBean The bean to be given as the source for any events.
12.91 + */
12.92 + public PropertyChangeSupport(Object sourceBean) {
12.93 + if (sourceBean == null) {
12.94 + throw new NullPointerException();
12.95 + }
12.96 + source = sourceBean;
12.97 + }
12.98 +
12.99 + /**
12.100 + * Add a PropertyChangeListener to the listener list.
12.101 + * The listener is registered for all properties.
12.102 + * The same listener object may be added more than once, and will be called
12.103 + * as many times as it is added.
12.104 + * If <code>listener</code> is null, no exception is thrown and no action
12.105 + * is taken.
12.106 + *
12.107 + * @param listener The PropertyChangeListener to be added
12.108 + */
12.109 + public void addPropertyChangeListener(PropertyChangeListener listener) {
12.110 + if (listener == null) {
12.111 + return;
12.112 + }
12.113 + if (listener instanceof PropertyChangeListenerProxy) {
12.114 + PropertyChangeListenerProxy proxy =
12.115 + (PropertyChangeListenerProxy)listener;
12.116 + // Call two argument add method.
12.117 + addPropertyChangeListener(proxy.getPropertyName(),
12.118 + proxy.getListener());
12.119 + } else {
12.120 + this.map.add(null, listener);
12.121 + }
12.122 + }
12.123 +
12.124 + /**
12.125 + * Remove a PropertyChangeListener from the listener list.
12.126 + * This removes a PropertyChangeListener that was registered
12.127 + * for all properties.
12.128 + * If <code>listener</code> was added more than once to the same event
12.129 + * source, it will be notified one less time after being removed.
12.130 + * If <code>listener</code> is null, or was never added, no exception is
12.131 + * thrown and no action is taken.
12.132 + *
12.133 + * @param listener The PropertyChangeListener to be removed
12.134 + */
12.135 + public void removePropertyChangeListener(PropertyChangeListener listener) {
12.136 + if (listener == null) {
12.137 + return;
12.138 + }
12.139 + if (listener instanceof PropertyChangeListenerProxy) {
12.140 + PropertyChangeListenerProxy proxy =
12.141 + (PropertyChangeListenerProxy)listener;
12.142 + // Call two argument remove method.
12.143 + removePropertyChangeListener(proxy.getPropertyName(),
12.144 + proxy.getListener());
12.145 + } else {
12.146 + this.map.remove(null, listener);
12.147 + }
12.148 + }
12.149 +
12.150 + /**
12.151 + * Returns an array of all the listeners that were added to the
12.152 + * PropertyChangeSupport object with addPropertyChangeListener().
12.153 + * <p>
12.154 + * If some listeners have been added with a named property, then
12.155 + * the returned array will be a mixture of PropertyChangeListeners
12.156 + * and <code>PropertyChangeListenerProxy</code>s. If the calling
12.157 + * method is interested in distinguishing the listeners then it must
12.158 + * test each element to see if it's a
12.159 + * <code>PropertyChangeListenerProxy</code>, perform the cast, and examine
12.160 + * the parameter.
12.161 + *
12.162 + * <pre>
12.163 + * PropertyChangeListener[] listeners = bean.getPropertyChangeListeners();
12.164 + * for (int i = 0; i < listeners.length; i++) {
12.165 + * if (listeners[i] instanceof PropertyChangeListenerProxy) {
12.166 + * PropertyChangeListenerProxy proxy =
12.167 + * (PropertyChangeListenerProxy)listeners[i];
12.168 + * if (proxy.getPropertyName().equals("foo")) {
12.169 + * // proxy is a PropertyChangeListener which was associated
12.170 + * // with the property named "foo"
12.171 + * }
12.172 + * }
12.173 + * }
12.174 + *</pre>
12.175 + *
12.176 + * @see PropertyChangeListenerProxy
12.177 + * @return all of the <code>PropertyChangeListeners</code> added or an
12.178 + * empty array if no listeners have been added
12.179 + * @since 1.4
12.180 + */
12.181 + public PropertyChangeListener[] getPropertyChangeListeners() {
12.182 + return this.map.getListeners();
12.183 + }
12.184 +
12.185 + /**
12.186 + * Add a PropertyChangeListener for a specific property. The listener
12.187 + * will be invoked only when a call on firePropertyChange names that
12.188 + * specific property.
12.189 + * The same listener object may be added more than once. For each
12.190 + * property, the listener will be invoked the number of times it was added
12.191 + * for that property.
12.192 + * If <code>propertyName</code> or <code>listener</code> is null, no
12.193 + * exception is thrown and no action is taken.
12.194 + *
12.195 + * @param propertyName The name of the property to listen on.
12.196 + * @param listener The PropertyChangeListener to be added
12.197 + */
12.198 + public void addPropertyChangeListener(
12.199 + String propertyName,
12.200 + PropertyChangeListener listener) {
12.201 + if (listener == null || propertyName == null) {
12.202 + return;
12.203 + }
12.204 + listener = this.map.extract(listener);
12.205 + if (listener != null) {
12.206 + this.map.add(propertyName, listener);
12.207 + }
12.208 + }
12.209 +
12.210 + /**
12.211 + * Remove a PropertyChangeListener for a specific property.
12.212 + * If <code>listener</code> was added more than once to the same event
12.213 + * source for the specified property, it will be notified one less time
12.214 + * after being removed.
12.215 + * If <code>propertyName</code> is null, no exception is thrown and no
12.216 + * action is taken.
12.217 + * If <code>listener</code> is null, or was never added for the specified
12.218 + * property, no exception is thrown and no action is taken.
12.219 + *
12.220 + * @param propertyName The name of the property that was listened on.
12.221 + * @param listener The PropertyChangeListener to be removed
12.222 + */
12.223 + public void removePropertyChangeListener(
12.224 + String propertyName,
12.225 + PropertyChangeListener listener) {
12.226 + if (listener == null || propertyName == null) {
12.227 + return;
12.228 + }
12.229 + listener = this.map.extract(listener);
12.230 + if (listener != null) {
12.231 + this.map.remove(propertyName, listener);
12.232 + }
12.233 + }
12.234 +
12.235 + /**
12.236 + * Returns an array of all the listeners which have been associated
12.237 + * with the named property.
12.238 + *
12.239 + * @param propertyName The name of the property being listened to
12.240 + * @return all of the <code>PropertyChangeListeners</code> associated with
12.241 + * the named property. If no such listeners have been added,
12.242 + * or if <code>propertyName</code> is null, an empty array is
12.243 + * returned.
12.244 + * @since 1.4
12.245 + */
12.246 + public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
12.247 + return this.map.getListeners(propertyName);
12.248 + }
12.249 +
12.250 + /**
12.251 + * Reports a bound property update to listeners
12.252 + * that have been registered to track updates of
12.253 + * all properties or a property with the specified name.
12.254 + * <p>
12.255 + * No event is fired if old and new values are equal and non-null.
12.256 + * <p>
12.257 + * This is merely a convenience wrapper around the more general
12.258 + * {@link #firePropertyChange(PropertyChangeEvent)} method.
12.259 + *
12.260 + * @param propertyName the programmatic name of the property that was changed
12.261 + * @param oldValue the old value of the property
12.262 + * @param newValue the new value of the property
12.263 + */
12.264 + public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
12.265 + if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
12.266 + firePropertyChange(new PropertyChangeEvent(this.source, propertyName, oldValue, newValue));
12.267 + }
12.268 + }
12.269 +
12.270 + /**
12.271 + * Reports an integer bound property update to listeners
12.272 + * that have been registered to track updates of
12.273 + * all properties or a property with the specified name.
12.274 + * <p>
12.275 + * No event is fired if old and new values are equal.
12.276 + * <p>
12.277 + * This is merely a convenience wrapper around the more general
12.278 + * {@link #firePropertyChange(String, Object, Object)} method.
12.279 + *
12.280 + * @param propertyName the programmatic name of the property that was changed
12.281 + * @param oldValue the old value of the property
12.282 + * @param newValue the new value of the property
12.283 + */
12.284 + public void firePropertyChange(String propertyName, int oldValue, int newValue) {
12.285 + if (oldValue != newValue) {
12.286 + firePropertyChange(propertyName, Integer.valueOf(oldValue), Integer.valueOf(newValue));
12.287 + }
12.288 + }
12.289 +
12.290 + /**
12.291 + * Reports a boolean bound property update to listeners
12.292 + * that have been registered to track updates of
12.293 + * all properties or a property with the specified name.
12.294 + * <p>
12.295 + * No event is fired if old and new values are equal.
12.296 + * <p>
12.297 + * This is merely a convenience wrapper around the more general
12.298 + * {@link #firePropertyChange(String, Object, Object)} method.
12.299 + *
12.300 + * @param propertyName the programmatic name of the property that was changed
12.301 + * @param oldValue the old value of the property
12.302 + * @param newValue the new value of the property
12.303 + */
12.304 + public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {
12.305 + if (oldValue != newValue) {
12.306 + firePropertyChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
12.307 + }
12.308 + }
12.309 +
12.310 + /**
12.311 + * Fires a property change event to listeners
12.312 + * that have been registered to track updates of
12.313 + * all properties or a property with the specified name.
12.314 + * <p>
12.315 + * No event is fired if the given event's old and new values are equal and non-null.
12.316 + *
12.317 + * @param event the {@code PropertyChangeEvent} to be fired
12.318 + */
12.319 + public void firePropertyChange(PropertyChangeEvent event) {
12.320 + Object oldValue = event.getOldValue();
12.321 + Object newValue = event.getNewValue();
12.322 + if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
12.323 + String name = event.getPropertyName();
12.324 +
12.325 + PropertyChangeListener[] common = this.map.get(null);
12.326 + PropertyChangeListener[] named = (name != null)
12.327 + ? this.map.get(name)
12.328 + : null;
12.329 +
12.330 + fire(common, event);
12.331 + fire(named, event);
12.332 + }
12.333 + }
12.334 +
12.335 + private static void fire(PropertyChangeListener[] listeners, PropertyChangeEvent event) {
12.336 + if (listeners != null) {
12.337 + for (PropertyChangeListener listener : listeners) {
12.338 + listener.propertyChange(event);
12.339 + }
12.340 + }
12.341 + }
12.342 +
12.343 + /**
12.344 + * Reports a bound indexed property update to listeners
12.345 + * that have been registered to track updates of
12.346 + * all properties or a property with the specified name.
12.347 + * <p>
12.348 + * No event is fired if old and new values are equal and non-null.
12.349 + * <p>
12.350 + * This is merely a convenience wrapper around the more general
12.351 + * {@link #firePropertyChange(PropertyChangeEvent)} method.
12.352 + *
12.353 + * @param propertyName the programmatic name of the property that was changed
12.354 + * @param index the index of the property element that was changed
12.355 + * @param oldValue the old value of the property
12.356 + * @param newValue the new value of the property
12.357 + * @since 1.5
12.358 + */
12.359 + public void fireIndexedPropertyChange(String propertyName, int index, Object oldValue, Object newValue) {
12.360 + if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
12.361 + firePropertyChange(new IndexedPropertyChangeEvent(source, propertyName, oldValue, newValue, index));
12.362 + }
12.363 + }
12.364 +
12.365 + /**
12.366 + * Reports an integer bound indexed property update to listeners
12.367 + * that have been registered to track updates of
12.368 + * all properties or a property with the specified name.
12.369 + * <p>
12.370 + * No event is fired if old and new values are equal.
12.371 + * <p>
12.372 + * This is merely a convenience wrapper around the more general
12.373 + * {@link #fireIndexedPropertyChange(String, int, Object, Object)} method.
12.374 + *
12.375 + * @param propertyName the programmatic name of the property that was changed
12.376 + * @param index the index of the property element that was changed
12.377 + * @param oldValue the old value of the property
12.378 + * @param newValue the new value of the property
12.379 + * @since 1.5
12.380 + */
12.381 + public void fireIndexedPropertyChange(String propertyName, int index, int oldValue, int newValue) {
12.382 + if (oldValue != newValue) {
12.383 + fireIndexedPropertyChange(propertyName, index, Integer.valueOf(oldValue), Integer.valueOf(newValue));
12.384 + }
12.385 + }
12.386 +
12.387 + /**
12.388 + * Reports a boolean bound indexed property update to listeners
12.389 + * that have been registered to track updates of
12.390 + * all properties or a property with the specified name.
12.391 + * <p>
12.392 + * No event is fired if old and new values are equal.
12.393 + * <p>
12.394 + * This is merely a convenience wrapper around the more general
12.395 + * {@link #fireIndexedPropertyChange(String, int, Object, Object)} method.
12.396 + *
12.397 + * @param propertyName the programmatic name of the property that was changed
12.398 + * @param index the index of the property element that was changed
12.399 + * @param oldValue the old value of the property
12.400 + * @param newValue the new value of the property
12.401 + * @since 1.5
12.402 + */
12.403 + public void fireIndexedPropertyChange(String propertyName, int index, boolean oldValue, boolean newValue) {
12.404 + if (oldValue != newValue) {
12.405 + fireIndexedPropertyChange(propertyName, index, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
12.406 + }
12.407 + }
12.408 +
12.409 + /**
12.410 + * Check if there are any listeners for a specific property, including
12.411 + * those registered on all properties. If <code>propertyName</code>
12.412 + * is null, only check for listeners registered on all properties.
12.413 + *
12.414 + * @param propertyName the property name.
12.415 + * @return true if there are one or more listeners for the given property
12.416 + */
12.417 + public boolean hasListeners(String propertyName) {
12.418 + return this.map.hasListeners(propertyName);
12.419 + }
12.420 +
12.421 + /**
12.422 + * @serialData Null terminated list of <code>PropertyChangeListeners</code>.
12.423 + * <p>
12.424 + * At serialization time we skip non-serializable listeners and
12.425 + * only serialize the serializable listeners.
12.426 + */
12.427 + private void writeObject(ObjectOutputStream s) throws IOException {
12.428 + Hashtable<String, PropertyChangeSupport> children = null;
12.429 + PropertyChangeListener[] listeners = null;
12.430 + synchronized (this.map) {
12.431 + for (Entry<String, PropertyChangeListener[]> entry : this.map.getEntries()) {
12.432 + String property = entry.getKey();
12.433 + if (property == null) {
12.434 + listeners = entry.getValue();
12.435 + } else {
12.436 + if (children == null) {
12.437 + children = new Hashtable<String, PropertyChangeSupport>();
12.438 + }
12.439 + PropertyChangeSupport pcs = new PropertyChangeSupport(this.source);
12.440 + pcs.map.set(null, entry.getValue());
12.441 + children.put(property, pcs);
12.442 + }
12.443 + }
12.444 + }
12.445 + ObjectOutputStream.PutField fields = s.putFields();
12.446 + fields.put("children", children);
12.447 + fields.put("source", this.source);
12.448 + fields.put("propertyChangeSupportSerializedDataVersion", 2);
12.449 + s.writeFields();
12.450 +
12.451 + if (listeners != null) {
12.452 + for (PropertyChangeListener l : listeners) {
12.453 + if (l instanceof Serializable) {
12.454 + s.writeObject(l);
12.455 + }
12.456 + }
12.457 + }
12.458 + s.writeObject(null);
12.459 + }
12.460 +
12.461 + private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
12.462 + this.map = new PropertyChangeListenerMap();
12.463 +
12.464 + ObjectInputStream.GetField fields = s.readFields();
12.465 +
12.466 + Hashtable<String, PropertyChangeSupport> children = (Hashtable<String, PropertyChangeSupport>) fields.get("children", null);
12.467 + this.source = fields.get("source", null);
12.468 + fields.get("propertyChangeSupportSerializedDataVersion", 2);
12.469 +
12.470 + Object listenerOrNull;
12.471 + while (null != (listenerOrNull = s.readObject())) {
12.472 + this.map.add(null, (PropertyChangeListener)listenerOrNull);
12.473 + }
12.474 + if (children != null) {
12.475 + for (Entry<String, PropertyChangeSupport> entry : children.entrySet()) {
12.476 + for (PropertyChangeListener listener : entry.getValue().getPropertyChangeListeners()) {
12.477 + this.map.add(entry.getKey(), listener);
12.478 + }
12.479 + }
12.480 + }
12.481 + }
12.482 +
12.483 + /**
12.484 + * The object to be provided as the "source" for any generated events.
12.485 + */
12.486 + private Object source;
12.487 +
12.488 + /**
12.489 + * @serialField children Hashtable
12.490 + * @serialField source Object
12.491 + * @serialField propertyChangeSupportSerializedDataVersion int
12.492 + */
12.493 + private static final ObjectStreamField[] serialPersistentFields = {
12.494 + new ObjectStreamField("children", Hashtable.class),
12.495 + new ObjectStreamField("source", Object.class),
12.496 + new ObjectStreamField("propertyChangeSupportSerializedDataVersion", Integer.TYPE)
12.497 + };
12.498 +
12.499 + /**
12.500 + * Serialization version ID, so we're compatible with JDK 1.1
12.501 + */
12.502 + static final long serialVersionUID = 6401253773779951803L;
12.503 +
12.504 + /**
12.505 + * This is a {@link ChangeListenerMap ChangeListenerMap} implementation
12.506 + * that works with {@link PropertyChangeListener PropertyChangeListener} objects.
12.507 + */
12.508 + private static final class PropertyChangeListenerMap extends ChangeListenerMap<PropertyChangeListener> {
12.509 + private static final PropertyChangeListener[] EMPTY = {};
12.510 +
12.511 + /**
12.512 + * Creates an array of {@link PropertyChangeListener PropertyChangeListener} objects.
12.513 + * This method uses the same instance of the empty array
12.514 + * when {@code length} equals {@code 0}.
12.515 + *
12.516 + * @param length the array length
12.517 + * @return an array with specified length
12.518 + */
12.519 + @Override
12.520 + protected PropertyChangeListener[] newArray(int length) {
12.521 + return (0 < length)
12.522 + ? new PropertyChangeListener[length]
12.523 + : EMPTY;
12.524 + }
12.525 +
12.526 + /**
12.527 + * Creates a {@link PropertyChangeListenerProxy PropertyChangeListenerProxy}
12.528 + * object for the specified property.
12.529 + *
12.530 + * @param name the name of the property to listen on
12.531 + * @param listener the listener to process events
12.532 + * @return a {@code PropertyChangeListenerProxy} object
12.533 + */
12.534 + @Override
12.535 + protected PropertyChangeListener newProxy(String name, PropertyChangeListener listener) {
12.536 + return new PropertyChangeListenerProxy(name, listener);
12.537 + }
12.538 + }
12.539 +}
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/emul/compact/src/main/java/java/beans/PropertyVetoException.java Sun Feb 17 17:58:34 2013 +0100
13.3 @@ -0,0 +1,64 @@
13.4 +/*
13.5 + * Copyright (c) 1996, 2009, 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.beans;
13.30 +
13.31 +
13.32 +/**
13.33 + * A PropertyVetoException is thrown when a proposed change to a
13.34 + * property represents an unacceptable value.
13.35 + */
13.36 +
13.37 +public
13.38 +class PropertyVetoException extends Exception {
13.39 + private static final long serialVersionUID = 129596057694162164L;
13.40 +
13.41 + /**
13.42 + * Constructs a <code>PropertyVetoException</code> with a
13.43 + * detailed message.
13.44 + *
13.45 + * @param mess Descriptive message
13.46 + * @param evt A PropertyChangeEvent describing the vetoed change.
13.47 + */
13.48 + public PropertyVetoException(String mess, PropertyChangeEvent evt) {
13.49 + super(mess);
13.50 + this.evt = evt;
13.51 + }
13.52 +
13.53 + /**
13.54 + * Gets the vetoed <code>PropertyChangeEvent</code>.
13.55 + *
13.56 + * @return A PropertyChangeEvent describing the vetoed change.
13.57 + */
13.58 + public PropertyChangeEvent getPropertyChangeEvent() {
13.59 + return evt;
13.60 + }
13.61 +
13.62 + /**
13.63 + * A PropertyChangeEvent describing the vetoed change.
13.64 + * @serial
13.65 + */
13.66 + private PropertyChangeEvent evt;
13.67 +}
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/emul/compact/src/main/java/java/beans/VetoableChangeListener.java Sun Feb 17 17:58:34 2013 +0100
14.3 @@ -0,0 +1,44 @@
14.4 +/*
14.5 + * Copyright (c) 1996, 1997, 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.beans;
14.30 +
14.31 +/**
14.32 + * A VetoableChange event gets fired whenever a bean changes a "constrained"
14.33 + * property. You can register a VetoableChangeListener with a source bean
14.34 + * so as to be notified of any constrained property updates.
14.35 + */
14.36 +public interface VetoableChangeListener extends java.util.EventListener {
14.37 + /**
14.38 + * This method gets called when a constrained property is changed.
14.39 + *
14.40 + * @param evt a <code>PropertyChangeEvent</code> object describing the
14.41 + * event source and the property that has changed.
14.42 + * @exception PropertyVetoException if the recipient wishes the property
14.43 + * change to be rolled back.
14.44 + */
14.45 + void vetoableChange(PropertyChangeEvent evt)
14.46 + throws PropertyVetoException;
14.47 +}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/emul/compact/src/main/java/java/beans/VetoableChangeListenerProxy.java Sun Feb 17 17:58:34 2013 +0100
15.3 @@ -0,0 +1,84 @@
15.4 +/*
15.5 + * Copyright (c) 2000, 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.beans;
15.30 +
15.31 +import java.util.EventListenerProxy;
15.32 +
15.33 +/**
15.34 + * A class which extends the {@code EventListenerProxy}
15.35 + * specifically for adding a {@code VetoableChangeListener}
15.36 + * with a "constrained" property.
15.37 + * Instances of this class can be added
15.38 + * as {@code VetoableChangeListener}s to a bean
15.39 + * which supports firing vetoable change events.
15.40 + * <p>
15.41 + * If the object has a {@code getVetoableChangeListeners} method
15.42 + * then the array returned could be a mixture of {@code VetoableChangeListener}
15.43 + * and {@code VetoableChangeListenerProxy} objects.
15.44 + *
15.45 + * @see java.util.EventListenerProxy
15.46 + * @see VetoableChangeSupport#getVetoableChangeListeners
15.47 + * @since 1.4
15.48 + */
15.49 +public class VetoableChangeListenerProxy
15.50 + extends EventListenerProxy<VetoableChangeListener>
15.51 + implements VetoableChangeListener {
15.52 +
15.53 + private final String propertyName;
15.54 +
15.55 + /**
15.56 + * Constructor which binds the {@code VetoableChangeListener}
15.57 + * to a specific property.
15.58 + *
15.59 + * @param propertyName the name of the property to listen on
15.60 + * @param listener the listener object
15.61 + */
15.62 + public VetoableChangeListenerProxy(String propertyName, VetoableChangeListener listener) {
15.63 + super(listener);
15.64 + this.propertyName = propertyName;
15.65 + }
15.66 +
15.67 + /**
15.68 + * Forwards the property change event to the listener delegate.
15.69 + *
15.70 + * @param event the property change event
15.71 + *
15.72 + * @exception PropertyVetoException if the recipient wishes the property
15.73 + * change to be rolled back
15.74 + */
15.75 + public void vetoableChange(PropertyChangeEvent event) throws PropertyVetoException{
15.76 + getListener().vetoableChange(event);
15.77 + }
15.78 +
15.79 + /**
15.80 + * Returns the name of the named property associated with the listener.
15.81 + *
15.82 + * @return the name of the named property associated with the listener
15.83 + */
15.84 + public String getPropertyName() {
15.85 + return this.propertyName;
15.86 + }
15.87 +}
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/emul/compact/src/main/java/java/beans/VetoableChangeSupport.java Sun Feb 17 17:58:34 2013 +0100
16.3 @@ -0,0 +1,526 @@
16.4 +/*
16.5 + * Copyright (c) 1996, 2011, 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 +package java.beans;
16.29 +
16.30 +import java.io.Serializable;
16.31 +import java.io.ObjectStreamField;
16.32 +import java.io.ObjectOutputStream;
16.33 +import java.io.ObjectInputStream;
16.34 +import java.io.IOException;
16.35 +import java.util.Hashtable;
16.36 +import java.util.Map.Entry;
16.37 +import org.apidesign.bck2brwsr.emul.lang.System;
16.38 +
16.39 +/**
16.40 + * This is a utility class that can be used by beans that support constrained
16.41 + * properties. It manages a list of listeners and dispatches
16.42 + * {@link PropertyChangeEvent}s to them. You can use an instance of this class
16.43 + * as a member field of your bean and delegate these types of work to it.
16.44 + * The {@link VetoableChangeListener} can be registered for all properties
16.45 + * or for a property specified by name.
16.46 + * <p>
16.47 + * Here is an example of {@code VetoableChangeSupport} usage that follows
16.48 + * the rules and recommendations laid out in the JavaBeans™ specification:
16.49 + * <pre>
16.50 + * public class MyBean {
16.51 + * private final VetoableChangeSupport vcs = new VetoableChangeSupport(this);
16.52 + *
16.53 + * public void addVetoableChangeListener(VetoableChangeListener listener) {
16.54 + * this.vcs.addVetoableChangeListener(listener);
16.55 + * }
16.56 + *
16.57 + * public void removeVetoableChangeListener(VetoableChangeListener listener) {
16.58 + * this.vcs.removeVetoableChangeListener(listener);
16.59 + * }
16.60 + *
16.61 + * private String value;
16.62 + *
16.63 + * public String getValue() {
16.64 + * return this.value;
16.65 + * }
16.66 + *
16.67 + * public void setValue(String newValue) throws PropertyVetoException {
16.68 + * String oldValue = this.value;
16.69 + * this.vcs.fireVetoableChange("value", oldValue, newValue);
16.70 + * this.value = newValue;
16.71 + * }
16.72 + *
16.73 + * [...]
16.74 + * }
16.75 + * </pre>
16.76 + * <p>
16.77 + * A {@code VetoableChangeSupport} instance is thread-safe.
16.78 + * <p>
16.79 + * This class is serializable. When it is serialized it will save
16.80 + * (and restore) any listeners that are themselves serializable. Any
16.81 + * non-serializable listeners will be skipped during serialization.
16.82 + *
16.83 + * @see PropertyChangeSupport
16.84 + */
16.85 +public class VetoableChangeSupport implements Serializable {
16.86 + private VetoableChangeListenerMap map = new VetoableChangeListenerMap();
16.87 +
16.88 + /**
16.89 + * Constructs a <code>VetoableChangeSupport</code> object.
16.90 + *
16.91 + * @param sourceBean The bean to be given as the source for any events.
16.92 + */
16.93 + public VetoableChangeSupport(Object sourceBean) {
16.94 + if (sourceBean == null) {
16.95 + throw new NullPointerException();
16.96 + }
16.97 + source = sourceBean;
16.98 + }
16.99 +
16.100 + /**
16.101 + * Add a VetoableChangeListener to the listener list.
16.102 + * The listener is registered for all properties.
16.103 + * The same listener object may be added more than once, and will be called
16.104 + * as many times as it is added.
16.105 + * If <code>listener</code> is null, no exception is thrown and no action
16.106 + * is taken.
16.107 + *
16.108 + * @param listener The VetoableChangeListener to be added
16.109 + */
16.110 + public void addVetoableChangeListener(VetoableChangeListener listener) {
16.111 + if (listener == null) {
16.112 + return;
16.113 + }
16.114 + if (listener instanceof VetoableChangeListenerProxy) {
16.115 + VetoableChangeListenerProxy proxy =
16.116 + (VetoableChangeListenerProxy)listener;
16.117 + // Call two argument add method.
16.118 + addVetoableChangeListener(proxy.getPropertyName(),
16.119 + proxy.getListener());
16.120 + } else {
16.121 + this.map.add(null, listener);
16.122 + }
16.123 + }
16.124 +
16.125 + /**
16.126 + * Remove a VetoableChangeListener from the listener list.
16.127 + * This removes a VetoableChangeListener that was registered
16.128 + * for all properties.
16.129 + * If <code>listener</code> was added more than once to the same event
16.130 + * source, it will be notified one less time after being removed.
16.131 + * If <code>listener</code> is null, or was never added, no exception is
16.132 + * thrown and no action is taken.
16.133 + *
16.134 + * @param listener The VetoableChangeListener to be removed
16.135 + */
16.136 + public void removeVetoableChangeListener(VetoableChangeListener listener) {
16.137 + if (listener == null) {
16.138 + return;
16.139 + }
16.140 + if (listener instanceof VetoableChangeListenerProxy) {
16.141 + VetoableChangeListenerProxy proxy =
16.142 + (VetoableChangeListenerProxy)listener;
16.143 + // Call two argument remove method.
16.144 + removeVetoableChangeListener(proxy.getPropertyName(),
16.145 + proxy.getListener());
16.146 + } else {
16.147 + this.map.remove(null, listener);
16.148 + }
16.149 + }
16.150 +
16.151 + /**
16.152 + * Returns an array of all the listeners that were added to the
16.153 + * VetoableChangeSupport object with addVetoableChangeListener().
16.154 + * <p>
16.155 + * If some listeners have been added with a named property, then
16.156 + * the returned array will be a mixture of VetoableChangeListeners
16.157 + * and <code>VetoableChangeListenerProxy</code>s. If the calling
16.158 + * method is interested in distinguishing the listeners then it must
16.159 + * test each element to see if it's a
16.160 + * <code>VetoableChangeListenerProxy</code>, perform the cast, and examine
16.161 + * the parameter.
16.162 + *
16.163 + * <pre>
16.164 + * VetoableChangeListener[] listeners = bean.getVetoableChangeListeners();
16.165 + * for (int i = 0; i < listeners.length; i++) {
16.166 + * if (listeners[i] instanceof VetoableChangeListenerProxy) {
16.167 + * VetoableChangeListenerProxy proxy =
16.168 + * (VetoableChangeListenerProxy)listeners[i];
16.169 + * if (proxy.getPropertyName().equals("foo")) {
16.170 + * // proxy is a VetoableChangeListener which was associated
16.171 + * // with the property named "foo"
16.172 + * }
16.173 + * }
16.174 + * }
16.175 + *</pre>
16.176 + *
16.177 + * @see VetoableChangeListenerProxy
16.178 + * @return all of the <code>VetoableChangeListeners</code> added or an
16.179 + * empty array if no listeners have been added
16.180 + * @since 1.4
16.181 + */
16.182 + public VetoableChangeListener[] getVetoableChangeListeners(){
16.183 + return this.map.getListeners();
16.184 + }
16.185 +
16.186 + /**
16.187 + * Add a VetoableChangeListener for a specific property. The listener
16.188 + * will be invoked only when a call on fireVetoableChange names that
16.189 + * specific property.
16.190 + * The same listener object may be added more than once. For each
16.191 + * property, the listener will be invoked the number of times it was added
16.192 + * for that property.
16.193 + * If <code>propertyName</code> or <code>listener</code> is null, no
16.194 + * exception is thrown and no action is taken.
16.195 + *
16.196 + * @param propertyName The name of the property to listen on.
16.197 + * @param listener The VetoableChangeListener to be added
16.198 + */
16.199 + public void addVetoableChangeListener(
16.200 + String propertyName,
16.201 + VetoableChangeListener listener) {
16.202 + if (listener == null || propertyName == null) {
16.203 + return;
16.204 + }
16.205 + listener = this.map.extract(listener);
16.206 + if (listener != null) {
16.207 + this.map.add(propertyName, listener);
16.208 + }
16.209 + }
16.210 +
16.211 + /**
16.212 + * Remove a VetoableChangeListener for a specific property.
16.213 + * If <code>listener</code> was added more than once to the same event
16.214 + * source for the specified property, it will be notified one less time
16.215 + * after being removed.
16.216 + * If <code>propertyName</code> is null, no exception is thrown and no
16.217 + * action is taken.
16.218 + * If <code>listener</code> is null, or was never added for the specified
16.219 + * property, no exception is thrown and no action is taken.
16.220 + *
16.221 + * @param propertyName The name of the property that was listened on.
16.222 + * @param listener The VetoableChangeListener to be removed
16.223 + */
16.224 + public void removeVetoableChangeListener(
16.225 + String propertyName,
16.226 + VetoableChangeListener listener) {
16.227 + if (listener == null || propertyName == null) {
16.228 + return;
16.229 + }
16.230 + listener = this.map.extract(listener);
16.231 + if (listener != null) {
16.232 + this.map.remove(propertyName, listener);
16.233 + }
16.234 + }
16.235 +
16.236 + /**
16.237 + * Returns an array of all the listeners which have been associated
16.238 + * with the named property.
16.239 + *
16.240 + * @param propertyName The name of the property being listened to
16.241 + * @return all the <code>VetoableChangeListeners</code> associated with
16.242 + * the named property. If no such listeners have been added,
16.243 + * or if <code>propertyName</code> is null, an empty array is
16.244 + * returned.
16.245 + * @since 1.4
16.246 + */
16.247 + public VetoableChangeListener[] getVetoableChangeListeners(String propertyName) {
16.248 + return this.map.getListeners(propertyName);
16.249 + }
16.250 +
16.251 + /**
16.252 + * Reports a constrained property update to listeners
16.253 + * that have been registered to track updates of
16.254 + * all properties or a property with the specified name.
16.255 + * <p>
16.256 + * Any listener can throw a {@code PropertyVetoException} to veto the update.
16.257 + * If one of the listeners vetoes the update, this method passes
16.258 + * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
16.259 + * to all listeners that already confirmed this update
16.260 + * and throws the {@code PropertyVetoException} again.
16.261 + * <p>
16.262 + * No event is fired if old and new values are equal and non-null.
16.263 + * <p>
16.264 + * This is merely a convenience wrapper around the more general
16.265 + * {@link #fireVetoableChange(PropertyChangeEvent)} method.
16.266 + *
16.267 + * @param propertyName the programmatic name of the property that is about to change
16.268 + * @param oldValue the old value of the property
16.269 + * @param newValue the new value of the property
16.270 + * @throws PropertyVetoException if one of listeners vetoes the property update
16.271 + */
16.272 + public void fireVetoableChange(String propertyName, Object oldValue, Object newValue)
16.273 + throws PropertyVetoException {
16.274 + if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
16.275 + fireVetoableChange(new PropertyChangeEvent(this.source, propertyName, oldValue, newValue));
16.276 + }
16.277 + }
16.278 +
16.279 + /**
16.280 + * Reports an integer constrained property update to listeners
16.281 + * that have been registered to track updates of
16.282 + * all properties or a property with the specified name.
16.283 + * <p>
16.284 + * Any listener can throw a {@code PropertyVetoException} to veto the update.
16.285 + * If one of the listeners vetoes the update, this method passes
16.286 + * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
16.287 + * to all listeners that already confirmed this update
16.288 + * and throws the {@code PropertyVetoException} again.
16.289 + * <p>
16.290 + * No event is fired if old and new values are equal.
16.291 + * <p>
16.292 + * This is merely a convenience wrapper around the more general
16.293 + * {@link #fireVetoableChange(String, Object, Object)} method.
16.294 + *
16.295 + * @param propertyName the programmatic name of the property that is about to change
16.296 + * @param oldValue the old value of the property
16.297 + * @param newValue the new value of the property
16.298 + * @throws PropertyVetoException if one of listeners vetoes the property update
16.299 + */
16.300 + public void fireVetoableChange(String propertyName, int oldValue, int newValue)
16.301 + throws PropertyVetoException {
16.302 + if (oldValue != newValue) {
16.303 + fireVetoableChange(propertyName, Integer.valueOf(oldValue), Integer.valueOf(newValue));
16.304 + }
16.305 + }
16.306 +
16.307 + /**
16.308 + * Reports a boolean constrained property update to listeners
16.309 + * that have been registered to track updates of
16.310 + * all properties or a property with the specified name.
16.311 + * <p>
16.312 + * Any listener can throw a {@code PropertyVetoException} to veto the update.
16.313 + * If one of the listeners vetoes the update, this method passes
16.314 + * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
16.315 + * to all listeners that already confirmed this update
16.316 + * and throws the {@code PropertyVetoException} again.
16.317 + * <p>
16.318 + * No event is fired if old and new values are equal.
16.319 + * <p>
16.320 + * This is merely a convenience wrapper around the more general
16.321 + * {@link #fireVetoableChange(String, Object, Object)} method.
16.322 + *
16.323 + * @param propertyName the programmatic name of the property that is about to change
16.324 + * @param oldValue the old value of the property
16.325 + * @param newValue the new value of the property
16.326 + * @throws PropertyVetoException if one of listeners vetoes the property update
16.327 + */
16.328 + public void fireVetoableChange(String propertyName, boolean oldValue, boolean newValue)
16.329 + throws PropertyVetoException {
16.330 + if (oldValue != newValue) {
16.331 + fireVetoableChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
16.332 + }
16.333 + }
16.334 +
16.335 + /**
16.336 + * Fires a property change event to listeners
16.337 + * that have been registered to track updates of
16.338 + * all properties or a property with the specified name.
16.339 + * <p>
16.340 + * Any listener can throw a {@code PropertyVetoException} to veto the update.
16.341 + * If one of the listeners vetoes the update, this method passes
16.342 + * a new "undo" {@code PropertyChangeEvent} that reverts to the old value
16.343 + * to all listeners that already confirmed this update
16.344 + * and throws the {@code PropertyVetoException} again.
16.345 + * <p>
16.346 + * No event is fired if the given event's old and new values are equal and non-null.
16.347 + *
16.348 + * @param event the {@code PropertyChangeEvent} to be fired
16.349 + * @throws PropertyVetoException if one of listeners vetoes the property update
16.350 + */
16.351 + public void fireVetoableChange(PropertyChangeEvent event)
16.352 + throws PropertyVetoException {
16.353 + Object oldValue = event.getOldValue();
16.354 + Object newValue = event.getNewValue();
16.355 + if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
16.356 + String name = event.getPropertyName();
16.357 +
16.358 + VetoableChangeListener[] common = this.map.get(null);
16.359 + VetoableChangeListener[] named = (name != null)
16.360 + ? this.map.get(name)
16.361 + : null;
16.362 +
16.363 + VetoableChangeListener[] listeners;
16.364 + if (common == null) {
16.365 + listeners = named;
16.366 + }
16.367 + else if (named == null) {
16.368 + listeners = common;
16.369 + }
16.370 + else {
16.371 + listeners = new VetoableChangeListener[common.length + named.length];
16.372 + System.arraycopy(common, 0, listeners, 0, common.length);
16.373 + System.arraycopy(named, 0, listeners, common.length, named.length);
16.374 + }
16.375 + if (listeners != null) {
16.376 + int current = 0;
16.377 + try {
16.378 + while (current < listeners.length) {
16.379 + listeners[current].vetoableChange(event);
16.380 + current++;
16.381 + }
16.382 + }
16.383 + catch (PropertyVetoException veto) {
16.384 + event = new PropertyChangeEvent(this.source, name, newValue, oldValue);
16.385 + for (int i = 0; i < current; i++) {
16.386 + try {
16.387 + listeners[i].vetoableChange(event);
16.388 + }
16.389 + catch (PropertyVetoException exception) {
16.390 + // ignore exceptions that occur during rolling back
16.391 + }
16.392 + }
16.393 + throw veto; // rethrow the veto exception
16.394 + }
16.395 + }
16.396 + }
16.397 + }
16.398 +
16.399 + /**
16.400 + * Check if there are any listeners for a specific property, including
16.401 + * those registered on all properties. If <code>propertyName</code>
16.402 + * is null, only check for listeners registered on all properties.
16.403 + *
16.404 + * @param propertyName the property name.
16.405 + * @return true if there are one or more listeners for the given property
16.406 + */
16.407 + public boolean hasListeners(String propertyName) {
16.408 + return this.map.hasListeners(propertyName);
16.409 + }
16.410 +
16.411 + /**
16.412 + * @serialData Null terminated list of <code>VetoableChangeListeners</code>.
16.413 + * <p>
16.414 + * At serialization time we skip non-serializable listeners and
16.415 + * only serialize the serializable listeners.
16.416 + */
16.417 + private void writeObject(ObjectOutputStream s) throws IOException {
16.418 + Hashtable<String, VetoableChangeSupport> children = null;
16.419 + VetoableChangeListener[] listeners = null;
16.420 + synchronized (this.map) {
16.421 + for (Entry<String, VetoableChangeListener[]> entry : this.map.getEntries()) {
16.422 + String property = entry.getKey();
16.423 + if (property == null) {
16.424 + listeners = entry.getValue();
16.425 + } else {
16.426 + if (children == null) {
16.427 + children = new Hashtable<String, VetoableChangeSupport>();
16.428 + }
16.429 + VetoableChangeSupport vcs = new VetoableChangeSupport(this.source);
16.430 + vcs.map.set(null, entry.getValue());
16.431 + children.put(property, vcs);
16.432 + }
16.433 + }
16.434 + }
16.435 + ObjectOutputStream.PutField fields = s.putFields();
16.436 + fields.put("children", children);
16.437 + fields.put("source", this.source);
16.438 + fields.put("vetoableChangeSupportSerializedDataVersion", 2);
16.439 + s.writeFields();
16.440 +
16.441 + if (listeners != null) {
16.442 + for (VetoableChangeListener l : listeners) {
16.443 + if (l instanceof Serializable) {
16.444 + s.writeObject(l);
16.445 + }
16.446 + }
16.447 + }
16.448 + s.writeObject(null);
16.449 + }
16.450 +
16.451 + private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
16.452 + this.map = new VetoableChangeListenerMap();
16.453 +
16.454 + ObjectInputStream.GetField fields = s.readFields();
16.455 +
16.456 + Hashtable<String, VetoableChangeSupport> children = (Hashtable<String, VetoableChangeSupport>) fields.get("children", null);
16.457 + this.source = fields.get("source", null);
16.458 + fields.get("vetoableChangeSupportSerializedDataVersion", 2);
16.459 +
16.460 + Object listenerOrNull;
16.461 + while (null != (listenerOrNull = s.readObject())) {
16.462 + this.map.add(null, (VetoableChangeListener)listenerOrNull);
16.463 + }
16.464 + if (children != null) {
16.465 + for (Entry<String, VetoableChangeSupport> entry : children.entrySet()) {
16.466 + for (VetoableChangeListener listener : entry.getValue().getVetoableChangeListeners()) {
16.467 + this.map.add(entry.getKey(), listener);
16.468 + }
16.469 + }
16.470 + }
16.471 + }
16.472 +
16.473 + /**
16.474 + * The object to be provided as the "source" for any generated events.
16.475 + */
16.476 + private Object source;
16.477 +
16.478 + /**
16.479 + * @serialField children Hashtable
16.480 + * @serialField source Object
16.481 + * @serialField vetoableChangeSupportSerializedDataVersion int
16.482 + */
16.483 + private static final ObjectStreamField[] serialPersistentFields = {
16.484 + new ObjectStreamField("children", Hashtable.class),
16.485 + new ObjectStreamField("source", Object.class),
16.486 + new ObjectStreamField("vetoableChangeSupportSerializedDataVersion", Integer.TYPE)
16.487 + };
16.488 +
16.489 + /**
16.490 + * Serialization version ID, so we're compatible with JDK 1.1
16.491 + */
16.492 + static final long serialVersionUID = -5090210921595982017L;
16.493 +
16.494 + /**
16.495 + * This is a {@link ChangeListenerMap ChangeListenerMap} implementation
16.496 + * that works with {@link VetoableChangeListener VetoableChangeListener} objects.
16.497 + */
16.498 + private static final class VetoableChangeListenerMap extends ChangeListenerMap<VetoableChangeListener> {
16.499 + private static final VetoableChangeListener[] EMPTY = {};
16.500 +
16.501 + /**
16.502 + * Creates an array of {@link VetoableChangeListener VetoableChangeListener} objects.
16.503 + * This method uses the same instance of the empty array
16.504 + * when {@code length} equals {@code 0}.
16.505 + *
16.506 + * @param length the array length
16.507 + * @return an array with specified length
16.508 + */
16.509 + @Override
16.510 + protected VetoableChangeListener[] newArray(int length) {
16.511 + return (0 < length)
16.512 + ? new VetoableChangeListener[length]
16.513 + : EMPTY;
16.514 + }
16.515 +
16.516 + /**
16.517 + * Creates a {@link VetoableChangeListenerProxy VetoableChangeListenerProxy}
16.518 + * object for the specified property.
16.519 + *
16.520 + * @param name the name of the property to listen on
16.521 + * @param listener the listener to process events
16.522 + * @return a {@code VetoableChangeListenerProxy} object
16.523 + */
16.524 + @Override
16.525 + protected VetoableChangeListener newProxy(String name, VetoableChangeListener listener) {
16.526 + return new VetoableChangeListenerProxy(name, listener);
16.527 + }
16.528 + }
16.529 +}
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/emul/compact/src/main/java/java/io/Bits.java Sun Feb 17 17:58:34 2013 +0100
17.3 @@ -0,0 +1,123 @@
17.4 +/*
17.5 + * Copyright (c) 2001, 2010, 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 + * Utility methods for packing/unpacking primitive values in/out of byte arrays
17.33 + * using big-endian byte ordering.
17.34 + */
17.35 +class Bits {
17.36 +
17.37 + /*
17.38 + * Methods for unpacking primitive values from byte arrays starting at
17.39 + * given offsets.
17.40 + */
17.41 +
17.42 + static boolean getBoolean(byte[] b, int off) {
17.43 + return b[off] != 0;
17.44 + }
17.45 +
17.46 + static char getChar(byte[] b, int off) {
17.47 + return (char) ((b[off + 1] & 0xFF) +
17.48 + (b[off] << 8));
17.49 + }
17.50 +
17.51 + static short getShort(byte[] b, int off) {
17.52 + return (short) ((b[off + 1] & 0xFF) +
17.53 + (b[off] << 8));
17.54 + }
17.55 +
17.56 + static int getInt(byte[] b, int off) {
17.57 + return ((b[off + 3] & 0xFF) ) +
17.58 + ((b[off + 2] & 0xFF) << 8) +
17.59 + ((b[off + 1] & 0xFF) << 16) +
17.60 + ((b[off ] ) << 24);
17.61 + }
17.62 +
17.63 + static float getFloat(byte[] b, int off) {
17.64 + return Float.intBitsToFloat(getInt(b, off));
17.65 + }
17.66 +
17.67 + static long getLong(byte[] b, int off) {
17.68 + return ((b[off + 7] & 0xFFL) ) +
17.69 + ((b[off + 6] & 0xFFL) << 8) +
17.70 + ((b[off + 5] & 0xFFL) << 16) +
17.71 + ((b[off + 4] & 0xFFL) << 24) +
17.72 + ((b[off + 3] & 0xFFL) << 32) +
17.73 + ((b[off + 2] & 0xFFL) << 40) +
17.74 + ((b[off + 1] & 0xFFL) << 48) +
17.75 + (((long) b[off]) << 56);
17.76 + }
17.77 +
17.78 + static double getDouble(byte[] b, int off) {
17.79 + return Double.longBitsToDouble(getLong(b, off));
17.80 + }
17.81 +
17.82 + /*
17.83 + * Methods for packing primitive values into byte arrays starting at given
17.84 + * offsets.
17.85 + */
17.86 +
17.87 + static void putBoolean(byte[] b, int off, boolean val) {
17.88 + b[off] = (byte) (val ? 1 : 0);
17.89 + }
17.90 +
17.91 + static void putChar(byte[] b, int off, char val) {
17.92 + b[off + 1] = (byte) (val );
17.93 + b[off ] = (byte) (val >>> 8);
17.94 + }
17.95 +
17.96 + static void putShort(byte[] b, int off, short val) {
17.97 + b[off + 1] = (byte) (val );
17.98 + b[off ] = (byte) (val >>> 8);
17.99 + }
17.100 +
17.101 + static void putInt(byte[] b, int off, int val) {
17.102 + b[off + 3] = (byte) (val );
17.103 + b[off + 2] = (byte) (val >>> 8);
17.104 + b[off + 1] = (byte) (val >>> 16);
17.105 + b[off ] = (byte) (val >>> 24);
17.106 + }
17.107 +
17.108 + static void putFloat(byte[] b, int off, float val) {
17.109 + putInt(b, off, Float.floatToIntBits(val));
17.110 + }
17.111 +
17.112 + static void putLong(byte[] b, int off, long val) {
17.113 + b[off + 7] = (byte) (val );
17.114 + b[off + 6] = (byte) (val >>> 8);
17.115 + b[off + 5] = (byte) (val >>> 16);
17.116 + b[off + 4] = (byte) (val >>> 24);
17.117 + b[off + 3] = (byte) (val >>> 32);
17.118 + b[off + 2] = (byte) (val >>> 40);
17.119 + b[off + 1] = (byte) (val >>> 48);
17.120 + b[off ] = (byte) (val >>> 56);
17.121 + }
17.122 +
17.123 + static void putDouble(byte[] b, int off, double val) {
17.124 + putLong(b, off, Double.doubleToLongBits(val));
17.125 + }
17.126 +}
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
18.2 +++ b/emul/compact/src/main/java/java/io/BufferedOutputStream.java Sun Feb 17 17:58:34 2013 +0100
18.3 @@ -0,0 +1,143 @@
18.4 +/*
18.5 + * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
18.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
18.7 + *
18.8 + * This code is free software; you can redistribute it and/or modify it
18.9 + * under the terms of the GNU General Public License version 2 only, as
18.10 + * published by the Free Software Foundation. Oracle designates this
18.11 + * particular file as subject to the "Classpath" exception as provided
18.12 + * by Oracle in the LICENSE file that accompanied this code.
18.13 + *
18.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
18.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18.17 + * version 2 for more details (a copy is included in the LICENSE file that
18.18 + * accompanied this code).
18.19 + *
18.20 + * You should have received a copy of the GNU General Public License version
18.21 + * 2 along with this work; if not, write to the Free Software Foundation,
18.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18.23 + *
18.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
18.25 + * or visit www.oracle.com if you need additional information or have any
18.26 + * questions.
18.27 + */
18.28 +
18.29 +package java.io;
18.30 +
18.31 +/**
18.32 + * The class implements a buffered output stream. By setting up such
18.33 + * an output stream, an application can write bytes to the underlying
18.34 + * output stream without necessarily causing a call to the underlying
18.35 + * system for each byte written.
18.36 + *
18.37 + * @author Arthur van Hoff
18.38 + * @since JDK1.0
18.39 + */
18.40 +public
18.41 +class BufferedOutputStream extends FilterOutputStream {
18.42 + /**
18.43 + * The internal buffer where data is stored.
18.44 + */
18.45 + protected byte buf[];
18.46 +
18.47 + /**
18.48 + * The number of valid bytes in the buffer. This value is always
18.49 + * in the range <tt>0</tt> through <tt>buf.length</tt>; elements
18.50 + * <tt>buf[0]</tt> through <tt>buf[count-1]</tt> contain valid
18.51 + * byte data.
18.52 + */
18.53 + protected int count;
18.54 +
18.55 + /**
18.56 + * Creates a new buffered output stream to write data to the
18.57 + * specified underlying output stream.
18.58 + *
18.59 + * @param out the underlying output stream.
18.60 + */
18.61 + public BufferedOutputStream(OutputStream out) {
18.62 + this(out, 8192);
18.63 + }
18.64 +
18.65 + /**
18.66 + * Creates a new buffered output stream to write data to the
18.67 + * specified underlying output stream with the specified buffer
18.68 + * size.
18.69 + *
18.70 + * @param out the underlying output stream.
18.71 + * @param size the buffer size.
18.72 + * @exception IllegalArgumentException if size <= 0.
18.73 + */
18.74 + public BufferedOutputStream(OutputStream out, int size) {
18.75 + super(out);
18.76 + if (size <= 0) {
18.77 + throw new IllegalArgumentException("Buffer size <= 0");
18.78 + }
18.79 + buf = new byte[size];
18.80 + }
18.81 +
18.82 + /** Flush the internal buffer */
18.83 + private void flushBuffer() throws IOException {
18.84 + if (count > 0) {
18.85 + out.write(buf, 0, count);
18.86 + count = 0;
18.87 + }
18.88 + }
18.89 +
18.90 + /**
18.91 + * Writes the specified byte to this buffered output stream.
18.92 + *
18.93 + * @param b the byte to be written.
18.94 + * @exception IOException if an I/O error occurs.
18.95 + */
18.96 + public synchronized void write(int b) throws IOException {
18.97 + if (count >= buf.length) {
18.98 + flushBuffer();
18.99 + }
18.100 + buf[count++] = (byte)b;
18.101 + }
18.102 +
18.103 + /**
18.104 + * Writes <code>len</code> bytes from the specified byte array
18.105 + * starting at offset <code>off</code> to this buffered output stream.
18.106 + *
18.107 + * <p> Ordinarily this method stores bytes from the given array into this
18.108 + * stream's buffer, flushing the buffer to the underlying output stream as
18.109 + * needed. If the requested length is at least as large as this stream's
18.110 + * buffer, however, then this method will flush the buffer and write the
18.111 + * bytes directly to the underlying output stream. Thus redundant
18.112 + * <code>BufferedOutputStream</code>s will not copy data unnecessarily.
18.113 + *
18.114 + * @param b the data.
18.115 + * @param off the start offset in the data.
18.116 + * @param len the number of bytes to write.
18.117 + * @exception IOException if an I/O error occurs.
18.118 + */
18.119 + public synchronized void write(byte b[], int off, int len) throws IOException {
18.120 + if (len >= buf.length) {
18.121 + /* If the request length exceeds the size of the output buffer,
18.122 + flush the output buffer and then write the data directly.
18.123 + In this way buffered streams will cascade harmlessly. */
18.124 + flushBuffer();
18.125 + out.write(b, off, len);
18.126 + return;
18.127 + }
18.128 + if (len > buf.length - count) {
18.129 + flushBuffer();
18.130 + }
18.131 + System.arraycopy(b, off, buf, count, len);
18.132 + count += len;
18.133 + }
18.134 +
18.135 + /**
18.136 + * Flushes this buffered output stream. This forces any buffered
18.137 + * output bytes to be written out to the underlying output stream.
18.138 + *
18.139 + * @exception IOException if an I/O error occurs.
18.140 + * @see java.io.FilterOutputStream#out
18.141 + */
18.142 + public synchronized void flush() throws IOException {
18.143 + flushBuffer();
18.144 + out.flush();
18.145 + }
18.146 +}
19.1 --- a/emul/compact/src/main/java/java/io/BufferedReader.java Fri Jan 25 15:08:24 2013 +0100
19.2 +++ b/emul/compact/src/main/java/java/io/BufferedReader.java Sun Feb 17 17:58:34 2013 +0100
19.3 @@ -25,7 +25,6 @@
19.4
19.5 package java.io;
19.6
19.7 -import org.apidesign.bck2brwsr.emul.lang.System;
19.8
19.9
19.10 /**
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
20.2 +++ b/emul/compact/src/main/java/java/io/ByteArrayOutputStream.java Sun Feb 17 17:58:34 2013 +0100
20.3 @@ -0,0 +1,272 @@
20.4 +/*
20.5 + * Copyright (c) 1994, 2010, 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 +import java.util.Arrays;
20.32 +
20.33 +/**
20.34 + * This class implements an output stream in which the data is
20.35 + * written into a byte array. The buffer automatically grows as data
20.36 + * is written to it.
20.37 + * The data can be retrieved using <code>toByteArray()</code> and
20.38 + * <code>toString()</code>.
20.39 + * <p>
20.40 + * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in
20.41 + * this class can be called after the stream has been closed without
20.42 + * generating an <tt>IOException</tt>.
20.43 + *
20.44 + * @author Arthur van Hoff
20.45 + * @since JDK1.0
20.46 + */
20.47 +
20.48 +public class ByteArrayOutputStream extends OutputStream {
20.49 +
20.50 + /**
20.51 + * The buffer where data is stored.
20.52 + */
20.53 + protected byte buf[];
20.54 +
20.55 + /**
20.56 + * The number of valid bytes in the buffer.
20.57 + */
20.58 + protected int count;
20.59 +
20.60 + /**
20.61 + * Creates a new byte array output stream. The buffer capacity is
20.62 + * initially 32 bytes, though its size increases if necessary.
20.63 + */
20.64 + public ByteArrayOutputStream() {
20.65 + this(32);
20.66 + }
20.67 +
20.68 + /**
20.69 + * Creates a new byte array output stream, with a buffer capacity of
20.70 + * the specified size, in bytes.
20.71 + *
20.72 + * @param size the initial size.
20.73 + * @exception IllegalArgumentException if size is negative.
20.74 + */
20.75 + public ByteArrayOutputStream(int size) {
20.76 + if (size < 0) {
20.77 + throw new IllegalArgumentException("Negative initial size: "
20.78 + + size);
20.79 + }
20.80 + buf = new byte[size];
20.81 + }
20.82 +
20.83 + /**
20.84 + * Increases the capacity if necessary to ensure that it can hold
20.85 + * at least the number of elements specified by the minimum
20.86 + * capacity argument.
20.87 + *
20.88 + * @param minCapacity the desired minimum capacity
20.89 + * @throws OutOfMemoryError if {@code minCapacity < 0}. This is
20.90 + * interpreted as a request for the unsatisfiably large capacity
20.91 + * {@code (long) Integer.MAX_VALUE + (minCapacity - Integer.MAX_VALUE)}.
20.92 + */
20.93 + private void ensureCapacity(int minCapacity) {
20.94 + // overflow-conscious code
20.95 + if (minCapacity - buf.length > 0)
20.96 + grow(minCapacity);
20.97 + }
20.98 +
20.99 + /**
20.100 + * Increases the capacity to ensure that it can hold at least the
20.101 + * number of elements specified by the minimum capacity argument.
20.102 + *
20.103 + * @param minCapacity the desired minimum capacity
20.104 + */
20.105 + private void grow(int minCapacity) {
20.106 + // overflow-conscious code
20.107 + int oldCapacity = buf.length;
20.108 + int newCapacity = oldCapacity << 1;
20.109 + if (newCapacity - minCapacity < 0)
20.110 + newCapacity = minCapacity;
20.111 + if (newCapacity < 0) {
20.112 + if (minCapacity < 0) // overflow
20.113 + throw new OutOfMemoryError();
20.114 + newCapacity = Integer.MAX_VALUE;
20.115 + }
20.116 + buf = Arrays.copyOf(buf, newCapacity);
20.117 + }
20.118 +
20.119 + /**
20.120 + * Writes the specified byte to this byte array output stream.
20.121 + *
20.122 + * @param b the byte to be written.
20.123 + */
20.124 + public synchronized void write(int b) {
20.125 + ensureCapacity(count + 1);
20.126 + buf[count] = (byte) b;
20.127 + count += 1;
20.128 + }
20.129 +
20.130 + /**
20.131 + * Writes <code>len</code> bytes from the specified byte array
20.132 + * starting at offset <code>off</code> to this byte array output stream.
20.133 + *
20.134 + * @param b the data.
20.135 + * @param off the start offset in the data.
20.136 + * @param len the number of bytes to write.
20.137 + */
20.138 + public synchronized void write(byte b[], int off, int len) {
20.139 + if ((off < 0) || (off > b.length) || (len < 0) ||
20.140 + ((off + len) - b.length > 0)) {
20.141 + throw new IndexOutOfBoundsException();
20.142 + }
20.143 + ensureCapacity(count + len);
20.144 + System.arraycopy(b, off, buf, count, len);
20.145 + count += len;
20.146 + }
20.147 +
20.148 + /**
20.149 + * Writes the complete contents of this byte array output stream to
20.150 + * the specified output stream argument, as if by calling the output
20.151 + * stream's write method using <code>out.write(buf, 0, count)</code>.
20.152 + *
20.153 + * @param out the output stream to which to write the data.
20.154 + * @exception IOException if an I/O error occurs.
20.155 + */
20.156 + public synchronized void writeTo(OutputStream out) throws IOException {
20.157 + out.write(buf, 0, count);
20.158 + }
20.159 +
20.160 + /**
20.161 + * Resets the <code>count</code> field of this byte array output
20.162 + * stream to zero, so that all currently accumulated output in the
20.163 + * output stream is discarded. The output stream can be used again,
20.164 + * reusing the already allocated buffer space.
20.165 + *
20.166 + * @see java.io.ByteArrayInputStream#count
20.167 + */
20.168 + public synchronized void reset() {
20.169 + count = 0;
20.170 + }
20.171 +
20.172 + /**
20.173 + * Creates a newly allocated byte array. Its size is the current
20.174 + * size of this output stream and the valid contents of the buffer
20.175 + * have been copied into it.
20.176 + *
20.177 + * @return the current contents of this output stream, as a byte array.
20.178 + * @see java.io.ByteArrayOutputStream#size()
20.179 + */
20.180 + public synchronized byte toByteArray()[] {
20.181 + return Arrays.copyOf(buf, count);
20.182 + }
20.183 +
20.184 + /**
20.185 + * Returns the current size of the buffer.
20.186 + *
20.187 + * @return the value of the <code>count</code> field, which is the number
20.188 + * of valid bytes in this output stream.
20.189 + * @see java.io.ByteArrayOutputStream#count
20.190 + */
20.191 + public synchronized int size() {
20.192 + return count;
20.193 + }
20.194 +
20.195 + /**
20.196 + * Converts the buffer's contents into a string decoding bytes using the
20.197 + * platform's default character set. The length of the new <tt>String</tt>
20.198 + * is a function of the character set, and hence may not be equal to the
20.199 + * size of the buffer.
20.200 + *
20.201 + * <p> This method always replaces malformed-input and unmappable-character
20.202 + * sequences with the default replacement string for the platform's
20.203 + * default character set. The {@linkplain java.nio.charset.CharsetDecoder}
20.204 + * class should be used when more control over the decoding process is
20.205 + * required.
20.206 + *
20.207 + * @return String decoded from the buffer's contents.
20.208 + * @since JDK1.1
20.209 + */
20.210 + public synchronized String toString() {
20.211 + return new String(buf, 0, count);
20.212 + }
20.213 +
20.214 + /**
20.215 + * Converts the buffer's contents into a string by decoding the bytes using
20.216 + * the specified {@link java.nio.charset.Charset charsetName}. The length of
20.217 + * the new <tt>String</tt> is a function of the charset, and hence may not be
20.218 + * equal to the length of the byte array.
20.219 + *
20.220 + * <p> This method always replaces malformed-input and unmappable-character
20.221 + * sequences with this charset's default replacement string. The {@link
20.222 + * java.nio.charset.CharsetDecoder} class should be used when more control
20.223 + * over the decoding process is required.
20.224 + *
20.225 + * @param charsetName the name of a supported
20.226 + * {@linkplain java.nio.charset.Charset </code>charset<code>}
20.227 + * @return String decoded from the buffer's contents.
20.228 + * @exception UnsupportedEncodingException
20.229 + * If the named charset is not supported
20.230 + * @since JDK1.1
20.231 + */
20.232 + public synchronized String toString(String charsetName)
20.233 + throws UnsupportedEncodingException
20.234 + {
20.235 + return new String(buf, 0, count, charsetName);
20.236 + }
20.237 +
20.238 + /**
20.239 + * Creates a newly allocated string. Its size is the current size of
20.240 + * the output stream and the valid contents of the buffer have been
20.241 + * copied into it. Each character <i>c</i> in the resulting string is
20.242 + * constructed from the corresponding element <i>b</i> in the byte
20.243 + * array such that:
20.244 + * <blockquote><pre>
20.245 + * c == (char)(((hibyte & 0xff) << 8) | (b & 0xff))
20.246 + * </pre></blockquote>
20.247 + *
20.248 + * @deprecated This method does not properly convert bytes into characters.
20.249 + * As of JDK 1.1, the preferred way to do this is via the
20.250 + * <code>toString(String enc)</code> method, which takes an encoding-name
20.251 + * argument, or the <code>toString()</code> method, which uses the
20.252 + * platform's default character encoding.
20.253 + *
20.254 + * @param hibyte the high byte of each resulting Unicode character.
20.255 + * @return the current contents of the output stream, as a string.
20.256 + * @see java.io.ByteArrayOutputStream#size()
20.257 + * @see java.io.ByteArrayOutputStream#toString(String)
20.258 + * @see java.io.ByteArrayOutputStream#toString()
20.259 + */
20.260 + @Deprecated
20.261 + public synchronized String toString(int hibyte) {
20.262 + return new String(buf, hibyte, 0, count);
20.263 + }
20.264 +
20.265 + /**
20.266 + * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in
20.267 + * this class can be called after the stream has been closed without
20.268 + * generating an <tt>IOException</tt>.
20.269 + * <p>
20.270 + *
20.271 + */
20.272 + public void close() throws IOException {
20.273 + }
20.274 +
20.275 +}
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/emul/compact/src/main/java/java/io/DataOutput.java Sun Feb 17 17:58:34 2013 +0100
21.3 @@ -0,0 +1,354 @@
21.4 +/*
21.5 + * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved.
21.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
21.7 + *
21.8 + * This code is free software; you can redistribute it and/or modify it
21.9 + * under the terms of the GNU General Public License version 2 only, as
21.10 + * published by the Free Software Foundation. Oracle designates this
21.11 + * particular file as subject to the "Classpath" exception as provided
21.12 + * by Oracle in the LICENSE file that accompanied this code.
21.13 + *
21.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
21.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21.17 + * version 2 for more details (a copy is included in the LICENSE file that
21.18 + * accompanied this code).
21.19 + *
21.20 + * You should have received a copy of the GNU General Public License version
21.21 + * 2 along with this work; if not, write to the Free Software Foundation,
21.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21.23 + *
21.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21.25 + * or visit www.oracle.com if you need additional information or have any
21.26 + * questions.
21.27 + */
21.28 +
21.29 +package java.io;
21.30 +
21.31 +/**
21.32 + * The <code>DataOutput</code> interface provides
21.33 + * for converting data from any of the Java
21.34 + * primitive types to a series of bytes and
21.35 + * writing these bytes to a binary stream.
21.36 + * There is also a facility for converting
21.37 + * a <code>String</code> into
21.38 + * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
21.39 + * format and writing the resulting series
21.40 + * of bytes.
21.41 + * <p>
21.42 + * For all the methods in this interface that
21.43 + * write bytes, it is generally true that if
21.44 + * a byte cannot be written for any reason,
21.45 + * an <code>IOException</code> is thrown.
21.46 + *
21.47 + * @author Frank Yellin
21.48 + * @see java.io.DataInput
21.49 + * @see java.io.DataOutputStream
21.50 + * @since JDK1.0
21.51 + */
21.52 +public
21.53 +interface DataOutput {
21.54 + /**
21.55 + * Writes to the output stream the eight
21.56 + * low-order bits of the argument <code>b</code>.
21.57 + * The 24 high-order bits of <code>b</code>
21.58 + * are ignored.
21.59 + *
21.60 + * @param b the byte to be written.
21.61 + * @throws IOException if an I/O error occurs.
21.62 + */
21.63 + void write(int b) throws IOException;
21.64 +
21.65 + /**
21.66 + * Writes to the output stream all the bytes in array <code>b</code>.
21.67 + * If <code>b</code> is <code>null</code>,
21.68 + * a <code>NullPointerException</code> is thrown.
21.69 + * If <code>b.length</code> is zero, then
21.70 + * no bytes are written. Otherwise, the byte
21.71 + * <code>b[0]</code> is written first, then
21.72 + * <code>b[1]</code>, and so on; the last byte
21.73 + * written is <code>b[b.length-1]</code>.
21.74 + *
21.75 + * @param b the data.
21.76 + * @throws IOException if an I/O error occurs.
21.77 + */
21.78 + void write(byte b[]) throws IOException;
21.79 +
21.80 + /**
21.81 + * Writes <code>len</code> bytes from array
21.82 + * <code>b</code>, in order, to
21.83 + * the output stream. If <code>b</code>
21.84 + * is <code>null</code>, a <code>NullPointerException</code>
21.85 + * is thrown. If <code>off</code> is negative,
21.86 + * or <code>len</code> is negative, or <code>off+len</code>
21.87 + * is greater than the length of the array
21.88 + * <code>b</code>, then an <code>IndexOutOfBoundsException</code>
21.89 + * is thrown. If <code>len</code> is zero,
21.90 + * then no bytes are written. Otherwise, the
21.91 + * byte <code>b[off]</code> is written first,
21.92 + * then <code>b[off+1]</code>, and so on; the
21.93 + * last byte written is <code>b[off+len-1]</code>.
21.94 + *
21.95 + * @param b the data.
21.96 + * @param off the start offset in the data.
21.97 + * @param len the number of bytes to write.
21.98 + * @throws IOException if an I/O error occurs.
21.99 + */
21.100 + void write(byte b[], int off, int len) throws IOException;
21.101 +
21.102 + /**
21.103 + * Writes a <code>boolean</code> value to this output stream.
21.104 + * If the argument <code>v</code>
21.105 + * is <code>true</code>, the value <code>(byte)1</code>
21.106 + * is written; if <code>v</code> is <code>false</code>,
21.107 + * the value <code>(byte)0</code> is written.
21.108 + * The byte written by this method may
21.109 + * be read by the <code>readBoolean</code>
21.110 + * method of interface <code>DataInput</code>,
21.111 + * which will then return a <code>boolean</code>
21.112 + * equal to <code>v</code>.
21.113 + *
21.114 + * @param v the boolean to be written.
21.115 + * @throws IOException if an I/O error occurs.
21.116 + */
21.117 + void writeBoolean(boolean v) throws IOException;
21.118 +
21.119 + /**
21.120 + * Writes to the output stream the eight low-
21.121 + * order bits of the argument <code>v</code>.
21.122 + * The 24 high-order bits of <code>v</code>
21.123 + * are ignored. (This means that <code>writeByte</code>
21.124 + * does exactly the same thing as <code>write</code>
21.125 + * for an integer argument.) The byte written
21.126 + * by this method may be read by the <code>readByte</code>
21.127 + * method of interface <code>DataInput</code>,
21.128 + * which will then return a <code>byte</code>
21.129 + * equal to <code>(byte)v</code>.
21.130 + *
21.131 + * @param v the byte value to be written.
21.132 + * @throws IOException if an I/O error occurs.
21.133 + */
21.134 + void writeByte(int v) throws IOException;
21.135 +
21.136 + /**
21.137 + * Writes two bytes to the output
21.138 + * stream to represent the value of the argument.
21.139 + * The byte values to be written, in the order
21.140 + * shown, are: <p>
21.141 + * <pre><code>
21.142 + * (byte)(0xff & (v >> 8))
21.143 + * (byte)(0xff & v)
21.144 + * </code> </pre> <p>
21.145 + * The bytes written by this method may be
21.146 + * read by the <code>readShort</code> method
21.147 + * of interface <code>DataInput</code> , which
21.148 + * will then return a <code>short</code> equal
21.149 + * to <code>(short)v</code>.
21.150 + *
21.151 + * @param v the <code>short</code> value to be written.
21.152 + * @throws IOException if an I/O error occurs.
21.153 + */
21.154 + void writeShort(int v) throws IOException;
21.155 +
21.156 + /**
21.157 + * Writes a <code>char</code> value, which
21.158 + * is comprised of two bytes, to the
21.159 + * output stream.
21.160 + * The byte values to be written, in the order
21.161 + * shown, are:
21.162 + * <p><pre><code>
21.163 + * (byte)(0xff & (v >> 8))
21.164 + * (byte)(0xff & v)
21.165 + * </code></pre><p>
21.166 + * The bytes written by this method may be
21.167 + * read by the <code>readChar</code> method
21.168 + * of interface <code>DataInput</code> , which
21.169 + * will then return a <code>char</code> equal
21.170 + * to <code>(char)v</code>.
21.171 + *
21.172 + * @param v the <code>char</code> value to be written.
21.173 + * @throws IOException if an I/O error occurs.
21.174 + */
21.175 + void writeChar(int v) throws IOException;
21.176 +
21.177 + /**
21.178 + * Writes an <code>int</code> value, which is
21.179 + * comprised of four bytes, to the output stream.
21.180 + * The byte values to be written, in the order
21.181 + * shown, are:
21.182 + * <p><pre><code>
21.183 + * (byte)(0xff & (v >> 24))
21.184 + * (byte)(0xff & (v >> 16))
21.185 + * (byte)(0xff & (v >>    8))
21.186 + * (byte)(0xff & v)
21.187 + * </code></pre><p>
21.188 + * The bytes written by this method may be read
21.189 + * by the <code>readInt</code> method of interface
21.190 + * <code>DataInput</code> , which will then
21.191 + * return an <code>int</code> equal to <code>v</code>.
21.192 + *
21.193 + * @param v the <code>int</code> value to be written.
21.194 + * @throws IOException if an I/O error occurs.
21.195 + */
21.196 + void writeInt(int v) throws IOException;
21.197 +
21.198 + /**
21.199 + * Writes a <code>long</code> value, which is
21.200 + * comprised of eight bytes, to the output stream.
21.201 + * The byte values to be written, in the order
21.202 + * shown, are:
21.203 + * <p><pre><code>
21.204 + * (byte)(0xff & (v >> 56))
21.205 + * (byte)(0xff & (v >> 48))
21.206 + * (byte)(0xff & (v >> 40))
21.207 + * (byte)(0xff & (v >> 32))
21.208 + * (byte)(0xff & (v >> 24))
21.209 + * (byte)(0xff & (v >> 16))
21.210 + * (byte)(0xff & (v >> 8))
21.211 + * (byte)(0xff & v)
21.212 + * </code></pre><p>
21.213 + * The bytes written by this method may be
21.214 + * read by the <code>readLong</code> method
21.215 + * of interface <code>DataInput</code> , which
21.216 + * will then return a <code>long</code> equal
21.217 + * to <code>v</code>.
21.218 + *
21.219 + * @param v the <code>long</code> value to be written.
21.220 + * @throws IOException if an I/O error occurs.
21.221 + */
21.222 + void writeLong(long v) throws IOException;
21.223 +
21.224 + /**
21.225 + * Writes a <code>float</code> value,
21.226 + * which is comprised of four bytes, to the output stream.
21.227 + * It does this as if it first converts this
21.228 + * <code>float</code> value to an <code>int</code>
21.229 + * in exactly the manner of the <code>Float.floatToIntBits</code>
21.230 + * method and then writes the <code>int</code>
21.231 + * value in exactly the manner of the <code>writeInt</code>
21.232 + * method. The bytes written by this method
21.233 + * may be read by the <code>readFloat</code>
21.234 + * method of interface <code>DataInput</code>,
21.235 + * which will then return a <code>float</code>
21.236 + * equal to <code>v</code>.
21.237 + *
21.238 + * @param v the <code>float</code> value to be written.
21.239 + * @throws IOException if an I/O error occurs.
21.240 + */
21.241 + void writeFloat(float v) throws IOException;
21.242 +
21.243 + /**
21.244 + * Writes a <code>double</code> value,
21.245 + * which is comprised of eight bytes, to the output stream.
21.246 + * It does this as if it first converts this
21.247 + * <code>double</code> value to a <code>long</code>
21.248 + * in exactly the manner of the <code>Double.doubleToLongBits</code>
21.249 + * method and then writes the <code>long</code>
21.250 + * value in exactly the manner of the <code>writeLong</code>
21.251 + * method. The bytes written by this method
21.252 + * may be read by the <code>readDouble</code>
21.253 + * method of interface <code>DataInput</code>,
21.254 + * which will then return a <code>double</code>
21.255 + * equal to <code>v</code>.
21.256 + *
21.257 + * @param v the <code>double</code> value to be written.
21.258 + * @throws IOException if an I/O error occurs.
21.259 + */
21.260 + void writeDouble(double v) throws IOException;
21.261 +
21.262 + /**
21.263 + * Writes a string to the output stream.
21.264 + * For every character in the string
21.265 + * <code>s</code>, taken in order, one byte
21.266 + * is written to the output stream. If
21.267 + * <code>s</code> is <code>null</code>, a <code>NullPointerException</code>
21.268 + * is thrown.<p> If <code>s.length</code>
21.269 + * is zero, then no bytes are written. Otherwise,
21.270 + * the character <code>s[0]</code> is written
21.271 + * first, then <code>s[1]</code>, and so on;
21.272 + * the last character written is <code>s[s.length-1]</code>.
21.273 + * For each character, one byte is written,
21.274 + * the low-order byte, in exactly the manner
21.275 + * of the <code>writeByte</code> method . The
21.276 + * high-order eight bits of each character
21.277 + * in the string are ignored.
21.278 + *
21.279 + * @param s the string of bytes to be written.
21.280 + * @throws IOException if an I/O error occurs.
21.281 + */
21.282 + void writeBytes(String s) throws IOException;
21.283 +
21.284 + /**
21.285 + * Writes every character in the string <code>s</code>,
21.286 + * to the output stream, in order,
21.287 + * two bytes per character. If <code>s</code>
21.288 + * is <code>null</code>, a <code>NullPointerException</code>
21.289 + * is thrown. If <code>s.length</code>
21.290 + * is zero, then no characters are written.
21.291 + * Otherwise, the character <code>s[0]</code>
21.292 + * is written first, then <code>s[1]</code>,
21.293 + * and so on; the last character written is
21.294 + * <code>s[s.length-1]</code>. For each character,
21.295 + * two bytes are actually written, high-order
21.296 + * byte first, in exactly the manner of the
21.297 + * <code>writeChar</code> method.
21.298 + *
21.299 + * @param s the string value to be written.
21.300 + * @throws IOException if an I/O error occurs.
21.301 + */
21.302 + void writeChars(String s) throws IOException;
21.303 +
21.304 + /**
21.305 + * Writes two bytes of length information
21.306 + * to the output stream, followed
21.307 + * by the
21.308 + * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
21.309 + * representation
21.310 + * of every character in the string <code>s</code>.
21.311 + * If <code>s</code> is <code>null</code>,
21.312 + * a <code>NullPointerException</code> is thrown.
21.313 + * Each character in the string <code>s</code>
21.314 + * is converted to a group of one, two, or
21.315 + * three bytes, depending on the value of the
21.316 + * character.<p>
21.317 + * If a character <code>c</code>
21.318 + * is in the range <code>\u0001</code> through
21.319 + * <code>\u007f</code>, it is represented
21.320 + * by one byte:<p>
21.321 + * <pre>(byte)c </pre> <p>
21.322 + * If a character <code>c</code> is <code>\u0000</code>
21.323 + * or is in the range <code>\u0080</code>
21.324 + * through <code>\u07ff</code>, then it is
21.325 + * represented by two bytes, to be written
21.326 + * in the order shown:<p> <pre><code>
21.327 + * (byte)(0xc0 | (0x1f & (c >> 6)))
21.328 + * (byte)(0x80 | (0x3f & c))
21.329 + * </code></pre> <p> If a character
21.330 + * <code>c</code> is in the range <code>\u0800</code>
21.331 + * through <code>uffff</code>, then it is
21.332 + * represented by three bytes, to be written
21.333 + * in the order shown:<p> <pre><code>
21.334 + * (byte)(0xe0 | (0x0f & (c >> 12)))
21.335 + * (byte)(0x80 | (0x3f & (c >> 6)))
21.336 + * (byte)(0x80 | (0x3f & c))
21.337 + * </code></pre> <p> First,
21.338 + * the total number of bytes needed to represent
21.339 + * all the characters of <code>s</code> is
21.340 + * calculated. If this number is larger than
21.341 + * <code>65535</code>, then a <code>UTFDataFormatException</code>
21.342 + * is thrown. Otherwise, this length is written
21.343 + * to the output stream in exactly the manner
21.344 + * of the <code>writeShort</code> method;
21.345 + * after this, the one-, two-, or three-byte
21.346 + * representation of each character in the
21.347 + * string <code>s</code> is written.<p> The
21.348 + * bytes written by this method may be read
21.349 + * by the <code>readUTF</code> method of interface
21.350 + * <code>DataInput</code> , which will then
21.351 + * return a <code>String</code> equal to <code>s</code>.
21.352 + *
21.353 + * @param s the string value to be written.
21.354 + * @throws IOException if an I/O error occurs.
21.355 + */
21.356 + void writeUTF(String s) throws IOException;
21.357 +}
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
22.2 +++ b/emul/compact/src/main/java/java/io/DataOutputStream.java Sun Feb 17 17:58:34 2013 +0100
22.3 @@ -0,0 +1,416 @@
22.4 +/*
22.5 + * Copyright (c) 1994, 2004, 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 + * A data output stream lets an application write primitive Java data
22.33 + * types to an output stream in a portable way. An application can
22.34 + * then use a data input stream to read the data back in.
22.35 + *
22.36 + * @author unascribed
22.37 + * @see java.io.DataInputStream
22.38 + * @since JDK1.0
22.39 + */
22.40 +public
22.41 +class DataOutputStream extends FilterOutputStream implements DataOutput {
22.42 + /**
22.43 + * The number of bytes written to the data output stream so far.
22.44 + * If this counter overflows, it will be wrapped to Integer.MAX_VALUE.
22.45 + */
22.46 + protected int written;
22.47 +
22.48 + /**
22.49 + * bytearr is initialized on demand by writeUTF
22.50 + */
22.51 + private byte[] bytearr = null;
22.52 +
22.53 + /**
22.54 + * Creates a new data output stream to write data to the specified
22.55 + * underlying output stream. The counter <code>written</code> is
22.56 + * set to zero.
22.57 + *
22.58 + * @param out the underlying output stream, to be saved for later
22.59 + * use.
22.60 + * @see java.io.FilterOutputStream#out
22.61 + */
22.62 + public DataOutputStream(OutputStream out) {
22.63 + super(out);
22.64 + }
22.65 +
22.66 + /**
22.67 + * Increases the written counter by the specified value
22.68 + * until it reaches Integer.MAX_VALUE.
22.69 + */
22.70 + private void incCount(int value) {
22.71 + int temp = written + value;
22.72 + if (temp < 0) {
22.73 + temp = Integer.MAX_VALUE;
22.74 + }
22.75 + written = temp;
22.76 + }
22.77 +
22.78 + /**
22.79 + * Writes the specified byte (the low eight bits of the argument
22.80 + * <code>b</code>) to the underlying output stream. If no exception
22.81 + * is thrown, the counter <code>written</code> is incremented by
22.82 + * <code>1</code>.
22.83 + * <p>
22.84 + * Implements the <code>write</code> method of <code>OutputStream</code>.
22.85 + *
22.86 + * @param b the <code>byte</code> to be written.
22.87 + * @exception IOException if an I/O error occurs.
22.88 + * @see java.io.FilterOutputStream#out
22.89 + */
22.90 + public synchronized void write(int b) throws IOException {
22.91 + out.write(b);
22.92 + incCount(1);
22.93 + }
22.94 +
22.95 + /**
22.96 + * Writes <code>len</code> bytes from the specified byte array
22.97 + * starting at offset <code>off</code> to the underlying output stream.
22.98 + * If no exception is thrown, the counter <code>written</code> is
22.99 + * incremented by <code>len</code>.
22.100 + *
22.101 + * @param b the data.
22.102 + * @param off the start offset in the data.
22.103 + * @param len the number of bytes to write.
22.104 + * @exception IOException if an I/O error occurs.
22.105 + * @see java.io.FilterOutputStream#out
22.106 + */
22.107 + public synchronized void write(byte b[], int off, int len)
22.108 + throws IOException
22.109 + {
22.110 + out.write(b, off, len);
22.111 + incCount(len);
22.112 + }
22.113 +
22.114 + /**
22.115 + * Flushes this data output stream. This forces any buffered output
22.116 + * bytes to be written out to the stream.
22.117 + * <p>
22.118 + * The <code>flush</code> method of <code>DataOutputStream</code>
22.119 + * calls the <code>flush</code> method of its underlying output stream.
22.120 + *
22.121 + * @exception IOException if an I/O error occurs.
22.122 + * @see java.io.FilterOutputStream#out
22.123 + * @see java.io.OutputStream#flush()
22.124 + */
22.125 + public void flush() throws IOException {
22.126 + out.flush();
22.127 + }
22.128 +
22.129 + /**
22.130 + * Writes a <code>boolean</code> to the underlying output stream as
22.131 + * a 1-byte value. The value <code>true</code> is written out as the
22.132 + * value <code>(byte)1</code>; the value <code>false</code> is
22.133 + * written out as the value <code>(byte)0</code>. If no exception is
22.134 + * thrown, the counter <code>written</code> is incremented by
22.135 + * <code>1</code>.
22.136 + *
22.137 + * @param v a <code>boolean</code> value to be written.
22.138 + * @exception IOException if an I/O error occurs.
22.139 + * @see java.io.FilterOutputStream#out
22.140 + */
22.141 + public final void writeBoolean(boolean v) throws IOException {
22.142 + out.write(v ? 1 : 0);
22.143 + incCount(1);
22.144 + }
22.145 +
22.146 + /**
22.147 + * Writes out a <code>byte</code> to the underlying output stream as
22.148 + * a 1-byte value. If no exception is thrown, the counter
22.149 + * <code>written</code> is incremented by <code>1</code>.
22.150 + *
22.151 + * @param v a <code>byte</code> value to be written.
22.152 + * @exception IOException if an I/O error occurs.
22.153 + * @see java.io.FilterOutputStream#out
22.154 + */
22.155 + public final void writeByte(int v) throws IOException {
22.156 + out.write(v);
22.157 + incCount(1);
22.158 + }
22.159 +
22.160 + /**
22.161 + * Writes a <code>short</code> to the underlying output stream as two
22.162 + * bytes, high byte first. If no exception is thrown, the counter
22.163 + * <code>written</code> is incremented by <code>2</code>.
22.164 + *
22.165 + * @param v a <code>short</code> to be written.
22.166 + * @exception IOException if an I/O error occurs.
22.167 + * @see java.io.FilterOutputStream#out
22.168 + */
22.169 + public final void writeShort(int v) throws IOException {
22.170 + out.write((v >>> 8) & 0xFF);
22.171 + out.write((v >>> 0) & 0xFF);
22.172 + incCount(2);
22.173 + }
22.174 +
22.175 + /**
22.176 + * Writes a <code>char</code> to the underlying output stream as a
22.177 + * 2-byte value, high byte first. If no exception is thrown, the
22.178 + * counter <code>written</code> is incremented by <code>2</code>.
22.179 + *
22.180 + * @param v a <code>char</code> value to be written.
22.181 + * @exception IOException if an I/O error occurs.
22.182 + * @see java.io.FilterOutputStream#out
22.183 + */
22.184 + public final void writeChar(int v) throws IOException {
22.185 + out.write((v >>> 8) & 0xFF);
22.186 + out.write((v >>> 0) & 0xFF);
22.187 + incCount(2);
22.188 + }
22.189 +
22.190 + /**
22.191 + * Writes an <code>int</code> to the underlying output stream as four
22.192 + * bytes, high byte first. If no exception is thrown, the counter
22.193 + * <code>written</code> is incremented by <code>4</code>.
22.194 + *
22.195 + * @param v an <code>int</code> to be written.
22.196 + * @exception IOException if an I/O error occurs.
22.197 + * @see java.io.FilterOutputStream#out
22.198 + */
22.199 + public final void writeInt(int v) throws IOException {
22.200 + out.write((v >>> 24) & 0xFF);
22.201 + out.write((v >>> 16) & 0xFF);
22.202 + out.write((v >>> 8) & 0xFF);
22.203 + out.write((v >>> 0) & 0xFF);
22.204 + incCount(4);
22.205 + }
22.206 +
22.207 + private byte writeBuffer[] = new byte[8];
22.208 +
22.209 + /**
22.210 + * Writes a <code>long</code> to the underlying output stream as eight
22.211 + * bytes, high byte first. In no exception is thrown, the counter
22.212 + * <code>written</code> is incremented by <code>8</code>.
22.213 + *
22.214 + * @param v a <code>long</code> to be written.
22.215 + * @exception IOException if an I/O error occurs.
22.216 + * @see java.io.FilterOutputStream#out
22.217 + */
22.218 + public final void writeLong(long v) throws IOException {
22.219 + writeBuffer[0] = (byte)(v >>> 56);
22.220 + writeBuffer[1] = (byte)(v >>> 48);
22.221 + writeBuffer[2] = (byte)(v >>> 40);
22.222 + writeBuffer[3] = (byte)(v >>> 32);
22.223 + writeBuffer[4] = (byte)(v >>> 24);
22.224 + writeBuffer[5] = (byte)(v >>> 16);
22.225 + writeBuffer[6] = (byte)(v >>> 8);
22.226 + writeBuffer[7] = (byte)(v >>> 0);
22.227 + out.write(writeBuffer, 0, 8);
22.228 + incCount(8);
22.229 + }
22.230 +
22.231 + /**
22.232 + * Converts the float argument to an <code>int</code> using the
22.233 + * <code>floatToIntBits</code> method in class <code>Float</code>,
22.234 + * and then writes that <code>int</code> value to the underlying
22.235 + * output stream as a 4-byte quantity, high byte first. If no
22.236 + * exception is thrown, the counter <code>written</code> is
22.237 + * incremented by <code>4</code>.
22.238 + *
22.239 + * @param v a <code>float</code> value to be written.
22.240 + * @exception IOException if an I/O error occurs.
22.241 + * @see java.io.FilterOutputStream#out
22.242 + * @see java.lang.Float#floatToIntBits(float)
22.243 + */
22.244 + public final void writeFloat(float v) throws IOException {
22.245 + writeInt(Float.floatToIntBits(v));
22.246 + }
22.247 +
22.248 + /**
22.249 + * Converts the double argument to a <code>long</code> using the
22.250 + * <code>doubleToLongBits</code> method in class <code>Double</code>,
22.251 + * and then writes that <code>long</code> value to the underlying
22.252 + * output stream as an 8-byte quantity, high byte first. If no
22.253 + * exception is thrown, the counter <code>written</code> is
22.254 + * incremented by <code>8</code>.
22.255 + *
22.256 + * @param v a <code>double</code> value to be written.
22.257 + * @exception IOException if an I/O error occurs.
22.258 + * @see java.io.FilterOutputStream#out
22.259 + * @see java.lang.Double#doubleToLongBits(double)
22.260 + */
22.261 + public final void writeDouble(double v) throws IOException {
22.262 + writeLong(Double.doubleToLongBits(v));
22.263 + }
22.264 +
22.265 + /**
22.266 + * Writes out the string to the underlying output stream as a
22.267 + * sequence of bytes. Each character in the string is written out, in
22.268 + * sequence, by discarding its high eight bits. If no exception is
22.269 + * thrown, the counter <code>written</code> is incremented by the
22.270 + * length of <code>s</code>.
22.271 + *
22.272 + * @param s a string of bytes to be written.
22.273 + * @exception IOException if an I/O error occurs.
22.274 + * @see java.io.FilterOutputStream#out
22.275 + */
22.276 + public final void writeBytes(String s) throws IOException {
22.277 + int len = s.length();
22.278 + for (int i = 0 ; i < len ; i++) {
22.279 + out.write((byte)s.charAt(i));
22.280 + }
22.281 + incCount(len);
22.282 + }
22.283 +
22.284 + /**
22.285 + * Writes a string to the underlying output stream as a sequence of
22.286 + * characters. Each character is written to the data output stream as
22.287 + * if by the <code>writeChar</code> method. If no exception is
22.288 + * thrown, the counter <code>written</code> is incremented by twice
22.289 + * the length of <code>s</code>.
22.290 + *
22.291 + * @param s a <code>String</code> value to be written.
22.292 + * @exception IOException if an I/O error occurs.
22.293 + * @see java.io.DataOutputStream#writeChar(int)
22.294 + * @see java.io.FilterOutputStream#out
22.295 + */
22.296 + public final void writeChars(String s) throws IOException {
22.297 + int len = s.length();
22.298 + for (int i = 0 ; i < len ; i++) {
22.299 + int v = s.charAt(i);
22.300 + out.write((v >>> 8) & 0xFF);
22.301 + out.write((v >>> 0) & 0xFF);
22.302 + }
22.303 + incCount(len * 2);
22.304 + }
22.305 +
22.306 + /**
22.307 + * Writes a string to the underlying output stream using
22.308 + * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
22.309 + * encoding in a machine-independent manner.
22.310 + * <p>
22.311 + * First, two bytes are written to the output stream as if by the
22.312 + * <code>writeShort</code> method giving the number of bytes to
22.313 + * follow. This value is the number of bytes actually written out,
22.314 + * not the length of the string. Following the length, each character
22.315 + * of the string is output, in sequence, using the modified UTF-8 encoding
22.316 + * for the character. If no exception is thrown, the counter
22.317 + * <code>written</code> is incremented by the total number of
22.318 + * bytes written to the output stream. This will be at least two
22.319 + * plus the length of <code>str</code>, and at most two plus
22.320 + * thrice the length of <code>str</code>.
22.321 + *
22.322 + * @param str a string to be written.
22.323 + * @exception IOException if an I/O error occurs.
22.324 + */
22.325 + public final void writeUTF(String str) throws IOException {
22.326 + writeUTF(str, this);
22.327 + }
22.328 +
22.329 + /**
22.330 + * Writes a string to the specified DataOutput using
22.331 + * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
22.332 + * encoding in a machine-independent manner.
22.333 + * <p>
22.334 + * First, two bytes are written to out as if by the <code>writeShort</code>
22.335 + * method giving the number of bytes to follow. This value is the number of
22.336 + * bytes actually written out, not the length of the string. Following the
22.337 + * length, each character of the string is output, in sequence, using the
22.338 + * modified UTF-8 encoding for the character. If no exception is thrown, the
22.339 + * counter <code>written</code> is incremented by the total number of
22.340 + * bytes written to the output stream. This will be at least two
22.341 + * plus the length of <code>str</code>, and at most two plus
22.342 + * thrice the length of <code>str</code>.
22.343 + *
22.344 + * @param str a string to be written.
22.345 + * @param out destination to write to
22.346 + * @return The number of bytes written out.
22.347 + * @exception IOException if an I/O error occurs.
22.348 + */
22.349 + static int writeUTF(String str, DataOutput out) throws IOException {
22.350 + int strlen = str.length();
22.351 + int utflen = 0;
22.352 + int c, count = 0;
22.353 +
22.354 + /* use charAt instead of copying String to char array */
22.355 + for (int i = 0; i < strlen; i++) {
22.356 + c = str.charAt(i);
22.357 + if ((c >= 0x0001) && (c <= 0x007F)) {
22.358 + utflen++;
22.359 + } else if (c > 0x07FF) {
22.360 + utflen += 3;
22.361 + } else {
22.362 + utflen += 2;
22.363 + }
22.364 + }
22.365 +
22.366 + if (utflen > 65535)
22.367 + throw new UTFDataFormatException(
22.368 + "encoded string too long: " + utflen + " bytes");
22.369 +
22.370 + byte[] bytearr = null;
22.371 + if (out instanceof DataOutputStream) {
22.372 + DataOutputStream dos = (DataOutputStream)out;
22.373 + if(dos.bytearr == null || (dos.bytearr.length < (utflen+2)))
22.374 + dos.bytearr = new byte[(utflen*2) + 2];
22.375 + bytearr = dos.bytearr;
22.376 + } else {
22.377 + bytearr = new byte[utflen+2];
22.378 + }
22.379 +
22.380 + bytearr[count++] = (byte) ((utflen >>> 8) & 0xFF);
22.381 + bytearr[count++] = (byte) ((utflen >>> 0) & 0xFF);
22.382 +
22.383 + int i=0;
22.384 + for (i=0; i<strlen; i++) {
22.385 + c = str.charAt(i);
22.386 + if (!((c >= 0x0001) && (c <= 0x007F))) break;
22.387 + bytearr[count++] = (byte) c;
22.388 + }
22.389 +
22.390 + for (;i < strlen; i++){
22.391 + c = str.charAt(i);
22.392 + if ((c >= 0x0001) && (c <= 0x007F)) {
22.393 + bytearr[count++] = (byte) c;
22.394 +
22.395 + } else if (c > 0x07FF) {
22.396 + bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
22.397 + bytearr[count++] = (byte) (0x80 | ((c >> 6) & 0x3F));
22.398 + bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
22.399 + } else {
22.400 + bytearr[count++] = (byte) (0xC0 | ((c >> 6) & 0x1F));
22.401 + bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
22.402 + }
22.403 + }
22.404 + out.write(bytearr, 0, utflen+2);
22.405 + return utflen + 2;
22.406 + }
22.407 +
22.408 + /**
22.409 + * Returns the current value of the counter <code>written</code>,
22.410 + * the number of bytes written to this data output stream so far.
22.411 + * If the counter overflows, it will be wrapped to Integer.MAX_VALUE.
22.412 + *
22.413 + * @return the value of the <code>written</code> field.
22.414 + * @see java.io.DataOutputStream#written
22.415 + */
22.416 + public final int size() {
22.417 + return written;
22.418 + }
22.419 +}
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
23.2 +++ b/emul/compact/src/main/java/java/io/Externalizable.java Sun Feb 17 17:58:34 2013 +0100
23.3 @@ -0,0 +1,97 @@
23.4 +/*
23.5 + * Copyright (c) 1996, 2004, 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 +import java.io.ObjectOutput;
23.32 +import java.io.ObjectInput;
23.33 +
23.34 +/**
23.35 + * Only the identity of the class of an Externalizable instance is
23.36 + * written in the serialization stream and it is the responsibility
23.37 + * of the class to save and restore the contents of its instances.
23.38 + *
23.39 + * The writeExternal and readExternal methods of the Externalizable
23.40 + * interface are implemented by a class to give the class complete
23.41 + * control over the format and contents of the stream for an object
23.42 + * and its supertypes. These methods must explicitly
23.43 + * coordinate with the supertype to save its state. These methods supersede
23.44 + * customized implementations of writeObject and readObject methods.<br>
23.45 + *
23.46 + * Object Serialization uses the Serializable and Externalizable
23.47 + * interfaces. Object persistence mechanisms can use them as well. Each
23.48 + * object to be stored is tested for the Externalizable interface. If
23.49 + * the object supports Externalizable, the writeExternal method is called. If the
23.50 + * object does not support Externalizable and does implement
23.51 + * Serializable, the object is saved using
23.52 + * ObjectOutputStream. <br> When an Externalizable object is
23.53 + * reconstructed, an instance is created using the public no-arg
23.54 + * constructor, then the readExternal method called. Serializable
23.55 + * objects are restored by reading them from an ObjectInputStream.<br>
23.56 + *
23.57 + * An Externalizable instance can designate a substitution object via
23.58 + * the writeReplace and readResolve methods documented in the Serializable
23.59 + * interface.<br>
23.60 + *
23.61 + * @author unascribed
23.62 + * @see java.io.ObjectOutputStream
23.63 + * @see java.io.ObjectInputStream
23.64 + * @see java.io.ObjectOutput
23.65 + * @see java.io.ObjectInput
23.66 + * @see java.io.Serializable
23.67 + * @since JDK1.1
23.68 + */
23.69 +public interface Externalizable extends java.io.Serializable {
23.70 + /**
23.71 + * The object implements the writeExternal method to save its contents
23.72 + * by calling the methods of DataOutput for its primitive values or
23.73 + * calling the writeObject method of ObjectOutput for objects, strings,
23.74 + * and arrays.
23.75 + *
23.76 + * @serialData Overriding methods should use this tag to describe
23.77 + * the data layout of this Externalizable object.
23.78 + * List the sequence of element types and, if possible,
23.79 + * relate the element to a public/protected field and/or
23.80 + * method of this Externalizable class.
23.81 + *
23.82 + * @param out the stream to write the object to
23.83 + * @exception IOException Includes any I/O exceptions that may occur
23.84 + */
23.85 + void writeExternal(ObjectOutput out) throws IOException;
23.86 +
23.87 + /**
23.88 + * The object implements the readExternal method to restore its
23.89 + * contents by calling the methods of DataInput for primitive
23.90 + * types and readObject for objects, strings and arrays. The
23.91 + * readExternal method must read the values in the same sequence
23.92 + * and with the same types as were written by writeExternal.
23.93 + *
23.94 + * @param in the stream to read data from in order to restore the object
23.95 + * @exception IOException if I/O errors occur
23.96 + * @exception ClassNotFoundException If the class for an object being
23.97 + * restored cannot be found.
23.98 + */
23.99 + void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
23.100 +}
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
24.2 +++ b/emul/compact/src/main/java/java/io/FilterOutputStream.java Sun Feb 17 17:58:34 2013 +0100
24.3 @@ -0,0 +1,162 @@
24.4 +/*
24.5 + * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
24.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
24.7 + *
24.8 + * This code is free software; you can redistribute it and/or modify it
24.9 + * under the terms of the GNU General Public License version 2 only, as
24.10 + * published by the Free Software Foundation. Oracle designates this
24.11 + * particular file as subject to the "Classpath" exception as provided
24.12 + * by Oracle in the LICENSE file that accompanied this code.
24.13 + *
24.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
24.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
24.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24.17 + * version 2 for more details (a copy is included in the LICENSE file that
24.18 + * accompanied this code).
24.19 + *
24.20 + * You should have received a copy of the GNU General Public License version
24.21 + * 2 along with this work; if not, write to the Free Software Foundation,
24.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24.23 + *
24.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
24.25 + * or visit www.oracle.com if you need additional information or have any
24.26 + * questions.
24.27 + */
24.28 +
24.29 +package java.io;
24.30 +
24.31 +/**
24.32 + * This class is the superclass of all classes that filter output
24.33 + * streams. These streams sit on top of an already existing output
24.34 + * stream (the <i>underlying</i> output stream) which it uses as its
24.35 + * basic sink of data, but possibly transforming the data along the
24.36 + * way or providing additional functionality.
24.37 + * <p>
24.38 + * The class <code>FilterOutputStream</code> itself simply overrides
24.39 + * all methods of <code>OutputStream</code> with versions that pass
24.40 + * all requests to the underlying output stream. Subclasses of
24.41 + * <code>FilterOutputStream</code> may further override some of these
24.42 + * methods as well as provide additional methods and fields.
24.43 + *
24.44 + * @author Jonathan Payne
24.45 + * @since JDK1.0
24.46 + */
24.47 +public
24.48 +class FilterOutputStream extends OutputStream {
24.49 + /**
24.50 + * The underlying output stream to be filtered.
24.51 + */
24.52 + protected OutputStream out;
24.53 +
24.54 + /**
24.55 + * Creates an output stream filter built on top of the specified
24.56 + * underlying output stream.
24.57 + *
24.58 + * @param out the underlying output stream to be assigned to
24.59 + * the field <tt>this.out</tt> for later use, or
24.60 + * <code>null</code> if this instance is to be
24.61 + * created without an underlying stream.
24.62 + */
24.63 + public FilterOutputStream(OutputStream out) {
24.64 + this.out = out;
24.65 + }
24.66 +
24.67 + /**
24.68 + * Writes the specified <code>byte</code> to this output stream.
24.69 + * <p>
24.70 + * The <code>write</code> method of <code>FilterOutputStream</code>
24.71 + * calls the <code>write</code> method of its underlying output stream,
24.72 + * that is, it performs <tt>out.write(b)</tt>.
24.73 + * <p>
24.74 + * Implements the abstract <tt>write</tt> method of <tt>OutputStream</tt>.
24.75 + *
24.76 + * @param b the <code>byte</code>.
24.77 + * @exception IOException if an I/O error occurs.
24.78 + */
24.79 + public void write(int b) throws IOException {
24.80 + out.write(b);
24.81 + }
24.82 +
24.83 + /**
24.84 + * Writes <code>b.length</code> bytes to this output stream.
24.85 + * <p>
24.86 + * The <code>write</code> method of <code>FilterOutputStream</code>
24.87 + * calls its <code>write</code> method of three arguments with the
24.88 + * arguments <code>b</code>, <code>0</code>, and
24.89 + * <code>b.length</code>.
24.90 + * <p>
24.91 + * Note that this method does not call the one-argument
24.92 + * <code>write</code> method of its underlying stream with the single
24.93 + * argument <code>b</code>.
24.94 + *
24.95 + * @param b the data to be written.
24.96 + * @exception IOException if an I/O error occurs.
24.97 + * @see java.io.FilterOutputStream#write(byte[], int, int)
24.98 + */
24.99 + public void write(byte b[]) throws IOException {
24.100 + write(b, 0, b.length);
24.101 + }
24.102 +
24.103 + /**
24.104 + * Writes <code>len</code> bytes from the specified
24.105 + * <code>byte</code> array starting at offset <code>off</code> to
24.106 + * this output stream.
24.107 + * <p>
24.108 + * The <code>write</code> method of <code>FilterOutputStream</code>
24.109 + * calls the <code>write</code> method of one argument on each
24.110 + * <code>byte</code> to output.
24.111 + * <p>
24.112 + * Note that this method does not call the <code>write</code> method
24.113 + * of its underlying input stream with the same arguments. Subclasses
24.114 + * of <code>FilterOutputStream</code> should provide a more efficient
24.115 + * implementation of this method.
24.116 + *
24.117 + * @param b the data.
24.118 + * @param off the start offset in the data.
24.119 + * @param len the number of bytes to write.
24.120 + * @exception IOException if an I/O error occurs.
24.121 + * @see java.io.FilterOutputStream#write(int)
24.122 + */
24.123 + public void write(byte b[], int off, int len) throws IOException {
24.124 + if ((off | len | (b.length - (len + off)) | (off + len)) < 0)
24.125 + throw new IndexOutOfBoundsException();
24.126 +
24.127 + for (int i = 0 ; i < len ; i++) {
24.128 + write(b[off + i]);
24.129 + }
24.130 + }
24.131 +
24.132 + /**
24.133 + * Flushes this output stream and forces any buffered output bytes
24.134 + * to be written out to the stream.
24.135 + * <p>
24.136 + * The <code>flush</code> method of <code>FilterOutputStream</code>
24.137 + * calls the <code>flush</code> method of its underlying output stream.
24.138 + *
24.139 + * @exception IOException if an I/O error occurs.
24.140 + * @see java.io.FilterOutputStream#out
24.141 + */
24.142 + public void flush() throws IOException {
24.143 + out.flush();
24.144 + }
24.145 +
24.146 + /**
24.147 + * Closes this output stream and releases any system resources
24.148 + * associated with the stream.
24.149 + * <p>
24.150 + * The <code>close</code> method of <code>FilterOutputStream</code>
24.151 + * calls its <code>flush</code> method, and then calls the
24.152 + * <code>close</code> method of its underlying output stream.
24.153 + *
24.154 + * @exception IOException if an I/O error occurs.
24.155 + * @see java.io.FilterOutputStream#flush()
24.156 + * @see java.io.FilterOutputStream#out
24.157 + */
24.158 + public void close() throws IOException {
24.159 + try {
24.160 + flush();
24.161 + } catch (IOException ignored) {
24.162 + }
24.163 + out.close();
24.164 + }
24.165 +}
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
25.2 +++ b/emul/compact/src/main/java/java/io/Flushable.java Sun Feb 17 17:58:34 2013 +0100
25.3 @@ -0,0 +1,47 @@
25.4 +/*
25.5 + * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
25.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
25.7 + *
25.8 + * This code is free software; you can redistribute it and/or modify it
25.9 + * under the terms of the GNU General Public License version 2 only, as
25.10 + * published by the Free Software Foundation. Oracle designates this
25.11 + * particular file as subject to the "Classpath" exception as provided
25.12 + * by Oracle in the LICENSE file that accompanied this code.
25.13 + *
25.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
25.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
25.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25.17 + * version 2 for more details (a copy is included in the LICENSE file that
25.18 + * accompanied this code).
25.19 + *
25.20 + * You should have received a copy of the GNU General Public License version
25.21 + * 2 along with this work; if not, write to the Free Software Foundation,
25.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
25.23 + *
25.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
25.25 + * or visit www.oracle.com if you need additional information or have any
25.26 + * questions.
25.27 + */
25.28 +
25.29 +package java.io;
25.30 +
25.31 +import java.io.IOException;
25.32 +
25.33 +/**
25.34 + * A <tt>Flushable</tt> is a destination of data that can be flushed. The
25.35 + * flush method is invoked to write any buffered output to the underlying
25.36 + * stream.
25.37 + *
25.38 + * @since 1.5
25.39 + */
25.40 +
25.41 +public interface Flushable {
25.42 +
25.43 + /**
25.44 + * Flushes this stream by writing any buffered output to the underlying
25.45 + * stream.
25.46 + *
25.47 + * @throws IOException If an I/O error occurs
25.48 + */
25.49 + void flush() throws IOException;
25.50 +}
26.1 --- a/emul/compact/src/main/java/java/io/InputStreamReader.java Fri Jan 25 15:08:24 2013 +0100
26.2 +++ b/emul/compact/src/main/java/java/io/InputStreamReader.java Sun Feb 17 17:58:34 2013 +0100
26.3 @@ -156,9 +156,39 @@
26.4 * @exception IOException If an I/O error occurs
26.5 */
26.6 public int read() throws IOException {
26.7 - return ((InputStream)lock).read();
26.8 + final InputStream is = (InputStream)lock;
26.9 + int c = is.read();
26.10 + if (c == -1) {
26.11 + return -1;
26.12 + }
26.13 + c = (int) c & 0xff;
26.14 + switch (c >> 4) {
26.15 + case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
26.16 + /* 0xxxxxxx*/
26.17 + return c;
26.18 + case 12: case 13: {
26.19 + /* 110x xxxx 10xx xxxx*/
26.20 + int char2 = (int) is.read();
26.21 + if ((char2 & 0xC0) != 0x80)
26.22 + throw new UTFDataFormatException("malformed input");
26.23 + return (((c & 0x1F) << 6) | (char2 & 0x3F));
26.24 + }
26.25 + case 14: {
26.26 + /* 1110 xxxx 10xx xxxx 10xx xxxx */
26.27 + int char2 = is.read();
26.28 + int char3 = is.read();
26.29 + if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
26.30 + throw new UTFDataFormatException("malformed input");
26.31 + return (((c & 0x0F) << 12) |
26.32 + ((char2 & 0x3F) << 6) |
26.33 + ((char3 & 0x3F) << 0));
26.34 + }
26.35 + default:
26.36 + /* 10xx xxxx, 1111 xxxx */
26.37 + throw new UTFDataFormatException("malformed input");
26.38 + }
26.39 }
26.40 -
26.41 +
26.42 /**
26.43 * Reads characters into a portion of an array.
26.44 *
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
27.2 +++ b/emul/compact/src/main/java/java/io/InvalidClassException.java Sun Feb 17 17:58:34 2013 +0100
27.3 @@ -0,0 +1,81 @@
27.4 +/*
27.5 + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
27.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
27.7 + *
27.8 + * This code is free software; you can redistribute it and/or modify it
27.9 + * under the terms of the GNU General Public License version 2 only, as
27.10 + * published by the Free Software Foundation. Oracle designates this
27.11 + * particular file as subject to the "Classpath" exception as provided
27.12 + * by Oracle in the LICENSE file that accompanied this code.
27.13 + *
27.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
27.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
27.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
27.17 + * version 2 for more details (a copy is included in the LICENSE file that
27.18 + * accompanied this code).
27.19 + *
27.20 + * You should have received a copy of the GNU General Public License version
27.21 + * 2 along with this work; if not, write to the Free Software Foundation,
27.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
27.23 + *
27.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
27.25 + * or visit www.oracle.com if you need additional information or have any
27.26 + * questions.
27.27 + */
27.28 +
27.29 +package java.io;
27.30 +
27.31 +/**
27.32 + * Thrown when the Serialization runtime detects one of the following
27.33 + * problems with a Class.
27.34 + * <UL>
27.35 + * <LI> The serial version of the class does not match that of the class
27.36 + * descriptor read from the stream
27.37 + * <LI> The class contains unknown datatypes
27.38 + * <LI> The class does not have an accessible no-arg constructor
27.39 + * </UL>
27.40 + *
27.41 + * @author unascribed
27.42 + * @since JDK1.1
27.43 + */
27.44 +public class InvalidClassException extends ObjectStreamException {
27.45 +
27.46 + private static final long serialVersionUID = -4333316296251054416L;
27.47 +
27.48 + /**
27.49 + * Name of the invalid class.
27.50 + *
27.51 + * @serial Name of the invalid class.
27.52 + */
27.53 + public String classname;
27.54 +
27.55 + /**
27.56 + * Report an InvalidClassException for the reason specified.
27.57 + *
27.58 + * @param reason String describing the reason for the exception.
27.59 + */
27.60 + public InvalidClassException(String reason) {
27.61 + super(reason);
27.62 + }
27.63 +
27.64 + /**
27.65 + * Constructs an InvalidClassException object.
27.66 + *
27.67 + * @param cname a String naming the invalid class.
27.68 + * @param reason a String describing the reason for the exception.
27.69 + */
27.70 + public InvalidClassException(String cname, String reason) {
27.71 + super(reason);
27.72 + classname = cname;
27.73 + }
27.74 +
27.75 + /**
27.76 + * Produce the message and include the classname, if present.
27.77 + */
27.78 + public String getMessage() {
27.79 + if (classname == null)
27.80 + return super.getMessage();
27.81 + else
27.82 + return classname + "; " + super.getMessage();
27.83 + }
27.84 +}
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
28.2 +++ b/emul/compact/src/main/java/java/io/InvalidObjectException.java Sun Feb 17 17:58:34 2013 +0100
28.3 @@ -0,0 +1,51 @@
28.4 +/*
28.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
28.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
28.7 + *
28.8 + * This code is free software; you can redistribute it and/or modify it
28.9 + * under the terms of the GNU General Public License version 2 only, as
28.10 + * published by the Free Software Foundation. Oracle designates this
28.11 + * particular file as subject to the "Classpath" exception as provided
28.12 + * by Oracle in the LICENSE file that accompanied this code.
28.13 + *
28.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
28.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
28.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
28.17 + * version 2 for more details (a copy is included in the LICENSE file that
28.18 + * accompanied this code).
28.19 + *
28.20 + * You should have received a copy of the GNU General Public License version
28.21 + * 2 along with this work; if not, write to the Free Software Foundation,
28.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
28.23 + *
28.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
28.25 + * or visit www.oracle.com if you need additional information or have any
28.26 + * questions.
28.27 + */
28.28 +
28.29 +package java.io;
28.30 +
28.31 +/**
28.32 + * Indicates that one or more deserialized objects failed validation
28.33 + * tests. The argument should provide the reason for the failure.
28.34 + *
28.35 + * @see ObjectInputValidation
28.36 + * @since JDK1.1
28.37 + *
28.38 + * @author unascribed
28.39 + * @since JDK1.1
28.40 + */
28.41 +public class InvalidObjectException extends ObjectStreamException {
28.42 +
28.43 + private static final long serialVersionUID = 3233174318281839583L;
28.44 +
28.45 + /**
28.46 + * Constructs an <code>InvalidObjectException</code>.
28.47 + * @param reason Detailed message explaining the reason for the failure.
28.48 + *
28.49 + * @see ObjectInputValidation
28.50 + */
28.51 + public InvalidObjectException(String reason) {
28.52 + super(reason);
28.53 + }
28.54 +}
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
29.2 +++ b/emul/compact/src/main/java/java/io/NotActiveException.java Sun Feb 17 17:58:34 2013 +0100
29.3 @@ -0,0 +1,53 @@
29.4 +/*
29.5 + * Copyright (c) 1996, 2005, 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 + * Thrown when serialization or deserialization is not active.
29.33 + *
29.34 + * @author unascribed
29.35 + * @since JDK1.1
29.36 + */
29.37 +public class NotActiveException extends ObjectStreamException {
29.38 +
29.39 + private static final long serialVersionUID = -3893467273049808895L;
29.40 +
29.41 + /**
29.42 + * Constructor to create a new NotActiveException with the reason given.
29.43 + *
29.44 + * @param reason a String describing the reason for the exception.
29.45 + */
29.46 + public NotActiveException(String reason) {
29.47 + super(reason);
29.48 + }
29.49 +
29.50 + /**
29.51 + * Constructor to create a new NotActiveException without a reason.
29.52 + */
29.53 + public NotActiveException() {
29.54 + super();
29.55 + }
29.56 +}
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
30.2 +++ b/emul/compact/src/main/java/java/io/NotSerializableException.java Sun Feb 17 17:58:34 2013 +0100
30.3 @@ -0,0 +1,55 @@
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 + * Thrown when an instance is required to have a Serializable interface.
30.33 + * The serialization runtime or the class of the instance can throw
30.34 + * this exception. The argument should be the name of the class.
30.35 + *
30.36 + * @author unascribed
30.37 + * @since JDK1.1
30.38 + */
30.39 +public class NotSerializableException extends ObjectStreamException {
30.40 +
30.41 + private static final long serialVersionUID = 2906642554793891381L;
30.42 +
30.43 + /**
30.44 + * Constructs a NotSerializableException object with message string.
30.45 + *
30.46 + * @param classname Class of the instance being serialized/deserialized.
30.47 + */
30.48 + public NotSerializableException(String classname) {
30.49 + super(classname);
30.50 + }
30.51 +
30.52 + /**
30.53 + * Constructs a NotSerializableException object.
30.54 + */
30.55 + public NotSerializableException() {
30.56 + super();
30.57 + }
30.58 +}
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
31.2 +++ b/emul/compact/src/main/java/java/io/ObjectInput.java Sun Feb 17 17:58:34 2013 +0100
31.3 @@ -0,0 +1,107 @@
31.4 +/*
31.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
31.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
31.7 + *
31.8 + * This code is free software; you can redistribute it and/or modify it
31.9 + * under the terms of the GNU General Public License version 2 only, as
31.10 + * published by the Free Software Foundation. Oracle designates this
31.11 + * particular file as subject to the "Classpath" exception as provided
31.12 + * by Oracle in the LICENSE file that accompanied this code.
31.13 + *
31.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
31.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
31.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
31.17 + * version 2 for more details (a copy is included in the LICENSE file that
31.18 + * accompanied this code).
31.19 + *
31.20 + * You should have received a copy of the GNU General Public License version
31.21 + * 2 along with this work; if not, write to the Free Software Foundation,
31.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
31.23 + *
31.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
31.25 + * or visit www.oracle.com if you need additional information or have any
31.26 + * questions.
31.27 + */
31.28 +
31.29 +package java.io;
31.30 +
31.31 +/**
31.32 + * ObjectInput extends the DataInput interface to include the reading of
31.33 + * objects. DataInput includes methods for the input of primitive types,
31.34 + * ObjectInput extends that interface to include objects, arrays, and Strings.
31.35 + *
31.36 + * @author unascribed
31.37 + * @see java.io.InputStream
31.38 + * @see java.io.ObjectOutputStream
31.39 + * @see java.io.ObjectInputStream
31.40 + * @since JDK1.1
31.41 + */
31.42 +public interface ObjectInput extends DataInput, AutoCloseable {
31.43 + /**
31.44 + * Read and return an object. The class that implements this interface
31.45 + * defines where the object is "read" from.
31.46 + *
31.47 + * @return the object read from the stream
31.48 + * @exception java.lang.ClassNotFoundException If the class of a serialized
31.49 + * object cannot be found.
31.50 + * @exception IOException If any of the usual Input/Output
31.51 + * related exceptions occur.
31.52 + */
31.53 + public Object readObject()
31.54 + throws ClassNotFoundException, IOException;
31.55 +
31.56 + /**
31.57 + * Reads a byte of data. This method will block if no input is
31.58 + * available.
31.59 + * @return the byte read, or -1 if the end of the
31.60 + * stream is reached.
31.61 + * @exception IOException If an I/O error has occurred.
31.62 + */
31.63 + public int read() throws IOException;
31.64 +
31.65 + /**
31.66 + * Reads into an array of bytes. This method will
31.67 + * block until some input is available.
31.68 + * @param b the buffer into which the data is read
31.69 + * @return the actual number of bytes read, -1 is
31.70 + * returned when the end of the stream is reached.
31.71 + * @exception IOException If an I/O error has occurred.
31.72 + */
31.73 + public int read(byte b[]) throws IOException;
31.74 +
31.75 + /**
31.76 + * Reads into an array of bytes. This method will
31.77 + * block until some input is available.
31.78 + * @param b the buffer into which the data is read
31.79 + * @param off the start offset of the data
31.80 + * @param len the maximum number of bytes read
31.81 + * @return the actual number of bytes read, -1 is
31.82 + * returned when the end of the stream is reached.
31.83 + * @exception IOException If an I/O error has occurred.
31.84 + */
31.85 + public int read(byte b[], int off, int len) throws IOException;
31.86 +
31.87 + /**
31.88 + * Skips n bytes of input.
31.89 + * @param n the number of bytes to be skipped
31.90 + * @return the actual number of bytes skipped.
31.91 + * @exception IOException If an I/O error has occurred.
31.92 + */
31.93 + public long skip(long n) throws IOException;
31.94 +
31.95 + /**
31.96 + * Returns the number of bytes that can be read
31.97 + * without blocking.
31.98 + * @return the number of available bytes.
31.99 + * @exception IOException If an I/O error has occurred.
31.100 + */
31.101 + public int available() throws IOException;
31.102 +
31.103 + /**
31.104 + * Closes the input stream. Must be called
31.105 + * to release any resources associated with
31.106 + * the stream.
31.107 + * @exception IOException If an I/O error has occurred.
31.108 + */
31.109 + public void close() throws IOException;
31.110 +}
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
32.2 +++ b/emul/compact/src/main/java/java/io/ObjectInputStream.java Sun Feb 17 17:58:34 2013 +0100
32.3 @@ -0,0 +1,3357 @@
32.4 +/*
32.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
32.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
32.7 + *
32.8 + * This code is free software; you can redistribute it and/or modify it
32.9 + * under the terms of the GNU General Public License version 2 only, as
32.10 + * published by the Free Software Foundation. Oracle designates this
32.11 + * particular file as subject to the "Classpath" exception as provided
32.12 + * by Oracle in the LICENSE file that accompanied this code.
32.13 + *
32.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
32.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
32.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
32.17 + * version 2 for more details (a copy is included in the LICENSE file that
32.18 + * accompanied this code).
32.19 + *
32.20 + * You should have received a copy of the GNU General Public License version
32.21 + * 2 along with this work; if not, write to the Free Software Foundation,
32.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
32.23 + *
32.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
32.25 + * or visit www.oracle.com if you need additional information or have any
32.26 + * questions.
32.27 + */
32.28 +
32.29 +package java.io;
32.30 +
32.31 +import java.lang.reflect.Array;
32.32 +import java.lang.reflect.Modifier;
32.33 +import java.lang.reflect.Proxy;
32.34 +import java.util.Arrays;
32.35 +import java.util.HashMap;
32.36 +import org.apidesign.bck2brwsr.emul.lang.System;
32.37 +
32.38 +/**
32.39 + * An ObjectInputStream deserializes primitive data and objects previously
32.40 + * written using an ObjectOutputStream.
32.41 + *
32.42 + * <p>ObjectOutputStream and ObjectInputStream can provide an application with
32.43 + * persistent storage for graphs of objects when used with a FileOutputStream
32.44 + * and FileInputStream respectively. ObjectInputStream is used to recover
32.45 + * those objects previously serialized. Other uses include passing objects
32.46 + * between hosts using a socket stream or for marshaling and unmarshaling
32.47 + * arguments and parameters in a remote communication system.
32.48 + *
32.49 + * <p>ObjectInputStream ensures that the types of all objects in the graph
32.50 + * created from the stream match the classes present in the Java Virtual
32.51 + * Machine. Classes are loaded as required using the standard mechanisms.
32.52 + *
32.53 + * <p>Only objects that support the java.io.Serializable or
32.54 + * java.io.Externalizable interface can be read from streams.
32.55 + *
32.56 + * <p>The method <code>readObject</code> is used to read an object from the
32.57 + * stream. Java's safe casting should be used to get the desired type. In
32.58 + * Java, strings and arrays are objects and are treated as objects during
32.59 + * serialization. When read they need to be cast to the expected type.
32.60 + *
32.61 + * <p>Primitive data types can be read from the stream using the appropriate
32.62 + * method on DataInput.
32.63 + *
32.64 + * <p>The default deserialization mechanism for objects restores the contents
32.65 + * of each field to the value and type it had when it was written. Fields
32.66 + * declared as transient or static are ignored by the deserialization process.
32.67 + * References to other objects cause those objects to be read from the stream
32.68 + * as necessary. Graphs of objects are restored correctly using a reference
32.69 + * sharing mechanism. New objects are always allocated when deserializing,
32.70 + * which prevents existing objects from being overwritten.
32.71 + *
32.72 + * <p>Reading an object is analogous to running the constructors of a new
32.73 + * object. Memory is allocated for the object and initialized to zero (NULL).
32.74 + * No-arg constructors are invoked for the non-serializable classes and then
32.75 + * the fields of the serializable classes are restored from the stream starting
32.76 + * with the serializable class closest to java.lang.object and finishing with
32.77 + * the object's most specific class.
32.78 + *
32.79 + * <p>For example to read from a stream as written by the example in
32.80 + * ObjectOutputStream:
32.81 + * <br>
32.82 + * <pre>
32.83 + * FileInputStream fis = new FileInputStream("t.tmp");
32.84 + * ObjectInputStream ois = new ObjectInputStream(fis);
32.85 + *
32.86 + * int i = ois.readInt();
32.87 + * String today = (String) ois.readObject();
32.88 + * Date date = (Date) ois.readObject();
32.89 + *
32.90 + * ois.close();
32.91 + * </pre>
32.92 + *
32.93 + * <p>Classes control how they are serialized by implementing either the
32.94 + * java.io.Serializable or java.io.Externalizable interfaces.
32.95 + *
32.96 + * <p>Implementing the Serializable interface allows object serialization to
32.97 + * save and restore the entire state of the object and it allows classes to
32.98 + * evolve between the time the stream is written and the time it is read. It
32.99 + * automatically traverses references between objects, saving and restoring
32.100 + * entire graphs.
32.101 + *
32.102 + * <p>Serializable classes that require special handling during the
32.103 + * serialization and deserialization process should implement the following
32.104 + * methods:<p>
32.105 + *
32.106 + * <pre>
32.107 + * private void writeObject(java.io.ObjectOutputStream stream)
32.108 + * throws IOException;
32.109 + * private void readObject(java.io.ObjectInputStream stream)
32.110 + * throws IOException, ClassNotFoundException;
32.111 + * private void readObjectNoData()
32.112 + * throws ObjectStreamException;
32.113 + * </pre>
32.114 + *
32.115 + * <p>The readObject method is responsible for reading and restoring the state
32.116 + * of the object for its particular class using data written to the stream by
32.117 + * the corresponding writeObject method. The method does not need to concern
32.118 + * itself with the state belonging to its superclasses or subclasses. State is
32.119 + * restored by reading data from the ObjectInputStream for the individual
32.120 + * fields and making assignments to the appropriate fields of the object.
32.121 + * Reading primitive data types is supported by DataInput.
32.122 + *
32.123 + * <p>Any attempt to read object data which exceeds the boundaries of the
32.124 + * custom data written by the corresponding writeObject method will cause an
32.125 + * OptionalDataException to be thrown with an eof field value of true.
32.126 + * Non-object reads which exceed the end of the allotted data will reflect the
32.127 + * end of data in the same way that they would indicate the end of the stream:
32.128 + * bytewise reads will return -1 as the byte read or number of bytes read, and
32.129 + * primitive reads will throw EOFExceptions. If there is no corresponding
32.130 + * writeObject method, then the end of default serialized data marks the end of
32.131 + * the allotted data.
32.132 + *
32.133 + * <p>Primitive and object read calls issued from within a readExternal method
32.134 + * behave in the same manner--if the stream is already positioned at the end of
32.135 + * data written by the corresponding writeExternal method, object reads will
32.136 + * throw OptionalDataExceptions with eof set to true, bytewise reads will
32.137 + * return -1, and primitive reads will throw EOFExceptions. Note that this
32.138 + * behavior does not hold for streams written with the old
32.139 + * <code>ObjectStreamConstants.PROTOCOL_VERSION_1</code> protocol, in which the
32.140 + * end of data written by writeExternal methods is not demarcated, and hence
32.141 + * cannot be detected.
32.142 + *
32.143 + * <p>The readObjectNoData method is responsible for initializing the state of
32.144 + * the object for its particular class in the event that the serialization
32.145 + * stream does not list the given class as a superclass of the object being
32.146 + * deserialized. This may occur in cases where the receiving party uses a
32.147 + * different version of the deserialized instance's class than the sending
32.148 + * party, and the receiver's version extends classes that are not extended by
32.149 + * the sender's version. This may also occur if the serialization stream has
32.150 + * been tampered; hence, readObjectNoData is useful for initializing
32.151 + * deserialized objects properly despite a "hostile" or incomplete source
32.152 + * stream.
32.153 + *
32.154 + * <p>Serialization does not read or assign values to the fields of any object
32.155 + * that does not implement the java.io.Serializable interface. Subclasses of
32.156 + * Objects that are not serializable can be serializable. In this case the
32.157 + * non-serializable class must have a no-arg constructor to allow its fields to
32.158 + * be initialized. In this case it is the responsibility of the subclass to
32.159 + * save and restore the state of the non-serializable class. It is frequently
32.160 + * the case that the fields of that class are accessible (public, package, or
32.161 + * protected) or that there are get and set methods that can be used to restore
32.162 + * the state.
32.163 + *
32.164 + * <p>Any exception that occurs while deserializing an object will be caught by
32.165 + * the ObjectInputStream and abort the reading process.
32.166 + *
32.167 + * <p>Implementing the Externalizable interface allows the object to assume
32.168 + * complete control over the contents and format of the object's serialized
32.169 + * form. The methods of the Externalizable interface, writeExternal and
32.170 + * readExternal, are called to save and restore the objects state. When
32.171 + * implemented by a class they can write and read their own state using all of
32.172 + * the methods of ObjectOutput and ObjectInput. It is the responsibility of
32.173 + * the objects to handle any versioning that occurs.
32.174 + *
32.175 + * <p>Enum constants are deserialized differently than ordinary serializable or
32.176 + * externalizable objects. The serialized form of an enum constant consists
32.177 + * solely of its name; field values of the constant are not transmitted. To
32.178 + * deserialize an enum constant, ObjectInputStream reads the constant name from
32.179 + * the stream; the deserialized constant is then obtained by calling the static
32.180 + * method <code>Enum.valueOf(Class, String)</code> with the enum constant's
32.181 + * base type and the received constant name as arguments. Like other
32.182 + * serializable or externalizable objects, enum constants can function as the
32.183 + * targets of back references appearing subsequently in the serialization
32.184 + * stream. The process by which enum constants are deserialized cannot be
32.185 + * customized: any class-specific readObject, readObjectNoData, and readResolve
32.186 + * methods defined by enum types are ignored during deserialization.
32.187 + * Similarly, any serialPersistentFields or serialVersionUID field declarations
32.188 + * are also ignored--all enum types have a fixed serialVersionUID of 0L.
32.189 + *
32.190 + * @author Mike Warres
32.191 + * @author Roger Riggs
32.192 + * @see java.io.DataInput
32.193 + * @see java.io.ObjectOutputStream
32.194 + * @see java.io.Serializable
32.195 + * @see <a href="../../../platform/serialization/spec/input.html"> Object Serialization Specification, Section 3, Object Input Classes</a>
32.196 + * @since JDK1.1
32.197 + */
32.198 +public class ObjectInputStream
32.199 + extends InputStream implements ObjectInput, ObjectStreamConstants
32.200 +{
32.201 + /** handle value representing null */
32.202 + private static final int NULL_HANDLE = -1;
32.203 +
32.204 + /** marker for unshared objects in internal handle table */
32.205 + private static final Object unsharedMarker = new Object();
32.206 +
32.207 + /** table mapping primitive type names to corresponding class objects */
32.208 + private static final HashMap<String, Class<?>> primClasses
32.209 + = new HashMap<>(8, 1.0F);
32.210 + static {
32.211 + primClasses.put("boolean", boolean.class);
32.212 + primClasses.put("byte", byte.class);
32.213 + primClasses.put("char", char.class);
32.214 + primClasses.put("short", short.class);
32.215 + primClasses.put("int", int.class);
32.216 + primClasses.put("long", long.class);
32.217 + primClasses.put("float", float.class);
32.218 + primClasses.put("double", double.class);
32.219 + primClasses.put("void", void.class);
32.220 + }
32.221 +
32.222 + /** filter stream for handling block data conversion */
32.223 + private final BlockDataInputStream bin;
32.224 + /** validation callback list */
32.225 + private final ValidationList vlist;
32.226 + /** recursion depth */
32.227 + private int depth;
32.228 + /** whether stream is closed */
32.229 + private boolean closed;
32.230 +
32.231 + /** wire handle -> obj/exception map */
32.232 + private final HandleTable handles;
32.233 + /** scratch field for passing handle values up/down call stack */
32.234 + private int passHandle = NULL_HANDLE;
32.235 + /** flag set when at end of field value block with no TC_ENDBLOCKDATA */
32.236 + private boolean defaultDataEnd = false;
32.237 +
32.238 + /** buffer for reading primitive field values */
32.239 + private byte[] primVals;
32.240 +
32.241 + /** if true, invoke readObjectOverride() instead of readObject() */
32.242 + private final boolean enableOverride;
32.243 + /** if true, invoke resolveObject() */
32.244 + private boolean enableResolve;
32.245 +
32.246 + /**
32.247 + * Context during upcalls to class-defined readObject methods; holds
32.248 + * object currently being deserialized and descriptor for current class.
32.249 + * Null when not during readObject upcall.
32.250 + */
32.251 + private Object curContext;
32.252 +
32.253 + /**
32.254 + * Creates an ObjectInputStream that reads from the specified InputStream.
32.255 + * A serialization stream header is read from the stream and verified.
32.256 + * This constructor will block until the corresponding ObjectOutputStream
32.257 + * has written and flushed the header.
32.258 + *
32.259 + * <p>If a security manager is installed, this constructor will check for
32.260 + * the "enableSubclassImplementation" SerializablePermission when invoked
32.261 + * directly or indirectly by the constructor of a subclass which overrides
32.262 + * the ObjectInputStream.readFields or ObjectInputStream.readUnshared
32.263 + * methods.
32.264 + *
32.265 + * @param in input stream to read from
32.266 + * @throws StreamCorruptedException if the stream header is incorrect
32.267 + * @throws IOException if an I/O error occurs while reading stream header
32.268 + * @throws SecurityException if untrusted subclass illegally overrides
32.269 + * security-sensitive methods
32.270 + * @throws NullPointerException if <code>in</code> is <code>null</code>
32.271 + * @see ObjectInputStream#ObjectInputStream()
32.272 + * @see ObjectInputStream#readFields()
32.273 + * @see ObjectOutputStream#ObjectOutputStream(OutputStream)
32.274 + */
32.275 + public ObjectInputStream(InputStream in) throws IOException {
32.276 + verifySubclass();
32.277 + bin = new BlockDataInputStream(in);
32.278 + handles = new HandleTable(10);
32.279 + vlist = new ValidationList();
32.280 + enableOverride = false;
32.281 + readStreamHeader();
32.282 + bin.setBlockDataMode(true);
32.283 + }
32.284 +
32.285 + /**
32.286 + * Provide a way for subclasses that are completely reimplementing
32.287 + * ObjectInputStream to not have to allocate private data just used by this
32.288 + * implementation of ObjectInputStream.
32.289 + *
32.290 + * <p>If there is a security manager installed, this method first calls the
32.291 + * security manager's <code>checkPermission</code> method with the
32.292 + * <code>SerializablePermission("enableSubclassImplementation")</code>
32.293 + * permission to ensure it's ok to enable subclassing.
32.294 + *
32.295 + * @throws SecurityException if a security manager exists and its
32.296 + * <code>checkPermission</code> method denies enabling
32.297 + * subclassing.
32.298 + * @see SecurityManager#checkPermission
32.299 + * @see java.io.SerializablePermission
32.300 + */
32.301 + protected ObjectInputStream() throws IOException, SecurityException {
32.302 + throw new SecurityException();
32.303 + }
32.304 +
32.305 + /**
32.306 + * Read an object from the ObjectInputStream. The class of the object, the
32.307 + * signature of the class, and the values of the non-transient and
32.308 + * non-static fields of the class and all of its supertypes are read.
32.309 + * Default deserializing for a class can be overriden using the writeObject
32.310 + * and readObject methods. Objects referenced by this object are read
32.311 + * transitively so that a complete equivalent graph of objects is
32.312 + * reconstructed by readObject.
32.313 + *
32.314 + * <p>The root object is completely restored when all of its fields and the
32.315 + * objects it references are completely restored. At this point the object
32.316 + * validation callbacks are executed in order based on their registered
32.317 + * priorities. The callbacks are registered by objects (in the readObject
32.318 + * special methods) as they are individually restored.
32.319 + *
32.320 + * <p>Exceptions are thrown for problems with the InputStream and for
32.321 + * classes that should not be deserialized. All exceptions are fatal to
32.322 + * the InputStream and leave it in an indeterminate state; it is up to the
32.323 + * caller to ignore or recover the stream state.
32.324 + *
32.325 + * @throws ClassNotFoundException Class of a serialized object cannot be
32.326 + * found.
32.327 + * @throws InvalidClassException Something is wrong with a class used by
32.328 + * serialization.
32.329 + * @throws StreamCorruptedException Control information in the
32.330 + * stream is inconsistent.
32.331 + * @throws OptionalDataException Primitive data was found in the
32.332 + * stream instead of objects.
32.333 + * @throws IOException Any of the usual Input/Output related exceptions.
32.334 + */
32.335 + public final Object readObject()
32.336 + throws IOException, ClassNotFoundException
32.337 + {
32.338 + throw new IOException();
32.339 + }
32.340 +
32.341 + /**
32.342 + * This method is called by trusted subclasses of ObjectOutputStream that
32.343 + * constructed ObjectOutputStream using the protected no-arg constructor.
32.344 + * The subclass is expected to provide an override method with the modifier
32.345 + * "final".
32.346 + *
32.347 + * @return the Object read from the stream.
32.348 + * @throws ClassNotFoundException Class definition of a serialized object
32.349 + * cannot be found.
32.350 + * @throws OptionalDataException Primitive data was found in the stream
32.351 + * instead of objects.
32.352 + * @throws IOException if I/O errors occurred while reading from the
32.353 + * underlying stream
32.354 + * @see #ObjectInputStream()
32.355 + * @see #readObject()
32.356 + * @since 1.2
32.357 + */
32.358 + protected Object readObjectOverride()
32.359 + throws IOException, ClassNotFoundException
32.360 + {
32.361 + return null;
32.362 + }
32.363 +
32.364 + /**
32.365 + * Reads an "unshared" object from the ObjectInputStream. This method is
32.366 + * identical to readObject, except that it prevents subsequent calls to
32.367 + * readObject and readUnshared from returning additional references to the
32.368 + * deserialized instance obtained via this call. Specifically:
32.369 + * <ul>
32.370 + * <li>If readUnshared is called to deserialize a back-reference (the
32.371 + * stream representation of an object which has been written
32.372 + * previously to the stream), an ObjectStreamException will be
32.373 + * thrown.
32.374 + *
32.375 + * <li>If readUnshared returns successfully, then any subsequent attempts
32.376 + * to deserialize back-references to the stream handle deserialized
32.377 + * by readUnshared will cause an ObjectStreamException to be thrown.
32.378 + * </ul>
32.379 + * Deserializing an object via readUnshared invalidates the stream handle
32.380 + * associated with the returned object. Note that this in itself does not
32.381 + * always guarantee that the reference returned by readUnshared is unique;
32.382 + * the deserialized object may define a readResolve method which returns an
32.383 + * object visible to other parties, or readUnshared may return a Class
32.384 + * object or enum constant obtainable elsewhere in the stream or through
32.385 + * external means. If the deserialized object defines a readResolve method
32.386 + * and the invocation of that method returns an array, then readUnshared
32.387 + * returns a shallow clone of that array; this guarantees that the returned
32.388 + * array object is unique and cannot be obtained a second time from an
32.389 + * invocation of readObject or readUnshared on the ObjectInputStream,
32.390 + * even if the underlying data stream has been manipulated.
32.391 + *
32.392 + * <p>ObjectInputStream subclasses which override this method can only be
32.393 + * constructed in security contexts possessing the
32.394 + * "enableSubclassImplementation" SerializablePermission; any attempt to
32.395 + * instantiate such a subclass without this permission will cause a
32.396 + * SecurityException to be thrown.
32.397 + *
32.398 + * @return reference to deserialized object
32.399 + * @throws ClassNotFoundException if class of an object to deserialize
32.400 + * cannot be found
32.401 + * @throws StreamCorruptedException if control information in the stream
32.402 + * is inconsistent
32.403 + * @throws ObjectStreamException if object to deserialize has already
32.404 + * appeared in stream
32.405 + * @throws OptionalDataException if primitive data is next in stream
32.406 + * @throws IOException if an I/O error occurs during deserialization
32.407 + * @since 1.4
32.408 + */
32.409 + public Object readUnshared() throws IOException, ClassNotFoundException {
32.410 + // if nested read, passHandle contains handle of enclosing object
32.411 + int outerHandle = passHandle;
32.412 + try {
32.413 + Object obj = readObject0(true);
32.414 + handles.markDependency(outerHandle, passHandle);
32.415 + ClassNotFoundException ex = handles.lookupException(passHandle);
32.416 + if (ex != null) {
32.417 + throw ex;
32.418 + }
32.419 + if (depth == 0) {
32.420 + vlist.doCallbacks();
32.421 + }
32.422 + return obj;
32.423 + } finally {
32.424 + passHandle = outerHandle;
32.425 + if (closed && depth == 0) {
32.426 + clear();
32.427 + }
32.428 + }
32.429 + }
32.430 +
32.431 + /**
32.432 + * Read the non-static and non-transient fields of the current class from
32.433 + * this stream. This may only be called from the readObject method of the
32.434 + * class being deserialized. It will throw the NotActiveException if it is
32.435 + * called otherwise.
32.436 + *
32.437 + * @throws ClassNotFoundException if the class of a serialized object
32.438 + * could not be found.
32.439 + * @throws IOException if an I/O error occurs.
32.440 + * @throws NotActiveException if the stream is not currently reading
32.441 + * objects.
32.442 + */
32.443 + public void defaultReadObject()
32.444 + throws IOException, ClassNotFoundException
32.445 + {
32.446 + if (curContext == null) {
32.447 + throw new NotActiveException("not in call to readObject");
32.448 + }
32.449 + Object curObj = null; // curContext.getObj();
32.450 + ObjectStreamClass curDesc = null; // curContext.getDesc();
32.451 + bin.setBlockDataMode(false);
32.452 + defaultReadFields(curObj, curDesc);
32.453 + bin.setBlockDataMode(true);
32.454 + if (!curDesc.hasWriteObjectData()) {
32.455 + /*
32.456 + * Fix for 4360508: since stream does not contain terminating
32.457 + * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
32.458 + * knows to simulate end-of-custom-data behavior.
32.459 + */
32.460 + defaultDataEnd = true;
32.461 + }
32.462 + ClassNotFoundException ex = handles.lookupException(passHandle);
32.463 + if (ex != null) {
32.464 + throw ex;
32.465 + }
32.466 + }
32.467 +
32.468 + /**
32.469 + * Reads the persistent fields from the stream and makes them available by
32.470 + * name.
32.471 + *
32.472 + * @return the <code>GetField</code> object representing the persistent
32.473 + * fields of the object being deserialized
32.474 + * @throws ClassNotFoundException if the class of a serialized object
32.475 + * could not be found.
32.476 + * @throws IOException if an I/O error occurs.
32.477 + * @throws NotActiveException if the stream is not currently reading
32.478 + * objects.
32.479 + * @since 1.2
32.480 + */
32.481 + public ObjectInputStream.GetField readFields()
32.482 + throws IOException, ClassNotFoundException
32.483 + {
32.484 + if (curContext == null) {
32.485 + throw new NotActiveException("not in call to readObject");
32.486 + }
32.487 + Object curObj = null; // curContext.getObj();
32.488 + ObjectStreamClass curDesc = null; // curContext.getDesc();
32.489 + bin.setBlockDataMode(false);
32.490 + GetFieldImpl getField = new GetFieldImpl(curDesc);
32.491 + getField.readFields();
32.492 + bin.setBlockDataMode(true);
32.493 + if (!curDesc.hasWriteObjectData()) {
32.494 + /*
32.495 + * Fix for 4360508: since stream does not contain terminating
32.496 + * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
32.497 + * knows to simulate end-of-custom-data behavior.
32.498 + */
32.499 + defaultDataEnd = true;
32.500 + }
32.501 +
32.502 + return getField;
32.503 + }
32.504 +
32.505 + /**
32.506 + * Register an object to be validated before the graph is returned. While
32.507 + * similar to resolveObject these validations are called after the entire
32.508 + * graph has been reconstituted. Typically, a readObject method will
32.509 + * register the object with the stream so that when all of the objects are
32.510 + * restored a final set of validations can be performed.
32.511 + *
32.512 + * @param obj the object to receive the validation callback.
32.513 + * @param prio controls the order of callbacks;zero is a good default.
32.514 + * Use higher numbers to be called back earlier, lower numbers for
32.515 + * later callbacks. Within a priority, callbacks are processed in
32.516 + * no particular order.
32.517 + * @throws NotActiveException The stream is not currently reading objects
32.518 + * so it is invalid to register a callback.
32.519 + * @throws InvalidObjectException The validation object is null.
32.520 + */
32.521 + public void registerValidation(ObjectInputValidation obj, int prio)
32.522 + throws NotActiveException, InvalidObjectException
32.523 + {
32.524 + if (depth == 0) {
32.525 + throw new NotActiveException("stream inactive");
32.526 + }
32.527 + vlist.register(obj, prio);
32.528 + }
32.529 +
32.530 + /**
32.531 + * Load the local class equivalent of the specified stream class
32.532 + * description. Subclasses may implement this method to allow classes to
32.533 + * be fetched from an alternate source.
32.534 + *
32.535 + * <p>The corresponding method in <code>ObjectOutputStream</code> is
32.536 + * <code>annotateClass</code>. This method will be invoked only once for
32.537 + * each unique class in the stream. This method can be implemented by
32.538 + * subclasses to use an alternate loading mechanism but must return a
32.539 + * <code>Class</code> object. Once returned, if the class is not an array
32.540 + * class, its serialVersionUID is compared to the serialVersionUID of the
32.541 + * serialized class, and if there is a mismatch, the deserialization fails
32.542 + * and an {@link InvalidClassException} is thrown.
32.543 + *
32.544 + * <p>The default implementation of this method in
32.545 + * <code>ObjectInputStream</code> returns the result of calling
32.546 + * <pre>
32.547 + * Class.forName(desc.getName(), false, loader)
32.548 + * </pre>
32.549 + * where <code>loader</code> is determined as follows: if there is a
32.550 + * method on the current thread's stack whose declaring class was
32.551 + * defined by a user-defined class loader (and was not a generated to
32.552 + * implement reflective invocations), then <code>loader</code> is class
32.553 + * loader corresponding to the closest such method to the currently
32.554 + * executing frame; otherwise, <code>loader</code> is
32.555 + * <code>null</code>. If this call results in a
32.556 + * <code>ClassNotFoundException</code> and the name of the passed
32.557 + * <code>ObjectStreamClass</code> instance is the Java language keyword
32.558 + * for a primitive type or void, then the <code>Class</code> object
32.559 + * representing that primitive type or void will be returned
32.560 + * (e.g., an <code>ObjectStreamClass</code> with the name
32.561 + * <code>"int"</code> will be resolved to <code>Integer.TYPE</code>).
32.562 + * Otherwise, the <code>ClassNotFoundException</code> will be thrown to
32.563 + * the caller of this method.
32.564 + *
32.565 + * @param desc an instance of class <code>ObjectStreamClass</code>
32.566 + * @return a <code>Class</code> object corresponding to <code>desc</code>
32.567 + * @throws IOException any of the usual Input/Output exceptions.
32.568 + * @throws ClassNotFoundException if class of a serialized object cannot
32.569 + * be found.
32.570 + */
32.571 + protected Class<?> resolveClass(ObjectStreamClass desc)
32.572 + throws IOException, ClassNotFoundException
32.573 + {
32.574 + String name = desc.getName();
32.575 + try {
32.576 + return Class.forName(name, false, latestUserDefinedLoader());
32.577 + } catch (ClassNotFoundException ex) {
32.578 + Class<?> cl = primClasses.get(name);
32.579 + if (cl != null) {
32.580 + return cl;
32.581 + } else {
32.582 + throw ex;
32.583 + }
32.584 + }
32.585 + }
32.586 +
32.587 + /**
32.588 + * Returns a proxy class that implements the interfaces named in a proxy
32.589 + * class descriptor; subclasses may implement this method to read custom
32.590 + * data from the stream along with the descriptors for dynamic proxy
32.591 + * classes, allowing them to use an alternate loading mechanism for the
32.592 + * interfaces and the proxy class.
32.593 + *
32.594 + * <p>This method is called exactly once for each unique proxy class
32.595 + * descriptor in the stream.
32.596 + *
32.597 + * <p>The corresponding method in <code>ObjectOutputStream</code> is
32.598 + * <code>annotateProxyClass</code>. For a given subclass of
32.599 + * <code>ObjectInputStream</code> that overrides this method, the
32.600 + * <code>annotateProxyClass</code> method in the corresponding subclass of
32.601 + * <code>ObjectOutputStream</code> must write any data or objects read by
32.602 + * this method.
32.603 + *
32.604 + * <p>The default implementation of this method in
32.605 + * <code>ObjectInputStream</code> returns the result of calling
32.606 + * <code>Proxy.getProxyClass</code> with the list of <code>Class</code>
32.607 + * objects for the interfaces that are named in the <code>interfaces</code>
32.608 + * parameter. The <code>Class</code> object for each interface name
32.609 + * <code>i</code> is the value returned by calling
32.610 + * <pre>
32.611 + * Class.forName(i, false, loader)
32.612 + * </pre>
32.613 + * where <code>loader</code> is that of the first non-<code>null</code>
32.614 + * class loader up the execution stack, or <code>null</code> if no
32.615 + * non-<code>null</code> class loaders are on the stack (the same class
32.616 + * loader choice used by the <code>resolveClass</code> method). Unless any
32.617 + * of the resolved interfaces are non-public, this same value of
32.618 + * <code>loader</code> is also the class loader passed to
32.619 + * <code>Proxy.getProxyClass</code>; if non-public interfaces are present,
32.620 + * their class loader is passed instead (if more than one non-public
32.621 + * interface class loader is encountered, an
32.622 + * <code>IllegalAccessError</code> is thrown).
32.623 + * If <code>Proxy.getProxyClass</code> throws an
32.624 + * <code>IllegalArgumentException</code>, <code>resolveProxyClass</code>
32.625 + * will throw a <code>ClassNotFoundException</code> containing the
32.626 + * <code>IllegalArgumentException</code>.
32.627 + *
32.628 + * @param interfaces the list of interface names that were
32.629 + * deserialized in the proxy class descriptor
32.630 + * @return a proxy class for the specified interfaces
32.631 + * @throws IOException any exception thrown by the underlying
32.632 + * <code>InputStream</code>
32.633 + * @throws ClassNotFoundException if the proxy class or any of the
32.634 + * named interfaces could not be found
32.635 + * @see ObjectOutputStream#annotateProxyClass(Class)
32.636 + * @since 1.3
32.637 + */
32.638 + protected Class<?> resolveProxyClass(String[] interfaces)
32.639 + throws IOException, ClassNotFoundException
32.640 + {
32.641 + ClassLoader latestLoader = latestUserDefinedLoader();
32.642 + ClassLoader nonPublicLoader = null;
32.643 + boolean hasNonPublicInterface = false;
32.644 +
32.645 + // define proxy in class loader of non-public interface(s), if any
32.646 + Class[] classObjs = new Class[interfaces.length];
32.647 + for (int i = 0; i < interfaces.length; i++) {
32.648 + Class cl = Class.forName(interfaces[i], false, latestLoader);
32.649 + if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
32.650 + if (hasNonPublicInterface) {
32.651 + if (nonPublicLoader != cl.getClassLoader()) {
32.652 + throw new IllegalAccessError(
32.653 + "conflicting non-public interface class loaders");
32.654 + }
32.655 + } else {
32.656 + nonPublicLoader = cl.getClassLoader();
32.657 + hasNonPublicInterface = true;
32.658 + }
32.659 + }
32.660 + classObjs[i] = cl;
32.661 + }
32.662 + try {
32.663 + return Proxy.getProxyClass(
32.664 + hasNonPublicInterface ? nonPublicLoader : latestLoader,
32.665 + classObjs);
32.666 + } catch (IllegalArgumentException e) {
32.667 + throw new ClassNotFoundException(null, e);
32.668 + }
32.669 + }
32.670 +
32.671 + /**
32.672 + * This method will allow trusted subclasses of ObjectInputStream to
32.673 + * substitute one object for another during deserialization. Replacing
32.674 + * objects is disabled until enableResolveObject is called. The
32.675 + * enableResolveObject method checks that the stream requesting to resolve
32.676 + * object can be trusted. Every reference to serializable objects is passed
32.677 + * to resolveObject. To insure that the private state of objects is not
32.678 + * unintentionally exposed only trusted streams may use resolveObject.
32.679 + *
32.680 + * <p>This method is called after an object has been read but before it is
32.681 + * returned from readObject. The default resolveObject method just returns
32.682 + * the same object.
32.683 + *
32.684 + * <p>When a subclass is replacing objects it must insure that the
32.685 + * substituted object is compatible with every field where the reference
32.686 + * will be stored. Objects whose type is not a subclass of the type of the
32.687 + * field or array element abort the serialization by raising an exception
32.688 + * and the object is not be stored.
32.689 + *
32.690 + * <p>This method is called only once when each object is first
32.691 + * encountered. All subsequent references to the object will be redirected
32.692 + * to the new object.
32.693 + *
32.694 + * @param obj object to be substituted
32.695 + * @return the substituted object
32.696 + * @throws IOException Any of the usual Input/Output exceptions.
32.697 + */
32.698 + protected Object resolveObject(Object obj) throws IOException {
32.699 + return obj;
32.700 + }
32.701 +
32.702 + /**
32.703 + * Enable the stream to allow objects read from the stream to be replaced.
32.704 + * When enabled, the resolveObject method is called for every object being
32.705 + * deserialized.
32.706 + *
32.707 + * <p>If <i>enable</i> is true, and there is a security manager installed,
32.708 + * this method first calls the security manager's
32.709 + * <code>checkPermission</code> method with the
32.710 + * <code>SerializablePermission("enableSubstitution")</code> permission to
32.711 + * ensure it's ok to enable the stream to allow objects read from the
32.712 + * stream to be replaced.
32.713 + *
32.714 + * @param enable true for enabling use of <code>resolveObject</code> for
32.715 + * every object being deserialized
32.716 + * @return the previous setting before this method was invoked
32.717 + * @throws SecurityException if a security manager exists and its
32.718 + * <code>checkPermission</code> method denies enabling the stream
32.719 + * to allow objects read from the stream to be replaced.
32.720 + * @see SecurityManager#checkPermission
32.721 + * @see java.io.SerializablePermission
32.722 + */
32.723 + protected boolean enableResolveObject(boolean enable)
32.724 + throws SecurityException
32.725 + {
32.726 + throw new SecurityException();
32.727 + }
32.728 +
32.729 + /**
32.730 + * The readStreamHeader method is provided to allow subclasses to read and
32.731 + * verify their own stream headers. It reads and verifies the magic number
32.732 + * and version number.
32.733 + *
32.734 + * @throws IOException if there are I/O errors while reading from the
32.735 + * underlying <code>InputStream</code>
32.736 + * @throws StreamCorruptedException if control information in the stream
32.737 + * is inconsistent
32.738 + */
32.739 + protected void readStreamHeader()
32.740 + throws IOException, StreamCorruptedException
32.741 + {
32.742 + short s0 = bin.readShort();
32.743 + short s1 = bin.readShort();
32.744 + if (s0 != STREAM_MAGIC || s1 != STREAM_VERSION) {
32.745 + throw new StreamCorruptedException(
32.746 + String.format("invalid stream header: %04X%04X", s0, s1));
32.747 + }
32.748 + }
32.749 +
32.750 + /**
32.751 + * Read a class descriptor from the serialization stream. This method is
32.752 + * called when the ObjectInputStream expects a class descriptor as the next
32.753 + * item in the serialization stream. Subclasses of ObjectInputStream may
32.754 + * override this method to read in class descriptors that have been written
32.755 + * in non-standard formats (by subclasses of ObjectOutputStream which have
32.756 + * overridden the <code>writeClassDescriptor</code> method). By default,
32.757 + * this method reads class descriptors according to the format defined in
32.758 + * the Object Serialization specification.
32.759 + *
32.760 + * @return the class descriptor read
32.761 + * @throws IOException If an I/O error has occurred.
32.762 + * @throws ClassNotFoundException If the Class of a serialized object used
32.763 + * in the class descriptor representation cannot be found
32.764 + * @see java.io.ObjectOutputStream#writeClassDescriptor(java.io.ObjectStreamClass)
32.765 + * @since 1.3
32.766 + */
32.767 + protected ObjectStreamClass readClassDescriptor()
32.768 + throws IOException, ClassNotFoundException
32.769 + {
32.770 + ObjectStreamClass desc = new ObjectStreamClass();
32.771 + desc.readNonProxy(this);
32.772 + return desc;
32.773 + }
32.774 +
32.775 + /**
32.776 + * Reads a byte of data. This method will block if no input is available.
32.777 + *
32.778 + * @return the byte read, or -1 if the end of the stream is reached.
32.779 + * @throws IOException If an I/O error has occurred.
32.780 + */
32.781 + public int read() throws IOException {
32.782 + return bin.read();
32.783 + }
32.784 +
32.785 + /**
32.786 + * Reads into an array of bytes. This method will block until some input
32.787 + * is available. Consider using java.io.DataInputStream.readFully to read
32.788 + * exactly 'length' bytes.
32.789 + *
32.790 + * @param buf the buffer into which the data is read
32.791 + * @param off the start offset of the data
32.792 + * @param len the maximum number of bytes read
32.793 + * @return the actual number of bytes read, -1 is returned when the end of
32.794 + * the stream is reached.
32.795 + * @throws IOException If an I/O error has occurred.
32.796 + * @see java.io.DataInputStream#readFully(byte[],int,int)
32.797 + */
32.798 + public int read(byte[] buf, int off, int len) throws IOException {
32.799 + if (buf == null) {
32.800 + throw new NullPointerException();
32.801 + }
32.802 + int endoff = off + len;
32.803 + if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
32.804 + throw new IndexOutOfBoundsException();
32.805 + }
32.806 + return bin.read(buf, off, len, false);
32.807 + }
32.808 +
32.809 + /**
32.810 + * Returns the number of bytes that can be read without blocking.
32.811 + *
32.812 + * @return the number of available bytes.
32.813 + * @throws IOException if there are I/O errors while reading from the
32.814 + * underlying <code>InputStream</code>
32.815 + */
32.816 + public int available() throws IOException {
32.817 + return bin.available();
32.818 + }
32.819 +
32.820 + /**
32.821 + * Closes the input stream. Must be called to release any resources
32.822 + * associated with the stream.
32.823 + *
32.824 + * @throws IOException If an I/O error has occurred.
32.825 + */
32.826 + public void close() throws IOException {
32.827 + /*
32.828 + * Even if stream already closed, propagate redundant close to
32.829 + * underlying stream to stay consistent with previous implementations.
32.830 + */
32.831 + closed = true;
32.832 + if (depth == 0) {
32.833 + clear();
32.834 + }
32.835 + bin.close();
32.836 + }
32.837 +
32.838 + /**
32.839 + * Reads in a boolean.
32.840 + *
32.841 + * @return the boolean read.
32.842 + * @throws EOFException If end of file is reached.
32.843 + * @throws IOException If other I/O error has occurred.
32.844 + */
32.845 + public boolean readBoolean() throws IOException {
32.846 + return bin.readBoolean();
32.847 + }
32.848 +
32.849 + /**
32.850 + * Reads an 8 bit byte.
32.851 + *
32.852 + * @return the 8 bit byte read.
32.853 + * @throws EOFException If end of file is reached.
32.854 + * @throws IOException If other I/O error has occurred.
32.855 + */
32.856 + public byte readByte() throws IOException {
32.857 + return bin.readByte();
32.858 + }
32.859 +
32.860 + /**
32.861 + * Reads an unsigned 8 bit byte.
32.862 + *
32.863 + * @return the 8 bit byte read.
32.864 + * @throws EOFException If end of file is reached.
32.865 + * @throws IOException If other I/O error has occurred.
32.866 + */
32.867 + public int readUnsignedByte() throws IOException {
32.868 + return bin.readUnsignedByte();
32.869 + }
32.870 +
32.871 + /**
32.872 + * Reads a 16 bit char.
32.873 + *
32.874 + * @return the 16 bit char read.
32.875 + * @throws EOFException If end of file is reached.
32.876 + * @throws IOException If other I/O error has occurred.
32.877 + */
32.878 + public char readChar() throws IOException {
32.879 + return bin.readChar();
32.880 + }
32.881 +
32.882 + /**
32.883 + * Reads a 16 bit short.
32.884 + *
32.885 + * @return the 16 bit short read.
32.886 + * @throws EOFException If end of file is reached.
32.887 + * @throws IOException If other I/O error has occurred.
32.888 + */
32.889 + public short readShort() throws IOException {
32.890 + return bin.readShort();
32.891 + }
32.892 +
32.893 + /**
32.894 + * Reads an unsigned 16 bit short.
32.895 + *
32.896 + * @return the 16 bit short read.
32.897 + * @throws EOFException If end of file is reached.
32.898 + * @throws IOException If other I/O error has occurred.
32.899 + */
32.900 + public int readUnsignedShort() throws IOException {
32.901 + return bin.readUnsignedShort();
32.902 + }
32.903 +
32.904 + /**
32.905 + * Reads a 32 bit int.
32.906 + *
32.907 + * @return the 32 bit integer read.
32.908 + * @throws EOFException If end of file is reached.
32.909 + * @throws IOException If other I/O error has occurred.
32.910 + */
32.911 + public int readInt() throws IOException {
32.912 + return bin.readInt();
32.913 + }
32.914 +
32.915 + /**
32.916 + * Reads a 64 bit long.
32.917 + *
32.918 + * @return the read 64 bit long.
32.919 + * @throws EOFException If end of file is reached.
32.920 + * @throws IOException If other I/O error has occurred.
32.921 + */
32.922 + public long readLong() throws IOException {
32.923 + return bin.readLong();
32.924 + }
32.925 +
32.926 + /**
32.927 + * Reads a 32 bit float.
32.928 + *
32.929 + * @return the 32 bit float read.
32.930 + * @throws EOFException If end of file is reached.
32.931 + * @throws IOException If other I/O error has occurred.
32.932 + */
32.933 + public float readFloat() throws IOException {
32.934 + return bin.readFloat();
32.935 + }
32.936 +
32.937 + /**
32.938 + * Reads a 64 bit double.
32.939 + *
32.940 + * @return the 64 bit double read.
32.941 + * @throws EOFException If end of file is reached.
32.942 + * @throws IOException If other I/O error has occurred.
32.943 + */
32.944 + public double readDouble() throws IOException {
32.945 + return bin.readDouble();
32.946 + }
32.947 +
32.948 + /**
32.949 + * Reads bytes, blocking until all bytes are read.
32.950 + *
32.951 + * @param buf the buffer into which the data is read
32.952 + * @throws EOFException If end of file is reached.
32.953 + * @throws IOException If other I/O error has occurred.
32.954 + */
32.955 + public void readFully(byte[] buf) throws IOException {
32.956 + bin.readFully(buf, 0, buf.length, false);
32.957 + }
32.958 +
32.959 + /**
32.960 + * Reads bytes, blocking until all bytes are read.
32.961 + *
32.962 + * @param buf the buffer into which the data is read
32.963 + * @param off the start offset of the data
32.964 + * @param len the maximum number of bytes to read
32.965 + * @throws EOFException If end of file is reached.
32.966 + * @throws IOException If other I/O error has occurred.
32.967 + */
32.968 + public void readFully(byte[] buf, int off, int len) throws IOException {
32.969 + int endoff = off + len;
32.970 + if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
32.971 + throw new IndexOutOfBoundsException();
32.972 + }
32.973 + bin.readFully(buf, off, len, false);
32.974 + }
32.975 +
32.976 + /**
32.977 + * Skips bytes.
32.978 + *
32.979 + * @param len the number of bytes to be skipped
32.980 + * @return the actual number of bytes skipped.
32.981 + * @throws IOException If an I/O error has occurred.
32.982 + */
32.983 + public int skipBytes(int len) throws IOException {
32.984 + return bin.skipBytes(len);
32.985 + }
32.986 +
32.987 + /**
32.988 + * Reads in a line that has been terminated by a \n, \r, \r\n or EOF.
32.989 + *
32.990 + * @return a String copy of the line.
32.991 + * @throws IOException if there are I/O errors while reading from the
32.992 + * underlying <code>InputStream</code>
32.993 + * @deprecated This method does not properly convert bytes to characters.
32.994 + * see DataInputStream for the details and alternatives.
32.995 + */
32.996 + @Deprecated
32.997 + public String readLine() throws IOException {
32.998 + return bin.readLine();
32.999 + }
32.1000 +
32.1001 + /**
32.1002 + * Reads a String in
32.1003 + * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
32.1004 + * format.
32.1005 + *
32.1006 + * @return the String.
32.1007 + * @throws IOException if there are I/O errors while reading from the
32.1008 + * underlying <code>InputStream</code>
32.1009 + * @throws UTFDataFormatException if read bytes do not represent a valid
32.1010 + * modified UTF-8 encoding of a string
32.1011 + */
32.1012 + public String readUTF() throws IOException {
32.1013 + return bin.readUTF();
32.1014 + }
32.1015 +
32.1016 + /**
32.1017 + * Provide access to the persistent fields read from the input stream.
32.1018 + */
32.1019 + public static abstract class GetField {
32.1020 +
32.1021 + /**
32.1022 + * Get the ObjectStreamClass that describes the fields in the stream.
32.1023 + *
32.1024 + * @return the descriptor class that describes the serializable fields
32.1025 + */
32.1026 + public abstract ObjectStreamClass getObjectStreamClass();
32.1027 +
32.1028 + /**
32.1029 + * Return true if the named field is defaulted and has no value in this
32.1030 + * stream.
32.1031 + *
32.1032 + * @param name the name of the field
32.1033 + * @return true, if and only if the named field is defaulted
32.1034 + * @throws IOException if there are I/O errors while reading from
32.1035 + * the underlying <code>InputStream</code>
32.1036 + * @throws IllegalArgumentException if <code>name</code> does not
32.1037 + * correspond to a serializable field
32.1038 + */
32.1039 + public abstract boolean defaulted(String name) throws IOException;
32.1040 +
32.1041 + /**
32.1042 + * Get the value of the named boolean field from the persistent field.
32.1043 + *
32.1044 + * @param name the name of the field
32.1045 + * @param val the default value to use if <code>name</code> does not
32.1046 + * have a value
32.1047 + * @return the value of the named <code>boolean</code> field
32.1048 + * @throws IOException if there are I/O errors while reading from the
32.1049 + * underlying <code>InputStream</code>
32.1050 + * @throws IllegalArgumentException if type of <code>name</code> is
32.1051 + * not serializable or if the field type is incorrect
32.1052 + */
32.1053 + public abstract boolean get(String name, boolean val)
32.1054 + throws IOException;
32.1055 +
32.1056 + /**
32.1057 + * Get the value of the named byte field from the persistent field.
32.1058 + *
32.1059 + * @param name the name of the field
32.1060 + * @param val the default value to use if <code>name</code> does not
32.1061 + * have a value
32.1062 + * @return the value of the named <code>byte</code> field
32.1063 + * @throws IOException if there are I/O errors while reading from the
32.1064 + * underlying <code>InputStream</code>
32.1065 + * @throws IllegalArgumentException if type of <code>name</code> is
32.1066 + * not serializable or if the field type is incorrect
32.1067 + */
32.1068 + public abstract byte get(String name, byte val) throws IOException;
32.1069 +
32.1070 + /**
32.1071 + * Get the value of the named char field from the persistent field.
32.1072 + *
32.1073 + * @param name the name of the field
32.1074 + * @param val the default value to use if <code>name</code> does not
32.1075 + * have a value
32.1076 + * @return the value of the named <code>char</code> field
32.1077 + * @throws IOException if there are I/O errors while reading from the
32.1078 + * underlying <code>InputStream</code>
32.1079 + * @throws IllegalArgumentException if type of <code>name</code> is
32.1080 + * not serializable or if the field type is incorrect
32.1081 + */
32.1082 + public abstract char get(String name, char val) throws IOException;
32.1083 +
32.1084 + /**
32.1085 + * Get the value of the named short field from the persistent field.
32.1086 + *
32.1087 + * @param name the name of the field
32.1088 + * @param val the default value to use if <code>name</code> does not
32.1089 + * have a value
32.1090 + * @return the value of the named <code>short</code> field
32.1091 + * @throws IOException if there are I/O errors while reading from the
32.1092 + * underlying <code>InputStream</code>
32.1093 + * @throws IllegalArgumentException if type of <code>name</code> is
32.1094 + * not serializable or if the field type is incorrect
32.1095 + */
32.1096 + public abstract short get(String name, short val) throws IOException;
32.1097 +
32.1098 + /**
32.1099 + * Get the value of the named int field from the persistent field.
32.1100 + *
32.1101 + * @param name the name of the field
32.1102 + * @param val the default value to use if <code>name</code> does not
32.1103 + * have a value
32.1104 + * @return the value of the named <code>int</code> field
32.1105 + * @throws IOException if there are I/O errors while reading from the
32.1106 + * underlying <code>InputStream</code>
32.1107 + * @throws IllegalArgumentException if type of <code>name</code> is
32.1108 + * not serializable or if the field type is incorrect
32.1109 + */
32.1110 + public abstract int get(String name, int val) throws IOException;
32.1111 +
32.1112 + /**
32.1113 + * Get the value of the named long field from the persistent field.
32.1114 + *
32.1115 + * @param name the name of the field
32.1116 + * @param val the default value to use if <code>name</code> does not
32.1117 + * have a value
32.1118 + * @return the value of the named <code>long</code> field
32.1119 + * @throws IOException if there are I/O errors while reading from the
32.1120 + * underlying <code>InputStream</code>
32.1121 + * @throws IllegalArgumentException if type of <code>name</code> is
32.1122 + * not serializable or if the field type is incorrect
32.1123 + */
32.1124 + public abstract long get(String name, long val) throws IOException;
32.1125 +
32.1126 + /**
32.1127 + * Get the value of the named float field from the persistent field.
32.1128 + *
32.1129 + * @param name the name of the field
32.1130 + * @param val the default value to use if <code>name</code> does not
32.1131 + * have a value
32.1132 + * @return the value of the named <code>float</code> field
32.1133 + * @throws IOException if there are I/O errors while reading from the
32.1134 + * underlying <code>InputStream</code>
32.1135 + * @throws IllegalArgumentException if type of <code>name</code> is
32.1136 + * not serializable or if the field type is incorrect
32.1137 + */
32.1138 + public abstract float get(String name, float val) throws IOException;
32.1139 +
32.1140 + /**
32.1141 + * Get the value of the named double field from the persistent field.
32.1142 + *
32.1143 + * @param name the name of the field
32.1144 + * @param val the default value to use if <code>name</code> does not
32.1145 + * have a value
32.1146 + * @return the value of the named <code>double</code> field
32.1147 + * @throws IOException if there are I/O errors while reading from the
32.1148 + * underlying <code>InputStream</code>
32.1149 + * @throws IllegalArgumentException if type of <code>name</code> is
32.1150 + * not serializable or if the field type is incorrect
32.1151 + */
32.1152 + public abstract double get(String name, double val) throws IOException;
32.1153 +
32.1154 + /**
32.1155 + * Get the value of the named Object field from the persistent field.
32.1156 + *
32.1157 + * @param name the name of the field
32.1158 + * @param val the default value to use if <code>name</code> does not
32.1159 + * have a value
32.1160 + * @return the value of the named <code>Object</code> field
32.1161 + * @throws IOException if there are I/O errors while reading from the
32.1162 + * underlying <code>InputStream</code>
32.1163 + * @throws IllegalArgumentException if type of <code>name</code> is
32.1164 + * not serializable or if the field type is incorrect
32.1165 + */
32.1166 + public abstract Object get(String name, Object val) throws IOException;
32.1167 + }
32.1168 +
32.1169 + /**
32.1170 + * Verifies that this (possibly subclass) instance can be constructed
32.1171 + * without violating security constraints: the subclass must not override
32.1172 + * security-sensitive non-final methods, or else the
32.1173 + * "enableSubclassImplementation" SerializablePermission is checked.
32.1174 + */
32.1175 + private void verifySubclass() {
32.1176 + Class cl = getClass();
32.1177 + if (cl == ObjectInputStream.class) {
32.1178 + return;
32.1179 + }
32.1180 + throw new SecurityException();
32.1181 + }
32.1182 +
32.1183 + /**
32.1184 + * Clears internal data structures.
32.1185 + */
32.1186 + private void clear() {
32.1187 + handles.clear();
32.1188 + vlist.clear();
32.1189 + }
32.1190 +
32.1191 + /**
32.1192 + * Underlying readObject implementation.
32.1193 + */
32.1194 + private Object readObject0(boolean unshared) throws IOException {
32.1195 + boolean oldMode = bin.getBlockDataMode();
32.1196 + if (oldMode) {
32.1197 + int remain = bin.currentBlockRemaining();
32.1198 + if (remain > 0) {
32.1199 + throw new OptionalDataException(remain);
32.1200 + } else if (defaultDataEnd) {
32.1201 + /*
32.1202 + * Fix for 4360508: stream is currently at the end of a field
32.1203 + * value block written via default serialization; since there
32.1204 + * is no terminating TC_ENDBLOCKDATA tag, simulate
32.1205 + * end-of-custom-data behavior explicitly.
32.1206 + */
32.1207 + throw new OptionalDataException(true);
32.1208 + }
32.1209 + bin.setBlockDataMode(false);
32.1210 + }
32.1211 +
32.1212 + byte tc;
32.1213 + while ((tc = bin.peekByte()) == TC_RESET) {
32.1214 + bin.readByte();
32.1215 + handleReset();
32.1216 + }
32.1217 +
32.1218 + depth++;
32.1219 + try {
32.1220 + switch (tc) {
32.1221 + case TC_NULL:
32.1222 + return readNull();
32.1223 +
32.1224 + case TC_REFERENCE:
32.1225 + return readHandle(unshared);
32.1226 +
32.1227 + case TC_CLASS:
32.1228 + return readClass(unshared);
32.1229 +
32.1230 + case TC_CLASSDESC:
32.1231 + case TC_PROXYCLASSDESC:
32.1232 + return readClassDesc(unshared);
32.1233 +
32.1234 + case TC_STRING:
32.1235 + case TC_LONGSTRING:
32.1236 + return checkResolve(readString(unshared));
32.1237 +
32.1238 + case TC_ARRAY:
32.1239 + return checkResolve(readArray(unshared));
32.1240 +
32.1241 + case TC_ENUM:
32.1242 + return checkResolve(readEnum(unshared));
32.1243 +
32.1244 + case TC_OBJECT:
32.1245 + return checkResolve(readOrdinaryObject(unshared));
32.1246 +
32.1247 + case TC_EXCEPTION:
32.1248 + IOException ex = readFatalException();
32.1249 + throw new WriteAbortedException("writing aborted", ex);
32.1250 +
32.1251 + case TC_BLOCKDATA:
32.1252 + case TC_BLOCKDATALONG:
32.1253 + if (oldMode) {
32.1254 + bin.setBlockDataMode(true);
32.1255 + bin.peek(); // force header read
32.1256 + throw new OptionalDataException(
32.1257 + bin.currentBlockRemaining());
32.1258 + } else {
32.1259 + throw new StreamCorruptedException(
32.1260 + "unexpected block data");
32.1261 + }
32.1262 +
32.1263 + case TC_ENDBLOCKDATA:
32.1264 + if (oldMode) {
32.1265 + throw new OptionalDataException(true);
32.1266 + } else {
32.1267 + throw new StreamCorruptedException(
32.1268 + "unexpected end of block data");
32.1269 + }
32.1270 +
32.1271 + default:
32.1272 + throw new StreamCorruptedException(
32.1273 + String.format("invalid type code: %02X", tc));
32.1274 + }
32.1275 + } finally {
32.1276 + depth--;
32.1277 + bin.setBlockDataMode(oldMode);
32.1278 + }
32.1279 + }
32.1280 +
32.1281 + /**
32.1282 + * If resolveObject has been enabled and given object does not have an
32.1283 + * exception associated with it, calls resolveObject to determine
32.1284 + * replacement for object, and updates handle table accordingly. Returns
32.1285 + * replacement object, or echoes provided object if no replacement
32.1286 + * occurred. Expects that passHandle is set to given object's handle prior
32.1287 + * to calling this method.
32.1288 + */
32.1289 + private Object checkResolve(Object obj) throws IOException {
32.1290 + if (!enableResolve || handles.lookupException(passHandle) != null) {
32.1291 + return obj;
32.1292 + }
32.1293 + Object rep = resolveObject(obj);
32.1294 + if (rep != obj) {
32.1295 + handles.setObject(passHandle, rep);
32.1296 + }
32.1297 + return rep;
32.1298 + }
32.1299 +
32.1300 + /**
32.1301 + * Reads string without allowing it to be replaced in stream. Called from
32.1302 + * within ObjectStreamClass.read().
32.1303 + */
32.1304 + String readTypeString() throws IOException {
32.1305 + int oldHandle = passHandle;
32.1306 + try {
32.1307 + byte tc = bin.peekByte();
32.1308 + switch (tc) {
32.1309 + case TC_NULL:
32.1310 + return (String) readNull();
32.1311 +
32.1312 + case TC_REFERENCE:
32.1313 + return (String) readHandle(false);
32.1314 +
32.1315 + case TC_STRING:
32.1316 + case TC_LONGSTRING:
32.1317 + return readString(false);
32.1318 +
32.1319 + default:
32.1320 + throw new StreamCorruptedException(
32.1321 + String.format("invalid type code: %02X", tc));
32.1322 + }
32.1323 + } finally {
32.1324 + passHandle = oldHandle;
32.1325 + }
32.1326 + }
32.1327 +
32.1328 + /**
32.1329 + * Reads in null code, sets passHandle to NULL_HANDLE and returns null.
32.1330 + */
32.1331 + private Object readNull() throws IOException {
32.1332 + if (bin.readByte() != TC_NULL) {
32.1333 + throw new InternalError();
32.1334 + }
32.1335 + passHandle = NULL_HANDLE;
32.1336 + return null;
32.1337 + }
32.1338 +
32.1339 + /**
32.1340 + * Reads in object handle, sets passHandle to the read handle, and returns
32.1341 + * object associated with the handle.
32.1342 + */
32.1343 + private Object readHandle(boolean unshared) throws IOException {
32.1344 + if (bin.readByte() != TC_REFERENCE) {
32.1345 + throw new InternalError();
32.1346 + }
32.1347 + passHandle = bin.readInt() - baseWireHandle;
32.1348 + if (passHandle < 0 || passHandle >= handles.size()) {
32.1349 + throw new StreamCorruptedException(
32.1350 + String.format("invalid handle value: %08X", passHandle +
32.1351 + baseWireHandle));
32.1352 + }
32.1353 + if (unshared) {
32.1354 + // REMIND: what type of exception to throw here?
32.1355 + throw new InvalidObjectException(
32.1356 + "cannot read back reference as unshared");
32.1357 + }
32.1358 +
32.1359 + Object obj = handles.lookupObject(passHandle);
32.1360 + if (obj == unsharedMarker) {
32.1361 + // REMIND: what type of exception to throw here?
32.1362 + throw new InvalidObjectException(
32.1363 + "cannot read back reference to unshared object");
32.1364 + }
32.1365 + return obj;
32.1366 + }
32.1367 +
32.1368 + /**
32.1369 + * Reads in and returns class object. Sets passHandle to class object's
32.1370 + * assigned handle. Returns null if class is unresolvable (in which case a
32.1371 + * ClassNotFoundException will be associated with the class' handle in the
32.1372 + * handle table).
32.1373 + */
32.1374 + private Class readClass(boolean unshared) throws IOException {
32.1375 + if (bin.readByte() != TC_CLASS) {
32.1376 + throw new InternalError();
32.1377 + }
32.1378 + ObjectStreamClass desc = readClassDesc(false);
32.1379 + Class cl = desc.forClass();
32.1380 + passHandle = handles.assign(unshared ? unsharedMarker : cl);
32.1381 +
32.1382 + ClassNotFoundException resolveEx = desc.getResolveException();
32.1383 + if (resolveEx != null) {
32.1384 + handles.markException(passHandle, resolveEx);
32.1385 + }
32.1386 +
32.1387 + handles.finish(passHandle);
32.1388 + return cl;
32.1389 + }
32.1390 +
32.1391 + /**
32.1392 + * Reads in and returns (possibly null) class descriptor. Sets passHandle
32.1393 + * to class descriptor's assigned handle. If class descriptor cannot be
32.1394 + * resolved to a class in the local VM, a ClassNotFoundException is
32.1395 + * associated with the class descriptor's handle.
32.1396 + */
32.1397 + private ObjectStreamClass readClassDesc(boolean unshared)
32.1398 + throws IOException
32.1399 + {
32.1400 + byte tc = bin.peekByte();
32.1401 + switch (tc) {
32.1402 + case TC_NULL:
32.1403 + return (ObjectStreamClass) readNull();
32.1404 +
32.1405 + case TC_REFERENCE:
32.1406 + return (ObjectStreamClass) readHandle(unshared);
32.1407 +
32.1408 + case TC_PROXYCLASSDESC:
32.1409 + return readProxyDesc(unshared);
32.1410 +
32.1411 + case TC_CLASSDESC:
32.1412 + return readNonProxyDesc(unshared);
32.1413 +
32.1414 + default:
32.1415 + throw new StreamCorruptedException(
32.1416 + String.format("invalid type code: %02X", tc));
32.1417 + }
32.1418 + }
32.1419 +
32.1420 + /**
32.1421 + * Reads in and returns class descriptor for a dynamic proxy class. Sets
32.1422 + * passHandle to proxy class descriptor's assigned handle. If proxy class
32.1423 + * descriptor cannot be resolved to a class in the local VM, a
32.1424 + * ClassNotFoundException is associated with the descriptor's handle.
32.1425 + */
32.1426 + private ObjectStreamClass readProxyDesc(boolean unshared)
32.1427 + throws IOException
32.1428 + {
32.1429 + if (bin.readByte() != TC_PROXYCLASSDESC) {
32.1430 + throw new InternalError();
32.1431 + }
32.1432 +
32.1433 + ObjectStreamClass desc = new ObjectStreamClass();
32.1434 + int descHandle = handles.assign(unshared ? unsharedMarker : desc);
32.1435 + passHandle = NULL_HANDLE;
32.1436 +
32.1437 + int numIfaces = bin.readInt();
32.1438 + String[] ifaces = new String[numIfaces];
32.1439 + for (int i = 0; i < numIfaces; i++) {
32.1440 + ifaces[i] = bin.readUTF();
32.1441 + }
32.1442 +
32.1443 + Class cl = null;
32.1444 + ClassNotFoundException resolveEx = null;
32.1445 + bin.setBlockDataMode(true);
32.1446 + try {
32.1447 + if ((cl = resolveProxyClass(ifaces)) == null) {
32.1448 + resolveEx = new ClassNotFoundException("null class");
32.1449 + }
32.1450 + } catch (ClassNotFoundException ex) {
32.1451 + resolveEx = ex;
32.1452 + }
32.1453 + skipCustomData();
32.1454 +
32.1455 + desc.initProxy(cl, resolveEx, readClassDesc(false));
32.1456 +
32.1457 + handles.finish(descHandle);
32.1458 + passHandle = descHandle;
32.1459 + return desc;
32.1460 + }
32.1461 +
32.1462 + /**
32.1463 + * Reads in and returns class descriptor for a class that is not a dynamic
32.1464 + * proxy class. Sets passHandle to class descriptor's assigned handle. If
32.1465 + * class descriptor cannot be resolved to a class in the local VM, a
32.1466 + * ClassNotFoundException is associated with the descriptor's handle.
32.1467 + */
32.1468 + private ObjectStreamClass readNonProxyDesc(boolean unshared)
32.1469 + throws IOException
32.1470 + {
32.1471 + if (bin.readByte() != TC_CLASSDESC) {
32.1472 + throw new InternalError();
32.1473 + }
32.1474 +
32.1475 + ObjectStreamClass desc = new ObjectStreamClass();
32.1476 + int descHandle = handles.assign(unshared ? unsharedMarker : desc);
32.1477 + passHandle = NULL_HANDLE;
32.1478 +
32.1479 + ObjectStreamClass readDesc = null;
32.1480 + try {
32.1481 + readDesc = readClassDescriptor();
32.1482 + } catch (ClassNotFoundException ex) {
32.1483 + throw (IOException) new InvalidClassException(
32.1484 + "failed to read class descriptor").initCause(ex);
32.1485 + }
32.1486 +
32.1487 + Class cl = null;
32.1488 + ClassNotFoundException resolveEx = null;
32.1489 + bin.setBlockDataMode(true);
32.1490 + try {
32.1491 + if ((cl = resolveClass(readDesc)) == null) {
32.1492 + resolveEx = new ClassNotFoundException("null class");
32.1493 + }
32.1494 + } catch (ClassNotFoundException ex) {
32.1495 + resolveEx = ex;
32.1496 + }
32.1497 + skipCustomData();
32.1498 +
32.1499 + desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));
32.1500 +
32.1501 + handles.finish(descHandle);
32.1502 + passHandle = descHandle;
32.1503 + return desc;
32.1504 + }
32.1505 +
32.1506 + /**
32.1507 + * Reads in and returns new string. Sets passHandle to new string's
32.1508 + * assigned handle.
32.1509 + */
32.1510 + private String readString(boolean unshared) throws IOException {
32.1511 + String str;
32.1512 + byte tc = bin.readByte();
32.1513 + switch (tc) {
32.1514 + case TC_STRING:
32.1515 + str = bin.readUTF();
32.1516 + break;
32.1517 +
32.1518 + case TC_LONGSTRING:
32.1519 + str = bin.readLongUTF();
32.1520 + break;
32.1521 +
32.1522 + default:
32.1523 + throw new StreamCorruptedException(
32.1524 + String.format("invalid type code: %02X", tc));
32.1525 + }
32.1526 + passHandle = handles.assign(unshared ? unsharedMarker : str);
32.1527 + handles.finish(passHandle);
32.1528 + return str;
32.1529 + }
32.1530 +
32.1531 + /**
32.1532 + * Reads in and returns array object, or null if array class is
32.1533 + * unresolvable. Sets passHandle to array's assigned handle.
32.1534 + */
32.1535 + private Object readArray(boolean unshared) throws IOException {
32.1536 + if (bin.readByte() != TC_ARRAY) {
32.1537 + throw new InternalError();
32.1538 + }
32.1539 +
32.1540 + ObjectStreamClass desc = readClassDesc(false);
32.1541 + int len = bin.readInt();
32.1542 +
32.1543 + Object array = null;
32.1544 + Class cl, ccl = null;
32.1545 + if ((cl = desc.forClass()) != null) {
32.1546 + ccl = cl.getComponentType();
32.1547 + array = Array.newInstance(ccl, len);
32.1548 + }
32.1549 +
32.1550 + int arrayHandle = handles.assign(unshared ? unsharedMarker : array);
32.1551 + ClassNotFoundException resolveEx = desc.getResolveException();
32.1552 + if (resolveEx != null) {
32.1553 + handles.markException(arrayHandle, resolveEx);
32.1554 + }
32.1555 +
32.1556 + if (ccl == null) {
32.1557 + for (int i = 0; i < len; i++) {
32.1558 + readObject0(false);
32.1559 + }
32.1560 + } else if (ccl.isPrimitive()) {
32.1561 + if (ccl == Integer.TYPE) {
32.1562 + bin.readInts((int[]) array, 0, len);
32.1563 + } else if (ccl == Byte.TYPE) {
32.1564 + bin.readFully((byte[]) array, 0, len, true);
32.1565 + } else if (ccl == Long.TYPE) {
32.1566 + bin.readLongs((long[]) array, 0, len);
32.1567 + } else if (ccl == Float.TYPE) {
32.1568 + bin.readFloats((float[]) array, 0, len);
32.1569 + } else if (ccl == Double.TYPE) {
32.1570 + bin.readDoubles((double[]) array, 0, len);
32.1571 + } else if (ccl == Short.TYPE) {
32.1572 + bin.readShorts((short[]) array, 0, len);
32.1573 + } else if (ccl == Character.TYPE) {
32.1574 + bin.readChars((char[]) array, 0, len);
32.1575 + } else if (ccl == Boolean.TYPE) {
32.1576 + bin.readBooleans((boolean[]) array, 0, len);
32.1577 + } else {
32.1578 + throw new InternalError();
32.1579 + }
32.1580 + } else {
32.1581 + Object[] oa = (Object[]) array;
32.1582 + for (int i = 0; i < len; i++) {
32.1583 + oa[i] = readObject0(false);
32.1584 + handles.markDependency(arrayHandle, passHandle);
32.1585 + }
32.1586 + }
32.1587 +
32.1588 + handles.finish(arrayHandle);
32.1589 + passHandle = arrayHandle;
32.1590 + return array;
32.1591 + }
32.1592 +
32.1593 + /**
32.1594 + * Reads in and returns enum constant, or null if enum type is
32.1595 + * unresolvable. Sets passHandle to enum constant's assigned handle.
32.1596 + */
32.1597 + private Enum readEnum(boolean unshared) throws IOException {
32.1598 + if (bin.readByte() != TC_ENUM) {
32.1599 + throw new InternalError();
32.1600 + }
32.1601 +
32.1602 + ObjectStreamClass desc = readClassDesc(false);
32.1603 + if (!desc.isEnum()) {
32.1604 + throw new InvalidClassException("non-enum class: " + desc);
32.1605 + }
32.1606 +
32.1607 + int enumHandle = handles.assign(unshared ? unsharedMarker : null);
32.1608 + ClassNotFoundException resolveEx = desc.getResolveException();
32.1609 + if (resolveEx != null) {
32.1610 + handles.markException(enumHandle, resolveEx);
32.1611 + }
32.1612 +
32.1613 + String name = readString(false);
32.1614 + Enum en = null;
32.1615 + Class cl = desc.forClass();
32.1616 + if (cl != null) {
32.1617 + try {
32.1618 + en = Enum.valueOf(cl, name);
32.1619 + } catch (IllegalArgumentException ex) {
32.1620 + throw (IOException) new InvalidObjectException(
32.1621 + "enum constant " + name + " does not exist in " +
32.1622 + cl).initCause(ex);
32.1623 + }
32.1624 + if (!unshared) {
32.1625 + handles.setObject(enumHandle, en);
32.1626 + }
32.1627 + }
32.1628 +
32.1629 + handles.finish(enumHandle);
32.1630 + passHandle = enumHandle;
32.1631 + return en;
32.1632 + }
32.1633 +
32.1634 + /**
32.1635 + * Reads and returns "ordinary" (i.e., not a String, Class,
32.1636 + * ObjectStreamClass, array, or enum constant) object, or null if object's
32.1637 + * class is unresolvable (in which case a ClassNotFoundException will be
32.1638 + * associated with object's handle). Sets passHandle to object's assigned
32.1639 + * handle.
32.1640 + */
32.1641 + private Object readOrdinaryObject(boolean unshared)
32.1642 + throws IOException
32.1643 + {
32.1644 + if (bin.readByte() != TC_OBJECT) {
32.1645 + throw new InternalError();
32.1646 + }
32.1647 +
32.1648 + ObjectStreamClass desc = readClassDesc(false);
32.1649 + desc.checkDeserialize();
32.1650 +
32.1651 + Object obj;
32.1652 + try {
32.1653 + obj = desc.isInstantiable() ? desc.newInstance() : null;
32.1654 + } catch (Exception ex) {
32.1655 + throw (IOException) new InvalidClassException(
32.1656 + desc.forClass().getName(),
32.1657 + "unable to create instance").initCause(ex);
32.1658 + }
32.1659 +
32.1660 + passHandle = handles.assign(unshared ? unsharedMarker : obj);
32.1661 + ClassNotFoundException resolveEx = desc.getResolveException();
32.1662 + if (resolveEx != null) {
32.1663 + handles.markException(passHandle, resolveEx);
32.1664 + }
32.1665 +
32.1666 + if (desc.isExternalizable()) {
32.1667 + readExternalData((Externalizable) obj, desc);
32.1668 + } else {
32.1669 + readSerialData(obj, desc);
32.1670 + }
32.1671 +
32.1672 + handles.finish(passHandle);
32.1673 +
32.1674 + if (obj != null &&
32.1675 + handles.lookupException(passHandle) == null &&
32.1676 + desc.hasReadResolveMethod())
32.1677 + {
32.1678 + Object rep = desc.invokeReadResolve(obj);
32.1679 + if (unshared && rep.getClass().isArray()) {
32.1680 + rep = cloneArray(rep);
32.1681 + }
32.1682 + if (rep != obj) {
32.1683 + handles.setObject(passHandle, obj = rep);
32.1684 + }
32.1685 + }
32.1686 +
32.1687 + return obj;
32.1688 + }
32.1689 +
32.1690 + /**
32.1691 + * If obj is non-null, reads externalizable data by invoking readExternal()
32.1692 + * method of obj; otherwise, attempts to skip over externalizable data.
32.1693 + * Expects that passHandle is set to obj's handle before this method is
32.1694 + * called.
32.1695 + */
32.1696 + private void readExternalData(Externalizable obj, ObjectStreamClass desc)
32.1697 + throws IOException
32.1698 + {
32.1699 + Object oldContext = curContext;
32.1700 + curContext = null;
32.1701 + try {
32.1702 + boolean blocked = desc.hasBlockExternalData();
32.1703 + if (blocked) {
32.1704 + bin.setBlockDataMode(true);
32.1705 + }
32.1706 + if (obj != null) {
32.1707 + try {
32.1708 + obj.readExternal(this);
32.1709 + } catch (ClassNotFoundException ex) {
32.1710 + /*
32.1711 + * In most cases, the handle table has already propagated
32.1712 + * a CNFException to passHandle at this point; this mark
32.1713 + * call is included to address cases where the readExternal
32.1714 + * method has cons'ed and thrown a new CNFException of its
32.1715 + * own.
32.1716 + */
32.1717 + handles.markException(passHandle, ex);
32.1718 + }
32.1719 + }
32.1720 + if (blocked) {
32.1721 + skipCustomData();
32.1722 + }
32.1723 + } finally {
32.1724 + curContext = oldContext;
32.1725 + }
32.1726 + /*
32.1727 + * At this point, if the externalizable data was not written in
32.1728 + * block-data form and either the externalizable class doesn't exist
32.1729 + * locally (i.e., obj == null) or readExternal() just threw a
32.1730 + * CNFException, then the stream is probably in an inconsistent state,
32.1731 + * since some (or all) of the externalizable data may not have been
32.1732 + * consumed. Since there's no "correct" action to take in this case,
32.1733 + * we mimic the behavior of past serialization implementations and
32.1734 + * blindly hope that the stream is in sync; if it isn't and additional
32.1735 + * externalizable data remains in the stream, a subsequent read will
32.1736 + * most likely throw a StreamCorruptedException.
32.1737 + */
32.1738 + }
32.1739 +
32.1740 + /**
32.1741 + * Reads (or attempts to skip, if obj is null or is tagged with a
32.1742 + * ClassNotFoundException) instance data for each serializable class of
32.1743 + * object in stream, from superclass to subclass. Expects that passHandle
32.1744 + * is set to obj's handle before this method is called.
32.1745 + */
32.1746 + private void readSerialData(Object obj, ObjectStreamClass desc)
32.1747 + throws IOException
32.1748 + {
32.1749 + ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
32.1750 + for (int i = 0; i < slots.length; i++) {
32.1751 + ObjectStreamClass slotDesc = slots[i].desc;
32.1752 +
32.1753 + if (slots[i].hasData) {
32.1754 + if (obj != null &&
32.1755 + slotDesc.hasReadObjectMethod() &&
32.1756 + handles.lookupException(passHandle) == null)
32.1757 + {
32.1758 + Object oldContext = curContext;
32.1759 +
32.1760 + try {
32.1761 + curContext = null; //new SerialCallbackContext(obj, slotDesc);
32.1762 +
32.1763 + bin.setBlockDataMode(true);
32.1764 + slotDesc.invokeReadObject(obj, this);
32.1765 + } catch (ClassNotFoundException ex) {
32.1766 + /*
32.1767 + * In most cases, the handle table has already
32.1768 + * propagated a CNFException to passHandle at this
32.1769 + * point; this mark call is included to address cases
32.1770 + * where the custom readObject method has cons'ed and
32.1771 + * thrown a new CNFException of its own.
32.1772 + */
32.1773 + handles.markException(passHandle, ex);
32.1774 + } finally {
32.1775 + //curContext.setUsed();
32.1776 + curContext = oldContext;
32.1777 + }
32.1778 +
32.1779 + /*
32.1780 + * defaultDataEnd may have been set indirectly by custom
32.1781 + * readObject() method when calling defaultReadObject() or
32.1782 + * readFields(); clear it to restore normal read behavior.
32.1783 + */
32.1784 + defaultDataEnd = false;
32.1785 + } else {
32.1786 + defaultReadFields(obj, slotDesc);
32.1787 + }
32.1788 + if (slotDesc.hasWriteObjectData()) {
32.1789 + skipCustomData();
32.1790 + } else {
32.1791 + bin.setBlockDataMode(false);
32.1792 + }
32.1793 + } else {
32.1794 + if (obj != null &&
32.1795 + slotDesc.hasReadObjectNoDataMethod() &&
32.1796 + handles.lookupException(passHandle) == null)
32.1797 + {
32.1798 + slotDesc.invokeReadObjectNoData(obj);
32.1799 + }
32.1800 + }
32.1801 + }
32.1802 + }
32.1803 +
32.1804 + /**
32.1805 + * Skips over all block data and objects until TC_ENDBLOCKDATA is
32.1806 + * encountered.
32.1807 + */
32.1808 + private void skipCustomData() throws IOException {
32.1809 + int oldHandle = passHandle;
32.1810 + for (;;) {
32.1811 + if (bin.getBlockDataMode()) {
32.1812 + bin.skipBlockData();
32.1813 + bin.setBlockDataMode(false);
32.1814 + }
32.1815 + switch (bin.peekByte()) {
32.1816 + case TC_BLOCKDATA:
32.1817 + case TC_BLOCKDATALONG:
32.1818 + bin.setBlockDataMode(true);
32.1819 + break;
32.1820 +
32.1821 + case TC_ENDBLOCKDATA:
32.1822 + bin.readByte();
32.1823 + passHandle = oldHandle;
32.1824 + return;
32.1825 +
32.1826 + default:
32.1827 + readObject0(false);
32.1828 + break;
32.1829 + }
32.1830 + }
32.1831 + }
32.1832 +
32.1833 + /**
32.1834 + * Reads in values of serializable fields declared by given class
32.1835 + * descriptor. If obj is non-null, sets field values in obj. Expects that
32.1836 + * passHandle is set to obj's handle before this method is called.
32.1837 + */
32.1838 + private void defaultReadFields(Object obj, ObjectStreamClass desc)
32.1839 + throws IOException
32.1840 + {
32.1841 + // REMIND: is isInstance check necessary?
32.1842 + Class cl = desc.forClass();
32.1843 + if (cl != null && obj != null && !cl.isInstance(obj)) {
32.1844 + throw new ClassCastException();
32.1845 + }
32.1846 +
32.1847 + int primDataSize = desc.getPrimDataSize();
32.1848 + if (primVals == null || primVals.length < primDataSize) {
32.1849 + primVals = new byte[primDataSize];
32.1850 + }
32.1851 + bin.readFully(primVals, 0, primDataSize, false);
32.1852 + if (obj != null) {
32.1853 + desc.setPrimFieldValues(obj, primVals);
32.1854 + }
32.1855 +
32.1856 + int objHandle = passHandle;
32.1857 + ObjectStreamField[] fields = desc.getFields(false);
32.1858 + Object[] objVals = new Object[desc.getNumObjFields()];
32.1859 + int numPrimFields = fields.length - objVals.length;
32.1860 + for (int i = 0; i < objVals.length; i++) {
32.1861 + ObjectStreamField f = fields[numPrimFields + i];
32.1862 + objVals[i] = readObject0(f.isUnshared());
32.1863 + if (f.getField() != null) {
32.1864 + handles.markDependency(objHandle, passHandle);
32.1865 + }
32.1866 + }
32.1867 + if (obj != null) {
32.1868 + desc.setObjFieldValues(obj, objVals);
32.1869 + }
32.1870 + passHandle = objHandle;
32.1871 + }
32.1872 +
32.1873 + /**
32.1874 + * Reads in and returns IOException that caused serialization to abort.
32.1875 + * All stream state is discarded prior to reading in fatal exception. Sets
32.1876 + * passHandle to fatal exception's handle.
32.1877 + */
32.1878 + private IOException readFatalException() throws IOException {
32.1879 + if (bin.readByte() != TC_EXCEPTION) {
32.1880 + throw new InternalError();
32.1881 + }
32.1882 + clear();
32.1883 + return (IOException) readObject0(false);
32.1884 + }
32.1885 +
32.1886 + /**
32.1887 + * If recursion depth is 0, clears internal data structures; otherwise,
32.1888 + * throws a StreamCorruptedException. This method is called when a
32.1889 + * TC_RESET typecode is encountered.
32.1890 + */
32.1891 + private void handleReset() throws StreamCorruptedException {
32.1892 + if (depth > 0) {
32.1893 + throw new StreamCorruptedException(
32.1894 + "unexpected reset; recursion depth: " + depth);
32.1895 + }
32.1896 + clear();
32.1897 + }
32.1898 +
32.1899 + /**
32.1900 + * Converts specified span of bytes into float values.
32.1901 + */
32.1902 + // REMIND: remove once hotspot inlines Float.intBitsToFloat
32.1903 + private static native void bytesToFloats(byte[] src, int srcpos,
32.1904 + float[] dst, int dstpos,
32.1905 + int nfloats);
32.1906 +
32.1907 + /**
32.1908 + * Converts specified span of bytes into double values.
32.1909 + */
32.1910 + // REMIND: remove once hotspot inlines Double.longBitsToDouble
32.1911 + private static native void bytesToDoubles(byte[] src, int srcpos,
32.1912 + double[] dst, int dstpos,
32.1913 + int ndoubles);
32.1914 +
32.1915 + /**
32.1916 + * Returns the first non-null class loader (not counting class loaders of
32.1917 + * generated reflection implementation classes) up the execution stack, or
32.1918 + * null if only code from the null class loader is on the stack. This
32.1919 + * method is also called via reflection by the following RMI-IIOP class:
32.1920 + *
32.1921 + * com.sun.corba.se.internal.util.JDKClassLoader
32.1922 + *
32.1923 + * This method should not be removed or its signature changed without
32.1924 + * corresponding modifications to the above class.
32.1925 + */
32.1926 + // REMIND: change name to something more accurate?
32.1927 + private static native ClassLoader latestUserDefinedLoader();
32.1928 +
32.1929 + /**
32.1930 + * Default GetField implementation.
32.1931 + */
32.1932 + private class GetFieldImpl extends GetField {
32.1933 +
32.1934 + /** class descriptor describing serializable fields */
32.1935 + private final ObjectStreamClass desc;
32.1936 + /** primitive field values */
32.1937 + private final byte[] primVals;
32.1938 + /** object field values */
32.1939 + private final Object[] objVals;
32.1940 + /** object field value handles */
32.1941 + private final int[] objHandles;
32.1942 +
32.1943 + /**
32.1944 + * Creates GetFieldImpl object for reading fields defined in given
32.1945 + * class descriptor.
32.1946 + */
32.1947 + GetFieldImpl(ObjectStreamClass desc) {
32.1948 + this.desc = desc;
32.1949 + primVals = new byte[desc.getPrimDataSize()];
32.1950 + objVals = new Object[desc.getNumObjFields()];
32.1951 + objHandles = new int[objVals.length];
32.1952 + }
32.1953 +
32.1954 + public ObjectStreamClass getObjectStreamClass() {
32.1955 + return desc;
32.1956 + }
32.1957 +
32.1958 + public boolean defaulted(String name) throws IOException {
32.1959 + return (getFieldOffset(name, null) < 0);
32.1960 + }
32.1961 +
32.1962 + public boolean get(String name, boolean val) throws IOException {
32.1963 + int off = getFieldOffset(name, Boolean.TYPE);
32.1964 + return (off >= 0) ? Bits.getBoolean(primVals, off) : val;
32.1965 + }
32.1966 +
32.1967 + public byte get(String name, byte val) throws IOException {
32.1968 + int off = getFieldOffset(name, Byte.TYPE);
32.1969 + return (off >= 0) ? primVals[off] : val;
32.1970 + }
32.1971 +
32.1972 + public char get(String name, char val) throws IOException {
32.1973 + int off = getFieldOffset(name, Character.TYPE);
32.1974 + return (off >= 0) ? Bits.getChar(primVals, off) : val;
32.1975 + }
32.1976 +
32.1977 + public short get(String name, short val) throws IOException {
32.1978 + int off = getFieldOffset(name, Short.TYPE);
32.1979 + return (off >= 0) ? Bits.getShort(primVals, off) : val;
32.1980 + }
32.1981 +
32.1982 + public int get(String name, int val) throws IOException {
32.1983 + int off = getFieldOffset(name, Integer.TYPE);
32.1984 + return (off >= 0) ? Bits.getInt(primVals, off) : val;
32.1985 + }
32.1986 +
32.1987 + public float get(String name, float val) throws IOException {
32.1988 + int off = getFieldOffset(name, Float.TYPE);
32.1989 + return (off >= 0) ? Bits.getFloat(primVals, off) : val;
32.1990 + }
32.1991 +
32.1992 + public long get(String name, long val) throws IOException {
32.1993 + int off = getFieldOffset(name, Long.TYPE);
32.1994 + return (off >= 0) ? Bits.getLong(primVals, off) : val;
32.1995 + }
32.1996 +
32.1997 + public double get(String name, double val) throws IOException {
32.1998 + int off = getFieldOffset(name, Double.TYPE);
32.1999 + return (off >= 0) ? Bits.getDouble(primVals, off) : val;
32.2000 + }
32.2001 +
32.2002 + public Object get(String name, Object val) throws IOException {
32.2003 + int off = getFieldOffset(name, Object.class);
32.2004 + if (off >= 0) {
32.2005 + int objHandle = objHandles[off];
32.2006 + handles.markDependency(passHandle, objHandle);
32.2007 + return (handles.lookupException(objHandle) == null) ?
32.2008 + objVals[off] : null;
32.2009 + } else {
32.2010 + return val;
32.2011 + }
32.2012 + }
32.2013 +
32.2014 + /**
32.2015 + * Reads primitive and object field values from stream.
32.2016 + */
32.2017 + void readFields() throws IOException {
32.2018 + bin.readFully(primVals, 0, primVals.length, false);
32.2019 +
32.2020 + int oldHandle = passHandle;
32.2021 + ObjectStreamField[] fields = desc.getFields(false);
32.2022 + int numPrimFields = fields.length - objVals.length;
32.2023 + for (int i = 0; i < objVals.length; i++) {
32.2024 + objVals[i] =
32.2025 + readObject0(fields[numPrimFields + i].isUnshared());
32.2026 + objHandles[i] = passHandle;
32.2027 + }
32.2028 + passHandle = oldHandle;
32.2029 + }
32.2030 +
32.2031 + /**
32.2032 + * Returns offset of field with given name and type. A specified type
32.2033 + * of null matches all types, Object.class matches all non-primitive
32.2034 + * types, and any other non-null type matches assignable types only.
32.2035 + * If no matching field is found in the (incoming) class
32.2036 + * descriptor but a matching field is present in the associated local
32.2037 + * class descriptor, returns -1. Throws IllegalArgumentException if
32.2038 + * neither incoming nor local class descriptor contains a match.
32.2039 + */
32.2040 + private int getFieldOffset(String name, Class type) {
32.2041 + ObjectStreamField field = desc.getField(name, type);
32.2042 + if (field != null) {
32.2043 + return field.getOffset();
32.2044 + } else if (desc.getLocalDesc().getField(name, type) != null) {
32.2045 + return -1;
32.2046 + } else {
32.2047 + throw new IllegalArgumentException("no such field " + name +
32.2048 + " with type " + type);
32.2049 + }
32.2050 + }
32.2051 + }
32.2052 +
32.2053 + /**
32.2054 + * Prioritized list of callbacks to be performed once object graph has been
32.2055 + * completely deserialized.
32.2056 + */
32.2057 + private static class ValidationList {
32.2058 +
32.2059 +
32.2060 + /**
32.2061 + * Creates new (empty) ValidationList.
32.2062 + */
32.2063 + ValidationList() {
32.2064 + }
32.2065 +
32.2066 + /**
32.2067 + * Registers callback. Throws InvalidObjectException if callback
32.2068 + * object is null.
32.2069 + */
32.2070 + void register(ObjectInputValidation obj, int priority)
32.2071 + throws InvalidObjectException
32.2072 + {
32.2073 + if (obj == null) {
32.2074 + throw new InvalidObjectException("null callback");
32.2075 + }
32.2076 + throw new InvalidObjectException("Does not work.");
32.2077 + }
32.2078 +
32.2079 + /**
32.2080 + * Invokes all registered callbacks and clears the callback list.
32.2081 + * Callbacks with higher priorities are called first; those with equal
32.2082 + * priorities may be called in any order. If any of the callbacks
32.2083 + * throws an InvalidObjectException, the callback process is terminated
32.2084 + * and the exception propagated upwards.
32.2085 + */
32.2086 + void doCallbacks() throws InvalidObjectException {
32.2087 + }
32.2088 +
32.2089 + /**
32.2090 + * Resets the callback list to its initial (empty) state.
32.2091 + */
32.2092 + public void clear() {
32.2093 + }
32.2094 + }
32.2095 +
32.2096 + /**
32.2097 + * Input stream supporting single-byte peek operations.
32.2098 + */
32.2099 + private static class PeekInputStream extends InputStream {
32.2100 +
32.2101 + /** underlying stream */
32.2102 + private final InputStream in;
32.2103 + /** peeked byte */
32.2104 + private int peekb = -1;
32.2105 +
32.2106 + /**
32.2107 + * Creates new PeekInputStream on top of given underlying stream.
32.2108 + */
32.2109 + PeekInputStream(InputStream in) {
32.2110 + this.in = in;
32.2111 + }
32.2112 +
32.2113 + /**
32.2114 + * Peeks at next byte value in stream. Similar to read(), except
32.2115 + * that it does not consume the read value.
32.2116 + */
32.2117 + int peek() throws IOException {
32.2118 + return (peekb >= 0) ? peekb : (peekb = in.read());
32.2119 + }
32.2120 +
32.2121 + public int read() throws IOException {
32.2122 + if (peekb >= 0) {
32.2123 + int v = peekb;
32.2124 + peekb = -1;
32.2125 + return v;
32.2126 + } else {
32.2127 + return in.read();
32.2128 + }
32.2129 + }
32.2130 +
32.2131 + public int read(byte[] b, int off, int len) throws IOException {
32.2132 + if (len == 0) {
32.2133 + return 0;
32.2134 + } else if (peekb < 0) {
32.2135 + return in.read(b, off, len);
32.2136 + } else {
32.2137 + b[off++] = (byte) peekb;
32.2138 + len--;
32.2139 + peekb = -1;
32.2140 + int n = in.read(b, off, len);
32.2141 + return (n >= 0) ? (n + 1) : 1;
32.2142 + }
32.2143 + }
32.2144 +
32.2145 + void readFully(byte[] b, int off, int len) throws IOException {
32.2146 + int n = 0;
32.2147 + while (n < len) {
32.2148 + int count = read(b, off + n, len - n);
32.2149 + if (count < 0) {
32.2150 + throw new EOFException();
32.2151 + }
32.2152 + n += count;
32.2153 + }
32.2154 + }
32.2155 +
32.2156 + public long skip(long n) throws IOException {
32.2157 + if (n <= 0) {
32.2158 + return 0;
32.2159 + }
32.2160 + int skipped = 0;
32.2161 + if (peekb >= 0) {
32.2162 + peekb = -1;
32.2163 + skipped++;
32.2164 + n--;
32.2165 + }
32.2166 + return skipped + skip(n);
32.2167 + }
32.2168 +
32.2169 + public int available() throws IOException {
32.2170 + return in.available() + ((peekb >= 0) ? 1 : 0);
32.2171 + }
32.2172 +
32.2173 + public void close() throws IOException {
32.2174 + in.close();
32.2175 + }
32.2176 + }
32.2177 +
32.2178 + /**
32.2179 + * Input stream with two modes: in default mode, inputs data written in the
32.2180 + * same format as DataOutputStream; in "block data" mode, inputs data
32.2181 + * bracketed by block data markers (see object serialization specification
32.2182 + * for details). Buffering depends on block data mode: when in default
32.2183 + * mode, no data is buffered in advance; when in block data mode, all data
32.2184 + * for the current data block is read in at once (and buffered).
32.2185 + */
32.2186 + private class BlockDataInputStream
32.2187 + extends InputStream implements DataInput
32.2188 + {
32.2189 + /** maximum data block length */
32.2190 + private static final int MAX_BLOCK_SIZE = 1024;
32.2191 + /** maximum data block header length */
32.2192 + private static final int MAX_HEADER_SIZE = 5;
32.2193 + /** (tunable) length of char buffer (for reading strings) */
32.2194 + private static final int CHAR_BUF_SIZE = 256;
32.2195 + /** readBlockHeader() return value indicating header read may block */
32.2196 + private static final int HEADER_BLOCKED = -2;
32.2197 +
32.2198 + /** buffer for reading general/block data */
32.2199 + private final byte[] buf = new byte[MAX_BLOCK_SIZE];
32.2200 + /** buffer for reading block data headers */
32.2201 + private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
32.2202 + /** char buffer for fast string reads */
32.2203 + private final char[] cbuf = new char[CHAR_BUF_SIZE];
32.2204 +
32.2205 + /** block data mode */
32.2206 + private boolean blkmode = false;
32.2207 +
32.2208 + // block data state fields; values meaningful only when blkmode true
32.2209 + /** current offset into buf */
32.2210 + private int pos = 0;
32.2211 + /** end offset of valid data in buf, or -1 if no more block data */
32.2212 + private int end = -1;
32.2213 + /** number of bytes in current block yet to be read from stream */
32.2214 + private int unread = 0;
32.2215 +
32.2216 + /** underlying stream (wrapped in peekable filter stream) */
32.2217 + private final PeekInputStream in;
32.2218 + /** loopback stream (for data reads that span data blocks) */
32.2219 + private final DataInputStream din;
32.2220 +
32.2221 + /**
32.2222 + * Creates new BlockDataInputStream on top of given underlying stream.
32.2223 + * Block data mode is turned off by default.
32.2224 + */
32.2225 + BlockDataInputStream(InputStream in) {
32.2226 + this.in = new PeekInputStream(in);
32.2227 + din = new DataInputStream(this);
32.2228 + }
32.2229 +
32.2230 + /**
32.2231 + * Sets block data mode to the given mode (true == on, false == off)
32.2232 + * and returns the previous mode value. If the new mode is the same as
32.2233 + * the old mode, no action is taken. Throws IllegalStateException if
32.2234 + * block data mode is being switched from on to off while unconsumed
32.2235 + * block data is still present in the stream.
32.2236 + */
32.2237 + boolean setBlockDataMode(boolean newmode) throws IOException {
32.2238 + if (blkmode == newmode) {
32.2239 + return blkmode;
32.2240 + }
32.2241 + if (newmode) {
32.2242 + pos = 0;
32.2243 + end = 0;
32.2244 + unread = 0;
32.2245 + } else if (pos < end) {
32.2246 + throw new IllegalStateException("unread block data");
32.2247 + }
32.2248 + blkmode = newmode;
32.2249 + return !blkmode;
32.2250 + }
32.2251 +
32.2252 + /**
32.2253 + * Returns true if the stream is currently in block data mode, false
32.2254 + * otherwise.
32.2255 + */
32.2256 + boolean getBlockDataMode() {
32.2257 + return blkmode;
32.2258 + }
32.2259 +
32.2260 + /**
32.2261 + * If in block data mode, skips to the end of the current group of data
32.2262 + * blocks (but does not unset block data mode). If not in block data
32.2263 + * mode, throws an IllegalStateException.
32.2264 + */
32.2265 + void skipBlockData() throws IOException {
32.2266 + if (!blkmode) {
32.2267 + throw new IllegalStateException("not in block data mode");
32.2268 + }
32.2269 + while (end >= 0) {
32.2270 + refill();
32.2271 + }
32.2272 + }
32.2273 +
32.2274 + /**
32.2275 + * Attempts to read in the next block data header (if any). If
32.2276 + * canBlock is false and a full header cannot be read without possibly
32.2277 + * blocking, returns HEADER_BLOCKED, else if the next element in the
32.2278 + * stream is a block data header, returns the block data length
32.2279 + * specified by the header, else returns -1.
32.2280 + */
32.2281 + private int readBlockHeader(boolean canBlock) throws IOException {
32.2282 + if (defaultDataEnd) {
32.2283 + /*
32.2284 + * Fix for 4360508: stream is currently at the end of a field
32.2285 + * value block written via default serialization; since there
32.2286 + * is no terminating TC_ENDBLOCKDATA tag, simulate
32.2287 + * end-of-custom-data behavior explicitly.
32.2288 + */
32.2289 + return -1;
32.2290 + }
32.2291 + try {
32.2292 + for (;;) {
32.2293 + int avail = canBlock ? Integer.MAX_VALUE : in.available();
32.2294 + if (avail == 0) {
32.2295 + return HEADER_BLOCKED;
32.2296 + }
32.2297 +
32.2298 + int tc = in.peek();
32.2299 + switch (tc) {
32.2300 + case TC_BLOCKDATA:
32.2301 + if (avail < 2) {
32.2302 + return HEADER_BLOCKED;
32.2303 + }
32.2304 + in.readFully(hbuf, 0, 2);
32.2305 + return hbuf[1] & 0xFF;
32.2306 +
32.2307 + case TC_BLOCKDATALONG:
32.2308 + if (avail < 5) {
32.2309 + return HEADER_BLOCKED;
32.2310 + }
32.2311 + in.readFully(hbuf, 0, 5);
32.2312 + int len = Bits.getInt(hbuf, 1);
32.2313 + if (len < 0) {
32.2314 + throw new StreamCorruptedException(
32.2315 + "illegal block data header length: " +
32.2316 + len);
32.2317 + }
32.2318 + return len;
32.2319 +
32.2320 + /*
32.2321 + * TC_RESETs may occur in between data blocks.
32.2322 + * Unfortunately, this case must be parsed at a lower
32.2323 + * level than other typecodes, since primitive data
32.2324 + * reads may span data blocks separated by a TC_RESET.
32.2325 + */
32.2326 + case TC_RESET:
32.2327 + in.read();
32.2328 + handleReset();
32.2329 + break;
32.2330 +
32.2331 + default:
32.2332 + if (tc >= 0 && (tc < TC_BASE || tc > TC_MAX)) {
32.2333 + throw new StreamCorruptedException(
32.2334 + String.format("invalid type code: %02X",
32.2335 + tc));
32.2336 + }
32.2337 + return -1;
32.2338 + }
32.2339 + }
32.2340 + } catch (EOFException ex) {
32.2341 + throw new StreamCorruptedException(
32.2342 + "unexpected EOF while reading block data header");
32.2343 + }
32.2344 + }
32.2345 +
32.2346 + /**
32.2347 + * Refills internal buffer buf with block data. Any data in buf at the
32.2348 + * time of the call is considered consumed. Sets the pos, end, and
32.2349 + * unread fields to reflect the new amount of available block data; if
32.2350 + * the next element in the stream is not a data block, sets pos and
32.2351 + * unread to 0 and end to -1.
32.2352 + */
32.2353 + private void refill() throws IOException {
32.2354 + try {
32.2355 + do {
32.2356 + pos = 0;
32.2357 + if (unread > 0) {
32.2358 + int n =
32.2359 + in.read(buf, 0, Math.min(unread, MAX_BLOCK_SIZE));
32.2360 + if (n >= 0) {
32.2361 + end = n;
32.2362 + unread -= n;
32.2363 + } else {
32.2364 + throw new StreamCorruptedException(
32.2365 + "unexpected EOF in middle of data block");
32.2366 + }
32.2367 + } else {
32.2368 + int n = readBlockHeader(true);
32.2369 + if (n >= 0) {
32.2370 + end = 0;
32.2371 + unread = n;
32.2372 + } else {
32.2373 + end = -1;
32.2374 + unread = 0;
32.2375 + }
32.2376 + }
32.2377 + } while (pos == end);
32.2378 + } catch (IOException ex) {
32.2379 + pos = 0;
32.2380 + end = -1;
32.2381 + unread = 0;
32.2382 + throw ex;
32.2383 + }
32.2384 + }
32.2385 +
32.2386 + /**
32.2387 + * If in block data mode, returns the number of unconsumed bytes
32.2388 + * remaining in the current data block. If not in block data mode,
32.2389 + * throws an IllegalStateException.
32.2390 + */
32.2391 + int currentBlockRemaining() {
32.2392 + if (blkmode) {
32.2393 + return (end >= 0) ? (end - pos) + unread : 0;
32.2394 + } else {
32.2395 + throw new IllegalStateException();
32.2396 + }
32.2397 + }
32.2398 +
32.2399 + /**
32.2400 + * Peeks at (but does not consume) and returns the next byte value in
32.2401 + * the stream, or -1 if the end of the stream/block data (if in block
32.2402 + * data mode) has been reached.
32.2403 + */
32.2404 + int peek() throws IOException {
32.2405 + if (blkmode) {
32.2406 + if (pos == end) {
32.2407 + refill();
32.2408 + }
32.2409 + return (end >= 0) ? (buf[pos] & 0xFF) : -1;
32.2410 + } else {
32.2411 + return in.peek();
32.2412 + }
32.2413 + }
32.2414 +
32.2415 + /**
32.2416 + * Peeks at (but does not consume) and returns the next byte value in
32.2417 + * the stream, or throws EOFException if end of stream/block data has
32.2418 + * been reached.
32.2419 + */
32.2420 + byte peekByte() throws IOException {
32.2421 + int val = peek();
32.2422 + if (val < 0) {
32.2423 + throw new EOFException();
32.2424 + }
32.2425 + return (byte) val;
32.2426 + }
32.2427 +
32.2428 +
32.2429 + /* ----------------- generic input stream methods ------------------ */
32.2430 + /*
32.2431 + * The following methods are equivalent to their counterparts in
32.2432 + * InputStream, except that they interpret data block boundaries and
32.2433 + * read the requested data from within data blocks when in block data
32.2434 + * mode.
32.2435 + */
32.2436 +
32.2437 + public int read() throws IOException {
32.2438 + if (blkmode) {
32.2439 + if (pos == end) {
32.2440 + refill();
32.2441 + }
32.2442 + return (end >= 0) ? (buf[pos++] & 0xFF) : -1;
32.2443 + } else {
32.2444 + return in.read();
32.2445 + }
32.2446 + }
32.2447 +
32.2448 + public int read(byte[] b, int off, int len) throws IOException {
32.2449 + return read(b, off, len, false);
32.2450 + }
32.2451 +
32.2452 + public long skip(long len) throws IOException {
32.2453 + long remain = len;
32.2454 + while (remain > 0) {
32.2455 + if (blkmode) {
32.2456 + if (pos == end) {
32.2457 + refill();
32.2458 + }
32.2459 + if (end < 0) {
32.2460 + break;
32.2461 + }
32.2462 + int nread = (int) Math.min(remain, end - pos);
32.2463 + remain -= nread;
32.2464 + pos += nread;
32.2465 + } else {
32.2466 + int nread = (int) Math.min(remain, MAX_BLOCK_SIZE);
32.2467 + if ((nread = in.read(buf, 0, nread)) < 0) {
32.2468 + break;
32.2469 + }
32.2470 + remain -= nread;
32.2471 + }
32.2472 + }
32.2473 + return len - remain;
32.2474 + }
32.2475 +
32.2476 + public int available() throws IOException {
32.2477 + if (blkmode) {
32.2478 + if ((pos == end) && (unread == 0)) {
32.2479 + int n;
32.2480 + while ((n = readBlockHeader(false)) == 0) ;
32.2481 + switch (n) {
32.2482 + case HEADER_BLOCKED:
32.2483 + break;
32.2484 +
32.2485 + case -1:
32.2486 + pos = 0;
32.2487 + end = -1;
32.2488 + break;
32.2489 +
32.2490 + default:
32.2491 + pos = 0;
32.2492 + end = 0;
32.2493 + unread = n;
32.2494 + break;
32.2495 + }
32.2496 + }
32.2497 + // avoid unnecessary call to in.available() if possible
32.2498 + int unreadAvail = (unread > 0) ?
32.2499 + Math.min(in.available(), unread) : 0;
32.2500 + return (end >= 0) ? (end - pos) + unreadAvail : 0;
32.2501 + } else {
32.2502 + return in.available();
32.2503 + }
32.2504 + }
32.2505 +
32.2506 + public void close() throws IOException {
32.2507 + if (blkmode) {
32.2508 + pos = 0;
32.2509 + end = -1;
32.2510 + unread = 0;
32.2511 + }
32.2512 + in.close();
32.2513 + }
32.2514 +
32.2515 + /**
32.2516 + * Attempts to read len bytes into byte array b at offset off. Returns
32.2517 + * the number of bytes read, or -1 if the end of stream/block data has
32.2518 + * been reached. If copy is true, reads values into an intermediate
32.2519 + * buffer before copying them to b (to avoid exposing a reference to
32.2520 + * b).
32.2521 + */
32.2522 + int read(byte[] b, int off, int len, boolean copy) throws IOException {
32.2523 + if (len == 0) {
32.2524 + return 0;
32.2525 + } else if (blkmode) {
32.2526 + if (pos == end) {
32.2527 + refill();
32.2528 + }
32.2529 + if (end < 0) {
32.2530 + return -1;
32.2531 + }
32.2532 + int nread = Math.min(len, end - pos);
32.2533 + System.arraycopy(buf, pos, b, off, nread);
32.2534 + pos += nread;
32.2535 + return nread;
32.2536 + } else if (copy) {
32.2537 + int nread = in.read(buf, 0, Math.min(len, MAX_BLOCK_SIZE));
32.2538 + if (nread > 0) {
32.2539 + System.arraycopy(buf, 0, b, off, nread);
32.2540 + }
32.2541 + return nread;
32.2542 + } else {
32.2543 + return in.read(b, off, len);
32.2544 + }
32.2545 + }
32.2546 +
32.2547 + /* ----------------- primitive data input methods ------------------ */
32.2548 + /*
32.2549 + * The following methods are equivalent to their counterparts in
32.2550 + * DataInputStream, except that they interpret data block boundaries
32.2551 + * and read the requested data from within data blocks when in block
32.2552 + * data mode.
32.2553 + */
32.2554 +
32.2555 + public void readFully(byte[] b) throws IOException {
32.2556 + readFully(b, 0, b.length, false);
32.2557 + }
32.2558 +
32.2559 + public void readFully(byte[] b, int off, int len) throws IOException {
32.2560 + readFully(b, off, len, false);
32.2561 + }
32.2562 +
32.2563 + public void readFully(byte[] b, int off, int len, boolean copy)
32.2564 + throws IOException
32.2565 + {
32.2566 + while (len > 0) {
32.2567 + int n = read(b, off, len, copy);
32.2568 + if (n < 0) {
32.2569 + throw new EOFException();
32.2570 + }
32.2571 + off += n;
32.2572 + len -= n;
32.2573 + }
32.2574 + }
32.2575 +
32.2576 + public int skipBytes(int n) throws IOException {
32.2577 + return din.skipBytes(n);
32.2578 + }
32.2579 +
32.2580 + public boolean readBoolean() throws IOException {
32.2581 + int v = read();
32.2582 + if (v < 0) {
32.2583 + throw new EOFException();
32.2584 + }
32.2585 + return (v != 0);
32.2586 + }
32.2587 +
32.2588 + public byte readByte() throws IOException {
32.2589 + int v = read();
32.2590 + if (v < 0) {
32.2591 + throw new EOFException();
32.2592 + }
32.2593 + return (byte) v;
32.2594 + }
32.2595 +
32.2596 + public int readUnsignedByte() throws IOException {
32.2597 + int v = read();
32.2598 + if (v < 0) {
32.2599 + throw new EOFException();
32.2600 + }
32.2601 + return v;
32.2602 + }
32.2603 +
32.2604 + public char readChar() throws IOException {
32.2605 + if (!blkmode) {
32.2606 + pos = 0;
32.2607 + in.readFully(buf, 0, 2);
32.2608 + } else if (end - pos < 2) {
32.2609 + return din.readChar();
32.2610 + }
32.2611 + char v = Bits.getChar(buf, pos);
32.2612 + pos += 2;
32.2613 + return v;
32.2614 + }
32.2615 +
32.2616 + public short readShort() throws IOException {
32.2617 + if (!blkmode) {
32.2618 + pos = 0;
32.2619 + in.readFully(buf, 0, 2);
32.2620 + } else if (end - pos < 2) {
32.2621 + return din.readShort();
32.2622 + }
32.2623 + short v = Bits.getShort(buf, pos);
32.2624 + pos += 2;
32.2625 + return v;
32.2626 + }
32.2627 +
32.2628 + public int readUnsignedShort() throws IOException {
32.2629 + if (!blkmode) {
32.2630 + pos = 0;
32.2631 + in.readFully(buf, 0, 2);
32.2632 + } else if (end - pos < 2) {
32.2633 + return din.readUnsignedShort();
32.2634 + }
32.2635 + int v = Bits.getShort(buf, pos) & 0xFFFF;
32.2636 + pos += 2;
32.2637 + return v;
32.2638 + }
32.2639 +
32.2640 + public int readInt() throws IOException {
32.2641 + if (!blkmode) {
32.2642 + pos = 0;
32.2643 + in.readFully(buf, 0, 4);
32.2644 + } else if (end - pos < 4) {
32.2645 + return din.readInt();
32.2646 + }
32.2647 + int v = Bits.getInt(buf, pos);
32.2648 + pos += 4;
32.2649 + return v;
32.2650 + }
32.2651 +
32.2652 + public float readFloat() throws IOException {
32.2653 + if (!blkmode) {
32.2654 + pos = 0;
32.2655 + in.readFully(buf, 0, 4);
32.2656 + } else if (end - pos < 4) {
32.2657 + return din.readFloat();
32.2658 + }
32.2659 + float v = Bits.getFloat(buf, pos);
32.2660 + pos += 4;
32.2661 + return v;
32.2662 + }
32.2663 +
32.2664 + public long readLong() throws IOException {
32.2665 + if (!blkmode) {
32.2666 + pos = 0;
32.2667 + in.readFully(buf, 0, 8);
32.2668 + } else if (end - pos < 8) {
32.2669 + return din.readLong();
32.2670 + }
32.2671 + long v = Bits.getLong(buf, pos);
32.2672 + pos += 8;
32.2673 + return v;
32.2674 + }
32.2675 +
32.2676 + public double readDouble() throws IOException {
32.2677 + if (!blkmode) {
32.2678 + pos = 0;
32.2679 + in.readFully(buf, 0, 8);
32.2680 + } else if (end - pos < 8) {
32.2681 + return din.readDouble();
32.2682 + }
32.2683 + double v = Bits.getDouble(buf, pos);
32.2684 + pos += 8;
32.2685 + return v;
32.2686 + }
32.2687 +
32.2688 + public String readUTF() throws IOException {
32.2689 + return readUTFBody(readUnsignedShort());
32.2690 + }
32.2691 +
32.2692 + public String readLine() throws IOException {
32.2693 + return din.readLine(); // deprecated, not worth optimizing
32.2694 + }
32.2695 +
32.2696 + /* -------------- primitive data array input methods --------------- */
32.2697 + /*
32.2698 + * The following methods read in spans of primitive data values.
32.2699 + * Though equivalent to calling the corresponding primitive read
32.2700 + * methods repeatedly, these methods are optimized for reading groups
32.2701 + * of primitive data values more efficiently.
32.2702 + */
32.2703 +
32.2704 + void readBooleans(boolean[] v, int off, int len) throws IOException {
32.2705 + int stop, endoff = off + len;
32.2706 + while (off < endoff) {
32.2707 + if (!blkmode) {
32.2708 + int span = Math.min(endoff - off, MAX_BLOCK_SIZE);
32.2709 + in.readFully(buf, 0, span);
32.2710 + stop = off + span;
32.2711 + pos = 0;
32.2712 + } else if (end - pos < 1) {
32.2713 + v[off++] = din.readBoolean();
32.2714 + continue;
32.2715 + } else {
32.2716 + stop = Math.min(endoff, off + end - pos);
32.2717 + }
32.2718 +
32.2719 + while (off < stop) {
32.2720 + v[off++] = Bits.getBoolean(buf, pos++);
32.2721 + }
32.2722 + }
32.2723 + }
32.2724 +
32.2725 + void readChars(char[] v, int off, int len) throws IOException {
32.2726 + int stop, endoff = off + len;
32.2727 + while (off < endoff) {
32.2728 + if (!blkmode) {
32.2729 + int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
32.2730 + in.readFully(buf, 0, span << 1);
32.2731 + stop = off + span;
32.2732 + pos = 0;
32.2733 + } else if (end - pos < 2) {
32.2734 + v[off++] = din.readChar();
32.2735 + continue;
32.2736 + } else {
32.2737 + stop = Math.min(endoff, off + ((end - pos) >> 1));
32.2738 + }
32.2739 +
32.2740 + while (off < stop) {
32.2741 + v[off++] = Bits.getChar(buf, pos);
32.2742 + pos += 2;
32.2743 + }
32.2744 + }
32.2745 + }
32.2746 +
32.2747 + void readShorts(short[] v, int off, int len) throws IOException {
32.2748 + int stop, endoff = off + len;
32.2749 + while (off < endoff) {
32.2750 + if (!blkmode) {
32.2751 + int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
32.2752 + in.readFully(buf, 0, span << 1);
32.2753 + stop = off + span;
32.2754 + pos = 0;
32.2755 + } else if (end - pos < 2) {
32.2756 + v[off++] = din.readShort();
32.2757 + continue;
32.2758 + } else {
32.2759 + stop = Math.min(endoff, off + ((end - pos) >> 1));
32.2760 + }
32.2761 +
32.2762 + while (off < stop) {
32.2763 + v[off++] = Bits.getShort(buf, pos);
32.2764 + pos += 2;
32.2765 + }
32.2766 + }
32.2767 + }
32.2768 +
32.2769 + void readInts(int[] v, int off, int len) throws IOException {
32.2770 + int stop, endoff = off + len;
32.2771 + while (off < endoff) {
32.2772 + if (!blkmode) {
32.2773 + int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
32.2774 + in.readFully(buf, 0, span << 2);
32.2775 + stop = off + span;
32.2776 + pos = 0;
32.2777 + } else if (end - pos < 4) {
32.2778 + v[off++] = din.readInt();
32.2779 + continue;
32.2780 + } else {
32.2781 + stop = Math.min(endoff, off + ((end - pos) >> 2));
32.2782 + }
32.2783 +
32.2784 + while (off < stop) {
32.2785 + v[off++] = Bits.getInt(buf, pos);
32.2786 + pos += 4;
32.2787 + }
32.2788 + }
32.2789 + }
32.2790 +
32.2791 + void readFloats(float[] v, int off, int len) throws IOException {
32.2792 + int span, endoff = off + len;
32.2793 + while (off < endoff) {
32.2794 + if (!blkmode) {
32.2795 + span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
32.2796 + in.readFully(buf, 0, span << 2);
32.2797 + pos = 0;
32.2798 + } else if (end - pos < 4) {
32.2799 + v[off++] = din.readFloat();
32.2800 + continue;
32.2801 + } else {
32.2802 + span = Math.min(endoff - off, ((end - pos) >> 2));
32.2803 + }
32.2804 +
32.2805 + bytesToFloats(buf, pos, v, off, span);
32.2806 + off += span;
32.2807 + pos += span << 2;
32.2808 + }
32.2809 + }
32.2810 +
32.2811 + void readLongs(long[] v, int off, int len) throws IOException {
32.2812 + int stop, endoff = off + len;
32.2813 + while (off < endoff) {
32.2814 + if (!blkmode) {
32.2815 + int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
32.2816 + in.readFully(buf, 0, span << 3);
32.2817 + stop = off + span;
32.2818 + pos = 0;
32.2819 + } else if (end - pos < 8) {
32.2820 + v[off++] = din.readLong();
32.2821 + continue;
32.2822 + } else {
32.2823 + stop = Math.min(endoff, off + ((end - pos) >> 3));
32.2824 + }
32.2825 +
32.2826 + while (off < stop) {
32.2827 + v[off++] = Bits.getLong(buf, pos);
32.2828 + pos += 8;
32.2829 + }
32.2830 + }
32.2831 + }
32.2832 +
32.2833 + void readDoubles(double[] v, int off, int len) throws IOException {
32.2834 + int span, endoff = off + len;
32.2835 + while (off < endoff) {
32.2836 + if (!blkmode) {
32.2837 + span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
32.2838 + in.readFully(buf, 0, span << 3);
32.2839 + pos = 0;
32.2840 + } else if (end - pos < 8) {
32.2841 + v[off++] = din.readDouble();
32.2842 + continue;
32.2843 + } else {
32.2844 + span = Math.min(endoff - off, ((end - pos) >> 3));
32.2845 + }
32.2846 +
32.2847 + bytesToDoubles(buf, pos, v, off, span);
32.2848 + off += span;
32.2849 + pos += span << 3;
32.2850 + }
32.2851 + }
32.2852 +
32.2853 + /**
32.2854 + * Reads in string written in "long" UTF format. "Long" UTF format is
32.2855 + * identical to standard UTF, except that it uses an 8 byte header
32.2856 + * (instead of the standard 2 bytes) to convey the UTF encoding length.
32.2857 + */
32.2858 + String readLongUTF() throws IOException {
32.2859 + return readUTFBody(readLong());
32.2860 + }
32.2861 +
32.2862 + /**
32.2863 + * Reads in the "body" (i.e., the UTF representation minus the 2-byte
32.2864 + * or 8-byte length header) of a UTF encoding, which occupies the next
32.2865 + * utflen bytes.
32.2866 + */
32.2867 + private String readUTFBody(long utflen) throws IOException {
32.2868 + StringBuilder sbuf = new StringBuilder();
32.2869 + if (!blkmode) {
32.2870 + end = pos = 0;
32.2871 + }
32.2872 +
32.2873 + while (utflen > 0) {
32.2874 + int avail = end - pos;
32.2875 + if (avail >= 3 || (long) avail == utflen) {
32.2876 + utflen -= readUTFSpan(sbuf, utflen);
32.2877 + } else {
32.2878 + if (blkmode) {
32.2879 + // near block boundary, read one byte at a time
32.2880 + utflen -= readUTFChar(sbuf, utflen);
32.2881 + } else {
32.2882 + // shift and refill buffer manually
32.2883 + if (avail > 0) {
32.2884 + System.arraycopy(buf, pos, buf, 0, avail);
32.2885 + }
32.2886 + pos = 0;
32.2887 + end = (int) Math.min(MAX_BLOCK_SIZE, utflen);
32.2888 + in.readFully(buf, avail, end - avail);
32.2889 + }
32.2890 + }
32.2891 + }
32.2892 +
32.2893 + return sbuf.toString();
32.2894 + }
32.2895 +
32.2896 + /**
32.2897 + * Reads span of UTF-encoded characters out of internal buffer
32.2898 + * (starting at offset pos and ending at or before offset end),
32.2899 + * consuming no more than utflen bytes. Appends read characters to
32.2900 + * sbuf. Returns the number of bytes consumed.
32.2901 + */
32.2902 + private long readUTFSpan(StringBuilder sbuf, long utflen)
32.2903 + throws IOException
32.2904 + {
32.2905 + int cpos = 0;
32.2906 + int start = pos;
32.2907 + int avail = Math.min(end - pos, CHAR_BUF_SIZE);
32.2908 + // stop short of last char unless all of utf bytes in buffer
32.2909 + int stop = pos + ((utflen > avail) ? avail - 2 : (int) utflen);
32.2910 + boolean outOfBounds = false;
32.2911 +
32.2912 + try {
32.2913 + while (pos < stop) {
32.2914 + int b1, b2, b3;
32.2915 + b1 = buf[pos++] & 0xFF;
32.2916 + switch (b1 >> 4) {
32.2917 + case 0:
32.2918 + case 1:
32.2919 + case 2:
32.2920 + case 3:
32.2921 + case 4:
32.2922 + case 5:
32.2923 + case 6:
32.2924 + case 7: // 1 byte format: 0xxxxxxx
32.2925 + cbuf[cpos++] = (char) b1;
32.2926 + break;
32.2927 +
32.2928 + case 12:
32.2929 + case 13: // 2 byte format: 110xxxxx 10xxxxxx
32.2930 + b2 = buf[pos++];
32.2931 + if ((b2 & 0xC0) != 0x80) {
32.2932 + throw new UTFDataFormatException();
32.2933 + }
32.2934 + cbuf[cpos++] = (char) (((b1 & 0x1F) << 6) |
32.2935 + ((b2 & 0x3F) << 0));
32.2936 + break;
32.2937 +
32.2938 + case 14: // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
32.2939 + b3 = buf[pos + 1];
32.2940 + b2 = buf[pos + 0];
32.2941 + pos += 2;
32.2942 + if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
32.2943 + throw new UTFDataFormatException();
32.2944 + }
32.2945 + cbuf[cpos++] = (char) (((b1 & 0x0F) << 12) |
32.2946 + ((b2 & 0x3F) << 6) |
32.2947 + ((b3 & 0x3F) << 0));
32.2948 + break;
32.2949 +
32.2950 + default: // 10xx xxxx, 1111 xxxx
32.2951 + throw new UTFDataFormatException();
32.2952 + }
32.2953 + }
32.2954 + } catch (ArrayIndexOutOfBoundsException ex) {
32.2955 + outOfBounds = true;
32.2956 + } finally {
32.2957 + if (outOfBounds || (pos - start) > utflen) {
32.2958 + /*
32.2959 + * Fix for 4450867: if a malformed utf char causes the
32.2960 + * conversion loop to scan past the expected end of the utf
32.2961 + * string, only consume the expected number of utf bytes.
32.2962 + */
32.2963 + pos = start + (int) utflen;
32.2964 + throw new UTFDataFormatException();
32.2965 + }
32.2966 + }
32.2967 +
32.2968 + sbuf.append(cbuf, 0, cpos);
32.2969 + return pos - start;
32.2970 + }
32.2971 +
32.2972 + /**
32.2973 + * Reads in single UTF-encoded character one byte at a time, appends
32.2974 + * the character to sbuf, and returns the number of bytes consumed.
32.2975 + * This method is used when reading in UTF strings written in block
32.2976 + * data mode to handle UTF-encoded characters which (potentially)
32.2977 + * straddle block-data boundaries.
32.2978 + */
32.2979 + private int readUTFChar(StringBuilder sbuf, long utflen)
32.2980 + throws IOException
32.2981 + {
32.2982 + int b1, b2, b3;
32.2983 + b1 = readByte() & 0xFF;
32.2984 + switch (b1 >> 4) {
32.2985 + case 0:
32.2986 + case 1:
32.2987 + case 2:
32.2988 + case 3:
32.2989 + case 4:
32.2990 + case 5:
32.2991 + case 6:
32.2992 + case 7: // 1 byte format: 0xxxxxxx
32.2993 + sbuf.append((char) b1);
32.2994 + return 1;
32.2995 +
32.2996 + case 12:
32.2997 + case 13: // 2 byte format: 110xxxxx 10xxxxxx
32.2998 + if (utflen < 2) {
32.2999 + throw new UTFDataFormatException();
32.3000 + }
32.3001 + b2 = readByte();
32.3002 + if ((b2 & 0xC0) != 0x80) {
32.3003 + throw new UTFDataFormatException();
32.3004 + }
32.3005 + sbuf.append((char) (((b1 & 0x1F) << 6) |
32.3006 + ((b2 & 0x3F) << 0)));
32.3007 + return 2;
32.3008 +
32.3009 + case 14: // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
32.3010 + if (utflen < 3) {
32.3011 + if (utflen == 2) {
32.3012 + readByte(); // consume remaining byte
32.3013 + }
32.3014 + throw new UTFDataFormatException();
32.3015 + }
32.3016 + b2 = readByte();
32.3017 + b3 = readByte();
32.3018 + if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
32.3019 + throw new UTFDataFormatException();
32.3020 + }
32.3021 + sbuf.append((char) (((b1 & 0x0F) << 12) |
32.3022 + ((b2 & 0x3F) << 6) |
32.3023 + ((b3 & 0x3F) << 0)));
32.3024 + return 3;
32.3025 +
32.3026 + default: // 10xx xxxx, 1111 xxxx
32.3027 + throw new UTFDataFormatException();
32.3028 + }
32.3029 + }
32.3030 + }
32.3031 +
32.3032 + /**
32.3033 + * Unsynchronized table which tracks wire handle to object mappings, as
32.3034 + * well as ClassNotFoundExceptions associated with deserialized objects.
32.3035 + * This class implements an exception-propagation algorithm for
32.3036 + * determining which objects should have ClassNotFoundExceptions associated
32.3037 + * with them, taking into account cycles and discontinuities (e.g., skipped
32.3038 + * fields) in the object graph.
32.3039 + *
32.3040 + * <p>General use of the table is as follows: during deserialization, a
32.3041 + * given object is first assigned a handle by calling the assign method.
32.3042 + * This method leaves the assigned handle in an "open" state, wherein
32.3043 + * dependencies on the exception status of other handles can be registered
32.3044 + * by calling the markDependency method, or an exception can be directly
32.3045 + * associated with the handle by calling markException. When a handle is
32.3046 + * tagged with an exception, the HandleTable assumes responsibility for
32.3047 + * propagating the exception to any other objects which depend
32.3048 + * (transitively) on the exception-tagged object.
32.3049 + *
32.3050 + * <p>Once all exception information/dependencies for the handle have been
32.3051 + * registered, the handle should be "closed" by calling the finish method
32.3052 + * on it. The act of finishing a handle allows the exception propagation
32.3053 + * algorithm to aggressively prune dependency links, lessening the
32.3054 + * performance/memory impact of exception tracking.
32.3055 + *
32.3056 + * <p>Note that the exception propagation algorithm used depends on handles
32.3057 + * being assigned/finished in LIFO order; however, for simplicity as well
32.3058 + * as memory conservation, it does not enforce this constraint.
32.3059 + */
32.3060 + // REMIND: add full description of exception propagation algorithm?
32.3061 + private static class HandleTable {
32.3062 +
32.3063 + /* status codes indicating whether object has associated exception */
32.3064 + private static final byte STATUS_OK = 1;
32.3065 + private static final byte STATUS_UNKNOWN = 2;
32.3066 + private static final byte STATUS_EXCEPTION = 3;
32.3067 +
32.3068 + /** array mapping handle -> object status */
32.3069 + byte[] status;
32.3070 + /** array mapping handle -> object/exception (depending on status) */
32.3071 + Object[] entries;
32.3072 + /** array mapping handle -> list of dependent handles (if any) */
32.3073 + HandleList[] deps;
32.3074 + /** lowest unresolved dependency */
32.3075 + int lowDep = -1;
32.3076 + /** number of handles in table */
32.3077 + int size = 0;
32.3078 +
32.3079 + /**
32.3080 + * Creates handle table with the given initial capacity.
32.3081 + */
32.3082 + HandleTable(int initialCapacity) {
32.3083 + status = new byte[initialCapacity];
32.3084 + entries = new Object[initialCapacity];
32.3085 + deps = new HandleList[initialCapacity];
32.3086 + }
32.3087 +
32.3088 + /**
32.3089 + * Assigns next available handle to given object, and returns assigned
32.3090 + * handle. Once object has been completely deserialized (and all
32.3091 + * dependencies on other objects identified), the handle should be
32.3092 + * "closed" by passing it to finish().
32.3093 + */
32.3094 + int assign(Object obj) {
32.3095 + if (size >= entries.length) {
32.3096 + grow();
32.3097 + }
32.3098 + status[size] = STATUS_UNKNOWN;
32.3099 + entries[size] = obj;
32.3100 + return size++;
32.3101 + }
32.3102 +
32.3103 + /**
32.3104 + * Registers a dependency (in exception status) of one handle on
32.3105 + * another. The dependent handle must be "open" (i.e., assigned, but
32.3106 + * not finished yet). No action is taken if either dependent or target
32.3107 + * handle is NULL_HANDLE.
32.3108 + */
32.3109 + void markDependency(int dependent, int target) {
32.3110 + if (dependent == NULL_HANDLE || target == NULL_HANDLE) {
32.3111 + return;
32.3112 + }
32.3113 + switch (status[dependent]) {
32.3114 +
32.3115 + case STATUS_UNKNOWN:
32.3116 + switch (status[target]) {
32.3117 + case STATUS_OK:
32.3118 + // ignore dependencies on objs with no exception
32.3119 + break;
32.3120 +
32.3121 + case STATUS_EXCEPTION:
32.3122 + // eagerly propagate exception
32.3123 + markException(dependent,
32.3124 + (ClassNotFoundException) entries[target]);
32.3125 + break;
32.3126 +
32.3127 + case STATUS_UNKNOWN:
32.3128 + // add to dependency list of target
32.3129 + if (deps[target] == null) {
32.3130 + deps[target] = new HandleList();
32.3131 + }
32.3132 + deps[target].add(dependent);
32.3133 +
32.3134 + // remember lowest unresolved target seen
32.3135 + if (lowDep < 0 || lowDep > target) {
32.3136 + lowDep = target;
32.3137 + }
32.3138 + break;
32.3139 +
32.3140 + default:
32.3141 + throw new InternalError();
32.3142 + }
32.3143 + break;
32.3144 +
32.3145 + case STATUS_EXCEPTION:
32.3146 + break;
32.3147 +
32.3148 + default:
32.3149 + throw new InternalError();
32.3150 + }
32.3151 + }
32.3152 +
32.3153 + /**
32.3154 + * Associates a ClassNotFoundException (if one not already associated)
32.3155 + * with the currently active handle and propagates it to other
32.3156 + * referencing objects as appropriate. The specified handle must be
32.3157 + * "open" (i.e., assigned, but not finished yet).
32.3158 + */
32.3159 + void markException(int handle, ClassNotFoundException ex) {
32.3160 + switch (status[handle]) {
32.3161 + case STATUS_UNKNOWN:
32.3162 + status[handle] = STATUS_EXCEPTION;
32.3163 + entries[handle] = ex;
32.3164 +
32.3165 + // propagate exception to dependents
32.3166 + HandleList dlist = deps[handle];
32.3167 + if (dlist != null) {
32.3168 + int ndeps = dlist.size();
32.3169 + for (int i = 0; i < ndeps; i++) {
32.3170 + markException(dlist.get(i), ex);
32.3171 + }
32.3172 + deps[handle] = null;
32.3173 + }
32.3174 + break;
32.3175 +
32.3176 + case STATUS_EXCEPTION:
32.3177 + break;
32.3178 +
32.3179 + default:
32.3180 + throw new InternalError();
32.3181 + }
32.3182 + }
32.3183 +
32.3184 + /**
32.3185 + * Marks given handle as finished, meaning that no new dependencies
32.3186 + * will be marked for handle. Calls to the assign and finish methods
32.3187 + * must occur in LIFO order.
32.3188 + */
32.3189 + void finish(int handle) {
32.3190 + int end;
32.3191 + if (lowDep < 0) {
32.3192 + // no pending unknowns, only resolve current handle
32.3193 + end = handle + 1;
32.3194 + } else if (lowDep >= handle) {
32.3195 + // pending unknowns now clearable, resolve all upward handles
32.3196 + end = size;
32.3197 + lowDep = -1;
32.3198 + } else {
32.3199 + // unresolved backrefs present, can't resolve anything yet
32.3200 + return;
32.3201 + }
32.3202 +
32.3203 + // change STATUS_UNKNOWN -> STATUS_OK in selected span of handles
32.3204 + for (int i = handle; i < end; i++) {
32.3205 + switch (status[i]) {
32.3206 + case STATUS_UNKNOWN:
32.3207 + status[i] = STATUS_OK;
32.3208 + deps[i] = null;
32.3209 + break;
32.3210 +
32.3211 + case STATUS_OK:
32.3212 + case STATUS_EXCEPTION:
32.3213 + break;
32.3214 +
32.3215 + default:
32.3216 + throw new InternalError();
32.3217 + }
32.3218 + }
32.3219 + }
32.3220 +
32.3221 + /**
32.3222 + * Assigns a new object to the given handle. The object previously
32.3223 + * associated with the handle is forgotten. This method has no effect
32.3224 + * if the given handle already has an exception associated with it.
32.3225 + * This method may be called at any time after the handle is assigned.
32.3226 + */
32.3227 + void setObject(int handle, Object obj) {
32.3228 + switch (status[handle]) {
32.3229 + case STATUS_UNKNOWN:
32.3230 + case STATUS_OK:
32.3231 + entries[handle] = obj;
32.3232 + break;
32.3233 +
32.3234 + case STATUS_EXCEPTION:
32.3235 + break;
32.3236 +
32.3237 + default:
32.3238 + throw new InternalError();
32.3239 + }
32.3240 + }
32.3241 +
32.3242 + /**
32.3243 + * Looks up and returns object associated with the given handle.
32.3244 + * Returns null if the given handle is NULL_HANDLE, or if it has an
32.3245 + * associated ClassNotFoundException.
32.3246 + */
32.3247 + Object lookupObject(int handle) {
32.3248 + return (handle != NULL_HANDLE &&
32.3249 + status[handle] != STATUS_EXCEPTION) ?
32.3250 + entries[handle] : null;
32.3251 + }
32.3252 +
32.3253 + /**
32.3254 + * Looks up and returns ClassNotFoundException associated with the
32.3255 + * given handle. Returns null if the given handle is NULL_HANDLE, or
32.3256 + * if there is no ClassNotFoundException associated with the handle.
32.3257 + */
32.3258 + ClassNotFoundException lookupException(int handle) {
32.3259 + return (handle != NULL_HANDLE &&
32.3260 + status[handle] == STATUS_EXCEPTION) ?
32.3261 + (ClassNotFoundException) entries[handle] : null;
32.3262 + }
32.3263 +
32.3264 + /**
32.3265 + * Resets table to its initial state.
32.3266 + */
32.3267 + void clear() {
32.3268 + Arrays.fill(status, 0, size, (byte) 0);
32.3269 + Arrays.fill(entries, 0, size, null);
32.3270 + Arrays.fill(deps, 0, size, null);
32.3271 + lowDep = -1;
32.3272 + size = 0;
32.3273 + }
32.3274 +
32.3275 + /**
32.3276 + * Returns number of handles registered in table.
32.3277 + */
32.3278 + int size() {
32.3279 + return size;
32.3280 + }
32.3281 +
32.3282 + /**
32.3283 + * Expands capacity of internal arrays.
32.3284 + */
32.3285 + private void grow() {
32.3286 + int newCapacity = (entries.length << 1) + 1;
32.3287 +
32.3288 + byte[] newStatus = new byte[newCapacity];
32.3289 + Object[] newEntries = new Object[newCapacity];
32.3290 + HandleList[] newDeps = new HandleList[newCapacity];
32.3291 +
32.3292 + System.arraycopy(status, 0, newStatus, 0, size);
32.3293 + System.arraycopy(entries, 0, newEntries, 0, size);
32.3294 + System.arraycopy(deps, 0, newDeps, 0, size);
32.3295 +
32.3296 + status = newStatus;
32.3297 + entries = newEntries;
32.3298 + deps = newDeps;
32.3299 + }
32.3300 +
32.3301 + /**
32.3302 + * Simple growable list of (integer) handles.
32.3303 + */
32.3304 + private static class HandleList {
32.3305 + private int[] list = new int[4];
32.3306 + private int size = 0;
32.3307 +
32.3308 + public HandleList() {
32.3309 + }
32.3310 +
32.3311 + public void add(int handle) {
32.3312 + if (size >= list.length) {
32.3313 + int[] newList = new int[list.length << 1];
32.3314 + System.arraycopy(list, 0, newList, 0, list.length);
32.3315 + list = newList;
32.3316 + }
32.3317 + list[size++] = handle;
32.3318 + }
32.3319 +
32.3320 + public int get(int index) {
32.3321 + if (index >= size) {
32.3322 + throw new ArrayIndexOutOfBoundsException();
32.3323 + }
32.3324 + return list[index];
32.3325 + }
32.3326 +
32.3327 + public int size() {
32.3328 + return size;
32.3329 + }
32.3330 + }
32.3331 + }
32.3332 +
32.3333 + /**
32.3334 + * Method for cloning arrays in case of using unsharing reading
32.3335 + */
32.3336 + private static Object cloneArray(Object array) {
32.3337 + if (array instanceof Object[]) {
32.3338 + return ((Object[]) array).clone();
32.3339 + } else if (array instanceof boolean[]) {
32.3340 + return ((boolean[]) array).clone();
32.3341 + } else if (array instanceof byte[]) {
32.3342 + return ((byte[]) array).clone();
32.3343 + } else if (array instanceof char[]) {
32.3344 + return ((char[]) array).clone();
32.3345 + } else if (array instanceof double[]) {
32.3346 + return ((double[]) array).clone();
32.3347 + } else if (array instanceof float[]) {
32.3348 + return ((float[]) array).clone();
32.3349 + } else if (array instanceof int[]) {
32.3350 + return ((int[]) array).clone();
32.3351 + } else if (array instanceof long[]) {
32.3352 + return ((long[]) array).clone();
32.3353 + } else if (array instanceof short[]) {
32.3354 + return ((short[]) array).clone();
32.3355 + } else {
32.3356 + throw new AssertionError();
32.3357 + }
32.3358 + }
32.3359 +
32.3360 +}
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
33.2 +++ b/emul/compact/src/main/java/java/io/ObjectInputValidation.java Sun Feb 17 17:58:34 2013 +0100
33.3 @@ -0,0 +1,45 @@
33.4 +/*
33.5 + * Copyright (c) 1996, 1999, 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 + * Callback interface to allow validation of objects within a graph.
33.33 + * Allows an object to be called when a complete graph of objects has
33.34 + * been deserialized.
33.35 + *
33.36 + * @author unascribed
33.37 + * @see ObjectInputStream
33.38 + * @see ObjectInputStream#registerValidation(java.io.ObjectInputValidation, int)
33.39 + * @since JDK1.1
33.40 + */
33.41 +public interface ObjectInputValidation {
33.42 + /**
33.43 + * Validates the object.
33.44 + *
33.45 + * @exception InvalidObjectException If the object cannot validate itself.
33.46 + */
33.47 + public void validateObject() throws InvalidObjectException;
33.48 +}
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
34.2 +++ b/emul/compact/src/main/java/java/io/ObjectOutput.java Sun Feb 17 17:58:34 2013 +0100
34.3 @@ -0,0 +1,90 @@
34.4 +/*
34.5 + * Copyright (c) 1996, 2010, 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 + * ObjectOutput extends the DataOutput interface to include writing of objects.
34.33 + * DataOutput includes methods for output of primitive types, ObjectOutput
34.34 + * extends that interface to include objects, arrays, and Strings.
34.35 + *
34.36 + * @author unascribed
34.37 + * @see java.io.InputStream
34.38 + * @see java.io.ObjectOutputStream
34.39 + * @see java.io.ObjectInputStream
34.40 + * @since JDK1.1
34.41 + */
34.42 +public interface ObjectOutput extends DataOutput, AutoCloseable {
34.43 + /**
34.44 + * Write an object to the underlying storage or stream. The
34.45 + * class that implements this interface defines how the object is
34.46 + * written.
34.47 + *
34.48 + * @param obj the object to be written
34.49 + * @exception IOException Any of the usual Input/Output related exceptions.
34.50 + */
34.51 + public void writeObject(Object obj)
34.52 + throws IOException;
34.53 +
34.54 + /**
34.55 + * Writes a byte. This method will block until the byte is actually
34.56 + * written.
34.57 + * @param b the byte
34.58 + * @exception IOException If an I/O error has occurred.
34.59 + */
34.60 + public void write(int b) throws IOException;
34.61 +
34.62 + /**
34.63 + * Writes an array of bytes. This method will block until the bytes
34.64 + * are actually written.
34.65 + * @param b the data to be written
34.66 + * @exception IOException If an I/O error has occurred.
34.67 + */
34.68 + public void write(byte b[]) throws IOException;
34.69 +
34.70 + /**
34.71 + * Writes a sub array of bytes.
34.72 + * @param b the data to be written
34.73 + * @param off the start offset in the data
34.74 + * @param len the number of bytes that are written
34.75 + * @exception IOException If an I/O error has occurred.
34.76 + */
34.77 + public void write(byte b[], int off, int len) throws IOException;
34.78 +
34.79 + /**
34.80 + * Flushes the stream. This will write any buffered
34.81 + * output bytes.
34.82 + * @exception IOException If an I/O error has occurred.
34.83 + */
34.84 + public void flush() throws IOException;
34.85 +
34.86 + /**
34.87 + * Closes the stream. This method must be called
34.88 + * to release any resources associated with the
34.89 + * stream.
34.90 + * @exception IOException If an I/O error has occurred.
34.91 + */
34.92 + public void close() throws IOException;
34.93 +}
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
35.2 +++ b/emul/compact/src/main/java/java/io/ObjectOutputStream.java Sun Feb 17 17:58:34 2013 +0100
35.3 @@ -0,0 +1,2369 @@
35.4 +/*
35.5 + * Copyright (c) 1996, 2010, 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 +import java.util.ArrayList;
35.32 +import java.util.Arrays;
35.33 +import java.util.List;
35.34 +import org.apidesign.bck2brwsr.emul.lang.System;
35.35 +
35.36 +/**
35.37 + * An ObjectOutputStream writes primitive data types and graphs of Java objects
35.38 + * to an OutputStream. The objects can be read (reconstituted) using an
35.39 + * ObjectInputStream. Persistent storage of objects can be accomplished by
35.40 + * using a file for the stream. If the stream is a network socket stream, the
35.41 + * objects can be reconstituted on another host or in another process.
35.42 + *
35.43 + * <p>Only objects that support the java.io.Serializable interface can be
35.44 + * written to streams. The class of each serializable object is encoded
35.45 + * including the class name and signature of the class, the values of the
35.46 + * object's fields and arrays, and the closure of any other objects referenced
35.47 + * from the initial objects.
35.48 + *
35.49 + * <p>The method writeObject is used to write an object to the stream. Any
35.50 + * object, including Strings and arrays, is written with writeObject. Multiple
35.51 + * objects or primitives can be written to the stream. The objects must be
35.52 + * read back from the corresponding ObjectInputstream with the same types and
35.53 + * in the same order as they were written.
35.54 + *
35.55 + * <p>Primitive data types can also be written to the stream using the
35.56 + * appropriate methods from DataOutput. Strings can also be written using the
35.57 + * writeUTF method.
35.58 + *
35.59 + * <p>The default serialization mechanism for an object writes the class of the
35.60 + * object, the class signature, and the values of all non-transient and
35.61 + * non-static fields. References to other objects (except in transient or
35.62 + * static fields) cause those objects to be written also. Multiple references
35.63 + * to a single object are encoded using a reference sharing mechanism so that
35.64 + * graphs of objects can be restored to the same shape as when the original was
35.65 + * written.
35.66 + *
35.67 + * <p>For example to write an object that can be read by the example in
35.68 + * ObjectInputStream:
35.69 + * <br>
35.70 + * <pre>
35.71 + * FileOutputStream fos = new FileOutputStream("t.tmp");
35.72 + * ObjectOutputStream oos = new ObjectOutputStream(fos);
35.73 + *
35.74 + * oos.writeInt(12345);
35.75 + * oos.writeObject("Today");
35.76 + * oos.writeObject(new Date());
35.77 + *
35.78 + * oos.close();
35.79 + * </pre>
35.80 + *
35.81 + * <p>Classes that require special handling during the serialization and
35.82 + * deserialization process must implement special methods with these exact
35.83 + * signatures:
35.84 + * <br>
35.85 + * <pre>
35.86 + * private void readObject(java.io.ObjectInputStream stream)
35.87 + * throws IOException, ClassNotFoundException;
35.88 + * private void writeObject(java.io.ObjectOutputStream stream)
35.89 + * throws IOException
35.90 + * private void readObjectNoData()
35.91 + * throws ObjectStreamException;
35.92 + * </pre>
35.93 + *
35.94 + * <p>The writeObject method is responsible for writing the state of the object
35.95 + * for its particular class so that the corresponding readObject method can
35.96 + * restore it. The method does not need to concern itself with the state
35.97 + * belonging to the object's superclasses or subclasses. State is saved by
35.98 + * writing the individual fields to the ObjectOutputStream using the
35.99 + * writeObject method or by using the methods for primitive data types
35.100 + * supported by DataOutput.
35.101 + *
35.102 + * <p>Serialization does not write out the fields of any object that does not
35.103 + * implement the java.io.Serializable interface. Subclasses of Objects that
35.104 + * are not serializable can be serializable. In this case the non-serializable
35.105 + * class must have a no-arg constructor to allow its fields to be initialized.
35.106 + * In this case it is the responsibility of the subclass to save and restore
35.107 + * the state of the non-serializable class. It is frequently the case that the
35.108 + * fields of that class are accessible (public, package, or protected) or that
35.109 + * there are get and set methods that can be used to restore the state.
35.110 + *
35.111 + * <p>Serialization of an object can be prevented by implementing writeObject
35.112 + * and readObject methods that throw the NotSerializableException. The
35.113 + * exception will be caught by the ObjectOutputStream and abort the
35.114 + * serialization process.
35.115 + *
35.116 + * <p>Implementing the Externalizable interface allows the object to assume
35.117 + * complete control over the contents and format of the object's serialized
35.118 + * form. The methods of the Externalizable interface, writeExternal and
35.119 + * readExternal, are called to save and restore the objects state. When
35.120 + * implemented by a class they can write and read their own state using all of
35.121 + * the methods of ObjectOutput and ObjectInput. It is the responsibility of
35.122 + * the objects to handle any versioning that occurs.
35.123 + *
35.124 + * <p>Enum constants are serialized differently than ordinary serializable or
35.125 + * externalizable objects. The serialized form of an enum constant consists
35.126 + * solely of its name; field values of the constant are not transmitted. To
35.127 + * serialize an enum constant, ObjectOutputStream writes the string returned by
35.128 + * the constant's name method. Like other serializable or externalizable
35.129 + * objects, enum constants can function as the targets of back references
35.130 + * appearing subsequently in the serialization stream. The process by which
35.131 + * enum constants are serialized cannot be customized; any class-specific
35.132 + * writeObject and writeReplace methods defined by enum types are ignored
35.133 + * during serialization. Similarly, any serialPersistentFields or
35.134 + * serialVersionUID field declarations are also ignored--all enum types have a
35.135 + * fixed serialVersionUID of 0L.
35.136 + *
35.137 + * <p>Primitive data, excluding serializable fields and externalizable data, is
35.138 + * written to the ObjectOutputStream in block-data records. A block data record
35.139 + * is composed of a header and data. The block data header consists of a marker
35.140 + * and the number of bytes to follow the header. Consecutive primitive data
35.141 + * writes are merged into one block-data record. The blocking factor used for
35.142 + * a block-data record will be 1024 bytes. Each block-data record will be
35.143 + * filled up to 1024 bytes, or be written whenever there is a termination of
35.144 + * block-data mode. Calls to the ObjectOutputStream methods writeObject,
35.145 + * defaultWriteObject and writeFields initially terminate any existing
35.146 + * block-data record.
35.147 + *
35.148 + * @author Mike Warres
35.149 + * @author Roger Riggs
35.150 + * @see java.io.DataOutput
35.151 + * @see java.io.ObjectInputStream
35.152 + * @see java.io.Serializable
35.153 + * @see java.io.Externalizable
35.154 + * @see <a href="../../../platform/serialization/spec/output.html">Object Serialization Specification, Section 2, Object Output Classes</a>
35.155 + * @since JDK1.1
35.156 + */
35.157 +public class ObjectOutputStream
35.158 + extends OutputStream implements ObjectOutput, ObjectStreamConstants
35.159 +{
35.160 + /** filter stream for handling block data conversion */
35.161 + private final BlockDataOutputStream bout;
35.162 + /** obj -> wire handle map */
35.163 + private final HandleTable handles;
35.164 + /** obj -> replacement obj map */
35.165 + private final ReplaceTable subs;
35.166 + /** stream protocol version */
35.167 + private int protocol = PROTOCOL_VERSION_2;
35.168 + /** recursion depth */
35.169 + private int depth;
35.170 +
35.171 + /** buffer for writing primitive field values */
35.172 + private byte[] primVals;
35.173 +
35.174 + /** if true, invoke writeObjectOverride() instead of writeObject() */
35.175 + private final boolean enableOverride;
35.176 + /** if true, invoke replaceObject() */
35.177 + private boolean enableReplace;
35.178 +
35.179 + // values below valid only during upcalls to writeObject()/writeExternal()
35.180 + /**
35.181 + * Context during upcalls to class-defined writeObject methods; holds
35.182 + * object currently being serialized and descriptor for current class.
35.183 + * Null when not during writeObject upcall.
35.184 + */
35.185 + private Object curContext;
35.186 + /** current PutField object */
35.187 + private PutFieldImpl curPut;
35.188 +
35.189 + /** custom storage for debug trace info */
35.190 + private final DebugTraceInfoStack debugInfoStack;
35.191 +
35.192 + /**
35.193 + * value of "sun.io.serialization.extendedDebugInfo" property,
35.194 + * as true or false for extended information about exception's place
35.195 + */
35.196 + private static final boolean extendedDebugInfo = false;
35.197 +
35.198 + /**
35.199 + * Creates an ObjectOutputStream that writes to the specified OutputStream.
35.200 + * This constructor writes the serialization stream header to the
35.201 + * underlying stream; callers may wish to flush the stream immediately to
35.202 + * ensure that constructors for receiving ObjectInputStreams will not block
35.203 + * when reading the header.
35.204 + *
35.205 + * <p>If a security manager is installed, this constructor will check for
35.206 + * the "enableSubclassImplementation" SerializablePermission when invoked
35.207 + * directly or indirectly by the constructor of a subclass which overrides
35.208 + * the ObjectOutputStream.putFields or ObjectOutputStream.writeUnshared
35.209 + * methods.
35.210 + *
35.211 + * @param out output stream to write to
35.212 + * @throws IOException if an I/O error occurs while writing stream header
35.213 + * @throws SecurityException if untrusted subclass illegally overrides
35.214 + * security-sensitive methods
35.215 + * @throws NullPointerException if <code>out</code> is <code>null</code>
35.216 + * @since 1.4
35.217 + * @see ObjectOutputStream#ObjectOutputStream()
35.218 + * @see ObjectOutputStream#putFields()
35.219 + * @see ObjectInputStream#ObjectInputStream(InputStream)
35.220 + */
35.221 + public ObjectOutputStream(OutputStream out) throws IOException {
35.222 + verifySubclass();
35.223 + bout = new BlockDataOutputStream(out);
35.224 + handles = new HandleTable(10, (float) 3.00);
35.225 + subs = new ReplaceTable(10, (float) 3.00);
35.226 + enableOverride = false;
35.227 + writeStreamHeader();
35.228 + bout.setBlockDataMode(true);
35.229 + if (extendedDebugInfo) {
35.230 + debugInfoStack = new DebugTraceInfoStack();
35.231 + } else {
35.232 + debugInfoStack = null;
35.233 + }
35.234 + }
35.235 +
35.236 + /**
35.237 + * Provide a way for subclasses that are completely reimplementing
35.238 + * ObjectOutputStream to not have to allocate private data just used by
35.239 + * this implementation of ObjectOutputStream.
35.240 + *
35.241 + * <p>If there is a security manager installed, this method first calls the
35.242 + * security manager's <code>checkPermission</code> method with a
35.243 + * <code>SerializablePermission("enableSubclassImplementation")</code>
35.244 + * permission to ensure it's ok to enable subclassing.
35.245 + *
35.246 + * @throws SecurityException if a security manager exists and its
35.247 + * <code>checkPermission</code> method denies enabling
35.248 + * subclassing.
35.249 + * @see SecurityManager#checkPermission
35.250 + * @see java.io.SerializablePermission
35.251 + */
35.252 + protected ObjectOutputStream() throws IOException, SecurityException {
35.253 + throw new SecurityException();
35.254 + }
35.255 +
35.256 + /**
35.257 + * Specify stream protocol version to use when writing the stream.
35.258 + *
35.259 + * <p>This routine provides a hook to enable the current version of
35.260 + * Serialization to write in a format that is backwards compatible to a
35.261 + * previous version of the stream format.
35.262 + *
35.263 + * <p>Every effort will be made to avoid introducing additional
35.264 + * backwards incompatibilities; however, sometimes there is no
35.265 + * other alternative.
35.266 + *
35.267 + * @param version use ProtocolVersion from java.io.ObjectStreamConstants.
35.268 + * @throws IllegalStateException if called after any objects
35.269 + * have been serialized.
35.270 + * @throws IllegalArgumentException if invalid version is passed in.
35.271 + * @throws IOException if I/O errors occur
35.272 + * @see java.io.ObjectStreamConstants#PROTOCOL_VERSION_1
35.273 + * @see java.io.ObjectStreamConstants#PROTOCOL_VERSION_2
35.274 + * @since 1.2
35.275 + */
35.276 + public void useProtocolVersion(int version) throws IOException {
35.277 + if (handles.size() != 0) {
35.278 + // REMIND: implement better check for pristine stream?
35.279 + throw new IllegalStateException("stream non-empty");
35.280 + }
35.281 + switch (version) {
35.282 + case PROTOCOL_VERSION_1:
35.283 + case PROTOCOL_VERSION_2:
35.284 + protocol = version;
35.285 + break;
35.286 +
35.287 + default:
35.288 + throw new IllegalArgumentException(
35.289 + "unknown version: " + version);
35.290 + }
35.291 + }
35.292 +
35.293 + /**
35.294 + * Write the specified object to the ObjectOutputStream. The class of the
35.295 + * object, the signature of the class, and the values of the non-transient
35.296 + * and non-static fields of the class and all of its supertypes are
35.297 + * written. Default serialization for a class can be overridden using the
35.298 + * writeObject and the readObject methods. Objects referenced by this
35.299 + * object are written transitively so that a complete equivalent graph of
35.300 + * objects can be reconstructed by an ObjectInputStream.
35.301 + *
35.302 + * <p>Exceptions are thrown for problems with the OutputStream and for
35.303 + * classes that should not be serialized. All exceptions are fatal to the
35.304 + * OutputStream, which is left in an indeterminate state, and it is up to
35.305 + * the caller to ignore or recover the stream state.
35.306 + *
35.307 + * @throws InvalidClassException Something is wrong with a class used by
35.308 + * serialization.
35.309 + * @throws NotSerializableException Some object to be serialized does not
35.310 + * implement the java.io.Serializable interface.
35.311 + * @throws IOException Any exception thrown by the underlying
35.312 + * OutputStream.
35.313 + */
35.314 + public final void writeObject(Object obj) throws IOException {
35.315 + if (enableOverride) {
35.316 + writeObjectOverride(obj);
35.317 + return;
35.318 + }
35.319 + try {
35.320 + writeObject0(obj, false);
35.321 + } catch (IOException ex) {
35.322 + if (depth == 0) {
35.323 + writeFatalException(ex);
35.324 + }
35.325 + throw ex;
35.326 + }
35.327 + }
35.328 +
35.329 + /**
35.330 + * Method used by subclasses to override the default writeObject method.
35.331 + * This method is called by trusted subclasses of ObjectInputStream that
35.332 + * constructed ObjectInputStream using the protected no-arg constructor.
35.333 + * The subclass is expected to provide an override method with the modifier
35.334 + * "final".
35.335 + *
35.336 + * @param obj object to be written to the underlying stream
35.337 + * @throws IOException if there are I/O errors while writing to the
35.338 + * underlying stream
35.339 + * @see #ObjectOutputStream()
35.340 + * @see #writeObject(Object)
35.341 + * @since 1.2
35.342 + */
35.343 + protected void writeObjectOverride(Object obj) throws IOException {
35.344 + }
35.345 +
35.346 + /**
35.347 + * Writes an "unshared" object to the ObjectOutputStream. This method is
35.348 + * identical to writeObject, except that it always writes the given object
35.349 + * as a new, unique object in the stream (as opposed to a back-reference
35.350 + * pointing to a previously serialized instance). Specifically:
35.351 + * <ul>
35.352 + * <li>An object written via writeUnshared is always serialized in the
35.353 + * same manner as a newly appearing object (an object that has not
35.354 + * been written to the stream yet), regardless of whether or not the
35.355 + * object has been written previously.
35.356 + *
35.357 + * <li>If writeObject is used to write an object that has been previously
35.358 + * written with writeUnshared, the previous writeUnshared operation
35.359 + * is treated as if it were a write of a separate object. In other
35.360 + * words, ObjectOutputStream will never generate back-references to
35.361 + * object data written by calls to writeUnshared.
35.362 + * </ul>
35.363 + * While writing an object via writeUnshared does not in itself guarantee a
35.364 + * unique reference to the object when it is deserialized, it allows a
35.365 + * single object to be defined multiple times in a stream, so that multiple
35.366 + * calls to readUnshared by the receiver will not conflict. Note that the
35.367 + * rules described above only apply to the base-level object written with
35.368 + * writeUnshared, and not to any transitively referenced sub-objects in the
35.369 + * object graph to be serialized.
35.370 + *
35.371 + * <p>ObjectOutputStream subclasses which override this method can only be
35.372 + * constructed in security contexts possessing the
35.373 + * "enableSubclassImplementation" SerializablePermission; any attempt to
35.374 + * instantiate such a subclass without this permission will cause a
35.375 + * SecurityException to be thrown.
35.376 + *
35.377 + * @param obj object to write to stream
35.378 + * @throws NotSerializableException if an object in the graph to be
35.379 + * serialized does not implement the Serializable interface
35.380 + * @throws InvalidClassException if a problem exists with the class of an
35.381 + * object to be serialized
35.382 + * @throws IOException if an I/O error occurs during serialization
35.383 + * @since 1.4
35.384 + */
35.385 + public void writeUnshared(Object obj) throws IOException {
35.386 + try {
35.387 + writeObject0(obj, true);
35.388 + } catch (IOException ex) {
35.389 + if (depth == 0) {
35.390 + writeFatalException(ex);
35.391 + }
35.392 + throw ex;
35.393 + }
35.394 + }
35.395 +
35.396 + /**
35.397 + * Write the non-static and non-transient fields of the current class to
35.398 + * this stream. This may only be called from the writeObject method of the
35.399 + * class being serialized. It will throw the NotActiveException if it is
35.400 + * called otherwise.
35.401 + *
35.402 + * @throws IOException if I/O errors occur while writing to the underlying
35.403 + * <code>OutputStream</code>
35.404 + */
35.405 + public void defaultWriteObject() throws IOException {
35.406 + if ( curContext == null ) {
35.407 + throw new NotActiveException("not in call to writeObject");
35.408 + }
35.409 + Object curObj = null; // curContext.getObj();
35.410 + ObjectStreamClass curDesc = null; // curContext.getDesc();
35.411 + bout.setBlockDataMode(false);
35.412 + defaultWriteFields(curObj, curDesc);
35.413 + bout.setBlockDataMode(true);
35.414 + }
35.415 +
35.416 + /**
35.417 + * Retrieve the object used to buffer persistent fields to be written to
35.418 + * the stream. The fields will be written to the stream when writeFields
35.419 + * method is called.
35.420 + *
35.421 + * @return an instance of the class Putfield that holds the serializable
35.422 + * fields
35.423 + * @throws IOException if I/O errors occur
35.424 + * @since 1.2
35.425 + */
35.426 + public ObjectOutputStream.PutField putFields() throws IOException {
35.427 + if (curPut == null) {
35.428 + if (curContext == null) {
35.429 + throw new NotActiveException("not in call to writeObject");
35.430 + }
35.431 + Object curObj = null; // curContext.getObj();
35.432 + ObjectStreamClass curDesc = null; // curContext.getDesc();
35.433 + curPut = new PutFieldImpl(curDesc);
35.434 + }
35.435 + return curPut;
35.436 + }
35.437 +
35.438 + /**
35.439 + * Write the buffered fields to the stream.
35.440 + *
35.441 + * @throws IOException if I/O errors occur while writing to the underlying
35.442 + * stream
35.443 + * @throws NotActiveException Called when a classes writeObject method was
35.444 + * not called to write the state of the object.
35.445 + * @since 1.2
35.446 + */
35.447 + public void writeFields() throws IOException {
35.448 + if (curPut == null) {
35.449 + throw new NotActiveException("no current PutField object");
35.450 + }
35.451 + bout.setBlockDataMode(false);
35.452 + curPut.writeFields();
35.453 + bout.setBlockDataMode(true);
35.454 + }
35.455 +
35.456 + /**
35.457 + * Reset will disregard the state of any objects already written to the
35.458 + * stream. The state is reset to be the same as a new ObjectOutputStream.
35.459 + * The current point in the stream is marked as reset so the corresponding
35.460 + * ObjectInputStream will be reset at the same point. Objects previously
35.461 + * written to the stream will not be refered to as already being in the
35.462 + * stream. They will be written to the stream again.
35.463 + *
35.464 + * @throws IOException if reset() is invoked while serializing an object.
35.465 + */
35.466 + public void reset() throws IOException {
35.467 + if (depth != 0) {
35.468 + throw new IOException("stream active");
35.469 + }
35.470 + bout.setBlockDataMode(false);
35.471 + bout.writeByte(TC_RESET);
35.472 + clear();
35.473 + bout.setBlockDataMode(true);
35.474 + }
35.475 +
35.476 + /**
35.477 + * Subclasses may implement this method to allow class data to be stored in
35.478 + * the stream. By default this method does nothing. The corresponding
35.479 + * method in ObjectInputStream is resolveClass. This method is called
35.480 + * exactly once for each unique class in the stream. The class name and
35.481 + * signature will have already been written to the stream. This method may
35.482 + * make free use of the ObjectOutputStream to save any representation of
35.483 + * the class it deems suitable (for example, the bytes of the class file).
35.484 + * The resolveClass method in the corresponding subclass of
35.485 + * ObjectInputStream must read and use any data or objects written by
35.486 + * annotateClass.
35.487 + *
35.488 + * @param cl the class to annotate custom data for
35.489 + * @throws IOException Any exception thrown by the underlying
35.490 + * OutputStream.
35.491 + */
35.492 + protected void annotateClass(Class<?> cl) throws IOException {
35.493 + }
35.494 +
35.495 + /**
35.496 + * Subclasses may implement this method to store custom data in the stream
35.497 + * along with descriptors for dynamic proxy classes.
35.498 + *
35.499 + * <p>This method is called exactly once for each unique proxy class
35.500 + * descriptor in the stream. The default implementation of this method in
35.501 + * <code>ObjectOutputStream</code> does nothing.
35.502 + *
35.503 + * <p>The corresponding method in <code>ObjectInputStream</code> is
35.504 + * <code>resolveProxyClass</code>. For a given subclass of
35.505 + * <code>ObjectOutputStream</code> that overrides this method, the
35.506 + * <code>resolveProxyClass</code> method in the corresponding subclass of
35.507 + * <code>ObjectInputStream</code> must read any data or objects written by
35.508 + * <code>annotateProxyClass</code>.
35.509 + *
35.510 + * @param cl the proxy class to annotate custom data for
35.511 + * @throws IOException any exception thrown by the underlying
35.512 + * <code>OutputStream</code>
35.513 + * @see ObjectInputStream#resolveProxyClass(String[])
35.514 + * @since 1.3
35.515 + */
35.516 + protected void annotateProxyClass(Class<?> cl) throws IOException {
35.517 + }
35.518 +
35.519 + /**
35.520 + * This method will allow trusted subclasses of ObjectOutputStream to
35.521 + * substitute one object for another during serialization. Replacing
35.522 + * objects is disabled until enableReplaceObject is called. The
35.523 + * enableReplaceObject method checks that the stream requesting to do
35.524 + * replacement can be trusted. The first occurrence of each object written
35.525 + * into the serialization stream is passed to replaceObject. Subsequent
35.526 + * references to the object are replaced by the object returned by the
35.527 + * original call to replaceObject. To ensure that the private state of
35.528 + * objects is not unintentionally exposed, only trusted streams may use
35.529 + * replaceObject.
35.530 + *
35.531 + * <p>The ObjectOutputStream.writeObject method takes a parameter of type
35.532 + * Object (as opposed to type Serializable) to allow for cases where
35.533 + * non-serializable objects are replaced by serializable ones.
35.534 + *
35.535 + * <p>When a subclass is replacing objects it must insure that either a
35.536 + * complementary substitution must be made during deserialization or that
35.537 + * the substituted object is compatible with every field where the
35.538 + * reference will be stored. Objects whose type is not a subclass of the
35.539 + * type of the field or array element abort the serialization by raising an
35.540 + * exception and the object is not be stored.
35.541 + *
35.542 + * <p>This method is called only once when each object is first
35.543 + * encountered. All subsequent references to the object will be redirected
35.544 + * to the new object. This method should return the object to be
35.545 + * substituted or the original object.
35.546 + *
35.547 + * <p>Null can be returned as the object to be substituted, but may cause
35.548 + * NullReferenceException in classes that contain references to the
35.549 + * original object since they may be expecting an object instead of
35.550 + * null.
35.551 + *
35.552 + * @param obj the object to be replaced
35.553 + * @return the alternate object that replaced the specified one
35.554 + * @throws IOException Any exception thrown by the underlying
35.555 + * OutputStream.
35.556 + */
35.557 + protected Object replaceObject(Object obj) throws IOException {
35.558 + return obj;
35.559 + }
35.560 +
35.561 + /**
35.562 + * Enable the stream to do replacement of objects in the stream. When
35.563 + * enabled, the replaceObject method is called for every object being
35.564 + * serialized.
35.565 + *
35.566 + * <p>If <code>enable</code> is true, and there is a security manager
35.567 + * installed, this method first calls the security manager's
35.568 + * <code>checkPermission</code> method with a
35.569 + * <code>SerializablePermission("enableSubstitution")</code> permission to
35.570 + * ensure it's ok to enable the stream to do replacement of objects in the
35.571 + * stream.
35.572 + *
35.573 + * @param enable boolean parameter to enable replacement of objects
35.574 + * @return the previous setting before this method was invoked
35.575 + * @throws SecurityException if a security manager exists and its
35.576 + * <code>checkPermission</code> method denies enabling the stream
35.577 + * to do replacement of objects in the stream.
35.578 + * @see SecurityManager#checkPermission
35.579 + * @see java.io.SerializablePermission
35.580 + */
35.581 + protected boolean enableReplaceObject(boolean enable)
35.582 + throws SecurityException
35.583 + {
35.584 + throw new SecurityException();
35.585 + }
35.586 +
35.587 + /**
35.588 + * The writeStreamHeader method is provided so subclasses can append or
35.589 + * prepend their own header to the stream. It writes the magic number and
35.590 + * version to the stream.
35.591 + *
35.592 + * @throws IOException if I/O errors occur while writing to the underlying
35.593 + * stream
35.594 + */
35.595 + protected void writeStreamHeader() throws IOException {
35.596 + bout.writeShort(STREAM_MAGIC);
35.597 + bout.writeShort(STREAM_VERSION);
35.598 + }
35.599 +
35.600 + /**
35.601 + * Write the specified class descriptor to the ObjectOutputStream. Class
35.602 + * descriptors are used to identify the classes of objects written to the
35.603 + * stream. Subclasses of ObjectOutputStream may override this method to
35.604 + * customize the way in which class descriptors are written to the
35.605 + * serialization stream. The corresponding method in ObjectInputStream,
35.606 + * <code>readClassDescriptor</code>, should then be overridden to
35.607 + * reconstitute the class descriptor from its custom stream representation.
35.608 + * By default, this method writes class descriptors according to the format
35.609 + * defined in the Object Serialization specification.
35.610 + *
35.611 + * <p>Note that this method will only be called if the ObjectOutputStream
35.612 + * is not using the old serialization stream format (set by calling
35.613 + * ObjectOutputStream's <code>useProtocolVersion</code> method). If this
35.614 + * serialization stream is using the old format
35.615 + * (<code>PROTOCOL_VERSION_1</code>), the class descriptor will be written
35.616 + * internally in a manner that cannot be overridden or customized.
35.617 + *
35.618 + * @param desc class descriptor to write to the stream
35.619 + * @throws IOException If an I/O error has occurred.
35.620 + * @see java.io.ObjectInputStream#readClassDescriptor()
35.621 + * @see #useProtocolVersion(int)
35.622 + * @see java.io.ObjectStreamConstants#PROTOCOL_VERSION_1
35.623 + * @since 1.3
35.624 + */
35.625 + protected void writeClassDescriptor(ObjectStreamClass desc)
35.626 + throws IOException
35.627 + {
35.628 + desc.writeNonProxy(this);
35.629 + }
35.630 +
35.631 + /**
35.632 + * Writes a byte. This method will block until the byte is actually
35.633 + * written.
35.634 + *
35.635 + * @param val the byte to be written to the stream
35.636 + * @throws IOException If an I/O error has occurred.
35.637 + */
35.638 + public void write(int val) throws IOException {
35.639 + bout.write(val);
35.640 + }
35.641 +
35.642 + /**
35.643 + * Writes an array of bytes. This method will block until the bytes are
35.644 + * actually written.
35.645 + *
35.646 + * @param buf the data to be written
35.647 + * @throws IOException If an I/O error has occurred.
35.648 + */
35.649 + public void write(byte[] buf) throws IOException {
35.650 + bout.write(buf, 0, buf.length, false);
35.651 + }
35.652 +
35.653 + /**
35.654 + * Writes a sub array of bytes.
35.655 + *
35.656 + * @param buf the data to be written
35.657 + * @param off the start offset in the data
35.658 + * @param len the number of bytes that are written
35.659 + * @throws IOException If an I/O error has occurred.
35.660 + */
35.661 + public void write(byte[] buf, int off, int len) throws IOException {
35.662 + if (buf == null) {
35.663 + throw new NullPointerException();
35.664 + }
35.665 + int endoff = off + len;
35.666 + if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
35.667 + throw new IndexOutOfBoundsException();
35.668 + }
35.669 + bout.write(buf, off, len, false);
35.670 + }
35.671 +
35.672 + /**
35.673 + * Flushes the stream. This will write any buffered output bytes and flush
35.674 + * through to the underlying stream.
35.675 + *
35.676 + * @throws IOException If an I/O error has occurred.
35.677 + */
35.678 + public void flush() throws IOException {
35.679 + bout.flush();
35.680 + }
35.681 +
35.682 + /**
35.683 + * Drain any buffered data in ObjectOutputStream. Similar to flush but
35.684 + * does not propagate the flush to the underlying stream.
35.685 + *
35.686 + * @throws IOException if I/O errors occur while writing to the underlying
35.687 + * stream
35.688 + */
35.689 + protected void drain() throws IOException {
35.690 + bout.drain();
35.691 + }
35.692 +
35.693 + /**
35.694 + * Closes the stream. This method must be called to release any resources
35.695 + * associated with the stream.
35.696 + *
35.697 + * @throws IOException If an I/O error has occurred.
35.698 + */
35.699 + public void close() throws IOException {
35.700 + flush();
35.701 + clear();
35.702 + bout.close();
35.703 + }
35.704 +
35.705 + /**
35.706 + * Writes a boolean.
35.707 + *
35.708 + * @param val the boolean to be written
35.709 + * @throws IOException if I/O errors occur while writing to the underlying
35.710 + * stream
35.711 + */
35.712 + public void writeBoolean(boolean val) throws IOException {
35.713 + bout.writeBoolean(val);
35.714 + }
35.715 +
35.716 + /**
35.717 + * Writes an 8 bit byte.
35.718 + *
35.719 + * @param val the byte value to be written
35.720 + * @throws IOException if I/O errors occur while writing to the underlying
35.721 + * stream
35.722 + */
35.723 + public void writeByte(int val) throws IOException {
35.724 + bout.writeByte(val);
35.725 + }
35.726 +
35.727 + /**
35.728 + * Writes a 16 bit short.
35.729 + *
35.730 + * @param val the short value to be written
35.731 + * @throws IOException if I/O errors occur while writing to the underlying
35.732 + * stream
35.733 + */
35.734 + public void writeShort(int val) throws IOException {
35.735 + bout.writeShort(val);
35.736 + }
35.737 +
35.738 + /**
35.739 + * Writes a 16 bit char.
35.740 + *
35.741 + * @param val the char value to be written
35.742 + * @throws IOException if I/O errors occur while writing to the underlying
35.743 + * stream
35.744 + */
35.745 + public void writeChar(int val) throws IOException {
35.746 + bout.writeChar(val);
35.747 + }
35.748 +
35.749 + /**
35.750 + * Writes a 32 bit int.
35.751 + *
35.752 + * @param val the integer value to be written
35.753 + * @throws IOException if I/O errors occur while writing to the underlying
35.754 + * stream
35.755 + */
35.756 + public void writeInt(int val) throws IOException {
35.757 + bout.writeInt(val);
35.758 + }
35.759 +
35.760 + /**
35.761 + * Writes a 64 bit long.
35.762 + *
35.763 + * @param val the long value to be written
35.764 + * @throws IOException if I/O errors occur while writing to the underlying
35.765 + * stream
35.766 + */
35.767 + public void writeLong(long val) throws IOException {
35.768 + bout.writeLong(val);
35.769 + }
35.770 +
35.771 + /**
35.772 + * Writes a 32 bit float.
35.773 + *
35.774 + * @param val the float value to be written
35.775 + * @throws IOException if I/O errors occur while writing to the underlying
35.776 + * stream
35.777 + */
35.778 + public void writeFloat(float val) throws IOException {
35.779 + bout.writeFloat(val);
35.780 + }
35.781 +
35.782 + /**
35.783 + * Writes a 64 bit double.
35.784 + *
35.785 + * @param val the double value to be written
35.786 + * @throws IOException if I/O errors occur while writing to the underlying
35.787 + * stream
35.788 + */
35.789 + public void writeDouble(double val) throws IOException {
35.790 + bout.writeDouble(val);
35.791 + }
35.792 +
35.793 + /**
35.794 + * Writes a String as a sequence of bytes.
35.795 + *
35.796 + * @param str the String of bytes to be written
35.797 + * @throws IOException if I/O errors occur while writing to the underlying
35.798 + * stream
35.799 + */
35.800 + public void writeBytes(String str) throws IOException {
35.801 + bout.writeBytes(str);
35.802 + }
35.803 +
35.804 + /**
35.805 + * Writes a String as a sequence of chars.
35.806 + *
35.807 + * @param str the String of chars to be written
35.808 + * @throws IOException if I/O errors occur while writing to the underlying
35.809 + * stream
35.810 + */
35.811 + public void writeChars(String str) throws IOException {
35.812 + bout.writeChars(str);
35.813 + }
35.814 +
35.815 + /**
35.816 + * Primitive data write of this String in
35.817 + * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
35.818 + * format. Note that there is a
35.819 + * significant difference between writing a String into the stream as
35.820 + * primitive data or as an Object. A String instance written by writeObject
35.821 + * is written into the stream as a String initially. Future writeObject()
35.822 + * calls write references to the string into the stream.
35.823 + *
35.824 + * @param str the String to be written
35.825 + * @throws IOException if I/O errors occur while writing to the underlying
35.826 + * stream
35.827 + */
35.828 + public void writeUTF(String str) throws IOException {
35.829 + bout.writeUTF(str);
35.830 + }
35.831 +
35.832 + /**
35.833 + * Provide programmatic access to the persistent fields to be written
35.834 + * to ObjectOutput.
35.835 + *
35.836 + * @since 1.2
35.837 + */
35.838 + public static abstract class PutField {
35.839 +
35.840 + /**
35.841 + * Put the value of the named boolean field into the persistent field.
35.842 + *
35.843 + * @param name the name of the serializable field
35.844 + * @param val the value to assign to the field
35.845 + * @throws IllegalArgumentException if <code>name</code> does not
35.846 + * match the name of a serializable field for the class whose fields
35.847 + * are being written, or if the type of the named field is not
35.848 + * <code>boolean</code>
35.849 + */
35.850 + public abstract void put(String name, boolean val);
35.851 +
35.852 + /**
35.853 + * Put the value of the named byte field into the persistent field.
35.854 + *
35.855 + * @param name the name of the serializable field
35.856 + * @param val the value to assign to the field
35.857 + * @throws IllegalArgumentException if <code>name</code> does not
35.858 + * match the name of a serializable field for the class whose fields
35.859 + * are being written, or if the type of the named field is not
35.860 + * <code>byte</code>
35.861 + */
35.862 + public abstract void put(String name, byte val);
35.863 +
35.864 + /**
35.865 + * Put the value of the named char field into the persistent field.
35.866 + *
35.867 + * @param name the name of the serializable field
35.868 + * @param val the value to assign to the field
35.869 + * @throws IllegalArgumentException if <code>name</code> does not
35.870 + * match the name of a serializable field for the class whose fields
35.871 + * are being written, or if the type of the named field is not
35.872 + * <code>char</code>
35.873 + */
35.874 + public abstract void put(String name, char val);
35.875 +
35.876 + /**
35.877 + * Put the value of the named short field into the persistent field.
35.878 + *
35.879 + * @param name the name of the serializable field
35.880 + * @param val the value to assign to the field
35.881 + * @throws IllegalArgumentException if <code>name</code> does not
35.882 + * match the name of a serializable field for the class whose fields
35.883 + * are being written, or if the type of the named field is not
35.884 + * <code>short</code>
35.885 + */
35.886 + public abstract void put(String name, short val);
35.887 +
35.888 + /**
35.889 + * Put the value of the named int field into the persistent field.
35.890 + *
35.891 + * @param name the name of the serializable field
35.892 + * @param val the value to assign to the field
35.893 + * @throws IllegalArgumentException if <code>name</code> does not
35.894 + * match the name of a serializable field for the class whose fields
35.895 + * are being written, or if the type of the named field is not
35.896 + * <code>int</code>
35.897 + */
35.898 + public abstract void put(String name, int val);
35.899 +
35.900 + /**
35.901 + * Put the value of the named long field into the persistent field.
35.902 + *
35.903 + * @param name the name of the serializable field
35.904 + * @param val the value to assign to the field
35.905 + * @throws IllegalArgumentException if <code>name</code> does not
35.906 + * match the name of a serializable field for the class whose fields
35.907 + * are being written, or if the type of the named field is not
35.908 + * <code>long</code>
35.909 + */
35.910 + public abstract void put(String name, long val);
35.911 +
35.912 + /**
35.913 + * Put the value of the named float field into the persistent field.
35.914 + *
35.915 + * @param name the name of the serializable field
35.916 + * @param val the value to assign to the field
35.917 + * @throws IllegalArgumentException if <code>name</code> does not
35.918 + * match the name of a serializable field for the class whose fields
35.919 + * are being written, or if the type of the named field is not
35.920 + * <code>float</code>
35.921 + */
35.922 + public abstract void put(String name, float val);
35.923 +
35.924 + /**
35.925 + * Put the value of the named double field into the persistent field.
35.926 + *
35.927 + * @param name the name of the serializable field
35.928 + * @param val the value to assign to the field
35.929 + * @throws IllegalArgumentException if <code>name</code> does not
35.930 + * match the name of a serializable field for the class whose fields
35.931 + * are being written, or if the type of the named field is not
35.932 + * <code>double</code>
35.933 + */
35.934 + public abstract void put(String name, double val);
35.935 +
35.936 + /**
35.937 + * Put the value of the named Object field into the persistent field.
35.938 + *
35.939 + * @param name the name of the serializable field
35.940 + * @param val the value to assign to the field
35.941 + * (which may be <code>null</code>)
35.942 + * @throws IllegalArgumentException if <code>name</code> does not
35.943 + * match the name of a serializable field for the class whose fields
35.944 + * are being written, or if the type of the named field is not a
35.945 + * reference type
35.946 + */
35.947 + public abstract void put(String name, Object val);
35.948 +
35.949 + /**
35.950 + * Write the data and fields to the specified ObjectOutput stream,
35.951 + * which must be the same stream that produced this
35.952 + * <code>PutField</code> object.
35.953 + *
35.954 + * @param out the stream to write the data and fields to
35.955 + * @throws IOException if I/O errors occur while writing to the
35.956 + * underlying stream
35.957 + * @throws IllegalArgumentException if the specified stream is not
35.958 + * the same stream that produced this <code>PutField</code>
35.959 + * object
35.960 + * @deprecated This method does not write the values contained by this
35.961 + * <code>PutField</code> object in a proper format, and may
35.962 + * result in corruption of the serialization stream. The
35.963 + * correct way to write <code>PutField</code> data is by
35.964 + * calling the {@link java.io.ObjectOutputStream#writeFields()}
35.965 + * method.
35.966 + */
35.967 + @Deprecated
35.968 + public abstract void write(ObjectOutput out) throws IOException;
35.969 + }
35.970 +
35.971 +
35.972 + /**
35.973 + * Returns protocol version in use.
35.974 + */
35.975 + int getProtocolVersion() {
35.976 + return protocol;
35.977 + }
35.978 +
35.979 + /**
35.980 + * Writes string without allowing it to be replaced in stream. Used by
35.981 + * ObjectStreamClass to write class descriptor type strings.
35.982 + */
35.983 + void writeTypeString(String str) throws IOException {
35.984 + int handle;
35.985 + if (str == null) {
35.986 + writeNull();
35.987 + } else if ((handle = handles.lookup(str)) != -1) {
35.988 + writeHandle(handle);
35.989 + } else {
35.990 + writeString(str, false);
35.991 + }
35.992 + }
35.993 +
35.994 + /**
35.995 + * Verifies that this (possibly subclass) instance can be constructed
35.996 + * without violating security constraints: the subclass must not override
35.997 + * security-sensitive non-final methods, or else the
35.998 + * "enableSubclassImplementation" SerializablePermission is checked.
35.999 + */
35.1000 + private void verifySubclass() {
35.1001 + Class cl = getClass();
35.1002 + if (cl == ObjectOutputStream.class) {
35.1003 + return;
35.1004 + }
35.1005 + throw new SecurityException();
35.1006 + }
35.1007 +
35.1008 + /**
35.1009 + * Clears internal data structures.
35.1010 + */
35.1011 + private void clear() {
35.1012 + subs.clear();
35.1013 + handles.clear();
35.1014 + }
35.1015 +
35.1016 + /**
35.1017 + * Underlying writeObject/writeUnshared implementation.
35.1018 + */
35.1019 + private void writeObject0(Object obj, boolean unshared)
35.1020 + throws IOException
35.1021 + {
35.1022 + boolean oldMode = bout.setBlockDataMode(false);
35.1023 + depth++;
35.1024 + try {
35.1025 + // handle previously written and non-replaceable objects
35.1026 + int h;
35.1027 + if ((obj = subs.lookup(obj)) == null) {
35.1028 + writeNull();
35.1029 + return;
35.1030 + } else if (!unshared && (h = handles.lookup(obj)) != -1) {
35.1031 + writeHandle(h);
35.1032 + return;
35.1033 + } else if (obj instanceof Class) {
35.1034 + writeClass((Class) obj, unshared);
35.1035 + return;
35.1036 + } else if (obj instanceof ObjectStreamClass) {
35.1037 + writeClassDesc((ObjectStreamClass) obj, unshared);
35.1038 + return;
35.1039 + }
35.1040 +
35.1041 + // check for replacement object
35.1042 + Object orig = obj;
35.1043 + Class cl = obj.getClass();
35.1044 + ObjectStreamClass desc;
35.1045 + for (;;) {
35.1046 + // REMIND: skip this check for strings/arrays?
35.1047 + Class repCl;
35.1048 + desc = ObjectStreamClass.lookup(cl, true);
35.1049 + if (!desc.hasWriteReplaceMethod() ||
35.1050 + (obj = desc.invokeWriteReplace(obj)) == null ||
35.1051 + (repCl = obj.getClass()) == cl)
35.1052 + {
35.1053 + break;
35.1054 + }
35.1055 + cl = repCl;
35.1056 + }
35.1057 + if (enableReplace) {
35.1058 + Object rep = replaceObject(obj);
35.1059 + if (rep != obj && rep != null) {
35.1060 + cl = rep.getClass();
35.1061 + desc = ObjectStreamClass.lookup(cl, true);
35.1062 + }
35.1063 + obj = rep;
35.1064 + }
35.1065 +
35.1066 + // if object replaced, run through original checks a second time
35.1067 + if (obj != orig) {
35.1068 + subs.assign(orig, obj);
35.1069 + if (obj == null) {
35.1070 + writeNull();
35.1071 + return;
35.1072 + } else if (!unshared && (h = handles.lookup(obj)) != -1) {
35.1073 + writeHandle(h);
35.1074 + return;
35.1075 + } else if (obj instanceof Class) {
35.1076 + writeClass((Class) obj, unshared);
35.1077 + return;
35.1078 + } else if (obj instanceof ObjectStreamClass) {
35.1079 + writeClassDesc((ObjectStreamClass) obj, unshared);
35.1080 + return;
35.1081 + }
35.1082 + }
35.1083 +
35.1084 + // remaining cases
35.1085 + if (obj instanceof String) {
35.1086 + writeString((String) obj, unshared);
35.1087 + } else if (cl.isArray()) {
35.1088 + writeArray(obj, desc, unshared);
35.1089 + } else if (obj instanceof Enum) {
35.1090 + writeEnum((Enum) obj, desc, unshared);
35.1091 + } else if (obj instanceof Serializable) {
35.1092 + writeOrdinaryObject(obj, desc, unshared);
35.1093 + } else {
35.1094 + if (extendedDebugInfo) {
35.1095 + throw new NotSerializableException(
35.1096 + cl.getName() + "\n" + debugInfoStack.toString());
35.1097 + } else {
35.1098 + throw new NotSerializableException(cl.getName());
35.1099 + }
35.1100 + }
35.1101 + } finally {
35.1102 + depth--;
35.1103 + bout.setBlockDataMode(oldMode);
35.1104 + }
35.1105 + }
35.1106 +
35.1107 + /**
35.1108 + * Writes null code to stream.
35.1109 + */
35.1110 + private void writeNull() throws IOException {
35.1111 + bout.writeByte(TC_NULL);
35.1112 + }
35.1113 +
35.1114 + /**
35.1115 + * Writes given object handle to stream.
35.1116 + */
35.1117 + private void writeHandle(int handle) throws IOException {
35.1118 + bout.writeByte(TC_REFERENCE);
35.1119 + bout.writeInt(baseWireHandle + handle);
35.1120 + }
35.1121 +
35.1122 + /**
35.1123 + * Writes representation of given class to stream.
35.1124 + */
35.1125 + private void writeClass(Class cl, boolean unshared) throws IOException {
35.1126 + bout.writeByte(TC_CLASS);
35.1127 + writeClassDesc(ObjectStreamClass.lookup(cl, true), false);
35.1128 + handles.assign(unshared ? null : cl);
35.1129 + }
35.1130 +
35.1131 + /**
35.1132 + * Writes representation of given class descriptor to stream.
35.1133 + */
35.1134 + private void writeClassDesc(ObjectStreamClass desc, boolean unshared)
35.1135 + throws IOException
35.1136 + {
35.1137 + int handle;
35.1138 + if (desc == null) {
35.1139 + writeNull();
35.1140 + } else if (!unshared && (handle = handles.lookup(desc)) != -1) {
35.1141 + writeHandle(handle);
35.1142 + } else if (desc.isProxy()) {
35.1143 + writeProxyDesc(desc, unshared);
35.1144 + } else {
35.1145 + writeNonProxyDesc(desc, unshared);
35.1146 + }
35.1147 + }
35.1148 +
35.1149 + /**
35.1150 + * Writes class descriptor representing a dynamic proxy class to stream.
35.1151 + */
35.1152 + private void writeProxyDesc(ObjectStreamClass desc, boolean unshared)
35.1153 + throws IOException
35.1154 + {
35.1155 + bout.writeByte(TC_PROXYCLASSDESC);
35.1156 + handles.assign(unshared ? null : desc);
35.1157 +
35.1158 + Class cl = desc.forClass();
35.1159 + Class[] ifaces = cl.getInterfaces();
35.1160 + bout.writeInt(ifaces.length);
35.1161 + for (int i = 0; i < ifaces.length; i++) {
35.1162 + bout.writeUTF(ifaces[i].getName());
35.1163 + }
35.1164 +
35.1165 + bout.setBlockDataMode(true);
35.1166 + annotateProxyClass(cl);
35.1167 + bout.setBlockDataMode(false);
35.1168 + bout.writeByte(TC_ENDBLOCKDATA);
35.1169 +
35.1170 + writeClassDesc(desc.getSuperDesc(), false);
35.1171 + }
35.1172 +
35.1173 + /**
35.1174 + * Writes class descriptor representing a standard (i.e., not a dynamic
35.1175 + * proxy) class to stream.
35.1176 + */
35.1177 + private void writeNonProxyDesc(ObjectStreamClass desc, boolean unshared)
35.1178 + throws IOException
35.1179 + {
35.1180 + bout.writeByte(TC_CLASSDESC);
35.1181 + handles.assign(unshared ? null : desc);
35.1182 +
35.1183 + if (protocol == PROTOCOL_VERSION_1) {
35.1184 + // do not invoke class descriptor write hook with old protocol
35.1185 + desc.writeNonProxy(this);
35.1186 + } else {
35.1187 + writeClassDescriptor(desc);
35.1188 + }
35.1189 +
35.1190 + Class cl = desc.forClass();
35.1191 + bout.setBlockDataMode(true);
35.1192 + annotateClass(cl);
35.1193 + bout.setBlockDataMode(false);
35.1194 + bout.writeByte(TC_ENDBLOCKDATA);
35.1195 +
35.1196 + writeClassDesc(desc.getSuperDesc(), false);
35.1197 + }
35.1198 +
35.1199 + /**
35.1200 + * Writes given string to stream, using standard or long UTF format
35.1201 + * depending on string length.
35.1202 + */
35.1203 + private void writeString(String str, boolean unshared) throws IOException {
35.1204 + handles.assign(unshared ? null : str);
35.1205 + long utflen = bout.getUTFLength(str);
35.1206 + if (utflen <= 0xFFFF) {
35.1207 + bout.writeByte(TC_STRING);
35.1208 + bout.writeUTF(str, utflen);
35.1209 + } else {
35.1210 + bout.writeByte(TC_LONGSTRING);
35.1211 + bout.writeLongUTF(str, utflen);
35.1212 + }
35.1213 + }
35.1214 +
35.1215 + /**
35.1216 + * Writes given array object to stream.
35.1217 + */
35.1218 + private void writeArray(Object array,
35.1219 + ObjectStreamClass desc,
35.1220 + boolean unshared)
35.1221 + throws IOException
35.1222 + {
35.1223 + bout.writeByte(TC_ARRAY);
35.1224 + writeClassDesc(desc, false);
35.1225 + handles.assign(unshared ? null : array);
35.1226 +
35.1227 + Class ccl = desc.forClass().getComponentType();
35.1228 + if (ccl.isPrimitive()) {
35.1229 + if (ccl == Integer.TYPE) {
35.1230 + int[] ia = (int[]) array;
35.1231 + bout.writeInt(ia.length);
35.1232 + bout.writeInts(ia, 0, ia.length);
35.1233 + } else if (ccl == Byte.TYPE) {
35.1234 + byte[] ba = (byte[]) array;
35.1235 + bout.writeInt(ba.length);
35.1236 + bout.write(ba, 0, ba.length, true);
35.1237 + } else if (ccl == Long.TYPE) {
35.1238 + long[] ja = (long[]) array;
35.1239 + bout.writeInt(ja.length);
35.1240 + bout.writeLongs(ja, 0, ja.length);
35.1241 + } else if (ccl == Float.TYPE) {
35.1242 + float[] fa = (float[]) array;
35.1243 + bout.writeInt(fa.length);
35.1244 + bout.writeFloats(fa, 0, fa.length);
35.1245 + } else if (ccl == Double.TYPE) {
35.1246 + double[] da = (double[]) array;
35.1247 + bout.writeInt(da.length);
35.1248 + bout.writeDoubles(da, 0, da.length);
35.1249 + } else if (ccl == Short.TYPE) {
35.1250 + short[] sa = (short[]) array;
35.1251 + bout.writeInt(sa.length);
35.1252 + bout.writeShorts(sa, 0, sa.length);
35.1253 + } else if (ccl == Character.TYPE) {
35.1254 + char[] ca = (char[]) array;
35.1255 + bout.writeInt(ca.length);
35.1256 + bout.writeChars(ca, 0, ca.length);
35.1257 + } else if (ccl == Boolean.TYPE) {
35.1258 + boolean[] za = (boolean[]) array;
35.1259 + bout.writeInt(za.length);
35.1260 + bout.writeBooleans(za, 0, za.length);
35.1261 + } else {
35.1262 + throw new InternalError();
35.1263 + }
35.1264 + } else {
35.1265 + Object[] objs = (Object[]) array;
35.1266 + int len = objs.length;
35.1267 + bout.writeInt(len);
35.1268 + if (extendedDebugInfo) {
35.1269 + debugInfoStack.push(
35.1270 + "array (class \"" + array.getClass().getName() +
35.1271 + "\", size: " + len + ")");
35.1272 + }
35.1273 + try {
35.1274 + for (int i = 0; i < len; i++) {
35.1275 + if (extendedDebugInfo) {
35.1276 + debugInfoStack.push(
35.1277 + "element of array (index: " + i + ")");
35.1278 + }
35.1279 + try {
35.1280 + writeObject0(objs[i], false);
35.1281 + } finally {
35.1282 + if (extendedDebugInfo) {
35.1283 + debugInfoStack.pop();
35.1284 + }
35.1285 + }
35.1286 + }
35.1287 + } finally {
35.1288 + if (extendedDebugInfo) {
35.1289 + debugInfoStack.pop();
35.1290 + }
35.1291 + }
35.1292 + }
35.1293 + }
35.1294 +
35.1295 + /**
35.1296 + * Writes given enum constant to stream.
35.1297 + */
35.1298 + private void writeEnum(Enum en,
35.1299 + ObjectStreamClass desc,
35.1300 + boolean unshared)
35.1301 + throws IOException
35.1302 + {
35.1303 + bout.writeByte(TC_ENUM);
35.1304 + ObjectStreamClass sdesc = desc.getSuperDesc();
35.1305 + writeClassDesc((sdesc.forClass() == Enum.class) ? desc : sdesc, false);
35.1306 + handles.assign(unshared ? null : en);
35.1307 + writeString(en.name(), false);
35.1308 + }
35.1309 +
35.1310 + /**
35.1311 + * Writes representation of a "ordinary" (i.e., not a String, Class,
35.1312 + * ObjectStreamClass, array, or enum constant) serializable object to the
35.1313 + * stream.
35.1314 + */
35.1315 + private void writeOrdinaryObject(Object obj,
35.1316 + ObjectStreamClass desc,
35.1317 + boolean unshared)
35.1318 + throws IOException
35.1319 + {
35.1320 + if (extendedDebugInfo) {
35.1321 + debugInfoStack.push(
35.1322 + (depth == 1 ? "root " : "") + "object (class \"" +
35.1323 + obj.getClass().getName() + "\", " + obj.toString() + ")");
35.1324 + }
35.1325 + try {
35.1326 + desc.checkSerialize();
35.1327 +
35.1328 + bout.writeByte(TC_OBJECT);
35.1329 + writeClassDesc(desc, false);
35.1330 + handles.assign(unshared ? null : obj);
35.1331 + if (desc.isExternalizable() && !desc.isProxy()) {
35.1332 + writeExternalData((Externalizable) obj);
35.1333 + } else {
35.1334 + writeSerialData(obj, desc);
35.1335 + }
35.1336 + } finally {
35.1337 + if (extendedDebugInfo) {
35.1338 + debugInfoStack.pop();
35.1339 + }
35.1340 + }
35.1341 + }
35.1342 +
35.1343 + /**
35.1344 + * Writes externalizable data of given object by invoking its
35.1345 + * writeExternal() method.
35.1346 + */
35.1347 + private void writeExternalData(Externalizable obj) throws IOException {
35.1348 + PutFieldImpl oldPut = curPut;
35.1349 + curPut = null;
35.1350 +
35.1351 + if (extendedDebugInfo) {
35.1352 + debugInfoStack.push("writeExternal data");
35.1353 + }
35.1354 + Object oldContext = curContext;
35.1355 + try {
35.1356 + curContext = null;
35.1357 + if (protocol == PROTOCOL_VERSION_1) {
35.1358 + obj.writeExternal(this);
35.1359 + } else {
35.1360 + bout.setBlockDataMode(true);
35.1361 + obj.writeExternal(this);
35.1362 + bout.setBlockDataMode(false);
35.1363 + bout.writeByte(TC_ENDBLOCKDATA);
35.1364 + }
35.1365 + } finally {
35.1366 + curContext = oldContext;
35.1367 + if (extendedDebugInfo) {
35.1368 + debugInfoStack.pop();
35.1369 + }
35.1370 + }
35.1371 +
35.1372 + curPut = oldPut;
35.1373 + }
35.1374 +
35.1375 + /**
35.1376 + * Writes instance data for each serializable class of given object, from
35.1377 + * superclass to subclass.
35.1378 + */
35.1379 + private void writeSerialData(Object obj, ObjectStreamClass desc)
35.1380 + throws IOException
35.1381 + {
35.1382 + ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
35.1383 + for (int i = 0; i < slots.length; i++) {
35.1384 + ObjectStreamClass slotDesc = slots[i].desc;
35.1385 + if (slotDesc.hasWriteObjectMethod()) {
35.1386 + PutFieldImpl oldPut = curPut;
35.1387 + curPut = null;
35.1388 + Object oldContext = curContext;
35.1389 +
35.1390 + if (extendedDebugInfo) {
35.1391 + debugInfoStack.push(
35.1392 + "custom writeObject data (class \"" +
35.1393 + slotDesc.getName() + "\")");
35.1394 + }
35.1395 + try {
35.1396 + curContext = new Object(); //new SerialCallbackContext(obj, slotDesc);
35.1397 + bout.setBlockDataMode(true);
35.1398 + slotDesc.invokeWriteObject(obj, this);
35.1399 + bout.setBlockDataMode(false);
35.1400 + bout.writeByte(TC_ENDBLOCKDATA);
35.1401 + } finally {
35.1402 + //curContext.setUsed();
35.1403 + curContext = oldContext;
35.1404 + if (extendedDebugInfo) {
35.1405 + debugInfoStack.pop();
35.1406 + }
35.1407 + }
35.1408 +
35.1409 + curPut = oldPut;
35.1410 + } else {
35.1411 + defaultWriteFields(obj, slotDesc);
35.1412 + }
35.1413 + }
35.1414 + }
35.1415 +
35.1416 + /**
35.1417 + * Fetches and writes values of serializable fields of given object to
35.1418 + * stream. The given class descriptor specifies which field values to
35.1419 + * write, and in which order they should be written.
35.1420 + */
35.1421 + private void defaultWriteFields(Object obj, ObjectStreamClass desc)
35.1422 + throws IOException
35.1423 + {
35.1424 + // REMIND: perform conservative isInstance check here?
35.1425 + desc.checkDefaultSerialize();
35.1426 +
35.1427 + int primDataSize = desc.getPrimDataSize();
35.1428 + if (primVals == null || primVals.length < primDataSize) {
35.1429 + primVals = new byte[primDataSize];
35.1430 + }
35.1431 + desc.getPrimFieldValues(obj, primVals);
35.1432 + bout.write(primVals, 0, primDataSize, false);
35.1433 +
35.1434 + ObjectStreamField[] fields = desc.getFields(false);
35.1435 + Object[] objVals = new Object[desc.getNumObjFields()];
35.1436 + int numPrimFields = fields.length - objVals.length;
35.1437 + desc.getObjFieldValues(obj, objVals);
35.1438 + for (int i = 0; i < objVals.length; i++) {
35.1439 + if (extendedDebugInfo) {
35.1440 + debugInfoStack.push(
35.1441 + "field (class \"" + desc.getName() + "\", name: \"" +
35.1442 + fields[numPrimFields + i].getName() + "\", type: \"" +
35.1443 + fields[numPrimFields + i].getType() + "\")");
35.1444 + }
35.1445 + try {
35.1446 + writeObject0(objVals[i],
35.1447 + fields[numPrimFields + i].isUnshared());
35.1448 + } finally {
35.1449 + if (extendedDebugInfo) {
35.1450 + debugInfoStack.pop();
35.1451 + }
35.1452 + }
35.1453 + }
35.1454 + }
35.1455 +
35.1456 + /**
35.1457 + * Attempts to write to stream fatal IOException that has caused
35.1458 + * serialization to abort.
35.1459 + */
35.1460 + private void writeFatalException(IOException ex) throws IOException {
35.1461 + /*
35.1462 + * Note: the serialization specification states that if a second
35.1463 + * IOException occurs while attempting to serialize the original fatal
35.1464 + * exception to the stream, then a StreamCorruptedException should be
35.1465 + * thrown (section 2.1). However, due to a bug in previous
35.1466 + * implementations of serialization, StreamCorruptedExceptions were
35.1467 + * rarely (if ever) actually thrown--the "root" exceptions from
35.1468 + * underlying streams were thrown instead. This historical behavior is
35.1469 + * followed here for consistency.
35.1470 + */
35.1471 + clear();
35.1472 + boolean oldMode = bout.setBlockDataMode(false);
35.1473 + try {
35.1474 + bout.writeByte(TC_EXCEPTION);
35.1475 + writeObject0(ex, false);
35.1476 + clear();
35.1477 + } finally {
35.1478 + bout.setBlockDataMode(oldMode);
35.1479 + }
35.1480 + }
35.1481 +
35.1482 + /**
35.1483 + * Converts specified span of float values into byte values.
35.1484 + */
35.1485 + // REMIND: remove once hotspot inlines Float.floatToIntBits
35.1486 + private static native void floatsToBytes(float[] src, int srcpos,
35.1487 + byte[] dst, int dstpos,
35.1488 + int nfloats);
35.1489 +
35.1490 + /**
35.1491 + * Converts specified span of double values into byte values.
35.1492 + */
35.1493 + // REMIND: remove once hotspot inlines Double.doubleToLongBits
35.1494 + private static native void doublesToBytes(double[] src, int srcpos,
35.1495 + byte[] dst, int dstpos,
35.1496 + int ndoubles);
35.1497 +
35.1498 + /**
35.1499 + * Default PutField implementation.
35.1500 + */
35.1501 + private class PutFieldImpl extends PutField {
35.1502 +
35.1503 + /** class descriptor describing serializable fields */
35.1504 + private final ObjectStreamClass desc;
35.1505 + /** primitive field values */
35.1506 + private final byte[] primVals;
35.1507 + /** object field values */
35.1508 + private final Object[] objVals;
35.1509 +
35.1510 + /**
35.1511 + * Creates PutFieldImpl object for writing fields defined in given
35.1512 + * class descriptor.
35.1513 + */
35.1514 + PutFieldImpl(ObjectStreamClass desc) {
35.1515 + this.desc = desc;
35.1516 + primVals = new byte[desc.getPrimDataSize()];
35.1517 + objVals = new Object[desc.getNumObjFields()];
35.1518 + }
35.1519 +
35.1520 + public void put(String name, boolean val) {
35.1521 + Bits.putBoolean(primVals, getFieldOffset(name, Boolean.TYPE), val);
35.1522 + }
35.1523 +
35.1524 + public void put(String name, byte val) {
35.1525 + primVals[getFieldOffset(name, Byte.TYPE)] = val;
35.1526 + }
35.1527 +
35.1528 + public void put(String name, char val) {
35.1529 + Bits.putChar(primVals, getFieldOffset(name, Character.TYPE), val);
35.1530 + }
35.1531 +
35.1532 + public void put(String name, short val) {
35.1533 + Bits.putShort(primVals, getFieldOffset(name, Short.TYPE), val);
35.1534 + }
35.1535 +
35.1536 + public void put(String name, int val) {
35.1537 + Bits.putInt(primVals, getFieldOffset(name, Integer.TYPE), val);
35.1538 + }
35.1539 +
35.1540 + public void put(String name, float val) {
35.1541 + Bits.putFloat(primVals, getFieldOffset(name, Float.TYPE), val);
35.1542 + }
35.1543 +
35.1544 + public void put(String name, long val) {
35.1545 + Bits.putLong(primVals, getFieldOffset(name, Long.TYPE), val);
35.1546 + }
35.1547 +
35.1548 + public void put(String name, double val) {
35.1549 + Bits.putDouble(primVals, getFieldOffset(name, Double.TYPE), val);
35.1550 + }
35.1551 +
35.1552 + public void put(String name, Object val) {
35.1553 + objVals[getFieldOffset(name, Object.class)] = val;
35.1554 + }
35.1555 +
35.1556 + // deprecated in ObjectOutputStream.PutField
35.1557 + public void write(ObjectOutput out) throws IOException {
35.1558 + /*
35.1559 + * Applications should *not* use this method to write PutField
35.1560 + * data, as it will lead to stream corruption if the PutField
35.1561 + * object writes any primitive data (since block data mode is not
35.1562 + * unset/set properly, as is done in OOS.writeFields()). This
35.1563 + * broken implementation is being retained solely for behavioral
35.1564 + * compatibility, in order to support applications which use
35.1565 + * OOS.PutField.write() for writing only non-primitive data.
35.1566 + *
35.1567 + * Serialization of unshared objects is not implemented here since
35.1568 + * it is not necessary for backwards compatibility; also, unshared
35.1569 + * semantics may not be supported by the given ObjectOutput
35.1570 + * instance. Applications which write unshared objects using the
35.1571 + * PutField API must use OOS.writeFields().
35.1572 + */
35.1573 + if (ObjectOutputStream.this != out) {
35.1574 + throw new IllegalArgumentException("wrong stream");
35.1575 + }
35.1576 + out.write(primVals, 0, primVals.length);
35.1577 +
35.1578 + ObjectStreamField[] fields = desc.getFields(false);
35.1579 + int numPrimFields = fields.length - objVals.length;
35.1580 + // REMIND: warn if numPrimFields > 0?
35.1581 + for (int i = 0; i < objVals.length; i++) {
35.1582 + if (fields[numPrimFields + i].isUnshared()) {
35.1583 + throw new IOException("cannot write unshared object");
35.1584 + }
35.1585 + out.writeObject(objVals[i]);
35.1586 + }
35.1587 + }
35.1588 +
35.1589 + /**
35.1590 + * Writes buffered primitive data and object fields to stream.
35.1591 + */
35.1592 + void writeFields() throws IOException {
35.1593 + bout.write(primVals, 0, primVals.length, false);
35.1594 +
35.1595 + ObjectStreamField[] fields = desc.getFields(false);
35.1596 + int numPrimFields = fields.length - objVals.length;
35.1597 + for (int i = 0; i < objVals.length; i++) {
35.1598 + if (extendedDebugInfo) {
35.1599 + debugInfoStack.push(
35.1600 + "field (class \"" + desc.getName() + "\", name: \"" +
35.1601 + fields[numPrimFields + i].getName() + "\", type: \"" +
35.1602 + fields[numPrimFields + i].getType() + "\")");
35.1603 + }
35.1604 + try {
35.1605 + writeObject0(objVals[i],
35.1606 + fields[numPrimFields + i].isUnshared());
35.1607 + } finally {
35.1608 + if (extendedDebugInfo) {
35.1609 + debugInfoStack.pop();
35.1610 + }
35.1611 + }
35.1612 + }
35.1613 + }
35.1614 +
35.1615 + /**
35.1616 + * Returns offset of field with given name and type. A specified type
35.1617 + * of null matches all types, Object.class matches all non-primitive
35.1618 + * types, and any other non-null type matches assignable types only.
35.1619 + * Throws IllegalArgumentException if no matching field found.
35.1620 + */
35.1621 + private int getFieldOffset(String name, Class type) {
35.1622 + ObjectStreamField field = desc.getField(name, type);
35.1623 + if (field == null) {
35.1624 + throw new IllegalArgumentException("no such field " + name +
35.1625 + " with type " + type);
35.1626 + }
35.1627 + return field.getOffset();
35.1628 + }
35.1629 + }
35.1630 +
35.1631 + /**
35.1632 + * Buffered output stream with two modes: in default mode, outputs data in
35.1633 + * same format as DataOutputStream; in "block data" mode, outputs data
35.1634 + * bracketed by block data markers (see object serialization specification
35.1635 + * for details).
35.1636 + */
35.1637 + private static class BlockDataOutputStream
35.1638 + extends OutputStream implements DataOutput
35.1639 + {
35.1640 + /** maximum data block length */
35.1641 + private static final int MAX_BLOCK_SIZE = 1024;
35.1642 + /** maximum data block header length */
35.1643 + private static final int MAX_HEADER_SIZE = 5;
35.1644 + /** (tunable) length of char buffer (for writing strings) */
35.1645 + private static final int CHAR_BUF_SIZE = 256;
35.1646 +
35.1647 + /** buffer for writing general/block data */
35.1648 + private final byte[] buf = new byte[MAX_BLOCK_SIZE];
35.1649 + /** buffer for writing block data headers */
35.1650 + private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
35.1651 + /** char buffer for fast string writes */
35.1652 + private final char[] cbuf = new char[CHAR_BUF_SIZE];
35.1653 +
35.1654 + /** block data mode */
35.1655 + private boolean blkmode = false;
35.1656 + /** current offset into buf */
35.1657 + private int pos = 0;
35.1658 +
35.1659 + /** underlying output stream */
35.1660 + private final OutputStream out;
35.1661 + /** loopback stream (for data writes that span data blocks) */
35.1662 + private final DataOutputStream dout;
35.1663 +
35.1664 + /**
35.1665 + * Creates new BlockDataOutputStream on top of given underlying stream.
35.1666 + * Block data mode is turned off by default.
35.1667 + */
35.1668 + BlockDataOutputStream(OutputStream out) {
35.1669 + this.out = out;
35.1670 + dout = new DataOutputStream(this);
35.1671 + }
35.1672 +
35.1673 + /**
35.1674 + * Sets block data mode to the given mode (true == on, false == off)
35.1675 + * and returns the previous mode value. If the new mode is the same as
35.1676 + * the old mode, no action is taken. If the new mode differs from the
35.1677 + * old mode, any buffered data is flushed before switching to the new
35.1678 + * mode.
35.1679 + */
35.1680 + boolean setBlockDataMode(boolean mode) throws IOException {
35.1681 + if (blkmode == mode) {
35.1682 + return blkmode;
35.1683 + }
35.1684 + drain();
35.1685 + blkmode = mode;
35.1686 + return !blkmode;
35.1687 + }
35.1688 +
35.1689 + /**
35.1690 + * Returns true if the stream is currently in block data mode, false
35.1691 + * otherwise.
35.1692 + */
35.1693 + boolean getBlockDataMode() {
35.1694 + return blkmode;
35.1695 + }
35.1696 +
35.1697 + /* ----------------- generic output stream methods ----------------- */
35.1698 + /*
35.1699 + * The following methods are equivalent to their counterparts in
35.1700 + * OutputStream, except that they partition written data into data
35.1701 + * blocks when in block data mode.
35.1702 + */
35.1703 +
35.1704 + public void write(int b) throws IOException {
35.1705 + if (pos >= MAX_BLOCK_SIZE) {
35.1706 + drain();
35.1707 + }
35.1708 + buf[pos++] = (byte) b;
35.1709 + }
35.1710 +
35.1711 + public void write(byte[] b) throws IOException {
35.1712 + write(b, 0, b.length, false);
35.1713 + }
35.1714 +
35.1715 + public void write(byte[] b, int off, int len) throws IOException {
35.1716 + write(b, off, len, false);
35.1717 + }
35.1718 +
35.1719 + public void flush() throws IOException {
35.1720 + drain();
35.1721 + out.flush();
35.1722 + }
35.1723 +
35.1724 + public void close() throws IOException {
35.1725 + flush();
35.1726 + out.close();
35.1727 + }
35.1728 +
35.1729 + /**
35.1730 + * Writes specified span of byte values from given array. If copy is
35.1731 + * true, copies the values to an intermediate buffer before writing
35.1732 + * them to underlying stream (to avoid exposing a reference to the
35.1733 + * original byte array).
35.1734 + */
35.1735 + void write(byte[] b, int off, int len, boolean copy)
35.1736 + throws IOException
35.1737 + {
35.1738 + if (!(copy || blkmode)) { // write directly
35.1739 + drain();
35.1740 + out.write(b, off, len);
35.1741 + return;
35.1742 + }
35.1743 +
35.1744 + while (len > 0) {
35.1745 + if (pos >= MAX_BLOCK_SIZE) {
35.1746 + drain();
35.1747 + }
35.1748 + if (len >= MAX_BLOCK_SIZE && !copy && pos == 0) {
35.1749 + // avoid unnecessary copy
35.1750 + writeBlockHeader(MAX_BLOCK_SIZE);
35.1751 + out.write(b, off, MAX_BLOCK_SIZE);
35.1752 + off += MAX_BLOCK_SIZE;
35.1753 + len -= MAX_BLOCK_SIZE;
35.1754 + } else {
35.1755 + int wlen = Math.min(len, MAX_BLOCK_SIZE - pos);
35.1756 + System.arraycopy(b, off, buf, pos, wlen);
35.1757 + pos += wlen;
35.1758 + off += wlen;
35.1759 + len -= wlen;
35.1760 + }
35.1761 + }
35.1762 + }
35.1763 +
35.1764 + /**
35.1765 + * Writes all buffered data from this stream to the underlying stream,
35.1766 + * but does not flush underlying stream.
35.1767 + */
35.1768 + void drain() throws IOException {
35.1769 + if (pos == 0) {
35.1770 + return;
35.1771 + }
35.1772 + if (blkmode) {
35.1773 + writeBlockHeader(pos);
35.1774 + }
35.1775 + out.write(buf, 0, pos);
35.1776 + pos = 0;
35.1777 + }
35.1778 +
35.1779 + /**
35.1780 + * Writes block data header. Data blocks shorter than 256 bytes are
35.1781 + * prefixed with a 2-byte header; all others start with a 5-byte
35.1782 + * header.
35.1783 + */
35.1784 + private void writeBlockHeader(int len) throws IOException {
35.1785 + if (len <= 0xFF) {
35.1786 + hbuf[0] = TC_BLOCKDATA;
35.1787 + hbuf[1] = (byte) len;
35.1788 + out.write(hbuf, 0, 2);
35.1789 + } else {
35.1790 + hbuf[0] = TC_BLOCKDATALONG;
35.1791 + Bits.putInt(hbuf, 1, len);
35.1792 + out.write(hbuf, 0, 5);
35.1793 + }
35.1794 + }
35.1795 +
35.1796 +
35.1797 + /* ----------------- primitive data output methods ----------------- */
35.1798 + /*
35.1799 + * The following methods are equivalent to their counterparts in
35.1800 + * DataOutputStream, except that they partition written data into data
35.1801 + * blocks when in block data mode.
35.1802 + */
35.1803 +
35.1804 + public void writeBoolean(boolean v) throws IOException {
35.1805 + if (pos >= MAX_BLOCK_SIZE) {
35.1806 + drain();
35.1807 + }
35.1808 + Bits.putBoolean(buf, pos++, v);
35.1809 + }
35.1810 +
35.1811 + public void writeByte(int v) throws IOException {
35.1812 + if (pos >= MAX_BLOCK_SIZE) {
35.1813 + drain();
35.1814 + }
35.1815 + buf[pos++] = (byte) v;
35.1816 + }
35.1817 +
35.1818 + public void writeChar(int v) throws IOException {
35.1819 + if (pos + 2 <= MAX_BLOCK_SIZE) {
35.1820 + Bits.putChar(buf, pos, (char) v);
35.1821 + pos += 2;
35.1822 + } else {
35.1823 + dout.writeChar(v);
35.1824 + }
35.1825 + }
35.1826 +
35.1827 + public void writeShort(int v) throws IOException {
35.1828 + if (pos + 2 <= MAX_BLOCK_SIZE) {
35.1829 + Bits.putShort(buf, pos, (short) v);
35.1830 + pos += 2;
35.1831 + } else {
35.1832 + dout.writeShort(v);
35.1833 + }
35.1834 + }
35.1835 +
35.1836 + public void writeInt(int v) throws IOException {
35.1837 + if (pos + 4 <= MAX_BLOCK_SIZE) {
35.1838 + Bits.putInt(buf, pos, v);
35.1839 + pos += 4;
35.1840 + } else {
35.1841 + dout.writeInt(v);
35.1842 + }
35.1843 + }
35.1844 +
35.1845 + public void writeFloat(float v) throws IOException {
35.1846 + if (pos + 4 <= MAX_BLOCK_SIZE) {
35.1847 + Bits.putFloat(buf, pos, v);
35.1848 + pos += 4;
35.1849 + } else {
35.1850 + dout.writeFloat(v);
35.1851 + }
35.1852 + }
35.1853 +
35.1854 + public void writeLong(long v) throws IOException {
35.1855 + if (pos + 8 <= MAX_BLOCK_SIZE) {
35.1856 + Bits.putLong(buf, pos, v);
35.1857 + pos += 8;
35.1858 + } else {
35.1859 + dout.writeLong(v);
35.1860 + }
35.1861 + }
35.1862 +
35.1863 + public void writeDouble(double v) throws IOException {
35.1864 + if (pos + 8 <= MAX_BLOCK_SIZE) {
35.1865 + Bits.putDouble(buf, pos, v);
35.1866 + pos += 8;
35.1867 + } else {
35.1868 + dout.writeDouble(v);
35.1869 + }
35.1870 + }
35.1871 +
35.1872 + public void writeBytes(String s) throws IOException {
35.1873 + int endoff = s.length();
35.1874 + int cpos = 0;
35.1875 + int csize = 0;
35.1876 + for (int off = 0; off < endoff; ) {
35.1877 + if (cpos >= csize) {
35.1878 + cpos = 0;
35.1879 + csize = Math.min(endoff - off, CHAR_BUF_SIZE);
35.1880 + s.getChars(off, off + csize, cbuf, 0);
35.1881 + }
35.1882 + if (pos >= MAX_BLOCK_SIZE) {
35.1883 + drain();
35.1884 + }
35.1885 + int n = Math.min(csize - cpos, MAX_BLOCK_SIZE - pos);
35.1886 + int stop = pos + n;
35.1887 + while (pos < stop) {
35.1888 + buf[pos++] = (byte) cbuf[cpos++];
35.1889 + }
35.1890 + off += n;
35.1891 + }
35.1892 + }
35.1893 +
35.1894 + public void writeChars(String s) throws IOException {
35.1895 + int endoff = s.length();
35.1896 + for (int off = 0; off < endoff; ) {
35.1897 + int csize = Math.min(endoff - off, CHAR_BUF_SIZE);
35.1898 + s.getChars(off, off + csize, cbuf, 0);
35.1899 + writeChars(cbuf, 0, csize);
35.1900 + off += csize;
35.1901 + }
35.1902 + }
35.1903 +
35.1904 + public void writeUTF(String s) throws IOException {
35.1905 + writeUTF(s, getUTFLength(s));
35.1906 + }
35.1907 +
35.1908 +
35.1909 + /* -------------- primitive data array output methods -------------- */
35.1910 + /*
35.1911 + * The following methods write out spans of primitive data values.
35.1912 + * Though equivalent to calling the corresponding primitive write
35.1913 + * methods repeatedly, these methods are optimized for writing groups
35.1914 + * of primitive data values more efficiently.
35.1915 + */
35.1916 +
35.1917 + void writeBooleans(boolean[] v, int off, int len) throws IOException {
35.1918 + int endoff = off + len;
35.1919 + while (off < endoff) {
35.1920 + if (pos >= MAX_BLOCK_SIZE) {
35.1921 + drain();
35.1922 + }
35.1923 + int stop = Math.min(endoff, off + (MAX_BLOCK_SIZE - pos));
35.1924 + while (off < stop) {
35.1925 + Bits.putBoolean(buf, pos++, v[off++]);
35.1926 + }
35.1927 + }
35.1928 + }
35.1929 +
35.1930 + void writeChars(char[] v, int off, int len) throws IOException {
35.1931 + int limit = MAX_BLOCK_SIZE - 2;
35.1932 + int endoff = off + len;
35.1933 + while (off < endoff) {
35.1934 + if (pos <= limit) {
35.1935 + int avail = (MAX_BLOCK_SIZE - pos) >> 1;
35.1936 + int stop = Math.min(endoff, off + avail);
35.1937 + while (off < stop) {
35.1938 + Bits.putChar(buf, pos, v[off++]);
35.1939 + pos += 2;
35.1940 + }
35.1941 + } else {
35.1942 + dout.writeChar(v[off++]);
35.1943 + }
35.1944 + }
35.1945 + }
35.1946 +
35.1947 + void writeShorts(short[] v, int off, int len) throws IOException {
35.1948 + int limit = MAX_BLOCK_SIZE - 2;
35.1949 + int endoff = off + len;
35.1950 + while (off < endoff) {
35.1951 + if (pos <= limit) {
35.1952 + int avail = (MAX_BLOCK_SIZE - pos) >> 1;
35.1953 + int stop = Math.min(endoff, off + avail);
35.1954 + while (off < stop) {
35.1955 + Bits.putShort(buf, pos, v[off++]);
35.1956 + pos += 2;
35.1957 + }
35.1958 + } else {
35.1959 + dout.writeShort(v[off++]);
35.1960 + }
35.1961 + }
35.1962 + }
35.1963 +
35.1964 + void writeInts(int[] v, int off, int len) throws IOException {
35.1965 + int limit = MAX_BLOCK_SIZE - 4;
35.1966 + int endoff = off + len;
35.1967 + while (off < endoff) {
35.1968 + if (pos <= limit) {
35.1969 + int avail = (MAX_BLOCK_SIZE - pos) >> 2;
35.1970 + int stop = Math.min(endoff, off + avail);
35.1971 + while (off < stop) {
35.1972 + Bits.putInt(buf, pos, v[off++]);
35.1973 + pos += 4;
35.1974 + }
35.1975 + } else {
35.1976 + dout.writeInt(v[off++]);
35.1977 + }
35.1978 + }
35.1979 + }
35.1980 +
35.1981 + void writeFloats(float[] v, int off, int len) throws IOException {
35.1982 + int limit = MAX_BLOCK_SIZE - 4;
35.1983 + int endoff = off + len;
35.1984 + while (off < endoff) {
35.1985 + if (pos <= limit) {
35.1986 + int avail = (MAX_BLOCK_SIZE - pos) >> 2;
35.1987 + int chunklen = Math.min(endoff - off, avail);
35.1988 + floatsToBytes(v, off, buf, pos, chunklen);
35.1989 + off += chunklen;
35.1990 + pos += chunklen << 2;
35.1991 + } else {
35.1992 + dout.writeFloat(v[off++]);
35.1993 + }
35.1994 + }
35.1995 + }
35.1996 +
35.1997 + void writeLongs(long[] v, int off, int len) throws IOException {
35.1998 + int limit = MAX_BLOCK_SIZE - 8;
35.1999 + int endoff = off + len;
35.2000 + while (off < endoff) {
35.2001 + if (pos <= limit) {
35.2002 + int avail = (MAX_BLOCK_SIZE - pos) >> 3;
35.2003 + int stop = Math.min(endoff, off + avail);
35.2004 + while (off < stop) {
35.2005 + Bits.putLong(buf, pos, v[off++]);
35.2006 + pos += 8;
35.2007 + }
35.2008 + } else {
35.2009 + dout.writeLong(v[off++]);
35.2010 + }
35.2011 + }
35.2012 + }
35.2013 +
35.2014 + void writeDoubles(double[] v, int off, int len) throws IOException {
35.2015 + int limit = MAX_BLOCK_SIZE - 8;
35.2016 + int endoff = off + len;
35.2017 + while (off < endoff) {
35.2018 + if (pos <= limit) {
35.2019 + int avail = (MAX_BLOCK_SIZE - pos) >> 3;
35.2020 + int chunklen = Math.min(endoff - off, avail);
35.2021 + doublesToBytes(v, off, buf, pos, chunklen);
35.2022 + off += chunklen;
35.2023 + pos += chunklen << 3;
35.2024 + } else {
35.2025 + dout.writeDouble(v[off++]);
35.2026 + }
35.2027 + }
35.2028 + }
35.2029 +
35.2030 + /**
35.2031 + * Returns the length in bytes of the UTF encoding of the given string.
35.2032 + */
35.2033 + long getUTFLength(String s) {
35.2034 + int len = s.length();
35.2035 + long utflen = 0;
35.2036 + for (int off = 0; off < len; ) {
35.2037 + int csize = Math.min(len - off, CHAR_BUF_SIZE);
35.2038 + s.getChars(off, off + csize, cbuf, 0);
35.2039 + for (int cpos = 0; cpos < csize; cpos++) {
35.2040 + char c = cbuf[cpos];
35.2041 + if (c >= 0x0001 && c <= 0x007F) {
35.2042 + utflen++;
35.2043 + } else if (c > 0x07FF) {
35.2044 + utflen += 3;
35.2045 + } else {
35.2046 + utflen += 2;
35.2047 + }
35.2048 + }
35.2049 + off += csize;
35.2050 + }
35.2051 + return utflen;
35.2052 + }
35.2053 +
35.2054 + /**
35.2055 + * Writes the given string in UTF format. This method is used in
35.2056 + * situations where the UTF encoding length of the string is already
35.2057 + * known; specifying it explicitly avoids a prescan of the string to
35.2058 + * determine its UTF length.
35.2059 + */
35.2060 + void writeUTF(String s, long utflen) throws IOException {
35.2061 + if (utflen > 0xFFFFL) {
35.2062 + throw new UTFDataFormatException();
35.2063 + }
35.2064 + writeShort((int) utflen);
35.2065 + if (utflen == (long) s.length()) {
35.2066 + writeBytes(s);
35.2067 + } else {
35.2068 + writeUTFBody(s);
35.2069 + }
35.2070 + }
35.2071 +
35.2072 + /**
35.2073 + * Writes given string in "long" UTF format. "Long" UTF format is
35.2074 + * identical to standard UTF, except that it uses an 8 byte header
35.2075 + * (instead of the standard 2 bytes) to convey the UTF encoding length.
35.2076 + */
35.2077 + void writeLongUTF(String s) throws IOException {
35.2078 + writeLongUTF(s, getUTFLength(s));
35.2079 + }
35.2080 +
35.2081 + /**
35.2082 + * Writes given string in "long" UTF format, where the UTF encoding
35.2083 + * length of the string is already known.
35.2084 + */
35.2085 + void writeLongUTF(String s, long utflen) throws IOException {
35.2086 + writeLong(utflen);
35.2087 + if (utflen == (long) s.length()) {
35.2088 + writeBytes(s);
35.2089 + } else {
35.2090 + writeUTFBody(s);
35.2091 + }
35.2092 + }
35.2093 +
35.2094 + /**
35.2095 + * Writes the "body" (i.e., the UTF representation minus the 2-byte or
35.2096 + * 8-byte length header) of the UTF encoding for the given string.
35.2097 + */
35.2098 + private void writeUTFBody(String s) throws IOException {
35.2099 + int limit = MAX_BLOCK_SIZE - 3;
35.2100 + int len = s.length();
35.2101 + for (int off = 0; off < len; ) {
35.2102 + int csize = Math.min(len - off, CHAR_BUF_SIZE);
35.2103 + s.getChars(off, off + csize, cbuf, 0);
35.2104 + for (int cpos = 0; cpos < csize; cpos++) {
35.2105 + char c = cbuf[cpos];
35.2106 + if (pos <= limit) {
35.2107 + if (c <= 0x007F && c != 0) {
35.2108 + buf[pos++] = (byte) c;
35.2109 + } else if (c > 0x07FF) {
35.2110 + buf[pos + 2] = (byte) (0x80 | ((c >> 0) & 0x3F));
35.2111 + buf[pos + 1] = (byte) (0x80 | ((c >> 6) & 0x3F));
35.2112 + buf[pos + 0] = (byte) (0xE0 | ((c >> 12) & 0x0F));
35.2113 + pos += 3;
35.2114 + } else {
35.2115 + buf[pos + 1] = (byte) (0x80 | ((c >> 0) & 0x3F));
35.2116 + buf[pos + 0] = (byte) (0xC0 | ((c >> 6) & 0x1F));
35.2117 + pos += 2;
35.2118 + }
35.2119 + } else { // write one byte at a time to normalize block
35.2120 + if (c <= 0x007F && c != 0) {
35.2121 + write(c);
35.2122 + } else if (c > 0x07FF) {
35.2123 + write(0xE0 | ((c >> 12) & 0x0F));
35.2124 + write(0x80 | ((c >> 6) & 0x3F));
35.2125 + write(0x80 | ((c >> 0) & 0x3F));
35.2126 + } else {
35.2127 + write(0xC0 | ((c >> 6) & 0x1F));
35.2128 + write(0x80 | ((c >> 0) & 0x3F));
35.2129 + }
35.2130 + }
35.2131 + }
35.2132 + off += csize;
35.2133 + }
35.2134 + }
35.2135 + }
35.2136 +
35.2137 + /**
35.2138 + * Lightweight identity hash table which maps objects to integer handles,
35.2139 + * assigned in ascending order.
35.2140 + */
35.2141 + private static class HandleTable {
35.2142 +
35.2143 + /* number of mappings in table/next available handle */
35.2144 + private int size;
35.2145 + /* size threshold determining when to expand hash spine */
35.2146 + private int threshold;
35.2147 + /* factor for computing size threshold */
35.2148 + private final float loadFactor;
35.2149 + /* maps hash value -> candidate handle value */
35.2150 + private int[] spine;
35.2151 + /* maps handle value -> next candidate handle value */
35.2152 + private int[] next;
35.2153 + /* maps handle value -> associated object */
35.2154 + private Object[] objs;
35.2155 +
35.2156 + /**
35.2157 + * Creates new HandleTable with given capacity and load factor.
35.2158 + */
35.2159 + HandleTable(int initialCapacity, float loadFactor) {
35.2160 + this.loadFactor = loadFactor;
35.2161 + spine = new int[initialCapacity];
35.2162 + next = new int[initialCapacity];
35.2163 + objs = new Object[initialCapacity];
35.2164 + threshold = (int) (initialCapacity * loadFactor);
35.2165 + clear();
35.2166 + }
35.2167 +
35.2168 + /**
35.2169 + * Assigns next available handle to given object, and returns handle
35.2170 + * value. Handles are assigned in ascending order starting at 0.
35.2171 + */
35.2172 + int assign(Object obj) {
35.2173 + if (size >= next.length) {
35.2174 + growEntries();
35.2175 + }
35.2176 + if (size >= threshold) {
35.2177 + growSpine();
35.2178 + }
35.2179 + insert(obj, size);
35.2180 + return size++;
35.2181 + }
35.2182 +
35.2183 + /**
35.2184 + * Looks up and returns handle associated with given object, or -1 if
35.2185 + * no mapping found.
35.2186 + */
35.2187 + int lookup(Object obj) {
35.2188 + if (size == 0) {
35.2189 + return -1;
35.2190 + }
35.2191 + int index = hash(obj) % spine.length;
35.2192 + for (int i = spine[index]; i >= 0; i = next[i]) {
35.2193 + if (objs[i] == obj) {
35.2194 + return i;
35.2195 + }
35.2196 + }
35.2197 + return -1;
35.2198 + }
35.2199 +
35.2200 + /**
35.2201 + * Resets table to its initial (empty) state.
35.2202 + */
35.2203 + void clear() {
35.2204 + Arrays.fill(spine, -1);
35.2205 + Arrays.fill(objs, 0, size, null);
35.2206 + size = 0;
35.2207 + }
35.2208 +
35.2209 + /**
35.2210 + * Returns the number of mappings currently in table.
35.2211 + */
35.2212 + int size() {
35.2213 + return size;
35.2214 + }
35.2215 +
35.2216 + /**
35.2217 + * Inserts mapping object -> handle mapping into table. Assumes table
35.2218 + * is large enough to accommodate new mapping.
35.2219 + */
35.2220 + private void insert(Object obj, int handle) {
35.2221 + int index = hash(obj) % spine.length;
35.2222 + objs[handle] = obj;
35.2223 + next[handle] = spine[index];
35.2224 + spine[index] = handle;
35.2225 + }
35.2226 +
35.2227 + /**
35.2228 + * Expands the hash "spine" -- equivalent to increasing the number of
35.2229 + * buckets in a conventional hash table.
35.2230 + */
35.2231 + private void growSpine() {
35.2232 + spine = new int[(spine.length << 1) + 1];
35.2233 + threshold = (int) (spine.length * loadFactor);
35.2234 + Arrays.fill(spine, -1);
35.2235 + for (int i = 0; i < size; i++) {
35.2236 + insert(objs[i], i);
35.2237 + }
35.2238 + }
35.2239 +
35.2240 + /**
35.2241 + * Increases hash table capacity by lengthening entry arrays.
35.2242 + */
35.2243 + private void growEntries() {
35.2244 + int newLength = (next.length << 1) + 1;
35.2245 + int[] newNext = new int[newLength];
35.2246 + System.arraycopy(next, 0, newNext, 0, size);
35.2247 + next = newNext;
35.2248 +
35.2249 + Object[] newObjs = new Object[newLength];
35.2250 + System.arraycopy(objs, 0, newObjs, 0, size);
35.2251 + objs = newObjs;
35.2252 + }
35.2253 +
35.2254 + /**
35.2255 + * Returns hash value for given object.
35.2256 + */
35.2257 + private int hash(Object obj) {
35.2258 + return System.identityHashCode(obj) & 0x7FFFFFFF;
35.2259 + }
35.2260 + }
35.2261 +
35.2262 + /**
35.2263 + * Lightweight identity hash table which maps objects to replacement
35.2264 + * objects.
35.2265 + */
35.2266 + private static class ReplaceTable {
35.2267 +
35.2268 + /* maps object -> index */
35.2269 + private final HandleTable htab;
35.2270 + /* maps index -> replacement object */
35.2271 + private Object[] reps;
35.2272 +
35.2273 + /**
35.2274 + * Creates new ReplaceTable with given capacity and load factor.
35.2275 + */
35.2276 + ReplaceTable(int initialCapacity, float loadFactor) {
35.2277 + htab = new HandleTable(initialCapacity, loadFactor);
35.2278 + reps = new Object[initialCapacity];
35.2279 + }
35.2280 +
35.2281 + /**
35.2282 + * Enters mapping from object to replacement object.
35.2283 + */
35.2284 + void assign(Object obj, Object rep) {
35.2285 + int index = htab.assign(obj);
35.2286 + while (index >= reps.length) {
35.2287 + grow();
35.2288 + }
35.2289 + reps[index] = rep;
35.2290 + }
35.2291 +
35.2292 + /**
35.2293 + * Looks up and returns replacement for given object. If no
35.2294 + * replacement is found, returns the lookup object itself.
35.2295 + */
35.2296 + Object lookup(Object obj) {
35.2297 + int index = htab.lookup(obj);
35.2298 + return (index >= 0) ? reps[index] : obj;
35.2299 + }
35.2300 +
35.2301 + /**
35.2302 + * Resets table to its initial (empty) state.
35.2303 + */
35.2304 + void clear() {
35.2305 + Arrays.fill(reps, 0, htab.size(), null);
35.2306 + htab.clear();
35.2307 + }
35.2308 +
35.2309 + /**
35.2310 + * Returns the number of mappings currently in table.
35.2311 + */
35.2312 + int size() {
35.2313 + return htab.size();
35.2314 + }
35.2315 +
35.2316 + /**
35.2317 + * Increases table capacity.
35.2318 + */
35.2319 + private void grow() {
35.2320 + Object[] newReps = new Object[(reps.length << 1) + 1];
35.2321 + System.arraycopy(reps, 0, newReps, 0, reps.length);
35.2322 + reps = newReps;
35.2323 + }
35.2324 + }
35.2325 +
35.2326 + /**
35.2327 + * Stack to keep debug information about the state of the
35.2328 + * serialization process, for embedding in exception messages.
35.2329 + */
35.2330 + private static class DebugTraceInfoStack {
35.2331 + private final List<String> stack;
35.2332 +
35.2333 + DebugTraceInfoStack() {
35.2334 + stack = new ArrayList<>();
35.2335 + }
35.2336 +
35.2337 + /**
35.2338 + * Removes all of the elements from enclosed list.
35.2339 + */
35.2340 + void clear() {
35.2341 + stack.clear();
35.2342 + }
35.2343 +
35.2344 + /**
35.2345 + * Removes the object at the top of enclosed list.
35.2346 + */
35.2347 + void pop() {
35.2348 + stack.remove(stack.size()-1);
35.2349 + }
35.2350 +
35.2351 + /**
35.2352 + * Pushes a String onto the top of enclosed list.
35.2353 + */
35.2354 + void push(String entry) {
35.2355 + stack.add("\t- " + entry);
35.2356 + }
35.2357 +
35.2358 + /**
35.2359 + * Returns a string representation of this object
35.2360 + */
35.2361 + public String toString() {
35.2362 + StringBuilder buffer = new StringBuilder();
35.2363 + if (!stack.isEmpty()) {
35.2364 + for(int i = stack.size(); i > 0; i-- ) {
35.2365 + buffer.append(stack.get(i-1) + ((i != 1) ? "\n" : ""));
35.2366 + }
35.2367 + }
35.2368 + return buffer.toString();
35.2369 + }
35.2370 + }
35.2371 +
35.2372 +}
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
36.2 +++ b/emul/compact/src/main/java/java/io/ObjectStreamClass.java Sun Feb 17 17:58:34 2013 +0100
36.3 @@ -0,0 +1,1396 @@
36.4 +/*
36.5 + * Copyright (c) 1996, 2011, 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.io;
36.30 +
36.31 +import java.lang.ref.Reference;
36.32 +import java.lang.ref.ReferenceQueue;
36.33 +import java.lang.ref.SoftReference;
36.34 +import java.lang.ref.WeakReference;
36.35 +import java.lang.reflect.Constructor;
36.36 +import java.lang.reflect.Field;
36.37 +import java.lang.reflect.InvocationTargetException;
36.38 +import java.lang.reflect.Member;
36.39 +import java.lang.reflect.Method;
36.40 +import java.lang.reflect.Modifier;
36.41 +import java.lang.reflect.Proxy;
36.42 +import java.util.ArrayList;
36.43 +import java.util.Arrays;
36.44 +import java.util.Collections;
36.45 +import java.util.Comparator;
36.46 +import java.util.HashSet;
36.47 +import java.util.Set;
36.48 +
36.49 +/**
36.50 + * Serialization's descriptor for classes. It contains the name and
36.51 + * serialVersionUID of the class. The ObjectStreamClass for a specific class
36.52 + * loaded in this Java VM can be found/created using the lookup method.
36.53 + *
36.54 + * <p>The algorithm to compute the SerialVersionUID is described in
36.55 + * <a href="../../../platform/serialization/spec/class.html#4100">Object
36.56 + * Serialization Specification, Section 4.6, Stream Unique Identifiers</a>.
36.57 + *
36.58 + * @author Mike Warres
36.59 + * @author Roger Riggs
36.60 + * @see ObjectStreamField
36.61 + * @see <a href="../../../platform/serialization/spec/class.html">Object Serialization Specification, Section 4, Class Descriptors</a>
36.62 + * @since JDK1.1
36.63 + */
36.64 +public class ObjectStreamClass implements Serializable {
36.65 +
36.66 + /** serialPersistentFields value indicating no serializable fields */
36.67 + public static final ObjectStreamField[] NO_FIELDS =
36.68 + new ObjectStreamField[0];
36.69 +
36.70 + private static final long serialVersionUID = -6120832682080437368L;
36.71 + private static final ObjectStreamField[] serialPersistentFields =
36.72 + NO_FIELDS;
36.73 +
36.74 +
36.75 + /** class associated with this descriptor (if any) */
36.76 + private Class<?> cl;
36.77 + /** name of class represented by this descriptor */
36.78 + private String name;
36.79 + /** serialVersionUID of represented class (null if not computed yet) */
36.80 + private volatile Long suid;
36.81 +
36.82 + /** true if represents dynamic proxy class */
36.83 + private boolean isProxy;
36.84 + /** true if represents enum type */
36.85 + private boolean isEnum;
36.86 + /** true if represented class implements Serializable */
36.87 + private boolean serializable;
36.88 + /** true if represented class implements Externalizable */
36.89 + private boolean externalizable;
36.90 + /** true if desc has data written by class-defined writeObject method */
36.91 + private boolean hasWriteObjectData;
36.92 + /**
36.93 + * true if desc has externalizable data written in block data format; this
36.94 + * must be true by default to accommodate ObjectInputStream subclasses which
36.95 + * override readClassDescriptor() to return class descriptors obtained from
36.96 + * ObjectStreamClass.lookup() (see 4461737)
36.97 + */
36.98 + private boolean hasBlockExternalData = true;
36.99 +
36.100 + /** exception (if any) thrown while attempting to resolve class */
36.101 + private ClassNotFoundException resolveEx;
36.102 + /** exception (if any) to throw if non-enum deserialization attempted */
36.103 + private InvalidClassException deserializeEx;
36.104 + /** exception (if any) to throw if non-enum serialization attempted */
36.105 + private InvalidClassException serializeEx;
36.106 + /** exception (if any) to throw if default serialization attempted */
36.107 + private InvalidClassException defaultSerializeEx;
36.108 +
36.109 + /** serializable fields */
36.110 + private ObjectStreamField[] fields;
36.111 + /** aggregate marshalled size of primitive fields */
36.112 + private int primDataSize;
36.113 + /** number of non-primitive fields */
36.114 + private int numObjFields;
36.115 + /** reflector for setting/getting serializable field values */
36.116 +// private FieldReflector fieldRefl;
36.117 + /** data layout of serialized objects described by this class desc */
36.118 + private volatile ClassDataSlot[] dataLayout;
36.119 +
36.120 + /** serialization-appropriate constructor, or null if none */
36.121 + private Constructor cons;
36.122 + /** class-defined writeObject method, or null if none */
36.123 + private Method writeObjectMethod;
36.124 + /** class-defined readObject method, or null if none */
36.125 + private Method readObjectMethod;
36.126 + /** class-defined readObjectNoData method, or null if none */
36.127 + private Method readObjectNoDataMethod;
36.128 + /** class-defined writeReplace method, or null if none */
36.129 + private Method writeReplaceMethod;
36.130 + /** class-defined readResolve method, or null if none */
36.131 + private Method readResolveMethod;
36.132 +
36.133 + /** local class descriptor for represented class (may point to self) */
36.134 + private ObjectStreamClass localDesc;
36.135 + /** superclass descriptor appearing in stream */
36.136 + private ObjectStreamClass superDesc;
36.137 +
36.138 + /**
36.139 + * Initializes native code.
36.140 + */
36.141 + private static native void initNative();
36.142 + static {
36.143 + initNative();
36.144 + }
36.145 +
36.146 + /**
36.147 + * Find the descriptor for a class that can be serialized. Creates an
36.148 + * ObjectStreamClass instance if one does not exist yet for class. Null is
36.149 + * returned if the specified class does not implement java.io.Serializable
36.150 + * or java.io.Externalizable.
36.151 + *
36.152 + * @param cl class for which to get the descriptor
36.153 + * @return the class descriptor for the specified class
36.154 + */
36.155 + public static ObjectStreamClass lookup(Class<?> cl) {
36.156 + return lookup(cl, false);
36.157 + }
36.158 +
36.159 + /**
36.160 + * Returns the descriptor for any class, regardless of whether it
36.161 + * implements {@link Serializable}.
36.162 + *
36.163 + * @param cl class for which to get the descriptor
36.164 + * @return the class descriptor for the specified class
36.165 + * @since 1.6
36.166 + */
36.167 + public static ObjectStreamClass lookupAny(Class<?> cl) {
36.168 + return lookup(cl, true);
36.169 + }
36.170 +
36.171 + /**
36.172 + * Returns the name of the class described by this descriptor.
36.173 + * This method returns the name of the class in the format that
36.174 + * is used by the {@link Class#getName} method.
36.175 + *
36.176 + * @return a string representing the name of the class
36.177 + */
36.178 + public String getName() {
36.179 + return name;
36.180 + }
36.181 +
36.182 + /**
36.183 + * Return the serialVersionUID for this class. The serialVersionUID
36.184 + * defines a set of classes all with the same name that have evolved from a
36.185 + * common root class and agree to be serialized and deserialized using a
36.186 + * common format. NonSerializable classes have a serialVersionUID of 0L.
36.187 + *
36.188 + * @return the SUID of the class described by this descriptor
36.189 + */
36.190 + public long getSerialVersionUID() {
36.191 + // REMIND: synchronize instead of relying on volatile?
36.192 + if (suid == null) {
36.193 + return computeDefaultSUID(cl);
36.194 + }
36.195 + return suid.longValue();
36.196 + }
36.197 +
36.198 + /**
36.199 + * Return the class in the local VM that this version is mapped to. Null
36.200 + * is returned if there is no corresponding local class.
36.201 + *
36.202 + * @return the <code>Class</code> instance that this descriptor represents
36.203 + */
36.204 + public Class<?> forClass() {
36.205 + return cl;
36.206 + }
36.207 +
36.208 + /**
36.209 + * Return an array of the fields of this serializable class.
36.210 + *
36.211 + * @return an array containing an element for each persistent field of
36.212 + * this class. Returns an array of length zero if there are no
36.213 + * fields.
36.214 + * @since 1.2
36.215 + */
36.216 + public ObjectStreamField[] getFields() {
36.217 + return getFields(true);
36.218 + }
36.219 +
36.220 + /**
36.221 + * Get the field of this class by name.
36.222 + *
36.223 + * @param name the name of the data field to look for
36.224 + * @return The ObjectStreamField object of the named field or null if
36.225 + * there is no such named field.
36.226 + */
36.227 + public ObjectStreamField getField(String name) {
36.228 + return getField(name, null);
36.229 + }
36.230 +
36.231 + /**
36.232 + * Return a string describing this ObjectStreamClass.
36.233 + */
36.234 + public String toString() {
36.235 + return name + ": static final long serialVersionUID = " +
36.236 + getSerialVersionUID() + "L;";
36.237 + }
36.238 +
36.239 + /**
36.240 + * Looks up and returns class descriptor for given class, or null if class
36.241 + * is non-serializable and "all" is set to false.
36.242 + *
36.243 + * @param cl class to look up
36.244 + * @param all if true, return descriptors for all classes; if false, only
36.245 + * return descriptors for serializable classes
36.246 + */
36.247 + static ObjectStreamClass lookup(Class<?> cl, boolean all) {
36.248 + if (!(all || Serializable.class.isAssignableFrom(cl))) {
36.249 + return null;
36.250 + }
36.251 + Object entry = null;
36.252 + EntryFuture future = null;
36.253 + if (entry == null) {
36.254 + EntryFuture newEntry = new EntryFuture();
36.255 + Reference<?> newRef = new SoftReference<>(newEntry);
36.256 + if (entry == null) {
36.257 + future = newEntry;
36.258 + }
36.259 + }
36.260 +
36.261 + if (entry instanceof ObjectStreamClass) { // check common case first
36.262 + return (ObjectStreamClass) entry;
36.263 + }
36.264 + if (entry instanceof EntryFuture) {
36.265 + future = (EntryFuture) entry;
36.266 + if (true) {
36.267 + /*
36.268 + * Handle nested call situation described by 4803747: waiting
36.269 + * for future value to be set by a lookup() call further up the
36.270 + * stack will result in deadlock, so calculate and set the
36.271 + * future value here instead.
36.272 + */
36.273 + entry = null;
36.274 + } else {
36.275 + entry = future.get();
36.276 + }
36.277 + }
36.278 + if (entry == null) {
36.279 + try {
36.280 + entry = new ObjectStreamClass(cl);
36.281 + } catch (Throwable th) {
36.282 + entry = th;
36.283 + }
36.284 + // nested lookup call already set future
36.285 + entry = future.get();
36.286 + }
36.287 +
36.288 + if (entry instanceof ObjectStreamClass) {
36.289 + return (ObjectStreamClass) entry;
36.290 + } else if (entry instanceof RuntimeException) {
36.291 + throw (RuntimeException) entry;
36.292 + } else if (entry instanceof Error) {
36.293 + throw (Error) entry;
36.294 + } else {
36.295 + throw new InternalError("unexpected entry: " + entry);
36.296 + }
36.297 + }
36.298 +
36.299 + /**
36.300 + * Placeholder used in class descriptor and field reflector lookup tables
36.301 + * for an entry in the process of being initialized. (Internal) callers
36.302 + * which receive an EntryFuture belonging to another thread as the result
36.303 + * of a lookup should call the get() method of the EntryFuture; this will
36.304 + * return the actual entry once it is ready for use and has been set(). To
36.305 + * conserve objects, EntryFutures synchronize on themselves.
36.306 + */
36.307 + private static class EntryFuture {
36.308 +
36.309 + private static final Object unset = new Object();
36.310 + private Object entry = unset;
36.311 +
36.312 + /**
36.313 + * Attempts to set the value contained by this EntryFuture. If the
36.314 + * EntryFuture's value has not been set already, then the value is
36.315 + * saved, any callers blocked in the get() method are notified, and
36.316 + * true is returned. If the value has already been set, then no saving
36.317 + * or notification occurs, and false is returned.
36.318 + */
36.319 + synchronized boolean set(Object entry) {
36.320 + if (this.entry != unset) {
36.321 + return false;
36.322 + }
36.323 + this.entry = entry;
36.324 + notifyAll();
36.325 + return true;
36.326 + }
36.327 +
36.328 + /**
36.329 + * Returns the value contained by this EntryFuture, blocking if
36.330 + * necessary until a value is set.
36.331 + */
36.332 + synchronized Object get() {
36.333 + boolean interrupted = false;
36.334 + while (entry == unset) {
36.335 + try {
36.336 + wait();
36.337 + } catch (InterruptedException ex) {
36.338 + interrupted = true;
36.339 + }
36.340 + }
36.341 + return entry;
36.342 + }
36.343 + }
36.344 +
36.345 + /**
36.346 + * Creates local class descriptor representing given class.
36.347 + */
36.348 + private ObjectStreamClass(final Class<?> cl) {
36.349 + this.cl = cl;
36.350 + name = cl.getName();
36.351 + isProxy = Proxy.isProxyClass(cl);
36.352 + isEnum = Enum.class.isAssignableFrom(cl);
36.353 + serializable = Serializable.class.isAssignableFrom(cl);
36.354 + externalizable = Externalizable.class.isAssignableFrom(cl);
36.355 +
36.356 + Class<?> superCl = cl.getSuperclass();
36.357 + superDesc = (superCl != null) ? lookup(superCl, false) : null;
36.358 + localDesc = this;
36.359 +
36.360 + suid = Long.valueOf(0);
36.361 + fields = NO_FIELDS;
36.362 +
36.363 +
36.364 + if (deserializeEx == null) {
36.365 + if (isEnum) {
36.366 + deserializeEx = new InvalidClassException(name, "enum type");
36.367 + } else if (cons == null) {
36.368 + deserializeEx = new InvalidClassException(
36.369 + name, "no valid constructor");
36.370 + }
36.371 + }
36.372 + for (int i = 0; i < fields.length; i++) {
36.373 + if (fields[i].getField() == null) {
36.374 + defaultSerializeEx = new InvalidClassException(
36.375 + name, "unmatched serializable field(s) declared");
36.376 + }
36.377 + }
36.378 + }
36.379 +
36.380 + /**
36.381 + * Creates blank class descriptor which should be initialized via a
36.382 + * subsequent call to initProxy(), initNonProxy() or readNonProxy().
36.383 + */
36.384 + ObjectStreamClass() {
36.385 + }
36.386 +
36.387 + /**
36.388 + * Initializes class descriptor representing a proxy class.
36.389 + */
36.390 + void initProxy(Class<?> cl,
36.391 + ClassNotFoundException resolveEx,
36.392 + ObjectStreamClass superDesc)
36.393 + throws InvalidClassException
36.394 + {
36.395 + this.cl = cl;
36.396 + this.resolveEx = resolveEx;
36.397 + this.superDesc = superDesc;
36.398 + isProxy = true;
36.399 + serializable = true;
36.400 + suid = Long.valueOf(0);
36.401 + fields = NO_FIELDS;
36.402 +
36.403 + if (cl != null) {
36.404 + localDesc = lookup(cl, true);
36.405 + if (!localDesc.isProxy) {
36.406 + throw new InvalidClassException(
36.407 + "cannot bind proxy descriptor to a non-proxy class");
36.408 + }
36.409 + name = localDesc.name;
36.410 + externalizable = localDesc.externalizable;
36.411 + cons = localDesc.cons;
36.412 + writeReplaceMethod = localDesc.writeReplaceMethod;
36.413 + readResolveMethod = localDesc.readResolveMethod;
36.414 + deserializeEx = localDesc.deserializeEx;
36.415 + }
36.416 + }
36.417 +
36.418 + /**
36.419 + * Initializes class descriptor representing a non-proxy class.
36.420 + */
36.421 + void initNonProxy(ObjectStreamClass model,
36.422 + Class<?> cl,
36.423 + ClassNotFoundException resolveEx,
36.424 + ObjectStreamClass superDesc)
36.425 + throws InvalidClassException
36.426 + {
36.427 + this.cl = cl;
36.428 + this.resolveEx = resolveEx;
36.429 + this.superDesc = superDesc;
36.430 + name = model.name;
36.431 + suid = Long.valueOf(model.getSerialVersionUID());
36.432 + isProxy = false;
36.433 + isEnum = model.isEnum;
36.434 + serializable = model.serializable;
36.435 + externalizable = model.externalizable;
36.436 + hasBlockExternalData = model.hasBlockExternalData;
36.437 + hasWriteObjectData = model.hasWriteObjectData;
36.438 + fields = model.fields;
36.439 + primDataSize = model.primDataSize;
36.440 + numObjFields = model.numObjFields;
36.441 +
36.442 + if (cl != null) {
36.443 + localDesc = lookup(cl, true);
36.444 + if (localDesc.isProxy) {
36.445 + throw new InvalidClassException(
36.446 + "cannot bind non-proxy descriptor to a proxy class");
36.447 + }
36.448 + if (isEnum != localDesc.isEnum) {
36.449 + throw new InvalidClassException(isEnum ?
36.450 + "cannot bind enum descriptor to a non-enum class" :
36.451 + "cannot bind non-enum descriptor to an enum class");
36.452 + }
36.453 +
36.454 + if (serializable == localDesc.serializable &&
36.455 + !cl.isArray() &&
36.456 + suid.longValue() != localDesc.getSerialVersionUID())
36.457 + {
36.458 + throw new InvalidClassException(localDesc.name,
36.459 + "local class incompatible: " +
36.460 + "stream classdesc serialVersionUID = " + suid +
36.461 + ", local class serialVersionUID = " +
36.462 + localDesc.getSerialVersionUID());
36.463 + }
36.464 +
36.465 + if (!classNamesEqual(name, localDesc.name)) {
36.466 + throw new InvalidClassException(localDesc.name,
36.467 + "local class name incompatible with stream class " +
36.468 + "name \"" + name + "\"");
36.469 + }
36.470 +
36.471 + if (!isEnum) {
36.472 + if ((serializable == localDesc.serializable) &&
36.473 + (externalizable != localDesc.externalizable))
36.474 + {
36.475 + throw new InvalidClassException(localDesc.name,
36.476 + "Serializable incompatible with Externalizable");
36.477 + }
36.478 +
36.479 + if ((serializable != localDesc.serializable) ||
36.480 + (externalizable != localDesc.externalizable) ||
36.481 + !(serializable || externalizable))
36.482 + {
36.483 + deserializeEx = new InvalidClassException(localDesc.name,
36.484 + "class invalid for deserialization");
36.485 + }
36.486 + }
36.487 +
36.488 + cons = localDesc.cons;
36.489 + writeObjectMethod = localDesc.writeObjectMethod;
36.490 + readObjectMethod = localDesc.readObjectMethod;
36.491 + readObjectNoDataMethod = localDesc.readObjectNoDataMethod;
36.492 + writeReplaceMethod = localDesc.writeReplaceMethod;
36.493 + readResolveMethod = localDesc.readResolveMethod;
36.494 + if (deserializeEx == null) {
36.495 + deserializeEx = localDesc.deserializeEx;
36.496 + }
36.497 + }
36.498 + // reassign to matched fields so as to reflect local unshared settings
36.499 + fields = null;
36.500 + }
36.501 +
36.502 + /**
36.503 + * Reads non-proxy class descriptor information from given input stream.
36.504 + * The resulting class descriptor is not fully functional; it can only be
36.505 + * used as input to the ObjectInputStream.resolveClass() and
36.506 + * ObjectStreamClass.initNonProxy() methods.
36.507 + */
36.508 + void readNonProxy(ObjectInputStream in)
36.509 + throws IOException, ClassNotFoundException
36.510 + {
36.511 + name = in.readUTF();
36.512 + suid = Long.valueOf(in.readLong());
36.513 + isProxy = false;
36.514 +
36.515 + byte flags = in.readByte();
36.516 + hasWriteObjectData =
36.517 + ((flags & ObjectStreamConstants.SC_WRITE_METHOD) != 0);
36.518 + hasBlockExternalData =
36.519 + ((flags & ObjectStreamConstants.SC_BLOCK_DATA) != 0);
36.520 + externalizable =
36.521 + ((flags & ObjectStreamConstants.SC_EXTERNALIZABLE) != 0);
36.522 + boolean sflag =
36.523 + ((flags & ObjectStreamConstants.SC_SERIALIZABLE) != 0);
36.524 + if (externalizable && sflag) {
36.525 + throw new InvalidClassException(
36.526 + name, "serializable and externalizable flags conflict");
36.527 + }
36.528 + serializable = externalizable || sflag;
36.529 + isEnum = ((flags & ObjectStreamConstants.SC_ENUM) != 0);
36.530 + if (isEnum && suid.longValue() != 0L) {
36.531 + throw new InvalidClassException(name,
36.532 + "enum descriptor has non-zero serialVersionUID: " + suid);
36.533 + }
36.534 +
36.535 + int numFields = in.readShort();
36.536 + if (isEnum && numFields != 0) {
36.537 + throw new InvalidClassException(name,
36.538 + "enum descriptor has non-zero field count: " + numFields);
36.539 + }
36.540 + fields = (numFields > 0) ?
36.541 + new ObjectStreamField[numFields] : NO_FIELDS;
36.542 + for (int i = 0; i < numFields; i++) {
36.543 + char tcode = (char) in.readByte();
36.544 + String fname = in.readUTF();
36.545 + String signature = ((tcode == 'L') || (tcode == '[')) ?
36.546 + in.readTypeString() : new String(new char[] { tcode });
36.547 + try {
36.548 + fields[i] = new ObjectStreamField(fname, signature, false);
36.549 + } catch (RuntimeException e) {
36.550 + throw (IOException) new InvalidClassException(name,
36.551 + "invalid descriptor for field " + fname).initCause(e);
36.552 + }
36.553 + }
36.554 + computeFieldOffsets();
36.555 + }
36.556 +
36.557 + /**
36.558 + * Writes non-proxy class descriptor information to given output stream.
36.559 + */
36.560 + void writeNonProxy(ObjectOutputStream out) throws IOException {
36.561 + out.writeUTF(name);
36.562 + out.writeLong(getSerialVersionUID());
36.563 +
36.564 + byte flags = 0;
36.565 + if (externalizable) {
36.566 + flags |= ObjectStreamConstants.SC_EXTERNALIZABLE;
36.567 + int protocol = out.getProtocolVersion();
36.568 + if (protocol != ObjectStreamConstants.PROTOCOL_VERSION_1) {
36.569 + flags |= ObjectStreamConstants.SC_BLOCK_DATA;
36.570 + }
36.571 + } else if (serializable) {
36.572 + flags |= ObjectStreamConstants.SC_SERIALIZABLE;
36.573 + }
36.574 + if (hasWriteObjectData) {
36.575 + flags |= ObjectStreamConstants.SC_WRITE_METHOD;
36.576 + }
36.577 + if (isEnum) {
36.578 + flags |= ObjectStreamConstants.SC_ENUM;
36.579 + }
36.580 + out.writeByte(flags);
36.581 +
36.582 + out.writeShort(fields.length);
36.583 + for (int i = 0; i < fields.length; i++) {
36.584 + ObjectStreamField f = fields[i];
36.585 + out.writeByte(f.getTypeCode());
36.586 + out.writeUTF(f.getName());
36.587 + if (!f.isPrimitive()) {
36.588 + out.writeTypeString(f.getTypeString());
36.589 + }
36.590 + }
36.591 + }
36.592 +
36.593 + /**
36.594 + * Returns ClassNotFoundException (if any) thrown while attempting to
36.595 + * resolve local class corresponding to this class descriptor.
36.596 + */
36.597 + ClassNotFoundException getResolveException() {
36.598 + return resolveEx;
36.599 + }
36.600 +
36.601 + /**
36.602 + * Throws an InvalidClassException if object instances referencing this
36.603 + * class descriptor should not be allowed to deserialize. This method does
36.604 + * not apply to deserialization of enum constants.
36.605 + */
36.606 + void checkDeserialize() throws InvalidClassException {
36.607 + if (deserializeEx != null) {
36.608 + InvalidClassException ice =
36.609 + new InvalidClassException(deserializeEx.classname,
36.610 + deserializeEx.getMessage());
36.611 + ice.initCause(deserializeEx);
36.612 + throw ice;
36.613 + }
36.614 + }
36.615 +
36.616 + /**
36.617 + * Throws an InvalidClassException if objects whose class is represented by
36.618 + * this descriptor should not be allowed to serialize. This method does
36.619 + * not apply to serialization of enum constants.
36.620 + */
36.621 + void checkSerialize() throws InvalidClassException {
36.622 + if (serializeEx != null) {
36.623 + InvalidClassException ice =
36.624 + new InvalidClassException(serializeEx.classname,
36.625 + serializeEx.getMessage());
36.626 + ice.initCause(serializeEx);
36.627 + throw ice;
36.628 + }
36.629 + }
36.630 +
36.631 + /**
36.632 + * Throws an InvalidClassException if objects whose class is represented by
36.633 + * this descriptor should not be permitted to use default serialization
36.634 + * (e.g., if the class declares serializable fields that do not correspond
36.635 + * to actual fields, and hence must use the GetField API). This method
36.636 + * does not apply to deserialization of enum constants.
36.637 + */
36.638 + void checkDefaultSerialize() throws InvalidClassException {
36.639 + if (defaultSerializeEx != null) {
36.640 + InvalidClassException ice =
36.641 + new InvalidClassException(defaultSerializeEx.classname,
36.642 + defaultSerializeEx.getMessage());
36.643 + ice.initCause(defaultSerializeEx);
36.644 + throw ice;
36.645 + }
36.646 + }
36.647 +
36.648 + /**
36.649 + * Returns superclass descriptor. Note that on the receiving side, the
36.650 + * superclass descriptor may be bound to a class that is not a superclass
36.651 + * of the subclass descriptor's bound class.
36.652 + */
36.653 + ObjectStreamClass getSuperDesc() {
36.654 + return superDesc;
36.655 + }
36.656 +
36.657 + /**
36.658 + * Returns the "local" class descriptor for the class associated with this
36.659 + * class descriptor (i.e., the result of
36.660 + * ObjectStreamClass.lookup(this.forClass())) or null if there is no class
36.661 + * associated with this descriptor.
36.662 + */
36.663 + ObjectStreamClass getLocalDesc() {
36.664 + return localDesc;
36.665 + }
36.666 +
36.667 + /**
36.668 + * Returns arrays of ObjectStreamFields representing the serializable
36.669 + * fields of the represented class. If copy is true, a clone of this class
36.670 + * descriptor's field array is returned, otherwise the array itself is
36.671 + * returned.
36.672 + */
36.673 + ObjectStreamField[] getFields(boolean copy) {
36.674 + return copy ? fields.clone() : fields;
36.675 + }
36.676 +
36.677 + /**
36.678 + * Looks up a serializable field of the represented class by name and type.
36.679 + * A specified type of null matches all types, Object.class matches all
36.680 + * non-primitive types, and any other non-null type matches assignable
36.681 + * types only. Returns matching field, or null if no match found.
36.682 + */
36.683 + ObjectStreamField getField(String name, Class<?> type) {
36.684 + for (int i = 0; i < fields.length; i++) {
36.685 + ObjectStreamField f = fields[i];
36.686 + if (f.getName().equals(name)) {
36.687 + if (type == null ||
36.688 + (type == Object.class && !f.isPrimitive()))
36.689 + {
36.690 + return f;
36.691 + }
36.692 + Class<?> ftype = f.getType();
36.693 + if (ftype != null && type.isAssignableFrom(ftype)) {
36.694 + return f;
36.695 + }
36.696 + }
36.697 + }
36.698 + return null;
36.699 + }
36.700 +
36.701 + /**
36.702 + * Returns true if class descriptor represents a dynamic proxy class, false
36.703 + * otherwise.
36.704 + */
36.705 + boolean isProxy() {
36.706 + return isProxy;
36.707 + }
36.708 +
36.709 + /**
36.710 + * Returns true if class descriptor represents an enum type, false
36.711 + * otherwise.
36.712 + */
36.713 + boolean isEnum() {
36.714 + return isEnum;
36.715 + }
36.716 +
36.717 + /**
36.718 + * Returns true if represented class implements Externalizable, false
36.719 + * otherwise.
36.720 + */
36.721 + boolean isExternalizable() {
36.722 + return externalizable;
36.723 + }
36.724 +
36.725 + /**
36.726 + * Returns true if represented class implements Serializable, false
36.727 + * otherwise.
36.728 + */
36.729 + boolean isSerializable() {
36.730 + return serializable;
36.731 + }
36.732 +
36.733 + /**
36.734 + * Returns true if class descriptor represents externalizable class that
36.735 + * has written its data in 1.2 (block data) format, false otherwise.
36.736 + */
36.737 + boolean hasBlockExternalData() {
36.738 + return hasBlockExternalData;
36.739 + }
36.740 +
36.741 + /**
36.742 + * Returns true if class descriptor represents serializable (but not
36.743 + * externalizable) class which has written its data via a custom
36.744 + * writeObject() method, false otherwise.
36.745 + */
36.746 + boolean hasWriteObjectData() {
36.747 + return hasWriteObjectData;
36.748 + }
36.749 +
36.750 + /**
36.751 + * Returns true if represented class is serializable/externalizable and can
36.752 + * be instantiated by the serialization runtime--i.e., if it is
36.753 + * externalizable and defines a public no-arg constructor, or if it is
36.754 + * non-externalizable and its first non-serializable superclass defines an
36.755 + * accessible no-arg constructor. Otherwise, returns false.
36.756 + */
36.757 + boolean isInstantiable() {
36.758 + return (cons != null);
36.759 + }
36.760 +
36.761 + /**
36.762 + * Returns true if represented class is serializable (but not
36.763 + * externalizable) and defines a conformant writeObject method. Otherwise,
36.764 + * returns false.
36.765 + */
36.766 + boolean hasWriteObjectMethod() {
36.767 + return (writeObjectMethod != null);
36.768 + }
36.769 +
36.770 + /**
36.771 + * Returns true if represented class is serializable (but not
36.772 + * externalizable) and defines a conformant readObject method. Otherwise,
36.773 + * returns false.
36.774 + */
36.775 + boolean hasReadObjectMethod() {
36.776 + return (readObjectMethod != null);
36.777 + }
36.778 +
36.779 + /**
36.780 + * Returns true if represented class is serializable (but not
36.781 + * externalizable) and defines a conformant readObjectNoData method.
36.782 + * Otherwise, returns false.
36.783 + */
36.784 + boolean hasReadObjectNoDataMethod() {
36.785 + return (readObjectNoDataMethod != null);
36.786 + }
36.787 +
36.788 + /**
36.789 + * Returns true if represented class is serializable or externalizable and
36.790 + * defines a conformant writeReplace method. Otherwise, returns false.
36.791 + */
36.792 + boolean hasWriteReplaceMethod() {
36.793 + return (writeReplaceMethod != null);
36.794 + }
36.795 +
36.796 + /**
36.797 + * Returns true if represented class is serializable or externalizable and
36.798 + * defines a conformant readResolve method. Otherwise, returns false.
36.799 + */
36.800 + boolean hasReadResolveMethod() {
36.801 + return (readResolveMethod != null);
36.802 + }
36.803 +
36.804 + /**
36.805 + * Creates a new instance of the represented class. If the class is
36.806 + * externalizable, invokes its public no-arg constructor; otherwise, if the
36.807 + * class is serializable, invokes the no-arg constructor of the first
36.808 + * non-serializable superclass. Throws UnsupportedOperationException if
36.809 + * this class descriptor is not associated with a class, if the associated
36.810 + * class is non-serializable or if the appropriate no-arg constructor is
36.811 + * inaccessible/unavailable.
36.812 + */
36.813 + Object newInstance()
36.814 + throws InstantiationException, InvocationTargetException,
36.815 + UnsupportedOperationException
36.816 + {
36.817 + if (cons != null) {
36.818 + try {
36.819 + return cons.newInstance();
36.820 + } catch (IllegalAccessException ex) {
36.821 + // should not occur, as access checks have been suppressed
36.822 + throw new InternalError();
36.823 + }
36.824 + } else {
36.825 + throw new UnsupportedOperationException();
36.826 + }
36.827 + }
36.828 +
36.829 + /**
36.830 + * Invokes the writeObject method of the represented serializable class.
36.831 + * Throws UnsupportedOperationException if this class descriptor is not
36.832 + * associated with a class, or if the class is externalizable,
36.833 + * non-serializable or does not define writeObject.
36.834 + */
36.835 + void invokeWriteObject(Object obj, ObjectOutputStream out)
36.836 + throws IOException, UnsupportedOperationException
36.837 + {
36.838 + if (writeObjectMethod != null) {
36.839 + try {
36.840 + writeObjectMethod.invoke(obj, new Object[]{ out });
36.841 + } catch (InvocationTargetException ex) {
36.842 + Throwable th = ex.getTargetException();
36.843 + if (th instanceof IOException) {
36.844 + throw (IOException) th;
36.845 + } else {
36.846 + throwMiscException(th);
36.847 + }
36.848 + } catch (IllegalAccessException ex) {
36.849 + // should not occur, as access checks have been suppressed
36.850 + throw new InternalError();
36.851 + }
36.852 + } else {
36.853 + throw new UnsupportedOperationException();
36.854 + }
36.855 + }
36.856 +
36.857 + /**
36.858 + * Invokes the readObject method of the represented serializable class.
36.859 + * Throws UnsupportedOperationException if this class descriptor is not
36.860 + * associated with a class, or if the class is externalizable,
36.861 + * non-serializable or does not define readObject.
36.862 + */
36.863 + void invokeReadObject(Object obj, ObjectInputStream in)
36.864 + throws ClassNotFoundException, IOException,
36.865 + UnsupportedOperationException
36.866 + {
36.867 + if (readObjectMethod != null) {
36.868 + try {
36.869 + readObjectMethod.invoke(obj, new Object[]{ in });
36.870 + } catch (InvocationTargetException ex) {
36.871 + Throwable th = ex.getTargetException();
36.872 + if (th instanceof ClassNotFoundException) {
36.873 + throw (ClassNotFoundException) th;
36.874 + } else if (th instanceof IOException) {
36.875 + throw (IOException) th;
36.876 + } else {
36.877 + throwMiscException(th);
36.878 + }
36.879 + } catch (IllegalAccessException ex) {
36.880 + // should not occur, as access checks have been suppressed
36.881 + throw new InternalError();
36.882 + }
36.883 + } else {
36.884 + throw new UnsupportedOperationException();
36.885 + }
36.886 + }
36.887 +
36.888 + /**
36.889 + * Invokes the readObjectNoData method of the represented serializable
36.890 + * class. Throws UnsupportedOperationException if this class descriptor is
36.891 + * not associated with a class, or if the class is externalizable,
36.892 + * non-serializable or does not define readObjectNoData.
36.893 + */
36.894 + void invokeReadObjectNoData(Object obj)
36.895 + throws IOException, UnsupportedOperationException
36.896 + {
36.897 + if (readObjectNoDataMethod != null) {
36.898 + try {
36.899 + readObjectNoDataMethod.invoke(obj, (Object[]) null);
36.900 + } catch (InvocationTargetException ex) {
36.901 + Throwable th = ex.getTargetException();
36.902 + if (th instanceof ObjectStreamException) {
36.903 + throw (ObjectStreamException) th;
36.904 + } else {
36.905 + throwMiscException(th);
36.906 + }
36.907 + } catch (IllegalAccessException ex) {
36.908 + // should not occur, as access checks have been suppressed
36.909 + throw new InternalError();
36.910 + }
36.911 + } else {
36.912 + throw new UnsupportedOperationException();
36.913 + }
36.914 + }
36.915 +
36.916 + /**
36.917 + * Invokes the writeReplace method of the represented serializable class and
36.918 + * returns the result. Throws UnsupportedOperationException if this class
36.919 + * descriptor is not associated with a class, or if the class is
36.920 + * non-serializable or does not define writeReplace.
36.921 + */
36.922 + Object invokeWriteReplace(Object obj)
36.923 + throws IOException, UnsupportedOperationException
36.924 + {
36.925 + if (writeReplaceMethod != null) {
36.926 + try {
36.927 + return writeReplaceMethod.invoke(obj, (Object[]) null);
36.928 + } catch (InvocationTargetException ex) {
36.929 + Throwable th = ex.getTargetException();
36.930 + if (th instanceof ObjectStreamException) {
36.931 + throw (ObjectStreamException) th;
36.932 + } else {
36.933 + throwMiscException(th);
36.934 + throw new InternalError(); // never reached
36.935 + }
36.936 + } catch (IllegalAccessException ex) {
36.937 + // should not occur, as access checks have been suppressed
36.938 + throw new InternalError();
36.939 + }
36.940 + } else {
36.941 + throw new UnsupportedOperationException();
36.942 + }
36.943 + }
36.944 +
36.945 + /**
36.946 + * Invokes the readResolve method of the represented serializable class and
36.947 + * returns the result. Throws UnsupportedOperationException if this class
36.948 + * descriptor is not associated with a class, or if the class is
36.949 + * non-serializable or does not define readResolve.
36.950 + */
36.951 + Object invokeReadResolve(Object obj)
36.952 + throws IOException, UnsupportedOperationException
36.953 + {
36.954 + if (readResolveMethod != null) {
36.955 + try {
36.956 + return readResolveMethod.invoke(obj, (Object[]) null);
36.957 + } catch (InvocationTargetException ex) {
36.958 + Throwable th = ex.getTargetException();
36.959 + if (th instanceof ObjectStreamException) {
36.960 + throw (ObjectStreamException) th;
36.961 + } else {
36.962 + throwMiscException(th);
36.963 + throw new InternalError(); // never reached
36.964 + }
36.965 + } catch (IllegalAccessException ex) {
36.966 + // should not occur, as access checks have been suppressed
36.967 + throw new InternalError();
36.968 + }
36.969 + } else {
36.970 + throw new UnsupportedOperationException();
36.971 + }
36.972 + }
36.973 +
36.974 + /**
36.975 + * Class representing the portion of an object's serialized form allotted
36.976 + * to data described by a given class descriptor. If "hasData" is false,
36.977 + * the object's serialized form does not contain data associated with the
36.978 + * class descriptor.
36.979 + */
36.980 + static class ClassDataSlot {
36.981 +
36.982 + /** class descriptor "occupying" this slot */
36.983 + final ObjectStreamClass desc;
36.984 + /** true if serialized form includes data for this slot's descriptor */
36.985 + final boolean hasData;
36.986 +
36.987 + ClassDataSlot(ObjectStreamClass desc, boolean hasData) {
36.988 + this.desc = desc;
36.989 + this.hasData = hasData;
36.990 + }
36.991 + }
36.992 +
36.993 + /**
36.994 + * Returns array of ClassDataSlot instances representing the data layout
36.995 + * (including superclass data) for serialized objects described by this
36.996 + * class descriptor. ClassDataSlots are ordered by inheritance with those
36.997 + * containing "higher" superclasses appearing first. The final
36.998 + * ClassDataSlot contains a reference to this descriptor.
36.999 + */
36.1000 + ClassDataSlot[] getClassDataLayout() throws InvalidClassException {
36.1001 + // REMIND: synchronize instead of relying on volatile?
36.1002 + if (dataLayout == null) {
36.1003 + dataLayout = getClassDataLayout0();
36.1004 + }
36.1005 + return dataLayout;
36.1006 + }
36.1007 +
36.1008 + private ClassDataSlot[] getClassDataLayout0()
36.1009 + throws InvalidClassException
36.1010 + {
36.1011 + ArrayList<ClassDataSlot> slots = new ArrayList<>();
36.1012 + Class<?> start = cl, end = cl;
36.1013 +
36.1014 + // locate closest non-serializable superclass
36.1015 + while (end != null && Serializable.class.isAssignableFrom(end)) {
36.1016 + end = end.getSuperclass();
36.1017 + }
36.1018 +
36.1019 + for (ObjectStreamClass d = this; d != null; d = d.superDesc) {
36.1020 +
36.1021 + // search up inheritance hierarchy for class with matching name
36.1022 + String searchName = (d.cl != null) ? d.cl.getName() : d.name;
36.1023 + Class<?> match = null;
36.1024 + for (Class<?> c = start; c != end; c = c.getSuperclass()) {
36.1025 + if (searchName.equals(c.getName())) {
36.1026 + match = c;
36.1027 + break;
36.1028 + }
36.1029 + }
36.1030 +
36.1031 + // add "no data" slot for each unmatched class below match
36.1032 + if (match != null) {
36.1033 + for (Class<?> c = start; c != match; c = c.getSuperclass()) {
36.1034 + slots.add(new ClassDataSlot(
36.1035 + ObjectStreamClass.lookup(c, true), false));
36.1036 + }
36.1037 + start = match.getSuperclass();
36.1038 + }
36.1039 +
36.1040 + // record descriptor/class pairing
36.1041 + slots.add(new ClassDataSlot(d.getVariantFor(match), true));
36.1042 + }
36.1043 +
36.1044 + // add "no data" slot for any leftover unmatched classes
36.1045 + for (Class<?> c = start; c != end; c = c.getSuperclass()) {
36.1046 + slots.add(new ClassDataSlot(
36.1047 + ObjectStreamClass.lookup(c, true), false));
36.1048 + }
36.1049 +
36.1050 + // order slots from superclass -> subclass
36.1051 + Collections.reverse(slots);
36.1052 + return slots.toArray(new ClassDataSlot[slots.size()]);
36.1053 + }
36.1054 +
36.1055 + /**
36.1056 + * Returns aggregate size (in bytes) of marshalled primitive field values
36.1057 + * for represented class.
36.1058 + */
36.1059 + int getPrimDataSize() {
36.1060 + return primDataSize;
36.1061 + }
36.1062 +
36.1063 + /**
36.1064 + * Returns number of non-primitive serializable fields of represented
36.1065 + * class.
36.1066 + */
36.1067 + int getNumObjFields() {
36.1068 + return numObjFields;
36.1069 + }
36.1070 +
36.1071 + /**
36.1072 + * Fetches the serializable primitive field values of object obj and
36.1073 + * marshals them into byte array buf starting at offset 0. It is the
36.1074 + * responsibility of the caller to ensure that obj is of the proper type if
36.1075 + * non-null.
36.1076 + */
36.1077 + void getPrimFieldValues(Object obj, byte[] buf) {
36.1078 + }
36.1079 +
36.1080 + /**
36.1081 + * Sets the serializable primitive fields of object obj using values
36.1082 + * unmarshalled from byte array buf starting at offset 0. It is the
36.1083 + * responsibility of the caller to ensure that obj is of the proper type if
36.1084 + * non-null.
36.1085 + */
36.1086 + void setPrimFieldValues(Object obj, byte[] buf) {
36.1087 + }
36.1088 +
36.1089 + /**
36.1090 + * Fetches the serializable object field values of object obj and stores
36.1091 + * them in array vals starting at offset 0. It is the responsibility of
36.1092 + * the caller to ensure that obj is of the proper type if non-null.
36.1093 + */
36.1094 + void getObjFieldValues(Object obj, Object[] vals) {
36.1095 + }
36.1096 +
36.1097 + /**
36.1098 + * Sets the serializable object fields of object obj using values from
36.1099 + * array vals starting at offset 0. It is the responsibility of the caller
36.1100 + * to ensure that obj is of the proper type if non-null.
36.1101 + */
36.1102 + void setObjFieldValues(Object obj, Object[] vals) {
36.1103 + }
36.1104 +
36.1105 + /**
36.1106 + * Calculates and sets serializable field offsets, as well as primitive
36.1107 + * data size and object field count totals. Throws InvalidClassException
36.1108 + * if fields are illegally ordered.
36.1109 + */
36.1110 + private void computeFieldOffsets() throws InvalidClassException {
36.1111 + primDataSize = 0;
36.1112 + numObjFields = 0;
36.1113 + int firstObjIndex = -1;
36.1114 +
36.1115 + for (int i = 0; i < fields.length; i++) {
36.1116 + ObjectStreamField f = fields[i];
36.1117 + switch (f.getTypeCode()) {
36.1118 + case 'Z':
36.1119 + case 'B':
36.1120 + f.setOffset(primDataSize++);
36.1121 + break;
36.1122 +
36.1123 + case 'C':
36.1124 + case 'S':
36.1125 + f.setOffset(primDataSize);
36.1126 + primDataSize += 2;
36.1127 + break;
36.1128 +
36.1129 + case 'I':
36.1130 + case 'F':
36.1131 + f.setOffset(primDataSize);
36.1132 + primDataSize += 4;
36.1133 + break;
36.1134 +
36.1135 + case 'J':
36.1136 + case 'D':
36.1137 + f.setOffset(primDataSize);
36.1138 + primDataSize += 8;
36.1139 + break;
36.1140 +
36.1141 + case '[':
36.1142 + case 'L':
36.1143 + f.setOffset(numObjFields++);
36.1144 + if (firstObjIndex == -1) {
36.1145 + firstObjIndex = i;
36.1146 + }
36.1147 + break;
36.1148 +
36.1149 + default:
36.1150 + throw new InternalError();
36.1151 + }
36.1152 + }
36.1153 + if (firstObjIndex != -1 &&
36.1154 + firstObjIndex + numObjFields != fields.length)
36.1155 + {
36.1156 + throw new InvalidClassException(name, "illegal field order");
36.1157 + }
36.1158 + }
36.1159 +
36.1160 + /**
36.1161 + * If given class is the same as the class associated with this class
36.1162 + * descriptor, returns reference to this class descriptor. Otherwise,
36.1163 + * returns variant of this class descriptor bound to given class.
36.1164 + */
36.1165 + private ObjectStreamClass getVariantFor(Class<?> cl)
36.1166 + throws InvalidClassException
36.1167 + {
36.1168 + if (this.cl == cl) {
36.1169 + return this;
36.1170 + }
36.1171 + ObjectStreamClass desc = new ObjectStreamClass();
36.1172 + if (isProxy) {
36.1173 + desc.initProxy(cl, null, superDesc);
36.1174 + } else {
36.1175 + desc.initNonProxy(this, cl, null, superDesc);
36.1176 + }
36.1177 + return desc;
36.1178 + }
36.1179 +
36.1180 + /**
36.1181 + * Returns public no-arg constructor of given class, or null if none found.
36.1182 + * Access checks are disabled on the returned constructor (if any), since
36.1183 + * the defining class may still be non-public.
36.1184 + */
36.1185 + private static Constructor getExternalizableConstructor(Class<?> cl) {
36.1186 + throw new SecurityException();
36.1187 + }
36.1188 +
36.1189 + /**
36.1190 + * Returns subclass-accessible no-arg constructor of first non-serializable
36.1191 + * superclass, or null if none found. Access checks are disabled on the
36.1192 + * returned constructor (if any).
36.1193 + */
36.1194 + private static Constructor getSerializableConstructor(Class<?> cl) {
36.1195 + Class<?> initCl = cl;
36.1196 + while (Serializable.class.isAssignableFrom(initCl)) {
36.1197 + if ((initCl = initCl.getSuperclass()) == null) {
36.1198 + return null;
36.1199 + }
36.1200 + }
36.1201 + throw new SecurityException();
36.1202 + }
36.1203 +
36.1204 + /**
36.1205 + * Returns non-static, non-abstract method with given signature provided it
36.1206 + * is defined by or accessible (via inheritance) by the given class, or
36.1207 + * null if no match found. Access checks are disabled on the returned
36.1208 + * method (if any).
36.1209 + */
36.1210 + private static Method getInheritableMethod(Class<?> cl, String name,
36.1211 + Class<?>[] argTypes,
36.1212 + Class<?> returnType)
36.1213 + {
36.1214 + throw new SecurityException();
36.1215 + }
36.1216 +
36.1217 + /**
36.1218 + * Returns non-static private method with given signature defined by given
36.1219 + * class, or null if none found. Access checks are disabled on the
36.1220 + * returned method (if any).
36.1221 + */
36.1222 + private static Method getPrivateMethod(Class<?> cl, String name,
36.1223 + Class<?>[] argTypes,
36.1224 + Class<?> returnType)
36.1225 + {
36.1226 + throw new SecurityException();
36.1227 + }
36.1228 +
36.1229 + /**
36.1230 + * Returns true if classes are defined in the same runtime package, false
36.1231 + * otherwise.
36.1232 + */
36.1233 + private static boolean packageEquals(Class<?> cl1, Class<?> cl2) {
36.1234 + return (cl1.getClassLoader() == cl2.getClassLoader() &&
36.1235 + getPackageName(cl1).equals(getPackageName(cl2)));
36.1236 + }
36.1237 +
36.1238 + /**
36.1239 + * Returns package name of given class.
36.1240 + */
36.1241 + private static String getPackageName(Class<?> cl) {
36.1242 + String s = cl.getName();
36.1243 + int i = s.lastIndexOf('[');
36.1244 + if (i >= 0) {
36.1245 + s = s.substring(i + 2);
36.1246 + }
36.1247 + i = s.lastIndexOf('.');
36.1248 + return (i >= 0) ? s.substring(0, i) : "";
36.1249 + }
36.1250 +
36.1251 + /**
36.1252 + * Compares class names for equality, ignoring package names. Returns true
36.1253 + * if class names equal, false otherwise.
36.1254 + */
36.1255 + private static boolean classNamesEqual(String name1, String name2) {
36.1256 + name1 = name1.substring(name1.lastIndexOf('.') + 1);
36.1257 + name2 = name2.substring(name2.lastIndexOf('.') + 1);
36.1258 + return name1.equals(name2);
36.1259 + }
36.1260 +
36.1261 + /**
36.1262 + * Returns JVM type signature for given class.
36.1263 + */
36.1264 + private static String getClassSignature(Class<?> cl) {
36.1265 + StringBuilder sbuf = new StringBuilder();
36.1266 + while (cl.isArray()) {
36.1267 + sbuf.append('[');
36.1268 + cl = cl.getComponentType();
36.1269 + }
36.1270 + if (cl.isPrimitive()) {
36.1271 + if (cl == Integer.TYPE) {
36.1272 + sbuf.append('I');
36.1273 + } else if (cl == Byte.TYPE) {
36.1274 + sbuf.append('B');
36.1275 + } else if (cl == Long.TYPE) {
36.1276 + sbuf.append('J');
36.1277 + } else if (cl == Float.TYPE) {
36.1278 + sbuf.append('F');
36.1279 + } else if (cl == Double.TYPE) {
36.1280 + sbuf.append('D');
36.1281 + } else if (cl == Short.TYPE) {
36.1282 + sbuf.append('S');
36.1283 + } else if (cl == Character.TYPE) {
36.1284 + sbuf.append('C');
36.1285 + } else if (cl == Boolean.TYPE) {
36.1286 + sbuf.append('Z');
36.1287 + } else if (cl == Void.TYPE) {
36.1288 + sbuf.append('V');
36.1289 + } else {
36.1290 + throw new InternalError();
36.1291 + }
36.1292 + } else {
36.1293 + sbuf.append('L' + cl.getName().replace('.', '/') + ';');
36.1294 + }
36.1295 + return sbuf.toString();
36.1296 + }
36.1297 +
36.1298 + /**
36.1299 + * Returns JVM type signature for given list of parameters and return type.
36.1300 + */
36.1301 + private static String getMethodSignature(Class<?>[] paramTypes,
36.1302 + Class<?> retType)
36.1303 + {
36.1304 + StringBuilder sbuf = new StringBuilder();
36.1305 + sbuf.append('(');
36.1306 + for (int i = 0; i < paramTypes.length; i++) {
36.1307 + sbuf.append(getClassSignature(paramTypes[i]));
36.1308 + }
36.1309 + sbuf.append(')');
36.1310 + sbuf.append(getClassSignature(retType));
36.1311 + return sbuf.toString();
36.1312 + }
36.1313 +
36.1314 + /**
36.1315 + * Convenience method for throwing an exception that is either a
36.1316 + * RuntimeException, Error, or of some unexpected type (in which case it is
36.1317 + * wrapped inside an IOException).
36.1318 + */
36.1319 + private static void throwMiscException(Throwable th) throws IOException {
36.1320 + if (th instanceof RuntimeException) {
36.1321 + throw (RuntimeException) th;
36.1322 + } else if (th instanceof Error) {
36.1323 + throw (Error) th;
36.1324 + } else {
36.1325 + IOException ex = new IOException("unexpected exception type");
36.1326 + ex.initCause(th);
36.1327 + throw ex;
36.1328 + }
36.1329 + }
36.1330 +
36.1331 + /**
36.1332 + * Returns ObjectStreamField array describing the serializable fields of
36.1333 + * the given class. Serializable fields backed by an actual field of the
36.1334 + * class are represented by ObjectStreamFields with corresponding non-null
36.1335 + * Field objects. Throws InvalidClassException if the (explicitly
36.1336 + * declared) serializable fields are invalid.
36.1337 + */
36.1338 + private static ObjectStreamField[] getSerialFields(Class<?> cl)
36.1339 + throws InvalidClassException
36.1340 + {
36.1341 + ObjectStreamField[] fields;
36.1342 + if (Serializable.class.isAssignableFrom(cl) &&
36.1343 + !Externalizable.class.isAssignableFrom(cl) &&
36.1344 + !Proxy.isProxyClass(cl) &&
36.1345 + !cl.isInterface())
36.1346 + {
36.1347 + if ((fields = getDeclaredSerialFields(cl)) == null) {
36.1348 + fields = getDefaultSerialFields(cl);
36.1349 + }
36.1350 + Arrays.sort(fields);
36.1351 + } else {
36.1352 + fields = NO_FIELDS;
36.1353 + }
36.1354 + return fields;
36.1355 + }
36.1356 +
36.1357 + /**
36.1358 + * Returns serializable fields of given class as defined explicitly by a
36.1359 + * "serialPersistentFields" field, or null if no appropriate
36.1360 + * "serialPersistentFields" field is defined. Serializable fields backed
36.1361 + * by an actual field of the class are represented by ObjectStreamFields
36.1362 + * with corresponding non-null Field objects. For compatibility with past
36.1363 + * releases, a "serialPersistentFields" field with a null value is
36.1364 + * considered equivalent to not declaring "serialPersistentFields". Throws
36.1365 + * InvalidClassException if the declared serializable fields are
36.1366 + * invalid--e.g., if multiple fields share the same name.
36.1367 + */
36.1368 + private static ObjectStreamField[] getDeclaredSerialFields(Class<?> cl)
36.1369 + throws InvalidClassException
36.1370 + {
36.1371 + throw new SecurityException();
36.1372 + }
36.1373 +
36.1374 + /**
36.1375 + * Returns array of ObjectStreamFields corresponding to all non-static
36.1376 + * non-transient fields declared by given class. Each ObjectStreamField
36.1377 + * contains a Field object for the field it represents. If no default
36.1378 + * serializable fields exist, NO_FIELDS is returned.
36.1379 + */
36.1380 + private static ObjectStreamField[] getDefaultSerialFields(Class<?> cl) {
36.1381 + throw new SecurityException();
36.1382 + }
36.1383 +
36.1384 + /**
36.1385 + * Returns explicit serial version UID value declared by given class, or
36.1386 + * null if none.
36.1387 + */
36.1388 + private static Long getDeclaredSUID(Class<?> cl) {
36.1389 + return null;
36.1390 + }
36.1391 +
36.1392 + /**
36.1393 + * Computes the default serial version UID value for the given class.
36.1394 + */
36.1395 + private static long computeDefaultSUID(Class<?> cl) {
36.1396 + throw new SecurityException();
36.1397 + }
36.1398 +
36.1399 +}
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
37.2 +++ b/emul/compact/src/main/java/java/io/ObjectStreamConstants.java Sun Feb 17 17:58:34 2013 +0100
37.3 @@ -0,0 +1,215 @@
37.4 +/*
37.5 + * Copyright (c) 1996, 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.io;
37.30 +
37.31 +/**
37.32 + * Constants written into the Object Serialization Stream.
37.33 + *
37.34 + * @author unascribed
37.35 + * @since JDK 1.1
37.36 + */
37.37 +public interface ObjectStreamConstants {
37.38 +
37.39 + /**
37.40 + * Magic number that is written to the stream header.
37.41 + */
37.42 + final static short STREAM_MAGIC = (short)0xaced;
37.43 +
37.44 + /**
37.45 + * Version number that is written to the stream header.
37.46 + */
37.47 + final static short STREAM_VERSION = 5;
37.48 +
37.49 + /* Each item in the stream is preceded by a tag
37.50 + */
37.51 +
37.52 + /**
37.53 + * First tag value.
37.54 + */
37.55 + final static byte TC_BASE = 0x70;
37.56 +
37.57 + /**
37.58 + * Null object reference.
37.59 + */
37.60 + final static byte TC_NULL = (byte)0x70;
37.61 +
37.62 + /**
37.63 + * Reference to an object already written into the stream.
37.64 + */
37.65 + final static byte TC_REFERENCE = (byte)0x71;
37.66 +
37.67 + /**
37.68 + * new Class Descriptor.
37.69 + */
37.70 + final static byte TC_CLASSDESC = (byte)0x72;
37.71 +
37.72 + /**
37.73 + * new Object.
37.74 + */
37.75 + final static byte TC_OBJECT = (byte)0x73;
37.76 +
37.77 + /**
37.78 + * new String.
37.79 + */
37.80 + final static byte TC_STRING = (byte)0x74;
37.81 +
37.82 + /**
37.83 + * new Array.
37.84 + */
37.85 + final static byte TC_ARRAY = (byte)0x75;
37.86 +
37.87 + /**
37.88 + * Reference to Class.
37.89 + */
37.90 + final static byte TC_CLASS = (byte)0x76;
37.91 +
37.92 + /**
37.93 + * Block of optional data. Byte following tag indicates number
37.94 + * of bytes in this block data.
37.95 + */
37.96 + final static byte TC_BLOCKDATA = (byte)0x77;
37.97 +
37.98 + /**
37.99 + * End of optional block data blocks for an object.
37.100 + */
37.101 + final static byte TC_ENDBLOCKDATA = (byte)0x78;
37.102 +
37.103 + /**
37.104 + * Reset stream context. All handles written into stream are reset.
37.105 + */
37.106 + final static byte TC_RESET = (byte)0x79;
37.107 +
37.108 + /**
37.109 + * long Block data. The long following the tag indicates the
37.110 + * number of bytes in this block data.
37.111 + */
37.112 + final static byte TC_BLOCKDATALONG= (byte)0x7A;
37.113 +
37.114 + /**
37.115 + * Exception during write.
37.116 + */
37.117 + final static byte TC_EXCEPTION = (byte)0x7B;
37.118 +
37.119 + /**
37.120 + * Long string.
37.121 + */
37.122 + final static byte TC_LONGSTRING = (byte)0x7C;
37.123 +
37.124 + /**
37.125 + * new Proxy Class Descriptor.
37.126 + */
37.127 + final static byte TC_PROXYCLASSDESC = (byte)0x7D;
37.128 +
37.129 + /**
37.130 + * new Enum constant.
37.131 + * @since 1.5
37.132 + */
37.133 + final static byte TC_ENUM = (byte)0x7E;
37.134 +
37.135 + /**
37.136 + * Last tag value.
37.137 + */
37.138 + final static byte TC_MAX = (byte)0x7E;
37.139 +
37.140 + /**
37.141 + * First wire handle to be assigned.
37.142 + */
37.143 + final static int baseWireHandle = 0x7e0000;
37.144 +
37.145 +
37.146 + /******************************************************/
37.147 + /* Bit masks for ObjectStreamClass flag.*/
37.148 +
37.149 + /**
37.150 + * Bit mask for ObjectStreamClass flag. Indicates a Serializable class
37.151 + * defines its own writeObject method.
37.152 + */
37.153 + final static byte SC_WRITE_METHOD = 0x01;
37.154 +
37.155 + /**
37.156 + * Bit mask for ObjectStreamClass flag. Indicates Externalizable data
37.157 + * written in Block Data mode.
37.158 + * Added for PROTOCOL_VERSION_2.
37.159 + *
37.160 + * @see #PROTOCOL_VERSION_2
37.161 + * @since 1.2
37.162 + */
37.163 + final static byte SC_BLOCK_DATA = 0x08;
37.164 +
37.165 + /**
37.166 + * Bit mask for ObjectStreamClass flag. Indicates class is Serializable.
37.167 + */
37.168 + final static byte SC_SERIALIZABLE = 0x02;
37.169 +
37.170 + /**
37.171 + * Bit mask for ObjectStreamClass flag. Indicates class is Externalizable.
37.172 + */
37.173 + final static byte SC_EXTERNALIZABLE = 0x04;
37.174 +
37.175 + /**
37.176 + * Bit mask for ObjectStreamClass flag. Indicates class is an enum type.
37.177 + * @since 1.5
37.178 + */
37.179 + final static byte SC_ENUM = 0x10;
37.180 +
37.181 +
37.182 + /* *******************************************************************/
37.183 + /* Security permissions */
37.184 +
37.185 + /**
37.186 + * A Stream Protocol Version. <p>
37.187 + *
37.188 + * All externalizable data is written in JDK 1.1 external data
37.189 + * format after calling this method. This version is needed to write
37.190 + * streams containing Externalizable data that can be read by
37.191 + * pre-JDK 1.1.6 JVMs.
37.192 + *
37.193 + * @see java.io.ObjectOutputStream#useProtocolVersion(int)
37.194 + * @since 1.2
37.195 + */
37.196 + public final static int PROTOCOL_VERSION_1 = 1;
37.197 +
37.198 +
37.199 + /**
37.200 + * A Stream Protocol Version. <p>
37.201 + *
37.202 + * This protocol is written by JVM 1.2.
37.203 + *
37.204 + * Externalizable data is written in block data mode and is
37.205 + * terminated with TC_ENDBLOCKDATA. Externalizable classdescriptor
37.206 + * flags has SC_BLOCK_DATA enabled. JVM 1.1.6 and greater can
37.207 + * read this format change.
37.208 + *
37.209 + * Enables writing a nonSerializable class descriptor into the
37.210 + * stream. The serialVersionUID of a nonSerializable class is
37.211 + * set to 0L.
37.212 + *
37.213 + * @see java.io.ObjectOutputStream#useProtocolVersion(int)
37.214 + * @see #SC_BLOCK_DATA
37.215 + * @since 1.2
37.216 + */
37.217 + public final static int PROTOCOL_VERSION_2 = 2;
37.218 +}
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
38.2 +++ b/emul/compact/src/main/java/java/io/ObjectStreamException.java Sun Feb 17 17:58:34 2013 +0100
38.3 @@ -0,0 +1,53 @@
38.4 +/*
38.5 + * Copyright (c) 1996, 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.io;
38.30 +
38.31 +/**
38.32 + * Superclass of all exceptions specific to Object Stream classes.
38.33 + *
38.34 + * @author unascribed
38.35 + * @since JDK1.1
38.36 + */
38.37 +public abstract class ObjectStreamException extends IOException {
38.38 +
38.39 + private static final long serialVersionUID = 7260898174833392607L;
38.40 +
38.41 + /**
38.42 + * Create an ObjectStreamException with the specified argument.
38.43 + *
38.44 + * @param classname the detailed message for the exception
38.45 + */
38.46 + protected ObjectStreamException(String classname) {
38.47 + super(classname);
38.48 + }
38.49 +
38.50 + /**
38.51 + * Create an ObjectStreamException.
38.52 + */
38.53 + protected ObjectStreamException() {
38.54 + super();
38.55 + }
38.56 +}
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
39.2 +++ b/emul/compact/src/main/java/java/io/ObjectStreamField.java Sun Feb 17 17:58:34 2013 +0100
39.3 @@ -0,0 +1,314 @@
39.4 +/*
39.5 + * Copyright (c) 1996, 2006, 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.io;
39.30 +
39.31 +import java.lang.reflect.Field;
39.32 +
39.33 +/**
39.34 + * A description of a Serializable field from a Serializable class. An array
39.35 + * of ObjectStreamFields is used to declare the Serializable fields of a class.
39.36 + *
39.37 + * @author Mike Warres
39.38 + * @author Roger Riggs
39.39 + * @see ObjectStreamClass
39.40 + * @since 1.2
39.41 + */
39.42 +public class ObjectStreamField
39.43 + implements Comparable<Object>
39.44 +{
39.45 +
39.46 + /** field name */
39.47 + private final String name;
39.48 + /** canonical JVM signature of field type */
39.49 + private final String signature;
39.50 + /** field type (Object.class if unknown non-primitive type) */
39.51 + private final Class<?> type;
39.52 + /** whether or not to (de)serialize field values as unshared */
39.53 + private final boolean unshared;
39.54 + /** corresponding reflective field object, if any */
39.55 + private final Field field;
39.56 + /** offset of field value in enclosing field group */
39.57 + private int offset = 0;
39.58 +
39.59 + /**
39.60 + * Create a Serializable field with the specified type. This field should
39.61 + * be documented with a <code>serialField</code> tag.
39.62 + *
39.63 + * @param name the name of the serializable field
39.64 + * @param type the <code>Class</code> object of the serializable field
39.65 + */
39.66 + public ObjectStreamField(String name, Class<?> type) {
39.67 + this(name, type, false);
39.68 + }
39.69 +
39.70 + /**
39.71 + * Creates an ObjectStreamField representing a serializable field with the
39.72 + * given name and type. If unshared is false, values of the represented
39.73 + * field are serialized and deserialized in the default manner--if the
39.74 + * field is non-primitive, object values are serialized and deserialized as
39.75 + * if they had been written and read by calls to writeObject and
39.76 + * readObject. If unshared is true, values of the represented field are
39.77 + * serialized and deserialized as if they had been written and read by
39.78 + * calls to writeUnshared and readUnshared.
39.79 + *
39.80 + * @param name field name
39.81 + * @param type field type
39.82 + * @param unshared if false, write/read field values in the same manner
39.83 + * as writeObject/readObject; if true, write/read in the same
39.84 + * manner as writeUnshared/readUnshared
39.85 + * @since 1.4
39.86 + */
39.87 + public ObjectStreamField(String name, Class<?> type, boolean unshared) {
39.88 + if (name == null) {
39.89 + throw new NullPointerException();
39.90 + }
39.91 + this.name = name;
39.92 + this.type = type;
39.93 + this.unshared = unshared;
39.94 + signature = getClassSignature(type).intern();
39.95 + field = null;
39.96 + }
39.97 +
39.98 + /**
39.99 + * Creates an ObjectStreamField representing a field with the given name,
39.100 + * signature and unshared setting.
39.101 + */
39.102 + ObjectStreamField(String name, String signature, boolean unshared) {
39.103 + if (name == null) {
39.104 + throw new NullPointerException();
39.105 + }
39.106 + this.name = name;
39.107 + this.signature = signature.intern();
39.108 + this.unshared = unshared;
39.109 + field = null;
39.110 +
39.111 + switch (signature.charAt(0)) {
39.112 + case 'Z': type = Boolean.TYPE; break;
39.113 + case 'B': type = Byte.TYPE; break;
39.114 + case 'C': type = Character.TYPE; break;
39.115 + case 'S': type = Short.TYPE; break;
39.116 + case 'I': type = Integer.TYPE; break;
39.117 + case 'J': type = Long.TYPE; break;
39.118 + case 'F': type = Float.TYPE; break;
39.119 + case 'D': type = Double.TYPE; break;
39.120 + case 'L':
39.121 + case '[': type = Object.class; break;
39.122 + default: throw new IllegalArgumentException("illegal signature");
39.123 + }
39.124 + }
39.125 +
39.126 + /**
39.127 + * Creates an ObjectStreamField representing the given field with the
39.128 + * specified unshared setting. For compatibility with the behavior of
39.129 + * earlier serialization implementations, a "showType" parameter is
39.130 + * necessary to govern whether or not a getType() call on this
39.131 + * ObjectStreamField (if non-primitive) will return Object.class (as
39.132 + * opposed to a more specific reference type).
39.133 + */
39.134 + ObjectStreamField(Field field, boolean unshared, boolean showType) {
39.135 + this.field = field;
39.136 + this.unshared = unshared;
39.137 + name = field.getName();
39.138 + Class<?> ftype = field.getType();
39.139 + type = (showType || ftype.isPrimitive()) ? ftype : Object.class;
39.140 + signature = getClassSignature(ftype).intern();
39.141 + }
39.142 +
39.143 + /**
39.144 + * Get the name of this field.
39.145 + *
39.146 + * @return a <code>String</code> representing the name of the serializable
39.147 + * field
39.148 + */
39.149 + public String getName() {
39.150 + return name;
39.151 + }
39.152 +
39.153 + /**
39.154 + * Get the type of the field. If the type is non-primitive and this
39.155 + * <code>ObjectStreamField</code> was obtained from a deserialized {@link
39.156 + * ObjectStreamClass} instance, then <code>Object.class</code> is returned.
39.157 + * Otherwise, the <code>Class</code> object for the type of the field is
39.158 + * returned.
39.159 + *
39.160 + * @return a <code>Class</code> object representing the type of the
39.161 + * serializable field
39.162 + */
39.163 + public Class<?> getType() {
39.164 + return type;
39.165 + }
39.166 +
39.167 + /**
39.168 + * Returns character encoding of field type. The encoding is as follows:
39.169 + * <blockquote><pre>
39.170 + * B byte
39.171 + * C char
39.172 + * D double
39.173 + * F float
39.174 + * I int
39.175 + * J long
39.176 + * L class or interface
39.177 + * S short
39.178 + * Z boolean
39.179 + * [ array
39.180 + * </pre></blockquote>
39.181 + *
39.182 + * @return the typecode of the serializable field
39.183 + */
39.184 + // REMIND: deprecate?
39.185 + public char getTypeCode() {
39.186 + return signature.charAt(0);
39.187 + }
39.188 +
39.189 + /**
39.190 + * Return the JVM type signature.
39.191 + *
39.192 + * @return null if this field has a primitive type.
39.193 + */
39.194 + // REMIND: deprecate?
39.195 + public String getTypeString() {
39.196 + return isPrimitive() ? null : signature;
39.197 + }
39.198 +
39.199 + /**
39.200 + * Offset of field within instance data.
39.201 + *
39.202 + * @return the offset of this field
39.203 + * @see #setOffset
39.204 + */
39.205 + // REMIND: deprecate?
39.206 + public int getOffset() {
39.207 + return offset;
39.208 + }
39.209 +
39.210 + /**
39.211 + * Offset within instance data.
39.212 + *
39.213 + * @param offset the offset of the field
39.214 + * @see #getOffset
39.215 + */
39.216 + // REMIND: deprecate?
39.217 + protected void setOffset(int offset) {
39.218 + this.offset = offset;
39.219 + }
39.220 +
39.221 + /**
39.222 + * Return true if this field has a primitive type.
39.223 + *
39.224 + * @return true if and only if this field corresponds to a primitive type
39.225 + */
39.226 + // REMIND: deprecate?
39.227 + public boolean isPrimitive() {
39.228 + char tcode = signature.charAt(0);
39.229 + return ((tcode != 'L') && (tcode != '['));
39.230 + }
39.231 +
39.232 + /**
39.233 + * Returns boolean value indicating whether or not the serializable field
39.234 + * represented by this ObjectStreamField instance is unshared.
39.235 + *
39.236 + * @since 1.4
39.237 + */
39.238 + public boolean isUnshared() {
39.239 + return unshared;
39.240 + }
39.241 +
39.242 + /**
39.243 + * Compare this field with another <code>ObjectStreamField</code>. Return
39.244 + * -1 if this is smaller, 0 if equal, 1 if greater. Types that are
39.245 + * primitives are "smaller" than object types. If equal, the field names
39.246 + * are compared.
39.247 + */
39.248 + // REMIND: deprecate?
39.249 + public int compareTo(Object obj) {
39.250 + ObjectStreamField other = (ObjectStreamField) obj;
39.251 + boolean isPrim = isPrimitive();
39.252 + if (isPrim != other.isPrimitive()) {
39.253 + return isPrim ? -1 : 1;
39.254 + }
39.255 + return name.compareTo(other.name);
39.256 + }
39.257 +
39.258 + /**
39.259 + * Return a string that describes this field.
39.260 + */
39.261 + public String toString() {
39.262 + return signature + ' ' + name;
39.263 + }
39.264 +
39.265 + /**
39.266 + * Returns field represented by this ObjectStreamField, or null if
39.267 + * ObjectStreamField is not associated with an actual field.
39.268 + */
39.269 + Field getField() {
39.270 + return field;
39.271 + }
39.272 +
39.273 + /**
39.274 + * Returns JVM type signature of field (similar to getTypeString, except
39.275 + * that signature strings are returned for primitive fields as well).
39.276 + */
39.277 + String getSignature() {
39.278 + return signature;
39.279 + }
39.280 +
39.281 + /**
39.282 + * Returns JVM type signature for given class.
39.283 + */
39.284 + private static String getClassSignature(Class<?> cl) {
39.285 + StringBuilder sbuf = new StringBuilder();
39.286 + while (cl.isArray()) {
39.287 + sbuf.append('[');
39.288 + cl = cl.getComponentType();
39.289 + }
39.290 + if (cl.isPrimitive()) {
39.291 + if (cl == Integer.TYPE) {
39.292 + sbuf.append('I');
39.293 + } else if (cl == Byte.TYPE) {
39.294 + sbuf.append('B');
39.295 + } else if (cl == Long.TYPE) {
39.296 + sbuf.append('J');
39.297 + } else if (cl == Float.TYPE) {
39.298 + sbuf.append('F');
39.299 + } else if (cl == Double.TYPE) {
39.300 + sbuf.append('D');
39.301 + } else if (cl == Short.TYPE) {
39.302 + sbuf.append('S');
39.303 + } else if (cl == Character.TYPE) {
39.304 + sbuf.append('C');
39.305 + } else if (cl == Boolean.TYPE) {
39.306 + sbuf.append('Z');
39.307 + } else if (cl == Void.TYPE) {
39.308 + sbuf.append('V');
39.309 + } else {
39.310 + throw new InternalError();
39.311 + }
39.312 + } else {
39.313 + sbuf.append('L' + cl.getName().replace('.', '/') + ';');
39.314 + }
39.315 + return sbuf.toString();
39.316 + }
39.317 +}
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
40.2 +++ b/emul/compact/src/main/java/java/io/OptionalDataException.java Sun Feb 17 17:58:34 2013 +0100
40.3 @@ -0,0 +1,83 @@
40.4 +/*
40.5 + * Copyright (c) 1996, 2005, 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 +package java.io;
40.29 +
40.30 +/**
40.31 + * Exception indicating the failure of an object read operation due to
40.32 + * unread primitive data, or the end of data belonging to a serialized
40.33 + * object in the stream. This exception may be thrown in two cases:
40.34 + *
40.35 + * <ul>
40.36 + * <li>An attempt was made to read an object when the next element in the
40.37 + * stream is primitive data. In this case, the OptionalDataException's
40.38 + * length field is set to the number of bytes of primitive data
40.39 + * immediately readable from the stream, and the eof field is set to
40.40 + * false.
40.41 + *
40.42 + * <li>An attempt was made to read past the end of data consumable by a
40.43 + * class-defined readObject or readExternal method. In this case, the
40.44 + * OptionalDataException's eof field is set to true, and the length field
40.45 + * is set to 0.
40.46 + * </ul>
40.47 + *
40.48 + * @author unascribed
40.49 + * @since JDK1.1
40.50 + */
40.51 +public class OptionalDataException extends ObjectStreamException {
40.52 +
40.53 + private static final long serialVersionUID = -8011121865681257820L;
40.54 +
40.55 + /*
40.56 + * Create an <code>OptionalDataException</code> with a length.
40.57 + */
40.58 + OptionalDataException(int len) {
40.59 + eof = false;
40.60 + length = len;
40.61 + }
40.62 +
40.63 + /*
40.64 + * Create an <code>OptionalDataException</code> signifying no
40.65 + * more primitive data is available.
40.66 + */
40.67 + OptionalDataException(boolean end) {
40.68 + length = 0;
40.69 + eof = end;
40.70 + }
40.71 +
40.72 + /**
40.73 + * The number of bytes of primitive data available to be read
40.74 + * in the current buffer.
40.75 + *
40.76 + * @serial
40.77 + */
40.78 + public int length;
40.79 +
40.80 + /**
40.81 + * True if there is no more data in the buffered part of the stream.
40.82 + *
40.83 + * @serial
40.84 + */
40.85 + public boolean eof;
40.86 +}
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
41.2 +++ b/emul/compact/src/main/java/java/io/OutputStream.java Sun Feb 17 17:58:34 2013 +0100
41.3 @@ -0,0 +1,154 @@
41.4 +/*
41.5 + * Copyright (c) 1994, 2004, 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 +package java.io;
41.30 +
41.31 +/**
41.32 + * This abstract class is the superclass of all classes representing
41.33 + * an output stream of bytes. An output stream accepts output bytes
41.34 + * and sends them to some sink.
41.35 + * <p>
41.36 + * Applications that need to define a subclass of
41.37 + * <code>OutputStream</code> must always provide at least a method
41.38 + * that writes one byte of output.
41.39 + *
41.40 + * @author Arthur van Hoff
41.41 + * @see java.io.BufferedOutputStream
41.42 + * @see java.io.ByteArrayOutputStream
41.43 + * @see java.io.DataOutputStream
41.44 + * @see java.io.FilterOutputStream
41.45 + * @see java.io.InputStream
41.46 + * @see java.io.OutputStream#write(int)
41.47 + * @since JDK1.0
41.48 + */
41.49 +public abstract class OutputStream implements Closeable, Flushable {
41.50 + /**
41.51 + * Writes the specified byte to this output stream. The general
41.52 + * contract for <code>write</code> is that one byte is written
41.53 + * to the output stream. The byte to be written is the eight
41.54 + * low-order bits of the argument <code>b</code>. The 24
41.55 + * high-order bits of <code>b</code> are ignored.
41.56 + * <p>
41.57 + * Subclasses of <code>OutputStream</code> must provide an
41.58 + * implementation for this method.
41.59 + *
41.60 + * @param b the <code>byte</code>.
41.61 + * @exception IOException if an I/O error occurs. In particular,
41.62 + * an <code>IOException</code> may be thrown if the
41.63 + * output stream has been closed.
41.64 + */
41.65 + public abstract void write(int b) throws IOException;
41.66 +
41.67 + /**
41.68 + * Writes <code>b.length</code> bytes from the specified byte array
41.69 + * to this output stream. The general contract for <code>write(b)</code>
41.70 + * is that it should have exactly the same effect as the call
41.71 + * <code>write(b, 0, b.length)</code>.
41.72 + *
41.73 + * @param b the data.
41.74 + * @exception IOException if an I/O error occurs.
41.75 + * @see java.io.OutputStream#write(byte[], int, int)
41.76 + */
41.77 + public void write(byte b[]) throws IOException {
41.78 + write(b, 0, b.length);
41.79 + }
41.80 +
41.81 + /**
41.82 + * Writes <code>len</code> bytes from the specified byte array
41.83 + * starting at offset <code>off</code> to this output stream.
41.84 + * The general contract for <code>write(b, off, len)</code> is that
41.85 + * some of the bytes in the array <code>b</code> are written to the
41.86 + * output stream in order; element <code>b[off]</code> is the first
41.87 + * byte written and <code>b[off+len-1]</code> is the last byte written
41.88 + * by this operation.
41.89 + * <p>
41.90 + * The <code>write</code> method of <code>OutputStream</code> calls
41.91 + * the write method of one argument on each of the bytes to be
41.92 + * written out. Subclasses are encouraged to override this method and
41.93 + * provide a more efficient implementation.
41.94 + * <p>
41.95 + * If <code>b</code> is <code>null</code>, a
41.96 + * <code>NullPointerException</code> is thrown.
41.97 + * <p>
41.98 + * If <code>off</code> is negative, or <code>len</code> is negative, or
41.99 + * <code>off+len</code> is greater than the length of the array
41.100 + * <code>b</code>, then an <tt>IndexOutOfBoundsException</tt> is thrown.
41.101 + *
41.102 + * @param b the data.
41.103 + * @param off the start offset in the data.
41.104 + * @param len the number of bytes to write.
41.105 + * @exception IOException if an I/O error occurs. In particular,
41.106 + * an <code>IOException</code> is thrown if the output
41.107 + * stream is closed.
41.108 + */
41.109 + public void write(byte b[], int off, int len) throws IOException {
41.110 + if (b == null) {
41.111 + throw new NullPointerException();
41.112 + } else if ((off < 0) || (off > b.length) || (len < 0) ||
41.113 + ((off + len) > b.length) || ((off + len) < 0)) {
41.114 + throw new IndexOutOfBoundsException();
41.115 + } else if (len == 0) {
41.116 + return;
41.117 + }
41.118 + for (int i = 0 ; i < len ; i++) {
41.119 + write(b[off + i]);
41.120 + }
41.121 + }
41.122 +
41.123 + /**
41.124 + * Flushes this output stream and forces any buffered output bytes
41.125 + * to be written out. The general contract of <code>flush</code> is
41.126 + * that calling it is an indication that, if any bytes previously
41.127 + * written have been buffered by the implementation of the output
41.128 + * stream, such bytes should immediately be written to their
41.129 + * intended destination.
41.130 + * <p>
41.131 + * If the intended destination of this stream is an abstraction provided by
41.132 + * the underlying operating system, for example a file, then flushing the
41.133 + * stream guarantees only that bytes previously written to the stream are
41.134 + * passed to the operating system for writing; it does not guarantee that
41.135 + * they are actually written to a physical device such as a disk drive.
41.136 + * <p>
41.137 + * The <code>flush</code> method of <code>OutputStream</code> does nothing.
41.138 + *
41.139 + * @exception IOException if an I/O error occurs.
41.140 + */
41.141 + public void flush() throws IOException {
41.142 + }
41.143 +
41.144 + /**
41.145 + * Closes this output stream and releases any system resources
41.146 + * associated with this stream. The general contract of <code>close</code>
41.147 + * is that it closes the output stream. A closed stream cannot perform
41.148 + * output operations and cannot be reopened.
41.149 + * <p>
41.150 + * The <code>close</code> method of <code>OutputStream</code> does nothing.
41.151 + *
41.152 + * @exception IOException if an I/O error occurs.
41.153 + */
41.154 + public void close() throws IOException {
41.155 + }
41.156 +
41.157 +}
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
42.2 +++ b/emul/compact/src/main/java/java/io/StreamCorruptedException.java Sun Feb 17 17:58:34 2013 +0100
42.3 @@ -0,0 +1,54 @@
42.4 +/*
42.5 + * Copyright (c) 1996, 2005, 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.io;
42.30 +
42.31 +/**
42.32 + * Thrown when control information that was read from an object stream
42.33 + * violates internal consistency checks.
42.34 + *
42.35 + * @author unascribed
42.36 + * @since JDK1.1
42.37 + */
42.38 +public class StreamCorruptedException extends ObjectStreamException {
42.39 +
42.40 + private static final long serialVersionUID = 8983558202217591746L;
42.41 +
42.42 + /**
42.43 + * Create a StreamCorruptedException and list a reason why thrown.
42.44 + *
42.45 + * @param reason String describing the reason for the exception.
42.46 + */
42.47 + public StreamCorruptedException(String reason) {
42.48 + super(reason);
42.49 + }
42.50 +
42.51 + /**
42.52 + * Create a StreamCorruptedException and list no reason why thrown.
42.53 + */
42.54 + public StreamCorruptedException() {
42.55 + super();
42.56 + }
42.57 +}
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
43.2 +++ b/emul/compact/src/main/java/java/io/WriteAbortedException.java Sun Feb 17 17:58:34 2013 +0100
43.3 @@ -0,0 +1,93 @@
43.4 +/*
43.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
43.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
43.7 + *
43.8 + * This code is free software; you can redistribute it and/or modify it
43.9 + * under the terms of the GNU General Public License version 2 only, as
43.10 + * published by the Free Software Foundation. Oracle designates this
43.11 + * particular file as subject to the "Classpath" exception as provided
43.12 + * by Oracle in the LICENSE file that accompanied this code.
43.13 + *
43.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
43.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
43.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
43.17 + * version 2 for more details (a copy is included in the LICENSE file that
43.18 + * accompanied this code).
43.19 + *
43.20 + * You should have received a copy of the GNU General Public License version
43.21 + * 2 along with this work; if not, write to the Free Software Foundation,
43.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
43.23 + *
43.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
43.25 + * or visit www.oracle.com if you need additional information or have any
43.26 + * questions.
43.27 + */
43.28 +
43.29 +package java.io;
43.30 +
43.31 +/**
43.32 + * Signals that one of the ObjectStreamExceptions was thrown during a
43.33 + * write operation. Thrown during a read operation when one of the
43.34 + * ObjectStreamExceptions was thrown during a write operation. The
43.35 + * exception that terminated the write can be found in the detail
43.36 + * field. The stream is reset to it's initial state and all references
43.37 + * to objects already deserialized are discarded.
43.38 + *
43.39 + * <p>As of release 1.4, this exception has been retrofitted to conform to
43.40 + * the general purpose exception-chaining mechanism. The "exception causing
43.41 + * the abort" that is provided at construction time and
43.42 + * accessed via the public {@link #detail} field is now known as the
43.43 + * <i>cause</i>, and may be accessed via the {@link Throwable#getCause()}
43.44 + * method, as well as the aforementioned "legacy field."
43.45 + *
43.46 + * @author unascribed
43.47 + * @since JDK1.1
43.48 + */
43.49 +public class WriteAbortedException extends ObjectStreamException {
43.50 + private static final long serialVersionUID = -3326426625597282442L;
43.51 +
43.52 + /**
43.53 + * Exception that was caught while writing the ObjectStream.
43.54 + *
43.55 + * <p>This field predates the general-purpose exception chaining facility.
43.56 + * The {@link Throwable#getCause()} method is now the preferred means of
43.57 + * obtaining this information.
43.58 + *
43.59 + * @serial
43.60 + */
43.61 + public Exception detail;
43.62 +
43.63 + /**
43.64 + * Constructs a WriteAbortedException with a string describing
43.65 + * the exception and the exception causing the abort.
43.66 + * @param s String describing the exception.
43.67 + * @param ex Exception causing the abort.
43.68 + */
43.69 + public WriteAbortedException(String s, Exception ex) {
43.70 + super(s);
43.71 + initCause(null); // Disallow subsequent initCause
43.72 + detail = ex;
43.73 + }
43.74 +
43.75 + /**
43.76 + * Produce the message and include the message from the nested
43.77 + * exception, if there is one.
43.78 + */
43.79 + public String getMessage() {
43.80 + if (detail == null)
43.81 + return super.getMessage();
43.82 + else
43.83 + return super.getMessage() + "; " + detail.toString();
43.84 + }
43.85 +
43.86 + /**
43.87 + * Returns the exception that terminated the operation (the <i>cause</i>).
43.88 + *
43.89 + * @return the exception that terminated the operation (the <i>cause</i>),
43.90 + * which may be null.
43.91 + * @since 1.4
43.92 + */
43.93 + public Throwable getCause() {
43.94 + return detail;
43.95 + }
43.96 +}
44.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
44.2 +++ b/emul/compact/src/main/java/java/lang/AbstractMethodError.java Sun Feb 17 17:58:34 2013 +0100
44.3 @@ -0,0 +1,58 @@
44.4 +/*
44.5 + * Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved.
44.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44.7 + *
44.8 + * This code is free software; you can redistribute it and/or modify it
44.9 + * under the terms of the GNU General Public License version 2 only, as
44.10 + * published by the Free Software Foundation. Oracle designates this
44.11 + * particular file as subject to the "Classpath" exception as provided
44.12 + * by Oracle in the LICENSE file that accompanied this code.
44.13 + *
44.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
44.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
44.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
44.17 + * version 2 for more details (a copy is included in the LICENSE file that
44.18 + * accompanied this code).
44.19 + *
44.20 + * You should have received a copy of the GNU General Public License version
44.21 + * 2 along with this work; if not, write to the Free Software Foundation,
44.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
44.23 + *
44.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
44.25 + * or visit www.oracle.com if you need additional information or have any
44.26 + * questions.
44.27 + */
44.28 +
44.29 +package java.lang;
44.30 +
44.31 +/**
44.32 + * Thrown when an application tries to call an abstract method.
44.33 + * Normally, this error is caught by the compiler; this error can
44.34 + * only occur at run time if the definition of some class has
44.35 + * incompatibly changed since the currently executing method was last
44.36 + * compiled.
44.37 + *
44.38 + * @author unascribed
44.39 + * @since JDK1.0
44.40 + */
44.41 +public
44.42 +class AbstractMethodError extends IncompatibleClassChangeError {
44.43 + private static final long serialVersionUID = -1654391082989018462L;
44.44 +
44.45 + /**
44.46 + * Constructs an <code>AbstractMethodError</code> with no detail message.
44.47 + */
44.48 + public AbstractMethodError() {
44.49 + super();
44.50 + }
44.51 +
44.52 + /**
44.53 + * Constructs an <code>AbstractMethodError</code> with the specified
44.54 + * detail message.
44.55 + *
44.56 + * @param s the detail message.
44.57 + */
44.58 + public AbstractMethodError(String s) {
44.59 + super(s);
44.60 + }
44.61 +}
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
45.2 +++ b/emul/compact/src/main/java/java/lang/IncompatibleClassChangeError.java Sun Feb 17 17:58:34 2013 +0100
45.3 @@ -0,0 +1,57 @@
45.4 +/*
45.5 + * Copyright (c) 1994, 2008, 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 + * Thrown when an incompatible class change has occurred to some class
45.33 + * definition. The definition of some class, on which the currently
45.34 + * executing method depends, has since changed.
45.35 + *
45.36 + * @author unascribed
45.37 + * @since JDK1.0
45.38 + */
45.39 +public
45.40 +class IncompatibleClassChangeError extends LinkageError {
45.41 + private static final long serialVersionUID = -4914975503642802119L;
45.42 +
45.43 + /**
45.44 + * Constructs an <code>IncompatibleClassChangeError</code> with no
45.45 + * detail message.
45.46 + */
45.47 + public IncompatibleClassChangeError () {
45.48 + super();
45.49 + }
45.50 +
45.51 + /**
45.52 + * Constructs an <code>IncompatibleClassChangeError</code> with the
45.53 + * specified detail message.
45.54 + *
45.55 + * @param s the detail message.
45.56 + */
45.57 + public IncompatibleClassChangeError(String s) {
45.58 + super(s);
45.59 + }
45.60 +}
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
46.2 +++ b/emul/compact/src/main/java/java/lang/NoSuchFieldError.java Sun Feb 17 17:58:34 2013 +0100
46.3 @@ -0,0 +1,59 @@
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 tries to access or modify a specified
46.33 + * field of an object, and that object no longer has that field.
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
46.43 +class NoSuchFieldError extends IncompatibleClassChangeError {
46.44 + private static final long serialVersionUID = -3456430195886129035L;
46.45 +
46.46 + /**
46.47 + * Constructs a <code>NoSuchFieldError</code> with no detail message.
46.48 + */
46.49 + public NoSuchFieldError() {
46.50 + super();
46.51 + }
46.52 +
46.53 + /**
46.54 + * Constructs a <code>NoSuchFieldError</code> with the specified
46.55 + * detail message.
46.56 + *
46.57 + * @param s the detail message.
46.58 + */
46.59 + public NoSuchFieldError(String s) {
46.60 + super(s);
46.61 + }
46.62 +}
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
47.2 +++ b/emul/compact/src/main/java/java/lang/System.java Sun Feb 17 17:58:34 2013 +0100
47.3 @@ -0,0 +1,36 @@
47.4 +/**
47.5 + * Back 2 Browser Bytecode Translator
47.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
47.7 + *
47.8 + * This program is free software: you can redistribute it and/or modify
47.9 + * it under the terms of the GNU General Public License as published by
47.10 + * the Free Software Foundation, version 2 of the License.
47.11 + *
47.12 + * This program is distributed in the hope that it will be useful,
47.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
47.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47.15 + * GNU General Public License for more details.
47.16 + *
47.17 + * You should have received a copy of the GNU General Public License
47.18 + * along with this program. Look for COPYING file in the top folder.
47.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
47.20 + */
47.21 +package java.lang;
47.22 +
47.23 +/** Poor man's re-implementation of most important System methods.
47.24 + *
47.25 + * @author Jaroslav Tulach <jtulach@netbeans.org>
47.26 + */
47.27 +public class System {
47.28 + private System() {
47.29 + }
47.30 +
47.31 + public static void arraycopy(Object value, int srcBegin, Object dst, int dstBegin, int count) {
47.32 + org.apidesign.bck2brwsr.emul.lang.System.arraycopy(value, srcBegin, dst, dstBegin, count);
47.33 + }
47.34 +
47.35 + public static long currentTimeMillis() {
47.36 + return org.apidesign.bck2brwsr.emul.lang.System.currentTimeMillis();
47.37 + }
47.38 +
47.39 +}
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
48.2 +++ b/emul/compact/src/main/java/java/lang/ref/PhantomReference.java Sun Feb 17 17:58:34 2013 +0100
48.3 @@ -0,0 +1,83 @@
48.4 +/*
48.5 + * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
48.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
48.7 + *
48.8 + * This code is free software; you can redistribute it and/or modify it
48.9 + * under the terms of the GNU General Public License version 2 only, as
48.10 + * published by the Free Software Foundation. Oracle designates this
48.11 + * particular file as subject to the "Classpath" exception as provided
48.12 + * by Oracle in the LICENSE file that accompanied this code.
48.13 + *
48.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
48.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
48.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
48.17 + * version 2 for more details (a copy is included in the LICENSE file that
48.18 + * accompanied this code).
48.19 + *
48.20 + * You should have received a copy of the GNU General Public License version
48.21 + * 2 along with this work; if not, write to the Free Software Foundation,
48.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
48.23 + *
48.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
48.25 + * or visit www.oracle.com if you need additional information or have any
48.26 + * questions.
48.27 + */
48.28 +
48.29 +package java.lang.ref;
48.30 +
48.31 +
48.32 +/**
48.33 + * Phantom reference objects, which are enqueued after the collector
48.34 + * determines that their referents may otherwise be reclaimed. Phantom
48.35 + * references are most often used for scheduling pre-mortem cleanup actions in
48.36 + * a more flexible way than is possible with the Java finalization mechanism.
48.37 + *
48.38 + * <p> If the garbage collector determines at a certain point in time that the
48.39 + * referent of a phantom reference is <a
48.40 + * href="package-summary.html#reachability">phantom reachable</a>, then at that
48.41 + * time or at some later time it will enqueue the reference.
48.42 + *
48.43 + * <p> In order to ensure that a reclaimable object remains so, the referent of
48.44 + * a phantom reference may not be retrieved: The <code>get</code> method of a
48.45 + * phantom reference always returns <code>null</code>.
48.46 + *
48.47 + * <p> Unlike soft and weak references, phantom references are not
48.48 + * automatically cleared by the garbage collector as they are enqueued. An
48.49 + * object that is reachable via phantom references will remain so until all
48.50 + * such references are cleared or themselves become unreachable.
48.51 + *
48.52 + * @author Mark Reinhold
48.53 + * @since 1.2
48.54 + */
48.55 +
48.56 +public class PhantomReference<T> extends Reference<T> {
48.57 +
48.58 + /**
48.59 + * Returns this reference object's referent. Because the referent of a
48.60 + * phantom reference is always inaccessible, this method always returns
48.61 + * <code>null</code>.
48.62 + *
48.63 + * @return <code>null</code>
48.64 + */
48.65 + public T get() {
48.66 + return null;
48.67 + }
48.68 +
48.69 + /**
48.70 + * Creates a new phantom reference that refers to the given object and
48.71 + * is registered with the given queue.
48.72 + *
48.73 + * <p> It is possible to create a phantom reference with a <tt>null</tt>
48.74 + * queue, but such a reference is completely useless: Its <tt>get</tt>
48.75 + * method will always return null and, since it does not have a queue, it
48.76 + * will never be enqueued.
48.77 + *
48.78 + * @param referent the object the new phantom reference will refer to
48.79 + * @param q the queue with which the reference is to be registered,
48.80 + * or <tt>null</tt> if registration is not required
48.81 + */
48.82 + public PhantomReference(T referent, ReferenceQueue<? super T> q) {
48.83 + super(referent, q);
48.84 + }
48.85 +
48.86 +}
49.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
49.2 +++ b/emul/compact/src/main/java/java/lang/ref/Reference.java Sun Feb 17 17:58:34 2013 +0100
49.3 @@ -0,0 +1,185 @@
49.4 +/*
49.5 + * Copyright (c) 1997, 2006, 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.ref;
49.30 +
49.31 +
49.32 +/**
49.33 + * Abstract base class for reference objects. This class defines the
49.34 + * operations common to all reference objects. Because reference objects are
49.35 + * implemented in close cooperation with the garbage collector, this class may
49.36 + * not be subclassed directly.
49.37 + *
49.38 + * @author Mark Reinhold
49.39 + * @since 1.2
49.40 + */
49.41 +
49.42 +public abstract class Reference<T> {
49.43 +
49.44 + /* A Reference instance is in one of four possible internal states:
49.45 + *
49.46 + * Active: Subject to special treatment by the garbage collector. Some
49.47 + * time after the collector detects that the reachability of the
49.48 + * referent has changed to the appropriate state, it changes the
49.49 + * instance's state to either Pending or Inactive, depending upon
49.50 + * whether or not the instance was registered with a queue when it was
49.51 + * created. In the former case it also adds the instance to the
49.52 + * pending-Reference list. Newly-created instances are Active.
49.53 + *
49.54 + * Pending: An element of the pending-Reference list, waiting to be
49.55 + * enqueued by the Reference-handler thread. Unregistered instances
49.56 + * are never in this state.
49.57 + *
49.58 + * Enqueued: An element of the queue with which the instance was
49.59 + * registered when it was created. When an instance is removed from
49.60 + * its ReferenceQueue, it is made Inactive. Unregistered instances are
49.61 + * never in this state.
49.62 + *
49.63 + * Inactive: Nothing more to do. Once an instance becomes Inactive its
49.64 + * state will never change again.
49.65 + *
49.66 + * The state is encoded in the queue and next fields as follows:
49.67 + *
49.68 + * Active: queue = ReferenceQueue with which instance is registered, or
49.69 + * ReferenceQueue.NULL if it was not registered with a queue; next =
49.70 + * null.
49.71 + *
49.72 + * Pending: queue = ReferenceQueue with which instance is registered;
49.73 + * next = Following instance in queue, or this if at end of list.
49.74 + *
49.75 + * Enqueued: queue = ReferenceQueue.ENQUEUED; next = Following instance
49.76 + * in queue, or this if at end of list.
49.77 + *
49.78 + * Inactive: queue = ReferenceQueue.NULL; next = this.
49.79 + *
49.80 + * With this scheme the collector need only examine the next field in order
49.81 + * to determine whether a Reference instance requires special treatment: If
49.82 + * the next field is null then the instance is active; if it is non-null,
49.83 + * then the collector should treat the instance normally.
49.84 + *
49.85 + * To ensure that concurrent collector can discover active Reference
49.86 + * objects without interfering with application threads that may apply
49.87 + * the enqueue() method to those objects, collectors should link
49.88 + * discovered objects through the discovered field.
49.89 + */
49.90 +
49.91 + private T referent; /* Treated specially by GC */
49.92 +
49.93 + ReferenceQueue<? super T> queue;
49.94 +
49.95 + Reference next;
49.96 + transient private Reference<T> discovered; /* used by VM */
49.97 +
49.98 +
49.99 + /* Object used to synchronize with the garbage collector. The collector
49.100 + * must acquire this lock at the beginning of each collection cycle. It is
49.101 + * therefore critical that any code holding this lock complete as quickly
49.102 + * as possible, allocate no new objects, and avoid calling user code.
49.103 + */
49.104 + static private class Lock { };
49.105 + private static Lock lock = new Lock();
49.106 +
49.107 +
49.108 + /* List of References waiting to be enqueued. The collector adds
49.109 + * References to this list, while the Reference-handler thread removes
49.110 + * them. This list is protected by the above lock object.
49.111 + */
49.112 + private static Reference pending = null;
49.113 +
49.114 +
49.115 +
49.116 + /* -- Referent accessor and setters -- */
49.117 +
49.118 + /**
49.119 + * Returns this reference object's referent. If this reference object has
49.120 + * been cleared, either by the program or by the garbage collector, then
49.121 + * this method returns <code>null</code>.
49.122 + *
49.123 + * @return The object to which this reference refers, or
49.124 + * <code>null</code> if this reference object has been cleared
49.125 + */
49.126 + public T get() {
49.127 + return this.referent;
49.128 + }
49.129 +
49.130 + /**
49.131 + * Clears this reference object. Invoking this method will not cause this
49.132 + * object to be enqueued.
49.133 + *
49.134 + * <p> This method is invoked only by Java code; when the garbage collector
49.135 + * clears references it does so directly, without invoking this method.
49.136 + */
49.137 + public void clear() {
49.138 + this.referent = null;
49.139 + }
49.140 +
49.141 +
49.142 + /* -- Queue operations -- */
49.143 +
49.144 + /**
49.145 + * Tells whether or not this reference object has been enqueued, either by
49.146 + * the program or by the garbage collector. If this reference object was
49.147 + * not registered with a queue when it was created, then this method will
49.148 + * always return <code>false</code>.
49.149 + *
49.150 + * @return <code>true</code> if and only if this reference object has
49.151 + * been enqueued
49.152 + */
49.153 + public boolean isEnqueued() {
49.154 + /* In terms of the internal states, this predicate actually tests
49.155 + whether the instance is either Pending or Enqueued */
49.156 + synchronized (this) {
49.157 + return (this.queue != ReferenceQueue.NULL) && (this.next != null);
49.158 + }
49.159 + }
49.160 +
49.161 + /**
49.162 + * Adds this reference object to the queue with which it is registered,
49.163 + * if any.
49.164 + *
49.165 + * <p> This method is invoked only by Java code; when the garbage collector
49.166 + * enqueues references it does so directly, without invoking this method.
49.167 + *
49.168 + * @return <code>true</code> if this reference object was successfully
49.169 + * enqueued; <code>false</code> if it was already enqueued or if
49.170 + * it was not registered with a queue when it was created
49.171 + */
49.172 + public boolean enqueue() {
49.173 + return this.queue.enqueue(this);
49.174 + }
49.175 +
49.176 +
49.177 + /* -- Constructors -- */
49.178 +
49.179 + Reference(T referent) {
49.180 + this(referent, null);
49.181 + }
49.182 +
49.183 + Reference(T referent, ReferenceQueue<? super T> queue) {
49.184 + this.referent = referent;
49.185 + this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
49.186 + }
49.187 +
49.188 +}
50.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
50.2 +++ b/emul/compact/src/main/java/java/lang/ref/ReferenceQueue.java Sun Feb 17 17:58:34 2013 +0100
50.3 @@ -0,0 +1,148 @@
50.4 +/*
50.5 + * Copyright (c) 1997, 2005, 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.ref;
50.30 +
50.31 +/**
50.32 + * Reference queues, to which registered reference objects are appended by the
50.33 + * garbage collector after the appropriate reachability changes are detected.
50.34 + *
50.35 + * @author Mark Reinhold
50.36 + * @since 1.2
50.37 + */
50.38 +
50.39 +public class ReferenceQueue<T> {
50.40 +
50.41 + /**
50.42 + * Constructs a new reference-object queue.
50.43 + */
50.44 + public ReferenceQueue() { }
50.45 +
50.46 + private static class Null extends ReferenceQueue {
50.47 + boolean enqueue(Reference r) {
50.48 + return false;
50.49 + }
50.50 + }
50.51 +
50.52 + static ReferenceQueue NULL = new Null();
50.53 + static ReferenceQueue ENQUEUED = new Null();
50.54 +
50.55 + static private class Lock { };
50.56 + private Lock lock = new Lock();
50.57 + private volatile Reference<? extends T> head = null;
50.58 + private long queueLength = 0;
50.59 +
50.60 + boolean enqueue(Reference<? extends T> r) { /* Called only by Reference class */
50.61 + synchronized (r) {
50.62 + if (r.queue == ENQUEUED) return false;
50.63 + synchronized (lock) {
50.64 + r.queue = ENQUEUED;
50.65 + r.next = (head == null) ? r : head;
50.66 + head = r;
50.67 + queueLength++;
50.68 + lock.notifyAll();
50.69 + return true;
50.70 + }
50.71 + }
50.72 + }
50.73 +
50.74 + private Reference<? extends T> reallyPoll() { /* Must hold lock */
50.75 + if (head != null) {
50.76 + Reference<? extends T> r = head;
50.77 + head = (r.next == r) ? null : r.next;
50.78 + r.queue = NULL;
50.79 + r.next = r;
50.80 + queueLength--;
50.81 + return r;
50.82 + }
50.83 + return null;
50.84 + }
50.85 +
50.86 + /**
50.87 + * Polls this queue to see if a reference object is available. If one is
50.88 + * available without further delay then it is removed from the queue and
50.89 + * returned. Otherwise this method immediately returns <tt>null</tt>.
50.90 + *
50.91 + * @return A reference object, if one was immediately available,
50.92 + * otherwise <code>null</code>
50.93 + */
50.94 + public Reference<? extends T> poll() {
50.95 + if (head == null)
50.96 + return null;
50.97 + synchronized (lock) {
50.98 + return reallyPoll();
50.99 + }
50.100 + }
50.101 +
50.102 + /**
50.103 + * Removes the next reference object in this queue, blocking until either
50.104 + * one becomes available or the given timeout period expires.
50.105 + *
50.106 + * <p> This method does not offer real-time guarantees: It schedules the
50.107 + * timeout as if by invoking the {@link Object#wait(long)} method.
50.108 + *
50.109 + * @param timeout If positive, block for up to <code>timeout</code>
50.110 + * milliseconds while waiting for a reference to be
50.111 + * added to this queue. If zero, block indefinitely.
50.112 + *
50.113 + * @return A reference object, if one was available within the specified
50.114 + * timeout period, otherwise <code>null</code>
50.115 + *
50.116 + * @throws IllegalArgumentException
50.117 + * If the value of the timeout argument is negative
50.118 + *
50.119 + * @throws InterruptedException
50.120 + * If the timeout wait is interrupted
50.121 + */
50.122 + public Reference<? extends T> remove(long timeout)
50.123 + throws IllegalArgumentException, InterruptedException
50.124 + {
50.125 + if (timeout < 0) {
50.126 + throw new IllegalArgumentException("Negative timeout value");
50.127 + }
50.128 + synchronized (lock) {
50.129 + Reference<? extends T> r = reallyPoll();
50.130 + if (r != null) return r;
50.131 + for (;;) {
50.132 + lock.wait(timeout);
50.133 + r = reallyPoll();
50.134 + if (r != null) return r;
50.135 + if (timeout != 0) return null;
50.136 + }
50.137 + }
50.138 + }
50.139 +
50.140 + /**
50.141 + * Removes the next reference object in this queue, blocking until one
50.142 + * becomes available.
50.143 + *
50.144 + * @return A reference object, blocking until one becomes available
50.145 + * @throws InterruptedException If the wait is interrupted
50.146 + */
50.147 + public Reference<? extends T> remove() throws InterruptedException {
50.148 + return remove(0);
50.149 + }
50.150 +
50.151 +}
51.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
51.2 +++ b/emul/compact/src/main/java/java/lang/ref/SoftReference.java Sun Feb 17 17:58:34 2013 +0100
51.3 @@ -0,0 +1,118 @@
51.4 +/*
51.5 + * Copyright (c) 1997, 2003, 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.ref;
51.30 +
51.31 +
51.32 +/**
51.33 + * Soft reference objects, which are cleared at the discretion of the garbage
51.34 + * collector in response to memory demand. Soft references are most often used
51.35 + * to implement memory-sensitive caches.
51.36 + *
51.37 + * <p> Suppose that the garbage collector determines at a certain point in time
51.38 + * that an object is <a href="package-summary.html#reachability">softly
51.39 + * reachable</a>. At that time it may choose to clear atomically all soft
51.40 + * references to that object and all soft references to any other
51.41 + * softly-reachable objects from which that object is reachable through a chain
51.42 + * of strong references. At the same time or at some later time it will
51.43 + * enqueue those newly-cleared soft references that are registered with
51.44 + * reference queues.
51.45 + *
51.46 + * <p> All soft references to softly-reachable objects are guaranteed to have
51.47 + * been cleared before the virtual machine throws an
51.48 + * <code>OutOfMemoryError</code>. Otherwise no constraints are placed upon the
51.49 + * time at which a soft reference will be cleared or the order in which a set
51.50 + * of such references to different objects will be cleared. Virtual machine
51.51 + * implementations are, however, encouraged to bias against clearing
51.52 + * recently-created or recently-used soft references.
51.53 + *
51.54 + * <p> Direct instances of this class may be used to implement simple caches;
51.55 + * this class or derived subclasses may also be used in larger data structures
51.56 + * to implement more sophisticated caches. As long as the referent of a soft
51.57 + * reference is strongly reachable, that is, is actually in use, the soft
51.58 + * reference will not be cleared. Thus a sophisticated cache can, for example,
51.59 + * prevent its most recently used entries from being discarded by keeping
51.60 + * strong referents to those entries, leaving the remaining entries to be
51.61 + * discarded at the discretion of the garbage collector.
51.62 + *
51.63 + * @author Mark Reinhold
51.64 + * @since 1.2
51.65 + */
51.66 +
51.67 +public class SoftReference<T> extends Reference<T> {
51.68 +
51.69 + /**
51.70 + * Timestamp clock, updated by the garbage collector
51.71 + */
51.72 + static private long clock;
51.73 +
51.74 + /**
51.75 + * Timestamp updated by each invocation of the get method. The VM may use
51.76 + * this field when selecting soft references to be cleared, but it is not
51.77 + * required to do so.
51.78 + */
51.79 + private long timestamp;
51.80 +
51.81 + /**
51.82 + * Creates a new soft reference that refers to the given object. The new
51.83 + * reference is not registered with any queue.
51.84 + *
51.85 + * @param referent object the new soft reference will refer to
51.86 + */
51.87 + public SoftReference(T referent) {
51.88 + super(referent);
51.89 + this.timestamp = clock;
51.90 + }
51.91 +
51.92 + /**
51.93 + * Creates a new soft reference that refers to the given object and is
51.94 + * registered with the given queue.
51.95 + *
51.96 + * @param referent object the new soft reference will refer to
51.97 + * @param q the queue with which the reference is to be registered,
51.98 + * or <tt>null</tt> if registration is not required
51.99 + *
51.100 + */
51.101 + public SoftReference(T referent, ReferenceQueue<? super T> q) {
51.102 + super(referent, q);
51.103 + this.timestamp = clock;
51.104 + }
51.105 +
51.106 + /**
51.107 + * Returns this reference object's referent. If this reference object has
51.108 + * been cleared, either by the program or by the garbage collector, then
51.109 + * this method returns <code>null</code>.
51.110 + *
51.111 + * @return The object to which this reference refers, or
51.112 + * <code>null</code> if this reference object has been cleared
51.113 + */
51.114 + public T get() {
51.115 + T o = super.get();
51.116 + if (o != null && this.timestamp != clock)
51.117 + this.timestamp = clock;
51.118 + return o;
51.119 + }
51.120 +
51.121 +}
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
52.2 +++ b/emul/compact/src/main/java/java/lang/ref/WeakReference.java Sun Feb 17 17:58:34 2013 +0100
52.3 @@ -0,0 +1,72 @@
52.4 +/*
52.5 + * Copyright (c) 1997, 2003, 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.ref;
52.30 +
52.31 +
52.32 +/**
52.33 + * Weak reference objects, which do not prevent their referents from being
52.34 + * made finalizable, finalized, and then reclaimed. Weak references are most
52.35 + * often used to implement canonicalizing mappings.
52.36 + *
52.37 + * <p> Suppose that the garbage collector determines at a certain point in time
52.38 + * that an object is <a href="package-summary.html#reachability">weakly
52.39 + * reachable</a>. At that time it will atomically clear all weak references to
52.40 + * that object and all weak references to any other weakly-reachable objects
52.41 + * from which that object is reachable through a chain of strong and soft
52.42 + * references. At the same time it will declare all of the formerly
52.43 + * weakly-reachable objects to be finalizable. At the same time or at some
52.44 + * later time it will enqueue those newly-cleared weak references that are
52.45 + * registered with reference queues.
52.46 + *
52.47 + * @author Mark Reinhold
52.48 + * @since 1.2
52.49 + */
52.50 +
52.51 +public class WeakReference<T> extends Reference<T> {
52.52 +
52.53 + /**
52.54 + * Creates a new weak reference that refers to the given object. The new
52.55 + * reference is not registered with any queue.
52.56 + *
52.57 + * @param referent object the new weak reference will refer to
52.58 + */
52.59 + public WeakReference(T referent) {
52.60 + super(referent);
52.61 + }
52.62 +
52.63 + /**
52.64 + * Creates a new weak reference that refers to the given object and is
52.65 + * registered with the given queue.
52.66 + *
52.67 + * @param referent object the new weak reference will refer to
52.68 + * @param q the queue with which the reference is to be registered,
52.69 + * or <tt>null</tt> if registration is not required
52.70 + */
52.71 + public WeakReference(T referent, ReferenceQueue<? super T> q) {
52.72 + super(referent, q);
52.73 + }
52.74 +
52.75 +}
53.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
53.2 +++ b/emul/compact/src/main/java/java/lang/ref/package.html Sun Feb 17 17:58:34 2013 +0100
53.3 @@ -0,0 +1,147 @@
53.4 +<!--
53.5 + Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved.
53.6 + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
53.7 +
53.8 + This code is free software; you can redistribute it and/or modify it
53.9 + under the terms of the GNU General Public License version 2 only, as
53.10 + published by the Free Software Foundation. Oracle designates this
53.11 + particular file as subject to the "Classpath" exception as provided
53.12 + by Oracle in the LICENSE file that accompanied this code.
53.13 +
53.14 + This code is distributed in the hope that it will be useful, but WITHOUT
53.15 + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
53.16 + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
53.17 + version 2 for more details (a copy is included in the LICENSE file that
53.18 + accompanied this code).
53.19 +
53.20 + You should have received a copy of the GNU General Public License version
53.21 + 2 along with this work; if not, write to the Free Software Foundation,
53.22 + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
53.23 +
53.24 + Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
53.25 + or visit www.oracle.com if you need additional information or have any
53.26 + questions.
53.27 +-->
53.28 +
53.29 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
53.30 +<html>
53.31 +<body bgcolor="white">
53.32 +
53.33 +
53.34 +Provides reference-object classes, which support a limited degree of
53.35 +interaction with the garbage collector. A program may use a reference object
53.36 +to maintain a reference to some other object in such a way that the latter
53.37 +object may still be reclaimed by the collector. A program may also arrange to
53.38 +be notified some time after the collector has determined that the reachability
53.39 +of a given object has changed.
53.40 +
53.41 +
53.42 +<h2>Package Specification</h2>
53.43 +
53.44 +A <em>reference object</em> encapsulates a reference to some other object so
53.45 +that the reference itself may be examined and manipulated like any other
53.46 +object. Three types of reference objects are provided, each weaker than the
53.47 +last: <em>soft</em>, <em>weak</em>, and <em>phantom</em>. Each type
53.48 +corresponds to a different level of reachability, as defined below. Soft
53.49 +references are for implementing memory-sensitive caches, weak references are
53.50 +for implementing canonicalizing mappings that do not prevent their keys (or
53.51 +values) from being reclaimed, and phantom references are for scheduling
53.52 +pre-mortem cleanup actions in a more flexible way than is possible with the
53.53 +Java finalization mechanism.
53.54 +
53.55 +<p> Each reference-object type is implemented by a subclass of the abstract
53.56 +base <code>{@link java.lang.ref.Reference}</code> class. An instance of one of
53.57 +these subclasses encapsulates a single reference to a particular object, called
53.58 +the <em>referent</em>. Every reference object provides methods for getting and
53.59 +clearing the reference. Aside from the clearing operation reference objects
53.60 +are otherwise immutable, so no <code>set</code> operation is provided. A
53.61 +program may further subclass these subclasses, adding whatever fields and
53.62 +methods are required for its purposes, or it may use these subclasses without
53.63 +change.
53.64 +
53.65 +
53.66 +<h3>Notification</h3>
53.67 +
53.68 +A program may request to be notified of changes in an object's reachability by
53.69 +<em>registering</em> an appropriate reference object with a <em>reference
53.70 +queue</em> at the time the reference object is created. Some time after the
53.71 +garbage collector determines that the reachability of the referent has changed
53.72 +to the value corresponding to the type of the reference, it will add the
53.73 +reference to the associated queue. At this point, the reference is considered
53.74 +to be <em>enqueued</em>. The program may remove references from a queue either
53.75 +by polling or by blocking until a reference becomes available. Reference
53.76 +queues are implemented by the <code>{@link java.lang.ref.ReferenceQueue}</code>
53.77 +class.
53.78 +
53.79 +<p> The relationship between a registered reference object and its queue is
53.80 +one-sided. That is, a queue does not keep track of the references that are
53.81 +registered with it. If a registered reference becomes unreachable itself, then
53.82 +it will never be enqueued. It is the responsibility of the program using
53.83 +reference objects to ensure that the objects remain reachable for as long as
53.84 +the program is interested in their referents.
53.85 +
53.86 +<p> While some programs will choose to dedicate a thread to removing reference
53.87 +objects from one or more queues and processing them, this is by no means
53.88 +necessary. A tactic that often works well is to examine a reference queue in
53.89 +the course of performing some other fairly-frequent action. For example, a
53.90 +hashtable that uses weak references to implement weak keys could poll its
53.91 +reference queue each time the table is accessed. This is how the <code>{@link
53.92 +java.util.WeakHashMap}</code> class works. Because the <code>{@link
53.93 +java.lang.ref.ReferenceQueue#poll ReferenceQueue.poll}</code> method simply
53.94 +checks an internal data structure, this check will add little overhead to the
53.95 +hashtable access methods.
53.96 +
53.97 +
53.98 +<h3>Automatically-cleared references</h3>
53.99 +
53.100 +Soft and weak references are automatically cleared by the collector before
53.101 +being added to the queues with which they are registered, if any. Therefore
53.102 +soft and weak references need not be registered with a queue in order to be
53.103 +useful, while phantom references do. An object that is reachable via phantom
53.104 +references will remain so until all such references are cleared or themselves
53.105 +become unreachable.
53.106 +
53.107 +
53.108 +<a name="reachability"></a>
53.109 +<h3>Reachability</h3>
53.110 +
53.111 +Going from strongest to weakest, the different levels of reachability reflect
53.112 +the life cycle of an object. They are operationally defined as follows:
53.113 +
53.114 +<ul>
53.115 +
53.116 +<li> An object is <em>strongly reachable</em> if it can be reached by some
53.117 +thread without traversing any reference objects. A newly-created object is
53.118 +strongly reachable by the thread that created it.
53.119 +
53.120 +<li> An object is <em>softly reachable</em> if it is not strongly reachable but
53.121 +can be reached by traversing a soft reference.
53.122 +
53.123 +<li> An object is <em>weakly reachable</em> if it is neither strongly nor
53.124 +softly reachable but can be reached by traversing a weak reference. When the
53.125 +weak references to a weakly-reachable object are cleared, the object becomes
53.126 +eligible for finalization.
53.127 +
53.128 +<li> An object is <em>phantom reachable</em> if it is neither strongly, softly,
53.129 +nor weakly reachable, it has been finalized, and some phantom reference refers
53.130 +to it.
53.131 +
53.132 +<li> Finally, an object is <em>unreachable</em>, and therefore eligible for
53.133 +reclamation, when it is not reachable in any of the above ways.
53.134 +
53.135 +</ul>
53.136 +
53.137 +
53.138 +@author Mark Reinhold
53.139 +@since 1.2
53.140 +
53.141 +<!--
53.142 +<h2>Related Documentation</h2>
53.143 +
53.144 +For overviews, tutorials, examples, guides, and tool documentation, please see:
53.145 +<ul>
53.146 + <li><a href="">##### REFER TO NON-SPEC DOCUMENTATION HERE #####</a>
53.147 +</ul>
53.148 +-->
53.149 +</body>
53.150 +</html>
54.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
54.2 +++ b/emul/compact/src/main/java/java/util/AbstractQueue.java Sun Feb 17 17:58:34 2013 +0100
54.3 @@ -0,0 +1,192 @@
54.4 +/*
54.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
54.6 + *
54.7 + * This code is free software; you can redistribute it and/or modify it
54.8 + * under the terms of the GNU General Public License version 2 only, as
54.9 + * published by the Free Software Foundation. Oracle designates this
54.10 + * particular file as subject to the "Classpath" exception as provided
54.11 + * by Oracle in the LICENSE file that accompanied this code.
54.12 + *
54.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
54.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
54.15 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
54.16 + * version 2 for more details (a copy is included in the LICENSE file that
54.17 + * accompanied this code).
54.18 + *
54.19 + * You should have received a copy of the GNU General Public License version
54.20 + * 2 along with this work; if not, write to the Free Software Foundation,
54.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
54.22 + *
54.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
54.24 + * or visit www.oracle.com if you need additional information or have any
54.25 + * questions.
54.26 + */
54.27 +
54.28 +/*
54.29 + * This file is available under and governed by the GNU General Public
54.30 + * License version 2 only, as published by the Free Software Foundation.
54.31 + * However, the following notice accompanied the original version of this
54.32 + * file:
54.33 + *
54.34 + * Written by Doug Lea with assistance from members of JCP JSR-166
54.35 + * Expert Group and released to the public domain, as explained at
54.36 + * http://creativecommons.org/publicdomain/zero/1.0/
54.37 + */
54.38 +
54.39 +package java.util;
54.40 +
54.41 +/**
54.42 + * This class provides skeletal implementations of some {@link Queue}
54.43 + * operations. The implementations in this class are appropriate when
54.44 + * the base implementation does <em>not</em> allow <tt>null</tt>
54.45 + * elements. Methods {@link #add add}, {@link #remove remove}, and
54.46 + * {@link #element element} are based on {@link #offer offer}, {@link
54.47 + * #poll poll}, and {@link #peek peek}, respectively, but throw
54.48 + * exceptions instead of indicating failure via <tt>false</tt> or
54.49 + * <tt>null</tt> returns.
54.50 + *
54.51 + * <p>A <tt>Queue</tt> implementation that extends this class must
54.52 + * minimally define a method {@link Queue#offer} which does not permit
54.53 + * insertion of <tt>null</tt> elements, along with methods {@link
54.54 + * Queue#peek}, {@link Queue#poll}, {@link Collection#size}, and
54.55 + * {@link Collection#iterator}. Typically, additional methods will be
54.56 + * overridden as well. If these requirements cannot be met, consider
54.57 + * instead subclassing {@link AbstractCollection}.
54.58 + *
54.59 + * <p>This class is a member of the
54.60 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
54.61 + * Java Collections Framework</a>.
54.62 + *
54.63 + * @since 1.5
54.64 + * @author Doug Lea
54.65 + * @param <E> the type of elements held in this collection
54.66 + */
54.67 +public abstract class AbstractQueue<E>
54.68 + extends AbstractCollection<E>
54.69 + implements Queue<E> {
54.70 +
54.71 + /**
54.72 + * Constructor for use by subclasses.
54.73 + */
54.74 + protected AbstractQueue() {
54.75 + }
54.76 +
54.77 + /**
54.78 + * Inserts the specified element into this queue if it is possible to do so
54.79 + * immediately without violating capacity restrictions, returning
54.80 + * <tt>true</tt> upon success and throwing an <tt>IllegalStateException</tt>
54.81 + * if no space is currently available.
54.82 + *
54.83 + * <p>This implementation returns <tt>true</tt> if <tt>offer</tt> succeeds,
54.84 + * else throws an <tt>IllegalStateException</tt>.
54.85 + *
54.86 + * @param e the element to add
54.87 + * @return <tt>true</tt> (as specified by {@link Collection#add})
54.88 + * @throws IllegalStateException if the element cannot be added at this
54.89 + * time due to capacity restrictions
54.90 + * @throws ClassCastException if the class of the specified element
54.91 + * prevents it from being added to this queue
54.92 + * @throws NullPointerException if the specified element is null and
54.93 + * this queue does not permit null elements
54.94 + * @throws IllegalArgumentException if some property of this element
54.95 + * prevents it from being added to this queue
54.96 + */
54.97 + public boolean add(E e) {
54.98 + if (offer(e))
54.99 + return true;
54.100 + else
54.101 + throw new IllegalStateException("Queue full");
54.102 + }
54.103 +
54.104 + /**
54.105 + * Retrieves and removes the head of this queue. This method differs
54.106 + * from {@link #poll poll} only in that it throws an exception if this
54.107 + * queue is empty.
54.108 + *
54.109 + * <p>This implementation returns the result of <tt>poll</tt>
54.110 + * unless the queue is empty.
54.111 + *
54.112 + * @return the head of this queue
54.113 + * @throws NoSuchElementException if this queue is empty
54.114 + */
54.115 + public E remove() {
54.116 + E x = poll();
54.117 + if (x != null)
54.118 + return x;
54.119 + else
54.120 + throw new NoSuchElementException();
54.121 + }
54.122 +
54.123 + /**
54.124 + * Retrieves, but does not remove, the head of this queue. This method
54.125 + * differs from {@link #peek peek} only in that it throws an exception if
54.126 + * this queue is empty.
54.127 + *
54.128 + * <p>This implementation returns the result of <tt>peek</tt>
54.129 + * unless the queue is empty.
54.130 + *
54.131 + * @return the head of this queue
54.132 + * @throws NoSuchElementException if this queue is empty
54.133 + */
54.134 + public E element() {
54.135 + E x = peek();
54.136 + if (x != null)
54.137 + return x;
54.138 + else
54.139 + throw new NoSuchElementException();
54.140 + }
54.141 +
54.142 + /**
54.143 + * Removes all of the elements from this queue.
54.144 + * The queue will be empty after this call returns.
54.145 + *
54.146 + * <p>This implementation repeatedly invokes {@link #poll poll} until it
54.147 + * returns <tt>null</tt>.
54.148 + */
54.149 + public void clear() {
54.150 + while (poll() != null)
54.151 + ;
54.152 + }
54.153 +
54.154 + /**
54.155 + * Adds all of the elements in the specified collection to this
54.156 + * queue. Attempts to addAll of a queue to itself result in
54.157 + * <tt>IllegalArgumentException</tt>. Further, the behavior of
54.158 + * this operation is undefined if the specified collection is
54.159 + * modified while the operation is in progress.
54.160 + *
54.161 + * <p>This implementation iterates over the specified collection,
54.162 + * and adds each element returned by the iterator to this
54.163 + * queue, in turn. A runtime exception encountered while
54.164 + * trying to add an element (including, in particular, a
54.165 + * <tt>null</tt> element) may result in only some of the elements
54.166 + * having been successfully added when the associated exception is
54.167 + * thrown.
54.168 + *
54.169 + * @param c collection containing elements to be added to this queue
54.170 + * @return <tt>true</tt> if this queue changed as a result of the call
54.171 + * @throws ClassCastException if the class of an element of the specified
54.172 + * collection prevents it from being added to this queue
54.173 + * @throws NullPointerException if the specified collection contains a
54.174 + * null element and this queue does not permit null elements,
54.175 + * or if the specified collection is null
54.176 + * @throws IllegalArgumentException if some property of an element of the
54.177 + * specified collection prevents it from being added to this
54.178 + * queue, or if the specified collection is this queue
54.179 + * @throws IllegalStateException if not all the elements can be added at
54.180 + * this time due to insertion restrictions
54.181 + * @see #add(Object)
54.182 + */
54.183 + public boolean addAll(Collection<? extends E> c) {
54.184 + if (c == null)
54.185 + throw new NullPointerException();
54.186 + if (c == this)
54.187 + throw new IllegalArgumentException();
54.188 + boolean modified = false;
54.189 + for (E e : c)
54.190 + if (add(e))
54.191 + modified = true;
54.192 + return modified;
54.193 + }
54.194 +
54.195 +}
55.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
55.2 +++ b/emul/compact/src/main/java/java/util/AbstractSequentialList.java Sun Feb 17 17:58:34 2013 +0100
55.3 @@ -0,0 +1,253 @@
55.4 +/*
55.5 + * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
55.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55.7 + *
55.8 + * This code is free software; you can redistribute it and/or modify it
55.9 + * under the terms of the GNU General Public License version 2 only, as
55.10 + * published by the Free Software Foundation. Oracle designates this
55.11 + * particular file as subject to the "Classpath" exception as provided
55.12 + * by Oracle in the LICENSE file that accompanied this code.
55.13 + *
55.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
55.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
55.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
55.17 + * version 2 for more details (a copy is included in the LICENSE file that
55.18 + * accompanied this code).
55.19 + *
55.20 + * You should have received a copy of the GNU General Public License version
55.21 + * 2 along with this work; if not, write to the Free Software Foundation,
55.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
55.23 + *
55.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
55.25 + * or visit www.oracle.com if you need additional information or have any
55.26 + * questions.
55.27 + */
55.28 +
55.29 +package java.util;
55.30 +
55.31 +/**
55.32 + * This class provides a skeletal implementation of the <tt>List</tt>
55.33 + * interface to minimize the effort required to implement this interface
55.34 + * backed by a "sequential access" data store (such as a linked list). For
55.35 + * random access data (such as an array), <tt>AbstractList</tt> should be used
55.36 + * in preference to this class.<p>
55.37 + *
55.38 + * This class is the opposite of the <tt>AbstractList</tt> class in the sense
55.39 + * that it implements the "random access" methods (<tt>get(int index)</tt>,
55.40 + * <tt>set(int index, E element)</tt>, <tt>add(int index, E element)</tt> and
55.41 + * <tt>remove(int index)</tt>) on top of the list's list iterator, instead of
55.42 + * the other way around.<p>
55.43 + *
55.44 + * To implement a list the programmer needs only to extend this class and
55.45 + * provide implementations for the <tt>listIterator</tt> and <tt>size</tt>
55.46 + * methods. For an unmodifiable list, the programmer need only implement the
55.47 + * list iterator's <tt>hasNext</tt>, <tt>next</tt>, <tt>hasPrevious</tt>,
55.48 + * <tt>previous</tt> and <tt>index</tt> methods.<p>
55.49 + *
55.50 + * For a modifiable list the programmer should additionally implement the list
55.51 + * iterator's <tt>set</tt> method. For a variable-size list the programmer
55.52 + * should additionally implement the list iterator's <tt>remove</tt> and
55.53 + * <tt>add</tt> methods.<p>
55.54 + *
55.55 + * The programmer should generally provide a void (no argument) and collection
55.56 + * constructor, as per the recommendation in the <tt>Collection</tt> interface
55.57 + * specification.<p>
55.58 + *
55.59 + * This class is a member of the
55.60 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
55.61 + * Java Collections Framework</a>.
55.62 + *
55.63 + * @author Josh Bloch
55.64 + * @author Neal Gafter
55.65 + * @see Collection
55.66 + * @see List
55.67 + * @see AbstractList
55.68 + * @see AbstractCollection
55.69 + * @since 1.2
55.70 + */
55.71 +
55.72 +public abstract class AbstractSequentialList<E> extends AbstractList<E> {
55.73 + /**
55.74 + * Sole constructor. (For invocation by subclass constructors, typically
55.75 + * implicit.)
55.76 + */
55.77 + protected AbstractSequentialList() {
55.78 + }
55.79 +
55.80 + /**
55.81 + * Returns the element at the specified position in this list.
55.82 + *
55.83 + * <p>This implementation first gets a list iterator pointing to the
55.84 + * indexed element (with <tt>listIterator(index)</tt>). Then, it gets
55.85 + * the element using <tt>ListIterator.next</tt> and returns it.
55.86 + *
55.87 + * @throws IndexOutOfBoundsException {@inheritDoc}
55.88 + */
55.89 + public E get(int index) {
55.90 + try {
55.91 + return listIterator(index).next();
55.92 + } catch (NoSuchElementException exc) {
55.93 + throw new IndexOutOfBoundsException("Index: "+index);
55.94 + }
55.95 + }
55.96 +
55.97 + /**
55.98 + * Replaces the element at the specified position in this list with the
55.99 + * specified element (optional operation).
55.100 + *
55.101 + * <p>This implementation first gets a list iterator pointing to the
55.102 + * indexed element (with <tt>listIterator(index)</tt>). Then, it gets
55.103 + * the current element using <tt>ListIterator.next</tt> and replaces it
55.104 + * with <tt>ListIterator.set</tt>.
55.105 + *
55.106 + * <p>Note that this implementation will throw an
55.107 + * <tt>UnsupportedOperationException</tt> if the list iterator does not
55.108 + * implement the <tt>set</tt> operation.
55.109 + *
55.110 + * @throws UnsupportedOperationException {@inheritDoc}
55.111 + * @throws ClassCastException {@inheritDoc}
55.112 + * @throws NullPointerException {@inheritDoc}
55.113 + * @throws IllegalArgumentException {@inheritDoc}
55.114 + * @throws IndexOutOfBoundsException {@inheritDoc}
55.115 + */
55.116 + public E set(int index, E element) {
55.117 + try {
55.118 + ListIterator<E> e = listIterator(index);
55.119 + E oldVal = e.next();
55.120 + e.set(element);
55.121 + return oldVal;
55.122 + } catch (NoSuchElementException exc) {
55.123 + throw new IndexOutOfBoundsException("Index: "+index);
55.124 + }
55.125 + }
55.126 +
55.127 + /**
55.128 + * Inserts the specified element at the specified position in this list
55.129 + * (optional operation). Shifts the element currently at that position
55.130 + * (if any) and any subsequent elements to the right (adds one to their
55.131 + * indices).
55.132 + *
55.133 + * <p>This implementation first gets a list iterator pointing to the
55.134 + * indexed element (with <tt>listIterator(index)</tt>). Then, it
55.135 + * inserts the specified element with <tt>ListIterator.add</tt>.
55.136 + *
55.137 + * <p>Note that this implementation will throw an
55.138 + * <tt>UnsupportedOperationException</tt> if the list iterator does not
55.139 + * implement the <tt>add</tt> operation.
55.140 + *
55.141 + * @throws UnsupportedOperationException {@inheritDoc}
55.142 + * @throws ClassCastException {@inheritDoc}
55.143 + * @throws NullPointerException {@inheritDoc}
55.144 + * @throws IllegalArgumentException {@inheritDoc}
55.145 + * @throws IndexOutOfBoundsException {@inheritDoc}
55.146 + */
55.147 + public void add(int index, E element) {
55.148 + try {
55.149 + listIterator(index).add(element);
55.150 + } catch (NoSuchElementException exc) {
55.151 + throw new IndexOutOfBoundsException("Index: "+index);
55.152 + }
55.153 + }
55.154 +
55.155 + /**
55.156 + * Removes the element at the specified position in this list (optional
55.157 + * operation). Shifts any subsequent elements to the left (subtracts one
55.158 + * from their indices). Returns the element that was removed from the
55.159 + * list.
55.160 + *
55.161 + * <p>This implementation first gets a list iterator pointing to the
55.162 + * indexed element (with <tt>listIterator(index)</tt>). Then, it removes
55.163 + * the element with <tt>ListIterator.remove</tt>.
55.164 + *
55.165 + * <p>Note that this implementation will throw an
55.166 + * <tt>UnsupportedOperationException</tt> if the list iterator does not
55.167 + * implement the <tt>remove</tt> operation.
55.168 + *
55.169 + * @throws UnsupportedOperationException {@inheritDoc}
55.170 + * @throws IndexOutOfBoundsException {@inheritDoc}
55.171 + */
55.172 + public E remove(int index) {
55.173 + try {
55.174 + ListIterator<E> e = listIterator(index);
55.175 + E outCast = e.next();
55.176 + e.remove();
55.177 + return outCast;
55.178 + } catch (NoSuchElementException exc) {
55.179 + throw new IndexOutOfBoundsException("Index: "+index);
55.180 + }
55.181 + }
55.182 +
55.183 +
55.184 + // Bulk Operations
55.185 +
55.186 + /**
55.187 + * Inserts all of the elements in the specified collection into this
55.188 + * list at the specified position (optional operation). Shifts the
55.189 + * element currently at that position (if any) and any subsequent
55.190 + * elements to the right (increases their indices). The new elements
55.191 + * will appear in this list in the order that they are returned by the
55.192 + * specified collection's iterator. The behavior of this operation is
55.193 + * undefined if the specified collection is modified while the
55.194 + * operation is in progress. (Note that this will occur if the specified
55.195 + * collection is this list, and it's nonempty.)
55.196 + *
55.197 + * <p>This implementation gets an iterator over the specified collection and
55.198 + * a list iterator over this list pointing to the indexed element (with
55.199 + * <tt>listIterator(index)</tt>). Then, it iterates over the specified
55.200 + * collection, inserting the elements obtained from the iterator into this
55.201 + * list, one at a time, using <tt>ListIterator.add</tt> followed by
55.202 + * <tt>ListIterator.next</tt> (to skip over the added element).
55.203 + *
55.204 + * <p>Note that this implementation will throw an
55.205 + * <tt>UnsupportedOperationException</tt> if the list iterator returned by
55.206 + * the <tt>listIterator</tt> method does not implement the <tt>add</tt>
55.207 + * operation.
55.208 + *
55.209 + * @throws UnsupportedOperationException {@inheritDoc}
55.210 + * @throws ClassCastException {@inheritDoc}
55.211 + * @throws NullPointerException {@inheritDoc}
55.212 + * @throws IllegalArgumentException {@inheritDoc}
55.213 + * @throws IndexOutOfBoundsException {@inheritDoc}
55.214 + */
55.215 + public boolean addAll(int index, Collection<? extends E> c) {
55.216 + try {
55.217 + boolean modified = false;
55.218 + ListIterator<E> e1 = listIterator(index);
55.219 + Iterator<? extends E> e2 = c.iterator();
55.220 + while (e2.hasNext()) {
55.221 + e1.add(e2.next());
55.222 + modified = true;
55.223 + }
55.224 + return modified;
55.225 + } catch (NoSuchElementException exc) {
55.226 + throw new IndexOutOfBoundsException("Index: "+index);
55.227 + }
55.228 + }
55.229 +
55.230 +
55.231 + // Iterators
55.232 +
55.233 + /**
55.234 + * Returns an iterator over the elements in this list (in proper
55.235 + * sequence).<p>
55.236 + *
55.237 + * This implementation merely returns a list iterator over the list.
55.238 + *
55.239 + * @return an iterator over the elements in this list (in proper sequence)
55.240 + */
55.241 + public Iterator<E> iterator() {
55.242 + return listIterator();
55.243 + }
55.244 +
55.245 + /**
55.246 + * Returns a list iterator over the elements in this list (in proper
55.247 + * sequence).
55.248 + *
55.249 + * @param index index of first element to be returned from the list
55.250 + * iterator (by a call to the <code>next</code> method)
55.251 + * @return a list iterator over the elements in this list (in proper
55.252 + * sequence)
55.253 + * @throws IndexOutOfBoundsException {@inheritDoc}
55.254 + */
55.255 + public abstract ListIterator<E> listIterator(int index);
55.256 +}
56.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
56.2 +++ b/emul/compact/src/main/java/java/util/ArrayDeque.java Sun Feb 17 17:58:34 2013 +0100
56.3 @@ -0,0 +1,830 @@
56.4 +/*
56.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
56.6 + *
56.7 + * This code is free software; you can redistribute it and/or modify it
56.8 + * under the terms of the GNU General Public License version 2 only, as
56.9 + * published by the Free Software Foundation. Oracle designates this
56.10 + * particular file as subject to the "Classpath" exception as provided
56.11 + * by Oracle in the LICENSE file that accompanied this code.
56.12 + *
56.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
56.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
56.15 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
56.16 + * version 2 for more details (a copy is included in the LICENSE file that
56.17 + * accompanied this code).
56.18 + *
56.19 + * You should have received a copy of the GNU General Public License version
56.20 + * 2 along with this work; if not, write to the Free Software Foundation,
56.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
56.22 + *
56.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
56.24 + * or visit www.oracle.com if you need additional information or have any
56.25 + * questions.
56.26 + */
56.27 +
56.28 +/*
56.29 + * This file is available under and governed by the GNU General Public
56.30 + * License version 2 only, as published by the Free Software Foundation.
56.31 + * However, the following notice accompanied the original version of this
56.32 + * file:
56.33 + *
56.34 + * Written by Josh Bloch of Google Inc. and released to the public domain,
56.35 + * as explained at http://creativecommons.org/publicdomain/zero/1.0/.
56.36 + */
56.37 +
56.38 +package java.util;
56.39 +import java.io.*;
56.40 +
56.41 +/**
56.42 + * Resizable-array implementation of the {@link Deque} interface. Array
56.43 + * deques have no capacity restrictions; they grow as necessary to support
56.44 + * usage. They are not thread-safe; in the absence of external
56.45 + * synchronization, they do not support concurrent access by multiple threads.
56.46 + * Null elements are prohibited. This class is likely to be faster than
56.47 + * {@link Stack} when used as a stack, and faster than {@link LinkedList}
56.48 + * when used as a queue.
56.49 + *
56.50 + * <p>Most <tt>ArrayDeque</tt> operations run in amortized constant time.
56.51 + * Exceptions include {@link #remove(Object) remove}, {@link
56.52 + * #removeFirstOccurrence removeFirstOccurrence}, {@link #removeLastOccurrence
56.53 + * removeLastOccurrence}, {@link #contains contains}, {@link #iterator
56.54 + * iterator.remove()}, and the bulk operations, all of which run in linear
56.55 + * time.
56.56 + *
56.57 + * <p>The iterators returned by this class's <tt>iterator</tt> method are
56.58 + * <i>fail-fast</i>: If the deque is modified at any time after the iterator
56.59 + * is created, in any way except through the iterator's own <tt>remove</tt>
56.60 + * method, the iterator will generally throw a {@link
56.61 + * ConcurrentModificationException}. Thus, in the face of concurrent
56.62 + * modification, the iterator fails quickly and cleanly, rather than risking
56.63 + * arbitrary, non-deterministic behavior at an undetermined time in the
56.64 + * future.
56.65 + *
56.66 + * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
56.67 + * as it is, generally speaking, impossible to make any hard guarantees in the
56.68 + * presence of unsynchronized concurrent modification. Fail-fast iterators
56.69 + * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
56.70 + * Therefore, it would be wrong to write a program that depended on this
56.71 + * exception for its correctness: <i>the fail-fast behavior of iterators
56.72 + * should be used only to detect bugs.</i>
56.73 + *
56.74 + * <p>This class and its iterator implement all of the
56.75 + * <em>optional</em> methods of the {@link Collection} and {@link
56.76 + * Iterator} interfaces.
56.77 + *
56.78 + * <p>This class is a member of the
56.79 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
56.80 + * Java Collections Framework</a>.
56.81 + *
56.82 + * @author Josh Bloch and Doug Lea
56.83 + * @since 1.6
56.84 + * @param <E> the type of elements held in this collection
56.85 + */
56.86 +public class ArrayDeque<E> extends AbstractCollection<E>
56.87 + implements Deque<E>, Cloneable, Serializable
56.88 +{
56.89 + /**
56.90 + * The array in which the elements of the deque are stored.
56.91 + * The capacity of the deque is the length of this array, which is
56.92 + * always a power of two. The array is never allowed to become
56.93 + * full, except transiently within an addX method where it is
56.94 + * resized (see doubleCapacity) immediately upon becoming full,
56.95 + * thus avoiding head and tail wrapping around to equal each
56.96 + * other. We also guarantee that all array cells not holding
56.97 + * deque elements are always null.
56.98 + */
56.99 + private transient E[] elements;
56.100 +
56.101 + /**
56.102 + * The index of the element at the head of the deque (which is the
56.103 + * element that would be removed by remove() or pop()); or an
56.104 + * arbitrary number equal to tail if the deque is empty.
56.105 + */
56.106 + private transient int head;
56.107 +
56.108 + /**
56.109 + * The index at which the next element would be added to the tail
56.110 + * of the deque (via addLast(E), add(E), or push(E)).
56.111 + */
56.112 + private transient int tail;
56.113 +
56.114 + /**
56.115 + * The minimum capacity that we'll use for a newly created deque.
56.116 + * Must be a power of 2.
56.117 + */
56.118 + private static final int MIN_INITIAL_CAPACITY = 8;
56.119 +
56.120 + // ****** Array allocation and resizing utilities ******
56.121 +
56.122 + /**
56.123 + * Allocate empty array to hold the given number of elements.
56.124 + *
56.125 + * @param numElements the number of elements to hold
56.126 + */
56.127 + private void allocateElements(int numElements) {
56.128 + int initialCapacity = MIN_INITIAL_CAPACITY;
56.129 + // Find the best power of two to hold elements.
56.130 + // Tests "<=" because arrays aren't kept full.
56.131 + if (numElements >= initialCapacity) {
56.132 + initialCapacity = numElements;
56.133 + initialCapacity |= (initialCapacity >>> 1);
56.134 + initialCapacity |= (initialCapacity >>> 2);
56.135 + initialCapacity |= (initialCapacity >>> 4);
56.136 + initialCapacity |= (initialCapacity >>> 8);
56.137 + initialCapacity |= (initialCapacity >>> 16);
56.138 + initialCapacity++;
56.139 +
56.140 + if (initialCapacity < 0) // Too many elements, must back off
56.141 + initialCapacity >>>= 1;// Good luck allocating 2 ^ 30 elements
56.142 + }
56.143 + elements = (E[]) new Object[initialCapacity];
56.144 + }
56.145 +
56.146 + /**
56.147 + * Double the capacity of this deque. Call only when full, i.e.,
56.148 + * when head and tail have wrapped around to become equal.
56.149 + */
56.150 + private void doubleCapacity() {
56.151 + assert head == tail;
56.152 + int p = head;
56.153 + int n = elements.length;
56.154 + int r = n - p; // number of elements to the right of p
56.155 + int newCapacity = n << 1;
56.156 + if (newCapacity < 0)
56.157 + throw new IllegalStateException("Sorry, deque too big");
56.158 + Object[] a = new Object[newCapacity];
56.159 + System.arraycopy(elements, p, a, 0, r);
56.160 + System.arraycopy(elements, 0, a, r, p);
56.161 + elements = (E[])a;
56.162 + head = 0;
56.163 + tail = n;
56.164 + }
56.165 +
56.166 + /**
56.167 + * Copies the elements from our element array into the specified array,
56.168 + * in order (from first to last element in the deque). It is assumed
56.169 + * that the array is large enough to hold all elements in the deque.
56.170 + *
56.171 + * @return its argument
56.172 + */
56.173 + private <T> T[] copyElements(T[] a) {
56.174 + if (head < tail) {
56.175 + System.arraycopy(elements, head, a, 0, size());
56.176 + } else if (head > tail) {
56.177 + int headPortionLen = elements.length - head;
56.178 + System.arraycopy(elements, head, a, 0, headPortionLen);
56.179 + System.arraycopy(elements, 0, a, headPortionLen, tail);
56.180 + }
56.181 + return a;
56.182 + }
56.183 +
56.184 + /**
56.185 + * Constructs an empty array deque with an initial capacity
56.186 + * sufficient to hold 16 elements.
56.187 + */
56.188 + public ArrayDeque() {
56.189 + elements = (E[]) new Object[16];
56.190 + }
56.191 +
56.192 + /**
56.193 + * Constructs an empty array deque with an initial capacity
56.194 + * sufficient to hold the specified number of elements.
56.195 + *
56.196 + * @param numElements lower bound on initial capacity of the deque
56.197 + */
56.198 + public ArrayDeque(int numElements) {
56.199 + allocateElements(numElements);
56.200 + }
56.201 +
56.202 + /**
56.203 + * Constructs a deque containing the elements of the specified
56.204 + * collection, in the order they are returned by the collection's
56.205 + * iterator. (The first element returned by the collection's
56.206 + * iterator becomes the first element, or <i>front</i> of the
56.207 + * deque.)
56.208 + *
56.209 + * @param c the collection whose elements are to be placed into the deque
56.210 + * @throws NullPointerException if the specified collection is null
56.211 + */
56.212 + public ArrayDeque(Collection<? extends E> c) {
56.213 + allocateElements(c.size());
56.214 + addAll(c);
56.215 + }
56.216 +
56.217 + // The main insertion and extraction methods are addFirst,
56.218 + // addLast, pollFirst, pollLast. The other methods are defined in
56.219 + // terms of these.
56.220 +
56.221 + /**
56.222 + * Inserts the specified element at the front of this deque.
56.223 + *
56.224 + * @param e the element to add
56.225 + * @throws NullPointerException if the specified element is null
56.226 + */
56.227 + public void addFirst(E e) {
56.228 + if (e == null)
56.229 + throw new NullPointerException();
56.230 + elements[head = (head - 1) & (elements.length - 1)] = e;
56.231 + if (head == tail)
56.232 + doubleCapacity();
56.233 + }
56.234 +
56.235 + /**
56.236 + * Inserts the specified element at the end of this deque.
56.237 + *
56.238 + * <p>This method is equivalent to {@link #add}.
56.239 + *
56.240 + * @param e the element to add
56.241 + * @throws NullPointerException if the specified element is null
56.242 + */
56.243 + public void addLast(E e) {
56.244 + if (e == null)
56.245 + throw new NullPointerException();
56.246 + elements[tail] = e;
56.247 + if ( (tail = (tail + 1) & (elements.length - 1)) == head)
56.248 + doubleCapacity();
56.249 + }
56.250 +
56.251 + /**
56.252 + * Inserts the specified element at the front of this deque.
56.253 + *
56.254 + * @param e the element to add
56.255 + * @return <tt>true</tt> (as specified by {@link Deque#offerFirst})
56.256 + * @throws NullPointerException if the specified element is null
56.257 + */
56.258 + public boolean offerFirst(E e) {
56.259 + addFirst(e);
56.260 + return true;
56.261 + }
56.262 +
56.263 + /**
56.264 + * Inserts the specified element at the end of this deque.
56.265 + *
56.266 + * @param e the element to add
56.267 + * @return <tt>true</tt> (as specified by {@link Deque#offerLast})
56.268 + * @throws NullPointerException if the specified element is null
56.269 + */
56.270 + public boolean offerLast(E e) {
56.271 + addLast(e);
56.272 + return true;
56.273 + }
56.274 +
56.275 + /**
56.276 + * @throws NoSuchElementException {@inheritDoc}
56.277 + */
56.278 + public E removeFirst() {
56.279 + E x = pollFirst();
56.280 + if (x == null)
56.281 + throw new NoSuchElementException();
56.282 + return x;
56.283 + }
56.284 +
56.285 + /**
56.286 + * @throws NoSuchElementException {@inheritDoc}
56.287 + */
56.288 + public E removeLast() {
56.289 + E x = pollLast();
56.290 + if (x == null)
56.291 + throw new NoSuchElementException();
56.292 + return x;
56.293 + }
56.294 +
56.295 + public E pollFirst() {
56.296 + int h = head;
56.297 + E result = elements[h]; // Element is null if deque empty
56.298 + if (result == null)
56.299 + return null;
56.300 + elements[h] = null; // Must null out slot
56.301 + head = (h + 1) & (elements.length - 1);
56.302 + return result;
56.303 + }
56.304 +
56.305 + public E pollLast() {
56.306 + int t = (tail - 1) & (elements.length - 1);
56.307 + E result = elements[t];
56.308 + if (result == null)
56.309 + return null;
56.310 + elements[t] = null;
56.311 + tail = t;
56.312 + return result;
56.313 + }
56.314 +
56.315 + /**
56.316 + * @throws NoSuchElementException {@inheritDoc}
56.317 + */
56.318 + public E getFirst() {
56.319 + E x = elements[head];
56.320 + if (x == null)
56.321 + throw new NoSuchElementException();
56.322 + return x;
56.323 + }
56.324 +
56.325 + /**
56.326 + * @throws NoSuchElementException {@inheritDoc}
56.327 + */
56.328 + public E getLast() {
56.329 + E x = elements[(tail - 1) & (elements.length - 1)];
56.330 + if (x == null)
56.331 + throw new NoSuchElementException();
56.332 + return x;
56.333 + }
56.334 +
56.335 + public E peekFirst() {
56.336 + return elements[head]; // elements[head] is null if deque empty
56.337 + }
56.338 +
56.339 + public E peekLast() {
56.340 + return elements[(tail - 1) & (elements.length - 1)];
56.341 + }
56.342 +
56.343 + /**
56.344 + * Removes the first occurrence of the specified element in this
56.345 + * deque (when traversing the deque from head to tail).
56.346 + * If the deque does not contain the element, it is unchanged.
56.347 + * More formally, removes the first element <tt>e</tt> such that
56.348 + * <tt>o.equals(e)</tt> (if such an element exists).
56.349 + * Returns <tt>true</tt> if this deque contained the specified element
56.350 + * (or equivalently, if this deque changed as a result of the call).
56.351 + *
56.352 + * @param o element to be removed from this deque, if present
56.353 + * @return <tt>true</tt> if the deque contained the specified element
56.354 + */
56.355 + public boolean removeFirstOccurrence(Object o) {
56.356 + if (o == null)
56.357 + return false;
56.358 + int mask = elements.length - 1;
56.359 + int i = head;
56.360 + E x;
56.361 + while ( (x = elements[i]) != null) {
56.362 + if (o.equals(x)) {
56.363 + delete(i);
56.364 + return true;
56.365 + }
56.366 + i = (i + 1) & mask;
56.367 + }
56.368 + return false;
56.369 + }
56.370 +
56.371 + /**
56.372 + * Removes the last occurrence of the specified element in this
56.373 + * deque (when traversing the deque from head to tail).
56.374 + * If the deque does not contain the element, it is unchanged.
56.375 + * More formally, removes the last element <tt>e</tt> such that
56.376 + * <tt>o.equals(e)</tt> (if such an element exists).
56.377 + * Returns <tt>true</tt> if this deque contained the specified element
56.378 + * (or equivalently, if this deque changed as a result of the call).
56.379 + *
56.380 + * @param o element to be removed from this deque, if present
56.381 + * @return <tt>true</tt> if the deque contained the specified element
56.382 + */
56.383 + public boolean removeLastOccurrence(Object o) {
56.384 + if (o == null)
56.385 + return false;
56.386 + int mask = elements.length - 1;
56.387 + int i = (tail - 1) & mask;
56.388 + E x;
56.389 + while ( (x = elements[i]) != null) {
56.390 + if (o.equals(x)) {
56.391 + delete(i);
56.392 + return true;
56.393 + }
56.394 + i = (i - 1) & mask;
56.395 + }
56.396 + return false;
56.397 + }
56.398 +
56.399 + // *** Queue methods ***
56.400 +
56.401 + /**
56.402 + * Inserts the specified element at the end of this deque.
56.403 + *
56.404 + * <p>This method is equivalent to {@link #addLast}.
56.405 + *
56.406 + * @param e the element to add
56.407 + * @return <tt>true</tt> (as specified by {@link Collection#add})
56.408 + * @throws NullPointerException if the specified element is null
56.409 + */
56.410 + public boolean add(E e) {
56.411 + addLast(e);
56.412 + return true;
56.413 + }
56.414 +
56.415 + /**
56.416 + * Inserts the specified element at the end of this deque.
56.417 + *
56.418 + * <p>This method is equivalent to {@link #offerLast}.
56.419 + *
56.420 + * @param e the element to add
56.421 + * @return <tt>true</tt> (as specified by {@link Queue#offer})
56.422 + * @throws NullPointerException if the specified element is null
56.423 + */
56.424 + public boolean offer(E e) {
56.425 + return offerLast(e);
56.426 + }
56.427 +
56.428 + /**
56.429 + * Retrieves and removes the head of the queue represented by this deque.
56.430 + *
56.431 + * This method differs from {@link #poll poll} only in that it throws an
56.432 + * exception if this deque is empty.
56.433 + *
56.434 + * <p>This method is equivalent to {@link #removeFirst}.
56.435 + *
56.436 + * @return the head of the queue represented by this deque
56.437 + * @throws NoSuchElementException {@inheritDoc}
56.438 + */
56.439 + public E remove() {
56.440 + return removeFirst();
56.441 + }
56.442 +
56.443 + /**
56.444 + * Retrieves and removes the head of the queue represented by this deque
56.445 + * (in other words, the first element of this deque), or returns
56.446 + * <tt>null</tt> if this deque is empty.
56.447 + *
56.448 + * <p>This method is equivalent to {@link #pollFirst}.
56.449 + *
56.450 + * @return the head of the queue represented by this deque, or
56.451 + * <tt>null</tt> if this deque is empty
56.452 + */
56.453 + public E poll() {
56.454 + return pollFirst();
56.455 + }
56.456 +
56.457 + /**
56.458 + * Retrieves, but does not remove, the head of the queue represented by
56.459 + * this deque. This method differs from {@link #peek peek} only in
56.460 + * that it throws an exception if this deque is empty.
56.461 + *
56.462 + * <p>This method is equivalent to {@link #getFirst}.
56.463 + *
56.464 + * @return the head of the queue represented by this deque
56.465 + * @throws NoSuchElementException {@inheritDoc}
56.466 + */
56.467 + public E element() {
56.468 + return getFirst();
56.469 + }
56.470 +
56.471 + /**
56.472 + * Retrieves, but does not remove, the head of the queue represented by
56.473 + * this deque, or returns <tt>null</tt> if this deque is empty.
56.474 + *
56.475 + * <p>This method is equivalent to {@link #peekFirst}.
56.476 + *
56.477 + * @return the head of the queue represented by this deque, or
56.478 + * <tt>null</tt> if this deque is empty
56.479 + */
56.480 + public E peek() {
56.481 + return peekFirst();
56.482 + }
56.483 +
56.484 + // *** Stack methods ***
56.485 +
56.486 + /**
56.487 + * Pushes an element onto the stack represented by this deque. In other
56.488 + * words, inserts the element at the front of this deque.
56.489 + *
56.490 + * <p>This method is equivalent to {@link #addFirst}.
56.491 + *
56.492 + * @param e the element to push
56.493 + * @throws NullPointerException if the specified element is null
56.494 + */
56.495 + public void push(E e) {
56.496 + addFirst(e);
56.497 + }
56.498 +
56.499 + /**
56.500 + * Pops an element from the stack represented by this deque. In other
56.501 + * words, removes and returns the first element of this deque.
56.502 + *
56.503 + * <p>This method is equivalent to {@link #removeFirst()}.
56.504 + *
56.505 + * @return the element at the front of this deque (which is the top
56.506 + * of the stack represented by this deque)
56.507 + * @throws NoSuchElementException {@inheritDoc}
56.508 + */
56.509 + public E pop() {
56.510 + return removeFirst();
56.511 + }
56.512 +
56.513 + private void checkInvariants() {
56.514 + assert elements[tail] == null;
56.515 + assert head == tail ? elements[head] == null :
56.516 + (elements[head] != null &&
56.517 + elements[(tail - 1) & (elements.length - 1)] != null);
56.518 + assert elements[(head - 1) & (elements.length - 1)] == null;
56.519 + }
56.520 +
56.521 + /**
56.522 + * Removes the element at the specified position in the elements array,
56.523 + * adjusting head and tail as necessary. This can result in motion of
56.524 + * elements backwards or forwards in the array.
56.525 + *
56.526 + * <p>This method is called delete rather than remove to emphasize
56.527 + * that its semantics differ from those of {@link List#remove(int)}.
56.528 + *
56.529 + * @return true if elements moved backwards
56.530 + */
56.531 + private boolean delete(int i) {
56.532 + checkInvariants();
56.533 + final E[] elements = this.elements;
56.534 + final int mask = elements.length - 1;
56.535 + final int h = head;
56.536 + final int t = tail;
56.537 + final int front = (i - h) & mask;
56.538 + final int back = (t - i) & mask;
56.539 +
56.540 + // Invariant: head <= i < tail mod circularity
56.541 + if (front >= ((t - h) & mask))
56.542 + throw new ConcurrentModificationException();
56.543 +
56.544 + // Optimize for least element motion
56.545 + if (front < back) {
56.546 + if (h <= i) {
56.547 + System.arraycopy(elements, h, elements, h + 1, front);
56.548 + } else { // Wrap around
56.549 + System.arraycopy(elements, 0, elements, 1, i);
56.550 + elements[0] = elements[mask];
56.551 + System.arraycopy(elements, h, elements, h + 1, mask - h);
56.552 + }
56.553 + elements[h] = null;
56.554 + head = (h + 1) & mask;
56.555 + return false;
56.556 + } else {
56.557 + if (i < t) { // Copy the null tail as well
56.558 + System.arraycopy(elements, i + 1, elements, i, back);
56.559 + tail = t - 1;
56.560 + } else { // Wrap around
56.561 + System.arraycopy(elements, i + 1, elements, i, mask - i);
56.562 + elements[mask] = elements[0];
56.563 + System.arraycopy(elements, 1, elements, 0, t);
56.564 + tail = (t - 1) & mask;
56.565 + }
56.566 + return true;
56.567 + }
56.568 + }
56.569 +
56.570 + // *** Collection Methods ***
56.571 +
56.572 + /**
56.573 + * Returns the number of elements in this deque.
56.574 + *
56.575 + * @return the number of elements in this deque
56.576 + */
56.577 + public int size() {
56.578 + return (tail - head) & (elements.length - 1);
56.579 + }
56.580 +
56.581 + /**
56.582 + * Returns <tt>true</tt> if this deque contains no elements.
56.583 + *
56.584 + * @return <tt>true</tt> if this deque contains no elements
56.585 + */
56.586 + public boolean isEmpty() {
56.587 + return head == tail;
56.588 + }
56.589 +
56.590 + /**
56.591 + * Returns an iterator over the elements in this deque. The elements
56.592 + * will be ordered from first (head) to last (tail). This is the same
56.593 + * order that elements would be dequeued (via successive calls to
56.594 + * {@link #remove} or popped (via successive calls to {@link #pop}).
56.595 + *
56.596 + * @return an iterator over the elements in this deque
56.597 + */
56.598 + public Iterator<E> iterator() {
56.599 + return new DeqIterator();
56.600 + }
56.601 +
56.602 + public Iterator<E> descendingIterator() {
56.603 + return new DescendingIterator();
56.604 + }
56.605 +
56.606 + private class DeqIterator implements Iterator<E> {
56.607 + /**
56.608 + * Index of element to be returned by subsequent call to next.
56.609 + */
56.610 + private int cursor = head;
56.611 +
56.612 + /**
56.613 + * Tail recorded at construction (also in remove), to stop
56.614 + * iterator and also to check for comodification.
56.615 + */
56.616 + private int fence = tail;
56.617 +
56.618 + /**
56.619 + * Index of element returned by most recent call to next.
56.620 + * Reset to -1 if element is deleted by a call to remove.
56.621 + */
56.622 + private int lastRet = -1;
56.623 +
56.624 + public boolean hasNext() {
56.625 + return cursor != fence;
56.626 + }
56.627 +
56.628 + public E next() {
56.629 + if (cursor == fence)
56.630 + throw new NoSuchElementException();
56.631 + E result = elements[cursor];
56.632 + // This check doesn't catch all possible comodifications,
56.633 + // but does catch the ones that corrupt traversal
56.634 + if (tail != fence || result == null)
56.635 + throw new ConcurrentModificationException();
56.636 + lastRet = cursor;
56.637 + cursor = (cursor + 1) & (elements.length - 1);
56.638 + return result;
56.639 + }
56.640 +
56.641 + public void remove() {
56.642 + if (lastRet < 0)
56.643 + throw new IllegalStateException();
56.644 + if (delete(lastRet)) { // if left-shifted, undo increment in next()
56.645 + cursor = (cursor - 1) & (elements.length - 1);
56.646 + fence = tail;
56.647 + }
56.648 + lastRet = -1;
56.649 + }
56.650 + }
56.651 +
56.652 + private class DescendingIterator implements Iterator<E> {
56.653 + /*
56.654 + * This class is nearly a mirror-image of DeqIterator, using
56.655 + * tail instead of head for initial cursor, and head instead of
56.656 + * tail for fence.
56.657 + */
56.658 + private int cursor = tail;
56.659 + private int fence = head;
56.660 + private int lastRet = -1;
56.661 +
56.662 + public boolean hasNext() {
56.663 + return cursor != fence;
56.664 + }
56.665 +
56.666 + public E next() {
56.667 + if (cursor == fence)
56.668 + throw new NoSuchElementException();
56.669 + cursor = (cursor - 1) & (elements.length - 1);
56.670 + E result = elements[cursor];
56.671 + if (head != fence || result == null)
56.672 + throw new ConcurrentModificationException();
56.673 + lastRet = cursor;
56.674 + return result;
56.675 + }
56.676 +
56.677 + public void remove() {
56.678 + if (lastRet < 0)
56.679 + throw new IllegalStateException();
56.680 + if (!delete(lastRet)) {
56.681 + cursor = (cursor + 1) & (elements.length - 1);
56.682 + fence = head;
56.683 + }
56.684 + lastRet = -1;
56.685 + }
56.686 + }
56.687 +
56.688 + /**
56.689 + * Returns <tt>true</tt> if this deque contains the specified element.
56.690 + * More formally, returns <tt>true</tt> if and only if this deque contains
56.691 + * at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
56.692 + *
56.693 + * @param o object to be checked for containment in this deque
56.694 + * @return <tt>true</tt> if this deque contains the specified element
56.695 + */
56.696 + public boolean contains(Object o) {
56.697 + if (o == null)
56.698 + return false;
56.699 + int mask = elements.length - 1;
56.700 + int i = head;
56.701 + E x;
56.702 + while ( (x = elements[i]) != null) {
56.703 + if (o.equals(x))
56.704 + return true;
56.705 + i = (i + 1) & mask;
56.706 + }
56.707 + return false;
56.708 + }
56.709 +
56.710 + /**
56.711 + * Removes a single instance of the specified element from this deque.
56.712 + * If the deque does not contain the element, it is unchanged.
56.713 + * More formally, removes the first element <tt>e</tt> such that
56.714 + * <tt>o.equals(e)</tt> (if such an element exists).
56.715 + * Returns <tt>true</tt> if this deque contained the specified element
56.716 + * (or equivalently, if this deque changed as a result of the call).
56.717 + *
56.718 + * <p>This method is equivalent to {@link #removeFirstOccurrence}.
56.719 + *
56.720 + * @param o element to be removed from this deque, if present
56.721 + * @return <tt>true</tt> if this deque contained the specified element
56.722 + */
56.723 + public boolean remove(Object o) {
56.724 + return removeFirstOccurrence(o);
56.725 + }
56.726 +
56.727 + /**
56.728 + * Removes all of the elements from this deque.
56.729 + * The deque will be empty after this call returns.
56.730 + */
56.731 + public void clear() {
56.732 + int h = head;
56.733 + int t = tail;
56.734 + if (h != t) { // clear all cells
56.735 + head = tail = 0;
56.736 + int i = h;
56.737 + int mask = elements.length - 1;
56.738 + do {
56.739 + elements[i] = null;
56.740 + i = (i + 1) & mask;
56.741 + } while (i != t);
56.742 + }
56.743 + }
56.744 +
56.745 + /**
56.746 + * Returns an array containing all of the elements in this deque
56.747 + * in proper sequence (from first to last element).
56.748 + *
56.749 + * <p>The returned array will be "safe" in that no references to it are
56.750 + * maintained by this deque. (In other words, this method must allocate
56.751 + * a new array). The caller is thus free to modify the returned array.
56.752 + *
56.753 + * <p>This method acts as bridge between array-based and collection-based
56.754 + * APIs.
56.755 + *
56.756 + * @return an array containing all of the elements in this deque
56.757 + */
56.758 + public Object[] toArray() {
56.759 + return copyElements(new Object[size()]);
56.760 + }
56.761 +
56.762 + /**
56.763 + * Returns an array containing all of the elements in this deque in
56.764 + * proper sequence (from first to last element); the runtime type of the
56.765 + * returned array is that of the specified array. If the deque fits in
56.766 + * the specified array, it is returned therein. Otherwise, a new array
56.767 + * is allocated with the runtime type of the specified array and the
56.768 + * size of this deque.
56.769 + *
56.770 + * <p>If this deque fits in the specified array with room to spare
56.771 + * (i.e., the array has more elements than this deque), the element in
56.772 + * the array immediately following the end of the deque is set to
56.773 + * <tt>null</tt>.
56.774 + *
56.775 + * <p>Like the {@link #toArray()} method, this method acts as bridge between
56.776 + * array-based and collection-based APIs. Further, this method allows
56.777 + * precise control over the runtime type of the output array, and may,
56.778 + * under certain circumstances, be used to save allocation costs.
56.779 + *
56.780 + * <p>Suppose <tt>x</tt> is a deque known to contain only strings.
56.781 + * The following code can be used to dump the deque into a newly
56.782 + * allocated array of <tt>String</tt>:
56.783 + *
56.784 + * <pre>
56.785 + * String[] y = x.toArray(new String[0]);</pre>
56.786 + *
56.787 + * Note that <tt>toArray(new Object[0])</tt> is identical in function to
56.788 + * <tt>toArray()</tt>.
56.789 + *
56.790 + * @param a the array into which the elements of the deque are to
56.791 + * be stored, if it is big enough; otherwise, a new array of the
56.792 + * same runtime type is allocated for this purpose
56.793 + * @return an array containing all of the elements in this deque
56.794 + * @throws ArrayStoreException if the runtime type of the specified array
56.795 + * is not a supertype of the runtime type of every element in
56.796 + * this deque
56.797 + * @throws NullPointerException if the specified array is null
56.798 + */
56.799 + public <T> T[] toArray(T[] a) {
56.800 + int size = size();
56.801 + if (a.length < size)
56.802 + a = (T[])java.lang.reflect.Array.newInstance(
56.803 + a.getClass().getComponentType(), size);
56.804 + copyElements(a);
56.805 + if (a.length > size)
56.806 + a[size] = null;
56.807 + return a;
56.808 + }
56.809 +
56.810 + // *** Object methods ***
56.811 +
56.812 + /**
56.813 + * Returns a copy of this deque.
56.814 + *
56.815 + * @return a copy of this deque
56.816 + */
56.817 + public ArrayDeque<E> clone() {
56.818 + try {
56.819 + ArrayDeque<E> result = (ArrayDeque<E>) super.clone();
56.820 + result.elements = Arrays.copyOf(elements, elements.length);
56.821 + return result;
56.822 +
56.823 + } catch (CloneNotSupportedException e) {
56.824 + throw new AssertionError();
56.825 + }
56.826 + }
56.827 +
56.828 + /**
56.829 + * Appease the serialization gods.
56.830 + */
56.831 + private static final long serialVersionUID = 2340985798034038923L;
56.832 +
56.833 +}
57.1 --- a/emul/compact/src/main/java/java/util/ArrayList.java Fri Jan 25 15:08:24 2013 +0100
57.2 +++ b/emul/compact/src/main/java/java/util/ArrayList.java Sun Feb 17 17:58:34 2013 +0100
57.3 @@ -25,7 +25,6 @@
57.4
57.5 package java.util;
57.6
57.7 -import org.apidesign.bck2brwsr.emul.lang.System;
57.8
57.9 /**
57.10 * Resizable-array implementation of the <tt>List</tt> interface. Implements
58.1 --- a/emul/compact/src/main/java/java/util/Arrays.java Fri Jan 25 15:08:24 2013 +0100
58.2 +++ b/emul/compact/src/main/java/java/util/Arrays.java Sun Feb 17 17:58:34 2013 +0100
58.3 @@ -26,7 +26,6 @@
58.4 package java.util;
58.5
58.6 import java.lang.reflect.*;
58.7 -import org.apidesign.bck2brwsr.emul.lang.System;
58.8
58.9 /**
58.10 * This class contains various methods for manipulating arrays (such as
59.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
59.2 +++ b/emul/compact/src/main/java/java/util/Collections.java Sun Feb 17 17:58:34 2013 +0100
59.3 @@ -0,0 +1,3953 @@
59.4 +/*
59.5 + * Copyright (c) 1997, 2011, 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;
59.30 +import java.io.Serializable;
59.31 +import java.io.IOException;
59.32 +import java.lang.reflect.Array;
59.33 +
59.34 +/**
59.35 + * This class consists exclusively of static methods that operate on or return
59.36 + * collections. It contains polymorphic algorithms that operate on
59.37 + * collections, "wrappers", which return a new collection backed by a
59.38 + * specified collection, and a few other odds and ends.
59.39 + *
59.40 + * <p>The methods of this class all throw a <tt>NullPointerException</tt>
59.41 + * if the collections or class objects provided to them are null.
59.42 + *
59.43 + * <p>The documentation for the polymorphic algorithms contained in this class
59.44 + * generally includes a brief description of the <i>implementation</i>. Such
59.45 + * descriptions should be regarded as <i>implementation notes</i>, rather than
59.46 + * parts of the <i>specification</i>. Implementors should feel free to
59.47 + * substitute other algorithms, so long as the specification itself is adhered
59.48 + * to. (For example, the algorithm used by <tt>sort</tt> does not have to be
59.49 + * a mergesort, but it does have to be <i>stable</i>.)
59.50 + *
59.51 + * <p>The "destructive" algorithms contained in this class, that is, the
59.52 + * algorithms that modify the collection on which they operate, are specified
59.53 + * to throw <tt>UnsupportedOperationException</tt> if the collection does not
59.54 + * support the appropriate mutation primitive(s), such as the <tt>set</tt>
59.55 + * method. These algorithms may, but are not required to, throw this
59.56 + * exception if an invocation would have no effect on the collection. For
59.57 + * example, invoking the <tt>sort</tt> method on an unmodifiable list that is
59.58 + * already sorted may or may not throw <tt>UnsupportedOperationException</tt>.
59.59 + *
59.60 + * <p>This class is a member of the
59.61 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
59.62 + * Java Collections Framework</a>.
59.63 + *
59.64 + * @author Josh Bloch
59.65 + * @author Neal Gafter
59.66 + * @see Collection
59.67 + * @see Set
59.68 + * @see List
59.69 + * @see Map
59.70 + * @since 1.2
59.71 + */
59.72 +
59.73 +public class Collections {
59.74 + // Suppresses default constructor, ensuring non-instantiability.
59.75 + private Collections() {
59.76 + }
59.77 +
59.78 + // Algorithms
59.79 +
59.80 + /*
59.81 + * Tuning parameters for algorithms - Many of the List algorithms have
59.82 + * two implementations, one of which is appropriate for RandomAccess
59.83 + * lists, the other for "sequential." Often, the random access variant
59.84 + * yields better performance on small sequential access lists. The
59.85 + * tuning parameters below determine the cutoff point for what constitutes
59.86 + * a "small" sequential access list for each algorithm. The values below
59.87 + * were empirically determined to work well for LinkedList. Hopefully
59.88 + * they should be reasonable for other sequential access List
59.89 + * implementations. Those doing performance work on this code would
59.90 + * do well to validate the values of these parameters from time to time.
59.91 + * (The first word of each tuning parameter name is the algorithm to which
59.92 + * it applies.)
59.93 + */
59.94 + private static final int BINARYSEARCH_THRESHOLD = 5000;
59.95 + private static final int REVERSE_THRESHOLD = 18;
59.96 + private static final int SHUFFLE_THRESHOLD = 5;
59.97 + private static final int FILL_THRESHOLD = 25;
59.98 + private static final int ROTATE_THRESHOLD = 100;
59.99 + private static final int COPY_THRESHOLD = 10;
59.100 + private static final int REPLACEALL_THRESHOLD = 11;
59.101 + private static final int INDEXOFSUBLIST_THRESHOLD = 35;
59.102 +
59.103 + /**
59.104 + * Sorts the specified list into ascending order, according to the
59.105 + * {@linkplain Comparable natural ordering} of its elements.
59.106 + * All elements in the list must implement the {@link Comparable}
59.107 + * interface. Furthermore, all elements in the list must be
59.108 + * <i>mutually comparable</i> (that is, {@code e1.compareTo(e2)}
59.109 + * must not throw a {@code ClassCastException} for any elements
59.110 + * {@code e1} and {@code e2} in the list).
59.111 + *
59.112 + * <p>This sort is guaranteed to be <i>stable</i>: equal elements will
59.113 + * not be reordered as a result of the sort.
59.114 + *
59.115 + * <p>The specified list must be modifiable, but need not be resizable.
59.116 + *
59.117 + * <p>Implementation note: This implementation is a stable, adaptive,
59.118 + * iterative mergesort that requires far fewer than n lg(n) comparisons
59.119 + * when the input array is partially sorted, while offering the
59.120 + * performance of a traditional mergesort when the input array is
59.121 + * randomly ordered. If the input array is nearly sorted, the
59.122 + * implementation requires approximately n comparisons. Temporary
59.123 + * storage requirements vary from a small constant for nearly sorted
59.124 + * input arrays to n/2 object references for randomly ordered input
59.125 + * arrays.
59.126 + *
59.127 + * <p>The implementation takes equal advantage of ascending and
59.128 + * descending order in its input array, and can take advantage of
59.129 + * ascending and descending order in different parts of the same
59.130 + * input array. It is well-suited to merging two or more sorted arrays:
59.131 + * simply concatenate the arrays and sort the resulting array.
59.132 + *
59.133 + * <p>The implementation was adapted from Tim Peters's list sort for Python
59.134 + * (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt">
59.135 + * TimSort</a>). It uses techiques from Peter McIlroy's "Optimistic
59.136 + * Sorting and Information Theoretic Complexity", in Proceedings of the
59.137 + * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474,
59.138 + * January 1993.
59.139 + *
59.140 + * <p>This implementation dumps the specified list into an array, sorts
59.141 + * the array, and iterates over the list resetting each element
59.142 + * from the corresponding position in the array. This avoids the
59.143 + * n<sup>2</sup> log(n) performance that would result from attempting
59.144 + * to sort a linked list in place.
59.145 + *
59.146 + * @param list the list to be sorted.
59.147 + * @throws ClassCastException if the list contains elements that are not
59.148 + * <i>mutually comparable</i> (for example, strings and integers).
59.149 + * @throws UnsupportedOperationException if the specified list's
59.150 + * list-iterator does not support the {@code set} operation.
59.151 + * @throws IllegalArgumentException (optional) if the implementation
59.152 + * detects that the natural ordering of the list elements is
59.153 + * found to violate the {@link Comparable} contract
59.154 + */
59.155 + public static <T extends Comparable<? super T>> void sort(List<T> list) {
59.156 + Object[] a = list.toArray();
59.157 + Arrays.sort(a);
59.158 + ListIterator<T> i = list.listIterator();
59.159 + for (int j=0; j<a.length; j++) {
59.160 + i.next();
59.161 + i.set((T)a[j]);
59.162 + }
59.163 + }
59.164 +
59.165 + /**
59.166 + * Sorts the specified list according to the order induced by the
59.167 + * specified comparator. All elements in the list must be <i>mutually
59.168 + * comparable</i> using the specified comparator (that is,
59.169 + * {@code c.compare(e1, e2)} must not throw a {@code ClassCastException}
59.170 + * for any elements {@code e1} and {@code e2} in the list).
59.171 + *
59.172 + * <p>This sort is guaranteed to be <i>stable</i>: equal elements will
59.173 + * not be reordered as a result of the sort.
59.174 + *
59.175 + * <p>The specified list must be modifiable, but need not be resizable.
59.176 + *
59.177 + * <p>Implementation note: This implementation is a stable, adaptive,
59.178 + * iterative mergesort that requires far fewer than n lg(n) comparisons
59.179 + * when the input array is partially sorted, while offering the
59.180 + * performance of a traditional mergesort when the input array is
59.181 + * randomly ordered. If the input array is nearly sorted, the
59.182 + * implementation requires approximately n comparisons. Temporary
59.183 + * storage requirements vary from a small constant for nearly sorted
59.184 + * input arrays to n/2 object references for randomly ordered input
59.185 + * arrays.
59.186 + *
59.187 + * <p>The implementation takes equal advantage of ascending and
59.188 + * descending order in its input array, and can take advantage of
59.189 + * ascending and descending order in different parts of the same
59.190 + * input array. It is well-suited to merging two or more sorted arrays:
59.191 + * simply concatenate the arrays and sort the resulting array.
59.192 + *
59.193 + * <p>The implementation was adapted from Tim Peters's list sort for Python
59.194 + * (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt">
59.195 + * TimSort</a>). It uses techiques from Peter McIlroy's "Optimistic
59.196 + * Sorting and Information Theoretic Complexity", in Proceedings of the
59.197 + * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474,
59.198 + * January 1993.
59.199 + *
59.200 + * <p>This implementation dumps the specified list into an array, sorts
59.201 + * the array, and iterates over the list resetting each element
59.202 + * from the corresponding position in the array. This avoids the
59.203 + * n<sup>2</sup> log(n) performance that would result from attempting
59.204 + * to sort a linked list in place.
59.205 + *
59.206 + * @param list the list to be sorted.
59.207 + * @param c the comparator to determine the order of the list. A
59.208 + * {@code null} value indicates that the elements' <i>natural
59.209 + * ordering</i> should be used.
59.210 + * @throws ClassCastException if the list contains elements that are not
59.211 + * <i>mutually comparable</i> using the specified comparator.
59.212 + * @throws UnsupportedOperationException if the specified list's
59.213 + * list-iterator does not support the {@code set} operation.
59.214 + * @throws IllegalArgumentException (optional) if the comparator is
59.215 + * found to violate the {@link Comparator} contract
59.216 + */
59.217 + public static <T> void sort(List<T> list, Comparator<? super T> c) {
59.218 + Object[] a = list.toArray();
59.219 + Arrays.sort(a, (Comparator)c);
59.220 + ListIterator i = list.listIterator();
59.221 + for (int j=0; j<a.length; j++) {
59.222 + i.next();
59.223 + i.set(a[j]);
59.224 + }
59.225 + }
59.226 +
59.227 +
59.228 + /**
59.229 + * Searches the specified list for the specified object using the binary
59.230 + * search algorithm. The list must be sorted into ascending order
59.231 + * according to the {@linkplain Comparable natural ordering} of its
59.232 + * elements (as by the {@link #sort(List)} method) prior to making this
59.233 + * call. If it is not sorted, the results are undefined. If the list
59.234 + * contains multiple elements equal to the specified object, there is no
59.235 + * guarantee which one will be found.
59.236 + *
59.237 + * <p>This method runs in log(n) time for a "random access" list (which
59.238 + * provides near-constant-time positional access). If the specified list
59.239 + * does not implement the {@link RandomAccess} interface and is large,
59.240 + * this method will do an iterator-based binary search that performs
59.241 + * O(n) link traversals and O(log n) element comparisons.
59.242 + *
59.243 + * @param list the list to be searched.
59.244 + * @param key the key to be searched for.
59.245 + * @return the index of the search key, if it is contained in the list;
59.246 + * otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>. The
59.247 + * <i>insertion point</i> is defined as the point at which the
59.248 + * key would be inserted into the list: the index of the first
59.249 + * element greater than the key, or <tt>list.size()</tt> if all
59.250 + * elements in the list are less than the specified key. Note
59.251 + * that this guarantees that the return value will be >= 0 if
59.252 + * and only if the key is found.
59.253 + * @throws ClassCastException if the list contains elements that are not
59.254 + * <i>mutually comparable</i> (for example, strings and
59.255 + * integers), or the search key is not mutually comparable
59.256 + * with the elements of the list.
59.257 + */
59.258 + public static <T>
59.259 + int binarySearch(List<? extends Comparable<? super T>> list, T key) {
59.260 + if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
59.261 + return Collections.indexedBinarySearch(list, key);
59.262 + else
59.263 + return Collections.iteratorBinarySearch(list, key);
59.264 + }
59.265 +
59.266 + private static <T>
59.267 + int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key)
59.268 + {
59.269 + int low = 0;
59.270 + int high = list.size()-1;
59.271 +
59.272 + while (low <= high) {
59.273 + int mid = (low + high) >>> 1;
59.274 + Comparable<? super T> midVal = list.get(mid);
59.275 + int cmp = midVal.compareTo(key);
59.276 +
59.277 + if (cmp < 0)
59.278 + low = mid + 1;
59.279 + else if (cmp > 0)
59.280 + high = mid - 1;
59.281 + else
59.282 + return mid; // key found
59.283 + }
59.284 + return -(low + 1); // key not found
59.285 + }
59.286 +
59.287 + private static <T>
59.288 + int iteratorBinarySearch(List<? extends Comparable<? super T>> list, T key)
59.289 + {
59.290 + int low = 0;
59.291 + int high = list.size()-1;
59.292 + ListIterator<? extends Comparable<? super T>> i = list.listIterator();
59.293 +
59.294 + while (low <= high) {
59.295 + int mid = (low + high) >>> 1;
59.296 + Comparable<? super T> midVal = get(i, mid);
59.297 + int cmp = midVal.compareTo(key);
59.298 +
59.299 + if (cmp < 0)
59.300 + low = mid + 1;
59.301 + else if (cmp > 0)
59.302 + high = mid - 1;
59.303 + else
59.304 + return mid; // key found
59.305 + }
59.306 + return -(low + 1); // key not found
59.307 + }
59.308 +
59.309 + /**
59.310 + * Gets the ith element from the given list by repositioning the specified
59.311 + * list listIterator.
59.312 + */
59.313 + private static <T> T get(ListIterator<? extends T> i, int index) {
59.314 + T obj = null;
59.315 + int pos = i.nextIndex();
59.316 + if (pos <= index) {
59.317 + do {
59.318 + obj = i.next();
59.319 + } while (pos++ < index);
59.320 + } else {
59.321 + do {
59.322 + obj = i.previous();
59.323 + } while (--pos > index);
59.324 + }
59.325 + return obj;
59.326 + }
59.327 +
59.328 + /**
59.329 + * Searches the specified list for the specified object using the binary
59.330 + * search algorithm. The list must be sorted into ascending order
59.331 + * according to the specified comparator (as by the
59.332 + * {@link #sort(List, Comparator) sort(List, Comparator)}
59.333 + * method), prior to making this call. If it is
59.334 + * not sorted, the results are undefined. If the list contains multiple
59.335 + * elements equal to the specified object, there is no guarantee which one
59.336 + * will be found.
59.337 + *
59.338 + * <p>This method runs in log(n) time for a "random access" list (which
59.339 + * provides near-constant-time positional access). If the specified list
59.340 + * does not implement the {@link RandomAccess} interface and is large,
59.341 + * this method will do an iterator-based binary search that performs
59.342 + * O(n) link traversals and O(log n) element comparisons.
59.343 + *
59.344 + * @param list the list to be searched.
59.345 + * @param key the key to be searched for.
59.346 + * @param c the comparator by which the list is ordered.
59.347 + * A <tt>null</tt> value indicates that the elements'
59.348 + * {@linkplain Comparable natural ordering} should be used.
59.349 + * @return the index of the search key, if it is contained in the list;
59.350 + * otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>. The
59.351 + * <i>insertion point</i> is defined as the point at which the
59.352 + * key would be inserted into the list: the index of the first
59.353 + * element greater than the key, or <tt>list.size()</tt> if all
59.354 + * elements in the list are less than the specified key. Note
59.355 + * that this guarantees that the return value will be >= 0 if
59.356 + * and only if the key is found.
59.357 + * @throws ClassCastException if the list contains elements that are not
59.358 + * <i>mutually comparable</i> using the specified comparator,
59.359 + * or the search key is not mutually comparable with the
59.360 + * elements of the list using this comparator.
59.361 + */
59.362 + public static <T> int binarySearch(List<? extends T> list, T key, Comparator<? super T> c) {
59.363 + if (c==null)
59.364 + return binarySearch((List) list, key);
59.365 +
59.366 + if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
59.367 + return Collections.indexedBinarySearch(list, key, c);
59.368 + else
59.369 + return Collections.iteratorBinarySearch(list, key, c);
59.370 + }
59.371 +
59.372 + private static <T> int indexedBinarySearch(List<? extends T> l, T key, Comparator<? super T> c) {
59.373 + int low = 0;
59.374 + int high = l.size()-1;
59.375 +
59.376 + while (low <= high) {
59.377 + int mid = (low + high) >>> 1;
59.378 + T midVal = l.get(mid);
59.379 + int cmp = c.compare(midVal, key);
59.380 +
59.381 + if (cmp < 0)
59.382 + low = mid + 1;
59.383 + else if (cmp > 0)
59.384 + high = mid - 1;
59.385 + else
59.386 + return mid; // key found
59.387 + }
59.388 + return -(low + 1); // key not found
59.389 + }
59.390 +
59.391 + private static <T> int iteratorBinarySearch(List<? extends T> l, T key, Comparator<? super T> c) {
59.392 + int low = 0;
59.393 + int high = l.size()-1;
59.394 + ListIterator<? extends T> i = l.listIterator();
59.395 +
59.396 + while (low <= high) {
59.397 + int mid = (low + high) >>> 1;
59.398 + T midVal = get(i, mid);
59.399 + int cmp = c.compare(midVal, key);
59.400 +
59.401 + if (cmp < 0)
59.402 + low = mid + 1;
59.403 + else if (cmp > 0)
59.404 + high = mid - 1;
59.405 + else
59.406 + return mid; // key found
59.407 + }
59.408 + return -(low + 1); // key not found
59.409 + }
59.410 +
59.411 + private interface SelfComparable extends Comparable<SelfComparable> {}
59.412 +
59.413 +
59.414 + /**
59.415 + * Reverses the order of the elements in the specified list.<p>
59.416 + *
59.417 + * This method runs in linear time.
59.418 + *
59.419 + * @param list the list whose elements are to be reversed.
59.420 + * @throws UnsupportedOperationException if the specified list or
59.421 + * its list-iterator does not support the <tt>set</tt> operation.
59.422 + */
59.423 + public static void reverse(List<?> list) {
59.424 + int size = list.size();
59.425 + if (size < REVERSE_THRESHOLD || list instanceof RandomAccess) {
59.426 + for (int i=0, mid=size>>1, j=size-1; i<mid; i++, j--)
59.427 + swap(list, i, j);
59.428 + } else {
59.429 + ListIterator fwd = list.listIterator();
59.430 + ListIterator rev = list.listIterator(size);
59.431 + for (int i=0, mid=list.size()>>1; i<mid; i++) {
59.432 + Object tmp = fwd.next();
59.433 + fwd.set(rev.previous());
59.434 + rev.set(tmp);
59.435 + }
59.436 + }
59.437 + }
59.438 +
59.439 + /**
59.440 + * Randomly permutes the specified list using a default source of
59.441 + * randomness. All permutations occur with approximately equal
59.442 + * likelihood.<p>
59.443 + *
59.444 + * The hedge "approximately" is used in the foregoing description because
59.445 + * default source of randomness is only approximately an unbiased source
59.446 + * of independently chosen bits. If it were a perfect source of randomly
59.447 + * chosen bits, then the algorithm would choose permutations with perfect
59.448 + * uniformity.<p>
59.449 + *
59.450 + * This implementation traverses the list backwards, from the last element
59.451 + * up to the second, repeatedly swapping a randomly selected element into
59.452 + * the "current position". Elements are randomly selected from the
59.453 + * portion of the list that runs from the first element to the current
59.454 + * position, inclusive.<p>
59.455 + *
59.456 + * This method runs in linear time. If the specified list does not
59.457 + * implement the {@link RandomAccess} interface and is large, this
59.458 + * implementation dumps the specified list into an array before shuffling
59.459 + * it, and dumps the shuffled array back into the list. This avoids the
59.460 + * quadratic behavior that would result from shuffling a "sequential
59.461 + * access" list in place.
59.462 + *
59.463 + * @param list the list to be shuffled.
59.464 + * @throws UnsupportedOperationException if the specified list or
59.465 + * its list-iterator does not support the <tt>set</tt> operation.
59.466 + */
59.467 + public static void shuffle(List<?> list) {
59.468 + Random rnd = r;
59.469 + if (rnd == null)
59.470 + r = rnd = new Random();
59.471 + shuffle(list, rnd);
59.472 + }
59.473 + private static Random r;
59.474 +
59.475 + /**
59.476 + * Randomly permute the specified list using the specified source of
59.477 + * randomness. All permutations occur with equal likelihood
59.478 + * assuming that the source of randomness is fair.<p>
59.479 + *
59.480 + * This implementation traverses the list backwards, from the last element
59.481 + * up to the second, repeatedly swapping a randomly selected element into
59.482 + * the "current position". Elements are randomly selected from the
59.483 + * portion of the list that runs from the first element to the current
59.484 + * position, inclusive.<p>
59.485 + *
59.486 + * This method runs in linear time. If the specified list does not
59.487 + * implement the {@link RandomAccess} interface and is large, this
59.488 + * implementation dumps the specified list into an array before shuffling
59.489 + * it, and dumps the shuffled array back into the list. This avoids the
59.490 + * quadratic behavior that would result from shuffling a "sequential
59.491 + * access" list in place.
59.492 + *
59.493 + * @param list the list to be shuffled.
59.494 + * @param rnd the source of randomness to use to shuffle the list.
59.495 + * @throws UnsupportedOperationException if the specified list or its
59.496 + * list-iterator does not support the <tt>set</tt> operation.
59.497 + */
59.498 + public static void shuffle(List<?> list, Random rnd) {
59.499 + int size = list.size();
59.500 + if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
59.501 + for (int i=size; i>1; i--)
59.502 + swap(list, i-1, rnd.nextInt(i));
59.503 + } else {
59.504 + Object arr[] = list.toArray();
59.505 +
59.506 + // Shuffle array
59.507 + for (int i=size; i>1; i--)
59.508 + swap(arr, i-1, rnd.nextInt(i));
59.509 +
59.510 + // Dump array back into list
59.511 + ListIterator it = list.listIterator();
59.512 + for (int i=0; i<arr.length; i++) {
59.513 + it.next();
59.514 + it.set(arr[i]);
59.515 + }
59.516 + }
59.517 + }
59.518 +
59.519 + /**
59.520 + * Swaps the elements at the specified positions in the specified list.
59.521 + * (If the specified positions are equal, invoking this method leaves
59.522 + * the list unchanged.)
59.523 + *
59.524 + * @param list The list in which to swap elements.
59.525 + * @param i the index of one element to be swapped.
59.526 + * @param j the index of the other element to be swapped.
59.527 + * @throws IndexOutOfBoundsException if either <tt>i</tt> or <tt>j</tt>
59.528 + * is out of range (i < 0 || i >= list.size()
59.529 + * || j < 0 || j >= list.size()).
59.530 + * @since 1.4
59.531 + */
59.532 + public static void swap(List<?> list, int i, int j) {
59.533 + final List l = list;
59.534 + l.set(i, l.set(j, l.get(i)));
59.535 + }
59.536 +
59.537 + /**
59.538 + * Swaps the two specified elements in the specified array.
59.539 + */
59.540 + private static void swap(Object[] arr, int i, int j) {
59.541 + Object tmp = arr[i];
59.542 + arr[i] = arr[j];
59.543 + arr[j] = tmp;
59.544 + }
59.545 +
59.546 + /**
59.547 + * Replaces all of the elements of the specified list with the specified
59.548 + * element. <p>
59.549 + *
59.550 + * This method runs in linear time.
59.551 + *
59.552 + * @param list the list to be filled with the specified element.
59.553 + * @param obj The element with which to fill the specified list.
59.554 + * @throws UnsupportedOperationException if the specified list or its
59.555 + * list-iterator does not support the <tt>set</tt> operation.
59.556 + */
59.557 + public static <T> void fill(List<? super T> list, T obj) {
59.558 + int size = list.size();
59.559 +
59.560 + if (size < FILL_THRESHOLD || list instanceof RandomAccess) {
59.561 + for (int i=0; i<size; i++)
59.562 + list.set(i, obj);
59.563 + } else {
59.564 + ListIterator<? super T> itr = list.listIterator();
59.565 + for (int i=0; i<size; i++) {
59.566 + itr.next();
59.567 + itr.set(obj);
59.568 + }
59.569 + }
59.570 + }
59.571 +
59.572 + /**
59.573 + * Copies all of the elements from one list into another. After the
59.574 + * operation, the index of each copied element in the destination list
59.575 + * will be identical to its index in the source list. The destination
59.576 + * list must be at least as long as the source list. If it is longer, the
59.577 + * remaining elements in the destination list are unaffected. <p>
59.578 + *
59.579 + * This method runs in linear time.
59.580 + *
59.581 + * @param dest The destination list.
59.582 + * @param src The source list.
59.583 + * @throws IndexOutOfBoundsException if the destination list is too small
59.584 + * to contain the entire source List.
59.585 + * @throws UnsupportedOperationException if the destination list's
59.586 + * list-iterator does not support the <tt>set</tt> operation.
59.587 + */
59.588 + public static <T> void copy(List<? super T> dest, List<? extends T> src) {
59.589 + int srcSize = src.size();
59.590 + if (srcSize > dest.size())
59.591 + throw new IndexOutOfBoundsException("Source does not fit in dest");
59.592 +
59.593 + if (srcSize < COPY_THRESHOLD ||
59.594 + (src instanceof RandomAccess && dest instanceof RandomAccess)) {
59.595 + for (int i=0; i<srcSize; i++)
59.596 + dest.set(i, src.get(i));
59.597 + } else {
59.598 + ListIterator<? super T> di=dest.listIterator();
59.599 + ListIterator<? extends T> si=src.listIterator();
59.600 + for (int i=0; i<srcSize; i++) {
59.601 + di.next();
59.602 + di.set(si.next());
59.603 + }
59.604 + }
59.605 + }
59.606 +
59.607 + /**
59.608 + * Returns the minimum element of the given collection, according to the
59.609 + * <i>natural ordering</i> of its elements. All elements in the
59.610 + * collection must implement the <tt>Comparable</tt> interface.
59.611 + * Furthermore, all elements in the collection must be <i>mutually
59.612 + * comparable</i> (that is, <tt>e1.compareTo(e2)</tt> must not throw a
59.613 + * <tt>ClassCastException</tt> for any elements <tt>e1</tt> and
59.614 + * <tt>e2</tt> in the collection).<p>
59.615 + *
59.616 + * This method iterates over the entire collection, hence it requires
59.617 + * time proportional to the size of the collection.
59.618 + *
59.619 + * @param coll the collection whose minimum element is to be determined.
59.620 + * @return the minimum element of the given collection, according
59.621 + * to the <i>natural ordering</i> of its elements.
59.622 + * @throws ClassCastException if the collection contains elements that are
59.623 + * not <i>mutually comparable</i> (for example, strings and
59.624 + * integers).
59.625 + * @throws NoSuchElementException if the collection is empty.
59.626 + * @see Comparable
59.627 + */
59.628 + public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll) {
59.629 + Iterator<? extends T> i = coll.iterator();
59.630 + T candidate = i.next();
59.631 +
59.632 + while (i.hasNext()) {
59.633 + T next = i.next();
59.634 + if (next.compareTo(candidate) < 0)
59.635 + candidate = next;
59.636 + }
59.637 + return candidate;
59.638 + }
59.639 +
59.640 + /**
59.641 + * Returns the minimum element of the given collection, according to the
59.642 + * order induced by the specified comparator. All elements in the
59.643 + * collection must be <i>mutually comparable</i> by the specified
59.644 + * comparator (that is, <tt>comp.compare(e1, e2)</tt> must not throw a
59.645 + * <tt>ClassCastException</tt> for any elements <tt>e1</tt> and
59.646 + * <tt>e2</tt> in the collection).<p>
59.647 + *
59.648 + * This method iterates over the entire collection, hence it requires
59.649 + * time proportional to the size of the collection.
59.650 + *
59.651 + * @param coll the collection whose minimum element is to be determined.
59.652 + * @param comp the comparator with which to determine the minimum element.
59.653 + * A <tt>null</tt> value indicates that the elements' <i>natural
59.654 + * ordering</i> should be used.
59.655 + * @return the minimum element of the given collection, according
59.656 + * to the specified comparator.
59.657 + * @throws ClassCastException if the collection contains elements that are
59.658 + * not <i>mutually comparable</i> using the specified comparator.
59.659 + * @throws NoSuchElementException if the collection is empty.
59.660 + * @see Comparable
59.661 + */
59.662 + public static <T> T min(Collection<? extends T> coll, Comparator<? super T> comp) {
59.663 + if (comp==null)
59.664 + return (T)min((Collection<SelfComparable>) (Collection) coll);
59.665 +
59.666 + Iterator<? extends T> i = coll.iterator();
59.667 + T candidate = i.next();
59.668 +
59.669 + while (i.hasNext()) {
59.670 + T next = i.next();
59.671 + if (comp.compare(next, candidate) < 0)
59.672 + candidate = next;
59.673 + }
59.674 + return candidate;
59.675 + }
59.676 +
59.677 + /**
59.678 + * Returns the maximum element of the given collection, according to the
59.679 + * <i>natural ordering</i> of its elements. All elements in the
59.680 + * collection must implement the <tt>Comparable</tt> interface.
59.681 + * Furthermore, all elements in the collection must be <i>mutually
59.682 + * comparable</i> (that is, <tt>e1.compareTo(e2)</tt> must not throw a
59.683 + * <tt>ClassCastException</tt> for any elements <tt>e1</tt> and
59.684 + * <tt>e2</tt> in the collection).<p>
59.685 + *
59.686 + * This method iterates over the entire collection, hence it requires
59.687 + * time proportional to the size of the collection.
59.688 + *
59.689 + * @param coll the collection whose maximum element is to be determined.
59.690 + * @return the maximum element of the given collection, according
59.691 + * to the <i>natural ordering</i> of its elements.
59.692 + * @throws ClassCastException if the collection contains elements that are
59.693 + * not <i>mutually comparable</i> (for example, strings and
59.694 + * integers).
59.695 + * @throws NoSuchElementException if the collection is empty.
59.696 + * @see Comparable
59.697 + */
59.698 + public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) {
59.699 + Iterator<? extends T> i = coll.iterator();
59.700 + T candidate = i.next();
59.701 +
59.702 + while (i.hasNext()) {
59.703 + T next = i.next();
59.704 + if (next.compareTo(candidate) > 0)
59.705 + candidate = next;
59.706 + }
59.707 + return candidate;
59.708 + }
59.709 +
59.710 + /**
59.711 + * Returns the maximum element of the given collection, according to the
59.712 + * order induced by the specified comparator. All elements in the
59.713 + * collection must be <i>mutually comparable</i> by the specified
59.714 + * comparator (that is, <tt>comp.compare(e1, e2)</tt> must not throw a
59.715 + * <tt>ClassCastException</tt> for any elements <tt>e1</tt> and
59.716 + * <tt>e2</tt> in the collection).<p>
59.717 + *
59.718 + * This method iterates over the entire collection, hence it requires
59.719 + * time proportional to the size of the collection.
59.720 + *
59.721 + * @param coll the collection whose maximum element is to be determined.
59.722 + * @param comp the comparator with which to determine the maximum element.
59.723 + * A <tt>null</tt> value indicates that the elements' <i>natural
59.724 + * ordering</i> should be used.
59.725 + * @return the maximum element of the given collection, according
59.726 + * to the specified comparator.
59.727 + * @throws ClassCastException if the collection contains elements that are
59.728 + * not <i>mutually comparable</i> using the specified comparator.
59.729 + * @throws NoSuchElementException if the collection is empty.
59.730 + * @see Comparable
59.731 + */
59.732 + public static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp) {
59.733 + if (comp==null)
59.734 + return (T)max((Collection<SelfComparable>) (Collection) coll);
59.735 +
59.736 + Iterator<? extends T> i = coll.iterator();
59.737 + T candidate = i.next();
59.738 +
59.739 + while (i.hasNext()) {
59.740 + T next = i.next();
59.741 + if (comp.compare(next, candidate) > 0)
59.742 + candidate = next;
59.743 + }
59.744 + return candidate;
59.745 + }
59.746 +
59.747 + /**
59.748 + * Rotates the elements in the specified list by the specified distance.
59.749 + * After calling this method, the element at index <tt>i</tt> will be
59.750 + * the element previously at index <tt>(i - distance)</tt> mod
59.751 + * <tt>list.size()</tt>, for all values of <tt>i</tt> between <tt>0</tt>
59.752 + * and <tt>list.size()-1</tt>, inclusive. (This method has no effect on
59.753 + * the size of the list.)
59.754 + *
59.755 + * <p>For example, suppose <tt>list</tt> comprises<tt> [t, a, n, k, s]</tt>.
59.756 + * After invoking <tt>Collections.rotate(list, 1)</tt> (or
59.757 + * <tt>Collections.rotate(list, -4)</tt>), <tt>list</tt> will comprise
59.758 + * <tt>[s, t, a, n, k]</tt>.
59.759 + *
59.760 + * <p>Note that this method can usefully be applied to sublists to
59.761 + * move one or more elements within a list while preserving the
59.762 + * order of the remaining elements. For example, the following idiom
59.763 + * moves the element at index <tt>j</tt> forward to position
59.764 + * <tt>k</tt> (which must be greater than or equal to <tt>j</tt>):
59.765 + * <pre>
59.766 + * Collections.rotate(list.subList(j, k+1), -1);
59.767 + * </pre>
59.768 + * To make this concrete, suppose <tt>list</tt> comprises
59.769 + * <tt>[a, b, c, d, e]</tt>. To move the element at index <tt>1</tt>
59.770 + * (<tt>b</tt>) forward two positions, perform the following invocation:
59.771 + * <pre>
59.772 + * Collections.rotate(l.subList(1, 4), -1);
59.773 + * </pre>
59.774 + * The resulting list is <tt>[a, c, d, b, e]</tt>.
59.775 + *
59.776 + * <p>To move more than one element forward, increase the absolute value
59.777 + * of the rotation distance. To move elements backward, use a positive
59.778 + * shift distance.
59.779 + *
59.780 + * <p>If the specified list is small or implements the {@link
59.781 + * RandomAccess} interface, this implementation exchanges the first
59.782 + * element into the location it should go, and then repeatedly exchanges
59.783 + * the displaced element into the location it should go until a displaced
59.784 + * element is swapped into the first element. If necessary, the process
59.785 + * is repeated on the second and successive elements, until the rotation
59.786 + * is complete. If the specified list is large and doesn't implement the
59.787 + * <tt>RandomAccess</tt> interface, this implementation breaks the
59.788 + * list into two sublist views around index <tt>-distance mod size</tt>.
59.789 + * Then the {@link #reverse(List)} method is invoked on each sublist view,
59.790 + * and finally it is invoked on the entire list. For a more complete
59.791 + * description of both algorithms, see Section 2.3 of Jon Bentley's
59.792 + * <i>Programming Pearls</i> (Addison-Wesley, 1986).
59.793 + *
59.794 + * @param list the list to be rotated.
59.795 + * @param distance the distance to rotate the list. There are no
59.796 + * constraints on this value; it may be zero, negative, or
59.797 + * greater than <tt>list.size()</tt>.
59.798 + * @throws UnsupportedOperationException if the specified list or
59.799 + * its list-iterator does not support the <tt>set</tt> operation.
59.800 + * @since 1.4
59.801 + */
59.802 + public static void rotate(List<?> list, int distance) {
59.803 + if (list instanceof RandomAccess || list.size() < ROTATE_THRESHOLD)
59.804 + rotate1(list, distance);
59.805 + else
59.806 + rotate2(list, distance);
59.807 + }
59.808 +
59.809 + private static <T> void rotate1(List<T> list, int distance) {
59.810 + int size = list.size();
59.811 + if (size == 0)
59.812 + return;
59.813 + distance = distance % size;
59.814 + if (distance < 0)
59.815 + distance += size;
59.816 + if (distance == 0)
59.817 + return;
59.818 +
59.819 + for (int cycleStart = 0, nMoved = 0; nMoved != size; cycleStart++) {
59.820 + T displaced = list.get(cycleStart);
59.821 + int i = cycleStart;
59.822 + do {
59.823 + i += distance;
59.824 + if (i >= size)
59.825 + i -= size;
59.826 + displaced = list.set(i, displaced);
59.827 + nMoved ++;
59.828 + } while (i != cycleStart);
59.829 + }
59.830 + }
59.831 +
59.832 + private static void rotate2(List<?> list, int distance) {
59.833 + int size = list.size();
59.834 + if (size == 0)
59.835 + return;
59.836 + int mid = -distance % size;
59.837 + if (mid < 0)
59.838 + mid += size;
59.839 + if (mid == 0)
59.840 + return;
59.841 +
59.842 + reverse(list.subList(0, mid));
59.843 + reverse(list.subList(mid, size));
59.844 + reverse(list);
59.845 + }
59.846 +
59.847 + /**
59.848 + * Replaces all occurrences of one specified value in a list with another.
59.849 + * More formally, replaces with <tt>newVal</tt> each element <tt>e</tt>
59.850 + * in <tt>list</tt> such that
59.851 + * <tt>(oldVal==null ? e==null : oldVal.equals(e))</tt>.
59.852 + * (This method has no effect on the size of the list.)
59.853 + *
59.854 + * @param list the list in which replacement is to occur.
59.855 + * @param oldVal the old value to be replaced.
59.856 + * @param newVal the new value with which <tt>oldVal</tt> is to be
59.857 + * replaced.
59.858 + * @return <tt>true</tt> if <tt>list</tt> contained one or more elements
59.859 + * <tt>e</tt> such that
59.860 + * <tt>(oldVal==null ? e==null : oldVal.equals(e))</tt>.
59.861 + * @throws UnsupportedOperationException if the specified list or
59.862 + * its list-iterator does not support the <tt>set</tt> operation.
59.863 + * @since 1.4
59.864 + */
59.865 + public static <T> boolean replaceAll(List<T> list, T oldVal, T newVal) {
59.866 + boolean result = false;
59.867 + int size = list.size();
59.868 + if (size < REPLACEALL_THRESHOLD || list instanceof RandomAccess) {
59.869 + if (oldVal==null) {
59.870 + for (int i=0; i<size; i++) {
59.871 + if (list.get(i)==null) {
59.872 + list.set(i, newVal);
59.873 + result = true;
59.874 + }
59.875 + }
59.876 + } else {
59.877 + for (int i=0; i<size; i++) {
59.878 + if (oldVal.equals(list.get(i))) {
59.879 + list.set(i, newVal);
59.880 + result = true;
59.881 + }
59.882 + }
59.883 + }
59.884 + } else {
59.885 + ListIterator<T> itr=list.listIterator();
59.886 + if (oldVal==null) {
59.887 + for (int i=0; i<size; i++) {
59.888 + if (itr.next()==null) {
59.889 + itr.set(newVal);
59.890 + result = true;
59.891 + }
59.892 + }
59.893 + } else {
59.894 + for (int i=0; i<size; i++) {
59.895 + if (oldVal.equals(itr.next())) {
59.896 + itr.set(newVal);
59.897 + result = true;
59.898 + }
59.899 + }
59.900 + }
59.901 + }
59.902 + return result;
59.903 + }
59.904 +
59.905 + /**
59.906 + * Returns the starting position of the first occurrence of the specified
59.907 + * target list within the specified source list, or -1 if there is no
59.908 + * such occurrence. More formally, returns the lowest index <tt>i</tt>
59.909 + * such that <tt>source.subList(i, i+target.size()).equals(target)</tt>,
59.910 + * or -1 if there is no such index. (Returns -1 if
59.911 + * <tt>target.size() > source.size()</tt>.)
59.912 + *
59.913 + * <p>This implementation uses the "brute force" technique of scanning
59.914 + * over the source list, looking for a match with the target at each
59.915 + * location in turn.
59.916 + *
59.917 + * @param source the list in which to search for the first occurrence
59.918 + * of <tt>target</tt>.
59.919 + * @param target the list to search for as a subList of <tt>source</tt>.
59.920 + * @return the starting position of the first occurrence of the specified
59.921 + * target list within the specified source list, or -1 if there
59.922 + * is no such occurrence.
59.923 + * @since 1.4
59.924 + */
59.925 + public static int indexOfSubList(List<?> source, List<?> target) {
59.926 + int sourceSize = source.size();
59.927 + int targetSize = target.size();
59.928 + int maxCandidate = sourceSize - targetSize;
59.929 +
59.930 + if (sourceSize < INDEXOFSUBLIST_THRESHOLD ||
59.931 + (source instanceof RandomAccess&&target instanceof RandomAccess)) {
59.932 + nextCand:
59.933 + for (int candidate = 0; candidate <= maxCandidate; candidate++) {
59.934 + for (int i=0, j=candidate; i<targetSize; i++, j++)
59.935 + if (!eq(target.get(i), source.get(j)))
59.936 + continue nextCand; // Element mismatch, try next cand
59.937 + return candidate; // All elements of candidate matched target
59.938 + }
59.939 + } else { // Iterator version of above algorithm
59.940 + ListIterator<?> si = source.listIterator();
59.941 + nextCand:
59.942 + for (int candidate = 0; candidate <= maxCandidate; candidate++) {
59.943 + ListIterator<?> ti = target.listIterator();
59.944 + for (int i=0; i<targetSize; i++) {
59.945 + if (!eq(ti.next(), si.next())) {
59.946 + // Back up source iterator to next candidate
59.947 + for (int j=0; j<i; j++)
59.948 + si.previous();
59.949 + continue nextCand;
59.950 + }
59.951 + }
59.952 + return candidate;
59.953 + }
59.954 + }
59.955 + return -1; // No candidate matched the target
59.956 + }
59.957 +
59.958 + /**
59.959 + * Returns the starting position of the last occurrence of the specified
59.960 + * target list within the specified source list, or -1 if there is no such
59.961 + * occurrence. More formally, returns the highest index <tt>i</tt>
59.962 + * such that <tt>source.subList(i, i+target.size()).equals(target)</tt>,
59.963 + * or -1 if there is no such index. (Returns -1 if
59.964 + * <tt>target.size() > source.size()</tt>.)
59.965 + *
59.966 + * <p>This implementation uses the "brute force" technique of iterating
59.967 + * over the source list, looking for a match with the target at each
59.968 + * location in turn.
59.969 + *
59.970 + * @param source the list in which to search for the last occurrence
59.971 + * of <tt>target</tt>.
59.972 + * @param target the list to search for as a subList of <tt>source</tt>.
59.973 + * @return the starting position of the last occurrence of the specified
59.974 + * target list within the specified source list, or -1 if there
59.975 + * is no such occurrence.
59.976 + * @since 1.4
59.977 + */
59.978 + public static int lastIndexOfSubList(List<?> source, List<?> target) {
59.979 + int sourceSize = source.size();
59.980 + int targetSize = target.size();
59.981 + int maxCandidate = sourceSize - targetSize;
59.982 +
59.983 + if (sourceSize < INDEXOFSUBLIST_THRESHOLD ||
59.984 + source instanceof RandomAccess) { // Index access version
59.985 + nextCand:
59.986 + for (int candidate = maxCandidate; candidate >= 0; candidate--) {
59.987 + for (int i=0, j=candidate; i<targetSize; i++, j++)
59.988 + if (!eq(target.get(i), source.get(j)))
59.989 + continue nextCand; // Element mismatch, try next cand
59.990 + return candidate; // All elements of candidate matched target
59.991 + }
59.992 + } else { // Iterator version of above algorithm
59.993 + if (maxCandidate < 0)
59.994 + return -1;
59.995 + ListIterator<?> si = source.listIterator(maxCandidate);
59.996 + nextCand:
59.997 + for (int candidate = maxCandidate; candidate >= 0; candidate--) {
59.998 + ListIterator<?> ti = target.listIterator();
59.999 + for (int i=0; i<targetSize; i++) {
59.1000 + if (!eq(ti.next(), si.next())) {
59.1001 + if (candidate != 0) {
59.1002 + // Back up source iterator to next candidate
59.1003 + for (int j=0; j<=i+1; j++)
59.1004 + si.previous();
59.1005 + }
59.1006 + continue nextCand;
59.1007 + }
59.1008 + }
59.1009 + return candidate;
59.1010 + }
59.1011 + }
59.1012 + return -1; // No candidate matched the target
59.1013 + }
59.1014 +
59.1015 +
59.1016 + // Unmodifiable Wrappers
59.1017 +
59.1018 + /**
59.1019 + * Returns an unmodifiable view of the specified collection. This method
59.1020 + * allows modules to provide users with "read-only" access to internal
59.1021 + * collections. Query operations on the returned collection "read through"
59.1022 + * to the specified collection, and attempts to modify the returned
59.1023 + * collection, whether direct or via its iterator, result in an
59.1024 + * <tt>UnsupportedOperationException</tt>.<p>
59.1025 + *
59.1026 + * The returned collection does <i>not</i> pass the hashCode and equals
59.1027 + * operations through to the backing collection, but relies on
59.1028 + * <tt>Object</tt>'s <tt>equals</tt> and <tt>hashCode</tt> methods. This
59.1029 + * is necessary to preserve the contracts of these operations in the case
59.1030 + * that the backing collection is a set or a list.<p>
59.1031 + *
59.1032 + * The returned collection will be serializable if the specified collection
59.1033 + * is serializable.
59.1034 + *
59.1035 + * @param c the collection for which an unmodifiable view is to be
59.1036 + * returned.
59.1037 + * @return an unmodifiable view of the specified collection.
59.1038 + */
59.1039 + public static <T> Collection<T> unmodifiableCollection(Collection<? extends T> c) {
59.1040 + return new UnmodifiableCollection<>(c);
59.1041 + }
59.1042 +
59.1043 + /**
59.1044 + * @serial include
59.1045 + */
59.1046 + static class UnmodifiableCollection<E> implements Collection<E>, Serializable {
59.1047 + private static final long serialVersionUID = 1820017752578914078L;
59.1048 +
59.1049 + final Collection<? extends E> c;
59.1050 +
59.1051 + UnmodifiableCollection(Collection<? extends E> c) {
59.1052 + if (c==null)
59.1053 + throw new NullPointerException();
59.1054 + this.c = c;
59.1055 + }
59.1056 +
59.1057 + public int size() {return c.size();}
59.1058 + public boolean isEmpty() {return c.isEmpty();}
59.1059 + public boolean contains(Object o) {return c.contains(o);}
59.1060 + public Object[] toArray() {return c.toArray();}
59.1061 + public <T> T[] toArray(T[] a) {return c.toArray(a);}
59.1062 + public String toString() {return c.toString();}
59.1063 +
59.1064 + public Iterator<E> iterator() {
59.1065 + return new Iterator<E>() {
59.1066 + private final Iterator<? extends E> i = c.iterator();
59.1067 +
59.1068 + public boolean hasNext() {return i.hasNext();}
59.1069 + public E next() {return i.next();}
59.1070 + public void remove() {
59.1071 + throw new UnsupportedOperationException();
59.1072 + }
59.1073 + };
59.1074 + }
59.1075 +
59.1076 + public boolean add(E e) {
59.1077 + throw new UnsupportedOperationException();
59.1078 + }
59.1079 + public boolean remove(Object o) {
59.1080 + throw new UnsupportedOperationException();
59.1081 + }
59.1082 +
59.1083 + public boolean containsAll(Collection<?> coll) {
59.1084 + return c.containsAll(coll);
59.1085 + }
59.1086 + public boolean addAll(Collection<? extends E> coll) {
59.1087 + throw new UnsupportedOperationException();
59.1088 + }
59.1089 + public boolean removeAll(Collection<?> coll) {
59.1090 + throw new UnsupportedOperationException();
59.1091 + }
59.1092 + public boolean retainAll(Collection<?> coll) {
59.1093 + throw new UnsupportedOperationException();
59.1094 + }
59.1095 + public void clear() {
59.1096 + throw new UnsupportedOperationException();
59.1097 + }
59.1098 + }
59.1099 +
59.1100 + /**
59.1101 + * Returns an unmodifiable view of the specified set. This method allows
59.1102 + * modules to provide users with "read-only" access to internal sets.
59.1103 + * Query operations on the returned set "read through" to the specified
59.1104 + * set, and attempts to modify the returned set, whether direct or via its
59.1105 + * iterator, result in an <tt>UnsupportedOperationException</tt>.<p>
59.1106 + *
59.1107 + * The returned set will be serializable if the specified set
59.1108 + * is serializable.
59.1109 + *
59.1110 + * @param s the set for which an unmodifiable view is to be returned.
59.1111 + * @return an unmodifiable view of the specified set.
59.1112 + */
59.1113 + public static <T> Set<T> unmodifiableSet(Set<? extends T> s) {
59.1114 + return new UnmodifiableSet<>(s);
59.1115 + }
59.1116 +
59.1117 + /**
59.1118 + * @serial include
59.1119 + */
59.1120 + static class UnmodifiableSet<E> extends UnmodifiableCollection<E>
59.1121 + implements Set<E>, Serializable {
59.1122 + private static final long serialVersionUID = -9215047833775013803L;
59.1123 +
59.1124 + UnmodifiableSet(Set<? extends E> s) {super(s);}
59.1125 + public boolean equals(Object o) {return o == this || c.equals(o);}
59.1126 + public int hashCode() {return c.hashCode();}
59.1127 + }
59.1128 +
59.1129 + /**
59.1130 + * Returns an unmodifiable view of the specified sorted set. This method
59.1131 + * allows modules to provide users with "read-only" access to internal
59.1132 + * sorted sets. Query operations on the returned sorted set "read
59.1133 + * through" to the specified sorted set. Attempts to modify the returned
59.1134 + * sorted set, whether direct, via its iterator, or via its
59.1135 + * <tt>subSet</tt>, <tt>headSet</tt>, or <tt>tailSet</tt> views, result in
59.1136 + * an <tt>UnsupportedOperationException</tt>.<p>
59.1137 + *
59.1138 + * The returned sorted set will be serializable if the specified sorted set
59.1139 + * is serializable.
59.1140 + *
59.1141 + * @param s the sorted set for which an unmodifiable view is to be
59.1142 + * returned.
59.1143 + * @return an unmodifiable view of the specified sorted set.
59.1144 + */
59.1145 + public static <T> SortedSet<T> unmodifiableSortedSet(SortedSet<T> s) {
59.1146 + return new UnmodifiableSortedSet<>(s);
59.1147 + }
59.1148 +
59.1149 + /**
59.1150 + * @serial include
59.1151 + */
59.1152 + static class UnmodifiableSortedSet<E>
59.1153 + extends UnmodifiableSet<E>
59.1154 + implements SortedSet<E>, Serializable {
59.1155 + private static final long serialVersionUID = -4929149591599911165L;
59.1156 + private final SortedSet<E> ss;
59.1157 +
59.1158 + UnmodifiableSortedSet(SortedSet<E> s) {super(s); ss = s;}
59.1159 +
59.1160 + public Comparator<? super E> comparator() {return ss.comparator();}
59.1161 +
59.1162 + public SortedSet<E> subSet(E fromElement, E toElement) {
59.1163 + return new UnmodifiableSortedSet<>(ss.subSet(fromElement,toElement));
59.1164 + }
59.1165 + public SortedSet<E> headSet(E toElement) {
59.1166 + return new UnmodifiableSortedSet<>(ss.headSet(toElement));
59.1167 + }
59.1168 + public SortedSet<E> tailSet(E fromElement) {
59.1169 + return new UnmodifiableSortedSet<>(ss.tailSet(fromElement));
59.1170 + }
59.1171 +
59.1172 + public E first() {return ss.first();}
59.1173 + public E last() {return ss.last();}
59.1174 + }
59.1175 +
59.1176 + /**
59.1177 + * Returns an unmodifiable view of the specified list. This method allows
59.1178 + * modules to provide users with "read-only" access to internal
59.1179 + * lists. Query operations on the returned list "read through" to the
59.1180 + * specified list, and attempts to modify the returned list, whether
59.1181 + * direct or via its iterator, result in an
59.1182 + * <tt>UnsupportedOperationException</tt>.<p>
59.1183 + *
59.1184 + * The returned list will be serializable if the specified list
59.1185 + * is serializable. Similarly, the returned list will implement
59.1186 + * {@link RandomAccess} if the specified list does.
59.1187 + *
59.1188 + * @param list the list for which an unmodifiable view is to be returned.
59.1189 + * @return an unmodifiable view of the specified list.
59.1190 + */
59.1191 + public static <T> List<T> unmodifiableList(List<? extends T> list) {
59.1192 + return (list instanceof RandomAccess ?
59.1193 + new UnmodifiableRandomAccessList<>(list) :
59.1194 + new UnmodifiableList<>(list));
59.1195 + }
59.1196 +
59.1197 + /**
59.1198 + * @serial include
59.1199 + */
59.1200 + static class UnmodifiableList<E> extends UnmodifiableCollection<E>
59.1201 + implements List<E> {
59.1202 + private static final long serialVersionUID = -283967356065247728L;
59.1203 + final List<? extends E> list;
59.1204 +
59.1205 + UnmodifiableList(List<? extends E> list) {
59.1206 + super(list);
59.1207 + this.list = list;
59.1208 + }
59.1209 +
59.1210 + public boolean equals(Object o) {return o == this || list.equals(o);}
59.1211 + public int hashCode() {return list.hashCode();}
59.1212 +
59.1213 + public E get(int index) {return list.get(index);}
59.1214 + public E set(int index, E element) {
59.1215 + throw new UnsupportedOperationException();
59.1216 + }
59.1217 + public void add(int index, E element) {
59.1218 + throw new UnsupportedOperationException();
59.1219 + }
59.1220 + public E remove(int index) {
59.1221 + throw new UnsupportedOperationException();
59.1222 + }
59.1223 + public int indexOf(Object o) {return list.indexOf(o);}
59.1224 + public int lastIndexOf(Object o) {return list.lastIndexOf(o);}
59.1225 + public boolean addAll(int index, Collection<? extends E> c) {
59.1226 + throw new UnsupportedOperationException();
59.1227 + }
59.1228 + public ListIterator<E> listIterator() {return listIterator(0);}
59.1229 +
59.1230 + public ListIterator<E> listIterator(final int index) {
59.1231 + return new ListIterator<E>() {
59.1232 + private final ListIterator<? extends E> i
59.1233 + = list.listIterator(index);
59.1234 +
59.1235 + public boolean hasNext() {return i.hasNext();}
59.1236 + public E next() {return i.next();}
59.1237 + public boolean hasPrevious() {return i.hasPrevious();}
59.1238 + public E previous() {return i.previous();}
59.1239 + public int nextIndex() {return i.nextIndex();}
59.1240 + public int previousIndex() {return i.previousIndex();}
59.1241 +
59.1242 + public void remove() {
59.1243 + throw new UnsupportedOperationException();
59.1244 + }
59.1245 + public void set(E e) {
59.1246 + throw new UnsupportedOperationException();
59.1247 + }
59.1248 + public void add(E e) {
59.1249 + throw new UnsupportedOperationException();
59.1250 + }
59.1251 + };
59.1252 + }
59.1253 +
59.1254 + public List<E> subList(int fromIndex, int toIndex) {
59.1255 + return new UnmodifiableList<>(list.subList(fromIndex, toIndex));
59.1256 + }
59.1257 +
59.1258 + /**
59.1259 + * UnmodifiableRandomAccessList instances are serialized as
59.1260 + * UnmodifiableList instances to allow them to be deserialized
59.1261 + * in pre-1.4 JREs (which do not have UnmodifiableRandomAccessList).
59.1262 + * This method inverts the transformation. As a beneficial
59.1263 + * side-effect, it also grafts the RandomAccess marker onto
59.1264 + * UnmodifiableList instances that were serialized in pre-1.4 JREs.
59.1265 + *
59.1266 + * Note: Unfortunately, UnmodifiableRandomAccessList instances
59.1267 + * serialized in 1.4.1 and deserialized in 1.4 will become
59.1268 + * UnmodifiableList instances, as this method was missing in 1.4.
59.1269 + */
59.1270 + private Object readResolve() {
59.1271 + return (list instanceof RandomAccess
59.1272 + ? new UnmodifiableRandomAccessList<>(list)
59.1273 + : this);
59.1274 + }
59.1275 + }
59.1276 +
59.1277 + /**
59.1278 + * @serial include
59.1279 + */
59.1280 + static class UnmodifiableRandomAccessList<E> extends UnmodifiableList<E>
59.1281 + implements RandomAccess
59.1282 + {
59.1283 + UnmodifiableRandomAccessList(List<? extends E> list) {
59.1284 + super(list);
59.1285 + }
59.1286 +
59.1287 + public List<E> subList(int fromIndex, int toIndex) {
59.1288 + return new UnmodifiableRandomAccessList<>(
59.1289 + list.subList(fromIndex, toIndex));
59.1290 + }
59.1291 +
59.1292 + private static final long serialVersionUID = -2542308836966382001L;
59.1293 +
59.1294 + /**
59.1295 + * Allows instances to be deserialized in pre-1.4 JREs (which do
59.1296 + * not have UnmodifiableRandomAccessList). UnmodifiableList has
59.1297 + * a readResolve method that inverts this transformation upon
59.1298 + * deserialization.
59.1299 + */
59.1300 + private Object writeReplace() {
59.1301 + return new UnmodifiableList<>(list);
59.1302 + }
59.1303 + }
59.1304 +
59.1305 + /**
59.1306 + * Returns an unmodifiable view of the specified map. This method
59.1307 + * allows modules to provide users with "read-only" access to internal
59.1308 + * maps. Query operations on the returned map "read through"
59.1309 + * to the specified map, and attempts to modify the returned
59.1310 + * map, whether direct or via its collection views, result in an
59.1311 + * <tt>UnsupportedOperationException</tt>.<p>
59.1312 + *
59.1313 + * The returned map will be serializable if the specified map
59.1314 + * is serializable.
59.1315 + *
59.1316 + * @param m the map for which an unmodifiable view is to be returned.
59.1317 + * @return an unmodifiable view of the specified map.
59.1318 + */
59.1319 + public static <K,V> Map<K,V> unmodifiableMap(Map<? extends K, ? extends V> m) {
59.1320 + return new UnmodifiableMap<>(m);
59.1321 + }
59.1322 +
59.1323 + /**
59.1324 + * @serial include
59.1325 + */
59.1326 + private static class UnmodifiableMap<K,V> implements Map<K,V>, Serializable {
59.1327 + private static final long serialVersionUID = -1034234728574286014L;
59.1328 +
59.1329 + private final Map<? extends K, ? extends V> m;
59.1330 +
59.1331 + UnmodifiableMap(Map<? extends K, ? extends V> m) {
59.1332 + if (m==null)
59.1333 + throw new NullPointerException();
59.1334 + this.m = m;
59.1335 + }
59.1336 +
59.1337 + public int size() {return m.size();}
59.1338 + public boolean isEmpty() {return m.isEmpty();}
59.1339 + public boolean containsKey(Object key) {return m.containsKey(key);}
59.1340 + public boolean containsValue(Object val) {return m.containsValue(val);}
59.1341 + public V get(Object key) {return m.get(key);}
59.1342 +
59.1343 + public V put(K key, V value) {
59.1344 + throw new UnsupportedOperationException();
59.1345 + }
59.1346 + public V remove(Object key) {
59.1347 + throw new UnsupportedOperationException();
59.1348 + }
59.1349 + public void putAll(Map<? extends K, ? extends V> m) {
59.1350 + throw new UnsupportedOperationException();
59.1351 + }
59.1352 + public void clear() {
59.1353 + throw new UnsupportedOperationException();
59.1354 + }
59.1355 +
59.1356 + private transient Set<K> keySet = null;
59.1357 + private transient Set<Map.Entry<K,V>> entrySet = null;
59.1358 + private transient Collection<V> values = null;
59.1359 +
59.1360 + public Set<K> keySet() {
59.1361 + if (keySet==null)
59.1362 + keySet = unmodifiableSet(m.keySet());
59.1363 + return keySet;
59.1364 + }
59.1365 +
59.1366 + public Set<Map.Entry<K,V>> entrySet() {
59.1367 + if (entrySet==null)
59.1368 + entrySet = new UnmodifiableEntrySet<>(m.entrySet());
59.1369 + return entrySet;
59.1370 + }
59.1371 +
59.1372 + public Collection<V> values() {
59.1373 + if (values==null)
59.1374 + values = unmodifiableCollection(m.values());
59.1375 + return values;
59.1376 + }
59.1377 +
59.1378 + public boolean equals(Object o) {return o == this || m.equals(o);}
59.1379 + public int hashCode() {return m.hashCode();}
59.1380 + public String toString() {return m.toString();}
59.1381 +
59.1382 + /**
59.1383 + * We need this class in addition to UnmodifiableSet as
59.1384 + * Map.Entries themselves permit modification of the backing Map
59.1385 + * via their setValue operation. This class is subtle: there are
59.1386 + * many possible attacks that must be thwarted.
59.1387 + *
59.1388 + * @serial include
59.1389 + */
59.1390 + static class UnmodifiableEntrySet<K,V>
59.1391 + extends UnmodifiableSet<Map.Entry<K,V>> {
59.1392 + private static final long serialVersionUID = 7854390611657943733L;
59.1393 +
59.1394 + UnmodifiableEntrySet(Set<? extends Map.Entry<? extends K, ? extends V>> s) {
59.1395 + super((Set)s);
59.1396 + }
59.1397 + public Iterator<Map.Entry<K,V>> iterator() {
59.1398 + return new Iterator<Map.Entry<K,V>>() {
59.1399 + private final Iterator<? extends Map.Entry<? extends K, ? extends V>> i = c.iterator();
59.1400 +
59.1401 + public boolean hasNext() {
59.1402 + return i.hasNext();
59.1403 + }
59.1404 + public Map.Entry<K,V> next() {
59.1405 + return new UnmodifiableEntry<>(i.next());
59.1406 + }
59.1407 + public void remove() {
59.1408 + throw new UnsupportedOperationException();
59.1409 + }
59.1410 + };
59.1411 + }
59.1412 +
59.1413 + public Object[] toArray() {
59.1414 + Object[] a = c.toArray();
59.1415 + for (int i=0; i<a.length; i++)
59.1416 + a[i] = new UnmodifiableEntry<>((Map.Entry<K,V>)a[i]);
59.1417 + return a;
59.1418 + }
59.1419 +
59.1420 + public <T> T[] toArray(T[] a) {
59.1421 + // We don't pass a to c.toArray, to avoid window of
59.1422 + // vulnerability wherein an unscrupulous multithreaded client
59.1423 + // could get his hands on raw (unwrapped) Entries from c.
59.1424 + Object[] arr = c.toArray(a.length==0 ? a : Arrays.copyOf(a, 0));
59.1425 +
59.1426 + for (int i=0; i<arr.length; i++)
59.1427 + arr[i] = new UnmodifiableEntry<>((Map.Entry<K,V>)arr[i]);
59.1428 +
59.1429 + if (arr.length > a.length)
59.1430 + return (T[])arr;
59.1431 +
59.1432 + System.arraycopy(arr, 0, a, 0, arr.length);
59.1433 + if (a.length > arr.length)
59.1434 + a[arr.length] = null;
59.1435 + return a;
59.1436 + }
59.1437 +
59.1438 + /**
59.1439 + * This method is overridden to protect the backing set against
59.1440 + * an object with a nefarious equals function that senses
59.1441 + * that the equality-candidate is Map.Entry and calls its
59.1442 + * setValue method.
59.1443 + */
59.1444 + public boolean contains(Object o) {
59.1445 + if (!(o instanceof Map.Entry))
59.1446 + return false;
59.1447 + return c.contains(
59.1448 + new UnmodifiableEntry<>((Map.Entry<?,?>) o));
59.1449 + }
59.1450 +
59.1451 + /**
59.1452 + * The next two methods are overridden to protect against
59.1453 + * an unscrupulous List whose contains(Object o) method senses
59.1454 + * when o is a Map.Entry, and calls o.setValue.
59.1455 + */
59.1456 + public boolean containsAll(Collection<?> coll) {
59.1457 + for (Object e : coll) {
59.1458 + if (!contains(e)) // Invokes safe contains() above
59.1459 + return false;
59.1460 + }
59.1461 + return true;
59.1462 + }
59.1463 + public boolean equals(Object o) {
59.1464 + if (o == this)
59.1465 + return true;
59.1466 +
59.1467 + if (!(o instanceof Set))
59.1468 + return false;
59.1469 + Set s = (Set) o;
59.1470 + if (s.size() != c.size())
59.1471 + return false;
59.1472 + return containsAll(s); // Invokes safe containsAll() above
59.1473 + }
59.1474 +
59.1475 + /**
59.1476 + * This "wrapper class" serves two purposes: it prevents
59.1477 + * the client from modifying the backing Map, by short-circuiting
59.1478 + * the setValue method, and it protects the backing Map against
59.1479 + * an ill-behaved Map.Entry that attempts to modify another
59.1480 + * Map Entry when asked to perform an equality check.
59.1481 + */
59.1482 + private static class UnmodifiableEntry<K,V> implements Map.Entry<K,V> {
59.1483 + private Map.Entry<? extends K, ? extends V> e;
59.1484 +
59.1485 + UnmodifiableEntry(Map.Entry<? extends K, ? extends V> e) {this.e = e;}
59.1486 +
59.1487 + public K getKey() {return e.getKey();}
59.1488 + public V getValue() {return e.getValue();}
59.1489 + public V setValue(V value) {
59.1490 + throw new UnsupportedOperationException();
59.1491 + }
59.1492 + public int hashCode() {return e.hashCode();}
59.1493 + public boolean equals(Object o) {
59.1494 + if (!(o instanceof Map.Entry))
59.1495 + return false;
59.1496 + Map.Entry t = (Map.Entry)o;
59.1497 + return eq(e.getKey(), t.getKey()) &&
59.1498 + eq(e.getValue(), t.getValue());
59.1499 + }
59.1500 + public String toString() {return e.toString();}
59.1501 + }
59.1502 + }
59.1503 + }
59.1504 +
59.1505 + /**
59.1506 + * Returns an unmodifiable view of the specified sorted map. This method
59.1507 + * allows modules to provide users with "read-only" access to internal
59.1508 + * sorted maps. Query operations on the returned sorted map "read through"
59.1509 + * to the specified sorted map. Attempts to modify the returned
59.1510 + * sorted map, whether direct, via its collection views, or via its
59.1511 + * <tt>subMap</tt>, <tt>headMap</tt>, or <tt>tailMap</tt> views, result in
59.1512 + * an <tt>UnsupportedOperationException</tt>.<p>
59.1513 + *
59.1514 + * The returned sorted map will be serializable if the specified sorted map
59.1515 + * is serializable.
59.1516 + *
59.1517 + * @param m the sorted map for which an unmodifiable view is to be
59.1518 + * returned.
59.1519 + * @return an unmodifiable view of the specified sorted map.
59.1520 + */
59.1521 + public static <K,V> SortedMap<K,V> unmodifiableSortedMap(SortedMap<K, ? extends V> m) {
59.1522 + return new UnmodifiableSortedMap<>(m);
59.1523 + }
59.1524 +
59.1525 + /**
59.1526 + * @serial include
59.1527 + */
59.1528 + static class UnmodifiableSortedMap<K,V>
59.1529 + extends UnmodifiableMap<K,V>
59.1530 + implements SortedMap<K,V>, Serializable {
59.1531 + private static final long serialVersionUID = -8806743815996713206L;
59.1532 +
59.1533 + private final SortedMap<K, ? extends V> sm;
59.1534 +
59.1535 + UnmodifiableSortedMap(SortedMap<K, ? extends V> m) {super(m); sm = m;}
59.1536 +
59.1537 + public Comparator<? super K> comparator() {return sm.comparator();}
59.1538 +
59.1539 + public SortedMap<K,V> subMap(K fromKey, K toKey) {
59.1540 + return new UnmodifiableSortedMap<>(sm.subMap(fromKey, toKey));
59.1541 + }
59.1542 + public SortedMap<K,V> headMap(K toKey) {
59.1543 + return new UnmodifiableSortedMap<>(sm.headMap(toKey));
59.1544 + }
59.1545 + public SortedMap<K,V> tailMap(K fromKey) {
59.1546 + return new UnmodifiableSortedMap<>(sm.tailMap(fromKey));
59.1547 + }
59.1548 +
59.1549 + public K firstKey() {return sm.firstKey();}
59.1550 + public K lastKey() {return sm.lastKey();}
59.1551 + }
59.1552 +
59.1553 +
59.1554 + // Synch Wrappers
59.1555 +
59.1556 + /**
59.1557 + * Returns a synchronized (thread-safe) collection backed by the specified
59.1558 + * collection. In order to guarantee serial access, it is critical that
59.1559 + * <strong>all</strong> access to the backing collection is accomplished
59.1560 + * through the returned collection.<p>
59.1561 + *
59.1562 + * It is imperative that the user manually synchronize on the returned
59.1563 + * collection when iterating over it:
59.1564 + * <pre>
59.1565 + * Collection c = Collections.synchronizedCollection(myCollection);
59.1566 + * ...
59.1567 + * synchronized (c) {
59.1568 + * Iterator i = c.iterator(); // Must be in the synchronized block
59.1569 + * while (i.hasNext())
59.1570 + * foo(i.next());
59.1571 + * }
59.1572 + * </pre>
59.1573 + * Failure to follow this advice may result in non-deterministic behavior.
59.1574 + *
59.1575 + * <p>The returned collection does <i>not</i> pass the <tt>hashCode</tt>
59.1576 + * and <tt>equals</tt> operations through to the backing collection, but
59.1577 + * relies on <tt>Object</tt>'s equals and hashCode methods. This is
59.1578 + * necessary to preserve the contracts of these operations in the case
59.1579 + * that the backing collection is a set or a list.<p>
59.1580 + *
59.1581 + * The returned collection will be serializable if the specified collection
59.1582 + * is serializable.
59.1583 + *
59.1584 + * @param c the collection to be "wrapped" in a synchronized collection.
59.1585 + * @return a synchronized view of the specified collection.
59.1586 + */
59.1587 + public static <T> Collection<T> synchronizedCollection(Collection<T> c) {
59.1588 + return new SynchronizedCollection<>(c);
59.1589 + }
59.1590 +
59.1591 + static <T> Collection<T> synchronizedCollection(Collection<T> c, Object mutex) {
59.1592 + return new SynchronizedCollection<>(c, mutex);
59.1593 + }
59.1594 +
59.1595 + /**
59.1596 + * @serial include
59.1597 + */
59.1598 + static class SynchronizedCollection<E> implements Collection<E>, Serializable {
59.1599 + private static final long serialVersionUID = 3053995032091335093L;
59.1600 +
59.1601 + final Collection<E> c; // Backing Collection
59.1602 + final Object mutex; // Object on which to synchronize
59.1603 +
59.1604 + SynchronizedCollection(Collection<E> c) {
59.1605 + if (c==null)
59.1606 + throw new NullPointerException();
59.1607 + this.c = c;
59.1608 + mutex = this;
59.1609 + }
59.1610 + SynchronizedCollection(Collection<E> c, Object mutex) {
59.1611 + this.c = c;
59.1612 + this.mutex = mutex;
59.1613 + }
59.1614 +
59.1615 + public int size() {
59.1616 + synchronized (mutex) {return c.size();}
59.1617 + }
59.1618 + public boolean isEmpty() {
59.1619 + synchronized (mutex) {return c.isEmpty();}
59.1620 + }
59.1621 + public boolean contains(Object o) {
59.1622 + synchronized (mutex) {return c.contains(o);}
59.1623 + }
59.1624 + public Object[] toArray() {
59.1625 + synchronized (mutex) {return c.toArray();}
59.1626 + }
59.1627 + public <T> T[] toArray(T[] a) {
59.1628 + synchronized (mutex) {return c.toArray(a);}
59.1629 + }
59.1630 +
59.1631 + public Iterator<E> iterator() {
59.1632 + return c.iterator(); // Must be manually synched by user!
59.1633 + }
59.1634 +
59.1635 + public boolean add(E e) {
59.1636 + synchronized (mutex) {return c.add(e);}
59.1637 + }
59.1638 + public boolean remove(Object o) {
59.1639 + synchronized (mutex) {return c.remove(o);}
59.1640 + }
59.1641 +
59.1642 + public boolean containsAll(Collection<?> coll) {
59.1643 + synchronized (mutex) {return c.containsAll(coll);}
59.1644 + }
59.1645 + public boolean addAll(Collection<? extends E> coll) {
59.1646 + synchronized (mutex) {return c.addAll(coll);}
59.1647 + }
59.1648 + public boolean removeAll(Collection<?> coll) {
59.1649 + synchronized (mutex) {return c.removeAll(coll);}
59.1650 + }
59.1651 + public boolean retainAll(Collection<?> coll) {
59.1652 + synchronized (mutex) {return c.retainAll(coll);}
59.1653 + }
59.1654 + public void clear() {
59.1655 + synchronized (mutex) {c.clear();}
59.1656 + }
59.1657 + public String toString() {
59.1658 + synchronized (mutex) {return c.toString();}
59.1659 + }
59.1660 + }
59.1661 +
59.1662 + /**
59.1663 + * Returns a synchronized (thread-safe) set backed by the specified
59.1664 + * set. In order to guarantee serial access, it is critical that
59.1665 + * <strong>all</strong> access to the backing set is accomplished
59.1666 + * through the returned set.<p>
59.1667 + *
59.1668 + * It is imperative that the user manually synchronize on the returned
59.1669 + * set when iterating over it:
59.1670 + * <pre>
59.1671 + * Set s = Collections.synchronizedSet(new HashSet());
59.1672 + * ...
59.1673 + * synchronized (s) {
59.1674 + * Iterator i = s.iterator(); // Must be in the synchronized block
59.1675 + * while (i.hasNext())
59.1676 + * foo(i.next());
59.1677 + * }
59.1678 + * </pre>
59.1679 + * Failure to follow this advice may result in non-deterministic behavior.
59.1680 + *
59.1681 + * <p>The returned set will be serializable if the specified set is
59.1682 + * serializable.
59.1683 + *
59.1684 + * @param s the set to be "wrapped" in a synchronized set.
59.1685 + * @return a synchronized view of the specified set.
59.1686 + */
59.1687 + public static <T> Set<T> synchronizedSet(Set<T> s) {
59.1688 + return new SynchronizedSet<>(s);
59.1689 + }
59.1690 +
59.1691 + static <T> Set<T> synchronizedSet(Set<T> s, Object mutex) {
59.1692 + return new SynchronizedSet<>(s, mutex);
59.1693 + }
59.1694 +
59.1695 + /**
59.1696 + * @serial include
59.1697 + */
59.1698 + static class SynchronizedSet<E>
59.1699 + extends SynchronizedCollection<E>
59.1700 + implements Set<E> {
59.1701 + private static final long serialVersionUID = 487447009682186044L;
59.1702 +
59.1703 + SynchronizedSet(Set<E> s) {
59.1704 + super(s);
59.1705 + }
59.1706 + SynchronizedSet(Set<E> s, Object mutex) {
59.1707 + super(s, mutex);
59.1708 + }
59.1709 +
59.1710 + public boolean equals(Object o) {
59.1711 + synchronized (mutex) {return c.equals(o);}
59.1712 + }
59.1713 + public int hashCode() {
59.1714 + synchronized (mutex) {return c.hashCode();}
59.1715 + }
59.1716 + }
59.1717 +
59.1718 + /**
59.1719 + * Returns a synchronized (thread-safe) sorted set backed by the specified
59.1720 + * sorted set. In order to guarantee serial access, it is critical that
59.1721 + * <strong>all</strong> access to the backing sorted set is accomplished
59.1722 + * through the returned sorted set (or its views).<p>
59.1723 + *
59.1724 + * It is imperative that the user manually synchronize on the returned
59.1725 + * sorted set when iterating over it or any of its <tt>subSet</tt>,
59.1726 + * <tt>headSet</tt>, or <tt>tailSet</tt> views.
59.1727 + * <pre>
59.1728 + * SortedSet s = Collections.synchronizedSortedSet(new TreeSet());
59.1729 + * ...
59.1730 + * synchronized (s) {
59.1731 + * Iterator i = s.iterator(); // Must be in the synchronized block
59.1732 + * while (i.hasNext())
59.1733 + * foo(i.next());
59.1734 + * }
59.1735 + * </pre>
59.1736 + * or:
59.1737 + * <pre>
59.1738 + * SortedSet s = Collections.synchronizedSortedSet(new TreeSet());
59.1739 + * SortedSet s2 = s.headSet(foo);
59.1740 + * ...
59.1741 + * synchronized (s) { // Note: s, not s2!!!
59.1742 + * Iterator i = s2.iterator(); // Must be in the synchronized block
59.1743 + * while (i.hasNext())
59.1744 + * foo(i.next());
59.1745 + * }
59.1746 + * </pre>
59.1747 + * Failure to follow this advice may result in non-deterministic behavior.
59.1748 + *
59.1749 + * <p>The returned sorted set will be serializable if the specified
59.1750 + * sorted set is serializable.
59.1751 + *
59.1752 + * @param s the sorted set to be "wrapped" in a synchronized sorted set.
59.1753 + * @return a synchronized view of the specified sorted set.
59.1754 + */
59.1755 + public static <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s) {
59.1756 + return new SynchronizedSortedSet<>(s);
59.1757 + }
59.1758 +
59.1759 + /**
59.1760 + * @serial include
59.1761 + */
59.1762 + static class SynchronizedSortedSet<E>
59.1763 + extends SynchronizedSet<E>
59.1764 + implements SortedSet<E>
59.1765 + {
59.1766 + private static final long serialVersionUID = 8695801310862127406L;
59.1767 +
59.1768 + private final SortedSet<E> ss;
59.1769 +
59.1770 + SynchronizedSortedSet(SortedSet<E> s) {
59.1771 + super(s);
59.1772 + ss = s;
59.1773 + }
59.1774 + SynchronizedSortedSet(SortedSet<E> s, Object mutex) {
59.1775 + super(s, mutex);
59.1776 + ss = s;
59.1777 + }
59.1778 +
59.1779 + public Comparator<? super E> comparator() {
59.1780 + synchronized (mutex) {return ss.comparator();}
59.1781 + }
59.1782 +
59.1783 + public SortedSet<E> subSet(E fromElement, E toElement) {
59.1784 + synchronized (mutex) {
59.1785 + return new SynchronizedSortedSet<>(
59.1786 + ss.subSet(fromElement, toElement), mutex);
59.1787 + }
59.1788 + }
59.1789 + public SortedSet<E> headSet(E toElement) {
59.1790 + synchronized (mutex) {
59.1791 + return new SynchronizedSortedSet<>(ss.headSet(toElement), mutex);
59.1792 + }
59.1793 + }
59.1794 + public SortedSet<E> tailSet(E fromElement) {
59.1795 + synchronized (mutex) {
59.1796 + return new SynchronizedSortedSet<>(ss.tailSet(fromElement),mutex);
59.1797 + }
59.1798 + }
59.1799 +
59.1800 + public E first() {
59.1801 + synchronized (mutex) {return ss.first();}
59.1802 + }
59.1803 + public E last() {
59.1804 + synchronized (mutex) {return ss.last();}
59.1805 + }
59.1806 + }
59.1807 +
59.1808 + /**
59.1809 + * Returns a synchronized (thread-safe) list backed by the specified
59.1810 + * list. In order to guarantee serial access, it is critical that
59.1811 + * <strong>all</strong> access to the backing list is accomplished
59.1812 + * through the returned list.<p>
59.1813 + *
59.1814 + * It is imperative that the user manually synchronize on the returned
59.1815 + * list when iterating over it:
59.1816 + * <pre>
59.1817 + * List list = Collections.synchronizedList(new ArrayList());
59.1818 + * ...
59.1819 + * synchronized (list) {
59.1820 + * Iterator i = list.iterator(); // Must be in synchronized block
59.1821 + * while (i.hasNext())
59.1822 + * foo(i.next());
59.1823 + * }
59.1824 + * </pre>
59.1825 + * Failure to follow this advice may result in non-deterministic behavior.
59.1826 + *
59.1827 + * <p>The returned list will be serializable if the specified list is
59.1828 + * serializable.
59.1829 + *
59.1830 + * @param list the list to be "wrapped" in a synchronized list.
59.1831 + * @return a synchronized view of the specified list.
59.1832 + */
59.1833 + public static <T> List<T> synchronizedList(List<T> list) {
59.1834 + return (list instanceof RandomAccess ?
59.1835 + new SynchronizedRandomAccessList<>(list) :
59.1836 + new SynchronizedList<>(list));
59.1837 + }
59.1838 +
59.1839 + static <T> List<T> synchronizedList(List<T> list, Object mutex) {
59.1840 + return (list instanceof RandomAccess ?
59.1841 + new SynchronizedRandomAccessList<>(list, mutex) :
59.1842 + new SynchronizedList<>(list, mutex));
59.1843 + }
59.1844 +
59.1845 + /**
59.1846 + * @serial include
59.1847 + */
59.1848 + static class SynchronizedList<E>
59.1849 + extends SynchronizedCollection<E>
59.1850 + implements List<E> {
59.1851 + private static final long serialVersionUID = -7754090372962971524L;
59.1852 +
59.1853 + final List<E> list;
59.1854 +
59.1855 + SynchronizedList(List<E> list) {
59.1856 + super(list);
59.1857 + this.list = list;
59.1858 + }
59.1859 + SynchronizedList(List<E> list, Object mutex) {
59.1860 + super(list, mutex);
59.1861 + this.list = list;
59.1862 + }
59.1863 +
59.1864 + public boolean equals(Object o) {
59.1865 + synchronized (mutex) {return list.equals(o);}
59.1866 + }
59.1867 + public int hashCode() {
59.1868 + synchronized (mutex) {return list.hashCode();}
59.1869 + }
59.1870 +
59.1871 + public E get(int index) {
59.1872 + synchronized (mutex) {return list.get(index);}
59.1873 + }
59.1874 + public E set(int index, E element) {
59.1875 + synchronized (mutex) {return list.set(index, element);}
59.1876 + }
59.1877 + public void add(int index, E element) {
59.1878 + synchronized (mutex) {list.add(index, element);}
59.1879 + }
59.1880 + public E remove(int index) {
59.1881 + synchronized (mutex) {return list.remove(index);}
59.1882 + }
59.1883 +
59.1884 + public int indexOf(Object o) {
59.1885 + synchronized (mutex) {return list.indexOf(o);}
59.1886 + }
59.1887 + public int lastIndexOf(Object o) {
59.1888 + synchronized (mutex) {return list.lastIndexOf(o);}
59.1889 + }
59.1890 +
59.1891 + public boolean addAll(int index, Collection<? extends E> c) {
59.1892 + synchronized (mutex) {return list.addAll(index, c);}
59.1893 + }
59.1894 +
59.1895 + public ListIterator<E> listIterator() {
59.1896 + return list.listIterator(); // Must be manually synched by user
59.1897 + }
59.1898 +
59.1899 + public ListIterator<E> listIterator(int index) {
59.1900 + return list.listIterator(index); // Must be manually synched by user
59.1901 + }
59.1902 +
59.1903 + public List<E> subList(int fromIndex, int toIndex) {
59.1904 + synchronized (mutex) {
59.1905 + return new SynchronizedList<>(list.subList(fromIndex, toIndex),
59.1906 + mutex);
59.1907 + }
59.1908 + }
59.1909 +
59.1910 + /**
59.1911 + * SynchronizedRandomAccessList instances are serialized as
59.1912 + * SynchronizedList instances to allow them to be deserialized
59.1913 + * in pre-1.4 JREs (which do not have SynchronizedRandomAccessList).
59.1914 + * This method inverts the transformation. As a beneficial
59.1915 + * side-effect, it also grafts the RandomAccess marker onto
59.1916 + * SynchronizedList instances that were serialized in pre-1.4 JREs.
59.1917 + *
59.1918 + * Note: Unfortunately, SynchronizedRandomAccessList instances
59.1919 + * serialized in 1.4.1 and deserialized in 1.4 will become
59.1920 + * SynchronizedList instances, as this method was missing in 1.4.
59.1921 + */
59.1922 + private Object readResolve() {
59.1923 + return (list instanceof RandomAccess
59.1924 + ? new SynchronizedRandomAccessList<>(list)
59.1925 + : this);
59.1926 + }
59.1927 + }
59.1928 +
59.1929 + /**
59.1930 + * @serial include
59.1931 + */
59.1932 + static class SynchronizedRandomAccessList<E>
59.1933 + extends SynchronizedList<E>
59.1934 + implements RandomAccess {
59.1935 +
59.1936 + SynchronizedRandomAccessList(List<E> list) {
59.1937 + super(list);
59.1938 + }
59.1939 +
59.1940 + SynchronizedRandomAccessList(List<E> list, Object mutex) {
59.1941 + super(list, mutex);
59.1942 + }
59.1943 +
59.1944 + public List<E> subList(int fromIndex, int toIndex) {
59.1945 + synchronized (mutex) {
59.1946 + return new SynchronizedRandomAccessList<>(
59.1947 + list.subList(fromIndex, toIndex), mutex);
59.1948 + }
59.1949 + }
59.1950 +
59.1951 + private static final long serialVersionUID = 1530674583602358482L;
59.1952 +
59.1953 + /**
59.1954 + * Allows instances to be deserialized in pre-1.4 JREs (which do
59.1955 + * not have SynchronizedRandomAccessList). SynchronizedList has
59.1956 + * a readResolve method that inverts this transformation upon
59.1957 + * deserialization.
59.1958 + */
59.1959 + private Object writeReplace() {
59.1960 + return new SynchronizedList<>(list);
59.1961 + }
59.1962 + }
59.1963 +
59.1964 + /**
59.1965 + * Returns a synchronized (thread-safe) map backed by the specified
59.1966 + * map. In order to guarantee serial access, it is critical that
59.1967 + * <strong>all</strong> access to the backing map is accomplished
59.1968 + * through the returned map.<p>
59.1969 + *
59.1970 + * It is imperative that the user manually synchronize on the returned
59.1971 + * map when iterating over any of its collection views:
59.1972 + * <pre>
59.1973 + * Map m = Collections.synchronizedMap(new HashMap());
59.1974 + * ...
59.1975 + * Set s = m.keySet(); // Needn't be in synchronized block
59.1976 + * ...
59.1977 + * synchronized (m) { // Synchronizing on m, not s!
59.1978 + * Iterator i = s.iterator(); // Must be in synchronized block
59.1979 + * while (i.hasNext())
59.1980 + * foo(i.next());
59.1981 + * }
59.1982 + * </pre>
59.1983 + * Failure to follow this advice may result in non-deterministic behavior.
59.1984 + *
59.1985 + * <p>The returned map will be serializable if the specified map is
59.1986 + * serializable.
59.1987 + *
59.1988 + * @param m the map to be "wrapped" in a synchronized map.
59.1989 + * @return a synchronized view of the specified map.
59.1990 + */
59.1991 + public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
59.1992 + return new SynchronizedMap<>(m);
59.1993 + }
59.1994 +
59.1995 + /**
59.1996 + * @serial include
59.1997 + */
59.1998 + private static class SynchronizedMap<K,V>
59.1999 + implements Map<K,V>, Serializable {
59.2000 + private static final long serialVersionUID = 1978198479659022715L;
59.2001 +
59.2002 + private final Map<K,V> m; // Backing Map
59.2003 + final Object mutex; // Object on which to synchronize
59.2004 +
59.2005 + SynchronizedMap(Map<K,V> m) {
59.2006 + if (m==null)
59.2007 + throw new NullPointerException();
59.2008 + this.m = m;
59.2009 + mutex = this;
59.2010 + }
59.2011 +
59.2012 + SynchronizedMap(Map<K,V> m, Object mutex) {
59.2013 + this.m = m;
59.2014 + this.mutex = mutex;
59.2015 + }
59.2016 +
59.2017 + public int size() {
59.2018 + synchronized (mutex) {return m.size();}
59.2019 + }
59.2020 + public boolean isEmpty() {
59.2021 + synchronized (mutex) {return m.isEmpty();}
59.2022 + }
59.2023 + public boolean containsKey(Object key) {
59.2024 + synchronized (mutex) {return m.containsKey(key);}
59.2025 + }
59.2026 + public boolean containsValue(Object value) {
59.2027 + synchronized (mutex) {return m.containsValue(value);}
59.2028 + }
59.2029 + public V get(Object key) {
59.2030 + synchronized (mutex) {return m.get(key);}
59.2031 + }
59.2032 +
59.2033 + public V put(K key, V value) {
59.2034 + synchronized (mutex) {return m.put(key, value);}
59.2035 + }
59.2036 + public V remove(Object key) {
59.2037 + synchronized (mutex) {return m.remove(key);}
59.2038 + }
59.2039 + public void putAll(Map<? extends K, ? extends V> map) {
59.2040 + synchronized (mutex) {m.putAll(map);}
59.2041 + }
59.2042 + public void clear() {
59.2043 + synchronized (mutex) {m.clear();}
59.2044 + }
59.2045 +
59.2046 + private transient Set<K> keySet = null;
59.2047 + private transient Set<Map.Entry<K,V>> entrySet = null;
59.2048 + private transient Collection<V> values = null;
59.2049 +
59.2050 + public Set<K> keySet() {
59.2051 + synchronized (mutex) {
59.2052 + if (keySet==null)
59.2053 + keySet = new SynchronizedSet<>(m.keySet(), mutex);
59.2054 + return keySet;
59.2055 + }
59.2056 + }
59.2057 +
59.2058 + public Set<Map.Entry<K,V>> entrySet() {
59.2059 + synchronized (mutex) {
59.2060 + if (entrySet==null)
59.2061 + entrySet = new SynchronizedSet<>(m.entrySet(), mutex);
59.2062 + return entrySet;
59.2063 + }
59.2064 + }
59.2065 +
59.2066 + public Collection<V> values() {
59.2067 + synchronized (mutex) {
59.2068 + if (values==null)
59.2069 + values = new SynchronizedCollection<>(m.values(), mutex);
59.2070 + return values;
59.2071 + }
59.2072 + }
59.2073 +
59.2074 + public boolean equals(Object o) {
59.2075 + synchronized (mutex) {return m.equals(o);}
59.2076 + }
59.2077 + public int hashCode() {
59.2078 + synchronized (mutex) {return m.hashCode();}
59.2079 + }
59.2080 + public String toString() {
59.2081 + synchronized (mutex) {return m.toString();}
59.2082 + }
59.2083 + }
59.2084 +
59.2085 + /**
59.2086 + * Returns a synchronized (thread-safe) sorted map backed by the specified
59.2087 + * sorted map. In order to guarantee serial access, it is critical that
59.2088 + * <strong>all</strong> access to the backing sorted map is accomplished
59.2089 + * through the returned sorted map (or its views).<p>
59.2090 + *
59.2091 + * It is imperative that the user manually synchronize on the returned
59.2092 + * sorted map when iterating over any of its collection views, or the
59.2093 + * collections views of any of its <tt>subMap</tt>, <tt>headMap</tt> or
59.2094 + * <tt>tailMap</tt> views.
59.2095 + * <pre>
59.2096 + * SortedMap m = Collections.synchronizedSortedMap(new TreeMap());
59.2097 + * ...
59.2098 + * Set s = m.keySet(); // Needn't be in synchronized block
59.2099 + * ...
59.2100 + * synchronized (m) { // Synchronizing on m, not s!
59.2101 + * Iterator i = s.iterator(); // Must be in synchronized block
59.2102 + * while (i.hasNext())
59.2103 + * foo(i.next());
59.2104 + * }
59.2105 + * </pre>
59.2106 + * or:
59.2107 + * <pre>
59.2108 + * SortedMap m = Collections.synchronizedSortedMap(new TreeMap());
59.2109 + * SortedMap m2 = m.subMap(foo, bar);
59.2110 + * ...
59.2111 + * Set s2 = m2.keySet(); // Needn't be in synchronized block
59.2112 + * ...
59.2113 + * synchronized (m) { // Synchronizing on m, not m2 or s2!
59.2114 + * Iterator i = s.iterator(); // Must be in synchronized block
59.2115 + * while (i.hasNext())
59.2116 + * foo(i.next());
59.2117 + * }
59.2118 + * </pre>
59.2119 + * Failure to follow this advice may result in non-deterministic behavior.
59.2120 + *
59.2121 + * <p>The returned sorted map will be serializable if the specified
59.2122 + * sorted map is serializable.
59.2123 + *
59.2124 + * @param m the sorted map to be "wrapped" in a synchronized sorted map.
59.2125 + * @return a synchronized view of the specified sorted map.
59.2126 + */
59.2127 + public static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m) {
59.2128 + return new SynchronizedSortedMap<>(m);
59.2129 + }
59.2130 +
59.2131 +
59.2132 + /**
59.2133 + * @serial include
59.2134 + */
59.2135 + static class SynchronizedSortedMap<K,V>
59.2136 + extends SynchronizedMap<K,V>
59.2137 + implements SortedMap<K,V>
59.2138 + {
59.2139 + private static final long serialVersionUID = -8798146769416483793L;
59.2140 +
59.2141 + private final SortedMap<K,V> sm;
59.2142 +
59.2143 + SynchronizedSortedMap(SortedMap<K,V> m) {
59.2144 + super(m);
59.2145 + sm = m;
59.2146 + }
59.2147 + SynchronizedSortedMap(SortedMap<K,V> m, Object mutex) {
59.2148 + super(m, mutex);
59.2149 + sm = m;
59.2150 + }
59.2151 +
59.2152 + public Comparator<? super K> comparator() {
59.2153 + synchronized (mutex) {return sm.comparator();}
59.2154 + }
59.2155 +
59.2156 + public SortedMap<K,V> subMap(K fromKey, K toKey) {
59.2157 + synchronized (mutex) {
59.2158 + return new SynchronizedSortedMap<>(
59.2159 + sm.subMap(fromKey, toKey), mutex);
59.2160 + }
59.2161 + }
59.2162 + public SortedMap<K,V> headMap(K toKey) {
59.2163 + synchronized (mutex) {
59.2164 + return new SynchronizedSortedMap<>(sm.headMap(toKey), mutex);
59.2165 + }
59.2166 + }
59.2167 + public SortedMap<K,V> tailMap(K fromKey) {
59.2168 + synchronized (mutex) {
59.2169 + return new SynchronizedSortedMap<>(sm.tailMap(fromKey),mutex);
59.2170 + }
59.2171 + }
59.2172 +
59.2173 + public K firstKey() {
59.2174 + synchronized (mutex) {return sm.firstKey();}
59.2175 + }
59.2176 + public K lastKey() {
59.2177 + synchronized (mutex) {return sm.lastKey();}
59.2178 + }
59.2179 + }
59.2180 +
59.2181 + // Dynamically typesafe collection wrappers
59.2182 +
59.2183 + /**
59.2184 + * Returns a dynamically typesafe view of the specified collection.
59.2185 + * Any attempt to insert an element of the wrong type will result in an
59.2186 + * immediate {@link ClassCastException}. Assuming a collection
59.2187 + * contains no incorrectly typed elements prior to the time a
59.2188 + * dynamically typesafe view is generated, and that all subsequent
59.2189 + * access to the collection takes place through the view, it is
59.2190 + * <i>guaranteed</i> that the collection cannot contain an incorrectly
59.2191 + * typed element.
59.2192 + *
59.2193 + * <p>The generics mechanism in the language provides compile-time
59.2194 + * (static) type checking, but it is possible to defeat this mechanism
59.2195 + * with unchecked casts. Usually this is not a problem, as the compiler
59.2196 + * issues warnings on all such unchecked operations. There are, however,
59.2197 + * times when static type checking alone is not sufficient. For example,
59.2198 + * suppose a collection is passed to a third-party library and it is
59.2199 + * imperative that the library code not corrupt the collection by
59.2200 + * inserting an element of the wrong type.
59.2201 + *
59.2202 + * <p>Another use of dynamically typesafe views is debugging. Suppose a
59.2203 + * program fails with a {@code ClassCastException}, indicating that an
59.2204 + * incorrectly typed element was put into a parameterized collection.
59.2205 + * Unfortunately, the exception can occur at any time after the erroneous
59.2206 + * element is inserted, so it typically provides little or no information
59.2207 + * as to the real source of the problem. If the problem is reproducible,
59.2208 + * one can quickly determine its source by temporarily modifying the
59.2209 + * program to wrap the collection with a dynamically typesafe view.
59.2210 + * For example, this declaration:
59.2211 + * <pre> {@code
59.2212 + * Collection<String> c = new HashSet<String>();
59.2213 + * }</pre>
59.2214 + * may be replaced temporarily by this one:
59.2215 + * <pre> {@code
59.2216 + * Collection<String> c = Collections.checkedCollection(
59.2217 + * new HashSet<String>(), String.class);
59.2218 + * }</pre>
59.2219 + * Running the program again will cause it to fail at the point where
59.2220 + * an incorrectly typed element is inserted into the collection, clearly
59.2221 + * identifying the source of the problem. Once the problem is fixed, the
59.2222 + * modified declaration may be reverted back to the original.
59.2223 + *
59.2224 + * <p>The returned collection does <i>not</i> pass the hashCode and equals
59.2225 + * operations through to the backing collection, but relies on
59.2226 + * {@code Object}'s {@code equals} and {@code hashCode} methods. This
59.2227 + * is necessary to preserve the contracts of these operations in the case
59.2228 + * that the backing collection is a set or a list.
59.2229 + *
59.2230 + * <p>The returned collection will be serializable if the specified
59.2231 + * collection is serializable.
59.2232 + *
59.2233 + * <p>Since {@code null} is considered to be a value of any reference
59.2234 + * type, the returned collection permits insertion of null elements
59.2235 + * whenever the backing collection does.
59.2236 + *
59.2237 + * @param c the collection for which a dynamically typesafe view is to be
59.2238 + * returned
59.2239 + * @param type the type of element that {@code c} is permitted to hold
59.2240 + * @return a dynamically typesafe view of the specified collection
59.2241 + * @since 1.5
59.2242 + */
59.2243 + public static <E> Collection<E> checkedCollection(Collection<E> c,
59.2244 + Class<E> type) {
59.2245 + return new CheckedCollection<>(c, type);
59.2246 + }
59.2247 +
59.2248 + @SuppressWarnings("unchecked")
59.2249 + static <T> T[] zeroLengthArray(Class<T> type) {
59.2250 + return (T[]) Array.newInstance(type, 0);
59.2251 + }
59.2252 +
59.2253 + /**
59.2254 + * @serial include
59.2255 + */
59.2256 + static class CheckedCollection<E> implements Collection<E>, Serializable {
59.2257 + private static final long serialVersionUID = 1578914078182001775L;
59.2258 +
59.2259 + final Collection<E> c;
59.2260 + final Class<E> type;
59.2261 +
59.2262 + void typeCheck(Object o) {
59.2263 + if (o != null && !type.isInstance(o))
59.2264 + throw new ClassCastException(badElementMsg(o));
59.2265 + }
59.2266 +
59.2267 + private String badElementMsg(Object o) {
59.2268 + return "Attempt to insert " + o.getClass() +
59.2269 + " element into collection with element type " + type;
59.2270 + }
59.2271 +
59.2272 + CheckedCollection(Collection<E> c, Class<E> type) {
59.2273 + if (c==null || type == null)
59.2274 + throw new NullPointerException();
59.2275 + this.c = c;
59.2276 + this.type = type;
59.2277 + }
59.2278 +
59.2279 + public int size() { return c.size(); }
59.2280 + public boolean isEmpty() { return c.isEmpty(); }
59.2281 + public boolean contains(Object o) { return c.contains(o); }
59.2282 + public Object[] toArray() { return c.toArray(); }
59.2283 + public <T> T[] toArray(T[] a) { return c.toArray(a); }
59.2284 + public String toString() { return c.toString(); }
59.2285 + public boolean remove(Object o) { return c.remove(o); }
59.2286 + public void clear() { c.clear(); }
59.2287 +
59.2288 + public boolean containsAll(Collection<?> coll) {
59.2289 + return c.containsAll(coll);
59.2290 + }
59.2291 + public boolean removeAll(Collection<?> coll) {
59.2292 + return c.removeAll(coll);
59.2293 + }
59.2294 + public boolean retainAll(Collection<?> coll) {
59.2295 + return c.retainAll(coll);
59.2296 + }
59.2297 +
59.2298 + public Iterator<E> iterator() {
59.2299 + final Iterator<E> it = c.iterator();
59.2300 + return new Iterator<E>() {
59.2301 + public boolean hasNext() { return it.hasNext(); }
59.2302 + public E next() { return it.next(); }
59.2303 + public void remove() { it.remove(); }};
59.2304 + }
59.2305 +
59.2306 + public boolean add(E e) {
59.2307 + typeCheck(e);
59.2308 + return c.add(e);
59.2309 + }
59.2310 +
59.2311 + private E[] zeroLengthElementArray = null; // Lazily initialized
59.2312 +
59.2313 + private E[] zeroLengthElementArray() {
59.2314 + return zeroLengthElementArray != null ? zeroLengthElementArray :
59.2315 + (zeroLengthElementArray = zeroLengthArray(type));
59.2316 + }
59.2317 +
59.2318 + @SuppressWarnings("unchecked")
59.2319 + Collection<E> checkedCopyOf(Collection<? extends E> coll) {
59.2320 + Object[] a = null;
59.2321 + try {
59.2322 + E[] z = zeroLengthElementArray();
59.2323 + a = coll.toArray(z);
59.2324 + // Defend against coll violating the toArray contract
59.2325 + if (a.getClass() != z.getClass())
59.2326 + a = Arrays.copyOf(a, a.length, z.getClass());
59.2327 + } catch (ArrayStoreException ignore) {
59.2328 + // To get better and consistent diagnostics,
59.2329 + // we call typeCheck explicitly on each element.
59.2330 + // We call clone() to defend against coll retaining a
59.2331 + // reference to the returned array and storing a bad
59.2332 + // element into it after it has been type checked.
59.2333 + a = coll.toArray().clone();
59.2334 + for (Object o : a)
59.2335 + typeCheck(o);
59.2336 + }
59.2337 + // A slight abuse of the type system, but safe here.
59.2338 + return (Collection<E>) Arrays.asList(a);
59.2339 + }
59.2340 +
59.2341 + public boolean addAll(Collection<? extends E> coll) {
59.2342 + // Doing things this way insulates us from concurrent changes
59.2343 + // in the contents of coll and provides all-or-nothing
59.2344 + // semantics (which we wouldn't get if we type-checked each
59.2345 + // element as we added it)
59.2346 + return c.addAll(checkedCopyOf(coll));
59.2347 + }
59.2348 + }
59.2349 +
59.2350 + /**
59.2351 + * Returns a dynamically typesafe view of the specified set.
59.2352 + * Any attempt to insert an element of the wrong type will result in
59.2353 + * an immediate {@link ClassCastException}. Assuming a set contains
59.2354 + * no incorrectly typed elements prior to the time a dynamically typesafe
59.2355 + * view is generated, and that all subsequent access to the set
59.2356 + * takes place through the view, it is <i>guaranteed</i> that the
59.2357 + * set cannot contain an incorrectly typed element.
59.2358 + *
59.2359 + * <p>A discussion of the use of dynamically typesafe views may be
59.2360 + * found in the documentation for the {@link #checkedCollection
59.2361 + * checkedCollection} method.
59.2362 + *
59.2363 + * <p>The returned set will be serializable if the specified set is
59.2364 + * serializable.
59.2365 + *
59.2366 + * <p>Since {@code null} is considered to be a value of any reference
59.2367 + * type, the returned set permits insertion of null elements whenever
59.2368 + * the backing set does.
59.2369 + *
59.2370 + * @param s the set for which a dynamically typesafe view is to be
59.2371 + * returned
59.2372 + * @param type the type of element that {@code s} is permitted to hold
59.2373 + * @return a dynamically typesafe view of the specified set
59.2374 + * @since 1.5
59.2375 + */
59.2376 + public static <E> Set<E> checkedSet(Set<E> s, Class<E> type) {
59.2377 + return new CheckedSet<>(s, type);
59.2378 + }
59.2379 +
59.2380 + /**
59.2381 + * @serial include
59.2382 + */
59.2383 + static class CheckedSet<E> extends CheckedCollection<E>
59.2384 + implements Set<E>, Serializable
59.2385 + {
59.2386 + private static final long serialVersionUID = 4694047833775013803L;
59.2387 +
59.2388 + CheckedSet(Set<E> s, Class<E> elementType) { super(s, elementType); }
59.2389 +
59.2390 + public boolean equals(Object o) { return o == this || c.equals(o); }
59.2391 + public int hashCode() { return c.hashCode(); }
59.2392 + }
59.2393 +
59.2394 + /**
59.2395 + * Returns a dynamically typesafe view of the specified sorted set.
59.2396 + * Any attempt to insert an element of the wrong type will result in an
59.2397 + * immediate {@link ClassCastException}. Assuming a sorted set
59.2398 + * contains no incorrectly typed elements prior to the time a
59.2399 + * dynamically typesafe view is generated, and that all subsequent
59.2400 + * access to the sorted set takes place through the view, it is
59.2401 + * <i>guaranteed</i> that the sorted set cannot contain an incorrectly
59.2402 + * typed element.
59.2403 + *
59.2404 + * <p>A discussion of the use of dynamically typesafe views may be
59.2405 + * found in the documentation for the {@link #checkedCollection
59.2406 + * checkedCollection} method.
59.2407 + *
59.2408 + * <p>The returned sorted set will be serializable if the specified sorted
59.2409 + * set is serializable.
59.2410 + *
59.2411 + * <p>Since {@code null} is considered to be a value of any reference
59.2412 + * type, the returned sorted set permits insertion of null elements
59.2413 + * whenever the backing sorted set does.
59.2414 + *
59.2415 + * @param s the sorted set for which a dynamically typesafe view is to be
59.2416 + * returned
59.2417 + * @param type the type of element that {@code s} is permitted to hold
59.2418 + * @return a dynamically typesafe view of the specified sorted set
59.2419 + * @since 1.5
59.2420 + */
59.2421 + public static <E> SortedSet<E> checkedSortedSet(SortedSet<E> s,
59.2422 + Class<E> type) {
59.2423 + return new CheckedSortedSet<>(s, type);
59.2424 + }
59.2425 +
59.2426 + /**
59.2427 + * @serial include
59.2428 + */
59.2429 + static class CheckedSortedSet<E> extends CheckedSet<E>
59.2430 + implements SortedSet<E>, Serializable
59.2431 + {
59.2432 + private static final long serialVersionUID = 1599911165492914959L;
59.2433 + private final SortedSet<E> ss;
59.2434 +
59.2435 + CheckedSortedSet(SortedSet<E> s, Class<E> type) {
59.2436 + super(s, type);
59.2437 + ss = s;
59.2438 + }
59.2439 +
59.2440 + public Comparator<? super E> comparator() { return ss.comparator(); }
59.2441 + public E first() { return ss.first(); }
59.2442 + public E last() { return ss.last(); }
59.2443 +
59.2444 + public SortedSet<E> subSet(E fromElement, E toElement) {
59.2445 + return checkedSortedSet(ss.subSet(fromElement,toElement), type);
59.2446 + }
59.2447 + public SortedSet<E> headSet(E toElement) {
59.2448 + return checkedSortedSet(ss.headSet(toElement), type);
59.2449 + }
59.2450 + public SortedSet<E> tailSet(E fromElement) {
59.2451 + return checkedSortedSet(ss.tailSet(fromElement), type);
59.2452 + }
59.2453 + }
59.2454 +
59.2455 + /**
59.2456 + * Returns a dynamically typesafe view of the specified list.
59.2457 + * Any attempt to insert an element of the wrong type will result in
59.2458 + * an immediate {@link ClassCastException}. Assuming a list contains
59.2459 + * no incorrectly typed elements prior to the time a dynamically typesafe
59.2460 + * view is generated, and that all subsequent access to the list
59.2461 + * takes place through the view, it is <i>guaranteed</i> that the
59.2462 + * list cannot contain an incorrectly typed element.
59.2463 + *
59.2464 + * <p>A discussion of the use of dynamically typesafe views may be
59.2465 + * found in the documentation for the {@link #checkedCollection
59.2466 + * checkedCollection} method.
59.2467 + *
59.2468 + * <p>The returned list will be serializable if the specified list
59.2469 + * is serializable.
59.2470 + *
59.2471 + * <p>Since {@code null} is considered to be a value of any reference
59.2472 + * type, the returned list permits insertion of null elements whenever
59.2473 + * the backing list does.
59.2474 + *
59.2475 + * @param list the list for which a dynamically typesafe view is to be
59.2476 + * returned
59.2477 + * @param type the type of element that {@code list} is permitted to hold
59.2478 + * @return a dynamically typesafe view of the specified list
59.2479 + * @since 1.5
59.2480 + */
59.2481 + public static <E> List<E> checkedList(List<E> list, Class<E> type) {
59.2482 + return (list instanceof RandomAccess ?
59.2483 + new CheckedRandomAccessList<>(list, type) :
59.2484 + new CheckedList<>(list, type));
59.2485 + }
59.2486 +
59.2487 + /**
59.2488 + * @serial include
59.2489 + */
59.2490 + static class CheckedList<E>
59.2491 + extends CheckedCollection<E>
59.2492 + implements List<E>
59.2493 + {
59.2494 + private static final long serialVersionUID = 65247728283967356L;
59.2495 + final List<E> list;
59.2496 +
59.2497 + CheckedList(List<E> list, Class<E> type) {
59.2498 + super(list, type);
59.2499 + this.list = list;
59.2500 + }
59.2501 +
59.2502 + public boolean equals(Object o) { return o == this || list.equals(o); }
59.2503 + public int hashCode() { return list.hashCode(); }
59.2504 + public E get(int index) { return list.get(index); }
59.2505 + public E remove(int index) { return list.remove(index); }
59.2506 + public int indexOf(Object o) { return list.indexOf(o); }
59.2507 + public int lastIndexOf(Object o) { return list.lastIndexOf(o); }
59.2508 +
59.2509 + public E set(int index, E element) {
59.2510 + typeCheck(element);
59.2511 + return list.set(index, element);
59.2512 + }
59.2513 +
59.2514 + public void add(int index, E element) {
59.2515 + typeCheck(element);
59.2516 + list.add(index, element);
59.2517 + }
59.2518 +
59.2519 + public boolean addAll(int index, Collection<? extends E> c) {
59.2520 + return list.addAll(index, checkedCopyOf(c));
59.2521 + }
59.2522 + public ListIterator<E> listIterator() { return listIterator(0); }
59.2523 +
59.2524 + public ListIterator<E> listIterator(final int index) {
59.2525 + final ListIterator<E> i = list.listIterator(index);
59.2526 +
59.2527 + return new ListIterator<E>() {
59.2528 + public boolean hasNext() { return i.hasNext(); }
59.2529 + public E next() { return i.next(); }
59.2530 + public boolean hasPrevious() { return i.hasPrevious(); }
59.2531 + public E previous() { return i.previous(); }
59.2532 + public int nextIndex() { return i.nextIndex(); }
59.2533 + public int previousIndex() { return i.previousIndex(); }
59.2534 + public void remove() { i.remove(); }
59.2535 +
59.2536 + public void set(E e) {
59.2537 + typeCheck(e);
59.2538 + i.set(e);
59.2539 + }
59.2540 +
59.2541 + public void add(E e) {
59.2542 + typeCheck(e);
59.2543 + i.add(e);
59.2544 + }
59.2545 + };
59.2546 + }
59.2547 +
59.2548 + public List<E> subList(int fromIndex, int toIndex) {
59.2549 + return new CheckedList<>(list.subList(fromIndex, toIndex), type);
59.2550 + }
59.2551 + }
59.2552 +
59.2553 + /**
59.2554 + * @serial include
59.2555 + */
59.2556 + static class CheckedRandomAccessList<E> extends CheckedList<E>
59.2557 + implements RandomAccess
59.2558 + {
59.2559 + private static final long serialVersionUID = 1638200125423088369L;
59.2560 +
59.2561 + CheckedRandomAccessList(List<E> list, Class<E> type) {
59.2562 + super(list, type);
59.2563 + }
59.2564 +
59.2565 + public List<E> subList(int fromIndex, int toIndex) {
59.2566 + return new CheckedRandomAccessList<>(
59.2567 + list.subList(fromIndex, toIndex), type);
59.2568 + }
59.2569 + }
59.2570 +
59.2571 + /**
59.2572 + * Returns a dynamically typesafe view of the specified map.
59.2573 + * Any attempt to insert a mapping whose key or value have the wrong
59.2574 + * type will result in an immediate {@link ClassCastException}.
59.2575 + * Similarly, any attempt to modify the value currently associated with
59.2576 + * a key will result in an immediate {@link ClassCastException},
59.2577 + * whether the modification is attempted directly through the map
59.2578 + * itself, or through a {@link Map.Entry} instance obtained from the
59.2579 + * map's {@link Map#entrySet() entry set} view.
59.2580 + *
59.2581 + * <p>Assuming a map contains no incorrectly typed keys or values
59.2582 + * prior to the time a dynamically typesafe view is generated, and
59.2583 + * that all subsequent access to the map takes place through the view
59.2584 + * (or one of its collection views), it is <i>guaranteed</i> that the
59.2585 + * map cannot contain an incorrectly typed key or value.
59.2586 + *
59.2587 + * <p>A discussion of the use of dynamically typesafe views may be
59.2588 + * found in the documentation for the {@link #checkedCollection
59.2589 + * checkedCollection} method.
59.2590 + *
59.2591 + * <p>The returned map will be serializable if the specified map is
59.2592 + * serializable.
59.2593 + *
59.2594 + * <p>Since {@code null} is considered to be a value of any reference
59.2595 + * type, the returned map permits insertion of null keys or values
59.2596 + * whenever the backing map does.
59.2597 + *
59.2598 + * @param m the map for which a dynamically typesafe view is to be
59.2599 + * returned
59.2600 + * @param keyType the type of key that {@code m} is permitted to hold
59.2601 + * @param valueType the type of value that {@code m} is permitted to hold
59.2602 + * @return a dynamically typesafe view of the specified map
59.2603 + * @since 1.5
59.2604 + */
59.2605 + public static <K, V> Map<K, V> checkedMap(Map<K, V> m,
59.2606 + Class<K> keyType,
59.2607 + Class<V> valueType) {
59.2608 + return new CheckedMap<>(m, keyType, valueType);
59.2609 + }
59.2610 +
59.2611 +
59.2612 + /**
59.2613 + * @serial include
59.2614 + */
59.2615 + private static class CheckedMap<K,V>
59.2616 + implements Map<K,V>, Serializable
59.2617 + {
59.2618 + private static final long serialVersionUID = 5742860141034234728L;
59.2619 +
59.2620 + private final Map<K, V> m;
59.2621 + final Class<K> keyType;
59.2622 + final Class<V> valueType;
59.2623 +
59.2624 + private void typeCheck(Object key, Object value) {
59.2625 + if (key != null && !keyType.isInstance(key))
59.2626 + throw new ClassCastException(badKeyMsg(key));
59.2627 +
59.2628 + if (value != null && !valueType.isInstance(value))
59.2629 + throw new ClassCastException(badValueMsg(value));
59.2630 + }
59.2631 +
59.2632 + private String badKeyMsg(Object key) {
59.2633 + return "Attempt to insert " + key.getClass() +
59.2634 + " key into map with key type " + keyType;
59.2635 + }
59.2636 +
59.2637 + private String badValueMsg(Object value) {
59.2638 + return "Attempt to insert " + value.getClass() +
59.2639 + " value into map with value type " + valueType;
59.2640 + }
59.2641 +
59.2642 + CheckedMap(Map<K, V> m, Class<K> keyType, Class<V> valueType) {
59.2643 + if (m == null || keyType == null || valueType == null)
59.2644 + throw new NullPointerException();
59.2645 + this.m = m;
59.2646 + this.keyType = keyType;
59.2647 + this.valueType = valueType;
59.2648 + }
59.2649 +
59.2650 + public int size() { return m.size(); }
59.2651 + public boolean isEmpty() { return m.isEmpty(); }
59.2652 + public boolean containsKey(Object key) { return m.containsKey(key); }
59.2653 + public boolean containsValue(Object v) { return m.containsValue(v); }
59.2654 + public V get(Object key) { return m.get(key); }
59.2655 + public V remove(Object key) { return m.remove(key); }
59.2656 + public void clear() { m.clear(); }
59.2657 + public Set<K> keySet() { return m.keySet(); }
59.2658 + public Collection<V> values() { return m.values(); }
59.2659 + public boolean equals(Object o) { return o == this || m.equals(o); }
59.2660 + public int hashCode() { return m.hashCode(); }
59.2661 + public String toString() { return m.toString(); }
59.2662 +
59.2663 + public V put(K key, V value) {
59.2664 + typeCheck(key, value);
59.2665 + return m.put(key, value);
59.2666 + }
59.2667 +
59.2668 + @SuppressWarnings("unchecked")
59.2669 + public void putAll(Map<? extends K, ? extends V> t) {
59.2670 + // Satisfy the following goals:
59.2671 + // - good diagnostics in case of type mismatch
59.2672 + // - all-or-nothing semantics
59.2673 + // - protection from malicious t
59.2674 + // - correct behavior if t is a concurrent map
59.2675 + Object[] entries = t.entrySet().toArray();
59.2676 + List<Map.Entry<K,V>> checked = new ArrayList<>(entries.length);
59.2677 + for (Object o : entries) {
59.2678 + Map.Entry<?,?> e = (Map.Entry<?,?>) o;
59.2679 + Object k = e.getKey();
59.2680 + Object v = e.getValue();
59.2681 + typeCheck(k, v);
59.2682 + checked.add(
59.2683 + new AbstractMap.SimpleImmutableEntry<>((K) k, (V) v));
59.2684 + }
59.2685 + for (Map.Entry<K,V> e : checked)
59.2686 + m.put(e.getKey(), e.getValue());
59.2687 + }
59.2688 +
59.2689 + private transient Set<Map.Entry<K,V>> entrySet = null;
59.2690 +
59.2691 + public Set<Map.Entry<K,V>> entrySet() {
59.2692 + if (entrySet==null)
59.2693 + entrySet = new CheckedEntrySet<>(m.entrySet(), valueType);
59.2694 + return entrySet;
59.2695 + }
59.2696 +
59.2697 + /**
59.2698 + * We need this class in addition to CheckedSet as Map.Entry permits
59.2699 + * modification of the backing Map via the setValue operation. This
59.2700 + * class is subtle: there are many possible attacks that must be
59.2701 + * thwarted.
59.2702 + *
59.2703 + * @serial exclude
59.2704 + */
59.2705 + static class CheckedEntrySet<K,V> implements Set<Map.Entry<K,V>> {
59.2706 + private final Set<Map.Entry<K,V>> s;
59.2707 + private final Class<V> valueType;
59.2708 +
59.2709 + CheckedEntrySet(Set<Map.Entry<K, V>> s, Class<V> valueType) {
59.2710 + this.s = s;
59.2711 + this.valueType = valueType;
59.2712 + }
59.2713 +
59.2714 + public int size() { return s.size(); }
59.2715 + public boolean isEmpty() { return s.isEmpty(); }
59.2716 + public String toString() { return s.toString(); }
59.2717 + public int hashCode() { return s.hashCode(); }
59.2718 + public void clear() { s.clear(); }
59.2719 +
59.2720 + public boolean add(Map.Entry<K, V> e) {
59.2721 + throw new UnsupportedOperationException();
59.2722 + }
59.2723 + public boolean addAll(Collection<? extends Map.Entry<K, V>> coll) {
59.2724 + throw new UnsupportedOperationException();
59.2725 + }
59.2726 +
59.2727 + public Iterator<Map.Entry<K,V>> iterator() {
59.2728 + final Iterator<Map.Entry<K, V>> i = s.iterator();
59.2729 + final Class<V> valueType = this.valueType;
59.2730 +
59.2731 + return new Iterator<Map.Entry<K,V>>() {
59.2732 + public boolean hasNext() { return i.hasNext(); }
59.2733 + public void remove() { i.remove(); }
59.2734 +
59.2735 + public Map.Entry<K,V> next() {
59.2736 + return checkedEntry(i.next(), valueType);
59.2737 + }
59.2738 + };
59.2739 + }
59.2740 +
59.2741 + @SuppressWarnings("unchecked")
59.2742 + public Object[] toArray() {
59.2743 + Object[] source = s.toArray();
59.2744 +
59.2745 + /*
59.2746 + * Ensure that we don't get an ArrayStoreException even if
59.2747 + * s.toArray returns an array of something other than Object
59.2748 + */
59.2749 + Object[] dest = (CheckedEntry.class.isInstance(
59.2750 + source.getClass().getComponentType()) ? source :
59.2751 + new Object[source.length]);
59.2752 +
59.2753 + for (int i = 0; i < source.length; i++)
59.2754 + dest[i] = checkedEntry((Map.Entry<K,V>)source[i],
59.2755 + valueType);
59.2756 + return dest;
59.2757 + }
59.2758 +
59.2759 + @SuppressWarnings("unchecked")
59.2760 + public <T> T[] toArray(T[] a) {
59.2761 + // We don't pass a to s.toArray, to avoid window of
59.2762 + // vulnerability wherein an unscrupulous multithreaded client
59.2763 + // could get his hands on raw (unwrapped) Entries from s.
59.2764 + T[] arr = s.toArray(a.length==0 ? a : Arrays.copyOf(a, 0));
59.2765 +
59.2766 + for (int i=0; i<arr.length; i++)
59.2767 + arr[i] = (T) checkedEntry((Map.Entry<K,V>)arr[i],
59.2768 + valueType);
59.2769 + if (arr.length > a.length)
59.2770 + return arr;
59.2771 +
59.2772 + System.arraycopy(arr, 0, a, 0, arr.length);
59.2773 + if (a.length > arr.length)
59.2774 + a[arr.length] = null;
59.2775 + return a;
59.2776 + }
59.2777 +
59.2778 + /**
59.2779 + * This method is overridden to protect the backing set against
59.2780 + * an object with a nefarious equals function that senses
59.2781 + * that the equality-candidate is Map.Entry and calls its
59.2782 + * setValue method.
59.2783 + */
59.2784 + public boolean contains(Object o) {
59.2785 + if (!(o instanceof Map.Entry))
59.2786 + return false;
59.2787 + Map.Entry<?,?> e = (Map.Entry<?,?>) o;
59.2788 + return s.contains(
59.2789 + (e instanceof CheckedEntry) ? e : checkedEntry(e, valueType));
59.2790 + }
59.2791 +
59.2792 + /**
59.2793 + * The bulk collection methods are overridden to protect
59.2794 + * against an unscrupulous collection whose contains(Object o)
59.2795 + * method senses when o is a Map.Entry, and calls o.setValue.
59.2796 + */
59.2797 + public boolean containsAll(Collection<?> c) {
59.2798 + for (Object o : c)
59.2799 + if (!contains(o)) // Invokes safe contains() above
59.2800 + return false;
59.2801 + return true;
59.2802 + }
59.2803 +
59.2804 + public boolean remove(Object o) {
59.2805 + if (!(o instanceof Map.Entry))
59.2806 + return false;
59.2807 + return s.remove(new AbstractMap.SimpleImmutableEntry
59.2808 + <>((Map.Entry<?,?>)o));
59.2809 + }
59.2810 +
59.2811 + public boolean removeAll(Collection<?> c) {
59.2812 + return batchRemove(c, false);
59.2813 + }
59.2814 + public boolean retainAll(Collection<?> c) {
59.2815 + return batchRemove(c, true);
59.2816 + }
59.2817 + private boolean batchRemove(Collection<?> c, boolean complement) {
59.2818 + boolean modified = false;
59.2819 + Iterator<Map.Entry<K,V>> it = iterator();
59.2820 + while (it.hasNext()) {
59.2821 + if (c.contains(it.next()) != complement) {
59.2822 + it.remove();
59.2823 + modified = true;
59.2824 + }
59.2825 + }
59.2826 + return modified;
59.2827 + }
59.2828 +
59.2829 + public boolean equals(Object o) {
59.2830 + if (o == this)
59.2831 + return true;
59.2832 + if (!(o instanceof Set))
59.2833 + return false;
59.2834 + Set<?> that = (Set<?>) o;
59.2835 + return that.size() == s.size()
59.2836 + && containsAll(that); // Invokes safe containsAll() above
59.2837 + }
59.2838 +
59.2839 + static <K,V,T> CheckedEntry<K,V,T> checkedEntry(Map.Entry<K,V> e,
59.2840 + Class<T> valueType) {
59.2841 + return new CheckedEntry<>(e, valueType);
59.2842 + }
59.2843 +
59.2844 + /**
59.2845 + * This "wrapper class" serves two purposes: it prevents
59.2846 + * the client from modifying the backing Map, by short-circuiting
59.2847 + * the setValue method, and it protects the backing Map against
59.2848 + * an ill-behaved Map.Entry that attempts to modify another
59.2849 + * Map.Entry when asked to perform an equality check.
59.2850 + */
59.2851 + private static class CheckedEntry<K,V,T> implements Map.Entry<K,V> {
59.2852 + private final Map.Entry<K, V> e;
59.2853 + private final Class<T> valueType;
59.2854 +
59.2855 + CheckedEntry(Map.Entry<K, V> e, Class<T> valueType) {
59.2856 + this.e = e;
59.2857 + this.valueType = valueType;
59.2858 + }
59.2859 +
59.2860 + public K getKey() { return e.getKey(); }
59.2861 + public V getValue() { return e.getValue(); }
59.2862 + public int hashCode() { return e.hashCode(); }
59.2863 + public String toString() { return e.toString(); }
59.2864 +
59.2865 + public V setValue(V value) {
59.2866 + if (value != null && !valueType.isInstance(value))
59.2867 + throw new ClassCastException(badValueMsg(value));
59.2868 + return e.setValue(value);
59.2869 + }
59.2870 +
59.2871 + private String badValueMsg(Object value) {
59.2872 + return "Attempt to insert " + value.getClass() +
59.2873 + " value into map with value type " + valueType;
59.2874 + }
59.2875 +
59.2876 + public boolean equals(Object o) {
59.2877 + if (o == this)
59.2878 + return true;
59.2879 + if (!(o instanceof Map.Entry))
59.2880 + return false;
59.2881 + return e.equals(new AbstractMap.SimpleImmutableEntry
59.2882 + <>((Map.Entry<?,?>)o));
59.2883 + }
59.2884 + }
59.2885 + }
59.2886 + }
59.2887 +
59.2888 + /**
59.2889 + * Returns a dynamically typesafe view of the specified sorted map.
59.2890 + * Any attempt to insert a mapping whose key or value have the wrong
59.2891 + * type will result in an immediate {@link ClassCastException}.
59.2892 + * Similarly, any attempt to modify the value currently associated with
59.2893 + * a key will result in an immediate {@link ClassCastException},
59.2894 + * whether the modification is attempted directly through the map
59.2895 + * itself, or through a {@link Map.Entry} instance obtained from the
59.2896 + * map's {@link Map#entrySet() entry set} view.
59.2897 + *
59.2898 + * <p>Assuming a map contains no incorrectly typed keys or values
59.2899 + * prior to the time a dynamically typesafe view is generated, and
59.2900 + * that all subsequent access to the map takes place through the view
59.2901 + * (or one of its collection views), it is <i>guaranteed</i> that the
59.2902 + * map cannot contain an incorrectly typed key or value.
59.2903 + *
59.2904 + * <p>A discussion of the use of dynamically typesafe views may be
59.2905 + * found in the documentation for the {@link #checkedCollection
59.2906 + * checkedCollection} method.
59.2907 + *
59.2908 + * <p>The returned map will be serializable if the specified map is
59.2909 + * serializable.
59.2910 + *
59.2911 + * <p>Since {@code null} is considered to be a value of any reference
59.2912 + * type, the returned map permits insertion of null keys or values
59.2913 + * whenever the backing map does.
59.2914 + *
59.2915 + * @param m the map for which a dynamically typesafe view is to be
59.2916 + * returned
59.2917 + * @param keyType the type of key that {@code m} is permitted to hold
59.2918 + * @param valueType the type of value that {@code m} is permitted to hold
59.2919 + * @return a dynamically typesafe view of the specified map
59.2920 + * @since 1.5
59.2921 + */
59.2922 + public static <K,V> SortedMap<K,V> checkedSortedMap(SortedMap<K, V> m,
59.2923 + Class<K> keyType,
59.2924 + Class<V> valueType) {
59.2925 + return new CheckedSortedMap<>(m, keyType, valueType);
59.2926 + }
59.2927 +
59.2928 + /**
59.2929 + * @serial include
59.2930 + */
59.2931 + static class CheckedSortedMap<K,V> extends CheckedMap<K,V>
59.2932 + implements SortedMap<K,V>, Serializable
59.2933 + {
59.2934 + private static final long serialVersionUID = 1599671320688067438L;
59.2935 +
59.2936 + private final SortedMap<K, V> sm;
59.2937 +
59.2938 + CheckedSortedMap(SortedMap<K, V> m,
59.2939 + Class<K> keyType, Class<V> valueType) {
59.2940 + super(m, keyType, valueType);
59.2941 + sm = m;
59.2942 + }
59.2943 +
59.2944 + public Comparator<? super K> comparator() { return sm.comparator(); }
59.2945 + public K firstKey() { return sm.firstKey(); }
59.2946 + public K lastKey() { return sm.lastKey(); }
59.2947 +
59.2948 + public SortedMap<K,V> subMap(K fromKey, K toKey) {
59.2949 + return checkedSortedMap(sm.subMap(fromKey, toKey),
59.2950 + keyType, valueType);
59.2951 + }
59.2952 + public SortedMap<K,V> headMap(K toKey) {
59.2953 + return checkedSortedMap(sm.headMap(toKey), keyType, valueType);
59.2954 + }
59.2955 + public SortedMap<K,V> tailMap(K fromKey) {
59.2956 + return checkedSortedMap(sm.tailMap(fromKey), keyType, valueType);
59.2957 + }
59.2958 + }
59.2959 +
59.2960 + // Empty collections
59.2961 +
59.2962 + /**
59.2963 + * Returns an iterator that has no elements. More precisely,
59.2964 + *
59.2965 + * <ul compact>
59.2966 + *
59.2967 + * <li>{@link Iterator#hasNext hasNext} always returns {@code
59.2968 + * false}.
59.2969 + *
59.2970 + * <li>{@link Iterator#next next} always throws {@link
59.2971 + * NoSuchElementException}.
59.2972 + *
59.2973 + * <li>{@link Iterator#remove remove} always throws {@link
59.2974 + * IllegalStateException}.
59.2975 + *
59.2976 + * </ul>
59.2977 + *
59.2978 + * <p>Implementations of this method are permitted, but not
59.2979 + * required, to return the same object from multiple invocations.
59.2980 + *
59.2981 + * @return an empty iterator
59.2982 + * @since 1.7
59.2983 + */
59.2984 + @SuppressWarnings("unchecked")
59.2985 + public static <T> Iterator<T> emptyIterator() {
59.2986 + return (Iterator<T>) EmptyIterator.EMPTY_ITERATOR;
59.2987 + }
59.2988 +
59.2989 + private static class EmptyIterator<E> implements Iterator<E> {
59.2990 + static final EmptyIterator<Object> EMPTY_ITERATOR
59.2991 + = new EmptyIterator<>();
59.2992 +
59.2993 + public boolean hasNext() { return false; }
59.2994 + public E next() { throw new NoSuchElementException(); }
59.2995 + public void remove() { throw new IllegalStateException(); }
59.2996 + }
59.2997 +
59.2998 + /**
59.2999 + * Returns a list iterator that has no elements. More precisely,
59.3000 + *
59.3001 + * <ul compact>
59.3002 + *
59.3003 + * <li>{@link Iterator#hasNext hasNext} and {@link
59.3004 + * ListIterator#hasPrevious hasPrevious} always return {@code
59.3005 + * false}.
59.3006 + *
59.3007 + * <li>{@link Iterator#next next} and {@link ListIterator#previous
59.3008 + * previous} always throw {@link NoSuchElementException}.
59.3009 + *
59.3010 + * <li>{@link Iterator#remove remove} and {@link ListIterator#set
59.3011 + * set} always throw {@link IllegalStateException}.
59.3012 + *
59.3013 + * <li>{@link ListIterator#add add} always throws {@link
59.3014 + * UnsupportedOperationException}.
59.3015 + *
59.3016 + * <li>{@link ListIterator#nextIndex nextIndex} always returns
59.3017 + * {@code 0} .
59.3018 + *
59.3019 + * <li>{@link ListIterator#previousIndex previousIndex} always
59.3020 + * returns {@code -1}.
59.3021 + *
59.3022 + * </ul>
59.3023 + *
59.3024 + * <p>Implementations of this method are permitted, but not
59.3025 + * required, to return the same object from multiple invocations.
59.3026 + *
59.3027 + * @return an empty list iterator
59.3028 + * @since 1.7
59.3029 + */
59.3030 + @SuppressWarnings("unchecked")
59.3031 + public static <T> ListIterator<T> emptyListIterator() {
59.3032 + return (ListIterator<T>) EmptyListIterator.EMPTY_ITERATOR;
59.3033 + }
59.3034 +
59.3035 + private static class EmptyListIterator<E>
59.3036 + extends EmptyIterator<E>
59.3037 + implements ListIterator<E>
59.3038 + {
59.3039 + static final EmptyListIterator<Object> EMPTY_ITERATOR
59.3040 + = new EmptyListIterator<>();
59.3041 +
59.3042 + public boolean hasPrevious() { return false; }
59.3043 + public E previous() { throw new NoSuchElementException(); }
59.3044 + public int nextIndex() { return 0; }
59.3045 + public int previousIndex() { return -1; }
59.3046 + public void set(E e) { throw new IllegalStateException(); }
59.3047 + public void add(E e) { throw new UnsupportedOperationException(); }
59.3048 + }
59.3049 +
59.3050 + /**
59.3051 + * Returns an enumeration that has no elements. More precisely,
59.3052 + *
59.3053 + * <ul compact>
59.3054 + *
59.3055 + * <li>{@link Enumeration#hasMoreElements hasMoreElements} always
59.3056 + * returns {@code false}.
59.3057 + *
59.3058 + * <li> {@link Enumeration#nextElement nextElement} always throws
59.3059 + * {@link NoSuchElementException}.
59.3060 + *
59.3061 + * </ul>
59.3062 + *
59.3063 + * <p>Implementations of this method are permitted, but not
59.3064 + * required, to return the same object from multiple invocations.
59.3065 + *
59.3066 + * @return an empty enumeration
59.3067 + * @since 1.7
59.3068 + */
59.3069 + @SuppressWarnings("unchecked")
59.3070 + public static <T> Enumeration<T> emptyEnumeration() {
59.3071 + return (Enumeration<T>) EmptyEnumeration.EMPTY_ENUMERATION;
59.3072 + }
59.3073 +
59.3074 + private static class EmptyEnumeration<E> implements Enumeration<E> {
59.3075 + static final EmptyEnumeration<Object> EMPTY_ENUMERATION
59.3076 + = new EmptyEnumeration<>();
59.3077 +
59.3078 + public boolean hasMoreElements() { return false; }
59.3079 + public E nextElement() { throw new NoSuchElementException(); }
59.3080 + }
59.3081 +
59.3082 + /**
59.3083 + * The empty set (immutable). This set is serializable.
59.3084 + *
59.3085 + * @see #emptySet()
59.3086 + */
59.3087 + @SuppressWarnings("unchecked")
59.3088 + public static final Set EMPTY_SET = new EmptySet<>();
59.3089 +
59.3090 + /**
59.3091 + * Returns the empty set (immutable). This set is serializable.
59.3092 + * Unlike the like-named field, this method is parameterized.
59.3093 + *
59.3094 + * <p>This example illustrates the type-safe way to obtain an empty set:
59.3095 + * <pre>
59.3096 + * Set<String> s = Collections.emptySet();
59.3097 + * </pre>
59.3098 + * Implementation note: Implementations of this method need not
59.3099 + * create a separate <tt>Set</tt> object for each call. Using this
59.3100 + * method is likely to have comparable cost to using the like-named
59.3101 + * field. (Unlike this method, the field does not provide type safety.)
59.3102 + *
59.3103 + * @see #EMPTY_SET
59.3104 + * @since 1.5
59.3105 + */
59.3106 + @SuppressWarnings("unchecked")
59.3107 + public static final <T> Set<T> emptySet() {
59.3108 + return (Set<T>) EMPTY_SET;
59.3109 + }
59.3110 +
59.3111 + /**
59.3112 + * @serial include
59.3113 + */
59.3114 + private static class EmptySet<E>
59.3115 + extends AbstractSet<E>
59.3116 + implements Serializable
59.3117 + {
59.3118 + private static final long serialVersionUID = 1582296315990362920L;
59.3119 +
59.3120 + public Iterator<E> iterator() { return emptyIterator(); }
59.3121 +
59.3122 + public int size() {return 0;}
59.3123 + public boolean isEmpty() {return true;}
59.3124 +
59.3125 + public boolean contains(Object obj) {return false;}
59.3126 + public boolean containsAll(Collection<?> c) { return c.isEmpty(); }
59.3127 +
59.3128 + public Object[] toArray() { return new Object[0]; }
59.3129 +
59.3130 + public <T> T[] toArray(T[] a) {
59.3131 + if (a.length > 0)
59.3132 + a[0] = null;
59.3133 + return a;
59.3134 + }
59.3135 +
59.3136 + // Preserves singleton property
59.3137 + private Object readResolve() {
59.3138 + return EMPTY_SET;
59.3139 + }
59.3140 + }
59.3141 +
59.3142 + /**
59.3143 + * The empty list (immutable). This list is serializable.
59.3144 + *
59.3145 + * @see #emptyList()
59.3146 + */
59.3147 + @SuppressWarnings("unchecked")
59.3148 + public static final List EMPTY_LIST = new EmptyList<>();
59.3149 +
59.3150 + /**
59.3151 + * Returns the empty list (immutable). This list is serializable.
59.3152 + *
59.3153 + * <p>This example illustrates the type-safe way to obtain an empty list:
59.3154 + * <pre>
59.3155 + * List<String> s = Collections.emptyList();
59.3156 + * </pre>
59.3157 + * Implementation note: Implementations of this method need not
59.3158 + * create a separate <tt>List</tt> object for each call. Using this
59.3159 + * method is likely to have comparable cost to using the like-named
59.3160 + * field. (Unlike this method, the field does not provide type safety.)
59.3161 + *
59.3162 + * @see #EMPTY_LIST
59.3163 + * @since 1.5
59.3164 + */
59.3165 + @SuppressWarnings("unchecked")
59.3166 + public static final <T> List<T> emptyList() {
59.3167 + return (List<T>) EMPTY_LIST;
59.3168 + }
59.3169 +
59.3170 + /**
59.3171 + * @serial include
59.3172 + */
59.3173 + private static class EmptyList<E>
59.3174 + extends AbstractList<E>
59.3175 + implements RandomAccess, Serializable {
59.3176 + private static final long serialVersionUID = 8842843931221139166L;
59.3177 +
59.3178 + public Iterator<E> iterator() {
59.3179 + return emptyIterator();
59.3180 + }
59.3181 + public ListIterator<E> listIterator() {
59.3182 + return emptyListIterator();
59.3183 + }
59.3184 +
59.3185 + public int size() {return 0;}
59.3186 + public boolean isEmpty() {return true;}
59.3187 +
59.3188 + public boolean contains(Object obj) {return false;}
59.3189 + public boolean containsAll(Collection<?> c) { return c.isEmpty(); }
59.3190 +
59.3191 + public Object[] toArray() { return new Object[0]; }
59.3192 +
59.3193 + public <T> T[] toArray(T[] a) {
59.3194 + if (a.length > 0)
59.3195 + a[0] = null;
59.3196 + return a;
59.3197 + }
59.3198 +
59.3199 + public E get(int index) {
59.3200 + throw new IndexOutOfBoundsException("Index: "+index);
59.3201 + }
59.3202 +
59.3203 + public boolean equals(Object o) {
59.3204 + return (o instanceof List) && ((List<?>)o).isEmpty();
59.3205 + }
59.3206 +
59.3207 + public int hashCode() { return 1; }
59.3208 +
59.3209 + // Preserves singleton property
59.3210 + private Object readResolve() {
59.3211 + return EMPTY_LIST;
59.3212 + }
59.3213 + }
59.3214 +
59.3215 + /**
59.3216 + * The empty map (immutable). This map is serializable.
59.3217 + *
59.3218 + * @see #emptyMap()
59.3219 + * @since 1.3
59.3220 + */
59.3221 + @SuppressWarnings("unchecked")
59.3222 + public static final Map EMPTY_MAP = new EmptyMap<>();
59.3223 +
59.3224 + /**
59.3225 + * Returns the empty map (immutable). This map is serializable.
59.3226 + *
59.3227 + * <p>This example illustrates the type-safe way to obtain an empty set:
59.3228 + * <pre>
59.3229 + * Map<String, Date> s = Collections.emptyMap();
59.3230 + * </pre>
59.3231 + * Implementation note: Implementations of this method need not
59.3232 + * create a separate <tt>Map</tt> object for each call. Using this
59.3233 + * method is likely to have comparable cost to using the like-named
59.3234 + * field. (Unlike this method, the field does not provide type safety.)
59.3235 + *
59.3236 + * @see #EMPTY_MAP
59.3237 + * @since 1.5
59.3238 + */
59.3239 + @SuppressWarnings("unchecked")
59.3240 + public static final <K,V> Map<K,V> emptyMap() {
59.3241 + return (Map<K,V>) EMPTY_MAP;
59.3242 + }
59.3243 +
59.3244 + /**
59.3245 + * @serial include
59.3246 + */
59.3247 + private static class EmptyMap<K,V>
59.3248 + extends AbstractMap<K,V>
59.3249 + implements Serializable
59.3250 + {
59.3251 + private static final long serialVersionUID = 6428348081105594320L;
59.3252 +
59.3253 + public int size() {return 0;}
59.3254 + public boolean isEmpty() {return true;}
59.3255 + public boolean containsKey(Object key) {return false;}
59.3256 + public boolean containsValue(Object value) {return false;}
59.3257 + public V get(Object key) {return null;}
59.3258 + public Set<K> keySet() {return emptySet();}
59.3259 + public Collection<V> values() {return emptySet();}
59.3260 + public Set<Map.Entry<K,V>> entrySet() {return emptySet();}
59.3261 +
59.3262 + public boolean equals(Object o) {
59.3263 + return (o instanceof Map) && ((Map<?,?>)o).isEmpty();
59.3264 + }
59.3265 +
59.3266 + public int hashCode() {return 0;}
59.3267 +
59.3268 + // Preserves singleton property
59.3269 + private Object readResolve() {
59.3270 + return EMPTY_MAP;
59.3271 + }
59.3272 + }
59.3273 +
59.3274 + // Singleton collections
59.3275 +
59.3276 + /**
59.3277 + * Returns an immutable set containing only the specified object.
59.3278 + * The returned set is serializable.
59.3279 + *
59.3280 + * @param o the sole object to be stored in the returned set.
59.3281 + * @return an immutable set containing only the specified object.
59.3282 + */
59.3283 + public static <T> Set<T> singleton(T o) {
59.3284 + return new SingletonSet<>(o);
59.3285 + }
59.3286 +
59.3287 + static <E> Iterator<E> singletonIterator(final E e) {
59.3288 + return new Iterator<E>() {
59.3289 + private boolean hasNext = true;
59.3290 + public boolean hasNext() {
59.3291 + return hasNext;
59.3292 + }
59.3293 + public E next() {
59.3294 + if (hasNext) {
59.3295 + hasNext = false;
59.3296 + return e;
59.3297 + }
59.3298 + throw new NoSuchElementException();
59.3299 + }
59.3300 + public void remove() {
59.3301 + throw new UnsupportedOperationException();
59.3302 + }
59.3303 + };
59.3304 + }
59.3305 +
59.3306 + /**
59.3307 + * @serial include
59.3308 + */
59.3309 + private static class SingletonSet<E>
59.3310 + extends AbstractSet<E>
59.3311 + implements Serializable
59.3312 + {
59.3313 + private static final long serialVersionUID = 3193687207550431679L;
59.3314 +
59.3315 + private final E element;
59.3316 +
59.3317 + SingletonSet(E e) {element = e;}
59.3318 +
59.3319 + public Iterator<E> iterator() {
59.3320 + return singletonIterator(element);
59.3321 + }
59.3322 +
59.3323 + public int size() {return 1;}
59.3324 +
59.3325 + public boolean contains(Object o) {return eq(o, element);}
59.3326 + }
59.3327 +
59.3328 + /**
59.3329 + * Returns an immutable list containing only the specified object.
59.3330 + * The returned list is serializable.
59.3331 + *
59.3332 + * @param o the sole object to be stored in the returned list.
59.3333 + * @return an immutable list containing only the specified object.
59.3334 + * @since 1.3
59.3335 + */
59.3336 + public static <T> List<T> singletonList(T o) {
59.3337 + return new SingletonList<>(o);
59.3338 + }
59.3339 +
59.3340 + /**
59.3341 + * @serial include
59.3342 + */
59.3343 + private static class SingletonList<E>
59.3344 + extends AbstractList<E>
59.3345 + implements RandomAccess, Serializable {
59.3346 +
59.3347 + private static final long serialVersionUID = 3093736618740652951L;
59.3348 +
59.3349 + private final E element;
59.3350 +
59.3351 + SingletonList(E obj) {element = obj;}
59.3352 +
59.3353 + public Iterator<E> iterator() {
59.3354 + return singletonIterator(element);
59.3355 + }
59.3356 +
59.3357 + public int size() {return 1;}
59.3358 +
59.3359 + public boolean contains(Object obj) {return eq(obj, element);}
59.3360 +
59.3361 + public E get(int index) {
59.3362 + if (index != 0)
59.3363 + throw new IndexOutOfBoundsException("Index: "+index+", Size: 1");
59.3364 + return element;
59.3365 + }
59.3366 + }
59.3367 +
59.3368 + /**
59.3369 + * Returns an immutable map, mapping only the specified key to the
59.3370 + * specified value. The returned map is serializable.
59.3371 + *
59.3372 + * @param key the sole key to be stored in the returned map.
59.3373 + * @param value the value to which the returned map maps <tt>key</tt>.
59.3374 + * @return an immutable map containing only the specified key-value
59.3375 + * mapping.
59.3376 + * @since 1.3
59.3377 + */
59.3378 + public static <K,V> Map<K,V> singletonMap(K key, V value) {
59.3379 + return new SingletonMap<>(key, value);
59.3380 + }
59.3381 +
59.3382 + /**
59.3383 + * @serial include
59.3384 + */
59.3385 + private static class SingletonMap<K,V>
59.3386 + extends AbstractMap<K,V>
59.3387 + implements Serializable {
59.3388 + private static final long serialVersionUID = -6979724477215052911L;
59.3389 +
59.3390 + private final K k;
59.3391 + private final V v;
59.3392 +
59.3393 + SingletonMap(K key, V value) {
59.3394 + k = key;
59.3395 + v = value;
59.3396 + }
59.3397 +
59.3398 + public int size() {return 1;}
59.3399 +
59.3400 + public boolean isEmpty() {return false;}
59.3401 +
59.3402 + public boolean containsKey(Object key) {return eq(key, k);}
59.3403 +
59.3404 + public boolean containsValue(Object value) {return eq(value, v);}
59.3405 +
59.3406 + public V get(Object key) {return (eq(key, k) ? v : null);}
59.3407 +
59.3408 + private transient Set<K> keySet = null;
59.3409 + private transient Set<Map.Entry<K,V>> entrySet = null;
59.3410 + private transient Collection<V> values = null;
59.3411 +
59.3412 + public Set<K> keySet() {
59.3413 + if (keySet==null)
59.3414 + keySet = singleton(k);
59.3415 + return keySet;
59.3416 + }
59.3417 +
59.3418 + public Set<Map.Entry<K,V>> entrySet() {
59.3419 + if (entrySet==null)
59.3420 + entrySet = Collections.<Map.Entry<K,V>>singleton(
59.3421 + new SimpleImmutableEntry<>(k, v));
59.3422 + return entrySet;
59.3423 + }
59.3424 +
59.3425 + public Collection<V> values() {
59.3426 + if (values==null)
59.3427 + values = singleton(v);
59.3428 + return values;
59.3429 + }
59.3430 +
59.3431 + }
59.3432 +
59.3433 + // Miscellaneous
59.3434 +
59.3435 + /**
59.3436 + * Returns an immutable list consisting of <tt>n</tt> copies of the
59.3437 + * specified object. The newly allocated data object is tiny (it contains
59.3438 + * a single reference to the data object). This method is useful in
59.3439 + * combination with the <tt>List.addAll</tt> method to grow lists.
59.3440 + * The returned list is serializable.
59.3441 + *
59.3442 + * @param n the number of elements in the returned list.
59.3443 + * @param o the element to appear repeatedly in the returned list.
59.3444 + * @return an immutable list consisting of <tt>n</tt> copies of the
59.3445 + * specified object.
59.3446 + * @throws IllegalArgumentException if {@code n < 0}
59.3447 + * @see List#addAll(Collection)
59.3448 + * @see List#addAll(int, Collection)
59.3449 + */
59.3450 + public static <T> List<T> nCopies(int n, T o) {
59.3451 + if (n < 0)
59.3452 + throw new IllegalArgumentException("List length = " + n);
59.3453 + return new CopiesList<>(n, o);
59.3454 + }
59.3455 +
59.3456 + /**
59.3457 + * @serial include
59.3458 + */
59.3459 + private static class CopiesList<E>
59.3460 + extends AbstractList<E>
59.3461 + implements RandomAccess, Serializable
59.3462 + {
59.3463 + private static final long serialVersionUID = 2739099268398711800L;
59.3464 +
59.3465 + final int n;
59.3466 + final E element;
59.3467 +
59.3468 + CopiesList(int n, E e) {
59.3469 + assert n >= 0;
59.3470 + this.n = n;
59.3471 + element = e;
59.3472 + }
59.3473 +
59.3474 + public int size() {
59.3475 + return n;
59.3476 + }
59.3477 +
59.3478 + public boolean contains(Object obj) {
59.3479 + return n != 0 && eq(obj, element);
59.3480 + }
59.3481 +
59.3482 + public int indexOf(Object o) {
59.3483 + return contains(o) ? 0 : -1;
59.3484 + }
59.3485 +
59.3486 + public int lastIndexOf(Object o) {
59.3487 + return contains(o) ? n - 1 : -1;
59.3488 + }
59.3489 +
59.3490 + public E get(int index) {
59.3491 + if (index < 0 || index >= n)
59.3492 + throw new IndexOutOfBoundsException("Index: "+index+
59.3493 + ", Size: "+n);
59.3494 + return element;
59.3495 + }
59.3496 +
59.3497 + public Object[] toArray() {
59.3498 + final Object[] a = new Object[n];
59.3499 + if (element != null)
59.3500 + Arrays.fill(a, 0, n, element);
59.3501 + return a;
59.3502 + }
59.3503 +
59.3504 + public <T> T[] toArray(T[] a) {
59.3505 + final int n = this.n;
59.3506 + if (a.length < n) {
59.3507 + a = (T[])java.lang.reflect.Array
59.3508 + .newInstance(a.getClass().getComponentType(), n);
59.3509 + if (element != null)
59.3510 + Arrays.fill(a, 0, n, element);
59.3511 + } else {
59.3512 + Arrays.fill(a, 0, n, element);
59.3513 + if (a.length > n)
59.3514 + a[n] = null;
59.3515 + }
59.3516 + return a;
59.3517 + }
59.3518 +
59.3519 + public List<E> subList(int fromIndex, int toIndex) {
59.3520 + if (fromIndex < 0)
59.3521 + throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
59.3522 + if (toIndex > n)
59.3523 + throw new IndexOutOfBoundsException("toIndex = " + toIndex);
59.3524 + if (fromIndex > toIndex)
59.3525 + throw new IllegalArgumentException("fromIndex(" + fromIndex +
59.3526 + ") > toIndex(" + toIndex + ")");
59.3527 + return new CopiesList<>(toIndex - fromIndex, element);
59.3528 + }
59.3529 + }
59.3530 +
59.3531 + /**
59.3532 + * Returns a comparator that imposes the reverse of the <em>natural
59.3533 + * ordering</em> on a collection of objects that implement the
59.3534 + * {@code Comparable} interface. (The natural ordering is the ordering
59.3535 + * imposed by the objects' own {@code compareTo} method.) This enables a
59.3536 + * simple idiom for sorting (or maintaining) collections (or arrays) of
59.3537 + * objects that implement the {@code Comparable} interface in
59.3538 + * reverse-natural-order. For example, suppose {@code a} is an array of
59.3539 + * strings. Then: <pre>
59.3540 + * Arrays.sort(a, Collections.reverseOrder());
59.3541 + * </pre> sorts the array in reverse-lexicographic (alphabetical) order.<p>
59.3542 + *
59.3543 + * The returned comparator is serializable.
59.3544 + *
59.3545 + * @return A comparator that imposes the reverse of the <i>natural
59.3546 + * ordering</i> on a collection of objects that implement
59.3547 + * the <tt>Comparable</tt> interface.
59.3548 + * @see Comparable
59.3549 + */
59.3550 + public static <T> Comparator<T> reverseOrder() {
59.3551 + return (Comparator<T>) ReverseComparator.REVERSE_ORDER;
59.3552 + }
59.3553 +
59.3554 + /**
59.3555 + * @serial include
59.3556 + */
59.3557 + private static class ReverseComparator
59.3558 + implements Comparator<Comparable<Object>>, Serializable {
59.3559 +
59.3560 + private static final long serialVersionUID = 7207038068494060240L;
59.3561 +
59.3562 + static final ReverseComparator REVERSE_ORDER
59.3563 + = new ReverseComparator();
59.3564 +
59.3565 + public int compare(Comparable<Object> c1, Comparable<Object> c2) {
59.3566 + return c2.compareTo(c1);
59.3567 + }
59.3568 +
59.3569 + private Object readResolve() { return reverseOrder(); }
59.3570 + }
59.3571 +
59.3572 + /**
59.3573 + * Returns a comparator that imposes the reverse ordering of the specified
59.3574 + * comparator. If the specified comparator is {@code null}, this method is
59.3575 + * equivalent to {@link #reverseOrder()} (in other words, it returns a
59.3576 + * comparator that imposes the reverse of the <em>natural ordering</em> on
59.3577 + * a collection of objects that implement the Comparable interface).
59.3578 + *
59.3579 + * <p>The returned comparator is serializable (assuming the specified
59.3580 + * comparator is also serializable or {@code null}).
59.3581 + *
59.3582 + * @param cmp a comparator who's ordering is to be reversed by the returned
59.3583 + * comparator or {@code null}
59.3584 + * @return A comparator that imposes the reverse ordering of the
59.3585 + * specified comparator.
59.3586 + * @since 1.5
59.3587 + */
59.3588 + public static <T> Comparator<T> reverseOrder(Comparator<T> cmp) {
59.3589 + if (cmp == null)
59.3590 + return reverseOrder();
59.3591 +
59.3592 + if (cmp instanceof ReverseComparator2)
59.3593 + return ((ReverseComparator2<T>)cmp).cmp;
59.3594 +
59.3595 + return new ReverseComparator2<>(cmp);
59.3596 + }
59.3597 +
59.3598 + /**
59.3599 + * @serial include
59.3600 + */
59.3601 + private static class ReverseComparator2<T> implements Comparator<T>,
59.3602 + Serializable
59.3603 + {
59.3604 + private static final long serialVersionUID = 4374092139857L;
59.3605 +
59.3606 + /**
59.3607 + * The comparator specified in the static factory. This will never
59.3608 + * be null, as the static factory returns a ReverseComparator
59.3609 + * instance if its argument is null.
59.3610 + *
59.3611 + * @serial
59.3612 + */
59.3613 + final Comparator<T> cmp;
59.3614 +
59.3615 + ReverseComparator2(Comparator<T> cmp) {
59.3616 + assert cmp != null;
59.3617 + this.cmp = cmp;
59.3618 + }
59.3619 +
59.3620 + public int compare(T t1, T t2) {
59.3621 + return cmp.compare(t2, t1);
59.3622 + }
59.3623 +
59.3624 + public boolean equals(Object o) {
59.3625 + return (o == this) ||
59.3626 + (o instanceof ReverseComparator2 &&
59.3627 + cmp.equals(((ReverseComparator2)o).cmp));
59.3628 + }
59.3629 +
59.3630 + public int hashCode() {
59.3631 + return cmp.hashCode() ^ Integer.MIN_VALUE;
59.3632 + }
59.3633 + }
59.3634 +
59.3635 + /**
59.3636 + * Returns an enumeration over the specified collection. This provides
59.3637 + * interoperability with legacy APIs that require an enumeration
59.3638 + * as input.
59.3639 + *
59.3640 + * @param c the collection for which an enumeration is to be returned.
59.3641 + * @return an enumeration over the specified collection.
59.3642 + * @see Enumeration
59.3643 + */
59.3644 + public static <T> Enumeration<T> enumeration(final Collection<T> c) {
59.3645 + return new Enumeration<T>() {
59.3646 + private final Iterator<T> i = c.iterator();
59.3647 +
59.3648 + public boolean hasMoreElements() {
59.3649 + return i.hasNext();
59.3650 + }
59.3651 +
59.3652 + public T nextElement() {
59.3653 + return i.next();
59.3654 + }
59.3655 + };
59.3656 + }
59.3657 +
59.3658 + /**
59.3659 + * Returns an array list containing the elements returned by the
59.3660 + * specified enumeration in the order they are returned by the
59.3661 + * enumeration. This method provides interoperability between
59.3662 + * legacy APIs that return enumerations and new APIs that require
59.3663 + * collections.
59.3664 + *
59.3665 + * @param e enumeration providing elements for the returned
59.3666 + * array list
59.3667 + * @return an array list containing the elements returned
59.3668 + * by the specified enumeration.
59.3669 + * @since 1.4
59.3670 + * @see Enumeration
59.3671 + * @see ArrayList
59.3672 + */
59.3673 + public static <T> ArrayList<T> list(Enumeration<T> e) {
59.3674 + ArrayList<T> l = new ArrayList<>();
59.3675 + while (e.hasMoreElements())
59.3676 + l.add(e.nextElement());
59.3677 + return l;
59.3678 + }
59.3679 +
59.3680 + /**
59.3681 + * Returns true if the specified arguments are equal, or both null.
59.3682 + */
59.3683 + static boolean eq(Object o1, Object o2) {
59.3684 + return o1==null ? o2==null : o1.equals(o2);
59.3685 + }
59.3686 +
59.3687 + /**
59.3688 + * Returns the number of elements in the specified collection equal to the
59.3689 + * specified object. More formally, returns the number of elements
59.3690 + * <tt>e</tt> in the collection such that
59.3691 + * <tt>(o == null ? e == null : o.equals(e))</tt>.
59.3692 + *
59.3693 + * @param c the collection in which to determine the frequency
59.3694 + * of <tt>o</tt>
59.3695 + * @param o the object whose frequency is to be determined
59.3696 + * @throws NullPointerException if <tt>c</tt> is null
59.3697 + * @since 1.5
59.3698 + */
59.3699 + public static int frequency(Collection<?> c, Object o) {
59.3700 + int result = 0;
59.3701 + if (o == null) {
59.3702 + for (Object e : c)
59.3703 + if (e == null)
59.3704 + result++;
59.3705 + } else {
59.3706 + for (Object e : c)
59.3707 + if (o.equals(e))
59.3708 + result++;
59.3709 + }
59.3710 + return result;
59.3711 + }
59.3712 +
59.3713 + /**
59.3714 + * Returns {@code true} if the two specified collections have no
59.3715 + * elements in common.
59.3716 + *
59.3717 + * <p>Care must be exercised if this method is used on collections that
59.3718 + * do not comply with the general contract for {@code Collection}.
59.3719 + * Implementations may elect to iterate over either collection and test
59.3720 + * for containment in the other collection (or to perform any equivalent
59.3721 + * computation). If either collection uses a nonstandard equality test
59.3722 + * (as does a {@link SortedSet} whose ordering is not <em>compatible with
59.3723 + * equals</em>, or the key set of an {@link IdentityHashMap}), both
59.3724 + * collections must use the same nonstandard equality test, or the
59.3725 + * result of this method is undefined.
59.3726 + *
59.3727 + * <p>Care must also be exercised when using collections that have
59.3728 + * restrictions on the elements that they may contain. Collection
59.3729 + * implementations are allowed to throw exceptions for any operation
59.3730 + * involving elements they deem ineligible. For absolute safety the
59.3731 + * specified collections should contain only elements which are
59.3732 + * eligible elements for both collections.
59.3733 + *
59.3734 + * <p>Note that it is permissible to pass the same collection in both
59.3735 + * parameters, in which case the method will return {@code true} if and
59.3736 + * only if the collection is empty.
59.3737 + *
59.3738 + * @param c1 a collection
59.3739 + * @param c2 a collection
59.3740 + * @return {@code true} if the two specified collections have no
59.3741 + * elements in common.
59.3742 + * @throws NullPointerException if either collection is {@code null}.
59.3743 + * @throws NullPointerException if one collection contains a {@code null}
59.3744 + * element and {@code null} is not an eligible element for the other collection.
59.3745 + * (<a href="Collection.html#optional-restrictions">optional</a>)
59.3746 + * @throws ClassCastException if one collection contains an element that is
59.3747 + * of a type which is ineligible for the other collection.
59.3748 + * (<a href="Collection.html#optional-restrictions">optional</a>)
59.3749 + * @since 1.5
59.3750 + */
59.3751 + public static boolean disjoint(Collection<?> c1, Collection<?> c2) {
59.3752 + // The collection to be used for contains(). Preference is given to
59.3753 + // the collection who's contains() has lower O() complexity.
59.3754 + Collection<?> contains = c2;
59.3755 + // The collection to be iterated. If the collections' contains() impl
59.3756 + // are of different O() complexity, the collection with slower
59.3757 + // contains() will be used for iteration. For collections who's
59.3758 + // contains() are of the same complexity then best performance is
59.3759 + // achieved by iterating the smaller collection.
59.3760 + Collection<?> iterate = c1;
59.3761 +
59.3762 + // Performance optimization cases. The heuristics:
59.3763 + // 1. Generally iterate over c1.
59.3764 + // 2. If c1 is a Set then iterate over c2.
59.3765 + // 3. If either collection is empty then result is always true.
59.3766 + // 4. Iterate over the smaller Collection.
59.3767 + if (c1 instanceof Set) {
59.3768 + // Use c1 for contains as a Set's contains() is expected to perform
59.3769 + // better than O(N/2)
59.3770 + iterate = c2;
59.3771 + contains = c1;
59.3772 + } else if (!(c2 instanceof Set)) {
59.3773 + // Both are mere Collections. Iterate over smaller collection.
59.3774 + // Example: If c1 contains 3 elements and c2 contains 50 elements and
59.3775 + // assuming contains() requires ceiling(N/2) comparisons then
59.3776 + // checking for all c1 elements in c2 would require 75 comparisons
59.3777 + // (3 * ceiling(50/2)) vs. checking all c2 elements in c1 requiring
59.3778 + // 100 comparisons (50 * ceiling(3/2)).
59.3779 + int c1size = c1.size();
59.3780 + int c2size = c2.size();
59.3781 + if (c1size == 0 || c2size == 0) {
59.3782 + // At least one collection is empty. Nothing will match.
59.3783 + return true;
59.3784 + }
59.3785 +
59.3786 + if (c1size > c2size) {
59.3787 + iterate = c2;
59.3788 + contains = c1;
59.3789 + }
59.3790 + }
59.3791 +
59.3792 + for (Object e : iterate) {
59.3793 + if (contains.contains(e)) {
59.3794 + // Found a common element. Collections are not disjoint.
59.3795 + return false;
59.3796 + }
59.3797 + }
59.3798 +
59.3799 + // No common elements were found.
59.3800 + return true;
59.3801 + }
59.3802 +
59.3803 + /**
59.3804 + * Adds all of the specified elements to the specified collection.
59.3805 + * Elements to be added may be specified individually or as an array.
59.3806 + * The behavior of this convenience method is identical to that of
59.3807 + * <tt>c.addAll(Arrays.asList(elements))</tt>, but this method is likely
59.3808 + * to run significantly faster under most implementations.
59.3809 + *
59.3810 + * <p>When elements are specified individually, this method provides a
59.3811 + * convenient way to add a few elements to an existing collection:
59.3812 + * <pre>
59.3813 + * Collections.addAll(flavors, "Peaches 'n Plutonium", "Rocky Racoon");
59.3814 + * </pre>
59.3815 + *
59.3816 + * @param c the collection into which <tt>elements</tt> are to be inserted
59.3817 + * @param elements the elements to insert into <tt>c</tt>
59.3818 + * @return <tt>true</tt> if the collection changed as a result of the call
59.3819 + * @throws UnsupportedOperationException if <tt>c</tt> does not support
59.3820 + * the <tt>add</tt> operation
59.3821 + * @throws NullPointerException if <tt>elements</tt> contains one or more
59.3822 + * null values and <tt>c</tt> does not permit null elements, or
59.3823 + * if <tt>c</tt> or <tt>elements</tt> are <tt>null</tt>
59.3824 + * @throws IllegalArgumentException if some property of a value in
59.3825 + * <tt>elements</tt> prevents it from being added to <tt>c</tt>
59.3826 + * @see Collection#addAll(Collection)
59.3827 + * @since 1.5
59.3828 + */
59.3829 + @SafeVarargs
59.3830 + public static <T> boolean addAll(Collection<? super T> c, T... elements) {
59.3831 + boolean result = false;
59.3832 + for (T element : elements)
59.3833 + result |= c.add(element);
59.3834 + return result;
59.3835 + }
59.3836 +
59.3837 + /**
59.3838 + * Returns a set backed by the specified map. The resulting set displays
59.3839 + * the same ordering, concurrency, and performance characteristics as the
59.3840 + * backing map. In essence, this factory method provides a {@link Set}
59.3841 + * implementation corresponding to any {@link Map} implementation. There
59.3842 + * is no need to use this method on a {@link Map} implementation that
59.3843 + * already has a corresponding {@link Set} implementation (such as {@link
59.3844 + * HashMap} or {@link TreeMap}).
59.3845 + *
59.3846 + * <p>Each method invocation on the set returned by this method results in
59.3847 + * exactly one method invocation on the backing map or its <tt>keySet</tt>
59.3848 + * view, with one exception. The <tt>addAll</tt> method is implemented
59.3849 + * as a sequence of <tt>put</tt> invocations on the backing map.
59.3850 + *
59.3851 + * <p>The specified map must be empty at the time this method is invoked,
59.3852 + * and should not be accessed directly after this method returns. These
59.3853 + * conditions are ensured if the map is created empty, passed directly
59.3854 + * to this method, and no reference to the map is retained, as illustrated
59.3855 + * in the following code fragment:
59.3856 + * <pre>
59.3857 + * Set<Object> weakHashSet = Collections.newSetFromMap(
59.3858 + * new WeakHashMap<Object, Boolean>());
59.3859 + * </pre>
59.3860 + *
59.3861 + * @param map the backing map
59.3862 + * @return the set backed by the map
59.3863 + * @throws IllegalArgumentException if <tt>map</tt> is not empty
59.3864 + * @since 1.6
59.3865 + */
59.3866 + public static <E> Set<E> newSetFromMap(Map<E, Boolean> map) {
59.3867 + return new SetFromMap<>(map);
59.3868 + }
59.3869 +
59.3870 + /**
59.3871 + * @serial include
59.3872 + */
59.3873 + private static class SetFromMap<E> extends AbstractSet<E>
59.3874 + implements Set<E>, Serializable
59.3875 + {
59.3876 + private final Map<E, Boolean> m; // The backing map
59.3877 + private transient Set<E> s; // Its keySet
59.3878 +
59.3879 + SetFromMap(Map<E, Boolean> map) {
59.3880 + if (!map.isEmpty())
59.3881 + throw new IllegalArgumentException("Map is non-empty");
59.3882 + m = map;
59.3883 + s = map.keySet();
59.3884 + }
59.3885 +
59.3886 + public void clear() { m.clear(); }
59.3887 + public int size() { return m.size(); }
59.3888 + public boolean isEmpty() { return m.isEmpty(); }
59.3889 + public boolean contains(Object o) { return m.containsKey(o); }
59.3890 + public boolean remove(Object o) { return m.remove(o) != null; }
59.3891 + public boolean add(E e) { return m.put(e, Boolean.TRUE) == null; }
59.3892 + public Iterator<E> iterator() { return s.iterator(); }
59.3893 + public Object[] toArray() { return s.toArray(); }
59.3894 + public <T> T[] toArray(T[] a) { return s.toArray(a); }
59.3895 + public String toString() { return s.toString(); }
59.3896 + public int hashCode() { return s.hashCode(); }
59.3897 + public boolean equals(Object o) { return o == this || s.equals(o); }
59.3898 + public boolean containsAll(Collection<?> c) {return s.containsAll(c);}
59.3899 + public boolean removeAll(Collection<?> c) {return s.removeAll(c);}
59.3900 + public boolean retainAll(Collection<?> c) {return s.retainAll(c);}
59.3901 + // addAll is the only inherited implementation
59.3902 +
59.3903 + private static final long serialVersionUID = 2454657854757543876L;
59.3904 +
59.3905 + }
59.3906 +
59.3907 + /**
59.3908 + * Returns a view of a {@link Deque} as a Last-in-first-out (Lifo)
59.3909 + * {@link Queue}. Method <tt>add</tt> is mapped to <tt>push</tt>,
59.3910 + * <tt>remove</tt> is mapped to <tt>pop</tt> and so on. This
59.3911 + * view can be useful when you would like to use a method
59.3912 + * requiring a <tt>Queue</tt> but you need Lifo ordering.
59.3913 + *
59.3914 + * <p>Each method invocation on the queue returned by this method
59.3915 + * results in exactly one method invocation on the backing deque, with
59.3916 + * one exception. The {@link Queue#addAll addAll} method is
59.3917 + * implemented as a sequence of {@link Deque#addFirst addFirst}
59.3918 + * invocations on the backing deque.
59.3919 + *
59.3920 + * @param deque the deque
59.3921 + * @return the queue
59.3922 + * @since 1.6
59.3923 + */
59.3924 + public static <T> Queue<T> asLifoQueue(Deque<T> deque) {
59.3925 + return new AsLIFOQueue<>(deque);
59.3926 + }
59.3927 +
59.3928 + /**
59.3929 + * @serial include
59.3930 + */
59.3931 + static class AsLIFOQueue<E> extends AbstractQueue<E>
59.3932 + implements Queue<E>, Serializable {
59.3933 + private static final long serialVersionUID = 1802017725587941708L;
59.3934 + private final Deque<E> q;
59.3935 + AsLIFOQueue(Deque<E> q) { this.q = q; }
59.3936 + public boolean add(E e) { q.addFirst(e); return true; }
59.3937 + public boolean offer(E e) { return q.offerFirst(e); }
59.3938 + public E poll() { return q.pollFirst(); }
59.3939 + public E remove() { return q.removeFirst(); }
59.3940 + public E peek() { return q.peekFirst(); }
59.3941 + public E element() { return q.getFirst(); }
59.3942 + public void clear() { q.clear(); }
59.3943 + public int size() { return q.size(); }
59.3944 + public boolean isEmpty() { return q.isEmpty(); }
59.3945 + public boolean contains(Object o) { return q.contains(o); }
59.3946 + public boolean remove(Object o) { return q.remove(o); }
59.3947 + public Iterator<E> iterator() { return q.iterator(); }
59.3948 + public Object[] toArray() { return q.toArray(); }
59.3949 + public <T> T[] toArray(T[] a) { return q.toArray(a); }
59.3950 + public String toString() { return q.toString(); }
59.3951 + public boolean containsAll(Collection<?> c) {return q.containsAll(c);}
59.3952 + public boolean removeAll(Collection<?> c) {return q.removeAll(c);}
59.3953 + public boolean retainAll(Collection<?> c) {return q.retainAll(c);}
59.3954 + // We use inherited addAll; forwarding addAll would be wrong
59.3955 + }
59.3956 +}
60.1 --- a/emul/compact/src/main/java/java/util/ComparableTimSort.java Fri Jan 25 15:08:24 2013 +0100
60.2 +++ b/emul/compact/src/main/java/java/util/ComparableTimSort.java Sun Feb 17 17:58:34 2013 +0100
60.3 @@ -25,7 +25,6 @@
60.4
60.5 package java.util;
60.6
60.7 -import org.apidesign.bck2brwsr.emul.lang.System;
60.8
60.9 /**
60.10 * This is a near duplicate of {@link TimSort}, modified for use with
61.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
61.2 +++ b/emul/compact/src/main/java/java/util/Deque.java Sun Feb 17 17:58:34 2013 +0100
61.3 @@ -0,0 +1,584 @@
61.4 +/*
61.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
61.6 + *
61.7 + * This code is free software; you can redistribute it and/or modify it
61.8 + * under the terms of the GNU General Public License version 2 only, as
61.9 + * published by the Free Software Foundation. Oracle designates this
61.10 + * particular file as subject to the "Classpath" exception as provided
61.11 + * by Oracle in the LICENSE file that accompanied this code.
61.12 + *
61.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
61.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
61.15 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
61.16 + * version 2 for more details (a copy is included in the LICENSE file that
61.17 + * accompanied this code).
61.18 + *
61.19 + * You should have received a copy of the GNU General Public License version
61.20 + * 2 along with this work; if not, write to the Free Software Foundation,
61.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
61.22 + *
61.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
61.24 + * or visit www.oracle.com if you need additional information or have any
61.25 + * questions.
61.26 + */
61.27 +
61.28 +/*
61.29 + * This file is available under and governed by the GNU General Public
61.30 + * License version 2 only, as published by the Free Software Foundation.
61.31 + * However, the following notice accompanied the original version of this
61.32 + * file:
61.33 + *
61.34 + * Written by Doug Lea and Josh Bloch with assistance from members of
61.35 + * JCP JSR-166 Expert Group and released to the public domain, as explained
61.36 + * at http://creativecommons.org/publicdomain/zero/1.0/
61.37 + */
61.38 +
61.39 +package java.util;
61.40 +
61.41 +/**
61.42 + * A linear collection that supports element insertion and removal at
61.43 + * both ends. The name <i>deque</i> is short for "double ended queue"
61.44 + * and is usually pronounced "deck". Most <tt>Deque</tt>
61.45 + * implementations place no fixed limits on the number of elements
61.46 + * they may contain, but this interface supports capacity-restricted
61.47 + * deques as well as those with no fixed size limit.
61.48 + *
61.49 + * <p>This interface defines methods to access the elements at both
61.50 + * ends of the deque. Methods are provided to insert, remove, and
61.51 + * examine the element. Each of these methods exists in two forms:
61.52 + * one throws an exception if the operation fails, the other returns a
61.53 + * special value (either <tt>null</tt> or <tt>false</tt>, depending on
61.54 + * the operation). The latter form of the insert operation is
61.55 + * designed specifically for use with capacity-restricted
61.56 + * <tt>Deque</tt> implementations; in most implementations, insert
61.57 + * operations cannot fail.
61.58 + *
61.59 + * <p>The twelve methods described above are summarized in the
61.60 + * following table:
61.61 + *
61.62 + * <p>
61.63 + * <table BORDER CELLPADDING=3 CELLSPACING=1>
61.64 + * <tr>
61.65 + * <td></td>
61.66 + * <td ALIGN=CENTER COLSPAN = 2> <b>First Element (Head)</b></td>
61.67 + * <td ALIGN=CENTER COLSPAN = 2> <b>Last Element (Tail)</b></td>
61.68 + * </tr>
61.69 + * <tr>
61.70 + * <td></td>
61.71 + * <td ALIGN=CENTER><em>Throws exception</em></td>
61.72 + * <td ALIGN=CENTER><em>Special value</em></td>
61.73 + * <td ALIGN=CENTER><em>Throws exception</em></td>
61.74 + * <td ALIGN=CENTER><em>Special value</em></td>
61.75 + * </tr>
61.76 + * <tr>
61.77 + * <td><b>Insert</b></td>
61.78 + * <td>{@link #addFirst addFirst(e)}</td>
61.79 + * <td>{@link #offerFirst offerFirst(e)}</td>
61.80 + * <td>{@link #addLast addLast(e)}</td>
61.81 + * <td>{@link #offerLast offerLast(e)}</td>
61.82 + * </tr>
61.83 + * <tr>
61.84 + * <td><b>Remove</b></td>
61.85 + * <td>{@link #removeFirst removeFirst()}</td>
61.86 + * <td>{@link #pollFirst pollFirst()}</td>
61.87 + * <td>{@link #removeLast removeLast()}</td>
61.88 + * <td>{@link #pollLast pollLast()}</td>
61.89 + * </tr>
61.90 + * <tr>
61.91 + * <td><b>Examine</b></td>
61.92 + * <td>{@link #getFirst getFirst()}</td>
61.93 + * <td>{@link #peekFirst peekFirst()}</td>
61.94 + * <td>{@link #getLast getLast()}</td>
61.95 + * <td>{@link #peekLast peekLast()}</td>
61.96 + * </tr>
61.97 + * </table>
61.98 + *
61.99 + * <p>This interface extends the {@link Queue} interface. When a deque is
61.100 + * used as a queue, FIFO (First-In-First-Out) behavior results. Elements are
61.101 + * added at the end of the deque and removed from the beginning. The methods
61.102 + * inherited from the <tt>Queue</tt> interface are precisely equivalent to
61.103 + * <tt>Deque</tt> methods as indicated in the following table:
61.104 + *
61.105 + * <p>
61.106 + * <table BORDER CELLPADDING=3 CELLSPACING=1>
61.107 + * <tr>
61.108 + * <td ALIGN=CENTER> <b><tt>Queue</tt> Method</b></td>
61.109 + * <td ALIGN=CENTER> <b>Equivalent <tt>Deque</tt> Method</b></td>
61.110 + * </tr>
61.111 + * <tr>
61.112 + * <td>{@link java.util.Queue#add add(e)}</td>
61.113 + * <td>{@link #addLast addLast(e)}</td>
61.114 + * </tr>
61.115 + * <tr>
61.116 + * <td>{@link java.util.Queue#offer offer(e)}</td>
61.117 + * <td>{@link #offerLast offerLast(e)}</td>
61.118 + * </tr>
61.119 + * <tr>
61.120 + * <td>{@link java.util.Queue#remove remove()}</td>
61.121 + * <td>{@link #removeFirst removeFirst()}</td>
61.122 + * </tr>
61.123 + * <tr>
61.124 + * <td>{@link java.util.Queue#poll poll()}</td>
61.125 + * <td>{@link #pollFirst pollFirst()}</td>
61.126 + * </tr>
61.127 + * <tr>
61.128 + * <td>{@link java.util.Queue#element element()}</td>
61.129 + * <td>{@link #getFirst getFirst()}</td>
61.130 + * </tr>
61.131 + * <tr>
61.132 + * <td>{@link java.util.Queue#peek peek()}</td>
61.133 + * <td>{@link #peek peekFirst()}</td>
61.134 + * </tr>
61.135 + * </table>
61.136 + *
61.137 + * <p>Deques can also be used as LIFO (Last-In-First-Out) stacks. This
61.138 + * interface should be used in preference to the legacy {@link Stack} class.
61.139 + * When a deque is used as a stack, elements are pushed and popped from the
61.140 + * beginning of the deque. Stack methods are precisely equivalent to
61.141 + * <tt>Deque</tt> methods as indicated in the table below:
61.142 + *
61.143 + * <p>
61.144 + * <table BORDER CELLPADDING=3 CELLSPACING=1>
61.145 + * <tr>
61.146 + * <td ALIGN=CENTER> <b>Stack Method</b></td>
61.147 + * <td ALIGN=CENTER> <b>Equivalent <tt>Deque</tt> Method</b></td>
61.148 + * </tr>
61.149 + * <tr>
61.150 + * <td>{@link #push push(e)}</td>
61.151 + * <td>{@link #addFirst addFirst(e)}</td>
61.152 + * </tr>
61.153 + * <tr>
61.154 + * <td>{@link #pop pop()}</td>
61.155 + * <td>{@link #removeFirst removeFirst()}</td>
61.156 + * </tr>
61.157 + * <tr>
61.158 + * <td>{@link #peek peek()}</td>
61.159 + * <td>{@link #peekFirst peekFirst()}</td>
61.160 + * </tr>
61.161 + * </table>
61.162 + *
61.163 + * <p>Note that the {@link #peek peek} method works equally well when
61.164 + * a deque is used as a queue or a stack; in either case, elements are
61.165 + * drawn from the beginning of the deque.
61.166 + *
61.167 + * <p>This interface provides two methods to remove interior
61.168 + * elements, {@link #removeFirstOccurrence removeFirstOccurrence} and
61.169 + * {@link #removeLastOccurrence removeLastOccurrence}.
61.170 + *
61.171 + * <p>Unlike the {@link List} interface, this interface does not
61.172 + * provide support for indexed access to elements.
61.173 + *
61.174 + * <p>While <tt>Deque</tt> implementations are not strictly required
61.175 + * to prohibit the insertion of null elements, they are strongly
61.176 + * encouraged to do so. Users of any <tt>Deque</tt> implementations
61.177 + * that do allow null elements are strongly encouraged <i>not</i> to
61.178 + * take advantage of the ability to insert nulls. This is so because
61.179 + * <tt>null</tt> is used as a special return value by various methods
61.180 + * to indicated that the deque is empty.
61.181 + *
61.182 + * <p><tt>Deque</tt> implementations generally do not define
61.183 + * element-based versions of the <tt>equals</tt> and <tt>hashCode</tt>
61.184 + * methods, but instead inherit the identity-based versions from class
61.185 + * <tt>Object</tt>.
61.186 + *
61.187 + * <p>This interface is a member of the <a
61.188 + * href="{@docRoot}/../technotes/guides/collections/index.html"> Java Collections
61.189 + * Framework</a>.
61.190 + *
61.191 + * @author Doug Lea
61.192 + * @author Josh Bloch
61.193 + * @since 1.6
61.194 + * @param <E> the type of elements held in this collection
61.195 + */
61.196 +
61.197 +public interface Deque<E> extends Queue<E> {
61.198 + /**
61.199 + * Inserts the specified element at the front of this deque if it is
61.200 + * possible to do so immediately without violating capacity restrictions.
61.201 + * When using a capacity-restricted deque, it is generally preferable to
61.202 + * use method {@link #offerFirst}.
61.203 + *
61.204 + * @param e the element to add
61.205 + * @throws IllegalStateException if the element cannot be added at this
61.206 + * time due to capacity restrictions
61.207 + * @throws ClassCastException if the class of the specified element
61.208 + * prevents it from being added to this deque
61.209 + * @throws NullPointerException if the specified element is null and this
61.210 + * deque does not permit null elements
61.211 + * @throws IllegalArgumentException if some property of the specified
61.212 + * element prevents it from being added to this deque
61.213 + */
61.214 + void addFirst(E e);
61.215 +
61.216 + /**
61.217 + * Inserts the specified element at the end of this deque if it is
61.218 + * possible to do so immediately without violating capacity restrictions.
61.219 + * When using a capacity-restricted deque, it is generally preferable to
61.220 + * use method {@link #offerLast}.
61.221 + *
61.222 + * <p>This method is equivalent to {@link #add}.
61.223 + *
61.224 + * @param e the element to add
61.225 + * @throws IllegalStateException if the element cannot be added at this
61.226 + * time due to capacity restrictions
61.227 + * @throws ClassCastException if the class of the specified element
61.228 + * prevents it from being added to this deque
61.229 + * @throws NullPointerException if the specified element is null and this
61.230 + * deque does not permit null elements
61.231 + * @throws IllegalArgumentException if some property of the specified
61.232 + * element prevents it from being added to this deque
61.233 + */
61.234 + void addLast(E e);
61.235 +
61.236 + /**
61.237 + * Inserts the specified element at the front of this deque unless it would
61.238 + * violate capacity restrictions. When using a capacity-restricted deque,
61.239 + * this method is generally preferable to the {@link #addFirst} method,
61.240 + * which can fail to insert an element only by throwing an exception.
61.241 + *
61.242 + * @param e the element to add
61.243 + * @return <tt>true</tt> if the element was added to this deque, else
61.244 + * <tt>false</tt>
61.245 + * @throws ClassCastException if the class of the specified element
61.246 + * prevents it from being added to this deque
61.247 + * @throws NullPointerException if the specified element is null and this
61.248 + * deque does not permit null elements
61.249 + * @throws IllegalArgumentException if some property of the specified
61.250 + * element prevents it from being added to this deque
61.251 + */
61.252 + boolean offerFirst(E e);
61.253 +
61.254 + /**
61.255 + * Inserts the specified element at the end of this deque unless it would
61.256 + * violate capacity restrictions. When using a capacity-restricted deque,
61.257 + * this method is generally preferable to the {@link #addLast} method,
61.258 + * which can fail to insert an element only by throwing an exception.
61.259 + *
61.260 + * @param e the element to add
61.261 + * @return <tt>true</tt> if the element was added to this deque, else
61.262 + * <tt>false</tt>
61.263 + * @throws ClassCastException if the class of the specified element
61.264 + * prevents it from being added to this deque
61.265 + * @throws NullPointerException if the specified element is null and this
61.266 + * deque does not permit null elements
61.267 + * @throws IllegalArgumentException if some property of the specified
61.268 + * element prevents it from being added to this deque
61.269 + */
61.270 + boolean offerLast(E e);
61.271 +
61.272 + /**
61.273 + * Retrieves and removes the first element of this deque. This method
61.274 + * differs from {@link #pollFirst pollFirst} only in that it throws an
61.275 + * exception if this deque is empty.
61.276 + *
61.277 + * @return the head of this deque
61.278 + * @throws NoSuchElementException if this deque is empty
61.279 + */
61.280 + E removeFirst();
61.281 +
61.282 + /**
61.283 + * Retrieves and removes the last element of this deque. This method
61.284 + * differs from {@link #pollLast pollLast} only in that it throws an
61.285 + * exception if this deque is empty.
61.286 + *
61.287 + * @return the tail of this deque
61.288 + * @throws NoSuchElementException if this deque is empty
61.289 + */
61.290 + E removeLast();
61.291 +
61.292 + /**
61.293 + * Retrieves and removes the first element of this deque,
61.294 + * or returns <tt>null</tt> if this deque is empty.
61.295 + *
61.296 + * @return the head of this deque, or <tt>null</tt> if this deque is empty
61.297 + */
61.298 + E pollFirst();
61.299 +
61.300 + /**
61.301 + * Retrieves and removes the last element of this deque,
61.302 + * or returns <tt>null</tt> if this deque is empty.
61.303 + *
61.304 + * @return the tail of this deque, or <tt>null</tt> if this deque is empty
61.305 + */
61.306 + E pollLast();
61.307 +
61.308 + /**
61.309 + * Retrieves, but does not remove, the first element of this deque.
61.310 + *
61.311 + * This method differs from {@link #peekFirst peekFirst} only in that it
61.312 + * throws an exception if this deque is empty.
61.313 + *
61.314 + * @return the head of this deque
61.315 + * @throws NoSuchElementException if this deque is empty
61.316 + */
61.317 + E getFirst();
61.318 +
61.319 + /**
61.320 + * Retrieves, but does not remove, the last element of this deque.
61.321 + * This method differs from {@link #peekLast peekLast} only in that it
61.322 + * throws an exception if this deque is empty.
61.323 + *
61.324 + * @return the tail of this deque
61.325 + * @throws NoSuchElementException if this deque is empty
61.326 + */
61.327 + E getLast();
61.328 +
61.329 + /**
61.330 + * Retrieves, but does not remove, the first element of this deque,
61.331 + * or returns <tt>null</tt> if this deque is empty.
61.332 + *
61.333 + * @return the head of this deque, or <tt>null</tt> if this deque is empty
61.334 + */
61.335 + E peekFirst();
61.336 +
61.337 + /**
61.338 + * Retrieves, but does not remove, the last element of this deque,
61.339 + * or returns <tt>null</tt> if this deque is empty.
61.340 + *
61.341 + * @return the tail of this deque, or <tt>null</tt> if this deque is empty
61.342 + */
61.343 + E peekLast();
61.344 +
61.345 + /**
61.346 + * Removes the first occurrence of the specified element from this deque.
61.347 + * If the deque does not contain the element, it is unchanged.
61.348 + * More formally, removes the first element <tt>e</tt> such that
61.349 + * <tt>(o==null ? e==null : o.equals(e))</tt>
61.350 + * (if such an element exists).
61.351 + * Returns <tt>true</tt> if this deque contained the specified element
61.352 + * (or equivalently, if this deque changed as a result of the call).
61.353 + *
61.354 + * @param o element to be removed from this deque, if present
61.355 + * @return <tt>true</tt> if an element was removed as a result of this call
61.356 + * @throws ClassCastException if the class of the specified element
61.357 + * is incompatible with this deque
61.358 + * (<a href="Collection.html#optional-restrictions">optional</a>)
61.359 + * @throws NullPointerException if the specified element is null and this
61.360 + * deque does not permit null elements
61.361 + * (<a href="Collection.html#optional-restrictions">optional</a>)
61.362 + */
61.363 + boolean removeFirstOccurrence(Object o);
61.364 +
61.365 + /**
61.366 + * Removes the last occurrence of the specified element from this deque.
61.367 + * If the deque does not contain the element, it is unchanged.
61.368 + * More formally, removes the last element <tt>e</tt> such that
61.369 + * <tt>(o==null ? e==null : o.equals(e))</tt>
61.370 + * (if such an element exists).
61.371 + * Returns <tt>true</tt> if this deque contained the specified element
61.372 + * (or equivalently, if this deque changed as a result of the call).
61.373 + *
61.374 + * @param o element to be removed from this deque, if present
61.375 + * @return <tt>true</tt> if an element was removed as a result of this call
61.376 + * @throws ClassCastException if the class of the specified element
61.377 + * is incompatible with this deque
61.378 + * (<a href="Collection.html#optional-restrictions">optional</a>)
61.379 + * @throws NullPointerException if the specified element is null and this
61.380 + * deque does not permit null elements
61.381 + * (<a href="Collection.html#optional-restrictions">optional</a>)
61.382 + */
61.383 + boolean removeLastOccurrence(Object o);
61.384 +
61.385 + // *** Queue methods ***
61.386 +
61.387 + /**
61.388 + * Inserts the specified element into the queue represented by this deque
61.389 + * (in other words, at the tail of this deque) if it is possible to do so
61.390 + * immediately without violating capacity restrictions, returning
61.391 + * <tt>true</tt> upon success and throwing an
61.392 + * <tt>IllegalStateException</tt> if no space is currently available.
61.393 + * When using a capacity-restricted deque, it is generally preferable to
61.394 + * use {@link #offer(Object) offer}.
61.395 + *
61.396 + * <p>This method is equivalent to {@link #addLast}.
61.397 + *
61.398 + * @param e the element to add
61.399 + * @return <tt>true</tt> (as specified by {@link Collection#add})
61.400 + * @throws IllegalStateException if the element cannot be added at this
61.401 + * time due to capacity restrictions
61.402 + * @throws ClassCastException if the class of the specified element
61.403 + * prevents it from being added to this deque
61.404 + * @throws NullPointerException if the specified element is null and this
61.405 + * deque does not permit null elements
61.406 + * @throws IllegalArgumentException if some property of the specified
61.407 + * element prevents it from being added to this deque
61.408 + */
61.409 + boolean add(E e);
61.410 +
61.411 + /**
61.412 + * Inserts the specified element into the queue represented by this deque
61.413 + * (in other words, at the tail of this deque) if it is possible to do so
61.414 + * immediately without violating capacity restrictions, returning
61.415 + * <tt>true</tt> upon success and <tt>false</tt> if no space is currently
61.416 + * available. When using a capacity-restricted deque, this method is
61.417 + * generally preferable to the {@link #add} method, which can fail to
61.418 + * insert an element only by throwing an exception.
61.419 + *
61.420 + * <p>This method is equivalent to {@link #offerLast}.
61.421 + *
61.422 + * @param e the element to add
61.423 + * @return <tt>true</tt> if the element was added to this deque, else
61.424 + * <tt>false</tt>
61.425 + * @throws ClassCastException if the class of the specified element
61.426 + * prevents it from being added to this deque
61.427 + * @throws NullPointerException if the specified element is null and this
61.428 + * deque does not permit null elements
61.429 + * @throws IllegalArgumentException if some property of the specified
61.430 + * element prevents it from being added to this deque
61.431 + */
61.432 + boolean offer(E e);
61.433 +
61.434 + /**
61.435 + * Retrieves and removes the head of the queue represented by this deque
61.436 + * (in other words, the first element of this deque).
61.437 + * This method differs from {@link #poll poll} only in that it throws an
61.438 + * exception if this deque is empty.
61.439 + *
61.440 + * <p>This method is equivalent to {@link #removeFirst()}.
61.441 + *
61.442 + * @return the head of the queue represented by this deque
61.443 + * @throws NoSuchElementException if this deque is empty
61.444 + */
61.445 + E remove();
61.446 +
61.447 + /**
61.448 + * Retrieves and removes the head of the queue represented by this deque
61.449 + * (in other words, the first element of this deque), or returns
61.450 + * <tt>null</tt> if this deque is empty.
61.451 + *
61.452 + * <p>This method is equivalent to {@link #pollFirst()}.
61.453 + *
61.454 + * @return the first element of this deque, or <tt>null</tt> if
61.455 + * this deque is empty
61.456 + */
61.457 + E poll();
61.458 +
61.459 + /**
61.460 + * Retrieves, but does not remove, the head of the queue represented by
61.461 + * this deque (in other words, the first element of this deque).
61.462 + * This method differs from {@link #peek peek} only in that it throws an
61.463 + * exception if this deque is empty.
61.464 + *
61.465 + * <p>This method is equivalent to {@link #getFirst()}.
61.466 + *
61.467 + * @return the head of the queue represented by this deque
61.468 + * @throws NoSuchElementException if this deque is empty
61.469 + */
61.470 + E element();
61.471 +
61.472 + /**
61.473 + * Retrieves, but does not remove, the head of the queue represented by
61.474 + * this deque (in other words, the first element of this deque), or
61.475 + * returns <tt>null</tt> if this deque is empty.
61.476 + *
61.477 + * <p>This method is equivalent to {@link #peekFirst()}.
61.478 + *
61.479 + * @return the head of the queue represented by this deque, or
61.480 + * <tt>null</tt> if this deque is empty
61.481 + */
61.482 + E peek();
61.483 +
61.484 +
61.485 + // *** Stack methods ***
61.486 +
61.487 + /**
61.488 + * Pushes an element onto the stack represented by this deque (in other
61.489 + * words, at the head of this deque) if it is possible to do so
61.490 + * immediately without violating capacity restrictions, returning
61.491 + * <tt>true</tt> upon success and throwing an
61.492 + * <tt>IllegalStateException</tt> if no space is currently available.
61.493 + *
61.494 + * <p>This method is equivalent to {@link #addFirst}.
61.495 + *
61.496 + * @param e the element to push
61.497 + * @throws IllegalStateException if the element cannot be added at this
61.498 + * time due to capacity restrictions
61.499 + * @throws ClassCastException if the class of the specified element
61.500 + * prevents it from being added to this deque
61.501 + * @throws NullPointerException if the specified element is null and this
61.502 + * deque does not permit null elements
61.503 + * @throws IllegalArgumentException if some property of the specified
61.504 + * element prevents it from being added to this deque
61.505 + */
61.506 + void push(E e);
61.507 +
61.508 + /**
61.509 + * Pops an element from the stack represented by this deque. In other
61.510 + * words, removes and returns the first element of this deque.
61.511 + *
61.512 + * <p>This method is equivalent to {@link #removeFirst()}.
61.513 + *
61.514 + * @return the element at the front of this deque (which is the top
61.515 + * of the stack represented by this deque)
61.516 + * @throws NoSuchElementException if this deque is empty
61.517 + */
61.518 + E pop();
61.519 +
61.520 +
61.521 + // *** Collection methods ***
61.522 +
61.523 + /**
61.524 + * Removes the first occurrence of the specified element from this deque.
61.525 + * If the deque does not contain the element, it is unchanged.
61.526 + * More formally, removes the first element <tt>e</tt> such that
61.527 + * <tt>(o==null ? e==null : o.equals(e))</tt>
61.528 + * (if such an element exists).
61.529 + * Returns <tt>true</tt> if this deque contained the specified element
61.530 + * (or equivalently, if this deque changed as a result of the call).
61.531 + *
61.532 + * <p>This method is equivalent to {@link #removeFirstOccurrence}.
61.533 + *
61.534 + * @param o element to be removed from this deque, if present
61.535 + * @return <tt>true</tt> if an element was removed as a result of this call
61.536 + * @throws ClassCastException if the class of the specified element
61.537 + * is incompatible with this deque
61.538 + * (<a href="Collection.html#optional-restrictions">optional</a>)
61.539 + * @throws NullPointerException if the specified element is null and this
61.540 + * deque does not permit null elements
61.541 + * (<a href="Collection.html#optional-restrictions">optional</a>)
61.542 + */
61.543 + boolean remove(Object o);
61.544 +
61.545 + /**
61.546 + * Returns <tt>true</tt> if this deque contains the specified element.
61.547 + * More formally, returns <tt>true</tt> if and only if this deque contains
61.548 + * at least one element <tt>e</tt> such that
61.549 + * <tt>(o==null ? e==null : o.equals(e))</tt>.
61.550 + *
61.551 + * @param o element whose presence in this deque is to be tested
61.552 + * @return <tt>true</tt> if this deque contains the specified element
61.553 + * @throws ClassCastException if the type of the specified element
61.554 + * is incompatible with this deque
61.555 + * (<a href="Collection.html#optional-restrictions">optional</a>)
61.556 + * @throws NullPointerException if the specified element is null and this
61.557 + * deque does not permit null elements
61.558 + * (<a href="Collection.html#optional-restrictions">optional</a>)
61.559 + */
61.560 + boolean contains(Object o);
61.561 +
61.562 + /**
61.563 + * Returns the number of elements in this deque.
61.564 + *
61.565 + * @return the number of elements in this deque
61.566 + */
61.567 + public int size();
61.568 +
61.569 + /**
61.570 + * Returns an iterator over the elements in this deque in proper sequence.
61.571 + * The elements will be returned in order from first (head) to last (tail).
61.572 + *
61.573 + * @return an iterator over the elements in this deque in proper sequence
61.574 + */
61.575 + Iterator<E> iterator();
61.576 +
61.577 + /**
61.578 + * Returns an iterator over the elements in this deque in reverse
61.579 + * sequential order. The elements will be returned in order from
61.580 + * last (tail) to first (head).
61.581 + *
61.582 + * @return an iterator over the elements in this deque in reverse
61.583 + * sequence
61.584 + */
61.585 + Iterator<E> descendingIterator();
61.586 +
61.587 +}
62.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
62.2 +++ b/emul/compact/src/main/java/java/util/Dictionary.java Sun Feb 17 17:58:34 2013 +0100
62.3 @@ -0,0 +1,155 @@
62.4 +/*
62.5 + * Copyright (c) 1995, 2004, 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;
62.30 +
62.31 +/**
62.32 + * The <code>Dictionary</code> class is the abstract parent of any
62.33 + * class, such as <code>Hashtable</code>, which maps keys to values.
62.34 + * Every key and every value is an object. In any one <tt>Dictionary</tt>
62.35 + * object, every key is associated with at most one value. Given a
62.36 + * <tt>Dictionary</tt> and a key, the associated element can be looked up.
62.37 + * Any non-<code>null</code> object can be used as a key and as a value.
62.38 + * <p>
62.39 + * As a rule, the <code>equals</code> method should be used by
62.40 + * implementations of this class to decide if two keys are the same.
62.41 + * <p>
62.42 + * <strong>NOTE: This class is obsolete. New implementations should
62.43 + * implement the Map interface, rather than extending this class.</strong>
62.44 + *
62.45 + * @author unascribed
62.46 + * @see java.util.Map
62.47 + * @see java.lang.Object#equals(java.lang.Object)
62.48 + * @see java.lang.Object#hashCode()
62.49 + * @see java.util.Hashtable
62.50 + * @since JDK1.0
62.51 + */
62.52 +public abstract
62.53 +class Dictionary<K,V> {
62.54 + /**
62.55 + * Sole constructor. (For invocation by subclass constructors, typically
62.56 + * implicit.)
62.57 + */
62.58 + public Dictionary() {
62.59 + }
62.60 +
62.61 + /**
62.62 + * Returns the number of entries (distinct keys) in this dictionary.
62.63 + *
62.64 + * @return the number of keys in this dictionary.
62.65 + */
62.66 + abstract public int size();
62.67 +
62.68 + /**
62.69 + * Tests if this dictionary maps no keys to value. The general contract
62.70 + * for the <tt>isEmpty</tt> method is that the result is true if and only
62.71 + * if this dictionary contains no entries.
62.72 + *
62.73 + * @return <code>true</code> if this dictionary maps no keys to values;
62.74 + * <code>false</code> otherwise.
62.75 + */
62.76 + abstract public boolean isEmpty();
62.77 +
62.78 + /**
62.79 + * Returns an enumeration of the keys in this dictionary. The general
62.80 + * contract for the keys method is that an <tt>Enumeration</tt> object
62.81 + * is returned that will generate all the keys for which this dictionary
62.82 + * contains entries.
62.83 + *
62.84 + * @return an enumeration of the keys in this dictionary.
62.85 + * @see java.util.Dictionary#elements()
62.86 + * @see java.util.Enumeration
62.87 + */
62.88 + abstract public Enumeration<K> keys();
62.89 +
62.90 + /**
62.91 + * Returns an enumeration of the values in this dictionary. The general
62.92 + * contract for the <tt>elements</tt> method is that an
62.93 + * <tt>Enumeration</tt> is returned that will generate all the elements
62.94 + * contained in entries in this dictionary.
62.95 + *
62.96 + * @return an enumeration of the values in this dictionary.
62.97 + * @see java.util.Dictionary#keys()
62.98 + * @see java.util.Enumeration
62.99 + */
62.100 + abstract public Enumeration<V> elements();
62.101 +
62.102 + /**
62.103 + * Returns the value to which the key is mapped in this dictionary.
62.104 + * The general contract for the <tt>isEmpty</tt> method is that if this
62.105 + * dictionary contains an entry for the specified key, the associated
62.106 + * value is returned; otherwise, <tt>null</tt> is returned.
62.107 + *
62.108 + * @return the value to which the key is mapped in this dictionary;
62.109 + * @param key a key in this dictionary.
62.110 + * <code>null</code> if the key is not mapped to any value in
62.111 + * this dictionary.
62.112 + * @exception NullPointerException if the <tt>key</tt> is <tt>null</tt>.
62.113 + * @see java.util.Dictionary#put(java.lang.Object, java.lang.Object)
62.114 + */
62.115 + abstract public V get(Object key);
62.116 +
62.117 + /**
62.118 + * Maps the specified <code>key</code> to the specified
62.119 + * <code>value</code> in this dictionary. Neither the key nor the
62.120 + * value can be <code>null</code>.
62.121 + * <p>
62.122 + * If this dictionary already contains an entry for the specified
62.123 + * <tt>key</tt>, the value already in this dictionary for that
62.124 + * <tt>key</tt> is returned, after modifying the entry to contain the
62.125 + * new element. <p>If this dictionary does not already have an entry
62.126 + * for the specified <tt>key</tt>, an entry is created for the
62.127 + * specified <tt>key</tt> and <tt>value</tt>, and <tt>null</tt> is
62.128 + * returned.
62.129 + * <p>
62.130 + * The <code>value</code> can be retrieved by calling the
62.131 + * <code>get</code> method with a <code>key</code> that is equal to
62.132 + * the original <code>key</code>.
62.133 + *
62.134 + * @param key the hashtable key.
62.135 + * @param value the value.
62.136 + * @return the previous value to which the <code>key</code> was mapped
62.137 + * in this dictionary, or <code>null</code> if the key did not
62.138 + * have a previous mapping.
62.139 + * @exception NullPointerException if the <code>key</code> or
62.140 + * <code>value</code> is <code>null</code>.
62.141 + * @see java.lang.Object#equals(java.lang.Object)
62.142 + * @see java.util.Dictionary#get(java.lang.Object)
62.143 + */
62.144 + abstract public V put(K key, V value);
62.145 +
62.146 + /**
62.147 + * Removes the <code>key</code> (and its corresponding
62.148 + * <code>value</code>) from this dictionary. This method does nothing
62.149 + * if the <code>key</code> is not in this dictionary.
62.150 + *
62.151 + * @param key the key that needs to be removed.
62.152 + * @return the value to which the <code>key</code> had been mapped in this
62.153 + * dictionary, or <code>null</code> if the key did not have a
62.154 + * mapping.
62.155 + * @exception NullPointerException if <tt>key</tt> is <tt>null</tt>.
62.156 + */
62.157 + abstract public V remove(Object key);
62.158 +}
63.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
63.2 +++ b/emul/compact/src/main/java/java/util/EmptyStackException.java Sun Feb 17 17:58:34 2013 +0100
63.3 @@ -0,0 +1,46 @@
63.4 +/*
63.5 + * Copyright (c) 1994, 2008, 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;
63.30 +
63.31 +/**
63.32 + * Thrown by methods in the <code>Stack</code> class to indicate
63.33 + * that the stack is empty.
63.34 + *
63.35 + * @author Jonathan Payne
63.36 + * @see java.util.Stack
63.37 + * @since JDK1.0
63.38 + */
63.39 +public
63.40 +class EmptyStackException extends RuntimeException {
63.41 + private static final long serialVersionUID = 5084686378493302095L;
63.42 +
63.43 + /**
63.44 + * Constructs a new <code>EmptyStackException</code> with <tt>null</tt>
63.45 + * as its error message string.
63.46 + */
63.47 + public EmptyStackException() {
63.48 + }
63.49 +}
64.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
64.2 +++ b/emul/compact/src/main/java/java/util/EventListener.java Sun Feb 17 17:58:34 2013 +0100
64.3 @@ -0,0 +1,33 @@
64.4 +/*
64.5 + * Copyright (c) 1996, 1999, 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;
64.30 +
64.31 +/**
64.32 + * A tagging interface that all event listener interfaces must extend.
64.33 + * @since JDK1.1
64.34 + */
64.35 +public interface EventListener {
64.36 +}
65.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
65.2 +++ b/emul/compact/src/main/java/java/util/EventListenerProxy.java Sun Feb 17 17:58:34 2013 +0100
65.3 @@ -0,0 +1,75 @@
65.4 +/*
65.5 + * Copyright (c) 2000, 2004, 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;
65.30 +
65.31 +/**
65.32 + * An abstract wrapper class for an {@code EventListener} class
65.33 + * which associates a set of additional parameters with the listener.
65.34 + * Subclasses must provide the storage and accessor methods
65.35 + * for the additional arguments or parameters.
65.36 + * <p>
65.37 + * For example, a bean which supports named properties
65.38 + * would have a two argument method signature for adding
65.39 + * a {@code PropertyChangeListener} for a property:
65.40 + * <pre>
65.41 + * public void addPropertyChangeListener(String propertyName,
65.42 + * PropertyChangeListener listener)
65.43 + * </pre>
65.44 + * If the bean also implemented the zero argument get listener method:
65.45 + * <pre>
65.46 + * public PropertyChangeListener[] getPropertyChangeListeners()
65.47 + * </pre>
65.48 + * then the array may contain inner {@code PropertyChangeListeners}
65.49 + * which are also {@code PropertyChangeListenerProxy} objects.
65.50 + * <p>
65.51 + * If the calling method is interested in retrieving the named property
65.52 + * then it would have to test the element to see if it is a proxy class.
65.53 + *
65.54 + * @since 1.4
65.55 + */
65.56 +public abstract class EventListenerProxy<T extends EventListener>
65.57 + implements EventListener {
65.58 +
65.59 + private final T listener;
65.60 +
65.61 + /**
65.62 + * Creates a proxy for the specified listener.
65.63 + *
65.64 + * @param listener the listener object
65.65 + */
65.66 + public EventListenerProxy(T listener) {
65.67 + this.listener = listener;
65.68 + }
65.69 +
65.70 + /**
65.71 + * Returns the listener associated with the proxy.
65.72 + *
65.73 + * @return the listener associated with the proxy
65.74 + */
65.75 + public T getListener() {
65.76 + return this.listener;
65.77 + }
65.78 +}
66.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
66.2 +++ b/emul/compact/src/main/java/java/util/EventObject.java Sun Feb 17 17:58:34 2013 +0100
66.3 @@ -0,0 +1,78 @@
66.4 +/*
66.5 + * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved.
66.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
66.7 + *
66.8 + * This code is free software; you can redistribute it and/or modify it
66.9 + * under the terms of the GNU General Public License version 2 only, as
66.10 + * published by the Free Software Foundation. Oracle designates this
66.11 + * particular file as subject to the "Classpath" exception as provided
66.12 + * by Oracle in the LICENSE file that accompanied this code.
66.13 + *
66.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
66.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
66.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
66.17 + * version 2 for more details (a copy is included in the LICENSE file that
66.18 + * accompanied this code).
66.19 + *
66.20 + * You should have received a copy of the GNU General Public License version
66.21 + * 2 along with this work; if not, write to the Free Software Foundation,
66.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
66.23 + *
66.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
66.25 + * or visit www.oracle.com if you need additional information or have any
66.26 + * questions.
66.27 + */
66.28 +
66.29 +package java.util;
66.30 +
66.31 +/**
66.32 + * <p>
66.33 + * The root class from which all event state objects shall be derived.
66.34 + * <p>
66.35 + * All Events are constructed with a reference to the object, the "source",
66.36 + * that is logically deemed to be the object upon which the Event in question
66.37 + * initially occurred upon.
66.38 + *
66.39 + * @since JDK1.1
66.40 + */
66.41 +
66.42 +public class EventObject implements java.io.Serializable {
66.43 +
66.44 + private static final long serialVersionUID = 5516075349620653480L;
66.45 +
66.46 + /**
66.47 + * The object on which the Event initially occurred.
66.48 + */
66.49 + protected transient Object source;
66.50 +
66.51 + /**
66.52 + * Constructs a prototypical Event.
66.53 + *
66.54 + * @param source The object on which the Event initially occurred.
66.55 + * @exception IllegalArgumentException if source is null.
66.56 + */
66.57 + public EventObject(Object source) {
66.58 + if (source == null)
66.59 + throw new IllegalArgumentException("null source");
66.60 +
66.61 + this.source = source;
66.62 + }
66.63 +
66.64 + /**
66.65 + * The object on which the Event initially occurred.
66.66 + *
66.67 + * @return The object on which the Event initially occurred.
66.68 + */
66.69 + public Object getSource() {
66.70 + return source;
66.71 + }
66.72 +
66.73 + /**
66.74 + * Returns a String representation of this EventObject.
66.75 + *
66.76 + * @return A a String representation of this EventObject.
66.77 + */
66.78 + public String toString() {
66.79 + return getClass().getName() + "[source=" + source + "]";
66.80 + }
66.81 +}
67.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
67.2 +++ b/emul/compact/src/main/java/java/util/Hashtable.java Sun Feb 17 17:58:34 2013 +0100
67.3 @@ -0,0 +1,1005 @@
67.4 +/*
67.5 + * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
67.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
67.7 + *
67.8 + * This code is free software; you can redistribute it and/or modify it
67.9 + * under the terms of the GNU General Public License version 2 only, as
67.10 + * published by the Free Software Foundation. Oracle designates this
67.11 + * particular file as subject to the "Classpath" exception as provided
67.12 + * by Oracle in the LICENSE file that accompanied this code.
67.13 + *
67.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
67.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
67.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
67.17 + * version 2 for more details (a copy is included in the LICENSE file that
67.18 + * accompanied this code).
67.19 + *
67.20 + * You should have received a copy of the GNU General Public License version
67.21 + * 2 along with this work; if not, write to the Free Software Foundation,
67.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
67.23 + *
67.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
67.25 + * or visit www.oracle.com if you need additional information or have any
67.26 + * questions.
67.27 + */
67.28 +
67.29 +package java.util;
67.30 +import java.io.*;
67.31 +
67.32 +/**
67.33 + * This class implements a hash table, which maps keys to values. Any
67.34 + * non-<code>null</code> object can be used as a key or as a value. <p>
67.35 + *
67.36 + * To successfully store and retrieve objects from a hashtable, the
67.37 + * objects used as keys must implement the <code>hashCode</code>
67.38 + * method and the <code>equals</code> method. <p>
67.39 + *
67.40 + * An instance of <code>Hashtable</code> has two parameters that affect its
67.41 + * performance: <i>initial capacity</i> and <i>load factor</i>. The
67.42 + * <i>capacity</i> is the number of <i>buckets</i> in the hash table, and the
67.43 + * <i>initial capacity</i> is simply the capacity at the time the hash table
67.44 + * is created. Note that the hash table is <i>open</i>: in the case of a "hash
67.45 + * collision", a single bucket stores multiple entries, which must be searched
67.46 + * sequentially. The <i>load factor</i> is a measure of how full the hash
67.47 + * table is allowed to get before its capacity is automatically increased.
67.48 + * The initial capacity and load factor parameters are merely hints to
67.49 + * the implementation. The exact details as to when and whether the rehash
67.50 + * method is invoked are implementation-dependent.<p>
67.51 + *
67.52 + * Generally, the default load factor (.75) offers a good tradeoff between
67.53 + * time and space costs. Higher values decrease the space overhead but
67.54 + * increase the time cost to look up an entry (which is reflected in most
67.55 + * <tt>Hashtable</tt> operations, including <tt>get</tt> and <tt>put</tt>).<p>
67.56 + *
67.57 + * The initial capacity controls a tradeoff between wasted space and the
67.58 + * need for <code>rehash</code> operations, which are time-consuming.
67.59 + * No <code>rehash</code> operations will <i>ever</i> occur if the initial
67.60 + * capacity is greater than the maximum number of entries the
67.61 + * <tt>Hashtable</tt> will contain divided by its load factor. However,
67.62 + * setting the initial capacity too high can waste space.<p>
67.63 + *
67.64 + * If many entries are to be made into a <code>Hashtable</code>,
67.65 + * creating it with a sufficiently large capacity may allow the
67.66 + * entries to be inserted more efficiently than letting it perform
67.67 + * automatic rehashing as needed to grow the table. <p>
67.68 + *
67.69 + * This example creates a hashtable of numbers. It uses the names of
67.70 + * the numbers as keys:
67.71 + * <pre> {@code
67.72 + * Hashtable<String, Integer> numbers
67.73 + * = new Hashtable<String, Integer>();
67.74 + * numbers.put("one", 1);
67.75 + * numbers.put("two", 2);
67.76 + * numbers.put("three", 3);}</pre>
67.77 + *
67.78 + * <p>To retrieve a number, use the following code:
67.79 + * <pre> {@code
67.80 + * Integer n = numbers.get("two");
67.81 + * if (n != null) {
67.82 + * System.out.println("two = " + n);
67.83 + * }}</pre>
67.84 + *
67.85 + * <p>The iterators returned by the <tt>iterator</tt> method of the collections
67.86 + * returned by all of this class's "collection view methods" are
67.87 + * <em>fail-fast</em>: if the Hashtable is structurally modified at any time
67.88 + * after the iterator is created, in any way except through the iterator's own
67.89 + * <tt>remove</tt> method, the iterator will throw a {@link
67.90 + * ConcurrentModificationException}. Thus, in the face of concurrent
67.91 + * modification, the iterator fails quickly and cleanly, rather than risking
67.92 + * arbitrary, non-deterministic behavior at an undetermined time in the future.
67.93 + * The Enumerations returned by Hashtable's keys and elements methods are
67.94 + * <em>not</em> fail-fast.
67.95 + *
67.96 + * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
67.97 + * as it is, generally speaking, impossible to make any hard guarantees in the
67.98 + * presence of unsynchronized concurrent modification. Fail-fast iterators
67.99 + * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
67.100 + * Therefore, it would be wrong to write a program that depended on this
67.101 + * exception for its correctness: <i>the fail-fast behavior of iterators
67.102 + * should be used only to detect bugs.</i>
67.103 + *
67.104 + * <p>As of the Java 2 platform v1.2, this class was retrofitted to
67.105 + * implement the {@link Map} interface, making it a member of the
67.106 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
67.107 + *
67.108 + * Java Collections Framework</a>. Unlike the new collection
67.109 + * implementations, {@code Hashtable} is synchronized. If a
67.110 + * thread-safe implementation is not needed, it is recommended to use
67.111 + * {@link HashMap} in place of {@code Hashtable}. If a thread-safe
67.112 + * highly-concurrent implementation is desired, then it is recommended
67.113 + * to use {@link java.util.concurrent.ConcurrentHashMap} in place of
67.114 + * {@code Hashtable}.
67.115 + *
67.116 + * @author Arthur van Hoff
67.117 + * @author Josh Bloch
67.118 + * @author Neal Gafter
67.119 + * @see Object#equals(java.lang.Object)
67.120 + * @see Object#hashCode()
67.121 + * @see Hashtable#rehash()
67.122 + * @see Collection
67.123 + * @see Map
67.124 + * @see HashMap
67.125 + * @see TreeMap
67.126 + * @since JDK1.0
67.127 + */
67.128 +public class Hashtable<K,V>
67.129 + extends Dictionary<K,V>
67.130 + implements Map<K,V>, Cloneable, java.io.Serializable {
67.131 +
67.132 + /**
67.133 + * The hash table data.
67.134 + */
67.135 + private transient Entry[] table;
67.136 +
67.137 + /**
67.138 + * The total number of entries in the hash table.
67.139 + */
67.140 + private transient int count;
67.141 +
67.142 + /**
67.143 + * The table is rehashed when its size exceeds this threshold. (The
67.144 + * value of this field is (int)(capacity * loadFactor).)
67.145 + *
67.146 + * @serial
67.147 + */
67.148 + private int threshold;
67.149 +
67.150 + /**
67.151 + * The load factor for the hashtable.
67.152 + *
67.153 + * @serial
67.154 + */
67.155 + private float loadFactor;
67.156 +
67.157 + /**
67.158 + * The number of times this Hashtable has been structurally modified
67.159 + * Structural modifications are those that change the number of entries in
67.160 + * the Hashtable or otherwise modify its internal structure (e.g.,
67.161 + * rehash). This field is used to make iterators on Collection-views of
67.162 + * the Hashtable fail-fast. (See ConcurrentModificationException).
67.163 + */
67.164 + private transient int modCount = 0;
67.165 +
67.166 + /** use serialVersionUID from JDK 1.0.2 for interoperability */
67.167 + private static final long serialVersionUID = 1421746759512286392L;
67.168 +
67.169 + /**
67.170 + * Constructs a new, empty hashtable with the specified initial
67.171 + * capacity and the specified load factor.
67.172 + *
67.173 + * @param initialCapacity the initial capacity of the hashtable.
67.174 + * @param loadFactor the load factor of the hashtable.
67.175 + * @exception IllegalArgumentException if the initial capacity is less
67.176 + * than zero, or if the load factor is nonpositive.
67.177 + */
67.178 + public Hashtable(int initialCapacity, float loadFactor) {
67.179 + if (initialCapacity < 0)
67.180 + throw new IllegalArgumentException("Illegal Capacity: "+
67.181 + initialCapacity);
67.182 + if (loadFactor <= 0 || Float.isNaN(loadFactor))
67.183 + throw new IllegalArgumentException("Illegal Load: "+loadFactor);
67.184 +
67.185 + if (initialCapacity==0)
67.186 + initialCapacity = 1;
67.187 + this.loadFactor = loadFactor;
67.188 + table = new Entry[initialCapacity];
67.189 + threshold = (int)(initialCapacity * loadFactor);
67.190 + }
67.191 +
67.192 + /**
67.193 + * Constructs a new, empty hashtable with the specified initial capacity
67.194 + * and default load factor (0.75).
67.195 + *
67.196 + * @param initialCapacity the initial capacity of the hashtable.
67.197 + * @exception IllegalArgumentException if the initial capacity is less
67.198 + * than zero.
67.199 + */
67.200 + public Hashtable(int initialCapacity) {
67.201 + this(initialCapacity, 0.75f);
67.202 + }
67.203 +
67.204 + /**
67.205 + * Constructs a new, empty hashtable with a default initial capacity (11)
67.206 + * and load factor (0.75).
67.207 + */
67.208 + public Hashtable() {
67.209 + this(11, 0.75f);
67.210 + }
67.211 +
67.212 + /**
67.213 + * Constructs a new hashtable with the same mappings as the given
67.214 + * Map. The hashtable is created with an initial capacity sufficient to
67.215 + * hold the mappings in the given Map and a default load factor (0.75).
67.216 + *
67.217 + * @param t the map whose mappings are to be placed in this map.
67.218 + * @throws NullPointerException if the specified map is null.
67.219 + * @since 1.2
67.220 + */
67.221 + public Hashtable(Map<? extends K, ? extends V> t) {
67.222 + this(Math.max(2*t.size(), 11), 0.75f);
67.223 + putAll(t);
67.224 + }
67.225 +
67.226 + /**
67.227 + * Returns the number of keys in this hashtable.
67.228 + *
67.229 + * @return the number of keys in this hashtable.
67.230 + */
67.231 + public synchronized int size() {
67.232 + return count;
67.233 + }
67.234 +
67.235 + /**
67.236 + * Tests if this hashtable maps no keys to values.
67.237 + *
67.238 + * @return <code>true</code> if this hashtable maps no keys to values;
67.239 + * <code>false</code> otherwise.
67.240 + */
67.241 + public synchronized boolean isEmpty() {
67.242 + return count == 0;
67.243 + }
67.244 +
67.245 + /**
67.246 + * Returns an enumeration of the keys in this hashtable.
67.247 + *
67.248 + * @return an enumeration of the keys in this hashtable.
67.249 + * @see Enumeration
67.250 + * @see #elements()
67.251 + * @see #keySet()
67.252 + * @see Map
67.253 + */
67.254 + public synchronized Enumeration<K> keys() {
67.255 + return this.<K>getEnumeration(KEYS);
67.256 + }
67.257 +
67.258 + /**
67.259 + * Returns an enumeration of the values in this hashtable.
67.260 + * Use the Enumeration methods on the returned object to fetch the elements
67.261 + * sequentially.
67.262 + *
67.263 + * @return an enumeration of the values in this hashtable.
67.264 + * @see java.util.Enumeration
67.265 + * @see #keys()
67.266 + * @see #values()
67.267 + * @see Map
67.268 + */
67.269 + public synchronized Enumeration<V> elements() {
67.270 + return this.<V>getEnumeration(VALUES);
67.271 + }
67.272 +
67.273 + /**
67.274 + * Tests if some key maps into the specified value in this hashtable.
67.275 + * This operation is more expensive than the {@link #containsKey
67.276 + * containsKey} method.
67.277 + *
67.278 + * <p>Note that this method is identical in functionality to
67.279 + * {@link #containsValue containsValue}, (which is part of the
67.280 + * {@link Map} interface in the collections framework).
67.281 + *
67.282 + * @param value a value to search for
67.283 + * @return <code>true</code> if and only if some key maps to the
67.284 + * <code>value</code> argument in this hashtable as
67.285 + * determined by the <tt>equals</tt> method;
67.286 + * <code>false</code> otherwise.
67.287 + * @exception NullPointerException if the value is <code>null</code>
67.288 + */
67.289 + public synchronized boolean contains(Object value) {
67.290 + if (value == null) {
67.291 + throw new NullPointerException();
67.292 + }
67.293 +
67.294 + Entry tab[] = table;
67.295 + for (int i = tab.length ; i-- > 0 ;) {
67.296 + for (Entry<K,V> e = tab[i] ; e != null ; e = e.next) {
67.297 + if (e.value.equals(value)) {
67.298 + return true;
67.299 + }
67.300 + }
67.301 + }
67.302 + return false;
67.303 + }
67.304 +
67.305 + /**
67.306 + * Returns true if this hashtable maps one or more keys to this value.
67.307 + *
67.308 + * <p>Note that this method is identical in functionality to {@link
67.309 + * #contains contains} (which predates the {@link Map} interface).
67.310 + *
67.311 + * @param value value whose presence in this hashtable is to be tested
67.312 + * @return <tt>true</tt> if this map maps one or more keys to the
67.313 + * specified value
67.314 + * @throws NullPointerException if the value is <code>null</code>
67.315 + * @since 1.2
67.316 + */
67.317 + public boolean containsValue(Object value) {
67.318 + return contains(value);
67.319 + }
67.320 +
67.321 + /**
67.322 + * Tests if the specified object is a key in this hashtable.
67.323 + *
67.324 + * @param key possible key
67.325 + * @return <code>true</code> if and only if the specified object
67.326 + * is a key in this hashtable, as determined by the
67.327 + * <tt>equals</tt> method; <code>false</code> otherwise.
67.328 + * @throws NullPointerException if the key is <code>null</code>
67.329 + * @see #contains(Object)
67.330 + */
67.331 + public synchronized boolean containsKey(Object key) {
67.332 + Entry tab[] = table;
67.333 + int hash = key.hashCode();
67.334 + int index = (hash & 0x7FFFFFFF) % tab.length;
67.335 + for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
67.336 + if ((e.hash == hash) && e.key.equals(key)) {
67.337 + return true;
67.338 + }
67.339 + }
67.340 + return false;
67.341 + }
67.342 +
67.343 + /**
67.344 + * Returns the value to which the specified key is mapped,
67.345 + * or {@code null} if this map contains no mapping for the key.
67.346 + *
67.347 + * <p>More formally, if this map contains a mapping from a key
67.348 + * {@code k} to a value {@code v} such that {@code (key.equals(k))},
67.349 + * then this method returns {@code v}; otherwise it returns
67.350 + * {@code null}. (There can be at most one such mapping.)
67.351 + *
67.352 + * @param key the key whose associated value is to be returned
67.353 + * @return the value to which the specified key is mapped, or
67.354 + * {@code null} if this map contains no mapping for the key
67.355 + * @throws NullPointerException if the specified key is null
67.356 + * @see #put(Object, Object)
67.357 + */
67.358 + public synchronized V get(Object key) {
67.359 + Entry tab[] = table;
67.360 + int hash = key.hashCode();
67.361 + int index = (hash & 0x7FFFFFFF) % tab.length;
67.362 + for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
67.363 + if ((e.hash == hash) && e.key.equals(key)) {
67.364 + return e.value;
67.365 + }
67.366 + }
67.367 + return null;
67.368 + }
67.369 +
67.370 + /**
67.371 + * The maximum size of array to allocate.
67.372 + * Some VMs reserve some header words in an array.
67.373 + * Attempts to allocate larger arrays may result in
67.374 + * OutOfMemoryError: Requested array size exceeds VM limit
67.375 + */
67.376 + private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
67.377 +
67.378 + /**
67.379 + * Increases the capacity of and internally reorganizes this
67.380 + * hashtable, in order to accommodate and access its entries more
67.381 + * efficiently. This method is called automatically when the
67.382 + * number of keys in the hashtable exceeds this hashtable's capacity
67.383 + * and load factor.
67.384 + */
67.385 + protected void rehash() {
67.386 + int oldCapacity = table.length;
67.387 + Entry[] oldMap = table;
67.388 +
67.389 + // overflow-conscious code
67.390 + int newCapacity = (oldCapacity << 1) + 1;
67.391 + if (newCapacity - MAX_ARRAY_SIZE > 0) {
67.392 + if (oldCapacity == MAX_ARRAY_SIZE)
67.393 + // Keep running with MAX_ARRAY_SIZE buckets
67.394 + return;
67.395 + newCapacity = MAX_ARRAY_SIZE;
67.396 + }
67.397 + Entry[] newMap = new Entry[newCapacity];
67.398 +
67.399 + modCount++;
67.400 + threshold = (int)(newCapacity * loadFactor);
67.401 + table = newMap;
67.402 +
67.403 + for (int i = oldCapacity ; i-- > 0 ;) {
67.404 + for (Entry<K,V> old = oldMap[i] ; old != null ; ) {
67.405 + Entry<K,V> e = old;
67.406 + old = old.next;
67.407 +
67.408 + int index = (e.hash & 0x7FFFFFFF) % newCapacity;
67.409 + e.next = newMap[index];
67.410 + newMap[index] = e;
67.411 + }
67.412 + }
67.413 + }
67.414 +
67.415 + /**
67.416 + * Maps the specified <code>key</code> to the specified
67.417 + * <code>value</code> in this hashtable. Neither the key nor the
67.418 + * value can be <code>null</code>. <p>
67.419 + *
67.420 + * The value can be retrieved by calling the <code>get</code> method
67.421 + * with a key that is equal to the original key.
67.422 + *
67.423 + * @param key the hashtable key
67.424 + * @param value the value
67.425 + * @return the previous value of the specified key in this hashtable,
67.426 + * or <code>null</code> if it did not have one
67.427 + * @exception NullPointerException if the key or value is
67.428 + * <code>null</code>
67.429 + * @see Object#equals(Object)
67.430 + * @see #get(Object)
67.431 + */
67.432 + public synchronized V put(K key, V value) {
67.433 + // Make sure the value is not null
67.434 + if (value == null) {
67.435 + throw new NullPointerException();
67.436 + }
67.437 +
67.438 + // Makes sure the key is not already in the hashtable.
67.439 + Entry tab[] = table;
67.440 + int hash = key.hashCode();
67.441 + int index = (hash & 0x7FFFFFFF) % tab.length;
67.442 + for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
67.443 + if ((e.hash == hash) && e.key.equals(key)) {
67.444 + V old = e.value;
67.445 + e.value = value;
67.446 + return old;
67.447 + }
67.448 + }
67.449 +
67.450 + modCount++;
67.451 + if (count >= threshold) {
67.452 + // Rehash the table if the threshold is exceeded
67.453 + rehash();
67.454 +
67.455 + tab = table;
67.456 + index = (hash & 0x7FFFFFFF) % tab.length;
67.457 + }
67.458 +
67.459 + // Creates the new entry.
67.460 + Entry<K,V> e = tab[index];
67.461 + tab[index] = new Entry<>(hash, key, value, e);
67.462 + count++;
67.463 + return null;
67.464 + }
67.465 +
67.466 + /**
67.467 + * Removes the key (and its corresponding value) from this
67.468 + * hashtable. This method does nothing if the key is not in the hashtable.
67.469 + *
67.470 + * @param key the key that needs to be removed
67.471 + * @return the value to which the key had been mapped in this hashtable,
67.472 + * or <code>null</code> if the key did not have a mapping
67.473 + * @throws NullPointerException if the key is <code>null</code>
67.474 + */
67.475 + public synchronized V remove(Object key) {
67.476 + Entry tab[] = table;
67.477 + int hash = key.hashCode();
67.478 + int index = (hash & 0x7FFFFFFF) % tab.length;
67.479 + for (Entry<K,V> e = tab[index], prev = null ; e != null ; prev = e, e = e.next) {
67.480 + if ((e.hash == hash) && e.key.equals(key)) {
67.481 + modCount++;
67.482 + if (prev != null) {
67.483 + prev.next = e.next;
67.484 + } else {
67.485 + tab[index] = e.next;
67.486 + }
67.487 + count--;
67.488 + V oldValue = e.value;
67.489 + e.value = null;
67.490 + return oldValue;
67.491 + }
67.492 + }
67.493 + return null;
67.494 + }
67.495 +
67.496 + /**
67.497 + * Copies all of the mappings from the specified map to this hashtable.
67.498 + * These mappings will replace any mappings that this hashtable had for any
67.499 + * of the keys currently in the specified map.
67.500 + *
67.501 + * @param t mappings to be stored in this map
67.502 + * @throws NullPointerException if the specified map is null
67.503 + * @since 1.2
67.504 + */
67.505 + public synchronized void putAll(Map<? extends K, ? extends V> t) {
67.506 + for (Map.Entry<? extends K, ? extends V> e : t.entrySet())
67.507 + put(e.getKey(), e.getValue());
67.508 + }
67.509 +
67.510 + /**
67.511 + * Clears this hashtable so that it contains no keys.
67.512 + */
67.513 + public synchronized void clear() {
67.514 + Entry tab[] = table;
67.515 + modCount++;
67.516 + for (int index = tab.length; --index >= 0; )
67.517 + tab[index] = null;
67.518 + count = 0;
67.519 + }
67.520 +
67.521 + /**
67.522 + * Creates a shallow copy of this hashtable. All the structure of the
67.523 + * hashtable itself is copied, but the keys and values are not cloned.
67.524 + * This is a relatively expensive operation.
67.525 + *
67.526 + * @return a clone of the hashtable
67.527 + */
67.528 + public synchronized Object clone() {
67.529 + try {
67.530 + Hashtable<K,V> t = (Hashtable<K,V>) super.clone();
67.531 + t.table = new Entry[table.length];
67.532 + for (int i = table.length ; i-- > 0 ; ) {
67.533 + t.table[i] = (table[i] != null)
67.534 + ? (Entry<K,V>) table[i].clone() : null;
67.535 + }
67.536 + t.keySet = null;
67.537 + t.entrySet = null;
67.538 + t.values = null;
67.539 + t.modCount = 0;
67.540 + return t;
67.541 + } catch (CloneNotSupportedException e) {
67.542 + // this shouldn't happen, since we are Cloneable
67.543 + throw new InternalError();
67.544 + }
67.545 + }
67.546 +
67.547 + /**
67.548 + * Returns a string representation of this <tt>Hashtable</tt> object
67.549 + * in the form of a set of entries, enclosed in braces and separated
67.550 + * by the ASCII characters "<tt>, </tt>" (comma and space). Each
67.551 + * entry is rendered as the key, an equals sign <tt>=</tt>, and the
67.552 + * associated element, where the <tt>toString</tt> method is used to
67.553 + * convert the key and element to strings.
67.554 + *
67.555 + * @return a string representation of this hashtable
67.556 + */
67.557 + public synchronized String toString() {
67.558 + int max = size() - 1;
67.559 + if (max == -1)
67.560 + return "{}";
67.561 +
67.562 + StringBuilder sb = new StringBuilder();
67.563 + Iterator<Map.Entry<K,V>> it = entrySet().iterator();
67.564 +
67.565 + sb.append('{');
67.566 + for (int i = 0; ; i++) {
67.567 + Map.Entry<K,V> e = it.next();
67.568 + K key = e.getKey();
67.569 + V value = e.getValue();
67.570 + sb.append(key == this ? "(this Map)" : key.toString());
67.571 + sb.append('=');
67.572 + sb.append(value == this ? "(this Map)" : value.toString());
67.573 +
67.574 + if (i == max)
67.575 + return sb.append('}').toString();
67.576 + sb.append(", ");
67.577 + }
67.578 + }
67.579 +
67.580 +
67.581 + private <T> Enumeration<T> getEnumeration(int type) {
67.582 + if (count == 0) {
67.583 + return Collections.emptyEnumeration();
67.584 + } else {
67.585 + return new Enumerator<>(type, false);
67.586 + }
67.587 + }
67.588 +
67.589 + private <T> Iterator<T> getIterator(int type) {
67.590 + if (count == 0) {
67.591 + return Collections.emptyIterator();
67.592 + } else {
67.593 + return new Enumerator<>(type, true);
67.594 + }
67.595 + }
67.596 +
67.597 + // Views
67.598 +
67.599 + /**
67.600 + * Each of these fields are initialized to contain an instance of the
67.601 + * appropriate view the first time this view is requested. The views are
67.602 + * stateless, so there's no reason to create more than one of each.
67.603 + */
67.604 + private transient volatile Set<K> keySet = null;
67.605 + private transient volatile Set<Map.Entry<K,V>> entrySet = null;
67.606 + private transient volatile Collection<V> values = null;
67.607 +
67.608 + /**
67.609 + * Returns a {@link Set} view of the keys contained in this map.
67.610 + * The set is backed by the map, so changes to the map are
67.611 + * reflected in the set, and vice-versa. If the map is modified
67.612 + * while an iteration over the set is in progress (except through
67.613 + * the iterator's own <tt>remove</tt> operation), the results of
67.614 + * the iteration are undefined. The set supports element removal,
67.615 + * which removes the corresponding mapping from the map, via the
67.616 + * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
67.617 + * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
67.618 + * operations. It does not support the <tt>add</tt> or <tt>addAll</tt>
67.619 + * operations.
67.620 + *
67.621 + * @since 1.2
67.622 + */
67.623 + public Set<K> keySet() {
67.624 + if (keySet == null)
67.625 + keySet = Collections.synchronizedSet(new KeySet(), this);
67.626 + return keySet;
67.627 + }
67.628 +
67.629 + private class KeySet extends AbstractSet<K> {
67.630 + public Iterator<K> iterator() {
67.631 + return getIterator(KEYS);
67.632 + }
67.633 + public int size() {
67.634 + return count;
67.635 + }
67.636 + public boolean contains(Object o) {
67.637 + return containsKey(o);
67.638 + }
67.639 + public boolean remove(Object o) {
67.640 + return Hashtable.this.remove(o) != null;
67.641 + }
67.642 + public void clear() {
67.643 + Hashtable.this.clear();
67.644 + }
67.645 + }
67.646 +
67.647 + /**
67.648 + * Returns a {@link Set} view of the mappings contained in this map.
67.649 + * The set is backed by the map, so changes to the map are
67.650 + * reflected in the set, and vice-versa. If the map is modified
67.651 + * while an iteration over the set is in progress (except through
67.652 + * the iterator's own <tt>remove</tt> operation, or through the
67.653 + * <tt>setValue</tt> operation on a map entry returned by the
67.654 + * iterator) the results of the iteration are undefined. The set
67.655 + * supports element removal, which removes the corresponding
67.656 + * mapping from the map, via the <tt>Iterator.remove</tt>,
67.657 + * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and
67.658 + * <tt>clear</tt> operations. It does not support the
67.659 + * <tt>add</tt> or <tt>addAll</tt> operations.
67.660 + *
67.661 + * @since 1.2
67.662 + */
67.663 + public Set<Map.Entry<K,V>> entrySet() {
67.664 + if (entrySet==null)
67.665 + entrySet = Collections.synchronizedSet(new EntrySet(), this);
67.666 + return entrySet;
67.667 + }
67.668 +
67.669 + private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
67.670 + public Iterator<Map.Entry<K,V>> iterator() {
67.671 + return getIterator(ENTRIES);
67.672 + }
67.673 +
67.674 + public boolean add(Map.Entry<K,V> o) {
67.675 + return super.add(o);
67.676 + }
67.677 +
67.678 + public boolean contains(Object o) {
67.679 + if (!(o instanceof Map.Entry))
67.680 + return false;
67.681 + Map.Entry entry = (Map.Entry)o;
67.682 + Object key = entry.getKey();
67.683 + Entry[] tab = table;
67.684 + int hash = key.hashCode();
67.685 + int index = (hash & 0x7FFFFFFF) % tab.length;
67.686 +
67.687 + for (Entry e = tab[index]; e != null; e = e.next)
67.688 + if (e.hash==hash && e.equals(entry))
67.689 + return true;
67.690 + return false;
67.691 + }
67.692 +
67.693 + public boolean remove(Object o) {
67.694 + if (!(o instanceof Map.Entry))
67.695 + return false;
67.696 + Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
67.697 + K key = entry.getKey();
67.698 + Entry[] tab = table;
67.699 + int hash = key.hashCode();
67.700 + int index = (hash & 0x7FFFFFFF) % tab.length;
67.701 +
67.702 + for (Entry<K,V> e = tab[index], prev = null; e != null;
67.703 + prev = e, e = e.next) {
67.704 + if (e.hash==hash && e.equals(entry)) {
67.705 + modCount++;
67.706 + if (prev != null)
67.707 + prev.next = e.next;
67.708 + else
67.709 + tab[index] = e.next;
67.710 +
67.711 + count--;
67.712 + e.value = null;
67.713 + return true;
67.714 + }
67.715 + }
67.716 + return false;
67.717 + }
67.718 +
67.719 + public int size() {
67.720 + return count;
67.721 + }
67.722 +
67.723 + public void clear() {
67.724 + Hashtable.this.clear();
67.725 + }
67.726 + }
67.727 +
67.728 + /**
67.729 + * Returns a {@link Collection} view of the values contained in this map.
67.730 + * The collection is backed by the map, so changes to the map are
67.731 + * reflected in the collection, and vice-versa. If the map is
67.732 + * modified while an iteration over the collection is in progress
67.733 + * (except through the iterator's own <tt>remove</tt> operation),
67.734 + * the results of the iteration are undefined. The collection
67.735 + * supports element removal, which removes the corresponding
67.736 + * mapping from the map, via the <tt>Iterator.remove</tt>,
67.737 + * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
67.738 + * <tt>retainAll</tt> and <tt>clear</tt> operations. It does not
67.739 + * support the <tt>add</tt> or <tt>addAll</tt> operations.
67.740 + *
67.741 + * @since 1.2
67.742 + */
67.743 + public Collection<V> values() {
67.744 + if (values==null)
67.745 + values = Collections.synchronizedCollection(new ValueCollection(),
67.746 + this);
67.747 + return values;
67.748 + }
67.749 +
67.750 + private class ValueCollection extends AbstractCollection<V> {
67.751 + public Iterator<V> iterator() {
67.752 + return getIterator(VALUES);
67.753 + }
67.754 + public int size() {
67.755 + return count;
67.756 + }
67.757 + public boolean contains(Object o) {
67.758 + return containsValue(o);
67.759 + }
67.760 + public void clear() {
67.761 + Hashtable.this.clear();
67.762 + }
67.763 + }
67.764 +
67.765 + // Comparison and hashing
67.766 +
67.767 + /**
67.768 + * Compares the specified Object with this Map for equality,
67.769 + * as per the definition in the Map interface.
67.770 + *
67.771 + * @param o object to be compared for equality with this hashtable
67.772 + * @return true if the specified Object is equal to this Map
67.773 + * @see Map#equals(Object)
67.774 + * @since 1.2
67.775 + */
67.776 + public synchronized boolean equals(Object o) {
67.777 + if (o == this)
67.778 + return true;
67.779 +
67.780 + if (!(o instanceof Map))
67.781 + return false;
67.782 + Map<K,V> t = (Map<K,V>) o;
67.783 + if (t.size() != size())
67.784 + return false;
67.785 +
67.786 + try {
67.787 + Iterator<Map.Entry<K,V>> i = entrySet().iterator();
67.788 + while (i.hasNext()) {
67.789 + Map.Entry<K,V> e = i.next();
67.790 + K key = e.getKey();
67.791 + V value = e.getValue();
67.792 + if (value == null) {
67.793 + if (!(t.get(key)==null && t.containsKey(key)))
67.794 + return false;
67.795 + } else {
67.796 + if (!value.equals(t.get(key)))
67.797 + return false;
67.798 + }
67.799 + }
67.800 + } catch (ClassCastException unused) {
67.801 + return false;
67.802 + } catch (NullPointerException unused) {
67.803 + return false;
67.804 + }
67.805 +
67.806 + return true;
67.807 + }
67.808 +
67.809 + /**
67.810 + * Returns the hash code value for this Map as per the definition in the
67.811 + * Map interface.
67.812 + *
67.813 + * @see Map#hashCode()
67.814 + * @since 1.2
67.815 + */
67.816 + public synchronized int hashCode() {
67.817 + /*
67.818 + * This code detects the recursion caused by computing the hash code
67.819 + * of a self-referential hash table and prevents the stack overflow
67.820 + * that would otherwise result. This allows certain 1.1-era
67.821 + * applets with self-referential hash tables to work. This code
67.822 + * abuses the loadFactor field to do double-duty as a hashCode
67.823 + * in progress flag, so as not to worsen the space performance.
67.824 + * A negative load factor indicates that hash code computation is
67.825 + * in progress.
67.826 + */
67.827 + int h = 0;
67.828 + if (count == 0 || loadFactor < 0)
67.829 + return h; // Returns zero
67.830 +
67.831 + loadFactor = -loadFactor; // Mark hashCode computation in progress
67.832 + Entry[] tab = table;
67.833 + for (int i = 0; i < tab.length; i++)
67.834 + for (Entry e = tab[i]; e != null; e = e.next)
67.835 + h += e.key.hashCode() ^ e.value.hashCode();
67.836 + loadFactor = -loadFactor; // Mark hashCode computation complete
67.837 +
67.838 + return h;
67.839 + }
67.840 +
67.841 + /**
67.842 + * Hashtable collision list.
67.843 + */
67.844 + private static class Entry<K,V> implements Map.Entry<K,V> {
67.845 + int hash;
67.846 + K key;
67.847 + V value;
67.848 + Entry<K,V> next;
67.849 +
67.850 + protected Entry(int hash, K key, V value, Entry<K,V> next) {
67.851 + this.hash = hash;
67.852 + this.key = key;
67.853 + this.value = value;
67.854 + this.next = next;
67.855 + }
67.856 +
67.857 + protected Object clone() {
67.858 + return new Entry<>(hash, key, value,
67.859 + (next==null ? null : (Entry<K,V>) next.clone()));
67.860 + }
67.861 +
67.862 + // Map.Entry Ops
67.863 +
67.864 + public K getKey() {
67.865 + return key;
67.866 + }
67.867 +
67.868 + public V getValue() {
67.869 + return value;
67.870 + }
67.871 +
67.872 + public V setValue(V value) {
67.873 + if (value == null)
67.874 + throw new NullPointerException();
67.875 +
67.876 + V oldValue = this.value;
67.877 + this.value = value;
67.878 + return oldValue;
67.879 + }
67.880 +
67.881 + public boolean equals(Object o) {
67.882 + if (!(o instanceof Map.Entry))
67.883 + return false;
67.884 + Map.Entry e = (Map.Entry)o;
67.885 +
67.886 + return (key==null ? e.getKey()==null : key.equals(e.getKey())) &&
67.887 + (value==null ? e.getValue()==null : value.equals(e.getValue()));
67.888 + }
67.889 +
67.890 + public int hashCode() {
67.891 + return hash ^ (value==null ? 0 : value.hashCode());
67.892 + }
67.893 +
67.894 + public String toString() {
67.895 + return key.toString()+"="+value.toString();
67.896 + }
67.897 + }
67.898 +
67.899 + // Types of Enumerations/Iterations
67.900 + private static final int KEYS = 0;
67.901 + private static final int VALUES = 1;
67.902 + private static final int ENTRIES = 2;
67.903 +
67.904 + /**
67.905 + * A hashtable enumerator class. This class implements both the
67.906 + * Enumeration and Iterator interfaces, but individual instances
67.907 + * can be created with the Iterator methods disabled. This is necessary
67.908 + * to avoid unintentionally increasing the capabilities granted a user
67.909 + * by passing an Enumeration.
67.910 + */
67.911 + private class Enumerator<T> implements Enumeration<T>, Iterator<T> {
67.912 + Entry[] table = Hashtable.this.table;
67.913 + int index = table.length;
67.914 + Entry<K,V> entry = null;
67.915 + Entry<K,V> lastReturned = null;
67.916 + int type;
67.917 +
67.918 + /**
67.919 + * Indicates whether this Enumerator is serving as an Iterator
67.920 + * or an Enumeration. (true -> Iterator).
67.921 + */
67.922 + boolean iterator;
67.923 +
67.924 + /**
67.925 + * The modCount value that the iterator believes that the backing
67.926 + * Hashtable should have. If this expectation is violated, the iterator
67.927 + * has detected concurrent modification.
67.928 + */
67.929 + protected int expectedModCount = modCount;
67.930 +
67.931 + Enumerator(int type, boolean iterator) {
67.932 + this.type = type;
67.933 + this.iterator = iterator;
67.934 + }
67.935 +
67.936 + public boolean hasMoreElements() {
67.937 + Entry<K,V> e = entry;
67.938 + int i = index;
67.939 + Entry[] t = table;
67.940 + /* Use locals for faster loop iteration */
67.941 + while (e == null && i > 0) {
67.942 + e = t[--i];
67.943 + }
67.944 + entry = e;
67.945 + index = i;
67.946 + return e != null;
67.947 + }
67.948 +
67.949 + public T nextElement() {
67.950 + Entry<K,V> et = entry;
67.951 + int i = index;
67.952 + Entry[] t = table;
67.953 + /* Use locals for faster loop iteration */
67.954 + while (et == null && i > 0) {
67.955 + et = t[--i];
67.956 + }
67.957 + entry = et;
67.958 + index = i;
67.959 + if (et != null) {
67.960 + Entry<K,V> e = lastReturned = entry;
67.961 + entry = e.next;
67.962 + return type == KEYS ? (T)e.key : (type == VALUES ? (T)e.value : (T)e);
67.963 + }
67.964 + throw new NoSuchElementException("Hashtable Enumerator");
67.965 + }
67.966 +
67.967 + // Iterator methods
67.968 + public boolean hasNext() {
67.969 + return hasMoreElements();
67.970 + }
67.971 +
67.972 + public T next() {
67.973 + if (modCount != expectedModCount)
67.974 + throw new ConcurrentModificationException();
67.975 + return nextElement();
67.976 + }
67.977 +
67.978 + public void remove() {
67.979 + if (!iterator)
67.980 + throw new UnsupportedOperationException();
67.981 + if (lastReturned == null)
67.982 + throw new IllegalStateException("Hashtable Enumerator");
67.983 + if (modCount != expectedModCount)
67.984 + throw new ConcurrentModificationException();
67.985 +
67.986 + synchronized(Hashtable.this) {
67.987 + Entry[] tab = Hashtable.this.table;
67.988 + int index = (lastReturned.hash & 0x7FFFFFFF) % tab.length;
67.989 +
67.990 + for (Entry<K,V> e = tab[index], prev = null; e != null;
67.991 + prev = e, e = e.next) {
67.992 + if (e == lastReturned) {
67.993 + modCount++;
67.994 + expectedModCount++;
67.995 + if (prev == null)
67.996 + tab[index] = e.next;
67.997 + else
67.998 + prev.next = e.next;
67.999 + count--;
67.1000 + lastReturned = null;
67.1001 + return;
67.1002 + }
67.1003 + }
67.1004 + throw new ConcurrentModificationException();
67.1005 + }
67.1006 + }
67.1007 + }
67.1008 +}
68.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
68.2 +++ b/emul/compact/src/main/java/java/util/LinkedList.java Sun Feb 17 17:58:34 2013 +0100
68.3 @@ -0,0 +1,1100 @@
68.4 +/*
68.5 + * Copyright (c) 1997, 2011, 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 + * This code is free software; you can redistribute it and/or modify it
68.9 + * under the terms of the GNU General Public License version 2 only, as
68.10 + * published by the Free Software Foundation. Oracle designates this
68.11 + * particular file as subject to the "Classpath" exception as provided
68.12 + * by Oracle in the LICENSE file that accompanied this code.
68.13 + *
68.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
68.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
68.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
68.17 + * version 2 for more details (a copy is included in the LICENSE file that
68.18 + * accompanied this code).
68.19 + *
68.20 + * You should have received a copy of the GNU General Public License version
68.21 + * 2 along with this work; if not, write to the Free Software Foundation,
68.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
68.23 + *
68.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
68.25 + * or visit www.oracle.com if you need additional information or have any
68.26 + * questions.
68.27 + */
68.28 +
68.29 +package java.util;
68.30 +
68.31 +/**
68.32 + * Doubly-linked list implementation of the {@code List} and {@code Deque}
68.33 + * interfaces. Implements all optional list operations, and permits all
68.34 + * elements (including {@code null}).
68.35 + *
68.36 + * <p>All of the operations perform as could be expected for a doubly-linked
68.37 + * list. Operations that index into the list will traverse the list from
68.38 + * the beginning or the end, whichever is closer to the specified index.
68.39 + *
68.40 + * <p><strong>Note that this implementation is not synchronized.</strong>
68.41 + * If multiple threads access a linked list concurrently, and at least
68.42 + * one of the threads modifies the list structurally, it <i>must</i> be
68.43 + * synchronized externally. (A structural modification is any operation
68.44 + * that adds or deletes one or more elements; merely setting the value of
68.45 + * an element is not a structural modification.) This is typically
68.46 + * accomplished by synchronizing on some object that naturally
68.47 + * encapsulates the list.
68.48 + *
68.49 + * If no such object exists, the list should be "wrapped" using the
68.50 + * {@link Collections#synchronizedList Collections.synchronizedList}
68.51 + * method. This is best done at creation time, to prevent accidental
68.52 + * unsynchronized access to the list:<pre>
68.53 + * List list = Collections.synchronizedList(new LinkedList(...));</pre>
68.54 + *
68.55 + * <p>The iterators returned by this class's {@code iterator} and
68.56 + * {@code listIterator} methods are <i>fail-fast</i>: if the list is
68.57 + * structurally modified at any time after the iterator is created, in
68.58 + * any way except through the Iterator's own {@code remove} or
68.59 + * {@code add} methods, the iterator will throw a {@link
68.60 + * ConcurrentModificationException}. Thus, in the face of concurrent
68.61 + * modification, the iterator fails quickly and cleanly, rather than
68.62 + * risking arbitrary, non-deterministic behavior at an undetermined
68.63 + * time in the future.
68.64 + *
68.65 + * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
68.66 + * as it is, generally speaking, impossible to make any hard guarantees in the
68.67 + * presence of unsynchronized concurrent modification. Fail-fast iterators
68.68 + * throw {@code ConcurrentModificationException} on a best-effort basis.
68.69 + * Therefore, it would be wrong to write a program that depended on this
68.70 + * exception for its correctness: <i>the fail-fast behavior of iterators
68.71 + * should be used only to detect bugs.</i>
68.72 + *
68.73 + * <p>This class is a member of the
68.74 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
68.75 + * Java Collections Framework</a>.
68.76 + *
68.77 + * @author Josh Bloch
68.78 + * @see List
68.79 + * @see ArrayList
68.80 + * @since 1.2
68.81 + * @param <E> the type of elements held in this collection
68.82 + */
68.83 +
68.84 +public class LinkedList<E>
68.85 + extends AbstractSequentialList<E>
68.86 + implements List<E>, Deque<E>, Cloneable, java.io.Serializable
68.87 +{
68.88 + transient int size = 0;
68.89 +
68.90 + /**
68.91 + * Pointer to first node.
68.92 + * Invariant: (first == null && last == null) ||
68.93 + * (first.prev == null && first.item != null)
68.94 + */
68.95 + transient Node<E> first;
68.96 +
68.97 + /**
68.98 + * Pointer to last node.
68.99 + * Invariant: (first == null && last == null) ||
68.100 + * (last.next == null && last.item != null)
68.101 + */
68.102 + transient Node<E> last;
68.103 +
68.104 + /**
68.105 + * Constructs an empty list.
68.106 + */
68.107 + public LinkedList() {
68.108 + }
68.109 +
68.110 + /**
68.111 + * Constructs a list containing the elements of the specified
68.112 + * collection, in the order they are returned by the collection's
68.113 + * iterator.
68.114 + *
68.115 + * @param c the collection whose elements are to be placed into this list
68.116 + * @throws NullPointerException if the specified collection is null
68.117 + */
68.118 + public LinkedList(Collection<? extends E> c) {
68.119 + this();
68.120 + addAll(c);
68.121 + }
68.122 +
68.123 + /**
68.124 + * Links e as first element.
68.125 + */
68.126 + private void linkFirst(E e) {
68.127 + final Node<E> f = first;
68.128 + final Node<E> newNode = new Node<>(null, e, f);
68.129 + first = newNode;
68.130 + if (f == null)
68.131 + last = newNode;
68.132 + else
68.133 + f.prev = newNode;
68.134 + size++;
68.135 + modCount++;
68.136 + }
68.137 +
68.138 + /**
68.139 + * Links e as last element.
68.140 + */
68.141 + void linkLast(E e) {
68.142 + final Node<E> l = last;
68.143 + final Node<E> newNode = new Node<>(l, e, null);
68.144 + last = newNode;
68.145 + if (l == null)
68.146 + first = newNode;
68.147 + else
68.148 + l.next = newNode;
68.149 + size++;
68.150 + modCount++;
68.151 + }
68.152 +
68.153 + /**
68.154 + * Inserts element e before non-null Node succ.
68.155 + */
68.156 + void linkBefore(E e, Node<E> succ) {
68.157 + // assert succ != null;
68.158 + final Node<E> pred = succ.prev;
68.159 + final Node<E> newNode = new Node<>(pred, e, succ);
68.160 + succ.prev = newNode;
68.161 + if (pred == null)
68.162 + first = newNode;
68.163 + else
68.164 + pred.next = newNode;
68.165 + size++;
68.166 + modCount++;
68.167 + }
68.168 +
68.169 + /**
68.170 + * Unlinks non-null first node f.
68.171 + */
68.172 + private E unlinkFirst(Node<E> f) {
68.173 + // assert f == first && f != null;
68.174 + final E element = f.item;
68.175 + final Node<E> next = f.next;
68.176 + f.item = null;
68.177 + f.next = null; // help GC
68.178 + first = next;
68.179 + if (next == null)
68.180 + last = null;
68.181 + else
68.182 + next.prev = null;
68.183 + size--;
68.184 + modCount++;
68.185 + return element;
68.186 + }
68.187 +
68.188 + /**
68.189 + * Unlinks non-null last node l.
68.190 + */
68.191 + private E unlinkLast(Node<E> l) {
68.192 + // assert l == last && l != null;
68.193 + final E element = l.item;
68.194 + final Node<E> prev = l.prev;
68.195 + l.item = null;
68.196 + l.prev = null; // help GC
68.197 + last = prev;
68.198 + if (prev == null)
68.199 + first = null;
68.200 + else
68.201 + prev.next = null;
68.202 + size--;
68.203 + modCount++;
68.204 + return element;
68.205 + }
68.206 +
68.207 + /**
68.208 + * Unlinks non-null node x.
68.209 + */
68.210 + E unlink(Node<E> x) {
68.211 + // assert x != null;
68.212 + final E element = x.item;
68.213 + final Node<E> next = x.next;
68.214 + final Node<E> prev = x.prev;
68.215 +
68.216 + if (prev == null) {
68.217 + first = next;
68.218 + } else {
68.219 + prev.next = next;
68.220 + x.prev = null;
68.221 + }
68.222 +
68.223 + if (next == null) {
68.224 + last = prev;
68.225 + } else {
68.226 + next.prev = prev;
68.227 + x.next = null;
68.228 + }
68.229 +
68.230 + x.item = null;
68.231 + size--;
68.232 + modCount++;
68.233 + return element;
68.234 + }
68.235 +
68.236 + /**
68.237 + * Returns the first element in this list.
68.238 + *
68.239 + * @return the first element in this list
68.240 + * @throws NoSuchElementException if this list is empty
68.241 + */
68.242 + public E getFirst() {
68.243 + final Node<E> f = first;
68.244 + if (f == null)
68.245 + throw new NoSuchElementException();
68.246 + return f.item;
68.247 + }
68.248 +
68.249 + /**
68.250 + * Returns the last element in this list.
68.251 + *
68.252 + * @return the last element in this list
68.253 + * @throws NoSuchElementException if this list is empty
68.254 + */
68.255 + public E getLast() {
68.256 + final Node<E> l = last;
68.257 + if (l == null)
68.258 + throw new NoSuchElementException();
68.259 + return l.item;
68.260 + }
68.261 +
68.262 + /**
68.263 + * Removes and returns the first element from this list.
68.264 + *
68.265 + * @return the first element from this list
68.266 + * @throws NoSuchElementException if this list is empty
68.267 + */
68.268 + public E removeFirst() {
68.269 + final Node<E> f = first;
68.270 + if (f == null)
68.271 + throw new NoSuchElementException();
68.272 + return unlinkFirst(f);
68.273 + }
68.274 +
68.275 + /**
68.276 + * Removes and returns the last element from this list.
68.277 + *
68.278 + * @return the last element from this list
68.279 + * @throws NoSuchElementException if this list is empty
68.280 + */
68.281 + public E removeLast() {
68.282 + final Node<E> l = last;
68.283 + if (l == null)
68.284 + throw new NoSuchElementException();
68.285 + return unlinkLast(l);
68.286 + }
68.287 +
68.288 + /**
68.289 + * Inserts the specified element at the beginning of this list.
68.290 + *
68.291 + * @param e the element to add
68.292 + */
68.293 + public void addFirst(E e) {
68.294 + linkFirst(e);
68.295 + }
68.296 +
68.297 + /**
68.298 + * Appends the specified element to the end of this list.
68.299 + *
68.300 + * <p>This method is equivalent to {@link #add}.
68.301 + *
68.302 + * @param e the element to add
68.303 + */
68.304 + public void addLast(E e) {
68.305 + linkLast(e);
68.306 + }
68.307 +
68.308 + /**
68.309 + * Returns {@code true} if this list contains the specified element.
68.310 + * More formally, returns {@code true} if and only if this list contains
68.311 + * at least one element {@code e} such that
68.312 + * <tt>(o==null ? e==null : o.equals(e))</tt>.
68.313 + *
68.314 + * @param o element whose presence in this list is to be tested
68.315 + * @return {@code true} if this list contains the specified element
68.316 + */
68.317 + public boolean contains(Object o) {
68.318 + return indexOf(o) != -1;
68.319 + }
68.320 +
68.321 + /**
68.322 + * Returns the number of elements in this list.
68.323 + *
68.324 + * @return the number of elements in this list
68.325 + */
68.326 + public int size() {
68.327 + return size;
68.328 + }
68.329 +
68.330 + /**
68.331 + * Appends the specified element to the end of this list.
68.332 + *
68.333 + * <p>This method is equivalent to {@link #addLast}.
68.334 + *
68.335 + * @param e element to be appended to this list
68.336 + * @return {@code true} (as specified by {@link Collection#add})
68.337 + */
68.338 + public boolean add(E e) {
68.339 + linkLast(e);
68.340 + return true;
68.341 + }
68.342 +
68.343 + /**
68.344 + * Removes the first occurrence of the specified element from this list,
68.345 + * if it is present. If this list does not contain the element, it is
68.346 + * unchanged. More formally, removes the element with the lowest index
68.347 + * {@code i} such that
68.348 + * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>
68.349 + * (if such an element exists). Returns {@code true} if this list
68.350 + * contained the specified element (or equivalently, if this list
68.351 + * changed as a result of the call).
68.352 + *
68.353 + * @param o element to be removed from this list, if present
68.354 + * @return {@code true} if this list contained the specified element
68.355 + */
68.356 + public boolean remove(Object o) {
68.357 + if (o == null) {
68.358 + for (Node<E> x = first; x != null; x = x.next) {
68.359 + if (x.item == null) {
68.360 + unlink(x);
68.361 + return true;
68.362 + }
68.363 + }
68.364 + } else {
68.365 + for (Node<E> x = first; x != null; x = x.next) {
68.366 + if (o.equals(x.item)) {
68.367 + unlink(x);
68.368 + return true;
68.369 + }
68.370 + }
68.371 + }
68.372 + return false;
68.373 + }
68.374 +
68.375 + /**
68.376 + * Appends all of the elements in the specified collection to the end of
68.377 + * this list, in the order that they are returned by the specified
68.378 + * collection's iterator. The behavior of this operation is undefined if
68.379 + * the specified collection is modified while the operation is in
68.380 + * progress. (Note that this will occur if the specified collection is
68.381 + * this list, and it's nonempty.)
68.382 + *
68.383 + * @param c collection containing elements to be added to this list
68.384 + * @return {@code true} if this list changed as a result of the call
68.385 + * @throws NullPointerException if the specified collection is null
68.386 + */
68.387 + public boolean addAll(Collection<? extends E> c) {
68.388 + return addAll(size, c);
68.389 + }
68.390 +
68.391 + /**
68.392 + * Inserts all of the elements in the specified collection into this
68.393 + * list, starting at the specified position. Shifts the element
68.394 + * currently at that position (if any) and any subsequent elements to
68.395 + * the right (increases their indices). The new elements will appear
68.396 + * in the list in the order that they are returned by the
68.397 + * specified collection's iterator.
68.398 + *
68.399 + * @param index index at which to insert the first element
68.400 + * from the specified collection
68.401 + * @param c collection containing elements to be added to this list
68.402 + * @return {@code true} if this list changed as a result of the call
68.403 + * @throws IndexOutOfBoundsException {@inheritDoc}
68.404 + * @throws NullPointerException if the specified collection is null
68.405 + */
68.406 + public boolean addAll(int index, Collection<? extends E> c) {
68.407 + checkPositionIndex(index);
68.408 +
68.409 + Object[] a = c.toArray();
68.410 + int numNew = a.length;
68.411 + if (numNew == 0)
68.412 + return false;
68.413 +
68.414 + Node<E> pred, succ;
68.415 + if (index == size) {
68.416 + succ = null;
68.417 + pred = last;
68.418 + } else {
68.419 + succ = node(index);
68.420 + pred = succ.prev;
68.421 + }
68.422 +
68.423 + for (Object o : a) {
68.424 + @SuppressWarnings("unchecked") E e = (E) o;
68.425 + Node<E> newNode = new Node<>(pred, e, null);
68.426 + if (pred == null)
68.427 + first = newNode;
68.428 + else
68.429 + pred.next = newNode;
68.430 + pred = newNode;
68.431 + }
68.432 +
68.433 + if (succ == null) {
68.434 + last = pred;
68.435 + } else {
68.436 + pred.next = succ;
68.437 + succ.prev = pred;
68.438 + }
68.439 +
68.440 + size += numNew;
68.441 + modCount++;
68.442 + return true;
68.443 + }
68.444 +
68.445 + /**
68.446 + * Removes all of the elements from this list.
68.447 + * The list will be empty after this call returns.
68.448 + */
68.449 + public void clear() {
68.450 + // Clearing all of the links between nodes is "unnecessary", but:
68.451 + // - helps a generational GC if the discarded nodes inhabit
68.452 + // more than one generation
68.453 + // - is sure to free memory even if there is a reachable Iterator
68.454 + for (Node<E> x = first; x != null; ) {
68.455 + Node<E> next = x.next;
68.456 + x.item = null;
68.457 + x.next = null;
68.458 + x.prev = null;
68.459 + x = next;
68.460 + }
68.461 + first = last = null;
68.462 + size = 0;
68.463 + modCount++;
68.464 + }
68.465 +
68.466 +
68.467 + // Positional Access Operations
68.468 +
68.469 + /**
68.470 + * Returns the element at the specified position in this list.
68.471 + *
68.472 + * @param index index of the element to return
68.473 + * @return the element at the specified position in this list
68.474 + * @throws IndexOutOfBoundsException {@inheritDoc}
68.475 + */
68.476 + public E get(int index) {
68.477 + checkElementIndex(index);
68.478 + return node(index).item;
68.479 + }
68.480 +
68.481 + /**
68.482 + * Replaces the element at the specified position in this list with the
68.483 + * specified element.
68.484 + *
68.485 + * @param index index of the element to replace
68.486 + * @param element element to be stored at the specified position
68.487 + * @return the element previously at the specified position
68.488 + * @throws IndexOutOfBoundsException {@inheritDoc}
68.489 + */
68.490 + public E set(int index, E element) {
68.491 + checkElementIndex(index);
68.492 + Node<E> x = node(index);
68.493 + E oldVal = x.item;
68.494 + x.item = element;
68.495 + return oldVal;
68.496 + }
68.497 +
68.498 + /**
68.499 + * Inserts the specified element at the specified position in this list.
68.500 + * Shifts the element currently at that position (if any) and any
68.501 + * subsequent elements to the right (adds one to their indices).
68.502 + *
68.503 + * @param index index at which the specified element is to be inserted
68.504 + * @param element element to be inserted
68.505 + * @throws IndexOutOfBoundsException {@inheritDoc}
68.506 + */
68.507 + public void add(int index, E element) {
68.508 + checkPositionIndex(index);
68.509 +
68.510 + if (index == size)
68.511 + linkLast(element);
68.512 + else
68.513 + linkBefore(element, node(index));
68.514 + }
68.515 +
68.516 + /**
68.517 + * Removes the element at the specified position in this list. Shifts any
68.518 + * subsequent elements to the left (subtracts one from their indices).
68.519 + * Returns the element that was removed from the list.
68.520 + *
68.521 + * @param index the index of the element to be removed
68.522 + * @return the element previously at the specified position
68.523 + * @throws IndexOutOfBoundsException {@inheritDoc}
68.524 + */
68.525 + public E remove(int index) {
68.526 + checkElementIndex(index);
68.527 + return unlink(node(index));
68.528 + }
68.529 +
68.530 + /**
68.531 + * Tells if the argument is the index of an existing element.
68.532 + */
68.533 + private boolean isElementIndex(int index) {
68.534 + return index >= 0 && index < size;
68.535 + }
68.536 +
68.537 + /**
68.538 + * Tells if the argument is the index of a valid position for an
68.539 + * iterator or an add operation.
68.540 + */
68.541 + private boolean isPositionIndex(int index) {
68.542 + return index >= 0 && index <= size;
68.543 + }
68.544 +
68.545 + /**
68.546 + * Constructs an IndexOutOfBoundsException detail message.
68.547 + * Of the many possible refactorings of the error handling code,
68.548 + * this "outlining" performs best with both server and client VMs.
68.549 + */
68.550 + private String outOfBoundsMsg(int index) {
68.551 + return "Index: "+index+", Size: "+size;
68.552 + }
68.553 +
68.554 + private void checkElementIndex(int index) {
68.555 + if (!isElementIndex(index))
68.556 + throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
68.557 + }
68.558 +
68.559 + private void checkPositionIndex(int index) {
68.560 + if (!isPositionIndex(index))
68.561 + throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
68.562 + }
68.563 +
68.564 + /**
68.565 + * Returns the (non-null) Node at the specified element index.
68.566 + */
68.567 + Node<E> node(int index) {
68.568 + // assert isElementIndex(index);
68.569 +
68.570 + if (index < (size >> 1)) {
68.571 + Node<E> x = first;
68.572 + for (int i = 0; i < index; i++)
68.573 + x = x.next;
68.574 + return x;
68.575 + } else {
68.576 + Node<E> x = last;
68.577 + for (int i = size - 1; i > index; i--)
68.578 + x = x.prev;
68.579 + return x;
68.580 + }
68.581 + }
68.582 +
68.583 + // Search Operations
68.584 +
68.585 + /**
68.586 + * Returns the index of the first occurrence of the specified element
68.587 + * in this list, or -1 if this list does not contain the element.
68.588 + * More formally, returns the lowest index {@code i} such that
68.589 + * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>,
68.590 + * or -1 if there is no such index.
68.591 + *
68.592 + * @param o element to search for
68.593 + * @return the index of the first occurrence of the specified element in
68.594 + * this list, or -1 if this list does not contain the element
68.595 + */
68.596 + public int indexOf(Object o) {
68.597 + int index = 0;
68.598 + if (o == null) {
68.599 + for (Node<E> x = first; x != null; x = x.next) {
68.600 + if (x.item == null)
68.601 + return index;
68.602 + index++;
68.603 + }
68.604 + } else {
68.605 + for (Node<E> x = first; x != null; x = x.next) {
68.606 + if (o.equals(x.item))
68.607 + return index;
68.608 + index++;
68.609 + }
68.610 + }
68.611 + return -1;
68.612 + }
68.613 +
68.614 + /**
68.615 + * Returns the index of the last occurrence of the specified element
68.616 + * in this list, or -1 if this list does not contain the element.
68.617 + * More formally, returns the highest index {@code i} such that
68.618 + * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>,
68.619 + * or -1 if there is no such index.
68.620 + *
68.621 + * @param o element to search for
68.622 + * @return the index of the last occurrence of the specified element in
68.623 + * this list, or -1 if this list does not contain the element
68.624 + */
68.625 + public int lastIndexOf(Object o) {
68.626 + int index = size;
68.627 + if (o == null) {
68.628 + for (Node<E> x = last; x != null; x = x.prev) {
68.629 + index--;
68.630 + if (x.item == null)
68.631 + return index;
68.632 + }
68.633 + } else {
68.634 + for (Node<E> x = last; x != null; x = x.prev) {
68.635 + index--;
68.636 + if (o.equals(x.item))
68.637 + return index;
68.638 + }
68.639 + }
68.640 + return -1;
68.641 + }
68.642 +
68.643 + // Queue operations.
68.644 +
68.645 + /**
68.646 + * Retrieves, but does not remove, the head (first element) of this list.
68.647 + *
68.648 + * @return the head of this list, or {@code null} if this list is empty
68.649 + * @since 1.5
68.650 + */
68.651 + public E peek() {
68.652 + final Node<E> f = first;
68.653 + return (f == null) ? null : f.item;
68.654 + }
68.655 +
68.656 + /**
68.657 + * Retrieves, but does not remove, the head (first element) of this list.
68.658 + *
68.659 + * @return the head of this list
68.660 + * @throws NoSuchElementException if this list is empty
68.661 + * @since 1.5
68.662 + */
68.663 + public E element() {
68.664 + return getFirst();
68.665 + }
68.666 +
68.667 + /**
68.668 + * Retrieves and removes the head (first element) of this list.
68.669 + *
68.670 + * @return the head of this list, or {@code null} if this list is empty
68.671 + * @since 1.5
68.672 + */
68.673 + public E poll() {
68.674 + final Node<E> f = first;
68.675 + return (f == null) ? null : unlinkFirst(f);
68.676 + }
68.677 +
68.678 + /**
68.679 + * Retrieves and removes the head (first element) of this list.
68.680 + *
68.681 + * @return the head of this list
68.682 + * @throws NoSuchElementException if this list is empty
68.683 + * @since 1.5
68.684 + */
68.685 + public E remove() {
68.686 + return removeFirst();
68.687 + }
68.688 +
68.689 + /**
68.690 + * Adds the specified element as the tail (last element) of this list.
68.691 + *
68.692 + * @param e the element to add
68.693 + * @return {@code true} (as specified by {@link Queue#offer})
68.694 + * @since 1.5
68.695 + */
68.696 + public boolean offer(E e) {
68.697 + return add(e);
68.698 + }
68.699 +
68.700 + // Deque operations
68.701 + /**
68.702 + * Inserts the specified element at the front of this list.
68.703 + *
68.704 + * @param e the element to insert
68.705 + * @return {@code true} (as specified by {@link Deque#offerFirst})
68.706 + * @since 1.6
68.707 + */
68.708 + public boolean offerFirst(E e) {
68.709 + addFirst(e);
68.710 + return true;
68.711 + }
68.712 +
68.713 + /**
68.714 + * Inserts the specified element at the end of this list.
68.715 + *
68.716 + * @param e the element to insert
68.717 + * @return {@code true} (as specified by {@link Deque#offerLast})
68.718 + * @since 1.6
68.719 + */
68.720 + public boolean offerLast(E e) {
68.721 + addLast(e);
68.722 + return true;
68.723 + }
68.724 +
68.725 + /**
68.726 + * Retrieves, but does not remove, the first element of this list,
68.727 + * or returns {@code null} if this list is empty.
68.728 + *
68.729 + * @return the first element of this list, or {@code null}
68.730 + * if this list is empty
68.731 + * @since 1.6
68.732 + */
68.733 + public E peekFirst() {
68.734 + final Node<E> f = first;
68.735 + return (f == null) ? null : f.item;
68.736 + }
68.737 +
68.738 + /**
68.739 + * Retrieves, but does not remove, the last element of this list,
68.740 + * or returns {@code null} if this list is empty.
68.741 + *
68.742 + * @return the last element of this list, or {@code null}
68.743 + * if this list is empty
68.744 + * @since 1.6
68.745 + */
68.746 + public E peekLast() {
68.747 + final Node<E> l = last;
68.748 + return (l == null) ? null : l.item;
68.749 + }
68.750 +
68.751 + /**
68.752 + * Retrieves and removes the first element of this list,
68.753 + * or returns {@code null} if this list is empty.
68.754 + *
68.755 + * @return the first element of this list, or {@code null} if
68.756 + * this list is empty
68.757 + * @since 1.6
68.758 + */
68.759 + public E pollFirst() {
68.760 + final Node<E> f = first;
68.761 + return (f == null) ? null : unlinkFirst(f);
68.762 + }
68.763 +
68.764 + /**
68.765 + * Retrieves and removes the last element of this list,
68.766 + * or returns {@code null} if this list is empty.
68.767 + *
68.768 + * @return the last element of this list, or {@code null} if
68.769 + * this list is empty
68.770 + * @since 1.6
68.771 + */
68.772 + public E pollLast() {
68.773 + final Node<E> l = last;
68.774 + return (l == null) ? null : unlinkLast(l);
68.775 + }
68.776 +
68.777 + /**
68.778 + * Pushes an element onto the stack represented by this list. In other
68.779 + * words, inserts the element at the front of this list.
68.780 + *
68.781 + * <p>This method is equivalent to {@link #addFirst}.
68.782 + *
68.783 + * @param e the element to push
68.784 + * @since 1.6
68.785 + */
68.786 + public void push(E e) {
68.787 + addFirst(e);
68.788 + }
68.789 +
68.790 + /**
68.791 + * Pops an element from the stack represented by this list. In other
68.792 + * words, removes and returns the first element of this list.
68.793 + *
68.794 + * <p>This method is equivalent to {@link #removeFirst()}.
68.795 + *
68.796 + * @return the element at the front of this list (which is the top
68.797 + * of the stack represented by this list)
68.798 + * @throws NoSuchElementException if this list is empty
68.799 + * @since 1.6
68.800 + */
68.801 + public E pop() {
68.802 + return removeFirst();
68.803 + }
68.804 +
68.805 + /**
68.806 + * Removes the first occurrence of the specified element in this
68.807 + * list (when traversing the list from head to tail). If the list
68.808 + * does not contain the element, it is unchanged.
68.809 + *
68.810 + * @param o element to be removed from this list, if present
68.811 + * @return {@code true} if the list contained the specified element
68.812 + * @since 1.6
68.813 + */
68.814 + public boolean removeFirstOccurrence(Object o) {
68.815 + return remove(o);
68.816 + }
68.817 +
68.818 + /**
68.819 + * Removes the last occurrence of the specified element in this
68.820 + * list (when traversing the list from head to tail). If the list
68.821 + * does not contain the element, it is unchanged.
68.822 + *
68.823 + * @param o element to be removed from this list, if present
68.824 + * @return {@code true} if the list contained the specified element
68.825 + * @since 1.6
68.826 + */
68.827 + public boolean removeLastOccurrence(Object o) {
68.828 + if (o == null) {
68.829 + for (Node<E> x = last; x != null; x = x.prev) {
68.830 + if (x.item == null) {
68.831 + unlink(x);
68.832 + return true;
68.833 + }
68.834 + }
68.835 + } else {
68.836 + for (Node<E> x = last; x != null; x = x.prev) {
68.837 + if (o.equals(x.item)) {
68.838 + unlink(x);
68.839 + return true;
68.840 + }
68.841 + }
68.842 + }
68.843 + return false;
68.844 + }
68.845 +
68.846 + /**
68.847 + * Returns a list-iterator of the elements in this list (in proper
68.848 + * sequence), starting at the specified position in the list.
68.849 + * Obeys the general contract of {@code List.listIterator(int)}.<p>
68.850 + *
68.851 + * The list-iterator is <i>fail-fast</i>: if the list is structurally
68.852 + * modified at any time after the Iterator is created, in any way except
68.853 + * through the list-iterator's own {@code remove} or {@code add}
68.854 + * methods, the list-iterator will throw a
68.855 + * {@code ConcurrentModificationException}. Thus, in the face of
68.856 + * concurrent modification, the iterator fails quickly and cleanly, rather
68.857 + * than risking arbitrary, non-deterministic behavior at an undetermined
68.858 + * time in the future.
68.859 + *
68.860 + * @param index index of the first element to be returned from the
68.861 + * list-iterator (by a call to {@code next})
68.862 + * @return a ListIterator of the elements in this list (in proper
68.863 + * sequence), starting at the specified position in the list
68.864 + * @throws IndexOutOfBoundsException {@inheritDoc}
68.865 + * @see List#listIterator(int)
68.866 + */
68.867 + public ListIterator<E> listIterator(int index) {
68.868 + checkPositionIndex(index);
68.869 + return new ListItr(index);
68.870 + }
68.871 +
68.872 + private class ListItr implements ListIterator<E> {
68.873 + private Node<E> lastReturned = null;
68.874 + private Node<E> next;
68.875 + private int nextIndex;
68.876 + private int expectedModCount = modCount;
68.877 +
68.878 + ListItr(int index) {
68.879 + // assert isPositionIndex(index);
68.880 + next = (index == size) ? null : node(index);
68.881 + nextIndex = index;
68.882 + }
68.883 +
68.884 + public boolean hasNext() {
68.885 + return nextIndex < size;
68.886 + }
68.887 +
68.888 + public E next() {
68.889 + checkForComodification();
68.890 + if (!hasNext())
68.891 + throw new NoSuchElementException();
68.892 +
68.893 + lastReturned = next;
68.894 + next = next.next;
68.895 + nextIndex++;
68.896 + return lastReturned.item;
68.897 + }
68.898 +
68.899 + public boolean hasPrevious() {
68.900 + return nextIndex > 0;
68.901 + }
68.902 +
68.903 + public E previous() {
68.904 + checkForComodification();
68.905 + if (!hasPrevious())
68.906 + throw new NoSuchElementException();
68.907 +
68.908 + lastReturned = next = (next == null) ? last : next.prev;
68.909 + nextIndex--;
68.910 + return lastReturned.item;
68.911 + }
68.912 +
68.913 + public int nextIndex() {
68.914 + return nextIndex;
68.915 + }
68.916 +
68.917 + public int previousIndex() {
68.918 + return nextIndex - 1;
68.919 + }
68.920 +
68.921 + public void remove() {
68.922 + checkForComodification();
68.923 + if (lastReturned == null)
68.924 + throw new IllegalStateException();
68.925 +
68.926 + Node<E> lastNext = lastReturned.next;
68.927 + unlink(lastReturned);
68.928 + if (next == lastReturned)
68.929 + next = lastNext;
68.930 + else
68.931 + nextIndex--;
68.932 + lastReturned = null;
68.933 + expectedModCount++;
68.934 + }
68.935 +
68.936 + public void set(E e) {
68.937 + if (lastReturned == null)
68.938 + throw new IllegalStateException();
68.939 + checkForComodification();
68.940 + lastReturned.item = e;
68.941 + }
68.942 +
68.943 + public void add(E e) {
68.944 + checkForComodification();
68.945 + lastReturned = null;
68.946 + if (next == null)
68.947 + linkLast(e);
68.948 + else
68.949 + linkBefore(e, next);
68.950 + nextIndex++;
68.951 + expectedModCount++;
68.952 + }
68.953 +
68.954 + final void checkForComodification() {
68.955 + if (modCount != expectedModCount)
68.956 + throw new ConcurrentModificationException();
68.957 + }
68.958 + }
68.959 +
68.960 + private static class Node<E> {
68.961 + E item;
68.962 + Node<E> next;
68.963 + Node<E> prev;
68.964 +
68.965 + Node(Node<E> prev, E element, Node<E> next) {
68.966 + this.item = element;
68.967 + this.next = next;
68.968 + this.prev = prev;
68.969 + }
68.970 + }
68.971 +
68.972 + /**
68.973 + * @since 1.6
68.974 + */
68.975 + public Iterator<E> descendingIterator() {
68.976 + return new DescendingIterator();
68.977 + }
68.978 +
68.979 + /**
68.980 + * Adapter to provide descending iterators via ListItr.previous
68.981 + */
68.982 + private class DescendingIterator implements Iterator<E> {
68.983 + private final ListItr itr = new ListItr(size());
68.984 + public boolean hasNext() {
68.985 + return itr.hasPrevious();
68.986 + }
68.987 + public E next() {
68.988 + return itr.previous();
68.989 + }
68.990 + public void remove() {
68.991 + itr.remove();
68.992 + }
68.993 + }
68.994 +
68.995 + @SuppressWarnings("unchecked")
68.996 + private LinkedList<E> superClone() {
68.997 + try {
68.998 + return (LinkedList<E>) super.clone();
68.999 + } catch (CloneNotSupportedException e) {
68.1000 + throw new InternalError();
68.1001 + }
68.1002 + }
68.1003 +
68.1004 + /**
68.1005 + * Returns a shallow copy of this {@code LinkedList}. (The elements
68.1006 + * themselves are not cloned.)
68.1007 + *
68.1008 + * @return a shallow copy of this {@code LinkedList} instance
68.1009 + */
68.1010 + public Object clone() {
68.1011 + LinkedList<E> clone = superClone();
68.1012 +
68.1013 + // Put clone into "virgin" state
68.1014 + clone.first = clone.last = null;
68.1015 + clone.size = 0;
68.1016 + clone.modCount = 0;
68.1017 +
68.1018 + // Initialize clone with our elements
68.1019 + for (Node<E> x = first; x != null; x = x.next)
68.1020 + clone.add(x.item);
68.1021 +
68.1022 + return clone;
68.1023 + }
68.1024 +
68.1025 + /**
68.1026 + * Returns an array containing all of the elements in this list
68.1027 + * in proper sequence (from first to last element).
68.1028 + *
68.1029 + * <p>The returned array will be "safe" in that no references to it are
68.1030 + * maintained by this list. (In other words, this method must allocate
68.1031 + * a new array). The caller is thus free to modify the returned array.
68.1032 + *
68.1033 + * <p>This method acts as bridge between array-based and collection-based
68.1034 + * APIs.
68.1035 + *
68.1036 + * @return an array containing all of the elements in this list
68.1037 + * in proper sequence
68.1038 + */
68.1039 + public Object[] toArray() {
68.1040 + Object[] result = new Object[size];
68.1041 + int i = 0;
68.1042 + for (Node<E> x = first; x != null; x = x.next)
68.1043 + result[i++] = x.item;
68.1044 + return result;
68.1045 + }
68.1046 +
68.1047 + /**
68.1048 + * Returns an array containing all of the elements in this list in
68.1049 + * proper sequence (from first to last element); the runtime type of
68.1050 + * the returned array is that of the specified array. If the list fits
68.1051 + * in the specified array, it is returned therein. Otherwise, a new
68.1052 + * array is allocated with the runtime type of the specified array and
68.1053 + * the size of this list.
68.1054 + *
68.1055 + * <p>If the list fits in the specified array with room to spare (i.e.,
68.1056 + * the array has more elements than the list), the element in the array
68.1057 + * immediately following the end of the list is set to {@code null}.
68.1058 + * (This is useful in determining the length of the list <i>only</i> if
68.1059 + * the caller knows that the list does not contain any null elements.)
68.1060 + *
68.1061 + * <p>Like the {@link #toArray()} method, this method acts as bridge between
68.1062 + * array-based and collection-based APIs. Further, this method allows
68.1063 + * precise control over the runtime type of the output array, and may,
68.1064 + * under certain circumstances, be used to save allocation costs.
68.1065 + *
68.1066 + * <p>Suppose {@code x} is a list known to contain only strings.
68.1067 + * The following code can be used to dump the list into a newly
68.1068 + * allocated array of {@code String}:
68.1069 + *
68.1070 + * <pre>
68.1071 + * String[] y = x.toArray(new String[0]);</pre>
68.1072 + *
68.1073 + * Note that {@code toArray(new Object[0])} is identical in function to
68.1074 + * {@code toArray()}.
68.1075 + *
68.1076 + * @param a the array into which the elements of the list are to
68.1077 + * be stored, if it is big enough; otherwise, a new array of the
68.1078 + * same runtime type is allocated for this purpose.
68.1079 + * @return an array containing the elements of the list
68.1080 + * @throws ArrayStoreException if the runtime type of the specified array
68.1081 + * is not a supertype of the runtime type of every element in
68.1082 + * this list
68.1083 + * @throws NullPointerException if the specified array is null
68.1084 + */
68.1085 + @SuppressWarnings("unchecked")
68.1086 + public <T> T[] toArray(T[] a) {
68.1087 + if (a.length < size)
68.1088 + a = (T[])java.lang.reflect.Array.newInstance(
68.1089 + a.getClass().getComponentType(), size);
68.1090 + int i = 0;
68.1091 + Object[] result = a;
68.1092 + for (Node<E> x = first; x != null; x = x.next)
68.1093 + result[i++] = x.item;
68.1094 +
68.1095 + if (a.length > size)
68.1096 + a[size] = null;
68.1097 +
68.1098 + return a;
68.1099 + }
68.1100 +
68.1101 + private static final long serialVersionUID = 876323262645176354L;
68.1102 +
68.1103 +}
69.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
69.2 +++ b/emul/compact/src/main/java/java/util/Objects.java Sun Feb 17 17:58:34 2013 +0100
69.3 @@ -0,0 +1,229 @@
69.4 +/*
69.5 + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
69.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
69.7 + *
69.8 + * This code is free software; you can redistribute it and/or modify it
69.9 + * under the terms of the GNU General Public License version 2 only, as
69.10 + * published by the Free Software Foundation. Oracle designates this
69.11 + * particular file as subject to the "Classpath" exception as provided
69.12 + * by Oracle in the LICENSE file that accompanied this code.
69.13 + *
69.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
69.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
69.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
69.17 + * version 2 for more details (a copy is included in the LICENSE file that
69.18 + * accompanied this code).
69.19 + *
69.20 + * You should have received a copy of the GNU General Public License version
69.21 + * 2 along with this work; if not, write to the Free Software Foundation,
69.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
69.23 + *
69.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
69.25 + * or visit www.oracle.com if you need additional information or have any
69.26 + * questions.
69.27 + */
69.28 +
69.29 +package java.util;
69.30 +
69.31 +/**
69.32 + * This class consists of {@code static} utility methods for operating
69.33 + * on objects. These utilities include {@code null}-safe or {@code
69.34 + * null}-tolerant methods for computing the hash code of an object,
69.35 + * returning a string for an object, and comparing two objects.
69.36 + *
69.37 + * @since 1.7
69.38 + */
69.39 +public final class Objects {
69.40 + private Objects() {
69.41 + throw new AssertionError("No java.util.Objects instances for you!");
69.42 + }
69.43 +
69.44 + /**
69.45 + * Returns {@code true} if the arguments are equal to each other
69.46 + * and {@code false} otherwise.
69.47 + * Consequently, if both arguments are {@code null}, {@code true}
69.48 + * is returned and if exactly one argument is {@code null}, {@code
69.49 + * false} is returned. Otherwise, equality is determined by using
69.50 + * the {@link Object#equals equals} method of the first
69.51 + * argument.
69.52 + *
69.53 + * @param a an object
69.54 + * @param b an object to be compared with {@code a} for equality
69.55 + * @return {@code true} if the arguments are equal to each other
69.56 + * and {@code false} otherwise
69.57 + * @see Object#equals(Object)
69.58 + */
69.59 + public static boolean equals(Object a, Object b) {
69.60 + return (a == b) || (a != null && a.equals(b));
69.61 + }
69.62 +
69.63 + /**
69.64 + * Returns {@code true} if the arguments are deeply equal to each other
69.65 + * and {@code false} otherwise.
69.66 + *
69.67 + * Two {@code null} values are deeply equal. If both arguments are
69.68 + * arrays, the algorithm in {@link Arrays#deepEquals(Object[],
69.69 + * Object[]) Arrays.deepEquals} is used to determine equality.
69.70 + * Otherwise, equality is determined by using the {@link
69.71 + * Object#equals equals} method of the first argument.
69.72 + *
69.73 + * @param a an object
69.74 + * @param b an object to be compared with {@code a} for deep equality
69.75 + * @return {@code true} if the arguments are deeply equal to each other
69.76 + * and {@code false} otherwise
69.77 + * @see Arrays#deepEquals(Object[], Object[])
69.78 + * @see Objects#equals(Object, Object)
69.79 + */
69.80 + public static boolean deepEquals(Object a, Object b) {
69.81 + if (a == b)
69.82 + return true;
69.83 + else if (a == null || b == null)
69.84 + return false;
69.85 + else
69.86 + return Arrays.deepEquals0(a, b);
69.87 + }
69.88 +
69.89 + /**
69.90 + * Returns the hash code of a non-{@code null} argument and 0 for
69.91 + * a {@code null} argument.
69.92 + *
69.93 + * @param o an object
69.94 + * @return the hash code of a non-{@code null} argument and 0 for
69.95 + * a {@code null} argument
69.96 + * @see Object#hashCode
69.97 + */
69.98 + public static int hashCode(Object o) {
69.99 + return o != null ? o.hashCode() : 0;
69.100 + }
69.101 +
69.102 + /**
69.103 + * Generates a hash code for a sequence of input values. The hash
69.104 + * code is generated as if all the input values were placed into an
69.105 + * array, and that array were hashed by calling {@link
69.106 + * Arrays#hashCode(Object[])}.
69.107 + *
69.108 + * <p>This method is useful for implementing {@link
69.109 + * Object#hashCode()} on objects containing multiple fields. For
69.110 + * example, if an object that has three fields, {@code x}, {@code
69.111 + * y}, and {@code z}, one could write:
69.112 + *
69.113 + * <blockquote><pre>
69.114 + * @Override public int hashCode() {
69.115 + * return Objects.hash(x, y, z);
69.116 + * }
69.117 + * </pre></blockquote>
69.118 + *
69.119 + * <b>Warning: When a single object reference is supplied, the returned
69.120 + * value does not equal the hash code of that object reference.</b> This
69.121 + * value can be computed by calling {@link #hashCode(Object)}.
69.122 + *
69.123 + * @param values the values to be hashed
69.124 + * @return a hash value of the sequence of input values
69.125 + * @see Arrays#hashCode(Object[])
69.126 + * @see List#hashCode
69.127 + */
69.128 + public static int hash(Object... values) {
69.129 + return Arrays.hashCode(values);
69.130 + }
69.131 +
69.132 + /**
69.133 + * Returns the result of calling {@code toString} for a non-{@code
69.134 + * null} argument and {@code "null"} for a {@code null} argument.
69.135 + *
69.136 + * @param o an object
69.137 + * @return the result of calling {@code toString} for a non-{@code
69.138 + * null} argument and {@code "null"} for a {@code null} argument
69.139 + * @see Object#toString
69.140 + * @see String#valueOf(Object)
69.141 + */
69.142 + public static String toString(Object o) {
69.143 + return String.valueOf(o);
69.144 + }
69.145 +
69.146 + /**
69.147 + * Returns the result of calling {@code toString} on the first
69.148 + * argument if the first argument is not {@code null} and returns
69.149 + * the second argument otherwise.
69.150 + *
69.151 + * @param o an object
69.152 + * @param nullDefault string to return if the first argument is
69.153 + * {@code null}
69.154 + * @return the result of calling {@code toString} on the first
69.155 + * argument if it is not {@code null} and the second argument
69.156 + * otherwise.
69.157 + * @see Objects#toString(Object)
69.158 + */
69.159 + public static String toString(Object o, String nullDefault) {
69.160 + return (o != null) ? o.toString() : nullDefault;
69.161 + }
69.162 +
69.163 + /**
69.164 + * Returns 0 if the arguments are identical and {@code
69.165 + * c.compare(a, b)} otherwise.
69.166 + * Consequently, if both arguments are {@code null} 0
69.167 + * is returned.
69.168 + *
69.169 + * <p>Note that if one of the arguments is {@code null}, a {@code
69.170 + * NullPointerException} may or may not be thrown depending on
69.171 + * what ordering policy, if any, the {@link Comparator Comparator}
69.172 + * chooses to have for {@code null} values.
69.173 + *
69.174 + * @param <T> the type of the objects being compared
69.175 + * @param a an object
69.176 + * @param b an object to be compared with {@code a}
69.177 + * @param c the {@code Comparator} to compare the first two arguments
69.178 + * @return 0 if the arguments are identical and {@code
69.179 + * c.compare(a, b)} otherwise.
69.180 + * @see Comparable
69.181 + * @see Comparator
69.182 + */
69.183 + public static <T> int compare(T a, T b, Comparator<? super T> c) {
69.184 + return (a == b) ? 0 : c.compare(a, b);
69.185 + }
69.186 +
69.187 + /**
69.188 + * Checks that the specified object reference is not {@code null}. This
69.189 + * method is designed primarily for doing parameter validation in methods
69.190 + * and constructors, as demonstrated below:
69.191 + * <blockquote><pre>
69.192 + * public Foo(Bar bar) {
69.193 + * this.bar = Objects.requireNonNull(bar);
69.194 + * }
69.195 + * </pre></blockquote>
69.196 + *
69.197 + * @param obj the object reference to check for nullity
69.198 + * @param <T> the type of the reference
69.199 + * @return {@code obj} if not {@code null}
69.200 + * @throws NullPointerException if {@code obj} is {@code null}
69.201 + */
69.202 + public static <T> T requireNonNull(T obj) {
69.203 + if (obj == null)
69.204 + throw new NullPointerException();
69.205 + return obj;
69.206 + }
69.207 +
69.208 + /**
69.209 + * Checks that the specified object reference is not {@code null} and
69.210 + * throws a customized {@link NullPointerException} if it is. This method
69.211 + * is designed primarily for doing parameter validation in methods and
69.212 + * constructors with multiple parameters, as demonstrated below:
69.213 + * <blockquote><pre>
69.214 + * public Foo(Bar bar, Baz baz) {
69.215 + * this.bar = Objects.requireNonNull(bar, "bar must not be null");
69.216 + * this.baz = Objects.requireNonNull(baz, "baz must not be null");
69.217 + * }
69.218 + * </pre></blockquote>
69.219 + *
69.220 + * @param obj the object reference to check for nullity
69.221 + * @param message detail message to be used in the event that a {@code
69.222 + * NullPointerException} is thrown
69.223 + * @param <T> the type of the reference
69.224 + * @return {@code obj} if not {@code null}
69.225 + * @throws NullPointerException if {@code obj} is {@code null}
69.226 + */
69.227 + public static <T> T requireNonNull(T obj, String message) {
69.228 + if (obj == null)
69.229 + throw new NullPointerException(message);
69.230 + return obj;
69.231 + }
69.232 +}
70.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
70.2 +++ b/emul/compact/src/main/java/java/util/PriorityQueue.java Sun Feb 17 17:58:34 2013 +0100
70.3 @@ -0,0 +1,731 @@
70.4 +/*
70.5 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
70.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
70.7 + *
70.8 + * This code is free software; you can redistribute it and/or modify it
70.9 + * under the terms of the GNU General Public License version 2 only, as
70.10 + * published by the Free Software Foundation. Oracle designates this
70.11 + * particular file as subject to the "Classpath" exception as provided
70.12 + * by Oracle in the LICENSE file that accompanied this code.
70.13 + *
70.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
70.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
70.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
70.17 + * version 2 for more details (a copy is included in the LICENSE file that
70.18 + * accompanied this code).
70.19 + *
70.20 + * You should have received a copy of the GNU General Public License version
70.21 + * 2 along with this work; if not, write to the Free Software Foundation,
70.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
70.23 + *
70.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
70.25 + * or visit www.oracle.com if you need additional information or have any
70.26 + * questions.
70.27 + */
70.28 +
70.29 +package java.util;
70.30 +
70.31 +
70.32 +/**
70.33 + * An unbounded priority {@linkplain Queue queue} based on a priority heap.
70.34 + * The elements of the priority queue are ordered according to their
70.35 + * {@linkplain Comparable natural ordering}, or by a {@link Comparator}
70.36 + * provided at queue construction time, depending on which constructor is
70.37 + * used. A priority queue does not permit {@code null} elements.
70.38 + * A priority queue relying on natural ordering also does not permit
70.39 + * insertion of non-comparable objects (doing so may result in
70.40 + * {@code ClassCastException}).
70.41 + *
70.42 + * <p>The <em>head</em> of this queue is the <em>least</em> element
70.43 + * with respect to the specified ordering. If multiple elements are
70.44 + * tied for least value, the head is one of those elements -- ties are
70.45 + * broken arbitrarily. The queue retrieval operations {@code poll},
70.46 + * {@code remove}, {@code peek}, and {@code element} access the
70.47 + * element at the head of the queue.
70.48 + *
70.49 + * <p>A priority queue is unbounded, but has an internal
70.50 + * <i>capacity</i> governing the size of an array used to store the
70.51 + * elements on the queue. It is always at least as large as the queue
70.52 + * size. As elements are added to a priority queue, its capacity
70.53 + * grows automatically. The details of the growth policy are not
70.54 + * specified.
70.55 + *
70.56 + * <p>This class and its iterator implement all of the
70.57 + * <em>optional</em> methods of the {@link Collection} and {@link
70.58 + * Iterator} interfaces. The Iterator provided in method {@link
70.59 + * #iterator()} is <em>not</em> guaranteed to traverse the elements of
70.60 + * the priority queue in any particular order. If you need ordered
70.61 + * traversal, consider using {@code Arrays.sort(pq.toArray())}.
70.62 + *
70.63 + * <p> <strong>Note that this implementation is not synchronized.</strong>
70.64 + * Multiple threads should not access a {@code PriorityQueue}
70.65 + * instance concurrently if any of the threads modifies the queue.
70.66 + * Instead, use the thread-safe {@link
70.67 + * java.util.concurrent.PriorityBlockingQueue} class.
70.68 + *
70.69 + * <p>Implementation note: this implementation provides
70.70 + * O(log(n)) time for the enqueing and dequeing methods
70.71 + * ({@code offer}, {@code poll}, {@code remove()} and {@code add});
70.72 + * linear time for the {@code remove(Object)} and {@code contains(Object)}
70.73 + * methods; and constant time for the retrieval methods
70.74 + * ({@code peek}, {@code element}, and {@code size}).
70.75 + *
70.76 + * <p>This class is a member of the
70.77 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
70.78 + * Java Collections Framework</a>.
70.79 + *
70.80 + * @since 1.5
70.81 + * @author Josh Bloch, Doug Lea
70.82 + * @param <E> the type of elements held in this collection
70.83 + */
70.84 +public class PriorityQueue<E> extends AbstractQueue<E>
70.85 + implements java.io.Serializable {
70.86 +
70.87 + private static final long serialVersionUID = -7720805057305804111L;
70.88 +
70.89 + private static final int DEFAULT_INITIAL_CAPACITY = 11;
70.90 +
70.91 + /**
70.92 + * Priority queue represented as a balanced binary heap: the two
70.93 + * children of queue[n] are queue[2*n+1] and queue[2*(n+1)]. The
70.94 + * priority queue is ordered by comparator, or by the elements'
70.95 + * natural ordering, if comparator is null: For each node n in the
70.96 + * heap and each descendant d of n, n <= d. The element with the
70.97 + * lowest value is in queue[0], assuming the queue is nonempty.
70.98 + */
70.99 + private transient Object[] queue;
70.100 +
70.101 + /**
70.102 + * The number of elements in the priority queue.
70.103 + */
70.104 + private int size = 0;
70.105 +
70.106 + /**
70.107 + * The comparator, or null if priority queue uses elements'
70.108 + * natural ordering.
70.109 + */
70.110 + private final Comparator<? super E> comparator;
70.111 +
70.112 + /**
70.113 + * The number of times this priority queue has been
70.114 + * <i>structurally modified</i>. See AbstractList for gory details.
70.115 + */
70.116 + private transient int modCount = 0;
70.117 +
70.118 + /**
70.119 + * Creates a {@code PriorityQueue} with the default initial
70.120 + * capacity (11) that orders its elements according to their
70.121 + * {@linkplain Comparable natural ordering}.
70.122 + */
70.123 + public PriorityQueue() {
70.124 + this(DEFAULT_INITIAL_CAPACITY, null);
70.125 + }
70.126 +
70.127 + /**
70.128 + * Creates a {@code PriorityQueue} with the specified initial
70.129 + * capacity that orders its elements according to their
70.130 + * {@linkplain Comparable natural ordering}.
70.131 + *
70.132 + * @param initialCapacity the initial capacity for this priority queue
70.133 + * @throws IllegalArgumentException if {@code initialCapacity} is less
70.134 + * than 1
70.135 + */
70.136 + public PriorityQueue(int initialCapacity) {
70.137 + this(initialCapacity, null);
70.138 + }
70.139 +
70.140 + /**
70.141 + * Creates a {@code PriorityQueue} with the specified initial capacity
70.142 + * that orders its elements according to the specified comparator.
70.143 + *
70.144 + * @param initialCapacity the initial capacity for this priority queue
70.145 + * @param comparator the comparator that will be used to order this
70.146 + * priority queue. If {@code null}, the {@linkplain Comparable
70.147 + * natural ordering} of the elements will be used.
70.148 + * @throws IllegalArgumentException if {@code initialCapacity} is
70.149 + * less than 1
70.150 + */
70.151 + public PriorityQueue(int initialCapacity,
70.152 + Comparator<? super E> comparator) {
70.153 + // Note: This restriction of at least one is not actually needed,
70.154 + // but continues for 1.5 compatibility
70.155 + if (initialCapacity < 1)
70.156 + throw new IllegalArgumentException();
70.157 + this.queue = new Object[initialCapacity];
70.158 + this.comparator = comparator;
70.159 + }
70.160 +
70.161 + /**
70.162 + * Creates a {@code PriorityQueue} containing the elements in the
70.163 + * specified collection. If the specified collection is an instance of
70.164 + * a {@link SortedSet} or is another {@code PriorityQueue}, this
70.165 + * priority queue will be ordered according to the same ordering.
70.166 + * Otherwise, this priority queue will be ordered according to the
70.167 + * {@linkplain Comparable natural ordering} of its elements.
70.168 + *
70.169 + * @param c the collection whose elements are to be placed
70.170 + * into this priority queue
70.171 + * @throws ClassCastException if elements of the specified collection
70.172 + * cannot be compared to one another according to the priority
70.173 + * queue's ordering
70.174 + * @throws NullPointerException if the specified collection or any
70.175 + * of its elements are null
70.176 + */
70.177 + @SuppressWarnings("unchecked")
70.178 + public PriorityQueue(Collection<? extends E> c) {
70.179 + if (c instanceof SortedSet<?>) {
70.180 + SortedSet<? extends E> ss = (SortedSet<? extends E>) c;
70.181 + this.comparator = (Comparator<? super E>) ss.comparator();
70.182 + initElementsFromCollection(ss);
70.183 + }
70.184 + else if (c instanceof PriorityQueue<?>) {
70.185 + PriorityQueue<? extends E> pq = (PriorityQueue<? extends E>) c;
70.186 + this.comparator = (Comparator<? super E>) pq.comparator();
70.187 + initFromPriorityQueue(pq);
70.188 + }
70.189 + else {
70.190 + this.comparator = null;
70.191 + initFromCollection(c);
70.192 + }
70.193 + }
70.194 +
70.195 + /**
70.196 + * Creates a {@code PriorityQueue} containing the elements in the
70.197 + * specified priority queue. This priority queue will be
70.198 + * ordered according to the same ordering as the given priority
70.199 + * queue.
70.200 + *
70.201 + * @param c the priority queue whose elements are to be placed
70.202 + * into this priority queue
70.203 + * @throws ClassCastException if elements of {@code c} cannot be
70.204 + * compared to one another according to {@code c}'s
70.205 + * ordering
70.206 + * @throws NullPointerException if the specified priority queue or any
70.207 + * of its elements are null
70.208 + */
70.209 + @SuppressWarnings("unchecked")
70.210 + public PriorityQueue(PriorityQueue<? extends E> c) {
70.211 + this.comparator = (Comparator<? super E>) c.comparator();
70.212 + initFromPriorityQueue(c);
70.213 + }
70.214 +
70.215 + /**
70.216 + * Creates a {@code PriorityQueue} containing the elements in the
70.217 + * specified sorted set. This priority queue will be ordered
70.218 + * according to the same ordering as the given sorted set.
70.219 + *
70.220 + * @param c the sorted set whose elements are to be placed
70.221 + * into this priority queue
70.222 + * @throws ClassCastException if elements of the specified sorted
70.223 + * set cannot be compared to one another according to the
70.224 + * sorted set's ordering
70.225 + * @throws NullPointerException if the specified sorted set or any
70.226 + * of its elements are null
70.227 + */
70.228 + @SuppressWarnings("unchecked")
70.229 + public PriorityQueue(SortedSet<? extends E> c) {
70.230 + this.comparator = (Comparator<? super E>) c.comparator();
70.231 + initElementsFromCollection(c);
70.232 + }
70.233 +
70.234 + private void initFromPriorityQueue(PriorityQueue<? extends E> c) {
70.235 + if (c.getClass() == PriorityQueue.class) {
70.236 + this.queue = c.toArray();
70.237 + this.size = c.size();
70.238 + } else {
70.239 + initFromCollection(c);
70.240 + }
70.241 + }
70.242 +
70.243 + private void initElementsFromCollection(Collection<? extends E> c) {
70.244 + Object[] a = c.toArray();
70.245 + // If c.toArray incorrectly doesn't return Object[], copy it.
70.246 + if (a.getClass() != Object[].class)
70.247 + a = Arrays.copyOf(a, a.length, Object[].class);
70.248 + int len = a.length;
70.249 + if (len == 1 || this.comparator != null)
70.250 + for (int i = 0; i < len; i++)
70.251 + if (a[i] == null)
70.252 + throw new NullPointerException();
70.253 + this.queue = a;
70.254 + this.size = a.length;
70.255 + }
70.256 +
70.257 + /**
70.258 + * Initializes queue array with elements from the given Collection.
70.259 + *
70.260 + * @param c the collection
70.261 + */
70.262 + private void initFromCollection(Collection<? extends E> c) {
70.263 + initElementsFromCollection(c);
70.264 + heapify();
70.265 + }
70.266 +
70.267 + /**
70.268 + * The maximum size of array to allocate.
70.269 + * Some VMs reserve some header words in an array.
70.270 + * Attempts to allocate larger arrays may result in
70.271 + * OutOfMemoryError: Requested array size exceeds VM limit
70.272 + */
70.273 + private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
70.274 +
70.275 + /**
70.276 + * Increases the capacity of the array.
70.277 + *
70.278 + * @param minCapacity the desired minimum capacity
70.279 + */
70.280 + private void grow(int minCapacity) {
70.281 + int oldCapacity = queue.length;
70.282 + // Double size if small; else grow by 50%
70.283 + int newCapacity = oldCapacity + ((oldCapacity < 64) ?
70.284 + (oldCapacity + 2) :
70.285 + (oldCapacity >> 1));
70.286 + // overflow-conscious code
70.287 + if (newCapacity - MAX_ARRAY_SIZE > 0)
70.288 + newCapacity = hugeCapacity(minCapacity);
70.289 + queue = Arrays.copyOf(queue, newCapacity);
70.290 + }
70.291 +
70.292 + private static int hugeCapacity(int minCapacity) {
70.293 + if (minCapacity < 0) // overflow
70.294 + throw new OutOfMemoryError();
70.295 + return (minCapacity > MAX_ARRAY_SIZE) ?
70.296 + Integer.MAX_VALUE :
70.297 + MAX_ARRAY_SIZE;
70.298 + }
70.299 +
70.300 + /**
70.301 + * Inserts the specified element into this priority queue.
70.302 + *
70.303 + * @return {@code true} (as specified by {@link Collection#add})
70.304 + * @throws ClassCastException if the specified element cannot be
70.305 + * compared with elements currently in this priority queue
70.306 + * according to the priority queue's ordering
70.307 + * @throws NullPointerException if the specified element is null
70.308 + */
70.309 + public boolean add(E e) {
70.310 + return offer(e);
70.311 + }
70.312 +
70.313 + /**
70.314 + * Inserts the specified element into this priority queue.
70.315 + *
70.316 + * @return {@code true} (as specified by {@link Queue#offer})
70.317 + * @throws ClassCastException if the specified element cannot be
70.318 + * compared with elements currently in this priority queue
70.319 + * according to the priority queue's ordering
70.320 + * @throws NullPointerException if the specified element is null
70.321 + */
70.322 + public boolean offer(E e) {
70.323 + if (e == null)
70.324 + throw new NullPointerException();
70.325 + modCount++;
70.326 + int i = size;
70.327 + if (i >= queue.length)
70.328 + grow(i + 1);
70.329 + size = i + 1;
70.330 + if (i == 0)
70.331 + queue[0] = e;
70.332 + else
70.333 + siftUp(i, e);
70.334 + return true;
70.335 + }
70.336 +
70.337 + public E peek() {
70.338 + if (size == 0)
70.339 + return null;
70.340 + return (E) queue[0];
70.341 + }
70.342 +
70.343 + private int indexOf(Object o) {
70.344 + if (o != null) {
70.345 + for (int i = 0; i < size; i++)
70.346 + if (o.equals(queue[i]))
70.347 + return i;
70.348 + }
70.349 + return -1;
70.350 + }
70.351 +
70.352 + /**
70.353 + * Removes a single instance of the specified element from this queue,
70.354 + * if it is present. More formally, removes an element {@code e} such
70.355 + * that {@code o.equals(e)}, if this queue contains one or more such
70.356 + * elements. Returns {@code true} if and only if this queue contained
70.357 + * the specified element (or equivalently, if this queue changed as a
70.358 + * result of the call).
70.359 + *
70.360 + * @param o element to be removed from this queue, if present
70.361 + * @return {@code true} if this queue changed as a result of the call
70.362 + */
70.363 + public boolean remove(Object o) {
70.364 + int i = indexOf(o);
70.365 + if (i == -1)
70.366 + return false;
70.367 + else {
70.368 + removeAt(i);
70.369 + return true;
70.370 + }
70.371 + }
70.372 +
70.373 + /**
70.374 + * Version of remove using reference equality, not equals.
70.375 + * Needed by iterator.remove.
70.376 + *
70.377 + * @param o element to be removed from this queue, if present
70.378 + * @return {@code true} if removed
70.379 + */
70.380 + boolean removeEq(Object o) {
70.381 + for (int i = 0; i < size; i++) {
70.382 + if (o == queue[i]) {
70.383 + removeAt(i);
70.384 + return true;
70.385 + }
70.386 + }
70.387 + return false;
70.388 + }
70.389 +
70.390 + /**
70.391 + * Returns {@code true} if this queue contains the specified element.
70.392 + * More formally, returns {@code true} if and only if this queue contains
70.393 + * at least one element {@code e} such that {@code o.equals(e)}.
70.394 + *
70.395 + * @param o object to be checked for containment in this queue
70.396 + * @return {@code true} if this queue contains the specified element
70.397 + */
70.398 + public boolean contains(Object o) {
70.399 + return indexOf(o) != -1;
70.400 + }
70.401 +
70.402 + /**
70.403 + * Returns an array containing all of the elements in this queue.
70.404 + * The elements are in no particular order.
70.405 + *
70.406 + * <p>The returned array will be "safe" in that no references to it are
70.407 + * maintained by this queue. (In other words, this method must allocate
70.408 + * a new array). The caller is thus free to modify the returned array.
70.409 + *
70.410 + * <p>This method acts as bridge between array-based and collection-based
70.411 + * APIs.
70.412 + *
70.413 + * @return an array containing all of the elements in this queue
70.414 + */
70.415 + public Object[] toArray() {
70.416 + return Arrays.copyOf(queue, size);
70.417 + }
70.418 +
70.419 + /**
70.420 + * Returns an array containing all of the elements in this queue; the
70.421 + * runtime type of the returned array is that of the specified array.
70.422 + * The returned array elements are in no particular order.
70.423 + * If the queue fits in the specified array, it is returned therein.
70.424 + * Otherwise, a new array is allocated with the runtime type of the
70.425 + * specified array and the size of this queue.
70.426 + *
70.427 + * <p>If the queue fits in the specified array with room to spare
70.428 + * (i.e., the array has more elements than the queue), the element in
70.429 + * the array immediately following the end of the collection is set to
70.430 + * {@code null}.
70.431 + *
70.432 + * <p>Like the {@link #toArray()} method, this method acts as bridge between
70.433 + * array-based and collection-based APIs. Further, this method allows
70.434 + * precise control over the runtime type of the output array, and may,
70.435 + * under certain circumstances, be used to save allocation costs.
70.436 + *
70.437 + * <p>Suppose <tt>x</tt> is a queue known to contain only strings.
70.438 + * The following code can be used to dump the queue into a newly
70.439 + * allocated array of <tt>String</tt>:
70.440 + *
70.441 + * <pre>
70.442 + * String[] y = x.toArray(new String[0]);</pre>
70.443 + *
70.444 + * Note that <tt>toArray(new Object[0])</tt> is identical in function to
70.445 + * <tt>toArray()</tt>.
70.446 + *
70.447 + * @param a the array into which the elements of the queue are to
70.448 + * be stored, if it is big enough; otherwise, a new array of the
70.449 + * same runtime type is allocated for this purpose.
70.450 + * @return an array containing all of the elements in this queue
70.451 + * @throws ArrayStoreException if the runtime type of the specified array
70.452 + * is not a supertype of the runtime type of every element in
70.453 + * this queue
70.454 + * @throws NullPointerException if the specified array is null
70.455 + */
70.456 + public <T> T[] toArray(T[] a) {
70.457 + if (a.length < size)
70.458 + // Make a new array of a's runtime type, but my contents:
70.459 + return (T[]) Arrays.copyOf(queue, size, a.getClass());
70.460 + System.arraycopy(queue, 0, a, 0, size);
70.461 + if (a.length > size)
70.462 + a[size] = null;
70.463 + return a;
70.464 + }
70.465 +
70.466 + /**
70.467 + * Returns an iterator over the elements in this queue. The iterator
70.468 + * does not return the elements in any particular order.
70.469 + *
70.470 + * @return an iterator over the elements in this queue
70.471 + */
70.472 + public Iterator<E> iterator() {
70.473 + return new Itr();
70.474 + }
70.475 +
70.476 + private final class Itr implements Iterator<E> {
70.477 + /**
70.478 + * Index (into queue array) of element to be returned by
70.479 + * subsequent call to next.
70.480 + */
70.481 + private int cursor = 0;
70.482 +
70.483 + /**
70.484 + * Index of element returned by most recent call to next,
70.485 + * unless that element came from the forgetMeNot list.
70.486 + * Set to -1 if element is deleted by a call to remove.
70.487 + */
70.488 + private int lastRet = -1;
70.489 +
70.490 + /**
70.491 + * A queue of elements that were moved from the unvisited portion of
70.492 + * the heap into the visited portion as a result of "unlucky" element
70.493 + * removals during the iteration. (Unlucky element removals are those
70.494 + * that require a siftup instead of a siftdown.) We must visit all of
70.495 + * the elements in this list to complete the iteration. We do this
70.496 + * after we've completed the "normal" iteration.
70.497 + *
70.498 + * We expect that most iterations, even those involving removals,
70.499 + * will not need to store elements in this field.
70.500 + */
70.501 + private ArrayDeque<E> forgetMeNot = null;
70.502 +
70.503 + /**
70.504 + * Element returned by the most recent call to next iff that
70.505 + * element was drawn from the forgetMeNot list.
70.506 + */
70.507 + private E lastRetElt = null;
70.508 +
70.509 + /**
70.510 + * The modCount value that the iterator believes that the backing
70.511 + * Queue should have. If this expectation is violated, the iterator
70.512 + * has detected concurrent modification.
70.513 + */
70.514 + private int expectedModCount = modCount;
70.515 +
70.516 + public boolean hasNext() {
70.517 + return cursor < size ||
70.518 + (forgetMeNot != null && !forgetMeNot.isEmpty());
70.519 + }
70.520 +
70.521 + public E next() {
70.522 + if (expectedModCount != modCount)
70.523 + throw new ConcurrentModificationException();
70.524 + if (cursor < size)
70.525 + return (E) queue[lastRet = cursor++];
70.526 + if (forgetMeNot != null) {
70.527 + lastRet = -1;
70.528 + lastRetElt = forgetMeNot.poll();
70.529 + if (lastRetElt != null)
70.530 + return lastRetElt;
70.531 + }
70.532 + throw new NoSuchElementException();
70.533 + }
70.534 +
70.535 + public void remove() {
70.536 + if (expectedModCount != modCount)
70.537 + throw new ConcurrentModificationException();
70.538 + if (lastRet != -1) {
70.539 + E moved = PriorityQueue.this.removeAt(lastRet);
70.540 + lastRet = -1;
70.541 + if (moved == null)
70.542 + cursor--;
70.543 + else {
70.544 + if (forgetMeNot == null)
70.545 + forgetMeNot = new ArrayDeque<>();
70.546 + forgetMeNot.add(moved);
70.547 + }
70.548 + } else if (lastRetElt != null) {
70.549 + PriorityQueue.this.removeEq(lastRetElt);
70.550 + lastRetElt = null;
70.551 + } else {
70.552 + throw new IllegalStateException();
70.553 + }
70.554 + expectedModCount = modCount;
70.555 + }
70.556 + }
70.557 +
70.558 + public int size() {
70.559 + return size;
70.560 + }
70.561 +
70.562 + /**
70.563 + * Removes all of the elements from this priority queue.
70.564 + * The queue will be empty after this call returns.
70.565 + */
70.566 + public void clear() {
70.567 + modCount++;
70.568 + for (int i = 0; i < size; i++)
70.569 + queue[i] = null;
70.570 + size = 0;
70.571 + }
70.572 +
70.573 + public E poll() {
70.574 + if (size == 0)
70.575 + return null;
70.576 + int s = --size;
70.577 + modCount++;
70.578 + E result = (E) queue[0];
70.579 + E x = (E) queue[s];
70.580 + queue[s] = null;
70.581 + if (s != 0)
70.582 + siftDown(0, x);
70.583 + return result;
70.584 + }
70.585 +
70.586 + /**
70.587 + * Removes the ith element from queue.
70.588 + *
70.589 + * Normally this method leaves the elements at up to i-1,
70.590 + * inclusive, untouched. Under these circumstances, it returns
70.591 + * null. Occasionally, in order to maintain the heap invariant,
70.592 + * it must swap a later element of the list with one earlier than
70.593 + * i. Under these circumstances, this method returns the element
70.594 + * that was previously at the end of the list and is now at some
70.595 + * position before i. This fact is used by iterator.remove so as to
70.596 + * avoid missing traversing elements.
70.597 + */
70.598 + private E removeAt(int i) {
70.599 + assert i >= 0 && i < size;
70.600 + modCount++;
70.601 + int s = --size;
70.602 + if (s == i) // removed last element
70.603 + queue[i] = null;
70.604 + else {
70.605 + E moved = (E) queue[s];
70.606 + queue[s] = null;
70.607 + siftDown(i, moved);
70.608 + if (queue[i] == moved) {
70.609 + siftUp(i, moved);
70.610 + if (queue[i] != moved)
70.611 + return moved;
70.612 + }
70.613 + }
70.614 + return null;
70.615 + }
70.616 +
70.617 + /**
70.618 + * Inserts item x at position k, maintaining heap invariant by
70.619 + * promoting x up the tree until it is greater than or equal to
70.620 + * its parent, or is the root.
70.621 + *
70.622 + * To simplify and speed up coercions and comparisons. the
70.623 + * Comparable and Comparator versions are separated into different
70.624 + * methods that are otherwise identical. (Similarly for siftDown.)
70.625 + *
70.626 + * @param k the position to fill
70.627 + * @param x the item to insert
70.628 + */
70.629 + private void siftUp(int k, E x) {
70.630 + if (comparator != null)
70.631 + siftUpUsingComparator(k, x);
70.632 + else
70.633 + siftUpComparable(k, x);
70.634 + }
70.635 +
70.636 + private void siftUpComparable(int k, E x) {
70.637 + Comparable<? super E> key = (Comparable<? super E>) x;
70.638 + while (k > 0) {
70.639 + int parent = (k - 1) >>> 1;
70.640 + Object e = queue[parent];
70.641 + if (key.compareTo((E) e) >= 0)
70.642 + break;
70.643 + queue[k] = e;
70.644 + k = parent;
70.645 + }
70.646 + queue[k] = key;
70.647 + }
70.648 +
70.649 + private void siftUpUsingComparator(int k, E x) {
70.650 + while (k > 0) {
70.651 + int parent = (k - 1) >>> 1;
70.652 + Object e = queue[parent];
70.653 + if (comparator.compare(x, (E) e) >= 0)
70.654 + break;
70.655 + queue[k] = e;
70.656 + k = parent;
70.657 + }
70.658 + queue[k] = x;
70.659 + }
70.660 +
70.661 + /**
70.662 + * Inserts item x at position k, maintaining heap invariant by
70.663 + * demoting x down the tree repeatedly until it is less than or
70.664 + * equal to its children or is a leaf.
70.665 + *
70.666 + * @param k the position to fill
70.667 + * @param x the item to insert
70.668 + */
70.669 + private void siftDown(int k, E x) {
70.670 + if (comparator != null)
70.671 + siftDownUsingComparator(k, x);
70.672 + else
70.673 + siftDownComparable(k, x);
70.674 + }
70.675 +
70.676 + private void siftDownComparable(int k, E x) {
70.677 + Comparable<? super E> key = (Comparable<? super E>)x;
70.678 + int half = size >>> 1; // loop while a non-leaf
70.679 + while (k < half) {
70.680 + int child = (k << 1) + 1; // assume left child is least
70.681 + Object c = queue[child];
70.682 + int right = child + 1;
70.683 + if (right < size &&
70.684 + ((Comparable<? super E>) c).compareTo((E) queue[right]) > 0)
70.685 + c = queue[child = right];
70.686 + if (key.compareTo((E) c) <= 0)
70.687 + break;
70.688 + queue[k] = c;
70.689 + k = child;
70.690 + }
70.691 + queue[k] = key;
70.692 + }
70.693 +
70.694 + private void siftDownUsingComparator(int k, E x) {
70.695 + int half = size >>> 1;
70.696 + while (k < half) {
70.697 + int child = (k << 1) + 1;
70.698 + Object c = queue[child];
70.699 + int right = child + 1;
70.700 + if (right < size &&
70.701 + comparator.compare((E) c, (E) queue[right]) > 0)
70.702 + c = queue[child = right];
70.703 + if (comparator.compare(x, (E) c) <= 0)
70.704 + break;
70.705 + queue[k] = c;
70.706 + k = child;
70.707 + }
70.708 + queue[k] = x;
70.709 + }
70.710 +
70.711 + /**
70.712 + * Establishes the heap invariant (described above) in the entire tree,
70.713 + * assuming nothing about the order of the elements prior to the call.
70.714 + */
70.715 + private void heapify() {
70.716 + for (int i = (size >>> 1) - 1; i >= 0; i--)
70.717 + siftDown(i, (E) queue[i]);
70.718 + }
70.719 +
70.720 + /**
70.721 + * Returns the comparator used to order the elements in this
70.722 + * queue, or {@code null} if this queue is sorted according to
70.723 + * the {@linkplain Comparable natural ordering} of its elements.
70.724 + *
70.725 + * @return the comparator used to order this queue, or
70.726 + * {@code null} if this queue is sorted according to the
70.727 + * natural ordering of its elements
70.728 + */
70.729 + public Comparator<? super E> comparator() {
70.730 + return comparator;
70.731 + }
70.732 +
70.733 +
70.734 +}
71.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
71.2 +++ b/emul/compact/src/main/java/java/util/Queue.java Sun Feb 17 17:58:34 2013 +0100
71.3 @@ -0,0 +1,218 @@
71.4 +/*
71.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
71.6 + *
71.7 + * This code is free software; you can redistribute it and/or modify it
71.8 + * under the terms of the GNU General Public License version 2 only, as
71.9 + * published by the Free Software Foundation. Oracle designates this
71.10 + * particular file as subject to the "Classpath" exception as provided
71.11 + * by Oracle in the LICENSE file that accompanied this code.
71.12 + *
71.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
71.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
71.15 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
71.16 + * version 2 for more details (a copy is included in the LICENSE file that
71.17 + * accompanied this code).
71.18 + *
71.19 + * You should have received a copy of the GNU General Public License version
71.20 + * 2 along with this work; if not, write to the Free Software Foundation,
71.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
71.22 + *
71.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
71.24 + * or visit www.oracle.com if you need additional information or have any
71.25 + * questions.
71.26 + */
71.27 +
71.28 +/*
71.29 + * This file is available under and governed by the GNU General Public
71.30 + * License version 2 only, as published by the Free Software Foundation.
71.31 + * However, the following notice accompanied the original version of this
71.32 + * file:
71.33 + *
71.34 + * Written by Doug Lea with assistance from members of JCP JSR-166
71.35 + * Expert Group and released to the public domain, as explained at
71.36 + * http://creativecommons.org/publicdomain/zero/1.0/
71.37 + */
71.38 +
71.39 +package java.util;
71.40 +
71.41 +/**
71.42 + * A collection designed for holding elements prior to processing.
71.43 + * Besides basic {@link java.util.Collection Collection} operations,
71.44 + * queues provide additional insertion, extraction, and inspection
71.45 + * operations. Each of these methods exists in two forms: one throws
71.46 + * an exception if the operation fails, the other returns a special
71.47 + * value (either <tt>null</tt> or <tt>false</tt>, depending on the
71.48 + * operation). The latter form of the insert operation is designed
71.49 + * specifically for use with capacity-restricted <tt>Queue</tt>
71.50 + * implementations; in most implementations, insert operations cannot
71.51 + * fail.
71.52 + *
71.53 + * <p>
71.54 + * <table BORDER CELLPADDING=3 CELLSPACING=1>
71.55 + * <tr>
71.56 + * <td></td>
71.57 + * <td ALIGN=CENTER><em>Throws exception</em></td>
71.58 + * <td ALIGN=CENTER><em>Returns special value</em></td>
71.59 + * </tr>
71.60 + * <tr>
71.61 + * <td><b>Insert</b></td>
71.62 + * <td>{@link #add add(e)}</td>
71.63 + * <td>{@link #offer offer(e)}</td>
71.64 + * </tr>
71.65 + * <tr>
71.66 + * <td><b>Remove</b></td>
71.67 + * <td>{@link #remove remove()}</td>
71.68 + * <td>{@link #poll poll()}</td>
71.69 + * </tr>
71.70 + * <tr>
71.71 + * <td><b>Examine</b></td>
71.72 + * <td>{@link #element element()}</td>
71.73 + * <td>{@link #peek peek()}</td>
71.74 + * </tr>
71.75 + * </table>
71.76 + *
71.77 + * <p>Queues typically, but do not necessarily, order elements in a
71.78 + * FIFO (first-in-first-out) manner. Among the exceptions are
71.79 + * priority queues, which order elements according to a supplied
71.80 + * comparator, or the elements' natural ordering, and LIFO queues (or
71.81 + * stacks) which order the elements LIFO (last-in-first-out).
71.82 + * Whatever the ordering used, the <em>head</em> of the queue is that
71.83 + * element which would be removed by a call to {@link #remove() } or
71.84 + * {@link #poll()}. In a FIFO queue, all new elements are inserted at
71.85 + * the <em> tail</em> of the queue. Other kinds of queues may use
71.86 + * different placement rules. Every <tt>Queue</tt> implementation
71.87 + * must specify its ordering properties.
71.88 + *
71.89 + * <p>The {@link #offer offer} method inserts an element if possible,
71.90 + * otherwise returning <tt>false</tt>. This differs from the {@link
71.91 + * java.util.Collection#add Collection.add} method, which can fail to
71.92 + * add an element only by throwing an unchecked exception. The
71.93 + * <tt>offer</tt> method is designed for use when failure is a normal,
71.94 + * rather than exceptional occurrence, for example, in fixed-capacity
71.95 + * (or "bounded") queues.
71.96 + *
71.97 + * <p>The {@link #remove()} and {@link #poll()} methods remove and
71.98 + * return the head of the queue.
71.99 + * Exactly which element is removed from the queue is a
71.100 + * function of the queue's ordering policy, which differs from
71.101 + * implementation to implementation. The <tt>remove()</tt> and
71.102 + * <tt>poll()</tt> methods differ only in their behavior when the
71.103 + * queue is empty: the <tt>remove()</tt> method throws an exception,
71.104 + * while the <tt>poll()</tt> method returns <tt>null</tt>.
71.105 + *
71.106 + * <p>The {@link #element()} and {@link #peek()} methods return, but do
71.107 + * not remove, the head of the queue.
71.108 + *
71.109 + * <p>The <tt>Queue</tt> interface does not define the <i>blocking queue
71.110 + * methods</i>, which are common in concurrent programming. These methods,
71.111 + * which wait for elements to appear or for space to become available, are
71.112 + * defined in the {@link java.util.concurrent.BlockingQueue} interface, which
71.113 + * extends this interface.
71.114 + *
71.115 + * <p><tt>Queue</tt> implementations generally do not allow insertion
71.116 + * of <tt>null</tt> elements, although some implementations, such as
71.117 + * {@link LinkedList}, do not prohibit insertion of <tt>null</tt>.
71.118 + * Even in the implementations that permit it, <tt>null</tt> should
71.119 + * not be inserted into a <tt>Queue</tt>, as <tt>null</tt> is also
71.120 + * used as a special return value by the <tt>poll</tt> method to
71.121 + * indicate that the queue contains no elements.
71.122 + *
71.123 + * <p><tt>Queue</tt> implementations generally do not define
71.124 + * element-based versions of methods <tt>equals</tt> and
71.125 + * <tt>hashCode</tt> but instead inherit the identity based versions
71.126 + * from class <tt>Object</tt>, because element-based equality is not
71.127 + * always well-defined for queues with the same elements but different
71.128 + * ordering properties.
71.129 + *
71.130 + *
71.131 + * <p>This interface is a member of the
71.132 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
71.133 + * Java Collections Framework</a>.
71.134 + *
71.135 + * @see java.util.Collection
71.136 + * @see LinkedList
71.137 + * @see PriorityQueue
71.138 + * @see java.util.concurrent.LinkedBlockingQueue
71.139 + * @see java.util.concurrent.BlockingQueue
71.140 + * @see java.util.concurrent.ArrayBlockingQueue
71.141 + * @see java.util.concurrent.LinkedBlockingQueue
71.142 + * @see java.util.concurrent.PriorityBlockingQueue
71.143 + * @since 1.5
71.144 + * @author Doug Lea
71.145 + * @param <E> the type of elements held in this collection
71.146 + */
71.147 +public interface Queue<E> extends Collection<E> {
71.148 + /**
71.149 + * Inserts the specified element into this queue if it is possible to do so
71.150 + * immediately without violating capacity restrictions, returning
71.151 + * <tt>true</tt> upon success and throwing an <tt>IllegalStateException</tt>
71.152 + * if no space is currently available.
71.153 + *
71.154 + * @param e the element to add
71.155 + * @return <tt>true</tt> (as specified by {@link Collection#add})
71.156 + * @throws IllegalStateException if the element cannot be added at this
71.157 + * time due to capacity restrictions
71.158 + * @throws ClassCastException if the class of the specified element
71.159 + * prevents it from being added to this queue
71.160 + * @throws NullPointerException if the specified element is null and
71.161 + * this queue does not permit null elements
71.162 + * @throws IllegalArgumentException if some property of this element
71.163 + * prevents it from being added to this queue
71.164 + */
71.165 + boolean add(E e);
71.166 +
71.167 + /**
71.168 + * Inserts the specified element into this queue if it is possible to do
71.169 + * so immediately without violating capacity restrictions.
71.170 + * When using a capacity-restricted queue, this method is generally
71.171 + * preferable to {@link #add}, which can fail to insert an element only
71.172 + * by throwing an exception.
71.173 + *
71.174 + * @param e the element to add
71.175 + * @return <tt>true</tt> if the element was added to this queue, else
71.176 + * <tt>false</tt>
71.177 + * @throws ClassCastException if the class of the specified element
71.178 + * prevents it from being added to this queue
71.179 + * @throws NullPointerException if the specified element is null and
71.180 + * this queue does not permit null elements
71.181 + * @throws IllegalArgumentException if some property of this element
71.182 + * prevents it from being added to this queue
71.183 + */
71.184 + boolean offer(E e);
71.185 +
71.186 + /**
71.187 + * Retrieves and removes the head of this queue. This method differs
71.188 + * from {@link #poll poll} only in that it throws an exception if this
71.189 + * queue is empty.
71.190 + *
71.191 + * @return the head of this queue
71.192 + * @throws NoSuchElementException if this queue is empty
71.193 + */
71.194 + E remove();
71.195 +
71.196 + /**
71.197 + * Retrieves and removes the head of this queue,
71.198 + * or returns <tt>null</tt> if this queue is empty.
71.199 + *
71.200 + * @return the head of this queue, or <tt>null</tt> if this queue is empty
71.201 + */
71.202 + E poll();
71.203 +
71.204 + /**
71.205 + * Retrieves, but does not remove, the head of this queue. This method
71.206 + * differs from {@link #peek peek} only in that it throws an exception
71.207 + * if this queue is empty.
71.208 + *
71.209 + * @return the head of this queue
71.210 + * @throws NoSuchElementException if this queue is empty
71.211 + */
71.212 + E element();
71.213 +
71.214 + /**
71.215 + * Retrieves, but does not remove, the head of this queue,
71.216 + * or returns <tt>null</tt> if this queue is empty.
71.217 + *
71.218 + * @return the head of this queue, or <tt>null</tt> if this queue is empty
71.219 + */
71.220 + E peek();
71.221 +}
72.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
72.2 +++ b/emul/compact/src/main/java/java/util/Random.java Sun Feb 17 17:58:34 2013 +0100
72.3 @@ -0,0 +1,503 @@
72.4 +/*
72.5 + * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
72.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
72.7 + *
72.8 + * This code is free software; you can redistribute it and/or modify it
72.9 + * under the terms of the GNU General Public License version 2 only, as
72.10 + * published by the Free Software Foundation. Oracle designates this
72.11 + * particular file as subject to the "Classpath" exception as provided
72.12 + * by Oracle in the LICENSE file that accompanied this code.
72.13 + *
72.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
72.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
72.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
72.17 + * version 2 for more details (a copy is included in the LICENSE file that
72.18 + * accompanied this code).
72.19 + *
72.20 + * You should have received a copy of the GNU General Public License version
72.21 + * 2 along with this work; if not, write to the Free Software Foundation,
72.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
72.23 + *
72.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
72.25 + * or visit www.oracle.com if you need additional information or have any
72.26 + * questions.
72.27 + */
72.28 +
72.29 +package java.util;
72.30 +
72.31 +import org.apidesign.bck2brwsr.emul.lang.System;
72.32 +
72.33 +/**
72.34 + * An instance of this class is used to generate a stream of
72.35 + * pseudorandom numbers. The class uses a 48-bit seed, which is
72.36 + * modified using a linear congruential formula. (See Donald Knuth,
72.37 + * <i>The Art of Computer Programming, Volume 2</i>, Section 3.2.1.)
72.38 + * <p>
72.39 + * If two instances of {@code Random} are created with the same
72.40 + * seed, and the same sequence of method calls is made for each, they
72.41 + * will generate and return identical sequences of numbers. In order to
72.42 + * guarantee this property, particular algorithms are specified for the
72.43 + * class {@code Random}. Java implementations must use all the algorithms
72.44 + * shown here for the class {@code Random}, for the sake of absolute
72.45 + * portability of Java code. However, subclasses of class {@code Random}
72.46 + * are permitted to use other algorithms, so long as they adhere to the
72.47 + * general contracts for all the methods.
72.48 + * <p>
72.49 + * The algorithms implemented by class {@code Random} use a
72.50 + * {@code protected} utility method that on each invocation can supply
72.51 + * up to 32 pseudorandomly generated bits.
72.52 + * <p>
72.53 + * Many applications will find the method {@link Math#random} simpler to use.
72.54 + *
72.55 + * <p>Instances of {@code java.util.Random} are threadsafe.
72.56 + * However, the concurrent use of the same {@code java.util.Random}
72.57 + * instance across threads may encounter contention and consequent
72.58 + * poor performance. Consider instead using
72.59 + * {@link java.util.concurrent.ThreadLocalRandom} in multithreaded
72.60 + * designs.
72.61 + *
72.62 + * <p>Instances of {@code java.util.Random} are not cryptographically
72.63 + * secure. Consider instead using {@link java.security.SecureRandom} to
72.64 + * get a cryptographically secure pseudo-random number generator for use
72.65 + * by security-sensitive applications.
72.66 + *
72.67 + * @author Frank Yellin
72.68 + * @since 1.0
72.69 + */
72.70 +public
72.71 +class Random implements java.io.Serializable {
72.72 + /** use serialVersionUID from JDK 1.1 for interoperability */
72.73 + static final long serialVersionUID = 3905348978240129619L;
72.74 +
72.75 + /**
72.76 + * The internal state associated with this pseudorandom number generator.
72.77 + * (The specs for the methods in this class describe the ongoing
72.78 + * computation of this value.)
72.79 + */
72.80 + private long seed;
72.81 +
72.82 + private static final long multiplier = 0x5DEECE66DL;
72.83 + private static final long addend = 0xBL;
72.84 + private static final long mask = (1L << 48) - 1;
72.85 +
72.86 + /**
72.87 + * Creates a new random number generator. This constructor sets
72.88 + * the seed of the random number generator to a value very likely
72.89 + * to be distinct from any other invocation of this constructor.
72.90 + */
72.91 + public Random() {
72.92 + this(seedUniquifier() ^ System.nanoTime());
72.93 + }
72.94 +
72.95 + private static synchronized long seedUniquifier() {
72.96 + // L'Ecuyer, "Tables of Linear Congruential Generators of
72.97 + // Different Sizes and Good Lattice Structure", 1999
72.98 + long current = seedUniquifier;
72.99 + long next = current * 181783497276652981L;
72.100 + seedUniquifier = next;
72.101 + return next;
72.102 + }
72.103 +
72.104 + private static long seedUniquifier = 8682522807148012L;
72.105 +
72.106 + /**
72.107 + * Creates a new random number generator using a single {@code long} seed.
72.108 + * The seed is the initial value of the internal state of the pseudorandom
72.109 + * number generator which is maintained by method {@link #next}.
72.110 + *
72.111 + * <p>The invocation {@code new Random(seed)} is equivalent to:
72.112 + * <pre> {@code
72.113 + * Random rnd = new Random();
72.114 + * rnd.setSeed(seed);}</pre>
72.115 + *
72.116 + * @param seed the initial seed
72.117 + * @see #setSeed(long)
72.118 + */
72.119 + public Random(long seed) {
72.120 + this.seed = initialScramble(seed);
72.121 + }
72.122 +
72.123 + private static long initialScramble(long seed) {
72.124 + return (seed ^ multiplier) & mask;
72.125 + }
72.126 +
72.127 + /**
72.128 + * Sets the seed of this random number generator using a single
72.129 + * {@code long} seed. The general contract of {@code setSeed} is
72.130 + * that it alters the state of this random number generator object
72.131 + * so as to be in exactly the same state as if it had just been
72.132 + * created with the argument {@code seed} as a seed. The method
72.133 + * {@code setSeed} is implemented by class {@code Random} by
72.134 + * atomically updating the seed to
72.135 + * <pre>{@code (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1)}</pre>
72.136 + * and clearing the {@code haveNextNextGaussian} flag used by {@link
72.137 + * #nextGaussian}.
72.138 + *
72.139 + * <p>The implementation of {@code setSeed} by class {@code Random}
72.140 + * happens to use only 48 bits of the given seed. In general, however,
72.141 + * an overriding method may use all 64 bits of the {@code long}
72.142 + * argument as a seed value.
72.143 + *
72.144 + * @param seed the initial seed
72.145 + */
72.146 + synchronized public void setSeed(long seed) {
72.147 + this.seed = initialScramble(seed);
72.148 + haveNextNextGaussian = false;
72.149 + }
72.150 +
72.151 + /**
72.152 + * Generates the next pseudorandom number. Subclasses should
72.153 + * override this, as this is used by all other methods.
72.154 + *
72.155 + * <p>The general contract of {@code next} is that it returns an
72.156 + * {@code int} value and if the argument {@code bits} is between
72.157 + * {@code 1} and {@code 32} (inclusive), then that many low-order
72.158 + * bits of the returned value will be (approximately) independently
72.159 + * chosen bit values, each of which is (approximately) equally
72.160 + * likely to be {@code 0} or {@code 1}. The method {@code next} is
72.161 + * implemented by class {@code Random} by atomically updating the seed to
72.162 + * <pre>{@code (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1)}</pre>
72.163 + * and returning
72.164 + * <pre>{@code (int)(seed >>> (48 - bits))}.</pre>
72.165 + *
72.166 + * This is a linear congruential pseudorandom number generator, as
72.167 + * defined by D. H. Lehmer and described by Donald E. Knuth in
72.168 + * <i>The Art of Computer Programming,</i> Volume 3:
72.169 + * <i>Seminumerical Algorithms</i>, section 3.2.1.
72.170 + *
72.171 + * @param bits random bits
72.172 + * @return the next pseudorandom value from this random number
72.173 + * generator's sequence
72.174 + * @since 1.1
72.175 + */
72.176 + protected synchronized int next(int bits) {
72.177 + long oldseed, nextseed;
72.178 + long seed = this.seed;
72.179 + oldseed = seed;
72.180 + nextseed = (oldseed * multiplier + addend) & mask;
72.181 + this.seed = nextseed;
72.182 + return (int)(nextseed >>> (48 - bits));
72.183 + }
72.184 +
72.185 + /**
72.186 + * Generates random bytes and places them into a user-supplied
72.187 + * byte array. The number of random bytes produced is equal to
72.188 + * the length of the byte array.
72.189 + *
72.190 + * <p>The method {@code nextBytes} is implemented by class {@code Random}
72.191 + * as if by:
72.192 + * <pre> {@code
72.193 + * public void nextBytes(byte[] bytes) {
72.194 + * for (int i = 0; i < bytes.length; )
72.195 + * for (int rnd = nextInt(), n = Math.min(bytes.length - i, 4);
72.196 + * n-- > 0; rnd >>= 8)
72.197 + * bytes[i++] = (byte)rnd;
72.198 + * }}</pre>
72.199 + *
72.200 + * @param bytes the byte array to fill with random bytes
72.201 + * @throws NullPointerException if the byte array is null
72.202 + * @since 1.1
72.203 + */
72.204 + public void nextBytes(byte[] bytes) {
72.205 + for (int i = 0, len = bytes.length; i < len; )
72.206 + for (int rnd = nextInt(),
72.207 + n = Math.min(len - i, Integer.SIZE/Byte.SIZE);
72.208 + n-- > 0; rnd >>= Byte.SIZE)
72.209 + bytes[i++] = (byte)rnd;
72.210 + }
72.211 +
72.212 + /**
72.213 + * Returns the next pseudorandom, uniformly distributed {@code int}
72.214 + * value from this random number generator's sequence. The general
72.215 + * contract of {@code nextInt} is that one {@code int} value is
72.216 + * pseudorandomly generated and returned. All 2<font size="-1"><sup>32
72.217 + * </sup></font> possible {@code int} values are produced with
72.218 + * (approximately) equal probability.
72.219 + *
72.220 + * <p>The method {@code nextInt} is implemented by class {@code Random}
72.221 + * as if by:
72.222 + * <pre> {@code
72.223 + * public int nextInt() {
72.224 + * return next(32);
72.225 + * }}</pre>
72.226 + *
72.227 + * @return the next pseudorandom, uniformly distributed {@code int}
72.228 + * value from this random number generator's sequence
72.229 + */
72.230 + public int nextInt() {
72.231 + return next(32);
72.232 + }
72.233 +
72.234 + /**
72.235 + * Returns a pseudorandom, uniformly distributed {@code int} value
72.236 + * between 0 (inclusive) and the specified value (exclusive), drawn from
72.237 + * this random number generator's sequence. The general contract of
72.238 + * {@code nextInt} is that one {@code int} value in the specified range
72.239 + * is pseudorandomly generated and returned. All {@code n} possible
72.240 + * {@code int} values are produced with (approximately) equal
72.241 + * probability. The method {@code nextInt(int n)} is implemented by
72.242 + * class {@code Random} as if by:
72.243 + * <pre> {@code
72.244 + * public int nextInt(int n) {
72.245 + * if (n <= 0)
72.246 + * throw new IllegalArgumentException("n must be positive");
72.247 + *
72.248 + * if ((n & -n) == n) // i.e., n is a power of 2
72.249 + * return (int)((n * (long)next(31)) >> 31);
72.250 + *
72.251 + * int bits, val;
72.252 + * do {
72.253 + * bits = next(31);
72.254 + * val = bits % n;
72.255 + * } while (bits - val + (n-1) < 0);
72.256 + * return val;
72.257 + * }}</pre>
72.258 + *
72.259 + * <p>The hedge "approximately" is used in the foregoing description only
72.260 + * because the next method is only approximately an unbiased source of
72.261 + * independently chosen bits. If it were a perfect source of randomly
72.262 + * chosen bits, then the algorithm shown would choose {@code int}
72.263 + * values from the stated range with perfect uniformity.
72.264 + * <p>
72.265 + * The algorithm is slightly tricky. It rejects values that would result
72.266 + * in an uneven distribution (due to the fact that 2^31 is not divisible
72.267 + * by n). The probability of a value being rejected depends on n. The
72.268 + * worst case is n=2^30+1, for which the probability of a reject is 1/2,
72.269 + * and the expected number of iterations before the loop terminates is 2.
72.270 + * <p>
72.271 + * The algorithm treats the case where n is a power of two specially: it
72.272 + * returns the correct number of high-order bits from the underlying
72.273 + * pseudo-random number generator. In the absence of special treatment,
72.274 + * the correct number of <i>low-order</i> bits would be returned. Linear
72.275 + * congruential pseudo-random number generators such as the one
72.276 + * implemented by this class are known to have short periods in the
72.277 + * sequence of values of their low-order bits. Thus, this special case
72.278 + * greatly increases the length of the sequence of values returned by
72.279 + * successive calls to this method if n is a small power of two.
72.280 + *
72.281 + * @param n the bound on the random number to be returned. Must be
72.282 + * positive.
72.283 + * @return the next pseudorandom, uniformly distributed {@code int}
72.284 + * value between {@code 0} (inclusive) and {@code n} (exclusive)
72.285 + * from this random number generator's sequence
72.286 + * @throws IllegalArgumentException if n is not positive
72.287 + * @since 1.2
72.288 + */
72.289 +
72.290 + public int nextInt(int n) {
72.291 + if (n <= 0)
72.292 + throw new IllegalArgumentException("n must be positive");
72.293 +
72.294 + if ((n & -n) == n) // i.e., n is a power of 2
72.295 + return (int)((n * (long)next(31)) >> 31);
72.296 +
72.297 + int bits, val;
72.298 + do {
72.299 + bits = next(31);
72.300 + val = bits % n;
72.301 + } while (bits - val + (n-1) < 0);
72.302 + return val;
72.303 + }
72.304 +
72.305 + /**
72.306 + * Returns the next pseudorandom, uniformly distributed {@code long}
72.307 + * value from this random number generator's sequence. The general
72.308 + * contract of {@code nextLong} is that one {@code long} value is
72.309 + * pseudorandomly generated and returned.
72.310 + *
72.311 + * <p>The method {@code nextLong} is implemented by class {@code Random}
72.312 + * as if by:
72.313 + * <pre> {@code
72.314 + * public long nextLong() {
72.315 + * return ((long)next(32) << 32) + next(32);
72.316 + * }}</pre>
72.317 + *
72.318 + * Because class {@code Random} uses a seed with only 48 bits,
72.319 + * this algorithm will not return all possible {@code long} values.
72.320 + *
72.321 + * @return the next pseudorandom, uniformly distributed {@code long}
72.322 + * value from this random number generator's sequence
72.323 + */
72.324 + public long nextLong() {
72.325 + // it's okay that the bottom word remains signed.
72.326 + return ((long)(next(32)) << 32) + next(32);
72.327 + }
72.328 +
72.329 + /**
72.330 + * Returns the next pseudorandom, uniformly distributed
72.331 + * {@code boolean} value from this random number generator's
72.332 + * sequence. The general contract of {@code nextBoolean} is that one
72.333 + * {@code boolean} value is pseudorandomly generated and returned. The
72.334 + * values {@code true} and {@code false} are produced with
72.335 + * (approximately) equal probability.
72.336 + *
72.337 + * <p>The method {@code nextBoolean} is implemented by class {@code Random}
72.338 + * as if by:
72.339 + * <pre> {@code
72.340 + * public boolean nextBoolean() {
72.341 + * return next(1) != 0;
72.342 + * }}</pre>
72.343 + *
72.344 + * @return the next pseudorandom, uniformly distributed
72.345 + * {@code boolean} value from this random number generator's
72.346 + * sequence
72.347 + * @since 1.2
72.348 + */
72.349 + public boolean nextBoolean() {
72.350 + return next(1) != 0;
72.351 + }
72.352 +
72.353 + /**
72.354 + * Returns the next pseudorandom, uniformly distributed {@code float}
72.355 + * value between {@code 0.0} and {@code 1.0} from this random
72.356 + * number generator's sequence.
72.357 + *
72.358 + * <p>The general contract of {@code nextFloat} is that one
72.359 + * {@code float} value, chosen (approximately) uniformly from the
72.360 + * range {@code 0.0f} (inclusive) to {@code 1.0f} (exclusive), is
72.361 + * pseudorandomly generated and returned. All 2<font
72.362 + * size="-1"><sup>24</sup></font> possible {@code float} values
72.363 + * of the form <i>m x </i>2<font
72.364 + * size="-1"><sup>-24</sup></font>, where <i>m</i> is a positive
72.365 + * integer less than 2<font size="-1"><sup>24</sup> </font>, are
72.366 + * produced with (approximately) equal probability.
72.367 + *
72.368 + * <p>The method {@code nextFloat} is implemented by class {@code Random}
72.369 + * as if by:
72.370 + * <pre> {@code
72.371 + * public float nextFloat() {
72.372 + * return next(24) / ((float)(1 << 24));
72.373 + * }}</pre>
72.374 + *
72.375 + * <p>The hedge "approximately" is used in the foregoing description only
72.376 + * because the next method is only approximately an unbiased source of
72.377 + * independently chosen bits. If it were a perfect source of randomly
72.378 + * chosen bits, then the algorithm shown would choose {@code float}
72.379 + * values from the stated range with perfect uniformity.<p>
72.380 + * [In early versions of Java, the result was incorrectly calculated as:
72.381 + * <pre> {@code
72.382 + * return next(30) / ((float)(1 << 30));}</pre>
72.383 + * This might seem to be equivalent, if not better, but in fact it
72.384 + * introduced a slight nonuniformity because of the bias in the rounding
72.385 + * of floating-point numbers: it was slightly more likely that the
72.386 + * low-order bit of the significand would be 0 than that it would be 1.]
72.387 + *
72.388 + * @return the next pseudorandom, uniformly distributed {@code float}
72.389 + * value between {@code 0.0} and {@code 1.0} from this
72.390 + * random number generator's sequence
72.391 + */
72.392 + public float nextFloat() {
72.393 + return next(24) / ((float)(1 << 24));
72.394 + }
72.395 +
72.396 + /**
72.397 + * Returns the next pseudorandom, uniformly distributed
72.398 + * {@code double} value between {@code 0.0} and
72.399 + * {@code 1.0} from this random number generator's sequence.
72.400 + *
72.401 + * <p>The general contract of {@code nextDouble} is that one
72.402 + * {@code double} value, chosen (approximately) uniformly from the
72.403 + * range {@code 0.0d} (inclusive) to {@code 1.0d} (exclusive), is
72.404 + * pseudorandomly generated and returned.
72.405 + *
72.406 + * <p>The method {@code nextDouble} is implemented by class {@code Random}
72.407 + * as if by:
72.408 + * <pre> {@code
72.409 + * public double nextDouble() {
72.410 + * return (((long)next(26) << 27) + next(27))
72.411 + * / (double)(1L << 53);
72.412 + * }}</pre>
72.413 + *
72.414 + * <p>The hedge "approximately" is used in the foregoing description only
72.415 + * because the {@code next} method is only approximately an unbiased
72.416 + * source of independently chosen bits. If it were a perfect source of
72.417 + * randomly chosen bits, then the algorithm shown would choose
72.418 + * {@code double} values from the stated range with perfect uniformity.
72.419 + * <p>[In early versions of Java, the result was incorrectly calculated as:
72.420 + * <pre> {@code
72.421 + * return (((long)next(27) << 27) + next(27))
72.422 + * / (double)(1L << 54);}</pre>
72.423 + * This might seem to be equivalent, if not better, but in fact it
72.424 + * introduced a large nonuniformity because of the bias in the rounding
72.425 + * of floating-point numbers: it was three times as likely that the
72.426 + * low-order bit of the significand would be 0 than that it would be 1!
72.427 + * This nonuniformity probably doesn't matter much in practice, but we
72.428 + * strive for perfection.]
72.429 + *
72.430 + * @return the next pseudorandom, uniformly distributed {@code double}
72.431 + * value between {@code 0.0} and {@code 1.0} from this
72.432 + * random number generator's sequence
72.433 + * @see Math#random
72.434 + */
72.435 + public double nextDouble() {
72.436 + return (((long)(next(26)) << 27) + next(27))
72.437 + / (double)(1L << 53);
72.438 + }
72.439 +
72.440 + private double nextNextGaussian;
72.441 + private boolean haveNextNextGaussian = false;
72.442 +
72.443 + /**
72.444 + * Returns the next pseudorandom, Gaussian ("normally") distributed
72.445 + * {@code double} value with mean {@code 0.0} and standard
72.446 + * deviation {@code 1.0} from this random number generator's sequence.
72.447 + * <p>
72.448 + * The general contract of {@code nextGaussian} is that one
72.449 + * {@code double} value, chosen from (approximately) the usual
72.450 + * normal distribution with mean {@code 0.0} and standard deviation
72.451 + * {@code 1.0}, is pseudorandomly generated and returned.
72.452 + *
72.453 + * <p>The method {@code nextGaussian} is implemented by class
72.454 + * {@code Random} as if by a threadsafe version of the following:
72.455 + * <pre> {@code
72.456 + * private double nextNextGaussian;
72.457 + * private boolean haveNextNextGaussian = false;
72.458 + *
72.459 + * public double nextGaussian() {
72.460 + * if (haveNextNextGaussian) {
72.461 + * haveNextNextGaussian = false;
72.462 + * return nextNextGaussian;
72.463 + * } else {
72.464 + * double v1, v2, s;
72.465 + * do {
72.466 + * v1 = 2 * nextDouble() - 1; // between -1.0 and 1.0
72.467 + * v2 = 2 * nextDouble() - 1; // between -1.0 and 1.0
72.468 + * s = v1 * v1 + v2 * v2;
72.469 + * } while (s >= 1 || s == 0);
72.470 + * double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s)/s);
72.471 + * nextNextGaussian = v2 * multiplier;
72.472 + * haveNextNextGaussian = true;
72.473 + * return v1 * multiplier;
72.474 + * }
72.475 + * }}</pre>
72.476 + * This uses the <i>polar method</i> of G. E. P. Box, M. E. Muller, and
72.477 + * G. Marsaglia, as described by Donald E. Knuth in <i>The Art of
72.478 + * Computer Programming</i>, Volume 3: <i>Seminumerical Algorithms</i>,
72.479 + * section 3.4.1, subsection C, algorithm P. Note that it generates two
72.480 + * independent values at the cost of only one call to {@code StrictMath.log}
72.481 + * and one call to {@code StrictMath.sqrt}.
72.482 + *
72.483 + * @return the next pseudorandom, Gaussian ("normally") distributed
72.484 + * {@code double} value with mean {@code 0.0} and
72.485 + * standard deviation {@code 1.0} from this random number
72.486 + * generator's sequence
72.487 + */
72.488 + synchronized public double nextGaussian() {
72.489 + // See Knuth, ACP, Section 3.4.1 Algorithm C.
72.490 + if (haveNextNextGaussian) {
72.491 + haveNextNextGaussian = false;
72.492 + return nextNextGaussian;
72.493 + } else {
72.494 + double v1, v2, s;
72.495 + do {
72.496 + v1 = 2 * nextDouble() - 1; // between -1 and 1
72.497 + v2 = 2 * nextDouble() - 1; // between -1 and 1
72.498 + s = v1 * v1 + v2 * v2;
72.499 + } while (s >= 1 || s == 0);
72.500 + double multiplier = Math.sqrt(-2 * Math.log(s)/s);
72.501 + nextNextGaussian = v2 * multiplier;
72.502 + haveNextNextGaussian = true;
72.503 + return v1 * multiplier;
72.504 + }
72.505 + }
72.506 +}
73.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
73.2 +++ b/emul/compact/src/main/java/java/util/SortedMap.java Sun Feb 17 17:58:34 2013 +0100
73.3 @@ -0,0 +1,284 @@
73.4 +/*
73.5 + * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
73.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
73.7 + *
73.8 + * This code is free software; you can redistribute it and/or modify it
73.9 + * under the terms of the GNU General Public License version 2 only, as
73.10 + * published by the Free Software Foundation. Oracle designates this
73.11 + * particular file as subject to the "Classpath" exception as provided
73.12 + * by Oracle in the LICENSE file that accompanied this code.
73.13 + *
73.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
73.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
73.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
73.17 + * version 2 for more details (a copy is included in the LICENSE file that
73.18 + * accompanied this code).
73.19 + *
73.20 + * You should have received a copy of the GNU General Public License version
73.21 + * 2 along with this work; if not, write to the Free Software Foundation,
73.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
73.23 + *
73.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
73.25 + * or visit www.oracle.com if you need additional information or have any
73.26 + * questions.
73.27 + */
73.28 +
73.29 +package java.util;
73.30 +
73.31 +/**
73.32 + * A {@link Map} that further provides a <em>total ordering</em> on its keys.
73.33 + * The map is ordered according to the {@linkplain Comparable natural
73.34 + * ordering} of its keys, or by a {@link Comparator} typically
73.35 + * provided at sorted map creation time. This order is reflected when
73.36 + * iterating over the sorted map's collection views (returned by the
73.37 + * {@code entrySet}, {@code keySet} and {@code values} methods).
73.38 + * Several additional operations are provided to take advantage of the
73.39 + * ordering. (This interface is the map analogue of {@link SortedSet}.)
73.40 + *
73.41 + * <p>All keys inserted into a sorted map must implement the {@code Comparable}
73.42 + * interface (or be accepted by the specified comparator). Furthermore, all
73.43 + * such keys must be <em>mutually comparable</em>: {@code k1.compareTo(k2)} (or
73.44 + * {@code comparator.compare(k1, k2)}) must not throw a
73.45 + * {@code ClassCastException} for any keys {@code k1} and {@code k2} in
73.46 + * the sorted map. Attempts to violate this restriction will cause the
73.47 + * offending method or constructor invocation to throw a
73.48 + * {@code ClassCastException}.
73.49 + *
73.50 + * <p>Note that the ordering maintained by a sorted map (whether or not an
73.51 + * explicit comparator is provided) must be <em>consistent with equals</em> if
73.52 + * the sorted map is to correctly implement the {@code Map} interface. (See
73.53 + * the {@code Comparable} interface or {@code Comparator} interface for a
73.54 + * precise definition of <em>consistent with equals</em>.) This is so because
73.55 + * the {@code Map} interface is defined in terms of the {@code equals}
73.56 + * operation, but a sorted map performs all key comparisons using its
73.57 + * {@code compareTo} (or {@code compare}) method, so two keys that are
73.58 + * deemed equal by this method are, from the standpoint of the sorted map,
73.59 + * equal. The behavior of a tree map <em>is</em> well-defined even if its
73.60 + * ordering is inconsistent with equals; it just fails to obey the general
73.61 + * contract of the {@code Map} interface.
73.62 + *
73.63 + * <p>All general-purpose sorted map implementation classes should provide four
73.64 + * "standard" constructors. It is not possible to enforce this recommendation
73.65 + * though as required constructors cannot be specified by interfaces. The
73.66 + * expected "standard" constructors for all sorted map implementations are:
73.67 + * <ol>
73.68 + * <li>A void (no arguments) constructor, which creates an empty sorted map
73.69 + * sorted according to the natural ordering of its keys.</li>
73.70 + * <li>A constructor with a single argument of type {@code Comparator}, which
73.71 + * creates an empty sorted map sorted according to the specified comparator.</li>
73.72 + * <li>A constructor with a single argument of type {@code Map}, which creates
73.73 + * a new map with the same key-value mappings as its argument, sorted
73.74 + * according to the keys' natural ordering.</li>
73.75 + * <li>A constructor with a single argument of type {@code SortedMap}, which
73.76 + * creates a new sorted map with the same key-value mappings and the same
73.77 + * ordering as the input sorted map.</li>
73.78 + * </ol>
73.79 + *
73.80 + * <p><strong>Note</strong>: several methods return submaps with restricted key
73.81 + * ranges. Such ranges are <em>half-open</em>, that is, they include their low
73.82 + * endpoint but not their high endpoint (where applicable). If you need a
73.83 + * <em>closed range</em> (which includes both endpoints), and the key type
73.84 + * allows for calculation of the successor of a given key, merely request
73.85 + * the subrange from {@code lowEndpoint} to
73.86 + * {@code successor(highEndpoint)}. For example, suppose that {@code m}
73.87 + * is a map whose keys are strings. The following idiom obtains a view
73.88 + * containing all of the key-value mappings in {@code m} whose keys are
73.89 + * between {@code low} and {@code high}, inclusive:<pre>
73.90 + * SortedMap<String, V> sub = m.subMap(low, high+"\0");</pre>
73.91 + *
73.92 + * A similar technique can be used to generate an <em>open range</em>
73.93 + * (which contains neither endpoint). The following idiom obtains a
73.94 + * view containing all of the key-value mappings in {@code m} whose keys
73.95 + * are between {@code low} and {@code high}, exclusive:<pre>
73.96 + * SortedMap<String, V> sub = m.subMap(low+"\0", high);</pre>
73.97 + *
73.98 + * <p>This interface is a member of the
73.99 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
73.100 + * Java Collections Framework</a>.
73.101 + *
73.102 + * @param <K> the type of keys maintained by this map
73.103 + * @param <V> the type of mapped values
73.104 + *
73.105 + * @author Josh Bloch
73.106 + * @see Map
73.107 + * @see TreeMap
73.108 + * @see SortedSet
73.109 + * @see Comparator
73.110 + * @see Comparable
73.111 + * @see Collection
73.112 + * @see ClassCastException
73.113 + * @since 1.2
73.114 + */
73.115 +
73.116 +public interface SortedMap<K,V> extends Map<K,V> {
73.117 + /**
73.118 + * Returns the comparator used to order the keys in this map, or
73.119 + * {@code null} if this map uses the {@linkplain Comparable
73.120 + * natural ordering} of its keys.
73.121 + *
73.122 + * @return the comparator used to order the keys in this map,
73.123 + * or {@code null} if this map uses the natural ordering
73.124 + * of its keys
73.125 + */
73.126 + Comparator<? super K> comparator();
73.127 +
73.128 + /**
73.129 + * Returns a view of the portion of this map whose keys range from
73.130 + * {@code fromKey}, inclusive, to {@code toKey}, exclusive. (If
73.131 + * {@code fromKey} and {@code toKey} are equal, the returned map
73.132 + * is empty.) The returned map is backed by this map, so changes
73.133 + * in the returned map are reflected in this map, and vice-versa.
73.134 + * The returned map supports all optional map operations that this
73.135 + * map supports.
73.136 + *
73.137 + * <p>The returned map will throw an {@code IllegalArgumentException}
73.138 + * on an attempt to insert a key outside its range.
73.139 + *
73.140 + * @param fromKey low endpoint (inclusive) of the keys in the returned map
73.141 + * @param toKey high endpoint (exclusive) of the keys in the returned map
73.142 + * @return a view of the portion of this map whose keys range from
73.143 + * {@code fromKey}, inclusive, to {@code toKey}, exclusive
73.144 + * @throws ClassCastException if {@code fromKey} and {@code toKey}
73.145 + * cannot be compared to one another using this map's comparator
73.146 + * (or, if the map has no comparator, using natural ordering).
73.147 + * Implementations may, but are not required to, throw this
73.148 + * exception if {@code fromKey} or {@code toKey}
73.149 + * cannot be compared to keys currently in the map.
73.150 + * @throws NullPointerException if {@code fromKey} or {@code toKey}
73.151 + * is null and this map does not permit null keys
73.152 + * @throws IllegalArgumentException if {@code fromKey} is greater than
73.153 + * {@code toKey}; or if this map itself has a restricted
73.154 + * range, and {@code fromKey} or {@code toKey} lies
73.155 + * outside the bounds of the range
73.156 + */
73.157 + SortedMap<K,V> subMap(K fromKey, K toKey);
73.158 +
73.159 + /**
73.160 + * Returns a view of the portion of this map whose keys are
73.161 + * strictly less than {@code toKey}. The returned map is backed
73.162 + * by this map, so changes in the returned map are reflected in
73.163 + * this map, and vice-versa. The returned map supports all
73.164 + * optional map operations that this map supports.
73.165 + *
73.166 + * <p>The returned map will throw an {@code IllegalArgumentException}
73.167 + * on an attempt to insert a key outside its range.
73.168 + *
73.169 + * @param toKey high endpoint (exclusive) of the keys in the returned map
73.170 + * @return a view of the portion of this map whose keys are strictly
73.171 + * less than {@code toKey}
73.172 + * @throws ClassCastException if {@code toKey} is not compatible
73.173 + * with this map's comparator (or, if the map has no comparator,
73.174 + * if {@code toKey} does not implement {@link Comparable}).
73.175 + * Implementations may, but are not required to, throw this
73.176 + * exception if {@code toKey} cannot be compared to keys
73.177 + * currently in the map.
73.178 + * @throws NullPointerException if {@code toKey} is null and
73.179 + * this map does not permit null keys
73.180 + * @throws IllegalArgumentException if this map itself has a
73.181 + * restricted range, and {@code toKey} lies outside the
73.182 + * bounds of the range
73.183 + */
73.184 + SortedMap<K,V> headMap(K toKey);
73.185 +
73.186 + /**
73.187 + * Returns a view of the portion of this map whose keys are
73.188 + * greater than or equal to {@code fromKey}. The returned map is
73.189 + * backed by this map, so changes in the returned map are
73.190 + * reflected in this map, and vice-versa. The returned map
73.191 + * supports all optional map operations that this map supports.
73.192 + *
73.193 + * <p>The returned map will throw an {@code IllegalArgumentException}
73.194 + * on an attempt to insert a key outside its range.
73.195 + *
73.196 + * @param fromKey low endpoint (inclusive) of the keys in the returned map
73.197 + * @return a view of the portion of this map whose keys are greater
73.198 + * than or equal to {@code fromKey}
73.199 + * @throws ClassCastException if {@code fromKey} is not compatible
73.200 + * with this map's comparator (or, if the map has no comparator,
73.201 + * if {@code fromKey} does not implement {@link Comparable}).
73.202 + * Implementations may, but are not required to, throw this
73.203 + * exception if {@code fromKey} cannot be compared to keys
73.204 + * currently in the map.
73.205 + * @throws NullPointerException if {@code fromKey} is null and
73.206 + * this map does not permit null keys
73.207 + * @throws IllegalArgumentException if this map itself has a
73.208 + * restricted range, and {@code fromKey} lies outside the
73.209 + * bounds of the range
73.210 + */
73.211 + SortedMap<K,V> tailMap(K fromKey);
73.212 +
73.213 + /**
73.214 + * Returns the first (lowest) key currently in this map.
73.215 + *
73.216 + * @return the first (lowest) key currently in this map
73.217 + * @throws NoSuchElementException if this map is empty
73.218 + */
73.219 + K firstKey();
73.220 +
73.221 + /**
73.222 + * Returns the last (highest) key currently in this map.
73.223 + *
73.224 + * @return the last (highest) key currently in this map
73.225 + * @throws NoSuchElementException if this map is empty
73.226 + */
73.227 + K lastKey();
73.228 +
73.229 + /**
73.230 + * Returns a {@link Set} view of the keys contained in this map.
73.231 + * The set's iterator returns the keys in ascending order.
73.232 + * The set is backed by the map, so changes to the map are
73.233 + * reflected in the set, and vice-versa. If the map is modified
73.234 + * while an iteration over the set is in progress (except through
73.235 + * the iterator's own {@code remove} operation), the results of
73.236 + * the iteration are undefined. The set supports element removal,
73.237 + * which removes the corresponding mapping from the map, via the
73.238 + * {@code Iterator.remove}, {@code Set.remove},
73.239 + * {@code removeAll}, {@code retainAll}, and {@code clear}
73.240 + * operations. It does not support the {@code add} or {@code addAll}
73.241 + * operations.
73.242 + *
73.243 + * @return a set view of the keys contained in this map, sorted in
73.244 + * ascending order
73.245 + */
73.246 + Set<K> keySet();
73.247 +
73.248 + /**
73.249 + * Returns a {@link Collection} view of the values contained in this map.
73.250 + * The collection's iterator returns the values in ascending order
73.251 + * of the corresponding keys.
73.252 + * The collection is backed by the map, so changes to the map are
73.253 + * reflected in the collection, and vice-versa. If the map is
73.254 + * modified while an iteration over the collection is in progress
73.255 + * (except through the iterator's own {@code remove} operation),
73.256 + * the results of the iteration are undefined. The collection
73.257 + * supports element removal, which removes the corresponding
73.258 + * mapping from the map, via the {@code Iterator.remove},
73.259 + * {@code Collection.remove}, {@code removeAll},
73.260 + * {@code retainAll} and {@code clear} operations. It does not
73.261 + * support the {@code add} or {@code addAll} operations.
73.262 + *
73.263 + * @return a collection view of the values contained in this map,
73.264 + * sorted in ascending key order
73.265 + */
73.266 + Collection<V> values();
73.267 +
73.268 + /**
73.269 + * Returns a {@link Set} view of the mappings contained in this map.
73.270 + * The set's iterator returns the entries in ascending key order.
73.271 + * The set is backed by the map, so changes to the map are
73.272 + * reflected in the set, and vice-versa. If the map is modified
73.273 + * while an iteration over the set is in progress (except through
73.274 + * the iterator's own {@code remove} operation, or through the
73.275 + * {@code setValue} operation on a map entry returned by the
73.276 + * iterator) the results of the iteration are undefined. The set
73.277 + * supports element removal, which removes the corresponding
73.278 + * mapping from the map, via the {@code Iterator.remove},
73.279 + * {@code Set.remove}, {@code removeAll}, {@code retainAll} and
73.280 + * {@code clear} operations. It does not support the
73.281 + * {@code add} or {@code addAll} operations.
73.282 + *
73.283 + * @return a set view of the mappings contained in this map,
73.284 + * sorted in ascending key order
73.285 + */
73.286 + Set<Map.Entry<K, V>> entrySet();
73.287 +}
74.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
74.2 +++ b/emul/compact/src/main/java/java/util/SortedSet.java Sun Feb 17 17:58:34 2013 +0100
74.3 @@ -0,0 +1,222 @@
74.4 +/*
74.5 + * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
74.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
74.7 + *
74.8 + * This code is free software; you can redistribute it and/or modify it
74.9 + * under the terms of the GNU General Public License version 2 only, as
74.10 + * published by the Free Software Foundation. Oracle designates this
74.11 + * particular file as subject to the "Classpath" exception as provided
74.12 + * by Oracle in the LICENSE file that accompanied this code.
74.13 + *
74.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
74.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
74.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
74.17 + * version 2 for more details (a copy is included in the LICENSE file that
74.18 + * accompanied this code).
74.19 + *
74.20 + * You should have received a copy of the GNU General Public License version
74.21 + * 2 along with this work; if not, write to the Free Software Foundation,
74.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
74.23 + *
74.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
74.25 + * or visit www.oracle.com if you need additional information or have any
74.26 + * questions.
74.27 + */
74.28 +
74.29 +package java.util;
74.30 +
74.31 +/**
74.32 + * A {@link Set} that further provides a <i>total ordering</i> on its elements.
74.33 + * The elements are ordered using their {@linkplain Comparable natural
74.34 + * ordering}, or by a {@link Comparator} typically provided at sorted
74.35 + * set creation time. The set's iterator will traverse the set in
74.36 + * ascending element order. Several additional operations are provided
74.37 + * to take advantage of the ordering. (This interface is the set
74.38 + * analogue of {@link SortedMap}.)
74.39 + *
74.40 + * <p>All elements inserted into a sorted set must implement the <tt>Comparable</tt>
74.41 + * interface (or be accepted by the specified comparator). Furthermore, all
74.42 + * such elements must be <i>mutually comparable</i>: <tt>e1.compareTo(e2)</tt>
74.43 + * (or <tt>comparator.compare(e1, e2)</tt>) must not throw a
74.44 + * <tt>ClassCastException</tt> for any elements <tt>e1</tt> and <tt>e2</tt> in
74.45 + * the sorted set. Attempts to violate this restriction will cause the
74.46 + * offending method or constructor invocation to throw a
74.47 + * <tt>ClassCastException</tt>.
74.48 + *
74.49 + * <p>Note that the ordering maintained by a sorted set (whether or not an
74.50 + * explicit comparator is provided) must be <i>consistent with equals</i> if
74.51 + * the sorted set is to correctly implement the <tt>Set</tt> interface. (See
74.52 + * the <tt>Comparable</tt> interface or <tt>Comparator</tt> interface for a
74.53 + * precise definition of <i>consistent with equals</i>.) This is so because
74.54 + * the <tt>Set</tt> interface is defined in terms of the <tt>equals</tt>
74.55 + * operation, but a sorted set performs all element comparisons using its
74.56 + * <tt>compareTo</tt> (or <tt>compare</tt>) method, so two elements that are
74.57 + * deemed equal by this method are, from the standpoint of the sorted set,
74.58 + * equal. The behavior of a sorted set <i>is</i> well-defined even if its
74.59 + * ordering is inconsistent with equals; it just fails to obey the general
74.60 + * contract of the <tt>Set</tt> interface.
74.61 + *
74.62 + * <p>All general-purpose sorted set implementation classes should
74.63 + * provide four "standard" constructors: 1) A void (no arguments)
74.64 + * constructor, which creates an empty sorted set sorted according to
74.65 + * the natural ordering of its elements. 2) A constructor with a
74.66 + * single argument of type <tt>Comparator</tt>, which creates an empty
74.67 + * sorted set sorted according to the specified comparator. 3) A
74.68 + * constructor with a single argument of type <tt>Collection</tt>,
74.69 + * which creates a new sorted set with the same elements as its
74.70 + * argument, sorted according to the natural ordering of the elements.
74.71 + * 4) A constructor with a single argument of type <tt>SortedSet</tt>,
74.72 + * which creates a new sorted set with the same elements and the same
74.73 + * ordering as the input sorted set. There is no way to enforce this
74.74 + * recommendation, as interfaces cannot contain constructors.
74.75 + *
74.76 + * <p>Note: several methods return subsets with restricted ranges.
74.77 + * Such ranges are <i>half-open</i>, that is, they include their low
74.78 + * endpoint but not their high endpoint (where applicable).
74.79 + * If you need a <i>closed range</i> (which includes both endpoints), and
74.80 + * the element type allows for calculation of the successor of a given
74.81 + * value, merely request the subrange from <tt>lowEndpoint</tt> to
74.82 + * <tt>successor(highEndpoint)</tt>. For example, suppose that <tt>s</tt>
74.83 + * is a sorted set of strings. The following idiom obtains a view
74.84 + * containing all of the strings in <tt>s</tt> from <tt>low</tt> to
74.85 + * <tt>high</tt>, inclusive:<pre>
74.86 + * SortedSet<String> sub = s.subSet(low, high+"\0");</pre>
74.87 + *
74.88 + * A similar technique can be used to generate an <i>open range</i> (which
74.89 + * contains neither endpoint). The following idiom obtains a view
74.90 + * containing all of the Strings in <tt>s</tt> from <tt>low</tt> to
74.91 + * <tt>high</tt>, exclusive:<pre>
74.92 + * SortedSet<String> sub = s.subSet(low+"\0", high);</pre>
74.93 + *
74.94 + * <p>This interface is a member of the
74.95 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
74.96 + * Java Collections Framework</a>.
74.97 + *
74.98 + * @param <E> the type of elements maintained by this set
74.99 + *
74.100 + * @author Josh Bloch
74.101 + * @see Set
74.102 + * @see TreeSet
74.103 + * @see SortedMap
74.104 + * @see Collection
74.105 + * @see Comparable
74.106 + * @see Comparator
74.107 + * @see ClassCastException
74.108 + * @since 1.2
74.109 + */
74.110 +
74.111 +public interface SortedSet<E> extends Set<E> {
74.112 + /**
74.113 + * Returns the comparator used to order the elements in this set,
74.114 + * or <tt>null</tt> if this set uses the {@linkplain Comparable
74.115 + * natural ordering} of its elements.
74.116 + *
74.117 + * @return the comparator used to order the elements in this set,
74.118 + * or <tt>null</tt> if this set uses the natural ordering
74.119 + * of its elements
74.120 + */
74.121 + Comparator<? super E> comparator();
74.122 +
74.123 + /**
74.124 + * Returns a view of the portion of this set whose elements range
74.125 + * from <tt>fromElement</tt>, inclusive, to <tt>toElement</tt>,
74.126 + * exclusive. (If <tt>fromElement</tt> and <tt>toElement</tt> are
74.127 + * equal, the returned set is empty.) The returned set is backed
74.128 + * by this set, so changes in the returned set are reflected in
74.129 + * this set, and vice-versa. The returned set supports all
74.130 + * optional set operations that this set supports.
74.131 + *
74.132 + * <p>The returned set will throw an <tt>IllegalArgumentException</tt>
74.133 + * on an attempt to insert an element outside its range.
74.134 + *
74.135 + * @param fromElement low endpoint (inclusive) of the returned set
74.136 + * @param toElement high endpoint (exclusive) of the returned set
74.137 + * @return a view of the portion of this set whose elements range from
74.138 + * <tt>fromElement</tt>, inclusive, to <tt>toElement</tt>, exclusive
74.139 + * @throws ClassCastException if <tt>fromElement</tt> and
74.140 + * <tt>toElement</tt> cannot be compared to one another using this
74.141 + * set's comparator (or, if the set has no comparator, using
74.142 + * natural ordering). Implementations may, but are not required
74.143 + * to, throw this exception if <tt>fromElement</tt> or
74.144 + * <tt>toElement</tt> cannot be compared to elements currently in
74.145 + * the set.
74.146 + * @throws NullPointerException if <tt>fromElement</tt> or
74.147 + * <tt>toElement</tt> is null and this set does not permit null
74.148 + * elements
74.149 + * @throws IllegalArgumentException if <tt>fromElement</tt> is
74.150 + * greater than <tt>toElement</tt>; or if this set itself
74.151 + * has a restricted range, and <tt>fromElement</tt> or
74.152 + * <tt>toElement</tt> lies outside the bounds of the range
74.153 + */
74.154 + SortedSet<E> subSet(E fromElement, E toElement);
74.155 +
74.156 + /**
74.157 + * Returns a view of the portion of this set whose elements are
74.158 + * strictly less than <tt>toElement</tt>. The returned set is
74.159 + * backed by this set, so changes in the returned set are
74.160 + * reflected in this set, and vice-versa. The returned set
74.161 + * supports all optional set operations that this set supports.
74.162 + *
74.163 + * <p>The returned set will throw an <tt>IllegalArgumentException</tt>
74.164 + * on an attempt to insert an element outside its range.
74.165 + *
74.166 + * @param toElement high endpoint (exclusive) of the returned set
74.167 + * @return a view of the portion of this set whose elements are strictly
74.168 + * less than <tt>toElement</tt>
74.169 + * @throws ClassCastException if <tt>toElement</tt> is not compatible
74.170 + * with this set's comparator (or, if the set has no comparator,
74.171 + * if <tt>toElement</tt> does not implement {@link Comparable}).
74.172 + * Implementations may, but are not required to, throw this
74.173 + * exception if <tt>toElement</tt> cannot be compared to elements
74.174 + * currently in the set.
74.175 + * @throws NullPointerException if <tt>toElement</tt> is null and
74.176 + * this set does not permit null elements
74.177 + * @throws IllegalArgumentException if this set itself has a
74.178 + * restricted range, and <tt>toElement</tt> lies outside the
74.179 + * bounds of the range
74.180 + */
74.181 + SortedSet<E> headSet(E toElement);
74.182 +
74.183 + /**
74.184 + * Returns a view of the portion of this set whose elements are
74.185 + * greater than or equal to <tt>fromElement</tt>. The returned
74.186 + * set is backed by this set, so changes in the returned set are
74.187 + * reflected in this set, and vice-versa. The returned set
74.188 + * supports all optional set operations that this set supports.
74.189 + *
74.190 + * <p>The returned set will throw an <tt>IllegalArgumentException</tt>
74.191 + * on an attempt to insert an element outside its range.
74.192 + *
74.193 + * @param fromElement low endpoint (inclusive) of the returned set
74.194 + * @return a view of the portion of this set whose elements are greater
74.195 + * than or equal to <tt>fromElement</tt>
74.196 + * @throws ClassCastException if <tt>fromElement</tt> is not compatible
74.197 + * with this set's comparator (or, if the set has no comparator,
74.198 + * if <tt>fromElement</tt> does not implement {@link Comparable}).
74.199 + * Implementations may, but are not required to, throw this
74.200 + * exception if <tt>fromElement</tt> cannot be compared to elements
74.201 + * currently in the set.
74.202 + * @throws NullPointerException if <tt>fromElement</tt> is null
74.203 + * and this set does not permit null elements
74.204 + * @throws IllegalArgumentException if this set itself has a
74.205 + * restricted range, and <tt>fromElement</tt> lies outside the
74.206 + * bounds of the range
74.207 + */
74.208 + SortedSet<E> tailSet(E fromElement);
74.209 +
74.210 + /**
74.211 + * Returns the first (lowest) element currently in this set.
74.212 + *
74.213 + * @return the first (lowest) element currently in this set
74.214 + * @throws NoSuchElementException if this set is empty
74.215 + */
74.216 + E first();
74.217 +
74.218 + /**
74.219 + * Returns the last (highest) element currently in this set.
74.220 + *
74.221 + * @return the last (highest) element currently in this set
74.222 + * @throws NoSuchElementException if this set is empty
74.223 + */
74.224 + E last();
74.225 +}
75.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
75.2 +++ b/emul/compact/src/main/java/java/util/Stack.java Sun Feb 17 17:58:34 2013 +0100
75.3 @@ -0,0 +1,141 @@
75.4 +/*
75.5 + * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
75.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
75.7 + *
75.8 + * This code is free software; you can redistribute it and/or modify it
75.9 + * under the terms of the GNU General Public License version 2 only, as
75.10 + * published by the Free Software Foundation. Oracle designates this
75.11 + * particular file as subject to the "Classpath" exception as provided
75.12 + * by Oracle in the LICENSE file that accompanied this code.
75.13 + *
75.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
75.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
75.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
75.17 + * version 2 for more details (a copy is included in the LICENSE file that
75.18 + * accompanied this code).
75.19 + *
75.20 + * You should have received a copy of the GNU General Public License version
75.21 + * 2 along with this work; if not, write to the Free Software Foundation,
75.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
75.23 + *
75.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
75.25 + * or visit www.oracle.com if you need additional information or have any
75.26 + * questions.
75.27 + */
75.28 +
75.29 +package java.util;
75.30 +
75.31 +/**
75.32 + * The <code>Stack</code> class represents a last-in-first-out
75.33 + * (LIFO) stack of objects. It extends class <tt>Vector</tt> with five
75.34 + * operations that allow a vector to be treated as a stack. The usual
75.35 + * <tt>push</tt> and <tt>pop</tt> operations are provided, as well as a
75.36 + * method to <tt>peek</tt> at the top item on the stack, a method to test
75.37 + * for whether the stack is <tt>empty</tt>, and a method to <tt>search</tt>
75.38 + * the stack for an item and discover how far it is from the top.
75.39 + * <p>
75.40 + * When a stack is first created, it contains no items.
75.41 + *
75.42 + * <p>A more complete and consistent set of LIFO stack operations is
75.43 + * provided by the {@link Deque} interface and its implementations, which
75.44 + * should be used in preference to this class. For example:
75.45 + * <pre> {@code
75.46 + * Deque<Integer> stack = new ArrayDeque<Integer>();}</pre>
75.47 + *
75.48 + * @author Jonathan Payne
75.49 + * @since JDK1.0
75.50 + */
75.51 +public
75.52 +class Stack<E> extends Vector<E> {
75.53 + /**
75.54 + * Creates an empty Stack.
75.55 + */
75.56 + public Stack() {
75.57 + }
75.58 +
75.59 + /**
75.60 + * Pushes an item onto the top of this stack. This has exactly
75.61 + * the same effect as:
75.62 + * <blockquote><pre>
75.63 + * addElement(item)</pre></blockquote>
75.64 + *
75.65 + * @param item the item to be pushed onto this stack.
75.66 + * @return the <code>item</code> argument.
75.67 + * @see java.util.Vector#addElement
75.68 + */
75.69 + public E push(E item) {
75.70 + addElement(item);
75.71 +
75.72 + return item;
75.73 + }
75.74 +
75.75 + /**
75.76 + * Removes the object at the top of this stack and returns that
75.77 + * object as the value of this function.
75.78 + *
75.79 + * @return The object at the top of this stack (the last item
75.80 + * of the <tt>Vector</tt> object).
75.81 + * @throws EmptyStackException if this stack is empty.
75.82 + */
75.83 + public synchronized E pop() {
75.84 + E obj;
75.85 + int len = size();
75.86 +
75.87 + obj = peek();
75.88 + removeElementAt(len - 1);
75.89 +
75.90 + return obj;
75.91 + }
75.92 +
75.93 + /**
75.94 + * Looks at the object at the top of this stack without removing it
75.95 + * from the stack.
75.96 + *
75.97 + * @return the object at the top of this stack (the last item
75.98 + * of the <tt>Vector</tt> object).
75.99 + * @throws EmptyStackException if this stack is empty.
75.100 + */
75.101 + public synchronized E peek() {
75.102 + int len = size();
75.103 +
75.104 + if (len == 0)
75.105 + throw new EmptyStackException();
75.106 + return elementAt(len - 1);
75.107 + }
75.108 +
75.109 + /**
75.110 + * Tests if this stack is empty.
75.111 + *
75.112 + * @return <code>true</code> if and only if this stack contains
75.113 + * no items; <code>false</code> otherwise.
75.114 + */
75.115 + public boolean empty() {
75.116 + return size() == 0;
75.117 + }
75.118 +
75.119 + /**
75.120 + * Returns the 1-based position where an object is on this stack.
75.121 + * If the object <tt>o</tt> occurs as an item in this stack, this
75.122 + * method returns the distance from the top of the stack of the
75.123 + * occurrence nearest the top of the stack; the topmost item on the
75.124 + * stack is considered to be at distance <tt>1</tt>. The <tt>equals</tt>
75.125 + * method is used to compare <tt>o</tt> to the
75.126 + * items in this stack.
75.127 + *
75.128 + * @param o the desired object.
75.129 + * @return the 1-based position from the top of the stack where
75.130 + * the object is located; the return value <code>-1</code>
75.131 + * indicates that the object is not on the stack.
75.132 + */
75.133 + public synchronized int search(Object o) {
75.134 + int i = lastIndexOf(o);
75.135 +
75.136 + if (i >= 0) {
75.137 + return size() - i;
75.138 + }
75.139 + return -1;
75.140 + }
75.141 +
75.142 + /** use serialVersionUID from JDK 1.0.2 for interoperability */
75.143 + private static final long serialVersionUID = 1224463164541339165L;
75.144 +}
76.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
76.2 +++ b/emul/compact/src/main/java/java/util/StringTokenizer.java Sun Feb 17 17:58:34 2013 +0100
76.3 @@ -0,0 +1,431 @@
76.4 +/*
76.5 + * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.
76.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
76.7 + *
76.8 + * This code is free software; you can redistribute it and/or modify it
76.9 + * under the terms of the GNU General Public License version 2 only, as
76.10 + * published by the Free Software Foundation. Oracle designates this
76.11 + * particular file as subject to the "Classpath" exception as provided
76.12 + * by Oracle in the LICENSE file that accompanied this code.
76.13 + *
76.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
76.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
76.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
76.17 + * version 2 for more details (a copy is included in the LICENSE file that
76.18 + * accompanied this code).
76.19 + *
76.20 + * You should have received a copy of the GNU General Public License version
76.21 + * 2 along with this work; if not, write to the Free Software Foundation,
76.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
76.23 + *
76.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
76.25 + * or visit www.oracle.com if you need additional information or have any
76.26 + * questions.
76.27 + */
76.28 +
76.29 +package java.util;
76.30 +
76.31 +import java.lang.*;
76.32 +
76.33 +/**
76.34 + * The string tokenizer class allows an application to break a
76.35 + * string into tokens. The tokenization method is much simpler than
76.36 + * the one used by the <code>StreamTokenizer</code> class. The
76.37 + * <code>StringTokenizer</code> methods do not distinguish among
76.38 + * identifiers, numbers, and quoted strings, nor do they recognize
76.39 + * and skip comments.
76.40 + * <p>
76.41 + * The set of delimiters (the characters that separate tokens) may
76.42 + * be specified either at creation time or on a per-token basis.
76.43 + * <p>
76.44 + * An instance of <code>StringTokenizer</code> behaves in one of two
76.45 + * ways, depending on whether it was created with the
76.46 + * <code>returnDelims</code> flag having the value <code>true</code>
76.47 + * or <code>false</code>:
76.48 + * <ul>
76.49 + * <li>If the flag is <code>false</code>, delimiter characters serve to
76.50 + * separate tokens. A token is a maximal sequence of consecutive
76.51 + * characters that are not delimiters.
76.52 + * <li>If the flag is <code>true</code>, delimiter characters are themselves
76.53 + * considered to be tokens. A token is thus either one delimiter
76.54 + * character, or a maximal sequence of consecutive characters that are
76.55 + * not delimiters.
76.56 + * </ul><p>
76.57 + * A <tt>StringTokenizer</tt> object internally maintains a current
76.58 + * position within the string to be tokenized. Some operations advance this
76.59 + * current position past the characters processed.<p>
76.60 + * A token is returned by taking a substring of the string that was used to
76.61 + * create the <tt>StringTokenizer</tt> object.
76.62 + * <p>
76.63 + * The following is one example of the use of the tokenizer. The code:
76.64 + * <blockquote><pre>
76.65 + * StringTokenizer st = new StringTokenizer("this is a test");
76.66 + * while (st.hasMoreTokens()) {
76.67 + * System.out.println(st.nextToken());
76.68 + * }
76.69 + * </pre></blockquote>
76.70 + * <p>
76.71 + * prints the following output:
76.72 + * <blockquote><pre>
76.73 + * this
76.74 + * is
76.75 + * a
76.76 + * test
76.77 + * </pre></blockquote>
76.78 + *
76.79 + * <p>
76.80 + * <tt>StringTokenizer</tt> is a legacy class that is retained for
76.81 + * compatibility reasons although its use is discouraged in new code. It is
76.82 + * recommended that anyone seeking this functionality use the <tt>split</tt>
76.83 + * method of <tt>String</tt> or the java.util.regex package instead.
76.84 + * <p>
76.85 + * The following example illustrates how the <tt>String.split</tt>
76.86 + * method can be used to break up a string into its basic tokens:
76.87 + * <blockquote><pre>
76.88 + * String[] result = "this is a test".split("\\s");
76.89 + * for (int x=0; x<result.length; x++)
76.90 + * System.out.println(result[x]);
76.91 + * </pre></blockquote>
76.92 + * <p>
76.93 + * prints the following output:
76.94 + * <blockquote><pre>
76.95 + * this
76.96 + * is
76.97 + * a
76.98 + * test
76.99 + * </pre></blockquote>
76.100 + *
76.101 + * @author unascribed
76.102 + * @see java.io.StreamTokenizer
76.103 + * @since JDK1.0
76.104 + */
76.105 +public
76.106 +class StringTokenizer implements Enumeration<Object> {
76.107 + private int currentPosition;
76.108 + private int newPosition;
76.109 + private int maxPosition;
76.110 + private String str;
76.111 + private String delimiters;
76.112 + private boolean retDelims;
76.113 + private boolean delimsChanged;
76.114 +
76.115 + /**
76.116 + * maxDelimCodePoint stores the value of the delimiter character with the
76.117 + * highest value. It is used to optimize the detection of delimiter
76.118 + * characters.
76.119 + *
76.120 + * It is unlikely to provide any optimization benefit in the
76.121 + * hasSurrogates case because most string characters will be
76.122 + * smaller than the limit, but we keep it so that the two code
76.123 + * paths remain similar.
76.124 + */
76.125 + private int maxDelimCodePoint;
76.126 +
76.127 + /**
76.128 + * If delimiters include any surrogates (including surrogate
76.129 + * pairs), hasSurrogates is true and the tokenizer uses the
76.130 + * different code path. This is because String.indexOf(int)
76.131 + * doesn't handle unpaired surrogates as a single character.
76.132 + */
76.133 + private boolean hasSurrogates = false;
76.134 +
76.135 + /**
76.136 + * When hasSurrogates is true, delimiters are converted to code
76.137 + * points and isDelimiter(int) is used to determine if the given
76.138 + * codepoint is a delimiter.
76.139 + */
76.140 + private int[] delimiterCodePoints;
76.141 +
76.142 + /**
76.143 + * Set maxDelimCodePoint to the highest char in the delimiter set.
76.144 + */
76.145 + private void setMaxDelimCodePoint() {
76.146 + if (delimiters == null) {
76.147 + maxDelimCodePoint = 0;
76.148 + return;
76.149 + }
76.150 +
76.151 + int m = 0;
76.152 + int c;
76.153 + int count = 0;
76.154 + for (int i = 0; i < delimiters.length(); i += Character.charCount(c)) {
76.155 + c = delimiters.charAt(i);
76.156 + if (c >= Character.MIN_HIGH_SURROGATE && c <= Character.MAX_LOW_SURROGATE) {
76.157 + c = delimiters.codePointAt(i);
76.158 + hasSurrogates = true;
76.159 + }
76.160 + if (m < c)
76.161 + m = c;
76.162 + count++;
76.163 + }
76.164 + maxDelimCodePoint = m;
76.165 +
76.166 + if (hasSurrogates) {
76.167 + delimiterCodePoints = new int[count];
76.168 + for (int i = 0, j = 0; i < count; i++, j += Character.charCount(c)) {
76.169 + c = delimiters.codePointAt(j);
76.170 + delimiterCodePoints[i] = c;
76.171 + }
76.172 + }
76.173 + }
76.174 +
76.175 + /**
76.176 + * Constructs a string tokenizer for the specified string. All
76.177 + * characters in the <code>delim</code> argument are the delimiters
76.178 + * for separating tokens.
76.179 + * <p>
76.180 + * If the <code>returnDelims</code> flag is <code>true</code>, then
76.181 + * the delimiter characters are also returned as tokens. Each
76.182 + * delimiter is returned as a string of length one. If the flag is
76.183 + * <code>false</code>, the delimiter characters are skipped and only
76.184 + * serve as separators between tokens.
76.185 + * <p>
76.186 + * Note that if <tt>delim</tt> is <tt>null</tt>, this constructor does
76.187 + * not throw an exception. However, trying to invoke other methods on the
76.188 + * resulting <tt>StringTokenizer</tt> may result in a
76.189 + * <tt>NullPointerException</tt>.
76.190 + *
76.191 + * @param str a string to be parsed.
76.192 + * @param delim the delimiters.
76.193 + * @param returnDelims flag indicating whether to return the delimiters
76.194 + * as tokens.
76.195 + * @exception NullPointerException if str is <CODE>null</CODE>
76.196 + */
76.197 + public StringTokenizer(String str, String delim, boolean returnDelims) {
76.198 + currentPosition = 0;
76.199 + newPosition = -1;
76.200 + delimsChanged = false;
76.201 + this.str = str;
76.202 + maxPosition = str.length();
76.203 + delimiters = delim;
76.204 + retDelims = returnDelims;
76.205 + setMaxDelimCodePoint();
76.206 + }
76.207 +
76.208 + /**
76.209 + * Constructs a string tokenizer for the specified string. The
76.210 + * characters in the <code>delim</code> argument are the delimiters
76.211 + * for separating tokens. Delimiter characters themselves will not
76.212 + * be treated as tokens.
76.213 + * <p>
76.214 + * Note that if <tt>delim</tt> is <tt>null</tt>, this constructor does
76.215 + * not throw an exception. However, trying to invoke other methods on the
76.216 + * resulting <tt>StringTokenizer</tt> may result in a
76.217 + * <tt>NullPointerException</tt>.
76.218 + *
76.219 + * @param str a string to be parsed.
76.220 + * @param delim the delimiters.
76.221 + * @exception NullPointerException if str is <CODE>null</CODE>
76.222 + */
76.223 + public StringTokenizer(String str, String delim) {
76.224 + this(str, delim, false);
76.225 + }
76.226 +
76.227 + /**
76.228 + * Constructs a string tokenizer for the specified string. The
76.229 + * tokenizer uses the default delimiter set, which is
76.230 + * <code>" \t\n\r\f"</code>: the space character,
76.231 + * the tab character, the newline character, the carriage-return character,
76.232 + * and the form-feed character. Delimiter characters themselves will
76.233 + * not be treated as tokens.
76.234 + *
76.235 + * @param str a string to be parsed.
76.236 + * @exception NullPointerException if str is <CODE>null</CODE>
76.237 + */
76.238 + public StringTokenizer(String str) {
76.239 + this(str, " \t\n\r\f", false);
76.240 + }
76.241 +
76.242 + /**
76.243 + * Skips delimiters starting from the specified position. If retDelims
76.244 + * is false, returns the index of the first non-delimiter character at or
76.245 + * after startPos. If retDelims is true, startPos is returned.
76.246 + */
76.247 + private int skipDelimiters(int startPos) {
76.248 + if (delimiters == null)
76.249 + throw new NullPointerException();
76.250 +
76.251 + int position = startPos;
76.252 + while (!retDelims && position < maxPosition) {
76.253 + if (!hasSurrogates) {
76.254 + char c = str.charAt(position);
76.255 + if ((c > maxDelimCodePoint) || (delimiters.indexOf(c) < 0))
76.256 + break;
76.257 + position++;
76.258 + } else {
76.259 + int c = str.codePointAt(position);
76.260 + if ((c > maxDelimCodePoint) || !isDelimiter(c)) {
76.261 + break;
76.262 + }
76.263 + position += Character.charCount(c);
76.264 + }
76.265 + }
76.266 + return position;
76.267 + }
76.268 +
76.269 + /**
76.270 + * Skips ahead from startPos and returns the index of the next delimiter
76.271 + * character encountered, or maxPosition if no such delimiter is found.
76.272 + */
76.273 + private int scanToken(int startPos) {
76.274 + int position = startPos;
76.275 + while (position < maxPosition) {
76.276 + if (!hasSurrogates) {
76.277 + char c = str.charAt(position);
76.278 + if ((c <= maxDelimCodePoint) && (delimiters.indexOf(c) >= 0))
76.279 + break;
76.280 + position++;
76.281 + } else {
76.282 + int c = str.codePointAt(position);
76.283 + if ((c <= maxDelimCodePoint) && isDelimiter(c))
76.284 + break;
76.285 + position += Character.charCount(c);
76.286 + }
76.287 + }
76.288 + if (retDelims && (startPos == position)) {
76.289 + if (!hasSurrogates) {
76.290 + char c = str.charAt(position);
76.291 + if ((c <= maxDelimCodePoint) && (delimiters.indexOf(c) >= 0))
76.292 + position++;
76.293 + } else {
76.294 + int c = str.codePointAt(position);
76.295 + if ((c <= maxDelimCodePoint) && isDelimiter(c))
76.296 + position += Character.charCount(c);
76.297 + }
76.298 + }
76.299 + return position;
76.300 + }
76.301 +
76.302 + private boolean isDelimiter(int codePoint) {
76.303 + for (int i = 0; i < delimiterCodePoints.length; i++) {
76.304 + if (delimiterCodePoints[i] == codePoint) {
76.305 + return true;
76.306 + }
76.307 + }
76.308 + return false;
76.309 + }
76.310 +
76.311 + /**
76.312 + * Tests if there are more tokens available from this tokenizer's string.
76.313 + * If this method returns <tt>true</tt>, then a subsequent call to
76.314 + * <tt>nextToken</tt> with no argument will successfully return a token.
76.315 + *
76.316 + * @return <code>true</code> if and only if there is at least one token
76.317 + * in the string after the current position; <code>false</code>
76.318 + * otherwise.
76.319 + */
76.320 + public boolean hasMoreTokens() {
76.321 + /*
76.322 + * Temporarily store this position and use it in the following
76.323 + * nextToken() method only if the delimiters haven't been changed in
76.324 + * that nextToken() invocation.
76.325 + */
76.326 + newPosition = skipDelimiters(currentPosition);
76.327 + return (newPosition < maxPosition);
76.328 + }
76.329 +
76.330 + /**
76.331 + * Returns the next token from this string tokenizer.
76.332 + *
76.333 + * @return the next token from this string tokenizer.
76.334 + * @exception NoSuchElementException if there are no more tokens in this
76.335 + * tokenizer's string.
76.336 + */
76.337 + public String nextToken() {
76.338 + /*
76.339 + * If next position already computed in hasMoreElements() and
76.340 + * delimiters have changed between the computation and this invocation,
76.341 + * then use the computed value.
76.342 + */
76.343 +
76.344 + currentPosition = (newPosition >= 0 && !delimsChanged) ?
76.345 + newPosition : skipDelimiters(currentPosition);
76.346 +
76.347 + /* Reset these anyway */
76.348 + delimsChanged = false;
76.349 + newPosition = -1;
76.350 +
76.351 + if (currentPosition >= maxPosition)
76.352 + throw new NoSuchElementException();
76.353 + int start = currentPosition;
76.354 + currentPosition = scanToken(currentPosition);
76.355 + return str.substring(start, currentPosition);
76.356 + }
76.357 +
76.358 + /**
76.359 + * Returns the next token in this string tokenizer's string. First,
76.360 + * the set of characters considered to be delimiters by this
76.361 + * <tt>StringTokenizer</tt> object is changed to be the characters in
76.362 + * the string <tt>delim</tt>. Then the next token in the string
76.363 + * after the current position is returned. The current position is
76.364 + * advanced beyond the recognized token. The new delimiter set
76.365 + * remains the default after this call.
76.366 + *
76.367 + * @param delim the new delimiters.
76.368 + * @return the next token, after switching to the new delimiter set.
76.369 + * @exception NoSuchElementException if there are no more tokens in this
76.370 + * tokenizer's string.
76.371 + * @exception NullPointerException if delim is <CODE>null</CODE>
76.372 + */
76.373 + public String nextToken(String delim) {
76.374 + delimiters = delim;
76.375 +
76.376 + /* delimiter string specified, so set the appropriate flag. */
76.377 + delimsChanged = true;
76.378 +
76.379 + setMaxDelimCodePoint();
76.380 + return nextToken();
76.381 + }
76.382 +
76.383 + /**
76.384 + * Returns the same value as the <code>hasMoreTokens</code>
76.385 + * method. It exists so that this class can implement the
76.386 + * <code>Enumeration</code> interface.
76.387 + *
76.388 + * @return <code>true</code> if there are more tokens;
76.389 + * <code>false</code> otherwise.
76.390 + * @see java.util.Enumeration
76.391 + * @see java.util.StringTokenizer#hasMoreTokens()
76.392 + */
76.393 + public boolean hasMoreElements() {
76.394 + return hasMoreTokens();
76.395 + }
76.396 +
76.397 + /**
76.398 + * Returns the same value as the <code>nextToken</code> method,
76.399 + * except that its declared return value is <code>Object</code> rather than
76.400 + * <code>String</code>. It exists so that this class can implement the
76.401 + * <code>Enumeration</code> interface.
76.402 + *
76.403 + * @return the next token in the string.
76.404 + * @exception NoSuchElementException if there are no more tokens in this
76.405 + * tokenizer's string.
76.406 + * @see java.util.Enumeration
76.407 + * @see java.util.StringTokenizer#nextToken()
76.408 + */
76.409 + public Object nextElement() {
76.410 + return nextToken();
76.411 + }
76.412 +
76.413 + /**
76.414 + * Calculates the number of times that this tokenizer's
76.415 + * <code>nextToken</code> method can be called before it generates an
76.416 + * exception. The current position is not advanced.
76.417 + *
76.418 + * @return the number of tokens remaining in the string using the current
76.419 + * delimiter set.
76.420 + * @see java.util.StringTokenizer#nextToken()
76.421 + */
76.422 + public int countTokens() {
76.423 + int count = 0;
76.424 + int currpos = currentPosition;
76.425 + while (currpos < maxPosition) {
76.426 + currpos = skipDelimiters(currpos);
76.427 + if (currpos >= maxPosition)
76.428 + break;
76.429 + currpos = scanToken(currpos);
76.430 + count++;
76.431 + }
76.432 + return count;
76.433 + }
76.434 +}
77.1 --- a/emul/compact/src/main/java/java/util/TimSort.java Fri Jan 25 15:08:24 2013 +0100
77.2 +++ b/emul/compact/src/main/java/java/util/TimSort.java Sun Feb 17 17:58:34 2013 +0100
77.3 @@ -25,7 +25,6 @@
77.4
77.5 package java.util;
77.6
77.7 -import org.apidesign.bck2brwsr.emul.lang.System;
77.8
77.9 /**
77.10 * A stable, adaptive, iterative mergesort that requires far fewer than
78.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
78.2 +++ b/emul/compact/src/main/java/java/util/Vector.java Sun Feb 17 17:58:34 2013 +0100
78.3 @@ -0,0 +1,1194 @@
78.4 +/*
78.5 + * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
78.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
78.7 + *
78.8 + * This code is free software; you can redistribute it and/or modify it
78.9 + * under the terms of the GNU General Public License version 2 only, as
78.10 + * published by the Free Software Foundation. Oracle designates this
78.11 + * particular file as subject to the "Classpath" exception as provided
78.12 + * by Oracle in the LICENSE file that accompanied this code.
78.13 + *
78.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
78.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
78.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
78.17 + * version 2 for more details (a copy is included in the LICENSE file that
78.18 + * accompanied this code).
78.19 + *
78.20 + * You should have received a copy of the GNU General Public License version
78.21 + * 2 along with this work; if not, write to the Free Software Foundation,
78.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
78.23 + *
78.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
78.25 + * or visit www.oracle.com if you need additional information or have any
78.26 + * questions.
78.27 + */
78.28 +
78.29 +package java.util;
78.30 +
78.31 +
78.32 +/**
78.33 + * The {@code Vector} class implements a growable array of
78.34 + * objects. Like an array, it contains components that can be
78.35 + * accessed using an integer index. However, the size of a
78.36 + * {@code Vector} can grow or shrink as needed to accommodate
78.37 + * adding and removing items after the {@code Vector} has been created.
78.38 + *
78.39 + * <p>Each vector tries to optimize storage management by maintaining a
78.40 + * {@code capacity} and a {@code capacityIncrement}. The
78.41 + * {@code capacity} is always at least as large as the vector
78.42 + * size; it is usually larger because as components are added to the
78.43 + * vector, the vector's storage increases in chunks the size of
78.44 + * {@code capacityIncrement}. An application can increase the
78.45 + * capacity of a vector before inserting a large number of
78.46 + * components; this reduces the amount of incremental reallocation.
78.47 + *
78.48 + * <p><a name="fail-fast"/>
78.49 + * The iterators returned by this class's {@link #iterator() iterator} and
78.50 + * {@link #listIterator(int) listIterator} methods are <em>fail-fast</em>:
78.51 + * if the vector is structurally modified at any time after the iterator is
78.52 + * created, in any way except through the iterator's own
78.53 + * {@link ListIterator#remove() remove} or
78.54 + * {@link ListIterator#add(Object) add} methods, the iterator will throw a
78.55 + * {@link ConcurrentModificationException}. Thus, in the face of
78.56 + * concurrent modification, the iterator fails quickly and cleanly, rather
78.57 + * than risking arbitrary, non-deterministic behavior at an undetermined
78.58 + * time in the future. The {@link Enumeration Enumerations} returned by
78.59 + * the {@link #elements() elements} method are <em>not</em> fail-fast.
78.60 + *
78.61 + * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
78.62 + * as it is, generally speaking, impossible to make any hard guarantees in the
78.63 + * presence of unsynchronized concurrent modification. Fail-fast iterators
78.64 + * throw {@code ConcurrentModificationException} on a best-effort basis.
78.65 + * Therefore, it would be wrong to write a program that depended on this
78.66 + * exception for its correctness: <i>the fail-fast behavior of iterators
78.67 + * should be used only to detect bugs.</i>
78.68 + *
78.69 + * <p>As of the Java 2 platform v1.2, this class was retrofitted to
78.70 + * implement the {@link List} interface, making it a member of the
78.71 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
78.72 + * Java Collections Framework</a>. Unlike the new collection
78.73 + * implementations, {@code Vector} is synchronized. If a thread-safe
78.74 + * implementation is not needed, it is recommended to use {@link
78.75 + * ArrayList} in place of {@code Vector}.
78.76 + *
78.77 + * @author Lee Boynton
78.78 + * @author Jonathan Payne
78.79 + * @see Collection
78.80 + * @see LinkedList
78.81 + * @since JDK1.0
78.82 + */
78.83 +public class Vector<E>
78.84 + extends AbstractList<E>
78.85 + implements List<E>, RandomAccess, Cloneable, java.io.Serializable
78.86 +{
78.87 + /**
78.88 + * The array buffer into which the components of the vector are
78.89 + * stored. The capacity of the vector is the length of this array buffer,
78.90 + * and is at least large enough to contain all the vector's elements.
78.91 + *
78.92 + * <p>Any array elements following the last element in the Vector are null.
78.93 + *
78.94 + * @serial
78.95 + */
78.96 + protected Object[] elementData;
78.97 +
78.98 + /**
78.99 + * The number of valid components in this {@code Vector} object.
78.100 + * Components {@code elementData[0]} through
78.101 + * {@code elementData[elementCount-1]} are the actual items.
78.102 + *
78.103 + * @serial
78.104 + */
78.105 + protected int elementCount;
78.106 +
78.107 + /**
78.108 + * The amount by which the capacity of the vector is automatically
78.109 + * incremented when its size becomes greater than its capacity. If
78.110 + * the capacity increment is less than or equal to zero, the capacity
78.111 + * of the vector is doubled each time it needs to grow.
78.112 + *
78.113 + * @serial
78.114 + */
78.115 + protected int capacityIncrement;
78.116 +
78.117 + /** use serialVersionUID from JDK 1.0.2 for interoperability */
78.118 + private static final long serialVersionUID = -2767605614048989439L;
78.119 +
78.120 + /**
78.121 + * Constructs an empty vector with the specified initial capacity and
78.122 + * capacity increment.
78.123 + *
78.124 + * @param initialCapacity the initial capacity of the vector
78.125 + * @param capacityIncrement the amount by which the capacity is
78.126 + * increased when the vector overflows
78.127 + * @throws IllegalArgumentException if the specified initial capacity
78.128 + * is negative
78.129 + */
78.130 + public Vector(int initialCapacity, int capacityIncrement) {
78.131 + super();
78.132 + if (initialCapacity < 0)
78.133 + throw new IllegalArgumentException("Illegal Capacity: "+
78.134 + initialCapacity);
78.135 + this.elementData = new Object[initialCapacity];
78.136 + this.capacityIncrement = capacityIncrement;
78.137 + }
78.138 +
78.139 + /**
78.140 + * Constructs an empty vector with the specified initial capacity and
78.141 + * with its capacity increment equal to zero.
78.142 + *
78.143 + * @param initialCapacity the initial capacity of the vector
78.144 + * @throws IllegalArgumentException if the specified initial capacity
78.145 + * is negative
78.146 + */
78.147 + public Vector(int initialCapacity) {
78.148 + this(initialCapacity, 0);
78.149 + }
78.150 +
78.151 + /**
78.152 + * Constructs an empty vector so that its internal data array
78.153 + * has size {@code 10} and its standard capacity increment is
78.154 + * zero.
78.155 + */
78.156 + public Vector() {
78.157 + this(10);
78.158 + }
78.159 +
78.160 + /**
78.161 + * Constructs a vector containing the elements of the specified
78.162 + * collection, in the order they are returned by the collection's
78.163 + * iterator.
78.164 + *
78.165 + * @param c the collection whose elements are to be placed into this
78.166 + * vector
78.167 + * @throws NullPointerException if the specified collection is null
78.168 + * @since 1.2
78.169 + */
78.170 + public Vector(Collection<? extends E> c) {
78.171 + elementData = c.toArray();
78.172 + elementCount = elementData.length;
78.173 + // c.toArray might (incorrectly) not return Object[] (see 6260652)
78.174 + if (elementData.getClass() != Object[].class)
78.175 + elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
78.176 + }
78.177 +
78.178 + /**
78.179 + * Copies the components of this vector into the specified array.
78.180 + * The item at index {@code k} in this vector is copied into
78.181 + * component {@code k} of {@code anArray}.
78.182 + *
78.183 + * @param anArray the array into which the components get copied
78.184 + * @throws NullPointerException if the given array is null
78.185 + * @throws IndexOutOfBoundsException if the specified array is not
78.186 + * large enough to hold all the components of this vector
78.187 + * @throws ArrayStoreException if a component of this vector is not of
78.188 + * a runtime type that can be stored in the specified array
78.189 + * @see #toArray(Object[])
78.190 + */
78.191 + public synchronized void copyInto(Object[] anArray) {
78.192 + System.arraycopy(elementData, 0, anArray, 0, elementCount);
78.193 + }
78.194 +
78.195 + /**
78.196 + * Trims the capacity of this vector to be the vector's current
78.197 + * size. If the capacity of this vector is larger than its current
78.198 + * size, then the capacity is changed to equal the size by replacing
78.199 + * its internal data array, kept in the field {@code elementData},
78.200 + * with a smaller one. An application can use this operation to
78.201 + * minimize the storage of a vector.
78.202 + */
78.203 + public synchronized void trimToSize() {
78.204 + modCount++;
78.205 + int oldCapacity = elementData.length;
78.206 + if (elementCount < oldCapacity) {
78.207 + elementData = Arrays.copyOf(elementData, elementCount);
78.208 + }
78.209 + }
78.210 +
78.211 + /**
78.212 + * Increases the capacity of this vector, if necessary, to ensure
78.213 + * that it can hold at least the number of components specified by
78.214 + * the minimum capacity argument.
78.215 + *
78.216 + * <p>If the current capacity of this vector is less than
78.217 + * {@code minCapacity}, then its capacity is increased by replacing its
78.218 + * internal data array, kept in the field {@code elementData}, with a
78.219 + * larger one. The size of the new data array will be the old size plus
78.220 + * {@code capacityIncrement}, unless the value of
78.221 + * {@code capacityIncrement} is less than or equal to zero, in which case
78.222 + * the new capacity will be twice the old capacity; but if this new size
78.223 + * is still smaller than {@code minCapacity}, then the new capacity will
78.224 + * be {@code minCapacity}.
78.225 + *
78.226 + * @param minCapacity the desired minimum capacity
78.227 + */
78.228 + public synchronized void ensureCapacity(int minCapacity) {
78.229 + if (minCapacity > 0) {
78.230 + modCount++;
78.231 + ensureCapacityHelper(minCapacity);
78.232 + }
78.233 + }
78.234 +
78.235 + /**
78.236 + * This implements the unsynchronized semantics of ensureCapacity.
78.237 + * Synchronized methods in this class can internally call this
78.238 + * method for ensuring capacity without incurring the cost of an
78.239 + * extra synchronization.
78.240 + *
78.241 + * @see #ensureCapacity(int)
78.242 + */
78.243 + private void ensureCapacityHelper(int minCapacity) {
78.244 + // overflow-conscious code
78.245 + if (minCapacity - elementData.length > 0)
78.246 + grow(minCapacity);
78.247 + }
78.248 +
78.249 + /**
78.250 + * The maximum size of array to allocate.
78.251 + * Some VMs reserve some header words in an array.
78.252 + * Attempts to allocate larger arrays may result in
78.253 + * OutOfMemoryError: Requested array size exceeds VM limit
78.254 + */
78.255 + private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
78.256 +
78.257 + private void grow(int minCapacity) {
78.258 + // overflow-conscious code
78.259 + int oldCapacity = elementData.length;
78.260 + int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
78.261 + capacityIncrement : oldCapacity);
78.262 + if (newCapacity - minCapacity < 0)
78.263 + newCapacity = minCapacity;
78.264 + if (newCapacity - MAX_ARRAY_SIZE > 0)
78.265 + newCapacity = hugeCapacity(minCapacity);
78.266 + elementData = Arrays.copyOf(elementData, newCapacity);
78.267 + }
78.268 +
78.269 + private static int hugeCapacity(int minCapacity) {
78.270 + if (minCapacity < 0) // overflow
78.271 + throw new OutOfMemoryError();
78.272 + return (minCapacity > MAX_ARRAY_SIZE) ?
78.273 + Integer.MAX_VALUE :
78.274 + MAX_ARRAY_SIZE;
78.275 + }
78.276 +
78.277 + /**
78.278 + * Sets the size of this vector. If the new size is greater than the
78.279 + * current size, new {@code null} items are added to the end of
78.280 + * the vector. If the new size is less than the current size, all
78.281 + * components at index {@code newSize} and greater are discarded.
78.282 + *
78.283 + * @param newSize the new size of this vector
78.284 + * @throws ArrayIndexOutOfBoundsException if the new size is negative
78.285 + */
78.286 + public synchronized void setSize(int newSize) {
78.287 + modCount++;
78.288 + if (newSize > elementCount) {
78.289 + ensureCapacityHelper(newSize);
78.290 + } else {
78.291 + for (int i = newSize ; i < elementCount ; i++) {
78.292 + elementData[i] = null;
78.293 + }
78.294 + }
78.295 + elementCount = newSize;
78.296 + }
78.297 +
78.298 + /**
78.299 + * Returns the current capacity of this vector.
78.300 + *
78.301 + * @return the current capacity (the length of its internal
78.302 + * data array, kept in the field {@code elementData}
78.303 + * of this vector)
78.304 + */
78.305 + public synchronized int capacity() {
78.306 + return elementData.length;
78.307 + }
78.308 +
78.309 + /**
78.310 + * Returns the number of components in this vector.
78.311 + *
78.312 + * @return the number of components in this vector
78.313 + */
78.314 + public synchronized int size() {
78.315 + return elementCount;
78.316 + }
78.317 +
78.318 + /**
78.319 + * Tests if this vector has no components.
78.320 + *
78.321 + * @return {@code true} if and only if this vector has
78.322 + * no components, that is, its size is zero;
78.323 + * {@code false} otherwise.
78.324 + */
78.325 + public synchronized boolean isEmpty() {
78.326 + return elementCount == 0;
78.327 + }
78.328 +
78.329 + /**
78.330 + * Returns an enumeration of the components of this vector. The
78.331 + * returned {@code Enumeration} object will generate all items in
78.332 + * this vector. The first item generated is the item at index {@code 0},
78.333 + * then the item at index {@code 1}, and so on.
78.334 + *
78.335 + * @return an enumeration of the components of this vector
78.336 + * @see Iterator
78.337 + */
78.338 + public Enumeration<E> elements() {
78.339 + return new Enumeration<E>() {
78.340 + int count = 0;
78.341 +
78.342 + public boolean hasMoreElements() {
78.343 + return count < elementCount;
78.344 + }
78.345 +
78.346 + public E nextElement() {
78.347 + synchronized (Vector.this) {
78.348 + if (count < elementCount) {
78.349 + return elementData(count++);
78.350 + }
78.351 + }
78.352 + throw new NoSuchElementException("Vector Enumeration");
78.353 + }
78.354 + };
78.355 + }
78.356 +
78.357 + /**
78.358 + * Returns {@code true} if this vector contains the specified element.
78.359 + * More formally, returns {@code true} if and only if this vector
78.360 + * contains at least one element {@code e} such that
78.361 + * <tt>(o==null ? e==null : o.equals(e))</tt>.
78.362 + *
78.363 + * @param o element whose presence in this vector is to be tested
78.364 + * @return {@code true} if this vector contains the specified element
78.365 + */
78.366 + public boolean contains(Object o) {
78.367 + return indexOf(o, 0) >= 0;
78.368 + }
78.369 +
78.370 + /**
78.371 + * Returns the index of the first occurrence of the specified element
78.372 + * in this vector, or -1 if this vector does not contain the element.
78.373 + * More formally, returns the lowest index {@code i} such that
78.374 + * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>,
78.375 + * or -1 if there is no such index.
78.376 + *
78.377 + * @param o element to search for
78.378 + * @return the index of the first occurrence of the specified element in
78.379 + * this vector, or -1 if this vector does not contain the element
78.380 + */
78.381 + public int indexOf(Object o) {
78.382 + return indexOf(o, 0);
78.383 + }
78.384 +
78.385 + /**
78.386 + * Returns the index of the first occurrence of the specified element in
78.387 + * this vector, searching forwards from {@code index}, or returns -1 if
78.388 + * the element is not found.
78.389 + * More formally, returns the lowest index {@code i} such that
78.390 + * <tt>(i >= index && (o==null ? get(i)==null : o.equals(get(i))))</tt>,
78.391 + * or -1 if there is no such index.
78.392 + *
78.393 + * @param o element to search for
78.394 + * @param index index to start searching from
78.395 + * @return the index of the first occurrence of the element in
78.396 + * this vector at position {@code index} or later in the vector;
78.397 + * {@code -1} if the element is not found.
78.398 + * @throws IndexOutOfBoundsException if the specified index is negative
78.399 + * @see Object#equals(Object)
78.400 + */
78.401 + public synchronized int indexOf(Object o, int index) {
78.402 + if (o == null) {
78.403 + for (int i = index ; i < elementCount ; i++)
78.404 + if (elementData[i]==null)
78.405 + return i;
78.406 + } else {
78.407 + for (int i = index ; i < elementCount ; i++)
78.408 + if (o.equals(elementData[i]))
78.409 + return i;
78.410 + }
78.411 + return -1;
78.412 + }
78.413 +
78.414 + /**
78.415 + * Returns the index of the last occurrence of the specified element
78.416 + * in this vector, or -1 if this vector does not contain the element.
78.417 + * More formally, returns the highest index {@code i} such that
78.418 + * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>,
78.419 + * or -1 if there is no such index.
78.420 + *
78.421 + * @param o element to search for
78.422 + * @return the index of the last occurrence of the specified element in
78.423 + * this vector, or -1 if this vector does not contain the element
78.424 + */
78.425 + public synchronized int lastIndexOf(Object o) {
78.426 + return lastIndexOf(o, elementCount-1);
78.427 + }
78.428 +
78.429 + /**
78.430 + * Returns the index of the last occurrence of the specified element in
78.431 + * this vector, searching backwards from {@code index}, or returns -1 if
78.432 + * the element is not found.
78.433 + * More formally, returns the highest index {@code i} such that
78.434 + * <tt>(i <= index && (o==null ? get(i)==null : o.equals(get(i))))</tt>,
78.435 + * or -1 if there is no such index.
78.436 + *
78.437 + * @param o element to search for
78.438 + * @param index index to start searching backwards from
78.439 + * @return the index of the last occurrence of the element at position
78.440 + * less than or equal to {@code index} in this vector;
78.441 + * -1 if the element is not found.
78.442 + * @throws IndexOutOfBoundsException if the specified index is greater
78.443 + * than or equal to the current size of this vector
78.444 + */
78.445 + public synchronized int lastIndexOf(Object o, int index) {
78.446 + if (index >= elementCount)
78.447 + throw new IndexOutOfBoundsException(index + " >= "+ elementCount);
78.448 +
78.449 + if (o == null) {
78.450 + for (int i = index; i >= 0; i--)
78.451 + if (elementData[i]==null)
78.452 + return i;
78.453 + } else {
78.454 + for (int i = index; i >= 0; i--)
78.455 + if (o.equals(elementData[i]))
78.456 + return i;
78.457 + }
78.458 + return -1;
78.459 + }
78.460 +
78.461 + /**
78.462 + * Returns the component at the specified index.
78.463 + *
78.464 + * <p>This method is identical in functionality to the {@link #get(int)}
78.465 + * method (which is part of the {@link List} interface).
78.466 + *
78.467 + * @param index an index into this vector
78.468 + * @return the component at the specified index
78.469 + * @throws ArrayIndexOutOfBoundsException if the index is out of range
78.470 + * ({@code index < 0 || index >= size()})
78.471 + */
78.472 + public synchronized E elementAt(int index) {
78.473 + if (index >= elementCount) {
78.474 + throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
78.475 + }
78.476 +
78.477 + return elementData(index);
78.478 + }
78.479 +
78.480 + /**
78.481 + * Returns the first component (the item at index {@code 0}) of
78.482 + * this vector.
78.483 + *
78.484 + * @return the first component of this vector
78.485 + * @throws NoSuchElementException if this vector has no components
78.486 + */
78.487 + public synchronized E firstElement() {
78.488 + if (elementCount == 0) {
78.489 + throw new NoSuchElementException();
78.490 + }
78.491 + return elementData(0);
78.492 + }
78.493 +
78.494 + /**
78.495 + * Returns the last component of the vector.
78.496 + *
78.497 + * @return the last component of the vector, i.e., the component at index
78.498 + * <code>size() - 1</code>.
78.499 + * @throws NoSuchElementException if this vector is empty
78.500 + */
78.501 + public synchronized E lastElement() {
78.502 + if (elementCount == 0) {
78.503 + throw new NoSuchElementException();
78.504 + }
78.505 + return elementData(elementCount - 1);
78.506 + }
78.507 +
78.508 + /**
78.509 + * Sets the component at the specified {@code index} of this
78.510 + * vector to be the specified object. The previous component at that
78.511 + * position is discarded.
78.512 + *
78.513 + * <p>The index must be a value greater than or equal to {@code 0}
78.514 + * and less than the current size of the vector.
78.515 + *
78.516 + * <p>This method is identical in functionality to the
78.517 + * {@link #set(int, Object) set(int, E)}
78.518 + * method (which is part of the {@link List} interface). Note that the
78.519 + * {@code set} method reverses the order of the parameters, to more closely
78.520 + * match array usage. Note also that the {@code set} method returns the
78.521 + * old value that was stored at the specified position.
78.522 + *
78.523 + * @param obj what the component is to be set to
78.524 + * @param index the specified index
78.525 + * @throws ArrayIndexOutOfBoundsException if the index is out of range
78.526 + * ({@code index < 0 || index >= size()})
78.527 + */
78.528 + public synchronized void setElementAt(E obj, int index) {
78.529 + if (index >= elementCount) {
78.530 + throw new ArrayIndexOutOfBoundsException(index + " >= " +
78.531 + elementCount);
78.532 + }
78.533 + elementData[index] = obj;
78.534 + }
78.535 +
78.536 + /**
78.537 + * Deletes the component at the specified index. Each component in
78.538 + * this vector with an index greater or equal to the specified
78.539 + * {@code index} is shifted downward to have an index one
78.540 + * smaller than the value it had previously. The size of this vector
78.541 + * is decreased by {@code 1}.
78.542 + *
78.543 + * <p>The index must be a value greater than or equal to {@code 0}
78.544 + * and less than the current size of the vector.
78.545 + *
78.546 + * <p>This method is identical in functionality to the {@link #remove(int)}
78.547 + * method (which is part of the {@link List} interface). Note that the
78.548 + * {@code remove} method returns the old value that was stored at the
78.549 + * specified position.
78.550 + *
78.551 + * @param index the index of the object to remove
78.552 + * @throws ArrayIndexOutOfBoundsException if the index is out of range
78.553 + * ({@code index < 0 || index >= size()})
78.554 + */
78.555 + public synchronized void removeElementAt(int index) {
78.556 + modCount++;
78.557 + if (index >= elementCount) {
78.558 + throw new ArrayIndexOutOfBoundsException(index + " >= " +
78.559 + elementCount);
78.560 + }
78.561 + else if (index < 0) {
78.562 + throw new ArrayIndexOutOfBoundsException(index);
78.563 + }
78.564 + int j = elementCount - index - 1;
78.565 + if (j > 0) {
78.566 + System.arraycopy(elementData, index + 1, elementData, index, j);
78.567 + }
78.568 + elementCount--;
78.569 + elementData[elementCount] = null; /* to let gc do its work */
78.570 + }
78.571 +
78.572 + /**
78.573 + * Inserts the specified object as a component in this vector at the
78.574 + * specified {@code index}. Each component in this vector with
78.575 + * an index greater or equal to the specified {@code index} is
78.576 + * shifted upward to have an index one greater than the value it had
78.577 + * previously.
78.578 + *
78.579 + * <p>The index must be a value greater than or equal to {@code 0}
78.580 + * and less than or equal to the current size of the vector. (If the
78.581 + * index is equal to the current size of the vector, the new element
78.582 + * is appended to the Vector.)
78.583 + *
78.584 + * <p>This method is identical in functionality to the
78.585 + * {@link #add(int, Object) add(int, E)}
78.586 + * method (which is part of the {@link List} interface). Note that the
78.587 + * {@code add} method reverses the order of the parameters, to more closely
78.588 + * match array usage.
78.589 + *
78.590 + * @param obj the component to insert
78.591 + * @param index where to insert the new component
78.592 + * @throws ArrayIndexOutOfBoundsException if the index is out of range
78.593 + * ({@code index < 0 || index > size()})
78.594 + */
78.595 + public synchronized void insertElementAt(E obj, int index) {
78.596 + modCount++;
78.597 + if (index > elementCount) {
78.598 + throw new ArrayIndexOutOfBoundsException(index
78.599 + + " > " + elementCount);
78.600 + }
78.601 + ensureCapacityHelper(elementCount + 1);
78.602 + System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
78.603 + elementData[index] = obj;
78.604 + elementCount++;
78.605 + }
78.606 +
78.607 + /**
78.608 + * Adds the specified component to the end of this vector,
78.609 + * increasing its size by one. The capacity of this vector is
78.610 + * increased if its size becomes greater than its capacity.
78.611 + *
78.612 + * <p>This method is identical in functionality to the
78.613 + * {@link #add(Object) add(E)}
78.614 + * method (which is part of the {@link List} interface).
78.615 + *
78.616 + * @param obj the component to be added
78.617 + */
78.618 + public synchronized void addElement(E obj) {
78.619 + modCount++;
78.620 + ensureCapacityHelper(elementCount + 1);
78.621 + elementData[elementCount++] = obj;
78.622 + }
78.623 +
78.624 + /**
78.625 + * Removes the first (lowest-indexed) occurrence of the argument
78.626 + * from this vector. If the object is found in this vector, each
78.627 + * component in the vector with an index greater or equal to the
78.628 + * object's index is shifted downward to have an index one smaller
78.629 + * than the value it had previously.
78.630 + *
78.631 + * <p>This method is identical in functionality to the
78.632 + * {@link #remove(Object)} method (which is part of the
78.633 + * {@link List} interface).
78.634 + *
78.635 + * @param obj the component to be removed
78.636 + * @return {@code true} if the argument was a component of this
78.637 + * vector; {@code false} otherwise.
78.638 + */
78.639 + public synchronized boolean removeElement(Object obj) {
78.640 + modCount++;
78.641 + int i = indexOf(obj);
78.642 + if (i >= 0) {
78.643 + removeElementAt(i);
78.644 + return true;
78.645 + }
78.646 + return false;
78.647 + }
78.648 +
78.649 + /**
78.650 + * Removes all components from this vector and sets its size to zero.
78.651 + *
78.652 + * <p>This method is identical in functionality to the {@link #clear}
78.653 + * method (which is part of the {@link List} interface).
78.654 + */
78.655 + public synchronized void removeAllElements() {
78.656 + modCount++;
78.657 + // Let gc do its work
78.658 + for (int i = 0; i < elementCount; i++)
78.659 + elementData[i] = null;
78.660 +
78.661 + elementCount = 0;
78.662 + }
78.663 +
78.664 + /**
78.665 + * Returns a clone of this vector. The copy will contain a
78.666 + * reference to a clone of the internal data array, not a reference
78.667 + * to the original internal data array of this {@code Vector} object.
78.668 + *
78.669 + * @return a clone of this vector
78.670 + */
78.671 + public synchronized Object clone() {
78.672 + try {
78.673 + @SuppressWarnings("unchecked")
78.674 + Vector<E> v = (Vector<E>) super.clone();
78.675 + v.elementData = Arrays.copyOf(elementData, elementCount);
78.676 + v.modCount = 0;
78.677 + return v;
78.678 + } catch (CloneNotSupportedException e) {
78.679 + // this shouldn't happen, since we are Cloneable
78.680 + throw new InternalError();
78.681 + }
78.682 + }
78.683 +
78.684 + /**
78.685 + * Returns an array containing all of the elements in this Vector
78.686 + * in the correct order.
78.687 + *
78.688 + * @since 1.2
78.689 + */
78.690 + public synchronized Object[] toArray() {
78.691 + return Arrays.copyOf(elementData, elementCount);
78.692 + }
78.693 +
78.694 + /**
78.695 + * Returns an array containing all of the elements in this Vector in the
78.696 + * correct order; the runtime type of the returned array is that of the
78.697 + * specified array. If the Vector fits in the specified array, it is
78.698 + * returned therein. Otherwise, a new array is allocated with the runtime
78.699 + * type of the specified array and the size of this Vector.
78.700 + *
78.701 + * <p>If the Vector fits in the specified array with room to spare
78.702 + * (i.e., the array has more elements than the Vector),
78.703 + * the element in the array immediately following the end of the
78.704 + * Vector is set to null. (This is useful in determining the length
78.705 + * of the Vector <em>only</em> if the caller knows that the Vector
78.706 + * does not contain any null elements.)
78.707 + *
78.708 + * @param a the array into which the elements of the Vector are to
78.709 + * be stored, if it is big enough; otherwise, a new array of the
78.710 + * same runtime type is allocated for this purpose.
78.711 + * @return an array containing the elements of the Vector
78.712 + * @throws ArrayStoreException if the runtime type of a is not a supertype
78.713 + * of the runtime type of every element in this Vector
78.714 + * @throws NullPointerException if the given array is null
78.715 + * @since 1.2
78.716 + */
78.717 + @SuppressWarnings("unchecked")
78.718 + public synchronized <T> T[] toArray(T[] a) {
78.719 + if (a.length < elementCount)
78.720 + return (T[]) Arrays.copyOf(elementData, elementCount, a.getClass());
78.721 +
78.722 + System.arraycopy(elementData, 0, a, 0, elementCount);
78.723 +
78.724 + if (a.length > elementCount)
78.725 + a[elementCount] = null;
78.726 +
78.727 + return a;
78.728 + }
78.729 +
78.730 + // Positional Access Operations
78.731 +
78.732 + @SuppressWarnings("unchecked")
78.733 + E elementData(int index) {
78.734 + return (E) elementData[index];
78.735 + }
78.736 +
78.737 + /**
78.738 + * Returns the element at the specified position in this Vector.
78.739 + *
78.740 + * @param index index of the element to return
78.741 + * @return object at the specified index
78.742 + * @throws ArrayIndexOutOfBoundsException if the index is out of range
78.743 + * ({@code index < 0 || index >= size()})
78.744 + * @since 1.2
78.745 + */
78.746 + public synchronized E get(int index) {
78.747 + if (index >= elementCount)
78.748 + throw new ArrayIndexOutOfBoundsException(index);
78.749 +
78.750 + return elementData(index);
78.751 + }
78.752 +
78.753 + /**
78.754 + * Replaces the element at the specified position in this Vector with the
78.755 + * specified element.
78.756 + *
78.757 + * @param index index of the element to replace
78.758 + * @param element element to be stored at the specified position
78.759 + * @return the element previously at the specified position
78.760 + * @throws ArrayIndexOutOfBoundsException if the index is out of range
78.761 + * ({@code index < 0 || index >= size()})
78.762 + * @since 1.2
78.763 + */
78.764 + public synchronized E set(int index, E element) {
78.765 + if (index >= elementCount)
78.766 + throw new ArrayIndexOutOfBoundsException(index);
78.767 +
78.768 + E oldValue = elementData(index);
78.769 + elementData[index] = element;
78.770 + return oldValue;
78.771 + }
78.772 +
78.773 + /**
78.774 + * Appends the specified element to the end of this Vector.
78.775 + *
78.776 + * @param e element to be appended to this Vector
78.777 + * @return {@code true} (as specified by {@link Collection#add})
78.778 + * @since 1.2
78.779 + */
78.780 + public synchronized boolean add(E e) {
78.781 + modCount++;
78.782 + ensureCapacityHelper(elementCount + 1);
78.783 + elementData[elementCount++] = e;
78.784 + return true;
78.785 + }
78.786 +
78.787 + /**
78.788 + * Removes the first occurrence of the specified element in this Vector
78.789 + * If the Vector does not contain the element, it is unchanged. More
78.790 + * formally, removes the element with the lowest index i such that
78.791 + * {@code (o==null ? get(i)==null : o.equals(get(i)))} (if such
78.792 + * an element exists).
78.793 + *
78.794 + * @param o element to be removed from this Vector, if present
78.795 + * @return true if the Vector contained the specified element
78.796 + * @since 1.2
78.797 + */
78.798 + public boolean remove(Object o) {
78.799 + return removeElement(o);
78.800 + }
78.801 +
78.802 + /**
78.803 + * Inserts the specified element at the specified position in this Vector.
78.804 + * Shifts the element currently at that position (if any) and any
78.805 + * subsequent elements to the right (adds one to their indices).
78.806 + *
78.807 + * @param index index at which the specified element is to be inserted
78.808 + * @param element element to be inserted
78.809 + * @throws ArrayIndexOutOfBoundsException if the index is out of range
78.810 + * ({@code index < 0 || index > size()})
78.811 + * @since 1.2
78.812 + */
78.813 + public void add(int index, E element) {
78.814 + insertElementAt(element, index);
78.815 + }
78.816 +
78.817 + /**
78.818 + * Removes the element at the specified position in this Vector.
78.819 + * Shifts any subsequent elements to the left (subtracts one from their
78.820 + * indices). Returns the element that was removed from the Vector.
78.821 + *
78.822 + * @throws ArrayIndexOutOfBoundsException if the index is out of range
78.823 + * ({@code index < 0 || index >= size()})
78.824 + * @param index the index of the element to be removed
78.825 + * @return element that was removed
78.826 + * @since 1.2
78.827 + */
78.828 + public synchronized E remove(int index) {
78.829 + modCount++;
78.830 + if (index >= elementCount)
78.831 + throw new ArrayIndexOutOfBoundsException(index);
78.832 + E oldValue = elementData(index);
78.833 +
78.834 + int numMoved = elementCount - index - 1;
78.835 + if (numMoved > 0)
78.836 + System.arraycopy(elementData, index+1, elementData, index,
78.837 + numMoved);
78.838 + elementData[--elementCount] = null; // Let gc do its work
78.839 +
78.840 + return oldValue;
78.841 + }
78.842 +
78.843 + /**
78.844 + * Removes all of the elements from this Vector. The Vector will
78.845 + * be empty after this call returns (unless it throws an exception).
78.846 + *
78.847 + * @since 1.2
78.848 + */
78.849 + public void clear() {
78.850 + removeAllElements();
78.851 + }
78.852 +
78.853 + // Bulk Operations
78.854 +
78.855 + /**
78.856 + * Returns true if this Vector contains all of the elements in the
78.857 + * specified Collection.
78.858 + *
78.859 + * @param c a collection whose elements will be tested for containment
78.860 + * in this Vector
78.861 + * @return true if this Vector contains all of the elements in the
78.862 + * specified collection
78.863 + * @throws NullPointerException if the specified collection is null
78.864 + */
78.865 + public synchronized boolean containsAll(Collection<?> c) {
78.866 + return super.containsAll(c);
78.867 + }
78.868 +
78.869 + /**
78.870 + * Appends all of the elements in the specified Collection to the end of
78.871 + * this Vector, in the order that they are returned by the specified
78.872 + * Collection's Iterator. The behavior of this operation is undefined if
78.873 + * the specified Collection is modified while the operation is in progress.
78.874 + * (This implies that the behavior of this call is undefined if the
78.875 + * specified Collection is this Vector, and this Vector is nonempty.)
78.876 + *
78.877 + * @param c elements to be inserted into this Vector
78.878 + * @return {@code true} if this Vector changed as a result of the call
78.879 + * @throws NullPointerException if the specified collection is null
78.880 + * @since 1.2
78.881 + */
78.882 + public synchronized boolean addAll(Collection<? extends E> c) {
78.883 + modCount++;
78.884 + Object[] a = c.toArray();
78.885 + int numNew = a.length;
78.886 + ensureCapacityHelper(elementCount + numNew);
78.887 + System.arraycopy(a, 0, elementData, elementCount, numNew);
78.888 + elementCount += numNew;
78.889 + return numNew != 0;
78.890 + }
78.891 +
78.892 + /**
78.893 + * Removes from this Vector all of its elements that are contained in the
78.894 + * specified Collection.
78.895 + *
78.896 + * @param c a collection of elements to be removed from the Vector
78.897 + * @return true if this Vector changed as a result of the call
78.898 + * @throws ClassCastException if the types of one or more elements
78.899 + * in this vector are incompatible with the specified
78.900 + * collection
78.901 + * (<a href="Collection.html#optional-restrictions">optional</a>)
78.902 + * @throws NullPointerException if this vector contains one or more null
78.903 + * elements and the specified collection does not support null
78.904 + * elements
78.905 + * (<a href="Collection.html#optional-restrictions">optional</a>),
78.906 + * or if the specified collection is null
78.907 + * @since 1.2
78.908 + */
78.909 + public synchronized boolean removeAll(Collection<?> c) {
78.910 + return super.removeAll(c);
78.911 + }
78.912 +
78.913 + /**
78.914 + * Retains only the elements in this Vector that are contained in the
78.915 + * specified Collection. In other words, removes from this Vector all
78.916 + * of its elements that are not contained in the specified Collection.
78.917 + *
78.918 + * @param c a collection of elements to be retained in this Vector
78.919 + * (all other elements are removed)
78.920 + * @return true if this Vector changed as a result of the call
78.921 + * @throws ClassCastException if the types of one or more elements
78.922 + * in this vector are incompatible with the specified
78.923 + * collection
78.924 + * (<a href="Collection.html#optional-restrictions">optional</a>)
78.925 + * @throws NullPointerException if this vector contains one or more null
78.926 + * elements and the specified collection does not support null
78.927 + * elements
78.928 + * (<a href="Collection.html#optional-restrictions">optional</a>),
78.929 + * or if the specified collection is null
78.930 + * @since 1.2
78.931 + */
78.932 + public synchronized boolean retainAll(Collection<?> c) {
78.933 + return super.retainAll(c);
78.934 + }
78.935 +
78.936 + /**
78.937 + * Inserts all of the elements in the specified Collection into this
78.938 + * Vector at the specified position. Shifts the element currently at
78.939 + * that position (if any) and any subsequent elements to the right
78.940 + * (increases their indices). The new elements will appear in the Vector
78.941 + * in the order that they are returned by the specified Collection's
78.942 + * iterator.
78.943 + *
78.944 + * @param index index at which to insert the first element from the
78.945 + * specified collection
78.946 + * @param c elements to be inserted into this Vector
78.947 + * @return {@code true} if this Vector changed as a result of the call
78.948 + * @throws ArrayIndexOutOfBoundsException if the index is out of range
78.949 + * ({@code index < 0 || index > size()})
78.950 + * @throws NullPointerException if the specified collection is null
78.951 + * @since 1.2
78.952 + */
78.953 + public synchronized boolean addAll(int index, Collection<? extends E> c) {
78.954 + modCount++;
78.955 + if (index < 0 || index > elementCount)
78.956 + throw new ArrayIndexOutOfBoundsException(index);
78.957 +
78.958 + Object[] a = c.toArray();
78.959 + int numNew = a.length;
78.960 + ensureCapacityHelper(elementCount + numNew);
78.961 +
78.962 + int numMoved = elementCount - index;
78.963 + if (numMoved > 0)
78.964 + System.arraycopy(elementData, index, elementData, index + numNew,
78.965 + numMoved);
78.966 +
78.967 + System.arraycopy(a, 0, elementData, index, numNew);
78.968 + elementCount += numNew;
78.969 + return numNew != 0;
78.970 + }
78.971 +
78.972 + /**
78.973 + * Compares the specified Object with this Vector for equality. Returns
78.974 + * true if and only if the specified Object is also a List, both Lists
78.975 + * have the same size, and all corresponding pairs of elements in the two
78.976 + * Lists are <em>equal</em>. (Two elements {@code e1} and
78.977 + * {@code e2} are <em>equal</em> if {@code (e1==null ? e2==null :
78.978 + * e1.equals(e2))}.) In other words, two Lists are defined to be
78.979 + * equal if they contain the same elements in the same order.
78.980 + *
78.981 + * @param o the Object to be compared for equality with this Vector
78.982 + * @return true if the specified Object is equal to this Vector
78.983 + */
78.984 + public synchronized boolean equals(Object o) {
78.985 + return super.equals(o);
78.986 + }
78.987 +
78.988 + /**
78.989 + * Returns the hash code value for this Vector.
78.990 + */
78.991 + public synchronized int hashCode() {
78.992 + return super.hashCode();
78.993 + }
78.994 +
78.995 + /**
78.996 + * Returns a string representation of this Vector, containing
78.997 + * the String representation of each element.
78.998 + */
78.999 + public synchronized String toString() {
78.1000 + return super.toString();
78.1001 + }
78.1002 +
78.1003 + /**
78.1004 + * Returns a view of the portion of this List between fromIndex,
78.1005 + * inclusive, and toIndex, exclusive. (If fromIndex and toIndex are
78.1006 + * equal, the returned List is empty.) The returned List is backed by this
78.1007 + * List, so changes in the returned List are reflected in this List, and
78.1008 + * vice-versa. The returned List supports all of the optional List
78.1009 + * operations supported by this List.
78.1010 + *
78.1011 + * <p>This method eliminates the need for explicit range operations (of
78.1012 + * the sort that commonly exist for arrays). Any operation that expects
78.1013 + * a List can be used as a range operation by operating on a subList view
78.1014 + * instead of a whole List. For example, the following idiom
78.1015 + * removes a range of elements from a List:
78.1016 + * <pre>
78.1017 + * list.subList(from, to).clear();
78.1018 + * </pre>
78.1019 + * Similar idioms may be constructed for indexOf and lastIndexOf,
78.1020 + * and all of the algorithms in the Collections class can be applied to
78.1021 + * a subList.
78.1022 + *
78.1023 + * <p>The semantics of the List returned by this method become undefined if
78.1024 + * the backing list (i.e., this List) is <i>structurally modified</i> in
78.1025 + * any way other than via the returned List. (Structural modifications are
78.1026 + * those that change the size of the List, or otherwise perturb it in such
78.1027 + * a fashion that iterations in progress may yield incorrect results.)
78.1028 + *
78.1029 + * @param fromIndex low endpoint (inclusive) of the subList
78.1030 + * @param toIndex high endpoint (exclusive) of the subList
78.1031 + * @return a view of the specified range within this List
78.1032 + * @throws IndexOutOfBoundsException if an endpoint index value is out of range
78.1033 + * {@code (fromIndex < 0 || toIndex > size)}
78.1034 + * @throws IllegalArgumentException if the endpoint indices are out of order
78.1035 + * {@code (fromIndex > toIndex)}
78.1036 + */
78.1037 + public synchronized List<E> subList(int fromIndex, int toIndex) {
78.1038 + return Collections.synchronizedList(super.subList(fromIndex, toIndex),
78.1039 + this);
78.1040 + }
78.1041 +
78.1042 + /**
78.1043 + * Removes from this list all of the elements whose index is between
78.1044 + * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
78.1045 + * Shifts any succeeding elements to the left (reduces their index).
78.1046 + * This call shortens the list by {@code (toIndex - fromIndex)} elements.
78.1047 + * (If {@code toIndex==fromIndex}, this operation has no effect.)
78.1048 + */
78.1049 + protected synchronized void removeRange(int fromIndex, int toIndex) {
78.1050 + modCount++;
78.1051 + int numMoved = elementCount - toIndex;
78.1052 + System.arraycopy(elementData, toIndex, elementData, fromIndex,
78.1053 + numMoved);
78.1054 +
78.1055 + // Let gc do its work
78.1056 + int newElementCount = elementCount - (toIndex-fromIndex);
78.1057 + while (elementCount != newElementCount)
78.1058 + elementData[--elementCount] = null;
78.1059 + }
78.1060 +
78.1061 + /**
78.1062 + * Returns a list iterator over the elements in this list (in proper
78.1063 + * sequence), starting at the specified position in the list.
78.1064 + * The specified index indicates the first element that would be
78.1065 + * returned by an initial call to {@link ListIterator#next next}.
78.1066 + * An initial call to {@link ListIterator#previous previous} would
78.1067 + * return the element with the specified index minus one.
78.1068 + *
78.1069 + * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
78.1070 + *
78.1071 + * @throws IndexOutOfBoundsException {@inheritDoc}
78.1072 + */
78.1073 + public synchronized ListIterator<E> listIterator(int index) {
78.1074 + if (index < 0 || index > elementCount)
78.1075 + throw new IndexOutOfBoundsException("Index: "+index);
78.1076 + return new ListItr(index);
78.1077 + }
78.1078 +
78.1079 + /**
78.1080 + * Returns a list iterator over the elements in this list (in proper
78.1081 + * sequence).
78.1082 + *
78.1083 + * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
78.1084 + *
78.1085 + * @see #listIterator(int)
78.1086 + */
78.1087 + public synchronized ListIterator<E> listIterator() {
78.1088 + return new ListItr(0);
78.1089 + }
78.1090 +
78.1091 + /**
78.1092 + * Returns an iterator over the elements in this list in proper sequence.
78.1093 + *
78.1094 + * <p>The returned iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
78.1095 + *
78.1096 + * @return an iterator over the elements in this list in proper sequence
78.1097 + */
78.1098 + public synchronized Iterator<E> iterator() {
78.1099 + return new Itr();
78.1100 + }
78.1101 +
78.1102 + /**
78.1103 + * An optimized version of AbstractList.Itr
78.1104 + */
78.1105 + private class Itr implements Iterator<E> {
78.1106 + int cursor; // index of next element to return
78.1107 + int lastRet = -1; // index of last element returned; -1 if no such
78.1108 + int expectedModCount = modCount;
78.1109 +
78.1110 + public boolean hasNext() {
78.1111 + // Racy but within spec, since modifications are checked
78.1112 + // within or after synchronization in next/previous
78.1113 + return cursor != elementCount;
78.1114 + }
78.1115 +
78.1116 + public E next() {
78.1117 + synchronized (Vector.this) {
78.1118 + checkForComodification();
78.1119 + int i = cursor;
78.1120 + if (i >= elementCount)
78.1121 + throw new NoSuchElementException();
78.1122 + cursor = i + 1;
78.1123 + return elementData(lastRet = i);
78.1124 + }
78.1125 + }
78.1126 +
78.1127 + public void remove() {
78.1128 + if (lastRet == -1)
78.1129 + throw new IllegalStateException();
78.1130 + synchronized (Vector.this) {
78.1131 + checkForComodification();
78.1132 + Vector.this.remove(lastRet);
78.1133 + expectedModCount = modCount;
78.1134 + }
78.1135 + cursor = lastRet;
78.1136 + lastRet = -1;
78.1137 + }
78.1138 +
78.1139 + final void checkForComodification() {
78.1140 + if (modCount != expectedModCount)
78.1141 + throw new ConcurrentModificationException();
78.1142 + }
78.1143 + }
78.1144 +
78.1145 + /**
78.1146 + * An optimized version of AbstractList.ListItr
78.1147 + */
78.1148 + final class ListItr extends Itr implements ListIterator<E> {
78.1149 + ListItr(int index) {
78.1150 + super();
78.1151 + cursor = index;
78.1152 + }
78.1153 +
78.1154 + public boolean hasPrevious() {
78.1155 + return cursor != 0;
78.1156 + }
78.1157 +
78.1158 + public int nextIndex() {
78.1159 + return cursor;
78.1160 + }
78.1161 +
78.1162 + public int previousIndex() {
78.1163 + return cursor - 1;
78.1164 + }
78.1165 +
78.1166 + public E previous() {
78.1167 + synchronized (Vector.this) {
78.1168 + checkForComodification();
78.1169 + int i = cursor - 1;
78.1170 + if (i < 0)
78.1171 + throw new NoSuchElementException();
78.1172 + cursor = i;
78.1173 + return elementData(lastRet = i);
78.1174 + }
78.1175 + }
78.1176 +
78.1177 + public void set(E e) {
78.1178 + if (lastRet == -1)
78.1179 + throw new IllegalStateException();
78.1180 + synchronized (Vector.this) {
78.1181 + checkForComodification();
78.1182 + Vector.this.set(lastRet, e);
78.1183 + }
78.1184 + }
78.1185 +
78.1186 + public void add(E e) {
78.1187 + int i = cursor;
78.1188 + synchronized (Vector.this) {
78.1189 + checkForComodification();
78.1190 + Vector.this.add(i, e);
78.1191 + expectedModCount = modCount;
78.1192 + }
78.1193 + cursor = i + 1;
78.1194 + lastRet = -1;
78.1195 + }
78.1196 + }
78.1197 +}
79.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
79.2 +++ b/emul/compact/src/main/java/java/util/concurrent/Callable.java Sun Feb 17 17:58:34 2013 +0100
79.3 @@ -0,0 +1,65 @@
79.4 +/*
79.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
79.6 + *
79.7 + * This code is free software; you can redistribute it and/or modify it
79.8 + * under the terms of the GNU General Public License version 2 only, as
79.9 + * published by the Free Software Foundation. Oracle designates this
79.10 + * particular file as subject to the "Classpath" exception as provided
79.11 + * by Oracle in the LICENSE file that accompanied this code.
79.12 + *
79.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
79.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
79.15 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
79.16 + * version 2 for more details (a copy is included in the LICENSE file that
79.17 + * accompanied this code).
79.18 + *
79.19 + * You should have received a copy of the GNU General Public License version
79.20 + * 2 along with this work; if not, write to the Free Software Foundation,
79.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
79.22 + *
79.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
79.24 + * or visit www.oracle.com if you need additional information or have any
79.25 + * questions.
79.26 + */
79.27 +
79.28 +/*
79.29 + * This file is available under and governed by the GNU General Public
79.30 + * License version 2 only, as published by the Free Software Foundation.
79.31 + * However, the following notice accompanied the original version of this
79.32 + * file:
79.33 + *
79.34 + * Written by Doug Lea with assistance from members of JCP JSR-166
79.35 + * Expert Group and released to the public domain, as explained at
79.36 + * http://creativecommons.org/publicdomain/zero/1.0/
79.37 + */
79.38 +
79.39 +package java.util.concurrent;
79.40 +
79.41 +/**
79.42 + * A task that returns a result and may throw an exception.
79.43 + * Implementors define a single method with no arguments called
79.44 + * <tt>call</tt>.
79.45 + *
79.46 + * <p>The <tt>Callable</tt> interface is similar to {@link
79.47 + * java.lang.Runnable}, in that both are designed for classes whose
79.48 + * instances are potentially executed by another thread. A
79.49 + * <tt>Runnable</tt>, however, does not return a result and cannot
79.50 + * throw a checked exception.
79.51 + *
79.52 + * <p> The {@link Executors} class contains utility methods to
79.53 + * convert from other common forms to <tt>Callable</tt> classes.
79.54 + *
79.55 + * @see Executor
79.56 + * @since 1.5
79.57 + * @author Doug Lea
79.58 + * @param <V> the result type of method <tt>call</tt>
79.59 + */
79.60 +public interface Callable<V> {
79.61 + /**
79.62 + * Computes a result, or throws an exception if unable to do so.
79.63 + *
79.64 + * @return computed result
79.65 + * @throws Exception if unable to compute a result
79.66 + */
79.67 + V call() throws Exception;
79.68 +}
80.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
80.2 +++ b/emul/compact/src/main/java/java/util/concurrent/TimeUnit.java Sun Feb 17 17:58:34 2013 +0100
80.3 @@ -0,0 +1,367 @@
80.4 +/*
80.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
80.6 + *
80.7 + * This code is free software; you can redistribute it and/or modify it
80.8 + * under the terms of the GNU General Public License version 2 only, as
80.9 + * published by the Free Software Foundation. Oracle designates this
80.10 + * particular file as subject to the "Classpath" exception as provided
80.11 + * by Oracle in the LICENSE file that accompanied this code.
80.12 + *
80.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
80.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
80.15 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
80.16 + * version 2 for more details (a copy is included in the LICENSE file that
80.17 + * accompanied this code).
80.18 + *
80.19 + * You should have received a copy of the GNU General Public License version
80.20 + * 2 along with this work; if not, write to the Free Software Foundation,
80.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
80.22 + *
80.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
80.24 + * or visit www.oracle.com if you need additional information or have any
80.25 + * questions.
80.26 + */
80.27 +
80.28 +/*
80.29 + * This file is available under and governed by the GNU General Public
80.30 + * License version 2 only, as published by the Free Software Foundation.
80.31 + * However, the following notice accompanied the original version of this
80.32 + * file:
80.33 + *
80.34 + * Written by Doug Lea with assistance from members of JCP JSR-166
80.35 + * Expert Group and released to the public domain, as explained at
80.36 + * http://creativecommons.org/publicdomain/zero/1.0/
80.37 + */
80.38 +
80.39 +package java.util.concurrent;
80.40 +
80.41 +/**
80.42 + * A <tt>TimeUnit</tt> represents time durations at a given unit of
80.43 + * granularity and provides utility methods to convert across units,
80.44 + * and to perform timing and delay operations in these units. A
80.45 + * <tt>TimeUnit</tt> does not maintain time information, but only
80.46 + * helps organize and use time representations that may be maintained
80.47 + * separately across various contexts. A nanosecond is defined as one
80.48 + * thousandth of a microsecond, a microsecond as one thousandth of a
80.49 + * millisecond, a millisecond as one thousandth of a second, a minute
80.50 + * as sixty seconds, an hour as sixty minutes, and a day as twenty four
80.51 + * hours.
80.52 + *
80.53 + * <p>A <tt>TimeUnit</tt> is mainly used to inform time-based methods
80.54 + * how a given timing parameter should be interpreted. For example,
80.55 + * the following code will timeout in 50 milliseconds if the {@link
80.56 + * java.util.concurrent.locks.Lock lock} is not available:
80.57 + *
80.58 + * <pre> Lock lock = ...;
80.59 + * if (lock.tryLock(50L, TimeUnit.MILLISECONDS)) ...
80.60 + * </pre>
80.61 + * while this code will timeout in 50 seconds:
80.62 + * <pre>
80.63 + * Lock lock = ...;
80.64 + * if (lock.tryLock(50L, TimeUnit.SECONDS)) ...
80.65 + * </pre>
80.66 + *
80.67 + * Note however, that there is no guarantee that a particular timeout
80.68 + * implementation will be able to notice the passage of time at the
80.69 + * same granularity as the given <tt>TimeUnit</tt>.
80.70 + *
80.71 + * @since 1.5
80.72 + * @author Doug Lea
80.73 + */
80.74 +public enum TimeUnit {
80.75 + NANOSECONDS {
80.76 + public long toNanos(long d) { return d; }
80.77 + public long toMicros(long d) { return d/(C1/C0); }
80.78 + public long toMillis(long d) { return d/(C2/C0); }
80.79 + public long toSeconds(long d) { return d/(C3/C0); }
80.80 + public long toMinutes(long d) { return d/(C4/C0); }
80.81 + public long toHours(long d) { return d/(C5/C0); }
80.82 + public long toDays(long d) { return d/(C6/C0); }
80.83 + public long convert(long d, TimeUnit u) { return u.toNanos(d); }
80.84 + int excessNanos(long d, long m) { return (int)(d - (m*C2)); }
80.85 + },
80.86 + MICROSECONDS {
80.87 + public long toNanos(long d) { return x(d, C1/C0, MAX/(C1/C0)); }
80.88 + public long toMicros(long d) { return d; }
80.89 + public long toMillis(long d) { return d/(C2/C1); }
80.90 + public long toSeconds(long d) { return d/(C3/C1); }
80.91 + public long toMinutes(long d) { return d/(C4/C1); }
80.92 + public long toHours(long d) { return d/(C5/C1); }
80.93 + public long toDays(long d) { return d/(C6/C1); }
80.94 + public long convert(long d, TimeUnit u) { return u.toMicros(d); }
80.95 + int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); }
80.96 + },
80.97 + MILLISECONDS {
80.98 + public long toNanos(long d) { return x(d, C2/C0, MAX/(C2/C0)); }
80.99 + public long toMicros(long d) { return x(d, C2/C1, MAX/(C2/C1)); }
80.100 + public long toMillis(long d) { return d; }
80.101 + public long toSeconds(long d) { return d/(C3/C2); }
80.102 + public long toMinutes(long d) { return d/(C4/C2); }
80.103 + public long toHours(long d) { return d/(C5/C2); }
80.104 + public long toDays(long d) { return d/(C6/C2); }
80.105 + public long convert(long d, TimeUnit u) { return u.toMillis(d); }
80.106 + int excessNanos(long d, long m) { return 0; }
80.107 + },
80.108 + SECONDS {
80.109 + public long toNanos(long d) { return x(d, C3/C0, MAX/(C3/C0)); }
80.110 + public long toMicros(long d) { return x(d, C3/C1, MAX/(C3/C1)); }
80.111 + public long toMillis(long d) { return x(d, C3/C2, MAX/(C3/C2)); }
80.112 + public long toSeconds(long d) { return d; }
80.113 + public long toMinutes(long d) { return d/(C4/C3); }
80.114 + public long toHours(long d) { return d/(C5/C3); }
80.115 + public long toDays(long d) { return d/(C6/C3); }
80.116 + public long convert(long d, TimeUnit u) { return u.toSeconds(d); }
80.117 + int excessNanos(long d, long m) { return 0; }
80.118 + },
80.119 + MINUTES {
80.120 + public long toNanos(long d) { return x(d, C4/C0, MAX/(C4/C0)); }
80.121 + public long toMicros(long d) { return x(d, C4/C1, MAX/(C4/C1)); }
80.122 + public long toMillis(long d) { return x(d, C4/C2, MAX/(C4/C2)); }
80.123 + public long toSeconds(long d) { return x(d, C4/C3, MAX/(C4/C3)); }
80.124 + public long toMinutes(long d) { return d; }
80.125 + public long toHours(long d) { return d/(C5/C4); }
80.126 + public long toDays(long d) { return d/(C6/C4); }
80.127 + public long convert(long d, TimeUnit u) { return u.toMinutes(d); }
80.128 + int excessNanos(long d, long m) { return 0; }
80.129 + },
80.130 + HOURS {
80.131 + public long toNanos(long d) { return x(d, C5/C0, MAX/(C5/C0)); }
80.132 + public long toMicros(long d) { return x(d, C5/C1, MAX/(C5/C1)); }
80.133 + public long toMillis(long d) { return x(d, C5/C2, MAX/(C5/C2)); }
80.134 + public long toSeconds(long d) { return x(d, C5/C3, MAX/(C5/C3)); }
80.135 + public long toMinutes(long d) { return x(d, C5/C4, MAX/(C5/C4)); }
80.136 + public long toHours(long d) { return d; }
80.137 + public long toDays(long d) { return d/(C6/C5); }
80.138 + public long convert(long d, TimeUnit u) { return u.toHours(d); }
80.139 + int excessNanos(long d, long m) { return 0; }
80.140 + },
80.141 + DAYS {
80.142 + public long toNanos(long d) { return x(d, C6/C0, MAX/(C6/C0)); }
80.143 + public long toMicros(long d) { return x(d, C6/C1, MAX/(C6/C1)); }
80.144 + public long toMillis(long d) { return x(d, C6/C2, MAX/(C6/C2)); }
80.145 + public long toSeconds(long d) { return x(d, C6/C3, MAX/(C6/C3)); }
80.146 + public long toMinutes(long d) { return x(d, C6/C4, MAX/(C6/C4)); }
80.147 + public long toHours(long d) { return x(d, C6/C5, MAX/(C6/C5)); }
80.148 + public long toDays(long d) { return d; }
80.149 + public long convert(long d, TimeUnit u) { return u.toDays(d); }
80.150 + int excessNanos(long d, long m) { return 0; }
80.151 + };
80.152 +
80.153 + // Handy constants for conversion methods
80.154 + static final long C0 = 1L;
80.155 + static final long C1 = C0 * 1000L;
80.156 + static final long C2 = C1 * 1000L;
80.157 + static final long C3 = C2 * 1000L;
80.158 + static final long C4 = C3 * 60L;
80.159 + static final long C5 = C4 * 60L;
80.160 + static final long C6 = C5 * 24L;
80.161 +
80.162 + static final long MAX = Long.MAX_VALUE;
80.163 +
80.164 + /**
80.165 + * Scale d by m, checking for overflow.
80.166 + * This has a short name to make above code more readable.
80.167 + */
80.168 + static long x(long d, long m, long over) {
80.169 + if (d > over) return Long.MAX_VALUE;
80.170 + if (d < -over) return Long.MIN_VALUE;
80.171 + return d * m;
80.172 + }
80.173 +
80.174 + // To maintain full signature compatibility with 1.5, and to improve the
80.175 + // clarity of the generated javadoc (see 6287639: Abstract methods in
80.176 + // enum classes should not be listed as abstract), method convert
80.177 + // etc. are not declared abstract but otherwise act as abstract methods.
80.178 +
80.179 + /**
80.180 + * Convert the given time duration in the given unit to this
80.181 + * unit. Conversions from finer to coarser granularities
80.182 + * truncate, so lose precision. For example converting
80.183 + * <tt>999</tt> milliseconds to seconds results in
80.184 + * <tt>0</tt>. Conversions from coarser to finer granularities
80.185 + * with arguments that would numerically overflow saturate to
80.186 + * <tt>Long.MIN_VALUE</tt> if negative or <tt>Long.MAX_VALUE</tt>
80.187 + * if positive.
80.188 + *
80.189 + * <p>For example, to convert 10 minutes to milliseconds, use:
80.190 + * <tt>TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)</tt>
80.191 + *
80.192 + * @param sourceDuration the time duration in the given <tt>sourceUnit</tt>
80.193 + * @param sourceUnit the unit of the <tt>sourceDuration</tt> argument
80.194 + * @return the converted duration in this unit,
80.195 + * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
80.196 + * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
80.197 + */
80.198 + public long convert(long sourceDuration, TimeUnit sourceUnit) {
80.199 + throw new AbstractMethodError();
80.200 + }
80.201 +
80.202 + /**
80.203 + * Equivalent to <tt>NANOSECONDS.convert(duration, this)</tt>.
80.204 + * @param duration the duration
80.205 + * @return the converted duration,
80.206 + * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
80.207 + * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
80.208 + * @see #convert
80.209 + */
80.210 + public long toNanos(long duration) {
80.211 + throw new AbstractMethodError();
80.212 + }
80.213 +
80.214 + /**
80.215 + * Equivalent to <tt>MICROSECONDS.convert(duration, this)</tt>.
80.216 + * @param duration the duration
80.217 + * @return the converted duration,
80.218 + * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
80.219 + * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
80.220 + * @see #convert
80.221 + */
80.222 + public long toMicros(long duration) {
80.223 + throw new AbstractMethodError();
80.224 + }
80.225 +
80.226 + /**
80.227 + * Equivalent to <tt>MILLISECONDS.convert(duration, this)</tt>.
80.228 + * @param duration the duration
80.229 + * @return the converted duration,
80.230 + * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
80.231 + * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
80.232 + * @see #convert
80.233 + */
80.234 + public long toMillis(long duration) {
80.235 + throw new AbstractMethodError();
80.236 + }
80.237 +
80.238 + /**
80.239 + * Equivalent to <tt>SECONDS.convert(duration, this)</tt>.
80.240 + * @param duration the duration
80.241 + * @return the converted duration,
80.242 + * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
80.243 + * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
80.244 + * @see #convert
80.245 + */
80.246 + public long toSeconds(long duration) {
80.247 + throw new AbstractMethodError();
80.248 + }
80.249 +
80.250 + /**
80.251 + * Equivalent to <tt>MINUTES.convert(duration, this)</tt>.
80.252 + * @param duration the duration
80.253 + * @return the converted duration,
80.254 + * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
80.255 + * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
80.256 + * @see #convert
80.257 + * @since 1.6
80.258 + */
80.259 + public long toMinutes(long duration) {
80.260 + throw new AbstractMethodError();
80.261 + }
80.262 +
80.263 + /**
80.264 + * Equivalent to <tt>HOURS.convert(duration, this)</tt>.
80.265 + * @param duration the duration
80.266 + * @return the converted duration,
80.267 + * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
80.268 + * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
80.269 + * @see #convert
80.270 + * @since 1.6
80.271 + */
80.272 + public long toHours(long duration) {
80.273 + throw new AbstractMethodError();
80.274 + }
80.275 +
80.276 + /**
80.277 + * Equivalent to <tt>DAYS.convert(duration, this)</tt>.
80.278 + * @param duration the duration
80.279 + * @return the converted duration
80.280 + * @see #convert
80.281 + * @since 1.6
80.282 + */
80.283 + public long toDays(long duration) {
80.284 + throw new AbstractMethodError();
80.285 + }
80.286 +
80.287 + /**
80.288 + * Utility to compute the excess-nanosecond argument to wait,
80.289 + * sleep, join.
80.290 + * @param d the duration
80.291 + * @param m the number of milliseconds
80.292 + * @return the number of nanoseconds
80.293 + */
80.294 + abstract int excessNanos(long d, long m);
80.295 +
80.296 + /**
80.297 + * Performs a timed {@link Object#wait(long, int) Object.wait}
80.298 + * using this time unit.
80.299 + * This is a convenience method that converts timeout arguments
80.300 + * into the form required by the <tt>Object.wait</tt> method.
80.301 + *
80.302 + * <p>For example, you could implement a blocking <tt>poll</tt>
80.303 + * method (see {@link BlockingQueue#poll BlockingQueue.poll})
80.304 + * using:
80.305 + *
80.306 + * <pre> {@code
80.307 + * public synchronized Object poll(long timeout, TimeUnit unit)
80.308 + * throws InterruptedException {
80.309 + * while (empty) {
80.310 + * unit.timedWait(this, timeout);
80.311 + * ...
80.312 + * }
80.313 + * }}</pre>
80.314 + *
80.315 + * @param obj the object to wait on
80.316 + * @param timeout the maximum time to wait. If less than
80.317 + * or equal to zero, do not wait at all.
80.318 + * @throws InterruptedException if interrupted while waiting
80.319 + */
80.320 + public void timedWait(Object obj, long timeout)
80.321 + throws InterruptedException {
80.322 + if (timeout > 0) {
80.323 + long ms = toMillis(timeout);
80.324 + int ns = excessNanos(timeout, ms);
80.325 + obj.wait(ms, ns);
80.326 + }
80.327 + }
80.328 +
80.329 + /**
80.330 + * Performs a timed {@link Thread#join(long, int) Thread.join}
80.331 + * using this time unit.
80.332 + * This is a convenience method that converts time arguments into the
80.333 + * form required by the <tt>Thread.join</tt> method.
80.334 + *
80.335 + * @param thread the thread to wait for
80.336 + * @param timeout the maximum time to wait. If less than
80.337 + * or equal to zero, do not wait at all.
80.338 + * @throws InterruptedException if interrupted while waiting
80.339 + */
80.340 +// public void timedJoin(Thread thread, long timeout)
80.341 +// throws InterruptedException {
80.342 +// if (timeout > 0) {
80.343 +// long ms = toMillis(timeout);
80.344 +// int ns = excessNanos(timeout, ms);
80.345 +// thread.join(ms, ns);
80.346 +// }
80.347 +// }
80.348 +
80.349 + /**
80.350 + * Performs a {@link Thread#sleep(long, int) Thread.sleep} using
80.351 + * this time unit.
80.352 + * This is a convenience method that converts time arguments into the
80.353 + * form required by the <tt>Thread.sleep</tt> method.
80.354 + *
80.355 + * @param timeout the minimum time to sleep. If less than
80.356 + * or equal to zero, do not sleep at all.
80.357 + * @throws InterruptedException if interrupted while sleeping
80.358 + */
80.359 + public void sleep(long timeout) throws InterruptedException {
80.360 + if (timeout > 0) {
80.361 + long ms = toMillis(timeout);
80.362 + int ns = excessNanos(timeout, ms);
80.363 + Object o = new Object();
80.364 + synchronized (o) {
80.365 + o.wait(ms, ns);
80.366 + }
80.367 + }
80.368 + }
80.369 +
80.370 +}
81.1 --- a/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/CollectionsTest.java Fri Jan 25 15:08:24 2013 +0100
81.2 +++ b/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/CollectionsTest.java Sun Feb 17 17:58:34 2013 +0100
81.3 @@ -25,6 +25,8 @@
81.4 import java.util.HashSet;
81.5 import java.util.List;
81.6 import java.util.Map;
81.7 +import java.util.Map.Entry;
81.8 +import java.util.Vector;
81.9 import org.apidesign.bck2brwsr.vmtest.Compare;
81.10 import org.apidesign.bck2brwsr.vmtest.VMTest;
81.11 import org.testng.annotations.Factory;
81.12 @@ -92,10 +94,9 @@
81.13 map.put("nine", 9);
81.14 map.put("ten", 10);
81.15
81.16 - Map.Entry<String,Integer>[] arr = map.entrySet().toArray(new Map.Entry[map.size()]);
81.17 - Arrays.sort(arr, new C());
81.18 -
81.19 - return Arrays.asList(arr).toString();
81.20 + List<Entry<String,Integer>> arr = new Vector<>();
81.21 + arr.addAll(map.entrySet());
81.22 + return arr.toString();
81.23 }
81.24
81.25 @Factory
82.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
82.2 +++ b/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/JFXIssuesTest.java Sun Feb 17 17:58:34 2013 +0100
82.3 @@ -0,0 +1,46 @@
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.compact.tck;
82.22 +
82.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
82.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
82.25 +import org.testng.annotations.Factory;
82.26 +
82.27 +
82.28 +public class JFXIssuesTest {
82.29 + private abstract class Application {
82.30 + public abstract int getID();
82.31 + }
82.32 +
82.33 + private class MyApplication extends Application {
82.34 +
82.35 + @Override
82.36 + public int getID() {
82.37 + return 1;
82.38 + }
82.39 +
82.40 + }
82.41 +
82.42 + @Compare public boolean isClassAssignable() {
82.43 + return Application.class.isAssignableFrom(MyApplication.class);
82.44 + }
82.45 +
82.46 + @Factory public static Object[] create() {
82.47 + return VMTest.create(JFXIssuesTest.class);
82.48 + }
82.49 +}
83.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
83.2 +++ b/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/RandomTest.java Sun Feb 17 17:58:34 2013 +0100
83.3 @@ -0,0 +1,40 @@
83.4 +/**
83.5 + * Back 2 Browser Bytecode Translator
83.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
83.7 + *
83.8 + * This program is free software: you can redistribute it and/or modify
83.9 + * it under the terms of the GNU General Public License as published by
83.10 + * the Free Software Foundation, version 2 of the License.
83.11 + *
83.12 + * This program is distributed in the hope that it will be useful,
83.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
83.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
83.15 + * GNU General Public License for more details.
83.16 + *
83.17 + * You should have received a copy of the GNU General Public License
83.18 + * along with this program. Look for COPYING file in the top folder.
83.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
83.20 + */
83.21 +package org.apidesign.bck2brwsr.compact.tck;
83.22 +
83.23 +import java.util.Random;
83.24 +import org.apidesign.bck2brwsr.vmtest.Compare;
83.25 +import org.apidesign.bck2brwsr.vmtest.VMTest;
83.26 +import org.testng.annotations.Factory;
83.27 +
83.28 +/**
83.29 + *
83.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
83.31 + */
83.32 +public class RandomTest {
83.33 + @Compare public boolean canInstantiateRandom() {
83.34 + Random r = new Random();
83.35 + r.nextInt();
83.36 + return r != null;
83.37 + }
83.38 +
83.39 +
83.40 + @Factory public static Object[] create() {
83.41 + return VMTest.create(RandomTest.class);
83.42 + }
83.43 +}
84.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
84.2 +++ b/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ReaderTest.java Sun Feb 17 17:58:34 2013 +0100
84.3 @@ -0,0 +1,61 @@
84.4 +/**
84.5 + * Back 2 Browser Bytecode Translator
84.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
84.7 + *
84.8 + * This program is free software: you can redistribute it and/or modify
84.9 + * it under the terms of the GNU General Public License as published by
84.10 + * the Free Software Foundation, version 2 of the License.
84.11 + *
84.12 + * This program is distributed in the hope that it will be useful,
84.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
84.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
84.15 + * GNU General Public License for more details.
84.16 + *
84.17 + * You should have received a copy of the GNU General Public License
84.18 + * along with this program. Look for COPYING file in the top folder.
84.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
84.20 + */
84.21 +package org.apidesign.bck2brwsr.compact.tck;
84.22 +
84.23 +import java.io.ByteArrayInputStream;
84.24 +import java.io.IOException;
84.25 +import java.io.InputStreamReader;
84.26 +import java.io.UnsupportedEncodingException;
84.27 +import java.util.Arrays;
84.28 +import org.apidesign.bck2brwsr.vmtest.Compare;
84.29 +import org.apidesign.bck2brwsr.vmtest.VMTest;
84.30 +import org.testng.annotations.Factory;
84.31 +
84.32 +/**
84.33 + *
84.34 + * @author Jaroslav Tulach <jtulach@netbeans.org>
84.35 + */
84.36 +public class ReaderTest {
84.37 + @Compare public String readUTFString() throws IOException {
84.38 + byte[] arr = {
84.39 + (byte)-59, (byte)-67, (byte)108, (byte)117, (byte)-59, (byte)-91,
84.40 + (byte)111, (byte)117, (byte)-60, (byte)-115, (byte)107, (byte)-61,
84.41 + (byte)-67, (byte)32, (byte)107, (byte)-59, (byte)-81, (byte)-59,
84.42 + (byte)-120
84.43 + };
84.44 + ByteArrayInputStream is = new ByteArrayInputStream(arr);
84.45 + InputStreamReader r = new InputStreamReader(is, "UTF-8");
84.46 +
84.47 + StringBuilder sb = new StringBuilder();
84.48 + for (;;) {
84.49 + int ch = r.read();
84.50 + if (ch == -1) {
84.51 + break;
84.52 + }
84.53 + sb.append((char)ch);
84.54 + }
84.55 + return sb.toString().toString();
84.56 + }
84.57 + @Compare public String stringToBytes() throws UnsupportedEncodingException {
84.58 + return Arrays.toString("\u017dlu\u0165ou\u010dk\u00fd k\u016f\u0148".getBytes("UTF-8"));
84.59 + }
84.60 +
84.61 + @Factory public static Object[] create() {
84.62 + return VMTest.create(ReaderTest.class);
84.63 + }
84.64 +}
85.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
85.2 +++ b/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ServiceLoaderTest.java Sun Feb 17 17:58:34 2013 +0100
85.3 @@ -0,0 +1,61 @@
85.4 +/**
85.5 + * Back 2 Browser Bytecode Translator
85.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
85.7 + *
85.8 + * This program is free software: you can redistribute it and/or modify
85.9 + * it under the terms of the GNU General Public License as published by
85.10 + * the Free Software Foundation, version 2 of the License.
85.11 + *
85.12 + * This program is distributed in the hope that it will be useful,
85.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
85.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
85.15 + * GNU General Public License for more details.
85.16 + *
85.17 + * You should have received a copy of the GNU General Public License
85.18 + * along with this program. Look for COPYING file in the top folder.
85.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
85.20 + */
85.21 +package org.apidesign.bck2brwsr.compact.tck;
85.22 +
85.23 +import java.io.IOException;
85.24 +import java.util.ServiceLoader;
85.25 +import org.apidesign.bck2brwsr.vmtest.Compare;
85.26 +import org.apidesign.bck2brwsr.vmtest.VMTest;
85.27 +import org.openide.util.lookup.ServiceProvider;
85.28 +import org.testng.annotations.Factory;
85.29 +
85.30 +/**
85.31 + *
85.32 + * @author Jaroslav Tulach <jtulach@netbeans.org>
85.33 + */
85.34 +public class ServiceLoaderTest {
85.35 + @Compare//(scripting = false)
85.36 + public Object findsIOException() {
85.37 +// delayStart();
85.38 + for (IOException e : ServiceLoader.load(IOException.class)) {
85.39 + return "Found service: " + e.getClass().getName();
85.40 + }
85.41 + return null;
85.42 + }
85.43 +/*
85.44 + @org.apidesign.bck2brwsr.core.JavaScriptBody(args = { "a" }, body = "alert(a);")
85.45 + private static void alert(String a) {
85.46 + }
85.47 + private void delayStart() {
85.48 + for (int i = 0; i < 10; i++) {
85.49 + alert("State: " + i);
85.50 + for (int j = 0; j < 493208409; j++) ;
85.51 + }
85.52 + }
85.53 +*/
85.54 +
85.55 + @Factory
85.56 + public static Object[] create() {
85.57 + return VMTest.create(ServiceLoaderTest.class);
85.58 + }
85.59 +
85.60 +
85.61 + @ServiceProvider(service = IOException.class)
85.62 + public static class MyException extends IOException {
85.63 + }
85.64 +}
86.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
86.2 +++ b/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ZipArchive.java Sun Feb 17 17:58:34 2013 +0100
86.3 @@ -0,0 +1,154 @@
86.4 +/**
86.5 + * Back 2 Browser Bytecode Translator
86.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
86.7 + *
86.8 + * This program is free software: you can redistribute it and/or modify
86.9 + * it under the terms of the GNU General Public License as published by
86.10 + * the Free Software Foundation, version 2 of the License.
86.11 + *
86.12 + * This program is distributed in the hope that it will be useful,
86.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
86.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
86.15 + * GNU General Public License for more details.
86.16 + *
86.17 + * You should have received a copy of the GNU General Public License
86.18 + * along with this program. Look for COPYING file in the top folder.
86.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
86.20 + */
86.21 +package org.apidesign.bck2brwsr.compact.tck;
86.22 +
86.23 +import java.io.ByteArrayOutputStream;
86.24 +import java.io.IOException;
86.25 +import java.io.InputStream;
86.26 +import java.util.Arrays;
86.27 +import java.util.LinkedHashMap;
86.28 +import java.util.Map;
86.29 +import java.util.Objects;
86.30 +import java.util.zip.ZipEntry;
86.31 +import org.apidesign.bck2brwsr.emul.zip.ZipInputStream;
86.32 +
86.33 +/**
86.34 + *
86.35 + * @author Jaroslav Tulach <jtulach@netbeans.org>
86.36 + */
86.37 +final class ZipArchive {
86.38 + private final Map<String, byte[]> entries = new LinkedHashMap<>();
86.39 +
86.40 + public static ZipArchive createZip(InputStream is) throws IOException {
86.41 + ZipArchive a = new ZipArchive();
86.42 + readZip(is, a);
86.43 + return a;
86.44 + }
86.45 +
86.46 + public static ZipArchive createReal(InputStream is) throws IOException {
86.47 + ZipArchive a = new ZipArchive();
86.48 + realZip(is, a);
86.49 + return a;
86.50 + }
86.51 +
86.52 + /**
86.53 + * Registers entry name and data
86.54 + */
86.55 + final void register(String entry, InputStream is) throws IOException {
86.56 + ByteArrayOutputStream os = new ByteArrayOutputStream();
86.57 + for (;;) {
86.58 + int ch = is.read();
86.59 + if (ch == -1) {
86.60 + break;
86.61 + }
86.62 + os.write(ch);
86.63 + }
86.64 + os.close();
86.65 + entries.put(entry, os.toByteArray());
86.66 + }
86.67 +
86.68 + @Override
86.69 + public int hashCode() {
86.70 + return entries.hashCode();
86.71 + }
86.72 +
86.73 + @Override
86.74 + public boolean equals(Object obj) {
86.75 + if (obj == null) {
86.76 + return false;
86.77 + }
86.78 + if (getClass() != obj.getClass()) {
86.79 + return false;
86.80 + }
86.81 + final ZipArchive other = (ZipArchive) obj;
86.82 + if (!Objects.deepEquals(this.entries, other.entries)) {
86.83 + return false;
86.84 + }
86.85 + return true;
86.86 + }
86.87 +
86.88 + @Override
86.89 + public String toString() {
86.90 + StringBuilder sb = new StringBuilder();
86.91 + for (Map.Entry<String, byte[]> en : entries.entrySet()) {
86.92 + String string = en.getKey();
86.93 + byte[] bs = en.getValue();
86.94 + sb.append(string).append(" = ").append(Arrays.toString(bs)).append("\n");
86.95 + }
86.96 + return sb.toString();
86.97 + }
86.98 +
86.99 + public void assertEquals(ZipArchive zip, String msg) {
86.100 + boolean ok = true;
86.101 + StringBuilder sb = new StringBuilder();
86.102 + sb.append(msg);
86.103 + for (Map.Entry<String, byte[]> en : entries.entrySet()) {
86.104 + String string = en.getKey();
86.105 + byte[] bs = en.getValue();
86.106 + byte[] other = zip.entries.get(string);
86.107 + sb.append("\n");
86.108 + if (other == null) {
86.109 + sb.append("EXTRA ").append(string).append(" = ").append(Arrays.toString(bs));
86.110 + ok = false;
86.111 + continue;
86.112 + }
86.113 + if (Arrays.equals(bs, other)) {
86.114 + sb.append("OK ").append(string);
86.115 + continue;
86.116 + } else {
86.117 + sb.append("DIFF ").append(string).append(" = ").append(Arrays.toString(bs)).append("\n");
86.118 + sb.append(" TO").append(string).append(" = ").append(Arrays.toString(other)).append("\n");
86.119 + ok = false;
86.120 + continue;
86.121 + }
86.122 + }
86.123 + for (Map.Entry<String, byte[]> entry : zip.entries.entrySet()) {
86.124 + String string = entry.getKey();
86.125 + if (entries.get(string) == null) {
86.126 + sb.append("MISS ").append(string).append(" = ").append(Arrays.toString(entry.getValue()));
86.127 + ok = false;
86.128 + }
86.129 + }
86.130 + if (!ok) {
86.131 + assert false : sb.toString();
86.132 + }
86.133 + }
86.134 +
86.135 + public static void readZip(InputStream is, ZipArchive data) throws IOException {
86.136 + ZipInputStream zip = new org.apidesign.bck2brwsr.emul.zip.ZipInputStream(is);
86.137 + for (;;) {
86.138 + ZipEntry en = zip.getNextEntry();
86.139 + if (en == null) {
86.140 + return;
86.141 + }
86.142 + data.register(en.getName(), zip);
86.143 + }
86.144 + }
86.145 +
86.146 + public static void realZip(InputStream is, ZipArchive data) throws IOException {
86.147 + java.util.zip.ZipInputStream zip = new java.util.zip.ZipInputStream(is);
86.148 + for (;;) {
86.149 + ZipEntry en = zip.getNextEntry();
86.150 + if (en == null) {
86.151 + return;
86.152 + }
86.153 + data.register(en.getName(), zip);
86.154 + }
86.155 + }
86.156 +
86.157 +}
87.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
87.2 +++ b/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ZipCompatibilityTest.java Sun Feb 17 17:58:34 2013 +0100
87.3 @@ -0,0 +1,42 @@
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.bck2brwsr.compact.tck;
87.22 +
87.23 +import java.io.IOException;
87.24 +import java.io.InputStream;
87.25 +import org.apidesign.bck2brwsr.vmtest.Compare;
87.26 +import org.apidesign.bck2brwsr.vmtest.VMTest;
87.27 +import org.testng.annotations.Factory;
87.28 +
87.29 +/**
87.30 + *
87.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
87.32 + */
87.33 +public class ZipCompatibilityTest {
87.34 + @Compare
87.35 + public String testDemoStaticCalculator() throws IOException {
87.36 + InputStream is = getClass().getResourceAsStream("demo.static.calculator-0.3-SNAPSHOT.jar");
87.37 + ZipArchive zip = ZipArchive.createZip(is);
87.38 + return zip.toString();
87.39 + }
87.40 +
87.41 + @Factory
87.42 + public static Object[] create() {
87.43 + return VMTest.create(ZipCompatibilityTest.class);
87.44 + }
87.45 +}
88.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
88.2 +++ b/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ZipVsJzLibTest.java Sun Feb 17 17:58:34 2013 +0100
88.3 @@ -0,0 +1,39 @@
88.4 +/**
88.5 + * Back 2 Browser Bytecode Translator
88.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
88.7 + *
88.8 + * This program is free software: you can redistribute it and/or modify
88.9 + * it under the terms of the GNU General Public License as published by
88.10 + * the Free Software Foundation, version 2 of the License.
88.11 + *
88.12 + * This program is distributed in the hope that it will be useful,
88.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
88.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
88.15 + * GNU General Public License for more details.
88.16 + *
88.17 + * You should have received a copy of the GNU General Public License
88.18 + * along with this program. Look for COPYING file in the top folder.
88.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
88.20 + */
88.21 +package org.apidesign.bck2brwsr.compact.tck;
88.22 +
88.23 +import java.io.IOException;
88.24 +import java.io.InputStream;
88.25 +import org.testng.annotations.Test;
88.26 +
88.27 +/**
88.28 + *
88.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
88.30 + */
88.31 +public class ZipVsJzLibTest {
88.32 + @Test public void r() throws IOException {
88.33 + InputStream is = getClass().getResourceAsStream("demo.static.calculator-0.3-SNAPSHOT.jar");
88.34 + ZipArchive zip = ZipArchive.createZip(is);
88.35 +
88.36 + is = getClass().getResourceAsStream("demo.static.calculator-0.3-SNAPSHOT.jar");
88.37 + ZipArchive real = ZipArchive.createReal(is);
88.38 +
88.39 + real.assertEquals(zip, "Are they the same?");
88.40 + }
88.41 +
88.42 +}
89.1 Binary file emul/compact/src/test/resources/org/apidesign/bck2brwsr/compact/tck/demo.static.calculator-0.3-SNAPSHOT.jar has changed
90.1 --- a/emul/mini/pom.xml Fri Jan 25 15:08:24 2013 +0100
90.2 +++ b/emul/mini/pom.xml Sun Feb 17 17:58:34 2013 +0100
90.3 @@ -22,6 +22,12 @@
90.4 <version>0.3-SNAPSHOT</version>
90.5 <type>jar</type>
90.6 </dependency>
90.7 + <dependency>
90.8 + <groupId>org.testng</groupId>
90.9 + <artifactId>testng</artifactId>
90.10 + <version>6.5.2</version>
90.11 + <scope>test</scope>
90.12 + </dependency>
90.13 </dependencies>
90.14 <build>
90.15 <plugins>
91.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
91.2 +++ b/emul/mini/src/main/java/java/lang/ArrayStoreException.java Sun Feb 17 17:58:34 2013 +0100
91.3 @@ -0,0 +1,60 @@
91.4 +/*
91.5 + * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
91.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
91.7 + *
91.8 + * This code is free software; you can redistribute it and/or modify it
91.9 + * under the terms of the GNU General Public License version 2 only, as
91.10 + * published by the Free Software Foundation. Oracle designates this
91.11 + * particular file as subject to the "Classpath" exception as provided
91.12 + * by Oracle in the LICENSE file that accompanied this code.
91.13 + *
91.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
91.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
91.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
91.17 + * version 2 for more details (a copy is included in the LICENSE file that
91.18 + * accompanied this code).
91.19 + *
91.20 + * You should have received a copy of the GNU General Public License version
91.21 + * 2 along with this work; if not, write to the Free Software Foundation,
91.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
91.23 + *
91.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
91.25 + * or visit www.oracle.com if you need additional information or have any
91.26 + * questions.
91.27 + */
91.28 +
91.29 +package java.lang;
91.30 +
91.31 +/**
91.32 + * Thrown to indicate that an attempt has been made to store the
91.33 + * wrong type of object into an array of objects. For example, the
91.34 + * following code generates an <code>ArrayStoreException</code>:
91.35 + * <p><blockquote><pre>
91.36 + * Object x[] = new String[3];
91.37 + * x[0] = new Integer(0);
91.38 + * </pre></blockquote>
91.39 + *
91.40 + * @author unascribed
91.41 + * @since JDK1.0
91.42 + */
91.43 +public
91.44 +class ArrayStoreException extends RuntimeException {
91.45 + private static final long serialVersionUID = -4522193890499838241L;
91.46 +
91.47 + /**
91.48 + * Constructs an <code>ArrayStoreException</code> with no detail message.
91.49 + */
91.50 + public ArrayStoreException() {
91.51 + super();
91.52 + }
91.53 +
91.54 + /**
91.55 + * Constructs an <code>ArrayStoreException</code> with the specified
91.56 + * detail message.
91.57 + *
91.58 + * @param s the detail message.
91.59 + */
91.60 + public ArrayStoreException(String s) {
91.61 + super(s);
91.62 + }
91.63 +}
92.1 --- a/emul/mini/src/main/java/java/lang/Character.java Fri Jan 25 15:08:24 2013 +0100
92.2 +++ b/emul/mini/src/main/java/java/lang/Character.java Sun Feb 17 17:58:34 2013 +0100
92.3 @@ -2026,7 +2026,7 @@
92.4 */
92.5 public static boolean isJavaIdentifierPart(int codePoint) {
92.6 return isJavaIdentifierStart(codePoint) ||
92.7 - ('0' <= codePoint && codePoint <= '9');
92.8 + ('0' <= codePoint && codePoint <= '9') || codePoint == '$';
92.9 }
92.10
92.11 /**
92.12 @@ -2193,6 +2193,10 @@
92.13 * @see Character#isDigit(int)
92.14 * @since 1.5
92.15 */
92.16 + @JavaScriptBody(args = { "codePoint", "radix" }, body=
92.17 + "var x = parseInt(String.fromCharCode(codePoint), radix);\n"
92.18 + + "return isNaN(x) ? -1 : x;"
92.19 + )
92.20 public static int digit(int codePoint, int radix) {
92.21 throw new UnsupportedOperationException();
92.22 }
93.1 --- a/emul/mini/src/main/java/java/lang/Class.java Fri Jan 25 15:08:24 2013 +0100
93.2 +++ b/emul/mini/src/main/java/java/lang/Class.java Sun Feb 17 17:58:34 2013 +0100
93.3 @@ -32,6 +32,7 @@
93.4 import java.lang.reflect.Field;
93.5 import java.lang.reflect.Method;
93.6 import java.lang.reflect.TypeVariable;
93.7 +import java.net.URL;
93.8 import org.apidesign.bck2brwsr.core.JavaScriptBody;
93.9 import org.apidesign.bck2brwsr.emul.reflect.MethodImpl;
93.10
93.11 @@ -230,12 +231,14 @@
93.12 }
93.13
93.14 @JavaScriptBody(args = {"n", "c" }, body =
93.15 - "if (vm[c]) return vm[c].$class;\n"
93.16 - + "if (vm.loadClass) {\n"
93.17 - + " vm.loadClass(n);\n"
93.18 - + " if (vm[c]) return vm[c].$class;\n"
93.19 + "if (!vm[c]) {\n"
93.20 + + " if (vm.loadClass) {\n"
93.21 + + " vm.loadClass(n);\n"
93.22 + + " }\n"
93.23 + + " if (!vm[c]) return null;\n"
93.24 + "}\n"
93.25 - + "return null;"
93.26 + + "vm[c](false);"
93.27 + + "return vm[c].$class;"
93.28 )
93.29 private static native Class<?> loadCls(String n, String c);
93.30
93.31 @@ -346,6 +349,9 @@
93.32 * @since JDK1.1
93.33 */
93.34 public boolean isInstance(Object obj) {
93.35 + if (obj == null) {
93.36 + return false;
93.37 + }
93.38 if (isArray()) {
93.39 return isAssignableFrom(obj.getClass());
93.40 }
93.41 @@ -397,10 +403,15 @@
93.42 return cmpType != null && getComponentType().isAssignableFrom(cmpType);
93.43 }
93.44 String prop = "$instOf_" + getName().replace('.', '_');
93.45 - return hasProperty(cls, prop);
93.46 + return hasCnstrProperty(cls, prop);
93.47 }
93.48
93.49 -
93.50 + @JavaScriptBody(args = { "who", "prop" }, body =
93.51 + "if (who.cnstr.prototype[prop]) return true; else return false;"
93.52 + )
93.53 + private static native boolean hasCnstrProperty(Object who, String prop);
93.54 +
93.55 +
93.56 /**
93.57 * Determines if the specified {@code Class} object represents an
93.58 * interface type.
93.59 @@ -605,7 +616,9 @@
93.60 * @see java.lang.reflect.Modifier
93.61 * @since JDK1.1
93.62 */
93.63 - public native int getModifiers();
93.64 + public int getModifiers() {
93.65 + return getAccess();
93.66 + }
93.67
93.68
93.69 /**
93.70 @@ -906,7 +919,50 @@
93.71 }
93.72 return m;
93.73 }
93.74 -
93.75 +
93.76 + /**
93.77 + * Returns an array of {@code Method} objects reflecting all the
93.78 + * methods declared by the class or interface represented by this
93.79 + * {@code Class} object. This includes public, protected, default
93.80 + * (package) access, and private methods, but excludes inherited methods.
93.81 + * The elements in the array returned are not sorted and are not in any
93.82 + * particular order. This method returns an array of length 0 if the class
93.83 + * or interface declares no methods, or if this {@code Class} object
93.84 + * represents a primitive type, an array class, or void. The class
93.85 + * initialization method {@code <clinit>} is not included in the
93.86 + * returned array. If the class declares multiple public member methods
93.87 + * with the same parameter types, they are all included in the returned
93.88 + * array.
93.89 + *
93.90 + * <p> See <em>The Java Language Specification</em>, section 8.2.
93.91 + *
93.92 + * @return the array of {@code Method} objects representing all the
93.93 + * declared methods of this class
93.94 + * @exception SecurityException
93.95 + * If a security manager, <i>s</i>, is present and any of the
93.96 + * following conditions is met:
93.97 + *
93.98 + * <ul>
93.99 + *
93.100 + * <li> invocation of
93.101 + * {@link SecurityManager#checkMemberAccess
93.102 + * s.checkMemberAccess(this, Member.DECLARED)} denies
93.103 + * access to the declared methods within this class
93.104 + *
93.105 + * <li> the caller's class loader is not the same as or an
93.106 + * ancestor of the class loader for the current class and
93.107 + * invocation of {@link SecurityManager#checkPackageAccess
93.108 + * s.checkPackageAccess()} denies access to the package
93.109 + * of this class
93.110 + *
93.111 + * </ul>
93.112 + *
93.113 + * @since JDK1.1
93.114 + */
93.115 + public Method[] getDeclaredMethods() throws SecurityException {
93.116 + throw new SecurityException();
93.117 + }
93.118 +
93.119 /**
93.120 * Character.isDigit answers {@code true} to some non-ascii
93.121 * digits. This one does not.
93.122 @@ -1028,15 +1084,16 @@
93.123 * @since JDK1.1
93.124 */
93.125 public java.net.URL getResource(String name) {
93.126 - name = resolveName(name);
93.127 - ClassLoader cl = null;
93.128 - if (cl==null) {
93.129 - // A system class.
93.130 - return ClassLoader.getSystemResource(name);
93.131 - }
93.132 - return cl.getResource(name);
93.133 + InputStream is = getResourceAsStream(name);
93.134 + return is == null ? null : newResourceURL(URL.class, "res:/" + name, is);
93.135 }
93.136 -
93.137 +
93.138 + @JavaScriptBody(args = { "url", "spec", "is" }, body =
93.139 + "var u = url.cnstr(true);\n"
93.140 + + "u.constructor.cons__VLjava_lang_String_2Ljava_io_InputStream_2.call(u, spec, is);\n"
93.141 + + "return u;"
93.142 + )
93.143 + private static native URL newResourceURL(Class<URL> url, String spec, InputStream is);
93.144
93.145 /**
93.146 * Add a package name prefix if the name is not absolute Remove leading "/"
93.147 @@ -1092,6 +1149,48 @@
93.148 public ClassLoader getClassLoader() {
93.149 throw new SecurityException();
93.150 }
93.151 +
93.152 + /**
93.153 + * Determines the interfaces implemented by the class or interface
93.154 + * represented by this object.
93.155 + *
93.156 + * <p> If this object represents a class, the return value is an array
93.157 + * containing objects representing all interfaces implemented by the
93.158 + * class. The order of the interface objects in the array corresponds to
93.159 + * the order of the interface names in the {@code implements} clause
93.160 + * of the declaration of the class represented by this object. For
93.161 + * example, given the declaration:
93.162 + * <blockquote>
93.163 + * {@code class Shimmer implements FloorWax, DessertTopping { ... }}
93.164 + * </blockquote>
93.165 + * suppose the value of {@code s} is an instance of
93.166 + * {@code Shimmer}; the value of the expression:
93.167 + * <blockquote>
93.168 + * {@code s.getClass().getInterfaces()[0]}
93.169 + * </blockquote>
93.170 + * is the {@code Class} object that represents interface
93.171 + * {@code FloorWax}; and the value of:
93.172 + * <blockquote>
93.173 + * {@code s.getClass().getInterfaces()[1]}
93.174 + * </blockquote>
93.175 + * is the {@code Class} object that represents interface
93.176 + * {@code DessertTopping}.
93.177 + *
93.178 + * <p> If this object represents an interface, the array contains objects
93.179 + * representing all interfaces extended by the interface. The order of the
93.180 + * interface objects in the array corresponds to the order of the interface
93.181 + * names in the {@code extends} clause of the declaration of the
93.182 + * interface represented by this object.
93.183 + *
93.184 + * <p> If this object represents a class or interface that implements no
93.185 + * interfaces, the method returns an array of length 0.
93.186 + *
93.187 + * <p> If this object represents a primitive type or void, the method
93.188 + * returns an array of length 0.
93.189 + *
93.190 + * @return an array of interfaces implemented by this class.
93.191 + */
93.192 + public native Class<?>[] getInterfaces();
93.193
93.194 /**
93.195 * Returns the {@code Class} representing the component type of an
94.1 --- a/emul/mini/src/main/java/java/lang/ClassLoader.java Fri Jan 25 15:08:24 2013 +0100
94.2 +++ b/emul/mini/src/main/java/java/lang/ClassLoader.java Sun Feb 17 17:58:34 2013 +0100
94.3 @@ -703,7 +703,7 @@
94.4 public static Enumeration<URL> getSystemResources(String name)
94.5 throws IOException
94.6 {
94.7 - ClassLoader system = getSystemClassLoader();
94.8 + ClassLoader system = null; // getSystemClassLoader();
94.9 if (system == null) {
94.10 return getBootstrapResources(name);
94.11 }
94.12 @@ -874,7 +874,29 @@
94.13 }
94.14
94.15 private static Enumeration<URL> getBootstrapResources(String name) {
94.16 - throw new UnsupportedOperationException();
94.17 + URL u = Object.class.getResource("/" + name);
94.18 + return new OneOrZeroEnum(u);
94.19 + }
94.20 +
94.21 + private static class OneOrZeroEnum implements Enumeration<URL> {
94.22 + private URL u;
94.23 +
94.24 + public OneOrZeroEnum(URL u) {
94.25 + this.u = u;
94.26 + }
94.27 +
94.28 + public boolean hasMoreElements() {
94.29 + return u != null;
94.30 + }
94.31 +
94.32 + public URL nextElement() {
94.33 + URL r = u;
94.34 + if (r == null) {
94.35 + throw new NoSuchElementException();
94.36 + }
94.37 + u = null;
94.38 + return r;
94.39 + }
94.40 }
94.41
94.42 private static class CompoundEnumeration implements Enumeration<URL> {
95.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
95.2 +++ b/emul/mini/src/main/java/java/lang/Cloneable.java Sun Feb 17 17:58:34 2013 +0100
95.3 @@ -0,0 +1,54 @@
95.4 +/*
95.5 + * Copyright (c) 1995, 2004, Oracle and/or its affiliates. All rights reserved.
95.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
95.7 + *
95.8 + * This code is free software; you can redistribute it and/or modify it
95.9 + * under the terms of the GNU General Public License version 2 only, as
95.10 + * published by the Free Software Foundation. Oracle designates this
95.11 + * particular file as subject to the "Classpath" exception as provided
95.12 + * by Oracle in the LICENSE file that accompanied this code.
95.13 + *
95.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
95.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
95.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
95.17 + * version 2 for more details (a copy is included in the LICENSE file that
95.18 + * accompanied this code).
95.19 + *
95.20 + * You should have received a copy of the GNU General Public License version
95.21 + * 2 along with this work; if not, write to the Free Software Foundation,
95.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
95.23 + *
95.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
95.25 + * or visit www.oracle.com if you need additional information or have any
95.26 + * questions.
95.27 + */
95.28 +
95.29 +package java.lang;
95.30 +
95.31 +/**
95.32 + * A class implements the <code>Cloneable</code> interface to
95.33 + * indicate to the {@link java.lang.Object#clone()} method that it
95.34 + * is legal for that method to make a
95.35 + * field-for-field copy of instances of that class.
95.36 + * <p>
95.37 + * Invoking Object's clone method on an instance that does not implement the
95.38 + * <code>Cloneable</code> interface results in the exception
95.39 + * <code>CloneNotSupportedException</code> being thrown.
95.40 + * <p>
95.41 + * By convention, classes that implement this interface should override
95.42 + * <tt>Object.clone</tt> (which is protected) with a public method.
95.43 + * See {@link java.lang.Object#clone()} for details on overriding this
95.44 + * method.
95.45 + * <p>
95.46 + * Note that this interface does <i>not</i> contain the <tt>clone</tt> method.
95.47 + * Therefore, it is not possible to clone an object merely by virtue of the
95.48 + * fact that it implements this interface. Even if the clone method is invoked
95.49 + * reflectively, there is no guarantee that it will succeed.
95.50 + *
95.51 + * @author unascribed
95.52 + * @see java.lang.CloneNotSupportedException
95.53 + * @see java.lang.Object#clone()
95.54 + * @since JDK1.0
95.55 + */
95.56 +public interface Cloneable {
95.57 +}
96.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
96.2 +++ b/emul/mini/src/main/java/java/lang/IllegalAccessError.java Sun Feb 17 17:58:34 2013 +0100
96.3 @@ -0,0 +1,58 @@
96.4 +/*
96.5 + * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
96.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
96.7 + *
96.8 + * This code is free software; you can redistribute it and/or modify it
96.9 + * under the terms of the GNU General Public License version 2 only, as
96.10 + * published by the Free Software Foundation. Oracle designates this
96.11 + * particular file as subject to the "Classpath" exception as provided
96.12 + * by Oracle in the LICENSE file that accompanied this code.
96.13 + *
96.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
96.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
96.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
96.17 + * version 2 for more details (a copy is included in the LICENSE file that
96.18 + * accompanied this code).
96.19 + *
96.20 + * You should have received a copy of the GNU General Public License version
96.21 + * 2 along with this work; if not, write to the Free Software Foundation,
96.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
96.23 + *
96.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
96.25 + * or visit www.oracle.com if you need additional information or have any
96.26 + * questions.
96.27 + */
96.28 +
96.29 +package java.lang;
96.30 +
96.31 +/**
96.32 + * Thrown if an application attempts to access or modify a field, or
96.33 + * to call a method that it does not have access to.
96.34 + * <p>
96.35 + * Normally, this error is caught by the compiler; this error can
96.36 + * only occur at run time if the definition of a class has
96.37 + * incompatibly changed.
96.38 + *
96.39 + * @author unascribed
96.40 + * @since JDK1.0
96.41 + */
96.42 +public class IllegalAccessError extends IncompatibleClassChangeError {
96.43 + private static final long serialVersionUID = -8988904074992417891L;
96.44 +
96.45 + /**
96.46 + * Constructs an <code>IllegalAccessError</code> with no detail message.
96.47 + */
96.48 + public IllegalAccessError() {
96.49 + super();
96.50 + }
96.51 +
96.52 + /**
96.53 + * Constructs an <code>IllegalAccessError</code> with the specified
96.54 + * detail message.
96.55 + *
96.56 + * @param s the detail message.
96.57 + */
96.58 + public IllegalAccessError(String s) {
96.59 + super(s);
96.60 + }
96.61 +}
97.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
97.2 +++ b/emul/mini/src/main/java/java/lang/IncompatibleClassChangeError.java Sun Feb 17 17:58:34 2013 +0100
97.3 @@ -0,0 +1,57 @@
97.4 +/*
97.5 + * Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved.
97.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
97.7 + *
97.8 + * This code is free software; you can redistribute it and/or modify it
97.9 + * under the terms of the GNU General Public License version 2 only, as
97.10 + * published by the Free Software Foundation. Oracle designates this
97.11 + * particular file as subject to the "Classpath" exception as provided
97.12 + * by Oracle in the LICENSE file that accompanied this code.
97.13 + *
97.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
97.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
97.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
97.17 + * version 2 for more details (a copy is included in the LICENSE file that
97.18 + * accompanied this code).
97.19 + *
97.20 + * You should have received a copy of the GNU General Public License version
97.21 + * 2 along with this work; if not, write to the Free Software Foundation,
97.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
97.23 + *
97.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
97.25 + * or visit www.oracle.com if you need additional information or have any
97.26 + * questions.
97.27 + */
97.28 +
97.29 +package java.lang;
97.30 +
97.31 +/**
97.32 + * Thrown when an incompatible class change has occurred to some class
97.33 + * definition. The definition of some class, on which the currently
97.34 + * executing method depends, has since changed.
97.35 + *
97.36 + * @author unascribed
97.37 + * @since JDK1.0
97.38 + */
97.39 +public
97.40 +class IncompatibleClassChangeError extends LinkageError {
97.41 + private static final long serialVersionUID = -4914975503642802119L;
97.42 +
97.43 + /**
97.44 + * Constructs an <code>IncompatibleClassChangeError</code> with no
97.45 + * detail message.
97.46 + */
97.47 + public IncompatibleClassChangeError () {
97.48 + super();
97.49 + }
97.50 +
97.51 + /**
97.52 + * Constructs an <code>IncompatibleClassChangeError</code> with the
97.53 + * specified detail message.
97.54 + *
97.55 + * @param s the detail message.
97.56 + */
97.57 + public IncompatibleClassChangeError(String s) {
97.58 + super(s);
97.59 + }
97.60 +}
98.1 --- a/emul/mini/src/main/java/java/lang/Long.java Fri Jan 25 15:08:24 2013 +0100
98.2 +++ b/emul/mini/src/main/java/java/lang/Long.java Sun Feb 17 17:58:34 2013 +0100
98.3 @@ -262,7 +262,7 @@
98.4 * @param i a {@code long} to be converted.
98.5 * @return a string representation of the argument in base 10.
98.6 */
98.7 - @JavaScriptBody(args = "i", body = "return i.toString();")
98.8 + @JavaScriptBody(args = "i", body = "return i.toExactString();")
98.9 public static String toString(long i) {
98.10 if (i == Long.MIN_VALUE)
98.11 return "-9223372036854775808";
99.1 --- a/emul/mini/src/main/java/java/lang/Math.java Fri Jan 25 15:08:24 2013 +0100
99.2 +++ b/emul/mini/src/main/java/java/lang/Math.java Sun Feb 17 17:58:34 2013 +0100
99.3 @@ -375,6 +375,68 @@
99.4 public static double floor(double a) {
99.5 throw new UnsupportedOperationException();
99.6 }
99.7 + /**
99.8 + * Computes the remainder operation on two arguments as prescribed
99.9 + * by the IEEE 754 standard.
99.10 + * The remainder value is mathematically equal to
99.11 + * <code>f1 - f2</code> × <i>n</i>,
99.12 + * where <i>n</i> is the mathematical integer closest to the exact
99.13 + * mathematical value of the quotient {@code f1/f2}, and if two
99.14 + * mathematical integers are equally close to {@code f1/f2},
99.15 + * then <i>n</i> is the integer that is even. If the remainder is
99.16 + * zero, its sign is the same as the sign of the first argument.
99.17 + * Special cases:
99.18 + * <ul><li>If either argument is NaN, or the first argument is infinite,
99.19 + * or the second argument is positive zero or negative zero, then the
99.20 + * result is NaN.
99.21 + * <li>If the first argument is finite and the second argument is
99.22 + * infinite, then the result is the same as the first argument.</ul>
99.23 + *
99.24 + * @param f1 the dividend.
99.25 + * @param f2 the divisor.
99.26 + * @return the remainder when {@code f1} is divided by
99.27 + * {@code f2}.
99.28 + */
99.29 + public static double IEEEremainder(double f1, double f2) {
99.30 + return f1 - (f2 * Math.round(f1 / f2));
99.31 + }
99.32 +
99.33 + /**
99.34 + * Returns the {@code double} value that is closest in value
99.35 + * to the argument and is equal to a mathematical integer. If two
99.36 + * {@code double} values that are mathematical integers are
99.37 + * equally close, the result is the integer value that is
99.38 + * even. Special cases:
99.39 + * <ul><li>If the argument value is already equal to a mathematical
99.40 + * integer, then the result is the same as the argument.
99.41 + * <li>If the argument is NaN or an infinity or positive zero or negative
99.42 + * zero, then the result is the same as the argument.</ul>
99.43 + *
99.44 + * @param a a {@code double} value.
99.45 + * @return the closest floating-point value to {@code a} that is
99.46 + * equal to a mathematical integer.
99.47 + */
99.48 + public static double rint(double a) {
99.49 + double ceil = ceil(a);
99.50 + double floor = floor(a);
99.51 +
99.52 + double dc = ceil - a;
99.53 + double df = a - floor;
99.54 +
99.55 + if (dc < df) {
99.56 + return ceil;
99.57 + } else if (dc > df) {
99.58 + return floor;
99.59 + }
99.60 +
99.61 + int tenC = (int) (ceil % 10.0);
99.62 +
99.63 + if (tenC % 2 == 0) {
99.64 + return ceil;
99.65 + } else {
99.66 + return floor;
99.67 + }
99.68 + }
99.69
99.70 /**
99.71 * Returns the angle <i>theta</i> from the conversion of rectangular
99.72 @@ -929,9 +991,11 @@
99.73 * @author Joseph D. Darcy
99.74 * @since 1.5
99.75 */
99.76 -// public static double signum(double d) {
99.77 -// return sun.misc.FpUtils.signum(d);
99.78 -// }
99.79 + public static double signum(double d) {
99.80 + if (d < 0.0) { return -1.0; }
99.81 + if (d > 0.0) { return 1.0; }
99.82 + return d;
99.83 + }
99.84
99.85 /**
99.86 * Returns the signum function of the argument; zero if the argument
99.87 @@ -950,9 +1014,11 @@
99.88 * @author Joseph D. Darcy
99.89 * @since 1.5
99.90 */
99.91 -// public static float signum(float f) {
99.92 -// return sun.misc.FpUtils.signum(f);
99.93 -// }
99.94 + public static float signum(float f) {
99.95 + if (f < 0.0f) { return -1.0f; }
99.96 + if (f > 0.0f) { return 1.0f; }
99.97 + return f;
99.98 + }
99.99
99.100 /**
99.101 * Returns the first floating-point argument with the sign of the
100.1 --- a/emul/mini/src/main/java/java/lang/Object.java Fri Jan 25 15:08:24 2013 +0100
100.2 +++ b/emul/mini/src/main/java/java/lang/Object.java Sun Feb 17 17:58:34 2013 +0100
100.3 @@ -117,7 +117,7 @@
100.4 )
100.5 public native int hashCode();
100.6
100.7 - @JavaScriptBody(args = {}, body = "Math.random() * Math.pow(2, 32);")
100.8 + @JavaScriptBody(args = {}, body = "return Math.random() * Math.pow(2, 32);")
100.9 native int computeHashCode();
100.10
100.11 /**
101.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
101.2 +++ b/emul/mini/src/main/java/java/lang/Override.java Sun Feb 17 17:58:34 2013 +0100
101.3 @@ -0,0 +1,52 @@
101.4 +/*
101.5 + * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
101.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
101.7 + *
101.8 + * This code is free software; you can redistribute it and/or modify it
101.9 + * under the terms of the GNU General Public License version 2 only, as
101.10 + * published by the Free Software Foundation. Oracle designates this
101.11 + * particular file as subject to the "Classpath" exception as provided
101.12 + * by Oracle in the LICENSE file that accompanied this code.
101.13 + *
101.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
101.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
101.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
101.17 + * version 2 for more details (a copy is included in the LICENSE file that
101.18 + * accompanied this code).
101.19 + *
101.20 + * You should have received a copy of the GNU General Public License version
101.21 + * 2 along with this work; if not, write to the Free Software Foundation,
101.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
101.23 + *
101.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
101.25 + * or visit www.oracle.com if you need additional information or have any
101.26 + * questions.
101.27 + */
101.28 +
101.29 +package java.lang;
101.30 +
101.31 +import java.lang.annotation.*;
101.32 +
101.33 +/**
101.34 + * Indicates that a method declaration is intended to override a
101.35 + * method declaration in a supertype. If a method is annotated with
101.36 + * this annotation type compilers are required to generate an error
101.37 + * message unless at least one of the following conditions hold:
101.38 + *
101.39 + * <ul><li>
101.40 + * The method does override or implement a method declared in a
101.41 + * supertype.
101.42 + * </li><li>
101.43 + * The method has a signature that is override-equivalent to that of
101.44 + * any public method declared in {@linkplain Object}.
101.45 + * </li></ul>
101.46 + *
101.47 + * @author Peter von der Ahé
101.48 + * @author Joshua Bloch
101.49 + * @jls 9.6.1.4 Override
101.50 + * @since 1.5
101.51 + */
101.52 +@Target(ElementType.METHOD)
101.53 +@Retention(RetentionPolicy.SOURCE)
101.54 +public @interface Override {
101.55 +}
102.1 --- a/emul/mini/src/main/java/java/lang/String.java Fri Jan 25 15:08:24 2013 +0100
102.2 +++ b/emul/mini/src/main/java/java/lang/String.java Sun Feb 17 17:58:34 2013 +0100
102.3 @@ -25,6 +25,7 @@
102.4
102.5 package java.lang;
102.6
102.7 +import java.io.UnsupportedEncodingException;
102.8 import java.util.Comparator;
102.9 import org.apidesign.bck2brwsr.core.ExtraJavaScript;
102.10 import org.apidesign.bck2brwsr.core.JavaScriptBody;
102.11 @@ -115,7 +116,7 @@
102.12 /** use serialVersionUID from JDK 1.0.2 for interoperability */
102.13 private static final long serialVersionUID = -6849794470754667710L;
102.14
102.15 - @JavaScriptOnly(name="toString", value="function() { return this.fld_r; }")
102.16 + @JavaScriptOnly(name="toString", value="String.prototype._r")
102.17 private static void jsToString() {
102.18 }
102.19
102.20 @@ -174,7 +175,7 @@
102.21 "for (var i = 0; i < charArr.length; i++) {\n"
102.22 + " if (typeof charArr[i] === 'number') charArr[i] = String.fromCharCode(charArr[i]);\n"
102.23 + "}\n"
102.24 - + "this.fld_r = charArr.join('');\n"
102.25 + + "this._r(charArr.join(''));\n"
102.26 )
102.27 public String(char value[]) {
102.28 }
102.29 @@ -200,15 +201,18 @@
102.30 * If the {@code offset} and {@code count} arguments index
102.31 * characters outside the bounds of the {@code value} array
102.32 */
102.33 + public String(char value[], int offset, int count) {
102.34 + initFromCharArray(value, offset, count);
102.35 + }
102.36 +
102.37 @JavaScriptBody(args = { "charArr", "off", "cnt" }, body =
102.38 "var up = off + cnt;\n" +
102.39 "for (var i = off; i < up; i++) {\n" +
102.40 " if (typeof charArr[i] === 'number') charArr[i] = String.fromCharCode(charArr[i]);\n" +
102.41 "}\n" +
102.42 - "this.fld_r = charArr.slice(off, up).join(\"\");\n"
102.43 + "this._r(charArr.slice(off, up).join(\"\"));\n"
102.44 )
102.45 - public String(char value[], int offset, int count) {
102.46 - }
102.47 + private native void initFromCharArray(char value[], int offset, int count);
102.48
102.49 /**
102.50 * Allocates a new {@code String} that contains characters from a subarray
102.51 @@ -331,7 +335,7 @@
102.52 value[i] = (char) (hibyte | (ascii[i + offset] & 0xff));
102.53 }
102.54 }
102.55 - this.r = new String(value, 0, count);
102.56 + initFromCharArray(value, offset, count);
102.57 }
102.58
102.59 /**
102.60 @@ -415,17 +419,11 @@
102.61 *
102.62 * @since JDK1.1
102.63 */
102.64 -// public String(byte bytes[], int offset, int length, String charsetName)
102.65 -// throws UnsupportedEncodingException
102.66 -// {
102.67 -// if (charsetName == null)
102.68 -// throw new NullPointerException("charsetName");
102.69 -// checkBounds(bytes, offset, length);
102.70 -// char[] v = StringCoding.decode(charsetName, bytes, offset, length);
102.71 -// this.offset = 0;
102.72 -// this.count = v.length;
102.73 -// this.value = v;
102.74 -// }
102.75 + public String(byte bytes[], int offset, int length, String charsetName)
102.76 + throws UnsupportedEncodingException
102.77 + {
102.78 + this(checkUTF8(bytes, charsetName), offset, length);
102.79 + }
102.80
102.81 /**
102.82 * Constructs a new {@code String} by decoding the specified subarray of
102.83 @@ -492,11 +490,11 @@
102.84 *
102.85 * @since JDK1.1
102.86 */
102.87 -// public String(byte bytes[], String charsetName)
102.88 -// throws UnsupportedEncodingException
102.89 -// {
102.90 -// this(bytes, 0, bytes.length, charsetName);
102.91 -// }
102.92 + public String(byte bytes[], String charsetName)
102.93 + throws UnsupportedEncodingException
102.94 + {
102.95 + this(bytes, 0, bytes.length, charsetName);
102.96 + }
102.97
102.98 /**
102.99 * Constructs a new {@code String} by decoding the specified array of
102.100 @@ -553,10 +551,14 @@
102.101 public String(byte bytes[], int offset, int length) {
102.102 checkBounds(bytes, offset, length);
102.103 char[] v = new char[length];
102.104 - for (int i = 0; i < length; i++) {
102.105 - v[i] = (char)bytes[offset++];
102.106 + int[] at = { offset };
102.107 + int end = offset + length;
102.108 + int chlen = 0;
102.109 + while (at[0] < end) {
102.110 + int ch = nextChar(bytes, at);
102.111 + v[chlen++] = (char)ch;
102.112 }
102.113 - this.r = new String(v, 0, v.length);
102.114 + initFromCharArray(v, 0, chlen);
102.115 }
102.116
102.117 /**
102.118 @@ -925,12 +927,12 @@
102.119 *
102.120 * @since JDK1.1
102.121 */
102.122 -// public byte[] getBytes(String charsetName)
102.123 -// throws UnsupportedEncodingException
102.124 -// {
102.125 -// if (charsetName == null) throw new NullPointerException();
102.126 -// return StringCoding.encode(charsetName, value, offset, count);
102.127 -// }
102.128 + public byte[] getBytes(String charsetName)
102.129 + throws UnsupportedEncodingException
102.130 + {
102.131 + checkUTF8(null, charsetName);
102.132 + return getBytes();
102.133 + }
102.134
102.135 /**
102.136 * Encodes this {@code String} into a sequence of bytes using the given
102.137 @@ -971,10 +973,24 @@
102.138 * @since JDK1.1
102.139 */
102.140 public byte[] getBytes() {
102.141 - byte[] arr = new byte[length()];
102.142 - for (int i = 0; i < arr.length; i++) {
102.143 - final char v = charAt(i);
102.144 - arr[i] = (byte)v;
102.145 + int len = length();
102.146 + byte[] arr = new byte[len];
102.147 + for (int i = 0, j = 0; j < len; j++) {
102.148 + final int v = charAt(j);
102.149 + if (v < 128) {
102.150 + arr[i++] = (byte) v;
102.151 + continue;
102.152 + }
102.153 + if (v < 0x0800) {
102.154 + arr = System.expandArray(arr, i + 1);
102.155 + arr[i++] = (byte) (0xC0 | (v >> 6));
102.156 + arr[i++] = (byte) (0x80 | (0x3F & v));
102.157 + continue;
102.158 + }
102.159 + arr = System.expandArray(arr, i + 2);
102.160 + arr[i++] = (byte) (0xE0 | (v >> 12));
102.161 + arr[i++] = (byte) (0x80 | ((v >> 6) & 0x7F));
102.162 + arr[i++] = (byte) (0x80 | (0x3F & v));
102.163 }
102.164 return arr;
102.165 }
102.166 @@ -1210,7 +1226,7 @@
102.167 private static int offset() {
102.168 return 0;
102.169 }
102.170 -
102.171 +
102.172 private static class CaseInsensitiveComparator
102.173 implements Comparator<String>, java.io.Serializable {
102.174 // use serialVersionUID from JDK 1.2.2 for interoperability
102.175 @@ -3007,4 +3023,57 @@
102.176 * guaranteed to be from a pool of unique strings.
102.177 */
102.178 public native String intern();
102.179 +
102.180 +
102.181 + private static <T> T checkUTF8(T data, String charsetName)
102.182 + throws UnsupportedEncodingException {
102.183 + if (charsetName == null) {
102.184 + throw new NullPointerException("charsetName");
102.185 + }
102.186 + if (!charsetName.equalsIgnoreCase("UTF-8")
102.187 + && !charsetName.equalsIgnoreCase("UTF8")) {
102.188 + throw new UnsupportedEncodingException(charsetName);
102.189 + }
102.190 + return data;
102.191 + }
102.192 +
102.193 + private static int nextChar(byte[] arr, int[] index) throws IndexOutOfBoundsException {
102.194 + int c = arr[index[0]++] & 0xff;
102.195 + switch (c >> 4) {
102.196 + case 0:
102.197 + case 1:
102.198 + case 2:
102.199 + case 3:
102.200 + case 4:
102.201 + case 5:
102.202 + case 6:
102.203 + case 7:
102.204 + /* 0xxxxxxx*/
102.205 + return c;
102.206 + case 12:
102.207 + case 13: {
102.208 + /* 110x xxxx 10xx xxxx*/
102.209 + int char2 = (int) arr[index[0]++];
102.210 + if ((char2 & 0xC0) != 0x80) {
102.211 + throw new IndexOutOfBoundsException("malformed input");
102.212 + }
102.213 + return (((c & 0x1F) << 6) | (char2 & 0x3F));
102.214 + }
102.215 + case 14: {
102.216 + /* 1110 xxxx 10xx xxxx 10xx xxxx */
102.217 + int char2 = arr[index[0]++];
102.218 + int char3 = arr[index[0]++];
102.219 + if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80)) {
102.220 + throw new IndexOutOfBoundsException("malformed input");
102.221 + }
102.222 + return (((c & 0x0F) << 12)
102.223 + | ((char2 & 0x3F) << 6)
102.224 + | ((char3 & 0x3F) << 0));
102.225 + }
102.226 + default:
102.227 + /* 10xx xxxx, 1111 xxxx */
102.228 + throw new IndexOutOfBoundsException("malformed input");
102.229 + }
102.230 +
102.231 + }
102.232 }
103.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
103.2 +++ b/emul/mini/src/main/java/java/lang/reflect/Constructor.java Sun Feb 17 17:58:34 2013 +0100
103.3 @@ -0,0 +1,567 @@
103.4 +/*
103.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
103.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
103.7 + *
103.8 + * This code is free software; you can redistribute it and/or modify it
103.9 + * under the terms of the GNU General Public License version 2 only, as
103.10 + * published by the Free Software Foundation. Oracle designates this
103.11 + * particular file as subject to the "Classpath" exception as provided
103.12 + * by Oracle in the LICENSE file that accompanied this code.
103.13 + *
103.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
103.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
103.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
103.17 + * version 2 for more details (a copy is included in the LICENSE file that
103.18 + * accompanied this code).
103.19 + *
103.20 + * You should have received a copy of the GNU General Public License version
103.21 + * 2 along with this work; if not, write to the Free Software Foundation,
103.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
103.23 + *
103.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
103.25 + * or visit www.oracle.com if you need additional information or have any
103.26 + * questions.
103.27 + */
103.28 +
103.29 +package java.lang.reflect;
103.30 +
103.31 +import java.lang.annotation.Annotation;
103.32 +import org.apidesign.bck2brwsr.emul.reflect.TypeProvider;
103.33 +
103.34 +/**
103.35 + * {@code Constructor} provides information about, and access to, a single
103.36 + * constructor for a class.
103.37 + *
103.38 + * <p>{@code Constructor} permits widening conversions to occur when matching the
103.39 + * actual parameters to newInstance() with the underlying
103.40 + * constructor's formal parameters, but throws an
103.41 + * {@code IllegalArgumentException} if a narrowing conversion would occur.
103.42 + *
103.43 + * @param <T> the class in which the constructor is declared
103.44 + *
103.45 + * @see Member
103.46 + * @see java.lang.Class
103.47 + * @see java.lang.Class#getConstructors()
103.48 + * @see java.lang.Class#getConstructor(Class[])
103.49 + * @see java.lang.Class#getDeclaredConstructors()
103.50 + *
103.51 + * @author Kenneth Russell
103.52 + * @author Nakul Saraiya
103.53 + */
103.54 +public final
103.55 + class Constructor<T> extends AccessibleObject implements
103.56 + GenericDeclaration,
103.57 + Member {
103.58 +
103.59 + private Class<T> clazz;
103.60 + private int slot;
103.61 + private Class<?>[] parameterTypes;
103.62 + private Class<?>[] exceptionTypes;
103.63 + private int modifiers;
103.64 + // Generics and annotations support
103.65 + private transient String signature;
103.66 + private byte[] annotations;
103.67 + private byte[] parameterAnnotations;
103.68 +
103.69 +
103.70 + // For sharing of ConstructorAccessors. This branching structure
103.71 + // is currently only two levels deep (i.e., one root Constructor
103.72 + // and potentially many Constructor objects pointing to it.)
103.73 + private Constructor<T> root;
103.74 +
103.75 + /**
103.76 + * Package-private constructor used by ReflectAccess to enable
103.77 + * instantiation of these objects in Java code from the java.lang
103.78 + * package via sun.reflect.LangReflectAccess.
103.79 + */
103.80 + Constructor(Class<T> declaringClass,
103.81 + Class<?>[] parameterTypes,
103.82 + Class<?>[] checkedExceptions,
103.83 + int modifiers,
103.84 + int slot,
103.85 + String signature,
103.86 + byte[] annotations,
103.87 + byte[] parameterAnnotations)
103.88 + {
103.89 + this.clazz = declaringClass;
103.90 + this.parameterTypes = parameterTypes;
103.91 + this.exceptionTypes = checkedExceptions;
103.92 + this.modifiers = modifiers;
103.93 + this.slot = slot;
103.94 + this.signature = signature;
103.95 + this.annotations = annotations;
103.96 + this.parameterAnnotations = parameterAnnotations;
103.97 + }
103.98 +
103.99 + /**
103.100 + * Package-private routine (exposed to java.lang.Class via
103.101 + * ReflectAccess) which returns a copy of this Constructor. The copy's
103.102 + * "root" field points to this Constructor.
103.103 + */
103.104 + Constructor<T> copy() {
103.105 + return this;
103.106 + }
103.107 +
103.108 + /**
103.109 + * Returns the {@code Class} object representing the class that declares
103.110 + * the constructor represented by this {@code Constructor} object.
103.111 + */
103.112 + public Class<T> getDeclaringClass() {
103.113 + return clazz;
103.114 + }
103.115 +
103.116 + /**
103.117 + * Returns the name of this constructor, as a string. This is
103.118 + * the binary name of the constructor's declaring class.
103.119 + */
103.120 + public String getName() {
103.121 + return getDeclaringClass().getName();
103.122 + }
103.123 +
103.124 + /**
103.125 + * Returns the Java language modifiers for the constructor
103.126 + * represented by this {@code Constructor} object, as an integer. The
103.127 + * {@code Modifier} class should be used to decode the modifiers.
103.128 + *
103.129 + * @see Modifier
103.130 + */
103.131 + public int getModifiers() {
103.132 + return modifiers;
103.133 + }
103.134 +
103.135 + /**
103.136 + * Returns an array of {@code TypeVariable} objects that represent the
103.137 + * type variables declared by the generic declaration represented by this
103.138 + * {@code GenericDeclaration} object, in declaration order. Returns an
103.139 + * array of length 0 if the underlying generic declaration declares no type
103.140 + * variables.
103.141 + *
103.142 + * @return an array of {@code TypeVariable} objects that represent
103.143 + * the type variables declared by this generic declaration
103.144 + * @throws GenericSignatureFormatError if the generic
103.145 + * signature of this generic declaration does not conform to
103.146 + * the format specified in
103.147 + * <cite>The Java™ Virtual Machine Specification</cite>
103.148 + * @since 1.5
103.149 + */
103.150 + public TypeVariable<Constructor<T>>[] getTypeParameters() {
103.151 + return TypeProvider.getDefault().getTypeParameters(this);
103.152 + }
103.153 +
103.154 +
103.155 + /**
103.156 + * Returns an array of {@code Class} objects that represent the formal
103.157 + * parameter types, in declaration order, of the constructor
103.158 + * represented by this {@code Constructor} object. Returns an array of
103.159 + * length 0 if the underlying constructor takes no parameters.
103.160 + *
103.161 + * @return the parameter types for the constructor this object
103.162 + * represents
103.163 + */
103.164 + public Class<?>[] getParameterTypes() {
103.165 + return (Class<?>[]) parameterTypes.clone();
103.166 + }
103.167 +
103.168 +
103.169 + /**
103.170 + * Returns an array of {@code Type} objects that represent the formal
103.171 + * parameter types, in declaration order, of the method represented by
103.172 + * this {@code Constructor} object. Returns an array of length 0 if the
103.173 + * underlying method takes no parameters.
103.174 + *
103.175 + * <p>If a formal parameter type is a parameterized type,
103.176 + * the {@code Type} object returned for it must accurately reflect
103.177 + * the actual type parameters used in the source code.
103.178 + *
103.179 + * <p>If a formal parameter type is a type variable or a parameterized
103.180 + * type, it is created. Otherwise, it is resolved.
103.181 + *
103.182 + * @return an array of {@code Type}s that represent the formal
103.183 + * parameter types of the underlying method, in declaration order
103.184 + * @throws GenericSignatureFormatError
103.185 + * if the generic method signature does not conform to the format
103.186 + * specified in
103.187 + * <cite>The Java™ Virtual Machine Specification</cite>
103.188 + * @throws TypeNotPresentException if any of the parameter
103.189 + * types of the underlying method refers to a non-existent type
103.190 + * declaration
103.191 + * @throws MalformedParameterizedTypeException if any of
103.192 + * the underlying method's parameter types refer to a parameterized
103.193 + * type that cannot be instantiated for any reason
103.194 + * @since 1.5
103.195 + */
103.196 + public Type[] getGenericParameterTypes() {
103.197 + return TypeProvider.getDefault().getGenericParameterTypes(this);
103.198 + }
103.199 +
103.200 +
103.201 + /**
103.202 + * Returns an array of {@code Class} objects that represent the types
103.203 + * of exceptions declared to be thrown by the underlying constructor
103.204 + * represented by this {@code Constructor} object. Returns an array of
103.205 + * length 0 if the constructor declares no exceptions in its {@code throws} clause.
103.206 + *
103.207 + * @return the exception types declared as being thrown by the
103.208 + * constructor this object represents
103.209 + */
103.210 + public Class<?>[] getExceptionTypes() {
103.211 + return (Class<?>[])exceptionTypes.clone();
103.212 + }
103.213 +
103.214 +
103.215 + /**
103.216 + * Returns an array of {@code Type} objects that represent the
103.217 + * exceptions declared to be thrown by this {@code Constructor} object.
103.218 + * Returns an array of length 0 if the underlying method declares
103.219 + * no exceptions in its {@code throws} clause.
103.220 + *
103.221 + * <p>If an exception type is a type variable or a parameterized
103.222 + * type, it is created. Otherwise, it is resolved.
103.223 + *
103.224 + * @return an array of Types that represent the exception types
103.225 + * thrown by the underlying method
103.226 + * @throws GenericSignatureFormatError
103.227 + * if the generic method signature does not conform to the format
103.228 + * specified in
103.229 + * <cite>The Java™ Virtual Machine Specification</cite>
103.230 + * @throws TypeNotPresentException if the underlying method's
103.231 + * {@code throws} clause refers to a non-existent type declaration
103.232 + * @throws MalformedParameterizedTypeException if
103.233 + * the underlying method's {@code throws} clause refers to a
103.234 + * parameterized type that cannot be instantiated for any reason
103.235 + * @since 1.5
103.236 + */
103.237 + public Type[] getGenericExceptionTypes() {
103.238 + return TypeProvider.getDefault().getGenericExceptionTypes(this);
103.239 + }
103.240 +
103.241 + /**
103.242 + * Compares this {@code Constructor} against the specified object.
103.243 + * Returns true if the objects are the same. Two {@code Constructor} objects are
103.244 + * the same if they were declared by the same class and have the
103.245 + * same formal parameter types.
103.246 + */
103.247 + public boolean equals(Object obj) {
103.248 + if (obj != null && obj instanceof Constructor) {
103.249 + Constructor<?> other = (Constructor<?>)obj;
103.250 + if (getDeclaringClass() == other.getDeclaringClass()) {
103.251 + /* Avoid unnecessary cloning */
103.252 + Class<?>[] params1 = parameterTypes;
103.253 + Class<?>[] params2 = other.parameterTypes;
103.254 + if (params1.length == params2.length) {
103.255 + for (int i = 0; i < params1.length; i++) {
103.256 + if (params1[i] != params2[i])
103.257 + return false;
103.258 + }
103.259 + return true;
103.260 + }
103.261 + }
103.262 + }
103.263 + return false;
103.264 + }
103.265 +
103.266 + /**
103.267 + * Returns a hashcode for this {@code Constructor}. The hashcode is
103.268 + * the same as the hashcode for the underlying constructor's
103.269 + * declaring class name.
103.270 + */
103.271 + public int hashCode() {
103.272 + return getDeclaringClass().getName().hashCode();
103.273 + }
103.274 +
103.275 + /**
103.276 + * Returns a string describing this {@code Constructor}. The string is
103.277 + * formatted as the constructor access modifiers, if any,
103.278 + * followed by the fully-qualified name of the declaring class,
103.279 + * followed by a parenthesized, comma-separated list of the
103.280 + * constructor's formal parameter types. For example:
103.281 + * <pre>
103.282 + * public java.util.Hashtable(int,float)
103.283 + * </pre>
103.284 + *
103.285 + * <p>The only possible modifiers for constructors are the access
103.286 + * modifiers {@code public}, {@code protected} or
103.287 + * {@code private}. Only one of these may appear, or none if the
103.288 + * constructor has default (package) access.
103.289 + */
103.290 + public String toString() {
103.291 + try {
103.292 + StringBuffer sb = new StringBuffer();
103.293 + int mod = getModifiers() & Modifier.constructorModifiers();
103.294 + if (mod != 0) {
103.295 + sb.append(Modifier.toString(mod) + " ");
103.296 + }
103.297 + sb.append(Field.getTypeName(getDeclaringClass()));
103.298 + sb.append("(");
103.299 + Class<?>[] params = parameterTypes; // avoid clone
103.300 + for (int j = 0; j < params.length; j++) {
103.301 + sb.append(Field.getTypeName(params[j]));
103.302 + if (j < (params.length - 1))
103.303 + sb.append(",");
103.304 + }
103.305 + sb.append(")");
103.306 + Class<?>[] exceptions = exceptionTypes; // avoid clone
103.307 + if (exceptions.length > 0) {
103.308 + sb.append(" throws ");
103.309 + for (int k = 0; k < exceptions.length; k++) {
103.310 + sb.append(exceptions[k].getName());
103.311 + if (k < (exceptions.length - 1))
103.312 + sb.append(",");
103.313 + }
103.314 + }
103.315 + return sb.toString();
103.316 + } catch (Exception e) {
103.317 + return "<" + e + ">";
103.318 + }
103.319 + }
103.320 +
103.321 + /**
103.322 + * Returns a string describing this {@code Constructor},
103.323 + * including type parameters. The string is formatted as the
103.324 + * constructor access modifiers, if any, followed by an
103.325 + * angle-bracketed comma separated list of the constructor's type
103.326 + * parameters, if any, followed by the fully-qualified name of the
103.327 + * declaring class, followed by a parenthesized, comma-separated
103.328 + * list of the constructor's generic formal parameter types.
103.329 + *
103.330 + * If this constructor was declared to take a variable number of
103.331 + * arguments, instead of denoting the last parameter as
103.332 + * "<tt><i>Type</i>[]</tt>", it is denoted as
103.333 + * "<tt><i>Type</i>...</tt>".
103.334 + *
103.335 + * A space is used to separate access modifiers from one another
103.336 + * and from the type parameters or return type. If there are no
103.337 + * type parameters, the type parameter list is elided; if the type
103.338 + * parameter list is present, a space separates the list from the
103.339 + * class name. If the constructor is declared to throw
103.340 + * exceptions, the parameter list is followed by a space, followed
103.341 + * by the word "{@code throws}" followed by a
103.342 + * comma-separated list of the thrown exception types.
103.343 + *
103.344 + * <p>The only possible modifiers for constructors are the access
103.345 + * modifiers {@code public}, {@code protected} or
103.346 + * {@code private}. Only one of these may appear, or none if the
103.347 + * constructor has default (package) access.
103.348 + *
103.349 + * @return a string describing this {@code Constructor},
103.350 + * include type parameters
103.351 + *
103.352 + * @since 1.5
103.353 + */
103.354 + public String toGenericString() {
103.355 + try {
103.356 + StringBuilder sb = new StringBuilder();
103.357 + int mod = getModifiers() & Modifier.constructorModifiers();
103.358 + if (mod != 0) {
103.359 + sb.append(Modifier.toString(mod) + " ");
103.360 + }
103.361 + TypeVariable<?>[] typeparms = getTypeParameters();
103.362 + if (typeparms.length > 0) {
103.363 + boolean first = true;
103.364 + sb.append("<");
103.365 + for(TypeVariable<?> typeparm: typeparms) {
103.366 + if (!first)
103.367 + sb.append(",");
103.368 + // Class objects can't occur here; no need to test
103.369 + // and call Class.getName().
103.370 + sb.append(typeparm.toString());
103.371 + first = false;
103.372 + }
103.373 + sb.append("> ");
103.374 + }
103.375 + sb.append(Field.getTypeName(getDeclaringClass()));
103.376 + sb.append("(");
103.377 + Type[] params = getGenericParameterTypes();
103.378 + for (int j = 0; j < params.length; j++) {
103.379 + String param = (params[j] instanceof Class<?>)?
103.380 + Field.getTypeName((Class<?>)params[j]):
103.381 + (params[j].toString());
103.382 + if (isVarArgs() && (j == params.length - 1)) // replace T[] with T...
103.383 + param = param.replaceFirst("\\[\\]$", "...");
103.384 + sb.append(param);
103.385 + if (j < (params.length - 1))
103.386 + sb.append(",");
103.387 + }
103.388 + sb.append(")");
103.389 + Type[] exceptions = getGenericExceptionTypes();
103.390 + if (exceptions.length > 0) {
103.391 + sb.append(" throws ");
103.392 + for (int k = 0; k < exceptions.length; k++) {
103.393 + sb.append((exceptions[k] instanceof Class)?
103.394 + ((Class<?>)exceptions[k]).getName():
103.395 + exceptions[k].toString());
103.396 + if (k < (exceptions.length - 1))
103.397 + sb.append(",");
103.398 + }
103.399 + }
103.400 + return sb.toString();
103.401 + } catch (Exception e) {
103.402 + return "<" + e + ">";
103.403 + }
103.404 + }
103.405 +
103.406 + /**
103.407 + * Uses the constructor represented by this {@code Constructor} object to
103.408 + * create and initialize a new instance of the constructor's
103.409 + * declaring class, with the specified initialization parameters.
103.410 + * Individual parameters are automatically unwrapped to match
103.411 + * primitive formal parameters, and both primitive and reference
103.412 + * parameters are subject to method invocation conversions as necessary.
103.413 + *
103.414 + * <p>If the number of formal parameters required by the underlying constructor
103.415 + * is 0, the supplied {@code initargs} array may be of length 0 or null.
103.416 + *
103.417 + * <p>If the constructor's declaring class is an inner class in a
103.418 + * non-static context, the first argument to the constructor needs
103.419 + * to be the enclosing instance; see section 15.9.3 of
103.420 + * <cite>The Java™ Language Specification</cite>.
103.421 + *
103.422 + * <p>If the required access and argument checks succeed and the
103.423 + * instantiation will proceed, the constructor's declaring class
103.424 + * is initialized if it has not already been initialized.
103.425 + *
103.426 + * <p>If the constructor completes normally, returns the newly
103.427 + * created and initialized instance.
103.428 + *
103.429 + * @param initargs array of objects to be passed as arguments to
103.430 + * the constructor call; values of primitive types are wrapped in
103.431 + * a wrapper object of the appropriate type (e.g. a {@code float}
103.432 + * in a {@link java.lang.Float Float})
103.433 + *
103.434 + * @return a new object created by calling the constructor
103.435 + * this object represents
103.436 + *
103.437 + * @exception IllegalAccessException if this {@code Constructor} object
103.438 + * is enforcing Java language access control and the underlying
103.439 + * constructor is inaccessible.
103.440 + * @exception IllegalArgumentException if the number of actual
103.441 + * and formal parameters differ; if an unwrapping
103.442 + * conversion for primitive arguments fails; or if,
103.443 + * after possible unwrapping, a parameter value
103.444 + * cannot be converted to the corresponding formal
103.445 + * parameter type by a method invocation conversion; if
103.446 + * this constructor pertains to an enum type.
103.447 + * @exception InstantiationException if the class that declares the
103.448 + * underlying constructor represents an abstract class.
103.449 + * @exception InvocationTargetException if the underlying constructor
103.450 + * throws an exception.
103.451 + * @exception ExceptionInInitializerError if the initialization provoked
103.452 + * by this method fails.
103.453 + */
103.454 + public T newInstance(Object ... initargs)
103.455 + throws InstantiationException, IllegalAccessException,
103.456 + IllegalArgumentException, InvocationTargetException
103.457 + {
103.458 + throw new SecurityException();
103.459 + }
103.460 +
103.461 + /**
103.462 + * Returns {@code true} if this constructor was declared to take
103.463 + * a variable number of arguments; returns {@code false}
103.464 + * otherwise.
103.465 + *
103.466 + * @return {@code true} if an only if this constructor was declared to
103.467 + * take a variable number of arguments.
103.468 + * @since 1.5
103.469 + */
103.470 + public boolean isVarArgs() {
103.471 + return (getModifiers() & Modifier.VARARGS) != 0;
103.472 + }
103.473 +
103.474 + /**
103.475 + * Returns {@code true} if this constructor is a synthetic
103.476 + * constructor; returns {@code false} otherwise.
103.477 + *
103.478 + * @return true if and only if this constructor is a synthetic
103.479 + * constructor as defined by
103.480 + * <cite>The Java™ Language Specification</cite>.
103.481 + * @since 1.5
103.482 + */
103.483 + public boolean isSynthetic() {
103.484 + return Modifier.isSynthetic(getModifiers());
103.485 + }
103.486 +
103.487 + int getSlot() {
103.488 + return slot;
103.489 + }
103.490 +
103.491 + String getSignature() {
103.492 + return signature;
103.493 + }
103.494 +
103.495 + byte[] getRawAnnotations() {
103.496 + return annotations;
103.497 + }
103.498 +
103.499 + byte[] getRawParameterAnnotations() {
103.500 + return parameterAnnotations;
103.501 + }
103.502 +
103.503 + /**
103.504 + * @throws NullPointerException {@inheritDoc}
103.505 + * @since 1.5
103.506 + */
103.507 + public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
103.508 + if (annotationClass == null)
103.509 + throw new NullPointerException();
103.510 +
103.511 + return null; // XXX (T) declaredAnnotations().get(annotationClass);
103.512 + }
103.513 +
103.514 + /**
103.515 + * @since 1.5
103.516 + */
103.517 + public Annotation[] getDeclaredAnnotations() {
103.518 + return new Annotation[0]; // XXX AnnotationParser.toArray(declaredAnnotations());
103.519 + }
103.520 +
103.521 + /**
103.522 + * Returns an array of arrays that represent the annotations on the formal
103.523 + * parameters, in declaration order, of the method represented by
103.524 + * this {@code Constructor} object. (Returns an array of length zero if the
103.525 + * underlying method is parameterless. If the method has one or more
103.526 + * parameters, a nested array of length zero is returned for each parameter
103.527 + * with no annotations.) The annotation objects contained in the returned
103.528 + * arrays are serializable. The caller of this method is free to modify
103.529 + * the returned arrays; it will have no effect on the arrays returned to
103.530 + * other callers.
103.531 + *
103.532 + * @return an array of arrays that represent the annotations on the formal
103.533 + * parameters, in declaration order, of the method represented by this
103.534 + * Constructor object
103.535 + * @since 1.5
103.536 + */
103.537 + public Annotation[][] getParameterAnnotations() {
103.538 + int numParameters = parameterTypes.length;
103.539 + if (parameterAnnotations == null)
103.540 + return new Annotation[numParameters][0];
103.541 +
103.542 + return new Annotation[numParameters][0]; // XXX
103.543 +/*
103.544 + Annotation[][] result = AnnotationParser.parseParameterAnnotations(
103.545 + parameterAnnotations,
103.546 + sun.misc.SharedSecrets.getJavaLangAccess().
103.547 + getConstantPool(getDeclaringClass()),
103.548 + getDeclaringClass());
103.549 + if (result.length != numParameters) {
103.550 + Class<?> declaringClass = getDeclaringClass();
103.551 + if (declaringClass.isEnum() ||
103.552 + declaringClass.isAnonymousClass() ||
103.553 + declaringClass.isLocalClass() )
103.554 + ; // Can't do reliable parameter counting
103.555 + else {
103.556 + if (!declaringClass.isMemberClass() || // top-level
103.557 + // Check for the enclosing instance parameter for
103.558 + // non-static member classes
103.559 + (declaringClass.isMemberClass() &&
103.560 + ((declaringClass.getModifiers() & Modifier.STATIC) == 0) &&
103.561 + result.length + 1 != numParameters) ) {
103.562 + throw new AnnotationFormatError(
103.563 + "Parameter annotations don't match number of parameters");
103.564 + }
103.565 + }
103.566 + }
103.567 + return result;
103.568 + */
103.569 + }
103.570 +}
104.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
104.2 +++ b/emul/mini/src/main/java/java/lang/reflect/InvocationHandler.java Sun Feb 17 17:58:34 2013 +0100
104.3 @@ -0,0 +1,95 @@
104.4 +/*
104.5 + * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved.
104.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
104.7 + *
104.8 + * This code is free software; you can redistribute it and/or modify it
104.9 + * under the terms of the GNU General Public License version 2 only, as
104.10 + * published by the Free Software Foundation. Oracle designates this
104.11 + * particular file as subject to the "Classpath" exception as provided
104.12 + * by Oracle in the LICENSE file that accompanied this code.
104.13 + *
104.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
104.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
104.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
104.17 + * version 2 for more details (a copy is included in the LICENSE file that
104.18 + * accompanied this code).
104.19 + *
104.20 + * You should have received a copy of the GNU General Public License version
104.21 + * 2 along with this work; if not, write to the Free Software Foundation,
104.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
104.23 + *
104.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
104.25 + * or visit www.oracle.com if you need additional information or have any
104.26 + * questions.
104.27 + */
104.28 +
104.29 +package java.lang.reflect;
104.30 +
104.31 +/**
104.32 + * {@code InvocationHandler} is the interface implemented by
104.33 + * the <i>invocation handler</i> of a proxy instance.
104.34 + *
104.35 + * <p>Each proxy instance has an associated invocation handler.
104.36 + * When a method is invoked on a proxy instance, the method
104.37 + * invocation is encoded and dispatched to the {@code invoke}
104.38 + * method of its invocation handler.
104.39 + *
104.40 + * @author Peter Jones
104.41 + * @see Proxy
104.42 + * @since 1.3
104.43 + */
104.44 +public interface InvocationHandler {
104.45 +
104.46 + /**
104.47 + * Processes a method invocation on a proxy instance and returns
104.48 + * the result. This method will be invoked on an invocation handler
104.49 + * when a method is invoked on a proxy instance that it is
104.50 + * associated with.
104.51 + *
104.52 + * @param proxy the proxy instance that the method was invoked on
104.53 + *
104.54 + * @param method the {@code Method} instance corresponding to
104.55 + * the interface method invoked on the proxy instance. The declaring
104.56 + * class of the {@code Method} object will be the interface that
104.57 + * the method was declared in, which may be a superinterface of the
104.58 + * proxy interface that the proxy class inherits the method through.
104.59 + *
104.60 + * @param args an array of objects containing the values of the
104.61 + * arguments passed in the method invocation on the proxy instance,
104.62 + * or {@code null} if interface method takes no arguments.
104.63 + * Arguments of primitive types are wrapped in instances of the
104.64 + * appropriate primitive wrapper class, such as
104.65 + * {@code java.lang.Integer} or {@code java.lang.Boolean}.
104.66 + *
104.67 + * @return the value to return from the method invocation on the
104.68 + * proxy instance. If the declared return type of the interface
104.69 + * method is a primitive type, then the value returned by
104.70 + * this method must be an instance of the corresponding primitive
104.71 + * wrapper class; otherwise, it must be a type assignable to the
104.72 + * declared return type. If the value returned by this method is
104.73 + * {@code null} and the interface method's return type is
104.74 + * primitive, then a {@code NullPointerException} will be
104.75 + * thrown by the method invocation on the proxy instance. If the
104.76 + * value returned by this method is otherwise not compatible with
104.77 + * the interface method's declared return type as described above,
104.78 + * a {@code ClassCastException} will be thrown by the method
104.79 + * invocation on the proxy instance.
104.80 + *
104.81 + * @throws Throwable the exception to throw from the method
104.82 + * invocation on the proxy instance. The exception's type must be
104.83 + * assignable either to any of the exception types declared in the
104.84 + * {@code throws} clause of the interface method or to the
104.85 + * unchecked exception types {@code java.lang.RuntimeException}
104.86 + * or {@code java.lang.Error}. If a checked exception is
104.87 + * thrown by this method that is not assignable to any of the
104.88 + * exception types declared in the {@code throws} clause of
104.89 + * the interface method, then an
104.90 + * {@link UndeclaredThrowableException} containing the
104.91 + * exception that was thrown by this method will be thrown by the
104.92 + * method invocation on the proxy instance.
104.93 + *
104.94 + * @see UndeclaredThrowableException
104.95 + */
104.96 + public Object invoke(Object proxy, Method method, Object[] args)
104.97 + throws Throwable;
104.98 +}
105.1 --- a/emul/mini/src/main/java/java/lang/reflect/Method.java Fri Jan 25 15:08:24 2013 +0100
105.2 +++ b/emul/mini/src/main/java/java/lang/reflect/Method.java Sun Feb 17 17:58:34 2013 +0100
105.3 @@ -533,7 +533,7 @@
105.4 + "} else {\n"
105.5 + " p = args;\n"
105.6 + "}\n"
105.7 - + "return method.fld_data.apply(self, p);\n"
105.8 + + "return method._data().apply(self, p);\n"
105.9 )
105.10 private static native Object invoke0(boolean isStatic, Method m, Object self, Object[] args);
105.11
105.12 @@ -648,8 +648,9 @@
105.13
105.14 @JavaScriptBody(args = { "ac" },
105.15 body =
105.16 - "if (this.fld_data.anno) {"
105.17 - + " return this.fld_data.anno['L' + ac.jvmName + ';'];"
105.18 + "var a = this._data().anno;"
105.19 + + "if (a) {"
105.20 + + " return a['L' + ac.jvmName + ';'];"
105.21 + "} else return null;"
105.22 )
105.23 private Object getAnnotationData(Class<?> annotationClass) {
106.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
106.2 +++ b/emul/mini/src/main/java/java/lang/reflect/Proxy.java Sun Feb 17 17:58:34 2013 +0100
106.3 @@ -0,0 +1,407 @@
106.4 +/*
106.5 + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
106.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
106.7 + *
106.8 + * This code is free software; you can redistribute it and/or modify it
106.9 + * under the terms of the GNU General Public License version 2 only, as
106.10 + * published by the Free Software Foundation. Oracle designates this
106.11 + * particular file as subject to the "Classpath" exception as provided
106.12 + * by Oracle in the LICENSE file that accompanied this code.
106.13 + *
106.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
106.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
106.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
106.17 + * version 2 for more details (a copy is included in the LICENSE file that
106.18 + * accompanied this code).
106.19 + *
106.20 + * You should have received a copy of the GNU General Public License version
106.21 + * 2 along with this work; if not, write to the Free Software Foundation,
106.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
106.23 + *
106.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
106.25 + * or visit www.oracle.com if you need additional information or have any
106.26 + * questions.
106.27 + */
106.28 +
106.29 +package java.lang.reflect;
106.30 +
106.31 +
106.32 +/**
106.33 + * {@code Proxy} provides static methods for creating dynamic proxy
106.34 + * classes and instances, and it is also the superclass of all
106.35 + * dynamic proxy classes created by those methods.
106.36 + *
106.37 + * <p>To create a proxy for some interface {@code Foo}:
106.38 + * <pre>
106.39 + * InvocationHandler handler = new MyInvocationHandler(...);
106.40 + * Class proxyClass = Proxy.getProxyClass(
106.41 + * Foo.class.getClassLoader(), new Class[] { Foo.class });
106.42 + * Foo f = (Foo) proxyClass.
106.43 + * getConstructor(new Class[] { InvocationHandler.class }).
106.44 + * newInstance(new Object[] { handler });
106.45 + * </pre>
106.46 + * or more simply:
106.47 + * <pre>
106.48 + * Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
106.49 + * new Class[] { Foo.class },
106.50 + * handler);
106.51 + * </pre>
106.52 + *
106.53 + * <p>A <i>dynamic proxy class</i> (simply referred to as a <i>proxy
106.54 + * class</i> below) is a class that implements a list of interfaces
106.55 + * specified at runtime when the class is created, with behavior as
106.56 + * described below.
106.57 + *
106.58 + * A <i>proxy interface</i> is such an interface that is implemented
106.59 + * by a proxy class.
106.60 + *
106.61 + * A <i>proxy instance</i> is an instance of a proxy class.
106.62 + *
106.63 + * Each proxy instance has an associated <i>invocation handler</i>
106.64 + * object, which implements the interface {@link InvocationHandler}.
106.65 + * A method invocation on a proxy instance through one of its proxy
106.66 + * interfaces will be dispatched to the {@link InvocationHandler#invoke
106.67 + * invoke} method of the instance's invocation handler, passing the proxy
106.68 + * instance, a {@code java.lang.reflect.Method} object identifying
106.69 + * the method that was invoked, and an array of type {@code Object}
106.70 + * containing the arguments. The invocation handler processes the
106.71 + * encoded method invocation as appropriate and the result that it
106.72 + * returns will be returned as the result of the method invocation on
106.73 + * the proxy instance.
106.74 + *
106.75 + * <p>A proxy class has the following properties:
106.76 + *
106.77 + * <ul>
106.78 + * <li>Proxy classes are public, final, and not abstract.
106.79 + *
106.80 + * <li>The unqualified name of a proxy class is unspecified. The space
106.81 + * of class names that begin with the string {@code "$Proxy"}
106.82 + * should be, however, reserved for proxy classes.
106.83 + *
106.84 + * <li>A proxy class extends {@code java.lang.reflect.Proxy}.
106.85 + *
106.86 + * <li>A proxy class implements exactly the interfaces specified at its
106.87 + * creation, in the same order.
106.88 + *
106.89 + * <li>If a proxy class implements a non-public interface, then it will
106.90 + * be defined in the same package as that interface. Otherwise, the
106.91 + * package of a proxy class is also unspecified. Note that package
106.92 + * sealing will not prevent a proxy class from being successfully defined
106.93 + * in a particular package at runtime, and neither will classes already
106.94 + * defined by the same class loader and the same package with particular
106.95 + * signers.
106.96 + *
106.97 + * <li>Since a proxy class implements all of the interfaces specified at
106.98 + * its creation, invoking {@code getInterfaces} on its
106.99 + * {@code Class} object will return an array containing the same
106.100 + * list of interfaces (in the order specified at its creation), invoking
106.101 + * {@code getMethods} on its {@code Class} object will return
106.102 + * an array of {@code Method} objects that include all of the
106.103 + * methods in those interfaces, and invoking {@code getMethod} will
106.104 + * find methods in the proxy interfaces as would be expected.
106.105 + *
106.106 + * <li>The {@link Proxy#isProxyClass Proxy.isProxyClass} method will
106.107 + * return true if it is passed a proxy class-- a class returned by
106.108 + * {@code Proxy.getProxyClass} or the class of an object returned by
106.109 + * {@code Proxy.newProxyInstance}-- and false otherwise.
106.110 + *
106.111 + * <li>The {@code java.security.ProtectionDomain} of a proxy class
106.112 + * is the same as that of system classes loaded by the bootstrap class
106.113 + * loader, such as {@code java.lang.Object}, because the code for a
106.114 + * proxy class is generated by trusted system code. This protection
106.115 + * domain will typically be granted
106.116 + * {@code java.security.AllPermission}.
106.117 + *
106.118 + * <li>Each proxy class has one public constructor that takes one argument,
106.119 + * an implementation of the interface {@link InvocationHandler}, to set
106.120 + * the invocation handler for a proxy instance. Rather than having to use
106.121 + * the reflection API to access the public constructor, a proxy instance
106.122 + * can be also be created by calling the {@link Proxy#newProxyInstance
106.123 + * Proxy.newProxyInstance} method, which combines the actions of calling
106.124 + * {@link Proxy#getProxyClass Proxy.getProxyClass} with invoking the
106.125 + * constructor with an invocation handler.
106.126 + * </ul>
106.127 + *
106.128 + * <p>A proxy instance has the following properties:
106.129 + *
106.130 + * <ul>
106.131 + * <li>Given a proxy instance {@code proxy} and one of the
106.132 + * interfaces implemented by its proxy class {@code Foo}, the
106.133 + * following expression will return true:
106.134 + * <pre>
106.135 + * {@code proxy instanceof Foo}
106.136 + * </pre>
106.137 + * and the following cast operation will succeed (rather than throwing
106.138 + * a {@code ClassCastException}):
106.139 + * <pre>
106.140 + * {@code (Foo) proxy}
106.141 + * </pre>
106.142 + *
106.143 + * <li>Each proxy instance has an associated invocation handler, the one
106.144 + * that was passed to its constructor. The static
106.145 + * {@link Proxy#getInvocationHandler Proxy.getInvocationHandler} method
106.146 + * will return the invocation handler associated with the proxy instance
106.147 + * passed as its argument.
106.148 + *
106.149 + * <li>An interface method invocation on a proxy instance will be
106.150 + * encoded and dispatched to the invocation handler's {@link
106.151 + * InvocationHandler#invoke invoke} method as described in the
106.152 + * documentation for that method.
106.153 + *
106.154 + * <li>An invocation of the {@code hashCode},
106.155 + * {@code equals}, or {@code toString} methods declared in
106.156 + * {@code java.lang.Object} on a proxy instance will be encoded and
106.157 + * dispatched to the invocation handler's {@code invoke} method in
106.158 + * the same manner as interface method invocations are encoded and
106.159 + * dispatched, as described above. The declaring class of the
106.160 + * {@code Method} object passed to {@code invoke} will be
106.161 + * {@code java.lang.Object}. Other public methods of a proxy
106.162 + * instance inherited from {@code java.lang.Object} are not
106.163 + * overridden by a proxy class, so invocations of those methods behave
106.164 + * like they do for instances of {@code java.lang.Object}.
106.165 + * </ul>
106.166 + *
106.167 + * <h3>Methods Duplicated in Multiple Proxy Interfaces</h3>
106.168 + *
106.169 + * <p>When two or more interfaces of a proxy class contain a method with
106.170 + * the same name and parameter signature, the order of the proxy class's
106.171 + * interfaces becomes significant. When such a <i>duplicate method</i>
106.172 + * is invoked on a proxy instance, the {@code Method} object passed
106.173 + * to the invocation handler will not necessarily be the one whose
106.174 + * declaring class is assignable from the reference type of the interface
106.175 + * that the proxy's method was invoked through. This limitation exists
106.176 + * because the corresponding method implementation in the generated proxy
106.177 + * class cannot determine which interface it was invoked through.
106.178 + * Therefore, when a duplicate method is invoked on a proxy instance,
106.179 + * the {@code Method} object for the method in the foremost interface
106.180 + * that contains the method (either directly or inherited through a
106.181 + * superinterface) in the proxy class's list of interfaces is passed to
106.182 + * the invocation handler's {@code invoke} method, regardless of the
106.183 + * reference type through which the method invocation occurred.
106.184 + *
106.185 + * <p>If a proxy interface contains a method with the same name and
106.186 + * parameter signature as the {@code hashCode}, {@code equals},
106.187 + * or {@code toString} methods of {@code java.lang.Object},
106.188 + * when such a method is invoked on a proxy instance, the
106.189 + * {@code Method} object passed to the invocation handler will have
106.190 + * {@code java.lang.Object} as its declaring class. In other words,
106.191 + * the public, non-final methods of {@code java.lang.Object}
106.192 + * logically precede all of the proxy interfaces for the determination of
106.193 + * which {@code Method} object to pass to the invocation handler.
106.194 + *
106.195 + * <p>Note also that when a duplicate method is dispatched to an
106.196 + * invocation handler, the {@code invoke} method may only throw
106.197 + * checked exception types that are assignable to one of the exception
106.198 + * types in the {@code throws} clause of the method in <i>all</i> of
106.199 + * the proxy interfaces that it can be invoked through. If the
106.200 + * {@code invoke} method throws a checked exception that is not
106.201 + * assignable to any of the exception types declared by the method in one
106.202 + * of the proxy interfaces that it can be invoked through, then an
106.203 + * unchecked {@code UndeclaredThrowableException} will be thrown by
106.204 + * the invocation on the proxy instance. This restriction means that not
106.205 + * all of the exception types returned by invoking
106.206 + * {@code getExceptionTypes} on the {@code Method} object
106.207 + * passed to the {@code invoke} method can necessarily be thrown
106.208 + * successfully by the {@code invoke} method.
106.209 + *
106.210 + * @author Peter Jones
106.211 + * @see InvocationHandler
106.212 + * @since 1.3
106.213 + */
106.214 +public class Proxy implements java.io.Serializable {
106.215 +
106.216 + private static final long serialVersionUID = -2222568056686623797L;
106.217 +
106.218 +
106.219 +
106.220 + /**
106.221 + * the invocation handler for this proxy instance.
106.222 + * @serial
106.223 + */
106.224 + protected InvocationHandler h;
106.225 +
106.226 + /**
106.227 + * Prohibits instantiation.
106.228 + */
106.229 + private Proxy() {
106.230 + }
106.231 +
106.232 + /**
106.233 + * Constructs a new {@code Proxy} instance from a subclass
106.234 + * (typically, a dynamic proxy class) with the specified value
106.235 + * for its invocation handler.
106.236 + *
106.237 + * @param h the invocation handler for this proxy instance
106.238 + */
106.239 + protected Proxy(InvocationHandler h) {
106.240 + this.h = h;
106.241 + }
106.242 +
106.243 + /**
106.244 + * Returns the {@code java.lang.Class} object for a proxy class
106.245 + * given a class loader and an array of interfaces. The proxy class
106.246 + * will be defined by the specified class loader and will implement
106.247 + * all of the supplied interfaces. If a proxy class for the same
106.248 + * permutation of interfaces has already been defined by the class
106.249 + * loader, then the existing proxy class will be returned; otherwise,
106.250 + * a proxy class for those interfaces will be generated dynamically
106.251 + * and defined by the class loader.
106.252 + *
106.253 + * <p>There are several restrictions on the parameters that may be
106.254 + * passed to {@code Proxy.getProxyClass}:
106.255 + *
106.256 + * <ul>
106.257 + * <li>All of the {@code Class} objects in the
106.258 + * {@code interfaces} array must represent interfaces, not
106.259 + * classes or primitive types.
106.260 + *
106.261 + * <li>No two elements in the {@code interfaces} array may
106.262 + * refer to identical {@code Class} objects.
106.263 + *
106.264 + * <li>All of the interface types must be visible by name through the
106.265 + * specified class loader. In other words, for class loader
106.266 + * {@code cl} and every interface {@code i}, the following
106.267 + * expression must be true:
106.268 + * <pre>
106.269 + * Class.forName(i.getName(), false, cl) == i
106.270 + * </pre>
106.271 + *
106.272 + * <li>All non-public interfaces must be in the same package;
106.273 + * otherwise, it would not be possible for the proxy class to
106.274 + * implement all of the interfaces, regardless of what package it is
106.275 + * defined in.
106.276 + *
106.277 + * <li>For any set of member methods of the specified interfaces
106.278 + * that have the same signature:
106.279 + * <ul>
106.280 + * <li>If the return type of any of the methods is a primitive
106.281 + * type or void, then all of the methods must have that same
106.282 + * return type.
106.283 + * <li>Otherwise, one of the methods must have a return type that
106.284 + * is assignable to all of the return types of the rest of the
106.285 + * methods.
106.286 + * </ul>
106.287 + *
106.288 + * <li>The resulting proxy class must not exceed any limits imposed
106.289 + * on classes by the virtual machine. For example, the VM may limit
106.290 + * the number of interfaces that a class may implement to 65535; in
106.291 + * that case, the size of the {@code interfaces} array must not
106.292 + * exceed 65535.
106.293 + * </ul>
106.294 + *
106.295 + * <p>If any of these restrictions are violated,
106.296 + * {@code Proxy.getProxyClass} will throw an
106.297 + * {@code IllegalArgumentException}. If the {@code interfaces}
106.298 + * array argument or any of its elements are {@code null}, a
106.299 + * {@code NullPointerException} will be thrown.
106.300 + *
106.301 + * <p>Note that the order of the specified proxy interfaces is
106.302 + * significant: two requests for a proxy class with the same combination
106.303 + * of interfaces but in a different order will result in two distinct
106.304 + * proxy classes.
106.305 + *
106.306 + * @param loader the class loader to define the proxy class
106.307 + * @param interfaces the list of interfaces for the proxy class
106.308 + * to implement
106.309 + * @return a proxy class that is defined in the specified class loader
106.310 + * and that implements the specified interfaces
106.311 + * @throws IllegalArgumentException if any of the restrictions on the
106.312 + * parameters that may be passed to {@code getProxyClass}
106.313 + * are violated
106.314 + * @throws NullPointerException if the {@code interfaces} array
106.315 + * argument or any of its elements are {@code null}
106.316 + */
106.317 + public static Class<?> getProxyClass(ClassLoader loader,
106.318 + Class<?>... interfaces)
106.319 + throws IllegalArgumentException
106.320 + {
106.321 + throw new IllegalArgumentException();
106.322 + }
106.323 +
106.324 + /**
106.325 + * Returns an instance of a proxy class for the specified interfaces
106.326 + * that dispatches method invocations to the specified invocation
106.327 + * handler. This method is equivalent to:
106.328 + * <pre>
106.329 + * Proxy.getProxyClass(loader, interfaces).
106.330 + * getConstructor(new Class[] { InvocationHandler.class }).
106.331 + * newInstance(new Object[] { handler });
106.332 + * </pre>
106.333 + *
106.334 + * <p>{@code Proxy.newProxyInstance} throws
106.335 + * {@code IllegalArgumentException} for the same reasons that
106.336 + * {@code Proxy.getProxyClass} does.
106.337 + *
106.338 + * @param loader the class loader to define the proxy class
106.339 + * @param interfaces the list of interfaces for the proxy class
106.340 + * to implement
106.341 + * @param h the invocation handler to dispatch method invocations to
106.342 + * @return a proxy instance with the specified invocation handler of a
106.343 + * proxy class that is defined by the specified class loader
106.344 + * and that implements the specified interfaces
106.345 + * @throws IllegalArgumentException if any of the restrictions on the
106.346 + * parameters that may be passed to {@code getProxyClass}
106.347 + * are violated
106.348 + * @throws NullPointerException if the {@code interfaces} array
106.349 + * argument or any of its elements are {@code null}, or
106.350 + * if the invocation handler, {@code h}, is
106.351 + * {@code null}
106.352 + */
106.353 + public static Object newProxyInstance(ClassLoader loader,
106.354 + Class<?>[] interfaces,
106.355 + InvocationHandler h)
106.356 + throws IllegalArgumentException
106.357 + {
106.358 + if (h == null) {
106.359 + throw new NullPointerException();
106.360 + }
106.361 + throw new IllegalArgumentException();
106.362 + }
106.363 +
106.364 + /**
106.365 + * Returns true if and only if the specified class was dynamically
106.366 + * generated to be a proxy class using the {@code getProxyClass}
106.367 + * method or the {@code newProxyInstance} method.
106.368 + *
106.369 + * <p>The reliability of this method is important for the ability
106.370 + * to use it to make security decisions, so its implementation should
106.371 + * not just test if the class in question extends {@code Proxy}.
106.372 + *
106.373 + * @param cl the class to test
106.374 + * @return {@code true} if the class is a proxy class and
106.375 + * {@code false} otherwise
106.376 + * @throws NullPointerException if {@code cl} is {@code null}
106.377 + */
106.378 + public static boolean isProxyClass(Class<?> cl) {
106.379 + if (cl == null) {
106.380 + throw new NullPointerException();
106.381 + }
106.382 +
106.383 + return false;
106.384 + }
106.385 +
106.386 + /**
106.387 + * Returns the invocation handler for the specified proxy instance.
106.388 + *
106.389 + * @param proxy the proxy instance to return the invocation handler for
106.390 + * @return the invocation handler for the proxy instance
106.391 + * @throws IllegalArgumentException if the argument is not a
106.392 + * proxy instance
106.393 + */
106.394 + public static InvocationHandler getInvocationHandler(Object proxy)
106.395 + throws IllegalArgumentException
106.396 + {
106.397 + /*
106.398 + * Verify that the object is actually a proxy instance.
106.399 + */
106.400 + if (!isProxyClass(proxy.getClass())) {
106.401 + throw new IllegalArgumentException("not a proxy instance");
106.402 + }
106.403 +
106.404 + Proxy p = (Proxy) proxy;
106.405 + return p.h;
106.406 + }
106.407 +
106.408 + private static native Class defineClass0(ClassLoader loader, String name,
106.409 + byte[] b, int off, int len);
106.410 +}
107.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
107.2 +++ b/emul/mini/src/main/java/java/lang/reflect/UndeclaredThrowableException.java Sun Feb 17 17:58:34 2013 +0100
107.3 @@ -0,0 +1,119 @@
107.4 +/*
107.5 + * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved.
107.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
107.7 + *
107.8 + * This code is free software; you can redistribute it and/or modify it
107.9 + * under the terms of the GNU General Public License version 2 only, as
107.10 + * published by the Free Software Foundation. Oracle designates this
107.11 + * particular file as subject to the "Classpath" exception as provided
107.12 + * by Oracle in the LICENSE file that accompanied this code.
107.13 + *
107.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
107.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
107.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
107.17 + * version 2 for more details (a copy is included in the LICENSE file that
107.18 + * accompanied this code).
107.19 + *
107.20 + * You should have received a copy of the GNU General Public License version
107.21 + * 2 along with this work; if not, write to the Free Software Foundation,
107.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
107.23 + *
107.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
107.25 + * or visit www.oracle.com if you need additional information or have any
107.26 + * questions.
107.27 + */
107.28 +
107.29 +package java.lang.reflect;
107.30 +
107.31 +/**
107.32 + * Thrown by a method invocation on a proxy instance if its invocation
107.33 + * handler's {@link InvocationHandler#invoke invoke} method throws a
107.34 + * checked exception (a {@code Throwable} that is not assignable
107.35 + * to {@code RuntimeException} or {@code Error}) that
107.36 + * is not assignable to any of the exception types declared in the
107.37 + * {@code throws} clause of the method that was invoked on the
107.38 + * proxy instance and dispatched to the invocation handler.
107.39 + *
107.40 + * <p>An {@code UndeclaredThrowableException} instance contains
107.41 + * the undeclared checked exception that was thrown by the invocation
107.42 + * handler, and it can be retrieved with the
107.43 + * {@code getUndeclaredThrowable()} method.
107.44 + * {@code UndeclaredThrowableException} extends
107.45 + * {@code RuntimeException}, so it is an unchecked exception
107.46 + * that wraps a checked exception.
107.47 + *
107.48 + * <p>As of release 1.4, this exception has been retrofitted to
107.49 + * conform to the general purpose exception-chaining mechanism. The
107.50 + * "undeclared checked exception that was thrown by the invocation
107.51 + * handler" that may be provided at construction time and accessed via
107.52 + * the {@link #getUndeclaredThrowable()} method is now known as the
107.53 + * <i>cause</i>, and may be accessed via the {@link
107.54 + * Throwable#getCause()} method, as well as the aforementioned "legacy
107.55 + * method."
107.56 + *
107.57 + * @author Peter Jones
107.58 + * @see InvocationHandler
107.59 + * @since 1.3
107.60 + */
107.61 +public class UndeclaredThrowableException extends RuntimeException {
107.62 + static final long serialVersionUID = 330127114055056639L;
107.63 +
107.64 + /**
107.65 + * the undeclared checked exception that was thrown
107.66 + * @serial
107.67 + */
107.68 + private Throwable undeclaredThrowable;
107.69 +
107.70 + /**
107.71 + * Constructs an {@code UndeclaredThrowableException} with the
107.72 + * specified {@code Throwable}.
107.73 + *
107.74 + * @param undeclaredThrowable the undeclared checked exception
107.75 + * that was thrown
107.76 + */
107.77 + public UndeclaredThrowableException(Throwable undeclaredThrowable) {
107.78 + super((Throwable) null); // Disallow initCause
107.79 + this.undeclaredThrowable = undeclaredThrowable;
107.80 + }
107.81 +
107.82 + /**
107.83 + * Constructs an {@code UndeclaredThrowableException} with the
107.84 + * specified {@code Throwable} and a detail message.
107.85 + *
107.86 + * @param undeclaredThrowable the undeclared checked exception
107.87 + * that was thrown
107.88 + * @param s the detail message
107.89 + */
107.90 + public UndeclaredThrowableException(Throwable undeclaredThrowable,
107.91 + String s)
107.92 + {
107.93 + super(s, null); // Disallow initCause
107.94 + this.undeclaredThrowable = undeclaredThrowable;
107.95 + }
107.96 +
107.97 + /**
107.98 + * Returns the {@code Throwable} instance wrapped in this
107.99 + * {@code UndeclaredThrowableException}, which may be {@code null}.
107.100 + *
107.101 + * <p>This method predates the general-purpose exception chaining facility.
107.102 + * The {@link Throwable#getCause()} method is now the preferred means of
107.103 + * obtaining this information.
107.104 + *
107.105 + * @return the undeclared checked exception that was thrown
107.106 + */
107.107 + public Throwable getUndeclaredThrowable() {
107.108 + return undeclaredThrowable;
107.109 + }
107.110 +
107.111 + /**
107.112 + * Returns the cause of this exception (the {@code Throwable}
107.113 + * instance wrapped in this {@code UndeclaredThrowableException},
107.114 + * which may be {@code null}).
107.115 + *
107.116 + * @return the cause of this exception.
107.117 + * @since 1.4
107.118 + */
107.119 + public Throwable getCause() {
107.120 + return undeclaredThrowable;
107.121 + }
107.122 +}
108.1 --- a/emul/mini/src/main/java/java/net/URL.java Fri Jan 25 15:08:24 2013 +0100
108.2 +++ b/emul/mini/src/main/java/java/net/URL.java Sun Feb 17 17:58:34 2013 +0100
108.3 @@ -25,10 +25,12 @@
108.4
108.5 package java.net;
108.6
108.7 +import java.io.ByteArrayInputStream;
108.8 import java.io.IOException;
108.9 import java.io.InputStream;
108.10 import org.apidesign.bck2brwsr.core.JavaScriptBody;
108.11
108.12 +
108.13 /**
108.14 * Class <code>URL</code> represents a Uniform Resource
108.15 * Locator, a pointer to a "resource" on the World
108.16 @@ -212,6 +214,9 @@
108.17 * @serial
108.18 */
108.19 private int hashCode = -1;
108.20 +
108.21 + /** input stream associated with the URL */
108.22 + private InputStream is;
108.23
108.24 /**
108.25 * Creates a <code>URL</code> object from the specified
108.26 @@ -421,6 +426,11 @@
108.27 public URL(String spec) throws MalformedURLException {
108.28 this(null, spec);
108.29 }
108.30 +
108.31 + private URL(String spec, InputStream is) throws MalformedURLException {
108.32 + this(null, spec);
108.33 + this.is = is;
108.34 + }
108.35
108.36 /**
108.37 * Creates a URL by parsing the given spec within a specified context.
108.38 @@ -496,6 +506,17 @@
108.39 public URL(URL context, String spec, URLStreamHandler handler)
108.40 throws MalformedURLException
108.41 {
108.42 + this(findContext(context), spec, handler != null);
108.43 + }
108.44 +
108.45 + private URL(URL context, String spec, boolean ishandler)
108.46 + throws MalformedURLException {
108.47 + // Check for permission to specify a handler
108.48 + if (ishandler) {
108.49 + throw new SecurityException();
108.50 + }
108.51 + URLStreamHandler handler = null;
108.52 +
108.53 String original = spec;
108.54 int i, limit, c;
108.55 int start = 0;
108.56 @@ -503,10 +524,6 @@
108.57 boolean aRef=false;
108.58 boolean isRelative = false;
108.59
108.60 - // Check for permission to specify a handler
108.61 - if (handler != null) {
108.62 - throw new SecurityException();
108.63 - }
108.64
108.65 try {
108.66 limit = spec.length();
108.67 @@ -950,8 +967,14 @@
108.68 * @see java.net.URLConnection#getInputStream()
108.69 */
108.70 public final InputStream openStream() throws java.io.IOException {
108.71 - throw new IOException();
108.72 -// return openConnection().getInputStream();
108.73 + if (is != null) {
108.74 + return is;
108.75 + }
108.76 + byte[] arr = (byte[]) getContent(new Class[] { byte[].class });
108.77 + if (arr == null) {
108.78 + throw new IOException();
108.79 + }
108.80 + return new ByteArrayInputStream(arr);
108.81 }
108.82
108.83 /**
108.84 @@ -976,6 +999,17 @@
108.85 )
108.86 private static native String loadText(String url) throws IOException;
108.87
108.88 + @JavaScriptBody(args = { "url", "arr" }, body = ""
108.89 + + "var request = new XMLHttpRequest();\n"
108.90 + + "request.open('GET', url, false);\n"
108.91 + + "request.overrideMimeType('text\\/plain; charset=x-user-defined');\n"
108.92 + + "request.send();\n"
108.93 + + "var t = request.responseText;\n"
108.94 + + "for (var i = 0; i < t.length; i++) arr.push(t.charCodeAt(i) & 0xff);\n"
108.95 + + "return arr;\n"
108.96 + )
108.97 + private static native Object loadBytes(String url, byte[] arr) throws IOException;
108.98 +
108.99 /**
108.100 * Gets the contents of this URL. This method is a shorthand for:
108.101 * <blockquote><pre>
108.102 @@ -994,7 +1028,10 @@
108.103 throws java.io.IOException {
108.104 for (Class<?> c : classes) {
108.105 if (c == String.class) {
108.106 - return getContent();
108.107 + return loadText(toExternalForm());
108.108 + }
108.109 + if (c == byte[].class) {
108.110 + return loadBytes(toExternalForm(), new byte[0]);
108.111 }
108.112 }
108.113 return null;
108.114 @@ -1005,8 +1042,24 @@
108.115 return universal;
108.116 }
108.117
108.118 + private static URL findContext(URL context) throws MalformedURLException {
108.119 + if (context == null) {
108.120 + String base = findBaseURL();
108.121 + if (base != null) {
108.122 + context = new URL(null, base, false);
108.123 + }
108.124 + }
108.125 + return context;
108.126 + }
108.127 +
108.128 + @JavaScriptBody(args = {}, body =
108.129 + "if (typeof window !== 'object') return null;\n"
108.130 + + "if (!window.location) return null;\n"
108.131 + + "if (!window.location.href) return null;\n"
108.132 + + "return window.location.href;\n"
108.133 + )
108.134 + private static native String findBaseURL();
108.135 }
108.136 -
108.137 class Parts {
108.138 String path, query, ref;
108.139
109.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
109.2 +++ b/emul/mini/src/main/java/java/util/zip/Adler32.java Sun Feb 17 17:58:34 2013 +0100
109.3 @@ -0,0 +1,205 @@
109.4 +/* Adler32.java - Computes Adler32 data checksum of a data stream
109.5 + Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
109.6 +
109.7 +This file is part of GNU Classpath.
109.8 +
109.9 +GNU Classpath is free software; you can redistribute it and/or modify
109.10 +it under the terms of the GNU General Public License as published by
109.11 +the Free Software Foundation; either version 2, or (at your option)
109.12 +any later version.
109.13 +
109.14 +GNU Classpath is distributed in the hope that it will be useful, but
109.15 +WITHOUT ANY WARRANTY; without even the implied warranty of
109.16 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
109.17 +General Public License for more details.
109.18 +
109.19 +You should have received a copy of the GNU General Public License
109.20 +along with GNU Classpath; see the file COPYING. If not, write to the
109.21 +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
109.22 +02111-1307 USA.
109.23 +
109.24 +Linking this library statically or dynamically with other modules is
109.25 +making a combined work based on this library. Thus, the terms and
109.26 +conditions of the GNU General Public License cover the whole
109.27 +combination.
109.28 +
109.29 +As a special exception, the copyright holders of this library give you
109.30 +permission to link this library with independent modules to produce an
109.31 +executable, regardless of the license terms of these independent
109.32 +modules, and to copy and distribute the resulting executable under
109.33 +terms of your choice, provided that you also meet, for each linked
109.34 +independent module, the terms and conditions of the license of that
109.35 +module. An independent module is a module which is not derived from
109.36 +or based on this library. If you modify this library, you may extend
109.37 +this exception to your version of the library, but you are not
109.38 +obligated to do so. If you do not wish to do so, delete this
109.39 +exception statement from your version. */
109.40 +
109.41 +package java.util.zip;
109.42 +
109.43 +/*
109.44 + * Written using on-line Java Platform 1.2 API Specification, as well
109.45 + * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
109.46 + * The actual Adler32 algorithm is taken from RFC 1950.
109.47 + * Status: Believed complete and correct.
109.48 + */
109.49 +
109.50 +/**
109.51 + * Computes Adler32 checksum for a stream of data. An Adler32
109.52 + * checksum is not as reliable as a CRC32 checksum, but a lot faster to
109.53 + * compute.
109.54 + *<p>
109.55 + * The specification for Adler32 may be found in RFC 1950.
109.56 + * (ZLIB Compressed Data Format Specification version 3.3)
109.57 + *<p>
109.58 + *<p>
109.59 + * From that document:
109.60 + *<p>
109.61 + * "ADLER32 (Adler-32 checksum)
109.62 + * This contains a checksum value of the uncompressed data
109.63 + * (excluding any dictionary data) computed according to Adler-32
109.64 + * algorithm. This algorithm is a 32-bit extension and improvement
109.65 + * of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073
109.66 + * standard.
109.67 + *<p>
109.68 + * Adler-32 is composed of two sums accumulated per byte: s1 is
109.69 + * the sum of all bytes, s2 is the sum of all s1 values. Both sums
109.70 + * are done modulo 65521. s1 is initialized to 1, s2 to zero. The
109.71 + * Adler-32 checksum is stored as s2*65536 + s1 in most-
109.72 + * significant-byte first (network) order."
109.73 + *<p>
109.74 + * "8.2. The Adler-32 algorithm
109.75 + *<p>
109.76 + * The Adler-32 algorithm is much faster than the CRC32 algorithm yet
109.77 + * still provides an extremely low probability of undetected errors.
109.78 + *<p>
109.79 + * The modulo on unsigned long accumulators can be delayed for 5552
109.80 + * bytes, so the modulo operation time is negligible. If the bytes
109.81 + * are a, b, c, the second sum is 3a + 2b + c + 3, and so is position
109.82 + * and order sensitive, unlike the first sum, which is just a
109.83 + * checksum. That 65521 is prime is important to avoid a possible
109.84 + * large class of two-byte errors that leave the check unchanged.
109.85 + * (The Fletcher checksum uses 255, which is not prime and which also
109.86 + * makes the Fletcher check insensitive to single byte changes 0 <->
109.87 + * 255.)
109.88 + *<p>
109.89 + * The sum s1 is initialized to 1 instead of zero to make the length
109.90 + * of the sequence part of s2, so that the length does not have to be
109.91 + * checked separately. (Any sequence of zeroes has a Fletcher
109.92 + * checksum of zero.)"
109.93 + *
109.94 + * @author John Leuner, Per Bothner
109.95 + * @since JDK 1.1
109.96 + *
109.97 + * @see InflaterInputStream
109.98 + * @see DeflaterOutputStream
109.99 + */
109.100 +public class Adler32 implements Checksum
109.101 +{
109.102 +
109.103 + /** largest prime smaller than 65536 */
109.104 + private static final int BASE = 65521;
109.105 +
109.106 + private int checksum; //we do all in int.
109.107 +
109.108 + //Note that java doesn't have unsigned integers,
109.109 + //so we have to be careful with what arithmetic
109.110 + //we do. We return the checksum as a long to
109.111 + //avoid sign confusion.
109.112 +
109.113 + /**
109.114 + * Creates a new instance of the <code>Adler32</code> class.
109.115 + * The checksum starts off with a value of 1.
109.116 + */
109.117 + public Adler32 ()
109.118 + {
109.119 + reset();
109.120 + }
109.121 +
109.122 + /**
109.123 + * Resets the Adler32 checksum to the initial value.
109.124 + */
109.125 + public void reset ()
109.126 + {
109.127 + checksum = 1; //Initialize to 1
109.128 + }
109.129 +
109.130 + /**
109.131 + * Updates the checksum with the byte b.
109.132 + *
109.133 + * @param bval the data value to add. The high byte of the int is ignored.
109.134 + */
109.135 + public void update (int bval)
109.136 + {
109.137 + //We could make a length 1 byte array and call update again, but I
109.138 + //would rather not have that overhead
109.139 + int s1 = checksum & 0xffff;
109.140 + int s2 = checksum >>> 16;
109.141 +
109.142 + s1 = (s1 + (bval & 0xFF)) % BASE;
109.143 + s2 = (s1 + s2) % BASE;
109.144 +
109.145 + checksum = (s2 << 16) + s1;
109.146 + }
109.147 +
109.148 + /**
109.149 + * Updates the checksum with the bytes taken from the array.
109.150 + *
109.151 + * @param buffer an array of bytes
109.152 + */
109.153 + public void update (byte[] buffer)
109.154 + {
109.155 + update(buffer, 0, buffer.length);
109.156 + }
109.157 +
109.158 + /**
109.159 + * Updates the checksum with the bytes taken from the array.
109.160 + *
109.161 + * @param buf an array of bytes
109.162 + * @param off the start of the data used for this update
109.163 + * @param len the number of bytes to use for this update
109.164 + */
109.165 + public void update (byte[] buf, int off, int len)
109.166 + {
109.167 + //(By Per Bothner)
109.168 + int s1 = checksum & 0xffff;
109.169 + int s2 = checksum >>> 16;
109.170 +
109.171 + while (len > 0)
109.172 + {
109.173 + // We can defer the modulo operation:
109.174 + // s1 maximally grows from 65521 to 65521 + 255 * 3800
109.175 + // s2 maximally grows by 3800 * median(s1) = 2090079800 < 2^31
109.176 + int n = 3800;
109.177 + if (n > len)
109.178 + n = len;
109.179 + len -= n;
109.180 + while (--n >= 0)
109.181 + {
109.182 + s1 = s1 + (buf[off++] & 0xFF);
109.183 + s2 = s2 + s1;
109.184 + }
109.185 + s1 %= BASE;
109.186 + s2 %= BASE;
109.187 + }
109.188 +
109.189 + /*Old implementation, borrowed from somewhere:
109.190 + int n;
109.191 +
109.192 + while (len-- > 0) {
109.193 +
109.194 + s1 = (s1 + (bs[offset++] & 0xff)) % BASE;
109.195 + s2 = (s2 + s1) % BASE;
109.196 + }*/
109.197 +
109.198 + checksum = (s2 << 16) | s1;
109.199 + }
109.200 +
109.201 + /**
109.202 + * Returns the Adler32 data checksum computed so far.
109.203 + */
109.204 + public long getValue()
109.205 + {
109.206 + return (long) checksum & 0xffffffffL;
109.207 + }
109.208 +}
110.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
110.2 +++ b/emul/mini/src/main/java/java/util/zip/CRC32.java Sun Feb 17 17:58:34 2013 +0100
110.3 @@ -0,0 +1,132 @@
110.4 +/* CRC32.java - Computes CRC32 data checksum of a data stream
110.5 + Copyright (C) 1999. 2000, 2001 Free Software Foundation, Inc.
110.6 +
110.7 +This file is part of GNU Classpath.
110.8 +
110.9 +GNU Classpath is free software; you can redistribute it and/or modify
110.10 +it under the terms of the GNU General Public License as published by
110.11 +the Free Software Foundation; either version 2, or (at your option)
110.12 +any later version.
110.13 +
110.14 +GNU Classpath is distributed in the hope that it will be useful, but
110.15 +WITHOUT ANY WARRANTY; without even the implied warranty of
110.16 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
110.17 +General Public License for more details.
110.18 +
110.19 +You should have received a copy of the GNU General Public License
110.20 +along with GNU Classpath; see the file COPYING. If not, write to the
110.21 +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
110.22 +02111-1307 USA.
110.23 +
110.24 +Linking this library statically or dynamically with other modules is
110.25 +making a combined work based on this library. Thus, the terms and
110.26 +conditions of the GNU General Public License cover the whole
110.27 +combination.
110.28 +
110.29 +As a special exception, the copyright holders of this library give you
110.30 +permission to link this library with independent modules to produce an
110.31 +executable, regardless of the license terms of these independent
110.32 +modules, and to copy and distribute the resulting executable under
110.33 +terms of your choice, provided that you also meet, for each linked
110.34 +independent module, the terms and conditions of the license of that
110.35 +module. An independent module is a module which is not derived from
110.36 +or based on this library. If you modify this library, you may extend
110.37 +this exception to your version of the library, but you are not
110.38 +obligated to do so. If you do not wish to do so, delete this
110.39 +exception statement from your version. */
110.40 +
110.41 +package java.util.zip;
110.42 +
110.43 +/*
110.44 + * Written using on-line Java Platform 1.2 API Specification, as well
110.45 + * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
110.46 + * The actual CRC32 algorithm is taken from RFC 1952.
110.47 + * Status: Believed complete and correct.
110.48 + */
110.49 +
110.50 +/**
110.51 + * Computes CRC32 data checksum of a data stream.
110.52 + * The actual CRC32 algorithm is described in RFC 1952
110.53 + * (GZIP file format specification version 4.3).
110.54 + * Can be used to get the CRC32 over a stream if used with checked input/output
110.55 + * streams.
110.56 + *
110.57 + * @see InflaterInputStream
110.58 + * @see DeflaterOutputStream
110.59 + *
110.60 + * @author Per Bothner
110.61 + * @date April 1, 1999.
110.62 + */
110.63 +public class CRC32 implements Checksum
110.64 +{
110.65 + /** The crc data checksum so far. */
110.66 + private int crc = 0;
110.67 +
110.68 + /** The fast CRC table. Computed once when the CRC32 class is loaded. */
110.69 + private static int[] crc_table = make_crc_table();
110.70 +
110.71 + /** Make the table for a fast CRC. */
110.72 + private static int[] make_crc_table ()
110.73 + {
110.74 + int[] crc_table = new int[256];
110.75 + for (int n = 0; n < 256; n++)
110.76 + {
110.77 + int c = n;
110.78 + for (int k = 8; --k >= 0; )
110.79 + {
110.80 + if ((c & 1) != 0)
110.81 + c = 0xedb88320 ^ (c >>> 1);
110.82 + else
110.83 + c = c >>> 1;
110.84 + }
110.85 + crc_table[n] = c;
110.86 + }
110.87 + return crc_table;
110.88 + }
110.89 +
110.90 + /**
110.91 + * Returns the CRC32 data checksum computed so far.
110.92 + */
110.93 + public long getValue ()
110.94 + {
110.95 + return (long) crc & 0xffffffffL;
110.96 + }
110.97 +
110.98 + /**
110.99 + * Resets the CRC32 data checksum as if no update was ever called.
110.100 + */
110.101 + public void reset () { crc = 0; }
110.102 +
110.103 + /**
110.104 + * Updates the checksum with the int bval.
110.105 + *
110.106 + * @param bval (the byte is taken as the lower 8 bits of bval)
110.107 + */
110.108 +
110.109 + public void update (int bval)
110.110 + {
110.111 + int c = ~crc;
110.112 + c = crc_table[(c ^ bval) & 0xff] ^ (c >>> 8);
110.113 + crc = ~c;
110.114 + }
110.115 +
110.116 + /**
110.117 + * Adds the byte array to the data checksum.
110.118 + *
110.119 + * @param buf the buffer which contains the data
110.120 + * @param off the offset in the buffer where the data starts
110.121 + * @param len the length of the data
110.122 + */
110.123 + public void update (byte[] buf, int off, int len)
110.124 + {
110.125 + int c = ~crc;
110.126 + while (--len >= 0)
110.127 + c = crc_table[(c ^ buf[off++]) & 0xff] ^ (c >>> 8);
110.128 + crc = ~c;
110.129 + }
110.130 +
110.131 + /**
110.132 + * Adds the complete byte array to the data checksum.
110.133 + */
110.134 + public void update (byte[] buf) { update(buf, 0, buf.length); }
110.135 +}
111.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
111.2 +++ b/emul/mini/src/main/java/java/util/zip/Checksum.java Sun Feb 17 17:58:34 2013 +0100
111.3 @@ -0,0 +1,60 @@
111.4 +/*
111.5 + * Copyright (c) 1996, 1999, Oracle and/or its affiliates. All rights reserved.
111.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
111.7 + *
111.8 + * This code is free software; you can redistribute it and/or modify it
111.9 + * under the terms of the GNU General Public License version 2 only, as
111.10 + * published by the Free Software Foundation. Oracle designates this
111.11 + * particular file as subject to the "Classpath" exception as provided
111.12 + * by Oracle in the LICENSE file that accompanied this code.
111.13 + *
111.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
111.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
111.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
111.17 + * version 2 for more details (a copy is included in the LICENSE file that
111.18 + * accompanied this code).
111.19 + *
111.20 + * You should have received a copy of the GNU General Public License version
111.21 + * 2 along with this work; if not, write to the Free Software Foundation,
111.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
111.23 + *
111.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
111.25 + * or visit www.oracle.com if you need additional information or have any
111.26 + * questions.
111.27 + */
111.28 +
111.29 +package java.util.zip;
111.30 +
111.31 +/**
111.32 + * An interface representing a data checksum.
111.33 + *
111.34 + * @author David Connelly
111.35 + */
111.36 +public
111.37 +interface Checksum {
111.38 + /**
111.39 + * Updates the current checksum with the specified byte.
111.40 + *
111.41 + * @param b the byte to update the checksum with
111.42 + */
111.43 + public void update(int b);
111.44 +
111.45 + /**
111.46 + * Updates the current checksum with the specified array of bytes.
111.47 + * @param b the byte array to update the checksum with
111.48 + * @param off the start offset of the data
111.49 + * @param len the number of bytes to use for the update
111.50 + */
111.51 + public void update(byte[] b, int off, int len);
111.52 +
111.53 + /**
111.54 + * Returns the current checksum value.
111.55 + * @return the current checksum value
111.56 + */
111.57 + public long getValue();
111.58 +
111.59 + /**
111.60 + * Resets the checksum to its initial value.
111.61 + */
111.62 + public void reset();
111.63 +}
112.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
112.2 +++ b/emul/mini/src/main/java/java/util/zip/DataFormatException.java Sun Feb 17 17:58:34 2013 +0100
112.3 @@ -0,0 +1,52 @@
112.4 +/*
112.5 + * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
112.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
112.7 + *
112.8 + * This code is free software; you can redistribute it and/or modify it
112.9 + * under the terms of the GNU General Public License version 2 only, as
112.10 + * published by the Free Software Foundation. Oracle designates this
112.11 + * particular file as subject to the "Classpath" exception as provided
112.12 + * by Oracle in the LICENSE file that accompanied this code.
112.13 + *
112.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
112.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
112.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
112.17 + * version 2 for more details (a copy is included in the LICENSE file that
112.18 + * accompanied this code).
112.19 + *
112.20 + * You should have received a copy of the GNU General Public License version
112.21 + * 2 along with this work; if not, write to the Free Software Foundation,
112.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
112.23 + *
112.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
112.25 + * or visit www.oracle.com if you need additional information or have any
112.26 + * questions.
112.27 + */
112.28 +
112.29 +package java.util.zip;
112.30 +
112.31 +/**
112.32 + * Signals that a data format error has occurred.
112.33 + *
112.34 + * @author David Connelly
112.35 + */
112.36 +public
112.37 +class DataFormatException extends Exception {
112.38 + private static final long serialVersionUID = 2219632870893641452L;
112.39 +
112.40 + /**
112.41 + * Constructs a DataFormatException with no detail message.
112.42 + */
112.43 + public DataFormatException() {
112.44 + super();
112.45 + }
112.46 +
112.47 + /**
112.48 + * Constructs a DataFormatException with the specified detail message.
112.49 + * A detail message is a String that describes this particular exception.
112.50 + * @param s the String containing a detail message
112.51 + */
112.52 + public DataFormatException(String s) {
112.53 + super(s);
112.54 + }
112.55 +}
113.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
113.2 +++ b/emul/mini/src/main/java/java/util/zip/Inflater.java Sun Feb 17 17:58:34 2013 +0100
113.3 @@ -0,0 +1,310 @@
113.4 +/*
113.5 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
113.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
113.7 + *
113.8 + * This code is free software; you can redistribute it and/or modify it
113.9 + * under the terms of the GNU General Public License version 2 only, as
113.10 + * published by the Free Software Foundation. Oracle designates this
113.11 + * particular file as subject to the "Classpath" exception as provided
113.12 + * by Oracle in the LICENSE file that accompanied this code.
113.13 + *
113.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
113.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
113.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
113.17 + * version 2 for more details (a copy is included in the LICENSE file that
113.18 + * accompanied this code).
113.19 + *
113.20 + * You should have received a copy of the GNU General Public License version
113.21 + * 2 along with this work; if not, write to the Free Software Foundation,
113.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
113.23 + *
113.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
113.25 + * or visit www.oracle.com if you need additional information or have any
113.26 + * questions.
113.27 + */
113.28 +
113.29 +package java.util.zip;
113.30 +
113.31 +/**
113.32 + * This class provides support for general purpose decompression using the
113.33 + * popular ZLIB compression library. The ZLIB compression library was
113.34 + * initially developed as part of the PNG graphics standard and is not
113.35 + * protected by patents. It is fully described in the specifications at
113.36 + * the <a href="package-summary.html#package_description">java.util.zip
113.37 + * package description</a>.
113.38 + *
113.39 + * <p>The following code fragment demonstrates a trivial compression
113.40 + * and decompression of a string using <tt>Deflater</tt> and
113.41 + * <tt>Inflater</tt>.
113.42 + *
113.43 + * <blockquote><pre>
113.44 + * try {
113.45 + * // Encode a String into bytes
113.46 + * String inputString = "blahblahblah\u20AC\u20AC";
113.47 + * byte[] input = inputString.getBytes("UTF-8");
113.48 + *
113.49 + * // Compress the bytes
113.50 + * byte[] output = new byte[100];
113.51 + * Deflater compresser = new Deflater();
113.52 + * compresser.setInput(input);
113.53 + * compresser.finish();
113.54 + * int compressedDataLength = compresser.deflate(output);
113.55 + *
113.56 + * // Decompress the bytes
113.57 + * Inflater decompresser = new Inflater();
113.58 + * decompresser.setInput(output, 0, compressedDataLength);
113.59 + * byte[] result = new byte[100];
113.60 + * int resultLength = decompresser.inflate(result);
113.61 + * decompresser.end();
113.62 + *
113.63 + * // Decode the bytes into a String
113.64 + * String outputString = new String(result, 0, resultLength, "UTF-8");
113.65 + * } catch(java.io.UnsupportedEncodingException ex) {
113.66 + * // handle
113.67 + * } catch (java.util.zip.DataFormatException ex) {
113.68 + * // handle
113.69 + * }
113.70 + * </pre></blockquote>
113.71 + *
113.72 + * @see Deflater
113.73 + * @author David Connelly
113.74 + *
113.75 + */
113.76 +public
113.77 +class Inflater {
113.78 + private final org.apidesign.bck2brwsr.emul.zip.Inflater impl;
113.79 +
113.80 + /**
113.81 + * Creates a new decompressor. If the parameter 'nowrap' is true then
113.82 + * the ZLIB header and checksum fields will not be used. This provides
113.83 + * compatibility with the compression format used by both GZIP and PKZIP.
113.84 + * <p>
113.85 + * Note: When using the 'nowrap' option it is also necessary to provide
113.86 + * an extra "dummy" byte as input. This is required by the ZLIB native
113.87 + * library in order to support certain optimizations.
113.88 + *
113.89 + * @param nowrap if true then support GZIP compatible compression
113.90 + */
113.91 + public Inflater(boolean nowrap) {
113.92 + if (getClass() == org.apidesign.bck2brwsr.emul.zip.Inflater.class) {
113.93 + impl = null;
113.94 + } else {
113.95 + impl = new org.apidesign.bck2brwsr.emul.zip.Inflater(nowrap);
113.96 + }
113.97 + }
113.98 +
113.99 + /**
113.100 + * Creates a new decompressor.
113.101 + */
113.102 + public Inflater() {
113.103 + this(false);
113.104 + }
113.105 +
113.106 + /**
113.107 + * Sets input data for decompression. Should be called whenever
113.108 + * needsInput() returns true indicating that more input data is
113.109 + * required.
113.110 + * @param b the input data bytes
113.111 + * @param off the start offset of the input data
113.112 + * @param len the length of the input data
113.113 + * @see Inflater#needsInput
113.114 + */
113.115 + public void setInput(byte[] b, int off, int len) {
113.116 + impl.setInput(b, off, len);
113.117 + }
113.118 +
113.119 + /**
113.120 + * Sets input data for decompression. Should be called whenever
113.121 + * needsInput() returns true indicating that more input data is
113.122 + * required.
113.123 + * @param b the input data bytes
113.124 + * @see Inflater#needsInput
113.125 + */
113.126 + public void setInput(byte[] b) {
113.127 + impl.setInput(b);
113.128 + }
113.129 +
113.130 + /**
113.131 + * Sets the preset dictionary to the given array of bytes. Should be
113.132 + * called when inflate() returns 0 and needsDictionary() returns true
113.133 + * indicating that a preset dictionary is required. The method getAdler()
113.134 + * can be used to get the Adler-32 value of the dictionary needed.
113.135 + * @param b the dictionary data bytes
113.136 + * @param off the start offset of the data
113.137 + * @param len the length of the data
113.138 + * @see Inflater#needsDictionary
113.139 + * @see Inflater#getAdler
113.140 + */
113.141 + public void setDictionary(byte[] b, int off, int len) {
113.142 + impl.setDictionary(b, off, len);
113.143 + }
113.144 +
113.145 + /**
113.146 + * Sets the preset dictionary to the given array of bytes. Should be
113.147 + * called when inflate() returns 0 and needsDictionary() returns true
113.148 + * indicating that a preset dictionary is required. The method getAdler()
113.149 + * can be used to get the Adler-32 value of the dictionary needed.
113.150 + * @param b the dictionary data bytes
113.151 + * @see Inflater#needsDictionary
113.152 + * @see Inflater#getAdler
113.153 + */
113.154 + public void setDictionary(byte[] b) {
113.155 + impl.setDictionary(b);
113.156 + }
113.157 +
113.158 + /**
113.159 + * Returns the total number of bytes remaining in the input buffer.
113.160 + * This can be used to find out what bytes still remain in the input
113.161 + * buffer after decompression has finished.
113.162 + * @return the total number of bytes remaining in the input buffer
113.163 + */
113.164 + public int getRemaining() {
113.165 + return impl.getRemaining();
113.166 + }
113.167 +
113.168 + /**
113.169 + * Returns true if no data remains in the input buffer. This can
113.170 + * be used to determine if #setInput should be called in order
113.171 + * to provide more input.
113.172 + * @return true if no data remains in the input buffer
113.173 + */
113.174 + public boolean needsInput() {
113.175 + return impl.needsInput();
113.176 + }
113.177 +
113.178 + /**
113.179 + * Returns true if a preset dictionary is needed for decompression.
113.180 + * @return true if a preset dictionary is needed for decompression
113.181 + * @see Inflater#setDictionary
113.182 + */
113.183 + public boolean needsDictionary() {
113.184 + return impl.needsDictionary();
113.185 + }
113.186 +
113.187 + /**
113.188 + * Returns true if the end of the compressed data stream has been
113.189 + * reached.
113.190 + * @return true if the end of the compressed data stream has been
113.191 + * reached
113.192 + */
113.193 + public boolean finished() {
113.194 + return impl.finished();
113.195 + }
113.196 +
113.197 + /**
113.198 + * Uncompresses bytes into specified buffer. Returns actual number
113.199 + * of bytes uncompressed. A return value of 0 indicates that
113.200 + * needsInput() or needsDictionary() should be called in order to
113.201 + * determine if more input data or a preset dictionary is required.
113.202 + * In the latter case, getAdler() can be used to get the Adler-32
113.203 + * value of the dictionary required.
113.204 + * @param b the buffer for the uncompressed data
113.205 + * @param off the start offset of the data
113.206 + * @param len the maximum number of uncompressed bytes
113.207 + * @return the actual number of uncompressed bytes
113.208 + * @exception DataFormatException if the compressed data format is invalid
113.209 + * @see Inflater#needsInput
113.210 + * @see Inflater#needsDictionary
113.211 + */
113.212 + public int inflate(byte[] b, int off, int len)
113.213 + throws DataFormatException
113.214 + {
113.215 + return impl.inflate(b, off, len);
113.216 + }
113.217 +
113.218 + /**
113.219 + * Uncompresses bytes into specified buffer. Returns actual number
113.220 + * of bytes uncompressed. A return value of 0 indicates that
113.221 + * needsInput() or needsDictionary() should be called in order to
113.222 + * determine if more input data or a preset dictionary is required.
113.223 + * In the latter case, getAdler() can be used to get the Adler-32
113.224 + * value of the dictionary required.
113.225 + * @param b the buffer for the uncompressed data
113.226 + * @return the actual number of uncompressed bytes
113.227 + * @exception DataFormatException if the compressed data format is invalid
113.228 + * @see Inflater#needsInput
113.229 + * @see Inflater#needsDictionary
113.230 + */
113.231 + public int inflate(byte[] b) throws DataFormatException {
113.232 + return impl.inflate(b);
113.233 + }
113.234 +
113.235 + /**
113.236 + * Returns the ADLER-32 value of the uncompressed data.
113.237 + * @return the ADLER-32 value of the uncompressed data
113.238 + */
113.239 + public int getAdler() {
113.240 + return impl.getAdler();
113.241 + }
113.242 +
113.243 + /**
113.244 + * Returns the total number of compressed bytes input so far.
113.245 + *
113.246 + * <p>Since the number of bytes may be greater than
113.247 + * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now
113.248 + * the preferred means of obtaining this information.</p>
113.249 + *
113.250 + * @return the total number of compressed bytes input so far
113.251 + */
113.252 + public int getTotalIn() {
113.253 + return impl.getTotalIn();
113.254 + }
113.255 +
113.256 + /**
113.257 + * Returns the total number of compressed bytes input so far.</p>
113.258 + *
113.259 + * @return the total (non-negative) number of compressed bytes input so far
113.260 + * @since 1.5
113.261 + */
113.262 + public long getBytesRead() {
113.263 + return impl.getBytesRead();
113.264 + }
113.265 +
113.266 + /**
113.267 + * Returns the total number of uncompressed bytes output so far.
113.268 + *
113.269 + * <p>Since the number of bytes may be greater than
113.270 + * Integer.MAX_VALUE, the {@link #getBytesWritten()} method is now
113.271 + * the preferred means of obtaining this information.</p>
113.272 + *
113.273 + * @return the total number of uncompressed bytes output so far
113.274 + */
113.275 + public int getTotalOut() {
113.276 + return impl.getTotalOut();
113.277 + }
113.278 +
113.279 + /**
113.280 + * Returns the total number of uncompressed bytes output so far.</p>
113.281 + *
113.282 + * @return the total (non-negative) number of uncompressed bytes output so far
113.283 + * @since 1.5
113.284 + */
113.285 + public long getBytesWritten() {
113.286 + return impl.getBytesWritten();
113.287 + }
113.288 +
113.289 + /**
113.290 + * Resets inflater so that a new set of input data can be processed.
113.291 + */
113.292 + public void reset() {
113.293 + impl.reset();
113.294 + }
113.295 +
113.296 + /**
113.297 + * Closes the decompressor and discards any unprocessed input.
113.298 + * This method should be called when the decompressor is no longer
113.299 + * being used, but will also be called automatically by the finalize()
113.300 + * method. Once this method is called, the behavior of the Inflater
113.301 + * object is undefined.
113.302 + */
113.303 + public void end() {
113.304 + impl.end();
113.305 + }
113.306 +
113.307 + /**
113.308 + * Closes the decompressor when garbage is collected.
113.309 + */
113.310 + protected void finalize() {
113.311 + end();
113.312 + }
113.313 +}
114.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
114.2 +++ b/emul/mini/src/main/java/java/util/zip/InflaterInputStream.java Sun Feb 17 17:58:34 2013 +0100
114.3 @@ -0,0 +1,288 @@
114.4 +/*
114.5 + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
114.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
114.7 + *
114.8 + * This code is free software; you can redistribute it and/or modify it
114.9 + * under the terms of the GNU General Public License version 2 only, as
114.10 + * published by the Free Software Foundation. Oracle designates this
114.11 + * particular file as subject to the "Classpath" exception as provided
114.12 + * by Oracle in the LICENSE file that accompanied this code.
114.13 + *
114.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
114.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
114.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
114.17 + * version 2 for more details (a copy is included in the LICENSE file that
114.18 + * accompanied this code).
114.19 + *
114.20 + * You should have received a copy of the GNU General Public License version
114.21 + * 2 along with this work; if not, write to the Free Software Foundation,
114.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
114.23 + *
114.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
114.25 + * or visit www.oracle.com if you need additional information or have any
114.26 + * questions.
114.27 + */
114.28 +
114.29 +package java.util.zip;
114.30 +
114.31 +import java.io.FilterInputStream;
114.32 +import java.io.InputStream;
114.33 +import java.io.IOException;
114.34 +import java.io.EOFException;
114.35 +
114.36 +/**
114.37 + * This class implements a stream filter for uncompressing data in the
114.38 + * "deflate" compression format. It is also used as the basis for other
114.39 + * decompression filters, such as GZIPInputStream.
114.40 + *
114.41 + * @see Inflater
114.42 + * @author David Connelly
114.43 + */
114.44 +public
114.45 +class InflaterInputStream extends FilterInputStream {
114.46 + /**
114.47 + * Decompressor for this stream.
114.48 + */
114.49 + protected Inflater inf;
114.50 +
114.51 + /**
114.52 + * Input buffer for decompression.
114.53 + */
114.54 + protected byte[] buf;
114.55 +
114.56 + /**
114.57 + * Length of input buffer.
114.58 + */
114.59 + protected int len;
114.60 +
114.61 + private boolean closed = false;
114.62 + // this flag is set to true after EOF has reached
114.63 + private boolean reachEOF = false;
114.64 +
114.65 + /**
114.66 + * Check to make sure that this stream has not been closed
114.67 + */
114.68 + private void ensureOpen() throws IOException {
114.69 + if (closed) {
114.70 + throw new IOException("Stream closed");
114.71 + }
114.72 + }
114.73 +
114.74 +
114.75 + /**
114.76 + * Creates a new input stream with the specified decompressor and
114.77 + * buffer size.
114.78 + * @param in the input stream
114.79 + * @param inf the decompressor ("inflater")
114.80 + * @param size the input buffer size
114.81 + * @exception IllegalArgumentException if size is <= 0
114.82 + */
114.83 + public InflaterInputStream(InputStream in, Inflater inf, int size) {
114.84 + super(in);
114.85 + if (in == null || inf == null) {
114.86 + throw new NullPointerException();
114.87 + } else if (size <= 0) {
114.88 + throw new IllegalArgumentException("buffer size <= 0");
114.89 + }
114.90 + this.inf = inf;
114.91 + buf = new byte[size];
114.92 + }
114.93 +
114.94 + /**
114.95 + * Creates a new input stream with the specified decompressor and a
114.96 + * default buffer size.
114.97 + * @param in the input stream
114.98 + * @param inf the decompressor ("inflater")
114.99 + */
114.100 + public InflaterInputStream(InputStream in, Inflater inf) {
114.101 + this(in, inf, 512);
114.102 + }
114.103 +
114.104 + boolean usesDefaultInflater = false;
114.105 +
114.106 + /**
114.107 + * Creates a new input stream with a default decompressor and buffer size.
114.108 + * @param in the input stream
114.109 + */
114.110 + public InflaterInputStream(InputStream in) {
114.111 + this(in, new Inflater());
114.112 + usesDefaultInflater = true;
114.113 + }
114.114 +
114.115 + private byte[] singleByteBuf = new byte[1];
114.116 +
114.117 + /**
114.118 + * Reads a byte of uncompressed data. This method will block until
114.119 + * enough input is available for decompression.
114.120 + * @return the byte read, or -1 if end of compressed input is reached
114.121 + * @exception IOException if an I/O error has occurred
114.122 + */
114.123 + public int read() throws IOException {
114.124 + ensureOpen();
114.125 + return read(singleByteBuf, 0, 1) == -1 ? -1 : singleByteBuf[0] & 0xff;
114.126 + }
114.127 +
114.128 + /**
114.129 + * Reads uncompressed data into an array of bytes. If <code>len</code> is not
114.130 + * zero, the method will block until some input can be decompressed; otherwise,
114.131 + * no bytes are read and <code>0</code> is returned.
114.132 + * @param b the buffer into which the data is read
114.133 + * @param off the start offset in the destination array <code>b</code>
114.134 + * @param len the maximum number of bytes read
114.135 + * @return the actual number of bytes read, or -1 if the end of the
114.136 + * compressed input is reached or a preset dictionary is needed
114.137 + * @exception NullPointerException If <code>b</code> is <code>null</code>.
114.138 + * @exception IndexOutOfBoundsException If <code>off</code> is negative,
114.139 + * <code>len</code> is negative, or <code>len</code> is greater than
114.140 + * <code>b.length - off</code>
114.141 + * @exception ZipException if a ZIP format error has occurred
114.142 + * @exception IOException if an I/O error has occurred
114.143 + */
114.144 + public int read(byte[] b, int off, int len) throws IOException {
114.145 + ensureOpen();
114.146 + if (b == null) {
114.147 + throw new NullPointerException();
114.148 + } else if (off < 0 || len < 0 || len > b.length - off) {
114.149 + throw new IndexOutOfBoundsException();
114.150 + } else if (len == 0) {
114.151 + return 0;
114.152 + }
114.153 + try {
114.154 + int n;
114.155 + while ((n = inf.inflate(b, off, len)) == 0) {
114.156 + if (inf.finished() || inf.needsDictionary()) {
114.157 + reachEOF = true;
114.158 + return -1;
114.159 + }
114.160 + if (inf.needsInput()) {
114.161 + fill();
114.162 + }
114.163 + }
114.164 + return n;
114.165 + } catch (DataFormatException e) {
114.166 + String s = e.getMessage();
114.167 + throw new ZipException(s != null ? s : "Invalid ZLIB data format");
114.168 + }
114.169 + }
114.170 +
114.171 + /**
114.172 + * Returns 0 after EOF has been reached, otherwise always return 1.
114.173 + * <p>
114.174 + * Programs should not count on this method to return the actual number
114.175 + * of bytes that could be read without blocking.
114.176 + *
114.177 + * @return 1 before EOF and 0 after EOF.
114.178 + * @exception IOException if an I/O error occurs.
114.179 + *
114.180 + */
114.181 + public int available() throws IOException {
114.182 + ensureOpen();
114.183 + if (reachEOF) {
114.184 + return 0;
114.185 + } else {
114.186 + return 1;
114.187 + }
114.188 + }
114.189 +
114.190 + private byte[] b = new byte[512];
114.191 +
114.192 + /**
114.193 + * Skips specified number of bytes of uncompressed data.
114.194 + * @param n the number of bytes to skip
114.195 + * @return the actual number of bytes skipped.
114.196 + * @exception IOException if an I/O error has occurred
114.197 + * @exception IllegalArgumentException if n < 0
114.198 + */
114.199 + public long skip(long n) throws IOException {
114.200 + if (n < 0) {
114.201 + throw new IllegalArgumentException("negative skip length");
114.202 + }
114.203 + ensureOpen();
114.204 + int max = (int)Math.min(n, Integer.MAX_VALUE);
114.205 + int total = 0;
114.206 + while (total < max) {
114.207 + int len = max - total;
114.208 + if (len > b.length) {
114.209 + len = b.length;
114.210 + }
114.211 + len = read(b, 0, len);
114.212 + if (len == -1) {
114.213 + reachEOF = true;
114.214 + break;
114.215 + }
114.216 + total += len;
114.217 + }
114.218 + return total;
114.219 + }
114.220 +
114.221 + /**
114.222 + * Closes this input stream and releases any system resources associated
114.223 + * with the stream.
114.224 + * @exception IOException if an I/O error has occurred
114.225 + */
114.226 + public void close() throws IOException {
114.227 + if (!closed) {
114.228 + if (usesDefaultInflater)
114.229 + inf.end();
114.230 + in.close();
114.231 + closed = true;
114.232 + }
114.233 + }
114.234 +
114.235 + /**
114.236 + * Fills input buffer with more data to decompress.
114.237 + * @exception IOException if an I/O error has occurred
114.238 + */
114.239 + protected void fill() throws IOException {
114.240 + ensureOpen();
114.241 + len = in.read(buf, 0, buf.length);
114.242 + if (len == -1) {
114.243 + throw new EOFException("Unexpected end of ZLIB input stream");
114.244 + }
114.245 + inf.setInput(buf, 0, len);
114.246 + }
114.247 +
114.248 + /**
114.249 + * Tests if this input stream supports the <code>mark</code> and
114.250 + * <code>reset</code> methods. The <code>markSupported</code>
114.251 + * method of <code>InflaterInputStream</code> returns
114.252 + * <code>false</code>.
114.253 + *
114.254 + * @return a <code>boolean</code> indicating if this stream type supports
114.255 + * the <code>mark</code> and <code>reset</code> methods.
114.256 + * @see java.io.InputStream#mark(int)
114.257 + * @see java.io.InputStream#reset()
114.258 + */
114.259 + public boolean markSupported() {
114.260 + return false;
114.261 + }
114.262 +
114.263 + /**
114.264 + * Marks the current position in this input stream.
114.265 + *
114.266 + * <p> The <code>mark</code> method of <code>InflaterInputStream</code>
114.267 + * does nothing.
114.268 + *
114.269 + * @param readlimit the maximum limit of bytes that can be read before
114.270 + * the mark position becomes invalid.
114.271 + * @see java.io.InputStream#reset()
114.272 + */
114.273 + public synchronized void mark(int readlimit) {
114.274 + }
114.275 +
114.276 + /**
114.277 + * Repositions this stream to the position at the time the
114.278 + * <code>mark</code> method was last called on this input stream.
114.279 + *
114.280 + * <p> The method <code>reset</code> for class
114.281 + * <code>InflaterInputStream</code> does nothing except throw an
114.282 + * <code>IOException</code>.
114.283 + *
114.284 + * @exception IOException if this method is invoked.
114.285 + * @see java.io.InputStream#mark(int)
114.286 + * @see java.io.IOException
114.287 + */
114.288 + public synchronized void reset() throws IOException {
114.289 + throw new IOException("mark/reset not supported");
114.290 + }
114.291 +}
115.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
115.2 +++ b/emul/mini/src/main/java/java/util/zip/ZStreamRef.java Sun Feb 17 17:58:34 2013 +0100
115.3 @@ -0,0 +1,46 @@
115.4 +/*
115.5 + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
115.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
115.7 + *
115.8 + * This code is free software; you can redistribute it and/or modify it
115.9 + * under the terms of the GNU General Public License version 2 only, as
115.10 + * published by the Free Software Foundation. Oracle designates this
115.11 + * particular file as subject to the "Classpath" exception as provided
115.12 + * by Oracle in the LICENSE file that accompanied this code.
115.13 + *
115.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
115.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
115.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
115.17 + * version 2 for more details (a copy is included in the LICENSE file that
115.18 + * accompanied this code).
115.19 + *
115.20 + * You should have received a copy of the GNU General Public License version
115.21 + * 2 along with this work; if not, write to the Free Software Foundation,
115.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
115.23 + *
115.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
115.25 + * or visit www.oracle.com if you need additional information or have any
115.26 + * questions.
115.27 + */
115.28 +
115.29 +package java.util.zip;
115.30 +
115.31 +/**
115.32 + * A reference to the native zlib's z_stream structure.
115.33 + */
115.34 +
115.35 +class ZStreamRef {
115.36 +
115.37 + private long address;
115.38 + ZStreamRef (long address) {
115.39 + this.address = address;
115.40 + }
115.41 +
115.42 + long address() {
115.43 + return address;
115.44 + }
115.45 +
115.46 + void clear() {
115.47 + address = 0;
115.48 + }
115.49 +}
116.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
116.2 +++ b/emul/mini/src/main/java/java/util/zip/ZipConstants.java Sun Feb 17 17:58:34 2013 +0100
116.3 @@ -0,0 +1,98 @@
116.4 +/*
116.5 + * Copyright (c) 1995, 1996, Oracle and/or its affiliates. All rights reserved.
116.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
116.7 + *
116.8 + * This code is free software; you can redistribute it and/or modify it
116.9 + * under the terms of the GNU General Public License version 2 only, as
116.10 + * published by the Free Software Foundation. Oracle designates this
116.11 + * particular file as subject to the "Classpath" exception as provided
116.12 + * by Oracle in the LICENSE file that accompanied this code.
116.13 + *
116.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
116.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
116.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
116.17 + * version 2 for more details (a copy is included in the LICENSE file that
116.18 + * accompanied this code).
116.19 + *
116.20 + * You should have received a copy of the GNU General Public License version
116.21 + * 2 along with this work; if not, write to the Free Software Foundation,
116.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
116.23 + *
116.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
116.25 + * or visit www.oracle.com if you need additional information or have any
116.26 + * questions.
116.27 + */
116.28 +
116.29 +package java.util.zip;
116.30 +
116.31 +/*
116.32 + * This interface defines the constants that are used by the classes
116.33 + * which manipulate ZIP files.
116.34 + *
116.35 + * @author David Connelly
116.36 + */
116.37 +interface ZipConstants {
116.38 + /*
116.39 + * Header signatures
116.40 + */
116.41 + static long LOCSIG = 0x04034b50L; // "PK\003\004"
116.42 + static long EXTSIG = 0x08074b50L; // "PK\007\008"
116.43 + static long CENSIG = 0x02014b50L; // "PK\001\002"
116.44 + static long ENDSIG = 0x06054b50L; // "PK\005\006"
116.45 +
116.46 + /*
116.47 + * Header sizes in bytes (including signatures)
116.48 + */
116.49 + static final int LOCHDR = 30; // LOC header size
116.50 + static final int EXTHDR = 16; // EXT header size
116.51 + static final int CENHDR = 46; // CEN header size
116.52 + static final int ENDHDR = 22; // END header size
116.53 +
116.54 + /*
116.55 + * Local file (LOC) header field offsets
116.56 + */
116.57 + static final int LOCVER = 4; // version needed to extract
116.58 + static final int LOCFLG = 6; // general purpose bit flag
116.59 + static final int LOCHOW = 8; // compression method
116.60 + static final int LOCTIM = 10; // modification time
116.61 + static final int LOCCRC = 14; // uncompressed file crc-32 value
116.62 + static final int LOCSIZ = 18; // compressed size
116.63 + static final int LOCLEN = 22; // uncompressed size
116.64 + static final int LOCNAM = 26; // filename length
116.65 + static final int LOCEXT = 28; // extra field length
116.66 +
116.67 + /*
116.68 + * Extra local (EXT) header field offsets
116.69 + */
116.70 + static final int EXTCRC = 4; // uncompressed file crc-32 value
116.71 + static final int EXTSIZ = 8; // compressed size
116.72 + static final int EXTLEN = 12; // uncompressed size
116.73 +
116.74 + /*
116.75 + * Central directory (CEN) header field offsets
116.76 + */
116.77 + static final int CENVEM = 4; // version made by
116.78 + static final int CENVER = 6; // version needed to extract
116.79 + static final int CENFLG = 8; // encrypt, decrypt flags
116.80 + static final int CENHOW = 10; // compression method
116.81 + static final int CENTIM = 12; // modification time
116.82 + static final int CENCRC = 16; // uncompressed file crc-32 value
116.83 + static final int CENSIZ = 20; // compressed size
116.84 + static final int CENLEN = 24; // uncompressed size
116.85 + static final int CENNAM = 28; // filename length
116.86 + static final int CENEXT = 30; // extra field length
116.87 + static final int CENCOM = 32; // comment length
116.88 + static final int CENDSK = 34; // disk number start
116.89 + static final int CENATT = 36; // internal file attributes
116.90 + static final int CENATX = 38; // external file attributes
116.91 + static final int CENOFF = 42; // LOC header offset
116.92 +
116.93 + /*
116.94 + * End of central directory (END) header field offsets
116.95 + */
116.96 + static final int ENDSUB = 8; // number of entries on this disk
116.97 + static final int ENDTOT = 10; // total number of entries
116.98 + static final int ENDSIZ = 12; // central directory size in bytes
116.99 + static final int ENDOFF = 16; // offset of first CEN header
116.100 + static final int ENDCOM = 20; // zip file comment length
116.101 +}
117.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
117.2 +++ b/emul/mini/src/main/java/java/util/zip/ZipEntry.java Sun Feb 17 17:58:34 2013 +0100
117.3 @@ -0,0 +1,331 @@
117.4 +/*
117.5 + * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
117.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
117.7 + *
117.8 + * This code is free software; you can redistribute it and/or modify it
117.9 + * under the terms of the GNU General Public License version 2 only, as
117.10 + * published by the Free Software Foundation. Oracle designates this
117.11 + * particular file as subject to the "Classpath" exception as provided
117.12 + * by Oracle in the LICENSE file that accompanied this code.
117.13 + *
117.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
117.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
117.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
117.17 + * version 2 for more details (a copy is included in the LICENSE file that
117.18 + * accompanied this code).
117.19 + *
117.20 + * You should have received a copy of the GNU General Public License version
117.21 + * 2 along with this work; if not, write to the Free Software Foundation,
117.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
117.23 + *
117.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
117.25 + * or visit www.oracle.com if you need additional information or have any
117.26 + * questions.
117.27 + */
117.28 +
117.29 +package java.util.zip;
117.30 +
117.31 +/**
117.32 + * This class is used to represent a ZIP file entry.
117.33 + *
117.34 + * @author David Connelly
117.35 + */
117.36 +public
117.37 +class ZipEntry implements ZipConstants, Cloneable {
117.38 + String name; // entry name
117.39 + long time = -1; // modification time (in DOS time)
117.40 + long crc = -1; // crc-32 of entry data
117.41 + long size = -1; // uncompressed size of entry data
117.42 + long csize = -1; // compressed size of entry data
117.43 + int method = -1; // compression method
117.44 + int flag = 0; // general purpose flag
117.45 + byte[] extra; // optional extra field data for entry
117.46 + String comment; // optional comment string for entry
117.47 +
117.48 + /**
117.49 + * Compression method for uncompressed entries.
117.50 + */
117.51 + public static final int STORED = 0;
117.52 +
117.53 + /**
117.54 + * Compression method for compressed (deflated) entries.
117.55 + */
117.56 + public static final int DEFLATED = 8;
117.57 +
117.58 + /**
117.59 + * Creates a new zip entry with the specified name.
117.60 + *
117.61 + * @param name the entry name
117.62 + * @exception NullPointerException if the entry name is null
117.63 + * @exception IllegalArgumentException if the entry name is longer than
117.64 + * 0xFFFF bytes
117.65 + */
117.66 + public ZipEntry(String name) {
117.67 + if (name == null) {
117.68 + throw new NullPointerException();
117.69 + }
117.70 + if (name.length() > 0xFFFF) {
117.71 + throw new IllegalArgumentException("entry name too long");
117.72 + }
117.73 + this.name = name;
117.74 + }
117.75 +
117.76 + /**
117.77 + * Creates a new zip entry with fields taken from the specified
117.78 + * zip entry.
117.79 + * @param e a zip Entry object
117.80 + */
117.81 + public ZipEntry(ZipEntry e) {
117.82 + name = e.name;
117.83 + time = e.time;
117.84 + crc = e.crc;
117.85 + size = e.size;
117.86 + csize = e.csize;
117.87 + method = e.method;
117.88 + flag = e.flag;
117.89 + extra = e.extra;
117.90 + comment = e.comment;
117.91 + }
117.92 +
117.93 + /*
117.94 + * Creates a new un-initialized zip entry
117.95 + */
117.96 + ZipEntry() {}
117.97 +
117.98 + /**
117.99 + * Returns the name of the entry.
117.100 + * @return the name of the entry
117.101 + */
117.102 + public String getName() {
117.103 + return name;
117.104 + }
117.105 +
117.106 + /**
117.107 + * Sets the modification time of the entry.
117.108 + * @param time the entry modification time in number of milliseconds
117.109 + * since the epoch
117.110 + * @see #getTime()
117.111 + */
117.112 + public void setTime(long time) {
117.113 + this.time = javaToDosTime(time);
117.114 + }
117.115 +
117.116 + /**
117.117 + * Returns the modification time of the entry, or -1 if not specified.
117.118 + * @return the modification time of the entry, or -1 if not specified
117.119 + * @see #setTime(long)
117.120 + */
117.121 + public long getTime() {
117.122 + return time != -1 ? dosToJavaTime(time) : -1;
117.123 + }
117.124 +
117.125 + /**
117.126 + * Sets the uncompressed size of the entry data.
117.127 + * @param size the uncompressed size in bytes
117.128 + * @exception IllegalArgumentException if the specified size is less
117.129 + * than 0, is greater than 0xFFFFFFFF when
117.130 + * <a href="package-summary.html#zip64">ZIP64 format</a> is not supported,
117.131 + * or is less than 0 when ZIP64 is supported
117.132 + * @see #getSize()
117.133 + */
117.134 + public void setSize(long size) {
117.135 + if (size < 0) {
117.136 + throw new IllegalArgumentException("invalid entry size");
117.137 + }
117.138 + this.size = size;
117.139 + }
117.140 +
117.141 + /**
117.142 + * Returns the uncompressed size of the entry data, or -1 if not known.
117.143 + * @return the uncompressed size of the entry data, or -1 if not known
117.144 + * @see #setSize(long)
117.145 + */
117.146 + public long getSize() {
117.147 + return size;
117.148 + }
117.149 +
117.150 + /**
117.151 + * Returns the size of the compressed entry data, or -1 if not known.
117.152 + * In the case of a stored entry, the compressed size will be the same
117.153 + * as the uncompressed size of the entry.
117.154 + * @return the size of the compressed entry data, or -1 if not known
117.155 + * @see #setCompressedSize(long)
117.156 + */
117.157 + public long getCompressedSize() {
117.158 + return csize;
117.159 + }
117.160 +
117.161 + /**
117.162 + * Sets the size of the compressed entry data.
117.163 + * @param csize the compressed size to set to
117.164 + * @see #getCompressedSize()
117.165 + */
117.166 + public void setCompressedSize(long csize) {
117.167 + this.csize = csize;
117.168 + }
117.169 +
117.170 + /**
117.171 + * Sets the CRC-32 checksum of the uncompressed entry data.
117.172 + * @param crc the CRC-32 value
117.173 + * @exception IllegalArgumentException if the specified CRC-32 value is
117.174 + * less than 0 or greater than 0xFFFFFFFF
117.175 + * @see #getCrc()
117.176 + */
117.177 + public void setCrc(long crc) {
117.178 + if (crc < 0 || crc > 0xFFFFFFFFL) {
117.179 + throw new IllegalArgumentException("invalid entry crc-32");
117.180 + }
117.181 + this.crc = crc;
117.182 + }
117.183 +
117.184 + /**
117.185 + * Returns the CRC-32 checksum of the uncompressed entry data, or -1 if
117.186 + * not known.
117.187 + * @return the CRC-32 checksum of the uncompressed entry data, or -1 if
117.188 + * not known
117.189 + * @see #setCrc(long)
117.190 + */
117.191 + public long getCrc() {
117.192 + return crc;
117.193 + }
117.194 +
117.195 + /**
117.196 + * Sets the compression method for the entry.
117.197 + * @param method the compression method, either STORED or DEFLATED
117.198 + * @exception IllegalArgumentException if the specified compression
117.199 + * method is invalid
117.200 + * @see #getMethod()
117.201 + */
117.202 + public void setMethod(int method) {
117.203 + if (method != STORED && method != DEFLATED) {
117.204 + throw new IllegalArgumentException("invalid compression method");
117.205 + }
117.206 + this.method = method;
117.207 + }
117.208 +
117.209 + /**
117.210 + * Returns the compression method of the entry, or -1 if not specified.
117.211 + * @return the compression method of the entry, or -1 if not specified
117.212 + * @see #setMethod(int)
117.213 + */
117.214 + public int getMethod() {
117.215 + return method;
117.216 + }
117.217 +
117.218 + /**
117.219 + * Sets the optional extra field data for the entry.
117.220 + * @param extra the extra field data bytes
117.221 + * @exception IllegalArgumentException if the length of the specified
117.222 + * extra field data is greater than 0xFFFF bytes
117.223 + * @see #getExtra()
117.224 + */
117.225 + public void setExtra(byte[] extra) {
117.226 + if (extra != null && extra.length > 0xFFFF) {
117.227 + throw new IllegalArgumentException("invalid extra field length");
117.228 + }
117.229 + this.extra = extra;
117.230 + }
117.231 +
117.232 + /**
117.233 + * Returns the extra field data for the entry, or null if none.
117.234 + * @return the extra field data for the entry, or null if none
117.235 + * @see #setExtra(byte[])
117.236 + */
117.237 + public byte[] getExtra() {
117.238 + return extra;
117.239 + }
117.240 +
117.241 + /**
117.242 + * Sets the optional comment string for the entry.
117.243 + *
117.244 + * <p>ZIP entry comments have maximum length of 0xffff. If the length of the
117.245 + * specified comment string is greater than 0xFFFF bytes after encoding, only
117.246 + * the first 0xFFFF bytes are output to the ZIP file entry.
117.247 + *
117.248 + * @param comment the comment string
117.249 + *
117.250 + * @see #getComment()
117.251 + */
117.252 + public void setComment(String comment) {
117.253 + this.comment = comment;
117.254 + }
117.255 +
117.256 + /**
117.257 + * Returns the comment string for the entry, or null if none.
117.258 + * @return the comment string for the entry, or null if none
117.259 + * @see #setComment(String)
117.260 + */
117.261 + public String getComment() {
117.262 + return comment;
117.263 + }
117.264 +
117.265 + /**
117.266 + * Returns true if this is a directory entry. A directory entry is
117.267 + * defined to be one whose name ends with a '/'.
117.268 + * @return true if this is a directory entry
117.269 + */
117.270 + public boolean isDirectory() {
117.271 + return name.endsWith("/");
117.272 + }
117.273 +
117.274 + /**
117.275 + * Returns a string representation of the ZIP entry.
117.276 + */
117.277 + public String toString() {
117.278 + return getName();
117.279 + }
117.280 +
117.281 + /*
117.282 + * Converts DOS time to Java time (number of milliseconds since epoch).
117.283 + */
117.284 + private static long dosToJavaTime(long dtime) {
117.285 + return dtime;
117.286 + /* XXX:
117.287 + Date d = new Date((int)(((dtime >> 25) & 0x7f) + 80),
117.288 + (int)(((dtime >> 21) & 0x0f) - 1),
117.289 + (int)((dtime >> 16) & 0x1f),
117.290 + (int)((dtime >> 11) & 0x1f),
117.291 + (int)((dtime >> 5) & 0x3f),
117.292 + (int)((dtime << 1) & 0x3e));
117.293 + return d.getTime();
117.294 + */
117.295 + }
117.296 +
117.297 + /*
117.298 + * Converts Java time to DOS time.
117.299 + */
117.300 + private static long javaToDosTime(long time) {
117.301 + return time;
117.302 + /* XXX:
117.303 + Date d = new Date(time);
117.304 + int year = d.getYear() + 1900;
117.305 + if (year < 1980) {
117.306 + return (1 << 21) | (1 << 16);
117.307 + }
117.308 + return (year - 1980) << 25 | (d.getMonth() + 1) << 21 |
117.309 + d.getDate() << 16 | d.getHours() << 11 | d.getMinutes() << 5 |
117.310 + d.getSeconds() >> 1;
117.311 + */
117.312 + }
117.313 +
117.314 + /**
117.315 + * Returns the hash code value for this entry.
117.316 + */
117.317 + public int hashCode() {
117.318 + return name.hashCode();
117.319 + }
117.320 +
117.321 + /**
117.322 + * Returns a copy of this entry.
117.323 + */
117.324 + public Object clone() {
117.325 + try {
117.326 + ZipEntry e = (ZipEntry)super.clone();
117.327 + e.extra = (extra == null) ? null : extra.clone();
117.328 + return e;
117.329 + } catch (CloneNotSupportedException e) {
117.330 + // This should never happen, since we are Cloneable
117.331 + throw new IllegalStateException();
117.332 + }
117.333 + }
117.334 +}
118.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
118.2 +++ b/emul/mini/src/main/java/java/util/zip/ZipException.java Sun Feb 17 17:58:34 2013 +0100
118.3 @@ -0,0 +1,60 @@
118.4 +/*
118.5 + * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
118.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
118.7 + *
118.8 + * This code is free software; you can redistribute it and/or modify it
118.9 + * under the terms of the GNU General Public License version 2 only, as
118.10 + * published by the Free Software Foundation. Oracle designates this
118.11 + * particular file as subject to the "Classpath" exception as provided
118.12 + * by Oracle in the LICENSE file that accompanied this code.
118.13 + *
118.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
118.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
118.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
118.17 + * version 2 for more details (a copy is included in the LICENSE file that
118.18 + * accompanied this code).
118.19 + *
118.20 + * You should have received a copy of the GNU General Public License version
118.21 + * 2 along with this work; if not, write to the Free Software Foundation,
118.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
118.23 + *
118.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
118.25 + * or visit www.oracle.com if you need additional information or have any
118.26 + * questions.
118.27 + */
118.28 +
118.29 +package java.util.zip;
118.30 +
118.31 +import java.io.IOException;
118.32 +
118.33 +/**
118.34 + * Signals that a Zip exception of some sort has occurred.
118.35 + *
118.36 + * @author unascribed
118.37 + * @see java.io.IOException
118.38 + * @since JDK1.0
118.39 + */
118.40 +
118.41 +public
118.42 +class ZipException extends IOException {
118.43 + private static final long serialVersionUID = 8000196834066748623L;
118.44 +
118.45 + /**
118.46 + * Constructs a <code>ZipException</code> with <code>null</code>
118.47 + * as its error detail message.
118.48 + */
118.49 + public ZipException() {
118.50 + super();
118.51 + }
118.52 +
118.53 + /**
118.54 + * Constructs a <code>ZipException</code> with the specified detail
118.55 + * message.
118.56 + *
118.57 + * @param s the detail message.
118.58 + */
118.59 +
118.60 + public ZipException(String s) {
118.61 + super(s);
118.62 + }
118.63 +}
119.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
119.2 +++ b/emul/mini/src/main/java/java/util/zip/ZipInputStream.java Sun Feb 17 17:58:34 2013 +0100
119.3 @@ -0,0 +1,194 @@
119.4 +/*
119.5 + * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
119.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
119.7 + *
119.8 + * This code is free software; you can redistribute it and/or modify it
119.9 + * under the terms of the GNU General Public License version 2 only, as
119.10 + * published by the Free Software Foundation. Oracle designates this
119.11 + * particular file as subject to the "Classpath" exception as provided
119.12 + * by Oracle in the LICENSE file that accompanied this code.
119.13 + *
119.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
119.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
119.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
119.17 + * version 2 for more details (a copy is included in the LICENSE file that
119.18 + * accompanied this code).
119.19 + *
119.20 + * You should have received a copy of the GNU General Public License version
119.21 + * 2 along with this work; if not, write to the Free Software Foundation,
119.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
119.23 + *
119.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
119.25 + * or visit www.oracle.com if you need additional information or have any
119.26 + * questions.
119.27 + */
119.28 +
119.29 +package java.util.zip;
119.30 +
119.31 +import java.io.InputStream;
119.32 +import java.io.IOException;
119.33 +
119.34 +/**
119.35 + * This class implements an input stream filter for reading files in the
119.36 + * ZIP file format. Includes support for both compressed and uncompressed
119.37 + * entries.
119.38 + *
119.39 + * @author David Connelly
119.40 + */
119.41 +public
119.42 +class ZipInputStream extends InflaterInputStream implements ZipConstants {
119.43 + private final org.apidesign.bck2brwsr.emul.zip.ZipInputStream impl;
119.44 +
119.45 + /**
119.46 + * Creates a new ZIP input stream.
119.47 + *
119.48 + * <p>The UTF-8 {@link java.nio.charset.Charset charset} is used to
119.49 + * decode the entry names.
119.50 + *
119.51 + * @param in the actual input stream
119.52 + */
119.53 + public ZipInputStream(InputStream in) {
119.54 + super(in);
119.55 + impl = new org.apidesign.bck2brwsr.emul.zip.ZipInputStream(in);
119.56 + }
119.57 +
119.58 + /**
119.59 + * Creates a new ZIP input stream.
119.60 + *
119.61 + * @param in the actual input stream
119.62 + *
119.63 + * @param charset
119.64 + * The {@linkplain java.nio.charset.Charset charset} to be
119.65 + * used to decode the ZIP entry name (ignored if the
119.66 + * <a href="package-summary.html#lang_encoding"> language
119.67 + * encoding bit</a> of the ZIP entry's general purpose bit
119.68 + * flag is set).
119.69 + *
119.70 + * @since 1.7
119.71 + *
119.72 + public ZipInputStream(InputStream in, Charset charset) {
119.73 + super(new PushbackInputStream(in, 512), new Inflater(true), 512);
119.74 + usesDefaultInflater = true;
119.75 + if(in == null) {
119.76 + throw new NullPointerException("in is null");
119.77 + }
119.78 + if (charset == null)
119.79 + throw new NullPointerException("charset is null");
119.80 + this.zc = ZipCoder.get(charset);
119.81 + }
119.82 + */
119.83 +
119.84 + /**
119.85 + * Reads the next ZIP file entry and positions the stream at the
119.86 + * beginning of the entry data.
119.87 + * @return the next ZIP file entry, or null if there are no more entries
119.88 + * @exception ZipException if a ZIP file error has occurred
119.89 + * @exception IOException if an I/O error has occurred
119.90 + */
119.91 + public ZipEntry getNextEntry() throws IOException {
119.92 + return impl.getNextEntry();
119.93 + }
119.94 +
119.95 + /**
119.96 + * Closes the current ZIP entry and positions the stream for reading the
119.97 + * next entry.
119.98 + * @exception ZipException if a ZIP file error has occurred
119.99 + * @exception IOException if an I/O error has occurred
119.100 + */
119.101 + public void closeEntry() throws IOException {
119.102 + impl.closeEntry();
119.103 + }
119.104 +
119.105 + /**
119.106 + * Returns 0 after EOF has reached for the current entry data,
119.107 + * otherwise always return 1.
119.108 + * <p>
119.109 + * Programs should not count on this method to return the actual number
119.110 + * of bytes that could be read without blocking.
119.111 + *
119.112 + * @return 1 before EOF and 0 after EOF has reached for current entry.
119.113 + * @exception IOException if an I/O error occurs.
119.114 + *
119.115 + */
119.116 + public int available() throws IOException {
119.117 + return impl.available();
119.118 + }
119.119 +
119.120 + /**
119.121 + * Reads from the current ZIP entry into an array of bytes.
119.122 + * If <code>len</code> is not zero, the method
119.123 + * blocks until some input is available; otherwise, no
119.124 + * bytes are read and <code>0</code> is returned.
119.125 + * @param b the buffer into which the data is read
119.126 + * @param off the start offset in the destination array <code>b</code>
119.127 + * @param len the maximum number of bytes read
119.128 + * @return the actual number of bytes read, or -1 if the end of the
119.129 + * entry is reached
119.130 + * @exception NullPointerException if <code>b</code> is <code>null</code>.
119.131 + * @exception IndexOutOfBoundsException if <code>off</code> is negative,
119.132 + * <code>len</code> is negative, or <code>len</code> is greater than
119.133 + * <code>b.length - off</code>
119.134 + * @exception ZipException if a ZIP file error has occurred
119.135 + * @exception IOException if an I/O error has occurred
119.136 + */
119.137 + public int read(byte[] b, int off, int len) throws IOException {
119.138 + return impl.read(b, off, len);
119.139 + }
119.140 +
119.141 + /**
119.142 + * Skips specified number of bytes in the current ZIP entry.
119.143 + * @param n the number of bytes to skip
119.144 + * @return the actual number of bytes skipped
119.145 + * @exception ZipException if a ZIP file error has occurred
119.146 + * @exception IOException if an I/O error has occurred
119.147 + * @exception IllegalArgumentException if n < 0
119.148 + */
119.149 + public long skip(long n) throws IOException {
119.150 + return impl.skip(n);
119.151 + }
119.152 +
119.153 + /**
119.154 + * Closes this input stream and releases any system resources associated
119.155 + * with the stream.
119.156 + * @exception IOException if an I/O error has occurred
119.157 + */
119.158 + public void close() throws IOException {
119.159 + impl.close();
119.160 + }
119.161 +
119.162 + /**
119.163 + * Creates a new <code>ZipEntry</code> object for the specified
119.164 + * entry name.
119.165 + *
119.166 + * @param name the ZIP file entry name
119.167 + * @return the ZipEntry just created
119.168 + */
119.169 + protected ZipEntry createZipEntry(String name) {
119.170 + return new ZipEntry(name);
119.171 + }
119.172 +
119.173 + @Override
119.174 + public int read() throws IOException {
119.175 + return impl.read();
119.176 + }
119.177 +
119.178 + @Override
119.179 + public boolean markSupported() {
119.180 + return impl.markSupported();
119.181 + }
119.182 +
119.183 + @Override
119.184 + public void mark(int readlimit) {
119.185 + impl.mark(readlimit);
119.186 + }
119.187 +
119.188 + @Override
119.189 + public void reset() throws IOException {
119.190 + impl.reset();
119.191 + }
119.192 +
119.193 + @Override
119.194 + public int read(byte[] b) throws IOException {
119.195 + return impl.read(b);
119.196 + }
119.197 +}
120.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
120.2 +++ b/emul/mini/src/main/java/java/util/zip/package.html Sun Feb 17 17:58:34 2013 +0100
120.3 @@ -0,0 +1,98 @@
120.4 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
120.5 +<html>
120.6 +<head>
120.7 +<!--
120.8 +Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
120.9 +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
120.10 +
120.11 +This code is free software; you can redistribute it and/or modify it
120.12 +under the terms of the GNU General Public License version 2 only, as
120.13 +published by the Free Software Foundation. Oracle designates this
120.14 +particular file as subject to the "Classpath" exception as provided
120.15 +by Oracle in the LICENSE file that accompanied this code.
120.16 +
120.17 +This code is distributed in the hope that it will be useful, but WITHOUT
120.18 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
120.19 +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
120.20 +version 2 for more details (a copy is included in the LICENSE file that
120.21 +accompanied this code).
120.22 +
120.23 +You should have received a copy of the GNU General Public License version
120.24 +2 along with this work; if not, write to the Free Software Foundation,
120.25 +Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
120.26 +
120.27 +Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
120.28 +or visit www.oracle.com if you need additional information or have any
120.29 +questions.
120.30 +-->
120.31 +
120.32 +</head>
120.33 +<body bgcolor="white">
120.34 +
120.35 +Provides classes for reading and writing the standard ZIP and GZIP
120.36 +file formats. Also includes classes for compressing and decompressing
120.37 +data using the DEFLATE compression algorithm, which is used by the
120.38 +ZIP and GZIP file formats. Additionally, there are utility classes
120.39 +for computing the CRC-32 and Adler-32 checksums of arbitrary
120.40 +input streams.
120.41 +
120.42 +
120.43 +<h2>Package Specification</h2>
120.44 +
120.45 +</a>
120.46 +<ul>
120.47 + <li><a href="ftp://ftp.uu.net/pub/archiving/zip/doc/appnote-970311-iz.zip">
120.48 + Info-ZIP Application Note 970311
120.49 + </a> - a detailed description of the Info-ZIP format upon which
120.50 + the <code>java.util.zip</code> classes are based.
120.51 +<p>
120.52 + <a name="zip64">
120.53 + <li>An implementation may optionally support the ZIP64(tm) format extensions
120.54 + defined by the
120.55 + <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">
120.56 + PKWARE ZIP File Format Specification</a>. The ZIP64(tm) format extensions
120.57 + are used to overcome the size limitations of the original ZIP format.
120.58 +<p>
120.59 + <a name="lang_encoding">
120.60 + <li>APPENDIX D of <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">
120.61 + PKWARE ZIP File Format Specification</a> - Language Encoding Flag (EFS) to
120.62 + encode ZIP entry filename and comment fields using UTF-8.
120.63 +<p>
120.64 + <li><a href="http://www.ietf.org/rfc/rfc1950.txt">
120.65 + ZLIB Compressed Data Format Specification version 3.3</a>
120.66 +
120.67 + <a href="http://www.ietf.org/rfc/rfc1950.txt.pdf">(pdf)</a>
120.68 + (RFC 1950)
120.69 +<p>
120.70 + <li><a href="http://www.ietf.org/rfc/rfc1951.txt">
120.71 + DEFLATE Compressed Data Format Specification version 1.3</a>
120.72 +
120.73 + <a href="http://www.ietf.org/rfc/rfc1951.txt.pdf">(pdf)</a>
120.74 + (RFC 1951)
120.75 +<p>
120.76 + <li><a href="http://www.ietf.org/rfc/rfc1952.txt">
120.77 + GZIP file format specification version 4.3</a>
120.78 +
120.79 + <a href="http://www.ietf.org/rfc/rfc1952.txt.pdf">(pdf)</a>
120.80 + (RFC 1952)
120.81 +<p>
120.82 + <li>CRC-32 checksum is described in RFC 1952 (above)
120.83 +<p>
120.84 + <li>Adler-32 checksum is described in RFC 1950 (above)
120.85 +</ul>
120.86 +
120.87 +
120.88 +<!--
120.89 +<h2>Related Documentation</h2>
120.90 +
120.91 +For overviews, tutorials, examples, guides, and tool documentation, please see:
120.92 +<ul>
120.93 + <li><a href="">##### REFER TO NON-SPEC DOCUMENTATION HERE #####</a>
120.94 +</ul>
120.95 +-->
120.96 +
120.97 +@since JDK1.1
120.98 +</body>
120.99 +</html>
120.100 +
120.101 +
121.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
121.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/ManifestInputStream.java Sun Feb 17 17:58:34 2013 +0100
121.3 @@ -0,0 +1,228 @@
121.4 +/*
121.5 + * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
121.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
121.7 + *
121.8 + * This code is free software; you can redistribute it and/or modify it
121.9 + * under the terms of the GNU General Public License version 2 only, as
121.10 + * published by the Free Software Foundation. Oracle designates this
121.11 + * particular file as subject to the "Classpath" exception as provided
121.12 + * by Oracle in the LICENSE file that accompanied this code.
121.13 + *
121.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
121.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
121.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
121.17 + * version 2 for more details (a copy is included in the LICENSE file that
121.18 + * accompanied this code).
121.19 + *
121.20 + * You should have received a copy of the GNU General Public License version
121.21 + * 2 along with this work; if not, write to the Free Software Foundation,
121.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
121.23 + *
121.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
121.25 + * or visit www.oracle.com if you need additional information or have any
121.26 + * questions.
121.27 + */
121.28 +package org.apidesign.bck2brwsr.emul.lang;
121.29 +
121.30 +import java.io.FilterInputStream;
121.31 +import java.io.IOException;
121.32 +import java.io.InputStream;
121.33 +
121.34 +/*
121.35 + * A fast buffered input stream for parsing manifest files.
121.36 + *
121.37 + * Taken from java.util.jar.Manifest.FastInputStream and modified to be
121.38 + * independent of other Manifest functionality.
121.39 + */
121.40 +public abstract class ManifestInputStream extends FilterInputStream {
121.41 + private byte[] buf;
121.42 + private int count = 0;
121.43 + private int pos = 0;
121.44 +
121.45 + protected ManifestInputStream(InputStream in) {
121.46 + this(in, 8192);
121.47 + }
121.48 +
121.49 + protected ManifestInputStream(InputStream in, int size) {
121.50 + super(in);
121.51 + buf = new byte[size];
121.52 + }
121.53 +
121.54 + public int read() throws IOException {
121.55 + if (pos >= count) {
121.56 + fill();
121.57 + if (pos >= count) {
121.58 + return -1;
121.59 + }
121.60 + }
121.61 + return buf[pos++] & 0xff;
121.62 + }
121.63 +
121.64 + public int read(byte[] b, int off, int len) throws IOException {
121.65 + int avail = count - pos;
121.66 + if (avail <= 0) {
121.67 + if (len >= buf.length) {
121.68 + return in.read(b, off, len);
121.69 + }
121.70 + fill();
121.71 + avail = count - pos;
121.72 + if (avail <= 0) {
121.73 + return -1;
121.74 + }
121.75 + }
121.76 + if (len > avail) {
121.77 + len = avail;
121.78 + }
121.79 + System.arraycopy(buf, pos, b, off, len);
121.80 + pos += len;
121.81 + return len;
121.82 + }
121.83 +
121.84 + /*
121.85 + * Reads 'len' bytes from the input stream, or until an end-of-line
121.86 + * is reached. Returns the number of bytes read.
121.87 + */
121.88 + public int readLine(byte[] b, int off, int len) throws IOException {
121.89 + byte[] tbuf = this.buf;
121.90 + int total = 0;
121.91 + while (total < len) {
121.92 + int avail = count - pos;
121.93 + if (avail <= 0) {
121.94 + fill();
121.95 + avail = count - pos;
121.96 + if (avail <= 0) {
121.97 + return -1;
121.98 + }
121.99 + }
121.100 + int n = len - total;
121.101 + if (n > avail) {
121.102 + n = avail;
121.103 + }
121.104 + int tpos = pos;
121.105 + int maxpos = tpos + n;
121.106 + while (tpos < maxpos && tbuf[tpos++] != '\n') {
121.107 + ;
121.108 + }
121.109 + n = tpos - pos;
121.110 + System.arraycopy(tbuf, pos, b, off, n);
121.111 + off += n;
121.112 + total += n;
121.113 + pos = tpos;
121.114 + if (tbuf[tpos - 1] == '\n') {
121.115 + break;
121.116 + }
121.117 + }
121.118 + return total;
121.119 + }
121.120 +
121.121 + public byte peek() throws IOException {
121.122 + if (pos == count) {
121.123 + fill();
121.124 + }
121.125 + if (pos == count) {
121.126 + return -1; // nothing left in buffer
121.127 + }
121.128 + return buf[pos];
121.129 + }
121.130 +
121.131 + public int readLine(byte[] b) throws IOException {
121.132 + return readLine(b, 0, b.length);
121.133 + }
121.134 +
121.135 + public long skip(long n) throws IOException {
121.136 + if (n <= 0) {
121.137 + return 0;
121.138 + }
121.139 + long avail = count - pos;
121.140 + if (avail <= 0) {
121.141 + return in.skip(n);
121.142 + }
121.143 + if (n > avail) {
121.144 + n = avail;
121.145 + }
121.146 + pos += n;
121.147 + return n;
121.148 + }
121.149 +
121.150 + public int available() throws IOException {
121.151 + return (count - pos) + in.available();
121.152 + }
121.153 +
121.154 + public void close() throws IOException {
121.155 + if (in != null) {
121.156 + in.close();
121.157 + in = null;
121.158 + buf = null;
121.159 + }
121.160 + }
121.161 +
121.162 + private void fill() throws IOException {
121.163 + count = pos = 0;
121.164 + int n = in.read(buf, 0, buf.length);
121.165 + if (n > 0) {
121.166 + count = n;
121.167 + }
121.168 + }
121.169 +
121.170 + protected abstract String putValue(String key, String value);
121.171 +
121.172 + public void readAttributes(byte[] lbuf) throws IOException {
121.173 + ManifestInputStream is = this;
121.174 +
121.175 + String name = null;
121.176 + String value = null;
121.177 + byte[] lastline = null;
121.178 + int len;
121.179 + while ((len = is.readLine(lbuf)) != -1) {
121.180 + boolean lineContinued = false;
121.181 + if (lbuf[--len] != '\n') {
121.182 + throw new IOException("line too long");
121.183 + }
121.184 + if (len > 0 && lbuf[len - 1] == '\r') {
121.185 + --len;
121.186 + }
121.187 + if (len == 0) {
121.188 + break;
121.189 + }
121.190 + int i = 0;
121.191 + if (lbuf[0] == ' ') {
121.192 + if (name == null) {
121.193 + throw new IOException("misplaced continuation line");
121.194 + }
121.195 + lineContinued = true;
121.196 + byte[] buf = new byte[lastline.length + len - 1];
121.197 + System.arraycopy(lastline, 0, buf, 0, lastline.length);
121.198 + System.arraycopy(lbuf, 1, buf, lastline.length, len - 1);
121.199 + if (is.peek() == ' ') {
121.200 + lastline = buf;
121.201 + continue;
121.202 + }
121.203 + value = new String(buf, 0, buf.length, "UTF8");
121.204 + lastline = null;
121.205 + } else {
121.206 + while (lbuf[i++] != ':') {
121.207 + if (i >= len) {
121.208 + throw new IOException("invalid header field");
121.209 + }
121.210 + }
121.211 + if (lbuf[i++] != ' ') {
121.212 + throw new IOException("invalid header field");
121.213 + }
121.214 + name = new String(lbuf, 0, 0, i - 2);
121.215 + if (is.peek() == ' ') {
121.216 + lastline = new byte[len - i];
121.217 + System.arraycopy(lbuf, i, lastline, 0, len - i);
121.218 + continue;
121.219 + }
121.220 + value = new String(lbuf, i, len - i, "UTF8");
121.221 + }
121.222 + try {
121.223 + if ((putValue(name, value) != null) && (!lineContinued)) {
121.224 + throw new IOException("Duplicate name in Manifest: " + name + ".\n" + "Ensure that the manifest does not " + "have duplicate entries, and\n" + "that blank lines separate " + "individual sections in both your\n" + "manifest and in the META-INF/MANIFEST.MF " + "entry in the jar file.");
121.225 + }
121.226 + } catch (IllegalArgumentException e) {
121.227 + throw new IOException("invalid header field name: " + name);
121.228 + }
121.229 + }
121.230 + }
121.231 +}
122.1 --- a/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/System.java Fri Jan 25 15:08:24 2013 +0100
122.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/System.java Sun Feb 17 17:58:34 2013 +0100
122.3 @@ -17,6 +17,7 @@
122.4 */
122.5 package org.apidesign.bck2brwsr.emul.lang;
122.6
122.7 +import java.lang.reflect.Method;
122.8 import org.apidesign.bck2brwsr.core.JavaScriptBody;
122.9
122.10 /**
122.11 @@ -38,5 +39,27 @@
122.12 " }\n" +
122.13 "}"
122.14 )
122.15 - public static native void arraycopy(Object value, int srcBegin, Object dst, int dstBegin, int count);
122.16 + public static void arraycopy(Object src, int srcBegin, Object dst, int dstBegin, int count) {
122.17 + try {
122.18 + Class<?> system = Class.forName("java.lang.System");
122.19 + Method m = system.getMethod("arraycopy", Object.class, int.class, Object.class, int.class, int.class);
122.20 + m.invoke(null, src, srcBegin, dst, dstBegin, count);
122.21 + } catch (Exception ex) {
122.22 + throw new IllegalStateException(ex);
122.23 + }
122.24 + }
122.25 +
122.26 + @JavaScriptBody(args = { "arr", "expectedSize" }, body =
122.27 + "while (expectedSize-- > arr.length) { arr.push(0); }; return arr;"
122.28 + )
122.29 + public static native byte[] expandArray(byte[] arr, int expectedSize);
122.30 +
122.31 + @JavaScriptBody(args = {}, body = "return new Date().getTime();")
122.32 + public static native long currentTimeMillis();
122.33 +
122.34 + public static long nanoTime() {
122.35 + return 1000000L * currentTimeMillis();
122.36 + }
122.37 + @JavaScriptBody(args = { "obj" }, body="return vm.java_lang_Object(false).hashCode__I.call(obj);")
122.38 + public static native int identityHashCode(Object obj);
122.39 }
123.1 --- a/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/AnnotationImpl.java Fri Jan 25 15:08:24 2013 +0100
123.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/AnnotationImpl.java Sun Feb 17 17:58:34 2013 +0100
123.3 @@ -18,6 +18,8 @@
123.4 package org.apidesign.bck2brwsr.emul.reflect;
123.5
123.6 import java.lang.annotation.Annotation;
123.7 +import java.lang.reflect.Method;
123.8 +import java.lang.reflect.Modifier;
123.9 import org.apidesign.bck2brwsr.core.JavaScriptBody;
123.10
123.11 /**
123.12 @@ -25,39 +27,73 @@
123.13 * @author Jaroslav Tulach <jtulach@netbeans.org>
123.14 */
123.15 public final class AnnotationImpl implements Annotation {
123.16 + private final Class<? extends Annotation> type;
123.17 +
123.18 + public AnnotationImpl(Class<? extends Annotation> type) {
123.19 + this.type = type;
123.20 + }
123.21 +
123.22 public Class<? extends Annotation> annotationType() {
123.23 - return getClass();
123.24 + return type;
123.25 }
123.26
123.27 - @JavaScriptBody(args = { "a", "n", "values" }, body = ""
123.28 - + "function f(v, p) {\n"
123.29 - + " var val = v;\n"
123.30 - + " var prop = p;\n"
123.31 + @JavaScriptBody(args = { "a", "n", "arr", "values" }, body = ""
123.32 + + "function f(val, prop, clazz) {\n"
123.33 + " return function() {\n"
123.34 - + " return val[prop];\n"
123.35 + + " if (clazz == null) return val[prop];\n"
123.36 + + " if (clazz.isArray__Z()) {\n"
123.37 + + " var valarr = val[prop];\n"
123.38 + + " var cmp = clazz.getComponentType__Ljava_lang_Class_2();\n"
123.39 + + " var retarr = vm.java_lang_reflect_Array(false).newInstance__Ljava_lang_Object_2Ljava_lang_Class_2I(cmp, valarr.length);\n"
123.40 + + " for (var i = 0; i < valarr.length; i++) {\n"
123.41 + + " retarr[i] = CLS.prototype.c__Ljava_lang_Object_2Ljava_lang_Class_2Ljava_lang_Object_2(cmp, valarr[i]);\n"
123.42 + + " }\n"
123.43 + + " return retarr;\n"
123.44 + + " }\n"
123.45 + + " return CLS.prototype.c__Ljava_lang_Object_2Ljava_lang_Class_2Ljava_lang_Object_2(clazz, val[prop]);\n"
123.46 + " };\n"
123.47 + "}\n"
123.48 - + "var props = Object.getOwnPropertyNames(values);\n"
123.49 - + "for (var i = 0; i < props.length; i++) {\n"
123.50 - + " var p = props[i];\n"
123.51 - + " a[p] = new f(values, p);\n"
123.52 + + "for (var i = 0; i < arr.length; i += 3) {\n"
123.53 + + " var m = arr[i];\n"
123.54 + + " var p = arr[i + 1];\n"
123.55 + + " var c = arr[i + 2];\n"
123.56 + + " a[m] = f(values, p, c);\n"
123.57 + "}\n"
123.58 + "a['$instOf_' + n] = true;\n"
123.59 + "return a;"
123.60 )
123.61 - private static <T extends Annotation> T create(AnnotationImpl a, String n, Object values) {
123.62 - return null;
123.63 + private static native <T extends Annotation> T create(
123.64 + AnnotationImpl a, String n, Object[] methodsAndProps, Object values
123.65 + );
123.66 +
123.67 + private static Object c(Class<? extends Annotation> a, Object v) {
123.68 + return create(a, v);
123.69 }
123.70 +
123.71 public static <T extends Annotation> T create(Class<T> annoClass, Object values) {
123.72 - return create(new AnnotationImpl(), annoClass.getName().replace('.', '_'), values);
123.73 + return create(new AnnotationImpl(annoClass),
123.74 + annoClass.getName().replace('.', '_'),
123.75 + findProps(annoClass), values
123.76 + );
123.77 }
123.78
123.79 public static Annotation[] create(Object anno) {
123.80 String[] names = findNames(anno);
123.81 Annotation[] ret = new Annotation[names.length];
123.82 for (int i = 0; i < names.length; i++) {
123.83 - String n = names[i].substring(1, names[i].length() - 1).replace('/', '_');
123.84 - ret[i] = create(new AnnotationImpl(), n, findData(anno, names[i]));
123.85 + String annoNameSlash = names[i].substring(1, names[i].length() - 1);
123.86 + Class<? extends Annotation> annoClass;
123.87 + try {
123.88 + annoClass = (Class<? extends Annotation>)Class.forName(annoNameSlash.replace('/', '.'));
123.89 + } catch (ClassNotFoundException ex) {
123.90 + throw new IllegalStateException("Can't find annotation class " + annoNameSlash);
123.91 + }
123.92 + ret[i] = create(
123.93 + new AnnotationImpl(annoClass),
123.94 + annoNameSlash.replace('/', '_'),
123.95 + findProps(annoClass),
123.96 + findData(anno, names[i])
123.97 + );
123.98 }
123.99 return ret;
123.100 }
123.101 @@ -70,12 +106,25 @@
123.102 + "}"
123.103 + "return arr;"
123.104 )
123.105 - private static String[] findNames(Object anno) {
123.106 - throw new UnsupportedOperationException();
123.107 - }
123.108 + private static native String[] findNames(Object anno);
123.109
123.110 @JavaScriptBody(args={ "anno", "p"}, body="return anno[p];")
123.111 - private static Object findData(Object anno, String p) {
123.112 - throw new UnsupportedOperationException();
123.113 + private static native Object findData(Object anno, String p);
123.114 +
123.115 + private static Object[] findProps(Class<?> annoClass) {
123.116 + final Method[] marr = MethodImpl.findMethods(annoClass, Modifier.PUBLIC);
123.117 + Object[] arr = new Object[marr.length * 3];
123.118 + int pos = 0;
123.119 + for (Method m : marr) {
123.120 + arr[pos++] = MethodImpl.toSignature(m);
123.121 + arr[pos++] = m.getName();
123.122 + final Class<?> rt = m.getReturnType();
123.123 + if (rt.isArray()) {
123.124 + arr[pos++] = rt.getComponentType().isAnnotation() ? rt : null;
123.125 + } else {
123.126 + arr[pos++] = rt.isAnnotation() ? rt : null;
123.127 + }
123.128 + }
123.129 + return arr;
123.130 }
123.131 }
124.1 --- a/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/MethodImpl.java Fri Jan 25 15:08:24 2013 +0100
124.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/MethodImpl.java Sun Feb 17 17:58:34 2013 +0100
124.3 @@ -1,29 +1,23 @@
124.4 -/*
124.5 - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
124.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
124.7 +/**
124.8 + * Back 2 Browser Bytecode Translator
124.9 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
124.10 *
124.11 - * This code is free software; you can redistribute it and/or modify it
124.12 - * under the terms of the GNU General Public License version 2 only, as
124.13 - * published by the Free Software Foundation. Oracle designates this
124.14 - * particular file as subject to the "Classpath" exception as provided
124.15 - * by Oracle in the LICENSE file that accompanied this code.
124.16 + * This program is free software: you can redistribute it and/or modify
124.17 + * it under the terms of the GNU General Public License as published by
124.18 + * the Free Software Foundation, version 2 of the License.
124.19 *
124.20 - * This code is distributed in the hope that it will be useful, but WITHOUT
124.21 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
124.22 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
124.23 - * version 2 for more details (a copy is included in the LICENSE file that
124.24 - * accompanied this code).
124.25 + * This program is distributed in the hope that it will be useful,
124.26 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
124.27 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
124.28 + * GNU General Public License for more details.
124.29 *
124.30 - * You should have received a copy of the GNU General Public License version
124.31 - * 2 along with this work; if not, write to the Free Software Foundation,
124.32 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
124.33 - *
124.34 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
124.35 - * or visit www.oracle.com if you need additional information or have any
124.36 - * questions.
124.37 + * You should have received a copy of the GNU General Public License
124.38 + * along with this program. Look for COPYING file in the top folder.
124.39 + * If not, see http://opensource.org/licenses/GPL-2.0.
124.40 */
124.41 package org.apidesign.bck2brwsr.emul.reflect;
124.42
124.43 +import java.lang.reflect.Array;
124.44 import java.lang.reflect.Method;
124.45 import java.util.Enumeration;
124.46 import org.apidesign.bck2brwsr.core.JavaScriptBody;
124.47 @@ -41,7 +35,7 @@
124.48 throw new IllegalStateException(ex);
124.49 }
124.50 }
124.51 -
124.52 +
124.53 protected abstract Method create(Class<?> declaringClass, String name, Object data, String sig);
124.54
124.55
124.56 @@ -55,8 +49,10 @@
124.57 + "var arr = new Array();\n"
124.58 + "for (m in c) {\n"
124.59 + " if (m.indexOf(prefix) === 0) {\n"
124.60 + + " if (!c[m].cls) continue;\n"
124.61 + " arr.push(m);\n"
124.62 + " arr.push(c[m]);\n"
124.63 + + " arr.push(c[m].cls.$class);\n"
124.64 + " }"
124.65 + "}\n"
124.66 + "return arr;")
124.67 @@ -66,9 +62,10 @@
124.68 public static Method findMethod(
124.69 Class<?> clazz, String name, Class<?>... parameterTypes) {
124.70 Object[] data = findMethodData(clazz, name + "__");
124.71 - BIG: for (int i = 0; i < data.length; i += 2) {
124.72 - String sig = ((String) data[0]).substring(name.length() + 2);
124.73 - Method tmp = INSTANCE.create(clazz, name, data[1], sig);
124.74 + BIG: for (int i = 0; i < data.length; i += 3) {
124.75 + String sig = ((String) data[i]).substring(name.length() + 2);
124.76 + Class<?> cls = (Class<?>) data[i + 2];
124.77 + Method tmp = INSTANCE.create(cls, name, data[i + 1], sig);
124.78 Class<?>[] tmpParms = tmp.getParameterTypes();
124.79 if (parameterTypes.length != tmpParms.length) {
124.80 continue;
124.81 @@ -86,7 +83,7 @@
124.82 public static Method[] findMethods(Class<?> clazz, int mask) {
124.83 Object[] namesAndData = findMethodData(clazz, "");
124.84 int cnt = 0;
124.85 - for (int i = 0; i < namesAndData.length; i += 2) {
124.86 + for (int i = 0; i < namesAndData.length; i += 3) {
124.87 String sig = (String) namesAndData[i];
124.88 Object data = namesAndData[i + 1];
124.89 int middle = sig.indexOf("__");
124.90 @@ -95,7 +92,8 @@
124.91 }
124.92 String name = sig.substring(0, middle);
124.93 sig = sig.substring(middle + 2);
124.94 - final Method m = INSTANCE.create(clazz, name, data, sig);
124.95 + Class<?> cls = (Class<?>) namesAndData[i + 2];
124.96 + final Method m = INSTANCE.create(cls, name, data, sig);
124.97 if ((m.getModifiers() & mask) == 0) {
124.98 continue;
124.99 }
124.100 @@ -107,6 +105,62 @@
124.101 }
124.102 return arr;
124.103 }
124.104 + static String toSignature(Method m) {
124.105 + StringBuilder sb = new StringBuilder();
124.106 + sb.append(m.getName()).append("__");
124.107 + appendType(sb, m.getReturnType());
124.108 + Class<?>[] arr = m.getParameterTypes();
124.109 + for (int i = 0; i < arr.length; i++) {
124.110 + appendType(sb, arr[i]);
124.111 + }
124.112 + return sb.toString();
124.113 + }
124.114 +
124.115 + private static void appendType(StringBuilder sb, Class<?> type) {
124.116 + if (type == Integer.TYPE) {
124.117 + sb.append('I');
124.118 + return;
124.119 + }
124.120 + if (type == Long.TYPE) {
124.121 + sb.append('J');
124.122 + return;
124.123 + }
124.124 + if (type == Double.TYPE) {
124.125 + sb.append('D');
124.126 + return;
124.127 + }
124.128 + if (type == Float.TYPE) {
124.129 + sb.append('F');
124.130 + return;
124.131 + }
124.132 + if (type == Byte.TYPE) {
124.133 + sb.append('B');
124.134 + return;
124.135 + }
124.136 + if (type == Boolean.TYPE) {
124.137 + sb.append('Z');
124.138 + return;
124.139 + }
124.140 + if (type == Short.TYPE) {
124.141 + sb.append('S');
124.142 + return;
124.143 + }
124.144 + if (type == Void.TYPE) {
124.145 + sb.append('V');
124.146 + return;
124.147 + }
124.148 + if (type == Character.TYPE) {
124.149 + sb.append('C');
124.150 + return;
124.151 + }
124.152 + if (type.isArray()) {
124.153 + sb.append("_3");
124.154 + appendType(sb, type.getComponentType());
124.155 + return;
124.156 + }
124.157 + sb.append('L').append(type.getName().replace('.', '_'));
124.158 + sb.append("_2");
124.159 + }
124.160
124.161 public static int signatureElements(String sig) {
124.162 Enumeration<Class> en = signatureParser(sig);
124.163 @@ -148,13 +202,19 @@
124.164 return Character.TYPE;
124.165 case 'L':
124.166 try {
124.167 - int up = sig.indexOf("_2");
124.168 - String type = sig.substring(1, up);
124.169 + int up = sig.indexOf("_2", pos);
124.170 + String type = sig.substring(pos, up);
124.171 pos = up + 2;
124.172 - return Class.forName(type);
124.173 + return Class.forName(type.replace('_', '.'));
124.174 } catch (ClassNotFoundException ex) {
124.175 - // should not happen
124.176 + throw new IllegalStateException(ex);
124.177 }
124.178 + case '_': {
124.179 + char nch = sig.charAt(pos++);
124.180 + assert nch == '3' : "Can't find '3' at " + sig.substring(pos - 1);
124.181 + final Class compType = nextElement();
124.182 + return Array.newInstance(compType, 0).getClass();
124.183 + }
124.184 }
124.185 throw new UnsupportedOperationException(sig + " at " + pos);
124.186 }
125.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
125.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/TypeProvider.java Sun Feb 17 17:58:34 2013 +0100
125.3 @@ -0,0 +1,40 @@
125.4 +/**
125.5 + * Back 2 Browser Bytecode Translator
125.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
125.7 + *
125.8 + * This program is free software: you can redistribute it and/or modify
125.9 + * it under the terms of the GNU General Public License as published by
125.10 + * the Free Software Foundation, version 2 of the License.
125.11 + *
125.12 + * This program is distributed in the hope that it will be useful,
125.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
125.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
125.15 + * GNU General Public License for more details.
125.16 + *
125.17 + * You should have received a copy of the GNU General Public License
125.18 + * along with this program. Look for COPYING file in the top folder.
125.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
125.20 + */
125.21 +package org.apidesign.bck2brwsr.emul.reflect;
125.22 +
125.23 +import java.lang.reflect.Constructor;
125.24 +import java.lang.reflect.Type;
125.25 +import java.lang.reflect.TypeVariable;
125.26 +
125.27 +/**
125.28 + *
125.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
125.30 + */
125.31 +public abstract class TypeProvider {
125.32 + private TypeProvider() {
125.33 + }
125.34 +
125.35 + public static TypeProvider getDefault() {
125.36 + return null;
125.37 + }
125.38 +
125.39 + public abstract <T> TypeVariable<Constructor<T>>[] getTypeParameters(Constructor<T> c);
125.40 + public abstract <T> Type[] getGenericParameterTypes(Constructor<T> c);
125.41 + public abstract <T> Type[] getGenericExceptionTypes(Constructor<T> c);
125.42 +
125.43 +}
126.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
126.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/Adler32.java Sun Feb 17 17:58:34 2013 +0100
126.3 @@ -0,0 +1,139 @@
126.4 +/* -*-mode:java; c-basic-offset:2; -*- */
126.5 +/*
126.6 +Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved.
126.7 +
126.8 +Redistribution and use in source and binary forms, with or without
126.9 +modification, are permitted provided that the following conditions are met:
126.10 +
126.11 + 1. Redistributions of source code must retain the above copyright notice,
126.12 + this list of conditions and the following disclaimer.
126.13 +
126.14 + 2. Redistributions in binary form must reproduce the above copyright
126.15 + notice, this list of conditions and the following disclaimer in
126.16 + the documentation and/or other materials provided with the distribution.
126.17 +
126.18 + 3. The names of the authors may not be used to endorse or promote products
126.19 + derived from this software without specific prior written permission.
126.20 +
126.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
126.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
126.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
126.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
126.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
126.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
126.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
126.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
126.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
126.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
126.31 + */
126.32 +/*
126.33 + * This program is based on zlib-1.1.3, so all credit should go authors
126.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
126.35 + * and contributors of zlib.
126.36 + */
126.37 +
126.38 +package org.apidesign.bck2brwsr.emul.zip;
126.39 +
126.40 +final class Adler32 implements Checksum {
126.41 +
126.42 + // largest prime smaller than 65536
126.43 + static final private int BASE=65521;
126.44 + // NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
126.45 + static final private int NMAX=5552;
126.46 +
126.47 + private long s1=1L;
126.48 + private long s2=0L;
126.49 +
126.50 + public void reset(long init){
126.51 + s1=init&0xffff;
126.52 + s2=(init>>16)&0xffff;
126.53 + }
126.54 +
126.55 + public void reset(){
126.56 + s1=1L;
126.57 + s2=0L;
126.58 + }
126.59 +
126.60 + public long getValue(){
126.61 + return ((s2<<16)|s1);
126.62 + }
126.63 +
126.64 + public void update(byte[] buf, int index, int len){
126.65 +
126.66 + if(len==1){
126.67 + s1+=buf[index++]&0xff; s2+=s1;
126.68 + s1%=BASE;
126.69 + s2%=BASE;
126.70 + return;
126.71 + }
126.72 +
126.73 + int len1 = len/NMAX;
126.74 + int len2 = len%NMAX;
126.75 + while(len1-->0) {
126.76 + int k=NMAX;
126.77 + len-=k;
126.78 + while(k-->0){
126.79 + s1+=buf[index++]&0xff; s2+=s1;
126.80 + }
126.81 + s1%=BASE;
126.82 + s2%=BASE;
126.83 + }
126.84 +
126.85 + int k=len2;
126.86 + len-=k;
126.87 + while(k-->0){
126.88 + s1+=buf[index++]&0xff; s2+=s1;
126.89 + }
126.90 + s1%=BASE;
126.91 + s2%=BASE;
126.92 + }
126.93 +
126.94 + public Adler32 copy(){
126.95 + Adler32 foo = new Adler32();
126.96 + foo.s1 = this.s1;
126.97 + foo.s2 = this.s2;
126.98 + return foo;
126.99 + }
126.100 +
126.101 + // The following logic has come from zlib.1.2.
126.102 + static long combine(long adler1, long adler2, long len2){
126.103 + long BASEL = (long)BASE;
126.104 + long sum1;
126.105 + long sum2;
126.106 + long rem; // unsigned int
126.107 +
126.108 + rem = len2 % BASEL;
126.109 + sum1 = adler1 & 0xffffL;
126.110 + sum2 = rem * sum1;
126.111 + sum2 %= BASEL; // MOD(sum2);
126.112 + sum1 += (adler2 & 0xffffL) + BASEL - 1;
126.113 + sum2 += ((adler1 >> 16) & 0xffffL) + ((adler2 >> 16) & 0xffffL) + BASEL - rem;
126.114 + if (sum1 >= BASEL) sum1 -= BASEL;
126.115 + if (sum1 >= BASEL) sum1 -= BASEL;
126.116 + if (sum2 >= (BASEL << 1)) sum2 -= (BASEL << 1);
126.117 + if (sum2 >= BASEL) sum2 -= BASEL;
126.118 + return sum1 | (sum2 << 16);
126.119 + }
126.120 +
126.121 +/*
126.122 + private java.util.zip.Adler32 adler=new java.util.zip.Adler32();
126.123 + public void update(byte[] buf, int index, int len){
126.124 + if(buf==null) {adler.reset();}
126.125 + else{adler.update(buf, index, len);}
126.126 + }
126.127 + public void reset(){
126.128 + adler.reset();
126.129 + }
126.130 + public void reset(long init){
126.131 + if(init==1L){
126.132 + adler.reset();
126.133 + }
126.134 + else{
126.135 + System.err.println("unsupported operation");
126.136 + }
126.137 + }
126.138 + public long getValue(){
126.139 + return adler.getValue();
126.140 + }
126.141 +*/
126.142 +}
127.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
127.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/CRC32.java Sun Feb 17 17:58:34 2013 +0100
127.3 @@ -0,0 +1,181 @@
127.4 +/* -*-mode:java; c-basic-offset:2; -*- */
127.5 +/*
127.6 +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
127.7 +
127.8 +Redistribution and use in source and binary forms, with or without
127.9 +modification, are permitted provided that the following conditions are met:
127.10 +
127.11 + 1. Redistributions of source code must retain the above copyright notice,
127.12 + this list of conditions and the following disclaimer.
127.13 +
127.14 + 2. Redistributions in binary form must reproduce the above copyright
127.15 + notice, this list of conditions and the following disclaimer in
127.16 + the documentation and/or other materials provided with the distribution.
127.17 +
127.18 + 3. The names of the authors may not be used to endorse or promote products
127.19 + derived from this software without specific prior written permission.
127.20 +
127.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
127.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
127.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
127.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
127.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
127.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
127.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
127.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
127.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
127.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
127.31 + */
127.32 +/*
127.33 + * This program is based on zlib-1.1.3, so all credit should go authors
127.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
127.35 + * and contributors of zlib.
127.36 + */
127.37 +
127.38 +package org.apidesign.bck2brwsr.emul.zip;
127.39 +
127.40 +import org.apidesign.bck2brwsr.emul.lang.System;
127.41 +
127.42 +final class CRC32 implements Checksum {
127.43 +
127.44 + /*
127.45 + * The following logic has come from RFC1952.
127.46 + */
127.47 + private int v = 0;
127.48 + private static int[] crc_table = null;
127.49 + static {
127.50 + crc_table = new int[256];
127.51 + for (int n = 0; n < 256; n++) {
127.52 + int c = n;
127.53 + for (int k = 8; --k >= 0; ) {
127.54 + if ((c & 1) != 0)
127.55 + c = 0xedb88320 ^ (c >>> 1);
127.56 + else
127.57 + c = c >>> 1;
127.58 + }
127.59 + crc_table[n] = c;
127.60 + }
127.61 + }
127.62 +
127.63 + public void update (byte[] buf, int index, int len) {
127.64 + int c = ~v;
127.65 + while (--len >= 0)
127.66 + c = crc_table[(c^buf[index++])&0xff]^(c >>> 8);
127.67 + v = ~c;
127.68 + }
127.69 +
127.70 + public void reset(){
127.71 + v = 0;
127.72 + }
127.73 +
127.74 + public void reset(long vv){
127.75 + v = (int)(vv&0xffffffffL);
127.76 + }
127.77 +
127.78 + public long getValue(){
127.79 + return (long)(v&0xffffffffL);
127.80 + }
127.81 +
127.82 + // The following logic has come from zlib.1.2.
127.83 + private static final int GF2_DIM = 32;
127.84 + static long combine(long crc1, long crc2, long len2){
127.85 + long row;
127.86 + long[] even = new long[GF2_DIM];
127.87 + long[] odd = new long[GF2_DIM];
127.88 +
127.89 + // degenerate case (also disallow negative lengths)
127.90 + if (len2 <= 0)
127.91 + return crc1;
127.92 +
127.93 + // put operator for one zero bit in odd
127.94 + odd[0] = 0xedb88320L; // CRC-32 polynomial
127.95 + row = 1;
127.96 + for (int n = 1; n < GF2_DIM; n++) {
127.97 + odd[n] = row;
127.98 + row <<= 1;
127.99 + }
127.100 +
127.101 + // put operator for two zero bits in even
127.102 + gf2_matrix_square(even, odd);
127.103 +
127.104 + // put operator for four zero bits in odd
127.105 + gf2_matrix_square(odd, even);
127.106 +
127.107 + // apply len2 zeros to crc1 (first square will put the operator for one
127.108 + // zero byte, eight zero bits, in even)
127.109 + do {
127.110 + // apply zeros operator for this bit of len2
127.111 + gf2_matrix_square(even, odd);
127.112 + if ((len2 & 1)!=0)
127.113 + crc1 = gf2_matrix_times(even, crc1);
127.114 + len2 >>= 1;
127.115 +
127.116 + // if no more bits set, then done
127.117 + if (len2 == 0)
127.118 + break;
127.119 +
127.120 + // another iteration of the loop with odd and even swapped
127.121 + gf2_matrix_square(odd, even);
127.122 + if ((len2 & 1)!=0)
127.123 + crc1 = gf2_matrix_times(odd, crc1);
127.124 + len2 >>= 1;
127.125 +
127.126 + // if no more bits set, then done
127.127 + } while (len2 != 0);
127.128 +
127.129 + /* return combined crc */
127.130 + crc1 ^= crc2;
127.131 + return crc1;
127.132 + }
127.133 +
127.134 + private static long gf2_matrix_times(long[] mat, long vec){
127.135 + long sum = 0;
127.136 + int index = 0;
127.137 + while (vec!=0) {
127.138 + if ((vec & 1)!=0)
127.139 + sum ^= mat[index];
127.140 + vec >>= 1;
127.141 + index++;
127.142 + }
127.143 + return sum;
127.144 + }
127.145 +
127.146 + static final void gf2_matrix_square(long[] square, long[] mat) {
127.147 + for (int n = 0; n < GF2_DIM; n++)
127.148 + square[n] = gf2_matrix_times(mat, mat[n]);
127.149 + }
127.150 +
127.151 + /*
127.152 + private java.util.zip.CRC32 crc32 = new java.util.zip.CRC32();
127.153 +
127.154 + public void update(byte[] buf, int index, int len){
127.155 + if(buf==null) {crc32.reset();}
127.156 + else{crc32.update(buf, index, len);}
127.157 + }
127.158 + public void reset(){
127.159 + crc32.reset();
127.160 + }
127.161 + public void reset(long init){
127.162 + if(init==0L){
127.163 + crc32.reset();
127.164 + }
127.165 + else{
127.166 + System.err.println("unsupported operation");
127.167 + }
127.168 + }
127.169 + public long getValue(){
127.170 + return crc32.getValue();
127.171 + }
127.172 +*/
127.173 + public CRC32 copy(){
127.174 + CRC32 foo = new CRC32();
127.175 + foo.v = this.v;
127.176 + return foo;
127.177 + }
127.178 +
127.179 + public static int[] getCRC32Table(){
127.180 + int[] tmp = new int[crc_table.length];
127.181 + System.arraycopy(crc_table, 0, tmp, 0, tmp.length);
127.182 + return tmp;
127.183 + }
127.184 +}
128.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
128.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/Checksum.java Sun Feb 17 17:58:34 2013 +0100
128.3 @@ -0,0 +1,43 @@
128.4 +/* -*-mode:java; c-basic-offset:2; -*- */
128.5 +/*
128.6 +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
128.7 +
128.8 +Redistribution and use in source and binary forms, with or without
128.9 +modification, are permitted provided that the following conditions are met:
128.10 +
128.11 + 1. Redistributions of source code must retain the above copyright notice,
128.12 + this list of conditions and the following disclaimer.
128.13 +
128.14 + 2. Redistributions in binary form must reproduce the above copyright
128.15 + notice, this list of conditions and the following disclaimer in
128.16 + the documentation and/or other materials provided with the distribution.
128.17 +
128.18 + 3. The names of the authors may not be used to endorse or promote products
128.19 + derived from this software without specific prior written permission.
128.20 +
128.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
128.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
128.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
128.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
128.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
128.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
128.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
128.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
128.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
128.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
128.31 + */
128.32 +/*
128.33 + * This program is based on zlib-1.1.3, so all credit should go authors
128.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
128.35 + * and contributors of zlib.
128.36 + */
128.37 +
128.38 +package org.apidesign.bck2brwsr.emul.zip;
128.39 +
128.40 +interface Checksum {
128.41 + void update(byte[] buf, int index, int len);
128.42 + void reset();
128.43 + void reset(long init);
128.44 + long getValue();
128.45 + Checksum copy();
128.46 +}
129.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
129.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/FastJar.java Sun Feb 17 17:58:34 2013 +0100
129.3 @@ -0,0 +1,175 @@
129.4 +/*
129.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
129.6 + *
129.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
129.8 + *
129.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
129.10 + * Other names may be trademarks of their respective owners.
129.11 + *
129.12 + * The contents of this file are subject to the terms of either the GNU
129.13 + * General Public License Version 2 only ("GPL") or the Common
129.14 + * Development and Distribution License("CDDL") (collectively, the
129.15 + * "License"). You may not use this file except in compliance with the
129.16 + * License. You can obtain a copy of the License at
129.17 + * http://www.netbeans.org/cddl-gplv2.html
129.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
129.19 + * specific language governing permissions and limitations under the
129.20 + * License. When distributing the software, include this License Header
129.21 + * Notice in each file and include the License file at
129.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
129.23 + * particular file as subject to the "Classpath" exception as provided
129.24 + * by Oracle in the GPL Version 2 section of the License file that
129.25 + * accompanied this code. If applicable, add the following below the
129.26 + * License Header, with the fields enclosed by brackets [] replaced by
129.27 + * your own identifying information:
129.28 + * "Portions Copyrighted [year] [name of copyright owner]"
129.29 + *
129.30 + * Contributor(s):
129.31 + *
129.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
129.33 + */
129.34 +package org.apidesign.bck2brwsr.emul.zip;
129.35 +
129.36 +import java.io.ByteArrayInputStream;
129.37 +import java.io.IOException;
129.38 +import java.io.InputStream;
129.39 +import java.util.zip.ZipEntry;
129.40 +import java.util.zip.ZipInputStream;
129.41 +
129.42 +/**
129.43 + *
129.44 + * @author Tomas Zezula
129.45 + */
129.46 +public final class FastJar {
129.47 + private final byte[] arr;
129.48 +
129.49 + public FastJar(byte[] arr) {
129.50 + this.arr = arr;
129.51 + }
129.52 +
129.53 +
129.54 + private static final int GIVE_UP = 1<<16;
129.55 +
129.56 + public static final class Entry {
129.57 +
129.58 + public final String name;
129.59 + final long offset;
129.60 + private final long dosTime;
129.61 +
129.62 + Entry (String name, long offset, long time) {
129.63 + assert name != null;
129.64 + this.name = name;
129.65 + this.offset = offset;
129.66 + this.dosTime = time;
129.67 + }
129.68 +/*
129.69 + public long getTime () {
129.70 + Date d = new Date((int)(((dosTime >> 25) & 0x7f) + 80),
129.71 + (int)(((dosTime >> 21) & 0x0f) - 1),
129.72 + (int)((dosTime >> 16) & 0x1f),
129.73 + (int)((dosTime >> 11) & 0x1f),
129.74 + (int)((dosTime >> 5) & 0x3f),
129.75 + (int)((dosTime << 1) & 0x3e));
129.76 + return d.getTime();
129.77 + }
129.78 + */
129.79 + }
129.80 +
129.81 + public InputStream getInputStream (final Entry e) throws IOException {
129.82 + return getInputStream(arr, e.offset);
129.83 + }
129.84 +
129.85 + private static InputStream getInputStream (byte[] arr, final long offset) throws IOException {
129.86 + ByteArrayInputStream is = new ByteArrayInputStream(arr);
129.87 + is.skip(offset);
129.88 + ZipInputStream in = new ZipInputStream (is);
129.89 + ZipEntry e = in.getNextEntry();
129.90 + if (e != null && e.getCrc() == 0L && e.getMethod() == ZipEntry.STORED) {
129.91 + int cp = arr.length - is.available();
129.92 + return new ByteArrayInputStream(arr, cp, (int)e.getSize());
129.93 + }
129.94 + return in;
129.95 + }
129.96 +
129.97 + public Entry[] list() throws IOException {
129.98 + final int size = arr.length;
129.99 +
129.100 + int at = size - ZipInputStream.ENDHDR;
129.101 +
129.102 + byte[] data = new byte[ZipInputStream.ENDHDR];
129.103 + int giveup = 0;
129.104 +
129.105 + do {
129.106 + org.apidesign.bck2brwsr.emul.lang.System.arraycopy(arr, at, data, 0, data.length);
129.107 + at--;
129.108 + giveup++;
129.109 + if (giveup > GIVE_UP) {
129.110 + throw new IOException ();
129.111 + }
129.112 + } while (getsig(data) != ZipInputStream.ENDSIG);
129.113 +
129.114 +
129.115 + final long censize = endsiz(data);
129.116 + final long cenoff = endoff(data);
129.117 + at = (int) cenoff;
129.118 +
129.119 + Entry[] result = new Entry[0];
129.120 + int cenread = 0;
129.121 + data = new byte[ZipInputStream.CENHDR];
129.122 + while (cenread < censize) {
129.123 + org.apidesign.bck2brwsr.emul.lang.System.arraycopy(arr, at, data, 0, data.length);
129.124 + at += data.length;
129.125 + if (getsig(data) != ZipInputStream.CENSIG) {
129.126 + throw new IOException("No central table"); //NOI18N
129.127 + }
129.128 + int cennam = cennam(data);
129.129 + int cenext = cenext(data);
129.130 + int cencom = cencom(data);
129.131 + long lhoff = cenoff(data);
129.132 + long centim = centim(data);
129.133 + String name = new String(arr, at, cennam, "UTF-8");
129.134 + at += cennam;
129.135 + int seekby = cenext+cencom;
129.136 + int cendatalen = ZipInputStream.CENHDR + cennam + seekby;
129.137 + cenread+=cendatalen;
129.138 + result = addEntry(result, new Entry(name,lhoff, centim));
129.139 + at += seekby;
129.140 + }
129.141 + return result;
129.142 + }
129.143 +
129.144 + private Entry[] addEntry(Entry[] result, Entry entry) {
129.145 + Entry[] e = new Entry[result.length + 1];
129.146 + e[result.length] = entry;
129.147 + org.apidesign.bck2brwsr.emul.lang.System.arraycopy(result, 0, e, 0, result.length);
129.148 + return e;
129.149 + }
129.150 +
129.151 + private static final long getsig(final byte[] b) throws IOException {return get32(b,0);}
129.152 + private static final long endsiz(final byte[] b) throws IOException {return get32(b,ZipInputStream.ENDSIZ);}
129.153 + private static final long endoff(final byte[] b) throws IOException {return get32(b,ZipInputStream.ENDOFF);}
129.154 + private static final long cenlen(final byte[] b) throws IOException {return get32(b,ZipInputStream.CENLEN);}
129.155 + private static final long censiz(final byte[] b) throws IOException {return get32(b,ZipInputStream.CENSIZ);}
129.156 + private static final long centim(final byte[] b) throws IOException {return get32(b,ZipInputStream.CENTIM);}
129.157 + private static final int cennam(final byte[] b) throws IOException {return get16(b,ZipInputStream.CENNAM);}
129.158 + private static final int cenext(final byte[] b) throws IOException {return get16(b,ZipInputStream.CENEXT);}
129.159 + private static final int cencom(final byte[] b) throws IOException {return get16(b,ZipInputStream.CENCOM);}
129.160 + private static final long cenoff (final byte[] b) throws IOException {return get32(b,ZipInputStream.CENOFF);}
129.161 + private static final int lochow(final byte[] b) throws IOException {return get16(b,ZipInputStream.LOCHOW);}
129.162 + private static final int locname(final byte[] b) throws IOException {return get16(b,ZipInputStream.LOCNAM);}
129.163 + private static final int locext(final byte[] b) throws IOException {return get16(b,ZipInputStream.LOCEXT);}
129.164 + private static final long locsiz(final byte[] b) throws IOException {return get32(b,ZipInputStream.LOCSIZ);}
129.165 +
129.166 + private static final int get16(final byte[] b, int off) throws IOException {
129.167 + final int b1 = b[off];
129.168 + final int b2 = b[off+1];
129.169 + return (b1 & 0xff) | ((b2 & 0xff) << 8);
129.170 + }
129.171 +
129.172 + private static final long get32(final byte[] b, int off) throws IOException {
129.173 + final int s1 = get16(b, off);
129.174 + final int s2 = get16(b, off+2);
129.175 + return s1 | ((long)s2 << 16);
129.176 + }
129.177 +
129.178 +}
130.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
130.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/GZIPHeader.java Sun Feb 17 17:58:34 2013 +0100
130.3 @@ -0,0 +1,215 @@
130.4 +/* -*-mode:java; c-basic-offset:2; -*- */
130.5 +/*
130.6 +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
130.7 +
130.8 +Redistribution and use in source and binary forms, with or without
130.9 +modification, are permitted provided that the following conditions are met:
130.10 +
130.11 + 1. Redistributions of source code must retain the above copyright notice,
130.12 + this list of conditions and the following disclaimer.
130.13 +
130.14 + 2. Redistributions in binary form must reproduce the above copyright
130.15 + notice, this list of conditions and the following disclaimer in
130.16 + the documentation and/or other materials provided with the distribution.
130.17 +
130.18 + 3. The names of the authors may not be used to endorse or promote products
130.19 + derived from this software without specific prior written permission.
130.20 +
130.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
130.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
130.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
130.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
130.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
130.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
130.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
130.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
130.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
130.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
130.31 + */
130.32 +/*
130.33 + * This program is based on zlib-1.1.3, so all credit should go authors
130.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
130.35 + * and contributors of zlib.
130.36 + */
130.37 +
130.38 +package org.apidesign.bck2brwsr.emul.zip;
130.39 +
130.40 +import org.apidesign.bck2brwsr.emul.lang.System;
130.41 +import java.io.UnsupportedEncodingException;
130.42 +
130.43 +/**
130.44 + * @see "http://www.ietf.org/rfc/rfc1952.txt"
130.45 + */
130.46 +final class GZIPHeader implements Cloneable {
130.47 +
130.48 + public static final byte OS_MSDOS = (byte) 0x00;
130.49 + public static final byte OS_AMIGA = (byte) 0x01;
130.50 + public static final byte OS_VMS = (byte) 0x02;
130.51 + public static final byte OS_UNIX = (byte) 0x03;
130.52 + public static final byte OS_ATARI = (byte) 0x05;
130.53 + public static final byte OS_OS2 = (byte) 0x06;
130.54 + public static final byte OS_MACOS = (byte) 0x07;
130.55 + public static final byte OS_TOPS20 = (byte) 0x0a;
130.56 + public static final byte OS_WIN32 = (byte) 0x0b;
130.57 + public static final byte OS_VMCMS = (byte) 0x04;
130.58 + public static final byte OS_ZSYSTEM = (byte) 0x08;
130.59 + public static final byte OS_CPM = (byte) 0x09;
130.60 + public static final byte OS_QDOS = (byte) 0x0c;
130.61 + public static final byte OS_RISCOS = (byte) 0x0d;
130.62 + public static final byte OS_UNKNOWN = (byte) 0xff;
130.63 +
130.64 + boolean text = false;
130.65 + private boolean fhcrc = false;
130.66 + long time;
130.67 + int xflags;
130.68 + int os = 255;
130.69 + byte[] extra;
130.70 + byte[] name;
130.71 + byte[] comment;
130.72 + int hcrc;
130.73 + long crc;
130.74 + boolean done = false;
130.75 + long mtime = 0;
130.76 +
130.77 + public void setModifiedTime(long mtime) {
130.78 + this.mtime = mtime;
130.79 + }
130.80 +
130.81 + public long getModifiedTime() {
130.82 + return mtime;
130.83 + }
130.84 +
130.85 + public void setOS(int os) {
130.86 + if((0<=os && os <=13) || os==255)
130.87 + this.os=os;
130.88 + else
130.89 + throw new IllegalArgumentException("os: "+os);
130.90 + }
130.91 +
130.92 + public int getOS(){
130.93 + return os;
130.94 + }
130.95 +
130.96 + public void setName(String name) {
130.97 + try{
130.98 + this.name=name.getBytes("ISO-8859-1");
130.99 + }
130.100 + catch(UnsupportedEncodingException e){
130.101 + throw new IllegalArgumentException("name must be in ISO-8859-1 "+name);
130.102 + }
130.103 + }
130.104 +
130.105 + public String getName(){
130.106 + if(name==null) return "";
130.107 + try {
130.108 + return new String(name, "ISO-8859-1");
130.109 + }
130.110 + catch (UnsupportedEncodingException e) {
130.111 + throw new IllegalArgumentException(e.toString());
130.112 + }
130.113 + }
130.114 +
130.115 + public void setComment(String comment) {
130.116 + try{
130.117 + this.comment=comment.getBytes("ISO-8859-1");
130.118 + }
130.119 + catch(UnsupportedEncodingException e){
130.120 + throw new IllegalArgumentException("comment must be in ISO-8859-1 "+name);
130.121 + }
130.122 + }
130.123 +
130.124 + public String getComment(){
130.125 + if(comment==null) return "";
130.126 + try {
130.127 + return new String(comment, "ISO-8859-1");
130.128 + }
130.129 + catch (UnsupportedEncodingException e) {
130.130 + throw new IllegalArgumentException(e.toString());
130.131 + }
130.132 + }
130.133 +
130.134 + public void setCRC(long crc){
130.135 + this.crc = crc;
130.136 + }
130.137 +
130.138 + public long getCRC(){
130.139 + return crc;
130.140 + }
130.141 +/*
130.142 + void put(Deflate d){
130.143 + int flag = 0;
130.144 + if(text){
130.145 + flag |= 1; // FTEXT
130.146 + }
130.147 + if(fhcrc){
130.148 + flag |= 2; // FHCRC
130.149 + }
130.150 + if(extra!=null){
130.151 + flag |= 4; // FEXTRA
130.152 + }
130.153 + if(name!=null){
130.154 + flag |= 8; // FNAME
130.155 + }
130.156 + if(comment!=null){
130.157 + flag |= 16; // FCOMMENT
130.158 + }
130.159 + int xfl = 0;
130.160 + if(d.level == JZlib.Z_BEST_SPEED){
130.161 + xfl |= 4;
130.162 + }
130.163 + else if (d.level == JZlib.Z_BEST_COMPRESSION){
130.164 + xfl |= 2;
130.165 + }
130.166 +
130.167 + d.put_short((short)0x8b1f); // ID1 ID2
130.168 + d.put_byte((byte)8); // CM(Compression Method)
130.169 + d.put_byte((byte)flag);
130.170 + d.put_byte((byte)mtime);
130.171 + d.put_byte((byte)(mtime>>8));
130.172 + d.put_byte((byte)(mtime>>16));
130.173 + d.put_byte((byte)(mtime>>24));
130.174 + d.put_byte((byte)xfl);
130.175 + d.put_byte((byte)os);
130.176 +
130.177 + if(extra!=null){
130.178 + d.put_byte((byte)extra.length);
130.179 + d.put_byte((byte)(extra.length>>8));
130.180 + d.put_byte(extra, 0, extra.length);
130.181 + }
130.182 +
130.183 + if(name!=null){
130.184 + d.put_byte(name, 0, name.length);
130.185 + d.put_byte((byte)0);
130.186 + }
130.187 +
130.188 + if(comment!=null){
130.189 + d.put_byte(comment, 0, comment.length);
130.190 + d.put_byte((byte)0);
130.191 + }
130.192 + }
130.193 +*/
130.194 + @Override
130.195 + public Object clone() throws CloneNotSupportedException {
130.196 + GZIPHeader gheader = (GZIPHeader)super.clone();
130.197 + byte[] tmp;
130.198 + if(gheader.extra!=null){
130.199 + tmp=new byte[gheader.extra.length];
130.200 + System.arraycopy(gheader.extra, 0, tmp, 0, tmp.length);
130.201 + gheader.extra = tmp;
130.202 + }
130.203 +
130.204 + if(gheader.name!=null){
130.205 + tmp=new byte[gheader.name.length];
130.206 + System.arraycopy(gheader.name, 0, tmp, 0, tmp.length);
130.207 + gheader.name = tmp;
130.208 + }
130.209 +
130.210 + if(gheader.comment!=null){
130.211 + tmp=new byte[gheader.comment.length];
130.212 + System.arraycopy(gheader.comment, 0, tmp, 0, tmp.length);
130.213 + gheader.comment = tmp;
130.214 + }
130.215 +
130.216 + return gheader;
130.217 + }
130.218 +}
131.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
131.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/InfBlocks.java Sun Feb 17 17:58:34 2013 +0100
131.3 @@ -0,0 +1,616 @@
131.4 +/* -*-mode:java; c-basic-offset:2; -*- */
131.5 +/*
131.6 +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
131.7 +
131.8 +Redistribution and use in source and binary forms, with or without
131.9 +modification, are permitted provided that the following conditions are met:
131.10 +
131.11 + 1. Redistributions of source code must retain the above copyright notice,
131.12 + this list of conditions and the following disclaimer.
131.13 +
131.14 + 2. Redistributions in binary form must reproduce the above copyright
131.15 + notice, this list of conditions and the following disclaimer in
131.16 + the documentation and/or other materials provided with the distribution.
131.17 +
131.18 + 3. The names of the authors may not be used to endorse or promote products
131.19 + derived from this software without specific prior written permission.
131.20 +
131.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
131.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
131.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
131.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
131.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
131.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
131.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
131.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
131.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
131.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
131.31 + */
131.32 +/*
131.33 + * This program is based on zlib-1.1.3, so all credit should go authors
131.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
131.35 + * and contributors of zlib.
131.36 + */
131.37 +
131.38 +package org.apidesign.bck2brwsr.emul.zip;
131.39 +
131.40 +import org.apidesign.bck2brwsr.emul.lang.System;
131.41 +
131.42 +final class InfBlocks{
131.43 + static final private int MANY=1440;
131.44 +
131.45 + // And'ing with mask[n] masks the lower n bits
131.46 + static final private int[] inflate_mask = {
131.47 + 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
131.48 + 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
131.49 + 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
131.50 + 0x00007fff, 0x0000ffff
131.51 + };
131.52 +
131.53 + // Table for deflate from PKZIP's appnote.txt.
131.54 + static final int[] border = { // Order of the bit length code lengths
131.55 + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
131.56 + };
131.57 +
131.58 + static final private int Z_OK=0;
131.59 + static final private int Z_STREAM_END=1;
131.60 + static final private int Z_NEED_DICT=2;
131.61 + static final private int Z_ERRNO=-1;
131.62 + static final private int Z_STREAM_ERROR=-2;
131.63 + static final private int Z_DATA_ERROR=-3;
131.64 + static final private int Z_MEM_ERROR=-4;
131.65 + static final private int Z_BUF_ERROR=-5;
131.66 + static final private int Z_VERSION_ERROR=-6;
131.67 +
131.68 + static final private int TYPE=0; // get type bits (3, including end bit)
131.69 + static final private int LENS=1; // get lengths for stored
131.70 + static final private int STORED=2;// processing stored block
131.71 + static final private int TABLE=3; // get table lengths
131.72 + static final private int BTREE=4; // get bit lengths tree for a dynamic block
131.73 + static final private int DTREE=5; // get length, distance trees for a dynamic block
131.74 + static final private int CODES=6; // processing fixed or dynamic block
131.75 + static final private int DRY=7; // output remaining window bytes
131.76 + static final private int DONE=8; // finished last block, done
131.77 + static final private int BAD=9; // ot a data error--stuck here
131.78 +
131.79 + int mode; // current inflate_block mode
131.80 +
131.81 + int left; // if STORED, bytes left to copy
131.82 +
131.83 + int table; // table lengths (14 bits)
131.84 + int index; // index into blens (or border)
131.85 + int[] blens; // bit lengths of codes
131.86 + int[] bb=new int[1]; // bit length tree depth
131.87 + int[] tb=new int[1]; // bit length decoding tree
131.88 +
131.89 + int[] bl=new int[1];
131.90 + int[] bd=new int[1];
131.91 +
131.92 + int[][] tl=new int[1][];
131.93 + int[][] td=new int[1][];
131.94 + int[] tli=new int[1]; // tl_index
131.95 + int[] tdi=new int[1]; // td_index
131.96 +
131.97 + private final InfCodes codes; // if CODES, current state
131.98 +
131.99 + int last; // true if this block is the last block
131.100 +
131.101 + // mode independent information
131.102 + int bitk; // bits in bit buffer
131.103 + int bitb; // bit buffer
131.104 + int[] hufts; // single malloc for tree space
131.105 + byte[] window; // sliding window
131.106 + int end; // one byte after sliding window
131.107 + int read; // window read pointer
131.108 + int write; // window write pointer
131.109 + private boolean check;
131.110 +
131.111 + private final InfTree inftree=new InfTree();
131.112 +
131.113 + private final ZStream z;
131.114 +
131.115 + InfBlocks(ZStream z, int w){
131.116 + this.z=z;
131.117 + this.codes=new InfCodes(this.z, this);
131.118 + hufts=new int[MANY*3];
131.119 + window=new byte[w];
131.120 + end=w;
131.121 + this.check = (z.istate.wrap==0) ? false : true;
131.122 + mode = TYPE;
131.123 + reset();
131.124 + }
131.125 +
131.126 + void reset(){
131.127 + if(mode==BTREE || mode==DTREE){
131.128 + }
131.129 + if(mode==CODES){
131.130 + codes.free(z);
131.131 + }
131.132 + mode=TYPE;
131.133 + bitk=0;
131.134 + bitb=0;
131.135 + read=write=0;
131.136 + if(check){
131.137 + z.adler.reset();
131.138 + }
131.139 + }
131.140 +
131.141 + int proc(int r){
131.142 + int t; // temporary storage
131.143 + int b; // bit buffer
131.144 + int k; // bits in bit buffer
131.145 + int p; // input data pointer
131.146 + int n; // bytes available there
131.147 + int q; // output window write pointer
131.148 + int m; // bytes to end of window or read pointer
131.149 +
131.150 + // copy input/output information to locals (UPDATE macro restores)
131.151 + {p=z.next_in_index;n=z.avail_in;b=bitb;k=bitk;}
131.152 + {q=write;m=(int)(q<read?read-q-1:end-q);}
131.153 +
131.154 + // process input based on current state
131.155 + while(true){
131.156 + switch (mode){
131.157 + case TYPE:
131.158 +
131.159 + while(k<(3)){
131.160 + if(n!=0){
131.161 + r=Z_OK;
131.162 + }
131.163 + else{
131.164 + bitb=b; bitk=k;
131.165 + z.avail_in=n;
131.166 + z.total_in+=p-z.next_in_index;z.next_in_index=p;
131.167 + write=q;
131.168 + return inflate_flush(r);
131.169 + };
131.170 + n--;
131.171 + b|=(z.next_in[p++]&0xff)<<k;
131.172 + k+=8;
131.173 + }
131.174 + t = (int)(b & 7);
131.175 + last = t & 1;
131.176 +
131.177 + switch (t >>> 1){
131.178 + case 0: // stored
131.179 + {b>>>=(3);k-=(3);}
131.180 + t = k & 7; // go to byte boundary
131.181 +
131.182 + {b>>>=(t);k-=(t);}
131.183 + mode = LENS; // get length of stored block
131.184 + break;
131.185 + case 1: // fixed
131.186 + InfTree.inflate_trees_fixed(bl, bd, tl, td, z);
131.187 + codes.init(bl[0], bd[0], tl[0], 0, td[0], 0);
131.188 +
131.189 + {b>>>=(3);k-=(3);}
131.190 +
131.191 + mode = CODES;
131.192 + break;
131.193 + case 2: // dynamic
131.194 +
131.195 + {b>>>=(3);k-=(3);}
131.196 +
131.197 + mode = TABLE;
131.198 + break;
131.199 + case 3: // illegal
131.200 +
131.201 + {b>>>=(3);k-=(3);}
131.202 + mode = BAD;
131.203 + z.msg = "invalid block type";
131.204 + r = Z_DATA_ERROR;
131.205 +
131.206 + bitb=b; bitk=k;
131.207 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
131.208 + write=q;
131.209 + return inflate_flush(r);
131.210 + }
131.211 + break;
131.212 + case LENS:
131.213 +
131.214 + while(k<(32)){
131.215 + if(n!=0){
131.216 + r=Z_OK;
131.217 + }
131.218 + else{
131.219 + bitb=b; bitk=k;
131.220 + z.avail_in=n;
131.221 + z.total_in+=p-z.next_in_index;z.next_in_index=p;
131.222 + write=q;
131.223 + return inflate_flush(r);
131.224 + };
131.225 + n--;
131.226 + b|=(z.next_in[p++]&0xff)<<k;
131.227 + k+=8;
131.228 + }
131.229 +
131.230 + if ((((~b) >>> 16) & 0xffff) != (b & 0xffff)){
131.231 + mode = BAD;
131.232 + z.msg = "invalid stored block lengths";
131.233 + r = Z_DATA_ERROR;
131.234 +
131.235 + bitb=b; bitk=k;
131.236 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
131.237 + write=q;
131.238 + return inflate_flush(r);
131.239 + }
131.240 + left = (b & 0xffff);
131.241 + b = k = 0; // dump bits
131.242 + mode = left!=0 ? STORED : (last!=0 ? DRY : TYPE);
131.243 + break;
131.244 + case STORED:
131.245 + if (n == 0){
131.246 + bitb=b; bitk=k;
131.247 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
131.248 + write=q;
131.249 + return inflate_flush(r);
131.250 + }
131.251 +
131.252 + if(m==0){
131.253 + if(q==end&&read!=0){
131.254 + q=0; m=(int)(q<read?read-q-1:end-q);
131.255 + }
131.256 + if(m==0){
131.257 + write=q;
131.258 + r=inflate_flush(r);
131.259 + q=write;m=(int)(q<read?read-q-1:end-q);
131.260 + if(q==end&&read!=0){
131.261 + q=0; m=(int)(q<read?read-q-1:end-q);
131.262 + }
131.263 + if(m==0){
131.264 + bitb=b; bitk=k;
131.265 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
131.266 + write=q;
131.267 + return inflate_flush(r);
131.268 + }
131.269 + }
131.270 + }
131.271 + r=Z_OK;
131.272 +
131.273 + t = left;
131.274 + if(t>n) t = n;
131.275 + if(t>m) t = m;
131.276 + System.arraycopy(z.next_in, p, window, q, t);
131.277 + p += t; n -= t;
131.278 + q += t; m -= t;
131.279 + if ((left -= t) != 0)
131.280 + break;
131.281 + mode = last!=0 ? DRY : TYPE;
131.282 + break;
131.283 + case TABLE:
131.284 +
131.285 + while(k<(14)){
131.286 + if(n!=0){
131.287 + r=Z_OK;
131.288 + }
131.289 + else{
131.290 + bitb=b; bitk=k;
131.291 + z.avail_in=n;
131.292 + z.total_in+=p-z.next_in_index;z.next_in_index=p;
131.293 + write=q;
131.294 + return inflate_flush(r);
131.295 + };
131.296 + n--;
131.297 + b|=(z.next_in[p++]&0xff)<<k;
131.298 + k+=8;
131.299 + }
131.300 +
131.301 + table = t = (b & 0x3fff);
131.302 + if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
131.303 + {
131.304 + mode = BAD;
131.305 + z.msg = "too many length or distance symbols";
131.306 + r = Z_DATA_ERROR;
131.307 +
131.308 + bitb=b; bitk=k;
131.309 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
131.310 + write=q;
131.311 + return inflate_flush(r);
131.312 + }
131.313 + t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
131.314 + if(blens==null || blens.length<t){
131.315 + blens=new int[t];
131.316 + }
131.317 + else{
131.318 + for(int i=0; i<t; i++){blens[i]=0;}
131.319 + }
131.320 +
131.321 + {b>>>=(14);k-=(14);}
131.322 +
131.323 + index = 0;
131.324 + mode = BTREE;
131.325 + case BTREE:
131.326 + while (index < 4 + (table >>> 10)){
131.327 + while(k<(3)){
131.328 + if(n!=0){
131.329 + r=Z_OK;
131.330 + }
131.331 + else{
131.332 + bitb=b; bitk=k;
131.333 + z.avail_in=n;
131.334 + z.total_in+=p-z.next_in_index;z.next_in_index=p;
131.335 + write=q;
131.336 + return inflate_flush(r);
131.337 + };
131.338 + n--;
131.339 + b|=(z.next_in[p++]&0xff)<<k;
131.340 + k+=8;
131.341 + }
131.342 +
131.343 + blens[border[index++]] = b&7;
131.344 +
131.345 + {b>>>=(3);k-=(3);}
131.346 + }
131.347 +
131.348 + while(index < 19){
131.349 + blens[border[index++]] = 0;
131.350 + }
131.351 +
131.352 + bb[0] = 7;
131.353 + t = inftree.inflate_trees_bits(blens, bb, tb, hufts, z);
131.354 + if (t != Z_OK){
131.355 + r = t;
131.356 + if (r == Z_DATA_ERROR){
131.357 + blens=null;
131.358 + mode = BAD;
131.359 + }
131.360 +
131.361 + bitb=b; bitk=k;
131.362 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
131.363 + write=q;
131.364 + return inflate_flush(r);
131.365 + }
131.366 +
131.367 + index = 0;
131.368 + mode = DTREE;
131.369 + case DTREE:
131.370 + while (true){
131.371 + t = table;
131.372 + if(!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))){
131.373 + break;
131.374 + }
131.375 +
131.376 + int[] h;
131.377 + int i, j, c;
131.378 +
131.379 + t = bb[0];
131.380 +
131.381 + while(k<(t)){
131.382 + if(n!=0){
131.383 + r=Z_OK;
131.384 + }
131.385 + else{
131.386 + bitb=b; bitk=k;
131.387 + z.avail_in=n;
131.388 + z.total_in+=p-z.next_in_index;z.next_in_index=p;
131.389 + write=q;
131.390 + return inflate_flush(r);
131.391 + };
131.392 + n--;
131.393 + b|=(z.next_in[p++]&0xff)<<k;
131.394 + k+=8;
131.395 + }
131.396 +
131.397 + if(tb[0]==-1){
131.398 + //System.err.println("null...");
131.399 + }
131.400 +
131.401 + t=hufts[(tb[0]+(b&inflate_mask[t]))*3+1];
131.402 + c=hufts[(tb[0]+(b&inflate_mask[t]))*3+2];
131.403 +
131.404 + if (c < 16){
131.405 + b>>>=(t);k-=(t);
131.406 + blens[index++] = c;
131.407 + }
131.408 + else { // c == 16..18
131.409 + i = c == 18 ? 7 : c - 14;
131.410 + j = c == 18 ? 11 : 3;
131.411 +
131.412 + while(k<(t+i)){
131.413 + if(n!=0){
131.414 + r=Z_OK;
131.415 + }
131.416 + else{
131.417 + bitb=b; bitk=k;
131.418 + z.avail_in=n;
131.419 + z.total_in+=p-z.next_in_index;z.next_in_index=p;
131.420 + write=q;
131.421 + return inflate_flush(r);
131.422 + };
131.423 + n--;
131.424 + b|=(z.next_in[p++]&0xff)<<k;
131.425 + k+=8;
131.426 + }
131.427 +
131.428 + b>>>=(t);k-=(t);
131.429 +
131.430 + j += (b & inflate_mask[i]);
131.431 +
131.432 + b>>>=(i);k-=(i);
131.433 +
131.434 + i = index;
131.435 + t = table;
131.436 + if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
131.437 + (c == 16 && i < 1)){
131.438 + blens=null;
131.439 + mode = BAD;
131.440 + z.msg = "invalid bit length repeat";
131.441 + r = Z_DATA_ERROR;
131.442 +
131.443 + bitb=b; bitk=k;
131.444 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
131.445 + write=q;
131.446 + return inflate_flush(r);
131.447 + }
131.448 +
131.449 + c = c == 16 ? blens[i-1] : 0;
131.450 + do{
131.451 + blens[i++] = c;
131.452 + }
131.453 + while (--j!=0);
131.454 + index = i;
131.455 + }
131.456 + }
131.457 +
131.458 + tb[0]=-1;
131.459 + {
131.460 + bl[0] = 9; // must be <= 9 for lookahead assumptions
131.461 + bd[0] = 6; // must be <= 9 for lookahead assumptions
131.462 + t = table;
131.463 + t = inftree.inflate_trees_dynamic(257 + (t & 0x1f),
131.464 + 1 + ((t >> 5) & 0x1f),
131.465 + blens, bl, bd, tli, tdi, hufts, z);
131.466 +
131.467 + if (t != Z_OK){
131.468 + if (t == Z_DATA_ERROR){
131.469 + blens=null;
131.470 + mode = BAD;
131.471 + }
131.472 + r = t;
131.473 +
131.474 + bitb=b; bitk=k;
131.475 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
131.476 + write=q;
131.477 + return inflate_flush(r);
131.478 + }
131.479 + codes.init(bl[0], bd[0], hufts, tli[0], hufts, tdi[0]);
131.480 + }
131.481 + mode = CODES;
131.482 + case CODES:
131.483 + bitb=b; bitk=k;
131.484 + z.avail_in=n; z.total_in+=p-z.next_in_index;z.next_in_index=p;
131.485 + write=q;
131.486 +
131.487 + if ((r = codes.proc(r)) != Z_STREAM_END){
131.488 + return inflate_flush(r);
131.489 + }
131.490 + r = Z_OK;
131.491 + codes.free(z);
131.492 +
131.493 + p=z.next_in_index; n=z.avail_in;b=bitb;k=bitk;
131.494 + q=write;m=(int)(q<read?read-q-1:end-q);
131.495 +
131.496 + if (last==0){
131.497 + mode = TYPE;
131.498 + break;
131.499 + }
131.500 + mode = DRY;
131.501 + case DRY:
131.502 + write=q;
131.503 + r=inflate_flush(r);
131.504 + q=write; m=(int)(q<read?read-q-1:end-q);
131.505 + if (read != write){
131.506 + bitb=b; bitk=k;
131.507 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
131.508 + write=q;
131.509 + return inflate_flush(r);
131.510 + }
131.511 + mode = DONE;
131.512 + case DONE:
131.513 + r = Z_STREAM_END;
131.514 +
131.515 + bitb=b; bitk=k;
131.516 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
131.517 + write=q;
131.518 + return inflate_flush(r);
131.519 + case BAD:
131.520 + r = Z_DATA_ERROR;
131.521 +
131.522 + bitb=b; bitk=k;
131.523 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
131.524 + write=q;
131.525 + return inflate_flush(r);
131.526 +
131.527 + default:
131.528 + r = Z_STREAM_ERROR;
131.529 +
131.530 + bitb=b; bitk=k;
131.531 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
131.532 + write=q;
131.533 + return inflate_flush(r);
131.534 + }
131.535 + }
131.536 + }
131.537 +
131.538 + void free(){
131.539 + reset();
131.540 + window=null;
131.541 + hufts=null;
131.542 + //ZFREE(z, s);
131.543 + }
131.544 +
131.545 + void set_dictionary(byte[] d, int start, int n){
131.546 + System.arraycopy(d, start, window, 0, n);
131.547 + read = write = n;
131.548 + }
131.549 +
131.550 + // Returns true if inflate is currently at the end of a block generated
131.551 + // by Z_SYNC_FLUSH or Z_FULL_FLUSH.
131.552 + int sync_point(){
131.553 + return mode == LENS ? 1 : 0;
131.554 + }
131.555 +
131.556 + // copy as much as possible from the sliding window to the output area
131.557 + int inflate_flush(int r){
131.558 + int n;
131.559 + int p;
131.560 + int q;
131.561 +
131.562 + // local copies of source and destination pointers
131.563 + p = z.next_out_index;
131.564 + q = read;
131.565 +
131.566 + // compute number of bytes to copy as far as end of window
131.567 + n = (int)((q <= write ? write : end) - q);
131.568 + if(n > z.avail_out) n = z.avail_out;
131.569 + if(n!=0 && r == Z_BUF_ERROR) r = Z_OK;
131.570 +
131.571 + // update counters
131.572 + z.avail_out -= n;
131.573 + z.total_out += n;
131.574 +
131.575 + // update check information
131.576 + if(check && n>0){
131.577 + z.adler.update(window, q, n);
131.578 + }
131.579 +
131.580 + // copy as far as end of window
131.581 + System.arraycopy(window, q, z.next_out, p, n);
131.582 + p += n;
131.583 + q += n;
131.584 +
131.585 + // see if more to copy at beginning of window
131.586 + if (q == end){
131.587 + // wrap pointers
131.588 + q = 0;
131.589 + if (write == end)
131.590 + write = 0;
131.591 +
131.592 + // compute bytes to copy
131.593 + n = write - q;
131.594 + if (n > z.avail_out) n = z.avail_out;
131.595 + if (n!=0 && r == Z_BUF_ERROR) r = Z_OK;
131.596 +
131.597 + // update counters
131.598 + z.avail_out -= n;
131.599 + z.total_out += n;
131.600 +
131.601 + // update check information
131.602 + if(check && n>0){
131.603 + z.adler.update(window, q, n);
131.604 + }
131.605 +
131.606 + // copy
131.607 + System.arraycopy(window, q, z.next_out, p, n);
131.608 + p += n;
131.609 + q += n;
131.610 + }
131.611 +
131.612 + // update pointers
131.613 + z.next_out_index = p;
131.614 + read = q;
131.615 +
131.616 + // done
131.617 + return r;
131.618 + }
131.619 +}
132.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
132.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/InfCodes.java Sun Feb 17 17:58:34 2013 +0100
132.3 @@ -0,0 +1,612 @@
132.4 +/* -*-mode:java; c-basic-offset:2; -*- */
132.5 +/*
132.6 +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
132.7 +
132.8 +Redistribution and use in source and binary forms, with or without
132.9 +modification, are permitted provided that the following conditions are met:
132.10 +
132.11 + 1. Redistributions of source code must retain the above copyright notice,
132.12 + this list of conditions and the following disclaimer.
132.13 +
132.14 + 2. Redistributions in binary form must reproduce the above copyright
132.15 + notice, this list of conditions and the following disclaimer in
132.16 + the documentation and/or other materials provided with the distribution.
132.17 +
132.18 + 3. The names of the authors may not be used to endorse or promote products
132.19 + derived from this software without specific prior written permission.
132.20 +
132.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
132.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
132.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
132.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
132.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
132.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
132.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
132.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
132.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
132.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
132.31 + */
132.32 +/*
132.33 + * This program is based on zlib-1.1.3, so all credit should go authors
132.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
132.35 + * and contributors of zlib.
132.36 + */
132.37 +
132.38 +package org.apidesign.bck2brwsr.emul.zip;
132.39 +
132.40 +import org.apidesign.bck2brwsr.emul.lang.System;
132.41 +
132.42 +final class InfCodes{
132.43 +
132.44 + static final private int[] inflate_mask = {
132.45 + 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
132.46 + 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
132.47 + 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
132.48 + 0x00007fff, 0x0000ffff
132.49 + };
132.50 +
132.51 + static final private int Z_OK=0;
132.52 + static final private int Z_STREAM_END=1;
132.53 + static final private int Z_NEED_DICT=2;
132.54 + static final private int Z_ERRNO=-1;
132.55 + static final private int Z_STREAM_ERROR=-2;
132.56 + static final private int Z_DATA_ERROR=-3;
132.57 + static final private int Z_MEM_ERROR=-4;
132.58 + static final private int Z_BUF_ERROR=-5;
132.59 + static final private int Z_VERSION_ERROR=-6;
132.60 +
132.61 + // waiting for "i:"=input,
132.62 + // "o:"=output,
132.63 + // "x:"=nothing
132.64 + static final private int START=0; // x: set up for LEN
132.65 + static final private int LEN=1; // i: get length/literal/eob next
132.66 + static final private int LENEXT=2; // i: getting length extra (have base)
132.67 + static final private int DIST=3; // i: get distance next
132.68 + static final private int DISTEXT=4;// i: getting distance extra
132.69 + static final private int COPY=5; // o: copying bytes in window, waiting for space
132.70 + static final private int LIT=6; // o: got literal, waiting for output space
132.71 + static final private int WASH=7; // o: got eob, possibly still output waiting
132.72 + static final private int END=8; // x: got eob and all data flushed
132.73 + static final private int BADCODE=9;// x: got error
132.74 +
132.75 + int mode; // current inflate_codes mode
132.76 +
132.77 + // mode dependent information
132.78 + int len;
132.79 +
132.80 + int[] tree; // pointer into tree
132.81 + int tree_index=0;
132.82 + int need; // bits needed
132.83 +
132.84 + int lit;
132.85 +
132.86 + // if EXT or COPY, where and how much
132.87 + int get; // bits to get for extra
132.88 + int dist; // distance back to copy from
132.89 +
132.90 + byte lbits; // ltree bits decoded per branch
132.91 + byte dbits; // dtree bits decoder per branch
132.92 + int[] ltree; // literal/length/eob tree
132.93 + int ltree_index; // literal/length/eob tree
132.94 + int[] dtree; // distance tree
132.95 + int dtree_index; // distance tree
132.96 +
132.97 + private final ZStream z;
132.98 + private final InfBlocks s;
132.99 + InfCodes(ZStream z, InfBlocks s){
132.100 + this.z=z;
132.101 + this.s=s;
132.102 + }
132.103 +
132.104 + void init(int bl, int bd,
132.105 + int[] tl, int tl_index,
132.106 + int[] td, int td_index){
132.107 + mode=START;
132.108 + lbits=(byte)bl;
132.109 + dbits=(byte)bd;
132.110 + ltree=tl;
132.111 + ltree_index=tl_index;
132.112 + dtree = td;
132.113 + dtree_index=td_index;
132.114 + tree=null;
132.115 + }
132.116 +
132.117 + int proc(int r){
132.118 + int j; // temporary storage
132.119 + int[] t; // temporary pointer
132.120 + int tindex; // temporary pointer
132.121 + int e; // extra bits or operation
132.122 + int b=0; // bit buffer
132.123 + int k=0; // bits in bit buffer
132.124 + int p=0; // input data pointer
132.125 + int n; // bytes available there
132.126 + int q; // output window write pointer
132.127 + int m; // bytes to end of window or read pointer
132.128 + int f; // pointer to copy strings from
132.129 +
132.130 + // copy input/output information to locals (UPDATE macro restores)
132.131 + p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
132.132 + q=s.write;m=q<s.read?s.read-q-1:s.end-q;
132.133 +
132.134 + // process input and output based on current state
132.135 + while (true){
132.136 + switch (mode){
132.137 + // waiting for "i:"=input, "o:"=output, "x:"=nothing
132.138 + case START: // x: set up for LEN
132.139 + if (m >= 258 && n >= 10){
132.140 +
132.141 + s.bitb=b;s.bitk=k;
132.142 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
132.143 + s.write=q;
132.144 + r = inflate_fast(lbits, dbits,
132.145 + ltree, ltree_index,
132.146 + dtree, dtree_index,
132.147 + s, z);
132.148 +
132.149 + p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
132.150 + q=s.write;m=q<s.read?s.read-q-1:s.end-q;
132.151 +
132.152 + if (r != Z_OK){
132.153 + mode = r == Z_STREAM_END ? WASH : BADCODE;
132.154 + break;
132.155 + }
132.156 + }
132.157 + need = lbits;
132.158 + tree = ltree;
132.159 + tree_index=ltree_index;
132.160 +
132.161 + mode = LEN;
132.162 + case LEN: // i: get length/literal/eob next
132.163 + j = need;
132.164 +
132.165 + while(k<(j)){
132.166 + if(n!=0)r=Z_OK;
132.167 + else{
132.168 +
132.169 + s.bitb=b;s.bitk=k;
132.170 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
132.171 + s.write=q;
132.172 + return s.inflate_flush(r);
132.173 + }
132.174 + n--;
132.175 + b|=(z.next_in[p++]&0xff)<<k;
132.176 + k+=8;
132.177 + }
132.178 +
132.179 + tindex=(tree_index+(b&inflate_mask[j]))*3;
132.180 +
132.181 + b>>>=(tree[tindex+1]);
132.182 + k-=(tree[tindex+1]);
132.183 +
132.184 + e=tree[tindex];
132.185 +
132.186 + if(e == 0){ // literal
132.187 + lit = tree[tindex+2];
132.188 + mode = LIT;
132.189 + break;
132.190 + }
132.191 + if((e & 16)!=0 ){ // length
132.192 + get = e & 15;
132.193 + len = tree[tindex+2];
132.194 + mode = LENEXT;
132.195 + break;
132.196 + }
132.197 + if ((e & 64) == 0){ // next table
132.198 + need = e;
132.199 + tree_index = tindex/3+tree[tindex+2];
132.200 + break;
132.201 + }
132.202 + if ((e & 32)!=0){ // end of block
132.203 + mode = WASH;
132.204 + break;
132.205 + }
132.206 + mode = BADCODE; // invalid code
132.207 + z.msg = "invalid literal/length code";
132.208 + r = Z_DATA_ERROR;
132.209 +
132.210 + s.bitb=b;s.bitk=k;
132.211 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
132.212 + s.write=q;
132.213 + return s.inflate_flush(r);
132.214 +
132.215 + case LENEXT: // i: getting length extra (have base)
132.216 + j = get;
132.217 +
132.218 + while(k<(j)){
132.219 + if(n!=0)r=Z_OK;
132.220 + else{
132.221 +
132.222 + s.bitb=b;s.bitk=k;
132.223 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
132.224 + s.write=q;
132.225 + return s.inflate_flush(r);
132.226 + }
132.227 + n--; b|=(z.next_in[p++]&0xff)<<k;
132.228 + k+=8;
132.229 + }
132.230 +
132.231 + len += (b & inflate_mask[j]);
132.232 +
132.233 + b>>=j;
132.234 + k-=j;
132.235 +
132.236 + need = dbits;
132.237 + tree = dtree;
132.238 + tree_index=dtree_index;
132.239 + mode = DIST;
132.240 + case DIST: // i: get distance next
132.241 + j = need;
132.242 +
132.243 + while(k<(j)){
132.244 + if(n!=0)r=Z_OK;
132.245 + else{
132.246 +
132.247 + s.bitb=b;s.bitk=k;
132.248 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
132.249 + s.write=q;
132.250 + return s.inflate_flush(r);
132.251 + }
132.252 + n--; b|=(z.next_in[p++]&0xff)<<k;
132.253 + k+=8;
132.254 + }
132.255 +
132.256 + tindex=(tree_index+(b & inflate_mask[j]))*3;
132.257 +
132.258 + b>>=tree[tindex+1];
132.259 + k-=tree[tindex+1];
132.260 +
132.261 + e = (tree[tindex]);
132.262 + if((e & 16)!=0){ // distance
132.263 + get = e & 15;
132.264 + dist = tree[tindex+2];
132.265 + mode = DISTEXT;
132.266 + break;
132.267 + }
132.268 + if ((e & 64) == 0){ // next table
132.269 + need = e;
132.270 + tree_index = tindex/3 + tree[tindex+2];
132.271 + break;
132.272 + }
132.273 + mode = BADCODE; // invalid code
132.274 + z.msg = "invalid distance code";
132.275 + r = Z_DATA_ERROR;
132.276 +
132.277 + s.bitb=b;s.bitk=k;
132.278 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
132.279 + s.write=q;
132.280 + return s.inflate_flush(r);
132.281 +
132.282 + case DISTEXT: // i: getting distance extra
132.283 + j = get;
132.284 +
132.285 + while(k<(j)){
132.286 + if(n!=0)r=Z_OK;
132.287 + else{
132.288 +
132.289 + s.bitb=b;s.bitk=k;
132.290 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
132.291 + s.write=q;
132.292 + return s.inflate_flush(r);
132.293 + }
132.294 + n--; b|=(z.next_in[p++]&0xff)<<k;
132.295 + k+=8;
132.296 + }
132.297 +
132.298 + dist += (b & inflate_mask[j]);
132.299 +
132.300 + b>>=j;
132.301 + k-=j;
132.302 +
132.303 + mode = COPY;
132.304 + case COPY: // o: copying bytes in window, waiting for space
132.305 + f = q - dist;
132.306 + while(f < 0){ // modulo window size-"while" instead
132.307 + f += s.end; // of "if" handles invalid distances
132.308 + }
132.309 + while (len!=0){
132.310 +
132.311 + if(m==0){
132.312 + if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
132.313 + if(m==0){
132.314 + s.write=q; r=s.inflate_flush(r);
132.315 + q=s.write;m=q<s.read?s.read-q-1:s.end-q;
132.316 +
132.317 + if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
132.318 +
132.319 + if(m==0){
132.320 + s.bitb=b;s.bitk=k;
132.321 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
132.322 + s.write=q;
132.323 + return s.inflate_flush(r);
132.324 + }
132.325 + }
132.326 + }
132.327 +
132.328 + s.window[q++]=s.window[f++]; m--;
132.329 +
132.330 + if (f == s.end)
132.331 + f = 0;
132.332 + len--;
132.333 + }
132.334 + mode = START;
132.335 + break;
132.336 + case LIT: // o: got literal, waiting for output space
132.337 + if(m==0){
132.338 + if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
132.339 + if(m==0){
132.340 + s.write=q; r=s.inflate_flush(r);
132.341 + q=s.write;m=q<s.read?s.read-q-1:s.end-q;
132.342 +
132.343 + if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
132.344 + if(m==0){
132.345 + s.bitb=b;s.bitk=k;
132.346 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
132.347 + s.write=q;
132.348 + return s.inflate_flush(r);
132.349 + }
132.350 + }
132.351 + }
132.352 + r=Z_OK;
132.353 +
132.354 + s.window[q++]=(byte)lit; m--;
132.355 +
132.356 + mode = START;
132.357 + break;
132.358 + case WASH: // o: got eob, possibly more output
132.359 + if (k > 7){ // return unused byte, if any
132.360 + k -= 8;
132.361 + n++;
132.362 + p--; // can always return one
132.363 + }
132.364 +
132.365 + s.write=q; r=s.inflate_flush(r);
132.366 + q=s.write;m=q<s.read?s.read-q-1:s.end-q;
132.367 +
132.368 + if (s.read != s.write){
132.369 + s.bitb=b;s.bitk=k;
132.370 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
132.371 + s.write=q;
132.372 + return s.inflate_flush(r);
132.373 + }
132.374 + mode = END;
132.375 + case END:
132.376 + r = Z_STREAM_END;
132.377 + s.bitb=b;s.bitk=k;
132.378 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
132.379 + s.write=q;
132.380 + return s.inflate_flush(r);
132.381 +
132.382 + case BADCODE: // x: got error
132.383 +
132.384 + r = Z_DATA_ERROR;
132.385 +
132.386 + s.bitb=b;s.bitk=k;
132.387 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
132.388 + s.write=q;
132.389 + return s.inflate_flush(r);
132.390 +
132.391 + default:
132.392 + r = Z_STREAM_ERROR;
132.393 +
132.394 + s.bitb=b;s.bitk=k;
132.395 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
132.396 + s.write=q;
132.397 + return s.inflate_flush(r);
132.398 + }
132.399 + }
132.400 + }
132.401 +
132.402 + void free(ZStream z){
132.403 + // ZFREE(z, c);
132.404 + }
132.405 +
132.406 + // Called with number of bytes left to write in window at least 258
132.407 + // (the maximum string length) and number of input bytes available
132.408 + // at least ten. The ten bytes are six bytes for the longest length/
132.409 + // distance pair plus four bytes for overloading the bit buffer.
132.410 +
132.411 + int inflate_fast(int bl, int bd,
132.412 + int[] tl, int tl_index,
132.413 + int[] td, int td_index,
132.414 + InfBlocks s, ZStream z){
132.415 + int t; // temporary pointer
132.416 + int[] tp; // temporary pointer
132.417 + int tp_index; // temporary pointer
132.418 + int e; // extra bits or operation
132.419 + int b; // bit buffer
132.420 + int k; // bits in bit buffer
132.421 + int p; // input data pointer
132.422 + int n; // bytes available there
132.423 + int q; // output window write pointer
132.424 + int m; // bytes to end of window or read pointer
132.425 + int ml; // mask for literal/length tree
132.426 + int md; // mask for distance tree
132.427 + int c; // bytes to copy
132.428 + int d; // distance back to copy from
132.429 + int r; // copy source pointer
132.430 +
132.431 + int tp_index_t_3; // (tp_index+t)*3
132.432 +
132.433 + // load input, output, bit values
132.434 + p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
132.435 + q=s.write;m=q<s.read?s.read-q-1:s.end-q;
132.436 +
132.437 + // initialize masks
132.438 + ml = inflate_mask[bl];
132.439 + md = inflate_mask[bd];
132.440 +
132.441 + // do until not enough input or output space for fast loop
132.442 + do { // assume called with m >= 258 && n >= 10
132.443 + // get literal/length code
132.444 + while(k<(20)){ // max bits for literal/length code
132.445 + n--;
132.446 + b|=(z.next_in[p++]&0xff)<<k;k+=8;
132.447 + }
132.448 +
132.449 + t= b&ml;
132.450 + tp=tl;
132.451 + tp_index=tl_index;
132.452 + tp_index_t_3=(tp_index+t)*3;
132.453 + if ((e = tp[tp_index_t_3]) == 0){
132.454 + b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
132.455 +
132.456 + s.window[q++] = (byte)tp[tp_index_t_3+2];
132.457 + m--;
132.458 + continue;
132.459 + }
132.460 + do {
132.461 +
132.462 + b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
132.463 +
132.464 + if((e&16)!=0){
132.465 + e &= 15;
132.466 + c = tp[tp_index_t_3+2] + ((int)b & inflate_mask[e]);
132.467 +
132.468 + b>>=e; k-=e;
132.469 +
132.470 + // decode distance base of block to copy
132.471 + while(k<(15)){ // max bits for distance code
132.472 + n--;
132.473 + b|=(z.next_in[p++]&0xff)<<k;k+=8;
132.474 + }
132.475 +
132.476 + t= b&md;
132.477 + tp=td;
132.478 + tp_index=td_index;
132.479 + tp_index_t_3=(tp_index+t)*3;
132.480 + e = tp[tp_index_t_3];
132.481 +
132.482 + do {
132.483 +
132.484 + b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
132.485 +
132.486 + if((e&16)!=0){
132.487 + // get extra bits to add to distance base
132.488 + e &= 15;
132.489 + while(k<(e)){ // get extra bits (up to 13)
132.490 + n--;
132.491 + b|=(z.next_in[p++]&0xff)<<k;k+=8;
132.492 + }
132.493 +
132.494 + d = tp[tp_index_t_3+2] + (b&inflate_mask[e]);
132.495 +
132.496 + b>>=(e); k-=(e);
132.497 +
132.498 + // do the copy
132.499 + m -= c;
132.500 + if (q >= d){ // offset before dest
132.501 + // just copy
132.502 + r=q-d;
132.503 + if(q-r>0 && 2>(q-r)){
132.504 + s.window[q++]=s.window[r++]; // minimum count is three,
132.505 + s.window[q++]=s.window[r++]; // so unroll loop a little
132.506 + c-=2;
132.507 + }
132.508 + else{
132.509 + System.arraycopy(s.window, r, s.window, q, 2);
132.510 + q+=2; r+=2; c-=2;
132.511 + }
132.512 + }
132.513 + else{ // else offset after destination
132.514 + r=q-d;
132.515 + do{
132.516 + r+=s.end; // force pointer in window
132.517 + }while(r<0); // covers invalid distances
132.518 + e=s.end-r;
132.519 + if(c>e){ // if source crosses,
132.520 + c-=e; // wrapped copy
132.521 + if(q-r>0 && e>(q-r)){
132.522 + do{s.window[q++] = s.window[r++];}
132.523 + while(--e!=0);
132.524 + }
132.525 + else{
132.526 + System.arraycopy(s.window, r, s.window, q, e);
132.527 + q+=e; r+=e; e=0;
132.528 + }
132.529 + r = 0; // copy rest from start of window
132.530 + }
132.531 +
132.532 + }
132.533 +
132.534 + // copy all or what's left
132.535 + if(q-r>0 && c>(q-r)){
132.536 + do{s.window[q++] = s.window[r++];}
132.537 + while(--c!=0);
132.538 + }
132.539 + else{
132.540 + System.arraycopy(s.window, r, s.window, q, c);
132.541 + q+=c; r+=c; c=0;
132.542 + }
132.543 + break;
132.544 + }
132.545 + else if((e&64)==0){
132.546 + t+=tp[tp_index_t_3+2];
132.547 + t+=(b&inflate_mask[e]);
132.548 + tp_index_t_3=(tp_index+t)*3;
132.549 + e=tp[tp_index_t_3];
132.550 + }
132.551 + else{
132.552 + z.msg = "invalid distance code";
132.553 +
132.554 + c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
132.555 +
132.556 + s.bitb=b;s.bitk=k;
132.557 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
132.558 + s.write=q;
132.559 +
132.560 + return Z_DATA_ERROR;
132.561 + }
132.562 + }
132.563 + while(true);
132.564 + break;
132.565 + }
132.566 +
132.567 + if((e&64)==0){
132.568 + t+=tp[tp_index_t_3+2];
132.569 + t+=(b&inflate_mask[e]);
132.570 + tp_index_t_3=(tp_index+t)*3;
132.571 + if((e=tp[tp_index_t_3])==0){
132.572 +
132.573 + b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
132.574 +
132.575 + s.window[q++]=(byte)tp[tp_index_t_3+2];
132.576 + m--;
132.577 + break;
132.578 + }
132.579 + }
132.580 + else if((e&32)!=0){
132.581 +
132.582 + c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
132.583 +
132.584 + s.bitb=b;s.bitk=k;
132.585 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
132.586 + s.write=q;
132.587 +
132.588 + return Z_STREAM_END;
132.589 + }
132.590 + else{
132.591 + z.msg="invalid literal/length code";
132.592 +
132.593 + c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
132.594 +
132.595 + s.bitb=b;s.bitk=k;
132.596 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
132.597 + s.write=q;
132.598 +
132.599 + return Z_DATA_ERROR;
132.600 + }
132.601 + }
132.602 + while(true);
132.603 + }
132.604 + while(m>=258 && n>= 10);
132.605 +
132.606 + // not enough input or output--restore pointers and return
132.607 + c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
132.608 +
132.609 + s.bitb=b;s.bitk=k;
132.610 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
132.611 + s.write=q;
132.612 +
132.613 + return Z_OK;
132.614 + }
132.615 +}
133.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
133.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/InfTree.java Sun Feb 17 17:58:34 2013 +0100
133.3 @@ -0,0 +1,520 @@
133.4 +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
133.5 +/*
133.6 +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
133.7 +
133.8 +Redistribution and use in source and binary forms, with or without
133.9 +modification, are permitted provided that the following conditions are met:
133.10 +
133.11 + 1. Redistributions of source code must retain the above copyright notice,
133.12 + this list of conditions and the following disclaimer.
133.13 +
133.14 + 2. Redistributions in binary form must reproduce the above copyright
133.15 + notice, this list of conditions and the following disclaimer in
133.16 + the documentation and/or other materials provided with the distribution.
133.17 +
133.18 + 3. The names of the authors may not be used to endorse or promote products
133.19 + derived from this software without specific prior written permission.
133.20 +
133.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
133.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
133.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
133.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
133.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
133.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
133.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
133.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
133.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
133.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
133.31 + */
133.32 +/*
133.33 + * This program is based on zlib-1.1.3, so all credit should go authors
133.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
133.35 + * and contributors of zlib.
133.36 + */
133.37 +
133.38 +package org.apidesign.bck2brwsr.emul.zip;
133.39 +
133.40 +import org.apidesign.bck2brwsr.emul.lang.System;
133.41 +
133.42 +final class InfTree{
133.43 +
133.44 + static final private int MANY=1440;
133.45 +
133.46 + static final private int Z_OK=0;
133.47 + static final private int Z_STREAM_END=1;
133.48 + static final private int Z_NEED_DICT=2;
133.49 + static final private int Z_ERRNO=-1;
133.50 + static final private int Z_STREAM_ERROR=-2;
133.51 + static final private int Z_DATA_ERROR=-3;
133.52 + static final private int Z_MEM_ERROR=-4;
133.53 + static final private int Z_BUF_ERROR=-5;
133.54 + static final private int Z_VERSION_ERROR=-6;
133.55 +
133.56 + static final int fixed_bl = 9;
133.57 + static final int fixed_bd = 5;
133.58 +
133.59 + static final int[] fixed_tl = {
133.60 + 96,7,256, 0,8,80, 0,8,16, 84,8,115,
133.61 + 82,7,31, 0,8,112, 0,8,48, 0,9,192,
133.62 + 80,7,10, 0,8,96, 0,8,32, 0,9,160,
133.63 + 0,8,0, 0,8,128, 0,8,64, 0,9,224,
133.64 + 80,7,6, 0,8,88, 0,8,24, 0,9,144,
133.65 + 83,7,59, 0,8,120, 0,8,56, 0,9,208,
133.66 + 81,7,17, 0,8,104, 0,8,40, 0,9,176,
133.67 + 0,8,8, 0,8,136, 0,8,72, 0,9,240,
133.68 + 80,7,4, 0,8,84, 0,8,20, 85,8,227,
133.69 + 83,7,43, 0,8,116, 0,8,52, 0,9,200,
133.70 + 81,7,13, 0,8,100, 0,8,36, 0,9,168,
133.71 + 0,8,4, 0,8,132, 0,8,68, 0,9,232,
133.72 + 80,7,8, 0,8,92, 0,8,28, 0,9,152,
133.73 + 84,7,83, 0,8,124, 0,8,60, 0,9,216,
133.74 + 82,7,23, 0,8,108, 0,8,44, 0,9,184,
133.75 + 0,8,12, 0,8,140, 0,8,76, 0,9,248,
133.76 + 80,7,3, 0,8,82, 0,8,18, 85,8,163,
133.77 + 83,7,35, 0,8,114, 0,8,50, 0,9,196,
133.78 + 81,7,11, 0,8,98, 0,8,34, 0,9,164,
133.79 + 0,8,2, 0,8,130, 0,8,66, 0,9,228,
133.80 + 80,7,7, 0,8,90, 0,8,26, 0,9,148,
133.81 + 84,7,67, 0,8,122, 0,8,58, 0,9,212,
133.82 + 82,7,19, 0,8,106, 0,8,42, 0,9,180,
133.83 + 0,8,10, 0,8,138, 0,8,74, 0,9,244,
133.84 + 80,7,5, 0,8,86, 0,8,22, 192,8,0,
133.85 + 83,7,51, 0,8,118, 0,8,54, 0,9,204,
133.86 + 81,7,15, 0,8,102, 0,8,38, 0,9,172,
133.87 + 0,8,6, 0,8,134, 0,8,70, 0,9,236,
133.88 + 80,7,9, 0,8,94, 0,8,30, 0,9,156,
133.89 + 84,7,99, 0,8,126, 0,8,62, 0,9,220,
133.90 + 82,7,27, 0,8,110, 0,8,46, 0,9,188,
133.91 + 0,8,14, 0,8,142, 0,8,78, 0,9,252,
133.92 + 96,7,256, 0,8,81, 0,8,17, 85,8,131,
133.93 + 82,7,31, 0,8,113, 0,8,49, 0,9,194,
133.94 + 80,7,10, 0,8,97, 0,8,33, 0,9,162,
133.95 + 0,8,1, 0,8,129, 0,8,65, 0,9,226,
133.96 + 80,7,6, 0,8,89, 0,8,25, 0,9,146,
133.97 + 83,7,59, 0,8,121, 0,8,57, 0,9,210,
133.98 + 81,7,17, 0,8,105, 0,8,41, 0,9,178,
133.99 + 0,8,9, 0,8,137, 0,8,73, 0,9,242,
133.100 + 80,7,4, 0,8,85, 0,8,21, 80,8,258,
133.101 + 83,7,43, 0,8,117, 0,8,53, 0,9,202,
133.102 + 81,7,13, 0,8,101, 0,8,37, 0,9,170,
133.103 + 0,8,5, 0,8,133, 0,8,69, 0,9,234,
133.104 + 80,7,8, 0,8,93, 0,8,29, 0,9,154,
133.105 + 84,7,83, 0,8,125, 0,8,61, 0,9,218,
133.106 + 82,7,23, 0,8,109, 0,8,45, 0,9,186,
133.107 + 0,8,13, 0,8,141, 0,8,77, 0,9,250,
133.108 + 80,7,3, 0,8,83, 0,8,19, 85,8,195,
133.109 + 83,7,35, 0,8,115, 0,8,51, 0,9,198,
133.110 + 81,7,11, 0,8,99, 0,8,35, 0,9,166,
133.111 + 0,8,3, 0,8,131, 0,8,67, 0,9,230,
133.112 + 80,7,7, 0,8,91, 0,8,27, 0,9,150,
133.113 + 84,7,67, 0,8,123, 0,8,59, 0,9,214,
133.114 + 82,7,19, 0,8,107, 0,8,43, 0,9,182,
133.115 + 0,8,11, 0,8,139, 0,8,75, 0,9,246,
133.116 + 80,7,5, 0,8,87, 0,8,23, 192,8,0,
133.117 + 83,7,51, 0,8,119, 0,8,55, 0,9,206,
133.118 + 81,7,15, 0,8,103, 0,8,39, 0,9,174,
133.119 + 0,8,7, 0,8,135, 0,8,71, 0,9,238,
133.120 + 80,7,9, 0,8,95, 0,8,31, 0,9,158,
133.121 + 84,7,99, 0,8,127, 0,8,63, 0,9,222,
133.122 + 82,7,27, 0,8,111, 0,8,47, 0,9,190,
133.123 + 0,8,15, 0,8,143, 0,8,79, 0,9,254,
133.124 + 96,7,256, 0,8,80, 0,8,16, 84,8,115,
133.125 + 82,7,31, 0,8,112, 0,8,48, 0,9,193,
133.126 +
133.127 + 80,7,10, 0,8,96, 0,8,32, 0,9,161,
133.128 + 0,8,0, 0,8,128, 0,8,64, 0,9,225,
133.129 + 80,7,6, 0,8,88, 0,8,24, 0,9,145,
133.130 + 83,7,59, 0,8,120, 0,8,56, 0,9,209,
133.131 + 81,7,17, 0,8,104, 0,8,40, 0,9,177,
133.132 + 0,8,8, 0,8,136, 0,8,72, 0,9,241,
133.133 + 80,7,4, 0,8,84, 0,8,20, 85,8,227,
133.134 + 83,7,43, 0,8,116, 0,8,52, 0,9,201,
133.135 + 81,7,13, 0,8,100, 0,8,36, 0,9,169,
133.136 + 0,8,4, 0,8,132, 0,8,68, 0,9,233,
133.137 + 80,7,8, 0,8,92, 0,8,28, 0,9,153,
133.138 + 84,7,83, 0,8,124, 0,8,60, 0,9,217,
133.139 + 82,7,23, 0,8,108, 0,8,44, 0,9,185,
133.140 + 0,8,12, 0,8,140, 0,8,76, 0,9,249,
133.141 + 80,7,3, 0,8,82, 0,8,18, 85,8,163,
133.142 + 83,7,35, 0,8,114, 0,8,50, 0,9,197,
133.143 + 81,7,11, 0,8,98, 0,8,34, 0,9,165,
133.144 + 0,8,2, 0,8,130, 0,8,66, 0,9,229,
133.145 + 80,7,7, 0,8,90, 0,8,26, 0,9,149,
133.146 + 84,7,67, 0,8,122, 0,8,58, 0,9,213,
133.147 + 82,7,19, 0,8,106, 0,8,42, 0,9,181,
133.148 + 0,8,10, 0,8,138, 0,8,74, 0,9,245,
133.149 + 80,7,5, 0,8,86, 0,8,22, 192,8,0,
133.150 + 83,7,51, 0,8,118, 0,8,54, 0,9,205,
133.151 + 81,7,15, 0,8,102, 0,8,38, 0,9,173,
133.152 + 0,8,6, 0,8,134, 0,8,70, 0,9,237,
133.153 + 80,7,9, 0,8,94, 0,8,30, 0,9,157,
133.154 + 84,7,99, 0,8,126, 0,8,62, 0,9,221,
133.155 + 82,7,27, 0,8,110, 0,8,46, 0,9,189,
133.156 + 0,8,14, 0,8,142, 0,8,78, 0,9,253,
133.157 + 96,7,256, 0,8,81, 0,8,17, 85,8,131,
133.158 + 82,7,31, 0,8,113, 0,8,49, 0,9,195,
133.159 + 80,7,10, 0,8,97, 0,8,33, 0,9,163,
133.160 + 0,8,1, 0,8,129, 0,8,65, 0,9,227,
133.161 + 80,7,6, 0,8,89, 0,8,25, 0,9,147,
133.162 + 83,7,59, 0,8,121, 0,8,57, 0,9,211,
133.163 + 81,7,17, 0,8,105, 0,8,41, 0,9,179,
133.164 + 0,8,9, 0,8,137, 0,8,73, 0,9,243,
133.165 + 80,7,4, 0,8,85, 0,8,21, 80,8,258,
133.166 + 83,7,43, 0,8,117, 0,8,53, 0,9,203,
133.167 + 81,7,13, 0,8,101, 0,8,37, 0,9,171,
133.168 + 0,8,5, 0,8,133, 0,8,69, 0,9,235,
133.169 + 80,7,8, 0,8,93, 0,8,29, 0,9,155,
133.170 + 84,7,83, 0,8,125, 0,8,61, 0,9,219,
133.171 + 82,7,23, 0,8,109, 0,8,45, 0,9,187,
133.172 + 0,8,13, 0,8,141, 0,8,77, 0,9,251,
133.173 + 80,7,3, 0,8,83, 0,8,19, 85,8,195,
133.174 + 83,7,35, 0,8,115, 0,8,51, 0,9,199,
133.175 + 81,7,11, 0,8,99, 0,8,35, 0,9,167,
133.176 + 0,8,3, 0,8,131, 0,8,67, 0,9,231,
133.177 + 80,7,7, 0,8,91, 0,8,27, 0,9,151,
133.178 + 84,7,67, 0,8,123, 0,8,59, 0,9,215,
133.179 + 82,7,19, 0,8,107, 0,8,43, 0,9,183,
133.180 + 0,8,11, 0,8,139, 0,8,75, 0,9,247,
133.181 + 80,7,5, 0,8,87, 0,8,23, 192,8,0,
133.182 + 83,7,51, 0,8,119, 0,8,55, 0,9,207,
133.183 + 81,7,15, 0,8,103, 0,8,39, 0,9,175,
133.184 + 0,8,7, 0,8,135, 0,8,71, 0,9,239,
133.185 + 80,7,9, 0,8,95, 0,8,31, 0,9,159,
133.186 + 84,7,99, 0,8,127, 0,8,63, 0,9,223,
133.187 + 82,7,27, 0,8,111, 0,8,47, 0,9,191,
133.188 + 0,8,15, 0,8,143, 0,8,79, 0,9,255
133.189 + };
133.190 + static final int[] fixed_td = {
133.191 + 80,5,1, 87,5,257, 83,5,17, 91,5,4097,
133.192 + 81,5,5, 89,5,1025, 85,5,65, 93,5,16385,
133.193 + 80,5,3, 88,5,513, 84,5,33, 92,5,8193,
133.194 + 82,5,9, 90,5,2049, 86,5,129, 192,5,24577,
133.195 + 80,5,2, 87,5,385, 83,5,25, 91,5,6145,
133.196 + 81,5,7, 89,5,1537, 85,5,97, 93,5,24577,
133.197 + 80,5,4, 88,5,769, 84,5,49, 92,5,12289,
133.198 + 82,5,13, 90,5,3073, 86,5,193, 192,5,24577
133.199 + };
133.200 +
133.201 + // Tables for deflate from PKZIP's appnote.txt.
133.202 + static final int[] cplens = { // Copy lengths for literal codes 257..285
133.203 + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
133.204 + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
133.205 + };
133.206 +
133.207 + // see note #13 above about 258
133.208 + static final int[] cplext = { // Extra bits for literal codes 257..285
133.209 + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
133.210 + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 // 112==invalid
133.211 + };
133.212 +
133.213 + static final int[] cpdist = { // Copy offsets for distance codes 0..29
133.214 + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
133.215 + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
133.216 + 8193, 12289, 16385, 24577
133.217 + };
133.218 +
133.219 + static final int[] cpdext = { // Extra bits for distance codes
133.220 + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
133.221 + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
133.222 + 12, 12, 13, 13};
133.223 +
133.224 + // If BMAX needs to be larger than 16, then h and x[] should be uLong.
133.225 + static final int BMAX=15; // maximum bit length of any code
133.226 +
133.227 + int[] hn = null; // hufts used in space
133.228 + int[] v = null; // work area for huft_build
133.229 + int[] c = null; // bit length count table
133.230 + int[] r = null; // table entry for structure assignment
133.231 + int[] u = null; // table stack
133.232 + int[] x = null; // bit offsets, then code stack
133.233 +
133.234 + private int huft_build(int[] b, // code lengths in bits (all assumed <= BMAX)
133.235 + int bindex,
133.236 + int n, // number of codes (assumed <= 288)
133.237 + int s, // number of simple-valued codes (0..s-1)
133.238 + int[] d, // list of base values for non-simple codes
133.239 + int[] e, // list of extra bits for non-simple codes
133.240 + int[] t, // result: starting table
133.241 + int[] m, // maximum lookup bits, returns actual
133.242 + int[] hp,// space for trees
133.243 + int[] hn,// hufts used in space
133.244 + int[] v // working area: values in order of bit length
133.245 + ){
133.246 + // Given a list of code lengths and a maximum table size, make a set of
133.247 + // tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
133.248 + // if the given code set is incomplete (the tables are still built in this
133.249 + // case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
133.250 + // lengths), or Z_MEM_ERROR if not enough memory.
133.251 +
133.252 + int a; // counter for codes of length k
133.253 + int f; // i repeats in table every f entries
133.254 + int g; // maximum code length
133.255 + int h; // table level
133.256 + int i; // counter, current code
133.257 + int j; // counter
133.258 + int k; // number of bits in current code
133.259 + int l; // bits per table (returned in m)
133.260 + int mask; // (1 << w) - 1, to avoid cc -O bug on HP
133.261 + int p; // pointer into c[], b[], or v[]
133.262 + int q; // points to current table
133.263 + int w; // bits before this table == (l * h)
133.264 + int xp; // pointer into x
133.265 + int y; // number of dummy codes added
133.266 + int z; // number of entries in current table
133.267 +
133.268 + // Generate counts for each bit length
133.269 +
133.270 + p = 0; i = n;
133.271 + do {
133.272 + c[b[bindex+p]]++; p++; i--; // assume all entries <= BMAX
133.273 + }while(i!=0);
133.274 +
133.275 + if(c[0] == n){ // null input--all zero length codes
133.276 + t[0] = -1;
133.277 + m[0] = 0;
133.278 + return Z_OK;
133.279 + }
133.280 +
133.281 + // Find minimum and maximum length, bound *m by those
133.282 + l = m[0];
133.283 + for (j = 1; j <= BMAX; j++)
133.284 + if(c[j]!=0) break;
133.285 + k = j; // minimum code length
133.286 + if(l < j){
133.287 + l = j;
133.288 + }
133.289 + for (i = BMAX; i!=0; i--){
133.290 + if(c[i]!=0) break;
133.291 + }
133.292 + g = i; // maximum code length
133.293 + if(l > i){
133.294 + l = i;
133.295 + }
133.296 + m[0] = l;
133.297 +
133.298 + // Adjust last length count to fill out codes, if needed
133.299 + for (y = 1 << j; j < i; j++, y <<= 1){
133.300 + if ((y -= c[j]) < 0){
133.301 + return Z_DATA_ERROR;
133.302 + }
133.303 + }
133.304 + if ((y -= c[i]) < 0){
133.305 + return Z_DATA_ERROR;
133.306 + }
133.307 + c[i] += y;
133.308 +
133.309 + // Generate starting offsets into the value table for each length
133.310 + x[1] = j = 0;
133.311 + p = 1; xp = 2;
133.312 + while (--i!=0) { // note that i == g from above
133.313 + x[xp] = (j += c[p]);
133.314 + xp++;
133.315 + p++;
133.316 + }
133.317 +
133.318 + // Make a table of values in order of bit lengths
133.319 + i = 0; p = 0;
133.320 + do {
133.321 + if ((j = b[bindex+p]) != 0){
133.322 + v[x[j]++] = i;
133.323 + }
133.324 + p++;
133.325 + }
133.326 + while (++i < n);
133.327 + n = x[g]; // set n to length of v
133.328 +
133.329 + // Generate the Huffman codes and for each, make the table entries
133.330 + x[0] = i = 0; // first Huffman code is zero
133.331 + p = 0; // grab values in bit order
133.332 + h = -1; // no tables yet--level -1
133.333 + w = -l; // bits decoded == (l * h)
133.334 + u[0] = 0; // just to keep compilers happy
133.335 + q = 0; // ditto
133.336 + z = 0; // ditto
133.337 +
133.338 + // go through the bit lengths (k already is bits in shortest code)
133.339 + for (; k <= g; k++){
133.340 + a = c[k];
133.341 + while (a--!=0){
133.342 + // here i is the Huffman code of length k bits for value *p
133.343 + // make tables up to required level
133.344 + while (k > w + l){
133.345 + h++;
133.346 + w += l; // previous table always l bits
133.347 + // compute minimum size table less than or equal to l bits
133.348 + z = g - w;
133.349 + z = (z > l) ? l : z; // table size upper limit
133.350 + if((f=1<<(j=k-w))>a+1){ // try a k-w bit table
133.351 + // too few codes for k-w bit table
133.352 + f -= a + 1; // deduct codes from patterns left
133.353 + xp = k;
133.354 + if(j < z){
133.355 + while (++j < z){ // try smaller tables up to z bits
133.356 + if((f <<= 1) <= c[++xp])
133.357 + break; // enough codes to use up j bits
133.358 + f -= c[xp]; // else deduct codes from patterns
133.359 + }
133.360 + }
133.361 + }
133.362 + z = 1 << j; // table entries for j-bit table
133.363 +
133.364 + // allocate new table
133.365 + if (hn[0] + z > MANY){ // (note: doesn't matter for fixed)
133.366 + return Z_DATA_ERROR; // overflow of MANY
133.367 + }
133.368 + u[h] = q = /*hp+*/ hn[0]; // DEBUG
133.369 + hn[0] += z;
133.370 +
133.371 + // connect to last table, if there is one
133.372 + if(h!=0){
133.373 + x[h]=i; // save pattern for backing up
133.374 + r[0]=(byte)j; // bits in this table
133.375 + r[1]=(byte)l; // bits to dump before this table
133.376 + j=i>>>(w - l);
133.377 + r[2] = (int)(q - u[h-1] - j); // offset to this table
133.378 + System.arraycopy(r, 0, hp, (u[h-1]+j)*3, 3); // connect to last table
133.379 + }
133.380 + else{
133.381 + t[0] = q; // first table is returned result
133.382 + }
133.383 + }
133.384 +
133.385 + // set up table entry in r
133.386 + r[1] = (byte)(k - w);
133.387 + if (p >= n){
133.388 + r[0] = 128 + 64; // out of values--invalid code
133.389 + }
133.390 + else if (v[p] < s){
133.391 + r[0] = (byte)(v[p] < 256 ? 0 : 32 + 64); // 256 is end-of-block
133.392 + r[2] = v[p++]; // simple code is just the value
133.393 + }
133.394 + else{
133.395 + r[0]=(byte)(e[v[p]-s]+16+64); // non-simple--look up in lists
133.396 + r[2]=d[v[p++] - s];
133.397 + }
133.398 +
133.399 + // fill code-like entries with r
133.400 + f=1<<(k-w);
133.401 + for (j=i>>>w;j<z;j+=f){
133.402 + System.arraycopy(r, 0, hp, (q+j)*3, 3);
133.403 + }
133.404 +
133.405 + // backwards increment the k-bit code i
133.406 + for (j = 1 << (k - 1); (i & j)!=0; j >>>= 1){
133.407 + i ^= j;
133.408 + }
133.409 + i ^= j;
133.410 +
133.411 + // backup over finished tables
133.412 + mask = (1 << w) - 1; // needed on HP, cc -O bug
133.413 + while ((i & mask) != x[h]){
133.414 + h--; // don't need to update q
133.415 + w -= l;
133.416 + mask = (1 << w) - 1;
133.417 + }
133.418 + }
133.419 + }
133.420 + // Return Z_BUF_ERROR if we were given an incomplete table
133.421 + return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
133.422 + }
133.423 +
133.424 + int inflate_trees_bits(int[] c, // 19 code lengths
133.425 + int[] bb, // bits tree desired/actual depth
133.426 + int[] tb, // bits tree result
133.427 + int[] hp, // space for trees
133.428 + ZStream z // for messages
133.429 + ){
133.430 + int result;
133.431 + initWorkArea(19);
133.432 + hn[0]=0;
133.433 + result = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);
133.434 +
133.435 + if(result == Z_DATA_ERROR){
133.436 + z.msg = "oversubscribed dynamic bit lengths tree";
133.437 + }
133.438 + else if(result == Z_BUF_ERROR || bb[0] == 0){
133.439 + z.msg = "incomplete dynamic bit lengths tree";
133.440 + result = Z_DATA_ERROR;
133.441 + }
133.442 + return result;
133.443 + }
133.444 +
133.445 + int inflate_trees_dynamic(int nl, // number of literal/length codes
133.446 + int nd, // number of distance codes
133.447 + int[] c, // that many (total) code lengths
133.448 + int[] bl, // literal desired/actual bit depth
133.449 + int[] bd, // distance desired/actual bit depth
133.450 + int[] tl, // literal/length tree result
133.451 + int[] td, // distance tree result
133.452 + int[] hp, // space for trees
133.453 + ZStream z // for messages
133.454 + ){
133.455 + int result;
133.456 +
133.457 + // build literal/length tree
133.458 + initWorkArea(288);
133.459 + hn[0]=0;
133.460 + result = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);
133.461 + if (result != Z_OK || bl[0] == 0){
133.462 + if(result == Z_DATA_ERROR){
133.463 + z.msg = "oversubscribed literal/length tree";
133.464 + }
133.465 + else if (result != Z_MEM_ERROR){
133.466 + z.msg = "incomplete literal/length tree";
133.467 + result = Z_DATA_ERROR;
133.468 + }
133.469 + return result;
133.470 + }
133.471 +
133.472 + // build distance tree
133.473 + initWorkArea(288);
133.474 + result = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);
133.475 +
133.476 + if (result != Z_OK || (bd[0] == 0 && nl > 257)){
133.477 + if (result == Z_DATA_ERROR){
133.478 + z.msg = "oversubscribed distance tree";
133.479 + }
133.480 + else if (result == Z_BUF_ERROR) {
133.481 + z.msg = "incomplete distance tree";
133.482 + result = Z_DATA_ERROR;
133.483 + }
133.484 + else if (result != Z_MEM_ERROR){
133.485 + z.msg = "empty distance tree with lengths";
133.486 + result = Z_DATA_ERROR;
133.487 + }
133.488 + return result;
133.489 + }
133.490 +
133.491 + return Z_OK;
133.492 + }
133.493 +
133.494 + static int inflate_trees_fixed(int[] bl, //literal desired/actual bit depth
133.495 + int[] bd, //distance desired/actual bit depth
133.496 + int[][] tl,//literal/length tree result
133.497 + int[][] td,//distance tree result
133.498 + ZStream z //for memory allocation
133.499 + ){
133.500 + bl[0]=fixed_bl;
133.501 + bd[0]=fixed_bd;
133.502 + tl[0]=fixed_tl;
133.503 + td[0]=fixed_td;
133.504 + return Z_OK;
133.505 + }
133.506 +
133.507 + private void initWorkArea(int vsize){
133.508 + if(hn==null){
133.509 + hn=new int[1];
133.510 + v=new int[vsize];
133.511 + c=new int[BMAX+1];
133.512 + r=new int[3];
133.513 + u=new int[BMAX];
133.514 + x=new int[BMAX+1];
133.515 + }
133.516 + if(v.length<vsize){ v=new int[vsize]; }
133.517 + for(int i=0; i<vsize; i++){v[i]=0;}
133.518 + for(int i=0; i<BMAX+1; i++){c[i]=0;}
133.519 + for(int i=0; i<3; i++){r[i]=0;}
133.520 + System.arraycopy(c, 0, u, 0, BMAX);
133.521 + System.arraycopy(c, 0, x, 0, BMAX+1);
133.522 + }
133.523 +}
134.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
134.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/Inflate.java Sun Feb 17 17:58:34 2013 +0100
134.3 @@ -0,0 +1,727 @@
134.4 +/* -*-mode:java; c-basic-offset:2; -*- */
134.5 +/*
134.6 +Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved.
134.7 +
134.8 +Redistribution and use in source and binary forms, with or without
134.9 +modification, are permitted provided that the following conditions are met:
134.10 +
134.11 + 1. Redistributions of source code must retain the above copyright notice,
134.12 + this list of conditions and the following disclaimer.
134.13 +
134.14 + 2. Redistributions in binary form must reproduce the above copyright
134.15 + notice, this list of conditions and the following disclaimer in
134.16 + the documentation and/or other materials provided with the distribution.
134.17 +
134.18 + 3. The names of the authors may not be used to endorse or promote products
134.19 + derived from this software without specific prior written permission.
134.20 +
134.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
134.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
134.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
134.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
134.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
134.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
134.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
134.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
134.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
134.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
134.31 + */
134.32 +/*
134.33 + * This program is based on zlib-1.1.3, so all credit should go authors
134.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
134.35 + * and contributors of zlib.
134.36 + */
134.37 +
134.38 +package org.apidesign.bck2brwsr.emul.zip;
134.39 +
134.40 +import org.apidesign.bck2brwsr.emul.lang.System;
134.41 +
134.42 +final class Inflate{
134.43 +
134.44 + static final private int MAX_WBITS=15; // 32K LZ77 window
134.45 +
134.46 + // preset dictionary flag in zlib header
134.47 + static final private int PRESET_DICT=0x20;
134.48 +
134.49 + static final int Z_NO_FLUSH=0;
134.50 + static final int Z_PARTIAL_FLUSH=1;
134.51 + static final int Z_SYNC_FLUSH=2;
134.52 + static final int Z_FULL_FLUSH=3;
134.53 + static final int Z_FINISH=4;
134.54 +
134.55 + static final private int Z_DEFLATED=8;
134.56 +
134.57 + static final private int Z_OK=0;
134.58 + static final private int Z_STREAM_END=1;
134.59 + static final private int Z_NEED_DICT=2;
134.60 + static final private int Z_ERRNO=-1;
134.61 + static final private int Z_STREAM_ERROR=-2;
134.62 + static final private int Z_DATA_ERROR=-3;
134.63 + static final private int Z_MEM_ERROR=-4;
134.64 + static final private int Z_BUF_ERROR=-5;
134.65 + static final private int Z_VERSION_ERROR=-6;
134.66 +
134.67 + static final private int METHOD=0; // waiting for method byte
134.68 + static final private int FLAG=1; // waiting for flag byte
134.69 + static final private int DICT4=2; // four dictionary check bytes to go
134.70 + static final private int DICT3=3; // three dictionary check bytes to go
134.71 + static final private int DICT2=4; // two dictionary check bytes to go
134.72 + static final private int DICT1=5; // one dictionary check byte to go
134.73 + static final int DICT0=6; // waiting for inflateSetDictionary
134.74 + static final private int BLOCKS=7; // decompressing blocks
134.75 + static final private int CHECK4=8; // four check bytes to go
134.76 + static final private int CHECK3=9; // three check bytes to go
134.77 + static final private int CHECK2=10; // two check bytes to go
134.78 + static final private int CHECK1=11; // one check byte to go
134.79 + static final private int DONE=12; // finished check, done
134.80 + static final private int BAD=13; // got an error--stay here
134.81 +
134.82 + static final private int HEAD=14;
134.83 + static final private int LENGTH=15;
134.84 + static final private int TIME=16;
134.85 + static final private int OS=17;
134.86 + static final private int EXLEN=18;
134.87 + static final private int EXTRA=19;
134.88 + static final private int NAME=20;
134.89 + static final private int COMMENT=21;
134.90 + static final private int HCRC=22;
134.91 + static final private int FLAGS=23;
134.92 +
134.93 + int mode; // current inflate mode
134.94 +
134.95 + // mode dependent information
134.96 + int method; // if FLAGS, method byte
134.97 +
134.98 + // if CHECK, check values to compare
134.99 + long was = -1; // computed check value
134.100 + long need; // stream check value
134.101 +
134.102 + // if BAD, inflateSync's marker bytes count
134.103 + int marker;
134.104 +
134.105 + // mode independent information
134.106 + int wrap; // flag for no wrapper
134.107 + int wbits; // log2(window size) (8..15, defaults to 15)
134.108 +
134.109 + InfBlocks blocks; // current inflate_blocks state
134.110 +
134.111 + private final ZStream z;
134.112 +
134.113 + private int flags;
134.114 +
134.115 + private int need_bytes = -1;
134.116 + private byte[] crcbuf=new byte[4];
134.117 +
134.118 + GZIPHeader gheader = null;
134.119 +
134.120 + int inflateReset(){
134.121 + if(z == null) return Z_STREAM_ERROR;
134.122 +
134.123 + z.total_in = z.total_out = 0;
134.124 + z.msg = null;
134.125 + this.mode = HEAD;
134.126 + this.need_bytes = -1;
134.127 + this.blocks.reset();
134.128 + return Z_OK;
134.129 + }
134.130 +
134.131 + int inflateEnd(){
134.132 + if(blocks != null){
134.133 + blocks.free();
134.134 + }
134.135 + return Z_OK;
134.136 + }
134.137 +
134.138 + Inflate(ZStream z){
134.139 + this.z=z;
134.140 + }
134.141 +
134.142 + int inflateInit(int w){
134.143 + z.msg = null;
134.144 + blocks = null;
134.145 +
134.146 + // handle undocumented wrap option (no zlib header or check)
134.147 + wrap = 0;
134.148 + if(w < 0){
134.149 + w = - w;
134.150 + }
134.151 + else {
134.152 + wrap = (w >> 4) + 1;
134.153 + if(w < 48)
134.154 + w &= 15;
134.155 + }
134.156 +
134.157 + if(w<8 ||w>15){
134.158 + inflateEnd();
134.159 + return Z_STREAM_ERROR;
134.160 + }
134.161 + if(blocks != null && wbits != w){
134.162 + blocks.free();
134.163 + blocks=null;
134.164 + }
134.165 +
134.166 + // set window size
134.167 + wbits=w;
134.168 +
134.169 + this.blocks=new InfBlocks(z, 1<<w);
134.170 +
134.171 + // reset state
134.172 + inflateReset();
134.173 +
134.174 + return Z_OK;
134.175 + }
134.176 +
134.177 + int inflate(int f){
134.178 + int hold = 0;
134.179 +
134.180 + int r;
134.181 + int b;
134.182 +
134.183 + if(z == null || z.next_in == null){
134.184 + if(f == Z_FINISH && this.mode==HEAD)
134.185 + return Z_OK;
134.186 + return Z_STREAM_ERROR;
134.187 + }
134.188 +
134.189 + f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
134.190 + r = Z_BUF_ERROR;
134.191 + while (true){
134.192 +
134.193 + switch (this.mode){
134.194 + case HEAD:
134.195 + if(wrap==0){
134.196 + this.mode = BLOCKS;
134.197 + break;
134.198 + }
134.199 +
134.200 + try { r=readBytes(2, r, f); }
134.201 + catch(Return e){ return e.r; }
134.202 +
134.203 + if((wrap&2)!=0 && this.need == 0x8b1fL) { // gzip header
134.204 + z.adler=new CRC32();
134.205 + checksum(2, this.need);
134.206 +
134.207 + if(gheader==null)
134.208 + gheader=new GZIPHeader();
134.209 +
134.210 + this.mode = FLAGS;
134.211 + break;
134.212 + }
134.213 +
134.214 + flags = 0;
134.215 +
134.216 + this.method = ((int)this.need)&0xff;
134.217 + b=((int)(this.need>>8))&0xff;
134.218 +
134.219 + if((wrap&1)==0 || // check if zlib header allowed
134.220 + (((this.method << 8)+b) % 31)!=0){
134.221 + this.mode = BAD;
134.222 + z.msg = "incorrect header check";
134.223 + // since zlib 1.2, it is allowted to inflateSync for this case.
134.224 + /*
134.225 + this.marker = 5; // can't try inflateSync
134.226 + */
134.227 + break;
134.228 + }
134.229 +
134.230 + if((this.method&0xf)!=Z_DEFLATED){
134.231 + this.mode = BAD;
134.232 + z.msg="unknown compression method";
134.233 + // since zlib 1.2, it is allowted to inflateSync for this case.
134.234 + /*
134.235 + this.marker = 5; // can't try inflateSync
134.236 + */
134.237 + break;
134.238 + }
134.239 +
134.240 + if((this.method>>4)+8>this.wbits){
134.241 + this.mode = BAD;
134.242 + z.msg="invalid window size";
134.243 + // since zlib 1.2, it is allowted to inflateSync for this case.
134.244 + /*
134.245 + this.marker = 5; // can't try inflateSync
134.246 + */
134.247 + break;
134.248 + }
134.249 +
134.250 + z.adler=new Adler32();
134.251 +
134.252 + if((b&PRESET_DICT)==0){
134.253 + this.mode = BLOCKS;
134.254 + break;
134.255 + }
134.256 + this.mode = DICT4;
134.257 + case DICT4:
134.258 +
134.259 + if(z.avail_in==0)return r;r=f;
134.260 +
134.261 + z.avail_in--; z.total_in++;
134.262 + this.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L;
134.263 + this.mode=DICT3;
134.264 + case DICT3:
134.265 +
134.266 + if(z.avail_in==0)return r;r=f;
134.267 +
134.268 + z.avail_in--; z.total_in++;
134.269 + this.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L;
134.270 + this.mode=DICT2;
134.271 + case DICT2:
134.272 +
134.273 + if(z.avail_in==0)return r;r=f;
134.274 +
134.275 + z.avail_in--; z.total_in++;
134.276 + this.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L;
134.277 + this.mode=DICT1;
134.278 + case DICT1:
134.279 +
134.280 + if(z.avail_in==0)return r;r=f;
134.281 +
134.282 + z.avail_in--; z.total_in++;
134.283 + this.need += (z.next_in[z.next_in_index++]&0xffL);
134.284 + z.adler.reset(this.need);
134.285 + this.mode = DICT0;
134.286 + return Z_NEED_DICT;
134.287 + case DICT0:
134.288 + this.mode = BAD;
134.289 + z.msg = "need dictionary";
134.290 + this.marker = 0; // can try inflateSync
134.291 + return Z_STREAM_ERROR;
134.292 + case BLOCKS:
134.293 + r = this.blocks.proc(r);
134.294 + if(r == Z_DATA_ERROR){
134.295 + this.mode = BAD;
134.296 + this.marker = 0; // can try inflateSync
134.297 + break;
134.298 + }
134.299 + if(r == Z_OK){
134.300 + r = f;
134.301 + }
134.302 + if(r != Z_STREAM_END){
134.303 + return r;
134.304 + }
134.305 + r = f;
134.306 + this.was=z.adler.getValue();
134.307 + this.blocks.reset();
134.308 + if(this.wrap==0){
134.309 + this.mode=DONE;
134.310 + break;
134.311 + }
134.312 + this.mode=CHECK4;
134.313 + case CHECK4:
134.314 +
134.315 + if(z.avail_in==0)return r;r=f;
134.316 +
134.317 + z.avail_in--; z.total_in++;
134.318 + this.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L;
134.319 + this.mode=CHECK3;
134.320 + case CHECK3:
134.321 +
134.322 + if(z.avail_in==0)return r;r=f;
134.323 +
134.324 + z.avail_in--; z.total_in++;
134.325 + this.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L;
134.326 + this.mode = CHECK2;
134.327 + case CHECK2:
134.328 +
134.329 + if(z.avail_in==0)return r;r=f;
134.330 +
134.331 + z.avail_in--; z.total_in++;
134.332 + this.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L;
134.333 + this.mode = CHECK1;
134.334 + case CHECK1:
134.335 +
134.336 + if(z.avail_in==0)return r;r=f;
134.337 +
134.338 + z.avail_in--; z.total_in++;
134.339 + this.need+=(z.next_in[z.next_in_index++]&0xffL);
134.340 +
134.341 + if(flags!=0){ // gzip
134.342 + this.need = ((this.need&0xff000000)>>24 |
134.343 + (this.need&0x00ff0000)>>8 |
134.344 + (this.need&0x0000ff00)<<8 |
134.345 + (this.need&0x0000ffff)<<24)&0xffffffffL;
134.346 + }
134.347 +
134.348 + if(((int)(this.was)) != ((int)(this.need))){
134.349 + z.msg = "incorrect data check";
134.350 + // chack is delayed
134.351 + /*
134.352 + this.mode = BAD;
134.353 + this.marker = 5; // can't try inflateSync
134.354 + break;
134.355 + */
134.356 + }
134.357 + else if(flags!=0 && gheader!=null){
134.358 + gheader.crc = this.need;
134.359 + }
134.360 +
134.361 + this.mode = LENGTH;
134.362 + case LENGTH:
134.363 + if (wrap!=0 && flags!=0) {
134.364 +
134.365 + try { r=readBytes(4, r, f); }
134.366 + catch(Return e){ return e.r; }
134.367 +
134.368 + if(z.msg!=null && z.msg.equals("incorrect data check")){
134.369 + this.mode = BAD;
134.370 + this.marker = 5; // can't try inflateSync
134.371 + break;
134.372 + }
134.373 +
134.374 + if (this.need != (z.total_out & 0xffffffffL)) {
134.375 + z.msg = "incorrect length check";
134.376 + this.mode = BAD;
134.377 + break;
134.378 + }
134.379 + z.msg = null;
134.380 + }
134.381 + else {
134.382 + if(z.msg!=null && z.msg.equals("incorrect data check")){
134.383 + this.mode = BAD;
134.384 + this.marker = 5; // can't try inflateSync
134.385 + break;
134.386 + }
134.387 + }
134.388 +
134.389 + this.mode = DONE;
134.390 + case DONE:
134.391 + return Z_STREAM_END;
134.392 + case BAD:
134.393 + return Z_DATA_ERROR;
134.394 +
134.395 + case FLAGS:
134.396 +
134.397 + try { r=readBytes(2, r, f); }
134.398 + catch(Return e){ return e.r; }
134.399 +
134.400 + flags = ((int)this.need)&0xffff;
134.401 +
134.402 + if ((flags & 0xff) != Z_DEFLATED) {
134.403 + z.msg = "unknown compression method";
134.404 + this.mode = BAD;
134.405 + break;
134.406 + }
134.407 + if ((flags & 0xe000)!=0) {
134.408 + z.msg = "unknown header flags set";
134.409 + this.mode = BAD;
134.410 + break;
134.411 + }
134.412 +
134.413 + if ((flags & 0x0200)!=0){
134.414 + checksum(2, this.need);
134.415 + }
134.416 +
134.417 + this.mode = TIME;
134.418 +
134.419 + case TIME:
134.420 + try { r=readBytes(4, r, f); }
134.421 + catch(Return e){ return e.r; }
134.422 + if(gheader!=null)
134.423 + gheader.time = this.need;
134.424 + if ((flags & 0x0200)!=0){
134.425 + checksum(4, this.need);
134.426 + }
134.427 + this.mode = OS;
134.428 + case OS:
134.429 + try { r=readBytes(2, r, f); }
134.430 + catch(Return e){ return e.r; }
134.431 + if(gheader!=null){
134.432 + gheader.xflags = ((int)this.need)&0xff;
134.433 + gheader.os = (((int)this.need)>>8)&0xff;
134.434 + }
134.435 + if ((flags & 0x0200)!=0){
134.436 + checksum(2, this.need);
134.437 + }
134.438 + this.mode = EXLEN;
134.439 + case EXLEN:
134.440 + if ((flags & 0x0400)!=0) {
134.441 + try { r=readBytes(2, r, f); }
134.442 + catch(Return e){ return e.r; }
134.443 + if(gheader!=null){
134.444 + gheader.extra = new byte[((int)this.need)&0xffff];
134.445 + }
134.446 + if ((flags & 0x0200)!=0){
134.447 + checksum(2, this.need);
134.448 + }
134.449 + }
134.450 + else if(gheader!=null){
134.451 + gheader.extra=null;
134.452 + }
134.453 + this.mode = EXTRA;
134.454 +
134.455 + case EXTRA:
134.456 + if ((flags & 0x0400)!=0) {
134.457 + try {
134.458 + r=readBytes(r, f);
134.459 + if(gheader!=null){
134.460 + byte[] foo = tmp_array;
134.461 + tmp_array=null;
134.462 + if(foo.length == gheader.extra.length){
134.463 + System.arraycopy(foo, 0, gheader.extra, 0, foo.length);
134.464 + }
134.465 + else{
134.466 + z.msg = "bad extra field length";
134.467 + this.mode = BAD;
134.468 + break;
134.469 + }
134.470 + }
134.471 + }
134.472 + catch(Return e){ return e.r; }
134.473 + }
134.474 + else if(gheader!=null){
134.475 + gheader.extra=null;
134.476 + }
134.477 + this.mode = NAME;
134.478 + case NAME:
134.479 + if ((flags & 0x0800)!=0) {
134.480 + try {
134.481 + r=readString(r, f);
134.482 + if(gheader!=null){
134.483 + gheader.name=tmp_array;
134.484 + }
134.485 + tmp_array=null;
134.486 + }
134.487 + catch(Return e){ return e.r; }
134.488 + }
134.489 + else if(gheader!=null){
134.490 + gheader.name=null;
134.491 + }
134.492 + this.mode = COMMENT;
134.493 + case COMMENT:
134.494 + if ((flags & 0x1000)!=0) {
134.495 + try {
134.496 + r=readString(r, f);
134.497 + if(gheader!=null){
134.498 + gheader.comment=tmp_array;
134.499 + }
134.500 + tmp_array=null;
134.501 + }
134.502 + catch(Return e){ return e.r; }
134.503 + }
134.504 + else if(gheader!=null){
134.505 + gheader.comment=null;
134.506 + }
134.507 + this.mode = HCRC;
134.508 + case HCRC:
134.509 + if ((flags & 0x0200)!=0) {
134.510 + try { r=readBytes(2, r, f); }
134.511 + catch(Return e){ return e.r; }
134.512 + if(gheader!=null){
134.513 + gheader.hcrc=(int)(this.need&0xffff);
134.514 + }
134.515 + if(this.need != (z.adler.getValue()&0xffffL)){
134.516 + this.mode = BAD;
134.517 + z.msg = "header crc mismatch";
134.518 + this.marker = 5; // can't try inflateSync
134.519 + break;
134.520 + }
134.521 + }
134.522 + z.adler = new CRC32();
134.523 +
134.524 + this.mode = BLOCKS;
134.525 + break;
134.526 + default:
134.527 + return Z_STREAM_ERROR;
134.528 + }
134.529 + }
134.530 + }
134.531 +
134.532 + int inflateSetDictionary(byte[] dictionary, int dictLength){
134.533 + if(z==null || (this.mode != DICT0 && this.wrap != 0)){
134.534 + return Z_STREAM_ERROR;
134.535 + }
134.536 +
134.537 + int index=0;
134.538 + int length = dictLength;
134.539 +
134.540 + if(this.mode==DICT0){
134.541 + long adler_need=z.adler.getValue();
134.542 + z.adler.reset();
134.543 + z.adler.update(dictionary, 0, dictLength);
134.544 + if(z.adler.getValue()!=adler_need){
134.545 + return Z_DATA_ERROR;
134.546 + }
134.547 + }
134.548 +
134.549 + z.adler.reset();
134.550 +
134.551 + if(length >= (1<<this.wbits)){
134.552 + length = (1<<this.wbits)-1;
134.553 + index=dictLength - length;
134.554 + }
134.555 + this.blocks.set_dictionary(dictionary, index, length);
134.556 + this.mode = BLOCKS;
134.557 + return Z_OK;
134.558 + }
134.559 +
134.560 + static private byte[] mark = {(byte)0, (byte)0, (byte)0xff, (byte)0xff};
134.561 +
134.562 + int inflateSync(){
134.563 + int n; // number of bytes to look at
134.564 + int p; // pointer to bytes
134.565 + int m; // number of marker bytes found in a row
134.566 + long r, w; // temporaries to save total_in and total_out
134.567 +
134.568 + // set up
134.569 + if(z == null)
134.570 + return Z_STREAM_ERROR;
134.571 + if(this.mode != BAD){
134.572 + this.mode = BAD;
134.573 + this.marker = 0;
134.574 + }
134.575 + if((n=z.avail_in)==0)
134.576 + return Z_BUF_ERROR;
134.577 +
134.578 + p=z.next_in_index;
134.579 + m=this.marker;
134.580 + // search
134.581 + while (n!=0 && m < 4){
134.582 + if(z.next_in[p] == mark[m]){
134.583 + m++;
134.584 + }
134.585 + else if(z.next_in[p]!=0){
134.586 + m = 0;
134.587 + }
134.588 + else{
134.589 + m = 4 - m;
134.590 + }
134.591 + p++; n--;
134.592 + }
134.593 +
134.594 + // restore
134.595 + z.total_in += p-z.next_in_index;
134.596 + z.next_in_index = p;
134.597 + z.avail_in = n;
134.598 + this.marker = m;
134.599 +
134.600 + // return no joy or set up to restart on a new block
134.601 + if(m != 4){
134.602 + return Z_DATA_ERROR;
134.603 + }
134.604 + r=z.total_in; w=z.total_out;
134.605 + inflateReset();
134.606 + z.total_in=r; z.total_out = w;
134.607 + this.mode = BLOCKS;
134.608 +
134.609 + return Z_OK;
134.610 + }
134.611 +
134.612 + // Returns true if inflate is currently at the end of a block generated
134.613 + // by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
134.614 + // implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
134.615 + // but removes the length bytes of the resulting empty stored block. When
134.616 + // decompressing, PPP checks that at the end of input packet, inflate is
134.617 + // waiting for these length bytes.
134.618 + int inflateSyncPoint(){
134.619 + if(z == null || this.blocks == null)
134.620 + return Z_STREAM_ERROR;
134.621 + return this.blocks.sync_point();
134.622 + }
134.623 +
134.624 + private int readBytes(int n, int r, int f) throws Return{
134.625 + if(need_bytes == -1){
134.626 + need_bytes=n;
134.627 + this.need=0;
134.628 + }
134.629 + while(need_bytes>0){
134.630 + if(z.avail_in==0){ throw new Return(r); }; r=f;
134.631 + z.avail_in--; z.total_in++;
134.632 + this.need = this.need |
134.633 + ((z.next_in[z.next_in_index++]&0xff)<<((n-need_bytes)*8));
134.634 + need_bytes--;
134.635 + }
134.636 + if(n==2){
134.637 + this.need&=0xffffL;
134.638 + }
134.639 + else if(n==4) {
134.640 + this.need&=0xffffffffL;
134.641 + }
134.642 + need_bytes=-1;
134.643 + return r;
134.644 + }
134.645 + class Return extends Exception{
134.646 + int r;
134.647 + Return(int r){this.r=r; }
134.648 + }
134.649 +
134.650 + private byte[] tmp_array;
134.651 + private int readString(int r, int f) throws Return{
134.652 + int b=0;
134.653 + byte[] arr = new byte[4092];
134.654 + int at = 0;
134.655 + do {
134.656 + if(z.avail_in==0){ throw new Return(r); }; r=f;
134.657 + z.avail_in--; z.total_in++;
134.658 + b = z.next_in[z.next_in_index];
134.659 + if(b!=0) arr = append(arr, z.next_in[z.next_in_index], at++);
134.660 + z.adler.update(z.next_in, z.next_in_index, 1);
134.661 + z.next_in_index++;
134.662 + }while(b!=0);
134.663 +
134.664 + tmp_array = copy(arr, at);
134.665 +
134.666 + return r;
134.667 + }
134.668 +
134.669 + private int readBytes(int r, int f) throws Return{
134.670 + int b=0;
134.671 + byte[] arr = new byte[4092];
134.672 + int at = 0;
134.673 + while(this.need>0){
134.674 + if(z.avail_in==0){ throw new Return(r); }; r=f;
134.675 + z.avail_in--; z.total_in++;
134.676 + b = z.next_in[z.next_in_index];
134.677 + arr = append(arr, z.next_in[z.next_in_index], at++);
134.678 + z.adler.update(z.next_in, z.next_in_index, 1);
134.679 + z.next_in_index++;
134.680 + this.need--;
134.681 + }
134.682 +
134.683 + tmp_array = copy(arr, at);
134.684 +
134.685 + return r;
134.686 + }
134.687 +
134.688 + private static byte[] copy(byte[] arr, int len) {
134.689 + byte[] ret = new byte[len];
134.690 + org.apidesign.bck2brwsr.emul.lang.System.arraycopy(arr, 0, ret, 0, len);
134.691 + return ret;
134.692 + }
134.693 + private static byte[] append(byte[] arr, byte b, int index) {
134.694 + arr[index] = b;
134.695 + return arr;
134.696 + }
134.697 +
134.698 + private void checksum(int n, long v){
134.699 + for(int i=0; i<n; i++){
134.700 + crcbuf[i]=(byte)(v&0xff);
134.701 + v>>=8;
134.702 + }
134.703 + z.adler.update(crcbuf, 0, n);
134.704 + }
134.705 +
134.706 + public GZIPHeader getGZIPHeader(){
134.707 + return gheader;
134.708 + }
134.709 +
134.710 + boolean inParsingHeader(){
134.711 + switch(mode){
134.712 + case HEAD:
134.713 + case DICT4:
134.714 + case DICT3:
134.715 + case DICT2:
134.716 + case DICT1:
134.717 + case FLAGS:
134.718 + case TIME:
134.719 + case OS:
134.720 + case EXLEN:
134.721 + case EXTRA:
134.722 + case NAME:
134.723 + case COMMENT:
134.724 + case HCRC:
134.725 + return true;
134.726 + default:
134.727 + return false;
134.728 + }
134.729 + }
134.730 +}
135.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
135.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/Inflater.java Sun Feb 17 17:58:34 2013 +0100
135.3 @@ -0,0 +1,338 @@
135.4 +/*
135.5 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
135.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
135.7 + *
135.8 + * This code is free software; you can redistribute it and/or modify it
135.9 + * under the terms of the GNU General Public License version 2 only, as
135.10 + * published by the Free Software Foundation. Oracle designates this
135.11 + * particular file as subject to the "Classpath" exception as provided
135.12 + * by Oracle in the LICENSE file that accompanied this code.
135.13 + *
135.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
135.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
135.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
135.17 + * version 2 for more details (a copy is included in the LICENSE file that
135.18 + * accompanied this code).
135.19 + *
135.20 + * You should have received a copy of the GNU General Public License version
135.21 + * 2 along with this work; if not, write to the Free Software Foundation,
135.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
135.23 + *
135.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
135.25 + * or visit www.oracle.com if you need additional information or have any
135.26 + * questions.
135.27 + */
135.28 +
135.29 +package org.apidesign.bck2brwsr.emul.zip;
135.30 +
135.31 +import java.util.zip.*;
135.32 +import java.io.IOException;
135.33 +
135.34 +/**
135.35 + * This class provides support for general purpose decompression using the
135.36 + * popular ZLIB compression library. The ZLIB compression library was
135.37 + * initially developed as part of the PNG graphics standard and is not
135.38 + * protected by patents. It is fully described in the specifications at
135.39 + * the <a href="package-summary.html#package_description">java.util.zip
135.40 + * package description</a>.
135.41 + *
135.42 + * <p>The following code fragment demonstrates a trivial compression
135.43 + * and decompression of a string using <tt>Deflater</tt> and
135.44 + * <tt>Inflater</tt>.
135.45 + *
135.46 + * <blockquote><pre>
135.47 + * try {
135.48 + * // Encode a String into bytes
135.49 + * String inputString = "blahblahblah\u20AC\u20AC";
135.50 + * byte[] input = inputString.getBytes("UTF-8");
135.51 + *
135.52 + * // Compress the bytes
135.53 + * byte[] output = new byte[100];
135.54 + * Deflater compresser = new Deflater();
135.55 + * compresser.setInput(input);
135.56 + * compresser.finish();
135.57 + * int compressedDataLength = compresser.deflate(output);
135.58 + *
135.59 + * // Decompress the bytes
135.60 + * Inflater decompresser = new Inflater();
135.61 + * decompresser.setInput(output, 0, compressedDataLength);
135.62 + * byte[] result = new byte[100];
135.63 + * int resultLength = decompresser.inflate(result);
135.64 + * decompresser.end();
135.65 + *
135.66 + * // Decode the bytes into a String
135.67 + * String outputString = new String(result, 0, resultLength, "UTF-8");
135.68 + * } catch(java.io.UnsupportedEncodingException ex) {
135.69 + * // handle
135.70 + * } catch (java.util.zip.DataFormatException ex) {
135.71 + * // handle
135.72 + * }
135.73 + * </pre></blockquote>
135.74 + *
135.75 + * @see Deflater
135.76 + * @author David Connelly
135.77 + *
135.78 + */
135.79 +public
135.80 +class Inflater extends java.util.zip.Inflater {
135.81 + private final boolean nowrap;
135.82 + private JzLibInflater impl;
135.83 +
135.84 + /**
135.85 + * Creates a new decompressor. If the parameter 'nowrap' is true then
135.86 + * the ZLIB header and checksum fields will not be used. This provides
135.87 + * compatibility with the compression format used by both GZIP and PKZIP.
135.88 + * <p>
135.89 + * Note: When using the 'nowrap' option it is also necessary to provide
135.90 + * an extra "dummy" byte as input. This is required by the ZLIB native
135.91 + * library in order to support certain optimizations.
135.92 + *
135.93 + * @param nowrap if true then support GZIP compatible compression
135.94 + */
135.95 + public Inflater(boolean nowrap) {
135.96 + this.nowrap = nowrap;
135.97 + reset();
135.98 + }
135.99 +
135.100 + /**
135.101 + * Creates a new decompressor.
135.102 + */
135.103 + public Inflater() {
135.104 + this(false);
135.105 + }
135.106 +
135.107 + /**
135.108 + * Sets input data for decompression. Should be called whenever
135.109 + * needsInput() returns true indicating that more input data is
135.110 + * required.
135.111 + * @param b the input data bytes
135.112 + * @param off the start offset of the input data
135.113 + * @param len the length of the input data
135.114 + * @see Inflater#needsInput
135.115 + */
135.116 + public void setInput(byte[] b, int off, int len) {
135.117 + if (b == null) {
135.118 + throw new NullPointerException();
135.119 + }
135.120 + if (off < 0 || len < 0 || off > b.length - len) {
135.121 + throw new ArrayIndexOutOfBoundsException();
135.122 + }
135.123 + impl.setInput(b, off, len, false);
135.124 + }
135.125 +
135.126 + /**
135.127 + * Sets input data for decompression. Should be called whenever
135.128 + * needsInput() returns true indicating that more input data is
135.129 + * required.
135.130 + * @param b the input data bytes
135.131 + * @see Inflater#needsInput
135.132 + */
135.133 + public void setInput(byte[] b) {
135.134 + setInput(b, 0, b.length);
135.135 + }
135.136 +
135.137 + /**
135.138 + * Sets the preset dictionary to the given array of bytes. Should be
135.139 + * called when inflate() returns 0 and needsDictionary() returns true
135.140 + * indicating that a preset dictionary is required. The method getAdler()
135.141 + * can be used to get the Adler-32 value of the dictionary needed.
135.142 + * @param b the dictionary data bytes
135.143 + * @param off the start offset of the data
135.144 + * @param len the length of the data
135.145 + * @see Inflater#needsDictionary
135.146 + * @see Inflater#getAdler
135.147 + */
135.148 + public void setDictionary(byte[] b, int off, int len) {
135.149 + if (b == null) {
135.150 + throw new NullPointerException();
135.151 + }
135.152 + if (off < 0 || len < 0 || off > b.length - len) {
135.153 + throw new ArrayIndexOutOfBoundsException();
135.154 + }
135.155 + byte[] arr;
135.156 + if (off == 0) {
135.157 + arr = b;
135.158 + } else {
135.159 + arr = new byte[len];
135.160 + org.apidesign.bck2brwsr.emul.lang.System.arraycopy(b, off, arr, 0, len);
135.161 + }
135.162 + impl.setDictionary(arr, len);
135.163 + }
135.164 +
135.165 + /**
135.166 + * Sets the preset dictionary to the given array of bytes. Should be
135.167 + * called when inflate() returns 0 and needsDictionary() returns true
135.168 + * indicating that a preset dictionary is required. The method getAdler()
135.169 + * can be used to get the Adler-32 value of the dictionary needed.
135.170 + * @param b the dictionary data bytes
135.171 + * @see Inflater#needsDictionary
135.172 + * @see Inflater#getAdler
135.173 + */
135.174 + public void setDictionary(byte[] b) {
135.175 + impl.setDictionary(b, b.length);
135.176 + }
135.177 +
135.178 + /**
135.179 + * Returns the total number of bytes remaining in the input buffer.
135.180 + * This can be used to find out what bytes still remain in the input
135.181 + * buffer after decompression has finished.
135.182 + * @return the total number of bytes remaining in the input buffer
135.183 + */
135.184 + public int getRemaining() {
135.185 + return impl.getAvailIn();
135.186 + }
135.187 +
135.188 + /**
135.189 + * Returns true if no data remains in the input buffer. This can
135.190 + * be used to determine if #setInput should be called in order
135.191 + * to provide more input.
135.192 + * @return true if no data remains in the input buffer
135.193 + */
135.194 + public boolean needsInput() {
135.195 + return getRemaining() <= 0;
135.196 + }
135.197 +
135.198 + /**
135.199 + * Returns true if a preset dictionary is needed for decompression.
135.200 + * @return true if a preset dictionary is needed for decompression
135.201 + * @see Inflater#setDictionary
135.202 + */
135.203 + public boolean needsDictionary() {
135.204 + return impl.needDict();
135.205 + }
135.206 +
135.207 + /**
135.208 + * Returns true if the end of the compressed data stream has been
135.209 + * reached.
135.210 + * @return true if the end of the compressed data stream has been
135.211 + * reached
135.212 + */
135.213 + public boolean finished() {
135.214 + return impl.finished();
135.215 + }
135.216 +
135.217 + /**
135.218 + * Uncompresses bytes into specified buffer. Returns actual number
135.219 + * of bytes uncompressed. A return value of 0 indicates that
135.220 + * needsInput() or needsDictionary() should be called in order to
135.221 + * determine if more input data or a preset dictionary is required.
135.222 + * In the latter case, getAdler() can be used to get the Adler-32
135.223 + * value of the dictionary required.
135.224 + * @param b the buffer for the uncompressed data
135.225 + * @param off the start offset of the data
135.226 + * @param len the maximum number of uncompressed bytes
135.227 + * @return the actual number of uncompressed bytes
135.228 + * @exception DataFormatException if the compressed data format is invalid
135.229 + * @see Inflater#needsInput
135.230 + * @see Inflater#needsDictionary
135.231 + */
135.232 + public int inflate(byte[] b, int off, int len)
135.233 + throws DataFormatException
135.234 + {
135.235 + if (b == null) {
135.236 + throw new NullPointerException();
135.237 + }
135.238 + if (off < 0 || len < 0 || off > b.length - len) {
135.239 + throw new ArrayIndexOutOfBoundsException();
135.240 + }
135.241 + impl.setOutput(b, off, len);
135.242 + int err = impl.inflate(JzLibInflater.Z_NO_FLUSH);
135.243 + return impl.next_out_index - off;
135.244 + }
135.245 +
135.246 + /**
135.247 + * Uncompresses bytes into specified buffer. Returns actual number
135.248 + * of bytes uncompressed. A return value of 0 indicates that
135.249 + * needsInput() or needsDictionary() should be called in order to
135.250 + * determine if more input data or a preset dictionary is required.
135.251 + * In the latter case, getAdler() can be used to get the Adler-32
135.252 + * value of the dictionary required.
135.253 + * @param b the buffer for the uncompressed data
135.254 + * @return the actual number of uncompressed bytes
135.255 + * @exception DataFormatException if the compressed data format is invalid
135.256 + * @see Inflater#needsInput
135.257 + * @see Inflater#needsDictionary
135.258 + */
135.259 + public int inflate(byte[] b) throws DataFormatException {
135.260 + return inflate(b, 0, b.length);
135.261 + }
135.262 +
135.263 + /**
135.264 + * Returns the ADLER-32 value of the uncompressed data.
135.265 + * @return the ADLER-32 value of the uncompressed data
135.266 + */
135.267 + public int getAdler() {
135.268 + return (int) impl.getAdler();
135.269 + }
135.270 +
135.271 + /**
135.272 + * Returns the total number of compressed bytes input so far.
135.273 + *
135.274 + * <p>Since the number of bytes may be greater than
135.275 + * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now
135.276 + * the preferred means of obtaining this information.</p>
135.277 + *
135.278 + * @return the total number of compressed bytes input so far
135.279 + */
135.280 + public int getTotalIn() {
135.281 + return (int) getBytesRead();
135.282 + }
135.283 +
135.284 + /**
135.285 + * Returns the total number of compressed bytes input so far.</p>
135.286 + *
135.287 + * @return the total (non-negative) number of compressed bytes input so far
135.288 + * @since 1.5
135.289 + */
135.290 + public long getBytesRead() {
135.291 + return impl.total_in;
135.292 + }
135.293 +
135.294 + /**
135.295 + * Returns the total number of uncompressed bytes output so far.
135.296 + *
135.297 + * <p>Since the number of bytes may be greater than
135.298 + * Integer.MAX_VALUE, the {@link #getBytesWritten()} method is now
135.299 + * the preferred means of obtaining this information.</p>
135.300 + *
135.301 + * @return the total number of uncompressed bytes output so far
135.302 + */
135.303 + public int getTotalOut() {
135.304 + return (int) getBytesWritten();
135.305 + }
135.306 +
135.307 + /**
135.308 + * Returns the total number of uncompressed bytes output so far.</p>
135.309 + *
135.310 + * @return the total (non-negative) number of uncompressed bytes output so far
135.311 + * @since 1.5
135.312 + */
135.313 + public long getBytesWritten() {
135.314 + return impl.total_out;
135.315 + }
135.316 +
135.317 + /**
135.318 + * Resets inflater so that a new set of input data can be processed.
135.319 + */
135.320 + public void reset() {
135.321 + impl = new JzLibInflater(15, nowrap);
135.322 + }
135.323 +
135.324 + /**
135.325 + * Closes the decompressor and discards any unprocessed input.
135.326 + * This method should be called when the decompressor is no longer
135.327 + * being used, but will also be called automatically by the finalize()
135.328 + * method. Once this method is called, the behavior of the Inflater
135.329 + * object is undefined.
135.330 + */
135.331 + public void end() {
135.332 + impl.end();
135.333 + }
135.334 +
135.335 + /**
135.336 + * Closes the decompressor when garbage is collected.
135.337 + */
135.338 + protected void finalize() {
135.339 + end();
135.340 + }
135.341 +}
136.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
136.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/JzLibInflater.java Sun Feb 17 17:58:34 2013 +0100
136.3 @@ -0,0 +1,137 @@
136.4 +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
136.5 +/*
136.6 +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
136.7 +
136.8 +Redistribution and use in source and binary forms, with or without
136.9 +modification, are permitted provided that the following conditions are met:
136.10 +
136.11 + 1. Redistributions of source code must retain the above copyright notice,
136.12 + this list of conditions and the following disclaimer.
136.13 +
136.14 + 2. Redistributions in binary form must reproduce the above copyright
136.15 + notice, this list of conditions and the following disclaimer in
136.16 + the documentation and/or other materials provided with the distribution.
136.17 +
136.18 + 3. The names of the authors may not be used to endorse or promote products
136.19 + derived from this software without specific prior written permission.
136.20 +
136.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
136.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
136.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
136.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
136.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
136.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
136.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
136.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
136.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
136.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
136.31 + */
136.32 +/*
136.33 + * This program is based on zlib-1.1.3, so all credit should go authors
136.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
136.35 + * and contributors of zlib.
136.36 + */
136.37 +
136.38 +package org.apidesign.bck2brwsr.emul.zip;
136.39 +
136.40 +final class JzLibInflater extends ZStream{
136.41 +
136.42 + static final private int MAX_WBITS=15; // 32K LZ77 window
136.43 + static final private int DEF_WBITS=MAX_WBITS;
136.44 +
136.45 + public static final int Z_NO_FLUSH=0;
136.46 + static final private int Z_PARTIAL_FLUSH=1;
136.47 + static final private int Z_SYNC_FLUSH=2;
136.48 + static final private int Z_FULL_FLUSH=3;
136.49 + static final private int Z_FINISH=4;
136.50 +
136.51 + static final private int MAX_MEM_LEVEL=9;
136.52 +
136.53 + static final private int Z_OK=0;
136.54 + static final private int Z_STREAM_END=1;
136.55 + static final private int Z_NEED_DICT=2;
136.56 + static final private int Z_ERRNO=-1;
136.57 + static final private int Z_STREAM_ERROR=-2;
136.58 + static final private int Z_DATA_ERROR=-3;
136.59 + static final private int Z_MEM_ERROR=-4;
136.60 + static final private int Z_BUF_ERROR=-5;
136.61 + static final private int Z_VERSION_ERROR=-6;
136.62 +
136.63 + public JzLibInflater() {
136.64 + super();
136.65 + init();
136.66 + }
136.67 +
136.68 + public JzLibInflater(int w) {
136.69 + this(w, false);
136.70 + }
136.71 +
136.72 + public JzLibInflater(int w, boolean nowrap) {
136.73 + super();
136.74 + int ret = init(w, nowrap);
136.75 + if(ret!=Z_OK)
136.76 + throw new IllegalStateException(ret+": "+msg);
136.77 + }
136.78 +
136.79 + private boolean finished = false;
136.80 +
136.81 + public int init(){
136.82 + return init(DEF_WBITS);
136.83 + }
136.84 +
136.85 + public int init(boolean nowrap){
136.86 + return init(DEF_WBITS, nowrap);
136.87 + }
136.88 +
136.89 + public int init(int w){
136.90 + return init(w, false);
136.91 + }
136.92 +
136.93 + public int init(int w, boolean nowrap){
136.94 + finished = false;
136.95 + istate=new Inflate(this);
136.96 + return istate.inflateInit(nowrap?-w:w);
136.97 + }
136.98 +
136.99 + public int inflate(int f){
136.100 + if(istate==null) return Z_STREAM_ERROR;
136.101 + int ret = istate.inflate(f);
136.102 + if(ret == Z_STREAM_END)
136.103 + finished = true;
136.104 + return ret;
136.105 + }
136.106 +
136.107 + public int end(){
136.108 + finished = true;
136.109 + if(istate==null) return Z_STREAM_ERROR;
136.110 + int ret=istate.inflateEnd();
136.111 +// istate = null;
136.112 + return ret;
136.113 + }
136.114 +
136.115 + public int sync(){
136.116 + if(istate == null)
136.117 + return Z_STREAM_ERROR;
136.118 + return istate.inflateSync();
136.119 + }
136.120 +
136.121 + public int syncPoint(){
136.122 + if(istate == null)
136.123 + return Z_STREAM_ERROR;
136.124 + return istate.inflateSyncPoint();
136.125 + }
136.126 +
136.127 + public int setDictionary(byte[] dictionary, int dictLength){
136.128 + if(istate == null)
136.129 + return Z_STREAM_ERROR;
136.130 + return istate.inflateSetDictionary(dictionary, dictLength);
136.131 + }
136.132 +
136.133 + public boolean finished(){
136.134 + return istate.mode==12 /*DONE*/;
136.135 + }
136.136 +
136.137 + public boolean needDict() {
136.138 + return istate == null ? false : istate.mode == Inflate.DICT0;
136.139 + }
136.140 +}
137.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
137.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/ZStream.java Sun Feb 17 17:58:34 2013 +0100
137.3 @@ -0,0 +1,253 @@
137.4 +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
137.5 +/*
137.6 +Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved.
137.7 +
137.8 +Redistribution and use in source and binary forms, with or without
137.9 +modification, are permitted provided that the following conditions are met:
137.10 +
137.11 + 1. Redistributions of source code must retain the above copyright notice,
137.12 + this list of conditions and the following disclaimer.
137.13 +
137.14 + 2. Redistributions in binary form must reproduce the above copyright
137.15 + notice, this list of conditions and the following disclaimer in
137.16 + the documentation and/or other materials provided with the distribution.
137.17 +
137.18 + 3. The names of the authors may not be used to endorse or promote products
137.19 + derived from this software without specific prior written permission.
137.20 +
137.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
137.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
137.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
137.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
137.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
137.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
137.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
137.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
137.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
137.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
137.31 + */
137.32 +/*
137.33 + * This program is based on zlib-1.1.3, so all credit should go authors
137.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
137.35 + * and contributors of zlib.
137.36 + */
137.37 +
137.38 +package org.apidesign.bck2brwsr.emul.zip;
137.39 +
137.40 +import org.apidesign.bck2brwsr.emul.lang.System;
137.41 +
137.42 +/**
137.43 + * ZStream
137.44 + *
137.45 + * @deprecated Not for public use in the future.
137.46 + */
137.47 +@Deprecated
137.48 +class ZStream{
137.49 +
137.50 + static final private int MAX_WBITS=15; // 32K LZ77 window
137.51 + static final private int DEF_WBITS=MAX_WBITS;
137.52 +
137.53 + static final private int Z_NO_FLUSH=0;
137.54 + static final private int Z_PARTIAL_FLUSH=1;
137.55 + static final private int Z_SYNC_FLUSH=2;
137.56 + static final private int Z_FULL_FLUSH=3;
137.57 + static final private int Z_FINISH=4;
137.58 +
137.59 + static final private int MAX_MEM_LEVEL=9;
137.60 +
137.61 + static final private int Z_OK=0;
137.62 + static final private int Z_STREAM_END=1;
137.63 + static final private int Z_NEED_DICT=2;
137.64 + static final private int Z_ERRNO=-1;
137.65 + static final private int Z_STREAM_ERROR=-2;
137.66 + static final private int Z_DATA_ERROR=-3;
137.67 + static final private int Z_MEM_ERROR=-4;
137.68 + static final private int Z_BUF_ERROR=-5;
137.69 + static final private int Z_VERSION_ERROR=-6;
137.70 +
137.71 + public byte[] next_in; // next input byte
137.72 + public int next_in_index;
137.73 + public int avail_in; // number of bytes available at next_in
137.74 + public long total_in; // total nb of input bytes read so far
137.75 +
137.76 + public byte[] next_out; // next output byte should be put there
137.77 + public int next_out_index;
137.78 + public int avail_out; // remaining free space at next_out
137.79 + public long total_out; // total nb of bytes output so far
137.80 +
137.81 + public String msg;
137.82 +
137.83 + Inflate istate;
137.84 +
137.85 + int data_type; // best guess about the data type: ascii or binary
137.86 +
137.87 + Checksum adler;
137.88 +
137.89 + public ZStream(){
137.90 + this(new Adler32());
137.91 + }
137.92 +
137.93 + public ZStream(Checksum adler){
137.94 + this.adler=adler;
137.95 + }
137.96 +
137.97 + public int inflateInit(){
137.98 + return inflateInit(DEF_WBITS);
137.99 + }
137.100 + public int inflateInit(boolean nowrap){
137.101 + return inflateInit(DEF_WBITS, nowrap);
137.102 + }
137.103 + public int inflateInit(int w){
137.104 + return inflateInit(w, false);
137.105 + }
137.106 +
137.107 + public int inflateInit(int w, boolean nowrap){
137.108 + istate=new Inflate(this);
137.109 + return istate.inflateInit(nowrap?-w:w);
137.110 + }
137.111 +
137.112 + public int inflate(int f){
137.113 + if(istate==null) return Z_STREAM_ERROR;
137.114 + return istate.inflate(f);
137.115 + }
137.116 + public int inflateEnd(){
137.117 + if(istate==null) return Z_STREAM_ERROR;
137.118 + int ret=istate.inflateEnd();
137.119 +// istate = null;
137.120 + return ret;
137.121 + }
137.122 +
137.123 + public int inflateSync(){
137.124 + if(istate == null)
137.125 + return Z_STREAM_ERROR;
137.126 + return istate.inflateSync();
137.127 + }
137.128 + public int inflateSyncPoint(){
137.129 + if(istate == null)
137.130 + return Z_STREAM_ERROR;
137.131 + return istate.inflateSyncPoint();
137.132 + }
137.133 + public int inflateSetDictionary(byte[] dictionary, int dictLength){
137.134 + if(istate == null)
137.135 + return Z_STREAM_ERROR;
137.136 + return istate.inflateSetDictionary(dictionary, dictLength);
137.137 + }
137.138 + public boolean inflateFinished(){
137.139 + return istate.mode==12 /*DONE*/;
137.140 + }
137.141 +
137.142 +
137.143 + public long getAdler(){
137.144 + return adler.getValue();
137.145 + }
137.146 +
137.147 + public void free(){
137.148 + next_in=null;
137.149 + next_out=null;
137.150 + msg=null;
137.151 + }
137.152 +
137.153 + public void setOutput(byte[] buf){
137.154 + setOutput(buf, 0, buf.length);
137.155 + }
137.156 +
137.157 + public void setOutput(byte[] buf, int off, int len){
137.158 + next_out = buf;
137.159 + next_out_index = off;
137.160 + avail_out = len;
137.161 + }
137.162 +
137.163 + public void setInput(byte[] buf){
137.164 + setInput(buf, 0, buf.length, false);
137.165 + }
137.166 +
137.167 + public void setInput(byte[] buf, boolean append){
137.168 + setInput(buf, 0, buf.length, append);
137.169 + }
137.170 +
137.171 + public void setInput(byte[] buf, int off, int len, boolean append){
137.172 + if(len<=0 && append && next_in!=null) return;
137.173 +
137.174 + if(avail_in>0 && append){
137.175 + byte[] tmp = new byte[avail_in+len];
137.176 + System.arraycopy(next_in, next_in_index, tmp, 0, avail_in);
137.177 + System.arraycopy(buf, off, tmp, avail_in, len);
137.178 + next_in=tmp;
137.179 + next_in_index=0;
137.180 + avail_in+=len;
137.181 + }
137.182 + else{
137.183 + next_in=buf;
137.184 + next_in_index=off;
137.185 + avail_in=len;
137.186 + }
137.187 + }
137.188 +
137.189 + public byte[] getNextIn(){
137.190 + return next_in;
137.191 + }
137.192 +
137.193 + public void setNextIn(byte[] next_in){
137.194 + this.next_in = next_in;
137.195 + }
137.196 +
137.197 + public int getNextInIndex(){
137.198 + return next_in_index;
137.199 + }
137.200 +
137.201 + public void setNextInIndex(int next_in_index){
137.202 + this.next_in_index = next_in_index;
137.203 + }
137.204 +
137.205 + public int getAvailIn(){
137.206 + return avail_in;
137.207 + }
137.208 +
137.209 + public void setAvailIn(int avail_in){
137.210 + this.avail_in = avail_in;
137.211 + }
137.212 +
137.213 + public byte[] getNextOut(){
137.214 + return next_out;
137.215 + }
137.216 +
137.217 + public void setNextOut(byte[] next_out){
137.218 + this.next_out = next_out;
137.219 + }
137.220 +
137.221 + public int getNextOutIndex(){
137.222 + return next_out_index;
137.223 + }
137.224 +
137.225 + public void setNextOutIndex(int next_out_index){
137.226 + this.next_out_index = next_out_index;
137.227 + }
137.228 +
137.229 + public int getAvailOut(){
137.230 + return avail_out;
137.231 +
137.232 + }
137.233 +
137.234 + public void setAvailOut(int avail_out){
137.235 + this.avail_out = avail_out;
137.236 + }
137.237 +
137.238 + public long getTotalOut(){
137.239 + return total_out;
137.240 + }
137.241 +
137.242 + public long getTotalIn(){
137.243 + return total_in;
137.244 + }
137.245 +
137.246 + public String getMessage(){
137.247 + return msg;
137.248 + }
137.249 +
137.250 + /**
137.251 + * Those methods are expected to be override by Inflater and Deflater.
137.252 + * In the future, they will become abstract methods.
137.253 + */
137.254 + public int end(){ return Z_OK; }
137.255 + public boolean finished(){ return false; }
137.256 +}
138.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
138.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/ZipConstants64.java Sun Feb 17 17:58:34 2013 +0100
138.3 @@ -0,0 +1,84 @@
138.4 +/*
138.5 + * Copyright (c) 1995, 1996, Oracle and/or its affiliates. All rights reserved.
138.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
138.7 + *
138.8 + * This code is free software; you can redistribute it and/or modify it
138.9 + * under the terms of the GNU General Public License version 2 only, as
138.10 + * published by the Free Software Foundation. Oracle designates this
138.11 + * particular file as subject to the "Classpath" exception as provided
138.12 + * by Oracle in the LICENSE file that accompanied this code.
138.13 + *
138.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
138.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
138.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
138.17 + * version 2 for more details (a copy is included in the LICENSE file that
138.18 + * accompanied this code).
138.19 + *
138.20 + * You should have received a copy of the GNU General Public License version
138.21 + * 2 along with this work; if not, write to the Free Software Foundation,
138.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
138.23 + *
138.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
138.25 + * or visit www.oracle.com if you need additional information or have any
138.26 + * questions.
138.27 + */
138.28 +
138.29 +package org.apidesign.bck2brwsr.emul.zip;
138.30 +
138.31 +/*
138.32 + * This class defines the constants that are used by the classes
138.33 + * which manipulate Zip64 files.
138.34 + */
138.35 +
138.36 +public class ZipConstants64 {
138.37 +
138.38 + /*
138.39 + * ZIP64 constants
138.40 + */
138.41 + static final long ZIP64_ENDSIG = 0x06064b50L; // "PK\006\006"
138.42 + static final long ZIP64_LOCSIG = 0x07064b50L; // "PK\006\007"
138.43 + static final int ZIP64_ENDHDR = 56; // ZIP64 end header size
138.44 + static final int ZIP64_LOCHDR = 20; // ZIP64 end loc header size
138.45 + static final int ZIP64_EXTHDR = 24; // EXT header size
138.46 + static final int ZIP64_EXTID = 0x0001; // Extra field Zip64 header ID
138.47 +
138.48 + static final int ZIP64_MAGICCOUNT = 0xFFFF;
138.49 + static final long ZIP64_MAGICVAL = 0xFFFFFFFFL;
138.50 +
138.51 + /*
138.52 + * Zip64 End of central directory (END) header field offsets
138.53 + */
138.54 + static final int ZIP64_ENDLEN = 4; // size of zip64 end of central dir
138.55 + static final int ZIP64_ENDVEM = 12; // version made by
138.56 + static final int ZIP64_ENDVER = 14; // version needed to extract
138.57 + static final int ZIP64_ENDNMD = 16; // number of this disk
138.58 + static final int ZIP64_ENDDSK = 20; // disk number of start
138.59 + static final int ZIP64_ENDTOD = 24; // total number of entries on this disk
138.60 + static final int ZIP64_ENDTOT = 32; // total number of entries
138.61 + static final int ZIP64_ENDSIZ = 40; // central directory size in bytes
138.62 + static final int ZIP64_ENDOFF = 48; // offset of first CEN header
138.63 + static final int ZIP64_ENDEXT = 56; // zip64 extensible data sector
138.64 +
138.65 + /*
138.66 + * Zip64 End of central directory locator field offsets
138.67 + */
138.68 + static final int ZIP64_LOCDSK = 4; // disk number start
138.69 + static final int ZIP64_LOCOFF = 8; // offset of zip64 end
138.70 + static final int ZIP64_LOCTOT = 16; // total number of disks
138.71 +
138.72 + /*
138.73 + * Zip64 Extra local (EXT) header field offsets
138.74 + */
138.75 + static final int ZIP64_EXTCRC = 4; // uncompressed file crc-32 value
138.76 + static final int ZIP64_EXTSIZ = 8; // compressed size, 8-byte
138.77 + static final int ZIP64_EXTLEN = 16; // uncompressed size, 8-byte
138.78 +
138.79 + /*
138.80 + * Language encoding flag EFS
138.81 + */
138.82 + static final int EFS = 0x800; // If this bit is set the filename and
138.83 + // comment fields for this file must be
138.84 + // encoded using UTF-8.
138.85 +
138.86 + private ZipConstants64() {}
138.87 +}
139.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
139.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/ZipInputStream.java Sun Feb 17 17:58:34 2013 +0100
139.3 @@ -0,0 +1,468 @@
139.4 +/*
139.5 + * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
139.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
139.7 + *
139.8 + * This code is free software; you can redistribute it and/or modify it
139.9 + * under the terms of the GNU General Public License version 2 only, as
139.10 + * published by the Free Software Foundation. Oracle designates this
139.11 + * particular file as subject to the "Classpath" exception as provided
139.12 + * by Oracle in the LICENSE file that accompanied this code.
139.13 + *
139.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
139.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
139.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
139.17 + * version 2 for more details (a copy is included in the LICENSE file that
139.18 + * accompanied this code).
139.19 + *
139.20 + * You should have received a copy of the GNU General Public License version
139.21 + * 2 along with this work; if not, write to the Free Software Foundation,
139.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
139.23 + *
139.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
139.25 + * or visit www.oracle.com if you need additional information or have any
139.26 + * questions.
139.27 + */
139.28 +
139.29 +package org.apidesign.bck2brwsr.emul.zip;
139.30 +
139.31 +import java.util.zip.*;
139.32 +import java.io.InputStream;
139.33 +import java.io.IOException;
139.34 +import java.io.EOFException;
139.35 +import java.io.PushbackInputStream;
139.36 +import static org.apidesign.bck2brwsr.emul.zip.ZipConstants64.*;
139.37 +import static java.util.zip.ZipInputStream.*;
139.38 +
139.39 +/**
139.40 + * This class implements an input stream filter for reading files in the
139.41 + * ZIP file format. Includes support for both compressed and uncompressed
139.42 + * entries.
139.43 + *
139.44 + * @author David Connelly
139.45 + */
139.46 +public
139.47 +class ZipInputStream extends InflaterInputStream {
139.48 + private ZipEntry entry;
139.49 + private int flag;
139.50 + private CRC32 crc = new CRC32();
139.51 + private long remaining;
139.52 + private byte[] tmpbuf = new byte[512];
139.53 +
139.54 + private static final int STORED = ZipEntry.STORED;
139.55 + private static final int DEFLATED = ZipEntry.DEFLATED;
139.56 +
139.57 + private boolean closed = false;
139.58 + // this flag is set to true after EOF has reached for
139.59 + // one entry
139.60 + private boolean entryEOF = false;
139.61 +
139.62 + /**
139.63 + * Check to make sure that this stream has not been closed
139.64 + */
139.65 + private void ensureOpen() throws IOException {
139.66 + if (closed) {
139.67 + throw new IOException("Stream closed");
139.68 + }
139.69 + }
139.70 +
139.71 + /**
139.72 + * Creates a new ZIP input stream.
139.73 + *
139.74 + * <p>The UTF-8 {@link java.nio.charset.Charset charset} is used to
139.75 + * decode the entry names.
139.76 + *
139.77 + * @param in the actual input stream
139.78 + */
139.79 + public ZipInputStream(InputStream in) {
139.80 +// this(in, "UTF-8");
139.81 + super(new PushbackInputStream(in, 512), new Inflater(true), 512);
139.82 + //usesDefaultInflater = true;
139.83 + if(in == null) {
139.84 + throw new NullPointerException("in is null");
139.85 + }
139.86 + }
139.87 +
139.88 + /**
139.89 + * Creates a new ZIP input stream.
139.90 + *
139.91 + * @param in the actual input stream
139.92 + *
139.93 + * @param charset
139.94 + * The {@linkplain java.nio.charset.Charset charset} to be
139.95 + * used to decode the ZIP entry name (ignored if the
139.96 + * <a href="package-summary.html#lang_encoding"> language
139.97 + * encoding bit</a> of the ZIP entry's general purpose bit
139.98 + * flag is set).
139.99 + *
139.100 + * @since 1.7
139.101 + *
139.102 + public ZipInputStream(InputStream in, Charset charset) {
139.103 + super(new PushbackInputStream(in, 512), new Inflater(true), 512);
139.104 + usesDefaultInflater = true;
139.105 + if(in == null) {
139.106 + throw new NullPointerException("in is null");
139.107 + }
139.108 + if (charset == null)
139.109 + throw new NullPointerException("charset is null");
139.110 + this.zc = ZipCoder.get(charset);
139.111 + }
139.112 + */
139.113 +
139.114 + /**
139.115 + * Reads the next ZIP file entry and positions the stream at the
139.116 + * beginning of the entry data.
139.117 + * @return the next ZIP file entry, or null if there are no more entries
139.118 + * @exception ZipException if a ZIP file error has occurred
139.119 + * @exception IOException if an I/O error has occurred
139.120 + */
139.121 + public ZipEntry getNextEntry() throws IOException {
139.122 + ensureOpen();
139.123 + if (entry != null) {
139.124 + closeEntry();
139.125 + }
139.126 + crc.reset();
139.127 + inf.reset();
139.128 + if ((entry = readLOC()) == null) {
139.129 + return null;
139.130 + }
139.131 + if (entry.getMethod() == STORED) {
139.132 + remaining = entry.getSize();
139.133 + }
139.134 + entryEOF = false;
139.135 + return entry;
139.136 + }
139.137 +
139.138 + /**
139.139 + * Closes the current ZIP entry and positions the stream for reading the
139.140 + * next entry.
139.141 + * @exception ZipException if a ZIP file error has occurred
139.142 + * @exception IOException if an I/O error has occurred
139.143 + */
139.144 + public void closeEntry() throws IOException {
139.145 + ensureOpen();
139.146 + while (read(tmpbuf, 0, tmpbuf.length) != -1) ;
139.147 + entryEOF = true;
139.148 + }
139.149 +
139.150 + /**
139.151 + * Returns 0 after EOF has reached for the current entry data,
139.152 + * otherwise always return 1.
139.153 + * <p>
139.154 + * Programs should not count on this method to return the actual number
139.155 + * of bytes that could be read without blocking.
139.156 + *
139.157 + * @return 1 before EOF and 0 after EOF has reached for current entry.
139.158 + * @exception IOException if an I/O error occurs.
139.159 + *
139.160 + */
139.161 + public int available() throws IOException {
139.162 + ensureOpen();
139.163 + if (entryEOF) {
139.164 + return 0;
139.165 + } else {
139.166 + return 1;
139.167 + }
139.168 + }
139.169 +
139.170 + /**
139.171 + * Reads from the current ZIP entry into an array of bytes.
139.172 + * If <code>len</code> is not zero, the method
139.173 + * blocks until some input is available; otherwise, no
139.174 + * bytes are read and <code>0</code> is returned.
139.175 + * @param b the buffer into which the data is read
139.176 + * @param off the start offset in the destination array <code>b</code>
139.177 + * @param len the maximum number of bytes read
139.178 + * @return the actual number of bytes read, or -1 if the end of the
139.179 + * entry is reached
139.180 + * @exception NullPointerException if <code>b</code> is <code>null</code>.
139.181 + * @exception IndexOutOfBoundsException if <code>off</code> is negative,
139.182 + * <code>len</code> is negative, or <code>len</code> is greater than
139.183 + * <code>b.length - off</code>
139.184 + * @exception ZipException if a ZIP file error has occurred
139.185 + * @exception IOException if an I/O error has occurred
139.186 + */
139.187 + public int read(byte[] b, int off, int len) throws IOException {
139.188 + ensureOpen();
139.189 + if (off < 0 || len < 0 || off > b.length - len) {
139.190 + throw new IndexOutOfBoundsException();
139.191 + } else if (len == 0) {
139.192 + return 0;
139.193 + }
139.194 +
139.195 + if (entry == null) {
139.196 + return -1;
139.197 + }
139.198 + switch (entry.getMethod()) {
139.199 + case DEFLATED:
139.200 + len = super.read(b, off, len);
139.201 + if (len == -1) {
139.202 + readEnd(entry);
139.203 + entryEOF = true;
139.204 + entry = null;
139.205 + } else {
139.206 + crc.update(b, off, len);
139.207 + }
139.208 + return len;
139.209 + case STORED:
139.210 + if (remaining <= 0) {
139.211 + entryEOF = true;
139.212 + entry = null;
139.213 + return -1;
139.214 + }
139.215 + if (len > remaining) {
139.216 + len = (int)remaining;
139.217 + }
139.218 + len = in.read(b, off, len);
139.219 + if (len == -1) {
139.220 + throw new ZipException("unexpected EOF");
139.221 + }
139.222 + crc.update(b, off, len);
139.223 + remaining -= len;
139.224 + if (remaining == 0 && entry.getCrc() != crc.getValue()) {
139.225 + throw new ZipException(
139.226 + "invalid entry CRC (expected 0x" + Long.toHexString(entry.getCrc()) +
139.227 + " but got 0x" + Long.toHexString(crc.getValue()) + ")");
139.228 + }
139.229 + return len;
139.230 + default:
139.231 + throw new ZipException("invalid compression method");
139.232 + }
139.233 + }
139.234 +
139.235 + /**
139.236 + * Skips specified number of bytes in the current ZIP entry.
139.237 + * @param n the number of bytes to skip
139.238 + * @return the actual number of bytes skipped
139.239 + * @exception ZipException if a ZIP file error has occurred
139.240 + * @exception IOException if an I/O error has occurred
139.241 + * @exception IllegalArgumentException if n < 0
139.242 + */
139.243 + public long skip(long n) throws IOException {
139.244 + if (n < 0) {
139.245 + throw new IllegalArgumentException("negative skip length");
139.246 + }
139.247 + ensureOpen();
139.248 + int max = (int)Math.min(n, Integer.MAX_VALUE);
139.249 + int total = 0;
139.250 + while (total < max) {
139.251 + int len = max - total;
139.252 + if (len > tmpbuf.length) {
139.253 + len = tmpbuf.length;
139.254 + }
139.255 + len = read(tmpbuf, 0, len);
139.256 + if (len == -1) {
139.257 + entryEOF = true;
139.258 + break;
139.259 + }
139.260 + total += len;
139.261 + }
139.262 + return total;
139.263 + }
139.264 +
139.265 + /**
139.266 + * Closes this input stream and releases any system resources associated
139.267 + * with the stream.
139.268 + * @exception IOException if an I/O error has occurred
139.269 + */
139.270 + public void close() throws IOException {
139.271 + if (!closed) {
139.272 + super.close();
139.273 + closed = true;
139.274 + }
139.275 + }
139.276 +
139.277 + private byte[] b = new byte[256];
139.278 +
139.279 + /*
139.280 + * Reads local file (LOC) header for next entry.
139.281 + */
139.282 + private ZipEntry readLOC() throws IOException {
139.283 + try {
139.284 + readFully(tmpbuf, 0, LOCHDR);
139.285 + } catch (EOFException e) {
139.286 + return null;
139.287 + }
139.288 + if (get32(tmpbuf, 0) != LOCSIG) {
139.289 + return null;
139.290 + }
139.291 + // get flag first, we need check EFS.
139.292 + flag = get16(tmpbuf, LOCFLG);
139.293 + // get the entry name and create the ZipEntry first
139.294 + int len = get16(tmpbuf, LOCNAM);
139.295 + int blen = b.length;
139.296 + if (len > blen) {
139.297 + do
139.298 + blen = blen * 2;
139.299 + while (len > blen);
139.300 + b = new byte[blen];
139.301 + }
139.302 + readFully(b, 0, len);
139.303 + // Force to use UTF-8 if the EFS bit is ON, even the cs is NOT UTF-8
139.304 + ZipEntry e = createZipEntry(((flag & EFS) != 0)
139.305 + ? toStringUTF8(b, len)
139.306 + : toString(b, len));
139.307 + // now get the remaining fields for the entry
139.308 + if ((flag & 1) == 1) {
139.309 + throw new ZipException("encrypted ZIP entry not supported");
139.310 + }
139.311 + e.setMethod(get16(tmpbuf, LOCHOW));
139.312 + e.setTime(get32(tmpbuf, LOCTIM));
139.313 + if ((flag & 8) == 8) {
139.314 + /* "Data Descriptor" present */
139.315 + if (e.getMethod() != DEFLATED) {
139.316 + throw new ZipException(
139.317 + "only DEFLATED entries can have EXT descriptor");
139.318 + }
139.319 + } else {
139.320 + e.setCrc(get32(tmpbuf, LOCCRC));
139.321 + e.setCompressedSize(get32(tmpbuf, LOCSIZ));
139.322 + e.setSize(get32(tmpbuf, LOCLEN));
139.323 + }
139.324 + len = get16(tmpbuf, LOCEXT);
139.325 + if (len > 0) {
139.326 + byte[] bb = new byte[len];
139.327 + readFully(bb, 0, len);
139.328 + e.setExtra(bb);
139.329 + // extra fields are in "HeaderID(2)DataSize(2)Data... format
139.330 + if (e.getCompressedSize() == ZIP64_MAGICVAL || e.getCompressedSize() == ZIP64_MAGICVAL) {
139.331 + int off = 0;
139.332 + while (off + 4 < len) {
139.333 + int sz = get16(bb, off + 2);
139.334 + if (get16(bb, off) == ZIP64_EXTID) {
139.335 + off += 4;
139.336 + // LOC extra zip64 entry MUST include BOTH original and
139.337 + // compressed file size fields
139.338 + if (sz < 16 || (off + sz) > len ) {
139.339 + // Invalid zip64 extra fields, simply skip. Even it's
139.340 + // rare, it's possible the entry size happens to be
139.341 + // the magic value and it "accidnetly" has some bytes
139.342 + // in extra match the id.
139.343 + return e;
139.344 + }
139.345 + e.setSize(get64(bb, off));
139.346 + e.setCompressedSize(get64(bb, off + 8));
139.347 + break;
139.348 + }
139.349 + off += (sz + 4);
139.350 + }
139.351 + }
139.352 + }
139.353 + return e;
139.354 + }
139.355 +
139.356 + /**
139.357 + * Creates a new <code>ZipEntry</code> object for the specified
139.358 + * entry name.
139.359 + *
139.360 + * @param name the ZIP file entry name
139.361 + * @return the ZipEntry just created
139.362 + */
139.363 + protected ZipEntry createZipEntry(String name) {
139.364 + return new ZipEntry(name);
139.365 + }
139.366 +
139.367 + /*
139.368 + * Reads end of deflated entry as well as EXT descriptor if present.
139.369 + */
139.370 + private void readEnd(ZipEntry e) throws IOException {
139.371 + int n = inf.getRemaining();
139.372 + if (n > 0) {
139.373 + ((PushbackInputStream)in).unread(buf, len - n, n);
139.374 + }
139.375 + if ((flag & 8) == 8) {
139.376 + /* "Data Descriptor" present */
139.377 + if (inf.getBytesWritten() > ZIP64_MAGICVAL ||
139.378 + inf.getBytesRead() > ZIP64_MAGICVAL) {
139.379 + // ZIP64 format
139.380 + readFully(tmpbuf, 0, ZIP64_EXTHDR);
139.381 + long sig = get32(tmpbuf, 0);
139.382 + if (sig != EXTSIG) { // no EXTSIG present
139.383 + e.setCrc(sig);
139.384 + e.setCompressedSize(get64(tmpbuf, ZIP64_EXTSIZ - ZIP64_EXTCRC));
139.385 + e.setSize(get64(tmpbuf, ZIP64_EXTLEN - ZIP64_EXTCRC));
139.386 + ((PushbackInputStream)in).unread(
139.387 + tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC - 1, ZIP64_EXTCRC);
139.388 + } else {
139.389 + e.setCrc(get32(tmpbuf, ZIP64_EXTCRC));
139.390 + e.setCompressedSize(get64(tmpbuf, ZIP64_EXTSIZ));
139.391 + e.setSize(get64(tmpbuf, ZIP64_EXTLEN));
139.392 + }
139.393 + } else {
139.394 + readFully(tmpbuf, 0, EXTHDR);
139.395 + long sig = get32(tmpbuf, 0);
139.396 + if (sig != EXTSIG) { // no EXTSIG present
139.397 + e.setCrc(sig);
139.398 + e.setCompressedSize(get32(tmpbuf, EXTSIZ - EXTCRC));
139.399 + e.setSize(get32(tmpbuf, EXTLEN - EXTCRC));
139.400 + ((PushbackInputStream)in).unread(
139.401 + tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC);
139.402 + } else {
139.403 + e.setCrc(get32(tmpbuf, EXTCRC));
139.404 + e.setCompressedSize(get32(tmpbuf, EXTSIZ));
139.405 + e.setSize(get32(tmpbuf, EXTLEN));
139.406 + }
139.407 + }
139.408 + }
139.409 + if (e.getSize() != inf.getBytesWritten()) {
139.410 + throw new ZipException(
139.411 + "invalid entry size (expected " + e.getSize() +
139.412 + " but got " + inf.getBytesWritten() + " bytes)");
139.413 + }
139.414 + if (e.getCompressedSize() != inf.getBytesRead()) {
139.415 + throw new ZipException(
139.416 + "invalid entry compressed size (expected " + e.getCompressedSize() +
139.417 + " but got " + inf.getBytesRead() + " bytes)");
139.418 + }
139.419 + if (e.getCrc() != crc.getValue()) {
139.420 + throw new ZipException(
139.421 + "invalid entry CRC (expected 0x" + Long.toHexString(e.getCrc()) +
139.422 + " but got 0x" + Long.toHexString(crc.getValue()) + ")");
139.423 + }
139.424 + }
139.425 +
139.426 + /*
139.427 + * Reads bytes, blocking until all bytes are read.
139.428 + */
139.429 + private void readFully(byte[] b, int off, int len) throws IOException {
139.430 + while (len > 0) {
139.431 + int n = in.read(b, off, len);
139.432 + if (n == -1) {
139.433 + throw new EOFException();
139.434 + }
139.435 + off += n;
139.436 + len -= n;
139.437 + }
139.438 + }
139.439 +
139.440 + /*
139.441 + * Fetches unsigned 16-bit value from byte array at specified offset.
139.442 + * The bytes are assumed to be in Intel (little-endian) byte order.
139.443 + */
139.444 + private static final int get16(byte b[], int off) {
139.445 + return (b[off] & 0xff) | ((b[off+1] & 0xff) << 8);
139.446 + }
139.447 +
139.448 + /*
139.449 + * Fetches unsigned 32-bit value from byte array at specified offset.
139.450 + * The bytes are assumed to be in Intel (little-endian) byte order.
139.451 + */
139.452 + private static final long get32(byte b[], int off) {
139.453 + return (get16(b, off) | ((long)get16(b, off+2) << 16)) & 0xffffffffL;
139.454 + }
139.455 +
139.456 + /*
139.457 + * Fetches signed 64-bit value from byte array at specified offset.
139.458 + * The bytes are assumed to be in Intel (little-endian) byte order.
139.459 + */
139.460 + private static final long get64(byte b[], int off) {
139.461 + return get32(b, off) | (get32(b, off+4) << 32);
139.462 + }
139.463 +
139.464 + private static String toStringUTF8(byte[] arr, int len) {
139.465 + return new String(arr, 0, len);
139.466 + }
139.467 +
139.468 + private static String toString(byte[] b, int len) {
139.469 + return new String(b, 0, len);
139.470 + }
139.471 +}
140.1 --- a/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js Fri Jan 25 15:08:24 2013 +0100
140.2 +++ b/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js Sun Feb 17 17:58:34 2013 +0100
140.3 @@ -4,6 +4,517 @@
140.4 Number.prototype.mul32 = function(x) {
140.5 return (((this * (x >> 16)) << 16) + this * (x & 0xFFFF)) | 0;
140.6 };
140.7 +Number.prototype.neg32 = function() { return (-this) | 0; };
140.8
140.9 Number.prototype.toInt8 = function() { return (this << 24) >> 24; };
140.10 -Number.prototype.toInt16 = function() { return (this << 16) >> 16; };
140.11 \ No newline at end of file
140.12 +Number.prototype.toInt16 = function() { return (this << 16) >> 16; };
140.13 +
140.14 +var __m32 = 0xFFFFFFFF;
140.15 +
140.16 +Number.prototype.next32 = function(low) {
140.17 + if (this === 0) {
140.18 + return low;
140.19 + }
140.20 + var l = new Number(low);
140.21 + l.hi = this | 0;
140.22 + return l;
140.23 +};
140.24 +
140.25 +Number.prototype.high32 = function() {
140.26 + return this.hi ? this.hi : (Math.floor(this / (__m32+1))) | 0;
140.27 +};
140.28 +Number.prototype.toInt32 = function() { return this | 0; };
140.29 +Number.prototype.toFP = function() {
140.30 + return this.hi ? this.hi * (__m32+1) + this : this;
140.31 +};
140.32 +Number.prototype.toLong = function() {
140.33 + var hi = (this > __m32) ? (Math.floor(this / (__m32+1))) | 0 : 0;
140.34 + return hi.next32(Math.floor(this % (__m32+1)));
140.35 +};
140.36 +
140.37 +Number.prototype.toExactString = function() {
140.38 + if (this.hi) {
140.39 + // check for Long.MIN_VALUE
140.40 + if ((this.hi == (0x80000000 | 0)) && (this == 0)) {
140.41 + return '-9223372036854775808';
140.42 + }
140.43 + var res = 0;
140.44 + var a = [ 6,9,2,7,6,9,4,9,2,4 ];
140.45 + var s = '';
140.46 + var digit;
140.47 + var neg = this.hi < 0;
140.48 + if (neg) {
140.49 + var x = this.neg64();
140.50 + var hi = x.hi;
140.51 + var low = x;
140.52 + } else {
140.53 + var hi = this.hi;
140.54 + var low = this;
140.55 + }
140.56 + for (var i = 0; i < a.length; i++) {
140.57 + res += hi * a[i];
140.58 + var low_digit = low % 10;
140.59 + digit = (res % 10) + low_digit;
140.60 +
140.61 + low = Math.floor(low / 10);
140.62 + res = Math.floor(res / 10);
140.63 +
140.64 + if (digit >= 10) {
140.65 + digit -= 10;
140.66 + res++;
140.67 + }
140.68 + s = String(digit).concat(s);
140.69 + }
140.70 + s = String(res).concat(s).replace(/^0+/, '');
140.71 + return (neg ? '-' : '').concat(s);
140.72 + }
140.73 + return String(this);
140.74 +};
140.75 +
140.76 +Number.prototype.add64 = function(x) {
140.77 + var low = this + x;
140.78 + carry = 0;
140.79 + if (low > __m32) {
140.80 + carry = 1;
140.81 + low -= (__m32+1);
140.82 + }
140.83 + var hi = (this.high32() + x.high32() + carry) | 0;
140.84 + return hi.next32(low);
140.85 +};
140.86 +
140.87 +Number.prototype.sub64 = function(x) {
140.88 + var low = this - x;
140.89 + carry = 0;
140.90 + if (low < 0) {
140.91 + carry = 1;
140.92 + low += (__m32+1);
140.93 + }
140.94 + var hi = (this.high32() - x.high32() - carry) | 0;
140.95 + return hi.next32(low);
140.96 +};
140.97 +
140.98 +Number.prototype.mul64 = function(x) {
140.99 + var low = this.mul32(x);
140.100 + low += (low < 0) ? (__m32+1) : 0;
140.101 + // first count upper 32 bits of (this.low * x.low)
140.102 + var hi_hi = 0;
140.103 + var hi_low = 0;
140.104 + var m = 1;
140.105 + for (var i = 0; i < 32; i++) {
140.106 + if (x & m) {
140.107 + hi_hi += this >>> 16;
140.108 + hi_low += this & 0xFFFF
140.109 + }
140.110 + hi_low >>= 1;
140.111 + hi_low += (hi_hi & 1) ? 0x8000 : 0;
140.112 + hi_hi >>= 1;
140.113 + m <<= 1;
140.114 + }
140.115 + var hi = (hi_hi << 16) + hi_low;
140.116 +
140.117 + var m1 = this.high32().mul32(x);
140.118 + var m2 = this.mul32(x.high32());
140.119 + hi = hi.add32(m1).add32(m2);
140.120 +
140.121 + return hi.next32(low);
140.122 +};
140.123 +
140.124 +Number.prototype.and64 = function(x) {
140.125 + var low = this & x;
140.126 + low += (low < 0) ? (__m32+1) : 0;
140.127 + if (this.hi && x.hi) {
140.128 + var hi = this.hi & x.hi;
140.129 + return hi.next32(low);
140.130 + };
140.131 + return low;
140.132 +};
140.133 +
140.134 +Number.prototype.or64 = function(x) {
140.135 + var low = this | x;
140.136 + low += (low < 0) ? (__m32+1) : 0;
140.137 + if (this.hi || x.hi) {
140.138 + var hi = this.hi | x.hi;
140.139 + return hi.next32(low);
140.140 + };
140.141 + return low;
140.142 +};
140.143 +
140.144 +Number.prototype.xor64 = function(x) {
140.145 + var low = this ^ x;
140.146 + low += (low < 0) ? (__m32+1) : 0;
140.147 + if (this.hi || x.hi) {
140.148 + var hi = this.hi ^ x.hi;
140.149 + return hi.next32(low);
140.150 + };
140.151 + return low;
140.152 +};
140.153 +
140.154 +Number.prototype.shl64 = function(x) {
140.155 + if (x >= 32) {
140.156 + var hi = this << (x - 32);
140.157 + return hi.next32(0);
140.158 + } else {
140.159 + var hi = this.high32() << x;
140.160 + var low_reminder = this >> (32 - x);
140.161 + hi |= low_reminder;
140.162 + var low = this << x;
140.163 + low += (low < 0) ? (__m32+1) : 0;
140.164 + return hi.next32(low);
140.165 + }
140.166 +};
140.167 +
140.168 +Number.prototype.shr64 = function(x) {
140.169 + if (x >= 32) {
140.170 + var low = this.high32() >> (x - 32);
140.171 + low += (low < 0) ? (__m32+1) : 0;
140.172 + return low;
140.173 + } else {
140.174 + var low = this >> x;
140.175 + var hi_reminder = this.high32() << (32 - x);
140.176 + low |= hi_reminder;
140.177 + low += (low < 0) ? (__m32+1) : 0;
140.178 + var hi = this.high32() >> x;
140.179 + return hi.next32(low);
140.180 + }
140.181 +};
140.182 +
140.183 +Number.prototype.ushr64 = function(x) {
140.184 + if (x >= 32) {
140.185 + var low = this.high32() >>> (x - 32);
140.186 + low += (low < 0) ? (__m32+1) : 0;
140.187 + return low;
140.188 + } else {
140.189 + var low = this >>> x;
140.190 + var hi_reminder = this.high32() << (32 - x);
140.191 + low |= hi_reminder;
140.192 + low += (low < 0) ? (__m32+1) : 0;
140.193 + var hi = this.high32() >>> x;
140.194 + return hi.next32(low);
140.195 + }
140.196 +};
140.197 +
140.198 +Number.prototype.compare64 = function(x) {
140.199 + if (this.high32() === x.high32()) {
140.200 + return (this < x) ? -1 : ((this > x) ? 1 : 0);
140.201 + }
140.202 + return (this.high32() < x.high32()) ? -1 : 1;
140.203 +};
140.204 +
140.205 +Number.prototype.neg64 = function() {
140.206 + var hi = this.high32();
140.207 + var low = this;
140.208 + if ((hi === 0) && (low < 0)) { return -low; }
140.209 + hi = ~hi;
140.210 + low = ~low;
140.211 + low += (low < 0) ? (__m32+1) : 0;
140.212 + var ret = hi.next32(low);
140.213 + return ret.add64(1);
140.214 +};
140.215 +
140.216 +(function(numberPrototype) {
140.217 + function __Int64(hi32, lo32) {
140.218 + this.hi32 = hi32 | 0;
140.219 + this.lo32 = lo32 | 0;
140.220 +
140.221 + this.get32 = function(bitIndex) {
140.222 + var v0;
140.223 + var v1;
140.224 + bitIndex += 32;
140.225 + var selector = bitIndex >>> 5;
140.226 + switch (selector) {
140.227 + case 0:
140.228 + v0 = 0;
140.229 + v1 = this.lo32;
140.230 + break;
140.231 + case 1:
140.232 + v0 = this.lo32;
140.233 + v1 = this.hi32;
140.234 + break;
140.235 + case 2:
140.236 + v0 = this.hi32;
140.237 + v1 = 0;
140.238 + break
140.239 + default:
140.240 + return 0;
140.241 + }
140.242 +
140.243 + var shift = bitIndex & 31;
140.244 + if (shift === 0) {
140.245 + return v0;
140.246 + }
140.247 +
140.248 + return (v1 << (32 - shift)) | (v0 >>> shift);
140.249 + }
140.250 +
140.251 + this.get16 = function(bitIndex) {
140.252 + return this.get32(bitIndex) & 0xffff;
140.253 + }
140.254 +
140.255 + this.set16 = function(bitIndex, value) {
140.256 + bitIndex += 32;
140.257 + var shift = bitIndex & 15;
140.258 + var svalue = (value & 0xffff) << shift;
140.259 + var smask = 0xffff << shift;
140.260 + var selector = bitIndex >>> 4;
140.261 + switch (selector) {
140.262 + case 0:
140.263 + break;
140.264 + case 1:
140.265 + this.lo32 = (this.lo32 & ~(smask >>> 16))
140.266 + | (svalue >>> 16);
140.267 + break;
140.268 + case 2:
140.269 + this.lo32 = (this.lo32 & ~smask) | svalue;
140.270 + break;
140.271 + case 3:
140.272 + this.lo32 = (this.lo32 & ~(smask << 16))
140.273 + | (svalue << 16);
140.274 + this.hi32 = (this.hi32 & ~(smask >>> 16))
140.275 + | (svalue >>> 16);
140.276 + break;
140.277 + case 4:
140.278 + this.hi32 = (this.hi32 & ~smask) | svalue;
140.279 + break;
140.280 + case 5:
140.281 + this.hi32 = (this.hi32 & ~(smask << 16))
140.282 + | (svalue << 16);
140.283 + break;
140.284 + }
140.285 + }
140.286 +
140.287 + this.getDigit = function(index, shift) {
140.288 + return this.get16((index << 4) - shift);
140.289 + }
140.290 +
140.291 + this.getTwoDigits = function(index, shift) {
140.292 + return this.get32(((index - 1) << 4) - shift);
140.293 + }
140.294 +
140.295 + this.setDigit = function(index, shift, value) {
140.296 + this.set16((index << 4) - shift, value);
140.297 + }
140.298 +
140.299 + this.countSignificantDigits = function() {
140.300 + var sd;
140.301 + var remaining;
140.302 +
140.303 + if (this.hi32 === 0) {
140.304 + if (this.lo32 === 0) {
140.305 + return 0;
140.306 + }
140.307 +
140.308 + sd = 2;
140.309 + remaining = this.lo32;
140.310 + } else {
140.311 + sd = 4;
140.312 + remaining = this.hi32;
140.313 + }
140.314 +
140.315 + if (remaining < 0) {
140.316 + return sd;
140.317 + }
140.318 +
140.319 + return (remaining < 65536) ? sd - 1 : sd;
140.320 + }
140.321 +
140.322 + this.toNumber = function() {
140.323 + var lo32 = this.lo32;
140.324 + if (lo32 < 0) {
140.325 + lo32 += 0x100000000;
140.326 + }
140.327 +
140.328 + return this.hi32.next32(lo32);
140.329 + }
140.330 + }
140.331 +
140.332 + function __countLeadingZeroes16(number) {
140.333 + var nlz = 0;
140.334 +
140.335 + if (number < 256) {
140.336 + nlz += 8;
140.337 + number <<= 8;
140.338 + }
140.339 +
140.340 + if (number < 4096) {
140.341 + nlz += 4;
140.342 + number <<= 4;
140.343 + }
140.344 +
140.345 + if (number < 16384) {
140.346 + nlz += 2;
140.347 + number <<= 2;
140.348 + }
140.349 +
140.350 + return (number < 32768) ? nlz + 1 : nlz;
140.351 + }
140.352 +
140.353 + // q = u / v; r = u - q * v;
140.354 + // v != 0
140.355 + function __div64(q, r, u, v) {
140.356 + var m = u.countSignificantDigits();
140.357 + var n = v.countSignificantDigits();
140.358 +
140.359 + q.hi32 = q.lo32 = 0;
140.360 +
140.361 + if (n === 1) {
140.362 + // v has single digit
140.363 + var vd = v.getDigit(0, 0);
140.364 + var carry = 0;
140.365 + for (var i = m - 1; i >= 0; --i) {
140.366 + var ui = (carry << 16) | u.getDigit(i, 0);
140.367 + if (ui < 0) {
140.368 + ui += 0x100000000;
140.369 + }
140.370 + var qi = (ui / vd) | 0;
140.371 + q.setDigit(i, 0, qi);
140.372 + carry = ui - qi * vd;
140.373 + }
140.374 +
140.375 + r.hi32 = 0;
140.376 + r.lo32 = carry;
140.377 + return;
140.378 + }
140.379 +
140.380 + r.hi32 = u.hi32;
140.381 + r.lo32 = u.lo32;
140.382 +
140.383 + if (m < n) {
140.384 + return;
140.385 + }
140.386 +
140.387 + // Normalize
140.388 + var nrm = __countLeadingZeroes16(v.getDigit(n - 1, 0));
140.389 +
140.390 + var vd1 = v.getDigit(n - 1, nrm);
140.391 + var vd0 = v.getDigit(n - 2, nrm);
140.392 + for (var j = m - n; j >= 0; --j) {
140.393 + // Calculate qj estimate
140.394 + var ud21 = r.getTwoDigits(j + n, nrm);
140.395 + var ud2 = ud21 >>> 16;
140.396 + if (ud21 < 0) {
140.397 + ud21 += 0x100000000;
140.398 + }
140.399 +
140.400 + var qest = (ud2 === vd1) ? 0xFFFF : ((ud21 / vd1) | 0);
140.401 + var rest = ud21 - qest * vd1;
140.402 +
140.403 + // 0 <= (qest - qj) <= 2
140.404 +
140.405 + // Refine qj estimate
140.406 + var ud0 = r.getDigit(j + n - 2, nrm);
140.407 + while ((qest * vd0) > ((rest * 0x10000) + ud0)) {
140.408 + --qest;
140.409 + rest += vd1;
140.410 + }
140.411 +
140.412 + // 0 <= (qest - qj) <= 1
140.413 +
140.414 + // Multiply and subtract
140.415 + var carry = 0;
140.416 + for (var i = 0; i < n; ++i) {
140.417 + var vi = qest * v.getDigit(i, nrm);
140.418 + var ui = r.getDigit(i + j, nrm) - carry - (vi & 0xffff);
140.419 + r.setDigit(i + j, nrm, ui);
140.420 + carry = (vi >>> 16) - (ui >> 16);
140.421 + }
140.422 + var uj = ud2 - carry;
140.423 +
140.424 + if (uj < 0) {
140.425 + // qest - qj = 1
140.426 +
140.427 + // Add back
140.428 + --qest;
140.429 + var carry = 0;
140.430 + for (var i = 0; i < n; ++i) {
140.431 + var ui = r.getDigit(i + j, nrm) + v.getDigit(i, nrm)
140.432 + + carry;
140.433 + r.setDigit(i + j, nrm, ui);
140.434 + carry = ui >> 16;
140.435 + }
140.436 + uj += carry;
140.437 + }
140.438 +
140.439 + q.setDigit(j, 0, qest);
140.440 + r.setDigit(j + n, nrm, uj);
140.441 + }
140.442 + }
140.443 +
140.444 + numberPrototype.div64 = function(x) {
140.445 + var negateResult = false;
140.446 + var u, v;
140.447 +
140.448 + if ((this.high32() & 0x80000000) != 0) {
140.449 + u = this.neg64();
140.450 + negateResult = !negateResult;
140.451 + } else {
140.452 + u = this;
140.453 + }
140.454 +
140.455 + if ((x.high32() & 0x80000000) != 0) {
140.456 + v = x.neg64();
140.457 + negateResult = !negateResult;
140.458 + } else {
140.459 + v = x;
140.460 + }
140.461 +
140.462 + if ((v === 0) && (v.high32() === 0)) {
140.463 + // TODO: throw
140.464 + }
140.465 +
140.466 + if (u.high32() === 0) {
140.467 + if (v.high32() === 0) {
140.468 + var result = (u / v) | 0;
140.469 + return negateResult ? result.neg64() : result;
140.470 + }
140.471 +
140.472 + return 0;
140.473 + }
140.474 +
140.475 + var u64 = new __Int64(u.high32(), u);
140.476 + var v64 = new __Int64(v.high32(), v);
140.477 + var q64 = new __Int64(0, 0);
140.478 + var r64 = new __Int64(0, 0);
140.479 +
140.480 + __div64(q64, r64, u64, v64);
140.481 +
140.482 + var result = q64.toNumber();
140.483 + return negateResult ? result.neg64() : result;
140.484 + }
140.485 +
140.486 + numberPrototype.mod64 = function(x) {
140.487 + var negateResult = false;
140.488 + var u, v;
140.489 +
140.490 + if ((this.high32() & 0x80000000) != 0) {
140.491 + u = this.neg64();
140.492 + negateResult = !negateResult;
140.493 + } else {
140.494 + u = this;
140.495 + }
140.496 +
140.497 + if ((x.high32() & 0x80000000) != 0) {
140.498 + v = x.neg64();
140.499 + } else {
140.500 + v = x;
140.501 + }
140.502 +
140.503 + if ((v === 0) && (v.high32() === 0)) {
140.504 + // TODO: throw
140.505 + }
140.506 +
140.507 + if (u.high32() === 0) {
140.508 + var result = (v.high32() === 0) ? (u % v) : u;
140.509 + return negateResult ? result.neg64() : result;
140.510 + }
140.511 +
140.512 + var u64 = new __Int64(u.high32(), u);
140.513 + var v64 = new __Int64(v.high32(), v);
140.514 + var q64 = new __Int64(0, 0);
140.515 + var r64 = new __Int64(0, 0);
140.516 +
140.517 + __div64(q64, r64, u64, v64);
140.518 +
140.519 + var result = r64.toNumber();
140.520 + return negateResult ? result.neg64() : result;
140.521 + }
140.522 +})(Number.prototype);
141.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
141.2 +++ b/emul/mini/src/test/java/org/apidesign/bck2brwsr/emul/reflect/MethodImplTest.java Sun Feb 17 17:58:34 2013 +0100
141.3 @@ -0,0 +1,49 @@
141.4 +/**
141.5 + * Back 2 Browser Bytecode Translator
141.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
141.7 + *
141.8 + * This program is free software: you can redistribute it and/or modify
141.9 + * it under the terms of the GNU General Public License as published by
141.10 + * the Free Software Foundation, version 2 of the License.
141.11 + *
141.12 + * This program is distributed in the hope that it will be useful,
141.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
141.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
141.15 + * GNU General Public License for more details.
141.16 + *
141.17 + * You should have received a copy of the GNU General Public License
141.18 + * along with this program. Look for COPYING file in the top folder.
141.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
141.20 + */
141.21 +package org.apidesign.bck2brwsr.emul.reflect;
141.22 +
141.23 +import java.lang.reflect.Method;
141.24 +import java.util.Enumeration;
141.25 +import org.testng.annotations.Test;
141.26 +
141.27 +/**
141.28 + *
141.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
141.30 + */
141.31 +public class MethodImplTest {
141.32 +
141.33 + public MethodImplTest() {
141.34 + }
141.35 +
141.36 + public static String[] arr(String... arr) {
141.37 + return arr;
141.38 + }
141.39 +
141.40 + @Test
141.41 + public void testSignatureForMethodWithAnArray() throws NoSuchMethodException {
141.42 + Method m = MethodImplTest.class.getMethod("arr", String[].class);
141.43 + String sig = MethodImpl.toSignature(m);
141.44 + int sep = sig.indexOf("__");
141.45 + assert sep > 0 : "Separator found " + sig;
141.46 +
141.47 + Enumeration<Class> en = MethodImpl.signatureParser(sig.substring(sep + 2));
141.48 +
141.49 + assert en.nextElement() == m.getReturnType() : "Return type is the same";
141.50 + assert en.nextElement() == m.getParameterTypes()[0] : "1st param type is the same";
141.51 + }
141.52 +}
141.53 \ No newline at end of file
142.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
142.2 +++ b/ide/editor/pom.xml Sun Feb 17 17:58:34 2013 +0100
142.3 @@ -0,0 +1,198 @@
142.4 +<?xml version="1.0" encoding="UTF-8"?>
142.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
142.6 + <modelVersion>4.0.0</modelVersion>
142.7 + <parent>
142.8 + <artifactId>ide</artifactId>
142.9 + <groupId>org.apidesign.bck2brwsr</groupId>
142.10 + <version>0.3-SNAPSHOT</version>
142.11 + </parent>
142.12 +
142.13 + <groupId>org.apidesign.bck2brwsr.ide.editor</groupId>
142.14 + <artifactId>editor</artifactId>
142.15 + <version>0.3-SNAPSHOT</version>
142.16 + <packaging>nbm</packaging>
142.17 +
142.18 + <name>Editor Support for Bck2Brwsr</name>
142.19 +
142.20 + <properties>
142.21 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
142.22 + <netbeans.version>RELEASE72</netbeans.version>
142.23 + <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
142.24 + </properties>
142.25 +
142.26 + <repositories>
142.27 + <!--
142.28 + Repository hosting NetBeans modules, especially APIs.
142.29 + Versions are based on IDE releases, e.g.: RELEASE691
142.30 + To create your own repository, use: nbm:populate-repository
142.31 + -->
142.32 + <repository>
142.33 + <id>netbeans</id>
142.34 + <name>NetBeans</name>
142.35 + <url>http://bits.netbeans.org/maven2/</url>
142.36 + <snapshots>
142.37 + <enabled>false</enabled>
142.38 + </snapshots>
142.39 + </repository>
142.40 + </repositories>
142.41 +
142.42 + <dependencies>
142.43 + <dependency>
142.44 + <groupId>org.netbeans.api</groupId>
142.45 + <artifactId>org-netbeans-api-annotations-common</artifactId>
142.46 + <version>${netbeans.version}</version>
142.47 + </dependency>
142.48 + <dependency>
142.49 + <groupId>org.netbeans.api</groupId>
142.50 + <artifactId>org-netbeans-modules-java-source</artifactId>
142.51 + <version>${netbeans.version}</version>
142.52 + </dependency>
142.53 + <dependency>
142.54 + <groupId>org.netbeans.api</groupId>
142.55 + <artifactId>org-netbeans-libs-javacapi</artifactId>
142.56 + <version>${netbeans.version}</version>
142.57 + </dependency>
142.58 + <dependency>
142.59 + <groupId>org.netbeans.api</groupId>
142.60 + <artifactId>org-netbeans-spi-java-hints</artifactId>
142.61 + <version>${netbeans.version}</version>
142.62 + </dependency>
142.63 + <dependency>
142.64 + <groupId>org.netbeans.api</groupId>
142.65 + <artifactId>org-netbeans-modules-parsing-api</artifactId>
142.66 + <version>${netbeans.version}</version>
142.67 + </dependency>
142.68 + <dependency>
142.69 + <groupId>org.netbeans.api</groupId>
142.70 + <artifactId>org-netbeans-spi-editor-hints</artifactId>
142.71 + <version>${netbeans.version}</version>
142.72 + </dependency>
142.73 + <dependency>
142.74 + <groupId>org.netbeans.api</groupId>
142.75 + <artifactId>org-openide-util</artifactId>
142.76 + <version>${netbeans.version}</version>
142.77 + </dependency>
142.78 + <dependency>
142.79 + <groupId>org.netbeans.api</groupId>
142.80 + <artifactId>org-netbeans-modules-java-lexer</artifactId>
142.81 + <version>${netbeans.version}</version>
142.82 + </dependency>
142.83 + <dependency>
142.84 + <groupId>org.netbeans.api</groupId>
142.85 + <artifactId>org-netbeans-modules-lexer</artifactId>
142.86 + <version>${netbeans.version}</version>
142.87 + </dependency>
142.88 + <dependency>
142.89 + <groupId>org.apidesign.bck2brwsr</groupId>
142.90 + <artifactId>core</artifactId>
142.91 + <version>0.3-SNAPSHOT</version>
142.92 + <type>jar</type>
142.93 + <scope>test</scope>
142.94 + </dependency>
142.95 + <dependency>
142.96 + <groupId>org.netbeans.api</groupId>
142.97 + <artifactId>org-netbeans-modules-java-hints-test</artifactId>
142.98 + <version>${netbeans.version}</version>
142.99 + <scope>test</scope>
142.100 + </dependency>
142.101 + <dependency>
142.102 + <groupId>org.netbeans.api</groupId>
142.103 + <artifactId>org-netbeans-libs-junit4</artifactId>
142.104 + <version>${netbeans.version}</version>
142.105 + <scope>test</scope>
142.106 + </dependency>
142.107 + <dependency>
142.108 + <groupId>org.netbeans.modules</groupId>
142.109 + <artifactId>org-netbeans-lib-nbjavac</artifactId>
142.110 + <version>${netbeans.version}</version>
142.111 + <scope>test</scope>
142.112 + </dependency>
142.113 + <dependency>
142.114 + <groupId>org.testng</groupId>
142.115 + <artifactId>testng</artifactId>
142.116 + <scope>test</scope>
142.117 + </dependency>
142.118 + </dependencies>
142.119 +
142.120 + <build>
142.121 + <plugins>
142.122 + <plugin>
142.123 + <groupId>org.codehaus.mojo</groupId>
142.124 + <artifactId>nbm-maven-plugin</artifactId>
142.125 + <version>3.8</version>
142.126 + <extensions>true</extensions>
142.127 + </plugin>
142.128 +
142.129 + <plugin>
142.130 + <!-- NetBeans 6.9+ requires JDK 6 -->
142.131 + <groupId>org.apache.maven.plugins</groupId>
142.132 + <artifactId>maven-compiler-plugin</artifactId>
142.133 + <version>2.5.1</version>
142.134 + <configuration>
142.135 + <source>1.6</source>
142.136 + <target>1.6</target>
142.137 + <compilerArguments>
142.138 + <endorseddirs>${endorsed.dir}</endorseddirs>
142.139 + </compilerArguments>
142.140 + </configuration>
142.141 + </plugin>
142.142 +
142.143 + <plugin>
142.144 + <groupId>org.apache.maven.plugins</groupId>
142.145 + <artifactId>maven-jar-plugin</artifactId>
142.146 + <version>2.4</version>
142.147 + <configuration>
142.148 + <!-- to have the jar plugin pickup the nbm generated manifest -->
142.149 + <useDefaultManifestFile>true</useDefaultManifestFile>
142.150 + </configuration>
142.151 + </plugin>
142.152 +
142.153 + <plugin>
142.154 + <groupId>org.apache.maven.plugins</groupId>
142.155 + <artifactId>maven-dependency-plugin</artifactId>
142.156 + <executions>
142.157 + <execution>
142.158 + <id>endorsed</id>
142.159 + <phase>validate</phase>
142.160 + <goals>
142.161 + <goal>copy</goal>
142.162 + </goals>
142.163 + </execution>
142.164 + </executions>
142.165 + <configuration>
142.166 + <outputDirectory>${endorsed.dir}</outputDirectory>
142.167 + <silent>true</silent>
142.168 + <artifactItems>
142.169 + <artifactItem>
142.170 + <groupId>org.netbeans.api</groupId>
142.171 + <artifactId>org-netbeans-libs-javacapi</artifactId>
142.172 + <version>${netbeans.version}</version>
142.173 + </artifactItem>
142.174 + <artifactItem>
142.175 + <groupId>org.netbeans.external</groupId>
142.176 + <artifactId>nb-javac-api</artifactId>
142.177 + <version>${netbeans.version}</version>
142.178 + </artifactItem>
142.179 + <artifactItem>
142.180 + <groupId>org.netbeans.modules</groupId>
142.181 + <artifactId>org-netbeans-libs-javacimpl</artifactId>
142.182 + <version>${netbeans.version}</version>
142.183 + </artifactItem>
142.184 + <artifactItem>
142.185 + <groupId>org.netbeans.external</groupId>
142.186 + <artifactId>nb-javac-impl</artifactId>
142.187 + <version>${netbeans.version}</version>
142.188 + </artifactItem>
142.189 + </artifactItems>
142.190 + </configuration>
142.191 + </plugin>
142.192 + <plugin>
142.193 + <groupId>org.apache.maven.plugins</groupId>
142.194 + <artifactId>maven-surefire-plugin</artifactId>
142.195 + <configuration>
142.196 + <argLine>-Djava.endorsed.dirs=${endorsed.dir}</argLine>
142.197 + </configuration>
142.198 + </plugin>
142.199 + </plugins>
142.200 + </build>
142.201 +</project>
143.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
143.2 +++ b/ide/editor/src/main/java/org/apidesign/bck2brwsr/ide/editor/JNIHelper.java Sun Feb 17 17:58:34 2013 +0100
143.3 @@ -0,0 +1,80 @@
143.4 +/**
143.5 + * Back 2 Browser Bytecode Translator
143.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
143.7 + *
143.8 + * This program is free software: you can redistribute it and/or modify
143.9 + * it under the terms of the GNU General Public License as published by
143.10 + * the Free Software Foundation, version 2 of the License.
143.11 + *
143.12 + * This program is distributed in the hope that it will be useful,
143.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
143.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
143.15 + * GNU General Public License for more details.
143.16 + *
143.17 + * You should have received a copy of the GNU General Public License
143.18 + * along with this program. Look for COPYING file in the top folder.
143.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
143.20 + */
143.21 +package org.apidesign.bck2brwsr.ide.editor;
143.22 +
143.23 +import java.lang.reflect.Method;
143.24 +import java.util.HashMap;
143.25 +import java.util.Map;
143.26 +
143.27 +/**
143.28 + * JNI Helper.
143.29 + * To facilitate lookup of methods by name and signature, instead of manually parsing signatures,
143.30 + * constructs the map of all methods and uses Class.getName() to generate almost-correct signatures.
143.31 + */
143.32 +class JNIHelper {
143.33 +
143.34 + static Method method(String clazz, String method, String signature) {
143.35 + final Map<String, Method> methods = methodMap(JNIHelper.clazz(clazz));
143.36 + return methods.get(methodKey(method, signature));
143.37 + }
143.38 +
143.39 + static Class<?> clazz(String clazz) {
143.40 + try {
143.41 + return Class.forName(clazz);
143.42 + } catch (ClassNotFoundException e) {
143.43 + throw new IllegalArgumentException(e);
143.44 + }
143.45 + }
143.46 +
143.47 + static Map<String, Method> methodMap(final Class<?> clazz) {
143.48 + final Map<String, Method> map = new HashMap<String, Method>();
143.49 + final Method[] methods = clazz.getDeclaredMethods();
143.50 + for (int i = 0; i < methods.length; i++) {
143.51 + final Method method = methods[i];
143.52 + map.put(methodKey(method.getName(), signature(method)), method);
143.53 + }
143.54 + return map;
143.55 + }
143.56 +
143.57 + static String methodKey(String method, String signature) {
143.58 + return method + '@' + signature;
143.59 + }
143.60 +
143.61 + static String signature(final Method method) {
143.62 + final Class<?>[] parameterTypes = method.getParameterTypes();
143.63 + final StringBuilder b = new StringBuilder();
143.64 + for (int j = 0; j < parameterTypes.length; j++) {
143.65 + b.append(signature(parameterTypes[j]));
143.66 + }
143.67 + return b.toString();
143.68 + }
143.69 +
143.70 + static String signature(final Class<?> clazz) {
143.71 + if (clazz == boolean.class) return "Z";
143.72 + else if (clazz == byte.class) return "B";
143.73 + else if (clazz == char.class) return "C";
143.74 + else if (clazz == double.class) return "D";
143.75 + else if (clazz == float.class) return "F";
143.76 + else if (clazz == int.class) return "I";
143.77 + else if (clazz == long.class) return "J";
143.78 + else if (clazz == short.class) return "S";
143.79 + else if (clazz == void.class) return "V";
143.80 + else if (clazz.isArray()) return clazz.getName().replace('.','/');
143.81 + else return "L" + clazz.getName().replace('.','/') + ";";
143.82 + }
143.83 +}
144.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
144.2 +++ b/ide/editor/src/main/java/org/apidesign/bck2brwsr/ide/editor/JSEmbeddingProvider.java Sun Feb 17 17:58:34 2013 +0100
144.3 @@ -0,0 +1,188 @@
144.4 +/**
144.5 + * Back 2 Browser Bytecode Translator
144.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
144.7 + *
144.8 + * This program is free software: you can redistribute it and/or modify
144.9 + * it under the terms of the GNU General Public License as published by
144.10 + * the Free Software Foundation, version 2 of the License.
144.11 + *
144.12 + * This program is distributed in the hope that it will be useful,
144.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
144.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
144.15 + * GNU General Public License for more details.
144.16 + *
144.17 + * You should have received a copy of the GNU General Public License
144.18 + * along with this program. Look for COPYING file in the top folder.
144.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
144.20 + */
144.21 +package org.apidesign.bck2brwsr.ide.editor;
144.22 +
144.23 +import com.sun.source.tree.AnnotationTree;
144.24 +import com.sun.source.tree.AssignmentTree;
144.25 +import com.sun.source.tree.CompilationUnitTree;
144.26 +import com.sun.source.tree.ExpressionTree;
144.27 +import com.sun.source.tree.LiteralTree;
144.28 +import com.sun.source.tree.MethodTree;
144.29 +import com.sun.source.util.SourcePositions;
144.30 +import com.sun.source.util.TreePath;
144.31 +import com.sun.source.util.TreePathScanner;
144.32 +import com.sun.source.util.Trees;
144.33 +import java.io.IOException;
144.34 +import java.util.ArrayList;
144.35 +import java.util.Collection;
144.36 +import java.util.Collections;
144.37 +import java.util.List;
144.38 +import java.util.concurrent.atomic.AtomicBoolean;
144.39 +import javax.lang.model.element.TypeElement;
144.40 +import javax.swing.text.Document;
144.41 +import org.netbeans.api.editor.mimelookup.MimeRegistration;
144.42 +import org.netbeans.api.java.source.CompilationInfo;
144.43 +import org.netbeans.api.java.source.JavaParserResultTask;
144.44 +import org.netbeans.api.java.source.JavaSource;
144.45 +import org.netbeans.api.lexer.Language;
144.46 +import org.netbeans.api.lexer.TokenHierarchy;
144.47 +import org.netbeans.api.lexer.TokenSequence;
144.48 +import org.netbeans.modules.parsing.api.Snapshot;
144.49 +import org.netbeans.modules.parsing.spi.Parser;
144.50 +import org.netbeans.modules.parsing.spi.Scheduler;
144.51 +import org.netbeans.modules.parsing.spi.SchedulerEvent;
144.52 +import org.netbeans.modules.parsing.spi.SchedulerTask;
144.53 +import org.netbeans.modules.parsing.spi.TaskFactory;
144.54 +import org.openide.util.Exceptions;
144.55 +
144.56 +/**
144.57 + *
144.58 + * @author Tomas Zezula
144.59 + */
144.60 +public final class JSEmbeddingProvider extends JavaParserResultTask<Parser.Result> {
144.61 +
144.62 + private static final int PRIORITY = 1000;
144.63 + private static final String JS_ANNOTATION = "org.apidesign.bck2brwsr.core.JavaScriptBody"; //NOI18N
144.64 + private static final String BODY = "body"; //NOI18N
144.65 + private static final String JAVA_MIME_TYPE = "text/x-java"; //NOI18N
144.66 + private static final String JAVASCRIPT_MIME_TYPE = "text/javascript"; //NOI18N
144.67 + private final AtomicBoolean canceled = new AtomicBoolean();
144.68 +
144.69 + private JSEmbeddingProvider() {
144.70 + super(JavaSource.Phase.ELEMENTS_RESOLVED);
144.71 + }
144.72 +
144.73 + @Override
144.74 + public int getPriority() {
144.75 + return PRIORITY;
144.76 + }
144.77 +
144.78 + @Override
144.79 + public void cancel() {
144.80 + canceled.set(true);
144.81 + }
144.82 +
144.83 + @Override
144.84 + public Class<? extends Scheduler> getSchedulerClass() {
144.85 + return Scheduler.EDITOR_SENSITIVE_TASK_SCHEDULER;
144.86 + }
144.87 +
144.88 + @Override
144.89 + public void run(Parser.Result t, SchedulerEvent se) {
144.90 + canceled.set(false);
144.91 + final CompilationInfo ci = CompilationInfo.get(t);
144.92 + final CompilationUnitTree cu = ci.getCompilationUnit();
144.93 + final Trees trees = ci.getTrees();
144.94 + final SourcePositions sp = trees.getSourcePositions();
144.95 + final Finder f = new Finder(trees);
144.96 + final List<LiteralTree> result = new ArrayList<LiteralTree>();
144.97 + f.scan(cu, result);
144.98 + if (!result.isEmpty()) {
144.99 + try {
144.100 + final TokenHierarchy<Document> tk = TokenHierarchy.get(ci.getDocument());
144.101 + final Language<?> java = Language.find(JAVA_MIME_TYPE);
144.102 + final Language<?> javaScript = Language.find(JAVASCRIPT_MIME_TYPE);
144.103 + if (java != null && javaScript != null) {
144.104 + final TokenSequence<?> seq = tk.tokenSequence(java);
144.105 + if (seq != null) {
144.106 + for (LiteralTree lt : result) {
144.107 + final int start = (int) sp.getStartPosition(cu, lt);
144.108 + final int end = (int) sp.getEndPosition(cu, lt);
144.109 + seq.move(start);
144.110 + while (seq.moveNext() && seq.offset() < end) {
144.111 + seq.createEmbedding(javaScript, 1, 1, true);
144.112 + }
144.113 + }
144.114 + }
144.115 + }
144.116 + } catch (IOException ioe) {
144.117 + Exceptions.printStackTrace(ioe);
144.118 + }
144.119 + }
144.120 + }
144.121 +
144.122 +
144.123 +
144.124 +
144.125 + private static final class Finder extends TreePathScanner<Void, List<? super LiteralTree>> {
144.126 +
144.127 + private final Trees trees;
144.128 + private CompilationUnitTree cu;
144.129 + private boolean inEmbedding;
144.130 +
144.131 + Finder(final Trees trees) {
144.132 + this.trees = trees;
144.133 + }
144.134 +
144.135 + @Override
144.136 + public Void visitCompilationUnit(
144.137 + final CompilationUnitTree unit,
144.138 + final List p) {
144.139 + this.cu = unit;
144.140 + return super.visitCompilationUnit(unit, p);
144.141 + }
144.142 +
144.143 +
144.144 +
144.145 + @Override
144.146 + public Void visitMethod(
144.147 + final MethodTree m,
144.148 + final List<? super LiteralTree> p) {
144.149 + for (AnnotationTree a : m.getModifiers().getAnnotations()) {
144.150 + final TypeElement ae = (TypeElement) trees.getElement(TreePath.getPath(cu, a.getAnnotationType()));
144.151 + if (ae != null && JS_ANNOTATION.contentEquals(ae.getQualifiedName())) {
144.152 + final List<? extends ExpressionTree> args = a.getArguments();
144.153 + for (ExpressionTree kvp : args) {
144.154 + if (kvp instanceof AssignmentTree) {
144.155 + final AssignmentTree assignemt = (AssignmentTree) kvp;
144.156 + if (BODY.equals(assignemt.getVariable().toString())) {
144.157 + inEmbedding = true;
144.158 + try {
144.159 + scan(assignemt.getExpression(), p);
144.160 + } finally {
144.161 + inEmbedding = false;
144.162 + }
144.163 + }
144.164 + }
144.165 + }
144.166 + }
144.167 + }
144.168 + return null;
144.169 + }
144.170 +
144.171 + @Override
144.172 + public Void visitLiteral(LiteralTree node, List<? super LiteralTree> p) {
144.173 + if (inEmbedding) {
144.174 + p.add(node);
144.175 + }
144.176 + return super.visitLiteral(node, p);
144.177 + }
144.178 +
144.179 + }
144.180 +
144.181 + @MimeRegistration(
144.182 + service = TaskFactory.class,
144.183 + mimeType = JAVA_MIME_TYPE)
144.184 + public static final class Factory extends TaskFactory {
144.185 + @Override
144.186 + public Collection<? extends SchedulerTask> create(Snapshot snpsht) {
144.187 + return Collections.singleton(new JSEmbeddingProvider());
144.188 + }
144.189 + }
144.190 +
144.191 +}
145.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
145.2 +++ b/ide/editor/src/main/java/org/apidesign/bck2brwsr/ide/editor/JSNI2JavaScriptBody.java Sun Feb 17 17:58:34 2013 +0100
145.3 @@ -0,0 +1,149 @@
145.4 +/**
145.5 + * Back 2 Browser Bytecode Translator
145.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
145.7 + *
145.8 + * This program is free software: you can redistribute it and/or modify
145.9 + * it under the terms of the GNU General Public License as published by
145.10 + * the Free Software Foundation, version 2 of the License.
145.11 + *
145.12 + * This program is distributed in the hope that it will be useful,
145.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
145.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
145.15 + * GNU General Public License for more details.
145.16 + *
145.17 + * You should have received a copy of the GNU General Public License
145.18 + * along with this program. Look for COPYING file in the top folder.
145.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
145.20 + */
145.21 +package org.apidesign.bck2brwsr.ide.editor;
145.22 +
145.23 +import com.sun.source.tree.AnnotationTree;
145.24 +import com.sun.source.tree.ExpressionTree;
145.25 +import com.sun.source.tree.LiteralTree;
145.26 +import com.sun.source.tree.MethodTree;
145.27 +import com.sun.source.tree.Tree.Kind;
145.28 +import com.sun.source.tree.VariableTree;
145.29 +import com.sun.source.util.TreePath;
145.30 +import java.util.ArrayList;
145.31 +import java.util.Arrays;
145.32 +import java.util.Collections;
145.33 +import java.util.List;
145.34 +import org.netbeans.api.java.lexer.JavaTokenId;
145.35 +import static org.netbeans.api.java.lexer.JavaTokenId.BLOCK_COMMENT;
145.36 +import static org.netbeans.api.java.lexer.JavaTokenId.JAVADOC_COMMENT;
145.37 +import static org.netbeans.api.java.lexer.JavaTokenId.LINE_COMMENT;
145.38 +import static org.netbeans.api.java.lexer.JavaTokenId.WHITESPACE;
145.39 +import org.netbeans.api.java.source.CompilationInfo;
145.40 +import org.netbeans.api.java.source.TreeMaker;
145.41 +import org.netbeans.api.lexer.Token;
145.42 +import org.netbeans.api.lexer.TokenSequence;
145.43 +import org.netbeans.spi.editor.hints.ErrorDescription;
145.44 +import org.netbeans.spi.editor.hints.Fix;
145.45 +import org.netbeans.spi.java.hints.ErrorDescriptionFactory;
145.46 +import org.netbeans.spi.java.hints.Hint;
145.47 +import org.netbeans.spi.java.hints.HintContext;
145.48 +import org.netbeans.spi.java.hints.JavaFix;
145.49 +import org.netbeans.spi.java.hints.TriggerTreeKind;
145.50 +import org.openide.util.NbBundle.Messages;
145.51 +
145.52 +@Hint(displayName = "#DN_JSNI2JavaScriptBody", description = "#DESC_JSNI2JavaScriptBody", category = "general")
145.53 +@Messages({
145.54 + "DN_JSNI2JavaScriptBody=JSNI to @JavaScriptBody",
145.55 + "DESC_JSNI2JavaScriptBody=JSNI to @JavaScriptBody"
145.56 +})
145.57 +public class JSNI2JavaScriptBody {
145.58 +
145.59 + @TriggerTreeKind(Kind.METHOD)
145.60 + @Messages("ERR_JSNI2JavaScriptBody=Can convert JSNI to @JavaScriptBody")
145.61 + public static ErrorDescription computeWarning(final HintContext ctx) {
145.62 + Token<JavaTokenId> token = findBlockToken(ctx.getInfo(), ctx.getPath(), ctx);
145.63 +
145.64 + if (token == null) {
145.65 + return null;
145.66 + }
145.67 +
145.68 + Fix fix = new FixImpl(ctx.getInfo(), ctx.getPath()).toEditorFix();
145.69 + return ErrorDescriptionFactory.forName(ctx, ctx.getPath(), Bundle.ERR_JSNI2JavaScriptBody(), fix);
145.70 + }
145.71 +
145.72 + private static Token<JavaTokenId> findBlockToken(CompilationInfo info, TreePath path, HintContext ctx) {
145.73 + int end = (int) info.getTrees().getSourcePositions().getEndPosition(path.getCompilationUnit(), path.getLeaf());
145.74 + TokenSequence<JavaTokenId> ts = info.getTokenHierarchy().tokenSequence(JavaTokenId.language());
145.75 +
145.76 + if (ts == null) return null;
145.77 +
145.78 + ts.move(end);
145.79 +
145.80 + if ((ctx != null && ctx.isCanceled()) || !ts.movePrevious() || ts.token().id() != JavaTokenId.SEMICOLON) return null;
145.81 +
145.82 + OUTER: while (ts.movePrevious()) {
145.83 + if (ctx != null && ctx.isCanceled()) return null;
145.84 +
145.85 + switch (ts.token().id()) {
145.86 + case WHITESPACE: break;
145.87 + case LINE_COMMENT: break;
145.88 + case JAVADOC_COMMENT: break;
145.89 + case BLOCK_COMMENT:
145.90 + final CharSequence tok = ts.token().text();
145.91 + final int l = tok.length();
145.92 + if (l > 4
145.93 + && tok.subSequence(0, 4).toString().equals("/*-{") // NOI18N
145.94 + && tok.subSequence(l - 4, l).toString().equals("}-*/") // NOI18N
145.95 + ) {
145.96 + return ts.offsetToken();
145.97 + }
145.98 + break;
145.99 + default:
145.100 + break OUTER;
145.101 + }
145.102 + }
145.103 +
145.104 + return null;
145.105 + }
145.106 +
145.107 + private static final class FixImpl extends JavaFix {
145.108 +
145.109 + public FixImpl(CompilationInfo info, TreePath tp) {
145.110 + super(info, tp);
145.111 + }
145.112 +
145.113 + @Override
145.114 + @Messages("FIX_JSNI2JavaScriptBody=Convert JSNI to @JavaScriptBody")
145.115 + protected String getText() {
145.116 + return Bundle.FIX_JSNI2JavaScriptBody();
145.117 + }
145.118 +
145.119 + @Override
145.120 + protected void performRewrite(TransformationContext ctx) {
145.121 + Token<JavaTokenId> jsniComment = findBlockToken(ctx.getWorkingCopy(), ctx.getPath(), null);
145.122 +
145.123 + if (jsniComment == null) {
145.124 + //XXX: warn?
145.125 + return ;
145.126 + }
145.127 +
145.128 + JsniCommentTokenizer tok = new JsniCommentTokenizer();
145.129 + ManglingSink ms = new ManglingSink();
145.130 + final CharSequence cmnt = jsniComment.text();
145.131 + tok.process(cmnt.subSequence(4, cmnt.length() - 4), ms);
145.132 +
145.133 + TreeMaker make = ctx.getWorkingCopy().getTreeMaker();
145.134 + MethodTree mt = (MethodTree) ctx.getPath().getLeaf();
145.135 + List<LiteralTree> params = new ArrayList<LiteralTree>();
145.136 +
145.137 + for (VariableTree p : mt.getParameters()) {
145.138 + params.add(make.Literal(p.getName().toString()));
145.139 + }
145.140 +
145.141 + AnnotationTree jsBody = make.Annotation(make.QualIdent("org.apidesign.bck2brwsr.core.JavaScriptBody"),
145.142 + Arrays.<ExpressionTree>asList(
145.143 + make.Assignment(make.Identifier("args"), make.NewArray(null, Collections.<ExpressionTree>emptyList(), params)),
145.144 + make.Assignment(make.Identifier("body"), make.Literal(ms.out.toString()))
145.145 + )
145.146 + );
145.147 +
145.148 +
145.149 + ctx.getWorkingCopy().rewrite(mt.getModifiers(), make.addModifiersAnnotation(mt.getModifiers(), jsBody));
145.150 + }
145.151 + }
145.152 +}
146.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
146.2 +++ b/ide/editor/src/main/java/org/apidesign/bck2brwsr/ide/editor/JsniCommentTokenizer.java Sun Feb 17 17:58:34 2013 +0100
146.3 @@ -0,0 +1,70 @@
146.4 +/**
146.5 + * Back 2 Browser Bytecode Translator
146.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
146.7 + *
146.8 + * This program is free software: you can redistribute it and/or modify
146.9 + * it under the terms of the GNU General Public License as published by
146.10 + * the Free Software Foundation, version 2 of the License.
146.11 + *
146.12 + * This program is distributed in the hope that it will be useful,
146.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
146.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
146.15 + * GNU General Public License for more details.
146.16 + *
146.17 + * You should have received a copy of the GNU General Public License
146.18 + * along with this program. Look for COPYING file in the top folder.
146.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
146.20 + */
146.21 +package org.apidesign.bck2brwsr.ide.editor;
146.22 +
146.23 +import java.util.regex.Matcher;
146.24 +import java.util.regex.Pattern;
146.25 +
146.26 +final class JsniCommentTokenizer {
146.27 +
146.28 + /**
146.29 + * Tokenize the contents of JSNI comment into the provided {@linkplain Sink}.
146.30 + * @param in the contents of JSNI comment
146.31 + * @param out the sink that consumes parsed tokens
146.32 + */
146.33 + public void process(final CharSequence in, final Sink out) {
146.34 + final Matcher member = Pattern.compile("@([^:]+)::([a-zA-Z_$][a-zA-Z\\d_$]*)").matcher(in);
146.35 + final Matcher signature = Pattern.compile("\\(([^\\)]*)\\)").matcher(in);
146.36 +
146.37 + int i = 0;
146.38 + while (true) {
146.39 + if (member.find(i)) {
146.40 + final int memberStart = member.start();
146.41 + final int memberEnd = member.end();
146.42 + if (memberStart > i) out.javascript(in.subSequence(i, memberStart).toString());
146.43 +
146.44 + final String clazz = member.group(1);
146.45 + final String name = member.group(2);
146.46 +
146.47 + if (in.charAt(memberEnd) == '(') {
146.48 + if (!signature.find(memberEnd)) {
146.49 + throw new IllegalStateException("Expected method signature");
146.50 + }
146.51 + assert signature.start() == memberEnd;
146.52 + out.method(clazz, name, signature.group(1));
146.53 + i = signature.end();
146.54 + } else {
146.55 + out.field(clazz, name);
146.56 + i = memberEnd;
146.57 + }
146.58 + } else {
146.59 + out.javascript(in.subSequence(i, in.length()).toString());
146.60 + break;
146.61 + }
146.62 + }
146.63 + }
146.64 +
146.65 +
146.66 + static interface Sink {
146.67 + void javascript(String s);
146.68 +
146.69 + void method(String clazz, String method, String signature);
146.70 +
146.71 + void field(String clazz, String field);
146.72 + }
146.73 +}
147.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
147.2 +++ b/ide/editor/src/main/java/org/apidesign/bck2brwsr/ide/editor/ManglingSink.java Sun Feb 17 17:58:34 2013 +0100
147.3 @@ -0,0 +1,71 @@
147.4 +/**
147.5 + * Back 2 Browser Bytecode Translator
147.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
147.7 + *
147.8 + * This program is free software: you can redistribute it and/or modify
147.9 + * it under the terms of the GNU General Public License as published by
147.10 + * the Free Software Foundation, version 2 of the License.
147.11 + *
147.12 + * This program is distributed in the hope that it will be useful,
147.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
147.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
147.15 + * GNU General Public License for more details.
147.16 + *
147.17 + * You should have received a copy of the GNU General Public License
147.18 + * along with this program. Look for COPYING file in the top folder.
147.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
147.20 + */
147.21 +package org.apidesign.bck2brwsr.ide.editor;
147.22 +
147.23 +/**
147.24 + * An implementation of {@linkplain JsniCommentTokenizer.Sink} that generates B2B
147.25 + */
147.26 +class ManglingSink implements JsniCommentTokenizer.Sink {
147.27 +
147.28 + final StringBuilder out = new StringBuilder();
147.29 +
147.30 + public void javascript(String s) {
147.31 + out.append(s);
147.32 + }
147.33 +
147.34 + public void method(String clazz, String method, String signature) {
147.35 + out.append(mangle(clazz, method, signature));
147.36 + }
147.37 +
147.38 + public void field(String clazz, String field) {
147.39 +// out.append(field);
147.40 + out.append('_').append(field).append('(').append(')');
147.41 + }
147.42 +
147.43 +
147.44 + @Override
147.45 + public String toString() {
147.46 + return out.toString();
147.47 + }
147.48 +
147.49 +
147.50 + static String mangle(String clazz, String method, String signature) {
147.51 + final StringBuilder builder = new StringBuilder();
147.52 + builder.append(method);
147.53 + builder.append("__");
147.54 + builder.append(mangle(JNIHelper.signature(JNIHelper.method(clazz, method, signature).getReturnType())));
147.55 + builder.append(mangle(signature));
147.56 + return builder.toString();
147.57 + }
147.58 +
147.59 +
147.60 + static String mangle(String txt) {
147.61 + final StringBuilder sb = new StringBuilder();
147.62 + for (int i = 0; i < txt.length(); i++) {
147.63 + final char ch = txt.charAt(i);
147.64 + switch (ch) {
147.65 + case '/': sb.append('_'); break;
147.66 + case '_': sb.append("_1"); break;
147.67 + case ';': sb.append("_2"); break;
147.68 + case '[': sb.append("_3"); break;
147.69 + default: sb.append(ch); break;
147.70 + }
147.71 + }
147.72 + return sb.toString();
147.73 + }
147.74 +}
148.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
148.2 +++ b/ide/editor/src/main/nbm/manifest.mf Sun Feb 17 17:58:34 2013 +0100
148.3 @@ -0,0 +1,2 @@
148.4 +Manifest-Version: 1.0
148.5 +OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/jackpot30/test/hints/Bundle.properties
149.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
149.2 +++ b/ide/editor/src/main/resources/org/netbeans/modules/jackpot30/test/hints/Bundle.properties Sun Feb 17 17:58:34 2013 +0100
149.3 @@ -0,0 +1,21 @@
149.4 +#
149.5 +# Back 2 Browser Bytecode Translator
149.6 +# Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
149.7 +#
149.8 +# This program is free software: you can redistribute it and/or modify
149.9 +# it under the terms of the GNU General Public License as published by
149.10 +# the Free Software Foundation, version 2 of the License.
149.11 +#
149.12 +# This program is distributed in the hope that it will be useful,
149.13 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
149.14 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
149.15 +# GNU General Public License for more details.
149.16 +#
149.17 +# You should have received a copy of the GNU General Public License
149.18 +# along with this program. Look for COPYING file in the top folder.
149.19 +# If not, see http://opensource.org/licenses/GPL-2.0.
149.20 +#
149.21 +
149.22 +OpenIDE-Module-Name=Bck2Brwsr Editor Support
149.23 +OpenIDE-Module-Short-Description=Provides hints, coloring, etc. for the bck2brwsr.apidesign.org project
149.24 +OpenIDE-Module-Display-Category=Java
150.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
150.2 +++ b/ide/editor/src/test/java/org/apidesign/bck2brwsr/ide/editor/DejsniReaderTest.java Sun Feb 17 17:58:34 2013 +0100
150.3 @@ -0,0 +1,84 @@
150.4 +/**
150.5 + * Back 2 Browser Bytecode Translator
150.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
150.7 + *
150.8 + * This program is free software: you can redistribute it and/or modify
150.9 + * it under the terms of the GNU General Public License as published by
150.10 + * the Free Software Foundation, version 2 of the License.
150.11 + *
150.12 + * This program is distributed in the hope that it will be useful,
150.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
150.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
150.15 + * GNU General Public License for more details.
150.16 + *
150.17 + * You should have received a copy of the GNU General Public License
150.18 + * along with this program. Look for COPYING file in the top folder.
150.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
150.20 + */
150.21 +package org.apidesign.bck2brwsr.ide.editor;
150.22 +
150.23 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
150.24 +import org.netbeans.modules.java.hints.test.api.HintTest;
150.25 +import org.openide.filesystems.FileUtil;
150.26 +import org.testng.annotations.Test;
150.27 +
150.28 +public class DejsniReaderTest {
150.29 +
150.30 + @Test
150.31 + public void test1() throws Exception {
150.32 + String s = "class Test {\n" +
150.33 + " /** javadoc */\n" +
150.34 + " public native void test() /*-{\n" +
150.35 + " // body\n" +
150.36 + " }-*/;\n" +
150.37 + "}\n";
150.38 +
150.39 + String expected = " import org.apidesign.bck2brwsr.core.JavaScriptBody;\n"
150.40 + + "class Test {\n" +
150.41 + "\n" +
150.42 + " /** javadoc */\n" +
150.43 + " @JavaScriptBody(args = {}, body = \"\\n // body\\n \")\n" +
150.44 + " public native void test();\n" +
150.45 + "}\n";
150.46 +
150.47 + HintTest.create()
150.48 + .input(s)
150.49 + .classpath(FileUtil.getArchiveRoot(JavaScriptBody.class.getProtectionDomain().getCodeSource().getLocation()))
150.50 + .run(JSNI2JavaScriptBody.class)
150.51 + .findWarning("2:23-2:27:verifier:" + Bundle.ERR_JSNI2JavaScriptBody())
150.52 + .applyFix()
150.53 + .assertCompilable()
150.54 + .assertOutput(expected);
150.55 + }
150.56 +
150.57 +
150.58 + @Test
150.59 + public void test2() throws Exception {
150.60 + String s = "class Test {\n" +
150.61 + " /** javadoc */\n" +
150.62 + " @SuppressWarnings(\"unused\")\n" +
150.63 + " // comment\n" +
150.64 + " public native void test() /*-{\n" +
150.65 + " // body\n" +
150.66 + " }-*/;\n" +
150.67 + "}\n";
150.68 +
150.69 + String expected = " import org.apidesign.bck2brwsr.core.JavaScriptBody;\n"
150.70 + + "class Test {\n" +
150.71 + "\n" +
150.72 + " /** javadoc */\n" +
150.73 + " @SuppressWarnings(\"unused\")\n" +
150.74 + " // comment\n" +
150.75 + " @JavaScriptBody(args = {}, body = \"\\n // body\\n \")\n" +
150.76 + " public native void test();\n" +
150.77 + "}\n";
150.78 + HintTest.create()
150.79 + .input(s)
150.80 + .classpath(FileUtil.getArchiveRoot(JavaScriptBody.class.getProtectionDomain().getCodeSource().getLocation()))
150.81 + .run(JSNI2JavaScriptBody.class)
150.82 + .findWarning("4:23-4:27:verifier:" + Bundle.ERR_JSNI2JavaScriptBody())
150.83 + .applyFix()
150.84 + .assertCompilable()
150.85 + .assertOutput(expected);
150.86 + }
150.87 +}
150.88 \ No newline at end of file
151.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
151.2 +++ b/ide/editor/src/test/java/org/apidesign/bck2brwsr/ide/editor/JSNI2JavaScriptBodyTest.java Sun Feb 17 17:58:34 2013 +0100
151.3 @@ -0,0 +1,46 @@
151.4 +/**
151.5 + * Back 2 Browser Bytecode Translator
151.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
151.7 + *
151.8 + * This program is free software: you can redistribute it and/or modify
151.9 + * it under the terms of the GNU General Public License as published by
151.10 + * the Free Software Foundation, version 2 of the License.
151.11 + *
151.12 + * This program is distributed in the hope that it will be useful,
151.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
151.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
151.15 + * GNU General Public License for more details.
151.16 + *
151.17 + * You should have received a copy of the GNU General Public License
151.18 + * along with this program. Look for COPYING file in the top folder.
151.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
151.20 + */
151.21 +package org.apidesign.bck2brwsr.ide.editor;
151.22 +
151.23 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
151.24 +import org.netbeans.modules.java.hints.test.api.HintTest;
151.25 +import org.openide.filesystems.FileUtil;
151.26 +import org.testng.annotations.Test;
151.27 +
151.28 +public class JSNI2JavaScriptBodyTest {
151.29 +
151.30 + @Test
151.31 + public void testFixWorking() throws Exception {
151.32 + HintTest.create()
151.33 + .input("package test;\n" +
151.34 + "public class Test {\n" +
151.35 + " public native void run(int a) /*-{ this.a = a; }-*/;\n" +
151.36 + "}\n")
151.37 + .classpath(FileUtil.getArchiveRoot(JavaScriptBody.class.getProtectionDomain().getCodeSource().getLocation()))
151.38 + .run(JSNI2JavaScriptBody.class)
151.39 + .findWarning("2:23-2:26:verifier:" + Bundle.ERR_JSNI2JavaScriptBody())
151.40 + .applyFix()
151.41 + .assertCompilable()
151.42 + .assertOutput("package test;\n" +
151.43 + "import org.apidesign.bck2brwsr.core.JavaScriptBody;\n" +
151.44 + "public class Test {\n" +
151.45 + " @JavaScriptBody(args = {\"a\"}, body = \" this.a = a; \")\n" +
151.46 + " public native void run(int a);\n" +
151.47 + "}\n");
151.48 + }
151.49 +}
152.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
152.2 +++ b/ide/editor/src/test/java/org/apidesign/bck2brwsr/ide/editor/JsniCommentTokenizerTest.java Sun Feb 17 17:58:34 2013 +0100
152.3 @@ -0,0 +1,154 @@
152.4 +/**
152.5 + * Back 2 Browser Bytecode Translator
152.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
152.7 + *
152.8 + * This program is free software: you can redistribute it and/or modify
152.9 + * it under the terms of the GNU General Public License as published by
152.10 + * the Free Software Foundation, version 2 of the License.
152.11 + *
152.12 + * This program is distributed in the hope that it will be useful,
152.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
152.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
152.15 + * GNU General Public License for more details.
152.16 + *
152.17 + * You should have received a copy of the GNU General Public License
152.18 + * along with this program. Look for COPYING file in the top folder.
152.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
152.20 + */
152.21 +package org.apidesign.bck2brwsr.ide.editor;
152.22 +
152.23 +import java.io.IOException;
152.24 +import java.util.ArrayList;
152.25 +import java.util.List;
152.26 +import org.testng.Assert;
152.27 +import org.testng.annotations.Test;
152.28 +
152.29 +public class JsniCommentTokenizerTest {
152.30 +
152.31 + private static class MockSink implements JsniCommentTokenizer.Sink {
152.32 + final List<String> out = new ArrayList<String>();
152.33 +
152.34 + public void javascript(String s) {
152.35 + out.add("J " + s);
152.36 + }
152.37 +
152.38 + public void method(String clazz, String method, String signature) {
152.39 + out.add("M " + clazz + "|" + method + "|" + signature);
152.40 + }
152.41 +
152.42 + public void field(String clazz, String field) {
152.43 + out.add("F " + clazz + "|" + field);
152.44 + }
152.45 + }
152.46 +
152.47 +
152.48 + @Test
152.49 + public void testProcess_nop() throws IOException {
152.50 + final String in = "foo bar";
152.51 + final List<String> expected = new ArrayList<String>();
152.52 + expected.add("J foo bar");
152.53 +
152.54 + final JsniCommentTokenizer jsniCommentTokenizer = new JsniCommentTokenizer();
152.55 + final MockSink out = new MockSink();
152.56 + jsniCommentTokenizer.process(in, out);
152.57 +
152.58 + Assert.assertEquals(expected, out.out);
152.59 + }
152.60 +
152.61 + @Test
152.62 + public void testProcess_read_static_field() throws IOException {
152.63 + final String in = " @com.google.gwt.examples.JSNIExample::myStaticField = val + \" and stuff\";";
152.64 + final List<String> expected = new ArrayList<String>();
152.65 + expected.add("J ");
152.66 + expected.add("F com.google.gwt.examples.JSNIExample|myStaticField");
152.67 + expected.add("J = val + \" and stuff\";");
152.68 +
152.69 + final JsniCommentTokenizer jsniCommentTokenizer = new JsniCommentTokenizer();
152.70 + final MockSink out = new MockSink();
152.71 + jsniCommentTokenizer.process(in, out);
152.72 +
152.73 + Assert.assertEquals(expected, out.out);
152.74 + }
152.75 +
152.76 + @Test
152.77 + public void testProcess_write_instance_field() throws IOException {
152.78 + final String in = " x.@com.google.gwt.examples.JSNIExample::myInstanceField = val + \" and stuff\";";
152.79 + final List<String> expected = new ArrayList<String>();
152.80 + expected.add("J x.");
152.81 + expected.add("F com.google.gwt.examples.JSNIExample|myInstanceField");
152.82 + expected.add("J = val + \" and stuff\";");
152.83 +
152.84 + final JsniCommentTokenizer jsniCommentTokenizer = new JsniCommentTokenizer();
152.85 + final MockSink out = new MockSink();
152.86 + jsniCommentTokenizer.process(in, out);
152.87 +
152.88 + Assert.assertEquals(expected, out.out);
152.89 + }
152.90 +
152.91 + @Test
152.92 + public void testProcess_read_instance_field() throws IOException {
152.93 + final String in = " var val = this.@com.google.gwt.examples.JSNIExample::myInstanceField;";
152.94 + final List<String> expected = new ArrayList<String>();
152.95 + expected.add("J var val = this.");
152.96 + expected.add("F com.google.gwt.examples.JSNIExample|myInstanceField");
152.97 + expected.add("J ;");
152.98 +
152.99 + final JsniCommentTokenizer jsniCommentTokenizer = new JsniCommentTokenizer();
152.100 + final MockSink out = new MockSink();
152.101 + jsniCommentTokenizer.process(in, out);
152.102 +
152.103 + Assert.assertEquals(expected, out.out);
152.104 + }
152.105 +
152.106 +
152.107 + @Test
152.108 + public void testProcess_static_method() throws IOException {
152.109 + final String in = " @com.google.gwt.examples.JSNIExample::staticFoo(Ljava/lang/String;)(s);";
152.110 + final List<String> expected = new ArrayList<String>();
152.111 + expected.add("J ");
152.112 + expected.add("M com.google.gwt.examples.JSNIExample|staticFoo|Ljava/lang/String;");
152.113 + expected.add("J (s);");
152.114 +
152.115 + final JsniCommentTokenizer jsniCommentTokenizer = new JsniCommentTokenizer();
152.116 + final MockSink out = new MockSink();
152.117 + jsniCommentTokenizer.process(in, out);
152.118 +
152.119 + Assert.assertEquals(expected, out.out);
152.120 + }
152.121 +
152.122 +
152.123 + @Test
152.124 + public void testProcess_instance_method() throws IOException {
152.125 + final String in = " x.@com.google.gwt.examples.JSNIExample::instanceFoo(Ljava/lang/String;)(s);";
152.126 + final List<String> expected = new ArrayList<String>();
152.127 + expected.add("J x.");
152.128 + expected.add("M com.google.gwt.examples.JSNIExample|instanceFoo|Ljava/lang/String;");
152.129 + expected.add("J (s);");
152.130 +
152.131 + final JsniCommentTokenizer jsniCommentTokenizer = new JsniCommentTokenizer();
152.132 + final MockSink out = new MockSink();
152.133 + jsniCommentTokenizer.process(in, out);
152.134 +
152.135 + Assert.assertEquals(expected, out.out);
152.136 + }
152.137 +
152.138 +
152.139 + @Test
152.140 + public void testProcess_multiline() throws IOException {
152.141 + final String in =
152.142 + " x.@com.google.gwt.examples.JSNIExample::instanceFoo(Ljava/lang/String;)(s);" +
152.143 + " @com.google.gwt.examples.JSNIExample::myStaticField = val + \" and stuff\";";
152.144 + final List<String> expected = new ArrayList<String>();
152.145 + expected.add("J x.");
152.146 + expected.add("M com.google.gwt.examples.JSNIExample|instanceFoo|Ljava/lang/String;");
152.147 + expected.add("J (s); ");
152.148 + expected.add("F com.google.gwt.examples.JSNIExample|myStaticField");
152.149 + expected.add("J = val + \" and stuff\";");
152.150 +
152.151 + final JsniCommentTokenizer jsniCommentTokenizer = new JsniCommentTokenizer();
152.152 + final MockSink out = new MockSink();
152.153 + jsniCommentTokenizer.process(in, out);
152.154 +
152.155 + Assert.assertEquals(expected, out.out);
152.156 + }
152.157 +}
153.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
153.2 +++ b/ide/editor/src/test/java/org/apidesign/bck2brwsr/ide/editor/ManglingSinkTest.java Sun Feb 17 17:58:34 2013 +0100
153.3 @@ -0,0 +1,58 @@
153.4 +/**
153.5 + * Back 2 Browser Bytecode Translator
153.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
153.7 + *
153.8 + * This program is free software: you can redistribute it and/or modify
153.9 + * it under the terms of the GNU General Public License as published by
153.10 + * the Free Software Foundation, version 2 of the License.
153.11 + *
153.12 + * This program is distributed in the hope that it will be useful,
153.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
153.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
153.15 + * GNU General Public License for more details.
153.16 + *
153.17 + * You should have received a copy of the GNU General Public License
153.18 + * along with this program. Look for COPYING file in the top folder.
153.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
153.20 + */
153.21 +package org.apidesign.bck2brwsr.ide.editor;
153.22 +
153.23 +import org.testng.Assert;
153.24 +import org.testng.annotations.Test;
153.25 +
153.26 +
153.27 +public class ManglingSinkTest {
153.28 +
153.29 + @Test
153.30 + public void testMangle_1() {
153.31 + Assert.assertEquals(
153.32 + "binarySearch__I_3BIIB",
153.33 + ManglingSink.mangle("java.util.Arrays", "binarySearch", "[BIIB")
153.34 + );
153.35 + }
153.36 +
153.37 + @Test
153.38 + public void testMangle_2() {
153.39 + Assert.assertEquals(
153.40 + "sort__V_3I",
153.41 + ManglingSink.mangle("java.util.Arrays", "sort", "[I")
153.42 + );
153.43 + }
153.44 +
153.45 + @Test
153.46 + public void testMangle_3() {
153.47 + Assert.assertEquals(
153.48 + "binarySearch__I_3Ljava_lang_Object_2IILjava_lang_Object_2",
153.49 + ManglingSink.mangle("java.util.Arrays", "binarySearch", "[Ljava/lang/Object;IILjava/lang/Object;")
153.50 + );
153.51 + }
153.52 +
153.53 +
153.54 + @Test
153.55 + public void testField() {
153.56 + final ManglingSink manglingSink = new ManglingSink();
153.57 + manglingSink.field(null, "value");
153.58 +
153.59 + Assert.assertEquals("_value()", manglingSink.toString());
153.60 + }
153.61 +}
154.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
154.2 +++ b/ide/pom.xml Sun Feb 17 17:58:34 2013 +0100
154.3 @@ -0,0 +1,17 @@
154.4 +<?xml version="1.0" encoding="UTF-8"?>
154.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
154.6 + <modelVersion>4.0.0</modelVersion>
154.7 + <parent>
154.8 + <artifactId>bck2brwsr</artifactId>
154.9 + <groupId>org.apidesign</groupId>
154.10 + <version>0.3-SNAPSHOT</version>
154.11 + </parent>
154.12 + <groupId>org.apidesign.bck2brwsr</groupId>
154.13 + <artifactId>ide</artifactId>
154.14 + <version>0.3-SNAPSHOT</version>
154.15 + <packaging>pom</packaging>
154.16 + <name>IDE Support</name>
154.17 + <modules>
154.18 + <module>editor</module>
154.19 + </modules>
154.20 +</project>
155.1 --- a/javap/src/main/java/org/apidesign/javap/AnnotationParser.java Fri Jan 25 15:08:24 2013 +0100
155.2 +++ b/javap/src/main/java/org/apidesign/javap/AnnotationParser.java Sun Feb 17 17:58:34 2013 +0100
155.3 @@ -35,22 +35,37 @@
155.4 */
155.5 public class AnnotationParser {
155.6 private final boolean textual;
155.7 + private final boolean iterateArray;
155.8
155.9 - protected AnnotationParser(boolean textual) {
155.10 + protected AnnotationParser(boolean textual, boolean iterateArray) {
155.11 this.textual = textual;
155.12 + this.iterateArray = iterateArray;
155.13 }
155.14
155.15 - protected void visitAnnotationStart(String type) throws IOException {
155.16 + protected void visitAnnotationStart(String type, boolean top) throws IOException {
155.17 }
155.18
155.19 - protected void visitAnnotationEnd(String type) throws IOException {
155.20 + protected void visitAnnotationEnd(String type, boolean top) throws IOException {
155.21 }
155.22 +
155.23 + protected void visitValueStart(String attrName, char type) throws IOException {
155.24 + }
155.25 +
155.26 + protected void visitValueEnd(String attrName, char type) throws IOException {
155.27 + }
155.28 +
155.29
155.30 protected void visitAttr(
155.31 String annoType, String attr, String attrType, String value
155.32 ) throws IOException {
155.33 }
155.34
155.35 + protected void visitEnumAttr(
155.36 + String annoType, String attr, String attrType, String value
155.37 + ) throws IOException {
155.38 + visitAttr(annoType, attr, attrType, value);
155.39 + }
155.40 +
155.41 /** Initialize the parsing with constant pool from <code>cd</code>.
155.42 *
155.43 * @param attr the attribute defining annotations
155.44 @@ -70,30 +85,32 @@
155.45 private void read(DataInputStream dis, ClassData cd) throws IOException {
155.46 int cnt = dis.readUnsignedShort();
155.47 for (int i = 0; i < cnt; i++) {
155.48 - readAnno(dis, cd);
155.49 + readAnno(dis, cd, true);
155.50 }
155.51 }
155.52
155.53 - private void readAnno(DataInputStream dis, ClassData cd) throws IOException {
155.54 + private void readAnno(DataInputStream dis, ClassData cd, boolean top) throws IOException {
155.55 int type = dis.readUnsignedShort();
155.56 String typeName = cd.StringValue(type);
155.57 - visitAnnotationStart(typeName);
155.58 + visitAnnotationStart(typeName, top);
155.59 int cnt = dis.readUnsignedShort();
155.60 for (int i = 0; i < cnt; i++) {
155.61 String attrName = cd.StringValue(dis.readUnsignedShort());
155.62 readValue(dis, cd, typeName, attrName);
155.63 }
155.64 - visitAnnotationEnd(typeName);
155.65 + visitAnnotationEnd(typeName, top);
155.66 if (cnt == 0) {
155.67 visitAttr(typeName, null, null, null);
155.68 }
155.69 }
155.70
155.71 - private void readValue(DataInputStream dis, ClassData cd, String typeName, String attrName)
155.72 - throws IOException {
155.73 + private void readValue(
155.74 + DataInputStream dis, ClassData cd, String typeName, String attrName
155.75 + ) throws IOException {
155.76 char type = (char)dis.readByte();
155.77 + visitValueStart(attrName, type);
155.78 if (type == '@') {
155.79 - readAnno(dis, cd);
155.80 + readAnno(dis, cd, false);
155.81 } else if ("CFJZsSIDB".indexOf(type) >= 0) { // NOI18N
155.82 int primitive = dis.readUnsignedShort();
155.83 String val = cd.stringValue(primitive, textual);
155.84 @@ -112,13 +129,17 @@
155.85 } else if (type == '[') {
155.86 int cnt = dis.readUnsignedShort();
155.87 for (int i = 0; i < cnt; i++) {
155.88 - readValue(dis, cd, typeName, attrName);
155.89 + readValue(dis, cd, typeName, iterateArray ? attrName : null);
155.90 }
155.91 } else if (type == 'e') {
155.92 int enumT = dis.readUnsignedShort();
155.93 + String attrType = cd.stringValue(enumT, textual);
155.94 int enumN = dis.readUnsignedShort();
155.95 + String val = cd.stringValue(enumN, textual);
155.96 + visitEnumAttr(typeName, attrName, attrType, val);
155.97 } else {
155.98 throw new IOException("Unknown type " + type);
155.99 }
155.100 + visitValueEnd(attrName, type);
155.101 }
155.102 }
156.1 --- a/javaquery/api/pom.xml Fri Jan 25 15:08:24 2013 +0100
156.2 +++ b/javaquery/api/pom.xml Sun Feb 17 17:58:34 2013 +0100
156.3 @@ -43,24 +43,20 @@
156.4 <dependency>
156.5 <groupId>org.netbeans.api</groupId>
156.6 <artifactId>org-openide-util-lookup</artifactId>
156.7 + <scope>provided</scope>
156.8 </dependency>
156.9 <dependency>
156.10 <groupId>org.apidesign.bck2brwsr</groupId>
156.11 - <artifactId>core</artifactId>
156.12 - <version>0.3-SNAPSHOT</version>
156.13 + <artifactId>emul</artifactId>
156.14 + <version>${project.version}</version>
156.15 + <classifier>rt</classifier>
156.16 <type>jar</type>
156.17 - </dependency>
156.18 - <dependency>
156.19 - <groupId>org.apidesign.bck2brwsr</groupId>
156.20 - <artifactId>emul.mini</artifactId>
156.21 - <version>0.3-SNAPSHOT</version>
156.22 - <type>jar</type>
156.23 - <scope>runtime</scope>
156.24 + <scope>compile</scope>
156.25 </dependency>
156.26 <dependency>
156.27 <groupId>org.apidesign.bck2brwsr</groupId>
156.28 <artifactId>vm4brwsr</artifactId>
156.29 - <version>0.3-SNAPSHOT</version>
156.30 + <version>${project.version}</version>
156.31 <type>jar</type>
156.32 <scope>test</scope>
156.33 </dependency>
157.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Canvas.java Fri Jan 25 15:08:24 2013 +0100
157.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Canvas.java Sun Feb 17 17:58:34 2013 +0100
157.3 @@ -47,7 +47,7 @@
157.4
157.5 @JavaScriptBody(
157.6 args = {"el"},
157.7 - body = "var e = window.document.getElementById(el.fld_id);\n"
157.8 + body = "var e = window.document.getElementById(el._id());\n"
157.9 + "return e.getContext('2d');\n")
157.10 private native static Object getContextImpl(Canvas el);
157.11
158.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Element.java Fri Jan 25 15:08:24 2013 +0100
158.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Element.java Sun Feb 17 17:58:34 2013 +0100
158.3 @@ -41,21 +41,21 @@
158.4
158.5 @JavaScriptBody(
158.6 args={"el", "property", "value"},
158.7 - body="var e = window.document.getElementById(el.fld_id);\n"
158.8 + body="var e = window.document.getElementById(el._id());\n"
158.9 + "e[property] = value;\n"
158.10 )
158.11 static native void setAttribute(Element el, String property, Object value);
158.12
158.13 @JavaScriptBody(
158.14 args={"el", "property"},
158.15 - body="var e = window.document.getElementById(el.fld_id);\n"
158.16 + body="var e = window.document.getElementById(el._id());\n"
158.17 + "return e[property];\n"
158.18 )
158.19 static native Object getAttribute(Element el, String property);
158.20
158.21 @JavaScriptBody(
158.22 args={"el"},
158.23 - body="return window.document.getElementById(el.fld_id);"
158.24 + body="return window.document.getElementById(el._id());"
158.25 )
158.26 static native Object getElementById(Element el);
158.27
158.28 @@ -65,8 +65,8 @@
158.29 */
158.30 @JavaScriptBody(
158.31 args={ "ev", "r" },
158.32 - body="var e = window.document.getElementById(this.fld_id);\n"
158.33 - + "e[ev.fld_id] = function() { r.run__V(); };\n"
158.34 + body="var e = window.document.getElementById(this._id());\n"
158.35 + + "e[ev._id()] = function() { r.run__V(); };\n"
158.36 )
158.37 final void on(OnEvent ev, Runnable r) {
158.38 }
159.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/GraphicsContext.java Fri Jan 25 15:08:24 2013 +0100
159.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/GraphicsContext.java Sun Feb 17 17:58:34 2013 +0100
159.3 @@ -32,7 +32,7 @@
159.4 }
159.5
159.6 @JavaScriptBody(args = {"centerx", "centery", "radius", "startangle", "endangle", "ccw"},
159.7 - body = "this.fld_context.arc(centerx,centery, radius, startangle, endangle,ccw);")
159.8 + body = "this._context().arc(centerx,centery, radius, startangle, endangle,ccw);")
159.9 public native void arc(double centerX,
159.10 double centerY,
159.11 double startAngle,
159.12 @@ -41,7 +41,7 @@
159.13 boolean ccw);
159.14
159.15 @JavaScriptBody(args = {"x1", "y1", "x2", "y2", "r"},
159.16 - body = "this.fld_context.arcTo(x1,y1,x2,y2,r);")
159.17 + body = "this._context().arcTo(x1,y1,x2,y2,r);")
159.18 public native void arcTo(double x1,
159.19 double y1,
159.20 double x2,
159.21 @@ -49,68 +49,68 @@
159.22 double r);
159.23
159.24 @JavaScriptBody(args = {"x", "y"},
159.25 - body = "return this.fld_context.isPointInPath(x,y);")
159.26 + body = "return this._context().isPointInPath(x,y);")
159.27 public native boolean isPointInPath(double x, double y);
159.28
159.29 - @JavaScriptBody(args = {}, body = "this.fld_context.fill();")
159.30 + @JavaScriptBody(args = {}, body = "this._context().fill();")
159.31 public native void fill();
159.32
159.33 - @JavaScriptBody(args = {}, body = "this.fld_context.stroke();")
159.34 + @JavaScriptBody(args = {}, body = "this._context().stroke();")
159.35 public native void stroke();
159.36
159.37 - @JavaScriptBody(args = {}, body = "this.fld_context.beginPath();")
159.38 + @JavaScriptBody(args = {}, body = "this._context().beginPath();")
159.39 public native void beginPath();
159.40
159.41 - @JavaScriptBody(args = {}, body = "this.fld_context.closePath();")
159.42 + @JavaScriptBody(args = {}, body = "this._context().closePath();")
159.43 public native void closePath();
159.44
159.45 - @JavaScriptBody(args = {}, body = "this.fld_context.clip();")
159.46 + @JavaScriptBody(args = {}, body = "this._context().clip();")
159.47 public native void clip();
159.48
159.49 - @JavaScriptBody(args = {"x", "y"}, body = "this.fld_context.moveTo(x,y);")
159.50 + @JavaScriptBody(args = {"x", "y"}, body = "this._context().moveTo(x,y);")
159.51 public native void moveTo(double x, double y);
159.52
159.53 - @JavaScriptBody(args = {"x", "y"}, body = "this.fld_context.lineTo(x,y);")
159.54 + @JavaScriptBody(args = {"x", "y"}, body = "this._context().lineTo(x,y);")
159.55 public native void lineTo(double x, double y);
159.56
159.57 - @JavaScriptBody(args = {"cpx", "cpy", "x", "y"}, body = "this.fld_context.quadraticCurveTo(cpx,cpy,x,y);")
159.58 + @JavaScriptBody(args = {"cpx", "cpy", "x", "y"}, body = "this._context().quadraticCurveTo(cpx,cpy,x,y);")
159.59 public native void quadraticCurveTo(double cpx, double cpy, double x, double y);
159.60
159.61 @JavaScriptBody(args = {"cp1x", "cp1y", "cp2x", "cp2y", "x", "y"},
159.62 - body = "this.fld_context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y);")
159.63 + body = "this._context().bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y);")
159.64 public native void bezierCurveTo(double cp1x, double cp1y, double cp2x, double cp2y, double x, double y);
159.65
159.66 - @JavaScriptBody(args = {"x", "y", "width", "height"}, body = "this.fld_context.fillRect(x,y,width,height);")
159.67 + @JavaScriptBody(args = {"x", "y", "width", "height"}, body = "this._context().fillRect(x,y,width,height);")
159.68 public native void fillRect(double x, double y, double width, double height);
159.69
159.70 - @JavaScriptBody(args = {"x", "y", "width", "height"}, body = "this.fld_context.strokeRect(x,y,width,height);")
159.71 + @JavaScriptBody(args = {"x", "y", "width", "height"}, body = "this._context().strokeRect(x,y,width,height);")
159.72 public native void strokeRect(double x, double y, double width, double height);
159.73
159.74 - @JavaScriptBody(args = {"x", "y", "width", "height"}, body = "this.fld_context.clearRect(x,y,width,height);")
159.75 + @JavaScriptBody(args = {"x", "y", "width", "height"}, body = "this._context().clearRect(x,y,width,height);")
159.76 public native void clearRect(double x, double y, double width, double height);
159.77
159.78 - @JavaScriptBody(args = {"x", "y", "width", "height"}, body = "this.fld_context.rectect(x,y,width,height);")
159.79 + @JavaScriptBody(args = {"x", "y", "width", "height"}, body = "this._context().rectect(x,y,width,height);")
159.80 public native void rect(double x, double y, double width, double height);
159.81
159.82 - @JavaScriptBody(args = {}, body = "this.fld_context.save();")
159.83 + @JavaScriptBody(args = {}, body = "this._context().save();")
159.84 public native void save();
159.85
159.86 - @JavaScriptBody(args = {}, body = "this.fld_context.restore();")
159.87 + @JavaScriptBody(args = {}, body = "this._context().restore();")
159.88 public native void restore();
159.89
159.90 - @JavaScriptBody(args = {"angle"}, body = "this.fld_context.rotate(angle);")
159.91 + @JavaScriptBody(args = {"angle"}, body = "this._context().rotate(angle);")
159.92 public native void rotate(double angle);
159.93
159.94 - @JavaScriptBody(args = {"a", "b", "c", "d", "e", "f"}, body = "this.fld_context.transform(a,b,c,d,e,f);")
159.95 + @JavaScriptBody(args = {"a", "b", "c", "d", "e", "f"}, body = "this._context().transform(a,b,c,d,e,f);")
159.96 public native void transform(double a, double b, double c, double d, double e, double f);
159.97
159.98 - @JavaScriptBody(args = {"a", "b", "c", "d", "e", "f"}, body = "this.fld_context.setTransform(a,b,c,d,e,f);")
159.99 + @JavaScriptBody(args = {"a", "b", "c", "d", "e", "f"}, body = "this._context().setTransform(a,b,c,d,e,f);")
159.100 public native void setTransform(double a, double b, double c, double d, double e, double f);
159.101
159.102 - @JavaScriptBody(args = {"x", "y"}, body = "this.fld_context.translate(x,y);")
159.103 + @JavaScriptBody(args = {"x", "y"}, body = "this._context().translate(x,y);")
159.104 public native void translate(double x, double y);
159.105
159.106 - @JavaScriptBody(args = {"x", "y"}, body = "this.fld_context.scale(x,y);")
159.107 + @JavaScriptBody(args = {"x", "y"}, body = "this._context().scale(x,y);")
159.108 public native void scale(double x, double y);
159.109
159.110 public void drawImage(Image image, double x, double y) {
159.111 @@ -134,10 +134,10 @@
159.112 @JavaScriptBody(args = {"ctx", "img", "x", "y"}, body = "ctx.drawImage(img,x,y);")
159.113 private native static void drawImageImpl(Object ctx, Object img, double x, double y);
159.114
159.115 - @JavaScriptBody(args = {"style"}, body = "this.fld_context.fillStyle=style;")
159.116 + @JavaScriptBody(args = {"style"}, body = "this._context().fillStyle=style;")
159.117 public native void setFillStyle(String style);
159.118
159.119 - @JavaScriptBody(args = {}, body = "return this.fld_context.fillStyle;")
159.120 + @JavaScriptBody(args = {}, body = "return this._context().fillStyle;")
159.121 public native String getFillStyle();
159.122
159.123 public void setFillStyle(LinearGradient style) {
159.124 @@ -155,7 +155,7 @@
159.125 @JavaScriptBody(args = {"context","obj"}, body = "context.fillStyle=obj;")
159.126 private native void setFillStyleImpl(Object context, Object obj);
159.127
159.128 - @JavaScriptBody(args = {"style"}, body = "this.fld_context.strokeStyle=style;")
159.129 + @JavaScriptBody(args = {"style"}, body = "this._context().strokeStyle=style;")
159.130 public native void setStrokeStyle(String style);
159.131
159.132 public void setStrokeStyle(LinearGradient style) {
159.133 @@ -166,7 +166,7 @@
159.134 setStrokeStyleImpl(context, style.object());
159.135 }
159.136
159.137 - @JavaScriptBody(args = {"style"}, body = "this.fld_context.fillStyle=style;")
159.138 + @JavaScriptBody(args = {"style"}, body = "this._context().fillStyle=style;")
159.139 public void setStrokeStyle(Pattern style) {
159.140 setStrokeStyleImpl(context, style.object());
159.141 }
159.142 @@ -174,79 +174,79 @@
159.143 @JavaScriptBody(args = {"context","obj"}, body = "context.strokeStyle=obj;")
159.144 private native void setStrokeStyleImpl(Object context, Object obj);
159.145
159.146 - @JavaScriptBody(args = {"color"}, body = "this.fld_context.shadowColor=color;")
159.147 + @JavaScriptBody(args = {"color"}, body = "this._context().shadowColor=color;")
159.148 public native void setShadowColor(String color);
159.149
159.150 - @JavaScriptBody(args = {"blur"}, body = "this.fld_context.shadowBlur=blur;")
159.151 + @JavaScriptBody(args = {"blur"}, body = "this._context().shadowBlur=blur;")
159.152 public native void setShadowBlur(double blur);
159.153
159.154 - @JavaScriptBody(args = {"x"}, body = "this.fld_context.shadowOffsetX=x;")
159.155 + @JavaScriptBody(args = {"x"}, body = "this._context().shadowOffsetX=x;")
159.156 public native void setShadowOffsetX(double x);
159.157
159.158 - @JavaScriptBody(args = {"y"}, body = "this.fld_context.shadowOffsetY=y;")
159.159 + @JavaScriptBody(args = {"y"}, body = "this._context().shadowOffsetY=y;")
159.160 public native void setShadowOffsetY(double y);
159.161
159.162 - @JavaScriptBody(args = {}, body = "return this.fld_context.strokeStyle;")
159.163 + @JavaScriptBody(args = {}, body = "return this._context().strokeStyle;")
159.164 public native String getStrokeStyle();
159.165
159.166 - @JavaScriptBody(args = {}, body = "return this.fld_context.shadowColor;")
159.167 + @JavaScriptBody(args = {}, body = "return this._context().shadowColor;")
159.168 public native String getShadowColor();
159.169
159.170 - @JavaScriptBody(args = {}, body = "return this.fld_context.shadowBlur;")
159.171 + @JavaScriptBody(args = {}, body = "return this._context().shadowBlur;")
159.172 public native double getShadowBlur();
159.173
159.174 - @JavaScriptBody(args = {}, body = "return this.fld_context.shadowOffsetX;")
159.175 + @JavaScriptBody(args = {}, body = "return this._context().shadowOffsetX;")
159.176 public native double getShadowOffsetX();
159.177
159.178 - @JavaScriptBody(args = {}, body = "return this.fld_context.shadowOffsetY;")
159.179 + @JavaScriptBody(args = {}, body = "return this._context().shadowOffsetY;")
159.180 public native double getShadowOffsetY();
159.181
159.182 - @JavaScriptBody(args = {}, body = "return this.fld_context.lineCap;")
159.183 + @JavaScriptBody(args = {}, body = "return this._context().lineCap;")
159.184 public native String getLineCap();
159.185
159.186 - @JavaScriptBody(args = {"style"}, body = "this.fld_context.lineCap=style;")
159.187 + @JavaScriptBody(args = {"style"}, body = "this._context().lineCap=style;")
159.188 public native void setLineCap(String style);
159.189
159.190 - @JavaScriptBody(args = {}, body = "return this.fld_context.lineJoin;")
159.191 + @JavaScriptBody(args = {}, body = "return this._context().lineJoin;")
159.192 public native String getLineJoin();
159.193
159.194 - @JavaScriptBody(args = {"style"}, body = "this.fld_context.lineJoin=style;")
159.195 + @JavaScriptBody(args = {"style"}, body = "this._context().lineJoin=style;")
159.196 public native void setLineJoin(String style) ;
159.197
159.198 - @JavaScriptBody(args = {}, body = "return this.fld_context.lineWidth;")
159.199 + @JavaScriptBody(args = {}, body = "return this._context().lineWidth;")
159.200 public native double getLineWidth();
159.201
159.202 - @JavaScriptBody(args = {"width"}, body = "this.fld_context.lineJoin=width;")
159.203 + @JavaScriptBody(args = {"width"}, body = "this._context().lineJoin=width;")
159.204 public native void setLineWidth(double width);
159.205
159.206 - @JavaScriptBody(args = {}, body = "return this.fld_context.miterLimit;")
159.207 + @JavaScriptBody(args = {}, body = "return this._context().miterLimit;")
159.208 public native double getMiterLimit();
159.209
159.210 - @JavaScriptBody(args = {"limit"}, body = "this.fld_context.miterLimit=limit;")
159.211 + @JavaScriptBody(args = {"limit"}, body = "this._context().miterLimit=limit;")
159.212 public native void setMiterLimit(double limit);
159.213
159.214 - @JavaScriptBody(args = {}, body = "return this.fld_context.font;")
159.215 + @JavaScriptBody(args = {}, body = "return this._context().font;")
159.216 public native String getFont();
159.217
159.218 - @JavaScriptBody(args = {"font"}, body = "this.fld_context.font=font;")
159.219 + @JavaScriptBody(args = {"font"}, body = "this._context().font=font;")
159.220 public native void setFont(String font);
159.221
159.222 - @JavaScriptBody(args = {}, body = "return this.fld_context.textAlign;")
159.223 + @JavaScriptBody(args = {}, body = "return this._context().textAlign;")
159.224 public native String getTextAlign();
159.225
159.226 - @JavaScriptBody(args = {"textalign"}, body = "this.fld_context.textAlign=textalign;")
159.227 + @JavaScriptBody(args = {"textalign"}, body = "this._context().textAlign=textalign;")
159.228 public native void setTextAlign(String textAlign);
159.229
159.230 - @JavaScriptBody(args = {}, body = "return this.fld_context.textBaseline;")
159.231 + @JavaScriptBody(args = {}, body = "return this._context().textBaseline;")
159.232 public native String getTextBaseline();
159.233
159.234 - @JavaScriptBody(args = {"textbaseline"}, body = "this.fld_context.textBaseline=textbaseline;")
159.235 + @JavaScriptBody(args = {"textbaseline"}, body = "this._context().textBaseline=textbaseline;")
159.236 public native void setTextBaseline(String textbaseline);
159.237
159.238 - @JavaScriptBody(args = {"text", "x", "y"}, body = "this.fld_context.fillText(text,x,y);")
159.239 + @JavaScriptBody(args = {"text", "x", "y"}, body = "this._context().fillText(text,x,y);")
159.240 public native void fillText(String text, double x, double y);
159.241
159.242 - @JavaScriptBody(args = {"text", "x", "y", "maxwidth"}, body = "this.fld_context.fillText(text,x,y,maxwidth);")
159.243 + @JavaScriptBody(args = {"text", "x", "y", "maxwidth"}, body = "this._context().fillText(text,x,y,maxwidth);")
159.244 public void fillText(String text, double x, double y, double maxWidth) {
159.245 }
159.246
159.247 @@ -255,13 +255,13 @@
159.248 }
159.249
159.250 @JavaScriptBody(args = {"text"},
159.251 - body = "return this.fld_context.measureText(text);")
159.252 + body = "return this._context().measureText(text);")
159.253 private native Object measureTextImpl(String text);
159.254
159.255 - @JavaScriptBody(args = {"text", "x", "y"}, body = "this.fld_context.strokeText(text,x,y);")
159.256 + @JavaScriptBody(args = {"text", "x", "y"}, body = "this._context().strokeText(text,x,y);")
159.257 public native void strokeText(String text, double x, double y);
159.258
159.259 - @JavaScriptBody(args = {"text", "x", "y", "maxWidth"}, body = "this.fld_context.strokeText(text,x,y,maxWidth);")
159.260 + @JavaScriptBody(args = {"text", "x", "y", "maxWidth"}, body = "this._context().strokeText(text,x,y,maxWidth);")
159.261 public native void strokeText(String text, double x, double y, double maxWidth) ;
159.262
159.263 public ImageData createImageData(double x, double y) {
159.264 @@ -269,7 +269,7 @@
159.265 }
159.266
159.267 @JavaScriptBody(args = {"x", "y"},
159.268 - body = "return this.fld_context.createImageData(x,y);")
159.269 + body = "return this._context().createImageData(x,y);")
159.270 private native Object createImageDataImpl(double x, double y);
159.271
159.272 public ImageData createImageData(ImageData imageData) {
159.273 @@ -281,7 +281,7 @@
159.274 }
159.275
159.276 @JavaScriptBody(args = {"x", "y", "width", "height"},
159.277 - body = "return this.fld_context.getImageData(x,y,width,height);")
159.278 + body = "return this._context().getImageData(x,y,width,height);")
159.279 private native Object getImageDataImpl(double x, double y, double width, double height);
159.280
159.281 public void putImageData(ImageData imageData, double x, double y) {
159.282 @@ -289,7 +289,7 @@
159.283 }
159.284
159.285 @JavaScriptBody(args = {"imageData", "x", "y"},
159.286 - body = "this.fld_context.putImageData(imageData,x,y);")
159.287 + body = "this._context().putImageData(imageData,x,y);")
159.288 private native void putImageDataImpl(Object imageData, double x, double y);
159.289
159.290 public void putImageData(ImageData imageData, double x, double y, double dirtyx, double dirtyy, double dirtywidth, double dirtyheight) {
159.291 @@ -297,20 +297,20 @@
159.292 }
159.293
159.294 @JavaScriptBody(args = {"imageData", "x", "y", "dirtyx", "dirtyy", "dirtywidth", "dirtyheight"},
159.295 - body = "this.fld_context.putImageData(imageData,x,y, dirtyx, dirtyy, dirtywidth,dirtyheight);")
159.296 + body = "this._context().putImageData(imageData,x,y, dirtyx, dirtyy, dirtywidth,dirtyheight);")
159.297 private native void putImageDataImpl(Object imageData, double x, double y, double dirtyx, double dirtyy, double dirtywidth, double dirtyheight);
159.298
159.299 - @JavaScriptBody(args = {"alpha"}, body = "this.fld_context.globalAlpha=alpha;")
159.300 + @JavaScriptBody(args = {"alpha"}, body = "this._context().globalAlpha=alpha;")
159.301 public native void setGlobalAlpha(double alpha) ;
159.302
159.303 - @JavaScriptBody(args = {}, body = "return this.fld_context.globalAlpha;")
159.304 + @JavaScriptBody(args = {}, body = "return this._context().globalAlpha;")
159.305 public native double getGlobalAlpha();
159.306
159.307 - @JavaScriptBody(args = {"operation"}, body = "this.fld_context.globalCompositeOperation=operation;")
159.308 - public native void setGlobalCompositeOperation(double alpha);
159.309 + @JavaScriptBody(args = {"operation"}, body = "this._context().globalCompositeOperation=operation;")
159.310 + public native void setGlobalCompositeOperation(String operation);
159.311
159.312 - @JavaScriptBody(args = {}, body = "return this.fld_context.globalCompositeOperation;")
159.313 - public native double getGlobalCompositeOperation();
159.314 + @JavaScriptBody(args = {}, body = "return this._context().globalCompositeOperation;")
159.315 + public native String getGlobalCompositeOperation();
159.316
159.317 public LinearGradient createLinearGradient(double x0, double y0, double x1, double y1) {
159.318 return new LinearGradient(createLinearGradientImpl(context, x0, y0, x1, y1));
160.1 --- a/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ProcessPageTest.java Fri Jan 25 15:08:24 2013 +0100
160.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ProcessPageTest.java Sun Feb 17 17:58:34 2013 +0100
160.3 @@ -128,6 +128,8 @@
160.4 sb = new StringBuilder();
160.5 }
160.6 Bck2Brwsr.generate(sb, ProcessPageTest.class.getClassLoader(), names);
160.7 + sb.append("var vm = this.bck2brwsr();\n");
160.8 +
160.9 ScriptEngineManager sem = new ScriptEngineManager();
160.10 ScriptEngine js = sem.getEngineByExtension("js");
160.11 try {
161.1 --- a/javaquery/demo-calculator-dynamic/pom.xml Fri Jan 25 15:08:24 2013 +0100
161.2 +++ b/javaquery/demo-calculator-dynamic/pom.xml Sun Feb 17 17:58:34 2013 +0100
161.3 @@ -40,14 +40,54 @@
161.4 <target>1.7</target>
161.5 </configuration>
161.6 </plugin>
161.7 + <plugin>
161.8 + <groupId>org.apache.maven.plugins</groupId>
161.9 + <artifactId>maven-jar-plugin</artifactId>
161.10 + <version>2.4</version>
161.11 + <configuration>
161.12 + <archive>
161.13 + <manifest>
161.14 + <addClasspath>true</addClasspath>
161.15 + <classpathPrefix>lib/</classpathPrefix>
161.16 + </manifest>
161.17 + </archive>
161.18 + </configuration>
161.19 + </plugin>
161.20 + <plugin>
161.21 + <groupId>org.apache.maven.plugins</groupId>
161.22 + <artifactId>maven-deploy-plugin</artifactId>
161.23 + <version>2.7</version>
161.24 + <configuration>
161.25 + <skip>true</skip>
161.26 + </configuration>
161.27 + </plugin>
161.28 + <plugin>
161.29 + <artifactId>maven-assembly-plugin</artifactId>
161.30 + <version>2.4</version>
161.31 + <executions>
161.32 + <execution>
161.33 + <id>distro-assembly</id>
161.34 + <phase>package</phase>
161.35 + <goals>
161.36 + <goal>single</goal>
161.37 + </goals>
161.38 + <configuration>
161.39 + <descriptors>
161.40 + <descriptor>src/main/assembly/bck2brwsr.xml</descriptor>
161.41 + </descriptors>
161.42 + </configuration>
161.43 + </execution>
161.44 + </executions>
161.45 + </plugin>
161.46 </plugins>
161.47 </build>
161.48
161.49 <dependencies>
161.50 <dependency>
161.51 <groupId>org.apidesign.bck2brwsr</groupId>
161.52 - <artifactId>emul.mini</artifactId>
161.53 + <artifactId>emul</artifactId>
161.54 <version>0.3-SNAPSHOT</version>
161.55 + <classifier>rt</classifier>
161.56 </dependency>
161.57 <dependency>
161.58 <groupId>org.apidesign.bck2brwsr</groupId>
161.59 @@ -60,5 +100,13 @@
161.60 <version>6.5.2</version>
161.61 <scope>test</scope>
161.62 </dependency>
161.63 + <dependency>
161.64 + <groupId>org.apidesign.bck2brwsr</groupId>
161.65 + <artifactId>vm4brwsr</artifactId>
161.66 + <classifier>js</classifier>
161.67 + <type>zip</type>
161.68 + <version>0.3-SNAPSHOT</version>
161.69 + <scope>provided</scope>
161.70 + </dependency>
161.71 </dependencies>
161.72 </project>
162.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
162.2 +++ b/javaquery/demo-calculator-dynamic/src/main/assembly/bck2brwsr.xml Sun Feb 17 17:58:34 2013 +0100
162.3 @@ -0,0 +1,62 @@
162.4 +<?xml version="1.0"?>
162.5 +<!--
162.6 +
162.7 + Back 2 Browser Bytecode Translator
162.8 + Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
162.9 +
162.10 + This program is free software: you can redistribute it and/or modify
162.11 + it under the terms of the GNU General Public License as published by
162.12 + the Free Software Foundation, version 2 of the License.
162.13 +
162.14 + This program is distributed in the hope that it will be useful,
162.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of
162.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
162.17 + GNU General Public License for more details.
162.18 +
162.19 + You should have received a copy of the GNU General Public License
162.20 + along with this program. Look for COPYING file in the top folder.
162.21 + If not, see http://opensource.org/licenses/GPL-2.0.
162.22 +
162.23 +-->
162.24 +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
162.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">
162.26 +
162.27 + <id>bck2brwsr</id>
162.28 + <formats>
162.29 + <format>zip</format>
162.30 + <format>dir</format>
162.31 + </formats>
162.32 + <baseDirectory>public_html</baseDirectory>
162.33 + <dependencySets>
162.34 + <dependencySet>
162.35 + <useProjectArtifact>false</useProjectArtifact>
162.36 + <scope>runtime</scope>
162.37 + <outputDirectory>lib</outputDirectory>
162.38 + <includes>
162.39 + <include>*:jar</include>
162.40 + <include>*:rt</include>
162.41 + </includes>
162.42 + </dependencySet>
162.43 + <dependencySet>
162.44 + <useProjectArtifact>false</useProjectArtifact>
162.45 + <scope>provided</scope>
162.46 + <includes>
162.47 + <include>*:js</include>
162.48 + </includes>
162.49 + <unpack>true</unpack>
162.50 + <outputDirectory>/</outputDirectory>
162.51 + </dependencySet>
162.52 + </dependencySets>
162.53 + <files>
162.54 + <file>
162.55 + <source>${project.build.directory}/${project.build.finalName}.jar</source>
162.56 + <outputDirectory>/</outputDirectory>
162.57 + </file>
162.58 + <file>
162.59 + <source>${project.build.directory}/classes/org/apidesign/bck2brwsr/demo/calc/Calculator.xhtml</source>
162.60 + <outputDirectory>/</outputDirectory>
162.61 + <destName>index.xhtml</destName>
162.62 + </file>
162.63 + </files>
162.64 +
162.65 +</assembly>
162.66 \ No newline at end of file
163.1 --- a/javaquery/demo-calculator-dynamic/src/main/resources/org/apidesign/bck2brwsr/demo/calc/Calculator.xhtml Fri Jan 25 15:08:24 2013 +0100
163.2 +++ b/javaquery/demo-calculator-dynamic/src/main/resources/org/apidesign/bck2brwsr/demo/calc/Calculator.xhtml Sun Feb 17 17:58:34 2013 +0100
163.3 @@ -78,9 +78,9 @@
163.4 </table>
163.5 <div data-bind="text: displayPreview"></div>
163.6
163.7 - <script src="/bck2brwsr.js"></script>
163.8 - <script src="/vm.js"></script>
163.9 + <script src="bck2brwsr.js"></script>
163.10 <script type="text/javascript">
163.11 + var vm = bck2brwsr('demo.calculator-0.3-SNAPSHOT.jar');
163.12 vm.loadClass('org.apidesign.bck2brwsr.demo.calc.Calc');
163.13 </script>
163.14
164.1 --- a/javaquery/demo-calculator/nbactions.xml Fri Jan 25 15:08:24 2013 +0100
164.2 +++ b/javaquery/demo-calculator/nbactions.xml Sun Feb 17 17:58:34 2013 +0100
164.3 @@ -22,8 +22,11 @@
164.4 <action>
164.5 <actionName>run</actionName>
164.6 <goals>
164.7 - <goal>process-classes</goal>
164.8 - <goal>org.codehaus.mojo:exec-maven-plugin:1.2.1:exec</goal>
164.9 + <goal>package</goal>
164.10 + <goal>org.apidesign.bck2brwsr:mojo:0.3-SNAPSHOT:brwsr</goal>
164.11 </goals>
164.12 + <properties>
164.13 + <skipTests>true</skipTests>
164.14 + </properties>
164.15 </action>
164.16 - </actions>
164.17 +</actions>
165.1 --- a/javaquery/demo-calculator/pom.xml Fri Jan 25 15:08:24 2013 +0100
165.2 +++ b/javaquery/demo-calculator/pom.xml Sun Feb 17 17:58:34 2013 +0100
165.3 @@ -16,34 +16,20 @@
165.4 </properties>
165.5 <build>
165.6 <plugins>
165.7 - <plugin>
165.8 - <groupId>org.apidesign.bck2brwsr</groupId>
165.9 - <artifactId>mojo</artifactId>
165.10 - <version>0.3-SNAPSHOT</version>
165.11 - <executions>
165.12 - <execution>
165.13 - <goals>
165.14 - <goal>j2js</goal>
165.15 - </goals>
165.16 - </execution>
165.17 - </executions>
165.18 - </plugin>
165.19 <plugin>
165.20 - <groupId>org.codehaus.mojo</groupId>
165.21 - <artifactId>exec-maven-plugin</artifactId>
165.22 - <version>1.2.1</version>
165.23 + <groupId>org.apidesign.bck2brwsr</groupId>
165.24 + <artifactId>mojo</artifactId>
165.25 + <version>0.3-SNAPSHOT</version>
165.26 <executions>
165.27 <execution>
165.28 <goals>
165.29 - <goal>exec</goal>
165.30 + <goal>brwsr</goal>
165.31 </goals>
165.32 </execution>
165.33 </executions>
165.34 <configuration>
165.35 - <executable>xdg-open</executable>
165.36 - <arguments>
165.37 - <argument>${project.build.directory}/classes/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml</argument>
165.38 - </arguments>
165.39 + <directory>${project.build.directory}/${project.build.finalName}-bck2brwsr/public_html/</directory>
165.40 + <startpage>index.xhtml</startpage>
165.41 </configuration>
165.42 </plugin>
165.43 <plugin>
165.44 @@ -55,19 +41,67 @@
165.45 <target>1.7</target>
165.46 </configuration>
165.47 </plugin>
165.48 + <plugin>
165.49 + <groupId>org.apache.maven.plugins</groupId>
165.50 + <artifactId>maven-jar-plugin</artifactId>
165.51 + <version>2.4</version>
165.52 + <configuration>
165.53 + <archive>
165.54 + <manifest>
165.55 + <addClasspath>true</addClasspath>
165.56 + <classpathPrefix>lib/</classpathPrefix>
165.57 + </manifest>
165.58 + </archive>
165.59 + </configuration>
165.60 + </plugin>
165.61 + <plugin>
165.62 + <artifactId>maven-assembly-plugin</artifactId>
165.63 + <version>2.4</version>
165.64 + <executions>
165.65 + <execution>
165.66 + <id>distro-assembly</id>
165.67 + <phase>package</phase>
165.68 + <goals>
165.69 + <goal>single</goal>
165.70 + </goals>
165.71 + <configuration>
165.72 + <descriptors>
165.73 + <descriptor>src/main/assembly/bck2brwsr.xml</descriptor>
165.74 + </descriptors>
165.75 + </configuration>
165.76 + </execution>
165.77 + </executions>
165.78 + </plugin>
165.79 + <plugin>
165.80 + <groupId>org.apache.maven.plugins</groupId>
165.81 + <artifactId>maven-deploy-plugin</artifactId>
165.82 + <version>2.7</version>
165.83 + <configuration>
165.84 + <skip>true</skip>
165.85 + </configuration>
165.86 + </plugin>
165.87 </plugins>
165.88 </build>
165.89
165.90 <dependencies>
165.91 <dependency>
165.92 <groupId>org.apidesign.bck2brwsr</groupId>
165.93 - <artifactId>emul.mini</artifactId>
165.94 + <artifactId>emul</artifactId>
165.95 <version>0.3-SNAPSHOT</version>
165.96 + <classifier>rt</classifier>
165.97 </dependency>
165.98 <dependency>
165.99 <groupId>org.apidesign.bck2brwsr</groupId>
165.100 <artifactId>javaquery.api</artifactId>
165.101 <version>0.3-SNAPSHOT</version>
165.102 </dependency>
165.103 + <dependency>
165.104 + <groupId>org.apidesign.bck2brwsr</groupId>
165.105 + <artifactId>vm4brwsr</artifactId>
165.106 + <classifier>js</classifier>
165.107 + <type>zip</type>
165.108 + <version>0.3-SNAPSHOT</version>
165.109 + <scope>provided</scope>
165.110 + </dependency>
165.111 </dependencies>
165.112 </project>
166.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
166.2 +++ b/javaquery/demo-calculator/src/main/assembly/bck2brwsr.xml Sun Feb 17 17:58:34 2013 +0100
166.3 @@ -0,0 +1,62 @@
166.4 +<?xml version="1.0"?>
166.5 +<!--
166.6 +
166.7 + Back 2 Browser Bytecode Translator
166.8 + Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
166.9 +
166.10 + This program is free software: you can redistribute it and/or modify
166.11 + it under the terms of the GNU General Public License as published by
166.12 + the Free Software Foundation, version 2 of the License.
166.13 +
166.14 + This program is distributed in the hope that it will be useful,
166.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of
166.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
166.17 + GNU General Public License for more details.
166.18 +
166.19 + You should have received a copy of the GNU General Public License
166.20 + along with this program. Look for COPYING file in the top folder.
166.21 + If not, see http://opensource.org/licenses/GPL-2.0.
166.22 +
166.23 +-->
166.24 +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
166.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">
166.26 +
166.27 + <id>bck2brwsr</id>
166.28 + <formats>
166.29 + <format>zip</format>
166.30 + <format>dir</format>
166.31 + </formats>
166.32 + <baseDirectory>public_html</baseDirectory>
166.33 + <dependencySets>
166.34 + <dependencySet>
166.35 + <useProjectArtifact>false</useProjectArtifact>
166.36 + <scope>runtime</scope>
166.37 + <outputDirectory>lib</outputDirectory>
166.38 + <includes>
166.39 + <include>*:jar</include>
166.40 + <include>*:rt</include>
166.41 + </includes>
166.42 + </dependencySet>
166.43 + <dependencySet>
166.44 + <useProjectArtifact>false</useProjectArtifact>
166.45 + <scope>provided</scope>
166.46 + <includes>
166.47 + <include>*:js</include>
166.48 + </includes>
166.49 + <unpack>true</unpack>
166.50 + <outputDirectory>/</outputDirectory>
166.51 + </dependencySet>
166.52 + </dependencySets>
166.53 + <files>
166.54 + <file>
166.55 + <source>${project.build.directory}/${project.build.finalName}.jar</source>
166.56 + <outputDirectory>/</outputDirectory>
166.57 + </file>
166.58 + <file>
166.59 + <source>${project.build.directory}/classes/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml</source>
166.60 + <outputDirectory>/</outputDirectory>
166.61 + <destName>index.xhtml</destName>
166.62 + </file>
166.63 + </files>
166.64 +
166.65 +</assembly>
166.66 \ No newline at end of file
167.1 --- a/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml Fri Jan 25 15:08:24 2013 +0100
167.2 +++ b/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml Sun Feb 17 17:58:34 2013 +0100
167.3 @@ -77,78 +77,10 @@
167.4 </tbody>
167.5 </table>
167.6 <div data-bind="text: displayPreview"></div>
167.7 - <script src="bootjava.js"/>
167.8 -
167.9 - <hr/>
167.10 - <pre>
167.11 - <span class="keyword-directive">package</span> org.apidesign.bck2brwsr.mavenhtml;
167.12 -
167.13 - <span class="keyword-directive">import</span> org.apidesign.bck2brwsr.htmlpage.api.OnClick;
167.14 - <span class="keyword-directive">import</span> org.apidesign.bck2brwsr.htmlpage.api.Page;
167.15 -
167.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>
167.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>
167.18 - <span class="comment"> * </span><span class="comment">an XHTML page and Java.</span>
167.19 - <span class="comment"> * </span>
167.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>
167.21 - <span class="comment">*/</span>
167.22 - @Page(xhtml=<span class="string">"</span><span class="string">Calculator.xhtml</span><span class="string">"</span>)
167.23 - <span class="keyword-directive">public</span> <span class="keyword-directive">class</span> App {
167.24 - <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> <span class="keyword-directive">double</span> memory;
167.25 - <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> String operation;
167.26 -
167.27 - @OnClick(id=<span class="string">"</span><span class="string">clear</span><span class="string">"</span>)
167.28 - <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> clear() {
167.29 - memory = <span class="number">0</span>;
167.30 - operation = <span class="keyword-directive">null</span>;
167.31 - Calculator.DISPLAY.setValue(<span class="string">"</span><span class="string">0</span><span class="string">"</span>);
167.32 - }
167.33 -
167.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> })
167.35 - <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> applyOp(String op) {
167.36 - memory = getValue();
167.37 - operation = op;
167.38 - Calculator.DISPLAY.setValue(<span class="string">"</span><span class="string">0</span><span class="string">"</span>);
167.39 - }
167.40 -
167.41 - @OnClick(id=<span class="string">"</span><span class="string">result</span><span class="string">"</span>)
167.42 - <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> computeTheValue() {
167.43 - <span class="keyword-directive">switch</span> (operation) {
167.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>;
167.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>;
167.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>;
167.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>;
167.48 - <span class="keyword-directive">default</span>: <span class="keyword-directive">throw</span> <span class="keyword-directive">new</span> IllegalStateException(operation);
167.49 - }
167.50 - }
167.51 -
167.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>})
167.53 - <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> addDigit(String digit) {
167.54 - digit = digit.substring(<span class="number">1</span>);
167.55 - String v = Calculator.DISPLAY.getValue();
167.56 - <span class="keyword-directive">if</span> (getValue() == <span class="number">0.0</span>) {
167.57 - Calculator.DISPLAY.setValue(digit);
167.58 - } <span class="keyword-directive">else</span> {
167.59 - Calculator.DISPLAY.setValue(v + digit);
167.60 - }
167.61 - }
167.62 -
167.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) {
167.64 - StringBuilder sb = <span class="keyword-directive">new</span> StringBuilder();
167.65 - sb.append(v);
167.66 - Calculator.DISPLAY.setValue(sb.toString());
167.67 - }
167.68 -
167.69 - <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> <span class="keyword-directive">double</span> getValue() {
167.70 - <span class="keyword-directive">try</span> {
167.71 - <span class="keyword-directive">return</span> Double.parseDouble(Calculator.DISPLAY.getValue());
167.72 - } <span class="keyword-directive">catch</span> (NumberFormatException ex) {
167.73 - Calculator.DISPLAY.setValue(<span class="string">"</span><span class="string">err</span><span class="string">"</span>);
167.74 - <span class="keyword-directive">return</span> <span class="number">0.0</span>;
167.75 - }
167.76 - }
167.77 - }
167.78 -
167.79 - </pre>
167.80 + <script src="bck2brwsr.js"/>
167.81 + <script>
167.82 + var vm = bck2brwsr('demo.static.calculator-0.3-SNAPSHOT.jar');
167.83 + vm.loadClass('org.apidesign.bck2brwsr.demo.calc.staticcompilation.Calc');
167.84 + </script>
167.85 </body>
167.86 </html>
168.1 --- a/launcher/pom.xml Fri Jan 25 15:08:24 2013 +0100
168.2 +++ b/launcher/pom.xml Sun Feb 17 17:58:34 2013 +0100
168.3 @@ -23,6 +23,14 @@
168.4 <target>1.7</target>
168.5 </configuration>
168.6 </plugin>
168.7 + <plugin>
168.8 + <groupId>org.apache.maven.plugins</groupId>
168.9 + <artifactId>maven-javadoc-plugin</artifactId>
168.10 + <version>2.8.1</version>
168.11 + <configuration>
168.12 + <excludePackageNames>org.apidesign.bck2brwsr.launcher.impl</excludePackageNames>
168.13 + </configuration>
168.14 + </plugin>
168.15 </plugins>
168.16 </build>
168.17 <properties>
169.1 --- a/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java Fri Jan 25 15:08:24 2013 +0100
169.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java Sun Feb 17 17:58:34 2013 +0100
169.3 @@ -39,6 +39,7 @@
169.4 import java.util.concurrent.TimeUnit;
169.5 import java.util.logging.Level;
169.6 import java.util.logging.Logger;
169.7 +import org.apidesign.bck2brwsr.launcher.InvocationContext.Resource;
169.8 import org.apidesign.vm4brwsr.Bck2Brwsr;
169.9 import org.glassfish.grizzly.PortRange;
169.10 import org.glassfish.grizzly.http.server.HttpHandler;
169.11 @@ -47,6 +48,7 @@
169.12 import org.glassfish.grizzly.http.server.Request;
169.13 import org.glassfish.grizzly.http.server.Response;
169.14 import org.glassfish.grizzly.http.server.ServerConfiguration;
169.15 +import org.glassfish.grizzly.http.util.HttpStatus;
169.16
169.17 /**
169.18 * Lightweight server to launch Bck2Brwsr applications and tests.
169.19 @@ -55,24 +57,23 @@
169.20 */
169.21 final class Bck2BrwsrLauncher extends Launcher implements Closeable {
169.22 private static final Logger LOG = Logger.getLogger(Bck2BrwsrLauncher.class.getName());
169.23 - private static final MethodInvocation END = new MethodInvocation(null, null, null);
169.24 - private Set<ClassLoader> loaders = new LinkedHashSet<>();
169.25 - private BlockingQueue<MethodInvocation> methods = new LinkedBlockingQueue<>();
169.26 + private static final InvocationContext END = new InvocationContext(null, null, null);
169.27 + private final Set<ClassLoader> loaders = new LinkedHashSet<>();
169.28 + private final BlockingQueue<InvocationContext> methods = new LinkedBlockingQueue<>();
169.29 private long timeOut;
169.30 private final Res resources = new Res();
169.31 private final String cmd;
169.32 private Object[] brwsr;
169.33 private HttpServer server;
169.34 private CountDownLatch wait;
169.35 -
169.36 +
169.37 public Bck2BrwsrLauncher(String cmd) {
169.38 this.cmd = cmd;
169.39 }
169.40
169.41 @Override
169.42 - MethodInvocation addMethod(Class<?> clazz, String method, String html) throws IOException {
169.43 - loaders.add(clazz.getClassLoader());
169.44 - MethodInvocation c = new MethodInvocation(clazz.getName(), method, html);
169.45 + InvocationContext runMethod(InvocationContext c) throws IOException {
169.46 + loaders.add(c.clazz.getClassLoader());
169.47 methods.add(c);
169.48 try {
169.49 c.await(timeOut);
169.50 @@ -94,9 +95,24 @@
169.51 if (!startpage.startsWith("/")) {
169.52 startpage = "/" + startpage;
169.53 }
169.54 - HttpServer s = initServer();
169.55 + HttpServer s = initServer(".", true);
169.56 + int last = startpage.lastIndexOf('/');
169.57 + String simpleName = startpage.substring(last);
169.58 + s.getServerConfiguration().addHttpHandler(new Page(resources, startpage), simpleName);
169.59 s.getServerConfiguration().addHttpHandler(new Page(resources, null), "/");
169.60 try {
169.61 + launchServerAndBrwsr(s, simpleName);
169.62 + } catch (URISyntaxException | InterruptedException ex) {
169.63 + throw new IOException(ex);
169.64 + }
169.65 + }
169.66 +
169.67 + void showDirectory(File dir, String startpage) throws IOException {
169.68 + if (!startpage.startsWith("/")) {
169.69 + startpage = "/" + startpage;
169.70 + }
169.71 + HttpServer s = initServer(dir.getPath(), false);
169.72 + try {
169.73 launchServerAndBrwsr(s, startpage);
169.74 } catch (URISyntaxException | InterruptedException ex) {
169.75 throw new IOException(ex);
169.76 @@ -122,37 +138,94 @@
169.77 }
169.78 }
169.79
169.80 - private HttpServer initServer() throws IOException {
169.81 - HttpServer s = HttpServer.createSimpleServer(".", new PortRange(8080, 65535));
169.82 + private HttpServer initServer(String path, boolean addClasses) throws IOException {
169.83 + HttpServer s = HttpServer.createSimpleServer(path, new PortRange(8080, 65535));
169.84
169.85 final ServerConfiguration conf = s.getServerConfiguration();
169.86 - conf.addHttpHandler(new VM(resources), "/vm.js");
169.87 - conf.addHttpHandler(new Classes(resources), "/classes/");
169.88 + if (addClasses) {
169.89 + conf.addHttpHandler(new VM(resources), "/bck2brwsr.js");
169.90 + conf.addHttpHandler(new Classes(resources), "/classes/");
169.91 + }
169.92 return s;
169.93 }
169.94
169.95 private void executeInBrowser() throws InterruptedException, URISyntaxException, IOException {
169.96 wait = new CountDownLatch(1);
169.97 - server = initServer();
169.98 - ServerConfiguration conf = server.getServerConfiguration();
169.99 + server = initServer(".", true);
169.100 + final ServerConfiguration conf = server.getServerConfiguration();
169.101 +
169.102 + class DynamicResourceHandler extends HttpHandler {
169.103 + private final InvocationContext ic;
169.104 + public DynamicResourceHandler(InvocationContext ic) {
169.105 + if (ic == null || ic.resources.isEmpty()) {
169.106 + throw new NullPointerException();
169.107 + }
169.108 + this.ic = ic;
169.109 + for (Resource r : ic.resources) {
169.110 + conf.addHttpHandler(this, r.httpPath);
169.111 + }
169.112 + }
169.113 +
169.114 + public void close() {
169.115 + conf.removeHttpHandler(this);
169.116 + }
169.117 +
169.118 + @Override
169.119 + public void service(Request request, Response response) throws Exception {
169.120 + for (Resource r : ic.resources) {
169.121 + if (r.httpPath.equals(request.getRequestURI())) {
169.122 + LOG.log(Level.INFO, "Serving HttpResource for {0}", request.getRequestURI());
169.123 + response.setContentType(r.httpType);
169.124 + copyStream(r.httpContent, response.getOutputStream(), null);
169.125 + }
169.126 + }
169.127 + }
169.128 + }
169.129 +
169.130 conf.addHttpHandler(new Page(resources,
169.131 "org/apidesign/bck2brwsr/launcher/harness.xhtml"
169.132 ), "/execute");
169.133 +
169.134 conf.addHttpHandler(new HttpHandler() {
169.135 int cnt;
169.136 - List<MethodInvocation> cases = new ArrayList<>();
169.137 + List<InvocationContext> cases = new ArrayList<>();
169.138 + DynamicResourceHandler prev;
169.139 @Override
169.140 public void service(Request request, Response response) throws Exception {
169.141 String id = request.getParameter("request");
169.142 String value = request.getParameter("result");
169.143
169.144 +
169.145 + InvocationContext mi = null;
169.146 + int caseNmbr = -1;
169.147 +
169.148 if (id != null && value != null) {
169.149 LOG.log(Level.INFO, "Received result for case {0} = {1}", new Object[]{id, value});
169.150 value = decodeURL(value);
169.151 - cases.get(Integer.parseInt(id)).result(value, null);
169.152 + int indx = Integer.parseInt(id);
169.153 + cases.get(indx).result(value, null);
169.154 + if (++indx < cases.size()) {
169.155 + mi = cases.get(indx);
169.156 + LOG.log(Level.INFO, "Re-executing case {0}", indx);
169.157 + caseNmbr = indx;
169.158 + }
169.159 + } else {
169.160 + if (!cases.isEmpty()) {
169.161 + LOG.info("Re-executing test cases");
169.162 + mi = cases.get(0);
169.163 + caseNmbr = 0;
169.164 + }
169.165 }
169.166
169.167 - MethodInvocation mi = methods.take();
169.168 + if (prev != null) {
169.169 + prev.close();
169.170 + prev = null;
169.171 + }
169.172 +
169.173 + if (mi == null) {
169.174 + mi = methods.take();
169.175 + caseNmbr = cnt++;
169.176 + }
169.177 if (mi == END) {
169.178 response.getWriter().write("");
169.179 wait.countDown();
169.180 @@ -161,14 +234,18 @@
169.181 return;
169.182 }
169.183
169.184 + if (!mi.resources.isEmpty()) {
169.185 + prev = new DynamicResourceHandler(mi);
169.186 + }
169.187 +
169.188 cases.add(mi);
169.189 - final String cn = mi.className;
169.190 + final String cn = mi.clazz.getName();
169.191 final String mn = mi.methodName;
169.192 - LOG.log(Level.INFO, "Request for {0} case. Sending {1}.{2}", new Object[]{cnt, cn, mn});
169.193 + LOG.log(Level.INFO, "Request for {0} case. Sending {1}.{2}", new Object[]{caseNmbr, cn, mn});
169.194 response.getWriter().write("{"
169.195 + "className: '" + cn + "', "
169.196 + "methodName: '" + mn + "', "
169.197 - + "request: " + cnt
169.198 + + "request: " + caseNmbr
169.199 );
169.200 if (mi.html != null) {
169.201 response.getWriter().write(", html: '");
169.202 @@ -176,7 +253,6 @@
169.203 response.getWriter().write("'");
169.204 }
169.205 response.getWriter().write("}");
169.206 - cnt++;
169.207 }
169.208 }, "/data");
169.209
169.210 @@ -236,10 +312,10 @@
169.211 if (ch == '$' && params.length > 0) {
169.212 int cnt = is.read() - '0';
169.213 if (cnt == 'U' - '0') {
169.214 - os.write(baseURL.getBytes());
169.215 + os.write(baseURL.getBytes("UTF-8"));
169.216 }
169.217 if (cnt >= 0 && cnt < params.length) {
169.218 - os.write(params[cnt].getBytes());
169.219 + os.write(params[cnt].getBytes("UTF-8"));
169.220 }
169.221 } else {
169.222 os.write(ch);
169.223 @@ -378,9 +454,9 @@
169.224 String r = resource;
169.225 if (r == null) {
169.226 r = request.getHttpHandlerPath();
169.227 - if (r.startsWith("/")) {
169.228 - r = r.substring(1);
169.229 - }
169.230 + }
169.231 + if (r.startsWith("/")) {
169.232 + r = r.substring(1);
169.233 }
169.234 String[] replace = {};
169.235 if (r.endsWith(".html")) {
169.236 @@ -411,14 +487,22 @@
169.237 StringBuilder sb = new StringBuilder();
169.238 Bck2Brwsr.generate(sb, loader);
169.239 sb.append(
169.240 - "function ldCls(res) {\n"
169.241 - + " var request = new XMLHttpRequest();\n"
169.242 - + " request.open('GET', '/classes/' + res, false);\n"
169.243 - + " request.send();\n"
169.244 - + " var arr = eval('(' + request.responseText + ')');\n"
169.245 - + " return arr;\n"
169.246 - + "}\n"
169.247 - + "var vm = new bck2brwsr(ldCls);\n"
169.248 + "(function WrapperVM(global) {"
169.249 + + " function ldCls(res) {\n"
169.250 + + " var request = new XMLHttpRequest();\n"
169.251 + + " request.open('GET', '/classes/' + res, false);\n"
169.252 + + " request.send();\n"
169.253 + + " if (request.status !== 200) return null;\n"
169.254 + + " var arr = eval('(' + request.responseText + ')');\n"
169.255 + + " return arr;\n"
169.256 + + " }\n"
169.257 + + " var prevvm = global.bck2brwsr;\n"
169.258 + + " global.bck2brwsr = function() {\n"
169.259 + + " var args = Array.prototype.slice.apply(arguments);\n"
169.260 + + " args.unshift(ldCls);\n"
169.261 + + " return prevvm.apply(null, args);\n"
169.262 + + " };\n"
169.263 + + "})(this);\n"
169.264 );
169.265 this.bck2brwsr = sb.toString();
169.266 }
169.267 @@ -466,6 +550,7 @@
169.268 }
169.269 w.append("\n]");
169.270 } catch (IOException ex) {
169.271 + response.setStatus(HttpStatus.NOT_FOUND_404);
169.272 response.setError();
169.273 response.setDetailMessage(ex.getMessage());
169.274 }
170.1 --- a/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Console.java Fri Jan 25 15:08:24 2013 +0100
170.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
170.3 @@ -1,253 +0,0 @@
170.4 -/**
170.5 - * Back 2 Browser Bytecode Translator
170.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
170.7 - *
170.8 - * This program is free software: you can redistribute it and/or modify
170.9 - * it under the terms of the GNU General Public License as published by
170.10 - * the Free Software Foundation, version 2 of the License.
170.11 - *
170.12 - * This program is distributed in the hope that it will be useful,
170.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
170.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
170.15 - * GNU General Public License for more details.
170.16 - *
170.17 - * You should have received a copy of the GNU General Public License
170.18 - * along with this program. Look for COPYING file in the top folder.
170.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
170.20 - */
170.21 -package org.apidesign.bck2brwsr.launcher;
170.22 -
170.23 -import java.io.IOException;
170.24 -import java.io.InputStream;
170.25 -import java.lang.reflect.InvocationTargetException;
170.26 -import java.lang.reflect.Method;
170.27 -import java.lang.reflect.Modifier;
170.28 -import java.net.URL;
170.29 -import java.util.Enumeration;
170.30 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
170.31 -
170.32 -/**
170.33 - *
170.34 - * @author Jaroslav Tulach <jtulach@netbeans.org>
170.35 - */
170.36 -public class Console {
170.37 - static {
170.38 - turnAssetionStatusOn();
170.39 - }
170.40 -
170.41 - @JavaScriptBody(args = {"id", "attr"}, body =
170.42 - "return window.document.getElementById(id)[attr].toString();")
170.43 - private static native Object getAttr(String id, String attr);
170.44 -
170.45 - @JavaScriptBody(args = {"id", "attr", "value"}, body =
170.46 - "window.document.getElementById(id)[attr] = value;")
170.47 - private static native void setAttr(String id, String attr, Object value);
170.48 -
170.49 - @JavaScriptBody(args = {}, body = "return; window.close();")
170.50 - private static native void closeWindow();
170.51 -
170.52 - private static void log(String newText) {
170.53 - String id = "bck2brwsr.result";
170.54 - String attr = "value";
170.55 - setAttr(id, attr, getAttr(id, attr) + "\n" + newText);
170.56 - setAttr(id, "scrollTop", getAttr(id, "scrollHeight"));
170.57 - }
170.58 -
170.59 - public static void execute() throws Exception {
170.60 - String clazz = (String) getAttr("clazz", "value");
170.61 - String method = (String) getAttr("method", "value");
170.62 - Object res = invokeMethod(clazz, method);
170.63 - setAttr("bck2brwsr.result", "value", res);
170.64 - }
170.65 -
170.66 - @JavaScriptBody(args = { "url", "callback", "arr" }, body = ""
170.67 - + "var request = new XMLHttpRequest();\n"
170.68 - + "request.open('GET', url, true);\n"
170.69 - + "request.onreadystatechange = function() {\n"
170.70 - + " if (this.readyState!==4) return;\n"
170.71 - + " arr[0] = this.responseText;\n"
170.72 - + " callback.run__V();\n"
170.73 - + "};"
170.74 - + "request.send();"
170.75 - )
170.76 - private static native void loadText(String url, Runnable callback, String[] arr) throws IOException;
170.77 -
170.78 - public static void harness(String url) throws IOException {
170.79 - log("Connecting to " + url);
170.80 - Request r = new Request(url);
170.81 - }
170.82 -
170.83 - private static class Request implements Runnable {
170.84 - private final String[] arr = { null };
170.85 - private final String url;
170.86 -
170.87 - private Request(String url) throws IOException {
170.88 - this.url = url;
170.89 - loadText(url, this, arr);
170.90 - }
170.91 -
170.92 - @Override
170.93 - public void run() {
170.94 - try {
170.95 - String data = arr[0];
170.96 - log("\nGot \"" + data + "\"");
170.97 -
170.98 - if (data == null) {
170.99 - log("Some error exiting");
170.100 - closeWindow();
170.101 - return;
170.102 - }
170.103 -
170.104 - if (data.isEmpty()) {
170.105 - log("No data, exiting");
170.106 - closeWindow();
170.107 - return;
170.108 - }
170.109 -
170.110 - Case c = Case.parseData(data);
170.111 - if (c.getHtmlFragment() != null) {
170.112 - setAttr("bck2brwsr.fragment", "innerHTML", c.getHtmlFragment());
170.113 - }
170.114 - log("Invoking " + c.getClassName() + '.' + c.getMethodName() + " as request: " + c.getRequestId());
170.115 -
170.116 - Object result = invokeMethod(c.getClassName(), c.getMethodName());
170.117 -
170.118 - setAttr("bck2brwsr.fragment", "innerHTML", "");
170.119 - log("Result: " + result);
170.120 -
170.121 - result = encodeURL("" + result);
170.122 -
170.123 - log("Sending back: " + url + "?request=" + c.getRequestId() + "&result=" + result);
170.124 - String u = url + "?request=" + c.getRequestId() + "&result=" + result;
170.125 -
170.126 - loadText(u, this, arr);
170.127 -
170.128 - } catch (Exception ex) {
170.129 - log(ex.getMessage());
170.130 - }
170.131 - }
170.132 - }
170.133 -
170.134 - private static String encodeURL(String r) {
170.135 - StringBuilder sb = new StringBuilder();
170.136 - for (int i = 0; i < r.length(); i++) {
170.137 - int ch = r.charAt(i);
170.138 - if (ch < 32 || ch == '%' || ch == '+') {
170.139 - sb.append("%").append(("0" + Integer.toHexString(ch)).substring(0, 2));
170.140 - } else {
170.141 - if (ch == 32) {
170.142 - sb.append("+");
170.143 - } else {
170.144 - sb.append((char)ch);
170.145 - }
170.146 - }
170.147 - }
170.148 - return sb.toString();
170.149 - }
170.150 -
170.151 - static String invoke(String clazz, String method) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException, InstantiationException {
170.152 - final Object r = invokeMethod(clazz, method);
170.153 - return r == null ? "null" : r.toString().toString();
170.154 - }
170.155 -
170.156 - /** Helper method that inspects the classpath and loads given resource
170.157 - * (usually a class file). Used while running tests in Rhino.
170.158 - *
170.159 - * @param name resource name to find
170.160 - * @return the array of bytes in the given resource
170.161 - * @throws IOException I/O in case something goes wrong
170.162 - */
170.163 - public static byte[] read(String name) throws IOException {
170.164 - URL u = null;
170.165 - Enumeration<URL> en = Console.class.getClassLoader().getResources(name);
170.166 - while (en.hasMoreElements()) {
170.167 - u = en.nextElement();
170.168 - }
170.169 - if (u == null) {
170.170 - throw new IOException("Can't find " + name);
170.171 - }
170.172 - try (InputStream is = u.openStream()) {
170.173 - byte[] arr;
170.174 - arr = new byte[is.available()];
170.175 - int offset = 0;
170.176 - while (offset < arr.length) {
170.177 - int len = is.read(arr, offset, arr.length - offset);
170.178 - if (len == -1) {
170.179 - throw new IOException("Can't read " + name);
170.180 - }
170.181 - offset += len;
170.182 - }
170.183 - return arr;
170.184 - }
170.185 - }
170.186 -
170.187 - private static Object invokeMethod(String clazz, String method)
170.188 - throws ClassNotFoundException, InvocationTargetException,
170.189 - SecurityException, IllegalAccessException, IllegalArgumentException,
170.190 - InstantiationException {
170.191 - Method found = null;
170.192 - Class<?> c = Class.forName(clazz);
170.193 - for (Method m : c.getMethods()) {
170.194 - if (m.getName().equals(method)) {
170.195 - found = m;
170.196 - }
170.197 - }
170.198 - Object res;
170.199 - if (found != null) {
170.200 - try {
170.201 - if ((found.getModifiers() & Modifier.STATIC) != 0) {
170.202 - res = found.invoke(null);
170.203 - } else {
170.204 - res = found.invoke(c.newInstance());
170.205 - }
170.206 - } catch (Throwable ex) {
170.207 - res = ex.getClass().getName() + ":" + ex.getMessage();
170.208 - }
170.209 - } else {
170.210 - res = "Can't find method " + method + " in " + clazz;
170.211 - }
170.212 - return res;
170.213 - }
170.214 -
170.215 - @JavaScriptBody(args = {}, body = "vm.desiredAssertionStatus = true;")
170.216 - private static void turnAssetionStatusOn() {
170.217 - }
170.218 -
170.219 - private static final class Case {
170.220 - private final Object data;
170.221 -
170.222 - private Case(Object data) {
170.223 - this.data = data;
170.224 - }
170.225 -
170.226 - public static Case parseData(String s) {
170.227 - return new Case(toJSON(s));
170.228 - }
170.229 -
170.230 - public String getMethodName() {
170.231 - return value("methodName", data);
170.232 - }
170.233 -
170.234 - public String getClassName() {
170.235 - return value("className", data);
170.236 - }
170.237 -
170.238 - public String getRequestId() {
170.239 - return value("request", data);
170.240 - }
170.241 -
170.242 - public String getHtmlFragment() {
170.243 - return value("html", data);
170.244 - }
170.245 -
170.246 - @JavaScriptBody(args = "s", body = "return eval('(' + s + ')');")
170.247 - private static native Object toJSON(String s);
170.248 -
170.249 - @JavaScriptBody(args = {"p", "d"}, body =
170.250 - "var v = d[p];\n"
170.251 - + "if (typeof v === 'undefined') return null;\n"
170.252 - + "return v.toString();"
170.253 - )
170.254 - private static native String value(String p, Object d);
170.255 - }
170.256 -}
171.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
171.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/InvocationContext.java Sun Feb 17 17:58:34 2013 +0100
171.3 @@ -0,0 +1,110 @@
171.4 +/**
171.5 + * Back 2 Browser Bytecode Translator
171.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
171.7 + *
171.8 + * This program is free software: you can redistribute it and/or modify
171.9 + * it under the terms of the GNU General Public License as published by
171.10 + * the Free Software Foundation, version 2 of the License.
171.11 + *
171.12 + * This program is distributed in the hope that it will be useful,
171.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
171.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
171.15 + * GNU General Public License for more details.
171.16 + *
171.17 + * You should have received a copy of the GNU General Public License
171.18 + * along with this program. Look for COPYING file in the top folder.
171.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
171.20 + */
171.21 +package org.apidesign.bck2brwsr.launcher;
171.22 +
171.23 +import java.io.IOException;
171.24 +import java.io.InputStream;
171.25 +import java.util.ArrayList;
171.26 +import java.util.List;
171.27 +import java.util.concurrent.CountDownLatch;
171.28 +import java.util.concurrent.TimeUnit;
171.29 +
171.30 +/** Represents individual method invocation, its context and its result.
171.31 + *
171.32 + * @author Jaroslav Tulach <jtulach@netbeans.org>
171.33 + */
171.34 +public final class InvocationContext {
171.35 + final CountDownLatch wait = new CountDownLatch(1);
171.36 + final Class<?> clazz;
171.37 + final String methodName;
171.38 + private final Launcher launcher;
171.39 + private String result;
171.40 + private Throwable exception;
171.41 + String html;
171.42 + final List<Resource> resources = new ArrayList<>();
171.43 +
171.44 + InvocationContext(Launcher launcher, Class<?> clazz, String methodName) {
171.45 + this.launcher = launcher;
171.46 + this.clazz = clazz;
171.47 + this.methodName = methodName;
171.48 + }
171.49 +
171.50 + /** An HTML fragment to be available for the execution. Useful primarily when
171.51 + * executing in a browser via {@link Launcher#createBrowser(java.lang.String)}.
171.52 + * @param html the html fragment
171.53 + */
171.54 + public void setHtmlFragment(String html) {
171.55 + this.html = html;
171.56 + }
171.57 +
171.58 + /** HTTP resource to be available during execution. An invocation may
171.59 + * perform an HTTP query and obtain a resource relative to the page.
171.60 + */
171.61 + public void addHttpResource(String relativePath, String mimeType, InputStream content) {
171.62 + if (relativePath == null || mimeType == null || content == null) {
171.63 + throw new NullPointerException();
171.64 + }
171.65 + resources.add(new Resource(content, mimeType, relativePath));
171.66 + }
171.67 +
171.68 + /** Invokes the associated method.
171.69 + * @return the textual result of the invocation
171.70 + */
171.71 + public String invoke() throws IOException {
171.72 + launcher.runMethod(this);
171.73 + return toString();
171.74 + }
171.75 +
171.76 + /** Obtains textual result of the invocation.
171.77 + * @return text representing the exception or result value
171.78 + */
171.79 + @Override
171.80 + public String toString() {
171.81 + if (exception != null) {
171.82 + return exception.toString();
171.83 + }
171.84 + return result;
171.85 + }
171.86 +
171.87 + /**
171.88 + * @param timeOut
171.89 + * @throws InterruptedException
171.90 + */
171.91 + void await(long timeOut) throws InterruptedException {
171.92 + wait.await(timeOut, TimeUnit.MILLISECONDS);
171.93 + }
171.94 +
171.95 + void result(String r, Throwable e) {
171.96 + this.result = r;
171.97 + this.exception = e;
171.98 + wait.countDown();
171.99 + }
171.100 +
171.101 +
171.102 + static final class Resource {
171.103 + final InputStream httpContent;
171.104 + final String httpType;
171.105 + final String httpPath;
171.106 +
171.107 + Resource(InputStream httpContent, String httpType, String httpPath) {
171.108 + this.httpContent = httpContent;
171.109 + this.httpType = httpType;
171.110 + this.httpPath = httpPath;
171.111 + }
171.112 + }
171.113 +}
172.1 --- a/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/JSLauncher.java Fri Jan 25 15:08:24 2013 +0100
172.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/JSLauncher.java Sun Feb 17 17:58:34 2013 +0100
172.3 @@ -17,12 +17,14 @@
172.4 */
172.5 package org.apidesign.bck2brwsr.launcher;
172.6
172.7 +import org.apidesign.bck2brwsr.launcher.impl.Console;
172.8 import java.io.IOException;
172.9 import java.io.InputStream;
172.10 import java.net.URL;
172.11 import java.util.Enumeration;
172.12 import java.util.LinkedHashSet;
172.13 import java.util.Set;
172.14 +import java.util.logging.Level;
172.15 import java.util.logging.Logger;
172.16 import javax.script.Invocable;
172.17 import javax.script.ScriptEngine;
172.18 @@ -42,14 +44,18 @@
172.19 private Object console;
172.20
172.21
172.22 - @Override MethodInvocation addMethod(Class<?> clazz, String method, String html) {
172.23 - loaders.add(clazz.getClassLoader());
172.24 - MethodInvocation mi = new MethodInvocation(clazz.getName(), method, html);
172.25 + @Override InvocationContext runMethod(InvocationContext mi) {
172.26 + loaders.add(mi.clazz.getClassLoader());
172.27 try {
172.28 - mi.result(code.invokeMethod(
172.29 + long time = System.currentTimeMillis();
172.30 + LOG.log(Level.FINE, "Invoking {0}.{1}", new Object[]{mi.clazz.getName(), mi.methodName});
172.31 + String res = code.invokeMethod(
172.32 console,
172.33 "invoke__Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2",
172.34 - mi.className, mi.methodName).toString(), null);
172.35 + mi.clazz.getName(), mi.methodName).toString();
172.36 + time = System.currentTimeMillis() - time;
172.37 + LOG.log(Level.FINE, "Resut of {0}.{1} = {2} in {3} ms", new Object[]{mi.clazz.getName(), mi.methodName, res, time});
172.38 + mi.result(res, null);
172.39 } catch (ScriptException | NoSuchMethodException ex) {
172.40 mi.result(null, ex);
172.41 }
172.42 @@ -83,7 +89,7 @@
172.43 ScriptEngine mach = sem.getEngineByExtension("js");
172.44
172.45 sb.append(
172.46 - "\nvar vm = new bck2brwsr(org.apidesign.bck2brwsr.launcher.Console.read);"
172.47 + "\nvar vm = new bck2brwsr(org.apidesign.bck2brwsr.launcher.impl.Console.read);"
172.48 + "\nfunction initVM() { return vm; };"
172.49 + "\n");
172.50
173.1 --- a/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java Fri Jan 25 15:08:24 2013 +0100
173.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java Sun Feb 17 17:58:34 2013 +0100
173.3 @@ -18,12 +18,14 @@
173.4 package org.apidesign.bck2brwsr.launcher;
173.5
173.6 import java.io.Closeable;
173.7 +import java.io.File;
173.8 import java.io.IOException;
173.9 import java.net.URLClassLoader;
173.10 import org.apidesign.vm4brwsr.Bck2Brwsr;
173.11
173.12 /** An abstraction for executing tests in a Bck2Brwsr virtual machine.
173.13 - * Either in JavaScript engine, or in external browser.
173.14 + * Either in {@linkm Launcher#createJavaScript JavaScript engine},
173.15 + * or in {@linkm Launcher#createBrowser external browser}.
173.16 *
173.17 * @author Jaroslav Tulach <jtulach@netbeans.org>
173.18 */
173.19 @@ -31,33 +33,83 @@
173.20
173.21 Launcher() {
173.22 }
173.23 +
173.24 + /** Initializes the launcher. This may mean starting a web browser or
173.25 + * initializing execution engine.
173.26 + * @throws IOException if something goes wrong
173.27 + */
173.28 + public abstract void initialize() throws IOException;
173.29
173.30 - abstract MethodInvocation addMethod(Class<?> clazz, String method, String html) throws IOException;
173.31 -
173.32 - public abstract void initialize() throws IOException;
173.33 + /** Shuts down the launcher.
173.34 + * @throws IOException if something goes wrong
173.35 + */
173.36 public abstract void shutdown() throws IOException;
173.37 - public MethodInvocation invokeMethod(Class<?> clazz, String method, String html) throws IOException {
173.38 - return addMethod(clazz, method, html);
173.39 +
173.40 +
173.41 + /** Builds an invocation context. The context can later be customized
173.42 + * and {@link InvocationContext#invoke() invoked}.
173.43 + *
173.44 + * @param clazz the class to execute method from
173.45 + * @param method the method to execute
173.46 + * @return the context pointing to the selected method
173.47 + */
173.48 + public InvocationContext createInvocation(Class<?> clazz, String method) {
173.49 + return new InvocationContext(this, clazz, method);
173.50 }
173.51
173.52 -
173.53
173.54 + /** Creates launcher that uses internal JavaScript engine (Rhino).
173.55 + * @return the launcher
173.56 + */
173.57 public static Launcher createJavaScript() {
173.58 final JSLauncher l = new JSLauncher();
173.59 l.addClassLoader(Bck2Brwsr.class.getClassLoader());
173.60 return l;
173.61 }
173.62
173.63 + /** Creates launcher that is using external browser.
173.64 + *
173.65 + * @param cmd <code>null</code> to use <code>java.awt.Desktop</code> to show the launcher
173.66 + * or a string to execute in an external process (with a parameter to the URL)
173.67 + * @return launcher executing in external browser.
173.68 + */
173.69 public static Launcher createBrowser(String cmd) {
173.70 final Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(cmd);
173.71 l.addClassLoader(Bck2Brwsr.class.getClassLoader());
173.72 l.setTimeout(180000);
173.73 return l;
173.74 }
173.75 +
173.76 + /** Starts an HTTP server which provides access to classes and resources
173.77 + * available in the <code>classes</code> URL and shows a start page
173.78 + * available as {@link ClassLoader#getResource(java.lang.String)} from the
173.79 + * provide classloader. Opens a browser with URL showing the start page.
173.80 + *
173.81 + * @param classes classloader offering access to classes and resources
173.82 + * @param startpage page to show in the browser
173.83 + * @return interface that allows one to stop the server
173.84 + * @throws IOException if something goes wrong
173.85 + */
173.86 public static Closeable showURL(URLClassLoader classes, String startpage) throws IOException {
173.87 Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(null);
173.88 l.addClassLoader(classes);
173.89 l.showURL(startpage);
173.90 return l;
173.91 }
173.92 + /** Starts an HTTP server which provides access to certain directory.
173.93 + * The <code>startpage</code> should be relative location inside the root
173.94 + * driecotry
173.95 + * Opens a browser with URL showing the start page.
173.96 + *
173.97 + * @param directory the root directory on disk
173.98 + * @praam startpage relative path from the root to the page
173.99 + * @exception IOException if something goes wrong.
173.100 + */
173.101 + public static Closeable showDir(File directory, String startpage) throws IOException {
173.102 + Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(null);
173.103 + l.showDirectory(directory, startpage);
173.104 + return l;
173.105 + }
173.106 +
173.107 + abstract InvocationContext runMethod(InvocationContext c) throws IOException;
173.108 }
174.1 --- a/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/MethodInvocation.java Fri Jan 25 15:08:24 2013 +0100
174.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
174.3 @@ -1,59 +0,0 @@
174.4 -/**
174.5 - * Back 2 Browser Bytecode Translator
174.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
174.7 - *
174.8 - * This program is free software: you can redistribute it and/or modify
174.9 - * it under the terms of the GNU General Public License as published by
174.10 - * the Free Software Foundation, version 2 of the License.
174.11 - *
174.12 - * This program is distributed in the hope that it will be useful,
174.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
174.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
174.15 - * GNU General Public License for more details.
174.16 - *
174.17 - * You should have received a copy of the GNU General Public License
174.18 - * along with this program. Look for COPYING file in the top folder.
174.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
174.20 - */
174.21 -package org.apidesign.bck2brwsr.launcher;
174.22 -
174.23 -import java.util.concurrent.CountDownLatch;
174.24 -import java.util.concurrent.TimeUnit;
174.25 -
174.26 -/**
174.27 - *
174.28 - * @author Jaroslav Tulach <jtulach@netbeans.org>
174.29 - */
174.30 -public final class MethodInvocation {
174.31 - final CountDownLatch wait = new CountDownLatch(1);
174.32 - final String className;
174.33 - final String methodName;
174.34 - final String html;
174.35 - private String result;
174.36 - private Throwable exception;
174.37 -
174.38 - MethodInvocation(String className, String methodName, String html) {
174.39 - this.className = className;
174.40 - this.methodName = methodName;
174.41 - this.html = html;
174.42 - }
174.43 -
174.44 - void await(long timeOut) throws InterruptedException {
174.45 - wait.await(timeOut, TimeUnit.MILLISECONDS);
174.46 - }
174.47 -
174.48 - void result(String r, Throwable e) {
174.49 - this.result = r;
174.50 - this.exception = e;
174.51 - wait.countDown();
174.52 - }
174.53 -
174.54 - @Override
174.55 - public String toString() {
174.56 - if (exception != null) {
174.57 - return exception.toString();
174.58 - }
174.59 - return result;
174.60 - }
174.61 -
174.62 -}
175.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
175.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/impl/Console.java Sun Feb 17 17:58:34 2013 +0100
175.3 @@ -0,0 +1,255 @@
175.4 +/**
175.5 + * Back 2 Browser Bytecode Translator
175.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
175.7 + *
175.8 + * This program is free software: you can redistribute it and/or modify
175.9 + * it under the terms of the GNU General Public License as published by
175.10 + * the Free Software Foundation, version 2 of the License.
175.11 + *
175.12 + * This program is distributed in the hope that it will be useful,
175.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
175.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
175.15 + * GNU General Public License for more details.
175.16 + *
175.17 + * You should have received a copy of the GNU General Public License
175.18 + * along with this program. Look for COPYING file in the top folder.
175.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
175.20 + */
175.21 +package org.apidesign.bck2brwsr.launcher.impl;
175.22 +
175.23 +import java.io.IOException;
175.24 +import java.io.InputStream;
175.25 +import java.lang.reflect.InvocationTargetException;
175.26 +import java.lang.reflect.Method;
175.27 +import java.lang.reflect.Modifier;
175.28 +import java.net.URL;
175.29 +import java.util.Enumeration;
175.30 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
175.31 +
175.32 +/**
175.33 + *
175.34 + * @author Jaroslav Tulach <jtulach@netbeans.org>
175.35 + */
175.36 +public class Console {
175.37 + private Console() {
175.38 + }
175.39 + static {
175.40 + turnAssetionStatusOn();
175.41 + }
175.42 +
175.43 + @JavaScriptBody(args = {"id", "attr"}, body =
175.44 + "return window.document.getElementById(id)[attr].toString();")
175.45 + private static native Object getAttr(String id, String attr);
175.46 +
175.47 + @JavaScriptBody(args = {"id", "attr", "value"}, body =
175.48 + "window.document.getElementById(id)[attr] = value;")
175.49 + private static native void setAttr(String id, String attr, Object value);
175.50 +
175.51 + @JavaScriptBody(args = {}, body = "return; window.close();")
175.52 + private static native void closeWindow();
175.53 +
175.54 + private static void log(String newText) {
175.55 + String id = "bck2brwsr.result";
175.56 + String attr = "value";
175.57 + setAttr(id, attr, getAttr(id, attr) + "\n" + newText);
175.58 + setAttr(id, "scrollTop", getAttr(id, "scrollHeight"));
175.59 + }
175.60 +
175.61 + public static void execute() throws Exception {
175.62 + String clazz = (String) getAttr("clazz", "value");
175.63 + String method = (String) getAttr("method", "value");
175.64 + Object res = invokeMethod(clazz, method);
175.65 + setAttr("bck2brwsr.result", "value", res);
175.66 + }
175.67 +
175.68 + @JavaScriptBody(args = { "url", "callback", "arr" }, body = ""
175.69 + + "var request = new XMLHttpRequest();\n"
175.70 + + "request.open('GET', url, true);\n"
175.71 + + "request.onreadystatechange = function() {\n"
175.72 + + " if (this.readyState!==4) return;\n"
175.73 + + " arr[0] = this.responseText;\n"
175.74 + + " callback.run__V();\n"
175.75 + + "};"
175.76 + + "request.send();"
175.77 + )
175.78 + private static native void loadText(String url, Runnable callback, String[] arr) throws IOException;
175.79 +
175.80 + public static void harness(String url) throws IOException {
175.81 + log("Connecting to " + url);
175.82 + Request r = new Request(url);
175.83 + }
175.84 +
175.85 + private static class Request implements Runnable {
175.86 + private final String[] arr = { null };
175.87 + private final String url;
175.88 +
175.89 + private Request(String url) throws IOException {
175.90 + this.url = url;
175.91 + loadText(url, this, arr);
175.92 + }
175.93 +
175.94 + @Override
175.95 + public void run() {
175.96 + try {
175.97 + String data = arr[0];
175.98 + log("\nGot \"" + data + "\"");
175.99 +
175.100 + if (data == null) {
175.101 + log("Some error exiting");
175.102 + closeWindow();
175.103 + return;
175.104 + }
175.105 +
175.106 + if (data.isEmpty()) {
175.107 + log("No data, exiting");
175.108 + closeWindow();
175.109 + return;
175.110 + }
175.111 +
175.112 + Case c = Case.parseData(data);
175.113 + if (c.getHtmlFragment() != null) {
175.114 + setAttr("bck2brwsr.fragment", "innerHTML", c.getHtmlFragment());
175.115 + }
175.116 + log("Invoking " + c.getClassName() + '.' + c.getMethodName() + " as request: " + c.getRequestId());
175.117 +
175.118 + Object result = invokeMethod(c.getClassName(), c.getMethodName());
175.119 +
175.120 + setAttr("bck2brwsr.fragment", "innerHTML", "");
175.121 + log("Result: " + result);
175.122 +
175.123 + result = encodeURL("" + result);
175.124 +
175.125 + log("Sending back: " + url + "?request=" + c.getRequestId() + "&result=" + result);
175.126 + String u = url + "?request=" + c.getRequestId() + "&result=" + result;
175.127 +
175.128 + loadText(u, this, arr);
175.129 +
175.130 + } catch (Exception ex) {
175.131 + log(ex.getClass().getName() + ":" + ex.getMessage());
175.132 + }
175.133 + }
175.134 + }
175.135 +
175.136 + private static String encodeURL(String r) {
175.137 + StringBuilder sb = new StringBuilder();
175.138 + for (int i = 0; i < r.length(); i++) {
175.139 + int ch = r.charAt(i);
175.140 + if (ch < 32 || ch == '%' || ch == '+') {
175.141 + sb.append("%").append(("0" + Integer.toHexString(ch)).substring(0, 2));
175.142 + } else {
175.143 + if (ch == 32) {
175.144 + sb.append("+");
175.145 + } else {
175.146 + sb.append((char)ch);
175.147 + }
175.148 + }
175.149 + }
175.150 + return sb.toString();
175.151 + }
175.152 +
175.153 + static String invoke(String clazz, String method) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException, InstantiationException {
175.154 + final Object r = invokeMethod(clazz, method);
175.155 + return r == null ? "null" : r.toString().toString();
175.156 + }
175.157 +
175.158 + /** Helper method that inspects the classpath and loads given resource
175.159 + * (usually a class file). Used while running tests in Rhino.
175.160 + *
175.161 + * @param name resource name to find
175.162 + * @return the array of bytes in the given resource
175.163 + * @throws IOException I/O in case something goes wrong
175.164 + */
175.165 + public static byte[] read(String name) throws IOException {
175.166 + URL u = null;
175.167 + Enumeration<URL> en = Console.class.getClassLoader().getResources(name);
175.168 + while (en.hasMoreElements()) {
175.169 + u = en.nextElement();
175.170 + }
175.171 + if (u == null) {
175.172 + throw new IOException("Can't find " + name);
175.173 + }
175.174 + try (InputStream is = u.openStream()) {
175.175 + byte[] arr;
175.176 + arr = new byte[is.available()];
175.177 + int offset = 0;
175.178 + while (offset < arr.length) {
175.179 + int len = is.read(arr, offset, arr.length - offset);
175.180 + if (len == -1) {
175.181 + throw new IOException("Can't read " + name);
175.182 + }
175.183 + offset += len;
175.184 + }
175.185 + return arr;
175.186 + }
175.187 + }
175.188 +
175.189 + private static Object invokeMethod(String clazz, String method)
175.190 + throws ClassNotFoundException, InvocationTargetException,
175.191 + SecurityException, IllegalAccessException, IllegalArgumentException,
175.192 + InstantiationException {
175.193 + Method found = null;
175.194 + Class<?> c = Class.forName(clazz);
175.195 + for (Method m : c.getMethods()) {
175.196 + if (m.getName().equals(method)) {
175.197 + found = m;
175.198 + }
175.199 + }
175.200 + Object res;
175.201 + if (found != null) {
175.202 + try {
175.203 + if ((found.getModifiers() & Modifier.STATIC) != 0) {
175.204 + res = found.invoke(null);
175.205 + } else {
175.206 + res = found.invoke(c.newInstance());
175.207 + }
175.208 + } catch (Throwable ex) {
175.209 + res = ex.getClass().getName() + ":" + ex.getMessage();
175.210 + }
175.211 + } else {
175.212 + res = "Can't find method " + method + " in " + clazz;
175.213 + }
175.214 + return res;
175.215 + }
175.216 +
175.217 + @JavaScriptBody(args = {}, body = "vm.desiredAssertionStatus = true;")
175.218 + private static void turnAssetionStatusOn() {
175.219 + }
175.220 +
175.221 + private static final class Case {
175.222 + private final Object data;
175.223 +
175.224 + private Case(Object data) {
175.225 + this.data = data;
175.226 + }
175.227 +
175.228 + public static Case parseData(String s) {
175.229 + return new Case(toJSON(s));
175.230 + }
175.231 +
175.232 + public String getMethodName() {
175.233 + return value("methodName", data);
175.234 + }
175.235 +
175.236 + public String getClassName() {
175.237 + return value("className", data);
175.238 + }
175.239 +
175.240 + public String getRequestId() {
175.241 + return value("request", data);
175.242 + }
175.243 +
175.244 + public String getHtmlFragment() {
175.245 + return value("html", data);
175.246 + }
175.247 +
175.248 + @JavaScriptBody(args = "s", body = "return eval('(' + s + ')');")
175.249 + private static native Object toJSON(String s);
175.250 +
175.251 + @JavaScriptBody(args = {"p", "d"}, body =
175.252 + "var v = d[p];\n"
175.253 + + "if (typeof v === 'undefined') return null;\n"
175.254 + + "return v.toString();"
175.255 + )
175.256 + private static native String value(String p, Object d);
175.257 + }
175.258 +}
176.1 --- a/launcher/src/main/resources/org/apidesign/bck2brwsr/launcher/harness.xhtml Fri Jan 25 15:08:24 2013 +0100
176.2 +++ b/launcher/src/main/resources/org/apidesign/bck2brwsr/launcher/harness.xhtml Sun Feb 17 17:58:34 2013 +0100
176.3 @@ -24,7 +24,10 @@
176.4 <title>Bck2Brwsr Harness</title>
176.5 </head>
176.6 <body>
176.7 - <script src="/vm.js"></script>
176.8 + <script src="/bck2brwsr.js"></script>
176.9 + <script>
176.10 + var vm = bck2brwsr();
176.11 + </script>
176.12
176.13 <h1>Bck2Brwsr Execution Harness</h1>
176.14
176.15 @@ -34,7 +37,7 @@
176.16 <div id="bck2brwsr.fragment"/>
176.17
176.18 <script type="text/javascript">
176.19 - vm.loadClass('org.apidesign.bck2brwsr.launcher.Console').harness__VLjava_lang_String_2('$U/../data');
176.20 + vm.loadClass('org.apidesign.bck2brwsr.launcher.impl.Console').harness__VLjava_lang_String_2('$U/../data');
176.21 </script>
176.22 </body>
176.23 </html>
177.1 --- a/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Bck2BrswrMojo.java Fri Jan 25 15:08:24 2013 +0100
177.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
177.3 @@ -1,122 +0,0 @@
177.4 -/**
177.5 - * Back 2 Browser Bytecode Translator
177.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
177.7 - *
177.8 - * This program is free software: you can redistribute it and/or modify
177.9 - * it under the terms of the GNU General Public License as published by
177.10 - * the Free Software Foundation, version 2 of the License.
177.11 - *
177.12 - * This program is distributed in the hope that it will be useful,
177.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
177.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
177.15 - * GNU General Public License for more details.
177.16 - *
177.17 - * You should have received a copy of the GNU General Public License
177.18 - * along with this program. Look for COPYING file in the top folder.
177.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
177.20 - */
177.21 -package org.apidesign.bck2brwsr.mojo;
177.22 -
177.23 -import org.apache.maven.plugin.AbstractMojo;
177.24 -
177.25 -import java.io.File;
177.26 -import java.io.FileWriter;
177.27 -import java.io.IOException;
177.28 -import java.net.MalformedURLException;
177.29 -import java.net.URL;
177.30 -import java.net.URLClassLoader;
177.31 -import java.util.ArrayList;
177.32 -import java.util.Collection;
177.33 -import java.util.List;
177.34 -import org.apache.maven.artifact.Artifact;
177.35 -import org.apache.maven.plugin.MojoExecutionException;
177.36 -import org.apache.maven.plugins.annotations.LifecyclePhase;
177.37 -import org.apache.maven.plugins.annotations.Mojo;
177.38 -import org.apache.maven.plugins.annotations.Parameter;
177.39 -import org.apache.maven.project.MavenProject;
177.40 -import org.apidesign.vm4brwsr.Bck2Brwsr;
177.41 -
177.42 -/** Compiles classes into JavaScript. */
177.43 -@Mojo(name="j2js", defaultPhase=LifecyclePhase.PROCESS_CLASSES)
177.44 -public class Bck2BrswrMojo extends AbstractMojo {
177.45 - public Bck2BrswrMojo() {
177.46 - }
177.47 - /** Root of the class files */
177.48 - @Parameter(defaultValue="${project.build.directory}/classes")
177.49 - private File classes;
177.50 - /** File to generate. Defaults bootjava.js in the first non-empty
177.51 - package under the classes directory */
177.52 - @Parameter
177.53 - private File javascript;
177.54 -
177.55 - @Parameter(defaultValue="${project}")
177.56 - private MavenProject prj;
177.57 -
177.58 -
177.59 -
177.60 - @Override
177.61 - public void execute() throws MojoExecutionException {
177.62 - if (!classes.isDirectory()) {
177.63 - throw new MojoExecutionException("Can't find " + classes);
177.64 - }
177.65 -
177.66 - if (javascript == null) {
177.67 - javascript = new File(findNonEmptyFolder(classes), "bootjava.js");
177.68 - }
177.69 -
177.70 - List<String> arr = new ArrayList<String>();
177.71 - long newest = collectAllClasses("", classes, arr);
177.72 -
177.73 - if (javascript.lastModified() > newest) {
177.74 - return;
177.75 - }
177.76 -
177.77 - try {
177.78 - URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts());
177.79 - FileWriter w = new FileWriter(javascript);
177.80 - Bck2Brwsr.generate(w, url, arr.toArray(new String[0]));
177.81 - w.close();
177.82 - } catch (IOException ex) {
177.83 - throw new MojoExecutionException("Can't compile", ex);
177.84 - }
177.85 - }
177.86 -
177.87 - private static File findNonEmptyFolder(File dir) throws MojoExecutionException {
177.88 - if (!dir.isDirectory()) {
177.89 - throw new MojoExecutionException("Not a directory " + dir);
177.90 - }
177.91 - File[] arr = dir.listFiles();
177.92 - if (arr.length == 1 && arr[0].isDirectory()) {
177.93 - return findNonEmptyFolder(arr[0]);
177.94 - }
177.95 - return dir;
177.96 - }
177.97 -
177.98 - private static long collectAllClasses(String prefix, File toCheck, List<String> arr) {
177.99 - File[] files = toCheck.listFiles();
177.100 - if (files != null) {
177.101 - long newest = 0L;
177.102 - for (File f : files) {
177.103 - long lastModified = collectAllClasses(prefix + f.getName() + "/", f, arr);
177.104 - if (newest < lastModified) {
177.105 - newest = lastModified;
177.106 - }
177.107 - }
177.108 - return newest;
177.109 - } else if (toCheck.getName().endsWith(".class")) {
177.110 - arr.add(prefix.substring(0, prefix.length() - 7));
177.111 - return toCheck.lastModified();
177.112 - } else {
177.113 - return 0L;
177.114 - }
177.115 - }
177.116 -
177.117 - private static URLClassLoader buildClassLoader(File root, Collection<Artifact> deps) throws MalformedURLException {
177.118 - List<URL> arr = new ArrayList<URL>();
177.119 - arr.add(root.toURI().toURL());
177.120 - for (Artifact a : deps) {
177.121 - arr.add(a.getFile().toURI().toURL());
177.122 - }
177.123 - return new URLClassLoader(arr.toArray(new URL[0]), Bck2BrswrMojo.class.getClassLoader());
177.124 - }
177.125 -}
178.1 --- a/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrswrMojo.java Fri Jan 25 15:08:24 2013 +0100
178.2 +++ b/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrswrMojo.java Sun Feb 17 17:58:34 2013 +0100
178.3 @@ -37,7 +37,7 @@
178.4 import org.apidesign.bck2brwsr.launcher.Launcher;
178.5
178.6 /** Executes given HTML page in a browser. */
178.7 -@Mojo(name="brwsr", defaultPhase=LifecyclePhase.DEPLOY)
178.8 +@Mojo(name="brwsr", defaultPhase=LifecyclePhase.NONE)
178.9 public class BrswrMojo extends AbstractMojo {
178.10 public BrswrMojo() {
178.11 }
178.12 @@ -51,21 +51,28 @@
178.13 /** Root of the class files */
178.14 @Parameter(defaultValue="${project.build.directory}/classes")
178.15 private File classes;
178.16 +
178.17 + /** Root of all pages, and files, etc. */
178.18 + @Parameter
178.19 + private File directory;
178.20
178.21 @Override
178.22 public void execute() throws MojoExecutionException {
178.23 if (startpage == null) {
178.24 throw new MojoExecutionException("You have to provide a start page");
178.25 }
178.26 -
178.27 +
178.28 try {
178.29 - URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts());
178.30 -
178.31 Closeable httpServer;
178.32 - try {
178.33 - httpServer = Launcher.showURL(url, startpage());
178.34 - } catch (Exception ex) {
178.35 - throw new MojoExecutionException("Can't open " + startpage(), ex);
178.36 + if (directory != null) {
178.37 + httpServer = Launcher.showDir(directory, startpage);
178.38 + } else {
178.39 + URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts());
178.40 + try {
178.41 + httpServer = Launcher.showURL(url, startpage());
178.42 + } catch (Exception ex) {
178.43 + throw new MojoExecutionException("Can't open " + startpage(), ex);
178.44 + }
178.45 }
178.46 System.in.read();
178.47 httpServer.close();
179.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
179.2 +++ b/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Java2JavaScript.java Sun Feb 17 17:58:34 2013 +0100
179.3 @@ -0,0 +1,122 @@
179.4 +/**
179.5 + * Back 2 Browser Bytecode Translator
179.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
179.7 + *
179.8 + * This program is free software: you can redistribute it and/or modify
179.9 + * it under the terms of the GNU General Public License as published by
179.10 + * the Free Software Foundation, version 2 of the License.
179.11 + *
179.12 + * This program is distributed in the hope that it will be useful,
179.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
179.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
179.15 + * GNU General Public License for more details.
179.16 + *
179.17 + * You should have received a copy of the GNU General Public License
179.18 + * along with this program. Look for COPYING file in the top folder.
179.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
179.20 + */
179.21 +package org.apidesign.bck2brwsr.mojo;
179.22 +
179.23 +import org.apache.maven.plugin.AbstractMojo;
179.24 +
179.25 +import java.io.File;
179.26 +import java.io.FileWriter;
179.27 +import java.io.IOException;
179.28 +import java.net.MalformedURLException;
179.29 +import java.net.URL;
179.30 +import java.net.URLClassLoader;
179.31 +import java.util.ArrayList;
179.32 +import java.util.Collection;
179.33 +import java.util.List;
179.34 +import org.apache.maven.artifact.Artifact;
179.35 +import org.apache.maven.plugin.MojoExecutionException;
179.36 +import org.apache.maven.plugins.annotations.LifecyclePhase;
179.37 +import org.apache.maven.plugins.annotations.Mojo;
179.38 +import org.apache.maven.plugins.annotations.Parameter;
179.39 +import org.apache.maven.project.MavenProject;
179.40 +import org.apidesign.vm4brwsr.Bck2Brwsr;
179.41 +
179.42 +/** Compiles classes into JavaScript. */
179.43 +@Mojo(name="j2js", defaultPhase=LifecyclePhase.PROCESS_CLASSES)
179.44 +public class Java2JavaScript extends AbstractMojo {
179.45 + public Java2JavaScript() {
179.46 + }
179.47 + /** Root of the class files */
179.48 + @Parameter(defaultValue="${project.build.directory}/classes")
179.49 + private File classes;
179.50 + /** File to generate. Defaults bootjava.js in the first non-empty
179.51 + package under the classes directory */
179.52 + @Parameter
179.53 + private File javascript;
179.54 +
179.55 + @Parameter(defaultValue="${project}")
179.56 + private MavenProject prj;
179.57 +
179.58 +
179.59 +
179.60 + @Override
179.61 + public void execute() throws MojoExecutionException {
179.62 + if (!classes.isDirectory()) {
179.63 + throw new MojoExecutionException("Can't find " + classes);
179.64 + }
179.65 +
179.66 + if (javascript == null) {
179.67 + javascript = new File(findNonEmptyFolder(classes), "bootjava.js");
179.68 + }
179.69 +
179.70 + List<String> arr = new ArrayList<String>();
179.71 + long newest = collectAllClasses("", classes, arr);
179.72 +
179.73 + if (javascript.lastModified() > newest) {
179.74 + return;
179.75 + }
179.76 +
179.77 + try {
179.78 + URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts());
179.79 + FileWriter w = new FileWriter(javascript);
179.80 + Bck2Brwsr.generate(w, url, arr.toArray(new String[0]));
179.81 + w.close();
179.82 + } catch (IOException ex) {
179.83 + throw new MojoExecutionException("Can't compile", ex);
179.84 + }
179.85 + }
179.86 +
179.87 + private static File findNonEmptyFolder(File dir) throws MojoExecutionException {
179.88 + if (!dir.isDirectory()) {
179.89 + throw new MojoExecutionException("Not a directory " + dir);
179.90 + }
179.91 + File[] arr = dir.listFiles();
179.92 + if (arr.length == 1 && arr[0].isDirectory()) {
179.93 + return findNonEmptyFolder(arr[0]);
179.94 + }
179.95 + return dir;
179.96 + }
179.97 +
179.98 + private static long collectAllClasses(String prefix, File toCheck, List<String> arr) {
179.99 + File[] files = toCheck.listFiles();
179.100 + if (files != null) {
179.101 + long newest = 0L;
179.102 + for (File f : files) {
179.103 + long lastModified = collectAllClasses(prefix + f.getName() + "/", f, arr);
179.104 + if (newest < lastModified) {
179.105 + newest = lastModified;
179.106 + }
179.107 + }
179.108 + return newest;
179.109 + } else if (toCheck.getName().endsWith(".class")) {
179.110 + arr.add(prefix.substring(0, prefix.length() - 7));
179.111 + return toCheck.lastModified();
179.112 + } else {
179.113 + return 0L;
179.114 + }
179.115 + }
179.116 +
179.117 + private static URLClassLoader buildClassLoader(File root, Collection<Artifact> deps) throws MalformedURLException {
179.118 + List<URL> arr = new ArrayList<URL>();
179.119 + arr.add(root.toURI().toURL());
179.120 + for (Artifact a : deps) {
179.121 + arr.add(a.getFile().toURI().toURL());
179.122 + }
179.123 + return new URLClassLoader(arr.toArray(new URL[0]), Java2JavaScript.class.getClassLoader());
179.124 + }
179.125 +}
180.1 --- a/mojo/src/main/resources/META-INF/maven/archetype-metadata.xml Fri Jan 25 15:08:24 2013 +0100
180.2 +++ b/mojo/src/main/resources/META-INF/maven/archetype-metadata.xml Sun Feb 17 17:58:34 2013 +0100
180.3 @@ -30,6 +30,7 @@
180.4 <directory>src/main/resources</directory>
180.5 <includes>
180.6 <include>**/*.xhtml</include>
180.7 + <include>**/*.html</include>
180.8 </includes>
180.9 </fileSet>
180.10 <fileSet filtered="true" packaged="true">
180.11 @@ -44,5 +45,11 @@
180.12 <include>nbactions.xml</include>
180.13 </includes>
180.14 </fileSet>
180.15 + <fileSet filtered="true" packaged="false">
180.16 + <directory></directory>
180.17 + <includes>
180.18 + <include>bck2brwsr-assembly.xml</include>
180.19 + </includes>
180.20 + </fileSet>
180.21 </fileSets>
180.22 </archetype-descriptor>
180.23 \ No newline at end of file
181.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
181.2 +++ b/mojo/src/main/resources/archetype-resources/bck2brwsr-assembly.xml Sun Feb 17 17:58:34 2013 +0100
181.3 @@ -0,0 +1,61 @@
181.4 +<?xml version="1.0"?>
181.5 +<!--
181.6 +
181.7 + Back 2 Browser Bytecode Translator
181.8 + Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
181.9 +
181.10 + This program is free software: you can redistribute it and/or modify
181.11 + it under the terms of the GNU General Public License as published by
181.12 + the Free Software Foundation, version 2 of the License.
181.13 +
181.14 + This program is distributed in the hope that it will be useful,
181.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of
181.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
181.17 + GNU General Public License for more details.
181.18 +
181.19 + You should have received a copy of the GNU General Public License
181.20 + along with this program. Look for COPYING file in the top folder.
181.21 + If not, see http://opensource.org/licenses/GPL-2.0.
181.22 +
181.23 +-->
181.24 +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
181.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">
181.26 +
181.27 + <id>bck2brwsr</id>
181.28 + <formats>
181.29 + <format>zip</format>
181.30 + </formats>
181.31 + <baseDirectory>public_html</baseDirectory>
181.32 + <dependencySets>
181.33 + <dependencySet>
181.34 + <useProjectArtifact>false</useProjectArtifact>
181.35 + <scope>runtime</scope>
181.36 + <outputDirectory>lib</outputDirectory>
181.37 + <includes>
181.38 + <include>*:jar</include>
181.39 + <include>*:rt</include>
181.40 + </includes>
181.41 + </dependencySet>
181.42 + <dependencySet>
181.43 + <useProjectArtifact>false</useProjectArtifact>
181.44 + <scope>provided</scope>
181.45 + <includes>
181.46 + <include>*:js</include>
181.47 + </includes>
181.48 + <unpack>true</unpack>
181.49 + <outputDirectory>/</outputDirectory>
181.50 + </dependencySet>
181.51 + </dependencySets>
181.52 + <files>
181.53 + <file>
181.54 + <source>${project.build.directory}/${project.build.finalName}.jar</source>
181.55 + <outputDirectory>/</outputDirectory>
181.56 + </file>
181.57 + <file>
181.58 + <source>${project.build.directory}/classes/${package.replace('.','/')}/index.html</source>
181.59 + <outputDirectory>/</outputDirectory>
181.60 + <destName>index.html</destName>
181.61 + </file>
181.62 + </files>
181.63 +
181.64 +</assembly>
181.65 \ No newline at end of file
182.1 --- a/mojo/src/main/resources/archetype-resources/pom.xml Fri Jan 25 15:08:24 2013 +0100
182.2 +++ b/mojo/src/main/resources/archetype-resources/pom.xml Sun Feb 17 17:58:34 2013 +0100
182.3 @@ -10,6 +10,32 @@
182.4
182.5 <name>${artifactId}</name>
182.6
182.7 + <repositories>
182.8 + <repository>
182.9 + <id>java.net</id>
182.10 + <name>Java.net</name>
182.11 + <url>https://maven.java.net/content/repositories/snapshots/</url>
182.12 + <snapshots>
182.13 + <enabled>true</enabled>
182.14 + </snapshots>
182.15 + </repository>
182.16 + <repository>
182.17 + <id>netbeans</id>
182.18 + <name>NetBeans</name>
182.19 + <url>http://bits.netbeans.org/maven2/</url>
182.20 + </repository>
182.21 + </repositories>
182.22 + <pluginRepositories>
182.23 + <pluginRepository>
182.24 + <id>java.net</id>
182.25 + <name>Local Maven repository of releases</name>
182.26 + <url>https://maven.java.net/content/repositories/snapshots/</url>
182.27 + <snapshots>
182.28 + <enabled>true</enabled>
182.29 + </snapshots>
182.30 + </pluginRepository>
182.31 + </pluginRepositories>
182.32 +
182.33 <properties>
182.34 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
182.35 </properties>
182.36 @@ -27,7 +53,7 @@
182.37 </execution>
182.38 </executions>
182.39 <configuration>
182.40 - <startpage>${package.replace('.','/')}/index.xhtml</startpage>
182.41 + <startpage>${package.replace('.','/')}/index.html</startpage>
182.42 </configuration>
182.43 </plugin>
182.44 <plugin>
182.45 @@ -39,14 +65,46 @@
182.46 <target>1.7</target>
182.47 </configuration>
182.48 </plugin>
182.49 + <plugin>
182.50 + <groupId>org.apache.maven.plugins</groupId>
182.51 + <artifactId>maven-jar-plugin</artifactId>
182.52 + <version>2.4</version>
182.53 + <configuration>
182.54 + <archive>
182.55 + <manifest>
182.56 + <addClasspath>true</addClasspath>
182.57 + <classpathPrefix>lib/</classpathPrefix>
182.58 + </manifest>
182.59 + </archive>
182.60 + </configuration>
182.61 + </plugin>
182.62 + <plugin>
182.63 + <artifactId>maven-assembly-plugin</artifactId>
182.64 + <version>2.4</version>
182.65 + <executions>
182.66 + <execution>
182.67 + <id>distro-assembly</id>
182.68 + <phase>package</phase>
182.69 + <goals>
182.70 + <goal>single</goal>
182.71 + </goals>
182.72 + <configuration>
182.73 + <descriptors>
182.74 + <descriptor>bck2brwsr-assembly.xml</descriptor>
182.75 + </descriptors>
182.76 + </configuration>
182.77 + </execution>
182.78 + </executions>
182.79 + </plugin>
182.80 </plugins>
182.81 </build>
182.82
182.83 <dependencies>
182.84 <dependency>
182.85 <groupId>org.apidesign.bck2brwsr</groupId>
182.86 - <artifactId>emul.mini</artifactId>
182.87 + <artifactId>emul</artifactId>
182.88 <version>0.3-SNAPSHOT</version>
182.89 + <classifier>rt</classifier>
182.90 </dependency>
182.91 <dependency>
182.92 <groupId>org.apidesign.bck2brwsr</groupId>
182.93 @@ -60,7 +118,15 @@
182.94 <scope>test</scope>
182.95 </dependency>
182.96 <dependency>
182.97 - <groupId>${project.groupId}</groupId>
182.98 + <groupId>org.apidesign.bck2brwsr</groupId>
182.99 + <artifactId>vm4brwsr</artifactId>
182.100 + <classifier>js</classifier>
182.101 + <type>zip</type>
182.102 + <version>0.3-SNAPSHOT</version>
182.103 + <scope>provided</scope>
182.104 + </dependency>
182.105 + <dependency>
182.106 + <groupId>org.apidesign.bck2brwsr</groupId>
182.107 <artifactId>vmtest</artifactId>
182.108 <version>0.3-SNAPSHOT</version>
182.109 <scope>test</scope>
183.1 --- a/mojo/src/main/resources/archetype-resources/src/main/java/App.java Fri Jan 25 15:08:24 2013 +0100
183.2 +++ b/mojo/src/main/resources/archetype-resources/src/main/java/App.java Sun Feb 17 17:58:34 2013 +0100
183.3 @@ -9,7 +9,7 @@
183.4 /** Edit the index.xhtml file. Use 'id' to name certain HTML elements.
183.5 * Use this class to define behavior of the elements.
183.6 */
183.7 -@Page(xhtml="index.xhtml", className="Index", properties={
183.8 +@Page(xhtml="index.html", className="Index", properties={
183.9 @Property(name="name", type=String.class)
183.10 })
183.11 public class App {
184.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
184.2 +++ b/mojo/src/main/resources/archetype-resources/src/main/resources/index.html Sun Feb 17 17:58:34 2013 +0100
184.3 @@ -0,0 +1,22 @@
184.4 +<?xml version="1.0" encoding="UTF-8"?>
184.5 +<!DOCTYPE html>
184.6 +<html xmlns="http://www.w3.org/1999/xhtml">
184.7 + <head>
184.8 + <title>Bck2Brwsr's Hello World</title>
184.9 + </head>
184.10 + <body>
184.11 + <h1 data-bind="text: helloMessage">Loading Bck2Brwsr's Hello World...</h1>
184.12 + Your name: <input id='input' data-bind="value: name, valueUpdate: 'afterkeydown'"></input>
184.13 + <button id="hello">Say Hello!</button>
184.14 + <p>
184.15 + <canvas id="canvas" width="300" height="50">
184.16 + </canvas>
184.17 + </p>
184.18 +
184.19 + <script src="bck2brwsr.js"></script>
184.20 + <script type="text/javascript">
184.21 + var vm = bck2brwsr('${artifactId}-${version}.jar');
184.22 + vm.loadClass('${package}.App');
184.23 + </script>
184.24 + </body>
184.25 +</html>
185.1 --- a/mojo/src/main/resources/archetype-resources/src/main/resources/index.xhtml Fri Jan 25 15:08:24 2013 +0100
185.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
185.3 @@ -1,22 +0,0 @@
185.4 -<?xml version="1.0" encoding="UTF-8"?>
185.5 -<!DOCTYPE html>
185.6 -<html xmlns="http://www.w3.org/1999/xhtml">
185.7 - <head>
185.8 - <title>Bck2Brwsr's Hello World</title>
185.9 - </head>
185.10 - <body>
185.11 - <h1 data-bind="text: helloMessage">Loading Bck2Brwsr's Hello World...</h1>
185.12 - Your name: <input id='input' data-bind="value: name, valueUpdate: 'afterkeydown'"></input>
185.13 - <button id="hello">Say Hello!</button>
185.14 - <p>
185.15 - <canvas id="canvas" width="300" height="50">
185.16 - </canvas>
185.17 - </p>
185.18 -
185.19 - <script src="/bck2brwsr.js"></script>
185.20 - <script src="/vm.js"></script>
185.21 - <script type="text/javascript">
185.22 - vm.loadClass('${package}.App');
185.23 - </script>
185.24 - </body>
185.25 -</html>
186.1 --- a/pom.xml Fri Jan 25 15:08:24 2013 +0100
186.2 +++ b/pom.xml Sun Feb 17 17:58:34 2013 +0100
186.3 @@ -6,6 +6,11 @@
186.4 <version>0.3-SNAPSHOT</version>
186.5 <packaging>pom</packaging>
186.6 <name>Back 2 Browser</name>
186.7 + <parent>
186.8 + <groupId>net.java</groupId>
186.9 + <artifactId>jvnet-parent</artifactId>
186.10 + <version>3</version>
186.11 + </parent>
186.12 <modules>
186.13 <module>vm</module>
186.14 <module>emul</module>
186.15 @@ -17,6 +22,7 @@
186.16 <module>benchmarks</module>
186.17 <module>launcher</module>
186.18 <module>vmtest</module>
186.19 + <module>ide</module>
186.20 </modules>
186.21 <licenses>
186.22 <license>
186.23 @@ -29,6 +35,11 @@
186.24 <name>API Design</name>
186.25 <url>http://apidesign.org</url>
186.26 </organization>
186.27 + <scm>
186.28 + <connection>scm:hg:http://source.apidesign.org/hg/bck2brwsr</connection>
186.29 + <developerConnection>scm:hg:https://source.apidesign.org/hg/bck2brwsr</developerConnection>
186.30 + <url>http://source.apidesign.org/hg/bck2brwsr</url>
186.31 + </scm>
186.32 <repositories>
186.33 <repository>
186.34 <id>netbeans</id>
186.35 @@ -82,6 +93,15 @@
186.36 </configuration>
186.37 </plugin>
186.38 </plugins>
186.39 + <pluginManagement>
186.40 + <plugins>
186.41 + <plugin>
186.42 + <groupId>org.apache.maven.plugins</groupId>
186.43 + <artifactId>maven-surefire-plugin</artifactId>
186.44 + <version>2.13</version>
186.45 + </plugin>
186.46 + </plugins>
186.47 + </pluginManagement>
186.48 </build>
186.49 <dependencyManagement>
186.50 <dependencies>
187.1 --- a/vm/pom.xml Fri Jan 25 15:08:24 2013 +0100
187.2 +++ b/vm/pom.xml Sun Feb 17 17:58:34 2013 +0100
187.3 @@ -12,7 +12,7 @@
187.4 <version>0.3-SNAPSHOT</version>
187.5 <packaging>jar</packaging>
187.6
187.7 - <name>Java VM for Browser</name>
187.8 + <name>Virtual Machine for Browser</name>
187.9 <url>http://bck2brwsr.apidesign.org</url>
187.10
187.11 <properties>
187.12 @@ -68,6 +68,45 @@
187.13 <target>1.7</target>
187.14 </configuration>
187.15 </plugin>
187.16 + <plugin>
187.17 + <groupId>org.codehaus.mojo</groupId>
187.18 + <artifactId>exec-maven-plugin</artifactId>
187.19 + <version>1.2.1</version>
187.20 + <executions>
187.21 + <execution>
187.22 + <id>generate-js</id>
187.23 + <phase>process-classes</phase>
187.24 + <goals>
187.25 + <goal>java</goal>
187.26 + </goals>
187.27 + </execution>
187.28 + </executions>
187.29 + <configuration>
187.30 + <mainClass>org.apidesign.vm4brwsr.Main</mainClass>
187.31 + <arguments>
187.32 + <argument>${project.build.directory}/bck2brwsr.js</argument>
187.33 + <argument>org/apidesign/vm4brwsr/Bck2Brwsr</argument>
187.34 + </arguments>
187.35 + </configuration>
187.36 + </plugin>
187.37 + <plugin>
187.38 + <artifactId>maven-assembly-plugin</artifactId>
187.39 + <version>2.4</version>
187.40 + <executions>
187.41 + <execution>
187.42 + <id>js</id>
187.43 + <phase>package</phase>
187.44 + <goals>
187.45 + <goal>single</goal>
187.46 + </goals>
187.47 + <configuration>
187.48 + <descriptors>
187.49 + <descriptor>src/main/assembly/bck2brwsr.xml</descriptor>
187.50 + </descriptors>
187.51 + </configuration>
187.52 + </execution>
187.53 + </executions>
187.54 + </plugin>
187.55 </plugins>
187.56 </build>
187.57 <dependencies>
187.58 @@ -85,19 +124,20 @@
187.59 <dependency>
187.60 <groupId>${project.groupId}</groupId>
187.61 <artifactId>core</artifactId>
187.62 - <version>0.3-SNAPSHOT</version>
187.63 + <version>${project.version}</version>
187.64 <type>jar</type>
187.65 </dependency>
187.66 <dependency>
187.67 <groupId>${project.groupId}</groupId>
187.68 <artifactId>emul.mini</artifactId>
187.69 - <version>0.3-SNAPSHOT</version>
187.70 - <scope>test</scope>
187.71 + <version>${project.version}</version>
187.72 + <scope>compile</scope>
187.73 </dependency>
187.74 <dependency>
187.75 <groupId>${project.groupId}</groupId>
187.76 <artifactId>javap</artifactId>
187.77 - <version>0.3-SNAPSHOT</version>
187.78 + <version>${project.version}</version>
187.79 + <scope>compile</scope>
187.80 </dependency>
187.81 </dependencies>
187.82 </project>
188.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
188.2 +++ b/vm/src/main/assembly/bck2brwsr.xml Sun Feb 17 17:58:34 2013 +0100
188.3 @@ -0,0 +1,36 @@
188.4 +<?xml version="1.0"?>
188.5 +<!--
188.6 +
188.7 + Back 2 Browser Bytecode Translator
188.8 + Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
188.9 +
188.10 + This program is free software: you can redistribute it and/or modify
188.11 + it under the terms of the GNU General Public License as published by
188.12 + the Free Software Foundation, version 2 of the License.
188.13 +
188.14 + This program is distributed in the hope that it will be useful,
188.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of
188.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
188.17 + GNU General Public License for more details.
188.18 +
188.19 + You should have received a copy of the GNU General Public License
188.20 + along with this program. Look for COPYING file in the top folder.
188.21 + If not, see http://opensource.org/licenses/GPL-2.0.
188.22 +
188.23 +-->
188.24 +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
188.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">
188.26 +
188.27 + <id>js</id>
188.28 + <formats>
188.29 + <format>zip</format>
188.30 + </formats>
188.31 + <baseDirectory>/</baseDirectory>
188.32 + <files>
188.33 + <file>
188.34 + <source>${project.build.directory}/bck2brwsr.js</source>
188.35 + <outputDirectory>/</outputDirectory>
188.36 + </file>
188.37 + </files>
188.38 +
188.39 +</assembly>
188.40 \ No newline at end of file
189.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java Fri Jan 25 15:08:24 2013 +0100
189.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java Sun Feb 17 17:58:34 2013 +0100
189.3 @@ -40,6 +40,16 @@
189.4 * In this scenario, when a request for an unknown class is made, the loader
189.5 * function is asked for its byte code and the system dynamically transforms
189.6 * it to JavaScript.
189.7 + * <p>
189.8 + * Instead of a loader function, one can also provide a URL to a JAR file.
189.9 + * The <code>bck2brwsr</code> system will do its best to download the file
189.10 + * and provide loader function for it automatically.
189.11 + * <p>
189.12 + * One can provide as many loader functions and JAR URL references as necessary.
189.13 + * Then the initialization code would look like:<pre>
189.14 + * var vm = bck2brwsr(url1, url2, fnctn1, url3, functn2);
189.15 + * </pre>
189.16 + * The provided URLs and loader functions will be consulted one by one.
189.17 *
189.18 * @author Jaroslav Tulach <jtulach@netbeans.org>
189.19 */
190.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Fri Jan 25 15:08:24 2013 +0100
190.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Sun Feb 17 17:58:34 2013 +0100
190.3 @@ -113,12 +113,7 @@
190.4 final String className = className(jc);
190.5 out.append("\n\n").append(assignClass(className));
190.6 out.append("function CLS() {");
190.7 - out.append("\n if (!CLS.prototype.$instOf_").append(className).append(") {");
190.8 - for (FieldData v : jc.getFields()) {
190.9 - if (v.isStatic()) {
190.10 - out.append("\n CLS.").append(v.getName()).append(initField(v));
190.11 - }
190.12 - }
190.13 + out.append("\n if (!CLS.$class) {");
190.14 if (proto == null) {
190.15 String sc = jc.getSuperClassName(); // with _
190.16 out.append("\n var pp = ").
190.17 @@ -134,6 +129,18 @@
190.18 out.append("\n var c = ").append(proto[0]).append(";");
190.19 out.append("\n var sprcls = null;");
190.20 }
190.21 + for (FieldData v : jc.getFields()) {
190.22 + if (v.isStatic()) {
190.23 + out.append("\n CLS.").append(v.getName()).append(initField(v));
190.24 + } else {
190.25 + out.append("\n c._").append(v.getName()).append(" = function (v) {")
190.26 + .append(" if (arguments.length == 1) this.fld_").
190.27 + append(className).append('_').append(v.getName())
190.28 + .append(" = v; return this.fld_").
190.29 + append(className).append('_').append(v.getName())
190.30 + .append("; };");
190.31 + }
190.32 + }
190.33 for (MethodData m : jc.getMethods()) {
190.34 byte[] onlyArr = m.findAnnotationData(true);
190.35 String[] only = findAnnotation(onlyArr, jc,
190.36 @@ -168,12 +175,14 @@
190.37 out.append("\n };");
190.38 }
190.39 out.append(prefix).append(mn).append(".access = " + m.getAccess()).append(";");
190.40 + out.append(prefix).append(mn).append(".cls = CLS;");
190.41 }
190.42 out.append("\n c.constructor = CLS;");
190.43 out.append("\n c.$instOf_").append(className).append(" = true;");
190.44 for (String superInterface : jc.getSuperInterfaces()) {
190.45 out.append("\n c.$instOf_").append(superInterface.replace('/', '_')).append(" = true;");
190.46 }
190.47 + out.append("\n CLS.$class = 'temp';");
190.48 out.append("\n CLS.$class = ");
190.49 out.append(accessClass("java_lang_Class(true);"));
190.50 out.append("\n CLS.$class.jvmName = '").append(jc.getClassName()).append("';");
190.51 @@ -206,6 +215,7 @@
190.52 }
190.53 if (!v.isStatic()) {
190.54 out.append("\n this.fld_").
190.55 + append(className).append('_').
190.56 append(v.getName()).append(initField(v));
190.57 }
190.58 }
190.59 @@ -270,6 +280,7 @@
190.60
190.61 int lastStackFrame = -1;
190.62 TrapData[] previousTrap = null;
190.63 + boolean wide = false;
190.64
190.65 out.append("\n var gt = 0;\n for(;;) switch(gt) {\n");
190.66 for (int i = 0; i < byteCodes.length; i++) {
190.67 @@ -295,7 +306,7 @@
190.68 out.append("try {");
190.69 previousTrap = trap.current();
190.70 }
190.71 - final int c = readByte(byteCodes, i);
190.72 + final int c = readUByte(byteCodes, i);
190.73 switch (c) {
190.74 case opc_aload_0:
190.75 emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(0));
190.76 @@ -358,61 +369,91 @@
190.77 emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(3));
190.78 break;
190.79 case opc_iload: {
190.80 - final int indx = readByte(byteCodes, ++i);
190.81 + ++i;
190.82 + final int indx = wide ? readUShort(byteCodes, i++)
190.83 + : readUByte(byteCodes, i);
190.84 + wide = false;
190.85 emit(out, "var @1 = @2;",
190.86 smapper.pushI(), lmapper.getI(indx));
190.87 break;
190.88 }
190.89 case opc_lload: {
190.90 - final int indx = readByte(byteCodes, ++i);
190.91 + ++i;
190.92 + final int indx = wide ? readUShort(byteCodes, i++)
190.93 + : readUByte(byteCodes, i);
190.94 + wide = false;
190.95 emit(out, "var @1 = @2;",
190.96 smapper.pushL(), lmapper.getL(indx));
190.97 break;
190.98 }
190.99 case opc_fload: {
190.100 - final int indx = readByte(byteCodes, ++i);
190.101 + ++i;
190.102 + final int indx = wide ? readUShort(byteCodes, i++)
190.103 + : readUByte(byteCodes, i);
190.104 + wide = false;
190.105 emit(out, "var @1 = @2;",
190.106 smapper.pushF(), lmapper.getF(indx));
190.107 break;
190.108 }
190.109 case opc_dload: {
190.110 - final int indx = readByte(byteCodes, ++i);
190.111 + ++i;
190.112 + final int indx = wide ? readUShort(byteCodes, i++)
190.113 + : readUByte(byteCodes, i);
190.114 + wide = false;
190.115 emit(out, "var @1 = @2;",
190.116 smapper.pushD(), lmapper.getD(indx));
190.117 break;
190.118 }
190.119 case opc_aload: {
190.120 - final int indx = readByte(byteCodes, ++i);
190.121 + ++i;
190.122 + final int indx = wide ? readUShort(byteCodes, i++)
190.123 + : readUByte(byteCodes, i);
190.124 + wide = false;
190.125 emit(out, "var @1 = @2;",
190.126 smapper.pushA(), lmapper.getA(indx));
190.127 break;
190.128 }
190.129 case opc_istore: {
190.130 - final int indx = readByte(byteCodes, ++i);
190.131 + ++i;
190.132 + final int indx = wide ? readUShort(byteCodes, i++)
190.133 + : readUByte(byteCodes, i);
190.134 + wide = false;
190.135 emit(out, "var @1 = @2;",
190.136 lmapper.setI(indx), smapper.popI());
190.137 break;
190.138 }
190.139 case opc_lstore: {
190.140 - final int indx = readByte(byteCodes, ++i);
190.141 + ++i;
190.142 + final int indx = wide ? readUShort(byteCodes, i++)
190.143 + : readUByte(byteCodes, i);
190.144 + wide = false;
190.145 emit(out, "var @1 = @2;",
190.146 lmapper.setL(indx), smapper.popL());
190.147 break;
190.148 }
190.149 case opc_fstore: {
190.150 - final int indx = readByte(byteCodes, ++i);
190.151 + ++i;
190.152 + final int indx = wide ? readUShort(byteCodes, i++)
190.153 + : readUByte(byteCodes, i);
190.154 + wide = false;
190.155 emit(out, "var @1 = @2;",
190.156 lmapper.setF(indx), smapper.popF());
190.157 break;
190.158 }
190.159 case opc_dstore: {
190.160 - final int indx = readByte(byteCodes, ++i);
190.161 + ++i;
190.162 + final int indx = wide ? readUShort(byteCodes, i++)
190.163 + : readUByte(byteCodes, i);
190.164 + wide = false;
190.165 emit(out, "var @1 = @2;",
190.166 lmapper.setD(indx), smapper.popD());
190.167 break;
190.168 }
190.169 case opc_astore: {
190.170 - final int indx = readByte(byteCodes, ++i);
190.171 + ++i;
190.172 + final int indx = wide ? readUShort(byteCodes, i++)
190.173 + : readUByte(byteCodes, i);
190.174 + wide = false;
190.175 emit(out, "var @1 = @2;",
190.176 lmapper.setA(indx), smapper.popA());
190.177 break;
190.178 @@ -481,7 +522,7 @@
190.179 emit(out, "@1 = @1.add32(@2);", smapper.getI(1), smapper.popI());
190.180 break;
190.181 case opc_ladd:
190.182 - emit(out, "@1 += @2;", smapper.getL(1), smapper.popL());
190.183 + emit(out, "@1 = @1.add64(@2);", smapper.getL(1), smapper.popL());
190.184 break;
190.185 case opc_fadd:
190.186 emit(out, "@1 += @2;", smapper.getF(1), smapper.popF());
190.187 @@ -493,7 +534,7 @@
190.188 emit(out, "@1 = @1.sub32(@2);", smapper.getI(1), smapper.popI());
190.189 break;
190.190 case opc_lsub:
190.191 - emit(out, "@1 -= @2;", smapper.getL(1), smapper.popL());
190.192 + emit(out, "@1 = @1.sub64(@2);", smapper.getL(1), smapper.popL());
190.193 break;
190.194 case opc_fsub:
190.195 emit(out, "@1 -= @2;", smapper.getF(1), smapper.popF());
190.196 @@ -505,7 +546,7 @@
190.197 emit(out, "@1 = @1.mul32(@2);", smapper.getI(1), smapper.popI());
190.198 break;
190.199 case opc_lmul:
190.200 - emit(out, "@1 *= @2;", smapper.getL(1), smapper.popL());
190.201 + emit(out, "@1 = @1.mul64(@2);", smapper.getL(1), smapper.popL());
190.202 break;
190.203 case opc_fmul:
190.204 emit(out, "@1 *= @2;", smapper.getF(1), smapper.popF());
190.205 @@ -518,7 +559,7 @@
190.206 smapper.getI(1), smapper.popI());
190.207 break;
190.208 case opc_ldiv:
190.209 - emit(out, "@1 = Math.floor(@1 / @2);",
190.210 + emit(out, "@1 = @1.div64(@2);",
190.211 smapper.getL(1), smapper.popL());
190.212 break;
190.213 case opc_fdiv:
190.214 @@ -531,7 +572,8 @@
190.215 emit(out, "@1 %= @2;", smapper.getI(1), smapper.popI());
190.216 break;
190.217 case opc_lrem:
190.218 - emit(out, "@1 %= @2;", smapper.getL(1), smapper.popL());
190.219 + emit(out, "@1 = @1.mod64(@2);",
190.220 + smapper.getL(1), smapper.popL());
190.221 break;
190.222 case opc_frem:
190.223 emit(out, "@1 %= @2;", smapper.getF(1), smapper.popF());
190.224 @@ -543,25 +585,25 @@
190.225 emit(out, "@1 &= @2;", smapper.getI(1), smapper.popI());
190.226 break;
190.227 case opc_land:
190.228 - emit(out, "@1 &= @2;", smapper.getL(1), smapper.popL());
190.229 + emit(out, "@1 = @1.and64(@2);", smapper.getL(1), smapper.popL());
190.230 break;
190.231 case opc_ior:
190.232 emit(out, "@1 |= @2;", smapper.getI(1), smapper.popI());
190.233 break;
190.234 case opc_lor:
190.235 - emit(out, "@1 |= @2;", smapper.getL(1), smapper.popL());
190.236 + emit(out, "@1 = @1.or64(@2);", smapper.getL(1), smapper.popL());
190.237 break;
190.238 case opc_ixor:
190.239 emit(out, "@1 ^= @2;", smapper.getI(1), smapper.popI());
190.240 break;
190.241 case opc_lxor:
190.242 - emit(out, "@1 ^= @2;", smapper.getL(1), smapper.popL());
190.243 + emit(out, "@1 = @1.xor64(@2);", smapper.getL(1), smapper.popL());
190.244 break;
190.245 case opc_ineg:
190.246 - emit(out, "@1 = -@1;", smapper.getI(0));
190.247 + emit(out, "@1 = @1.neg32();", smapper.getI(0));
190.248 break;
190.249 case opc_lneg:
190.250 - emit(out, "@1 = -@1;", smapper.getL(0));
190.251 + emit(out, "@1 = @1.neg64();", smapper.getL(0));
190.252 break;
190.253 case opc_fneg:
190.254 emit(out, "@1 = -@1;", smapper.getF(0));
190.255 @@ -573,23 +615,28 @@
190.256 emit(out, "@1 <<= @2;", smapper.getI(1), smapper.popI());
190.257 break;
190.258 case opc_lshl:
190.259 - emit(out, "@1 <<= @2;", smapper.getL(1), smapper.popI());
190.260 + emit(out, "@1 = @1.shl64(@2);", smapper.getL(1), smapper.popI());
190.261 break;
190.262 case opc_ishr:
190.263 emit(out, "@1 >>= @2;", smapper.getI(1), smapper.popI());
190.264 break;
190.265 case opc_lshr:
190.266 - emit(out, "@1 >>= @2;", smapper.getL(1), smapper.popI());
190.267 + emit(out, "@1 = @1.shr64(@2);", smapper.getL(1), smapper.popI());
190.268 break;
190.269 case opc_iushr:
190.270 emit(out, "@1 >>>= @2;", smapper.getI(1), smapper.popI());
190.271 break;
190.272 case opc_lushr:
190.273 - emit(out, "@1 >>>= @2;", smapper.getL(1), smapper.popI());
190.274 + emit(out, "@1 = @1.ushr64(@2);", smapper.getL(1), smapper.popI());
190.275 break;
190.276 case opc_iinc: {
190.277 - final int varIndx = readByte(byteCodes, ++i);
190.278 - final int incrBy = byteCodes[++i];
190.279 + ++i;
190.280 + final int varIndx = wide ? readUShort(byteCodes, i++)
190.281 + : readUByte(byteCodes, i);
190.282 + ++i;
190.283 + final int incrBy = wide ? readShort(byteCodes, i++)
190.284 + : byteCodes[i];
190.285 + wide = false;
190.286 if (incrBy == 1) {
190.287 emit(out, "@1++;", lmapper.getI(varIndx));
190.288 } else {
190.289 @@ -627,14 +674,14 @@
190.290 emit(out, "var @2 = @1;", smapper.popI(), smapper.pushD());
190.291 break;
190.292 case opc_l2i:
190.293 - emit(out, "var @2 = @1;", smapper.popL(), smapper.pushI());
190.294 + emit(out, "var @2 = @1.toInt32();", smapper.popL(), smapper.pushI());
190.295 break;
190.296 // max int check?
190.297 case opc_l2f:
190.298 - emit(out, "var @2 = @1;", smapper.popL(), smapper.pushF());
190.299 + emit(out, "var @2 = @1.toFP();", smapper.popL(), smapper.pushF());
190.300 break;
190.301 case opc_l2d:
190.302 - emit(out, "var @2 = @1;", smapper.popL(), smapper.pushD());
190.303 + emit(out, "var @2 = @1.toFP();", smapper.popL(), smapper.pushD());
190.304 break;
190.305 case opc_f2d:
190.306 emit(out, "var @2 = @1;", smapper.popF(), smapper.pushD());
190.307 @@ -647,7 +694,7 @@
190.308 smapper.popF(), smapper.pushI());
190.309 break;
190.310 case opc_f2l:
190.311 - emit(out, "var @2 = Math.floor(@1);",
190.312 + emit(out, "var @2 = Math.floor(@1).toLong();",
190.313 smapper.popF(), smapper.pushL());
190.314 break;
190.315 case opc_d2i:
190.316 @@ -655,7 +702,7 @@
190.317 smapper.popD(), smapper.pushI());
190.318 break;
190.319 case opc_d2l:
190.320 - emit(out, "var @2 = Math.floor(@1);",
190.321 + emit(out, "var @2 = Math.floor(@1).toLong();",
190.322 smapper.popD(), smapper.pushL());
190.323 break;
190.324 case opc_i2b:
190.325 @@ -713,7 +760,7 @@
190.326 emit(out, "var @1 = 5;", smapper.pushI());
190.327 break;
190.328 case opc_ldc: {
190.329 - int indx = readByte(byteCodes, ++i);
190.330 + int indx = readUByte(byteCodes, ++i);
190.331 String v = encodeConstant(indx);
190.332 int type = VarType.fromConstantType(jc.getTag(indx));
190.333 emit(out, "var @1 = @2;", smapper.pushT(type), v);
190.334 @@ -725,11 +772,19 @@
190.335 i += 2;
190.336 String v = encodeConstant(indx);
190.337 int type = VarType.fromConstantType(jc.getTag(indx));
190.338 - emit(out, "var @1 = @2;", smapper.pushT(type), v);
190.339 + if (type == VarType.LONG) {
190.340 + final Long lv = new Long(v);
190.341 + final int low = (int)(lv.longValue() & 0xFFFFFFFF);
190.342 + final int hi = (int)(lv.longValue() >> 32);
190.343 + emit(out, "var @1 = 0x@3.next32(0x@2);", smapper.pushL(),
190.344 + Integer.toHexString(low), Integer.toHexString(hi));
190.345 + } else {
190.346 + emit(out, "var @1 = @2;", smapper.pushT(type), v);
190.347 + }
190.348 break;
190.349 }
190.350 case opc_lcmp:
190.351 - emit(out, "var @3 = (@2 == @1) ? 0 : ((@2 < @1) ? -1 : 1);",
190.352 + emit(out, "var @3 = @2.compare64(@1);",
190.353 smapper.popL(), smapper.popL(), smapper.pushI());
190.354 break;
190.355 case opc_fcmpl:
190.356 @@ -896,7 +951,7 @@
190.357 break;
190.358 }
190.359 case opc_newarray:
190.360 - int atype = readByte(byteCodes, ++i);
190.361 + int atype = readUByte(byteCodes, ++i);
190.362 String jvmType;
190.363 switch (atype) {
190.364 case 4: jvmType = "[Z"; break;
190.365 @@ -929,7 +984,7 @@
190.366 int type = readIntArg(byteCodes, i);
190.367 i += 2;
190.368 String typeName = jc.getClassName(type);
190.369 - int dim = readByte(byteCodes, ++i);
190.370 + int dim = readUByte(byteCodes, ++i);
190.371 StringBuilder dims = new StringBuilder();
190.372 dims.append('[');
190.373 for (int d = 0; d < dim; d++) {
190.374 @@ -1004,16 +1059,16 @@
190.375 break;
190.376 }
190.377 case opc_dup2: {
190.378 - if (smapper.get(0).isCategory2()) {
190.379 - final Variable v = smapper.get(0);
190.380 + final Variable vi1 = smapper.get(0);
190.381 +
190.382 + if (vi1.isCategory2()) {
190.383 emit(out, "var @1 = @2;",
190.384 - smapper.pushT(v.getType()), v);
190.385 + smapper.pushT(vi1.getType()), vi1);
190.386 } else {
190.387 - final Variable v1 = smapper.get(0);
190.388 - final Variable v2 = smapper.get(1);
190.389 + final Variable vi2 = smapper.get(1);
190.390 emit(out, "var @1 = @2, @3 = @4;",
190.391 - smapper.pushT(v2.getType()), v2,
190.392 - smapper.pushT(v1.getType()), v1);
190.393 + smapper.pushT(vi2.getType()), vi2,
190.394 + smapper.pushT(vi1.getType()), vi1);
190.395 }
190.396 break;
190.397 }
190.398 @@ -1028,10 +1083,11 @@
190.399 vo1, vi1, vo2, vi2, vo3, vo1);
190.400 break;
190.401 }
190.402 - case opc_dup_x2: {
190.403 - if (smapper.get(1).isCategory2()) {
190.404 - final Variable vi1 = smapper.pop();
190.405 - final Variable vi2 = smapper.pop();
190.406 + case opc_dup2_x1: {
190.407 + final Variable vi1 = smapper.pop();
190.408 + final Variable vi2 = smapper.pop();
190.409 +
190.410 + if (vi1.isCategory2()) {
190.411 final Variable vo3 = smapper.pushT(vi1.getType());
190.412 final Variable vo2 = smapper.pushT(vi2.getType());
190.413 final Variable vo1 = smapper.pushT(vi1.getType());
190.414 @@ -1039,8 +1095,32 @@
190.415 emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
190.416 vo1, vi1, vo2, vi2, vo3, vo1);
190.417 } else {
190.418 - final Variable vi1 = smapper.pop();
190.419 - final Variable vi2 = smapper.pop();
190.420 + final Variable vi3 = smapper.pop();
190.421 + final Variable vo5 = smapper.pushT(vi2.getType());
190.422 + final Variable vo4 = smapper.pushT(vi1.getType());
190.423 + final Variable vo3 = smapper.pushT(vi3.getType());
190.424 + final Variable vo2 = smapper.pushT(vi2.getType());
190.425 + final Variable vo1 = smapper.pushT(vi1.getType());
190.426 +
190.427 + emit(out, "var @1 = @2, @3 = @4, @5 = @6,",
190.428 + vo1, vi1, vo2, vi2, vo3, vi3);
190.429 + emit(out, " @1 = @2, @3 = @4;",
190.430 + vo4, vo1, vo5, vo2);
190.431 + }
190.432 + break;
190.433 + }
190.434 + case opc_dup_x2: {
190.435 + final Variable vi1 = smapper.pop();
190.436 + final Variable vi2 = smapper.pop();
190.437 +
190.438 + if (vi2.isCategory2()) {
190.439 + final Variable vo3 = smapper.pushT(vi1.getType());
190.440 + final Variable vo2 = smapper.pushT(vi2.getType());
190.441 + final Variable vo1 = smapper.pushT(vi1.getType());
190.442 +
190.443 + emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
190.444 + vo1, vi1, vo2, vi2, vo3, vo1);
190.445 + } else {
190.446 final Variable vi3 = smapper.pop();
190.447 final Variable vo4 = smapper.pushT(vi1.getType());
190.448 final Variable vo3 = smapper.pushT(vi3.getType());
190.449 @@ -1052,6 +1132,76 @@
190.450 }
190.451 break;
190.452 }
190.453 + case opc_dup2_x2: {
190.454 + final Variable vi1 = smapper.pop();
190.455 + final Variable vi2 = smapper.pop();
190.456 +
190.457 + if (vi1.isCategory2()) {
190.458 + if (vi2.isCategory2()) {
190.459 + final Variable vo3 = smapper.pushT(vi1.getType());
190.460 + final Variable vo2 = smapper.pushT(vi2.getType());
190.461 + final Variable vo1 = smapper.pushT(vi1.getType());
190.462 +
190.463 + emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
190.464 + vo1, vi1, vo2, vi2, vo3, vo1);
190.465 + } else {
190.466 + final Variable vi3 = smapper.pop();
190.467 + final Variable vo4 = smapper.pushT(vi1.getType());
190.468 + final Variable vo3 = smapper.pushT(vi3.getType());
190.469 + final Variable vo2 = smapper.pushT(vi2.getType());
190.470 + final Variable vo1 = smapper.pushT(vi1.getType());
190.471 +
190.472 + emit(out, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8;",
190.473 + vo1, vi1, vo2, vi2, vo3, vi3, vo4, vo1);
190.474 + }
190.475 + } else {
190.476 + final Variable vi3 = smapper.pop();
190.477 +
190.478 + if (vi3.isCategory2()) {
190.479 + final Variable vo5 = smapper.pushT(vi2.getType());
190.480 + final Variable vo4 = smapper.pushT(vi1.getType());
190.481 + final Variable vo3 = smapper.pushT(vi3.getType());
190.482 + final Variable vo2 = smapper.pushT(vi2.getType());
190.483 + final Variable vo1 = smapper.pushT(vi1.getType());
190.484 +
190.485 + emit(out, "var @1 = @2, @3 = @4, @5 = @6,",
190.486 + vo1, vi1, vo2, vi2, vo3, vi3);
190.487 + emit(out, " @1 = @2, @3 = @4;",
190.488 + vo4, vo1, vo5, vo2);
190.489 + } else {
190.490 + final Variable vi4 = smapper.pop();
190.491 + final Variable vo6 = smapper.pushT(vi2.getType());
190.492 + final Variable vo5 = smapper.pushT(vi1.getType());
190.493 + final Variable vo4 = smapper.pushT(vi4.getType());
190.494 + final Variable vo3 = smapper.pushT(vi3.getType());
190.495 + final Variable vo2 = smapper.pushT(vi2.getType());
190.496 + final Variable vo1 = smapper.pushT(vi1.getType());
190.497 +
190.498 + emit(out, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8,",
190.499 + vo1, vi1, vo2, vi2, vo3, vi3, vo4, vi4);
190.500 + emit(out, " @1 = @2, @3 = @4;",
190.501 + vo5, vo1, vo6, vo2);
190.502 + }
190.503 + }
190.504 + break;
190.505 + }
190.506 + case opc_swap: {
190.507 + final Variable vi1 = smapper.get(0);
190.508 + final Variable vi2 = smapper.get(1);
190.509 +
190.510 + if (vi1.getType() == vi2.getType()) {
190.511 + final Variable tmp = smapper.pushT(vi1.getType());
190.512 +
190.513 + emit(out, "var @1 = @2, @2 = @3, @3 = @1;",
190.514 + tmp, vi1, vi2);
190.515 + smapper.pop(1);
190.516 + } else {
190.517 + smapper.pop(2);
190.518 + smapper.pushT(vi1.getType());
190.519 + smapper.pushT(vi2.getType());
190.520 + }
190.521 + break;
190.522 + }
190.523 case opc_bipush:
190.524 emit(out, "var @1 = @2;",
190.525 smapper.pushI(), Integer.toString(byteCodes[++i]));
190.526 @@ -1066,8 +1216,26 @@
190.527 int indx = readIntArg(byteCodes, i);
190.528 String[] fi = jc.getFieldInfoName(indx);
190.529 final int type = VarType.fromFieldType(fi[2].charAt(0));
190.530 - emit(out, "var @2 = @1.fld_@3;",
190.531 - smapper.popA(), smapper.pushT(type), fi[1]);
190.532 + final String mangleClass = mangleSig(fi[0]);
190.533 + final String mangleClassAccess = accessClass(mangleClass);
190.534 + emit(out, "var @2 = @4(false)._@3.call(@1);",
190.535 + smapper.popA(),
190.536 + smapper.pushT(type), fi[1], mangleClassAccess
190.537 + );
190.538 + i += 2;
190.539 + break;
190.540 + }
190.541 + case opc_putfield: {
190.542 + int indx = readIntArg(byteCodes, i);
190.543 + String[] fi = jc.getFieldInfoName(indx);
190.544 + final int type = VarType.fromFieldType(fi[2].charAt(0));
190.545 + final String mangleClass = mangleSig(fi[0]);
190.546 + final String mangleClassAccess = accessClass(mangleClass);
190.547 + emit(out, "@4(false)._@3.call(@2, @1);",
190.548 + smapper.popT(type),
190.549 + smapper.popA(), fi[1],
190.550 + mangleClassAccess
190.551 + );
190.552 i += 2;
190.553 break;
190.554 }
190.555 @@ -1082,15 +1250,6 @@
190.556 addReference(fi[0]);
190.557 break;
190.558 }
190.559 - case opc_putfield: {
190.560 - int indx = readIntArg(byteCodes, i);
190.561 - String[] fi = jc.getFieldInfoName(indx);
190.562 - final int type = VarType.fromFieldType(fi[2].charAt(0));
190.563 - emit(out, "@2.fld_@3 = @1;",
190.564 - smapper.popT(type), smapper.popA(), fi[1]);
190.565 - i += 2;
190.566 - break;
190.567 - }
190.568 case opc_putstatic: {
190.569 int indx = readIntArg(byteCodes, i);
190.570 String[] fi = jc.getFieldInfoName(indx);
190.571 @@ -1121,7 +1280,7 @@
190.572 int indx = readIntArg(byteCodes, i);
190.573 final String type = jc.getClassName(indx);
190.574 if (!type.startsWith("[")) {
190.575 - emit(out, "var @2 = @1.$instOf_@3 ? 1 : 0;",
190.576 + emit(out, "var @2 = @1 != null && @1.$instOf_@3 ? 1 : 0;",
190.577 smapper.popA(), smapper.pushI(),
190.578 type.replace('/', '_'));
190.579 } else {
190.580 @@ -1154,7 +1313,12 @@
190.581 break;
190.582 }
190.583
190.584 + case opc_wide:
190.585 + wide = true;
190.586 + break;
190.587 +
190.588 default: {
190.589 + wide = false;
190.590 emit(out, "throw 'unknown bytecode @1';",
190.591 Integer.toString(c));
190.592 }
190.593 @@ -1162,7 +1326,7 @@
190.594 if (debug(" //")) {
190.595 for (int j = prev; j <= i; j++) {
190.596 out.append(" ");
190.597 - final int cc = readByte(byteCodes, j);
190.598 + final int cc = readUByte(byteCodes, j);
190.599 out.append(Integer.toString(cc));
190.600 }
190.601 }
190.602 @@ -1191,17 +1355,27 @@
190.603 final int indxLo = byteCodes[offsetInstruction + 2];
190.604 return (indxHi & 0xffffff00) | (indxLo & 0xff);
190.605 }
190.606 - private int readInt4(byte[] byteCodes, int offsetInstruction) {
190.607 - final int d = byteCodes[offsetInstruction + 0] << 24;
190.608 - final int c = byteCodes[offsetInstruction + 1] << 16;
190.609 - final int b = byteCodes[offsetInstruction + 2] << 8;
190.610 - final int a = byteCodes[offsetInstruction + 3];
190.611 + private int readInt4(byte[] byteCodes, int offset) {
190.612 + final int d = byteCodes[offset + 0] << 24;
190.613 + final int c = byteCodes[offset + 1] << 16;
190.614 + final int b = byteCodes[offset + 2] << 8;
190.615 + final int a = byteCodes[offset + 3];
190.616 return (d & 0xff000000) | (c & 0xff0000) | (b & 0xff00) | (a & 0xff);
190.617 }
190.618 - private int readByte(byte[] byteCodes, int offsetInstruction) {
190.619 - return byteCodes[offsetInstruction] & 0xff;
190.620 + private int readUByte(byte[] byteCodes, int offset) {
190.621 + return byteCodes[offset] & 0xff;
190.622 }
190.623 -
190.624 +
190.625 + private int readUShort(byte[] byteCodes, int offset) {
190.626 + return ((byteCodes[offset] & 0xff) << 8)
190.627 + | (byteCodes[offset + 1] & 0xff);
190.628 + }
190.629 +
190.630 + private int readShort(byte[] byteCodes, int offset) {
190.631 + return (byteCodes[offset] << 8)
190.632 + | (byteCodes[offset + 1] & 0xff);
190.633 + }
190.634 +
190.635 private static void countArgs(String descriptor, char[] returnType, StringBuilder sig, StringBuilder cnt) {
190.636 int i = 0;
190.637 Boolean count = null;
190.638 @@ -1279,6 +1453,10 @@
190.639 }
190.640 }
190.641
190.642 + static String mangleSig(String sig) {
190.643 + return mangleSig(sig, 0, sig.length());
190.644 + }
190.645 +
190.646 private static String mangleSig(String txt, int first, int last) {
190.647 StringBuilder sb = new StringBuilder();
190.648 for (int i = first; i < last; i++) {
190.649 @@ -1443,7 +1621,7 @@
190.650 final String jvmType = "Lorg/apidesign/bck2brwsr/core/JavaScriptBody;";
190.651 class P extends AnnotationParser {
190.652 public P() {
190.653 - super(false);
190.654 + super(false, true);
190.655 }
190.656
190.657 int cnt;
190.658 @@ -1499,7 +1677,7 @@
190.659 final String[] values = new String[attrNames.length];
190.660 final boolean[] found = { false };
190.661 final String jvmType = "L" + className.replace('.', '/') + ";";
190.662 - AnnotationParser ap = new AnnotationParser(false) {
190.663 + AnnotationParser ap = new AnnotationParser(false, true) {
190.664 @Override
190.665 protected void visitAttr(String type, String attr, String at, String value) {
190.666 if (type.equals(jvmType)) {
190.667 @@ -1536,35 +1714,71 @@
190.668 return " = null;";
190.669 }
190.670
190.671 - private static void generateAnno(ClassData cd, final Appendable out, byte[] data) throws IOException {
190.672 - AnnotationParser ap = new AnnotationParser(true) {
190.673 - int anno;
190.674 - int cnt;
190.675 + private void generateAnno(ClassData cd, final Appendable out, byte[] data) throws IOException {
190.676 + AnnotationParser ap = new AnnotationParser(true, false) {
190.677 + int[] cnt = new int[32];
190.678 + int depth;
190.679
190.680 @Override
190.681 - protected void visitAnnotationStart(String type) throws IOException {
190.682 - if (anno++ > 0) {
190.683 + protected void visitAnnotationStart(String attrType, boolean top) throws IOException {
190.684 + final String slashType = attrType.substring(1, attrType.length() - 1);
190.685 + requireReference(slashType);
190.686 +
190.687 + if (cnt[depth]++ > 0) {
190.688 out.append(",");
190.689 }
190.690 - out.append('"').append(type).append("\" : {\n");
190.691 - cnt = 0;
190.692 + if (top) {
190.693 + out.append('"').append(attrType).append("\" : ");
190.694 + }
190.695 + out.append("{\n");
190.696 + cnt[++depth] = 0;
190.697 }
190.698
190.699 @Override
190.700 - protected void visitAnnotationEnd(String type) throws IOException {
190.701 + protected void visitAnnotationEnd(String type, boolean top) throws IOException {
190.702 out.append("\n}\n");
190.703 + depth--;
190.704 + }
190.705 +
190.706 + @Override
190.707 + protected void visitValueStart(String attrName, char type) throws IOException {
190.708 + if (cnt[depth]++ > 0) {
190.709 + out.append(",\n");
190.710 + }
190.711 + cnt[++depth] = 0;
190.712 + if (attrName != null) {
190.713 + out.append(attrName).append(" : ");
190.714 + }
190.715 + if (type == '[') {
190.716 + out.append("[");
190.717 + }
190.718 + }
190.719 +
190.720 + @Override
190.721 + protected void visitValueEnd(String attrName, char type) throws IOException {
190.722 + if (type == '[') {
190.723 + out.append("]");
190.724 + }
190.725 + depth--;
190.726 }
190.727
190.728 @Override
190.729 protected void visitAttr(String type, String attr, String attrType, String value)
190.730 throws IOException {
190.731 - if (attr == null) {
190.732 + if (attr == null && value == null) {
190.733 return;
190.734 }
190.735 - if (cnt++ > 0) {
190.736 - out.append(",\n");
190.737 - }
190.738 - out.append(attr).append("__").append(attrType).append(" : ").append(value);
190.739 + out.append(value);
190.740 + }
190.741 +
190.742 + @Override
190.743 + protected void visitEnumAttr(String type, String attr, String attrType, String value)
190.744 + throws IOException {
190.745 + final String slashType = attrType.substring(1, attrType.length() - 1);
190.746 + requireReference(slashType);
190.747 +
190.748 + out.append(accessClass(slashType.replace('/', '_')))
190.749 + .append("(false).constructor.").append(value);
190.750 }
190.751 };
190.752 ap.parse(data, cd);
191.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
191.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ParseMan.java Sun Feb 17 17:58:34 2013 +0100
191.3 @@ -0,0 +1,57 @@
191.4 +/**
191.5 + * Back 2 Browser Bytecode Translator
191.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
191.7 + *
191.8 + * This program is free software: you can redistribute it and/or modify
191.9 + * it under the terms of the GNU General Public License as published by
191.10 + * the Free Software Foundation, version 2 of the License.
191.11 + *
191.12 + * This program is distributed in the hope that it will be useful,
191.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
191.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
191.15 + * GNU General Public License for more details.
191.16 + *
191.17 + * You should have received a copy of the GNU General Public License
191.18 + * along with this program. Look for COPYING file in the top folder.
191.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
191.20 + */
191.21 +package org.apidesign.vm4brwsr;
191.22 +
191.23 +import java.io.IOException;
191.24 +import java.io.InputStream;
191.25 +import org.apidesign.bck2brwsr.emul.lang.ManifestInputStream;
191.26 +
191.27 +/**
191.28 + *
191.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
191.30 + */
191.31 +final class ParseMan extends ManifestInputStream {
191.32 + private String cp;
191.33 + private String mc;
191.34 +
191.35 + public ParseMan(InputStream is) throws IOException {
191.36 + super(is);
191.37 + readAttributes(new byte[512]);
191.38 + }
191.39 +
191.40 + @Override
191.41 + protected String putValue(String key, String value) {
191.42 + if ("Class-Path".equals(key)) {
191.43 + cp = value;
191.44 + }
191.45 + if ("Main-Class".equals(key)) {
191.46 + mc = value;
191.47 + }
191.48 + return null;
191.49 + }
191.50 +
191.51 + String getMainClass() {
191.52 + return mc;
191.53 + }
191.54 +
191.55 + @Override
191.56 + public String toString() {
191.57 + return cp;
191.58 + }
191.59 +
191.60 +}
192.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Fri Jan 25 15:08:24 2013 +0100
192.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Sun Feb 17 17:58:34 2013 +0100
192.3 @@ -31,7 +31,12 @@
192.4
192.5 static {
192.6 // uses VMLazy to load dynamic classes
192.7 - VMLazy.init();
192.8 + boolean assertsOn = false;
192.9 + assert assertsOn = true;
192.10 + if (assertsOn) {
192.11 + VMLazy.init();
192.12 + Zips.init();
192.13 + }
192.14 }
192.15
192.16 @Override
192.17 @@ -43,8 +48,7 @@
192.18 new VM(out).doCompile(l, names);
192.19 }
192.20 protected void doCompile(Bck2Brwsr.Resources l, StringArray names) throws IOException {
192.21 - out.append("(function VM(global) {");
192.22 - out.append("\n var vm = {};");
192.23 + out.append("(function VM(global) {var fillInVMSkeleton = function(vm) {");
192.24 StringArray processed = new StringArray();
192.25 StringArray initCode = new StringArray();
192.26 for (String baseClass : names.toArray()) {
192.27 @@ -112,25 +116,31 @@
192.28 }
192.29 }
192.30 out.append(
192.31 - " global.bck2brwsr = function() {\n"
192.32 - + " var args = arguments;\n"
192.33 + " return vm;\n"
192.34 + + " };\n"
192.35 + + " global.bck2brwsr = function() {\n"
192.36 + + " var args = Array.prototype.slice.apply(arguments);\n"
192.37 + + " var vm = fillInVMSkeleton({});\n"
192.38 + " var loader = {};\n"
192.39 + " loader.vm = vm;\n"
192.40 + " loader.loadClass = function(name) {\n"
192.41 + " var attr = name.replace__Ljava_lang_String_2CC('.','_');\n"
192.42 + " var fn = vm[attr];\n"
192.43 + " if (fn) return fn(false);\n"
192.44 - + " if (!args[0]) throw 'bck2brwsr initialized without loader function, cannot load ' + name;\n"
192.45 + " return vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
192.46 + " load__Ljava_lang_Object_2Ljava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, name, args);\n"
192.47 + " }\n"
192.48 - + " if (args[0]) {\n"
192.49 - + " vm.loadClass = loader.loadClass;\n"
192.50 - + " vm.loadBytes = function(name) {\n"
192.51 - + " if (!args[0]) throw 'bck2brwsr initialized without loader function, cannot load ' + name;\n"
192.52 - + " return args[0](name);\n"
192.53 - + " }\n"
192.54 + + " if (vm.loadClass) {\n"
192.55 + + " throw 'Cannot initialize the bck2brwsr VM twice!';\n"
192.56 + " }\n"
192.57 + + " vm.loadClass = loader.loadClass;\n"
192.58 + + " vm.loadBytes = function(name) {\n"
192.59 + + " return vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
192.60 + + " loadBytes___3BLjava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, name, args);\n"
192.61 + + " }\n"
192.62 + + " vm.java_lang_reflect_Array(false);\n"
192.63 + + " vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
192.64 + + " loadBytes___3BLjava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, null, args);\n"
192.65 + " return loader;\n"
192.66 + " };\n");
192.67 out.append("}(this));");
193.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java Fri Jan 25 15:08:24 2013 +0100
193.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java Sun Feb 17 17:58:34 2013 +0100
193.3 @@ -20,6 +20,7 @@
193.4 import java.io.ByteArrayInputStream;
193.5 import java.io.IOException;
193.6 import java.io.InputStream;
193.7 +import java.lang.reflect.Array;
193.8 import org.apidesign.bck2brwsr.core.JavaScriptBody;
193.9
193.10 /**
193.11 @@ -38,23 +39,19 @@
193.12 static void init() {
193.13 }
193.14
193.15 - @JavaScriptBody(args={"l", "res", "args" }, body = ""
193.16 - + "\ntry {"
193.17 - + "\n return args[0](res.toString());"
193.18 - + "\n} catch (x) {"
193.19 - + "\n throw Object.getOwnPropertyNames(l.vm).toString() + x.toString();"
193.20 - + "\n}")
193.21 - private static native byte[] read(Object l, String res, Object[] args);
193.22 -
193.23 static Object load(Object loader, String name, Object[] arguments)
193.24 throws IOException, ClassNotFoundException {
193.25 return new VMLazy(loader, arguments).load(name, false);
193.26 }
193.27
193.28 + static byte[] loadBytes(Object loader, String name, Object[] arguments) throws Exception {
193.29 + return Zips.loadFromCp(arguments, name);
193.30 + }
193.31 +
193.32 private Object load(String name, boolean instance)
193.33 throws IOException, ClassNotFoundException {
193.34 String res = name.replace('.', '/') + ".class";
193.35 - byte[] arr = read(loader, res, args);
193.36 + byte[] arr = Zips.loadFromCp(args, res);
193.37 if (arr == null) {
193.38 throw new ClassNotFoundException(name);
193.39 }
193.40 @@ -117,8 +114,8 @@
193.41 body =
193.42 "var cls = n.replace__Ljava_lang_String_2CC('/','_').toString();"
193.43 + "\nvar dot = n.replace__Ljava_lang_String_2CC('/','.').toString();"
193.44 - + "\nvar lazy = this.fld_lazy;"
193.45 - + "\nvar loader = lazy.fld_loader;"
193.46 + + "\nvar lazy = this._lazy();"
193.47 + + "\nvar loader = lazy._loader();"
193.48 + "\nvar vm = loader.vm;"
193.49 + "\nif (vm[cls]) return false;"
193.50 + "\nvm[cls] = function() {"
194.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/VarType.java Fri Jan 25 15:08:24 2013 +0100
194.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/VarType.java Sun Feb 17 17:58:34 2013 +0100
194.3 @@ -45,13 +45,13 @@
194.4 return VarType.DOUBLE;
194.5 case RuntimeConstants.ITEM_Long:
194.6 return VarType.LONG;
194.7 + case RuntimeConstants.ITEM_Null:
194.8 + case RuntimeConstants.ITEM_InitObject:
194.9 case RuntimeConstants.ITEM_Object:
194.10 + case RuntimeConstants.ITEM_NewObject:
194.11 return VarType.REFERENCE;
194.12
194.13 case RuntimeConstants.ITEM_Bogus:
194.14 - case RuntimeConstants.ITEM_Null:
194.15 - case RuntimeConstants.ITEM_InitObject:
194.16 - case RuntimeConstants.ITEM_NewObject:
194.17 /* unclear how to handle for now */
194.18 default:
194.19 throw new IllegalStateException("Unhandled stack map type");
195.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
195.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/Zips.java Sun Feb 17 17:58:34 2013 +0100
195.3 @@ -0,0 +1,187 @@
195.4 +/**
195.5 + * Back 2 Browser Bytecode Translator
195.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
195.7 + *
195.8 + * This program is free software: you can redistribute it and/or modify
195.9 + * it under the terms of the GNU General Public License as published by
195.10 + * the Free Software Foundation, version 2 of the License.
195.11 + *
195.12 + * This program is distributed in the hope that it will be useful,
195.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
195.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
195.15 + * GNU General Public License for more details.
195.16 + *
195.17 + * You should have received a copy of the GNU General Public License
195.18 + * along with this program. Look for COPYING file in the top folder.
195.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
195.20 + */
195.21 +package org.apidesign.vm4brwsr;
195.22 +
195.23 +import java.io.ByteArrayInputStream;
195.24 +import java.io.IOException;
195.25 +import java.io.InputStream;
195.26 +import java.net.URL;
195.27 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
195.28 +import org.apidesign.bck2brwsr.emul.zip.FastJar;
195.29 +
195.30 +/** Conversion from classpath to load function.
195.31 + *
195.32 + * @author Jaroslav Tulach <jtulach@netbeans.org>
195.33 + */
195.34 +final class Zips {
195.35 + private final FastJar fj;
195.36 +
195.37 + private Zips(String path, byte[] zipData) throws IOException {
195.38 + long bef = timeNow();
195.39 + fj = new FastJar(zipData);
195.40 + for (FastJar.Entry e : fj.list()) {
195.41 + putRes(e.name, e);
195.42 + }
195.43 + log("Iterating thru " + path + " took " + (timeNow() - bef) + "ms");
195.44 + }
195.45 +
195.46 + public static void init() {
195.47 + }
195.48 + @JavaScriptBody(args = { "arr" }, body = "return arr.length;")
195.49 + private static native int length(Object arr);
195.50 + @JavaScriptBody(args = { "arr", "index" }, body = "return arr[index];")
195.51 + private static native Object at(Object arr, int index);
195.52 + @JavaScriptBody(args = { "arr", "index", "value" }, body = "arr[index] = value; return value;")
195.53 + private static native Object set(Object arr, int index, Object value);
195.54 +
195.55 + public static byte[] loadFromCp(Object classpath, String res)
195.56 + throws IOException, ClassNotFoundException {
195.57 + for (int i = 0; i < length(classpath); i++) {
195.58 + Object c = at(classpath, i);
195.59 + if (c instanceof String) {
195.60 + try {
195.61 + String url = (String)c;
195.62 + final Zips z = toZip(url);
195.63 + c = set(classpath, i, z);
195.64 + final byte[] man = z.findRes("META-INF/MANIFEST.MF");
195.65 + if (man != null) {
195.66 + String mainClass = processClassPathAttr(man, url, classpath);
195.67 +// if (mainClass != null) {
195.68 +// Class.forName(mainClass);
195.69 +// }
195.70 + }
195.71 + } catch (IOException ex) {
195.72 + set(classpath, i, ex);
195.73 + log("Cannot load " + c + " - " + ex.getClass().getName() + ":" + ex.getMessage());
195.74 + }
195.75 + }
195.76 + if (res != null) {
195.77 + byte[] checkRes;
195.78 + if (c instanceof Zips) {
195.79 + checkRes = ((Zips)c).findRes(res);
195.80 + } else {
195.81 + checkRes = callFunction(c, res);
195.82 + }
195.83 + if (checkRes != null) {
195.84 + return checkRes;
195.85 + }
195.86 + }
195.87 + }
195.88 + return null;
195.89 + }
195.90 +
195.91 + @JavaScriptBody(args = { "fn", "res" }, body =
195.92 + "if (typeof fn === 'function') return fn(res);\n"
195.93 + + "return null;"
195.94 + )
195.95 + private static native byte[] callFunction(Object fn, String res);
195.96 +
195.97 + @JavaScriptBody(args = { "msg" }, body = "console.log(msg.toString());")
195.98 + private static native void log(String msg);
195.99 +
195.100 + private byte[] findRes(String res) throws IOException {
195.101 + Object arr = findResImpl(res);
195.102 + if (arr instanceof FastJar.Entry) {
195.103 + long bef = timeNow();
195.104 + InputStream zip = fj.getInputStream((FastJar.Entry)arr);
195.105 + arr = readFully(new byte[512], zip);
195.106 + putRes(res, arr);
195.107 + log("Reading " + res + " took " + (timeNow() - bef) + "ms");
195.108 + }
195.109 + return (byte[]) arr;
195.110 + }
195.111 +
195.112 + @JavaScriptBody(args = { "res" }, body = "var r = this[res]; return r ? r : null;")
195.113 + private native Object findResImpl(String res);
195.114 +
195.115 + @JavaScriptBody(args = { "res", "arr" }, body = "this[res] = arr;")
195.116 + private native void putRes(String res, Object arr);
195.117 +
195.118 + private static Zips toZip(String path) throws IOException {
195.119 + URL u = new URL(path);
195.120 + byte[] zipData = (byte[]) u.getContent(new Class[] { byte[].class });
195.121 + return new Zips(path, zipData);
195.122 + }
195.123 +
195.124 + private static String processClassPathAttr(final byte[] man, String url, Object classpath) throws IOException {
195.125 + try (ParseMan is = new ParseMan(new ByteArrayInputStream(man))) {
195.126 + String cp = is.toString();
195.127 + if (cp != null) {
195.128 + cp = cp.trim();
195.129 + for (int p = 0; p < cp.length();) {
195.130 + int n = cp.indexOf(' ', p);
195.131 + if (n == -1) {
195.132 + n = cp.length();
195.133 + }
195.134 + String el = cp.substring(p, n);
195.135 + URL u = new URL(new URL(url), el);
195.136 + classpath = addToArray(classpath, u.toString());
195.137 + p = n + 1;
195.138 + }
195.139 + }
195.140 + return is.getMainClass();
195.141 + }
195.142 + }
195.143 +
195.144 + private static Object addToArray(Object arr, String value) {
195.145 + final int last = length(arr);
195.146 + Object ret = enlargeArray(arr, last + 1);
195.147 + set(ret, last, value);
195.148 + return ret;
195.149 + }
195.150 +
195.151 + @JavaScriptBody(args = { "arr", "len" }, body = "while (arr.length < len) arr.push(null); return arr;")
195.152 + private static native Object enlargeArray(Object arr, int len);
195.153 + @JavaScriptBody(args = { "arr", "len" }, body = "while (arr.length < len) arr.push(0);")
195.154 + private static native void enlargeBytes(byte[] arr, int len);
195.155 +
195.156 + @JavaScriptBody(args = { "arr", "len" }, body = "arr.splice(len, arr.length - len);")
195.157 + private static native void sliceArray(byte[] arr, int len);
195.158 +
195.159 + private static Object readFully(byte[] arr, InputStream zip) throws IOException {
195.160 + int offset = 0;
195.161 + for (;;) {
195.162 + int len = zip.read(arr, offset, arr.length - offset);
195.163 + if (len == -1) {
195.164 + break;
195.165 + }
195.166 + offset += len;
195.167 + if (offset == arr.length) {
195.168 + enlargeBytes(arr, arr.length + 4096);
195.169 + }
195.170 + }
195.171 + sliceArray(arr, offset);
195.172 + return arr;
195.173 + }
195.174 +
195.175 + private static long timeNow() {
195.176 + double time = m();
195.177 + if (time >= 0) {
195.178 + return (long)time;
195.179 + }
195.180 + return org.apidesign.bck2brwsr.emul.lang.System.currentTimeMillis();
195.181 + }
195.182 + @JavaScriptBody(args = {}, body =
195.183 + "if (typeof window.performance === 'undefined') return -1;\n"
195.184 + + "if (typeof window.performance.now === 'undefined') return -1;\n"
195.185 + + "return window.performance.now();"
195.186 + )
195.187 + private static native double m();
195.188 +
195.189 +
195.190 +}
196.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java Fri Jan 25 15:08:24 2013 +0100
196.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java Sun Feb 17 17:58:34 2013 +0100
196.3 @@ -17,7 +17,6 @@
196.4 */
196.5 package org.apidesign.vm4brwsr;
196.6
196.7 -import javax.script.Invocable;
196.8 import static org.testng.Assert.*;
196.9 import org.testng.annotations.BeforeClass;
196.10 import org.testng.annotations.Test;
196.11 @@ -76,18 +75,13 @@
196.12 assertExec("Returns 'false'", Array.class, "instanceOfArray__ZLjava_lang_Object_2", Double.valueOf(0), "non-array");
196.13 }
196.14
196.15 - private static CharSequence codeSeq;
196.16 - private static Invocable code;
196.17 + private static TestVM code;
196.18
196.19 @BeforeClass
196.20 public void compileTheCode() throws Exception {
196.21 - StringBuilder sb = new StringBuilder();
196.22 - code = StaticMethodTest.compileClass(sb,
196.23 - "org/apidesign/vm4brwsr/Array"
196.24 - );
196.25 - codeSeq = sb;
196.26 + code = TestVM.compileClass("org/apidesign/vm4brwsr/Array");
196.27 }
196.28 private static void assertExec(String msg, Class clazz, String method, Object expRes, Object... args) throws Exception {
196.29 - StaticMethodTest.assertExec(code, codeSeq, msg, clazz, method, expRes, args);
196.30 + code.assertExec(msg, clazz, method, expRes, args);
196.31 }
196.32 }
197.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java Fri Jan 25 15:08:24 2013 +0100
197.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java Sun Feb 17 17:58:34 2013 +0100
197.3 @@ -17,7 +17,6 @@
197.4 */
197.5 package org.apidesign.vm4brwsr;
197.6
197.7 -import javax.script.Invocable;
197.8 import org.testng.annotations.Test;
197.9 import static org.testng.Assert.*;
197.10 import org.testng.annotations.BeforeClass;
197.11 @@ -87,12 +86,27 @@
197.12 @Test public void jsAnnotation() throws Exception {
197.13 assertExec("Check class annotation", Classes.class, "getMarker__I", Double.valueOf(10));
197.14 }
197.15 + @Test public void jsArrayAnnotation() throws Exception {
197.16 + assertExec("Check array annotation", Classes.class, "getMarkerNicknames__Ljava_lang_String_2", Classes.getMarkerNicknames());
197.17 + }
197.18 + @Test public void jsEnumAnnotation() throws Exception {
197.19 + assertExec("Check enum annotation", Classes.class, "getMarkerE__Ljava_lang_String_2", Classes.getMarkerE());
197.20 + }
197.21 + @Test public void jsRetentionAnnotation() throws Exception {
197.22 + assertExec("Check enum annotation", Classes.class, "getRetention__Ljava_lang_String_2", Classes.getRetention());
197.23 + }
197.24 @Test public void jsStringAnnotation() throws Exception {
197.25 assertExec("Check class annotation", Classes.class, "getNamer__Ljava_lang_String_2Z", "my text", true);
197.26 }
197.27 @Test public void jsStringAnnotationFromArray() throws Exception {
197.28 assertExec("Check class annotation", Classes.class, "getNamer__Ljava_lang_String_2Z", "my text", false);
197.29 }
197.30 + @Test public void jsInnerAnnotation() throws Exception {
197.31 + assertExec("Check inner annotation", Classes.class, "getInnerNamer__I", Double.valueOf(Classes.getInnerNamer()));
197.32 + }
197.33 + @Test public void jsInnerAnnotationFromArray() throws Exception {
197.34 + assertExec("Check inner annotation", Classes.class, "getInnerNamers__I", Double.valueOf(Classes.getInnerNamers()));
197.35 + }
197.36 @Test public void javaInvokeMethod() throws Exception {
197.37 assertEquals(Classes.reflectiveMethodCall(true, "name"), "java.io.IOException", "Calls the name() method via reflection");
197.38 }
197.39 @@ -102,6 +116,14 @@
197.40 "java.io.IOException", true, "name"
197.41 );
197.42 }
197.43 +
197.44 + @Test public void jsMethodDeclaredInObject() throws Exception {
197.45 + assertExec("Defined in Object", Classes.class,
197.46 + "objectName__Ljava_lang_String_2",
197.47 + "java.lang.Object"
197.48 + );
197.49 + }
197.50 +
197.51 @Test public void jsInvokeParamMethod() throws Exception {
197.52 assertExec("sums two numbers via reflection", Classes.class,
197.53 "reflectiveSum__III", Double.valueOf(5), 2, 3
197.54 @@ -149,14 +171,12 @@
197.55 0.0, "java.lang.String"
197.56 );
197.57 }
197.58 - /*
197.59 @Test public void isInterface() throws Exception {
197.60 assertExec("Calls Class.isInterface", Classes.class,
197.61 "isInterface__ZLjava_lang_String_2",
197.62 1.0, "java.lang.Runnable"
197.63 );
197.64 }
197.65 - */
197.66 @Test public void integerType() throws Exception {
197.67 assertExec("Computes the type", Classes.class,
197.68 "intType__Ljava_lang_String_2",
197.69 @@ -164,22 +184,23 @@
197.70 );
197.71 }
197.72
197.73 - private static CharSequence codeSeq;
197.74 - private static Invocable code;
197.75 + private static TestVM code;
197.76
197.77 @BeforeClass
197.78 public void compileTheCode() throws Exception {
197.79 - if (codeSeq == null) {
197.80 - StringBuilder sb = new StringBuilder();
197.81 - code = StaticMethodTest.compileClass(sb, "org/apidesign/vm4brwsr/Classes");
197.82 - codeSeq = sb;
197.83 - }
197.84 + code = TestVM.compileClass("org/apidesign/vm4brwsr/Classes");
197.85 }
197.86
197.87 private void assertExec(
197.88 String msg, Class clazz, String method, Object expRes, Object... args
197.89 ) throws Exception {
197.90 - StaticMethodTest.assertExec(code, codeSeq, msg, clazz, method, expRes, args);
197.91 + code.assertExec(msg, clazz, method, expRes, args);
197.92 + }
197.93 + @Test public void isClassAssignable() throws Exception {
197.94 + assertExec("isAssignable works on subclasses", Classes.class,
197.95 + "isClassAssignable__Z",
197.96 + true
197.97 + );
197.98 }
197.99
197.100 }
198.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java Fri Jan 25 15:08:24 2013 +0100
198.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java Sun Feb 17 17:58:34 2013 +0100
198.3 @@ -19,6 +19,8 @@
198.4
198.5 import java.io.IOException;
198.6 import java.lang.annotation.Annotation;
198.7 +import java.lang.annotation.Retention;
198.8 +import java.lang.annotation.RetentionPolicy;
198.9 import java.lang.reflect.Method;
198.10 import java.net.MalformedURLException;
198.11 import org.apidesign.bck2brwsr.core.JavaScriptBody;
198.12 @@ -27,8 +29,11 @@
198.13 *
198.14 * @author Jaroslav Tulach <jtulach@netbeans.org>
198.15 */
198.16 -@ClassesMarker(number = 10)
198.17 -@ClassesNamer(name = "my text")
198.18 +@ClassesMarker(number = 10, nicknames = { "Ten", "Deset" }, count = ClassesMarker.E.TWO, subs = {
198.19 + @ClassesMarker.Anno(Integer.SIZE),
198.20 + @ClassesMarker.Anno(Integer.MIN_VALUE)
198.21 +})
198.22 +@ClassesNamer(name = "my text", anno = @ClassesMarker.Anno(333))
198.23 public class Classes {
198.24 public static String nameOfIO() {
198.25 return nameFor(IOException.class);
198.26 @@ -38,6 +43,8 @@
198.27 return c.getName();
198.28 }
198.29
198.30 + private static final Class<?> PRELOAD = Runnable.class;
198.31 +
198.32 public static boolean isInterface(String s) throws ClassNotFoundException {
198.33 return Class.forName(s).isInterface();
198.34 }
198.35 @@ -55,7 +62,7 @@
198.36 return new IOException().getClass().getName().toString();
198.37 }
198.38
198.39 - @ClassesMarker(number = 1)
198.40 + @ClassesMarker(number = 1, nicknames = { "One", "Jedna" } )
198.41 public static String name() {
198.42 return IOException.class.getName().toString();
198.43 }
198.44 @@ -65,6 +72,11 @@
198.45 public static String canonicalName() {
198.46 return IOException.class.getCanonicalName();
198.47 }
198.48 +
198.49 + public static String objectName() throws NoSuchMethodException {
198.50 + return IOException.class.getMethod("wait").getDeclaringClass().getName();
198.51 + }
198.52 +
198.53 public static boolean newInstance() throws Exception {
198.54 IOException ioe = IOException.class.newInstance();
198.55 if (ioe instanceof IOException) {
198.56 @@ -85,8 +97,45 @@
198.57 return -2;
198.58 }
198.59 ClassesMarker cm = Classes.class.getAnnotation(ClassesMarker.class);
198.60 + assert cm instanceof Object : "Is object " + cm;
198.61 + assert cm instanceof Annotation : "Is annotation " + cm;
198.62 + assert !((Object)cm instanceof Class) : "Is not Class " + cm;
198.63 return cm == null ? -1 : cm.number();
198.64 }
198.65 + public static String getMarkerNicknames() {
198.66 + ClassesMarker cm = Classes.class.getAnnotation(ClassesMarker.class);
198.67 + if (cm == null) {
198.68 + return null;
198.69 + }
198.70 +
198.71 + final Object[] arr = cm.nicknames();
198.72 + assert arr instanceof Object[] : "Instance of Object array: " + arr;
198.73 + assert arr instanceof String[] : "Instance of String array: " + arr;
198.74 + assert !(arr instanceof Integer[]) : "Not instance of Integer array: " + arr;
198.75 +
198.76 + StringBuilder sb = new StringBuilder();
198.77 + for (String s : cm.nicknames()) {
198.78 + sb.append(s).append("\n");
198.79 + }
198.80 + return sb.toString().toString();
198.81 + }
198.82 + @Retention(RetentionPolicy.CLASS)
198.83 + @interface Ann {
198.84 + }
198.85 +
198.86 + public static String getRetention() throws Exception {
198.87 + Retention r = Ann.class.getAnnotation(Retention.class);
198.88 + assert r != null : "Annotation is present";
198.89 + assert r.value() == RetentionPolicy.CLASS : "Policy value is OK: " + r.value();
198.90 + return r.annotationType().getName();
198.91 + }
198.92 + public static String getMarkerE() {
198.93 + ClassesMarker cm = Classes.class.getAnnotation(ClassesMarker.class);
198.94 + if (cm == null) {
198.95 + return null;
198.96 + }
198.97 + return cm.count().name();
198.98 + }
198.99 public static String getNamer(boolean direct) {
198.100 if (direct) {
198.101 ClassesNamer cm = Classes.class.getAnnotation(ClassesNamer.class);
198.102 @@ -99,6 +148,20 @@
198.103 }
198.104 return null;
198.105 }
198.106 + public static int getInnerNamer() {
198.107 + ClassesNamer cm = Classes.class.getAnnotation(ClassesNamer.class);
198.108 + assert cm != null : "ClassesNamer is present";
198.109 + return cm.anno().value();
198.110 + }
198.111 + public static int getInnerNamers() {
198.112 + ClassesMarker cm = Classes.class.getAnnotation(ClassesMarker.class);
198.113 + assert cm != null : "ClassesNamer is present";
198.114 + int sum = 0;
198.115 + for (ClassesMarker.Anno anno : cm.subs()) {
198.116 + sum += anno.value();
198.117 + }
198.118 + return sum;
198.119 + }
198.120
198.121 public static String intType() {
198.122 return Integer.TYPE.getName();
198.123 @@ -151,4 +214,20 @@
198.124 Method m = StaticMethod.class.getMethod("sum", int.class, int.class);
198.125 return (int) m.invoke(null, a, b);
198.126 }
198.127 +
198.128 + private abstract class Application {
198.129 + public abstract int getID();
198.130 + }
198.131 +
198.132 + private class MyApplication extends Application {
198.133 + @Override
198.134 + public int getID() {
198.135 + return 1;
198.136 + }
198.137 + }
198.138 +
198.139 + public static boolean isClassAssignable() {
198.140 + return Application.class.isAssignableFrom(MyApplication.class);
198.141 + }
198.142 +
198.143 }
199.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ClassesMarker.java Fri Jan 25 15:08:24 2013 +0100
199.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassesMarker.java Sun Feb 17 17:58:34 2013 +0100
199.3 @@ -27,4 +27,16 @@
199.4 @Retention(RetentionPolicy.RUNTIME)
199.5 public @interface ClassesMarker {
199.6 int number();
199.7 + String[] nicknames();
199.8 + E count() default E.ONE;
199.9 +
199.10 + enum E {
199.11 + ONE, TWO;
199.12 + }
199.13 +
199.14 + Anno[] subs() default {};
199.15 +
199.16 + public @interface Anno {
199.17 + int value();
199.18 + }
199.19 }
200.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ClassesNamer.java Fri Jan 25 15:08:24 2013 +0100
200.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassesNamer.java Sun Feb 17 17:58:34 2013 +0100
200.3 @@ -27,4 +27,5 @@
200.4 @Retention(RetentionPolicy.RUNTIME)
200.5 public @interface ClassesNamer {
200.6 String name();
200.7 + ClassesMarker.Anno anno();
200.8 }
201.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ExceptionsTest.java Fri Jan 25 15:08:24 2013 +0100
201.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ExceptionsTest.java Sun Feb 17 17:58:34 2013 +0100
201.3 @@ -17,7 +17,6 @@
201.4 */
201.5 package org.apidesign.vm4brwsr;
201.6
201.7 -import javax.script.Invocable;
201.8 import javax.script.ScriptException;
201.9 import static org.testng.Assert.*;
201.10 import org.testng.annotations.BeforeClass;
201.11 @@ -81,8 +80,7 @@
201.12 }
201.13
201.14 @Test public void testThreeCalls() throws Exception {
201.15 - Object vm = code.invokeFunction("bck2brwsr");
201.16 - Object clazz = code.invokeMethod(vm, "loadClass", Exceptions.class.getName());
201.17 + Object clazz = code.loadClass("loadClass", Exceptions.class.getName());
201.18
201.19 String method = "readCounter__ILjava_lang_String_2";
201.20
201.21 @@ -104,18 +102,13 @@
201.22 }
201.23 }
201.24
201.25 - private static CharSequence codeSeq;
201.26 - private static Invocable code;
201.27 + private static TestVM code;
201.28
201.29 @BeforeClass
201.30 public void compileTheCode() throws Exception {
201.31 - StringBuilder sb = new StringBuilder();
201.32 - code = StaticMethodTest.compileClass(sb,
201.33 - "org/apidesign/vm4brwsr/Exceptions"
201.34 - );
201.35 - codeSeq = sb;
201.36 + code = TestVM.compileClass("org/apidesign/vm4brwsr/Exceptions");
201.37 }
201.38 private static void assertExec(String msg, Class clazz, String method, Object expRes, Object... args) throws Exception {
201.39 - StaticMethodTest.assertExec(code, codeSeq, msg, clazz, method, expRes, args);
201.40 + code.assertExec(msg, clazz, method, expRes, args);
201.41 }
201.42 }
202.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/Instance.java Fri Jan 25 15:08:24 2013 +0100
202.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Instance.java Sun Feb 17 17:58:34 2013 +0100
202.3 @@ -68,12 +68,12 @@
202.4 GetByte i = new InstanceSub(7, 2.2d);
202.5 return i.getByte();
202.6 }
202.7 - public static boolean instanceOf(boolean sub) {
202.8 + public static boolean instanceOf(int sub) {
202.9 Instance i = createInstance(sub);
202.10 return isInstanceSubOf(i);
202.11 }
202.12 public static int castsWork(boolean interfc) {
202.13 - Instance i = createInstance(true);
202.14 + Instance i = createInstance(2);
202.15 if (interfc) {
202.16 GetByte b = (GetByte)i;
202.17 } else {
202.18 @@ -85,11 +85,16 @@
202.19 private static boolean isInstanceSubOf(Instance instance) {
202.20 return instance instanceof InstanceSub;
202.21 }
202.22 - private static Instance createInstance(boolean sub) {
202.23 - return sub ? new InstanceSub(3, 0) : new Instance();
202.24 + private static Instance createInstance(int type) {
202.25 + switch (type) {
202.26 + case 0: return null;
202.27 + case 1: return new Instance();
202.28 + case 2: return new InstanceSub(3, 0);
202.29 + }
202.30 + throw new IllegalArgumentException();
202.31 }
202.32 private static boolean isNull() {
202.33 - return createInstance(true) == null;
202.34 + return createInstance(2) == null;
202.35 }
202.36
202.37 @JavaScriptBody(args = "obj", body = "return obj.constructor;")
203.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/InstanceTest.java Fri Jan 25 15:08:24 2013 +0100
203.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/InstanceTest.java Sun Feb 17 17:58:34 2013 +0100
203.3 @@ -17,7 +17,6 @@
203.4 */
203.5 package org.apidesign.vm4brwsr;
203.6
203.7 -import javax.script.Invocable;
203.8 import org.testng.annotations.Test;
203.9 import org.testng.annotations.BeforeClass;
203.10
203.11 @@ -80,16 +79,23 @@
203.12 @Test public void isInstanceOf() throws Exception {
203.13 assertExec(
203.14 "Yes, we are instance",
203.15 - Instance.class, "instanceOf__ZZ",
203.16 - Double.valueOf(1.0), true
203.17 + Instance.class, "instanceOf__ZI",
203.18 + Double.valueOf(1.0), 2
203.19 );
203.20 }
203.21
203.22 @Test public void notInstanceOf() throws Exception {
203.23 assertExec(
203.24 "No, we are not an instance",
203.25 - Instance.class, "instanceOf__ZZ",
203.26 - Double.valueOf(0.0), false
203.27 + Instance.class, "instanceOf__ZI",
203.28 + Double.valueOf(0.0), 1
203.29 + );
203.30 + }
203.31 + @Test public void nullInstanceOf() throws Exception {
203.32 + assertExec(
203.33 + "No, null is not an instance",
203.34 + Instance.class, "instanceOf__ZI",
203.35 + Double.valueOf(0.0), 0
203.36 );
203.37 }
203.38
203.39 @@ -144,22 +150,17 @@
203.40 return "org/apidesign/vm4brwsr/Instance";
203.41 }
203.42
203.43 - private static CharSequence codeSeq;
203.44 - private static Invocable code;
203.45 + private static TestVM code;
203.46
203.47 @BeforeClass
203.48 public void compileTheCode() throws Exception {
203.49 - if (codeSeq == null) {
203.50 - StringBuilder sb = new StringBuilder();
203.51 - code = StaticMethodTest.compileClass(sb, startCompilationWith());
203.52 - codeSeq = sb;
203.53 - }
203.54 + code = TestVM.compileClass(startCompilationWith());
203.55 }
203.56
203.57 private void assertExec(
203.58 String msg, Class clazz, String method, Object expRes, Object... args
203.59 ) throws Exception {
203.60 - StaticMethodTest.assertExec(code, codeSeq, msg, clazz, method, expRes, args);
203.61 + code.assertExec(msg, clazz, method, expRes, args);
203.62 }
203.63
203.64 }
204.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java Fri Jan 25 15:08:24 2013 +0100
204.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java Sun Feb 17 17:58:34 2013 +0100
204.3 @@ -17,8 +17,6 @@
204.4 */
204.5 package org.apidesign.vm4brwsr;
204.6
204.7 -import javax.script.Invocable;
204.8 -import javax.script.ScriptException;
204.9 import static org.testng.Assert.*;
204.10 import org.testng.annotations.BeforeClass;
204.11 import org.testng.annotations.Test;
204.12 @@ -143,45 +141,29 @@
204.13 s
204.14 );
204.15 }
204.16 -
204.17 - private static CharSequence codeSeq;
204.18 - private static Invocable code;
204.19 +
204.20 + private static TestVM code;
204.21
204.22 @BeforeClass
204.23 public void compileTheCode() throws Exception {
204.24 - if (codeSeq == null) {
204.25 - StringBuilder sb = new StringBuilder();
204.26 - code = StaticMethodTest.compileClass(sb, "org/apidesign/vm4brwsr/Numbers");
204.27 - codeSeq = sb;
204.28 - }
204.29 + code = TestVM.compileClass("org/apidesign/vm4brwsr/Numbers");
204.30 }
204.31
204.32 private static void assertExec(
204.33 - String msg, Class<?> clazz, String method, Object expRes, Object... args) throws Exception {
204.34 -
204.35 - Object ret = null;
204.36 - try {
204.37 - ret = code.invokeFunction("bck2brwsr");
204.38 - ret = code.invokeMethod(ret, "loadClass", clazz.getName());
204.39 - ret = code.invokeMethod(ret, method, args);
204.40 - } catch (ScriptException ex) {
204.41 - fail("Execution failed in\n" + StaticMethodTest.dumpJS(codeSeq), ex);
204.42 - } catch (NoSuchMethodException ex) {
204.43 - fail("Cannot find method in\n" + StaticMethodTest.dumpJS(codeSeq), ex);
204.44 - }
204.45 - if (ret == null && expRes == null) {
204.46 - return;
204.47 - }
204.48 - if (expRes.equals(ret)) {
204.49 + String msg, Class<?> clazz, String method, Object expRes, Object... args) throws Exception
204.50 + {
204.51 + Object ret = code.execCode(msg, clazz, method, expRes, args);
204.52 + if (ret == null) {
204.53 return;
204.54 }
204.55 if (expRes instanceof Double && ret instanceof Double) {
204.56 double expD = ((Double)expRes).doubleValue();
204.57 double retD = ((Double)ret).doubleValue();
204.58 - assertEquals(retD, expD, 0.000004, msg + " was " + ret + "\n" + StaticMethodTest.dumpJS(codeSeq));
204.59 + assertEquals(retD, expD, 0.000004, msg + " "
204.60 + + code.toString());
204.61 return;
204.62 }
204.63 - assertEquals(ret, expRes, msg + "was: " + ret + "\n" + StaticMethodTest.dumpJS(codeSeq));
204.64 + assertEquals(ret, expRes, msg + " " + code.toString());
204.65 }
204.66
204.67 }
205.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethodTest.java Fri Jan 25 15:08:24 2013 +0100
205.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethodTest.java Sun Feb 17 17:58:34 2013 +0100
205.3 @@ -17,16 +17,6 @@
205.4 */
205.5 package org.apidesign.vm4brwsr;
205.6
205.7 -import java.io.File;
205.8 -import java.io.FileWriter;
205.9 -import java.io.IOException;
205.10 -import java.io.InputStream;
205.11 -import java.net.URL;
205.12 -import java.util.Enumeration;
205.13 -import javax.script.Invocable;
205.14 -import javax.script.ScriptEngine;
205.15 -import javax.script.ScriptEngineManager;
205.16 -import javax.script.ScriptException;
205.17 import static org.testng.Assert.*;
205.18 import org.testng.annotations.BeforeClass;
205.19 import org.testng.annotations.Test;
205.20 @@ -78,6 +68,89 @@
205.21 3.0d, 1l
205.22 );
205.23 }
205.24 +
205.25 + @Test public void rintNegativeUp() throws Exception {
205.26 + final double cnts = -453904.634;
205.27 + assertExec(
205.28 + "Should round up to end with 5",
205.29 + Math.class, "rint__DD",
205.30 + -453905.0, cnts
205.31 + );
205.32 + }
205.33 +
205.34 + @Test public void rintNegativeDown() throws Exception {
205.35 + final double cnts = -453904.434;
205.36 + assertExec(
205.37 + "Should round up to end with 4",
205.38 + Math.class, "rint__DD",
205.39 + -453904.0, cnts
205.40 + );
205.41 + }
205.42 +
205.43 + @Test public void rintPositiveUp() throws Exception {
205.44 + final double cnts = 453904.634;
205.45 + assertExec(
205.46 + "Should round up to end with 5",
205.47 + Math.class, "rint__DD",
205.48 + 453905.0, cnts
205.49 + );
205.50 + }
205.51 + @Test public void rintPositiveDown() throws Exception {
205.52 + final double cnts = 453904.434;
205.53 + assertExec(
205.54 + "Should round up to end with 4",
205.55 + Math.class, "rint__DD",
205.56 + 453904.0, cnts
205.57 + );
205.58 + }
205.59 + @Test public void rintOneHalf() throws Exception {
205.60 + final double cnts = 1.5;
205.61 + assertExec(
205.62 + "Should round up to end with 2",
205.63 + Math.class, "rint__DD",
205.64 + 2.0, cnts
205.65 + );
205.66 + }
205.67 + @Test public void rintNegativeOneHalf() throws Exception {
205.68 + final double cnts = -1.5;
205.69 + assertExec(
205.70 + "Should round up to end with 2",
205.71 + Math.class, "rint__DD",
205.72 + -2.0, cnts
205.73 + );
205.74 + }
205.75 + @Test public void rintTwoAndHalf() throws Exception {
205.76 + final double cnts = 2.5;
205.77 + assertExec(
205.78 + "Should round up to end with 2",
205.79 + Math.class, "rint__DD",
205.80 + 2.0, cnts
205.81 + );
205.82 + }
205.83 + @Test public void rintNegativeTwoOneHalf() throws Exception {
205.84 + final double cnts = -2.5;
205.85 + assertExec(
205.86 + "Should round up to end with 2",
205.87 + Math.class, "rint__DD",
205.88 + -2.0, cnts
205.89 + );
205.90 + }
205.91 +
205.92 + @Test public void ieeeReminder1() throws Exception {
205.93 + assertExec(
205.94 + "Same result 1",
205.95 + Math.class, "IEEEremainder__DDD",
205.96 + Math.IEEEremainder(10.0, 4.5), 10.0, 4.5
205.97 + );
205.98 + }
205.99 +
205.100 + @Test public void ieeeReminder2() throws Exception {
205.101 + assertExec(
205.102 + "Same result 1",
205.103 + Math.class, "IEEEremainder__DDD",
205.104 + Math.IEEEremainder(Integer.MAX_VALUE, -4.5), Integer.MAX_VALUE, -4.5
205.105 + );
205.106 + }
205.107
205.108 @Test public void divAndRound() throws Exception {
205.109 assertExec(
205.110 @@ -248,97 +321,18 @@
205.111 );
205.112 }
205.113
205.114 - private static CharSequence codeSeq;
205.115 - private static Invocable code;
205.116 + private static TestVM code;
205.117
205.118 @BeforeClass
205.119 public void compileTheCode() throws Exception {
205.120 StringBuilder sb = new StringBuilder();
205.121 - code = compileClass(sb, "org/apidesign/vm4brwsr/StaticMethod");
205.122 - codeSeq = sb;
205.123 - }
205.124 -
205.125 -
205.126 - private static void assertExec(
205.127 - String msg, Class clazz, String method,
205.128 - Object expRes, Object... args
205.129 - ) throws Exception {
205.130 - assertExec(code, codeSeq, msg, clazz, method, expRes, args);
205.131 - }
205.132 - static void assertExec(
205.133 - Invocable toRun, CharSequence theCode,
205.134 - String msg, Class clazz, String method,
205.135 - Object expRes, Object... args
205.136 - ) throws Exception {
205.137 - Object ret = null;
205.138 - try {
205.139 - ret = toRun.invokeFunction("bck2brwsr");
205.140 - ret = toRun.invokeMethod(ret, "loadClass", clazz.getName());
205.141 - ret = toRun.invokeMethod(ret, method, args);
205.142 - } catch (ScriptException ex) {
205.143 - fail("Execution failed in\n" + dumpJS(theCode), ex);
205.144 - } catch (NoSuchMethodException ex) {
205.145 - fail("Cannot find method in\n" + dumpJS(theCode), ex);
205.146 - }
205.147 - if (ret == null && expRes == null) {
205.148 - return;
205.149 - }
205.150 - if (expRes != null && expRes.equals(ret)) {
205.151 - return;
205.152 - }
205.153 - assertEquals(ret, expRes, msg + "was: " + ret + "\n" + dumpJS(theCode));
205.154 -
205.155 + code = TestVM.compileClass(sb, "org/apidesign/vm4brwsr/StaticMethod");
205.156 }
205.157
205.158 - static Invocable compileClass(StringBuilder sb, String... names) throws ScriptException, IOException {
205.159 - return compileClass(sb, null, names);
205.160 - }
205.161 - static Invocable compileClass(
205.162 - StringBuilder sb, ScriptEngine[] eng, String... names
205.163 - ) throws ScriptException, IOException {
205.164 - if (sb == null) {
205.165 - sb = new StringBuilder();
205.166 - }
205.167 - Bck2Brwsr.generate(sb, new EmulationResources(), names);
205.168 - ScriptEngineManager sem = new ScriptEngineManager();
205.169 - ScriptEngine js = sem.getEngineByExtension("js");
205.170 - if (eng != null) {
205.171 - eng[0] = js;
205.172 - }
205.173 - try {
205.174 - Object res = js.eval(sb.toString());
205.175 - assertTrue(js instanceof Invocable, "It is invocable object: " + res);
205.176 - return (Invocable)js;
205.177 - } catch (Exception ex) {
205.178 - if (sb.length() > 2000) {
205.179 - sb = dumpJS(sb);
205.180 - }
205.181 - fail("Could not evaluate:\n" + sb, ex);
205.182 - return null;
205.183 - }
205.184 - }
205.185 - static StringBuilder dumpJS(CharSequence sb) throws IOException {
205.186 - File f = File.createTempFile("execution", ".js");
205.187 - FileWriter w = new FileWriter(f);
205.188 - w.append(sb);
205.189 - w.close();
205.190 - return new StringBuilder(f.getPath());
205.191 - }
205.192 - private static class EmulationResources implements Bck2Brwsr.Resources {
205.193 - @Override
205.194 - public InputStream get(String name) throws IOException {
205.195 - Enumeration<URL> en = StaticMethodTest.class.getClassLoader().getResources(name);
205.196 - URL u = null;
205.197 - while (en.hasMoreElements()) {
205.198 - u = en.nextElement();
205.199 - }
205.200 - if (u == null) {
205.201 - throw new IOException("Can't find " + name);
205.202 - }
205.203 - if (u.toExternalForm().contains("rt.jar!")) {
205.204 - throw new IOException("No emulation for " + u);
205.205 - }
205.206 - return u.openStream();
205.207 - }
205.208 + private void assertExec(
205.209 + String msg, Class<?> clazz, String method,
205.210 + Object ret, Object... args
205.211 + ) throws Exception {
205.212 + code.assertExec(msg, clazz, method, ret, args);
205.213 }
205.214 }
206.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/StringSample.java Fri Jan 25 15:08:24 2013 +0100
206.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StringSample.java Sun Feb 17 17:58:34 2013 +0100
206.3 @@ -17,6 +17,8 @@
206.4 */
206.5 package org.apidesign.vm4brwsr;
206.6
206.7 +import java.io.UnsupportedEncodingException;
206.8 +
206.9 /**
206.10 *
206.11 * @author Jaroslav Tulach <jtulach@netbeans.org>
206.12 @@ -68,6 +70,15 @@
206.13 return chars('a', (char)30, 'b') instanceof String;
206.14 }
206.15
206.16 + public static String getBytes(String s) throws UnsupportedEncodingException {
206.17 + byte[] arr = s.getBytes("UTF-8");
206.18 + StringBuilder sb = new StringBuilder();
206.19 + for (int i = 0; i < arr.length; i++) {
206.20 + sb.append(arr[i]).append(" ");
206.21 + }
206.22 + return sb.toString().toString();
206.23 + }
206.24 +
206.25 public static String insertBuffer() {
206.26 StringBuilder sb = new StringBuilder();
206.27 sb.append("Jardo!");
207.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/StringTest.java Fri Jan 25 15:08:24 2013 +0100
207.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StringTest.java Sun Feb 17 17:58:34 2013 +0100
207.3 @@ -17,7 +17,6 @@
207.4 */
207.5 package org.apidesign.vm4brwsr;
207.6
207.7 -import javax.script.Invocable;
207.8 import org.testng.annotations.Test;
207.9 import static org.testng.Assert.*;
207.10 import org.testng.annotations.BeforeClass;
207.11 @@ -75,6 +74,16 @@
207.12 );
207.13 }
207.14
207.15 + @Test public void getBytes() throws Exception {
207.16 + final String horse = "\u017dlu\u0165ou\u010dk\u00fd k\u016f\u0148";
207.17 + final String expected = StringSample.getBytes(horse);
207.18 + assertExec(
207.19 + "Bytes look simplar",
207.20 + StringSample.class, "getBytes__Ljava_lang_String_2Ljava_lang_String_2",
207.21 + expected, horse
207.22 + );
207.23 + }
207.24 +
207.25 @Test(timeOut=10000) public void toStringConcatenation() throws Exception {
207.26 assertExec(
207.27 "Five executions should generate 5Hello World!",
207.28 @@ -184,23 +193,20 @@
207.29
207.30 }
207.31
207.32 - private static CharSequence codeSeq;
207.33 - private static Invocable code;
207.34 + private static TestVM code;
207.35
207.36 @BeforeClass
207.37 public void compileTheCode() throws Exception {
207.38 - StringBuilder sb = new StringBuilder();
207.39 - code = StaticMethodTest.compileClass(sb,
207.40 + code = TestVM.compileClass(
207.41 "org/apidesign/vm4brwsr/StringSample",
207.42 "java/lang/String"
207.43 );
207.44 - codeSeq = sb;
207.45 }
207.46
207.47 private static void assertExec(String msg,
207.48 Class<?> clazz, String method, Object expRes, Object... args
207.49 ) throws Exception {
207.50 - StaticMethodTest.assertExec(code, codeSeq, msg, clazz, method, expRes, args);
207.51 + code.assertExec(msg, clazz, method, expRes, args);
207.52 }
207.53
207.54 }
208.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
208.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/SystemTest.java Sun Feb 17 17:58:34 2013 +0100
208.3 @@ -0,0 +1,56 @@
208.4 +/**
208.5 + * Back 2 Browser Bytecode Translator
208.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
208.7 + *
208.8 + * This program is free software: you can redistribute it and/or modify
208.9 + * it under the terms of the GNU General Public License as published by
208.10 + * the Free Software Foundation, version 2 of the License.
208.11 + *
208.12 + * This program is distributed in the hope that it will be useful,
208.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
208.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
208.15 + * GNU General Public License for more details.
208.16 + *
208.17 + * You should have received a copy of the GNU General Public License
208.18 + * along with this program. Look for COPYING file in the top folder.
208.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
208.20 + */
208.21 +package org.apidesign.vm4brwsr;
208.22 +
208.23 +import org.testng.annotations.BeforeClass;
208.24 +import static org.testng.Assert.*;
208.25 +import org.testng.annotations.Test;
208.26 +
208.27 +/**
208.28 + *
208.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
208.30 + */
208.31 +public class SystemTest {
208.32 + private static TestVM code;
208.33 +
208.34 + @Test public void verifyJSTime() throws Exception {
208.35 + long now = System.currentTimeMillis();
208.36 +
208.37 + Object js = code.execCode("Get js time",
208.38 + org.apidesign.bck2brwsr.emul.lang.System.class, "currentTimeMillis__J",
208.39 + null
208.40 + );
208.41 +
208.42 + assertTrue(js instanceof Double, "Double " + js);
208.43 + long time = ((Double)js).longValue();
208.44 +
208.45 + long later = System.currentTimeMillis();
208.46 +
208.47 + assertTrue(now <= time, "Lower bound is OK: " + now + " <= " + time);
208.48 + assertTrue(time <= later, "Upper bound is OK: " + time + " <= " + later);
208.49 + }
208.50 +
208.51 +
208.52 + @BeforeClass
208.53 + public static void compileTheCode() throws Exception {
208.54 + code = TestVM.compileClass(
208.55 + "org/apidesign/bck2brwsr/emul/lang/System");
208.56 + }
208.57 +
208.58 +}
208.59 +
209.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
209.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/TestVM.java Sun Feb 17 17:58:34 2013 +0100
209.3 @@ -0,0 +1,170 @@
209.4 +/**
209.5 + * Back 2 Browser Bytecode Translator
209.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
209.7 + *
209.8 + * This program is free software: you can redistribute it and/or modify
209.9 + * it under the terms of the GNU General Public License as published by
209.10 + * the Free Software Foundation, version 2 of the License.
209.11 + *
209.12 + * This program is distributed in the hope that it will be useful,
209.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
209.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
209.15 + * GNU General Public License for more details.
209.16 + *
209.17 + * You should have received a copy of the GNU General Public License
209.18 + * along with this program. Look for COPYING file in the top folder.
209.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
209.20 + */
209.21 +package org.apidesign.vm4brwsr;
209.22 +
209.23 +import java.io.File;
209.24 +import java.io.FileWriter;
209.25 +import java.io.IOException;
209.26 +import java.io.InputStream;
209.27 +import java.net.URL;
209.28 +import java.util.Enumeration;
209.29 +import javax.script.Invocable;
209.30 +import javax.script.ScriptEngine;
209.31 +import javax.script.ScriptEngineManager;
209.32 +import javax.script.ScriptException;
209.33 +import static org.testng.Assert.*;
209.34 +
209.35 +final class TestVM {
209.36 + private final Invocable code;
209.37 + private final CharSequence codeSeq;
209.38 + private final Object bck2brwsr;
209.39 +
209.40 +
209.41 + private TestVM(Invocable code, CharSequence codeSeq) throws ScriptException, NoSuchMethodException {
209.42 + this.code = code;
209.43 + this.codeSeq = codeSeq;
209.44 + this.bck2brwsr = code.invokeFunction("bck2brwsr");
209.45 + }
209.46 +
209.47 +
209.48 + public Object execCode(
209.49 + String msg, Class<?> clazz, String method,
209.50 + Object expRes, Object... args
209.51 + ) throws Exception {
209.52 + Object ret = null;
209.53 + try {
209.54 + ret = code.invokeMethod(bck2brwsr, "loadClass", clazz.getName());
209.55 + ret = code.invokeMethod(ret, method, args);
209.56 + } catch (ScriptException ex) {
209.57 + fail("Execution failed in " + dumpJS(codeSeq), ex);
209.58 + } catch (NoSuchMethodException ex) {
209.59 + fail("Cannot find method in " + dumpJS(codeSeq), ex);
209.60 + }
209.61 + if (ret == null && expRes == null) {
209.62 + return null;
209.63 + }
209.64 + if (expRes != null && expRes.equals(ret)) {
209.65 + return null;
209.66 + }
209.67 + if (expRes instanceof Number) {
209.68 + // in case of Long it is necessary convert it to number
209.69 + // since the Long is represented by two numbers in JavaScript
209.70 + try {
209.71 + ret = code.invokeMethod(ret, "toFP");
209.72 + ret = code.invokeFunction("Number", ret);
209.73 + } catch (ScriptException ex) {
209.74 + fail("Conversion to number failed in " + dumpJS(codeSeq), ex);
209.75 + } catch (NoSuchMethodException ex) {
209.76 + fail("Cannot find global Number(x) function in " + dumpJS(codeSeq), ex);
209.77 + }
209.78 + }
209.79 + return ret;
209.80 + }
209.81 +
209.82 + void assertExec(
209.83 + String msg, Class clazz, String method, Object expRes, Object... args
209.84 + ) throws Exception {
209.85 + Object ret = execCode(msg, clazz, method, expRes, args);
209.86 + if (ret == null) {
209.87 + return;
209.88 + }
209.89 + if (expRes != null && expRes.equals(ret)) {
209.90 + return;
209.91 + }
209.92 + assertEquals(ret, expRes, msg + "was: " + ret + "\n" + dumpJS(codeSeq));
209.93 + }
209.94 +
209.95 + static TestVM compileClass(String... names) throws ScriptException, IOException {
209.96 + return compileClass(null, names);
209.97 + }
209.98 +
209.99 + static TestVM compileClass(StringBuilder sb, String... names) throws ScriptException, IOException {
209.100 + return compileClass(sb, null, names);
209.101 + }
209.102 +
209.103 + static TestVM compileClass(StringBuilder sb, ScriptEngine[] eng, String... names) throws ScriptException, IOException {
209.104 + if (sb == null) {
209.105 + sb = new StringBuilder();
209.106 + }
209.107 + Bck2Brwsr.generate(sb, new EmulationResources(), names);
209.108 + ScriptEngineManager sem = new ScriptEngineManager();
209.109 + ScriptEngine js = sem.getEngineByExtension("js");
209.110 + if (eng != null) {
209.111 + eng[0] = js;
209.112 + }
209.113 + try {
209.114 + Object res = js.eval(sb.toString());
209.115 + assertTrue(js instanceof Invocable, "It is invocable object: " + res);
209.116 + return new TestVM((Invocable) js, sb);
209.117 + } catch (Exception ex) {
209.118 + if (sb.length() > 2000) {
209.119 + sb = dumpJS(sb);
209.120 + }
209.121 + fail("Could not evaluate:\n" + sb, ex);
209.122 + return null;
209.123 + }
209.124 + }
209.125 +
209.126 + Object loadClass(String loadClass, String name) throws ScriptException, NoSuchMethodException {
209.127 + return code.invokeMethod(bck2brwsr, "loadClass", Exceptions.class.getName());
209.128 + }
209.129 +
209.130 + Object invokeMethod(Object obj, String method, Object... params) throws ScriptException, NoSuchMethodException {
209.131 + return code.invokeMethod(obj, method, params);
209.132 + }
209.133 +
209.134 + Object invokeFunction(String methodName, Object... args) throws ScriptException, NoSuchMethodException {
209.135 + return code.invokeFunction(methodName, args);
209.136 + }
209.137 +
209.138 + static StringBuilder dumpJS(CharSequence sb) throws IOException {
209.139 + File f = File.createTempFile("execution", ".js");
209.140 + FileWriter w = new FileWriter(f);
209.141 + w.append(sb);
209.142 + w.close();
209.143 + return new StringBuilder(f.getPath());
209.144 + }
209.145 +
209.146 + @Override
209.147 + public String toString() {
209.148 + try {
209.149 + return dumpJS(codeSeq).toString();
209.150 + } catch (IOException ex) {
209.151 + return ex.toString();
209.152 + }
209.153 + }
209.154 +
209.155 +
209.156 + private static class EmulationResources implements Bck2Brwsr.Resources {
209.157 + @Override
209.158 + public InputStream get(String name) throws IOException {
209.159 + Enumeration<URL> en = StaticMethodTest.class.getClassLoader().getResources(name);
209.160 + URL u = null;
209.161 + while (en.hasMoreElements()) {
209.162 + u = en.nextElement();
209.163 + }
209.164 + if (u == null) {
209.165 + throw new IOException("Can't find " + name);
209.166 + }
209.167 + if (u.toExternalForm().contains("rt.jar!")) {
209.168 + throw new IOException("No emulation for " + u);
209.169 + }
209.170 + return u.openStream();
209.171 + }
209.172 + }
209.173 +}
210.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/VMLazyTest.java Fri Jan 25 15:08:24 2013 +0100
210.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/VMLazyTest.java Sun Feb 17 17:58:34 2013 +0100
210.3 @@ -17,7 +17,6 @@
210.4 */
210.5 package org.apidesign.vm4brwsr;
210.6
210.7 -import javax.script.Invocable;
210.8 import javax.script.ScriptContext;
210.9 import javax.script.ScriptEngine;
210.10 import javax.script.ScriptException;
210.11 @@ -30,10 +29,7 @@
210.12 * @author Jaroslav Tulach <jtulach@netbeans.org>
210.13 */
210.14 public class VMLazyTest {
210.15 -
210.16 -
210.17 - private static CharSequence codeSeq;
210.18 - private static Invocable code;
210.19 + private static TestVM code;
210.20
210.21 @BeforeClass
210.22 public void compileTheCode() throws Exception {
210.23 @@ -50,11 +46,10 @@
210.24 sb.append("\n}");
210.25
210.26 ScriptEngine[] arr = { null };
210.27 - code = StaticMethodTest.compileClass(sb, arr,
210.28 - "org/apidesign/vm4brwsr/VM"
210.29 + code = TestVM.compileClass(sb, arr,
210.30 + new String[]{"org/apidesign/vm4brwsr/VM", "org/apidesign/vm4brwsr/StaticMethod"}
210.31 );
210.32 arr[0].getContext().setAttribute("loader", new BytesLoader(), ScriptContext.ENGINE_SCOPE);
210.33 - codeSeq = sb;
210.34 }
210.35
210.36 @Test public void invokeStaticMethod() throws Exception {
210.37 @@ -83,9 +78,9 @@
210.38 try {
210.39 ret = code.invokeFunction(methodName, args);
210.40 } catch (ScriptException ex) {
210.41 - fail("Execution failed in\n" + StaticMethodTest.dumpJS(codeSeq), ex);
210.42 + fail("Execution failed in\n" + code.toString(), ex);
210.43 } catch (NoSuchMethodException ex) {
210.44 - fail("Cannot find method in\n" + StaticMethodTest.dumpJS(codeSeq), ex);
210.45 + fail("Cannot find method in\n" + code.toString(), ex);
210.46 }
210.47 if (ret == null && expRes == null) {
210.48 return;
210.49 @@ -93,6 +88,6 @@
210.50 if (expRes.equals(ret)) {
210.51 return;
210.52 }
210.53 - assertEquals(ret, expRes, msg + "was: " + ret + "\n" + StaticMethodTest.dumpJS(codeSeq));
210.54 + assertEquals(ret, expRes, msg + "was: " + ret + "\n" + code.toString());
210.55 }
210.56 }
211.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/VMinVMTest.java Fri Jan 25 15:08:24 2013 +0100
211.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/VMinVMTest.java Sun Feb 17 17:58:34 2013 +0100
211.3 @@ -21,7 +21,6 @@
211.4 import java.io.FileWriter;
211.5 import java.io.IOException;
211.6 import static org.testng.Assert.*;
211.7 -import javax.script.Invocable;
211.8 import org.testng.annotations.BeforeClass;
211.9 import org.testng.annotations.Test;
211.10
211.11 @@ -30,9 +29,7 @@
211.12 * @author Jaroslav Tulach <jtulach@netbeans.org>
211.13 */
211.14 public class VMinVMTest {
211.15 -
211.16 - private static CharSequence codeSeq;
211.17 - private static Invocable code;
211.18 + private static TestVM code;
211.19
211.20 @Test public void compareGeneratedCodeForArrayClass() throws Exception {
211.21 compareCode("org/apidesign/vm4brwsr/Array.class");
211.22 @@ -44,11 +41,7 @@
211.23
211.24 @BeforeClass
211.25 public void compileTheCode() throws Exception {
211.26 - StringBuilder sb = new StringBuilder();
211.27 - code = StaticMethodTest.compileClass(sb,
211.28 - "org/apidesign/vm4brwsr/VMinVM"
211.29 - );
211.30 - codeSeq = sb;
211.31 + code = TestVM.compileClass("org/apidesign/vm4brwsr/VMinVM");
211.32 }
211.33
211.34 private void compareCode(final String nm) throws Exception, IOException {
211.35 @@ -73,7 +66,7 @@
211.36 }
211.37 }
211.38 w.append("\n];\n");
211.39 - w.append(codeSeq);
211.40 + w.append(code.toString());
211.41 w.close();
211.42 throw new Exception(ex.getMessage() + " file: " + f, ex);
211.43 }
211.44 @@ -83,11 +76,11 @@
211.45
211.46 if (!ret1.toString().equals(ret)) {
211.47 StringBuilder msg = new StringBuilder("Difference found between ");
211.48 - msg.append(StaticMethodTest.dumpJS(ret1));
211.49 + msg.append(TestVM.dumpJS(ret1));
211.50 msg.append(" ");
211.51 - msg.append(StaticMethodTest.dumpJS((CharSequence) ret));
211.52 + msg.append(TestVM.dumpJS((CharSequence) ret));
211.53 msg.append(" compiled by ");
211.54 - msg.append(StaticMethodTest.dumpJS(codeSeq));
211.55 + msg.append(code.toString());
211.56 fail(msg.toString());
211.57 }
211.58 }
212.1 --- a/vmtest/pom.xml Fri Jan 25 15:08:24 2013 +0100
212.2 +++ b/vmtest/pom.xml Sun Feb 17 17:58:34 2013 +0100
212.3 @@ -58,5 +58,10 @@
212.4 <artifactId>launcher</artifactId>
212.5 <version>${project.version}</version>
212.6 </dependency>
212.7 + <dependency>
212.8 + <groupId>org.netbeans.api</groupId>
212.9 + <artifactId>org-openide-util-lookup</artifactId>
212.10 + <scope>provided</scope>
212.11 + </dependency>
212.12 </dependencies>
212.13 </project>
213.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
213.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/Http.java Sun Feb 17 17:58:34 2013 +0100
213.3 @@ -0,0 +1,56 @@
213.4 +/**
213.5 + * Back 2 Browser Bytecode Translator
213.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
213.7 + *
213.8 + * This program is free software: you can redistribute it and/or modify
213.9 + * it under the terms of the GNU General Public License as published by
213.10 + * the Free Software Foundation, version 2 of the License.
213.11 + *
213.12 + * This program is distributed in the hope that it will be useful,
213.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
213.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
213.15 + * GNU General Public License for more details.
213.16 + *
213.17 + * You should have received a copy of the GNU General Public License
213.18 + * along with this program. Look for COPYING file in the top folder.
213.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
213.20 + */
213.21 +package org.apidesign.bck2brwsr.vmtest;
213.22 +
213.23 +import java.lang.annotation.ElementType;
213.24 +import java.lang.annotation.Retention;
213.25 +import java.lang.annotation.RetentionPolicy;
213.26 +import java.lang.annotation.Target;
213.27 +
213.28 +/**
213.29 + * Exposes HTTP page or pages to the running {@link BrwsrTest}, so it can access under
213.30 + * the relative path.
213.31 + *
213.32 + * @author Jaroslav Tulach <jtulach@netbeans.org>
213.33 + */
213.34 +@Retention(RetentionPolicy.RUNTIME)
213.35 +@Target({ElementType.METHOD, ElementType.TYPE})
213.36 +public @interface Http {
213.37 + /** Set of pages to make available */
213.38 + public Resource[] value();
213.39 +
213.40 + /** Exposes an HTTP page to the running {@link BrwsrTest}, so it can access
213.41 + * under the relative path.
213.42 + *
213.43 + * @author Jaroslav Tulach <jtulach@netbeans.org>
213.44 + */
213.45 + @Retention(RetentionPolicy.RUNTIME)
213.46 + @Target({})
213.47 + public @interface Resource {
213.48 + /** path on the server that the test can use to access the exposed resource */
213.49 + String path();
213.50 + /** the content of the HttpResource */
213.51 + String content();
213.52 + /** resource relative to the class that should be used instead of <code>content</code>.
213.53 + * Leave content equal to empty string.
213.54 + */
213.55 + String resource() default "";
213.56 + /** mime type of the resource */
213.57 + String mimeType();
213.58 + }
213.59 +}
214.1 --- a/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java Fri Jan 25 15:08:24 2013 +0100
214.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java Sun Feb 17 17:58:34 2013 +0100
214.3 @@ -17,16 +17,18 @@
214.4 */
214.5 package org.apidesign.bck2brwsr.vmtest.impl;
214.6
214.7 +import java.io.ByteArrayInputStream;
214.8 import java.io.File;
214.9 import java.io.FileWriter;
214.10 import java.io.IOException;
214.11 +import java.io.InputStream;
214.12 import java.lang.reflect.Constructor;
214.13 import java.lang.reflect.InvocationTargetException;
214.14 import java.lang.reflect.Method;
214.15 -import java.util.Map;
214.16 -import java.util.WeakHashMap;
214.17 import org.apidesign.bck2brwsr.launcher.Launcher;
214.18 -import org.apidesign.bck2brwsr.launcher.MethodInvocation;
214.19 +import org.apidesign.bck2brwsr.launcher.InvocationContext;
214.20 +import org.apidesign.bck2brwsr.vmtest.HtmlFragment;
214.21 +import org.apidesign.bck2brwsr.vmtest.Http;
214.22 import org.testng.ITest;
214.23 import org.testng.annotations.Test;
214.24
214.25 @@ -39,22 +41,38 @@
214.26 private final Launcher l;
214.27 private final String type;
214.28 private final boolean fail;
214.29 + private final HtmlFragment html;
214.30 + private final Http.Resource[] http;
214.31 Object value;
214.32 - private final String html;
214.33
214.34 - Bck2BrwsrCase(Method m, String type, Launcher l, boolean fail, String html) {
214.35 + Bck2BrwsrCase(Method m, String type, Launcher l, boolean fail, HtmlFragment html, Http.Resource[] http) {
214.36 this.l = l;
214.37 this.m = m;
214.38 this.type = type;
214.39 this.fail = fail;
214.40 this.html = html;
214.41 + this.http = http;
214.42 }
214.43
214.44 @Test(groups = "run")
214.45 public void executeCode() throws Throwable {
214.46 if (l != null) {
214.47 - MethodInvocation c = l.invokeMethod(m.getDeclaringClass(), m.getName(), html);
214.48 - String res = c.toString();
214.49 + InvocationContext c = l.createInvocation(m.getDeclaringClass(), m.getName());
214.50 + if (html != null) {
214.51 + c.setHtmlFragment(html.value());
214.52 + }
214.53 + if (http != null) {
214.54 + for (Http.Resource r : http) {
214.55 + if (!r.content().isEmpty()) {
214.56 + InputStream is = new ByteArrayInputStream(r.content().getBytes("UTF-8"));
214.57 + c.addHttpResource(r.path(), r.mimeType(), is);
214.58 + } else {
214.59 + InputStream is = m.getDeclaringClass().getResourceAsStream(r.resource());
214.60 + c.addHttpResource(r.path(), r.mimeType(), is);
214.61 + }
214.62 + }
214.63 + }
214.64 + String res = c.invoke();
214.65 value = res;
214.66 if (fail) {
214.67 int idx = res.indexOf(':');
214.68 @@ -94,6 +112,9 @@
214.69 } catch (InvocationTargetException ex) {
214.70 Throwable t = ex.getTargetException();
214.71 value = t.getClass().getName() + ":" + t.getMessage();
214.72 + if (t instanceof AssertionError) {
214.73 + throw t;
214.74 + }
214.75 }
214.76 }
214.77 }
215.1 --- a/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java Fri Jan 25 15:08:24 2013 +0100
215.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java Sun Feb 17 17:58:34 2013 +0100
215.3 @@ -111,17 +111,17 @@
215.4 if (c == null) {
215.5 return;
215.6 }
215.7 - final Bck2BrwsrCase real = new Bck2BrwsrCase(m, "Java", null, false, null);
215.8 + final Bck2BrwsrCase real = new Bck2BrwsrCase(m, "Java", null, false, null, null);
215.9 ret.add(real);
215.10 if (c.scripting()) {
215.11 - final Bck2BrwsrCase js = new Bck2BrwsrCase(m, "JavaScript", l.javaScript(), false, null);
215.12 + final Bck2BrwsrCase js = new Bck2BrwsrCase(m, "JavaScript", l.javaScript(), false, null, null);
215.13 ret.add(js);
215.14 ret.add(new CompareCase(m, real, js));
215.15 }
215.16 for (String b : brwsr) {
215.17 final Launcher s = l.brwsr(b);
215.18 ret.add(s);
215.19 - final Bck2BrwsrCase cse = new Bck2BrwsrCase(m, b, s, false, null);
215.20 + final Bck2BrwsrCase cse = new Bck2BrwsrCase(m, b, s, false, null, null);
215.21 ret.add(cse);
215.22 ret.add(new CompareCase(m, real, cse));
215.23 }
215.24 @@ -135,16 +135,25 @@
215.25 if (f == null) {
215.26 f = m.getDeclaringClass().getAnnotation(HtmlFragment.class);
215.27 }
215.28 - String html = f == null ? null : f.value();
215.29 + Http.Resource[] r = {};
215.30 + Http h = m.getAnnotation(Http.class);
215.31 + if (h == null) {
215.32 + h = m.getDeclaringClass().getAnnotation(Http.class);
215.33 + if (h != null) {
215.34 + r = h.value();
215.35 + }
215.36 + } else {
215.37 + r = h.value();
215.38 + }
215.39 if (brwsr.length == 0) {
215.40 final Launcher s = l.brwsr(null);
215.41 ret.add(s);
215.42 - ret.add(new Bck2BrwsrCase(m, "Brwsr", s, true, html));
215.43 + ret.add(new Bck2BrwsrCase(m, "Brwsr", s, true, f, r));
215.44 } else {
215.45 for (String b : brwsr) {
215.46 final Launcher s = l.brwsr(b);
215.47 ret.add(s);
215.48 - ret.add(new Bck2BrwsrCase(m, b, s, true, html));
215.49 + ret.add(new Bck2BrwsrCase(m, b, s, true, f, r));
215.50 }
215.51 }
215.52 }
216.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
216.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/GenerateZip.java Sun Feb 17 17:58:34 2013 +0100
216.3 @@ -0,0 +1,36 @@
216.4 +/**
216.5 + * Back 2 Browser Bytecode Translator
216.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
216.7 + *
216.8 + * This program is free software: you can redistribute it and/or modify
216.9 + * it under the terms of the GNU General Public License as published by
216.10 + * the Free Software Foundation, version 2 of the License.
216.11 + *
216.12 + * This program is distributed in the hope that it will be useful,
216.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
216.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
216.15 + * GNU General Public License for more details.
216.16 + *
216.17 + * You should have received a copy of the GNU General Public License
216.18 + * along with this program. Look for COPYING file in the top folder.
216.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
216.20 + */
216.21 +package org.apidesign.bck2brwsr.vmtest.impl;
216.22 +
216.23 +import java.lang.annotation.Retention;
216.24 +import java.lang.annotation.RetentionPolicy;
216.25 +
216.26 +/** Annotation to generate a ZIP or JAR file during build.
216.27 + *
216.28 + * @author Jaroslav Tulach <jtulach@netbeans.org>
216.29 + */
216.30 +@Retention(RetentionPolicy.SOURCE)
216.31 +@interface GenerateZip {
216.32 + String name();
216.33 +
216.34 + /** manifest for the file */
216.35 + String manifest() default "";
216.36 +
216.37 + /** Array of names (at odd positions) and their content (on even) */
216.38 + String[] contents();
216.39 +}
217.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
217.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/GenerateZipProcessor.java Sun Feb 17 17:58:34 2013 +0100
217.3 @@ -0,0 +1,101 @@
217.4 +/**
217.5 + * Back 2 Browser Bytecode Translator
217.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
217.7 + *
217.8 + * This program is free software: you can redistribute it and/or modify
217.9 + * it under the terms of the GNU General Public License as published by
217.10 + * the Free Software Foundation, version 2 of the License.
217.11 + *
217.12 + * This program is distributed in the hope that it will be useful,
217.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
217.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
217.15 + * GNU General Public License for more details.
217.16 + *
217.17 + * You should have received a copy of the GNU General Public License
217.18 + * along with this program. Look for COPYING file in the top folder.
217.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
217.20 + */
217.21 +package org.apidesign.bck2brwsr.vmtest.impl;
217.22 +
217.23 +import java.io.ByteArrayInputStream;
217.24 +import java.io.IOException;
217.25 +import java.io.OutputStream;
217.26 +import java.util.Set;
217.27 +import java.util.jar.JarEntry;
217.28 +import java.util.jar.JarOutputStream;
217.29 +import java.util.jar.Manifest;
217.30 +import javax.annotation.processing.AbstractProcessor;
217.31 +import javax.annotation.processing.Filer;
217.32 +import javax.annotation.processing.Processor;
217.33 +import javax.annotation.processing.RoundEnvironment;
217.34 +import javax.annotation.processing.SupportedAnnotationTypes;
217.35 +import javax.lang.model.element.Element;
217.36 +import javax.lang.model.element.ElementKind;
217.37 +import javax.lang.model.element.PackageElement;
217.38 +import javax.lang.model.element.TypeElement;
217.39 +import javax.tools.Diagnostic;
217.40 +import javax.tools.FileObject;
217.41 +import javax.tools.StandardLocation;
217.42 +import org.openide.util.lookup.ServiceProvider;
217.43 +
217.44 +/**
217.45 + *
217.46 + * @author Jaroslav Tulach <jtulach@netbeans.org>
217.47 + */
217.48 +@ServiceProvider(service = Processor.class)
217.49 +@SupportedAnnotationTypes("org.apidesign.bck2brwsr.vmtest.impl.GenerateZip")
217.50 +public class GenerateZipProcessor extends AbstractProcessor {
217.51 +
217.52 + @Override
217.53 + public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
217.54 + for (Element e : roundEnv.getElementsAnnotatedWith(GenerateZip.class)) {
217.55 + GenerateZip gz = e.getAnnotation(GenerateZip.class);
217.56 + if (gz == null) {
217.57 + continue;
217.58 + }
217.59 + PackageElement pe = findPackage(e);
217.60 + try {
217.61 + generateJar(pe, gz, e);
217.62 + } catch (IOException ex) {
217.63 + processingEnv.getMessager().printMessage(
217.64 + Diagnostic.Kind.ERROR,
217.65 + "Can't generate JAR " + gz.name() + ": " + ex.getMessage()
217.66 + );
217.67 + }
217.68 + }
217.69 + return true;
217.70 + }
217.71 +
217.72 + private static PackageElement findPackage(Element e) {
217.73 + while (e.getKind() != ElementKind.PACKAGE) {
217.74 + e = e.getEnclosingElement();
217.75 + }
217.76 + return (PackageElement)e;
217.77 + }
217.78 +
217.79 + private void generateJar(PackageElement pe, GenerateZip gz, Element e) throws IOException {
217.80 + final Filer filer = processingEnv.getFiler();
217.81 + FileObject res = filer.createResource(
217.82 + StandardLocation.CLASS_OUTPUT,
217.83 + pe.getQualifiedName().toString(),
217.84 + gz.name(), e
217.85 + );
217.86 + OutputStream os = res.openOutputStream();
217.87 + JarOutputStream jar;
217.88 + if (gz.manifest().isEmpty()) {
217.89 + jar = new JarOutputStream(os);
217.90 + } else {
217.91 + Manifest mf = new Manifest(new ByteArrayInputStream(gz.manifest().getBytes("UTF-8")));
217.92 + jar = new JarOutputStream(os, mf);
217.93 + }
217.94 + String[] arr = gz.contents();
217.95 + for (int i = 0; i < arr.length; i += 2) {
217.96 + JarEntry je = new JarEntry(arr[i]);
217.97 + jar.putNextEntry(je);
217.98 + jar.write(arr[i + 1].getBytes("UTF-8"));
217.99 + jar.closeEntry();
217.100 + }
217.101 + jar.close();
217.102 + }
217.103 +
217.104 +}
218.1 --- a/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/LaunchSetup.java Fri Jan 25 15:08:24 2013 +0100
218.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/LaunchSetup.java Sun Feb 17 17:58:34 2013 +0100
218.3 @@ -31,13 +31,19 @@
218.4 public final class LaunchSetup {
218.5 static LaunchSetup INSTANCE = new LaunchSetup();
218.6
218.7 - private final Launcher js = Launcher.createJavaScript();
218.8 + private Launcher js;
218.9 private final Map<String,Launcher> brwsrs = new LinkedHashMap<>();
218.10
218.11 private LaunchSetup() {
218.12 }
218.13
218.14 - public Launcher javaScript() {
218.15 + public Launcher javaScript() {
218.16 + return js(true);
218.17 + }
218.18 + private synchronized Launcher js(boolean create) {
218.19 + if (js == null && create) {
218.20 + js = Launcher.createJavaScript();
218.21 + }
218.22 return js;
218.23 }
218.24
218.25 @@ -52,7 +58,9 @@
218.26
218.27 @BeforeGroups("run")
218.28 public void initializeLauncher() throws IOException {
218.29 - js.initialize();
218.30 + if (js(false) != null) {
218.31 + js(true).initialize();
218.32 + }
218.33 for (Launcher launcher : brwsrs.values()) {
218.34 launcher.initialize();
218.35 }
218.36 @@ -60,7 +68,9 @@
218.37
218.38 @AfterGroups("run")
218.39 public void shutDownLauncher() throws IOException, InterruptedException {
218.40 - js.shutdown();
218.41 + if (js(false) != null) {
218.42 + js(true).shutdown();
218.43 + }
218.44 for (Launcher launcher : brwsrs.values()) {
218.45 launcher.shutdown();
218.46 }
219.1 --- a/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/AssertionTest.java Fri Jan 25 15:08:24 2013 +0100
219.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/AssertionTest.java Sun Feb 17 17:58:34 2013 +0100
219.3 @@ -28,8 +28,12 @@
219.4 public class AssertionTest {
219.5
219.6 @Compare public Object checkAssert() throws ClassNotFoundException {
219.7 - assert false : "Is assertion status on?";
219.8 - return null;
219.9 + try {
219.10 + assert false : "Is assertion status on?";
219.11 + return null;
219.12 + } catch (AssertionError ex) {
219.13 + return ex.getClass().getName();
219.14 + }
219.15 }
219.16
219.17 @Factory
220.1 --- a/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java Fri Jan 25 15:08:24 2013 +0100
220.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java Sun Feb 17 17:58:34 2013 +0100
220.3 @@ -17,6 +17,7 @@
220.4 */
220.5 package org.apidesign.bck2brwsr.tck;
220.6
220.7 +import java.io.UnsupportedEncodingException;
220.8 import java.net.MalformedURLException;
220.9 import java.net.URL;
220.10 import org.apidesign.bck2brwsr.vmtest.Compare;
220.11 @@ -46,6 +47,19 @@
220.12 return "Ahoj".equals(null);
220.13 }
220.14
220.15 + @Compare public int highByteLenght() {
220.16 + byte[] arr= { 77,97,110,105,102,101,115,116,45,86,101,114,115,105,111,110 };
220.17 + return new String(arr, 0).length();
220.18 + }
220.19 +
220.20 + @Compare public String highByte() {
220.21 + byte[] arr= { 77,97,110,105,102,101,115,116,45,86,101,114,115,105,111,110 };
220.22 + StringBuilder sb = new StringBuilder();
220.23 + sb.append("pref:");
220.24 + sb.append(new String(arr, 0));
220.25 + return sb.toString();
220.26 + }
220.27 +
220.28 @Compare public static Object compareURLs() throws MalformedURLException {
220.29 return new URL("http://apidesign.org:8080/wiki/").toExternalForm().toString();
220.30 }
220.31 @@ -120,6 +134,21 @@
220.32 NullField nf = new NullField();
220.33 return ("" + nf.name).toString();
220.34 }
220.35 + @Compare
220.36 + public String toUTFString() throws UnsupportedEncodingException {
220.37 + byte[] arr = {
220.38 + (byte) -59, (byte) -67, (byte) 108, (byte) 117, (byte) -59, (byte) -91,
220.39 + (byte) 111, (byte) 117, (byte) -60, (byte) -115, (byte) 107, (byte) -61,
220.40 + (byte) -67, (byte) 32, (byte) 107, (byte) -59, (byte) -81, (byte) -59,
220.41 + (byte) -120
220.42 + };
220.43 + return new String(arr, "utf-8");
220.44 + }
220.45 +
220.46 + @Compare
220.47 + public int stringToBytesLenght() throws UnsupportedEncodingException {
220.48 + return "\u017dlu\u0165ou\u010dk\u00fd k\u016f\u0148".getBytes("utf8").length;
220.49 + }
220.50
220.51 @Factory
220.52 public static Object[] create() {
221.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
221.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/HttpResourceTest.java Sun Feb 17 17:58:34 2013 +0100
221.3 @@ -0,0 +1,106 @@
221.4 +/**
221.5 + * Back 2 Browser Bytecode Translator
221.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
221.7 + *
221.8 + * This program is free software: you can redistribute it and/or modify
221.9 + * it under the terms of the GNU General Public License as published by
221.10 + * the Free Software Foundation, version 2 of the License.
221.11 + *
221.12 + * This program is distributed in the hope that it will be useful,
221.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
221.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
221.15 + * GNU General Public License for more details.
221.16 + *
221.17 + * You should have received a copy of the GNU General Public License
221.18 + * along with this program. Look for COPYING file in the top folder.
221.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
221.20 + */
221.21 +package org.apidesign.bck2brwsr.tck;
221.22 +
221.23 +import java.io.InputStream;
221.24 +import java.net.URL;
221.25 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
221.26 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
221.27 +import org.apidesign.bck2brwsr.vmtest.Http;
221.28 +import org.apidesign.bck2brwsr.vmtest.VMTest;
221.29 +import org.testng.annotations.Factory;
221.30 +
221.31 +/**
221.32 + *
221.33 + * @author Jaroslav Tulach <jtulach@netbeans.org>
221.34 + */
221.35 +public class HttpResourceTest {
221.36 +
221.37 + @Http({
221.38 + @Http.Resource(path = "/xhr", content = "Hello Brwsr!", mimeType = "text/plain")
221.39 + })
221.40 + @BrwsrTest
221.41 +
221.42 +
221.43 + public String testReadContentViaXHR() throws Exception {
221.44 + String msg = read("/xhr");
221.45 + assert "Hello Brwsr!".equals(msg) : "The message was " + msg;
221.46 + return msg;
221.47 + }
221.48 +
221.49 + @Http({
221.50 + @Http.Resource(path = "/url", content = "Hello via URL!", mimeType = "text/plain")
221.51 + })
221.52 + @BrwsrTest
221.53 + public String testReadContentViaURL() throws Exception {
221.54 + URL url = new URL("http:/url");
221.55 + String msg = (String) url.getContent();
221.56 + assert "Hello via URL!".equals(msg) : "The message was " + msg;
221.57 + return msg;
221.58 + }
221.59 + @Http({
221.60 + @Http.Resource(path = "/url", content = "Hello via URL!", mimeType = "text/plain")
221.61 + })
221.62 + @BrwsrTest
221.63 + public String testReadContentViaURLWithStringParam() throws Exception {
221.64 + URL url = new URL("http:/url");
221.65 + String msg = (String) url.getContent(new Class[] { String.class });
221.66 + assert "Hello via URL!".equals(msg) : "The message was " + msg;
221.67 + return msg;
221.68 + }
221.69 +
221.70 + @Http({
221.71 + @Http.Resource(path = "/bytes", content = "", resource = "0xfe", mimeType = "x-application/binary")
221.72 + })
221.73 + @BrwsrTest
221.74 + public void testReadByte() throws Exception {
221.75 + URL url = new URL("http:/bytes");
221.76 + final Object res = url.getContent(new Class[] { byte[].class });
221.77 + assert res instanceof byte[] : "Expecting byte[]: " + res;
221.78 + byte[] arr = (byte[]) res;
221.79 + assert arr.length == 1 : "One byte " + arr.length;
221.80 + assert arr[0] == 0xfe : "It is 0xfe: " + Integer.toHexString(arr[0]);
221.81 + }
221.82 +
221.83 + @Http({
221.84 + @Http.Resource(path = "/bytes", content = "", resource = "0xfe", mimeType = "x-application/binary")
221.85 + })
221.86 + @BrwsrTest
221.87 + public void testReadByteViaInputStream() throws Exception {
221.88 + URL url = new URL("http:/bytes");
221.89 + InputStream is = url.openStream();
221.90 + byte[] arr = new byte[10];
221.91 + int len = is.read(arr);
221.92 + assert len == 1 : "One byte " + len;
221.93 + assert arr[0] == 0xfe : "It is 0xfe: " + Integer.toHexString(arr[0]);
221.94 + }
221.95 +
221.96 + @JavaScriptBody(args = { "url" }, body =
221.97 + "var req = new XMLHttpRequest();\n"
221.98 + + "req.open('GET', url, false);\n"
221.99 + + "req.send();\n"
221.100 + + "return req.responseText;"
221.101 + )
221.102 + private static native String read(String url);
221.103 +
221.104 +
221.105 + @Factory
221.106 + public static Object[] create() {
221.107 + return VMTest.create(HttpResourceTest.class);
221.108 + }
221.109 +}
222.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
222.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceA.java Sun Feb 17 17:58:34 2013 +0100
222.3 @@ -0,0 +1,34 @@
222.4 +/**
222.5 + * Back 2 Browser Bytecode Translator
222.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
222.7 + *
222.8 + * This program is free software: you can redistribute it and/or modify
222.9 + * it under the terms of the GNU General Public License as published by
222.10 + * the Free Software Foundation, version 2 of the License.
222.11 + *
222.12 + * This program is distributed in the hope that it will be useful,
222.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
222.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
222.15 + * GNU General Public License for more details.
222.16 + *
222.17 + * You should have received a copy of the GNU General Public License
222.18 + * along with this program. Look for COPYING file in the top folder.
222.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
222.20 + */
222.21 +package org.apidesign.bck2brwsr.tck;
222.22 +
222.23 +/**
222.24 + *
222.25 + * @author Jaroslav Tulach <jtulach@netbeans.org>
222.26 + */
222.27 +public class InheritanceA {
222.28 + private String name;
222.29 +
222.30 + public void setA(String n) {
222.31 + this.name = n;
222.32 + }
222.33 +
222.34 + public String getA() {
222.35 + return name;
222.36 + }
222.37 +}
223.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
223.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceB.java Sun Feb 17 17:58:34 2013 +0100
223.3 @@ -0,0 +1,34 @@
223.4 +/**
223.5 + * Back 2 Browser Bytecode Translator
223.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
223.7 + *
223.8 + * This program is free software: you can redistribute it and/or modify
223.9 + * it under the terms of the GNU General Public License as published by
223.10 + * the Free Software Foundation, version 2 of the License.
223.11 + *
223.12 + * This program is distributed in the hope that it will be useful,
223.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
223.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
223.15 + * GNU General Public License for more details.
223.16 + *
223.17 + * You should have received a copy of the GNU General Public License
223.18 + * along with this program. Look for COPYING file in the top folder.
223.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
223.20 + */
223.21 +package org.apidesign.bck2brwsr.tck;
223.22 +
223.23 +/**
223.24 + *
223.25 + * @author Jaroslav Tulach <jtulach@netbeans.org>
223.26 + */
223.27 +public class InheritanceB extends InheritanceA {
223.28 + private String name;
223.29 +
223.30 + public void setB(String n) {
223.31 + this.name = n;
223.32 + }
223.33 +
223.34 + public String getB() {
223.35 + return name;
223.36 + }
223.37 +}
224.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
224.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceTest.java Sun Feb 17 17:58:34 2013 +0100
224.3 @@ -0,0 +1,41 @@
224.4 +/**
224.5 + * Back 2 Browser Bytecode Translator
224.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
224.7 + *
224.8 + * This program is free software: you can redistribute it and/or modify
224.9 + * it under the terms of the GNU General Public License as published by
224.10 + * the Free Software Foundation, version 2 of the License.
224.11 + *
224.12 + * This program is distributed in the hope that it will be useful,
224.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
224.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
224.15 + * GNU General Public License for more details.
224.16 + *
224.17 + * You should have received a copy of the GNU General Public License
224.18 + * along with this program. Look for COPYING file in the top folder.
224.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
224.20 + */
224.21 +package org.apidesign.bck2brwsr.tck;
224.22 +
224.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
224.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
224.25 +import org.testng.annotations.Factory;
224.26 +
224.27 +/**
224.28 + *
224.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
224.30 + */
224.31 +public class InheritanceTest {
224.32 +
224.33 + @Compare public String checkFieldsIndependent() throws ClassNotFoundException {
224.34 + InheritanceB ib = new InheritanceB();
224.35 + ib.setA("A");
224.36 + ib.setB("B");
224.37 + return "A: " + ib.getA() + " B: " + ib.getB();
224.38 + }
224.39 +
224.40 + @Factory
224.41 + public static Object[] create() {
224.42 + return VMTest.create(InheritanceTest.class);
224.43 + }
224.44 +}
225.1 --- a/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/IntegerArithmeticTest.java Fri Jan 25 15:08:24 2013 +0100
225.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/IntegerArithmeticTest.java Sun Feb 17 17:58:34 2013 +0100
225.3 @@ -47,6 +47,10 @@
225.4 return x % y;
225.5 }
225.6
225.7 + private static int neg(int x) {
225.8 + return (-x);
225.9 + }
225.10 +
225.11 @Compare public int addOverflow() {
225.12 return add(Integer.MAX_VALUE, 1);
225.13 }
225.14 @@ -91,6 +95,18 @@
225.15 return mod(1, 2);
225.16 }
225.17
225.18 + @Compare public int negate() {
225.19 + return neg(123456);
225.20 + }
225.21 +
225.22 + @Compare public int negateMaxInt() {
225.23 + return neg(Integer.MAX_VALUE);
225.24 + }
225.25 +
225.26 + @Compare public int negateMinInt() {
225.27 + return neg(Integer.MIN_VALUE);
225.28 + }
225.29 +
225.30 @Compare public int sumTwoDimensions() {
225.31 int[][] matrix = createMatrix(4, 3);
225.32 matrix[0][0] += 10;
226.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
226.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/LongArithmeticTest.java Sun Feb 17 17:58:34 2013 +0100
226.3 @@ -0,0 +1,334 @@
226.4 +/**
226.5 + * Back 2 Browser Bytecode Translator
226.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
226.7 + *
226.8 + * This program is free software: you can redistribute it and/or modify
226.9 + * it under the terms of the GNU General Public License as published by
226.10 + * the Free Software Foundation, version 2 of the License.
226.11 + *
226.12 + * This program is distributed in the hope that it will be useful,
226.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
226.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
226.15 + * GNU General Public License for more details.
226.16 + *
226.17 + * You should have received a copy of the GNU General Public License
226.18 + * along with this program. Look for COPYING file in the top folder.
226.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
226.20 + */
226.21 +package org.apidesign.bck2brwsr.tck;
226.22 +
226.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
226.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
226.25 +import org.testng.annotations.Factory;
226.26 +
226.27 +/**
226.28 + *
226.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
226.30 + */
226.31 +public class LongArithmeticTest {
226.32 +
226.33 + private static long add(long x, long y) {
226.34 + return (x + y);
226.35 + }
226.36 +
226.37 + private static long sub(long x, long y) {
226.38 + return (x - y);
226.39 + }
226.40 +
226.41 + private static long mul(long x, long y) {
226.42 + return (x * y);
226.43 + }
226.44 +
226.45 + private static long div(long x, long y) {
226.46 + return (x / y);
226.47 + }
226.48 +
226.49 + private static long mod(long x, long y) {
226.50 + return (x % y);
226.51 + }
226.52 +
226.53 + private static long neg(long x) {
226.54 + return (-x);
226.55 + }
226.56 +
226.57 + private static long shl(long x, int b) {
226.58 + return (x << b);
226.59 + }
226.60 +
226.61 + private static long shr(long x, int b) {
226.62 + return (x >> b);
226.63 + }
226.64 +
226.65 + private static long ushr(long x, int b) {
226.66 + return (x >>> b);
226.67 + }
226.68 +
226.69 + private static long and(long x, long y) {
226.70 + return (x & y);
226.71 + }
226.72 +
226.73 + private static long or(long x, long y) {
226.74 + return (x | y);
226.75 + }
226.76 +
226.77 + private static long xor(long x, long y) {
226.78 + return (x ^ y);
226.79 + }
226.80 +
226.81 + public static int compare(long x, long y, int zero) {
226.82 + final int xyResult = compareL(x, y, zero);
226.83 + final int yxResult = compareL(y, x, zero);
226.84 +
226.85 + return ((xyResult + yxResult) == 0) ? xyResult : -2;
226.86 + }
226.87 +
226.88 + private static int compareL(long x, long y, int zero) {
226.89 + int result = -2;
226.90 + int trueCount = 0;
226.91 +
226.92 + x += zero;
226.93 + if (x == y) {
226.94 + result = 0;
226.95 + ++trueCount;
226.96 + }
226.97 +
226.98 + x += zero;
226.99 + if (x < y) {
226.100 + result = -1;
226.101 + ++trueCount;
226.102 + }
226.103 +
226.104 + x += zero;
226.105 + if (x > y) {
226.106 + result = 1;
226.107 + ++trueCount;
226.108 + }
226.109 +
226.110 + return (trueCount == 1) ? result : -2;
226.111 + }
226.112 +
226.113 + @Compare public long conversion() {
226.114 + return Long.MAX_VALUE;
226.115 + }
226.116 +
226.117 + @Compare public long negate1() {
226.118 + return neg(0x00fa37d7763e0ca1l);
226.119 + }
226.120 +
226.121 + @Compare public long negate2() {
226.122 + return neg(0x80fa37d7763e0ca1l);
226.123 + }
226.124 +
226.125 + @Compare public long negate3() {
226.126 + return neg(0xfffffffffffffeddl);
226.127 + }
226.128 +
226.129 + @Compare public long addOverflow() {
226.130 + return add(Long.MAX_VALUE, 1l);
226.131 + }
226.132 +
226.133 + @Compare public long subUnderflow() {
226.134 + return sub(Long.MIN_VALUE, 1l);
226.135 + }
226.136 +
226.137 + @Compare public long addMaxLongAndMaxLong() {
226.138 + return add(Long.MAX_VALUE, Long.MAX_VALUE);
226.139 + }
226.140 +
226.141 + @Compare public long subMinLongAndMinLong() {
226.142 + return sub(Long.MIN_VALUE, Long.MIN_VALUE);
226.143 + }
226.144 +
226.145 + @Compare public long subMinLongAndMaxLong() {
226.146 + return sub(Long.MIN_VALUE, Long.MAX_VALUE);
226.147 + }
226.148 +
226.149 + @Compare public long multiplyMaxLong() {
226.150 + return mul(Long.MAX_VALUE, 2l);
226.151 + }
226.152 +
226.153 + @Compare public long multiplyMaxLongAndMaxLong() {
226.154 + return mul(Long.MAX_VALUE, Long.MAX_VALUE);
226.155 + }
226.156 +
226.157 + @Compare public long multiplyMinLong() {
226.158 + return mul(Long.MIN_VALUE, 2l);
226.159 + }
226.160 +
226.161 + @Compare public long multiplyMinLongAndMinLong() {
226.162 + return mul(Long.MIN_VALUE, Long.MIN_VALUE);
226.163 + }
226.164 +
226.165 + @Compare public long multiplyPrecision() {
226.166 + return mul(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el);
226.167 + }
226.168 +
226.169 + @Compare public long divideSmallPositiveNumbers() {
226.170 + return div(0xabcdef, 0x123);
226.171 + }
226.172 +
226.173 + @Compare public long divideSmallNegativeNumbers() {
226.174 + return div(-0xabcdef, -0x123);
226.175 + }
226.176 +
226.177 + @Compare public long divideSmallMixedNumbers() {
226.178 + return div(0xabcdef, -0x123);
226.179 + }
226.180 +
226.181 + @Compare public long dividePositiveNumbersOneDigitDenom() {
226.182 + return div(0xabcdef0102ffffl, 0x654);
226.183 + }
226.184 +
226.185 + @Compare public long divideNegativeNumbersOneDigitDenom() {
226.186 + return div(-0xabcdef0102ffffl, -0x654);
226.187 + }
226.188 +
226.189 + @Compare public long divideMixedNumbersOneDigitDenom() {
226.190 + return div(-0xabcdef0102ffffl, 0x654);
226.191 + }
226.192 +
226.193 + @Compare public long dividePositiveNumbersMultiDigitDenom() {
226.194 + return div(0x7ffefc003322aabbl, 0x89ab1000l);
226.195 + }
226.196 +
226.197 + @Compare public long divideNegativeNumbersMultiDigitDenom() {
226.198 + return div(-0x7ffefc003322aabbl, -0x123489ab1001l);
226.199 + }
226.200 +
226.201 + @Compare public long divideMixedNumbersMultiDigitDenom() {
226.202 + return div(0x7ffefc003322aabbl, -0x38f49b0b7574e36l);
226.203 + }
226.204 +
226.205 + @Compare public long divideWithOverflow() {
226.206 + return div(0x8000fffe0000l, 0x8000ffffl);
226.207 + }
226.208 +
226.209 + @Compare public long divideWithCorrection() {
226.210 + return div(0x7fff800000000000l, 0x800000000001l);
226.211 + }
226.212 +
226.213 + @Compare public long moduloSmallPositiveNumbers() {
226.214 + return mod(0xabcdef, 0x123);
226.215 + }
226.216 +
226.217 + @Compare public long moduloSmallNegativeNumbers() {
226.218 + return mod(-0xabcdef, -0x123);
226.219 + }
226.220 +
226.221 + @Compare public long moduloSmallMixedNumbers() {
226.222 + return mod(0xabcdef, -0x123);
226.223 + }
226.224 +
226.225 + @Compare public long moduloPositiveNumbersOneDigitDenom() {
226.226 + return mod(0xabcdef0102ffffl, 0x654);
226.227 + }
226.228 +
226.229 + @Compare public long moduloNegativeNumbersOneDigitDenom() {
226.230 + return mod(-0xabcdef0102ffffl, -0x654);
226.231 + }
226.232 +
226.233 + @Compare public long moduloMixedNumbersOneDigitDenom() {
226.234 + return mod(-0xabcdef0102ffffl, 0x654);
226.235 + }
226.236 +
226.237 + @Compare public long moduloPositiveNumbersMultiDigitDenom() {
226.238 + return mod(0x7ffefc003322aabbl, 0x89ab1000l);
226.239 + }
226.240 +
226.241 + @Compare public long moduloNegativeNumbersMultiDigitDenom() {
226.242 + return mod(-0x7ffefc003322aabbl, -0x123489ab1001l);
226.243 + }
226.244 +
226.245 + @Compare public long moduloMixedNumbersMultiDigitDenom() {
226.246 + return mod(0x7ffefc003322aabbl, -0x38f49b0b7574e36l);
226.247 + }
226.248 +
226.249 + @Compare public long moduloWithOverflow() {
226.250 + return mod(0x8000fffe0000l, 0x8000ffffl);
226.251 + }
226.252 +
226.253 + @Compare public long moduloWithCorrection() {
226.254 + return mod(0x7fff800000000000l, 0x800000000001l);
226.255 + }
226.256 +
226.257 + @Compare public long shiftL1() {
226.258 + return shl(0x00fa37d7763e0ca1l, 5);
226.259 + }
226.260 +
226.261 + @Compare public long shiftL2() {
226.262 + return shl(0x00fa37d7763e0ca1l, 32);
226.263 + }
226.264 +
226.265 + @Compare public long shiftL3() {
226.266 + return shl(0x00fa37d7763e0ca1l, 45);
226.267 + }
226.268 +
226.269 + @Compare public long shiftR1() {
226.270 + return shr(0x00fa37d7763e0ca1l, 5);
226.271 + }
226.272 +
226.273 + @Compare public long shiftR2() {
226.274 + return shr(0x00fa37d7763e0ca1l, 32);
226.275 + }
226.276 +
226.277 + @Compare public long shiftR3() {
226.278 + return shr(0x00fa37d7763e0ca1l, 45);
226.279 + }
226.280 +
226.281 + @Compare public long uShiftR1() {
226.282 + return ushr(0x00fa37d7763e0ca1l, 5);
226.283 + }
226.284 +
226.285 + @Compare public long uShiftR2() {
226.286 + return ushr(0x00fa37d7763e0ca1l, 45);
226.287 + }
226.288 +
226.289 + @Compare public long uShiftR3() {
226.290 + return ushr(0xf0fa37d7763e0ca1l, 5);
226.291 + }
226.292 +
226.293 + @Compare public long uShiftR4() {
226.294 + return ushr(0xf0fa37d7763e0ca1l, 45);
226.295 + }
226.296 +
226.297 + @Compare public long and1() {
226.298 + return and(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el);
226.299 + }
226.300 +
226.301 + @Compare public long or1() {
226.302 + return or(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el);
226.303 + }
226.304 +
226.305 + @Compare public long xor1() {
226.306 + return xor(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el);
226.307 + }
226.308 +
226.309 + @Compare public long xor2() {
226.310 + return xor(0x00fa37d7763e0ca1l, 0x00000000ff00123el);
226.311 + }
226.312 +
226.313 + @Compare public long xor3() {
226.314 + return xor(0x00000000763e0ca1l, 0x00000000ff00123el);
226.315 + }
226.316 +
226.317 + @Compare public int compareSameNumbers() {
226.318 + return compare(0x0000000000000000l, 0x0000000000000000l, 0);
226.319 + }
226.320 +
226.321 + @Compare public int comparePositiveNumbers() {
226.322 + return compare(0x0000000000200000l, 0x0000000010000000l, 0);
226.323 + }
226.324 +
226.325 + @Compare public int compareNegativeNumbers() {
226.326 + return compare(0xffffffffffffffffl, 0xffffffff00000000l, 0);
226.327 + }
226.328 +
226.329 + @Compare public int compareMixedNumbers() {
226.330 + return compare(0x8000000000000000l, 0x7fffffffffffffffl, 0);
226.331 + }
226.332 +
226.333 + @Factory
226.334 + public static Object[] create() {
226.335 + return VMTest.create(LongArithmeticTest.class);
226.336 + }
226.337 +}
227.1 --- a/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java Fri Jan 25 15:08:24 2013 +0100
227.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java Sun Feb 17 17:58:34 2013 +0100
227.3 @@ -17,12 +17,12 @@
227.4 */
227.5 package org.apidesign.bck2brwsr.tck;
227.6
227.7 +import java.lang.annotation.Retention;
227.8 +import java.lang.annotation.RetentionPolicy;
227.9 import java.lang.reflect.Method;
227.10 import java.util.Arrays;
227.11 import java.util.Collections;
227.12 import java.util.List;
227.13 -import java.util.logging.Level;
227.14 -import java.util.logging.Logger;
227.15 import org.apidesign.bck2brwsr.core.JavaScriptBody;
227.16 import org.apidesign.bck2brwsr.vmtest.Compare;
227.17 import org.apidesign.bck2brwsr.vmtest.VMTest;
227.18 @@ -49,6 +49,14 @@
227.19 return long.class.toString();
227.20 }
227.21
227.22 + @Compare public boolean isRunnableInterface() {
227.23 + return Runnable.class.isInterface();
227.24 + }
227.25 +
227.26 + @Compare public String isRunnableHasRunMethod() throws NoSuchMethodException {
227.27 + return Runnable.class.getMethod("run").getName();
227.28 + }
227.29 +
227.30 @Compare public String namesOfMethods() {
227.31 StringBuilder sb = new StringBuilder();
227.32 String[] arr = new String[20];
227.33 @@ -61,6 +69,19 @@
227.34 }
227.35 return sb.toString();
227.36 }
227.37 +
227.38 + @Compare public String namesOfDeclaringClassesOfMethods() {
227.39 + StringBuilder sb = new StringBuilder();
227.40 + String[] arr = new String[20];
227.41 + int i = 0;
227.42 + for (Method m : StaticUse.class.getMethods()) {
227.43 + arr[i++] = m.getName() + "@" + m.getDeclaringClass().getName();
227.44 + }
227.45 + for (String s : sort(arr, i)) {
227.46 + sb.append(s).append("\n");
227.47 + }
227.48 + return sb.toString();
227.49 + }
227.50
227.51 @Compare public String cannotCallNonStaticMethodWithNull() throws Exception {
227.52 StaticUse.class.getMethod("instanceMethod").invoke(null);
227.53 @@ -71,6 +92,35 @@
227.54 return StaticUse.class.getMethod("instanceMethod").getReturnType();
227.55 }
227.56
227.57 + @Retention(RetentionPolicy.RUNTIME)
227.58 + @interface Ann {
227.59 + }
227.60 +
227.61 + @Compare public String annoClass() throws Exception {
227.62 + Retention r = Ann.class.getAnnotation(Retention.class);
227.63 + assert r != null : "Annotation is present";
227.64 + assert r.value() == RetentionPolicy.RUNTIME : "Policy value is OK: " + r.value();
227.65 + return r.annotationType().getName();
227.66 + }
227.67 +
227.68 + @Compare public boolean isAnnotation() {
227.69 + return Ann.class.isAnnotation();
227.70 + }
227.71 + @Compare public boolean isNotAnnotation() {
227.72 + return String.class.isAnnotation();
227.73 + }
227.74 + @Compare public boolean isNotAnnotationEnum() {
227.75 + return E.class.isAnnotation();
227.76 + }
227.77 + enum E { A, B };
227.78 + @Compare public boolean isEnum() {
227.79 + return E.A.getClass().isEnum();
227.80 + }
227.81 +
227.82 + @Compare public boolean isNotEnum() {
227.83 + return "".getClass().isEnum();
227.84 + }
227.85 +
227.86 @Compare public String newInstanceFails() throws InstantiationException {
227.87 try {
227.88 return "success: " + StaticUse.class.newInstance();
228.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
228.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/CRC32Test.java Sun Feb 17 17:58:34 2013 +0100
228.3 @@ -0,0 +1,41 @@
228.4 +/**
228.5 + * Back 2 Browser Bytecode Translator
228.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
228.7 + *
228.8 + * This program is free software: you can redistribute it and/or modify
228.9 + * it under the terms of the GNU General Public License as published by
228.10 + * the Free Software Foundation, version 2 of the License.
228.11 + *
228.12 + * This program is distributed in the hope that it will be useful,
228.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
228.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
228.15 + * GNU General Public License for more details.
228.16 + *
228.17 + * You should have received a copy of the GNU General Public License
228.18 + * along with this program. Look for COPYING file in the top folder.
228.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
228.20 + */
228.21 +package org.apidesign.bck2brwsr.vmtest.impl;
228.22 +
228.23 +import java.io.UnsupportedEncodingException;
228.24 +import java.util.zip.CRC32;
228.25 +import org.apidesign.bck2brwsr.vmtest.Compare;
228.26 +import org.apidesign.bck2brwsr.vmtest.VMTest;
228.27 +import org.testng.annotations.Factory;
228.28 +
228.29 +/**
228.30 + *
228.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
228.32 + */
228.33 +public class CRC32Test {
228.34 +
228.35 + @Compare public long crc1() throws UnsupportedEncodingException {
228.36 + CRC32 crc = new CRC32();
228.37 + crc.update("Hello World!".getBytes("UTF-8"));
228.38 + return crc.getValue();
228.39 + }
228.40 +
228.41 + @Factory public static Object[] create() {
228.42 + return VMTest.create(CRC32Test.class);
228.43 + }
228.44 +}
229.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
229.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipEntryTest.java Sun Feb 17 17:58:34 2013 +0100
229.3 @@ -0,0 +1,67 @@
229.4 +/**
229.5 + * Back 2 Browser Bytecode Translator
229.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
229.7 + *
229.8 + * This program is free software: you can redistribute it and/or modify
229.9 + * it under the terms of the GNU General Public License as published by
229.10 + * the Free Software Foundation, version 2 of the License.
229.11 + *
229.12 + * This program is distributed in the hope that it will be useful,
229.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
229.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
229.15 + * GNU General Public License for more details.
229.16 + *
229.17 + * You should have received a copy of the GNU General Public License
229.18 + * along with this program. Look for COPYING file in the top folder.
229.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
229.20 + */
229.21 +package org.apidesign.bck2brwsr.vmtest.impl;
229.22 +
229.23 +import java.io.ByteArrayInputStream;
229.24 +import java.io.IOException;
229.25 +import java.io.InputStream;
229.26 +import org.apidesign.bck2brwsr.emul.zip.FastJar;
229.27 +import org.testng.annotations.Test;
229.28 +import static org.testng.Assert.*;
229.29 +
229.30 +/**
229.31 + *
229.32 + * @author Jaroslav Tulach <jtulach@netbeans.org>
229.33 + */
229.34 +@GenerateZip(name = "five.zip", contents = {
229.35 + "1.txt", "one",
229.36 + "2.txt", "duo",
229.37 + "3.txt", "three",
229.38 + "4.txt", "four",
229.39 + "5.txt", "five"
229.40 +})
229.41 +public class ZipEntryTest {
229.42 + @Test
229.43 + public void readEntriesEffectively() throws IOException {
229.44 + InputStream is = ZipEntryTest.class.getResourceAsStream("five.zip");
229.45 + byte[] arr = new byte[is.available()];
229.46 + int len = is.read(arr);
229.47 + assertEquals(len, arr.length, "Read fully");
229.48 +
229.49 + FastJar fj = new FastJar(arr);
229.50 + FastJar.Entry[] entrs = fj.list();
229.51 +
229.52 + assertEquals(5, entrs.length, "Five entries");
229.53 +
229.54 + for (int i = 1; i <= 5; i++) {
229.55 + FastJar.Entry en = entrs[i - 1];
229.56 + assertEquals(en.name, i + ".txt");
229.57 +// assertEquals(cis.cnt, 0, "Content of the file should be skipped, not read");
229.58 + }
229.59 +
229.60 + assertContent("three", fj.getInputStream(entrs[3 - 1]), "read OK");
229.61 + assertContent("five", fj.getInputStream(entrs[5 - 1]), "read OK");
229.62 + }
229.63 +
229.64 + private static void assertContent(String exp, InputStream is, String msg) throws IOException {
229.65 + byte[] arr = new byte[512];
229.66 + int len = is.read(arr);
229.67 + String s = new String(arr, 0, len);
229.68 + assertEquals(exp, s, msg);
229.69 + }
229.70 +}
230.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
230.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java Sun Feb 17 17:58:34 2013 +0100
230.3 @@ -0,0 +1,108 @@
230.4 +/**
230.5 + * Back 2 Browser Bytecode Translator
230.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
230.7 + *
230.8 + * This program is free software: you can redistribute it and/or modify
230.9 + * it under the terms of the GNU General Public License as published by
230.10 + * the Free Software Foundation, version 2 of the License.
230.11 + *
230.12 + * This program is distributed in the hope that it will be useful,
230.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
230.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
230.15 + * GNU General Public License for more details.
230.16 + *
230.17 + * You should have received a copy of the GNU General Public License
230.18 + * along with this program. Look for COPYING file in the top folder.
230.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
230.20 + */
230.21 +package org.apidesign.bck2brwsr.vmtest.impl;
230.22 +
230.23 +import java.io.IOException;
230.24 +import java.io.InputStream;
230.25 +import java.util.Objects;
230.26 +import java.util.zip.ZipEntry;
230.27 +import java.util.zip.ZipInputStream;
230.28 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
230.29 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
230.30 +import org.apidesign.bck2brwsr.vmtest.Compare;
230.31 +import org.apidesign.bck2brwsr.vmtest.Http;
230.32 +import org.apidesign.bck2brwsr.vmtest.VMTest;
230.33 +import org.testng.annotations.Factory;
230.34 +
230.35 +/**
230.36 + *
230.37 + * @author Jaroslav Tulach <jtulach@netbeans.org>
230.38 + */
230.39 +@GenerateZip(name = "readAnEntry.zip", contents = {
230.40 + "my/main/file.txt", "Hello World!"
230.41 +})
230.42 +public class ZipFileTest {
230.43 +
230.44 + @Compare public String readAnEntry() throws IOException {
230.45 + InputStream is = ZipFileTest.class.getResourceAsStream("readAnEntry.zip");
230.46 + ZipInputStream zip = new ZipInputStream(is);
230.47 + ZipEntry entry = zip.getNextEntry();
230.48 + assertEquals(entry.getName(), "my/main/file.txt", "Correct entry");
230.49 +
230.50 + byte[] arr = new byte[4096];
230.51 + int len = zip.read(arr);
230.52 +
230.53 + assertEquals(zip.getNextEntry(), null, "No next entry");
230.54 +
230.55 + final String ret = new String(arr, 0, len, "UTF-8");
230.56 + return ret;
230.57 + }
230.58 +
230.59 + @JavaScriptBody(args = { "res", "path" }, body =
230.60 + "var myvm = bck2brwsr.apply(null, path);\n"
230.61 + + "var cls = myvm.loadClass('java.lang.String');\n"
230.62 + + "return cls.getClass__Ljava_lang_Class_2().getResourceAsStream__Ljava_io_InputStream_2Ljava_lang_String_2(res);\n"
230.63 + )
230.64 + private static native Object loadVMResource(String res, String...path);
230.65 +
230.66 + @Http({
230.67 + @Http.Resource(path = "/readAnEntry.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip")
230.68 + })
230.69 + @BrwsrTest public void canVmLoadResourceFromZip() throws IOException {
230.70 + Object res = loadVMResource("/my/main/file.txt", "/readAnEntry.jar");
230.71 + assert res instanceof InputStream : "Got array of bytes: " + res;
230.72 + InputStream is = (InputStream)res;
230.73 +
230.74 + byte[] arr = new byte[4096];
230.75 + int len = is.read(arr);
230.76 +
230.77 + final String ret = new String(arr, 0, len, "UTF-8");
230.78 +
230.79 + assertEquals(ret, "Hello World!", "Can read the bytes");
230.80 + }
230.81 +
230.82 + @GenerateZip(name = "cpattr.zip", contents = {
230.83 + "META-INF/MANIFEST.MF", "Manifest-Version: 1.0\n"
230.84 + + "Created-By: hand\n"
230.85 + + "Class-Path: realJar.jar\n\n\n"
230.86 + })
230.87 + @Http({
230.88 + @Http.Resource(path = "/readComplexEntry.jar", mimeType = "x-application/zip", content = "", resource="cpattr.zip"),
230.89 + @Http.Resource(path = "/realJar.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip"),
230.90 + })
230.91 + @BrwsrTest public void understandsClassPathAttr() throws IOException {
230.92 + Object res = loadVMResource("/my/main/file.txt", "/readComplexEntry.jar");
230.93 + assert res instanceof InputStream : "Got array of bytes: " + res;
230.94 + InputStream is = (InputStream)res;
230.95 +
230.96 + byte[] arr = new byte[4096];
230.97 + int len = is.read(arr);
230.98 +
230.99 + final String ret = new String(arr, 0, len, "UTF-8");
230.100 +
230.101 + assertEquals(ret, "Hello World!", "Can read the bytes from secondary JAR");
230.102 + }
230.103 +
230.104 + private static void assertEquals(Object real, Object exp, String msg) {
230.105 + assert Objects.equals(exp, real) : msg + " exp: " + exp + " real: " + real;
230.106 + }
230.107 +
230.108 + @Factory public static Object[] create() {
230.109 + return VMTest.create(ZipFileTest.class);
230.110 + }
230.111 +}
231.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
231.2 +++ b/vmtest/src/test/resources/org/apidesign/bck2brwsr/tck/0xfe Sun Feb 17 17:58:34 2013 +0100
231.3 @@ -0,0 +1,1 @@
231.4 +þ
231.5 \ No newline at end of file