Bringing in latest default branch model
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Sun, 17 Feb 2013 17:58:34 +0100
branchmodel
changeset 75941e1dc88a399
parent 596 d443b6c05a01
parent 751 c6878807b0d4
child 760 4bd6f3bc6c64
Bringing in latest default branch
launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Console.java
launcher/src/main/java/org/apidesign/bck2brwsr/launcher/MethodInvocation.java
mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Bck2BrswrMojo.java
mojo/src/main/resources/archetype-resources/src/main/resources/index.xhtml
     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&trade; 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&trade; 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&trade; 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 &lt;= 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 &amp; 0xff) &lt;&lt; 8) | (b &amp; 0xff))
  20.246 +     * </pre></blockquote>
  20.247 +     *
  20.248 +     * @deprecated This method does not properly convert bytes into characters.
  20.249 +     * As of JDK&nbsp;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 &amp; (v &gt;&gt; 8))
  21.143 +     * (byte)(0xff &amp; 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 &amp; (v &gt;&gt; 8))
  21.164 +     * (byte)(0xff &amp; 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 &amp; (v &gt;&gt; 24))
  21.184 +     * (byte)(0xff &amp; (v &gt;&gt; 16))
  21.185 +     * (byte)(0xff &amp; (v &gt;&gt; &#32; &#32;8))
  21.186 +     * (byte)(0xff &amp; 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 &amp; (v &gt;&gt; 56))
  21.205 +     * (byte)(0xff &amp; (v &gt;&gt; 48))
  21.206 +     * (byte)(0xff &amp; (v &gt;&gt; 40))
  21.207 +     * (byte)(0xff &amp; (v &gt;&gt; 32))
  21.208 +     * (byte)(0xff &amp; (v &gt;&gt; 24))
  21.209 +     * (byte)(0xff &amp; (v &gt;&gt; 16))
  21.210 +     * (byte)(0xff &amp; (v &gt;&gt;  8))
  21.211 +     * (byte)(0xff &amp; 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>&#92;u0001</code> through
  21.319 +     * <code>&#92;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>&#92;u0000</code>
  21.323 +     * or is in the range <code>&#92;u0080</code>
  21.324 +     * through <code>&#92;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 &amp; (c &gt;&gt; 6)))
  21.328 +     * (byte)(0x80 | (0x3f &amp; c))
  21.329 +     *  </code></pre>  <p> If a character
  21.330 +     * <code>c</code> is in the range <code>&#92;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 &amp; (c &gt;&gt; 12)))
  21.335 +     * (byte)(0x80 | (0x3f &amp; (c &gt;&gt;  6)))
  21.336 +     * (byte)(0x80 | (0x3f &amp; 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 &gt;= 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 &gt;= 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 &lt; 0 || i &gt;= list.size()
  59.529 +     *         || j &lt; 0 || j &gt;= 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&lt;String&gt; 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&lt;String&gt; 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&lt;String, Date&gt; 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&lt;Object&gt; weakHashSet = Collections.newSetFromMap(
 59.3858 +     *        new WeakHashMap&lt;Object, Boolean&gt;());
 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&nbsp;?&nbsp;e==null&nbsp;:&nbsp;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&nbsp;?&nbsp;e==null&nbsp;:&nbsp;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&nbsp;?&nbsp;e==null&nbsp;:&nbsp;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&nbsp;?&nbsp;e==null&nbsp;:&nbsp;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>,&nbsp;</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&nbsp;?&nbsp;e==null&nbsp;:&nbsp;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&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;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&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;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&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;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 +    * &#064;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 &quot;bounded&quot;) 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&nbsp;x&nbsp</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&lt;String, V&gt; 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&lt;String, V&gt; 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&lt;String&gt; 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&lt;String&gt; 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&lt;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>"&nbsp;&#92;t&#92;n&#92;r&#92;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&nbsp;?&nbsp;e==null&nbsp;:&nbsp;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&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;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&nbsp;&gt;=&nbsp;index&nbsp;&amp;&amp;&nbsp;(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;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&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;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&nbsp;&lt;=&nbsp;index&nbsp;&amp;&amp;&nbsp;(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;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()&nbsp;-&nbsp;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&nbsp;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&nbsp;-&nbsp;f2</code>&nbsp;&times;&nbsp;<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&eacute;
  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&trade; 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&trade; 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&trade; 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&trade; 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&trade; 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 +      &nbsp;
  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 +      &nbsp;
  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 +      &nbsp;
  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"> &amp; </span><span class="comment">Java</span> <span class="comment">demo</span> <span class="comment">showing</span> <span class="comment">the</span> <span class="comment">power</span> <span class="comment">of</span> <a href="http://wiki.apidesign.org/wiki/AnnotationProcessor">annotation processors</a>
  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">&lt;jaroslav.tulach@apidesign.org&gt;</span>
  167.21 -     <span class="comment">*/</span>
  167.22 -    @Page(xhtml=<span class="string">&quot;</span><span class="string">Calculator.xhtml</span><span class="string">&quot;</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">&quot;</span><span class="string">clear</span><span class="string">&quot;</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">&quot;</span><span class="string">0</span><span class="string">&quot;</span>);
  167.32 -        }
  167.33 -
  167.34 -        @OnClick(id= { <span class="string">&quot;</span><span class="string">plus</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">minus</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">mul</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">div</span><span class="string">&quot;</span> })
  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">&quot;</span><span class="string">0</span><span class="string">&quot;</span>);
  167.39 -        }
  167.40 -
  167.41 -        @OnClick(id=<span class="string">&quot;</span><span class="string">result</span><span class="string">&quot;</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">&quot;</span><span class="string">plus</span><span class="string">&quot;</span>: setValue(memory + getValue()); <span class="keyword-directive">break</span>;
  167.45 -                <span class="keyword-directive">case</span> <span class="string">&quot;</span><span class="string">minus</span><span class="string">&quot;</span>: setValue(memory - getValue()); <span class="keyword-directive">break</span>;
  167.46 -                <span class="keyword-directive">case</span> <span class="string">&quot;</span><span class="string">mul</span><span class="string">&quot;</span>: setValue(memory * getValue()); <span class="keyword-directive">break</span>;
  167.47 -                <span class="keyword-directive">case</span> <span class="string">&quot;</span><span class="string">div</span><span class="string">&quot;</span>: setValue(memory / getValue()); <span class="keyword-directive">break</span>;
  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">&quot;</span><span class="string">n0</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n1</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n2</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n3</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n4</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n5</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n6</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n7</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n8</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n9</span><span class="string">&quot;</span>}) 
  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">&quot;</span><span class="string">err</span><span class="string">&quot;</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