Merge with trunk arithmetic
authorLubomir Nerad <lubomir.nerad@oracle.com>
Tue, 19 Feb 2013 15:59:27 +0100
brancharithmetic
changeset 753cc0e6767259b
parent 752 cc3871bdd83c
parent 751 c6878807b0d4
child 754 39712168230d
child 755 5652acd48509
Merge with trunk
emul/mini/src/main/java/java/util/zip/ZipConstants64.java
mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Bck2BrswrMojo.java
mojo/src/main/resources/archetype-resources/src/main/resources/index.xhtml
vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java
vm/src/test/java/org/apidesign/vm4brwsr/TestUtils.java
vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/HttpResource.java
     1.1 --- a/dew/src/main/java/org/apidesign/bck2brwsr/dew/Dew.java	Tue Feb 19 15:33:32 2013 +0100
     1.2 +++ b/dew/src/main/java/org/apidesign/bck2brwsr/dew/Dew.java	Tue Feb 19 15:59:27 2013 +0100
     1.3 @@ -96,7 +96,9 @@
     1.4          }
     1.5          if (r.equals("/result.html")) {
     1.6              response.setContentType("text/html");
     1.7 -            response.getOutputBuffer().write(data.getHtml());
     1.8 +            if (data != null) {
     1.9 +                response.getOutputBuffer().write(data.getHtml());
    1.10 +            }
    1.11              response.setStatus(HttpStatus.OK_200);
    1.12              return;
    1.13          }
     2.1 --- a/dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/app.js	Tue Feb 19 15:33:32 2013 +0100
     2.2 +++ b/dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/app.js	Tue Feb 19 15:59:27 2013 +0100
     2.3 @@ -112,7 +112,7 @@
     2.4  "     var arr = eval('(' + request.responseText + ')');\n" +
     2.5  "     return arr;\n" +
     2.6  "   }\n" +
     2.7 -"   var vm = new bck2brwsr(ldCls);\n" +
     2.8 +"   var vm = bck2brwsr(ldCls);\n" +
     2.9  "   vm.loadClass('${fqn}');\n" +
    2.10  " </script>\n" +
    2.11  "</body></html>";
     3.1 --- a/emul/compact/pom.xml	Tue Feb 19 15:33:32 2013 +0100
     3.2 +++ b/emul/compact/pom.xml	Tue Feb 19 15:59:27 2013 +0100
     3.3 @@ -10,7 +10,7 @@
     3.4    <groupId>org.apidesign.bck2brwsr</groupId>
     3.5    <artifactId>emul</artifactId>
     3.6    <version>0.3-SNAPSHOT</version>
     3.7 -  <name>Compact API Profile</name>
     3.8 +  <name>Bck2Brwsr API Profile</name>
     3.9    <url>http://maven.apache.org</url>
    3.10    <properties>
    3.11      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    3.12 @@ -20,6 +20,7 @@
    3.13        <groupId>${project.groupId}</groupId>
    3.14        <artifactId>emul.mini</artifactId>
    3.15        <version>${project.version}</version>
    3.16 +      <scope>provided</scope>
    3.17      </dependency>
    3.18      <dependency>
    3.19        <groupId>${project.groupId}</groupId>
    3.20 @@ -47,6 +48,25 @@
    3.21                   <target>1.7</target>
    3.22                </configuration>
    3.23            </plugin>
    3.24 +         <plugin>
    3.25 +            <artifactId>maven-assembly-plugin</artifactId>
    3.26 +                <version>2.4</version>
    3.27 +                <executions>
    3.28 +                    <execution>
    3.29 +                        <id>rt</id>
    3.30 +                        <phase>package</phase>
    3.31 +                        <goals>
    3.32 +                            <goal>single</goal>
    3.33 +                        </goals>
    3.34 +                        <configuration>
    3.35 +                            <descriptors>
    3.36 +                                <descriptor>src/main/assembly/rt.xml</descriptor>
    3.37 +                            </descriptors>
    3.38 +                            <finalName>bck2brwsr-${project.version}</finalName>
    3.39 +                        </configuration>
    3.40 +                    </execution>
    3.41 +                </executions>                
    3.42 +            </plugin>      
    3.43        </plugins>
    3.44    </build>
    3.45  </project>
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/emul/compact/src/main/assembly/rt.xml	Tue Feb 19 15:59:27 2013 +0100
     4.3 @@ -0,0 +1,26 @@
     4.4 +<?xml version="1.0"?>
     4.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">
     4.6 +  <id>rt</id>
     4.7 +  <formats>
     4.8 +    <format>jar</format>
     4.9 +  </formats>
    4.10 +  <includeBaseDirectory>false</includeBaseDirectory>
    4.11 +  <dependencySets>
    4.12 +    <dependencySet>
    4.13 +      <useProjectArtifact>true</useProjectArtifact>
    4.14 +      <unpack>true</unpack>
    4.15 +      <scope>provided</scope>
    4.16 +      <unpackOptions>
    4.17 +        <excludes>
    4.18 +          <exclude>META-INF/maven/**</exclude>
    4.19 +        </excludes>
    4.20 +      </unpackOptions>
    4.21 +    </dependencySet>
    4.22 +  </dependencySets>
    4.23 +  <fileSets>
    4.24 +    <fileSet>
    4.25 +      <directory>${project.build.outputDirectory}</directory>
    4.26 +      <outputDirectory>/</outputDirectory>
    4.27 +    </fileSet>
    4.28 +  </fileSets>
    4.29 +</assembly>
    4.30 \ No newline at end of file
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/emul/compact/src/main/java/java/io/BufferedOutputStream.java	Tue Feb 19 15:59:27 2013 +0100
     5.3 @@ -0,0 +1,143 @@
     5.4 +/*
     5.5 + * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
     5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     5.7 + *
     5.8 + * This code is free software; you can redistribute it and/or modify it
     5.9 + * under the terms of the GNU General Public License version 2 only, as
    5.10 + * published by the Free Software Foundation.  Oracle designates this
    5.11 + * particular file as subject to the "Classpath" exception as provided
    5.12 + * by Oracle in the LICENSE file that accompanied this code.
    5.13 + *
    5.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    5.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    5.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    5.17 + * version 2 for more details (a copy is included in the LICENSE file that
    5.18 + * accompanied this code).
    5.19 + *
    5.20 + * You should have received a copy of the GNU General Public License version
    5.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    5.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    5.23 + *
    5.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    5.25 + * or visit www.oracle.com if you need additional information or have any
    5.26 + * questions.
    5.27 + */
    5.28 +
    5.29 +package java.io;
    5.30 +
    5.31 +/**
    5.32 + * The class implements a buffered output stream. By setting up such
    5.33 + * an output stream, an application can write bytes to the underlying
    5.34 + * output stream without necessarily causing a call to the underlying
    5.35 + * system for each byte written.
    5.36 + *
    5.37 + * @author  Arthur van Hoff
    5.38 + * @since   JDK1.0
    5.39 + */
    5.40 +public
    5.41 +class BufferedOutputStream extends FilterOutputStream {
    5.42 +    /**
    5.43 +     * The internal buffer where data is stored.
    5.44 +     */
    5.45 +    protected byte buf[];
    5.46 +
    5.47 +    /**
    5.48 +     * The number of valid bytes in the buffer. This value is always
    5.49 +     * in the range <tt>0</tt> through <tt>buf.length</tt>; elements
    5.50 +     * <tt>buf[0]</tt> through <tt>buf[count-1]</tt> contain valid
    5.51 +     * byte data.
    5.52 +     */
    5.53 +    protected int count;
    5.54 +
    5.55 +    /**
    5.56 +     * Creates a new buffered output stream to write data to the
    5.57 +     * specified underlying output stream.
    5.58 +     *
    5.59 +     * @param   out   the underlying output stream.
    5.60 +     */
    5.61 +    public BufferedOutputStream(OutputStream out) {
    5.62 +        this(out, 8192);
    5.63 +    }
    5.64 +
    5.65 +    /**
    5.66 +     * Creates a new buffered output stream to write data to the
    5.67 +     * specified underlying output stream with the specified buffer
    5.68 +     * size.
    5.69 +     *
    5.70 +     * @param   out    the underlying output stream.
    5.71 +     * @param   size   the buffer size.
    5.72 +     * @exception IllegalArgumentException if size &lt;= 0.
    5.73 +     */
    5.74 +    public BufferedOutputStream(OutputStream out, int size) {
    5.75 +        super(out);
    5.76 +        if (size <= 0) {
    5.77 +            throw new IllegalArgumentException("Buffer size <= 0");
    5.78 +        }
    5.79 +        buf = new byte[size];
    5.80 +    }
    5.81 +
    5.82 +    /** Flush the internal buffer */
    5.83 +    private void flushBuffer() throws IOException {
    5.84 +        if (count > 0) {
    5.85 +            out.write(buf, 0, count);
    5.86 +            count = 0;
    5.87 +        }
    5.88 +    }
    5.89 +
    5.90 +    /**
    5.91 +     * Writes the specified byte to this buffered output stream.
    5.92 +     *
    5.93 +     * @param      b   the byte to be written.
    5.94 +     * @exception  IOException  if an I/O error occurs.
    5.95 +     */
    5.96 +    public synchronized void write(int b) throws IOException {
    5.97 +        if (count >= buf.length) {
    5.98 +            flushBuffer();
    5.99 +        }
   5.100 +        buf[count++] = (byte)b;
   5.101 +    }
   5.102 +
   5.103 +    /**
   5.104 +     * Writes <code>len</code> bytes from the specified byte array
   5.105 +     * starting at offset <code>off</code> to this buffered output stream.
   5.106 +     *
   5.107 +     * <p> Ordinarily this method stores bytes from the given array into this
   5.108 +     * stream's buffer, flushing the buffer to the underlying output stream as
   5.109 +     * needed.  If the requested length is at least as large as this stream's
   5.110 +     * buffer, however, then this method will flush the buffer and write the
   5.111 +     * bytes directly to the underlying output stream.  Thus redundant
   5.112 +     * <code>BufferedOutputStream</code>s will not copy data unnecessarily.
   5.113 +     *
   5.114 +     * @param      b     the data.
   5.115 +     * @param      off   the start offset in the data.
   5.116 +     * @param      len   the number of bytes to write.
   5.117 +     * @exception  IOException  if an I/O error occurs.
   5.118 +     */
   5.119 +    public synchronized void write(byte b[], int off, int len) throws IOException {
   5.120 +        if (len >= buf.length) {
   5.121 +            /* If the request length exceeds the size of the output buffer,
   5.122 +               flush the output buffer and then write the data directly.
   5.123 +               In this way buffered streams will cascade harmlessly. */
   5.124 +            flushBuffer();
   5.125 +            out.write(b, off, len);
   5.126 +            return;
   5.127 +        }
   5.128 +        if (len > buf.length - count) {
   5.129 +            flushBuffer();
   5.130 +        }
   5.131 +        System.arraycopy(b, off, buf, count, len);
   5.132 +        count += len;
   5.133 +    }
   5.134 +
   5.135 +    /**
   5.136 +     * Flushes this buffered output stream. This forces any buffered
   5.137 +     * output bytes to be written out to the underlying output stream.
   5.138 +     *
   5.139 +     * @exception  IOException  if an I/O error occurs.
   5.140 +     * @see        java.io.FilterOutputStream#out
   5.141 +     */
   5.142 +    public synchronized void flush() throws IOException {
   5.143 +        flushBuffer();
   5.144 +        out.flush();
   5.145 +    }
   5.146 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/emul/compact/src/main/java/java/io/ByteArrayOutputStream.java	Tue Feb 19 15:59:27 2013 +0100
     6.3 @@ -0,0 +1,272 @@
     6.4 +/*
     6.5 + * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
     6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     6.7 + *
     6.8 + * This code is free software; you can redistribute it and/or modify it
     6.9 + * under the terms of the GNU General Public License version 2 only, as
    6.10 + * published by the Free Software Foundation.  Oracle designates this
    6.11 + * particular file as subject to the "Classpath" exception as provided
    6.12 + * by Oracle in the LICENSE file that accompanied this code.
    6.13 + *
    6.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    6.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    6.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    6.17 + * version 2 for more details (a copy is included in the LICENSE file that
    6.18 + * accompanied this code).
    6.19 + *
    6.20 + * You should have received a copy of the GNU General Public License version
    6.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    6.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    6.23 + *
    6.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    6.25 + * or visit www.oracle.com if you need additional information or have any
    6.26 + * questions.
    6.27 + */
    6.28 +
    6.29 +package java.io;
    6.30 +
    6.31 +import java.util.Arrays;
    6.32 +
    6.33 +/**
    6.34 + * This class implements an output stream in which the data is
    6.35 + * written into a byte array. The buffer automatically grows as data
    6.36 + * is written to it.
    6.37 + * The data can be retrieved using <code>toByteArray()</code> and
    6.38 + * <code>toString()</code>.
    6.39 + * <p>
    6.40 + * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in
    6.41 + * this class can be called after the stream has been closed without
    6.42 + * generating an <tt>IOException</tt>.
    6.43 + *
    6.44 + * @author  Arthur van Hoff
    6.45 + * @since   JDK1.0
    6.46 + */
    6.47 +
    6.48 +public class ByteArrayOutputStream extends OutputStream {
    6.49 +
    6.50 +    /**
    6.51 +     * The buffer where data is stored.
    6.52 +     */
    6.53 +    protected byte buf[];
    6.54 +
    6.55 +    /**
    6.56 +     * The number of valid bytes in the buffer.
    6.57 +     */
    6.58 +    protected int count;
    6.59 +
    6.60 +    /**
    6.61 +     * Creates a new byte array output stream. The buffer capacity is
    6.62 +     * initially 32 bytes, though its size increases if necessary.
    6.63 +     */
    6.64 +    public ByteArrayOutputStream() {
    6.65 +        this(32);
    6.66 +    }
    6.67 +
    6.68 +    /**
    6.69 +     * Creates a new byte array output stream, with a buffer capacity of
    6.70 +     * the specified size, in bytes.
    6.71 +     *
    6.72 +     * @param   size   the initial size.
    6.73 +     * @exception  IllegalArgumentException if size is negative.
    6.74 +     */
    6.75 +    public ByteArrayOutputStream(int size) {
    6.76 +        if (size < 0) {
    6.77 +            throw new IllegalArgumentException("Negative initial size: "
    6.78 +                                               + size);
    6.79 +        }
    6.80 +        buf = new byte[size];
    6.81 +    }
    6.82 +
    6.83 +    /**
    6.84 +     * Increases the capacity if necessary to ensure that it can hold
    6.85 +     * at least the number of elements specified by the minimum
    6.86 +     * capacity argument.
    6.87 +     *
    6.88 +     * @param minCapacity the desired minimum capacity
    6.89 +     * @throws OutOfMemoryError if {@code minCapacity < 0}.  This is
    6.90 +     * interpreted as a request for the unsatisfiably large capacity
    6.91 +     * {@code (long) Integer.MAX_VALUE + (minCapacity - Integer.MAX_VALUE)}.
    6.92 +     */
    6.93 +    private void ensureCapacity(int minCapacity) {
    6.94 +        // overflow-conscious code
    6.95 +        if (minCapacity - buf.length > 0)
    6.96 +            grow(minCapacity);
    6.97 +    }
    6.98 +
    6.99 +    /**
   6.100 +     * Increases the capacity to ensure that it can hold at least the
   6.101 +     * number of elements specified by the minimum capacity argument.
   6.102 +     *
   6.103 +     * @param minCapacity the desired minimum capacity
   6.104 +     */
   6.105 +    private void grow(int minCapacity) {
   6.106 +        // overflow-conscious code
   6.107 +        int oldCapacity = buf.length;
   6.108 +        int newCapacity = oldCapacity << 1;
   6.109 +        if (newCapacity - minCapacity < 0)
   6.110 +            newCapacity = minCapacity;
   6.111 +        if (newCapacity < 0) {
   6.112 +            if (minCapacity < 0) // overflow
   6.113 +                throw new OutOfMemoryError();
   6.114 +            newCapacity = Integer.MAX_VALUE;
   6.115 +        }
   6.116 +        buf = Arrays.copyOf(buf, newCapacity);
   6.117 +    }
   6.118 +
   6.119 +    /**
   6.120 +     * Writes the specified byte to this byte array output stream.
   6.121 +     *
   6.122 +     * @param   b   the byte to be written.
   6.123 +     */
   6.124 +    public synchronized void write(int b) {
   6.125 +        ensureCapacity(count + 1);
   6.126 +        buf[count] = (byte) b;
   6.127 +        count += 1;
   6.128 +    }
   6.129 +
   6.130 +    /**
   6.131 +     * Writes <code>len</code> bytes from the specified byte array
   6.132 +     * starting at offset <code>off</code> to this byte array output stream.
   6.133 +     *
   6.134 +     * @param   b     the data.
   6.135 +     * @param   off   the start offset in the data.
   6.136 +     * @param   len   the number of bytes to write.
   6.137 +     */
   6.138 +    public synchronized void write(byte b[], int off, int len) {
   6.139 +        if ((off < 0) || (off > b.length) || (len < 0) ||
   6.140 +            ((off + len) - b.length > 0)) {
   6.141 +            throw new IndexOutOfBoundsException();
   6.142 +        }
   6.143 +        ensureCapacity(count + len);
   6.144 +        System.arraycopy(b, off, buf, count, len);
   6.145 +        count += len;
   6.146 +    }
   6.147 +
   6.148 +    /**
   6.149 +     * Writes the complete contents of this byte array output stream to
   6.150 +     * the specified output stream argument, as if by calling the output
   6.151 +     * stream's write method using <code>out.write(buf, 0, count)</code>.
   6.152 +     *
   6.153 +     * @param      out   the output stream to which to write the data.
   6.154 +     * @exception  IOException  if an I/O error occurs.
   6.155 +     */
   6.156 +    public synchronized void writeTo(OutputStream out) throws IOException {
   6.157 +        out.write(buf, 0, count);
   6.158 +    }
   6.159 +
   6.160 +    /**
   6.161 +     * Resets the <code>count</code> field of this byte array output
   6.162 +     * stream to zero, so that all currently accumulated output in the
   6.163 +     * output stream is discarded. The output stream can be used again,
   6.164 +     * reusing the already allocated buffer space.
   6.165 +     *
   6.166 +     * @see     java.io.ByteArrayInputStream#count
   6.167 +     */
   6.168 +    public synchronized void reset() {
   6.169 +        count = 0;
   6.170 +    }
   6.171 +
   6.172 +    /**
   6.173 +     * Creates a newly allocated byte array. Its size is the current
   6.174 +     * size of this output stream and the valid contents of the buffer
   6.175 +     * have been copied into it.
   6.176 +     *
   6.177 +     * @return  the current contents of this output stream, as a byte array.
   6.178 +     * @see     java.io.ByteArrayOutputStream#size()
   6.179 +     */
   6.180 +    public synchronized byte toByteArray()[] {
   6.181 +        return Arrays.copyOf(buf, count);
   6.182 +    }
   6.183 +
   6.184 +    /**
   6.185 +     * Returns the current size of the buffer.
   6.186 +     *
   6.187 +     * @return  the value of the <code>count</code> field, which is the number
   6.188 +     *          of valid bytes in this output stream.
   6.189 +     * @see     java.io.ByteArrayOutputStream#count
   6.190 +     */
   6.191 +    public synchronized int size() {
   6.192 +        return count;
   6.193 +    }
   6.194 +
   6.195 +    /**
   6.196 +     * Converts the buffer's contents into a string decoding bytes using the
   6.197 +     * platform's default character set. The length of the new <tt>String</tt>
   6.198 +     * is a function of the character set, and hence may not be equal to the
   6.199 +     * size of the buffer.
   6.200 +     *
   6.201 +     * <p> This method always replaces malformed-input and unmappable-character
   6.202 +     * sequences with the default replacement string for the platform's
   6.203 +     * default character set. The {@linkplain java.nio.charset.CharsetDecoder}
   6.204 +     * class should be used when more control over the decoding process is
   6.205 +     * required.
   6.206 +     *
   6.207 +     * @return String decoded from the buffer's contents.
   6.208 +     * @since  JDK1.1
   6.209 +     */
   6.210 +    public synchronized String toString() {
   6.211 +        return new String(buf, 0, count);
   6.212 +    }
   6.213 +
   6.214 +    /**
   6.215 +     * Converts the buffer's contents into a string by decoding the bytes using
   6.216 +     * the specified {@link java.nio.charset.Charset charsetName}. The length of
   6.217 +     * the new <tt>String</tt> is a function of the charset, and hence may not be
   6.218 +     * equal to the length of the byte array.
   6.219 +     *
   6.220 +     * <p> This method always replaces malformed-input and unmappable-character
   6.221 +     * sequences with this charset's default replacement string. The {@link
   6.222 +     * java.nio.charset.CharsetDecoder} class should be used when more control
   6.223 +     * over the decoding process is required.
   6.224 +     *
   6.225 +     * @param  charsetName  the name of a supported
   6.226 +     *              {@linkplain java.nio.charset.Charset </code>charset<code>}
   6.227 +     * @return String decoded from the buffer's contents.
   6.228 +     * @exception  UnsupportedEncodingException
   6.229 +     *             If the named charset is not supported
   6.230 +     * @since   JDK1.1
   6.231 +     */
   6.232 +    public synchronized String toString(String charsetName)
   6.233 +        throws UnsupportedEncodingException
   6.234 +    {
   6.235 +        return new String(buf, 0, count, charsetName);
   6.236 +    }
   6.237 +
   6.238 +    /**
   6.239 +     * Creates a newly allocated string. Its size is the current size of
   6.240 +     * the output stream and the valid contents of the buffer have been
   6.241 +     * copied into it. Each character <i>c</i> in the resulting string is
   6.242 +     * constructed from the corresponding element <i>b</i> in the byte
   6.243 +     * array such that:
   6.244 +     * <blockquote><pre>
   6.245 +     *     c == (char)(((hibyte &amp; 0xff) &lt;&lt; 8) | (b &amp; 0xff))
   6.246 +     * </pre></blockquote>
   6.247 +     *
   6.248 +     * @deprecated This method does not properly convert bytes into characters.
   6.249 +     * As of JDK&nbsp;1.1, the preferred way to do this is via the
   6.250 +     * <code>toString(String enc)</code> method, which takes an encoding-name
   6.251 +     * argument, or the <code>toString()</code> method, which uses the
   6.252 +     * platform's default character encoding.
   6.253 +     *
   6.254 +     * @param      hibyte    the high byte of each resulting Unicode character.
   6.255 +     * @return     the current contents of the output stream, as a string.
   6.256 +     * @see        java.io.ByteArrayOutputStream#size()
   6.257 +     * @see        java.io.ByteArrayOutputStream#toString(String)
   6.258 +     * @see        java.io.ByteArrayOutputStream#toString()
   6.259 +     */
   6.260 +    @Deprecated
   6.261 +    public synchronized String toString(int hibyte) {
   6.262 +        return new String(buf, hibyte, 0, count);
   6.263 +    }
   6.264 +
   6.265 +    /**
   6.266 +     * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in
   6.267 +     * this class can be called after the stream has been closed without
   6.268 +     * generating an <tt>IOException</tt>.
   6.269 +     * <p>
   6.270 +     *
   6.271 +     */
   6.272 +    public void close() throws IOException {
   6.273 +    }
   6.274 +
   6.275 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/emul/compact/src/main/java/java/util/Objects.java	Tue Feb 19 15:59:27 2013 +0100
     7.3 @@ -0,0 +1,229 @@
     7.4 +/*
     7.5 + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
     7.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     7.7 + *
     7.8 + * This code is free software; you can redistribute it and/or modify it
     7.9 + * under the terms of the GNU General Public License version 2 only, as
    7.10 + * published by the Free Software Foundation.  Oracle designates this
    7.11 + * particular file as subject to the "Classpath" exception as provided
    7.12 + * by Oracle in the LICENSE file that accompanied this code.
    7.13 + *
    7.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    7.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    7.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    7.17 + * version 2 for more details (a copy is included in the LICENSE file that
    7.18 + * accompanied this code).
    7.19 + *
    7.20 + * You should have received a copy of the GNU General Public License version
    7.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    7.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    7.23 + *
    7.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    7.25 + * or visit www.oracle.com if you need additional information or have any
    7.26 + * questions.
    7.27 + */
    7.28 +
    7.29 +package java.util;
    7.30 +
    7.31 +/**
    7.32 + * This class consists of {@code static} utility methods for operating
    7.33 + * on objects.  These utilities include {@code null}-safe or {@code
    7.34 + * null}-tolerant methods for computing the hash code of an object,
    7.35 + * returning a string for an object, and comparing two objects.
    7.36 + *
    7.37 + * @since 1.7
    7.38 + */
    7.39 +public final class Objects {
    7.40 +    private Objects() {
    7.41 +        throw new AssertionError("No java.util.Objects instances for you!");
    7.42 +    }
    7.43 +
    7.44 +    /**
    7.45 +     * Returns {@code true} if the arguments are equal to each other
    7.46 +     * and {@code false} otherwise.
    7.47 +     * Consequently, if both arguments are {@code null}, {@code true}
    7.48 +     * is returned and if exactly one argument is {@code null}, {@code
    7.49 +     * false} is returned.  Otherwise, equality is determined by using
    7.50 +     * the {@link Object#equals equals} method of the first
    7.51 +     * argument.
    7.52 +     *
    7.53 +     * @param a an object
    7.54 +     * @param b an object to be compared with {@code a} for equality
    7.55 +     * @return {@code true} if the arguments are equal to each other
    7.56 +     * and {@code false} otherwise
    7.57 +     * @see Object#equals(Object)
    7.58 +     */
    7.59 +    public static boolean equals(Object a, Object b) {
    7.60 +        return (a == b) || (a != null && a.equals(b));
    7.61 +    }
    7.62 +
    7.63 +   /**
    7.64 +    * Returns {@code true} if the arguments are deeply equal to each other
    7.65 +    * and {@code false} otherwise.
    7.66 +    *
    7.67 +    * Two {@code null} values are deeply equal.  If both arguments are
    7.68 +    * arrays, the algorithm in {@link Arrays#deepEquals(Object[],
    7.69 +    * Object[]) Arrays.deepEquals} is used to determine equality.
    7.70 +    * Otherwise, equality is determined by using the {@link
    7.71 +    * Object#equals equals} method of the first argument.
    7.72 +    *
    7.73 +    * @param a an object
    7.74 +    * @param b an object to be compared with {@code a} for deep equality
    7.75 +    * @return {@code true} if the arguments are deeply equal to each other
    7.76 +    * and {@code false} otherwise
    7.77 +    * @see Arrays#deepEquals(Object[], Object[])
    7.78 +    * @see Objects#equals(Object, Object)
    7.79 +    */
    7.80 +    public static boolean deepEquals(Object a, Object b) {
    7.81 +        if (a == b)
    7.82 +            return true;
    7.83 +        else if (a == null || b == null)
    7.84 +            return false;
    7.85 +        else
    7.86 +            return Arrays.deepEquals0(a, b);
    7.87 +    }
    7.88 +
    7.89 +    /**
    7.90 +     * Returns the hash code of a non-{@code null} argument and 0 for
    7.91 +     * a {@code null} argument.
    7.92 +     *
    7.93 +     * @param o an object
    7.94 +     * @return the hash code of a non-{@code null} argument and 0 for
    7.95 +     * a {@code null} argument
    7.96 +     * @see Object#hashCode
    7.97 +     */
    7.98 +    public static int hashCode(Object o) {
    7.99 +        return o != null ? o.hashCode() : 0;
   7.100 +    }
   7.101 +
   7.102 +   /**
   7.103 +    * Generates a hash code for a sequence of input values. The hash
   7.104 +    * code is generated as if all the input values were placed into an
   7.105 +    * array, and that array were hashed by calling {@link
   7.106 +    * Arrays#hashCode(Object[])}.
   7.107 +    *
   7.108 +    * <p>This method is useful for implementing {@link
   7.109 +    * Object#hashCode()} on objects containing multiple fields. For
   7.110 +    * example, if an object that has three fields, {@code x}, {@code
   7.111 +    * y}, and {@code z}, one could write:
   7.112 +    *
   7.113 +    * <blockquote><pre>
   7.114 +    * &#064;Override public int hashCode() {
   7.115 +    *     return Objects.hash(x, y, z);
   7.116 +    * }
   7.117 +    * </pre></blockquote>
   7.118 +    *
   7.119 +    * <b>Warning: When a single object reference is supplied, the returned
   7.120 +    * value does not equal the hash code of that object reference.</b> This
   7.121 +    * value can be computed by calling {@link #hashCode(Object)}.
   7.122 +    *
   7.123 +    * @param values the values to be hashed
   7.124 +    * @return a hash value of the sequence of input values
   7.125 +    * @see Arrays#hashCode(Object[])
   7.126 +    * @see List#hashCode
   7.127 +    */
   7.128 +    public static int hash(Object... values) {
   7.129 +        return Arrays.hashCode(values);
   7.130 +    }
   7.131 +
   7.132 +    /**
   7.133 +     * Returns the result of calling {@code toString} for a non-{@code
   7.134 +     * null} argument and {@code "null"} for a {@code null} argument.
   7.135 +     *
   7.136 +     * @param o an object
   7.137 +     * @return the result of calling {@code toString} for a non-{@code
   7.138 +     * null} argument and {@code "null"} for a {@code null} argument
   7.139 +     * @see Object#toString
   7.140 +     * @see String#valueOf(Object)
   7.141 +     */
   7.142 +    public static String toString(Object o) {
   7.143 +        return String.valueOf(o);
   7.144 +    }
   7.145 +
   7.146 +    /**
   7.147 +     * Returns the result of calling {@code toString} on the first
   7.148 +     * argument if the first argument is not {@code null} and returns
   7.149 +     * the second argument otherwise.
   7.150 +     *
   7.151 +     * @param o an object
   7.152 +     * @param nullDefault string to return if the first argument is
   7.153 +     *        {@code null}
   7.154 +     * @return the result of calling {@code toString} on the first
   7.155 +     * argument if it is not {@code null} and the second argument
   7.156 +     * otherwise.
   7.157 +     * @see Objects#toString(Object)
   7.158 +     */
   7.159 +    public static String toString(Object o, String nullDefault) {
   7.160 +        return (o != null) ? o.toString() : nullDefault;
   7.161 +    }
   7.162 +
   7.163 +    /**
   7.164 +     * Returns 0 if the arguments are identical and {@code
   7.165 +     * c.compare(a, b)} otherwise.
   7.166 +     * Consequently, if both arguments are {@code null} 0
   7.167 +     * is returned.
   7.168 +     *
   7.169 +     * <p>Note that if one of the arguments is {@code null}, a {@code
   7.170 +     * NullPointerException} may or may not be thrown depending on
   7.171 +     * what ordering policy, if any, the {@link Comparator Comparator}
   7.172 +     * chooses to have for {@code null} values.
   7.173 +     *
   7.174 +     * @param <T> the type of the objects being compared
   7.175 +     * @param a an object
   7.176 +     * @param b an object to be compared with {@code a}
   7.177 +     * @param c the {@code Comparator} to compare the first two arguments
   7.178 +     * @return 0 if the arguments are identical and {@code
   7.179 +     * c.compare(a, b)} otherwise.
   7.180 +     * @see Comparable
   7.181 +     * @see Comparator
   7.182 +     */
   7.183 +    public static <T> int compare(T a, T b, Comparator<? super T> c) {
   7.184 +        return (a == b) ? 0 :  c.compare(a, b);
   7.185 +    }
   7.186 +
   7.187 +    /**
   7.188 +     * Checks that the specified object reference is not {@code null}. This
   7.189 +     * method is designed primarily for doing parameter validation in methods
   7.190 +     * and constructors, as demonstrated below:
   7.191 +     * <blockquote><pre>
   7.192 +     * public Foo(Bar bar) {
   7.193 +     *     this.bar = Objects.requireNonNull(bar);
   7.194 +     * }
   7.195 +     * </pre></blockquote>
   7.196 +     *
   7.197 +     * @param obj the object reference to check for nullity
   7.198 +     * @param <T> the type of the reference
   7.199 +     * @return {@code obj} if not {@code null}
   7.200 +     * @throws NullPointerException if {@code obj} is {@code null}
   7.201 +     */
   7.202 +    public static <T> T requireNonNull(T obj) {
   7.203 +        if (obj == null)
   7.204 +            throw new NullPointerException();
   7.205 +        return obj;
   7.206 +    }
   7.207 +
   7.208 +    /**
   7.209 +     * Checks that the specified object reference is not {@code null} and
   7.210 +     * throws a customized {@link NullPointerException} if it is. This method
   7.211 +     * is designed primarily for doing parameter validation in methods and
   7.212 +     * constructors with multiple parameters, as demonstrated below:
   7.213 +     * <blockquote><pre>
   7.214 +     * public Foo(Bar bar, Baz baz) {
   7.215 +     *     this.bar = Objects.requireNonNull(bar, "bar must not be null");
   7.216 +     *     this.baz = Objects.requireNonNull(baz, "baz must not be null");
   7.217 +     * }
   7.218 +     * </pre></blockquote>
   7.219 +     *
   7.220 +     * @param obj     the object reference to check for nullity
   7.221 +     * @param message detail message to be used in the event that a {@code
   7.222 +     *                NullPointerException} is thrown
   7.223 +     * @param <T> the type of the reference
   7.224 +     * @return {@code obj} if not {@code null}
   7.225 +     * @throws NullPointerException if {@code obj} is {@code null}
   7.226 +     */
   7.227 +    public static <T> T requireNonNull(T obj, String message) {
   7.228 +        if (obj == null)
   7.229 +            throw new NullPointerException(message);
   7.230 +        return obj;
   7.231 +    }
   7.232 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ZipArchive.java	Tue Feb 19 15:59:27 2013 +0100
     8.3 @@ -0,0 +1,154 @@
     8.4 +/**
     8.5 + * Back 2 Browser Bytecode Translator
     8.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     8.7 + *
     8.8 + * This program is free software: you can redistribute it and/or modify
     8.9 + * it under the terms of the GNU General Public License as published by
    8.10 + * the Free Software Foundation, version 2 of the License.
    8.11 + *
    8.12 + * This program is distributed in the hope that it will be useful,
    8.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    8.15 + * GNU General Public License for more details.
    8.16 + *
    8.17 + * You should have received a copy of the GNU General Public License
    8.18 + * along with this program. Look for COPYING file in the top folder.
    8.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    8.20 + */
    8.21 +package org.apidesign.bck2brwsr.compact.tck;
    8.22 +
    8.23 +import java.io.ByteArrayOutputStream;
    8.24 +import java.io.IOException;
    8.25 +import java.io.InputStream;
    8.26 +import java.util.Arrays;
    8.27 +import java.util.LinkedHashMap;
    8.28 +import java.util.Map;
    8.29 +import java.util.Objects;
    8.30 +import java.util.zip.ZipEntry;
    8.31 +import org.apidesign.bck2brwsr.emul.zip.ZipInputStream;
    8.32 +
    8.33 +/**
    8.34 + *
    8.35 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    8.36 + */
    8.37 +final class ZipArchive {
    8.38 +    private final Map<String, byte[]> entries = new LinkedHashMap<>();
    8.39 +
    8.40 +    public static ZipArchive createZip(InputStream is) throws IOException {
    8.41 +        ZipArchive a = new ZipArchive();
    8.42 +        readZip(is, a);
    8.43 +        return a;
    8.44 +    }
    8.45 +
    8.46 +    public static ZipArchive createReal(InputStream is) throws IOException {
    8.47 +        ZipArchive a = new ZipArchive();
    8.48 +        realZip(is, a);
    8.49 +        return a;
    8.50 +    }
    8.51 +
    8.52 +    /**
    8.53 +     * Registers entry name and data
    8.54 +     */
    8.55 +    final void register(String entry, InputStream is) throws IOException {
    8.56 +        ByteArrayOutputStream os = new ByteArrayOutputStream();
    8.57 +        for (;;) {
    8.58 +            int ch = is.read();
    8.59 +            if (ch == -1) {
    8.60 +                break;
    8.61 +            }
    8.62 +            os.write(ch);
    8.63 +        }
    8.64 +        os.close();
    8.65 +        entries.put(entry, os.toByteArray());
    8.66 +    }
    8.67 +
    8.68 +    @Override
    8.69 +    public int hashCode() {
    8.70 +        return entries.hashCode();
    8.71 +    }
    8.72 +
    8.73 +    @Override
    8.74 +    public boolean equals(Object obj) {
    8.75 +        if (obj == null) {
    8.76 +            return false;
    8.77 +        }
    8.78 +        if (getClass() != obj.getClass()) {
    8.79 +            return false;
    8.80 +        }
    8.81 +        final ZipArchive other = (ZipArchive) obj;
    8.82 +        if (!Objects.deepEquals(this.entries, other.entries)) {
    8.83 +            return false;
    8.84 +        }
    8.85 +        return true;
    8.86 +    }
    8.87 +
    8.88 +    @Override
    8.89 +    public String toString() {
    8.90 +        StringBuilder sb = new StringBuilder();
    8.91 +        for (Map.Entry<String, byte[]> en : entries.entrySet()) {
    8.92 +            String string = en.getKey();
    8.93 +            byte[] bs = en.getValue();
    8.94 +            sb.append(string).append(" = ").append(Arrays.toString(bs)).append("\n");
    8.95 +        }
    8.96 +        return sb.toString();
    8.97 +    }
    8.98 +
    8.99 +    public void assertEquals(ZipArchive zip, String msg) {
   8.100 +        boolean ok = true;
   8.101 +        StringBuilder sb = new StringBuilder();
   8.102 +        sb.append(msg);
   8.103 +        for (Map.Entry<String, byte[]> en : entries.entrySet()) {
   8.104 +            String string = en.getKey();
   8.105 +            byte[] bs = en.getValue();
   8.106 +            byte[] other = zip.entries.get(string);
   8.107 +            sb.append("\n");
   8.108 +            if (other == null) {
   8.109 +                sb.append("EXTRA ").append(string).append(" = ").append(Arrays.toString(bs));
   8.110 +                ok = false;
   8.111 +                continue;
   8.112 +            }
   8.113 +            if (Arrays.equals(bs, other)) {
   8.114 +                sb.append("OK    ").append(string);
   8.115 +                continue;
   8.116 +            } else {
   8.117 +                sb.append("DIFF  ").append(string).append(" = ").append(Arrays.toString(bs)).append("\n");
   8.118 +                sb.append("    TO").append(string).append(" = ").append(Arrays.toString(other)).append("\n");
   8.119 +                ok = false;
   8.120 +                continue;
   8.121 +            }
   8.122 +        }
   8.123 +        for (Map.Entry<String, byte[]> entry : zip.entries.entrySet()) {
   8.124 +            String string = entry.getKey();
   8.125 +            if (entries.get(string) == null) {
   8.126 +                sb.append("MISS  ").append(string).append(" = ").append(Arrays.toString(entry.getValue()));
   8.127 +                ok = false;
   8.128 +            }
   8.129 +        }
   8.130 +        if (!ok) {
   8.131 +            assert false : sb.toString();
   8.132 +        }
   8.133 +    }
   8.134 +
   8.135 +    public static void readZip(InputStream is, ZipArchive data) throws IOException {
   8.136 +        ZipInputStream zip = new org.apidesign.bck2brwsr.emul.zip.ZipInputStream(is);
   8.137 +        for (;;) {
   8.138 +            ZipEntry en = zip.getNextEntry();
   8.139 +            if (en == null) {
   8.140 +                return;
   8.141 +            }
   8.142 +            data.register(en.getName(), zip);
   8.143 +        }
   8.144 +    }
   8.145 +
   8.146 +    public static void realZip(InputStream is, ZipArchive data) throws IOException {
   8.147 +        java.util.zip.ZipInputStream zip = new java.util.zip.ZipInputStream(is);
   8.148 +        for (;;) {
   8.149 +            ZipEntry en = zip.getNextEntry();
   8.150 +            if (en == null) {
   8.151 +                return;
   8.152 +            }
   8.153 +            data.register(en.getName(), zip);
   8.154 +        }
   8.155 +    }
   8.156 +    
   8.157 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ZipCompatibilityTest.java	Tue Feb 19 15:59:27 2013 +0100
     9.3 @@ -0,0 +1,42 @@
     9.4 +/**
     9.5 + * Back 2 Browser Bytecode Translator
     9.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     9.7 + *
     9.8 + * This program is free software: you can redistribute it and/or modify
     9.9 + * it under the terms of the GNU General Public License as published by
    9.10 + * the Free Software Foundation, version 2 of the License.
    9.11 + *
    9.12 + * This program is distributed in the hope that it will be useful,
    9.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    9.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    9.15 + * GNU General Public License for more details.
    9.16 + *
    9.17 + * You should have received a copy of the GNU General Public License
    9.18 + * along with this program. Look for COPYING file in the top folder.
    9.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    9.20 + */
    9.21 +package org.apidesign.bck2brwsr.compact.tck;
    9.22 +
    9.23 +import java.io.IOException;
    9.24 +import java.io.InputStream;
    9.25 +import org.apidesign.bck2brwsr.vmtest.Compare;
    9.26 +import org.apidesign.bck2brwsr.vmtest.VMTest;
    9.27 +import org.testng.annotations.Factory;
    9.28 +
    9.29 +/**
    9.30 + *
    9.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    9.32 + */
    9.33 +public class ZipCompatibilityTest {
    9.34 +    @Compare
    9.35 +    public String testDemoStaticCalculator() throws IOException {
    9.36 +        InputStream is = getClass().getResourceAsStream("demo.static.calculator-0.3-SNAPSHOT.jar");
    9.37 +        ZipArchive zip = ZipArchive.createZip(is);
    9.38 +        return zip.toString();
    9.39 +    }
    9.40 +    
    9.41 +    @Factory
    9.42 +    public static Object[] create() {
    9.43 +        return VMTest.create(ZipCompatibilityTest.class);
    9.44 +    }
    9.45 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ZipVsJzLibTest.java	Tue Feb 19 15:59:27 2013 +0100
    10.3 @@ -0,0 +1,39 @@
    10.4 +/**
    10.5 + * Back 2 Browser Bytecode Translator
    10.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    10.7 + *
    10.8 + * This program is free software: you can redistribute it and/or modify
    10.9 + * it under the terms of the GNU General Public License as published by
   10.10 + * the Free Software Foundation, version 2 of the License.
   10.11 + *
   10.12 + * This program is distributed in the hope that it will be useful,
   10.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   10.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   10.15 + * GNU General Public License for more details.
   10.16 + *
   10.17 + * You should have received a copy of the GNU General Public License
   10.18 + * along with this program. Look for COPYING file in the top folder.
   10.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   10.20 + */
   10.21 +package org.apidesign.bck2brwsr.compact.tck;
   10.22 +
   10.23 +import java.io.IOException;
   10.24 +import java.io.InputStream;
   10.25 +import org.testng.annotations.Test;
   10.26 +
   10.27 +/**
   10.28 + *
   10.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   10.30 + */
   10.31 +public class ZipVsJzLibTest {
   10.32 +    @Test public void r() throws IOException {
   10.33 +        InputStream is = getClass().getResourceAsStream("demo.static.calculator-0.3-SNAPSHOT.jar");
   10.34 +        ZipArchive zip = ZipArchive.createZip(is);
   10.35 +        
   10.36 +        is = getClass().getResourceAsStream("demo.static.calculator-0.3-SNAPSHOT.jar");
   10.37 +        ZipArchive real = ZipArchive.createReal(is);
   10.38 +        
   10.39 +        real.assertEquals(zip, "Are they the same?");
   10.40 +    }
   10.41 +    
   10.42 +}
    11.1 Binary file emul/compact/src/test/resources/org/apidesign/bck2brwsr/compact/tck/demo.static.calculator-0.3-SNAPSHOT.jar has changed
    12.1 --- a/emul/mini/pom.xml	Tue Feb 19 15:33:32 2013 +0100
    12.2 +++ b/emul/mini/pom.xml	Tue Feb 19 15:59:27 2013 +0100
    12.3 @@ -22,6 +22,12 @@
    12.4        <version>0.3-SNAPSHOT</version>
    12.5        <type>jar</type>
    12.6      </dependency>
    12.7 +    <dependency>
    12.8 +      <groupId>org.testng</groupId>
    12.9 +      <artifactId>testng</artifactId>
   12.10 +      <version>6.5.2</version>
   12.11 +      <scope>test</scope>
   12.12 +    </dependency>
   12.13    </dependencies>
   12.14    <build>
   12.15        <plugins>
    13.1 --- a/emul/mini/src/main/java/java/lang/Class.java	Tue Feb 19 15:33:32 2013 +0100
    13.2 +++ b/emul/mini/src/main/java/java/lang/Class.java	Tue Feb 19 15:59:27 2013 +0100
    13.3 @@ -231,12 +231,14 @@
    13.4      }
    13.5      
    13.6      @JavaScriptBody(args = {"n", "c" }, body =
    13.7 -        "if (vm[c]) return vm[c].$class;\n"
    13.8 -      + "if (vm.loadClass) {\n"
    13.9 -      + "  vm.loadClass(n);\n"
   13.10 -      + "  if (vm[c]) return vm[c].$class;\n"
   13.11 +        "if (!vm[c]) {\n"
   13.12 +      + "  if (vm.loadClass) {\n"
   13.13 +      + "    vm.loadClass(n);\n"
   13.14 +      + "  }\n"
   13.15 +      + "  if (!vm[c]) return null;\n"
   13.16        + "}\n"
   13.17 -      + "return null;"
   13.18 +      + "vm[c](false);"
   13.19 +      + "return vm[c].$class;"
   13.20      )
   13.21      private static native Class<?> loadCls(String n, String c);
   13.22  
    14.1 --- a/emul/mini/src/main/java/java/lang/Object.java	Tue Feb 19 15:33:32 2013 +0100
    14.2 +++ b/emul/mini/src/main/java/java/lang/Object.java	Tue Feb 19 15:59:27 2013 +0100
    14.3 @@ -117,7 +117,7 @@
    14.4      )
    14.5      public native int hashCode();
    14.6  
    14.7 -    @JavaScriptBody(args = {}, body = "Math.random() * Math.pow(2, 32);")
    14.8 +    @JavaScriptBody(args = {}, body = "return Math.random() * Math.pow(2, 32);")
    14.9      native int computeHashCode();
   14.10      
   14.11      /**
    15.1 --- a/emul/mini/src/main/java/java/lang/String.java	Tue Feb 19 15:33:32 2013 +0100
    15.2 +++ b/emul/mini/src/main/java/java/lang/String.java	Tue Feb 19 15:59:27 2013 +0100
    15.3 @@ -335,7 +335,7 @@
    15.4                  value[i] = (char) (hibyte | (ascii[i + offset] & 0xff));
    15.5              }
    15.6          }
    15.7 -        this.r = new String(value, 0, count);
    15.8 +        initFromCharArray(value, offset, count);
    15.9      }
   15.10  
   15.11      /**
    16.1 --- a/emul/mini/src/main/java/java/util/zip/Inflater.java	Tue Feb 19 15:33:32 2013 +0100
    16.2 +++ b/emul/mini/src/main/java/java/util/zip/Inflater.java	Tue Feb 19 15:59:27 2013 +0100
    16.3 @@ -1,44 +1,30 @@
    16.4 -/* Inflater.java - Decompress a data stream
    16.5 -   Copyright (C) 1999, 2000, 2001, 2003  Free Software Foundation, Inc.
    16.6 -
    16.7 -This file is part of GNU Classpath.
    16.8 -
    16.9 -GNU Classpath is free software; you can redistribute it and/or modify
   16.10 -it under the terms of the GNU General Public License as published by
   16.11 -the Free Software Foundation; either version 2, or (at your option)
   16.12 -any later version.
   16.13 - 
   16.14 -GNU Classpath is distributed in the hope that it will be useful, but
   16.15 -WITHOUT ANY WARRANTY; without even the implied warranty of
   16.16 -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   16.17 -General Public License for more details.
   16.18 -
   16.19 -You should have received a copy of the GNU General Public License
   16.20 -along with GNU Classpath; see the file COPYING.  If not, write to the
   16.21 -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   16.22 -02111-1307 USA.
   16.23 -
   16.24 -Linking this library statically or dynamically with other modules is
   16.25 -making a combined work based on this library.  Thus, the terms and
   16.26 -conditions of the GNU General Public License cover the whole
   16.27 -combination.
   16.28 -
   16.29 -As a special exception, the copyright holders of this library give you
   16.30 -permission to link this library with independent modules to produce an
   16.31 -executable, regardless of the license terms of these independent
   16.32 -modules, and to copy and distribute the resulting executable under
   16.33 -terms of your choice, provided that you also meet, for each linked
   16.34 -independent module, the terms and conditions of the license of that
   16.35 -module.  An independent module is a module which is not derived from
   16.36 -or based on this library.  If you modify this library, you may extend
   16.37 -this exception to your version of the library, but you are not
   16.38 -obligated to do so.  If you do not wish to do so, delete this
   16.39 -exception statement from your version. */
   16.40 +/*
   16.41 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
   16.42 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   16.43 + *
   16.44 + * This code is free software; you can redistribute it and/or modify it
   16.45 + * under the terms of the GNU General Public License version 2 only, as
   16.46 + * published by the Free Software Foundation.  Oracle designates this
   16.47 + * particular file as subject to the "Classpath" exception as provided
   16.48 + * by Oracle in the LICENSE file that accompanied this code.
   16.49 + *
   16.50 + * This code is distributed in the hope that it will be useful, but WITHOUT
   16.51 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   16.52 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   16.53 + * version 2 for more details (a copy is included in the LICENSE file that
   16.54 + * accompanied this code).
   16.55 + *
   16.56 + * You should have received a copy of the GNU General Public License version
   16.57 + * 2 along with this work; if not, write to the Free Software Foundation,
   16.58 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   16.59 + *
   16.60 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   16.61 + * or visit www.oracle.com if you need additional information or have any
   16.62 + * questions.
   16.63 + */
   16.64  
   16.65  package java.util.zip;
   16.66  
   16.67 -import org.apidesign.bck2brwsr.emul.lang.System;
   16.68 -
   16.69  /**
   16.70   * This class provides support for general purpose decompression using the
   16.71   * popular ZLIB compression library. The ZLIB compression library was
   16.72 @@ -84,1392 +70,241 @@
   16.73   * @author      David Connelly
   16.74   *
   16.75   */
   16.76 +public
   16.77 +class Inflater {
   16.78 +    private final org.apidesign.bck2brwsr.emul.zip.Inflater impl;
   16.79 +    
   16.80 +    /**
   16.81 +     * Creates a new decompressor. If the parameter 'nowrap' is true then
   16.82 +     * the ZLIB header and checksum fields will not be used. This provides
   16.83 +     * compatibility with the compression format used by both GZIP and PKZIP.
   16.84 +     * <p>
   16.85 +     * Note: When using the 'nowrap' option it is also necessary to provide
   16.86 +     * an extra "dummy" byte as input. This is required by the ZLIB native
   16.87 +     * library in order to support certain optimizations.
   16.88 +     *
   16.89 +     * @param nowrap if true then support GZIP compatible compression
   16.90 +     */
   16.91 +    public Inflater(boolean nowrap) {
   16.92 +        if (getClass() == org.apidesign.bck2brwsr.emul.zip.Inflater.class) {
   16.93 +            impl = null;
   16.94 +        } else {
   16.95 +            impl = new org.apidesign.bck2brwsr.emul.zip.Inflater(nowrap);
   16.96 +        }
   16.97 +    }
   16.98  
   16.99 -/* Written using on-line Java Platform 1.2 API Specification
  16.100 - * and JCL book.
  16.101 - * Believed complete and correct.
  16.102 - */
  16.103 +    /**
  16.104 +     * Creates a new decompressor.
  16.105 +     */
  16.106 +    public Inflater() {
  16.107 +        this(false);
  16.108 +    }
  16.109  
  16.110 -/**
  16.111 - * Inflater is used to decompress data that has been compressed according 
  16.112 - * to the "deflate" standard described in rfc1950.
  16.113 - *
  16.114 - * The usage is as following.  First you have to set some input with
  16.115 - * <code>setInput()</code>, then inflate() it.  If inflate doesn't
  16.116 - * inflate any bytes there may be three reasons:
  16.117 - * <ul>
  16.118 - * <li>needsInput() returns true because the input buffer is empty.
  16.119 - * You have to provide more input with <code>setInput()</code>.  
  16.120 - * NOTE: needsInput() also returns true when, the stream is finished.
  16.121 - * </li>
  16.122 - * <li>needsDictionary() returns true, you have to provide a preset 
  16.123 - *     dictionary with <code>setDictionary()</code>.</li>
  16.124 - * <li>finished() returns true, the inflater has finished.</li>
  16.125 - * </ul>
  16.126 - * Once the first output byte is produced, a dictionary will not be
  16.127 - * needed at a later stage.
  16.128 - *
  16.129 - * @author John Leuner, Jochen Hoenicke
  16.130 - * @author Tom Tromey
  16.131 - * @date May 17, 1999
  16.132 - * @since JDK 1.1
  16.133 - */
  16.134 -public class Inflater
  16.135 -{
  16.136 -  /* Copy lengths for literal codes 257..285 */
  16.137 -  private static final int CPLENS[] = 
  16.138 -  { 
  16.139 -    3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
  16.140 -    35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
  16.141 -  };
  16.142 -  
  16.143 -  /* Extra bits for literal codes 257..285 */  
  16.144 -  private static final int CPLEXT[] = 
  16.145 -  { 
  16.146 -    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
  16.147 -    3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
  16.148 -  };
  16.149 +    /**
  16.150 +     * Sets input data for decompression. Should be called whenever
  16.151 +     * needsInput() returns true indicating that more input data is
  16.152 +     * required.
  16.153 +     * @param b the input data bytes
  16.154 +     * @param off the start offset of the input data
  16.155 +     * @param len the length of the input data
  16.156 +     * @see Inflater#needsInput
  16.157 +     */
  16.158 +    public void setInput(byte[] b, int off, int len) {
  16.159 +        impl.setInput(b, off, len);
  16.160 +    }
  16.161  
  16.162 -  /* Copy offsets for distance codes 0..29 */
  16.163 -  private static final int CPDIST[] = {
  16.164 -    1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
  16.165 -    257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
  16.166 -    8193, 12289, 16385, 24577
  16.167 -  };
  16.168 -  
  16.169 -  /* Extra bits for distance codes */
  16.170 -  private static final int CPDEXT[] = {
  16.171 -    0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
  16.172 -    7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 
  16.173 -    12, 12, 13, 13
  16.174 -  };
  16.175 +    /**
  16.176 +     * Sets input data for decompression. Should be called whenever
  16.177 +     * needsInput() returns true indicating that more input data is
  16.178 +     * required.
  16.179 +     * @param b the input data bytes
  16.180 +     * @see Inflater#needsInput
  16.181 +     */
  16.182 +    public void setInput(byte[] b) {
  16.183 +        impl.setInput(b);
  16.184 +    }
  16.185  
  16.186 -  /* This are the state in which the inflater can be.  */
  16.187 -  private static final int DECODE_HEADER           = 0;
  16.188 -  private static final int DECODE_DICT             = 1;
  16.189 -  private static final int DECODE_BLOCKS           = 2;
  16.190 -  private static final int DECODE_STORED_LEN1      = 3;
  16.191 -  private static final int DECODE_STORED_LEN2      = 4;
  16.192 -  private static final int DECODE_STORED           = 5;
  16.193 -  private static final int DECODE_DYN_HEADER       = 6;
  16.194 -  private static final int DECODE_HUFFMAN          = 7;
  16.195 -  private static final int DECODE_HUFFMAN_LENBITS  = 8;
  16.196 -  private static final int DECODE_HUFFMAN_DIST     = 9;
  16.197 -  private static final int DECODE_HUFFMAN_DISTBITS = 10;
  16.198 -  private static final int DECODE_CHKSUM           = 11;
  16.199 -  private static final int FINISHED                = 12;
  16.200 +    /**
  16.201 +     * Sets the preset dictionary to the given array of bytes. Should be
  16.202 +     * called when inflate() returns 0 and needsDictionary() returns true
  16.203 +     * indicating that a preset dictionary is required. The method getAdler()
  16.204 +     * can be used to get the Adler-32 value of the dictionary needed.
  16.205 +     * @param b the dictionary data bytes
  16.206 +     * @param off the start offset of the data
  16.207 +     * @param len the length of the data
  16.208 +     * @see Inflater#needsDictionary
  16.209 +     * @see Inflater#getAdler
  16.210 +     */
  16.211 +    public void setDictionary(byte[] b, int off, int len) {
  16.212 +        impl.setDictionary(b, off, len);
  16.213 +    }
  16.214  
  16.215 -  /** This variable contains the current state. */
  16.216 -  private int mode;
  16.217 +    /**
  16.218 +     * Sets the preset dictionary to the given array of bytes. Should be
  16.219 +     * called when inflate() returns 0 and needsDictionary() returns true
  16.220 +     * indicating that a preset dictionary is required. The method getAdler()
  16.221 +     * can be used to get the Adler-32 value of the dictionary needed.
  16.222 +     * @param b the dictionary data bytes
  16.223 +     * @see Inflater#needsDictionary
  16.224 +     * @see Inflater#getAdler
  16.225 +     */
  16.226 +    public void setDictionary(byte[] b) {
  16.227 +        impl.setDictionary(b);
  16.228 +    }
  16.229  
  16.230 -  /**
  16.231 -   * The adler checksum of the dictionary or of the decompressed
  16.232 -   * stream, as it is written in the header resp. footer of the
  16.233 -   * compressed stream.  <br>
  16.234 -   *
  16.235 -   * Only valid if mode is DECODE_DICT or DECODE_CHKSUM.
  16.236 -   */
  16.237 -  private int readAdler;
  16.238 -  /** 
  16.239 -   * The number of bits needed to complete the current state.  This
  16.240 -   * is valid, if mode is DECODE_DICT, DECODE_CHKSUM,
  16.241 -   * DECODE_HUFFMAN_LENBITS or DECODE_HUFFMAN_DISTBITS.  
  16.242 -   */
  16.243 -  private int neededBits;
  16.244 -  private int repLength, repDist;
  16.245 -  private int uncomprLen;
  16.246 -  /**
  16.247 -   * True, if the last block flag was set in the last block of the
  16.248 -   * inflated stream.  This means that the stream ends after the
  16.249 -   * current block.  
  16.250 -   */
  16.251 -  private boolean isLastBlock;
  16.252 +    /**
  16.253 +     * Returns the total number of bytes remaining in the input buffer.
  16.254 +     * This can be used to find out what bytes still remain in the input
  16.255 +     * buffer after decompression has finished.
  16.256 +     * @return the total number of bytes remaining in the input buffer
  16.257 +     */
  16.258 +    public int getRemaining() {
  16.259 +        return impl.getRemaining();
  16.260 +    }
  16.261  
  16.262 -  /**
  16.263 -   * The total number of inflated bytes.
  16.264 -   */
  16.265 -  private long totalOut;
  16.266 -  /**
  16.267 -   * The total number of bytes set with setInput().  This is not the
  16.268 -   * value returned by getTotalIn(), since this also includes the 
  16.269 -   * unprocessed input.
  16.270 -   */
  16.271 -  private long totalIn;
  16.272 -  /**
  16.273 -   * This variable stores the nowrap flag that was given to the constructor.
  16.274 -   * True means, that the inflated stream doesn't contain a header nor the
  16.275 -   * checksum in the footer.
  16.276 -   */
  16.277 -  private boolean nowrap;
  16.278 +    /**
  16.279 +     * Returns true if no data remains in the input buffer. This can
  16.280 +     * be used to determine if #setInput should be called in order
  16.281 +     * to provide more input.
  16.282 +     * @return true if no data remains in the input buffer
  16.283 +     */
  16.284 +    public boolean needsInput() {
  16.285 +        return impl.needsInput();
  16.286 +    }
  16.287  
  16.288 -  private StreamManipulator input;
  16.289 -  private OutputWindow outputWindow;
  16.290 -  private InflaterDynHeader dynHeader;
  16.291 -  private InflaterHuffmanTree litlenTree, distTree;
  16.292 -  private Adler32 adler;
  16.293 +    /**
  16.294 +     * Returns true if a preset dictionary is needed for decompression.
  16.295 +     * @return true if a preset dictionary is needed for decompression
  16.296 +     * @see Inflater#setDictionary
  16.297 +     */
  16.298 +    public boolean needsDictionary() {
  16.299 +        return impl.needsDictionary();
  16.300 +    }
  16.301  
  16.302 -  /**
  16.303 -   * Creates a new inflater.
  16.304 -   */
  16.305 -  public Inflater ()
  16.306 -  {
  16.307 -    this (false);
  16.308 -  }
  16.309 +    /**
  16.310 +     * Returns true if the end of the compressed data stream has been
  16.311 +     * reached.
  16.312 +     * @return true if the end of the compressed data stream has been
  16.313 +     * reached
  16.314 +     */
  16.315 +    public boolean finished() {
  16.316 +        return impl.finished();
  16.317 +    }
  16.318  
  16.319 -  /**
  16.320 -   * Creates a new inflater.
  16.321 -   * @param nowrap true if no header and checksum field appears in the
  16.322 -   * stream.  This is used for GZIPed input.  For compatibility with
  16.323 -   * Sun JDK you should provide one byte of input more than needed in
  16.324 -   * this case.
  16.325 -   */
  16.326 -  public Inflater (boolean nowrap)
  16.327 -  {
  16.328 -    this.nowrap = nowrap;
  16.329 -    this.adler = new Adler32();
  16.330 -    input = new StreamManipulator();
  16.331 -    outputWindow = new OutputWindow();
  16.332 -    mode = nowrap ? DECODE_BLOCKS : DECODE_HEADER;
  16.333 -  }
  16.334 +    /**
  16.335 +     * Uncompresses bytes into specified buffer. Returns actual number
  16.336 +     * of bytes uncompressed. A return value of 0 indicates that
  16.337 +     * needsInput() or needsDictionary() should be called in order to
  16.338 +     * determine if more input data or a preset dictionary is required.
  16.339 +     * In the latter case, getAdler() can be used to get the Adler-32
  16.340 +     * value of the dictionary required.
  16.341 +     * @param b the buffer for the uncompressed data
  16.342 +     * @param off the start offset of the data
  16.343 +     * @param len the maximum number of uncompressed bytes
  16.344 +     * @return the actual number of uncompressed bytes
  16.345 +     * @exception DataFormatException if the compressed data format is invalid
  16.346 +     * @see Inflater#needsInput
  16.347 +     * @see Inflater#needsDictionary
  16.348 +     */
  16.349 +    public int inflate(byte[] b, int off, int len)
  16.350 +        throws DataFormatException
  16.351 +    {
  16.352 +        return impl.inflate(b, off, len);
  16.353 +    }
  16.354  
  16.355 -  /**
  16.356 -   * Finalizes this object.
  16.357 -   */
  16.358 -  protected void finalize ()
  16.359 -  {
  16.360 -    /* Exists only for compatibility */
  16.361 -  }
  16.362 +    /**
  16.363 +     * Uncompresses bytes into specified buffer. Returns actual number
  16.364 +     * of bytes uncompressed. A return value of 0 indicates that
  16.365 +     * needsInput() or needsDictionary() should be called in order to
  16.366 +     * determine if more input data or a preset dictionary is required.
  16.367 +     * In the latter case, getAdler() can be used to get the Adler-32
  16.368 +     * value of the dictionary required.
  16.369 +     * @param b the buffer for the uncompressed data
  16.370 +     * @return the actual number of uncompressed bytes
  16.371 +     * @exception DataFormatException if the compressed data format is invalid
  16.372 +     * @see Inflater#needsInput
  16.373 +     * @see Inflater#needsDictionary
  16.374 +     */
  16.375 +    public int inflate(byte[] b) throws DataFormatException {
  16.376 +        return impl.inflate(b);
  16.377 +    }
  16.378  
  16.379 -  /**
  16.380 -   * Frees all objects allocated by the inflater.  There's no reason
  16.381 -   * to call this, since you can just rely on garbage collection (even
  16.382 -   * for the Sun implementation).  Exists only for compatibility
  16.383 -   * with Sun's JDK, where the compressor allocates native memory.
  16.384 -   * If you call any method (even reset) afterwards the behaviour is
  16.385 -   * <i>undefined</i>.  
  16.386 -   * @deprecated Just clear all references to inflater instead.
  16.387 -   */
  16.388 -  public void end ()
  16.389 -  {
  16.390 -    outputWindow = null;
  16.391 -    input = null;
  16.392 -    dynHeader = null;
  16.393 -    litlenTree = null;
  16.394 -    distTree = null;
  16.395 -    adler = null;
  16.396 -  }
  16.397 +    /**
  16.398 +     * Returns the ADLER-32 value of the uncompressed data.
  16.399 +     * @return the ADLER-32 value of the uncompressed data
  16.400 +     */
  16.401 +    public int getAdler() {
  16.402 +        return impl.getAdler();
  16.403 +    }
  16.404  
  16.405 -  /**
  16.406 -   * Returns true, if the inflater has finished.  This means, that no
  16.407 -   * input is needed and no output can be produced.
  16.408 -   */
  16.409 -  public boolean finished() 
  16.410 -  {
  16.411 -    return mode == FINISHED && outputWindow.getAvailable() == 0;
  16.412 -  }
  16.413 +    /**
  16.414 +     * Returns the total number of compressed bytes input so far.
  16.415 +     *
  16.416 +     * <p>Since the number of bytes may be greater than
  16.417 +     * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now
  16.418 +     * the preferred means of obtaining this information.</p>
  16.419 +     *
  16.420 +     * @return the total number of compressed bytes input so far
  16.421 +     */
  16.422 +    public int getTotalIn() {
  16.423 +        return impl.getTotalIn();
  16.424 +    }
  16.425  
  16.426 -  /**
  16.427 -   * Gets the adler checksum.  This is either the checksum of all
  16.428 -   * uncompressed bytes returned by inflate(), or if needsDictionary()
  16.429 -   * returns true (and thus no output was yet produced) this is the
  16.430 -   * adler checksum of the expected dictionary.
  16.431 -   * @returns the adler checksum.
  16.432 -   */
  16.433 -  public int getAdler()
  16.434 -  {
  16.435 -    return needsDictionary() ? readAdler : (int) adler.getValue();
  16.436 -  }
  16.437 -  
  16.438 -  /**
  16.439 -   * Gets the number of unprocessed input.  Useful, if the end of the
  16.440 -   * stream is reached and you want to further process the bytes after
  16.441 -   * the deflate stream.  
  16.442 -   * @return the number of bytes of the input which were not processed.
  16.443 -   */
  16.444 -  public int getRemaining()
  16.445 -  {
  16.446 -    return input.getAvailableBytes();
  16.447 -  }
  16.448 -  
  16.449 -  /**
  16.450 -   * Gets the total number of processed compressed input bytes.
  16.451 -   * @return the total number of bytes of processed input bytes.
  16.452 -   */
  16.453 -  public int getTotalIn()
  16.454 -  {
  16.455 -    return (int)getBytesRead();
  16.456 -  }
  16.457 -  
  16.458 -  /**
  16.459 -   * Gets the total number of output bytes returned by inflate().
  16.460 -   * @return the total number of output bytes.
  16.461 -   */
  16.462 -  public int getTotalOut()
  16.463 -  {
  16.464 -    return (int)totalOut;
  16.465 -  }
  16.466 -  
  16.467 -  public long getBytesWritten() {
  16.468 -     return totalOut;
  16.469 -  }
  16.470 +    /**
  16.471 +     * Returns the total number of compressed bytes input so far.</p>
  16.472 +     *
  16.473 +     * @return the total (non-negative) number of compressed bytes input so far
  16.474 +     * @since 1.5
  16.475 +     */
  16.476 +    public long getBytesRead() {
  16.477 +        return impl.getBytesRead();
  16.478 +    }
  16.479  
  16.480 -  public long getBytesRead() {
  16.481 -    return totalIn - getRemaining();
  16.482 -  }
  16.483 -  
  16.484 +    /**
  16.485 +     * Returns the total number of uncompressed bytes output so far.
  16.486 +     *
  16.487 +     * <p>Since the number of bytes may be greater than
  16.488 +     * Integer.MAX_VALUE, the {@link #getBytesWritten()} method is now
  16.489 +     * the preferred means of obtaining this information.</p>
  16.490 +     *
  16.491 +     * @return the total number of uncompressed bytes output so far
  16.492 +     */
  16.493 +    public int getTotalOut() {
  16.494 +        return impl.getTotalOut();
  16.495 +    }
  16.496  
  16.497 -  /**
  16.498 -   * Inflates the compressed stream to the output buffer.  If this
  16.499 -   * returns 0, you should check, whether needsDictionary(),
  16.500 -   * needsInput() or finished() returns true, to determine why no 
  16.501 -   * further output is produced.
  16.502 -   * @param buffer the output buffer.
  16.503 -   * @return the number of bytes written to the buffer, 0 if no further
  16.504 -   * output can be produced.  
  16.505 -   * @exception DataFormatException if deflated stream is invalid.
  16.506 -   * @exception IllegalArgumentException if buf has length 0.
  16.507 -   */
  16.508 -  public int inflate (byte[] buf) throws DataFormatException
  16.509 -  {
  16.510 -    return inflate (buf, 0, buf.length);
  16.511 -  }
  16.512 +    /**
  16.513 +     * Returns the total number of uncompressed bytes output so far.</p>
  16.514 +     *
  16.515 +     * @return the total (non-negative) number of uncompressed bytes output so far
  16.516 +     * @since 1.5
  16.517 +     */
  16.518 +    public long getBytesWritten() {
  16.519 +        return impl.getBytesWritten();
  16.520 +    }
  16.521  
  16.522 -  /**
  16.523 -   * Inflates the compressed stream to the output buffer.  If this
  16.524 -   * returns 0, you should check, whether needsDictionary(),
  16.525 -   * needsInput() or finished() returns true, to determine why no 
  16.526 -   * further output is produced.
  16.527 -   * @param buffer the output buffer.
  16.528 -   * @param off the offset into buffer where the output should start.
  16.529 -   * @param len the maximum length of the output.
  16.530 -   * @return the number of bytes written to the buffer, 0 if no further
  16.531 -   * output can be produced.  
  16.532 -   * @exception DataFormatException if deflated stream is invalid.
  16.533 -   * @exception IndexOutOfBoundsException if the off and/or len are wrong.
  16.534 -   */
  16.535 -  public int inflate (byte[] buf, int off, int len) throws DataFormatException
  16.536 -  {
  16.537 -    /* Special case: len may be zero */
  16.538 -    if (len == 0)
  16.539 -      return 0;
  16.540 -    /* Check for correct buff, off, len triple */
  16.541 -    if (0 > off || off > off + len || off + len > buf.length)
  16.542 -      throw new ArrayIndexOutOfBoundsException();
  16.543 -    int count = 0;
  16.544 -    int more;
  16.545 -    do
  16.546 -      {
  16.547 -	if (mode != DECODE_CHKSUM)
  16.548 -	  {
  16.549 -	    /* Don't give away any output, if we are waiting for the
  16.550 -	     * checksum in the input stream.
  16.551 -	     *
  16.552 -	     * With this trick we have always:
  16.553 -	     *   needsInput() and not finished() 
  16.554 -	     *   implies more output can be produced.  
  16.555 -	     */
  16.556 -	    more = outputWindow.copyOutput(buf, off, len);
  16.557 -	    adler.update(buf, off, more);
  16.558 -	    off += more;
  16.559 -	    count += more;
  16.560 -	    totalOut += more;
  16.561 -	    len -= more;
  16.562 -	    if (len == 0)
  16.563 -	      return count;
  16.564 -	  }
  16.565 -      }
  16.566 -    while (decode() || (outputWindow.getAvailable() > 0
  16.567 -			&& mode != DECODE_CHKSUM));
  16.568 -    return count;
  16.569 -  }
  16.570 +    /**
  16.571 +     * Resets inflater so that a new set of input data can be processed.
  16.572 +     */
  16.573 +    public void reset() {
  16.574 +        impl.reset();
  16.575 +    }
  16.576  
  16.577 -  /**
  16.578 -   * Returns true, if a preset dictionary is needed to inflate the input.
  16.579 -   */
  16.580 -  public boolean needsDictionary ()
  16.581 -  {
  16.582 -    return mode == DECODE_DICT && neededBits == 0;
  16.583 -  }
  16.584 +    /**
  16.585 +     * Closes the decompressor and discards any unprocessed input.
  16.586 +     * This method should be called when the decompressor is no longer
  16.587 +     * being used, but will also be called automatically by the finalize()
  16.588 +     * method. Once this method is called, the behavior of the Inflater
  16.589 +     * object is undefined.
  16.590 +     */
  16.591 +    public void end() {
  16.592 +        impl.end();
  16.593 +    }
  16.594  
  16.595 -  /**
  16.596 -   * Returns true, if the input buffer is empty.
  16.597 -   * You should then call setInput(). <br>
  16.598 -   *
  16.599 -   * <em>NOTE</em>: This method also returns true when the stream is finished.
  16.600 -   */
  16.601 -  public boolean needsInput () 
  16.602 -  {
  16.603 -    return input.needsInput ();
  16.604 -  }
  16.605 -
  16.606 -  /**
  16.607 -   * Resets the inflater so that a new stream can be decompressed.  All
  16.608 -   * pending input and output will be discarded.
  16.609 -   */
  16.610 -  public void reset ()
  16.611 -  {
  16.612 -    mode = nowrap ? DECODE_BLOCKS : DECODE_HEADER;
  16.613 -    totalIn = totalOut = 0;
  16.614 -    input.reset();
  16.615 -    outputWindow.reset();
  16.616 -    dynHeader = null;
  16.617 -    litlenTree = null;
  16.618 -    distTree = null;
  16.619 -    isLastBlock = false;
  16.620 -    adler.reset();
  16.621 -  }
  16.622 -
  16.623 -  /**
  16.624 -   * Sets the preset dictionary.  This should only be called, if
  16.625 -   * needsDictionary() returns true and it should set the same
  16.626 -   * dictionary, that was used for deflating.  The getAdler()
  16.627 -   * function returns the checksum of the dictionary needed.
  16.628 -   * @param buffer the dictionary.
  16.629 -   * @exception IllegalStateException if no dictionary is needed.
  16.630 -   * @exception IllegalArgumentException if the dictionary checksum is
  16.631 -   * wrong.  
  16.632 -   */
  16.633 -  public void setDictionary (byte[] buffer)
  16.634 -  {
  16.635 -    setDictionary(buffer, 0, buffer.length);
  16.636 -  }
  16.637 -
  16.638 -  /**
  16.639 -   * Sets the preset dictionary.  This should only be called, if
  16.640 -   * needsDictionary() returns true and it should set the same
  16.641 -   * dictionary, that was used for deflating.  The getAdler()
  16.642 -   * function returns the checksum of the dictionary needed.
  16.643 -   * @param buffer the dictionary.
  16.644 -   * @param off the offset into buffer where the dictionary starts.
  16.645 -   * @param len the length of the dictionary.
  16.646 -   * @exception IllegalStateException if no dictionary is needed.
  16.647 -   * @exception IllegalArgumentException if the dictionary checksum is
  16.648 -   * wrong.  
  16.649 -   * @exception IndexOutOfBoundsException if the off and/or len are wrong.
  16.650 -   */
  16.651 -  public void setDictionary (byte[] buffer, int off, int len)
  16.652 -  {
  16.653 -    if (!needsDictionary())
  16.654 -      throw new IllegalStateException();
  16.655 -
  16.656 -    adler.update(buffer, off, len);
  16.657 -    if ((int) adler.getValue() != readAdler)
  16.658 -      throw new IllegalArgumentException("Wrong adler checksum");
  16.659 -    adler.reset();
  16.660 -    outputWindow.copyDict(buffer, off, len);
  16.661 -    mode = DECODE_BLOCKS;
  16.662 -  }
  16.663 -
  16.664 -  /**
  16.665 -   * Sets the input.  This should only be called, if needsInput()
  16.666 -   * returns true.
  16.667 -   * @param buffer the input.
  16.668 -   * @exception IllegalStateException if no input is needed.
  16.669 -   */
  16.670 -  public void setInput (byte[] buf) 
  16.671 -  {
  16.672 -    setInput (buf, 0, buf.length);
  16.673 -  }
  16.674 -
  16.675 -  /**
  16.676 -   * Sets the input.  This should only be called, if needsInput()
  16.677 -   * returns true.
  16.678 -   * @param buffer the input.
  16.679 -   * @param off the offset into buffer where the input starts.
  16.680 -   * @param len the length of the input.  
  16.681 -   * @exception IllegalStateException if no input is needed.
  16.682 -   * @exception IndexOutOfBoundsException if the off and/or len are wrong.
  16.683 -   */
  16.684 -  public void setInput (byte[] buf, int off, int len) 
  16.685 -  {
  16.686 -    input.setInput (buf, off, len);
  16.687 -    totalIn += len;
  16.688 -  }
  16.689 -  private static final int DEFLATED = 8;
  16.690 -  /**
  16.691 -   * Decodes the deflate header.
  16.692 -   * @return false if more input is needed. 
  16.693 -   * @exception DataFormatException if header is invalid.
  16.694 -   */
  16.695 -  private boolean decodeHeader () throws DataFormatException
  16.696 -  {
  16.697 -    int header = input.peekBits(16);
  16.698 -    if (header < 0)
  16.699 -      return false;
  16.700 -    input.dropBits(16);
  16.701 -    
  16.702 -    /* The header is written in "wrong" byte order */
  16.703 -    header = ((header << 8) | (header >> 8)) & 0xffff;
  16.704 -    if (header % 31 != 0)
  16.705 -      throw new DataFormatException("Header checksum illegal");
  16.706 -    
  16.707 -    if ((header & 0x0f00) != (DEFLATED << 8))
  16.708 -      throw new DataFormatException("Compression Method unknown");
  16.709 -
  16.710 -    /* Maximum size of the backwards window in bits. 
  16.711 -     * We currently ignore this, but we could use it to make the
  16.712 -     * inflater window more space efficient. On the other hand the
  16.713 -     * full window (15 bits) is needed most times, anyway.
  16.714 -     int max_wbits = ((header & 0x7000) >> 12) + 8;
  16.715 +    /**
  16.716 +     * Closes the decompressor when garbage is collected.
  16.717       */
  16.718 -    
  16.719 -    if ((header & 0x0020) == 0) // Dictionary flag?
  16.720 -      {
  16.721 -	mode = DECODE_BLOCKS;
  16.722 -      }
  16.723 -    else
  16.724 -      {
  16.725 -	mode = DECODE_DICT;
  16.726 -	neededBits = 32;      
  16.727 -      }
  16.728 -    return true;
  16.729 -  }
  16.730 -   
  16.731 -  /**
  16.732 -   * Decodes the dictionary checksum after the deflate header.
  16.733 -   * @return false if more input is needed. 
  16.734 -   */
  16.735 -  private boolean decodeDict ()
  16.736 -  {
  16.737 -    while (neededBits > 0)
  16.738 -      {
  16.739 -	int dictByte = input.peekBits(8);
  16.740 -	if (dictByte < 0)
  16.741 -	  return false;
  16.742 -	input.dropBits(8);
  16.743 -	readAdler = (readAdler << 8) | dictByte;
  16.744 -	neededBits -= 8;
  16.745 -      }
  16.746 -    return false;
  16.747 -  }
  16.748 -
  16.749 -  /**
  16.750 -   * Decodes the huffman encoded symbols in the input stream.
  16.751 -   * @return false if more input is needed, true if output window is
  16.752 -   * full or the current block ends.
  16.753 -   * @exception DataFormatException if deflated stream is invalid.  
  16.754 -   */
  16.755 -  private boolean decodeHuffman () throws DataFormatException
  16.756 -  {
  16.757 -    int free = outputWindow.getFreeSpace();
  16.758 -    while (free >= 258)
  16.759 -      {
  16.760 -	int symbol;
  16.761 -	switch (mode)
  16.762 -	  {
  16.763 -	  case DECODE_HUFFMAN:
  16.764 -	    /* This is the inner loop so it is optimized a bit */
  16.765 -	    while (((symbol = litlenTree.getSymbol(input)) & ~0xff) == 0)
  16.766 -	      {
  16.767 -		outputWindow.write(symbol);
  16.768 -		if (--free < 258)
  16.769 -		  return true;
  16.770 -	      } 
  16.771 -	    if (symbol < 257)
  16.772 -	      {
  16.773 -		if (symbol < 0)
  16.774 -		  return false;
  16.775 -		else
  16.776 -		  {
  16.777 -		    /* symbol == 256: end of block */
  16.778 -		    distTree = null;
  16.779 -		    litlenTree = null;
  16.780 -		    mode = DECODE_BLOCKS;
  16.781 -		    return true;
  16.782 -		  }
  16.783 -	      }
  16.784 -		
  16.785 -	    try
  16.786 -	      {
  16.787 -		repLength = CPLENS[symbol - 257];
  16.788 -		neededBits = CPLEXT[symbol - 257];
  16.789 -	      }
  16.790 -	    catch (ArrayIndexOutOfBoundsException ex)
  16.791 -	      {
  16.792 -		throw new DataFormatException("Illegal rep length code");
  16.793 -	      }
  16.794 -	    /* fall through */
  16.795 -	  case DECODE_HUFFMAN_LENBITS:
  16.796 -	    if (neededBits > 0)
  16.797 -	      {
  16.798 -		mode = DECODE_HUFFMAN_LENBITS;
  16.799 -		int i = input.peekBits(neededBits);
  16.800 -		if (i < 0)
  16.801 -		  return false;
  16.802 -		input.dropBits(neededBits);
  16.803 -		repLength += i;
  16.804 -	      }
  16.805 -	    mode = DECODE_HUFFMAN_DIST;
  16.806 -	    /* fall through */
  16.807 -	  case DECODE_HUFFMAN_DIST:
  16.808 -	    symbol = distTree.getSymbol(input);
  16.809 -	    if (symbol < 0)
  16.810 -	      return false;
  16.811 -	    try 
  16.812 -	      {
  16.813 -		repDist = CPDIST[symbol];
  16.814 -		neededBits = CPDEXT[symbol];
  16.815 -	      }
  16.816 -	    catch (ArrayIndexOutOfBoundsException ex)
  16.817 -	      {
  16.818 -		throw new DataFormatException("Illegal rep dist code");
  16.819 -	      }
  16.820 -	    /* fall through */
  16.821 -	  case DECODE_HUFFMAN_DISTBITS:
  16.822 -	    if (neededBits > 0)
  16.823 -	      {
  16.824 -		mode = DECODE_HUFFMAN_DISTBITS;
  16.825 -		int i = input.peekBits(neededBits);
  16.826 -		if (i < 0)
  16.827 -		  return false;
  16.828 -		input.dropBits(neededBits);
  16.829 -		repDist += i;
  16.830 -	      }
  16.831 -	    outputWindow.repeat(repLength, repDist);
  16.832 -	    free -= repLength;
  16.833 -	    mode = DECODE_HUFFMAN;
  16.834 -	    break;
  16.835 -	  default:
  16.836 -	    throw new IllegalStateException();
  16.837 -	  }
  16.838 -      }
  16.839 -    return true;
  16.840 -  }
  16.841 -
  16.842 -  /**
  16.843 -   * Decodes the adler checksum after the deflate stream.
  16.844 -   * @return false if more input is needed. 
  16.845 -   * @exception DataFormatException if checksum doesn't match.
  16.846 -   */
  16.847 -  private boolean decodeChksum () throws DataFormatException
  16.848 -  {
  16.849 -    while (neededBits > 0)
  16.850 -      {
  16.851 -	int chkByte = input.peekBits(8);
  16.852 -	if (chkByte < 0)
  16.853 -	  return false;
  16.854 -	input.dropBits(8);
  16.855 -	readAdler = (readAdler << 8) | chkByte;
  16.856 -	neededBits -= 8;
  16.857 -      }
  16.858 -    if ((int) adler.getValue() != readAdler)
  16.859 -      throw new DataFormatException("Adler chksum doesn't match: "
  16.860 -				    +Integer.toHexString((int)adler.getValue())
  16.861 -				    +" vs. "+Integer.toHexString(readAdler));
  16.862 -    mode = FINISHED;
  16.863 -    return false;
  16.864 -  }
  16.865 -
  16.866 -  /**
  16.867 -   * Decodes the deflated stream.
  16.868 -   * @return false if more input is needed, or if finished. 
  16.869 -   * @exception DataFormatException if deflated stream is invalid.
  16.870 -   */
  16.871 -  private boolean decode () throws DataFormatException
  16.872 -  {
  16.873 -    switch (mode) 
  16.874 -      {
  16.875 -      case DECODE_HEADER:
  16.876 -	return decodeHeader();
  16.877 -      case DECODE_DICT:
  16.878 -	return decodeDict();
  16.879 -      case DECODE_CHKSUM:
  16.880 -	return decodeChksum();
  16.881 -
  16.882 -      case DECODE_BLOCKS:
  16.883 -	if (isLastBlock)
  16.884 -	  {
  16.885 -	    if (nowrap)
  16.886 -	      {
  16.887 -		mode = FINISHED;
  16.888 -		return false;
  16.889 -	      }
  16.890 -	    else
  16.891 -	      {
  16.892 -		input.skipToByteBoundary();
  16.893 -		neededBits = 32;
  16.894 -		mode = DECODE_CHKSUM;
  16.895 -		return true;
  16.896 -	      }
  16.897 -	  }
  16.898 -
  16.899 -	int type = input.peekBits(3);
  16.900 -	if (type < 0)
  16.901 -	  return false;
  16.902 -	input.dropBits(3);
  16.903 -
  16.904 -	if ((type & 1) != 0)
  16.905 -	  isLastBlock = true;
  16.906 -	switch (type >> 1)
  16.907 -	  {
  16.908 -	  case DeflaterConstants.STORED_BLOCK:
  16.909 -	    input.skipToByteBoundary();
  16.910 -	    mode = DECODE_STORED_LEN1;
  16.911 -	    break;
  16.912 -	  case DeflaterConstants.STATIC_TREES:
  16.913 -	    litlenTree = InflaterHuffmanTree.defLitLenTree;
  16.914 -	    distTree = InflaterHuffmanTree.defDistTree;
  16.915 -	    mode = DECODE_HUFFMAN;
  16.916 -	    break;
  16.917 -	  case DeflaterConstants.DYN_TREES:
  16.918 -	    dynHeader = new InflaterDynHeader();
  16.919 -	    mode = DECODE_DYN_HEADER;
  16.920 -	    break;
  16.921 -	  default:
  16.922 -	    throw new DataFormatException("Unknown block type "+type);
  16.923 -	  }
  16.924 -	return true;
  16.925 -
  16.926 -      case DECODE_STORED_LEN1:
  16.927 -	{
  16.928 -	  if ((uncomprLen = input.peekBits(16)) < 0)
  16.929 -	    return false;
  16.930 -	  input.dropBits(16);
  16.931 -	  mode = DECODE_STORED_LEN2;
  16.932 -	}
  16.933 -	/* fall through */
  16.934 -      case DECODE_STORED_LEN2:
  16.935 -	{
  16.936 -	  int nlen = input.peekBits(16);
  16.937 -	  if (nlen < 0)
  16.938 -	    return false;
  16.939 -	  input.dropBits(16);
  16.940 -	  if (nlen != (uncomprLen ^ 0xffff))
  16.941 -	    throw new DataFormatException("broken uncompressed block");
  16.942 -	  mode = DECODE_STORED;
  16.943 -	}
  16.944 -	/* fall through */
  16.945 -      case DECODE_STORED:
  16.946 -	{
  16.947 -	  int more = outputWindow.copyStored(input, uncomprLen);
  16.948 -	  uncomprLen -= more;
  16.949 -	  if (uncomprLen == 0)
  16.950 -	    {
  16.951 -	      mode = DECODE_BLOCKS;
  16.952 -	      return true;
  16.953 -	    }
  16.954 -	  return !input.needsInput();
  16.955 -	}
  16.956 -
  16.957 -      case DECODE_DYN_HEADER:
  16.958 -	if (!dynHeader.decode(input))
  16.959 -	  return false;
  16.960 -	litlenTree = dynHeader.buildLitLenTree();
  16.961 -	distTree = dynHeader.buildDistTree();
  16.962 -	mode = DECODE_HUFFMAN;
  16.963 -	/* fall through */
  16.964 -      case DECODE_HUFFMAN:
  16.965 -      case DECODE_HUFFMAN_LENBITS:
  16.966 -      case DECODE_HUFFMAN_DIST:
  16.967 -      case DECODE_HUFFMAN_DISTBITS:
  16.968 -	return decodeHuffman();
  16.969 -      case FINISHED:
  16.970 -	return false;
  16.971 -      default:
  16.972 -	throw new IllegalStateException();
  16.973 -      }	
  16.974 -  }
  16.975 -
  16.976 -
  16.977 -    interface DeflaterConstants {
  16.978 -      final static boolean DEBUGGING = false;
  16.979 -
  16.980 -      final static int STORED_BLOCK = 0;
  16.981 -      final static int STATIC_TREES = 1;
  16.982 -      final static int DYN_TREES    = 2;
  16.983 -      final static int PRESET_DICT  = 0x20;
  16.984 -
  16.985 -      final static int DEFAULT_MEM_LEVEL = 8;
  16.986 -
  16.987 -      final static int MAX_MATCH = 258;
  16.988 -      final static int MIN_MATCH = 3;
  16.989 -
  16.990 -      final static int MAX_WBITS = 15;
  16.991 -      final static int WSIZE = 1 << MAX_WBITS;
  16.992 -      final static int WMASK = WSIZE - 1;
  16.993 -
  16.994 -      final static int HASH_BITS = DEFAULT_MEM_LEVEL + 7;
  16.995 -      final static int HASH_SIZE = 1 << HASH_BITS;
  16.996 -      final static int HASH_MASK = HASH_SIZE - 1;
  16.997 -      final static int HASH_SHIFT = (HASH_BITS + MIN_MATCH - 1) / MIN_MATCH;
  16.998 -
  16.999 -      final static int MIN_LOOKAHEAD = MAX_MATCH + MIN_MATCH + 1;
 16.1000 -      final static int MAX_DIST = WSIZE - MIN_LOOKAHEAD;
 16.1001 -
 16.1002 -      final static int PENDING_BUF_SIZE = 1 << (DEFAULT_MEM_LEVEL + 8);
 16.1003 -      final static int MAX_BLOCK_SIZE = Math.min(65535, PENDING_BUF_SIZE-5);
 16.1004 -
 16.1005 -      final static int DEFLATE_STORED = 0;
 16.1006 -      final static int DEFLATE_FAST   = 1;
 16.1007 -      final static int DEFLATE_SLOW   = 2;
 16.1008 -
 16.1009 -      final static int GOOD_LENGTH[] = { 0,4, 4, 4, 4, 8,  8,  8,  32,  32 };
 16.1010 -      final static int MAX_LAZY[]    = { 0,4, 5, 6, 4,16, 16, 32, 128, 258 };
 16.1011 -      final static int NICE_LENGTH[] = { 0,8,16,32,16,32,128,128, 258, 258 };
 16.1012 -      final static int MAX_CHAIN[]   = { 0,4, 8,32,16,32,128,256,1024,4096 };
 16.1013 -      final static int COMPR_FUNC[]  = { 0,1, 1, 1, 1, 2,  2,  2,   2,   2 };
 16.1014 +    protected void finalize() {
 16.1015 +        end();
 16.1016      }
 16.1017 -    private static class InflaterHuffmanTree {
 16.1018 -      private final static int MAX_BITLEN = 15;
 16.1019 -      private short[] tree;
 16.1020 -
 16.1021 -      public static InflaterHuffmanTree defLitLenTree, defDistTree;
 16.1022 -
 16.1023 -      static
 16.1024 -      {
 16.1025 -        try 
 16.1026 -          {
 16.1027 -        byte[] codeLengths = new byte[288];
 16.1028 -        int i = 0;
 16.1029 -        while (i < 144)
 16.1030 -          codeLengths[i++] = 8;
 16.1031 -        while (i < 256)
 16.1032 -          codeLengths[i++] = 9;
 16.1033 -        while (i < 280)
 16.1034 -          codeLengths[i++] = 7;
 16.1035 -        while (i < 288)
 16.1036 -          codeLengths[i++] = 8;
 16.1037 -        defLitLenTree = new InflaterHuffmanTree(codeLengths);
 16.1038 -
 16.1039 -        codeLengths = new byte[32];
 16.1040 -        i = 0;
 16.1041 -        while (i < 32)
 16.1042 -          codeLengths[i++] = 5;
 16.1043 -        defDistTree = new InflaterHuffmanTree(codeLengths);
 16.1044 -          } 
 16.1045 -        catch (DataFormatException ex)
 16.1046 -          {
 16.1047 -        throw new IllegalStateException
 16.1048 -          ("InflaterHuffmanTree: static tree length illegal");
 16.1049 -          }
 16.1050 -      }
 16.1051 -
 16.1052 -      /**
 16.1053 -       * Constructs a Huffman tree from the array of code lengths.
 16.1054 -       *
 16.1055 -       * @param codeLengths the array of code lengths
 16.1056 -       */
 16.1057 -      public InflaterHuffmanTree(byte[] codeLengths) throws DataFormatException
 16.1058 -      {
 16.1059 -        buildTree(codeLengths);
 16.1060 -      }
 16.1061 -
 16.1062 -      private void buildTree(byte[] codeLengths) throws DataFormatException
 16.1063 -      {
 16.1064 -        int[] blCount = new int[MAX_BITLEN+1];
 16.1065 -        int[] nextCode = new int[MAX_BITLEN+1];
 16.1066 -        for (int i = 0; i < codeLengths.length; i++)
 16.1067 -          {
 16.1068 -        int bits = codeLengths[i];
 16.1069 -        if (bits > 0)
 16.1070 -          blCount[bits]++;
 16.1071 -          }
 16.1072 -
 16.1073 -        int code = 0;
 16.1074 -        int treeSize = 512;
 16.1075 -        for (int bits = 1; bits <= MAX_BITLEN; bits++)
 16.1076 -          {
 16.1077 -        nextCode[bits] = code;
 16.1078 -        code += blCount[bits] << (16 - bits);
 16.1079 -        if (bits >= 10)
 16.1080 -          {
 16.1081 -            /* We need an extra table for bit lengths >= 10. */
 16.1082 -            int start = nextCode[bits] & 0x1ff80;
 16.1083 -            int end   = code & 0x1ff80;
 16.1084 -            treeSize += (end - start) >> (16 - bits);
 16.1085 -          }
 16.1086 -          }
 16.1087 -        if (code != 65536)
 16.1088 -          throw new DataFormatException("Code lengths don't add up properly.");
 16.1089 -
 16.1090 -        /* Now create and fill the extra tables from longest to shortest
 16.1091 -         * bit len.  This way the sub trees will be aligned.
 16.1092 -         */
 16.1093 -        tree = new short[treeSize];
 16.1094 -        int treePtr = 512;
 16.1095 -        for (int bits = MAX_BITLEN; bits >= 10; bits--)
 16.1096 -          {
 16.1097 -        int end   = code & 0x1ff80;
 16.1098 -        code -= blCount[bits] << (16 - bits);
 16.1099 -        int start = code & 0x1ff80;
 16.1100 -        for (int i = start; i < end; i += 1 << 7)
 16.1101 -          {
 16.1102 -            tree[bitReverse(i)]
 16.1103 -              = (short) ((-treePtr << 4) | bits);
 16.1104 -            treePtr += 1 << (bits-9);
 16.1105 -          }
 16.1106 -          }
 16.1107 -
 16.1108 -        for (int i = 0; i < codeLengths.length; i++)
 16.1109 -          {
 16.1110 -        int bits = codeLengths[i];
 16.1111 -        if (bits == 0)
 16.1112 -          continue;
 16.1113 -        code = nextCode[bits];
 16.1114 -        int revcode = bitReverse(code);
 16.1115 -        if (bits <= 9)
 16.1116 -          {
 16.1117 -            do
 16.1118 -              {
 16.1119 -            tree[revcode] = (short) ((i << 4) | bits);
 16.1120 -            revcode += 1 << bits;
 16.1121 -              }
 16.1122 -            while (revcode < 512);
 16.1123 -          }
 16.1124 -        else
 16.1125 -          {
 16.1126 -            int subTree = tree[revcode & 511];
 16.1127 -            int treeLen = 1 << (subTree & 15);
 16.1128 -            subTree = -(subTree >> 4);
 16.1129 -            do
 16.1130 -              { 
 16.1131 -            tree[subTree | (revcode >> 9)] = (short) ((i << 4) | bits);
 16.1132 -            revcode += 1 << bits;
 16.1133 -              }
 16.1134 -            while (revcode < treeLen);
 16.1135 -          }
 16.1136 -        nextCode[bits] = code + (1 << (16 - bits));
 16.1137 -          }
 16.1138 -      }
 16.1139 -      private final static String bit4Reverse =
 16.1140 -        "\000\010\004\014\002\012\006\016\001\011\005\015\003\013\007\017";
 16.1141 -      static short bitReverse(int value) {
 16.1142 -            return (short) (bit4Reverse.charAt(value & 0xf) << 12
 16.1143 -                | bit4Reverse.charAt((value >> 4) & 0xf) << 8
 16.1144 -                | bit4Reverse.charAt((value >> 8) & 0xf) << 4
 16.1145 -                | bit4Reverse.charAt(value >> 12));
 16.1146 -      }
 16.1147 -
 16.1148 -      /**
 16.1149 -       * Reads the next symbol from input.  The symbol is encoded using the
 16.1150 -       * huffman tree.
 16.1151 -       * @param input the input source.
 16.1152 -       * @return the next symbol, or -1 if not enough input is available.
 16.1153 -       */
 16.1154 -      public int getSymbol(StreamManipulator input) throws DataFormatException
 16.1155 -      {
 16.1156 -        int lookahead, symbol;
 16.1157 -        if ((lookahead = input.peekBits(9)) >= 0)
 16.1158 -          {
 16.1159 -        if ((symbol = tree[lookahead]) >= 0)
 16.1160 -          {
 16.1161 -            input.dropBits(symbol & 15);
 16.1162 -            return symbol >> 4;
 16.1163 -          }
 16.1164 -        int subtree = -(symbol >> 4);
 16.1165 -        int bitlen = symbol & 15;
 16.1166 -        if ((lookahead = input.peekBits(bitlen)) >= 0)
 16.1167 -          {
 16.1168 -            symbol = tree[subtree | (lookahead >> 9)];
 16.1169 -            input.dropBits(symbol & 15);
 16.1170 -            return symbol >> 4;
 16.1171 -          }
 16.1172 -        else
 16.1173 -          {
 16.1174 -            int bits = input.getAvailableBits();
 16.1175 -            lookahead = input.peekBits(bits);
 16.1176 -            symbol = tree[subtree | (lookahead >> 9)];
 16.1177 -            if ((symbol & 15) <= bits)
 16.1178 -              {
 16.1179 -            input.dropBits(symbol & 15);
 16.1180 -            return symbol >> 4;
 16.1181 -              }
 16.1182 -            else
 16.1183 -              return -1;
 16.1184 -          }
 16.1185 -          }
 16.1186 -        else
 16.1187 -          {
 16.1188 -        int bits = input.getAvailableBits();
 16.1189 -        lookahead = input.peekBits(bits);
 16.1190 -        symbol = tree[lookahead];
 16.1191 -        if (symbol >= 0 && (symbol & 15) <= bits)
 16.1192 -          {
 16.1193 -            input.dropBits(symbol & 15);
 16.1194 -            return symbol >> 4;
 16.1195 -          }
 16.1196 -        else
 16.1197 -          return -1;
 16.1198 -          }
 16.1199 -      }
 16.1200 -    }
 16.1201 -    private static class InflaterDynHeader
 16.1202 -    {
 16.1203 -      private static final int LNUM   = 0;
 16.1204 -      private static final int DNUM   = 1;
 16.1205 -      private static final int BLNUM  = 2;
 16.1206 -      private static final int BLLENS = 3;
 16.1207 -      private static final int LENS   = 4;
 16.1208 -      private static final int REPS   = 5;
 16.1209 -
 16.1210 -      private static final int repMin[]  = { 3, 3, 11 };
 16.1211 -      private static final int repBits[] = { 2, 3,  7 };
 16.1212 -
 16.1213 -
 16.1214 -      private byte[] blLens;
 16.1215 -      private byte[] litdistLens;
 16.1216 -
 16.1217 -      private InflaterHuffmanTree blTree;
 16.1218 -
 16.1219 -      private int mode;
 16.1220 -      private int lnum, dnum, blnum, num;
 16.1221 -      private int repSymbol;
 16.1222 -      private byte lastLen;
 16.1223 -      private int ptr;
 16.1224 -
 16.1225 -      private static final int[] BL_ORDER =
 16.1226 -      { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
 16.1227 -
 16.1228 -      public InflaterDynHeader()
 16.1229 -      {
 16.1230 -      }
 16.1231 -
 16.1232 -      public boolean decode(StreamManipulator input) throws DataFormatException
 16.1233 -      {
 16.1234 -      decode_loop:
 16.1235 -        for (;;)
 16.1236 -          {
 16.1237 -        switch (mode)
 16.1238 -          {
 16.1239 -          case LNUM:
 16.1240 -            lnum = input.peekBits(5);
 16.1241 -            if (lnum < 0)
 16.1242 -              return false;
 16.1243 -            lnum += 257;
 16.1244 -            input.dropBits(5);
 16.1245 -    //  	    System.err.println("LNUM: "+lnum);
 16.1246 -            mode = DNUM;
 16.1247 -            /* fall through */
 16.1248 -          case DNUM:
 16.1249 -            dnum = input.peekBits(5);
 16.1250 -            if (dnum < 0)
 16.1251 -              return false;
 16.1252 -            dnum++;
 16.1253 -            input.dropBits(5);
 16.1254 -    //  	    System.err.println("DNUM: "+dnum);
 16.1255 -            num = lnum+dnum;
 16.1256 -            litdistLens = new byte[num];
 16.1257 -            mode = BLNUM;
 16.1258 -            /* fall through */
 16.1259 -          case BLNUM:
 16.1260 -            blnum = input.peekBits(4);
 16.1261 -            if (blnum < 0)
 16.1262 -              return false;
 16.1263 -            blnum += 4;
 16.1264 -            input.dropBits(4);
 16.1265 -            blLens = new byte[19];
 16.1266 -            ptr = 0;
 16.1267 -    //  	    System.err.println("BLNUM: "+blnum);
 16.1268 -            mode = BLLENS;
 16.1269 -            /* fall through */
 16.1270 -          case BLLENS:
 16.1271 -            while (ptr < blnum)
 16.1272 -              {
 16.1273 -            int len = input.peekBits(3);
 16.1274 -            if (len < 0)
 16.1275 -              return false;
 16.1276 -            input.dropBits(3);
 16.1277 -    //  		System.err.println("blLens["+BL_ORDER[ptr]+"]: "+len);
 16.1278 -            blLens[BL_ORDER[ptr]] = (byte) len;
 16.1279 -            ptr++;
 16.1280 -              }
 16.1281 -            blTree = new InflaterHuffmanTree(blLens);
 16.1282 -            blLens = null;
 16.1283 -            ptr = 0;
 16.1284 -            mode = LENS;
 16.1285 -            /* fall through */
 16.1286 -          case LENS:
 16.1287 -            {
 16.1288 -              int symbol;
 16.1289 -              while (((symbol = blTree.getSymbol(input)) & ~15) == 0)
 16.1290 -            {
 16.1291 -              /* Normal case: symbol in [0..15] */
 16.1292 -
 16.1293 -    //  		  System.err.println("litdistLens["+ptr+"]: "+symbol);
 16.1294 -              litdistLens[ptr++] = lastLen = (byte) symbol;
 16.1295 -
 16.1296 -              if (ptr == num)
 16.1297 -                {
 16.1298 -                  /* Finished */
 16.1299 -                  return true;
 16.1300 -                }
 16.1301 -            }
 16.1302 -
 16.1303 -              /* need more input ? */
 16.1304 -              if (symbol < 0)
 16.1305 -            return false;
 16.1306 -
 16.1307 -              /* otherwise repeat code */
 16.1308 -              if (symbol >= 17)
 16.1309 -            {
 16.1310 -              /* repeat zero */
 16.1311 -    //  		  System.err.println("repeating zero");
 16.1312 -              lastLen = 0;
 16.1313 -            }
 16.1314 -              else
 16.1315 -            {
 16.1316 -              if (ptr == 0)
 16.1317 -                throw new DataFormatException();
 16.1318 -            }
 16.1319 -              repSymbol = symbol-16;
 16.1320 -              mode = REPS;
 16.1321 -            }
 16.1322 -            /* fall through */
 16.1323 -
 16.1324 -          case REPS:
 16.1325 -            {
 16.1326 -              int bits = repBits[repSymbol];
 16.1327 -              int count = input.peekBits(bits);
 16.1328 -              if (count < 0)
 16.1329 -            return false;
 16.1330 -              input.dropBits(bits);
 16.1331 -              count += repMin[repSymbol];
 16.1332 -    //  	      System.err.println("litdistLens repeated: "+count);
 16.1333 -
 16.1334 -              if (ptr + count > num)
 16.1335 -            throw new DataFormatException();
 16.1336 -              while (count-- > 0)
 16.1337 -            litdistLens[ptr++] = lastLen;
 16.1338 -
 16.1339 -              if (ptr == num)
 16.1340 -            {
 16.1341 -              /* Finished */
 16.1342 -              return true;
 16.1343 -            }
 16.1344 -            }
 16.1345 -            mode = LENS;
 16.1346 -            continue decode_loop;
 16.1347 -          }
 16.1348 -          }
 16.1349 -      }
 16.1350 -
 16.1351 -      public InflaterHuffmanTree buildLitLenTree() throws DataFormatException
 16.1352 -      {
 16.1353 -        byte[] litlenLens = new byte[lnum];
 16.1354 -        System.arraycopy(litdistLens, 0, litlenLens, 0, lnum);
 16.1355 -        return new InflaterHuffmanTree(litlenLens);
 16.1356 -      }
 16.1357 -
 16.1358 -      public InflaterHuffmanTree buildDistTree() throws DataFormatException
 16.1359 -      {
 16.1360 -        byte[] distLens = new byte[dnum];
 16.1361 -        System.arraycopy(litdistLens, lnum, distLens, 0, dnum);
 16.1362 -        return new InflaterHuffmanTree(distLens);
 16.1363 -      }
 16.1364 -    }
 16.1365 -    /**
 16.1366 -     * This class allows us to retrieve a specified amount of bits from
 16.1367 -     * the input buffer, as well as copy big byte blocks.
 16.1368 -     *
 16.1369 -     * It uses an int buffer to store up to 31 bits for direct
 16.1370 -     * manipulation.  This guarantees that we can get at least 16 bits,
 16.1371 -     * but we only need at most 15, so this is all safe.
 16.1372 -     *
 16.1373 -     * There are some optimizations in this class, for example, you must
 16.1374 -     * never peek more then 8 bits more than needed, and you must first 
 16.1375 -     * peek bits before you may drop them.  This is not a general purpose
 16.1376 -     * class but optimized for the behaviour of the Inflater.
 16.1377 -     *
 16.1378 -     * @author John Leuner, Jochen Hoenicke
 16.1379 -     */
 16.1380 -
 16.1381 -    private static class StreamManipulator
 16.1382 -    {
 16.1383 -      private byte[] window;
 16.1384 -      private int window_start = 0;
 16.1385 -      private int window_end = 0;
 16.1386 -
 16.1387 -      private int buffer = 0;
 16.1388 -      private int bits_in_buffer = 0;
 16.1389 -
 16.1390 -      /**
 16.1391 -       * Get the next n bits but don't increase input pointer.  n must be
 16.1392 -       * less or equal 16 and if you if this call succeeds, you must drop
 16.1393 -       * at least n-8 bits in the next call.
 16.1394 -       * 
 16.1395 -       * @return the value of the bits, or -1 if not enough bits available.  */
 16.1396 -      public final int peekBits(int n)
 16.1397 -      {
 16.1398 -        if (bits_in_buffer < n)
 16.1399 -          {
 16.1400 -        if (window_start == window_end)
 16.1401 -          return -1;
 16.1402 -        buffer |= (window[window_start++] & 0xff
 16.1403 -               | (window[window_start++] & 0xff) << 8) << bits_in_buffer;
 16.1404 -        bits_in_buffer += 16;
 16.1405 -          }
 16.1406 -        return buffer & ((1 << n) - 1);
 16.1407 -      }
 16.1408 -
 16.1409 -      /* Drops the next n bits from the input.  You should have called peekBits
 16.1410 -       * with a bigger or equal n before, to make sure that enough bits are in
 16.1411 -       * the bit buffer.
 16.1412 -       */
 16.1413 -      public final void dropBits(int n)
 16.1414 -      {
 16.1415 -        buffer >>>= n;
 16.1416 -        bits_in_buffer -= n;
 16.1417 -      }
 16.1418 -
 16.1419 -      /**
 16.1420 -       * Gets the next n bits and increases input pointer.  This is equivalent
 16.1421 -       * to peekBits followed by dropBits, except for correct error handling.
 16.1422 -       * @return the value of the bits, or -1 if not enough bits available. 
 16.1423 -       */
 16.1424 -      public final int getBits(int n)
 16.1425 -      {
 16.1426 -        int bits = peekBits(n);
 16.1427 -        if (bits >= 0)
 16.1428 -          dropBits(n);
 16.1429 -        return bits;
 16.1430 -      }
 16.1431 -      /**
 16.1432 -       * Gets the number of bits available in the bit buffer.  This must be
 16.1433 -       * only called when a previous peekBits() returned -1.
 16.1434 -       * @return the number of bits available.
 16.1435 -       */
 16.1436 -      public final int getAvailableBits()
 16.1437 -      {
 16.1438 -        return bits_in_buffer;
 16.1439 -      }
 16.1440 -
 16.1441 -      /**
 16.1442 -       * Gets the number of bytes available.  
 16.1443 -       * @return the number of bytes available.
 16.1444 -       */
 16.1445 -      public final int getAvailableBytes()
 16.1446 -      {
 16.1447 -        return window_end - window_start + (bits_in_buffer >> 3);
 16.1448 -      }
 16.1449 -
 16.1450 -      /**
 16.1451 -       * Skips to the next byte boundary.
 16.1452 -       */
 16.1453 -      public void skipToByteBoundary()
 16.1454 -      {
 16.1455 -        buffer >>= (bits_in_buffer & 7);
 16.1456 -        bits_in_buffer &= ~7;
 16.1457 -      }
 16.1458 -
 16.1459 -      public final boolean needsInput() {
 16.1460 -        return window_start == window_end;
 16.1461 -      }
 16.1462 -
 16.1463 -
 16.1464 -      /* Copies length bytes from input buffer to output buffer starting
 16.1465 -       * at output[offset].  You have to make sure, that the buffer is
 16.1466 -       * byte aligned.  If not enough bytes are available, copies fewer
 16.1467 -       * bytes.
 16.1468 -       * @param length the length to copy, 0 is allowed.
 16.1469 -       * @return the number of bytes copied, 0 if no byte is available.  
 16.1470 -       */
 16.1471 -      public int copyBytes(byte[] output, int offset, int length)
 16.1472 -      {
 16.1473 -        if (length < 0)
 16.1474 -          throw new IllegalArgumentException("length negative");
 16.1475 -        if ((bits_in_buffer & 7) != 0)  
 16.1476 -          /* bits_in_buffer may only be 0 or 8 */
 16.1477 -          throw new IllegalStateException("Bit buffer is not aligned!");
 16.1478 -
 16.1479 -        int count = 0;
 16.1480 -        while (bits_in_buffer > 0 && length > 0)
 16.1481 -          {
 16.1482 -        output[offset++] = (byte) buffer;
 16.1483 -        buffer >>>= 8;
 16.1484 -        bits_in_buffer -= 8;
 16.1485 -        length--;
 16.1486 -        count++;
 16.1487 -          }
 16.1488 -        if (length == 0)
 16.1489 -          return count;
 16.1490 -
 16.1491 -        int avail = window_end - window_start;
 16.1492 -        if (length > avail)
 16.1493 -          length = avail;
 16.1494 -        System.arraycopy(window, window_start, output, offset, length);
 16.1495 -        window_start += length;
 16.1496 -
 16.1497 -        if (((window_start - window_end) & 1) != 0)
 16.1498 -          {
 16.1499 -        /* We always want an even number of bytes in input, see peekBits */
 16.1500 -        buffer = (window[window_start++] & 0xff);
 16.1501 -        bits_in_buffer = 8;
 16.1502 -          }
 16.1503 -        return count + length;
 16.1504 -      }
 16.1505 -
 16.1506 -      public StreamManipulator()
 16.1507 -      {
 16.1508 -      }
 16.1509 -
 16.1510 -      public void reset()
 16.1511 -      {
 16.1512 -        window_start = window_end = buffer = bits_in_buffer = 0;
 16.1513 -      }
 16.1514 -
 16.1515 -      public void setInput(byte[] buf, int off, int len)
 16.1516 -      {
 16.1517 -        if (window_start < window_end)
 16.1518 -          throw new IllegalStateException
 16.1519 -        ("Old input was not completely processed");
 16.1520 -
 16.1521 -        int end = off + len;
 16.1522 -
 16.1523 -        /* We want to throw an ArrayIndexOutOfBoundsException early.  The
 16.1524 -         * check is very tricky: it also handles integer wrap around.  
 16.1525 -         */
 16.1526 -        if (0 > off || off > end || end > buf.length)
 16.1527 -          throw new ArrayIndexOutOfBoundsException();
 16.1528 -
 16.1529 -        if ((len & 1) != 0)
 16.1530 -          {
 16.1531 -        /* We always want an even number of bytes in input, see peekBits */
 16.1532 -        buffer |= (buf[off++] & 0xff) << bits_in_buffer;
 16.1533 -        bits_in_buffer += 8;
 16.1534 -          }
 16.1535 -
 16.1536 -        window = buf;
 16.1537 -        window_start = off;
 16.1538 -        window_end = end;
 16.1539 -      }
 16.1540 -    }
 16.1541 -    /*
 16.1542 -     * Contains the output from the Inflation process.
 16.1543 -     *
 16.1544 -     * We need to have a window so that we can refer backwards into the output stream
 16.1545 -     * to repeat stuff.
 16.1546 -     *
 16.1547 -     * @author John Leuner
 16.1548 -     * @since JDK 1.1
 16.1549 -     */
 16.1550 -
 16.1551 -    private static class OutputWindow
 16.1552 -    {
 16.1553 -      private final int WINDOW_SIZE = 1 << 15;
 16.1554 -      private final int WINDOW_MASK = WINDOW_SIZE - 1;
 16.1555 -
 16.1556 -      private byte[] window = new byte[WINDOW_SIZE]; //The window is 2^15 bytes
 16.1557 -      private int window_end  = 0;
 16.1558 -      private int window_filled = 0;
 16.1559 -
 16.1560 -      public void write(int abyte)
 16.1561 -      {
 16.1562 -        if (window_filled++ == WINDOW_SIZE)
 16.1563 -          throw new IllegalStateException("Window full");
 16.1564 -        window[window_end++] = (byte) abyte;
 16.1565 -        window_end &= WINDOW_MASK;
 16.1566 -      }
 16.1567 -
 16.1568 -
 16.1569 -      private final void slowRepeat(int rep_start, int len, int dist)
 16.1570 -      {
 16.1571 -        while (len-- > 0)
 16.1572 -          {
 16.1573 -        window[window_end++] = window[rep_start++];
 16.1574 -        window_end &= WINDOW_MASK;
 16.1575 -        rep_start &= WINDOW_MASK;
 16.1576 -          }
 16.1577 -      }
 16.1578 -
 16.1579 -      public void repeat(int len, int dist)
 16.1580 -      {
 16.1581 -        if ((window_filled += len) > WINDOW_SIZE)
 16.1582 -          throw new IllegalStateException("Window full");
 16.1583 -
 16.1584 -        int rep_start = (window_end - dist) & WINDOW_MASK;
 16.1585 -        int border = WINDOW_SIZE - len;
 16.1586 -        if (rep_start <= border && window_end < border)
 16.1587 -          {
 16.1588 -        if (len <= dist)
 16.1589 -          {
 16.1590 -            System.arraycopy(window, rep_start, window, window_end, len);
 16.1591 -            window_end += len;
 16.1592 -          }
 16.1593 -        else
 16.1594 -          {
 16.1595 -            /* We have to copy manually, since the repeat pattern overlaps.
 16.1596 -             */
 16.1597 -            while (len-- > 0)
 16.1598 -              window[window_end++] = window[rep_start++];
 16.1599 -          }
 16.1600 -          }
 16.1601 -        else
 16.1602 -          slowRepeat(rep_start, len, dist);
 16.1603 -      }
 16.1604 -
 16.1605 -      public int copyStored(StreamManipulator input, int len)
 16.1606 -      {
 16.1607 -        len = Math.min(Math.min(len, WINDOW_SIZE - window_filled), 
 16.1608 -               input.getAvailableBytes());
 16.1609 -        int copied;
 16.1610 -
 16.1611 -        int tailLen = WINDOW_SIZE - window_end;
 16.1612 -        if (len > tailLen)
 16.1613 -          {
 16.1614 -        copied = input.copyBytes(window, window_end, tailLen);
 16.1615 -        if (copied == tailLen)
 16.1616 -          copied += input.copyBytes(window, 0, len - tailLen);
 16.1617 -          }
 16.1618 -        else
 16.1619 -          copied = input.copyBytes(window, window_end, len);
 16.1620 -
 16.1621 -        window_end = (window_end + copied) & WINDOW_MASK;
 16.1622 -        window_filled += copied;
 16.1623 -        return copied;
 16.1624 -      }
 16.1625 -
 16.1626 -      public void copyDict(byte[] dict, int offset, int len)
 16.1627 -      {
 16.1628 -        if (window_filled > 0)
 16.1629 -          throw new IllegalStateException();
 16.1630 -
 16.1631 -        if (len > WINDOW_SIZE)
 16.1632 -          {
 16.1633 -        offset += len - WINDOW_SIZE;
 16.1634 -        len = WINDOW_SIZE;
 16.1635 -          }
 16.1636 -        System.arraycopy(dict, offset, window, 0, len);
 16.1637 -        window_end = len & WINDOW_MASK;
 16.1638 -      }
 16.1639 -
 16.1640 -      public int getFreeSpace()
 16.1641 -      {
 16.1642 -        return WINDOW_SIZE - window_filled;
 16.1643 -      }
 16.1644 -
 16.1645 -      public int getAvailable()
 16.1646 -      {
 16.1647 -        return window_filled;
 16.1648 -      }
 16.1649 -
 16.1650 -      public int copyOutput(byte[] output, int offset, int len)
 16.1651 -      {
 16.1652 -        int copy_end = window_end;
 16.1653 -        if (len > window_filled)
 16.1654 -          len = window_filled;
 16.1655 -        else
 16.1656 -          copy_end = (window_end - window_filled + len) & WINDOW_MASK;
 16.1657 -
 16.1658 -        int copied = len;
 16.1659 -        int tailLen = len - copy_end;
 16.1660 -
 16.1661 -        if (tailLen > 0)
 16.1662 -          {
 16.1663 -        System.arraycopy(window, WINDOW_SIZE - tailLen,
 16.1664 -                 output, offset, tailLen);
 16.1665 -        offset += tailLen;
 16.1666 -        len = copy_end;
 16.1667 -          }
 16.1668 -        System.arraycopy(window, copy_end - len, output, offset, len);
 16.1669 -        window_filled -= copied;
 16.1670 -        if (window_filled < 0)
 16.1671 -          throw new IllegalStateException();
 16.1672 -        return copied;
 16.1673 -      }
 16.1674 -
 16.1675 -      public void reset() {
 16.1676 -        window_filled = window_end = 0;
 16.1677 -      }
 16.1678 -    }
 16.1679 -  
 16.1680  }
    17.1 --- a/emul/mini/src/main/java/java/util/zip/ZipConstants64.java	Tue Feb 19 15:33:32 2013 +0100
    17.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.3 @@ -1,84 +0,0 @@
    17.4 -/*
    17.5 - * Copyright (c) 1995, 1996, 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.util.zip;
   17.30 -
   17.31 -/*
   17.32 - * This class defines the constants that are used by the classes
   17.33 - * which manipulate Zip64 files.
   17.34 - */
   17.35 -
   17.36 -class ZipConstants64 {
   17.37 -
   17.38 -    /*
   17.39 -     * ZIP64 constants
   17.40 -     */
   17.41 -    static final long ZIP64_ENDSIG = 0x06064b50L;  // "PK\006\006"
   17.42 -    static final long ZIP64_LOCSIG = 0x07064b50L;  // "PK\006\007"
   17.43 -    static final int  ZIP64_ENDHDR = 56;           // ZIP64 end header size
   17.44 -    static final int  ZIP64_LOCHDR = 20;           // ZIP64 end loc header size
   17.45 -    static final int  ZIP64_EXTHDR = 24;           // EXT header size
   17.46 -    static final int  ZIP64_EXTID  = 0x0001;       // Extra field Zip64 header ID
   17.47 -
   17.48 -    static final int  ZIP64_MAGICCOUNT = 0xFFFF;
   17.49 -    static final long ZIP64_MAGICVAL = 0xFFFFFFFFL;
   17.50 -
   17.51 -    /*
   17.52 -     * Zip64 End of central directory (END) header field offsets
   17.53 -     */
   17.54 -    static final int  ZIP64_ENDLEN = 4;       // size of zip64 end of central dir
   17.55 -    static final int  ZIP64_ENDVEM = 12;      // version made by
   17.56 -    static final int  ZIP64_ENDVER = 14;      // version needed to extract
   17.57 -    static final int  ZIP64_ENDNMD = 16;      // number of this disk
   17.58 -    static final int  ZIP64_ENDDSK = 20;      // disk number of start
   17.59 -    static final int  ZIP64_ENDTOD = 24;      // total number of entries on this disk
   17.60 -    static final int  ZIP64_ENDTOT = 32;      // total number of entries
   17.61 -    static final int  ZIP64_ENDSIZ = 40;      // central directory size in bytes
   17.62 -    static final int  ZIP64_ENDOFF = 48;      // offset of first CEN header
   17.63 -    static final int  ZIP64_ENDEXT = 56;      // zip64 extensible data sector
   17.64 -
   17.65 -    /*
   17.66 -     * Zip64 End of central directory locator field offsets
   17.67 -     */
   17.68 -    static final int  ZIP64_LOCDSK = 4;       // disk number start
   17.69 -    static final int  ZIP64_LOCOFF = 8;       // offset of zip64 end
   17.70 -    static final int  ZIP64_LOCTOT = 16;      // total number of disks
   17.71 -
   17.72 -    /*
   17.73 -     * Zip64 Extra local (EXT) header field offsets
   17.74 -     */
   17.75 -    static final int  ZIP64_EXTCRC = 4;       // uncompressed file crc-32 value
   17.76 -    static final int  ZIP64_EXTSIZ = 8;       // compressed size, 8-byte
   17.77 -    static final int  ZIP64_EXTLEN = 16;      // uncompressed size, 8-byte
   17.78 -
   17.79 -    /*
   17.80 -     * Language encoding flag EFS
   17.81 -     */
   17.82 -    static final int EFS = 0x800;       // If this bit is set the filename and
   17.83 -                                        // comment fields for this file must be
   17.84 -                                        // encoded using UTF-8.
   17.85 -
   17.86 -    private ZipConstants64() {}
   17.87 -}
    18.1 --- a/emul/mini/src/main/java/java/util/zip/ZipInputStream.java	Tue Feb 19 15:33:32 2013 +0100
    18.2 +++ b/emul/mini/src/main/java/java/util/zip/ZipInputStream.java	Tue Feb 19 15:59:27 2013 +0100
    18.3 @@ -27,10 +27,6 @@
    18.4  
    18.5  import java.io.InputStream;
    18.6  import java.io.IOException;
    18.7 -import java.io.EOFException;
    18.8 -import java.io.PushbackInputStream;
    18.9 -import static java.util.zip.ZipConstants64.*;
   18.10 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
   18.11  
   18.12  /**
   18.13   * This class implements an input stream filter for reading files in the
   18.14 @@ -41,28 +37,7 @@
   18.15   */
   18.16  public
   18.17  class ZipInputStream extends InflaterInputStream implements ZipConstants {
   18.18 -    private ZipEntry entry;
   18.19 -    private int flag;
   18.20 -    private CRC32 crc = new CRC32();
   18.21 -    private long remaining;
   18.22 -    private byte[] tmpbuf = new byte[512];
   18.23 -
   18.24 -    private static final int STORED = ZipEntry.STORED;
   18.25 -    private static final int DEFLATED = ZipEntry.DEFLATED;
   18.26 -
   18.27 -    private boolean closed = false;
   18.28 -    // this flag is set to true after EOF has reached for
   18.29 -    // one entry
   18.30 -    private boolean entryEOF = false;
   18.31 -
   18.32 -    /**
   18.33 -     * Check to make sure that this stream has not been closed
   18.34 -     */
   18.35 -    private void ensureOpen() throws IOException {
   18.36 -        if (closed) {
   18.37 -            throw new IOException("Stream closed");
   18.38 -        }
   18.39 -    }
   18.40 +    private final org.apidesign.bck2brwsr.emul.zip.ZipInputStream impl;
   18.41  
   18.42      /**
   18.43       * Creates a new ZIP input stream.
   18.44 @@ -73,12 +48,8 @@
   18.45       * @param in the actual input stream
   18.46       */
   18.47      public ZipInputStream(InputStream in) {
   18.48 -//        this(in, "UTF-8");
   18.49 -        super(new PushbackInputStream(in, 512), new Inflater(true), 512);
   18.50 -        usesDefaultInflater = true;
   18.51 -        if(in == null) {
   18.52 -            throw new NullPointerException("in is null");
   18.53 -        }
   18.54 +        super(in);
   18.55 +        impl = new org.apidesign.bck2brwsr.emul.zip.ZipInputStream(in);
   18.56      }
   18.57  
   18.58      /**
   18.59 @@ -115,20 +86,7 @@
   18.60       * @exception IOException if an I/O error has occurred
   18.61       */
   18.62      public ZipEntry getNextEntry() throws IOException {
   18.63 -        ensureOpen();
   18.64 -        if (entry != null) {
   18.65 -            closeEntry();
   18.66 -        }
   18.67 -        crc.reset();
   18.68 -        inf.reset();
   18.69 -        if ((entry = readLOC()) == null) {
   18.70 -            return null;
   18.71 -        }
   18.72 -        if (entry.method == STORED) {
   18.73 -            remaining = entry.size;
   18.74 -        }
   18.75 -        entryEOF = false;
   18.76 -        return entry;
   18.77 +        return impl.getNextEntry();
   18.78      }
   18.79  
   18.80      /**
   18.81 @@ -138,9 +96,7 @@
   18.82       * @exception IOException if an I/O error has occurred
   18.83       */
   18.84      public void closeEntry() throws IOException {
   18.85 -        ensureOpen();
   18.86 -        while (read(tmpbuf, 0, tmpbuf.length) != -1) ;
   18.87 -        entryEOF = true;
   18.88 +        impl.closeEntry();
   18.89      }
   18.90  
   18.91      /**
   18.92 @@ -155,12 +111,7 @@
   18.93       *
   18.94       */
   18.95      public int available() throws IOException {
   18.96 -        ensureOpen();
   18.97 -        if (entryEOF) {
   18.98 -            return 0;
   18.99 -        } else {
  18.100 -            return 1;
  18.101 -        }
  18.102 +        return impl.available();
  18.103      }
  18.104  
  18.105      /**
  18.106 @@ -181,51 +132,7 @@
  18.107       * @exception IOException if an I/O error has occurred
  18.108       */
  18.109      public int read(byte[] b, int off, int len) throws IOException {
  18.110 -        ensureOpen();
  18.111 -        if (off < 0 || len < 0 || off > b.length - len) {
  18.112 -            throw new IndexOutOfBoundsException();
  18.113 -        } else if (len == 0) {
  18.114 -            return 0;
  18.115 -        }
  18.116 -
  18.117 -        if (entry == null) {
  18.118 -            return -1;
  18.119 -        }
  18.120 -        switch (entry.method) {
  18.121 -        case DEFLATED:
  18.122 -            len = super.read(b, off, len);
  18.123 -            if (len == -1) {
  18.124 -                readEnd(entry);
  18.125 -                entryEOF = true;
  18.126 -                entry = null;
  18.127 -            } else {
  18.128 -                crc.update(b, off, len);
  18.129 -            }
  18.130 -            return len;
  18.131 -        case STORED:
  18.132 -            if (remaining <= 0) {
  18.133 -                entryEOF = true;
  18.134 -                entry = null;
  18.135 -                return -1;
  18.136 -            }
  18.137 -            if (len > remaining) {
  18.138 -                len = (int)remaining;
  18.139 -            }
  18.140 -            len = in.read(b, off, len);
  18.141 -            if (len == -1) {
  18.142 -                throw new ZipException("unexpected EOF");
  18.143 -            }
  18.144 -            crc.update(b, off, len);
  18.145 -            remaining -= len;
  18.146 -            if (remaining == 0 && entry.crc != crc.getValue()) {
  18.147 -                throw new ZipException(
  18.148 -                    "invalid entry CRC (expected 0x" + Long.toHexString(entry.crc) +
  18.149 -                    " but got 0x" + Long.toHexString(crc.getValue()) + ")");
  18.150 -            }
  18.151 -            return len;
  18.152 -        default:
  18.153 -            throw new ZipException("invalid compression method");
  18.154 -        }
  18.155 +        return impl.read(b, off, len);
  18.156      }
  18.157  
  18.158      /**
  18.159 @@ -237,25 +144,7 @@
  18.160       * @exception IllegalArgumentException if n < 0
  18.161       */
  18.162      public long skip(long n) throws IOException {
  18.163 -        if (n < 0) {
  18.164 -            throw new IllegalArgumentException("negative skip length");
  18.165 -        }
  18.166 -        ensureOpen();
  18.167 -        int max = (int)Math.min(n, Integer.MAX_VALUE);
  18.168 -        int total = 0;
  18.169 -        while (total < max) {
  18.170 -            int len = max - total;
  18.171 -            if (len > tmpbuf.length) {
  18.172 -                len = tmpbuf.length;
  18.173 -            }
  18.174 -            len = read(tmpbuf, 0, len);
  18.175 -            if (len == -1) {
  18.176 -                entryEOF = true;
  18.177 -                break;
  18.178 -            }
  18.179 -            total += len;
  18.180 -        }
  18.181 -        return total;
  18.182 +        return impl.skip(n);
  18.183      }
  18.184  
  18.185      /**
  18.186 @@ -264,89 +153,7 @@
  18.187       * @exception IOException if an I/O error has occurred
  18.188       */
  18.189      public void close() throws IOException {
  18.190 -        if (!closed) {
  18.191 -            super.close();
  18.192 -            closed = true;
  18.193 -        }
  18.194 -    }
  18.195 -
  18.196 -    private byte[] b = new byte[256];
  18.197 -
  18.198 -    /*
  18.199 -     * Reads local file (LOC) header for next entry.
  18.200 -     */
  18.201 -    private ZipEntry readLOC() throws IOException {
  18.202 -        try {
  18.203 -            readFully(tmpbuf, 0, LOCHDR);
  18.204 -        } catch (EOFException e) {
  18.205 -            return null;
  18.206 -        }
  18.207 -        if (get32(tmpbuf, 0) != LOCSIG) {
  18.208 -            return null;
  18.209 -        }
  18.210 -        // get flag first, we need check EFS.
  18.211 -        flag = get16(tmpbuf, LOCFLG);
  18.212 -        // get the entry name and create the ZipEntry first
  18.213 -        int len = get16(tmpbuf, LOCNAM);
  18.214 -        int blen = b.length;
  18.215 -        if (len > blen) {
  18.216 -            do
  18.217 -                blen = blen * 2;
  18.218 -            while (len > blen);
  18.219 -            b = new byte[blen];
  18.220 -        }
  18.221 -        readFully(b, 0, len);
  18.222 -        // Force to use UTF-8 if the EFS bit is ON, even the cs is NOT UTF-8
  18.223 -        ZipEntry e = createZipEntry(((flag & EFS) != 0)
  18.224 -                                    ? toStringUTF8(b, len)
  18.225 -                                    : toString(b, len));
  18.226 -        // now get the remaining fields for the entry
  18.227 -        if ((flag & 1) == 1) {
  18.228 -            throw new ZipException("encrypted ZIP entry not supported");
  18.229 -        }
  18.230 -        e.method = get16(tmpbuf, LOCHOW);
  18.231 -        e.time = get32(tmpbuf, LOCTIM);
  18.232 -        if ((flag & 8) == 8) {
  18.233 -            /* "Data Descriptor" present */
  18.234 -            if (e.method != DEFLATED) {
  18.235 -                throw new ZipException(
  18.236 -                        "only DEFLATED entries can have EXT descriptor");
  18.237 -            }
  18.238 -        } else {
  18.239 -            e.crc = get32(tmpbuf, LOCCRC);
  18.240 -            e.csize = get32(tmpbuf, LOCSIZ);
  18.241 -            e.size = get32(tmpbuf, LOCLEN);
  18.242 -        }
  18.243 -        len = get16(tmpbuf, LOCEXT);
  18.244 -        if (len > 0) {
  18.245 -            byte[] bb = new byte[len];
  18.246 -            readFully(bb, 0, len);
  18.247 -            e.setExtra(bb);
  18.248 -            // extra fields are in "HeaderID(2)DataSize(2)Data... format
  18.249 -            if (e.csize == ZIP64_MAGICVAL || e.size == ZIP64_MAGICVAL) {
  18.250 -                int off = 0;
  18.251 -                while (off + 4 < len) {
  18.252 -                    int sz = get16(bb, off + 2);
  18.253 -                    if (get16(bb, off) == ZIP64_EXTID) {
  18.254 -                        off += 4;
  18.255 -                        // LOC extra zip64 entry MUST include BOTH original and
  18.256 -                        // compressed file size fields
  18.257 -                        if (sz < 16 || (off + sz) > len ) {
  18.258 -                            // Invalid zip64 extra fields, simply skip. Even it's
  18.259 -                            // rare, it's possible the entry size happens to be
  18.260 -                            // the magic value and it "accidnetly" has some bytes
  18.261 -                            // in extra match the id.
  18.262 -                            return e;
  18.263 -                        }
  18.264 -                        e.size = get64(bb, off);
  18.265 -                        e.csize = get64(bb, off + 8);
  18.266 -                        break;
  18.267 -                    }
  18.268 -                    off += (sz + 4);
  18.269 -                }
  18.270 -            }
  18.271 -        }
  18.272 -        return e;
  18.273 +        impl.close();
  18.274      }
  18.275  
  18.276      /**
  18.277 @@ -360,108 +167,28 @@
  18.278          return new ZipEntry(name);
  18.279      }
  18.280  
  18.281 -    /*
  18.282 -     * Reads end of deflated entry as well as EXT descriptor if present.
  18.283 -     */
  18.284 -    private void readEnd(ZipEntry e) throws IOException {
  18.285 -        int n = inf.getRemaining();
  18.286 -        if (n > 0) {
  18.287 -            ((PushbackInputStream)in).unread(buf, len - n, n);
  18.288 -        }
  18.289 -        if ((flag & 8) == 8) {
  18.290 -            /* "Data Descriptor" present */
  18.291 -            if (inf.getBytesWritten() > ZIP64_MAGICVAL ||
  18.292 -                inf.getBytesRead() > ZIP64_MAGICVAL) {
  18.293 -                // ZIP64 format
  18.294 -                readFully(tmpbuf, 0, ZIP64_EXTHDR);
  18.295 -                long sig = get32(tmpbuf, 0);
  18.296 -                if (sig != EXTSIG) { // no EXTSIG present
  18.297 -                    e.crc = sig;
  18.298 -                    e.csize = get64(tmpbuf, ZIP64_EXTSIZ - ZIP64_EXTCRC);
  18.299 -                    e.size = get64(tmpbuf, ZIP64_EXTLEN - ZIP64_EXTCRC);
  18.300 -                    ((PushbackInputStream)in).unread(
  18.301 -                        tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC - 1, ZIP64_EXTCRC);
  18.302 -                } else {
  18.303 -                    e.crc = get32(tmpbuf, ZIP64_EXTCRC);
  18.304 -                    e.csize = get64(tmpbuf, ZIP64_EXTSIZ);
  18.305 -                    e.size = get64(tmpbuf, ZIP64_EXTLEN);
  18.306 -                }
  18.307 -            } else {
  18.308 -                readFully(tmpbuf, 0, EXTHDR);
  18.309 -                long sig = get32(tmpbuf, 0);
  18.310 -                if (sig != EXTSIG) { // no EXTSIG present
  18.311 -                    e.crc = sig;
  18.312 -                    e.csize = get32(tmpbuf, EXTSIZ - EXTCRC);
  18.313 -                    e.size = get32(tmpbuf, EXTLEN - EXTCRC);
  18.314 -                    ((PushbackInputStream)in).unread(
  18.315 -                                               tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC);
  18.316 -                } else {
  18.317 -                    e.crc = get32(tmpbuf, EXTCRC);
  18.318 -                    e.csize = get32(tmpbuf, EXTSIZ);
  18.319 -                    e.size = get32(tmpbuf, EXTLEN);
  18.320 -                }
  18.321 -            }
  18.322 -        }
  18.323 -        if (e.size != inf.getBytesWritten()) {
  18.324 -            throw new ZipException(
  18.325 -                "invalid entry size (expected " + e.size +
  18.326 -                " but got " + inf.getBytesWritten() + " bytes)");
  18.327 -        }
  18.328 -        if (e.csize != inf.getBytesRead()) {
  18.329 -            throw new ZipException(
  18.330 -                "invalid entry compressed size (expected " + e.csize +
  18.331 -                " but got " + inf.getBytesRead() + " bytes)");
  18.332 -        }
  18.333 -        if (e.crc != crc.getValue()) {
  18.334 -            throw new ZipException(
  18.335 -                "invalid entry CRC (expected 0x" + Long.toHexString(e.crc) +
  18.336 -                " but got 0x" + Long.toHexString(crc.getValue()) + ")");
  18.337 -        }
  18.338 +    @Override
  18.339 +    public int read() throws IOException {
  18.340 +        return impl.read();
  18.341      }
  18.342  
  18.343 -    /*
  18.344 -     * Reads bytes, blocking until all bytes are read.
  18.345 -     */
  18.346 -    private void readFully(byte[] b, int off, int len) throws IOException {
  18.347 -        while (len > 0) {
  18.348 -            int n = in.read(b, off, len);
  18.349 -            if (n == -1) {
  18.350 -                throw new EOFException();
  18.351 -            }
  18.352 -            off += n;
  18.353 -            len -= n;
  18.354 -        }
  18.355 +    @Override
  18.356 +    public boolean markSupported() {
  18.357 +        return impl.markSupported();
  18.358      }
  18.359  
  18.360 -    /*
  18.361 -     * Fetches unsigned 16-bit value from byte array at specified offset.
  18.362 -     * The bytes are assumed to be in Intel (little-endian) byte order.
  18.363 -     */
  18.364 -    private static final int get16(byte b[], int off) {
  18.365 -        return (b[off] & 0xff) | ((b[off+1] & 0xff) << 8);
  18.366 +    @Override
  18.367 +    public void mark(int readlimit) {
  18.368 +        impl.mark(readlimit);
  18.369      }
  18.370  
  18.371 -    /*
  18.372 -     * Fetches unsigned 32-bit value from byte array at specified offset.
  18.373 -     * The bytes are assumed to be in Intel (little-endian) byte order.
  18.374 -     */
  18.375 -    private static final long get32(byte b[], int off) {
  18.376 -        return (get16(b, off) | ((long)get16(b, off+2) << 16)) & 0xffffffffL;
  18.377 +    @Override
  18.378 +    public void reset() throws IOException {
  18.379 +        impl.reset();
  18.380      }
  18.381  
  18.382 -    /*
  18.383 -     * Fetches signed 64-bit value from byte array at specified offset.
  18.384 -     * The bytes are assumed to be in Intel (little-endian) byte order.
  18.385 -     */
  18.386 -    private static final long get64(byte b[], int off) {
  18.387 -        return get32(b, off) | (get32(b, off+4) << 32);
  18.388 -    }
  18.389 -
  18.390 -    private static String toStringUTF8(byte[] arr, int len) {
  18.391 -        return new String(arr, 0, len);
  18.392 -    }
  18.393 -    
  18.394 -    private static String toString(byte[] b, int len) {
  18.395 -        return new String(b, 0, len);
  18.396 +    @Override
  18.397 +    public int read(byte[] b) throws IOException {
  18.398 +        return impl.read(b);
  18.399      }
  18.400  }
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/ManifestInputStream.java	Tue Feb 19 15:59:27 2013 +0100
    19.3 @@ -0,0 +1,228 @@
    19.4 +/*
    19.5 + * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
    19.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    19.7 + *
    19.8 + * This code is free software; you can redistribute it and/or modify it
    19.9 + * under the terms of the GNU General Public License version 2 only, as
   19.10 + * published by the Free Software Foundation.  Oracle designates this
   19.11 + * particular file as subject to the "Classpath" exception as provided
   19.12 + * by Oracle in the LICENSE file that accompanied this code.
   19.13 + *
   19.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   19.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   19.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   19.17 + * version 2 for more details (a copy is included in the LICENSE file that
   19.18 + * accompanied this code).
   19.19 + *
   19.20 + * You should have received a copy of the GNU General Public License version
   19.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   19.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   19.23 + *
   19.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   19.25 + * or visit www.oracle.com if you need additional information or have any
   19.26 + * questions.
   19.27 + */
   19.28 +package org.apidesign.bck2brwsr.emul.lang;
   19.29 +
   19.30 +import java.io.FilterInputStream;
   19.31 +import java.io.IOException;
   19.32 +import java.io.InputStream;
   19.33 +
   19.34 +/*
   19.35 + * A fast buffered input stream for parsing manifest files.
   19.36 + * 
   19.37 + * Taken from java.util.jar.Manifest.FastInputStream and modified to be
   19.38 + * independent of other Manifest functionality.
   19.39 + */
   19.40 +public abstract class ManifestInputStream extends FilterInputStream {
   19.41 +    private byte[] buf;
   19.42 +    private int count = 0;
   19.43 +    private int pos = 0;
   19.44 +
   19.45 +    protected ManifestInputStream(InputStream in) {
   19.46 +        this(in, 8192);
   19.47 +    }
   19.48 +
   19.49 +    protected ManifestInputStream(InputStream in, int size) {
   19.50 +        super(in);
   19.51 +        buf = new byte[size];
   19.52 +    }
   19.53 +
   19.54 +    public int read() throws IOException {
   19.55 +        if (pos >= count) {
   19.56 +            fill();
   19.57 +            if (pos >= count) {
   19.58 +                return -1;
   19.59 +            }
   19.60 +        }
   19.61 +        return buf[pos++] & 0xff;
   19.62 +    }
   19.63 +
   19.64 +    public int read(byte[] b, int off, int len) throws IOException {
   19.65 +        int avail = count - pos;
   19.66 +        if (avail <= 0) {
   19.67 +            if (len >= buf.length) {
   19.68 +                return in.read(b, off, len);
   19.69 +            }
   19.70 +            fill();
   19.71 +            avail = count - pos;
   19.72 +            if (avail <= 0) {
   19.73 +                return -1;
   19.74 +            }
   19.75 +        }
   19.76 +        if (len > avail) {
   19.77 +            len = avail;
   19.78 +        }
   19.79 +        System.arraycopy(buf, pos, b, off, len);
   19.80 +        pos += len;
   19.81 +        return len;
   19.82 +    }
   19.83 +
   19.84 +    /*
   19.85 +     * Reads 'len' bytes from the input stream, or until an end-of-line
   19.86 +     * is reached. Returns the number of bytes read.
   19.87 +     */
   19.88 +    public int readLine(byte[] b, int off, int len) throws IOException {
   19.89 +        byte[] tbuf = this.buf;
   19.90 +        int total = 0;
   19.91 +        while (total < len) {
   19.92 +            int avail = count - pos;
   19.93 +            if (avail <= 0) {
   19.94 +                fill();
   19.95 +                avail = count - pos;
   19.96 +                if (avail <= 0) {
   19.97 +                    return -1;
   19.98 +                }
   19.99 +            }
  19.100 +            int n = len - total;
  19.101 +            if (n > avail) {
  19.102 +                n = avail;
  19.103 +            }
  19.104 +            int tpos = pos;
  19.105 +            int maxpos = tpos + n;
  19.106 +            while (tpos < maxpos && tbuf[tpos++] != '\n') {
  19.107 +                ;
  19.108 +            }
  19.109 +            n = tpos - pos;
  19.110 +            System.arraycopy(tbuf, pos, b, off, n);
  19.111 +            off += n;
  19.112 +            total += n;
  19.113 +            pos = tpos;
  19.114 +            if (tbuf[tpos - 1] == '\n') {
  19.115 +                break;
  19.116 +            }
  19.117 +        }
  19.118 +        return total;
  19.119 +    }
  19.120 +
  19.121 +    public byte peek() throws IOException {
  19.122 +        if (pos == count) {
  19.123 +            fill();
  19.124 +        }
  19.125 +        if (pos == count) {
  19.126 +            return -1; // nothing left in buffer
  19.127 +        }
  19.128 +        return buf[pos];
  19.129 +    }
  19.130 +
  19.131 +    public int readLine(byte[] b) throws IOException {
  19.132 +        return readLine(b, 0, b.length);
  19.133 +    }
  19.134 +
  19.135 +    public long skip(long n) throws IOException {
  19.136 +        if (n <= 0) {
  19.137 +            return 0;
  19.138 +        }
  19.139 +        long avail = count - pos;
  19.140 +        if (avail <= 0) {
  19.141 +            return in.skip(n);
  19.142 +        }
  19.143 +        if (n > avail) {
  19.144 +            n = avail;
  19.145 +        }
  19.146 +        pos += n;
  19.147 +        return n;
  19.148 +    }
  19.149 +
  19.150 +    public int available() throws IOException {
  19.151 +        return (count - pos) + in.available();
  19.152 +    }
  19.153 +
  19.154 +    public void close() throws IOException {
  19.155 +        if (in != null) {
  19.156 +            in.close();
  19.157 +            in = null;
  19.158 +            buf = null;
  19.159 +        }
  19.160 +    }
  19.161 +
  19.162 +    private void fill() throws IOException {
  19.163 +        count = pos = 0;
  19.164 +        int n = in.read(buf, 0, buf.length);
  19.165 +        if (n > 0) {
  19.166 +            count = n;
  19.167 +        }
  19.168 +    }
  19.169 +    
  19.170 +    protected abstract String putValue(String key, String value);
  19.171 +
  19.172 +    public void readAttributes(byte[] lbuf) throws IOException {
  19.173 +        ManifestInputStream is = this;
  19.174 +
  19.175 +        String name = null;
  19.176 +        String value = null;
  19.177 +        byte[] lastline = null;
  19.178 +        int len;
  19.179 +        while ((len = is.readLine(lbuf)) != -1) {
  19.180 +            boolean lineContinued = false;
  19.181 +            if (lbuf[--len] != '\n') {
  19.182 +                throw new IOException("line too long");
  19.183 +            }
  19.184 +            if (len > 0 && lbuf[len - 1] == '\r') {
  19.185 +                --len;
  19.186 +            }
  19.187 +            if (len == 0) {
  19.188 +                break;
  19.189 +            }
  19.190 +            int i = 0;
  19.191 +            if (lbuf[0] == ' ') {
  19.192 +                if (name == null) {
  19.193 +                    throw new IOException("misplaced continuation line");
  19.194 +                }
  19.195 +                lineContinued = true;
  19.196 +                byte[] buf = new byte[lastline.length + len - 1];
  19.197 +                System.arraycopy(lastline, 0, buf, 0, lastline.length);
  19.198 +                System.arraycopy(lbuf, 1, buf, lastline.length, len - 1);
  19.199 +                if (is.peek() == ' ') {
  19.200 +                    lastline = buf;
  19.201 +                    continue;
  19.202 +                }
  19.203 +                value = new String(buf, 0, buf.length, "UTF8");
  19.204 +                lastline = null;
  19.205 +            } else {
  19.206 +                while (lbuf[i++] != ':') {
  19.207 +                    if (i >= len) {
  19.208 +                        throw new IOException("invalid header field");
  19.209 +                    }
  19.210 +                }
  19.211 +                if (lbuf[i++] != ' ') {
  19.212 +                    throw new IOException("invalid header field");
  19.213 +                }
  19.214 +                name = new String(lbuf, 0, 0, i - 2);
  19.215 +                if (is.peek() == ' ') {
  19.216 +                    lastline = new byte[len - i];
  19.217 +                    System.arraycopy(lbuf, i, lastline, 0, len - i);
  19.218 +                    continue;
  19.219 +                }
  19.220 +                value = new String(lbuf, i, len - i, "UTF8");
  19.221 +            }
  19.222 +            try {
  19.223 +                if ((putValue(name, value) != null) && (!lineContinued)) {
  19.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.");
  19.225 +                }
  19.226 +            } catch (IllegalArgumentException e) {
  19.227 +                throw new IOException("invalid header field name: " + name);
  19.228 +            }
  19.229 +        }
  19.230 +    }
  19.231 +}
    20.1 --- a/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/System.java	Tue Feb 19 15:33:32 2013 +0100
    20.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/System.java	Tue Feb 19 15:59:27 2013 +0100
    20.3 @@ -17,6 +17,7 @@
    20.4   */
    20.5  package org.apidesign.bck2brwsr.emul.lang;
    20.6  
    20.7 +import java.lang.reflect.Method;
    20.8  import org.apidesign.bck2brwsr.core.JavaScriptBody;
    20.9  
   20.10  /**
   20.11 @@ -38,7 +39,15 @@
   20.12          "    }\n" +
   20.13          "}"
   20.14      )
   20.15 -    public static native void arraycopy(Object value, int srcBegin, Object dst, int dstBegin, int count);
   20.16 +    public static void arraycopy(Object src, int srcBegin, Object dst, int dstBegin, int count) {
   20.17 +        try {
   20.18 +            Class<?> system = Class.forName("java.lang.System");
   20.19 +            Method m = system.getMethod("arraycopy", Object.class, int.class, Object.class, int.class, int.class);
   20.20 +            m.invoke(null, src, srcBegin, dst, dstBegin, count);
   20.21 +        } catch (Exception ex) {
   20.22 +            throw new IllegalStateException(ex);
   20.23 +        }
   20.24 +    }
   20.25  
   20.26      @JavaScriptBody(args = { "arr", "expectedSize" }, body = 
   20.27          "while (expectedSize-- > arr.length) { arr.push(0); }; return arr;"
   20.28 @@ -53,5 +62,4 @@
   20.29      }
   20.30      @JavaScriptBody(args = { "obj" }, body="return vm.java_lang_Object(false).hashCode__I.call(obj);")
   20.31      public static native int identityHashCode(Object obj);
   20.32 -    
   20.33  }
    21.1 --- a/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/AnnotationImpl.java	Tue Feb 19 15:33:32 2013 +0100
    21.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/AnnotationImpl.java	Tue Feb 19 15:59:27 2013 +0100
    21.3 @@ -18,6 +18,8 @@
    21.4  package org.apidesign.bck2brwsr.emul.reflect;
    21.5  
    21.6  import java.lang.annotation.Annotation;
    21.7 +import java.lang.reflect.Method;
    21.8 +import java.lang.reflect.Modifier;
    21.9  import org.apidesign.bck2brwsr.core.JavaScriptBody;
   21.10  
   21.11  /**
   21.12 @@ -25,39 +27,73 @@
   21.13   * @author Jaroslav Tulach <jtulach@netbeans.org>
   21.14   */
   21.15  public final class AnnotationImpl implements Annotation {
   21.16 +    private final Class<? extends Annotation> type;
   21.17 +
   21.18 +    public AnnotationImpl(Class<? extends Annotation> type) {
   21.19 +        this.type = type;
   21.20 +    }
   21.21 +    
   21.22      public Class<? extends Annotation> annotationType() {
   21.23 -        return getClass();
   21.24 +        return type;
   21.25      }
   21.26  
   21.27 -    @JavaScriptBody(args = { "a", "n", "values" }, body = ""
   21.28 -        + "function f(v, p) {\n"
   21.29 -        + "  var val = v;\n"
   21.30 -        + "  var prop = p;\n"
   21.31 +    @JavaScriptBody(args = { "a", "n", "arr", "values" }, body = ""
   21.32 +        + "function f(val, prop, clazz) {\n"
   21.33          + "  return function() {\n"
   21.34 -        + "    return val[prop];\n"
   21.35 +        + "    if (clazz == null) return val[prop];\n"
   21.36 +        + "    if (clazz.isArray__Z()) {\n"
   21.37 +        + "      var valarr = val[prop];\n"
   21.38 +        + "      var cmp = clazz.getComponentType__Ljava_lang_Class_2();\n"
   21.39 +        + "      var retarr = vm.java_lang_reflect_Array(false).newInstance__Ljava_lang_Object_2Ljava_lang_Class_2I(cmp, valarr.length);\n"
   21.40 +        + "      for (var i = 0; i < valarr.length; i++) {\n"
   21.41 +        + "        retarr[i] = CLS.prototype.c__Ljava_lang_Object_2Ljava_lang_Class_2Ljava_lang_Object_2(cmp, valarr[i]);\n"
   21.42 +        + "      }\n"
   21.43 +        + "      return retarr;\n"
   21.44 +        + "    }\n"
   21.45 +        + "    return CLS.prototype.c__Ljava_lang_Object_2Ljava_lang_Class_2Ljava_lang_Object_2(clazz, val[prop]);\n"
   21.46          + "  };\n"
   21.47          + "}\n"
   21.48 -        + "var props = Object.getOwnPropertyNames(values);\n"
   21.49 -        + "for (var i = 0; i < props.length; i++) {\n"
   21.50 -        + "  var p = props[i];\n"
   21.51 -        + "  a[p] = new f(values, p);\n"
   21.52 +        + "for (var i = 0; i < arr.length; i += 3) {\n"
   21.53 +        + "  var m = arr[i];\n"
   21.54 +        + "  var p = arr[i + 1];\n"
   21.55 +        + "  var c = arr[i + 2];\n"
   21.56 +        + "  a[m] = f(values, p, c);\n"
   21.57          + "}\n"
   21.58          + "a['$instOf_' + n] = true;\n"
   21.59          + "return a;"
   21.60      )
   21.61 -    private static <T extends Annotation> T create(AnnotationImpl a, String n, Object values) {
   21.62 -        return null;
   21.63 +    private static native <T extends Annotation> T create(
   21.64 +        AnnotationImpl a, String n, Object[] methodsAndProps, Object values
   21.65 +    );
   21.66 +    
   21.67 +    private static Object c(Class<? extends Annotation> a, Object v) {
   21.68 +        return create(a, v);
   21.69      }
   21.70 +    
   21.71      public static <T extends Annotation> T create(Class<T> annoClass, Object values) {
   21.72 -        return create(new AnnotationImpl(), annoClass.getName().replace('.', '_'), values);
   21.73 +        return create(new AnnotationImpl(annoClass), 
   21.74 +            annoClass.getName().replace('.', '_'), 
   21.75 +            findProps(annoClass), values
   21.76 +        );
   21.77      }
   21.78  
   21.79      public static Annotation[] create(Object anno) {
   21.80          String[] names = findNames(anno);
   21.81          Annotation[] ret = new Annotation[names.length];
   21.82          for (int i = 0; i < names.length; i++) {
   21.83 -            String n = names[i].substring(1, names[i].length() - 1).replace('/', '_');
   21.84 -            ret[i] = create(new AnnotationImpl(), n, findData(anno, names[i]));
   21.85 +            String annoNameSlash = names[i].substring(1, names[i].length() - 1);
   21.86 +            Class<? extends Annotation> annoClass;
   21.87 +            try {
   21.88 +                annoClass = (Class<? extends Annotation>)Class.forName(annoNameSlash.replace('/', '.'));
   21.89 +            } catch (ClassNotFoundException ex) {
   21.90 +                throw new IllegalStateException("Can't find annotation class " + annoNameSlash);
   21.91 +            }
   21.92 +            ret[i] = create(
   21.93 +                new AnnotationImpl(annoClass), 
   21.94 +                annoNameSlash.replace('/', '_'),
   21.95 +                findProps(annoClass),
   21.96 +                findData(anno, names[i])
   21.97 +            );
   21.98          }
   21.99          return ret;
  21.100      }
  21.101 @@ -70,12 +106,25 @@
  21.102          + "}"
  21.103          + "return arr;"
  21.104      )
  21.105 -    private static String[] findNames(Object anno) {
  21.106 -        throw new UnsupportedOperationException();
  21.107 -    }
  21.108 +    private static native String[] findNames(Object anno);
  21.109  
  21.110      @JavaScriptBody(args={ "anno", "p"}, body="return anno[p];")
  21.111 -    private static Object findData(Object anno, String p) {
  21.112 -        throw new UnsupportedOperationException();
  21.113 +    private static native Object findData(Object anno, String p);
  21.114 +
  21.115 +    private static Object[] findProps(Class<?> annoClass) {
  21.116 +        final Method[] marr = MethodImpl.findMethods(annoClass, Modifier.PUBLIC);
  21.117 +        Object[] arr = new Object[marr.length * 3];
  21.118 +        int pos = 0;
  21.119 +        for (Method m : marr) {
  21.120 +            arr[pos++] = MethodImpl.toSignature(m);
  21.121 +            arr[pos++] = m.getName();
  21.122 +            final Class<?> rt = m.getReturnType();
  21.123 +            if (rt.isArray()) {
  21.124 +                arr[pos++] = rt.getComponentType().isAnnotation() ? rt : null;
  21.125 +            } else {
  21.126 +                arr[pos++] = rt.isAnnotation() ? rt : null;
  21.127 +            }
  21.128 +        }
  21.129 +        return arr;
  21.130      }
  21.131  }
    22.1 --- a/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/MethodImpl.java	Tue Feb 19 15:33:32 2013 +0100
    22.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/MethodImpl.java	Tue Feb 19 15:59:27 2013 +0100
    22.3 @@ -17,6 +17,7 @@
    22.4   */
    22.5  package org.apidesign.bck2brwsr.emul.reflect;
    22.6  
    22.7 +import java.lang.reflect.Array;
    22.8  import java.lang.reflect.Method;
    22.9  import java.util.Enumeration;
   22.10  import org.apidesign.bck2brwsr.core.JavaScriptBody;
   22.11 @@ -34,7 +35,7 @@
   22.12              throw new IllegalStateException(ex);
   22.13          }
   22.14      }
   22.15 -    
   22.16 +
   22.17      protected abstract Method create(Class<?> declaringClass, String name, Object data, String sig);
   22.18      
   22.19      
   22.20 @@ -48,8 +49,10 @@
   22.21          + "var arr = new Array();\n"
   22.22          + "for (m in c) {\n"
   22.23          + "  if (m.indexOf(prefix) === 0) {\n"
   22.24 +        + "     if (!c[m].cls) continue;\n"
   22.25          + "     arr.push(m);\n"
   22.26          + "     arr.push(c[m]);\n"
   22.27 +        + "     arr.push(c[m].cls.$class);\n"
   22.28          + "  }"
   22.29          + "}\n"
   22.30          + "return arr;")
   22.31 @@ -59,9 +62,10 @@
   22.32      public static Method findMethod(
   22.33          Class<?> clazz, String name, Class<?>... parameterTypes) {
   22.34          Object[] data = findMethodData(clazz, name + "__");
   22.35 -        BIG: for (int i = 0; i < data.length; i += 2) {
   22.36 -            String sig = ((String) data[0]).substring(name.length() + 2);
   22.37 -            Method tmp = INSTANCE.create(clazz, name, data[1], sig);
   22.38 +        BIG: for (int i = 0; i < data.length; i += 3) {
   22.39 +            String sig = ((String) data[i]).substring(name.length() + 2);
   22.40 +            Class<?> cls = (Class<?>) data[i + 2];
   22.41 +            Method tmp = INSTANCE.create(cls, name, data[i + 1], sig);
   22.42              Class<?>[] tmpParms = tmp.getParameterTypes();
   22.43              if (parameterTypes.length != tmpParms.length) {
   22.44                  continue;
   22.45 @@ -79,7 +83,7 @@
   22.46      public static Method[] findMethods(Class<?> clazz, int mask) {
   22.47          Object[] namesAndData = findMethodData(clazz, "");
   22.48          int cnt = 0;
   22.49 -        for (int i = 0; i < namesAndData.length; i += 2) {
   22.50 +        for (int i = 0; i < namesAndData.length; i += 3) {
   22.51              String sig = (String) namesAndData[i];
   22.52              Object data = namesAndData[i + 1];
   22.53              int middle = sig.indexOf("__");
   22.54 @@ -88,7 +92,8 @@
   22.55              }
   22.56              String name = sig.substring(0, middle);
   22.57              sig = sig.substring(middle + 2);
   22.58 -            final Method m = INSTANCE.create(clazz, name, data, sig);
   22.59 +            Class<?> cls = (Class<?>) namesAndData[i + 2];
   22.60 +            final Method m = INSTANCE.create(cls, name, data, sig);
   22.61              if ((m.getModifiers() & mask) == 0) {
   22.62                  continue;
   22.63              }
   22.64 @@ -100,6 +105,62 @@
   22.65          }
   22.66          return arr;
   22.67      }
   22.68 +    static String toSignature(Method m) {
   22.69 +        StringBuilder sb = new StringBuilder();
   22.70 +        sb.append(m.getName()).append("__");
   22.71 +        appendType(sb, m.getReturnType());
   22.72 +        Class<?>[] arr = m.getParameterTypes();
   22.73 +        for (int i = 0; i < arr.length; i++) {
   22.74 +            appendType(sb, arr[i]);
   22.75 +        }
   22.76 +        return sb.toString();
   22.77 +    }
   22.78 +    
   22.79 +    private static void appendType(StringBuilder sb, Class<?> type) {
   22.80 +        if (type == Integer.TYPE) {
   22.81 +            sb.append('I');
   22.82 +            return;
   22.83 +        }
   22.84 +        if (type == Long.TYPE) {
   22.85 +            sb.append('J');
   22.86 +            return;
   22.87 +        }
   22.88 +        if (type == Double.TYPE) {
   22.89 +            sb.append('D');
   22.90 +            return;
   22.91 +        }
   22.92 +        if (type == Float.TYPE) {
   22.93 +            sb.append('F');
   22.94 +            return;
   22.95 +        }
   22.96 +        if (type == Byte.TYPE) {
   22.97 +            sb.append('B');
   22.98 +            return;
   22.99 +        }
  22.100 +        if (type == Boolean.TYPE) {
  22.101 +            sb.append('Z');
  22.102 +            return;
  22.103 +        }
  22.104 +        if (type == Short.TYPE) {
  22.105 +            sb.append('S');
  22.106 +            return;
  22.107 +        }
  22.108 +        if (type == Void.TYPE) {
  22.109 +            sb.append('V');
  22.110 +            return;
  22.111 +        }
  22.112 +        if (type == Character.TYPE) {
  22.113 +            sb.append('C');
  22.114 +            return;
  22.115 +        }
  22.116 +        if (type.isArray()) {
  22.117 +            sb.append("_3");
  22.118 +            appendType(sb, type.getComponentType());
  22.119 +            return;
  22.120 +        }
  22.121 +        sb.append('L').append(type.getName().replace('.', '_'));
  22.122 +        sb.append("_2");
  22.123 +    }
  22.124  
  22.125      public static int signatureElements(String sig) {
  22.126          Enumeration<Class> en = signatureParser(sig);
  22.127 @@ -141,13 +202,19 @@
  22.128                          return Character.TYPE;
  22.129                      case 'L':
  22.130                          try {
  22.131 -                            int up = sig.indexOf("_2");
  22.132 -                            String type = sig.substring(1, up);
  22.133 +                            int up = sig.indexOf("_2", pos);
  22.134 +                            String type = sig.substring(pos, up);
  22.135                              pos = up + 2;
  22.136 -                            return Class.forName(type);
  22.137 +                            return Class.forName(type.replace('_', '.'));
  22.138                          } catch (ClassNotFoundException ex) {
  22.139 -                            // should not happen
  22.140 +                            throw new IllegalStateException(ex);
  22.141                          }
  22.142 +                    case '_': {
  22.143 +                        char nch = sig.charAt(pos++);
  22.144 +                        assert nch == '3' : "Can't find '3' at " + sig.substring(pos - 1);
  22.145 +                        final Class compType = nextElement();
  22.146 +                        return Array.newInstance(compType, 0).getClass();
  22.147 +                    }
  22.148                  }
  22.149                  throw new UnsupportedOperationException(sig + " at " + pos);
  22.150              }
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/Adler32.java	Tue Feb 19 15:59:27 2013 +0100
    23.3 @@ -0,0 +1,139 @@
    23.4 +/* -*-mode:java; c-basic-offset:2; -*- */
    23.5 +/*
    23.6 +Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved.
    23.7 +
    23.8 +Redistribution and use in source and binary forms, with or without
    23.9 +modification, are permitted provided that the following conditions are met:
   23.10 +
   23.11 +  1. Redistributions of source code must retain the above copyright notice,
   23.12 +     this list of conditions and the following disclaimer.
   23.13 +
   23.14 +  2. Redistributions in binary form must reproduce the above copyright 
   23.15 +     notice, this list of conditions and the following disclaimer in 
   23.16 +     the documentation and/or other materials provided with the distribution.
   23.17 +
   23.18 +  3. The names of the authors may not be used to endorse or promote products
   23.19 +     derived from this software without specific prior written permission.
   23.20 +
   23.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   23.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   23.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
   23.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
   23.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   23.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
   23.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   23.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   23.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   23.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   23.31 + */
   23.32 +/*
   23.33 + * This program is based on zlib-1.1.3, so all credit should go authors
   23.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
   23.35 + * and contributors of zlib.
   23.36 + */
   23.37 +
   23.38 +package org.apidesign.bck2brwsr.emul.zip;
   23.39 +
   23.40 +final class Adler32 implements Checksum {
   23.41 +
   23.42 +  // largest prime smaller than 65536
   23.43 +  static final private int BASE=65521; 
   23.44 +  // NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
   23.45 +  static final private int NMAX=5552;
   23.46 +
   23.47 +  private long s1=1L;
   23.48 +  private long s2=0L;
   23.49 +
   23.50 +  public void reset(long init){
   23.51 +    s1=init&0xffff;
   23.52 +    s2=(init>>16)&0xffff;
   23.53 +  }
   23.54 +
   23.55 +  public void reset(){
   23.56 +    s1=1L;
   23.57 +    s2=0L;
   23.58 +  }
   23.59 +
   23.60 +  public long getValue(){
   23.61 +    return ((s2<<16)|s1);
   23.62 +  }
   23.63 +
   23.64 +  public void update(byte[] buf, int index, int len){
   23.65 +
   23.66 +    if(len==1){
   23.67 +      s1+=buf[index++]&0xff; s2+=s1;
   23.68 +      s1%=BASE;
   23.69 +      s2%=BASE;
   23.70 +      return;
   23.71 +    }
   23.72 +
   23.73 +    int len1 = len/NMAX;
   23.74 +    int len2 = len%NMAX;
   23.75 +    while(len1-->0) {
   23.76 +      int k=NMAX;
   23.77 +      len-=k;
   23.78 +      while(k-->0){
   23.79 +	s1+=buf[index++]&0xff; s2+=s1;
   23.80 +      }
   23.81 +      s1%=BASE;
   23.82 +      s2%=BASE;
   23.83 +    }
   23.84 +
   23.85 +    int k=len2;
   23.86 +    len-=k;
   23.87 +    while(k-->0){
   23.88 +      s1+=buf[index++]&0xff; s2+=s1;
   23.89 +    }
   23.90 +    s1%=BASE;
   23.91 +    s2%=BASE;
   23.92 +  }
   23.93 +
   23.94 +  public Adler32 copy(){
   23.95 +    Adler32 foo = new Adler32();
   23.96 +    foo.s1 = this.s1;
   23.97 +    foo.s2 = this.s2;
   23.98 +    return foo;
   23.99 +  }
  23.100 +
  23.101 +  // The following logic has come from zlib.1.2.
  23.102 +  static long combine(long adler1, long adler2, long len2){
  23.103 +    long BASEL = (long)BASE;
  23.104 +    long sum1;
  23.105 +    long sum2;
  23.106 +    long rem;  // unsigned int
  23.107 +
  23.108 +    rem = len2 % BASEL;
  23.109 +    sum1 = adler1 & 0xffffL;
  23.110 +    sum2 = rem * sum1;
  23.111 +    sum2 %= BASEL; // MOD(sum2);
  23.112 +    sum1 += (adler2 & 0xffffL) + BASEL - 1;
  23.113 +    sum2 += ((adler1 >> 16) & 0xffffL) + ((adler2 >> 16) & 0xffffL) + BASEL - rem;
  23.114 +    if (sum1 >= BASEL) sum1 -= BASEL;
  23.115 +    if (sum1 >= BASEL) sum1 -= BASEL;
  23.116 +    if (sum2 >= (BASEL << 1)) sum2 -= (BASEL << 1);
  23.117 +    if (sum2 >= BASEL) sum2 -= BASEL;
  23.118 +    return sum1 | (sum2 << 16);
  23.119 +  }
  23.120 +
  23.121 +/*
  23.122 +  private java.util.zip.Adler32 adler=new java.util.zip.Adler32();
  23.123 +  public void update(byte[] buf, int index, int len){
  23.124 +    if(buf==null) {adler.reset();}
  23.125 +    else{adler.update(buf, index, len);}
  23.126 +  }
  23.127 +  public void reset(){
  23.128 +    adler.reset();
  23.129 +  }
  23.130 +  public void reset(long init){
  23.131 +    if(init==1L){
  23.132 +      adler.reset();
  23.133 +    }
  23.134 +    else{
  23.135 +      System.err.println("unsupported operation");
  23.136 +    }
  23.137 +  }
  23.138 +  public long getValue(){
  23.139 +    return adler.getValue();
  23.140 +  }
  23.141 +*/
  23.142 +}
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/CRC32.java	Tue Feb 19 15:59:27 2013 +0100
    24.3 @@ -0,0 +1,181 @@
    24.4 +/* -*-mode:java; c-basic-offset:2; -*- */
    24.5 +/*
    24.6 +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
    24.7 +
    24.8 +Redistribution and use in source and binary forms, with or without
    24.9 +modification, are permitted provided that the following conditions are met:
   24.10 +
   24.11 +  1. Redistributions of source code must retain the above copyright notice,
   24.12 +     this list of conditions and the following disclaimer.
   24.13 +
   24.14 +  2. Redistributions in binary form must reproduce the above copyright 
   24.15 +     notice, this list of conditions and the following disclaimer in 
   24.16 +     the documentation and/or other materials provided with the distribution.
   24.17 +
   24.18 +  3. The names of the authors may not be used to endorse or promote products
   24.19 +     derived from this software without specific prior written permission.
   24.20 +
   24.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   24.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   24.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
   24.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
   24.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   24.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
   24.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   24.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   24.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   24.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   24.31 + */
   24.32 +/*
   24.33 + * This program is based on zlib-1.1.3, so all credit should go authors
   24.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
   24.35 + * and contributors of zlib.
   24.36 + */
   24.37 +
   24.38 +package org.apidesign.bck2brwsr.emul.zip;
   24.39 +
   24.40 +import org.apidesign.bck2brwsr.emul.lang.System;
   24.41 +
   24.42 +final class CRC32 implements Checksum {
   24.43 +
   24.44 +  /*
   24.45 +   *  The following logic has come from RFC1952.
   24.46 +   */
   24.47 +  private int v = 0;
   24.48 +  private static int[] crc_table = null;
   24.49 +  static {
   24.50 +    crc_table = new int[256];
   24.51 +    for (int n = 0; n < 256; n++) {
   24.52 +      int c = n;
   24.53 +      for (int k = 8;  --k >= 0; ) {
   24.54 +        if ((c & 1) != 0)
   24.55 +	  c = 0xedb88320 ^ (c >>> 1);
   24.56 +        else
   24.57 +          c = c >>> 1;
   24.58 +      }
   24.59 +      crc_table[n] = c;
   24.60 +    }
   24.61 +  }
   24.62 +
   24.63 +  public void update (byte[] buf, int index, int len) {
   24.64 +    int c = ~v;
   24.65 +    while (--len >= 0)
   24.66 +      c = crc_table[(c^buf[index++])&0xff]^(c >>> 8);
   24.67 +    v = ~c;
   24.68 +  }
   24.69 +
   24.70 +  public void reset(){
   24.71 +    v = 0;
   24.72 +  }
   24.73 +
   24.74 +  public void reset(long vv){
   24.75 +    v = (int)(vv&0xffffffffL);
   24.76 +  }
   24.77 +
   24.78 +  public long getValue(){
   24.79 +    return (long)(v&0xffffffffL);
   24.80 +  }
   24.81 +
   24.82 +  // The following logic has come from zlib.1.2.
   24.83 +  private static final int GF2_DIM = 32;
   24.84 +  static long combine(long crc1, long crc2, long len2){
   24.85 +    long row;
   24.86 +    long[] even = new long[GF2_DIM];
   24.87 +    long[] odd = new long[GF2_DIM];
   24.88 +
   24.89 +    // degenerate case (also disallow negative lengths)
   24.90 +    if (len2 <= 0)
   24.91 +      return crc1;
   24.92 +
   24.93 +    // put operator for one zero bit in odd
   24.94 +    odd[0] = 0xedb88320L;          // CRC-32 polynomial
   24.95 +    row = 1;
   24.96 +    for (int n = 1; n < GF2_DIM; n++) {
   24.97 +        odd[n] = row;
   24.98 +        row <<= 1;
   24.99 +    }
  24.100 +
  24.101 +    // put operator for two zero bits in even
  24.102 +    gf2_matrix_square(even, odd);
  24.103 +
  24.104 +    // put operator for four zero bits in odd
  24.105 +    gf2_matrix_square(odd, even);
  24.106 +
  24.107 +    // apply len2 zeros to crc1 (first square will put the operator for one
  24.108 +    // zero byte, eight zero bits, in even)
  24.109 +    do {
  24.110 +      // apply zeros operator for this bit of len2
  24.111 +      gf2_matrix_square(even, odd);
  24.112 +      if ((len2 & 1)!=0)
  24.113 +        crc1 = gf2_matrix_times(even, crc1);
  24.114 +      len2 >>= 1;
  24.115 +
  24.116 +      // if no more bits set, then done
  24.117 +      if (len2 == 0)
  24.118 +        break;
  24.119 +
  24.120 +      // another iteration of the loop with odd and even swapped
  24.121 +      gf2_matrix_square(odd, even);
  24.122 +      if ((len2 & 1)!=0)
  24.123 +        crc1 = gf2_matrix_times(odd, crc1);
  24.124 +      len2 >>= 1;
  24.125 +
  24.126 +      // if no more bits set, then done
  24.127 +    } while (len2 != 0);
  24.128 +
  24.129 +    /* return combined crc */
  24.130 +    crc1 ^= crc2;
  24.131 +    return crc1;
  24.132 +  }
  24.133 +
  24.134 +  private static long gf2_matrix_times(long[] mat, long vec){
  24.135 +    long sum = 0;
  24.136 +    int index = 0;
  24.137 +    while (vec!=0) {
  24.138 +      if ((vec & 1)!=0)
  24.139 +        sum ^= mat[index];
  24.140 +      vec >>= 1;
  24.141 +      index++;
  24.142 +    }
  24.143 +    return sum;
  24.144 +  }
  24.145 +
  24.146 +  static final void gf2_matrix_square(long[] square, long[] mat) {
  24.147 +    for (int n = 0; n < GF2_DIM; n++)
  24.148 +      square[n] = gf2_matrix_times(mat, mat[n]);
  24.149 +  }
  24.150 +
  24.151 +  /*
  24.152 +  private java.util.zip.CRC32 crc32 = new java.util.zip.CRC32();
  24.153 +
  24.154 +  public void update(byte[] buf, int index, int len){
  24.155 +    if(buf==null) {crc32.reset();}
  24.156 +    else{crc32.update(buf, index, len);}
  24.157 +  }
  24.158 +  public void reset(){
  24.159 +    crc32.reset();
  24.160 +  }
  24.161 +  public void reset(long init){
  24.162 +    if(init==0L){
  24.163 +      crc32.reset();
  24.164 +    }
  24.165 +    else{
  24.166 +      System.err.println("unsupported operation");
  24.167 +    }
  24.168 +  }
  24.169 +  public long getValue(){
  24.170 +    return crc32.getValue();
  24.171 +  }
  24.172 +*/
  24.173 +  public CRC32 copy(){
  24.174 +    CRC32 foo = new CRC32();
  24.175 +    foo.v = this.v;
  24.176 +    return foo;
  24.177 +  }
  24.178 +
  24.179 +  public static int[] getCRC32Table(){
  24.180 +    int[] tmp = new int[crc_table.length];
  24.181 +    System.arraycopy(crc_table, 0, tmp, 0, tmp.length);
  24.182 +    return tmp;
  24.183 +  }
  24.184 +}
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/Checksum.java	Tue Feb 19 15:59:27 2013 +0100
    25.3 @@ -0,0 +1,43 @@
    25.4 +/* -*-mode:java; c-basic-offset:2; -*- */
    25.5 +/*
    25.6 +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
    25.7 +
    25.8 +Redistribution and use in source and binary forms, with or without
    25.9 +modification, are permitted provided that the following conditions are met:
   25.10 +
   25.11 +  1. Redistributions of source code must retain the above copyright notice,
   25.12 +     this list of conditions and the following disclaimer.
   25.13 +
   25.14 +  2. Redistributions in binary form must reproduce the above copyright 
   25.15 +     notice, this list of conditions and the following disclaimer in 
   25.16 +     the documentation and/or other materials provided with the distribution.
   25.17 +
   25.18 +  3. The names of the authors may not be used to endorse or promote products
   25.19 +     derived from this software without specific prior written permission.
   25.20 +
   25.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   25.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   25.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
   25.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
   25.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   25.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
   25.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   25.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   25.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   25.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   25.31 + */
   25.32 +/*
   25.33 + * This program is based on zlib-1.1.3, so all credit should go authors
   25.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
   25.35 + * and contributors of zlib.
   25.36 + */
   25.37 +
   25.38 +package org.apidesign.bck2brwsr.emul.zip;
   25.39 +
   25.40 +interface Checksum {
   25.41 +  void update(byte[] buf, int index, int len);
   25.42 +  void reset();
   25.43 +  void reset(long init);
   25.44 +  long getValue();
   25.45 +  Checksum copy();
   25.46 +}
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/FastJar.java	Tue Feb 19 15:59:27 2013 +0100
    26.3 @@ -0,0 +1,175 @@
    26.4 +/*
    26.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    26.6 + *
    26.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    26.8 + *
    26.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   26.10 + * Other names may be trademarks of their respective owners.
   26.11 + *
   26.12 + * The contents of this file are subject to the terms of either the GNU
   26.13 + * General Public License Version 2 only ("GPL") or the Common
   26.14 + * Development and Distribution License("CDDL") (collectively, the
   26.15 + * "License"). You may not use this file except in compliance with the
   26.16 + * License. You can obtain a copy of the License at
   26.17 + * http://www.netbeans.org/cddl-gplv2.html
   26.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   26.19 + * specific language governing permissions and limitations under the
   26.20 + * License.  When distributing the software, include this License Header
   26.21 + * Notice in each file and include the License file at
   26.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   26.23 + * particular file as subject to the "Classpath" exception as provided
   26.24 + * by Oracle in the GPL Version 2 section of the License file that
   26.25 + * accompanied this code. If applicable, add the following below the
   26.26 + * License Header, with the fields enclosed by brackets [] replaced by
   26.27 + * your own identifying information:
   26.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   26.29 + *
   26.30 + * Contributor(s):
   26.31 + *
   26.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
   26.33 + */
   26.34 +package org.apidesign.bck2brwsr.emul.zip;
   26.35 +
   26.36 +import java.io.ByteArrayInputStream;
   26.37 +import java.io.IOException;
   26.38 +import java.io.InputStream;
   26.39 +import java.util.zip.ZipEntry;
   26.40 +import java.util.zip.ZipInputStream;
   26.41 +
   26.42 +/**
   26.43 + *
   26.44 + * @author Tomas Zezula
   26.45 + */
   26.46 +public final class FastJar {
   26.47 +    private final byte[] arr;
   26.48 +
   26.49 +    public FastJar(byte[] arr) {
   26.50 +        this.arr = arr;
   26.51 +    }
   26.52 +    
   26.53 +    
   26.54 +    private static final int GIVE_UP = 1<<16;
   26.55 +
   26.56 +    public static final  class Entry {
   26.57 +        
   26.58 +        public final String name;
   26.59 +        final long offset;
   26.60 +        private final long dosTime;
   26.61 +        
   26.62 +        Entry (String name, long offset, long time) {
   26.63 +            assert name != null;
   26.64 +            this.name = name;
   26.65 +            this.offset = offset;
   26.66 +            this.dosTime = time;
   26.67 +        }        
   26.68 +/*        
   26.69 +        public long getTime () {
   26.70 +            Date d = new Date((int)(((dosTime >> 25) & 0x7f) + 80),
   26.71 +                    (int)(((dosTime >> 21) & 0x0f) - 1),
   26.72 +                    (int)((dosTime >> 16) & 0x1f),
   26.73 +                    (int)((dosTime >> 11) & 0x1f),
   26.74 +                    (int)((dosTime >> 5) & 0x3f),
   26.75 +                    (int)((dosTime << 1) & 0x3e));
   26.76 +            return d.getTime();
   26.77 +        }
   26.78 +        */
   26.79 +    }
   26.80 +    
   26.81 +    public InputStream getInputStream (final Entry e) throws IOException {
   26.82 +        return getInputStream(arr, e.offset);
   26.83 +    }
   26.84 +    
   26.85 +    private static InputStream getInputStream (byte[] arr, final long offset) throws IOException {
   26.86 +        ByteArrayInputStream is = new ByteArrayInputStream(arr);
   26.87 +        is.skip(offset);
   26.88 +        ZipInputStream in = new ZipInputStream (is);
   26.89 +        ZipEntry e = in.getNextEntry();
   26.90 +        if (e != null && e.getCrc() == 0L && e.getMethod() == ZipEntry.STORED) {
   26.91 +            int cp = arr.length - is.available();
   26.92 +            return new ByteArrayInputStream(arr, cp, (int)e.getSize());
   26.93 +        }
   26.94 +        return in;
   26.95 +    }
   26.96 +    
   26.97 +    public Entry[] list() throws IOException {
   26.98 +        final int size = arr.length;
   26.99 +
  26.100 +        int at = size - ZipInputStream.ENDHDR;
  26.101 +
  26.102 +        byte[] data = new byte[ZipInputStream.ENDHDR];        
  26.103 +        int giveup = 0;
  26.104 +
  26.105 +        do {
  26.106 +            org.apidesign.bck2brwsr.emul.lang.System.arraycopy(arr, at, data, 0, data.length);
  26.107 +            at--;
  26.108 +            giveup++;
  26.109 +            if (giveup > GIVE_UP) {
  26.110 +                throw new IOException ();
  26.111 +            }
  26.112 +        } while (getsig(data) != ZipInputStream.ENDSIG);
  26.113 +
  26.114 +
  26.115 +        final long censize = endsiz(data);
  26.116 +        final long cenoff  = endoff(data);
  26.117 +        at = (int) cenoff;                                                     
  26.118 +
  26.119 +        Entry[] result = new Entry[0];
  26.120 +        int cenread = 0;
  26.121 +        data = new byte[ZipInputStream.CENHDR];
  26.122 +        while (cenread < censize) {
  26.123 +            org.apidesign.bck2brwsr.emul.lang.System.arraycopy(arr, at, data, 0, data.length);
  26.124 +            at += data.length;
  26.125 +            if (getsig(data) != ZipInputStream.CENSIG) {
  26.126 +                throw new IOException("No central table");          //NOI18N
  26.127 +            }
  26.128 +            int cennam = cennam(data);
  26.129 +            int cenext = cenext(data);
  26.130 +            int cencom = cencom(data);
  26.131 +            long lhoff = cenoff(data);
  26.132 +            long centim = centim(data);
  26.133 +            String name = new String(arr, at, cennam, "UTF-8");
  26.134 +            at += cennam;
  26.135 +            int seekby = cenext+cencom;
  26.136 +            int cendatalen = ZipInputStream.CENHDR + cennam + seekby;
  26.137 +            cenread+=cendatalen;
  26.138 +            result = addEntry(result, new Entry(name,lhoff, centim));
  26.139 +            at += seekby;
  26.140 +        }
  26.141 +        return result;
  26.142 +    }
  26.143 +
  26.144 +    private Entry[] addEntry(Entry[] result, Entry entry) {
  26.145 +        Entry[] e = new Entry[result.length + 1];
  26.146 +        e[result.length] = entry;
  26.147 +        org.apidesign.bck2brwsr.emul.lang.System.arraycopy(result, 0, e, 0, result.length);
  26.148 +        return e;
  26.149 +    }
  26.150 +
  26.151 +    private static final long getsig(final byte[] b) throws IOException {return get32(b,0);}
  26.152 +    private static final long endsiz(final byte[] b) throws IOException {return get32(b,ZipInputStream.ENDSIZ);}
  26.153 +    private static final long endoff(final byte[] b) throws IOException {return get32(b,ZipInputStream.ENDOFF);}
  26.154 +    private static final long  cenlen(final byte[] b) throws IOException {return get32(b,ZipInputStream.CENLEN);}
  26.155 +    private static final long  censiz(final byte[] b) throws IOException {return get32(b,ZipInputStream.CENSIZ);}
  26.156 +    private static final long centim(final byte[] b) throws IOException {return get32(b,ZipInputStream.CENTIM);}
  26.157 +    private static final int  cennam(final byte[] b) throws IOException {return get16(b,ZipInputStream.CENNAM);}
  26.158 +    private static final int  cenext(final byte[] b) throws IOException {return get16(b,ZipInputStream.CENEXT);}
  26.159 +    private static final int  cencom(final byte[] b) throws IOException {return get16(b,ZipInputStream.CENCOM);}
  26.160 +    private static final long cenoff (final byte[] b) throws IOException {return get32(b,ZipInputStream.CENOFF);}
  26.161 +    private static final int lochow(final byte[] b) throws IOException {return get16(b,ZipInputStream.LOCHOW);}
  26.162 +    private static final int locname(final byte[] b) throws IOException {return get16(b,ZipInputStream.LOCNAM);}
  26.163 +    private static final int locext(final byte[] b) throws IOException {return get16(b,ZipInputStream.LOCEXT);}
  26.164 +    private static final long locsiz(final byte[] b) throws IOException {return get32(b,ZipInputStream.LOCSIZ);}
  26.165 +    
  26.166 +    private static final int get16(final byte[] b, int off) throws IOException {        
  26.167 +        final int b1 = b[off];
  26.168 +	final int b2 = b[off+1];
  26.169 +        return (b1 & 0xff) | ((b2 & 0xff) << 8);
  26.170 +    }
  26.171 +
  26.172 +    private static final long get32(final byte[] b, int off) throws IOException {
  26.173 +	final int s1 = get16(b, off);
  26.174 +	final int s2 = get16(b, off+2);
  26.175 +        return s1 | ((long)s2 << 16);
  26.176 +    }
  26.177 +
  26.178 +}
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/GZIPHeader.java	Tue Feb 19 15:59:27 2013 +0100
    27.3 @@ -0,0 +1,215 @@
    27.4 +/* -*-mode:java; c-basic-offset:2; -*- */
    27.5 +/*
    27.6 +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
    27.7 +
    27.8 +Redistribution and use in source and binary forms, with or without
    27.9 +modification, are permitted provided that the following conditions are met:
   27.10 +
   27.11 +  1. Redistributions of source code must retain the above copyright notice,
   27.12 +     this list of conditions and the following disclaimer.
   27.13 +
   27.14 +  2. Redistributions in binary form must reproduce the above copyright 
   27.15 +     notice, this list of conditions and the following disclaimer in 
   27.16 +     the documentation and/or other materials provided with the distribution.
   27.17 +
   27.18 +  3. The names of the authors may not be used to endorse or promote products
   27.19 +     derived from this software without specific prior written permission.
   27.20 +
   27.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   27.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   27.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
   27.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
   27.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   27.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
   27.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   27.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   27.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   27.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27.31 + */
   27.32 +/*
   27.33 + * This program is based on zlib-1.1.3, so all credit should go authors
   27.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
   27.35 + * and contributors of zlib.
   27.36 + */
   27.37 +
   27.38 +package org.apidesign.bck2brwsr.emul.zip;
   27.39 +
   27.40 +import org.apidesign.bck2brwsr.emul.lang.System;
   27.41 +import java.io.UnsupportedEncodingException;
   27.42 +
   27.43 +/**
   27.44 + * @see "http://www.ietf.org/rfc/rfc1952.txt"
   27.45 + */
   27.46 +final class GZIPHeader implements Cloneable {
   27.47 +
   27.48 +  public static final byte OS_MSDOS = (byte) 0x00;
   27.49 +  public static final byte OS_AMIGA = (byte) 0x01;
   27.50 +  public static final byte OS_VMS = (byte) 0x02;
   27.51 +  public static final byte OS_UNIX = (byte) 0x03;
   27.52 +  public static final byte OS_ATARI = (byte) 0x05;
   27.53 +  public static final byte OS_OS2 = (byte) 0x06;
   27.54 +  public static final byte OS_MACOS = (byte) 0x07;
   27.55 +  public static final byte OS_TOPS20 = (byte) 0x0a;
   27.56 +  public static final byte OS_WIN32 = (byte) 0x0b;
   27.57 +  public static final byte OS_VMCMS = (byte) 0x04;
   27.58 +  public static final byte OS_ZSYSTEM = (byte) 0x08;
   27.59 +  public static final byte OS_CPM = (byte) 0x09;
   27.60 +  public static final byte OS_QDOS = (byte) 0x0c;
   27.61 +  public static final byte OS_RISCOS = (byte) 0x0d;
   27.62 +  public static final byte OS_UNKNOWN = (byte) 0xff;
   27.63 +
   27.64 +  boolean text = false;
   27.65 +  private boolean fhcrc = false;
   27.66 +  long time;
   27.67 +  int xflags;
   27.68 +  int os = 255;
   27.69 +  byte[] extra;
   27.70 +  byte[] name;
   27.71 +  byte[] comment;
   27.72 +  int hcrc;
   27.73 +  long crc;
   27.74 +  boolean done = false;
   27.75 +  long mtime = 0;
   27.76 +
   27.77 +  public void setModifiedTime(long mtime) {
   27.78 +    this.mtime = mtime;
   27.79 +  }
   27.80 +
   27.81 +  public long getModifiedTime() {
   27.82 +    return mtime;
   27.83 +  }
   27.84 +
   27.85 +  public void setOS(int os) {
   27.86 +    if((0<=os && os <=13) || os==255)
   27.87 +      this.os=os;
   27.88 +    else
   27.89 +      throw new IllegalArgumentException("os: "+os);
   27.90 +  }
   27.91 +
   27.92 +  public int getOS(){
   27.93 +    return os;
   27.94 +  }
   27.95 +
   27.96 +  public void setName(String name) {
   27.97 +    try{
   27.98 +      this.name=name.getBytes("ISO-8859-1");
   27.99 +    }
  27.100 +    catch(UnsupportedEncodingException e){
  27.101 +      throw new IllegalArgumentException("name must be in ISO-8859-1 "+name);
  27.102 +    }
  27.103 +  }
  27.104 +
  27.105 +  public String getName(){
  27.106 +    if(name==null) return "";
  27.107 +    try {
  27.108 +      return new String(name, "ISO-8859-1");
  27.109 +    }
  27.110 +    catch (UnsupportedEncodingException e) {
  27.111 +      throw new IllegalArgumentException(e.toString());
  27.112 +    }
  27.113 +  }
  27.114 +
  27.115 +  public void setComment(String comment) {
  27.116 +    try{
  27.117 +      this.comment=comment.getBytes("ISO-8859-1");
  27.118 +    }
  27.119 +    catch(UnsupportedEncodingException e){
  27.120 +      throw new IllegalArgumentException("comment must be in ISO-8859-1 "+name);
  27.121 +    }
  27.122 +  }
  27.123 +
  27.124 +  public String getComment(){
  27.125 +    if(comment==null) return "";
  27.126 +    try {
  27.127 +      return new String(comment, "ISO-8859-1");
  27.128 +    }
  27.129 +    catch (UnsupportedEncodingException e) {
  27.130 +      throw new IllegalArgumentException(e.toString());
  27.131 +    }
  27.132 +  }
  27.133 +
  27.134 +  public void setCRC(long crc){
  27.135 +    this.crc = crc;
  27.136 +  }
  27.137 +
  27.138 +  public long getCRC(){
  27.139 +    return crc;
  27.140 +  }
  27.141 +/*
  27.142 +  void put(Deflate d){
  27.143 +    int flag = 0;
  27.144 +    if(text){
  27.145 +      flag |= 1;     // FTEXT
  27.146 +    }
  27.147 +    if(fhcrc){
  27.148 +      flag |= 2;     // FHCRC
  27.149 +    }
  27.150 +    if(extra!=null){
  27.151 +      flag |= 4;     // FEXTRA
  27.152 +    }
  27.153 +    if(name!=null){
  27.154 +      flag |= 8;    // FNAME
  27.155 +    }
  27.156 +    if(comment!=null){
  27.157 +      flag |= 16;   // FCOMMENT
  27.158 +    }
  27.159 +    int xfl = 0;
  27.160 +    if(d.level == JZlib.Z_BEST_SPEED){
  27.161 +      xfl |= 4;
  27.162 +    }
  27.163 +    else if (d.level == JZlib.Z_BEST_COMPRESSION){
  27.164 +      xfl |= 2;
  27.165 +    }
  27.166 +
  27.167 +    d.put_short((short)0x8b1f);  // ID1 ID2
  27.168 +    d.put_byte((byte)8);         // CM(Compression Method)
  27.169 +    d.put_byte((byte)flag);
  27.170 +    d.put_byte((byte)mtime);
  27.171 +    d.put_byte((byte)(mtime>>8));
  27.172 +    d.put_byte((byte)(mtime>>16));
  27.173 +    d.put_byte((byte)(mtime>>24));
  27.174 +    d.put_byte((byte)xfl);
  27.175 +    d.put_byte((byte)os);
  27.176 +
  27.177 +    if(extra!=null){
  27.178 +      d.put_byte((byte)extra.length);
  27.179 +      d.put_byte((byte)(extra.length>>8));
  27.180 +      d.put_byte(extra, 0, extra.length);
  27.181 +    }
  27.182 +
  27.183 +    if(name!=null){
  27.184 +      d.put_byte(name, 0, name.length);
  27.185 +      d.put_byte((byte)0);
  27.186 +    }
  27.187 +
  27.188 +    if(comment!=null){
  27.189 +      d.put_byte(comment, 0, comment.length);
  27.190 +      d.put_byte((byte)0);
  27.191 +    }
  27.192 +  }
  27.193 +*/
  27.194 +  @Override
  27.195 +  public Object clone() throws CloneNotSupportedException {
  27.196 +    GZIPHeader gheader = (GZIPHeader)super.clone();
  27.197 +    byte[] tmp;
  27.198 +    if(gheader.extra!=null){
  27.199 +      tmp=new byte[gheader.extra.length];
  27.200 +      System.arraycopy(gheader.extra, 0, tmp, 0, tmp.length);
  27.201 +      gheader.extra = tmp;
  27.202 +    }
  27.203 +
  27.204 +    if(gheader.name!=null){
  27.205 +      tmp=new byte[gheader.name.length];
  27.206 +      System.arraycopy(gheader.name, 0, tmp, 0, tmp.length);
  27.207 +      gheader.name = tmp;
  27.208 +    }
  27.209 +
  27.210 +    if(gheader.comment!=null){
  27.211 +      tmp=new byte[gheader.comment.length];
  27.212 +      System.arraycopy(gheader.comment, 0, tmp, 0, tmp.length);
  27.213 +      gheader.comment = tmp;
  27.214 +    }
  27.215 +
  27.216 +    return gheader;
  27.217 +  }
  27.218 +}
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/InfBlocks.java	Tue Feb 19 15:59:27 2013 +0100
    28.3 @@ -0,0 +1,616 @@
    28.4 +/* -*-mode:java; c-basic-offset:2; -*- */
    28.5 +/*
    28.6 +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
    28.7 +
    28.8 +Redistribution and use in source and binary forms, with or without
    28.9 +modification, are permitted provided that the following conditions are met:
   28.10 +
   28.11 +  1. Redistributions of source code must retain the above copyright notice,
   28.12 +     this list of conditions and the following disclaimer.
   28.13 +
   28.14 +  2. Redistributions in binary form must reproduce the above copyright 
   28.15 +     notice, this list of conditions and the following disclaimer in 
   28.16 +     the documentation and/or other materials provided with the distribution.
   28.17 +
   28.18 +  3. The names of the authors may not be used to endorse or promote products
   28.19 +     derived from this software without specific prior written permission.
   28.20 +
   28.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   28.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   28.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
   28.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
   28.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   28.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
   28.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   28.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   28.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   28.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   28.31 + */
   28.32 +/*
   28.33 + * This program is based on zlib-1.1.3, so all credit should go authors
   28.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
   28.35 + * and contributors of zlib.
   28.36 + */
   28.37 +
   28.38 +package org.apidesign.bck2brwsr.emul.zip;
   28.39 +
   28.40 +import org.apidesign.bck2brwsr.emul.lang.System;
   28.41 +
   28.42 +final class InfBlocks{
   28.43 +  static final private int MANY=1440;
   28.44 +
   28.45 +  // And'ing with mask[n] masks the lower n bits
   28.46 +  static final private int[] inflate_mask = {
   28.47 +    0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
   28.48 +    0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
   28.49 +    0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
   28.50 +    0x00007fff, 0x0000ffff
   28.51 +  };
   28.52 +
   28.53 +  // Table for deflate from PKZIP's appnote.txt.
   28.54 +  static final int[] border = { // Order of the bit length code lengths
   28.55 +    16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
   28.56 +  };
   28.57 +
   28.58 +  static final private int Z_OK=0;
   28.59 +  static final private int Z_STREAM_END=1;
   28.60 +  static final private int Z_NEED_DICT=2;
   28.61 +  static final private int Z_ERRNO=-1;
   28.62 +  static final private int Z_STREAM_ERROR=-2;
   28.63 +  static final private int Z_DATA_ERROR=-3;
   28.64 +  static final private int Z_MEM_ERROR=-4;
   28.65 +  static final private int Z_BUF_ERROR=-5;
   28.66 +  static final private int Z_VERSION_ERROR=-6;
   28.67 +
   28.68 +  static final private int TYPE=0;  // get type bits (3, including end bit)
   28.69 +  static final private int LENS=1;  // get lengths for stored
   28.70 +  static final private int STORED=2;// processing stored block
   28.71 +  static final private int TABLE=3; // get table lengths
   28.72 +  static final private int BTREE=4; // get bit lengths tree for a dynamic block
   28.73 +  static final private int DTREE=5; // get length, distance trees for a dynamic block
   28.74 +  static final private int CODES=6; // processing fixed or dynamic block
   28.75 +  static final private int DRY=7;   // output remaining window bytes
   28.76 +  static final private int DONE=8;  // finished last block, done
   28.77 +  static final private int BAD=9;   // ot a data error--stuck here
   28.78 +
   28.79 +  int mode;            // current inflate_block mode 
   28.80 +
   28.81 +  int left;            // if STORED, bytes left to copy 
   28.82 +
   28.83 +  int table;           // table lengths (14 bits) 
   28.84 +  int index;           // index into blens (or border) 
   28.85 +  int[] blens;         // bit lengths of codes 
   28.86 +  int[] bb=new int[1]; // bit length tree depth 
   28.87 +  int[] tb=new int[1]; // bit length decoding tree 
   28.88 +
   28.89 +  int[] bl=new int[1];
   28.90 +  int[] bd=new int[1];
   28.91 +
   28.92 +  int[][] tl=new int[1][];
   28.93 +  int[][] td=new int[1][];
   28.94 +  int[] tli=new int[1]; // tl_index
   28.95 +  int[] tdi=new int[1]; // td_index
   28.96 +
   28.97 +  private final InfCodes codes;      // if CODES, current state 
   28.98 +
   28.99 +  int last;            // true if this block is the last block 
  28.100 +
  28.101 +  // mode independent information 
  28.102 +  int bitk;            // bits in bit buffer 
  28.103 +  int bitb;            // bit buffer 
  28.104 +  int[] hufts;         // single malloc for tree space 
  28.105 +  byte[] window;       // sliding window 
  28.106 +  int end;             // one byte after sliding window 
  28.107 +  int read;            // window read pointer 
  28.108 +  int write;           // window write pointer 
  28.109 +  private boolean check;
  28.110 +
  28.111 +  private final InfTree inftree=new InfTree();
  28.112 +
  28.113 +  private final ZStream z; 
  28.114 +
  28.115 +  InfBlocks(ZStream z, int w){
  28.116 +    this.z=z;
  28.117 +    this.codes=new InfCodes(this.z, this);
  28.118 +    hufts=new int[MANY*3];
  28.119 +    window=new byte[w];
  28.120 +    end=w;
  28.121 +    this.check = (z.istate.wrap==0) ? false : true;
  28.122 +    mode = TYPE;
  28.123 +    reset();
  28.124 +  }
  28.125 +
  28.126 +  void reset(){
  28.127 +    if(mode==BTREE || mode==DTREE){
  28.128 +    }
  28.129 +    if(mode==CODES){
  28.130 +      codes.free(z);
  28.131 +    }
  28.132 +    mode=TYPE;
  28.133 +    bitk=0;
  28.134 +    bitb=0;
  28.135 +    read=write=0;
  28.136 +    if(check){
  28.137 +      z.adler.reset();
  28.138 +    }
  28.139 +  }
  28.140 +
  28.141 +  int proc(int r){
  28.142 +    int t;              // temporary storage
  28.143 +    int b;              // bit buffer
  28.144 +    int k;              // bits in bit buffer
  28.145 +    int p;              // input data pointer
  28.146 +    int n;              // bytes available there
  28.147 +    int q;              // output window write pointer
  28.148 +    int m;              // bytes to end of window or read pointer
  28.149 +
  28.150 +    // copy input/output information to locals (UPDATE macro restores)
  28.151 +    {p=z.next_in_index;n=z.avail_in;b=bitb;k=bitk;}
  28.152 +    {q=write;m=(int)(q<read?read-q-1:end-q);}
  28.153 +
  28.154 +    // process input based on current state
  28.155 +    while(true){
  28.156 +      switch (mode){
  28.157 +      case TYPE:
  28.158 +
  28.159 +	while(k<(3)){
  28.160 +	  if(n!=0){
  28.161 +	    r=Z_OK;
  28.162 +	  }
  28.163 +	  else{
  28.164 +	    bitb=b; bitk=k; 
  28.165 +	    z.avail_in=n;
  28.166 +	    z.total_in+=p-z.next_in_index;z.next_in_index=p;
  28.167 +	    write=q;
  28.168 +	    return inflate_flush(r);
  28.169 +	  };
  28.170 +	  n--;
  28.171 +	  b|=(z.next_in[p++]&0xff)<<k;
  28.172 +	  k+=8;
  28.173 +	}
  28.174 +	t = (int)(b & 7);
  28.175 +	last = t & 1;
  28.176 +
  28.177 +	switch (t >>> 1){
  28.178 +        case 0:                         // stored 
  28.179 +          {b>>>=(3);k-=(3);}
  28.180 +          t = k & 7;                    // go to byte boundary
  28.181 +
  28.182 +          {b>>>=(t);k-=(t);}
  28.183 +          mode = LENS;                  // get length of stored block
  28.184 +          break;
  28.185 +        case 1:                         // fixed
  28.186 +          InfTree.inflate_trees_fixed(bl, bd, tl, td, z);
  28.187 +          codes.init(bl[0], bd[0], tl[0], 0, td[0], 0);
  28.188 +
  28.189 +          {b>>>=(3);k-=(3);}
  28.190 +
  28.191 +          mode = CODES;
  28.192 +          break;
  28.193 +        case 2:                         // dynamic
  28.194 +
  28.195 +          {b>>>=(3);k-=(3);}
  28.196 +
  28.197 +          mode = TABLE;
  28.198 +          break;
  28.199 +        case 3:                         // illegal
  28.200 +
  28.201 +          {b>>>=(3);k-=(3);}
  28.202 +          mode = BAD;
  28.203 +          z.msg = "invalid block type";
  28.204 +          r = Z_DATA_ERROR;
  28.205 +
  28.206 +	  bitb=b; bitk=k; 
  28.207 +	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  28.208 +	  write=q;
  28.209 +	  return inflate_flush(r);
  28.210 +	}
  28.211 +	break;
  28.212 +      case LENS:
  28.213 +
  28.214 +	while(k<(32)){
  28.215 +	  if(n!=0){
  28.216 +	    r=Z_OK;
  28.217 +	  }
  28.218 +	  else{
  28.219 +	    bitb=b; bitk=k; 
  28.220 +	    z.avail_in=n;
  28.221 +	    z.total_in+=p-z.next_in_index;z.next_in_index=p;
  28.222 +	    write=q;
  28.223 +	    return inflate_flush(r);
  28.224 +	  };
  28.225 +	  n--;
  28.226 +	  b|=(z.next_in[p++]&0xff)<<k;
  28.227 +	  k+=8;
  28.228 +	}
  28.229 +
  28.230 +	if ((((~b) >>> 16) & 0xffff) != (b & 0xffff)){
  28.231 +	  mode = BAD;
  28.232 +	  z.msg = "invalid stored block lengths";
  28.233 +	  r = Z_DATA_ERROR;
  28.234 +
  28.235 +	  bitb=b; bitk=k; 
  28.236 +	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  28.237 +	  write=q;
  28.238 +	  return inflate_flush(r);
  28.239 +	}
  28.240 +	left = (b & 0xffff);
  28.241 +	b = k = 0;                       // dump bits
  28.242 +	mode = left!=0 ? STORED : (last!=0 ? DRY : TYPE);
  28.243 +	break;
  28.244 +      case STORED:
  28.245 +	if (n == 0){
  28.246 +	  bitb=b; bitk=k; 
  28.247 +	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  28.248 +	  write=q;
  28.249 +	  return inflate_flush(r);
  28.250 +	}
  28.251 +
  28.252 +	if(m==0){
  28.253 +	  if(q==end&&read!=0){
  28.254 +	    q=0; m=(int)(q<read?read-q-1:end-q);
  28.255 +	  }
  28.256 +	  if(m==0){
  28.257 +	    write=q; 
  28.258 +	    r=inflate_flush(r);
  28.259 +	    q=write;m=(int)(q<read?read-q-1:end-q);
  28.260 +	    if(q==end&&read!=0){
  28.261 +	      q=0; m=(int)(q<read?read-q-1:end-q);
  28.262 +	    }
  28.263 +	    if(m==0){
  28.264 +	      bitb=b; bitk=k; 
  28.265 +	      z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  28.266 +	      write=q;
  28.267 +	      return inflate_flush(r);
  28.268 +	    }
  28.269 +	  }
  28.270 +	}
  28.271 +	r=Z_OK;
  28.272 +
  28.273 +	t = left;
  28.274 +	if(t>n) t = n;
  28.275 +	if(t>m) t = m;
  28.276 +	System.arraycopy(z.next_in, p, window, q, t);
  28.277 +	p += t;  n -= t;
  28.278 +	q += t;  m -= t;
  28.279 +	if ((left -= t) != 0)
  28.280 +	  break;
  28.281 +	mode = last!=0 ? DRY : TYPE;
  28.282 +	break;
  28.283 +      case TABLE:
  28.284 +
  28.285 +	while(k<(14)){
  28.286 +	  if(n!=0){
  28.287 +	    r=Z_OK;
  28.288 +	  }
  28.289 +	  else{
  28.290 +	    bitb=b; bitk=k; 
  28.291 +	    z.avail_in=n;
  28.292 +	    z.total_in+=p-z.next_in_index;z.next_in_index=p;
  28.293 +	    write=q;
  28.294 +	    return inflate_flush(r);
  28.295 +	  };
  28.296 +	  n--;
  28.297 +	  b|=(z.next_in[p++]&0xff)<<k;
  28.298 +	  k+=8;
  28.299 +	}
  28.300 +
  28.301 +	table = t = (b & 0x3fff);
  28.302 +	if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
  28.303 +	  {
  28.304 +	    mode = BAD;
  28.305 +	    z.msg = "too many length or distance symbols";
  28.306 +	    r = Z_DATA_ERROR;
  28.307 +
  28.308 +	    bitb=b; bitk=k; 
  28.309 +	    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  28.310 +	    write=q;
  28.311 +	    return inflate_flush(r);
  28.312 +	  }
  28.313 +	t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
  28.314 +	if(blens==null || blens.length<t){
  28.315 +	  blens=new int[t];
  28.316 +	}
  28.317 +	else{
  28.318 +	  for(int i=0; i<t; i++){blens[i]=0;}
  28.319 +	}
  28.320 +
  28.321 +	{b>>>=(14);k-=(14);}
  28.322 +
  28.323 +	index = 0;
  28.324 +	mode = BTREE;
  28.325 +      case BTREE:
  28.326 +	while (index < 4 + (table >>> 10)){
  28.327 +	  while(k<(3)){
  28.328 +	    if(n!=0){
  28.329 +	      r=Z_OK;
  28.330 +	    }
  28.331 +	    else{
  28.332 +	      bitb=b; bitk=k; 
  28.333 +	      z.avail_in=n;
  28.334 +	      z.total_in+=p-z.next_in_index;z.next_in_index=p;
  28.335 +	      write=q;
  28.336 +	      return inflate_flush(r);
  28.337 +	    };
  28.338 +	    n--;
  28.339 +	    b|=(z.next_in[p++]&0xff)<<k;
  28.340 +	    k+=8;
  28.341 +	  }
  28.342 +
  28.343 +	  blens[border[index++]] = b&7;
  28.344 +
  28.345 +	  {b>>>=(3);k-=(3);}
  28.346 +	}
  28.347 +
  28.348 +	while(index < 19){
  28.349 +	  blens[border[index++]] = 0;
  28.350 +	}
  28.351 +
  28.352 +	bb[0] = 7;
  28.353 +	t = inftree.inflate_trees_bits(blens, bb, tb, hufts, z);
  28.354 +	if (t != Z_OK){
  28.355 +	  r = t;
  28.356 +	  if (r == Z_DATA_ERROR){
  28.357 +	    blens=null;
  28.358 +	    mode = BAD;
  28.359 +	  }
  28.360 +
  28.361 +	  bitb=b; bitk=k; 
  28.362 +	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  28.363 +	  write=q;
  28.364 +	  return inflate_flush(r);
  28.365 +	}
  28.366 +
  28.367 +	index = 0;
  28.368 +	mode = DTREE;
  28.369 +      case DTREE:
  28.370 +	while (true){
  28.371 +	  t = table;
  28.372 +	  if(!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))){
  28.373 +	    break;
  28.374 +	  }
  28.375 +
  28.376 +	  int[] h;
  28.377 +	  int i, j, c;
  28.378 +
  28.379 +	  t = bb[0];
  28.380 +
  28.381 +	  while(k<(t)){
  28.382 +	    if(n!=0){
  28.383 +	      r=Z_OK;
  28.384 +	    }
  28.385 +	    else{
  28.386 +	      bitb=b; bitk=k; 
  28.387 +	      z.avail_in=n;
  28.388 +	      z.total_in+=p-z.next_in_index;z.next_in_index=p;
  28.389 +	      write=q;
  28.390 +	      return inflate_flush(r);
  28.391 +	    };
  28.392 +	    n--;
  28.393 +	    b|=(z.next_in[p++]&0xff)<<k;
  28.394 +	    k+=8;
  28.395 +	  }
  28.396 +
  28.397 +	  if(tb[0]==-1){
  28.398 +            //System.err.println("null...");
  28.399 +	  }
  28.400 +
  28.401 +	  t=hufts[(tb[0]+(b&inflate_mask[t]))*3+1];
  28.402 +	  c=hufts[(tb[0]+(b&inflate_mask[t]))*3+2];
  28.403 +
  28.404 +	  if (c < 16){
  28.405 +	    b>>>=(t);k-=(t);
  28.406 +	    blens[index++] = c;
  28.407 +	  }
  28.408 +	  else { // c == 16..18
  28.409 +	    i = c == 18 ? 7 : c - 14;
  28.410 +	    j = c == 18 ? 11 : 3;
  28.411 +
  28.412 +	    while(k<(t+i)){
  28.413 +	      if(n!=0){
  28.414 +		r=Z_OK;
  28.415 +	      }
  28.416 +	      else{
  28.417 +		bitb=b; bitk=k; 
  28.418 +		z.avail_in=n;
  28.419 +		z.total_in+=p-z.next_in_index;z.next_in_index=p;
  28.420 +		write=q;
  28.421 +		return inflate_flush(r);
  28.422 +	      };
  28.423 +	      n--;
  28.424 +	      b|=(z.next_in[p++]&0xff)<<k;
  28.425 +	      k+=8;
  28.426 +	    }
  28.427 +
  28.428 +	    b>>>=(t);k-=(t);
  28.429 +
  28.430 +	    j += (b & inflate_mask[i]);
  28.431 +
  28.432 +	    b>>>=(i);k-=(i);
  28.433 +
  28.434 +	    i = index;
  28.435 +	    t = table;
  28.436 +	    if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
  28.437 +		(c == 16 && i < 1)){
  28.438 +	      blens=null;
  28.439 +	      mode = BAD;
  28.440 +	      z.msg = "invalid bit length repeat";
  28.441 +	      r = Z_DATA_ERROR;
  28.442 +
  28.443 +	      bitb=b; bitk=k; 
  28.444 +	      z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  28.445 +	      write=q;
  28.446 +	      return inflate_flush(r);
  28.447 +	    }
  28.448 +
  28.449 +	    c = c == 16 ? blens[i-1] : 0;
  28.450 +	    do{
  28.451 +	      blens[i++] = c;
  28.452 +	    }
  28.453 +	    while (--j!=0);
  28.454 +	    index = i;
  28.455 +	  }
  28.456 +	}
  28.457 +
  28.458 +	tb[0]=-1;
  28.459 +	{
  28.460 +	  bl[0] = 9;         // must be <= 9 for lookahead assumptions
  28.461 +	  bd[0] = 6;         // must be <= 9 for lookahead assumptions
  28.462 +	  t = table;
  28.463 +	  t = inftree.inflate_trees_dynamic(257 + (t & 0x1f), 
  28.464 +					    1 + ((t >> 5) & 0x1f),
  28.465 +					    blens, bl, bd, tli, tdi, hufts, z);
  28.466 +
  28.467 +	  if (t != Z_OK){
  28.468 +	    if (t == Z_DATA_ERROR){
  28.469 +	      blens=null;
  28.470 +	      mode = BAD;
  28.471 +	    }
  28.472 +	    r = t;
  28.473 +
  28.474 +	    bitb=b; bitk=k; 
  28.475 +	    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  28.476 +	    write=q;
  28.477 +	    return inflate_flush(r);
  28.478 +	  }
  28.479 +	  codes.init(bl[0], bd[0], hufts, tli[0], hufts, tdi[0]);
  28.480 +	}
  28.481 +	mode = CODES;
  28.482 +      case CODES:
  28.483 +	bitb=b; bitk=k;
  28.484 +	z.avail_in=n; z.total_in+=p-z.next_in_index;z.next_in_index=p;
  28.485 +	write=q;
  28.486 +
  28.487 +	if ((r = codes.proc(r)) != Z_STREAM_END){
  28.488 +	  return inflate_flush(r);
  28.489 +	}
  28.490 +	r = Z_OK;
  28.491 +	codes.free(z);
  28.492 +
  28.493 +	p=z.next_in_index; n=z.avail_in;b=bitb;k=bitk;
  28.494 +	q=write;m=(int)(q<read?read-q-1:end-q);
  28.495 +
  28.496 +	if (last==0){
  28.497 +	  mode = TYPE;
  28.498 +	  break;
  28.499 +	}
  28.500 +	mode = DRY;
  28.501 +      case DRY:
  28.502 +	write=q; 
  28.503 +	r=inflate_flush(r); 
  28.504 +	q=write; m=(int)(q<read?read-q-1:end-q);
  28.505 +	if (read != write){
  28.506 +	  bitb=b; bitk=k; 
  28.507 +	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  28.508 +	  write=q;
  28.509 +	  return inflate_flush(r);
  28.510 +	}
  28.511 +	mode = DONE;
  28.512 +      case DONE:
  28.513 +	r = Z_STREAM_END;
  28.514 +
  28.515 +	bitb=b; bitk=k; 
  28.516 +	z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  28.517 +	write=q;
  28.518 +	return inflate_flush(r);
  28.519 +      case BAD:
  28.520 +	r = Z_DATA_ERROR;
  28.521 +
  28.522 +	bitb=b; bitk=k; 
  28.523 +	z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  28.524 +	write=q;
  28.525 +	return inflate_flush(r);
  28.526 +
  28.527 +      default:
  28.528 +	r = Z_STREAM_ERROR;
  28.529 +
  28.530 +	bitb=b; bitk=k; 
  28.531 +	z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  28.532 +	write=q;
  28.533 +	return inflate_flush(r);
  28.534 +      }
  28.535 +    }
  28.536 +  }
  28.537 +
  28.538 +  void free(){
  28.539 +    reset();
  28.540 +    window=null;
  28.541 +    hufts=null;
  28.542 +    //ZFREE(z, s);
  28.543 +  }
  28.544 +
  28.545 +  void set_dictionary(byte[] d, int start, int n){
  28.546 +    System.arraycopy(d, start, window, 0, n);
  28.547 +    read = write = n;
  28.548 +  }
  28.549 +
  28.550 +  // Returns true if inflate is currently at the end of a block generated
  28.551 +  // by Z_SYNC_FLUSH or Z_FULL_FLUSH. 
  28.552 +  int sync_point(){
  28.553 +    return mode == LENS ? 1 : 0;
  28.554 +  }
  28.555 +
  28.556 +  // copy as much as possible from the sliding window to the output area
  28.557 +  int inflate_flush(int r){
  28.558 +    int n;
  28.559 +    int p;
  28.560 +    int q;
  28.561 +
  28.562 +    // local copies of source and destination pointers
  28.563 +    p = z.next_out_index;
  28.564 +    q = read;
  28.565 +
  28.566 +    // compute number of bytes to copy as far as end of window
  28.567 +    n = (int)((q <= write ? write : end) - q);
  28.568 +    if(n > z.avail_out) n = z.avail_out;
  28.569 +    if(n!=0 && r == Z_BUF_ERROR) r = Z_OK;
  28.570 +
  28.571 +    // update counters
  28.572 +    z.avail_out -= n;
  28.573 +    z.total_out += n;
  28.574 +
  28.575 +    // update check information
  28.576 +    if(check && n>0){
  28.577 +      z.adler.update(window, q, n);
  28.578 +    }
  28.579 +
  28.580 +    // copy as far as end of window
  28.581 +    System.arraycopy(window, q, z.next_out, p, n);
  28.582 +    p += n;
  28.583 +    q += n;
  28.584 +
  28.585 +    // see if more to copy at beginning of window
  28.586 +    if (q == end){
  28.587 +      // wrap pointers
  28.588 +      q = 0;
  28.589 +      if (write == end)
  28.590 +        write = 0;
  28.591 +
  28.592 +      // compute bytes to copy
  28.593 +      n = write - q;
  28.594 +      if (n > z.avail_out) n = z.avail_out;
  28.595 +      if (n!=0 && r == Z_BUF_ERROR) r = Z_OK;
  28.596 +
  28.597 +      // update counters
  28.598 +      z.avail_out -= n;
  28.599 +      z.total_out += n;
  28.600 +
  28.601 +      // update check information
  28.602 +      if(check && n>0){
  28.603 +	z.adler.update(window, q, n);
  28.604 +      }
  28.605 +
  28.606 +      // copy
  28.607 +      System.arraycopy(window, q, z.next_out, p, n);
  28.608 +      p += n;
  28.609 +      q += n;
  28.610 +    }
  28.611 +
  28.612 +    // update pointers
  28.613 +    z.next_out_index = p;
  28.614 +    read = q;
  28.615 +
  28.616 +    // done
  28.617 +    return r;
  28.618 +  }
  28.619 +}
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/InfCodes.java	Tue Feb 19 15:59:27 2013 +0100
    29.3 @@ -0,0 +1,612 @@
    29.4 +/* -*-mode:java; c-basic-offset:2; -*- */
    29.5 +/*
    29.6 +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
    29.7 +
    29.8 +Redistribution and use in source and binary forms, with or without
    29.9 +modification, are permitted provided that the following conditions are met:
   29.10 +
   29.11 +  1. Redistributions of source code must retain the above copyright notice,
   29.12 +     this list of conditions and the following disclaimer.
   29.13 +
   29.14 +  2. Redistributions in binary form must reproduce the above copyright 
   29.15 +     notice, this list of conditions and the following disclaimer in 
   29.16 +     the documentation and/or other materials provided with the distribution.
   29.17 +
   29.18 +  3. The names of the authors may not be used to endorse or promote products
   29.19 +     derived from this software without specific prior written permission.
   29.20 +
   29.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   29.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   29.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
   29.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
   29.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   29.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
   29.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   29.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   29.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   29.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   29.31 + */
   29.32 +/*
   29.33 + * This program is based on zlib-1.1.3, so all credit should go authors
   29.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
   29.35 + * and contributors of zlib.
   29.36 + */
   29.37 +
   29.38 +package org.apidesign.bck2brwsr.emul.zip;
   29.39 +
   29.40 +import org.apidesign.bck2brwsr.emul.lang.System;
   29.41 +
   29.42 +final class InfCodes{
   29.43 +
   29.44 +  static final private int[] inflate_mask = {
   29.45 +    0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
   29.46 +    0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
   29.47 +    0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
   29.48 +    0x00007fff, 0x0000ffff
   29.49 +  };
   29.50 +
   29.51 +  static final private int Z_OK=0;
   29.52 +  static final private int Z_STREAM_END=1;
   29.53 +  static final private int Z_NEED_DICT=2;
   29.54 +  static final private int Z_ERRNO=-1;
   29.55 +  static final private int Z_STREAM_ERROR=-2;
   29.56 +  static final private int Z_DATA_ERROR=-3;
   29.57 +  static final private int Z_MEM_ERROR=-4;
   29.58 +  static final private int Z_BUF_ERROR=-5;
   29.59 +  static final private int Z_VERSION_ERROR=-6;
   29.60 +
   29.61 +  // waiting for "i:"=input,
   29.62 +  //             "o:"=output,
   29.63 +  //             "x:"=nothing
   29.64 +  static final private int START=0;  // x: set up for LEN
   29.65 +  static final private int LEN=1;    // i: get length/literal/eob next
   29.66 +  static final private int LENEXT=2; // i: getting length extra (have base)
   29.67 +  static final private int DIST=3;   // i: get distance next
   29.68 +  static final private int DISTEXT=4;// i: getting distance extra
   29.69 +  static final private int COPY=5;   // o: copying bytes in window, waiting for space
   29.70 +  static final private int LIT=6;    // o: got literal, waiting for output space
   29.71 +  static final private int WASH=7;   // o: got eob, possibly still output waiting
   29.72 +  static final private int END=8;    // x: got eob and all data flushed
   29.73 +  static final private int BADCODE=9;// x: got error
   29.74 +
   29.75 +  int mode;      // current inflate_codes mode
   29.76 +
   29.77 +  // mode dependent information
   29.78 +  int len;
   29.79 +
   29.80 +  int[] tree; // pointer into tree
   29.81 +  int tree_index=0;
   29.82 +  int need;   // bits needed
   29.83 +
   29.84 +  int lit;
   29.85 +
   29.86 +  // if EXT or COPY, where and how much
   29.87 +  int get;              // bits to get for extra
   29.88 +  int dist;             // distance back to copy from
   29.89 +
   29.90 +  byte lbits;           // ltree bits decoded per branch
   29.91 +  byte dbits;           // dtree bits decoder per branch
   29.92 +  int[] ltree;          // literal/length/eob tree
   29.93 +  int ltree_index;      // literal/length/eob tree
   29.94 +  int[] dtree;          // distance tree
   29.95 +  int dtree_index;      // distance tree
   29.96 +
   29.97 +  private final ZStream z;
   29.98 +  private final InfBlocks s;
   29.99 +  InfCodes(ZStream z, InfBlocks s){
  29.100 +    this.z=z; 
  29.101 +    this.s=s; 
  29.102 +  }
  29.103 +
  29.104 +  void init(int bl, int bd,
  29.105 +	   int[] tl, int tl_index,
  29.106 +	   int[] td, int td_index){
  29.107 +    mode=START;
  29.108 +    lbits=(byte)bl;
  29.109 +    dbits=(byte)bd;
  29.110 +    ltree=tl;
  29.111 +    ltree_index=tl_index;
  29.112 +    dtree = td;
  29.113 +    dtree_index=td_index;
  29.114 +    tree=null;
  29.115 +  }
  29.116 +
  29.117 +  int proc(int r){ 
  29.118 +    int j;              // temporary storage
  29.119 +    int[] t;            // temporary pointer
  29.120 +    int tindex;         // temporary pointer
  29.121 +    int e;              // extra bits or operation
  29.122 +    int b=0;            // bit buffer
  29.123 +    int k=0;            // bits in bit buffer
  29.124 +    int p=0;            // input data pointer
  29.125 +    int n;              // bytes available there
  29.126 +    int q;              // output window write pointer
  29.127 +    int m;              // bytes to end of window or read pointer
  29.128 +    int f;              // pointer to copy strings from
  29.129 +
  29.130 +    // copy input/output information to locals (UPDATE macro restores)
  29.131 +    p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
  29.132 +    q=s.write;m=q<s.read?s.read-q-1:s.end-q;
  29.133 +
  29.134 +    // process input and output based on current state
  29.135 +    while (true){
  29.136 +      switch (mode){
  29.137 +	// waiting for "i:"=input, "o:"=output, "x:"=nothing
  29.138 +      case START:         // x: set up for LEN
  29.139 +	if (m >= 258 && n >= 10){
  29.140 +
  29.141 +	  s.bitb=b;s.bitk=k;
  29.142 +	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  29.143 +	  s.write=q;
  29.144 +	  r = inflate_fast(lbits, dbits, 
  29.145 +			   ltree, ltree_index, 
  29.146 +			   dtree, dtree_index,
  29.147 +			   s, z);
  29.148 +
  29.149 +	  p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
  29.150 +	  q=s.write;m=q<s.read?s.read-q-1:s.end-q;
  29.151 +
  29.152 +	  if (r != Z_OK){
  29.153 +	    mode = r == Z_STREAM_END ? WASH : BADCODE;
  29.154 +	    break;
  29.155 +	  }
  29.156 +	}
  29.157 +	need = lbits;
  29.158 +	tree = ltree;
  29.159 +	tree_index=ltree_index;
  29.160 +
  29.161 +	mode = LEN;
  29.162 +      case LEN:           // i: get length/literal/eob next
  29.163 +	j = need;
  29.164 +
  29.165 +	while(k<(j)){
  29.166 +	  if(n!=0)r=Z_OK;
  29.167 +	  else{
  29.168 +
  29.169 +	    s.bitb=b;s.bitk=k;
  29.170 +	    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  29.171 +	    s.write=q;
  29.172 +	    return s.inflate_flush(r);
  29.173 +	  }
  29.174 +	  n--;
  29.175 +	  b|=(z.next_in[p++]&0xff)<<k;
  29.176 +	  k+=8;
  29.177 +	}
  29.178 +
  29.179 +	tindex=(tree_index+(b&inflate_mask[j]))*3;
  29.180 +
  29.181 +	b>>>=(tree[tindex+1]);
  29.182 +	k-=(tree[tindex+1]);
  29.183 +
  29.184 +	e=tree[tindex];
  29.185 +
  29.186 +	if(e == 0){               // literal
  29.187 +	  lit = tree[tindex+2];
  29.188 +	  mode = LIT;
  29.189 +	  break;
  29.190 +	}
  29.191 +	if((e & 16)!=0 ){          // length
  29.192 +	  get = e & 15;
  29.193 +	  len = tree[tindex+2];
  29.194 +	  mode = LENEXT;
  29.195 +	  break;
  29.196 +	}
  29.197 +	if ((e & 64) == 0){        // next table
  29.198 +	  need = e;
  29.199 +	  tree_index = tindex/3+tree[tindex+2];
  29.200 +	  break;
  29.201 +	}
  29.202 +	if ((e & 32)!=0){               // end of block
  29.203 +	  mode = WASH;
  29.204 +	  break;
  29.205 +	}
  29.206 +	mode = BADCODE;        // invalid code
  29.207 +	z.msg = "invalid literal/length code";
  29.208 +	r = Z_DATA_ERROR;
  29.209 +
  29.210 +	s.bitb=b;s.bitk=k;
  29.211 +	z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  29.212 +	s.write=q;
  29.213 +	return s.inflate_flush(r);
  29.214 +
  29.215 +      case LENEXT:        // i: getting length extra (have base)
  29.216 +	j = get;
  29.217 +
  29.218 +	while(k<(j)){
  29.219 +	  if(n!=0)r=Z_OK;
  29.220 +	  else{
  29.221 +
  29.222 +	    s.bitb=b;s.bitk=k;
  29.223 +	    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  29.224 +	    s.write=q;
  29.225 +	    return s.inflate_flush(r);
  29.226 +	  }
  29.227 +	  n--; b|=(z.next_in[p++]&0xff)<<k;
  29.228 +	  k+=8;
  29.229 +	}
  29.230 +
  29.231 +	len += (b & inflate_mask[j]);
  29.232 +
  29.233 +	b>>=j;
  29.234 +	k-=j;
  29.235 +
  29.236 +	need = dbits;
  29.237 +	tree = dtree;
  29.238 +	tree_index=dtree_index;
  29.239 +	mode = DIST;
  29.240 +      case DIST:          // i: get distance next
  29.241 +	j = need;
  29.242 +
  29.243 +	while(k<(j)){
  29.244 +	  if(n!=0)r=Z_OK;
  29.245 +	  else{
  29.246 +
  29.247 +	    s.bitb=b;s.bitk=k;
  29.248 +	    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  29.249 +	    s.write=q;
  29.250 +	    return s.inflate_flush(r);
  29.251 +	  }
  29.252 +	  n--; b|=(z.next_in[p++]&0xff)<<k;
  29.253 +	  k+=8;
  29.254 +	}
  29.255 +
  29.256 +	tindex=(tree_index+(b & inflate_mask[j]))*3;
  29.257 +
  29.258 +	b>>=tree[tindex+1];
  29.259 +	k-=tree[tindex+1];
  29.260 +
  29.261 +	e = (tree[tindex]);
  29.262 +	if((e & 16)!=0){               // distance
  29.263 +	  get = e & 15;
  29.264 +	  dist = tree[tindex+2];
  29.265 +	  mode = DISTEXT;
  29.266 +	  break;
  29.267 +	}
  29.268 +	if ((e & 64) == 0){        // next table
  29.269 +	  need = e;
  29.270 +	  tree_index = tindex/3 + tree[tindex+2];
  29.271 +	  break;
  29.272 +	}
  29.273 +	mode = BADCODE;        // invalid code
  29.274 +	z.msg = "invalid distance code";
  29.275 +	r = Z_DATA_ERROR;
  29.276 +
  29.277 +	s.bitb=b;s.bitk=k;
  29.278 +	z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  29.279 +	s.write=q;
  29.280 +	return s.inflate_flush(r);
  29.281 +
  29.282 +      case DISTEXT:       // i: getting distance extra
  29.283 +	j = get;
  29.284 +
  29.285 +	while(k<(j)){
  29.286 +	  if(n!=0)r=Z_OK;
  29.287 +	  else{
  29.288 +
  29.289 +	    s.bitb=b;s.bitk=k;
  29.290 +	    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  29.291 +	    s.write=q;
  29.292 +	    return s.inflate_flush(r);
  29.293 +	  }
  29.294 +	  n--; b|=(z.next_in[p++]&0xff)<<k;
  29.295 +	  k+=8;
  29.296 +	}
  29.297 +
  29.298 +	dist += (b & inflate_mask[j]);
  29.299 +
  29.300 +	b>>=j;
  29.301 +	k-=j;
  29.302 +
  29.303 +	mode = COPY;
  29.304 +      case COPY:          // o: copying bytes in window, waiting for space
  29.305 +        f = q - dist;
  29.306 +        while(f < 0){     // modulo window size-"while" instead
  29.307 +          f += s.end;     // of "if" handles invalid distances
  29.308 +	}
  29.309 +	while (len!=0){
  29.310 +
  29.311 +	  if(m==0){
  29.312 +	    if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
  29.313 +	    if(m==0){
  29.314 +	      s.write=q; r=s.inflate_flush(r);
  29.315 +	      q=s.write;m=q<s.read?s.read-q-1:s.end-q;
  29.316 +
  29.317 +	      if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
  29.318 +
  29.319 +	      if(m==0){
  29.320 +		s.bitb=b;s.bitk=k;
  29.321 +		z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  29.322 +		s.write=q;
  29.323 +		return s.inflate_flush(r);
  29.324 +	      }  
  29.325 +	    }
  29.326 +	  }
  29.327 +
  29.328 +	  s.window[q++]=s.window[f++]; m--;
  29.329 +
  29.330 +	  if (f == s.end)
  29.331 +            f = 0;
  29.332 +	  len--;
  29.333 +	}
  29.334 +	mode = START;
  29.335 +	break;
  29.336 +      case LIT:           // o: got literal, waiting for output space
  29.337 +	if(m==0){
  29.338 +	  if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
  29.339 +	  if(m==0){
  29.340 +	    s.write=q; r=s.inflate_flush(r);
  29.341 +	    q=s.write;m=q<s.read?s.read-q-1:s.end-q;
  29.342 +
  29.343 +	    if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
  29.344 +	    if(m==0){
  29.345 +	      s.bitb=b;s.bitk=k;
  29.346 +	      z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  29.347 +	      s.write=q;
  29.348 +	      return s.inflate_flush(r);
  29.349 +	    }
  29.350 +	  }
  29.351 +	}
  29.352 +	r=Z_OK;
  29.353 +
  29.354 +	s.window[q++]=(byte)lit; m--;
  29.355 +
  29.356 +	mode = START;
  29.357 +	break;
  29.358 +      case WASH:           // o: got eob, possibly more output
  29.359 +	if (k > 7){        // return unused byte, if any
  29.360 +	  k -= 8;
  29.361 +	  n++;
  29.362 +	  p--;             // can always return one
  29.363 +	}
  29.364 +
  29.365 +	s.write=q; r=s.inflate_flush(r);
  29.366 +	q=s.write;m=q<s.read?s.read-q-1:s.end-q;
  29.367 +
  29.368 +	if (s.read != s.write){
  29.369 +	  s.bitb=b;s.bitk=k;
  29.370 +	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  29.371 +	  s.write=q;
  29.372 +	  return s.inflate_flush(r);
  29.373 +	}
  29.374 +	mode = END;
  29.375 +      case END:
  29.376 +	r = Z_STREAM_END;
  29.377 +	s.bitb=b;s.bitk=k;
  29.378 +	z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  29.379 +	s.write=q;
  29.380 +	return s.inflate_flush(r);
  29.381 +
  29.382 +      case BADCODE:       // x: got error
  29.383 +
  29.384 +	r = Z_DATA_ERROR;
  29.385 +
  29.386 +	s.bitb=b;s.bitk=k;
  29.387 +	z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  29.388 +	s.write=q;
  29.389 +	return s.inflate_flush(r);
  29.390 +
  29.391 +      default:
  29.392 +	r = Z_STREAM_ERROR;
  29.393 +
  29.394 +	s.bitb=b;s.bitk=k;
  29.395 +	z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  29.396 +	s.write=q;
  29.397 +	return s.inflate_flush(r);
  29.398 +      }
  29.399 +    }
  29.400 +  }
  29.401 +
  29.402 +  void free(ZStream z){
  29.403 +    //  ZFREE(z, c);
  29.404 +  }
  29.405 +
  29.406 +  // Called with number of bytes left to write in window at least 258
  29.407 +  // (the maximum string length) and number of input bytes available
  29.408 +  // at least ten.  The ten bytes are six bytes for the longest length/
  29.409 +  // distance pair plus four bytes for overloading the bit buffer.
  29.410 +
  29.411 +  int inflate_fast(int bl, int bd, 
  29.412 +		   int[] tl, int tl_index,
  29.413 +		   int[] td, int td_index,
  29.414 +		   InfBlocks s, ZStream z){
  29.415 +    int t;                // temporary pointer
  29.416 +    int[] tp;             // temporary pointer
  29.417 +    int tp_index;         // temporary pointer
  29.418 +    int e;                // extra bits or operation
  29.419 +    int b;                // bit buffer
  29.420 +    int k;                // bits in bit buffer
  29.421 +    int p;                // input data pointer
  29.422 +    int n;                // bytes available there
  29.423 +    int q;                // output window write pointer
  29.424 +    int m;                // bytes to end of window or read pointer
  29.425 +    int ml;               // mask for literal/length tree
  29.426 +    int md;               // mask for distance tree
  29.427 +    int c;                // bytes to copy
  29.428 +    int d;                // distance back to copy from
  29.429 +    int r;                // copy source pointer
  29.430 +
  29.431 +    int tp_index_t_3;     // (tp_index+t)*3
  29.432 +
  29.433 +    // load input, output, bit values
  29.434 +    p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
  29.435 +    q=s.write;m=q<s.read?s.read-q-1:s.end-q;
  29.436 +
  29.437 +    // initialize masks
  29.438 +    ml = inflate_mask[bl];
  29.439 +    md = inflate_mask[bd];
  29.440 +
  29.441 +    // do until not enough input or output space for fast loop
  29.442 +    do {                          // assume called with m >= 258 && n >= 10
  29.443 +      // get literal/length code
  29.444 +      while(k<(20)){              // max bits for literal/length code
  29.445 +	n--;
  29.446 +	b|=(z.next_in[p++]&0xff)<<k;k+=8;
  29.447 +      }
  29.448 +
  29.449 +      t= b&ml;
  29.450 +      tp=tl; 
  29.451 +      tp_index=tl_index;
  29.452 +      tp_index_t_3=(tp_index+t)*3;
  29.453 +      if ((e = tp[tp_index_t_3]) == 0){
  29.454 +	b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
  29.455 +
  29.456 +	s.window[q++] = (byte)tp[tp_index_t_3+2];
  29.457 +	m--;
  29.458 +	continue;
  29.459 +      }
  29.460 +      do {
  29.461 +
  29.462 +	b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
  29.463 +
  29.464 +	if((e&16)!=0){
  29.465 +	  e &= 15;
  29.466 +	  c = tp[tp_index_t_3+2] + ((int)b & inflate_mask[e]);
  29.467 +
  29.468 +	  b>>=e; k-=e;
  29.469 +
  29.470 +	  // decode distance base of block to copy
  29.471 +	  while(k<(15)){           // max bits for distance code
  29.472 +	    n--;
  29.473 +	    b|=(z.next_in[p++]&0xff)<<k;k+=8;
  29.474 +	  }
  29.475 +
  29.476 +	  t= b&md;
  29.477 +	  tp=td;
  29.478 +	  tp_index=td_index;
  29.479 +          tp_index_t_3=(tp_index+t)*3;
  29.480 +	  e = tp[tp_index_t_3];
  29.481 +
  29.482 +	  do {
  29.483 +
  29.484 +	    b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
  29.485 +
  29.486 +	    if((e&16)!=0){
  29.487 +	      // get extra bits to add to distance base
  29.488 +	      e &= 15;
  29.489 +	      while(k<(e)){         // get extra bits (up to 13)
  29.490 +		n--;
  29.491 +		b|=(z.next_in[p++]&0xff)<<k;k+=8;
  29.492 +	      }
  29.493 +
  29.494 +	      d = tp[tp_index_t_3+2] + (b&inflate_mask[e]);
  29.495 +
  29.496 +	      b>>=(e); k-=(e);
  29.497 +
  29.498 +	      // do the copy
  29.499 +	      m -= c;
  29.500 +	      if (q >= d){                // offset before dest
  29.501 +		//  just copy
  29.502 +		r=q-d;
  29.503 +		if(q-r>0 && 2>(q-r)){           
  29.504 +		  s.window[q++]=s.window[r++]; // minimum count is three,
  29.505 +		  s.window[q++]=s.window[r++]; // so unroll loop a little
  29.506 +		  c-=2;
  29.507 +		}
  29.508 +		else{
  29.509 +		  System.arraycopy(s.window, r, s.window, q, 2);
  29.510 +		  q+=2; r+=2; c-=2;
  29.511 +		}
  29.512 +	      }
  29.513 +	      else{                  // else offset after destination
  29.514 +                r=q-d;
  29.515 +                do{
  29.516 +                  r+=s.end;          // force pointer in window
  29.517 +                }while(r<0);         // covers invalid distances
  29.518 +		e=s.end-r;
  29.519 +		if(c>e){             // if source crosses,
  29.520 +		  c-=e;              // wrapped copy
  29.521 +		  if(q-r>0 && e>(q-r)){           
  29.522 +		    do{s.window[q++] = s.window[r++];}
  29.523 +		    while(--e!=0);
  29.524 +		  }
  29.525 +		  else{
  29.526 +		    System.arraycopy(s.window, r, s.window, q, e);
  29.527 +		    q+=e; r+=e; e=0;
  29.528 +		  }
  29.529 +		  r = 0;                  // copy rest from start of window
  29.530 +		}
  29.531 +
  29.532 +	      }
  29.533 +
  29.534 +	      // copy all or what's left
  29.535 +	      if(q-r>0 && c>(q-r)){           
  29.536 +		do{s.window[q++] = s.window[r++];}
  29.537 +		while(--c!=0);
  29.538 +	      }
  29.539 +	      else{
  29.540 +		System.arraycopy(s.window, r, s.window, q, c);
  29.541 +		q+=c; r+=c; c=0;
  29.542 +	      }
  29.543 +	      break;
  29.544 +	    }
  29.545 +	    else if((e&64)==0){
  29.546 +	      t+=tp[tp_index_t_3+2];
  29.547 +	      t+=(b&inflate_mask[e]);
  29.548 +	      tp_index_t_3=(tp_index+t)*3;
  29.549 +	      e=tp[tp_index_t_3];
  29.550 +	    }
  29.551 +	    else{
  29.552 +	      z.msg = "invalid distance code";
  29.553 +
  29.554 +	      c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
  29.555 +
  29.556 +	      s.bitb=b;s.bitk=k;
  29.557 +	      z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  29.558 +	      s.write=q;
  29.559 +
  29.560 +	      return Z_DATA_ERROR;
  29.561 +	    }
  29.562 +	  }
  29.563 +	  while(true);
  29.564 +	  break;
  29.565 +	}
  29.566 +
  29.567 +	if((e&64)==0){
  29.568 +	  t+=tp[tp_index_t_3+2];
  29.569 +	  t+=(b&inflate_mask[e]);
  29.570 +	  tp_index_t_3=(tp_index+t)*3;
  29.571 +	  if((e=tp[tp_index_t_3])==0){
  29.572 +
  29.573 +	    b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
  29.574 +
  29.575 +	    s.window[q++]=(byte)tp[tp_index_t_3+2];
  29.576 +	    m--;
  29.577 +	    break;
  29.578 +	  }
  29.579 +	}
  29.580 +	else if((e&32)!=0){
  29.581 +
  29.582 +	  c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
  29.583 + 
  29.584 +	  s.bitb=b;s.bitk=k;
  29.585 +	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  29.586 +	  s.write=q;
  29.587 +
  29.588 +	  return Z_STREAM_END;
  29.589 +	}
  29.590 +	else{
  29.591 +	  z.msg="invalid literal/length code";
  29.592 +
  29.593 +	  c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
  29.594 +
  29.595 +	  s.bitb=b;s.bitk=k;
  29.596 +	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  29.597 +	  s.write=q;
  29.598 +
  29.599 +	  return Z_DATA_ERROR;
  29.600 +	}
  29.601 +      } 
  29.602 +      while(true);
  29.603 +    } 
  29.604 +    while(m>=258 && n>= 10);
  29.605 +
  29.606 +    // not enough input or output--restore pointers and return
  29.607 +    c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
  29.608 +
  29.609 +    s.bitb=b;s.bitk=k;
  29.610 +    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  29.611 +    s.write=q;
  29.612 +
  29.613 +    return Z_OK;
  29.614 +  }
  29.615 +}
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/InfTree.java	Tue Feb 19 15:59:27 2013 +0100
    30.3 @@ -0,0 +1,520 @@
    30.4 +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
    30.5 +/*
    30.6 +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
    30.7 +
    30.8 +Redistribution and use in source and binary forms, with or without
    30.9 +modification, are permitted provided that the following conditions are met:
   30.10 +
   30.11 +  1. Redistributions of source code must retain the above copyright notice,
   30.12 +     this list of conditions and the following disclaimer.
   30.13 +
   30.14 +  2. Redistributions in binary form must reproduce the above copyright 
   30.15 +     notice, this list of conditions and the following disclaimer in 
   30.16 +     the documentation and/or other materials provided with the distribution.
   30.17 +
   30.18 +  3. The names of the authors may not be used to endorse or promote products
   30.19 +     derived from this software without specific prior written permission.
   30.20 +
   30.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   30.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   30.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
   30.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
   30.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   30.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
   30.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   30.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   30.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   30.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   30.31 + */
   30.32 +/*
   30.33 + * This program is based on zlib-1.1.3, so all credit should go authors
   30.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
   30.35 + * and contributors of zlib.
   30.36 + */
   30.37 +
   30.38 +package org.apidesign.bck2brwsr.emul.zip;
   30.39 +
   30.40 +import org.apidesign.bck2brwsr.emul.lang.System;
   30.41 +
   30.42 +final class InfTree{
   30.43 +
   30.44 +  static final private int MANY=1440;
   30.45 +
   30.46 +  static final private int Z_OK=0;
   30.47 +  static final private int Z_STREAM_END=1;
   30.48 +  static final private int Z_NEED_DICT=2;
   30.49 +  static final private int Z_ERRNO=-1;
   30.50 +  static final private int Z_STREAM_ERROR=-2;
   30.51 +  static final private int Z_DATA_ERROR=-3;
   30.52 +  static final private int Z_MEM_ERROR=-4;
   30.53 +  static final private int Z_BUF_ERROR=-5;
   30.54 +  static final private int Z_VERSION_ERROR=-6;
   30.55 +
   30.56 +  static final int fixed_bl = 9;
   30.57 +  static final int fixed_bd = 5;
   30.58 +
   30.59 +  static final int[] fixed_tl = {
   30.60 +    96,7,256, 0,8,80, 0,8,16, 84,8,115,
   30.61 +    82,7,31, 0,8,112, 0,8,48, 0,9,192,
   30.62 +    80,7,10, 0,8,96, 0,8,32, 0,9,160,
   30.63 +    0,8,0, 0,8,128, 0,8,64, 0,9,224,
   30.64 +    80,7,6, 0,8,88, 0,8,24, 0,9,144,
   30.65 +    83,7,59, 0,8,120, 0,8,56, 0,9,208,
   30.66 +    81,7,17, 0,8,104, 0,8,40, 0,9,176,
   30.67 +    0,8,8, 0,8,136, 0,8,72, 0,9,240,
   30.68 +    80,7,4, 0,8,84, 0,8,20, 85,8,227,
   30.69 +    83,7,43, 0,8,116, 0,8,52, 0,9,200,
   30.70 +    81,7,13, 0,8,100, 0,8,36, 0,9,168,
   30.71 +    0,8,4, 0,8,132, 0,8,68, 0,9,232,
   30.72 +    80,7,8, 0,8,92, 0,8,28, 0,9,152,
   30.73 +    84,7,83, 0,8,124, 0,8,60, 0,9,216,
   30.74 +    82,7,23, 0,8,108, 0,8,44, 0,9,184,
   30.75 +    0,8,12, 0,8,140, 0,8,76, 0,9,248,
   30.76 +    80,7,3, 0,8,82, 0,8,18, 85,8,163,
   30.77 +    83,7,35, 0,8,114, 0,8,50, 0,9,196,
   30.78 +    81,7,11, 0,8,98, 0,8,34, 0,9,164,
   30.79 +    0,8,2, 0,8,130, 0,8,66, 0,9,228,
   30.80 +    80,7,7, 0,8,90, 0,8,26, 0,9,148,
   30.81 +    84,7,67, 0,8,122, 0,8,58, 0,9,212,
   30.82 +    82,7,19, 0,8,106, 0,8,42, 0,9,180,
   30.83 +    0,8,10, 0,8,138, 0,8,74, 0,9,244,
   30.84 +    80,7,5, 0,8,86, 0,8,22, 192,8,0,
   30.85 +    83,7,51, 0,8,118, 0,8,54, 0,9,204,
   30.86 +    81,7,15, 0,8,102, 0,8,38, 0,9,172,
   30.87 +    0,8,6, 0,8,134, 0,8,70, 0,9,236,
   30.88 +    80,7,9, 0,8,94, 0,8,30, 0,9,156,
   30.89 +    84,7,99, 0,8,126, 0,8,62, 0,9,220,
   30.90 +    82,7,27, 0,8,110, 0,8,46, 0,9,188,
   30.91 +    0,8,14, 0,8,142, 0,8,78, 0,9,252,
   30.92 +    96,7,256, 0,8,81, 0,8,17, 85,8,131,
   30.93 +    82,7,31, 0,8,113, 0,8,49, 0,9,194,
   30.94 +    80,7,10, 0,8,97, 0,8,33, 0,9,162,
   30.95 +    0,8,1, 0,8,129, 0,8,65, 0,9,226,
   30.96 +    80,7,6, 0,8,89, 0,8,25, 0,9,146,
   30.97 +    83,7,59, 0,8,121, 0,8,57, 0,9,210,
   30.98 +    81,7,17, 0,8,105, 0,8,41, 0,9,178,
   30.99 +    0,8,9, 0,8,137, 0,8,73, 0,9,242,
  30.100 +    80,7,4, 0,8,85, 0,8,21, 80,8,258,
  30.101 +    83,7,43, 0,8,117, 0,8,53, 0,9,202,
  30.102 +    81,7,13, 0,8,101, 0,8,37, 0,9,170,
  30.103 +    0,8,5, 0,8,133, 0,8,69, 0,9,234,
  30.104 +    80,7,8, 0,8,93, 0,8,29, 0,9,154,
  30.105 +    84,7,83, 0,8,125, 0,8,61, 0,9,218,
  30.106 +    82,7,23, 0,8,109, 0,8,45, 0,9,186,
  30.107 +    0,8,13, 0,8,141, 0,8,77, 0,9,250,
  30.108 +    80,7,3, 0,8,83, 0,8,19, 85,8,195,
  30.109 +    83,7,35, 0,8,115, 0,8,51, 0,9,198,
  30.110 +    81,7,11, 0,8,99, 0,8,35, 0,9,166,
  30.111 +    0,8,3, 0,8,131, 0,8,67, 0,9,230,
  30.112 +    80,7,7, 0,8,91, 0,8,27, 0,9,150,
  30.113 +    84,7,67, 0,8,123, 0,8,59, 0,9,214,
  30.114 +    82,7,19, 0,8,107, 0,8,43, 0,9,182,
  30.115 +    0,8,11, 0,8,139, 0,8,75, 0,9,246,
  30.116 +    80,7,5, 0,8,87, 0,8,23, 192,8,0,
  30.117 +    83,7,51, 0,8,119, 0,8,55, 0,9,206,
  30.118 +    81,7,15, 0,8,103, 0,8,39, 0,9,174,
  30.119 +    0,8,7, 0,8,135, 0,8,71, 0,9,238,
  30.120 +    80,7,9, 0,8,95, 0,8,31, 0,9,158,
  30.121 +    84,7,99, 0,8,127, 0,8,63, 0,9,222,
  30.122 +    82,7,27, 0,8,111, 0,8,47, 0,9,190,
  30.123 +    0,8,15, 0,8,143, 0,8,79, 0,9,254,
  30.124 +    96,7,256, 0,8,80, 0,8,16, 84,8,115,
  30.125 +    82,7,31, 0,8,112, 0,8,48, 0,9,193,
  30.126 +
  30.127 +    80,7,10, 0,8,96, 0,8,32, 0,9,161,
  30.128 +    0,8,0, 0,8,128, 0,8,64, 0,9,225,
  30.129 +    80,7,6, 0,8,88, 0,8,24, 0,9,145,
  30.130 +    83,7,59, 0,8,120, 0,8,56, 0,9,209,
  30.131 +    81,7,17, 0,8,104, 0,8,40, 0,9,177,
  30.132 +    0,8,8, 0,8,136, 0,8,72, 0,9,241,
  30.133 +    80,7,4, 0,8,84, 0,8,20, 85,8,227,
  30.134 +    83,7,43, 0,8,116, 0,8,52, 0,9,201,
  30.135 +    81,7,13, 0,8,100, 0,8,36, 0,9,169,
  30.136 +    0,8,4, 0,8,132, 0,8,68, 0,9,233,
  30.137 +    80,7,8, 0,8,92, 0,8,28, 0,9,153,
  30.138 +    84,7,83, 0,8,124, 0,8,60, 0,9,217,
  30.139 +    82,7,23, 0,8,108, 0,8,44, 0,9,185,
  30.140 +    0,8,12, 0,8,140, 0,8,76, 0,9,249,
  30.141 +    80,7,3, 0,8,82, 0,8,18, 85,8,163,
  30.142 +    83,7,35, 0,8,114, 0,8,50, 0,9,197,
  30.143 +    81,7,11, 0,8,98, 0,8,34, 0,9,165,
  30.144 +    0,8,2, 0,8,130, 0,8,66, 0,9,229,
  30.145 +    80,7,7, 0,8,90, 0,8,26, 0,9,149,
  30.146 +    84,7,67, 0,8,122, 0,8,58, 0,9,213,
  30.147 +    82,7,19, 0,8,106, 0,8,42, 0,9,181,
  30.148 +    0,8,10, 0,8,138, 0,8,74, 0,9,245,
  30.149 +    80,7,5, 0,8,86, 0,8,22, 192,8,0,
  30.150 +    83,7,51, 0,8,118, 0,8,54, 0,9,205,
  30.151 +    81,7,15, 0,8,102, 0,8,38, 0,9,173,
  30.152 +    0,8,6, 0,8,134, 0,8,70, 0,9,237,
  30.153 +    80,7,9, 0,8,94, 0,8,30, 0,9,157,
  30.154 +    84,7,99, 0,8,126, 0,8,62, 0,9,221,
  30.155 +    82,7,27, 0,8,110, 0,8,46, 0,9,189,
  30.156 +    0,8,14, 0,8,142, 0,8,78, 0,9,253,
  30.157 +    96,7,256, 0,8,81, 0,8,17, 85,8,131,
  30.158 +    82,7,31, 0,8,113, 0,8,49, 0,9,195,
  30.159 +    80,7,10, 0,8,97, 0,8,33, 0,9,163,
  30.160 +    0,8,1, 0,8,129, 0,8,65, 0,9,227,
  30.161 +    80,7,6, 0,8,89, 0,8,25, 0,9,147,
  30.162 +    83,7,59, 0,8,121, 0,8,57, 0,9,211,
  30.163 +    81,7,17, 0,8,105, 0,8,41, 0,9,179,
  30.164 +    0,8,9, 0,8,137, 0,8,73, 0,9,243,
  30.165 +    80,7,4, 0,8,85, 0,8,21, 80,8,258,
  30.166 +    83,7,43, 0,8,117, 0,8,53, 0,9,203,
  30.167 +    81,7,13, 0,8,101, 0,8,37, 0,9,171,
  30.168 +    0,8,5, 0,8,133, 0,8,69, 0,9,235,
  30.169 +    80,7,8, 0,8,93, 0,8,29, 0,9,155,
  30.170 +    84,7,83, 0,8,125, 0,8,61, 0,9,219,
  30.171 +    82,7,23, 0,8,109, 0,8,45, 0,9,187,
  30.172 +    0,8,13, 0,8,141, 0,8,77, 0,9,251,
  30.173 +    80,7,3, 0,8,83, 0,8,19, 85,8,195,
  30.174 +    83,7,35, 0,8,115, 0,8,51, 0,9,199,
  30.175 +    81,7,11, 0,8,99, 0,8,35, 0,9,167,
  30.176 +    0,8,3, 0,8,131, 0,8,67, 0,9,231,
  30.177 +    80,7,7, 0,8,91, 0,8,27, 0,9,151,
  30.178 +    84,7,67, 0,8,123, 0,8,59, 0,9,215,
  30.179 +    82,7,19, 0,8,107, 0,8,43, 0,9,183,
  30.180 +    0,8,11, 0,8,139, 0,8,75, 0,9,247,
  30.181 +    80,7,5, 0,8,87, 0,8,23, 192,8,0,
  30.182 +    83,7,51, 0,8,119, 0,8,55, 0,9,207,
  30.183 +    81,7,15, 0,8,103, 0,8,39, 0,9,175,
  30.184 +    0,8,7, 0,8,135, 0,8,71, 0,9,239,
  30.185 +    80,7,9, 0,8,95, 0,8,31, 0,9,159,
  30.186 +    84,7,99, 0,8,127, 0,8,63, 0,9,223,
  30.187 +    82,7,27, 0,8,111, 0,8,47, 0,9,191,
  30.188 +    0,8,15, 0,8,143, 0,8,79, 0,9,255
  30.189 +  };
  30.190 +  static final int[] fixed_td = {
  30.191 +    80,5,1, 87,5,257, 83,5,17, 91,5,4097,
  30.192 +    81,5,5, 89,5,1025, 85,5,65, 93,5,16385,
  30.193 +    80,5,3, 88,5,513, 84,5,33, 92,5,8193,
  30.194 +    82,5,9, 90,5,2049, 86,5,129, 192,5,24577,
  30.195 +    80,5,2, 87,5,385, 83,5,25, 91,5,6145,
  30.196 +    81,5,7, 89,5,1537, 85,5,97, 93,5,24577,
  30.197 +    80,5,4, 88,5,769, 84,5,49, 92,5,12289,
  30.198 +    82,5,13, 90,5,3073, 86,5,193, 192,5,24577
  30.199 +  };
  30.200 +
  30.201 +  // Tables for deflate from PKZIP's appnote.txt.
  30.202 +  static final int[] cplens = { // Copy lengths for literal codes 257..285
  30.203 +        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
  30.204 +        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
  30.205 +  };
  30.206 +
  30.207 +  // see note #13 above about 258
  30.208 +  static final int[] cplext = { // Extra bits for literal codes 257..285
  30.209 +        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
  30.210 +        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112  // 112==invalid
  30.211 +  };
  30.212 +
  30.213 +  static final int[] cpdist = { // Copy offsets for distance codes 0..29
  30.214 +        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
  30.215 +        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
  30.216 +        8193, 12289, 16385, 24577
  30.217 +  };
  30.218 +
  30.219 +  static final int[] cpdext = { // Extra bits for distance codes
  30.220 +        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
  30.221 +        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
  30.222 +        12, 12, 13, 13};
  30.223 +
  30.224 +  // If BMAX needs to be larger than 16, then h and x[] should be uLong.
  30.225 +  static final int BMAX=15;         // maximum bit length of any code
  30.226 +
  30.227 +  int[] hn = null;  // hufts used in space
  30.228 +  int[] v = null;   // work area for huft_build 
  30.229 +  int[] c = null;   // bit length count table
  30.230 +  int[] r = null;   // table entry for structure assignment
  30.231 +  int[] u = null;   // table stack
  30.232 +  int[] x = null;   // bit offsets, then code stack
  30.233 +
  30.234 +  private int huft_build(int[] b, // code lengths in bits (all assumed <= BMAX)
  30.235 +                         int bindex, 
  30.236 +                         int n,   // number of codes (assumed <= 288)
  30.237 +                         int s,   // number of simple-valued codes (0..s-1)
  30.238 +                         int[] d, // list of base values for non-simple codes
  30.239 +                         int[] e, // list of extra bits for non-simple codes
  30.240 +                         int[] t, // result: starting table
  30.241 +                         int[] m, // maximum lookup bits, returns actual
  30.242 +                         int[] hp,// space for trees
  30.243 +                         int[] hn,// hufts used in space
  30.244 +                         int[] v  // working area: values in order of bit length
  30.245 +                         ){
  30.246 +    // Given a list of code lengths and a maximum table size, make a set of
  30.247 +    // tables to decode that set of codes.  Return Z_OK on success, Z_BUF_ERROR
  30.248 +    // if the given code set is incomplete (the tables are still built in this
  30.249 +    // case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
  30.250 +    // lengths), or Z_MEM_ERROR if not enough memory.
  30.251 +
  30.252 +    int a;                       // counter for codes of length k
  30.253 +    int f;                       // i repeats in table every f entries
  30.254 +    int g;                       // maximum code length
  30.255 +    int h;                       // table level
  30.256 +    int i;                       // counter, current code
  30.257 +    int j;                       // counter
  30.258 +    int k;                       // number of bits in current code
  30.259 +    int l;                       // bits per table (returned in m)
  30.260 +    int mask;                    // (1 << w) - 1, to avoid cc -O bug on HP
  30.261 +    int p;                       // pointer into c[], b[], or v[]
  30.262 +    int q;                       // points to current table
  30.263 +    int w;                       // bits before this table == (l * h)
  30.264 +    int xp;                      // pointer into x
  30.265 +    int y;                       // number of dummy codes added
  30.266 +    int z;                       // number of entries in current table
  30.267 +
  30.268 +    // Generate counts for each bit length
  30.269 +
  30.270 +    p = 0; i = n;
  30.271 +    do {
  30.272 +      c[b[bindex+p]]++; p++; i--;   // assume all entries <= BMAX
  30.273 +    }while(i!=0);
  30.274 +
  30.275 +    if(c[0] == n){                // null input--all zero length codes
  30.276 +      t[0] = -1;
  30.277 +      m[0] = 0;
  30.278 +      return Z_OK;
  30.279 +    }
  30.280 +
  30.281 +    // Find minimum and maximum length, bound *m by those
  30.282 +    l = m[0];
  30.283 +    for (j = 1; j <= BMAX; j++)
  30.284 +      if(c[j]!=0) break;
  30.285 +    k = j;                        // minimum code length
  30.286 +    if(l < j){
  30.287 +      l = j;
  30.288 +    }
  30.289 +    for (i = BMAX; i!=0; i--){
  30.290 +      if(c[i]!=0) break;
  30.291 +    }
  30.292 +    g = i;                        // maximum code length
  30.293 +    if(l > i){
  30.294 +      l = i;
  30.295 +    }
  30.296 +    m[0] = l;
  30.297 +
  30.298 +    // Adjust last length count to fill out codes, if needed
  30.299 +    for (y = 1 << j; j < i; j++, y <<= 1){
  30.300 +      if ((y -= c[j]) < 0){
  30.301 +        return Z_DATA_ERROR;
  30.302 +      }
  30.303 +    }
  30.304 +    if ((y -= c[i]) < 0){
  30.305 +      return Z_DATA_ERROR;
  30.306 +    }
  30.307 +    c[i] += y;
  30.308 +
  30.309 +    // Generate starting offsets into the value table for each length
  30.310 +    x[1] = j = 0;
  30.311 +    p = 1;  xp = 2;
  30.312 +    while (--i!=0) {                 // note that i == g from above
  30.313 +      x[xp] = (j += c[p]);
  30.314 +      xp++;
  30.315 +      p++;
  30.316 +    }
  30.317 +
  30.318 +    // Make a table of values in order of bit lengths
  30.319 +    i = 0; p = 0;
  30.320 +    do {
  30.321 +      if ((j = b[bindex+p]) != 0){
  30.322 +        v[x[j]++] = i;
  30.323 +      }
  30.324 +      p++;
  30.325 +    }
  30.326 +    while (++i < n);
  30.327 +    n = x[g];                     // set n to length of v
  30.328 +
  30.329 +    // Generate the Huffman codes and for each, make the table entries
  30.330 +    x[0] = i = 0;                 // first Huffman code is zero
  30.331 +    p = 0;                        // grab values in bit order
  30.332 +    h = -1;                       // no tables yet--level -1
  30.333 +    w = -l;                       // bits decoded == (l * h)
  30.334 +    u[0] = 0;                     // just to keep compilers happy
  30.335 +    q = 0;                        // ditto
  30.336 +    z = 0;                        // ditto
  30.337 +
  30.338 +    // go through the bit lengths (k already is bits in shortest code)
  30.339 +    for (; k <= g; k++){
  30.340 +      a = c[k];
  30.341 +      while (a--!=0){
  30.342 +	// here i is the Huffman code of length k bits for value *p
  30.343 +	// make tables up to required level
  30.344 +        while (k > w + l){
  30.345 +          h++;
  30.346 +          w += l;                 // previous table always l bits
  30.347 +	  // compute minimum size table less than or equal to l bits
  30.348 +          z = g - w;
  30.349 +          z = (z > l) ? l : z;        // table size upper limit
  30.350 +          if((f=1<<(j=k-w))>a+1){     // try a k-w bit table
  30.351 +                                      // too few codes for k-w bit table
  30.352 +            f -= a + 1;               // deduct codes from patterns left
  30.353 +            xp = k;
  30.354 +            if(j < z){
  30.355 +              while (++j < z){        // try smaller tables up to z bits
  30.356 +                if((f <<= 1) <= c[++xp])
  30.357 +                  break;              // enough codes to use up j bits
  30.358 +                f -= c[xp];           // else deduct codes from patterns
  30.359 +              }
  30.360 +	    }
  30.361 +          }
  30.362 +          z = 1 << j;                 // table entries for j-bit table
  30.363 +
  30.364 +	  // allocate new table
  30.365 +          if (hn[0] + z > MANY){       // (note: doesn't matter for fixed)
  30.366 +            return Z_DATA_ERROR;       // overflow of MANY
  30.367 +          }
  30.368 +          u[h] = q = /*hp+*/ hn[0];   // DEBUG
  30.369 +          hn[0] += z;
  30.370 + 
  30.371 +	  // connect to last table, if there is one
  30.372 +	  if(h!=0){
  30.373 +            x[h]=i;           // save pattern for backing up
  30.374 +            r[0]=(byte)j;     // bits in this table
  30.375 +            r[1]=(byte)l;     // bits to dump before this table
  30.376 +            j=i>>>(w - l);
  30.377 +            r[2] = (int)(q - u[h-1] - j);               // offset to this table
  30.378 +            System.arraycopy(r, 0, hp, (u[h-1]+j)*3, 3); // connect to last table
  30.379 +          }
  30.380 +          else{
  30.381 +            t[0] = q;               // first table is returned result
  30.382 +	  }
  30.383 +        }
  30.384 +
  30.385 +	// set up table entry in r
  30.386 +        r[1] = (byte)(k - w);
  30.387 +        if (p >= n){
  30.388 +          r[0] = 128 + 64;      // out of values--invalid code
  30.389 +	}
  30.390 +        else if (v[p] < s){
  30.391 +          r[0] = (byte)(v[p] < 256 ? 0 : 32 + 64);  // 256 is end-of-block
  30.392 +          r[2] = v[p++];          // simple code is just the value
  30.393 +        }
  30.394 +        else{
  30.395 +          r[0]=(byte)(e[v[p]-s]+16+64); // non-simple--look up in lists
  30.396 +          r[2]=d[v[p++] - s];
  30.397 +        }
  30.398 +
  30.399 +        // fill code-like entries with r
  30.400 +        f=1<<(k-w);
  30.401 +        for (j=i>>>w;j<z;j+=f){
  30.402 +          System.arraycopy(r, 0, hp, (q+j)*3, 3);
  30.403 +	}
  30.404 +
  30.405 +	// backwards increment the k-bit code i
  30.406 +        for (j = 1 << (k - 1); (i & j)!=0; j >>>= 1){
  30.407 +          i ^= j;
  30.408 +	}
  30.409 +        i ^= j;
  30.410 +
  30.411 +	// backup over finished tables
  30.412 +        mask = (1 << w) - 1;      // needed on HP, cc -O bug
  30.413 +        while ((i & mask) != x[h]){
  30.414 +          h--;                    // don't need to update q
  30.415 +          w -= l;
  30.416 +          mask = (1 << w) - 1;
  30.417 +        }
  30.418 +      }
  30.419 +    }
  30.420 +    // Return Z_BUF_ERROR if we were given an incomplete table
  30.421 +    return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
  30.422 +  }
  30.423 +
  30.424 +  int inflate_trees_bits(int[] c,  // 19 code lengths
  30.425 +                         int[] bb, // bits tree desired/actual depth
  30.426 +                         int[] tb, // bits tree result
  30.427 +                         int[] hp, // space for trees
  30.428 +                         ZStream z // for messages
  30.429 +                         ){
  30.430 +    int result;
  30.431 +    initWorkArea(19);
  30.432 +    hn[0]=0;
  30.433 +    result = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);
  30.434 +
  30.435 +    if(result == Z_DATA_ERROR){
  30.436 +      z.msg = "oversubscribed dynamic bit lengths tree";
  30.437 +    }
  30.438 +    else if(result == Z_BUF_ERROR || bb[0] == 0){
  30.439 +      z.msg = "incomplete dynamic bit lengths tree";
  30.440 +      result = Z_DATA_ERROR;
  30.441 +    }
  30.442 +    return result;
  30.443 +  }
  30.444 +
  30.445 +  int inflate_trees_dynamic(int nl,   // number of literal/length codes
  30.446 +                            int nd,   // number of distance codes
  30.447 +                            int[] c,  // that many (total) code lengths
  30.448 +                            int[] bl, // literal desired/actual bit depth
  30.449 +                            int[] bd, // distance desired/actual bit depth 
  30.450 +                            int[] tl, // literal/length tree result
  30.451 +                            int[] td, // distance tree result
  30.452 +                            int[] hp, // space for trees
  30.453 +                            ZStream z // for messages
  30.454 +                            ){
  30.455 +    int result;
  30.456 +
  30.457 +    // build literal/length tree
  30.458 +    initWorkArea(288);
  30.459 +    hn[0]=0;
  30.460 +    result = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);
  30.461 +    if (result != Z_OK || bl[0] == 0){
  30.462 +      if(result == Z_DATA_ERROR){
  30.463 +        z.msg = "oversubscribed literal/length tree";
  30.464 +      }
  30.465 +      else if (result != Z_MEM_ERROR){
  30.466 +        z.msg = "incomplete literal/length tree";
  30.467 +        result = Z_DATA_ERROR;
  30.468 +      }
  30.469 +      return result;
  30.470 +    }
  30.471 +
  30.472 +    // build distance tree
  30.473 +    initWorkArea(288);
  30.474 +    result = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);
  30.475 +
  30.476 +    if (result != Z_OK || (bd[0] == 0 && nl > 257)){
  30.477 +      if (result == Z_DATA_ERROR){
  30.478 +        z.msg = "oversubscribed distance tree";
  30.479 +      }
  30.480 +      else if (result == Z_BUF_ERROR) {
  30.481 +        z.msg = "incomplete distance tree";
  30.482 +        result = Z_DATA_ERROR;
  30.483 +      }
  30.484 +      else if (result != Z_MEM_ERROR){
  30.485 +        z.msg = "empty distance tree with lengths";
  30.486 +        result = Z_DATA_ERROR;
  30.487 +      }
  30.488 +      return result;
  30.489 +    }
  30.490 +
  30.491 +    return Z_OK;
  30.492 +  }
  30.493 +
  30.494 +  static int inflate_trees_fixed(int[] bl,  //literal desired/actual bit depth
  30.495 +                                 int[] bd,  //distance desired/actual bit depth
  30.496 +                                 int[][] tl,//literal/length tree result
  30.497 +                                 int[][] td,//distance tree result 
  30.498 +                                 ZStream z  //for memory allocation
  30.499 +				 ){
  30.500 +    bl[0]=fixed_bl;
  30.501 +    bd[0]=fixed_bd;
  30.502 +    tl[0]=fixed_tl;
  30.503 +    td[0]=fixed_td;
  30.504 +    return Z_OK;
  30.505 +  }
  30.506 +
  30.507 +  private void initWorkArea(int vsize){
  30.508 +    if(hn==null){
  30.509 +      hn=new int[1];
  30.510 +      v=new int[vsize];
  30.511 +      c=new int[BMAX+1];
  30.512 +      r=new int[3];
  30.513 +      u=new int[BMAX];
  30.514 +      x=new int[BMAX+1];
  30.515 +    }
  30.516 +    if(v.length<vsize){ v=new int[vsize]; }
  30.517 +    for(int i=0; i<vsize; i++){v[i]=0;}
  30.518 +    for(int i=0; i<BMAX+1; i++){c[i]=0;}
  30.519 +    for(int i=0; i<3; i++){r[i]=0;}
  30.520 +    System.arraycopy(c, 0, u, 0, BMAX);
  30.521 +    System.arraycopy(c, 0, x, 0, BMAX+1);
  30.522 +  }
  30.523 +}
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/Inflate.java	Tue Feb 19 15:59:27 2013 +0100
    31.3 @@ -0,0 +1,727 @@
    31.4 +/* -*-mode:java; c-basic-offset:2; -*- */
    31.5 +/*
    31.6 +Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved.
    31.7 +
    31.8 +Redistribution and use in source and binary forms, with or without
    31.9 +modification, are permitted provided that the following conditions are met:
   31.10 +
   31.11 +  1. Redistributions of source code must retain the above copyright notice,
   31.12 +     this list of conditions and the following disclaimer.
   31.13 +
   31.14 +  2. Redistributions in binary form must reproduce the above copyright 
   31.15 +     notice, this list of conditions and the following disclaimer in 
   31.16 +     the documentation and/or other materials provided with the distribution.
   31.17 +
   31.18 +  3. The names of the authors may not be used to endorse or promote products
   31.19 +     derived from this software without specific prior written permission.
   31.20 +
   31.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   31.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   31.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
   31.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
   31.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   31.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
   31.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   31.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   31.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   31.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   31.31 + */
   31.32 +/*
   31.33 + * This program is based on zlib-1.1.3, so all credit should go authors
   31.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
   31.35 + * and contributors of zlib.
   31.36 + */
   31.37 +
   31.38 +package org.apidesign.bck2brwsr.emul.zip;
   31.39 +
   31.40 +import org.apidesign.bck2brwsr.emul.lang.System;
   31.41 +
   31.42 +final class Inflate{
   31.43 +  
   31.44 +  static final private int MAX_WBITS=15; // 32K LZ77 window
   31.45 +
   31.46 +  // preset dictionary flag in zlib header
   31.47 +  static final private int PRESET_DICT=0x20;
   31.48 +
   31.49 +  static final int Z_NO_FLUSH=0;
   31.50 +  static final int Z_PARTIAL_FLUSH=1;
   31.51 +  static final int Z_SYNC_FLUSH=2;
   31.52 +  static final int Z_FULL_FLUSH=3;
   31.53 +  static final int Z_FINISH=4;
   31.54 +
   31.55 +  static final private int Z_DEFLATED=8;
   31.56 +
   31.57 +  static final private int Z_OK=0;
   31.58 +  static final private int Z_STREAM_END=1;
   31.59 +  static final private int Z_NEED_DICT=2;
   31.60 +  static final private int Z_ERRNO=-1;
   31.61 +  static final private int Z_STREAM_ERROR=-2;
   31.62 +  static final private int Z_DATA_ERROR=-3;
   31.63 +  static final private int Z_MEM_ERROR=-4;
   31.64 +  static final private int Z_BUF_ERROR=-5;
   31.65 +  static final private int Z_VERSION_ERROR=-6;
   31.66 +
   31.67 +  static final private int METHOD=0;   // waiting for method byte
   31.68 +  static final private int FLAG=1;     // waiting for flag byte
   31.69 +  static final private int DICT4=2;    // four dictionary check bytes to go
   31.70 +  static final private int DICT3=3;    // three dictionary check bytes to go
   31.71 +  static final private int DICT2=4;    // two dictionary check bytes to go
   31.72 +  static final private int DICT1=5;    // one dictionary check byte to go
   31.73 +  static final int DICT0=6;    // waiting for inflateSetDictionary
   31.74 +  static final private int BLOCKS=7;   // decompressing blocks
   31.75 +  static final private int CHECK4=8;   // four check bytes to go
   31.76 +  static final private int CHECK3=9;   // three check bytes to go
   31.77 +  static final private int CHECK2=10;  // two check bytes to go
   31.78 +  static final private int CHECK1=11;  // one check byte to go
   31.79 +  static final private int DONE=12;    // finished check, done
   31.80 +  static final private int BAD=13;     // got an error--stay here
   31.81 +
   31.82 +  static final private int HEAD=14;
   31.83 +  static final private int LENGTH=15;
   31.84 +  static final private int TIME=16;
   31.85 +  static final private int OS=17;
   31.86 +  static final private int EXLEN=18;
   31.87 +  static final private int EXTRA=19;
   31.88 +  static final private int NAME=20;
   31.89 +  static final private int COMMENT=21;
   31.90 +  static final private int HCRC=22;
   31.91 +  static final private int FLAGS=23;
   31.92 +
   31.93 +  int mode;                            // current inflate mode
   31.94 +
   31.95 +  // mode dependent information
   31.96 +  int method;        // if FLAGS, method byte
   31.97 +
   31.98 +  // if CHECK, check values to compare
   31.99 +  long was = -1;           // computed check value
  31.100 +  long need;               // stream check value
  31.101 +
  31.102 +  // if BAD, inflateSync's marker bytes count
  31.103 +  int marker;
  31.104 +
  31.105 +  // mode independent information
  31.106 +  int  wrap;          // flag for no wrapper
  31.107 +  int wbits;            // log2(window size)  (8..15, defaults to 15)
  31.108 +
  31.109 +  InfBlocks blocks;     // current inflate_blocks state
  31.110 +
  31.111 +  private final ZStream z;
  31.112 +
  31.113 +  private int flags; 
  31.114 +
  31.115 +  private int need_bytes = -1;
  31.116 +  private byte[] crcbuf=new byte[4];
  31.117 +
  31.118 +  GZIPHeader gheader = null;
  31.119 +
  31.120 +  int inflateReset(){
  31.121 +    if(z == null) return Z_STREAM_ERROR;
  31.122 +    
  31.123 +    z.total_in = z.total_out = 0;
  31.124 +    z.msg = null;
  31.125 +    this.mode = HEAD;
  31.126 +    this.need_bytes = -1;
  31.127 +    this.blocks.reset();
  31.128 +    return Z_OK;
  31.129 +  }
  31.130 +
  31.131 +  int inflateEnd(){
  31.132 +    if(blocks != null){
  31.133 +      blocks.free();
  31.134 +    }
  31.135 +    return Z_OK;
  31.136 +  }
  31.137 +
  31.138 +  Inflate(ZStream z){
  31.139 +    this.z=z;
  31.140 +  }
  31.141 +
  31.142 +  int inflateInit(int w){
  31.143 +    z.msg = null;
  31.144 +    blocks = null;
  31.145 +
  31.146 +    // handle undocumented wrap option (no zlib header or check)
  31.147 +    wrap = 0;
  31.148 +    if(w < 0){
  31.149 +      w = - w;
  31.150 +    }
  31.151 +    else {
  31.152 +      wrap = (w >> 4) + 1;
  31.153 +      if(w < 48)
  31.154 +        w &= 15;
  31.155 +    }
  31.156 +
  31.157 +    if(w<8 ||w>15){
  31.158 +      inflateEnd();
  31.159 +      return Z_STREAM_ERROR;
  31.160 +    }
  31.161 +    if(blocks != null && wbits != w){
  31.162 +      blocks.free();
  31.163 +      blocks=null;
  31.164 +    }
  31.165 +
  31.166 +    // set window size
  31.167 +    wbits=w;
  31.168 +
  31.169 +    this.blocks=new InfBlocks(z, 1<<w);
  31.170 +
  31.171 +    // reset state
  31.172 +    inflateReset();
  31.173 +
  31.174 +    return Z_OK;
  31.175 +  }
  31.176 +
  31.177 +  int inflate(int f){
  31.178 +    int hold = 0;
  31.179 +
  31.180 +    int r;
  31.181 +    int b;
  31.182 +
  31.183 +    if(z == null || z.next_in == null){
  31.184 +      if(f == Z_FINISH && this.mode==HEAD)
  31.185 +        return Z_OK; 
  31.186 +      return Z_STREAM_ERROR;
  31.187 +    }
  31.188 +
  31.189 +    f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
  31.190 +    r = Z_BUF_ERROR;
  31.191 +    while (true){
  31.192 +
  31.193 +      switch (this.mode){
  31.194 +      case HEAD:
  31.195 +        if(wrap==0){
  31.196 +	  this.mode = BLOCKS;
  31.197 +          break;
  31.198 +        } 
  31.199 +
  31.200 +        try { r=readBytes(2, r, f); }
  31.201 +        catch(Return e){ return e.r; }
  31.202 +
  31.203 +        if((wrap&2)!=0 && this.need == 0x8b1fL) {   // gzip header
  31.204 +	  z.adler=new CRC32();
  31.205 +          checksum(2, this.need);
  31.206 +
  31.207 +          if(gheader==null) 
  31.208 +            gheader=new GZIPHeader();
  31.209 +
  31.210 +          this.mode = FLAGS;
  31.211 +          break;
  31.212 +        }
  31.213 +
  31.214 +        flags = 0;
  31.215 +
  31.216 +        this.method = ((int)this.need)&0xff;
  31.217 +        b=((int)(this.need>>8))&0xff;
  31.218 +
  31.219 +        if((wrap&1)==0 ||  // check if zlib header allowed
  31.220 +           (((this.method << 8)+b) % 31)!=0){
  31.221 +          this.mode = BAD;
  31.222 +          z.msg = "incorrect header check";
  31.223 +          // since zlib 1.2, it is allowted to inflateSync for this case.
  31.224 +          /*
  31.225 +          this.marker = 5;       // can't try inflateSync
  31.226 +          */
  31.227 +          break;
  31.228 +        }
  31.229 +
  31.230 +        if((this.method&0xf)!=Z_DEFLATED){
  31.231 +          this.mode = BAD;
  31.232 +          z.msg="unknown compression method";
  31.233 +          // since zlib 1.2, it is allowted to inflateSync for this case.
  31.234 +	  /*
  31.235 +          this.marker = 5;       // can't try inflateSync
  31.236 +	  */
  31.237 +          break;
  31.238 +        }
  31.239 +
  31.240 +        if((this.method>>4)+8>this.wbits){
  31.241 +          this.mode = BAD;
  31.242 +          z.msg="invalid window size";
  31.243 +          // since zlib 1.2, it is allowted to inflateSync for this case.
  31.244 +	  /*
  31.245 +          this.marker = 5;       // can't try inflateSync
  31.246 +	  */
  31.247 +          break;
  31.248 +        }
  31.249 +
  31.250 +        z.adler=new Adler32();
  31.251 +
  31.252 +        if((b&PRESET_DICT)==0){
  31.253 +          this.mode = BLOCKS;
  31.254 +          break;
  31.255 +        }
  31.256 +        this.mode = DICT4;
  31.257 +      case DICT4:
  31.258 +
  31.259 +        if(z.avail_in==0)return r;r=f;
  31.260 +
  31.261 +        z.avail_in--; z.total_in++;
  31.262 +        this.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L;
  31.263 +        this.mode=DICT3;
  31.264 +      case DICT3:
  31.265 +
  31.266 +        if(z.avail_in==0)return r;r=f;
  31.267 +
  31.268 +        z.avail_in--; z.total_in++;
  31.269 +        this.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L;
  31.270 +        this.mode=DICT2;
  31.271 +      case DICT2:
  31.272 +
  31.273 +        if(z.avail_in==0)return r;r=f;
  31.274 +
  31.275 +        z.avail_in--; z.total_in++;
  31.276 +        this.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L;
  31.277 +        this.mode=DICT1;
  31.278 +      case DICT1:
  31.279 +
  31.280 +        if(z.avail_in==0)return r;r=f;
  31.281 +
  31.282 +        z.avail_in--; z.total_in++;
  31.283 +        this.need += (z.next_in[z.next_in_index++]&0xffL);
  31.284 +        z.adler.reset(this.need);
  31.285 +        this.mode = DICT0;
  31.286 +        return Z_NEED_DICT;
  31.287 +      case DICT0:
  31.288 +        this.mode = BAD;
  31.289 +        z.msg = "need dictionary";
  31.290 +        this.marker = 0;       // can try inflateSync
  31.291 +        return Z_STREAM_ERROR;
  31.292 +      case BLOCKS:
  31.293 +        r = this.blocks.proc(r);
  31.294 +        if(r == Z_DATA_ERROR){
  31.295 +          this.mode = BAD;
  31.296 +          this.marker = 0;     // can try inflateSync
  31.297 +          break;
  31.298 +        }
  31.299 +        if(r == Z_OK){
  31.300 +          r = f;
  31.301 +        }
  31.302 +        if(r != Z_STREAM_END){
  31.303 +          return r;
  31.304 +        }
  31.305 +        r = f;
  31.306 +        this.was=z.adler.getValue();
  31.307 +        this.blocks.reset();
  31.308 +        if(this.wrap==0){
  31.309 +          this.mode=DONE;
  31.310 +          break;
  31.311 +        }
  31.312 +        this.mode=CHECK4;
  31.313 +      case CHECK4:
  31.314 +
  31.315 +        if(z.avail_in==0)return r;r=f;
  31.316 +
  31.317 +        z.avail_in--; z.total_in++;
  31.318 +        this.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L;
  31.319 +        this.mode=CHECK3;
  31.320 +      case CHECK3:
  31.321 +
  31.322 +        if(z.avail_in==0)return r;r=f;
  31.323 +
  31.324 +        z.avail_in--; z.total_in++;
  31.325 +        this.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L;
  31.326 +        this.mode = CHECK2;
  31.327 +      case CHECK2:
  31.328 +
  31.329 +        if(z.avail_in==0)return r;r=f;
  31.330 +
  31.331 +        z.avail_in--; z.total_in++;
  31.332 +        this.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L;
  31.333 +        this.mode = CHECK1;
  31.334 +      case CHECK1:
  31.335 +
  31.336 +        if(z.avail_in==0)return r;r=f;
  31.337 +
  31.338 +        z.avail_in--; z.total_in++;
  31.339 +        this.need+=(z.next_in[z.next_in_index++]&0xffL);
  31.340 +
  31.341 +        if(flags!=0){  // gzip
  31.342 +          this.need = ((this.need&0xff000000)>>24 | 
  31.343 +                          (this.need&0x00ff0000)>>8 | 
  31.344 +                          (this.need&0x0000ff00)<<8 | 
  31.345 +                          (this.need&0x0000ffff)<<24)&0xffffffffL;
  31.346 +        }
  31.347 +
  31.348 +        if(((int)(this.was)) != ((int)(this.need))){
  31.349 +          z.msg = "incorrect data check";
  31.350 +          // chack is delayed
  31.351 +          /*
  31.352 +          this.mode = BAD;
  31.353 +          this.marker = 5;       // can't try inflateSync
  31.354 +          break;
  31.355 +	  */
  31.356 +        }
  31.357 +        else if(flags!=0 && gheader!=null){
  31.358 +          gheader.crc = this.need; 
  31.359 +        }
  31.360 +
  31.361 +        this.mode = LENGTH;
  31.362 +      case LENGTH:
  31.363 +        if (wrap!=0 && flags!=0) {
  31.364 +
  31.365 +          try { r=readBytes(4, r, f); }
  31.366 +          catch(Return e){ return e.r; }
  31.367 +
  31.368 +          if(z.msg!=null && z.msg.equals("incorrect data check")){
  31.369 +            this.mode = BAD;
  31.370 +            this.marker = 5;       // can't try inflateSync
  31.371 +            break;
  31.372 +          }
  31.373 +
  31.374 +          if (this.need != (z.total_out & 0xffffffffL)) {
  31.375 +            z.msg = "incorrect length check";
  31.376 +            this.mode = BAD;
  31.377 +            break;
  31.378 +          }
  31.379 +          z.msg = null;
  31.380 +        }
  31.381 +        else {
  31.382 +          if(z.msg!=null && z.msg.equals("incorrect data check")){
  31.383 +            this.mode = BAD;
  31.384 +            this.marker = 5;       // can't try inflateSync
  31.385 +            break;
  31.386 +          }
  31.387 +        }
  31.388 +
  31.389 +        this.mode = DONE;
  31.390 +      case DONE:
  31.391 +        return Z_STREAM_END;
  31.392 +      case BAD:
  31.393 +        return Z_DATA_ERROR;
  31.394 +
  31.395 +      case FLAGS:
  31.396 +
  31.397 +        try { r=readBytes(2, r, f); }
  31.398 +        catch(Return e){ return e.r; }
  31.399 +
  31.400 +        flags = ((int)this.need)&0xffff;
  31.401 +
  31.402 +        if ((flags & 0xff) != Z_DEFLATED) {
  31.403 +          z.msg = "unknown compression method";
  31.404 +          this.mode = BAD; 
  31.405 +          break;
  31.406 +        }
  31.407 +        if ((flags & 0xe000)!=0) {
  31.408 +          z.msg = "unknown header flags set";
  31.409 +          this.mode = BAD; 
  31.410 +          break;
  31.411 +        }
  31.412 +
  31.413 +        if ((flags & 0x0200)!=0){
  31.414 +          checksum(2, this.need);
  31.415 +        } 
  31.416 +
  31.417 +        this.mode = TIME;
  31.418 +
  31.419 +      case TIME:
  31.420 +        try { r=readBytes(4, r, f); }
  31.421 +        catch(Return e){ return e.r; }
  31.422 +        if(gheader!=null)
  31.423 +          gheader.time = this.need;
  31.424 +        if ((flags & 0x0200)!=0){
  31.425 +          checksum(4, this.need);
  31.426 +        }
  31.427 +        this.mode = OS;
  31.428 +      case OS:
  31.429 +        try { r=readBytes(2, r, f); }
  31.430 +        catch(Return e){ return e.r; }
  31.431 +        if(gheader!=null){
  31.432 +          gheader.xflags = ((int)this.need)&0xff;
  31.433 +          gheader.os = (((int)this.need)>>8)&0xff;
  31.434 +        }
  31.435 +        if ((flags & 0x0200)!=0){
  31.436 +          checksum(2, this.need);
  31.437 +        }
  31.438 +        this.mode = EXLEN;
  31.439 +      case EXLEN:
  31.440 +        if ((flags & 0x0400)!=0) {
  31.441 +          try { r=readBytes(2, r, f); }
  31.442 +          catch(Return e){ return e.r; }
  31.443 +          if(gheader!=null){
  31.444 +            gheader.extra = new byte[((int)this.need)&0xffff];
  31.445 +          }
  31.446 +          if ((flags & 0x0200)!=0){
  31.447 +            checksum(2, this.need);
  31.448 +          }
  31.449 +        }
  31.450 +        else if(gheader!=null){
  31.451 +          gheader.extra=null;
  31.452 +        }
  31.453 +        this.mode = EXTRA;
  31.454 +
  31.455 +      case EXTRA:
  31.456 +        if ((flags & 0x0400)!=0) {
  31.457 +          try { 
  31.458 +            r=readBytes(r, f);
  31.459 +            if(gheader!=null){
  31.460 +              byte[] foo = tmp_array;
  31.461 +              tmp_array=null;
  31.462 +              if(foo.length == gheader.extra.length){
  31.463 +                System.arraycopy(foo, 0, gheader.extra, 0, foo.length);
  31.464 +	      }
  31.465 +              else{
  31.466 +                z.msg = "bad extra field length";
  31.467 +                this.mode = BAD; 
  31.468 +                break;
  31.469 +	      }
  31.470 +            }
  31.471 +          }
  31.472 +          catch(Return e){ return e.r; }
  31.473 +        }
  31.474 +        else if(gheader!=null){
  31.475 +          gheader.extra=null;
  31.476 +	}
  31.477 +	this.mode = NAME;
  31.478 +      case NAME:
  31.479 +	if ((flags & 0x0800)!=0) {
  31.480 +          try { 
  31.481 +            r=readString(r, f);
  31.482 +            if(gheader!=null){
  31.483 +              gheader.name=tmp_array;
  31.484 +            }
  31.485 +            tmp_array=null;
  31.486 +          }
  31.487 +          catch(Return e){ return e.r; }
  31.488 +        }
  31.489 +        else if(gheader!=null){
  31.490 +          gheader.name=null;
  31.491 +	}
  31.492 +        this.mode = COMMENT;
  31.493 +      case COMMENT:
  31.494 +        if ((flags & 0x1000)!=0) {
  31.495 +          try { 
  31.496 +            r=readString(r, f);
  31.497 +            if(gheader!=null){
  31.498 +              gheader.comment=tmp_array;
  31.499 +            }
  31.500 +            tmp_array=null;
  31.501 +          }
  31.502 +          catch(Return e){ return e.r; }
  31.503 +        }
  31.504 +        else if(gheader!=null){
  31.505 +          gheader.comment=null;
  31.506 +	}
  31.507 +        this.mode = HCRC;
  31.508 +      case HCRC:
  31.509 +	if ((flags & 0x0200)!=0) {
  31.510 +          try { r=readBytes(2, r, f); }
  31.511 +          catch(Return e){ return e.r; }
  31.512 +          if(gheader!=null){
  31.513 +            gheader.hcrc=(int)(this.need&0xffff);
  31.514 +          }
  31.515 +          if(this.need != (z.adler.getValue()&0xffffL)){
  31.516 +            this.mode = BAD;
  31.517 +            z.msg = "header crc mismatch";
  31.518 +            this.marker = 5;       // can't try inflateSync
  31.519 +            break;
  31.520 +          }
  31.521 +        }
  31.522 +        z.adler = new CRC32();
  31.523 +
  31.524 +        this.mode = BLOCKS;
  31.525 +        break;
  31.526 +      default:
  31.527 +        return Z_STREAM_ERROR;
  31.528 +      }
  31.529 +    }
  31.530 +  }
  31.531 +
  31.532 +  int inflateSetDictionary(byte[] dictionary, int dictLength){
  31.533 +    if(z==null || (this.mode != DICT0 && this.wrap != 0)){
  31.534 +      return Z_STREAM_ERROR;
  31.535 +    }
  31.536 +
  31.537 +    int index=0;
  31.538 +    int length = dictLength;
  31.539 +
  31.540 +    if(this.mode==DICT0){
  31.541 +      long adler_need=z.adler.getValue();
  31.542 +      z.adler.reset();
  31.543 +      z.adler.update(dictionary, 0, dictLength);
  31.544 +      if(z.adler.getValue()!=adler_need){
  31.545 +        return Z_DATA_ERROR;
  31.546 +      }
  31.547 +    }
  31.548 +
  31.549 +    z.adler.reset();
  31.550 +
  31.551 +    if(length >= (1<<this.wbits)){
  31.552 +      length = (1<<this.wbits)-1;
  31.553 +      index=dictLength - length;
  31.554 +    }
  31.555 +    this.blocks.set_dictionary(dictionary, index, length);
  31.556 +    this.mode = BLOCKS;
  31.557 +    return Z_OK;
  31.558 +  }
  31.559 +
  31.560 +  static private byte[] mark = {(byte)0, (byte)0, (byte)0xff, (byte)0xff};
  31.561 +
  31.562 +  int inflateSync(){
  31.563 +    int n;       // number of bytes to look at
  31.564 +    int p;       // pointer to bytes
  31.565 +    int m;       // number of marker bytes found in a row
  31.566 +    long r, w;   // temporaries to save total_in and total_out
  31.567 +
  31.568 +    // set up
  31.569 +    if(z == null)
  31.570 +      return Z_STREAM_ERROR;
  31.571 +    if(this.mode != BAD){
  31.572 +      this.mode = BAD;
  31.573 +      this.marker = 0;
  31.574 +    }
  31.575 +    if((n=z.avail_in)==0)
  31.576 +      return Z_BUF_ERROR;
  31.577 +
  31.578 +    p=z.next_in_index;
  31.579 +    m=this.marker;
  31.580 +    // search
  31.581 +    while (n!=0 && m < 4){
  31.582 +      if(z.next_in[p] == mark[m]){
  31.583 +        m++;
  31.584 +      }
  31.585 +      else if(z.next_in[p]!=0){
  31.586 +        m = 0;
  31.587 +      }
  31.588 +      else{
  31.589 +        m = 4 - m;
  31.590 +      }
  31.591 +      p++; n--;
  31.592 +    }
  31.593 +
  31.594 +    // restore
  31.595 +    z.total_in += p-z.next_in_index;
  31.596 +    z.next_in_index = p;
  31.597 +    z.avail_in = n;
  31.598 +    this.marker = m;
  31.599 +
  31.600 +    // return no joy or set up to restart on a new block
  31.601 +    if(m != 4){
  31.602 +      return Z_DATA_ERROR;
  31.603 +    }
  31.604 +    r=z.total_in;  w=z.total_out;
  31.605 +    inflateReset();
  31.606 +    z.total_in=r;  z.total_out = w;
  31.607 +    this.mode = BLOCKS;
  31.608 +
  31.609 +    return Z_OK;
  31.610 +  }
  31.611 +
  31.612 +  // Returns true if inflate is currently at the end of a block generated
  31.613 +  // by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
  31.614 +  // implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
  31.615 +  // but removes the length bytes of the resulting empty stored block. When
  31.616 +  // decompressing, PPP checks that at the end of input packet, inflate is
  31.617 +  // waiting for these length bytes.
  31.618 +  int inflateSyncPoint(){
  31.619 +    if(z == null || this.blocks == null)
  31.620 +      return Z_STREAM_ERROR;
  31.621 +    return this.blocks.sync_point();
  31.622 +  }
  31.623 +
  31.624 +  private int readBytes(int n, int r, int f) throws Return{
  31.625 +    if(need_bytes == -1){
  31.626 +      need_bytes=n;
  31.627 +      this.need=0;
  31.628 +    }
  31.629 +    while(need_bytes>0){
  31.630 +      if(z.avail_in==0){ throw new Return(r); }; r=f;
  31.631 +      z.avail_in--; z.total_in++;
  31.632 +      this.need = this.need | 
  31.633 +	((z.next_in[z.next_in_index++]&0xff)<<((n-need_bytes)*8));
  31.634 +      need_bytes--;
  31.635 +    }
  31.636 +    if(n==2){
  31.637 +      this.need&=0xffffL;
  31.638 +    }
  31.639 +    else if(n==4) {
  31.640 +      this.need&=0xffffffffL;
  31.641 +    }
  31.642 +    need_bytes=-1;
  31.643 +    return r;
  31.644 +  }
  31.645 +  class Return extends Exception{
  31.646 +    int r;
  31.647 +    Return(int r){this.r=r; }
  31.648 +  }
  31.649 +
  31.650 +  private byte[] tmp_array;
  31.651 +  private int readString(int r, int f) throws Return{
  31.652 +    int b=0; 
  31.653 +    byte[] arr = new byte[4092];
  31.654 +    int at = 0;
  31.655 +    do {
  31.656 +      if(z.avail_in==0){ throw new Return(r); }; r=f;
  31.657 +      z.avail_in--; z.total_in++;
  31.658 +      b = z.next_in[z.next_in_index];
  31.659 +      if(b!=0) arr = append(arr, z.next_in[z.next_in_index], at++);
  31.660 +      z.adler.update(z.next_in, z.next_in_index, 1);
  31.661 +      z.next_in_index++;
  31.662 +    }while(b!=0);
  31.663 +    
  31.664 +    tmp_array = copy(arr, at);
  31.665 +    
  31.666 +    return r;
  31.667 +  }
  31.668 +
  31.669 +  private int readBytes(int r, int f) throws Return{
  31.670 +    int b=0; 
  31.671 +    byte[] arr = new byte[4092];
  31.672 +    int at = 0;
  31.673 +    while(this.need>0){
  31.674 +      if(z.avail_in==0){ throw new Return(r); }; r=f;
  31.675 +      z.avail_in--; z.total_in++;
  31.676 +      b = z.next_in[z.next_in_index];
  31.677 +      arr = append(arr, z.next_in[z.next_in_index], at++);
  31.678 +      z.adler.update(z.next_in, z.next_in_index, 1);
  31.679 +      z.next_in_index++;
  31.680 +      this.need--;
  31.681 +    }
  31.682 +    
  31.683 +    tmp_array = copy(arr, at);
  31.684 +    
  31.685 +    return r;
  31.686 +  }
  31.687 +  
  31.688 +  private static byte[] copy(byte[] arr, int len) {
  31.689 +      byte[] ret = new byte[len];
  31.690 +      org.apidesign.bck2brwsr.emul.lang.System.arraycopy(arr, 0, ret, 0, len);
  31.691 +      return ret;
  31.692 +  }
  31.693 +  private static byte[] append(byte[] arr, byte b, int index) {
  31.694 +      arr[index] = b;
  31.695 +      return arr;
  31.696 +  }
  31.697 +
  31.698 +  private void checksum(int n, long v){
  31.699 +    for(int i=0; i<n; i++){
  31.700 +      crcbuf[i]=(byte)(v&0xff);
  31.701 +      v>>=8;
  31.702 +    }
  31.703 +    z.adler.update(crcbuf, 0, n);
  31.704 +  }
  31.705 +
  31.706 +  public GZIPHeader getGZIPHeader(){
  31.707 +    return gheader;
  31.708 +  }
  31.709 +
  31.710 +  boolean inParsingHeader(){
  31.711 +    switch(mode){
  31.712 +      case HEAD:
  31.713 +      case DICT4:
  31.714 +      case DICT3:
  31.715 +      case DICT2:
  31.716 +      case DICT1:
  31.717 +      case FLAGS:
  31.718 +      case TIME:
  31.719 +      case OS:
  31.720 +      case EXLEN:
  31.721 +      case EXTRA:
  31.722 +      case NAME:
  31.723 +      case COMMENT:
  31.724 +      case HCRC:
  31.725 +	return true;
  31.726 +      default:
  31.727 +	return false;
  31.728 +    }
  31.729 +  }
  31.730 +}
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/Inflater.java	Tue Feb 19 15:59:27 2013 +0100
    32.3 @@ -0,0 +1,338 @@
    32.4 +/*
    32.5 + * Copyright (c) 1996, 2011, 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 org.apidesign.bck2brwsr.emul.zip;
   32.30 +
   32.31 +import java.util.zip.*;
   32.32 +import java.io.IOException;
   32.33 +
   32.34 +/**
   32.35 + * This class provides support for general purpose decompression using the
   32.36 + * popular ZLIB compression library. The ZLIB compression library was
   32.37 + * initially developed as part of the PNG graphics standard and is not
   32.38 + * protected by patents. It is fully described in the specifications at
   32.39 + * the <a href="package-summary.html#package_description">java.util.zip
   32.40 + * package description</a>.
   32.41 + *
   32.42 + * <p>The following code fragment demonstrates a trivial compression
   32.43 + * and decompression of a string using <tt>Deflater</tt> and
   32.44 + * <tt>Inflater</tt>.
   32.45 + *
   32.46 + * <blockquote><pre>
   32.47 + * try {
   32.48 + *     // Encode a String into bytes
   32.49 + *     String inputString = "blahblahblah\u20AC\u20AC";
   32.50 + *     byte[] input = inputString.getBytes("UTF-8");
   32.51 + *
   32.52 + *     // Compress the bytes
   32.53 + *     byte[] output = new byte[100];
   32.54 + *     Deflater compresser = new Deflater();
   32.55 + *     compresser.setInput(input);
   32.56 + *     compresser.finish();
   32.57 + *     int compressedDataLength = compresser.deflate(output);
   32.58 + *
   32.59 + *     // Decompress the bytes
   32.60 + *     Inflater decompresser = new Inflater();
   32.61 + *     decompresser.setInput(output, 0, compressedDataLength);
   32.62 + *     byte[] result = new byte[100];
   32.63 + *     int resultLength = decompresser.inflate(result);
   32.64 + *     decompresser.end();
   32.65 + *
   32.66 + *     // Decode the bytes into a String
   32.67 + *     String outputString = new String(result, 0, resultLength, "UTF-8");
   32.68 + * } catch(java.io.UnsupportedEncodingException ex) {
   32.69 + *     // handle
   32.70 + * } catch (java.util.zip.DataFormatException ex) {
   32.71 + *     // handle
   32.72 + * }
   32.73 + * </pre></blockquote>
   32.74 + *
   32.75 + * @see         Deflater
   32.76 + * @author      David Connelly
   32.77 + *
   32.78 + */
   32.79 +public
   32.80 +class Inflater extends java.util.zip.Inflater {
   32.81 +    private final boolean nowrap;
   32.82 +    private JzLibInflater impl;
   32.83 +    
   32.84 +    /**
   32.85 +     * Creates a new decompressor. If the parameter 'nowrap' is true then
   32.86 +     * the ZLIB header and checksum fields will not be used. This provides
   32.87 +     * compatibility with the compression format used by both GZIP and PKZIP.
   32.88 +     * <p>
   32.89 +     * Note: When using the 'nowrap' option it is also necessary to provide
   32.90 +     * an extra "dummy" byte as input. This is required by the ZLIB native
   32.91 +     * library in order to support certain optimizations.
   32.92 +     *
   32.93 +     * @param nowrap if true then support GZIP compatible compression
   32.94 +     */
   32.95 +    public Inflater(boolean nowrap) {
   32.96 +        this.nowrap = nowrap;
   32.97 +        reset();
   32.98 +    }
   32.99 +
  32.100 +    /**
  32.101 +     * Creates a new decompressor.
  32.102 +     */
  32.103 +    public Inflater() {
  32.104 +        this(false);
  32.105 +    }
  32.106 +
  32.107 +    /**
  32.108 +     * Sets input data for decompression. Should be called whenever
  32.109 +     * needsInput() returns true indicating that more input data is
  32.110 +     * required.
  32.111 +     * @param b the input data bytes
  32.112 +     * @param off the start offset of the input data
  32.113 +     * @param len the length of the input data
  32.114 +     * @see Inflater#needsInput
  32.115 +     */
  32.116 +    public void setInput(byte[] b, int off, int len) {
  32.117 +        if (b == null) {
  32.118 +            throw new NullPointerException();
  32.119 +        }
  32.120 +        if (off < 0 || len < 0 || off > b.length - len) {
  32.121 +            throw new ArrayIndexOutOfBoundsException();
  32.122 +        }
  32.123 +        impl.setInput(b, off, len, false);
  32.124 +    }
  32.125 +
  32.126 +    /**
  32.127 +     * Sets input data for decompression. Should be called whenever
  32.128 +     * needsInput() returns true indicating that more input data is
  32.129 +     * required.
  32.130 +     * @param b the input data bytes
  32.131 +     * @see Inflater#needsInput
  32.132 +     */
  32.133 +    public void setInput(byte[] b) {
  32.134 +        setInput(b, 0, b.length);
  32.135 +    }
  32.136 +
  32.137 +    /**
  32.138 +     * Sets the preset dictionary to the given array of bytes. Should be
  32.139 +     * called when inflate() returns 0 and needsDictionary() returns true
  32.140 +     * indicating that a preset dictionary is required. The method getAdler()
  32.141 +     * can be used to get the Adler-32 value of the dictionary needed.
  32.142 +     * @param b the dictionary data bytes
  32.143 +     * @param off the start offset of the data
  32.144 +     * @param len the length of the data
  32.145 +     * @see Inflater#needsDictionary
  32.146 +     * @see Inflater#getAdler
  32.147 +     */
  32.148 +    public void setDictionary(byte[] b, int off, int len) {
  32.149 +        if (b == null) {
  32.150 +            throw new NullPointerException();
  32.151 +        }
  32.152 +        if (off < 0 || len < 0 || off > b.length - len) {
  32.153 +            throw new ArrayIndexOutOfBoundsException();
  32.154 +        }
  32.155 +        byte[] arr;
  32.156 +        if (off == 0) {
  32.157 +            arr = b;
  32.158 +        } else {
  32.159 +            arr = new byte[len];
  32.160 +            org.apidesign.bck2brwsr.emul.lang.System.arraycopy(b, off, arr, 0, len);
  32.161 +        }
  32.162 +        impl.setDictionary(arr, len);
  32.163 +    }
  32.164 +
  32.165 +    /**
  32.166 +     * Sets the preset dictionary to the given array of bytes. Should be
  32.167 +     * called when inflate() returns 0 and needsDictionary() returns true
  32.168 +     * indicating that a preset dictionary is required. The method getAdler()
  32.169 +     * can be used to get the Adler-32 value of the dictionary needed.
  32.170 +     * @param b the dictionary data bytes
  32.171 +     * @see Inflater#needsDictionary
  32.172 +     * @see Inflater#getAdler
  32.173 +     */
  32.174 +    public void setDictionary(byte[] b) {
  32.175 +        impl.setDictionary(b, b.length);
  32.176 +    }
  32.177 +
  32.178 +    /**
  32.179 +     * Returns the total number of bytes remaining in the input buffer.
  32.180 +     * This can be used to find out what bytes still remain in the input
  32.181 +     * buffer after decompression has finished.
  32.182 +     * @return the total number of bytes remaining in the input buffer
  32.183 +     */
  32.184 +    public int getRemaining() {
  32.185 +        return impl.getAvailIn();
  32.186 +    }
  32.187 +
  32.188 +    /**
  32.189 +     * Returns true if no data remains in the input buffer. This can
  32.190 +     * be used to determine if #setInput should be called in order
  32.191 +     * to provide more input.
  32.192 +     * @return true if no data remains in the input buffer
  32.193 +     */
  32.194 +    public boolean needsInput() {
  32.195 +        return getRemaining() <= 0;
  32.196 +    }
  32.197 +
  32.198 +    /**
  32.199 +     * Returns true if a preset dictionary is needed for decompression.
  32.200 +     * @return true if a preset dictionary is needed for decompression
  32.201 +     * @see Inflater#setDictionary
  32.202 +     */
  32.203 +    public boolean needsDictionary() {
  32.204 +        return impl.needDict();
  32.205 +    }
  32.206 +
  32.207 +    /**
  32.208 +     * Returns true if the end of the compressed data stream has been
  32.209 +     * reached.
  32.210 +     * @return true if the end of the compressed data stream has been
  32.211 +     * reached
  32.212 +     */
  32.213 +    public boolean finished() {
  32.214 +        return impl.finished();
  32.215 +    }
  32.216 +
  32.217 +    /**
  32.218 +     * Uncompresses bytes into specified buffer. Returns actual number
  32.219 +     * of bytes uncompressed. A return value of 0 indicates that
  32.220 +     * needsInput() or needsDictionary() should be called in order to
  32.221 +     * determine if more input data or a preset dictionary is required.
  32.222 +     * In the latter case, getAdler() can be used to get the Adler-32
  32.223 +     * value of the dictionary required.
  32.224 +     * @param b the buffer for the uncompressed data
  32.225 +     * @param off the start offset of the data
  32.226 +     * @param len the maximum number of uncompressed bytes
  32.227 +     * @return the actual number of uncompressed bytes
  32.228 +     * @exception DataFormatException if the compressed data format is invalid
  32.229 +     * @see Inflater#needsInput
  32.230 +     * @see Inflater#needsDictionary
  32.231 +     */
  32.232 +    public int inflate(byte[] b, int off, int len)
  32.233 +        throws DataFormatException
  32.234 +    {
  32.235 +        if (b == null) {
  32.236 +            throw new NullPointerException();
  32.237 +        }
  32.238 +        if (off < 0 || len < 0 || off > b.length - len) {
  32.239 +            throw new ArrayIndexOutOfBoundsException();
  32.240 +        }
  32.241 +        impl.setOutput(b, off, len);
  32.242 +        int err = impl.inflate(JzLibInflater.Z_NO_FLUSH);
  32.243 +        return impl.next_out_index - off;
  32.244 +    }
  32.245 +
  32.246 +    /**
  32.247 +     * Uncompresses bytes into specified buffer. Returns actual number
  32.248 +     * of bytes uncompressed. A return value of 0 indicates that
  32.249 +     * needsInput() or needsDictionary() should be called in order to
  32.250 +     * determine if more input data or a preset dictionary is required.
  32.251 +     * In the latter case, getAdler() can be used to get the Adler-32
  32.252 +     * value of the dictionary required.
  32.253 +     * @param b the buffer for the uncompressed data
  32.254 +     * @return the actual number of uncompressed bytes
  32.255 +     * @exception DataFormatException if the compressed data format is invalid
  32.256 +     * @see Inflater#needsInput
  32.257 +     * @see Inflater#needsDictionary
  32.258 +     */
  32.259 +    public int inflate(byte[] b) throws DataFormatException {
  32.260 +        return inflate(b, 0, b.length);
  32.261 +    }
  32.262 +
  32.263 +    /**
  32.264 +     * Returns the ADLER-32 value of the uncompressed data.
  32.265 +     * @return the ADLER-32 value of the uncompressed data
  32.266 +     */
  32.267 +    public int getAdler() {
  32.268 +        return (int) impl.getAdler();
  32.269 +    }
  32.270 +
  32.271 +    /**
  32.272 +     * Returns the total number of compressed bytes input so far.
  32.273 +     *
  32.274 +     * <p>Since the number of bytes may be greater than
  32.275 +     * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now
  32.276 +     * the preferred means of obtaining this information.</p>
  32.277 +     *
  32.278 +     * @return the total number of compressed bytes input so far
  32.279 +     */
  32.280 +    public int getTotalIn() {
  32.281 +        return (int) getBytesRead();
  32.282 +    }
  32.283 +
  32.284 +    /**
  32.285 +     * Returns the total number of compressed bytes input so far.</p>
  32.286 +     *
  32.287 +     * @return the total (non-negative) number of compressed bytes input so far
  32.288 +     * @since 1.5
  32.289 +     */
  32.290 +    public long getBytesRead() {
  32.291 +        return impl.total_in;
  32.292 +    }
  32.293 +
  32.294 +    /**
  32.295 +     * Returns the total number of uncompressed bytes output so far.
  32.296 +     *
  32.297 +     * <p>Since the number of bytes may be greater than
  32.298 +     * Integer.MAX_VALUE, the {@link #getBytesWritten()} method is now
  32.299 +     * the preferred means of obtaining this information.</p>
  32.300 +     *
  32.301 +     * @return the total number of uncompressed bytes output so far
  32.302 +     */
  32.303 +    public int getTotalOut() {
  32.304 +        return (int) getBytesWritten();
  32.305 +    }
  32.306 +
  32.307 +    /**
  32.308 +     * Returns the total number of uncompressed bytes output so far.</p>
  32.309 +     *
  32.310 +     * @return the total (non-negative) number of uncompressed bytes output so far
  32.311 +     * @since 1.5
  32.312 +     */
  32.313 +    public long getBytesWritten() {
  32.314 +        return impl.total_out;
  32.315 +    }
  32.316 +
  32.317 +    /**
  32.318 +     * Resets inflater so that a new set of input data can be processed.
  32.319 +     */
  32.320 +    public void reset() {
  32.321 +        impl = new JzLibInflater(15, nowrap);
  32.322 +    }
  32.323 +
  32.324 +    /**
  32.325 +     * Closes the decompressor and discards any unprocessed input.
  32.326 +     * This method should be called when the decompressor is no longer
  32.327 +     * being used, but will also be called automatically by the finalize()
  32.328 +     * method. Once this method is called, the behavior of the Inflater
  32.329 +     * object is undefined.
  32.330 +     */
  32.331 +    public void end() {
  32.332 +        impl.end();
  32.333 +    }
  32.334 +
  32.335 +    /**
  32.336 +     * Closes the decompressor when garbage is collected.
  32.337 +     */
  32.338 +    protected void finalize() {
  32.339 +        end();
  32.340 +    }
  32.341 +}
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/JzLibInflater.java	Tue Feb 19 15:59:27 2013 +0100
    33.3 @@ -0,0 +1,137 @@
    33.4 +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
    33.5 +/*
    33.6 +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
    33.7 +
    33.8 +Redistribution and use in source and binary forms, with or without
    33.9 +modification, are permitted provided that the following conditions are met:
   33.10 +
   33.11 +  1. Redistributions of source code must retain the above copyright notice,
   33.12 +     this list of conditions and the following disclaimer.
   33.13 +
   33.14 +  2. Redistributions in binary form must reproduce the above copyright 
   33.15 +     notice, this list of conditions and the following disclaimer in 
   33.16 +     the documentation and/or other materials provided with the distribution.
   33.17 +
   33.18 +  3. The names of the authors may not be used to endorse or promote products
   33.19 +     derived from this software without specific prior written permission.
   33.20 +
   33.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   33.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   33.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
   33.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
   33.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   33.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
   33.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   33.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   33.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   33.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   33.31 + */
   33.32 +/*
   33.33 + * This program is based on zlib-1.1.3, so all credit should go authors
   33.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
   33.35 + * and contributors of zlib.
   33.36 + */
   33.37 +
   33.38 +package org.apidesign.bck2brwsr.emul.zip;
   33.39 +
   33.40 +final class JzLibInflater extends ZStream{
   33.41 +
   33.42 +  static final private int MAX_WBITS=15;        // 32K LZ77 window
   33.43 +  static final private int DEF_WBITS=MAX_WBITS;
   33.44 +
   33.45 +  public static final int Z_NO_FLUSH=0;
   33.46 +  static final private int Z_PARTIAL_FLUSH=1;
   33.47 +  static final private int Z_SYNC_FLUSH=2;
   33.48 +  static final private int Z_FULL_FLUSH=3;
   33.49 +  static final private int Z_FINISH=4;
   33.50 +
   33.51 +  static final private int MAX_MEM_LEVEL=9;
   33.52 +
   33.53 +  static final private int Z_OK=0;
   33.54 +  static final private int Z_STREAM_END=1;
   33.55 +  static final private int Z_NEED_DICT=2;
   33.56 +  static final private int Z_ERRNO=-1;
   33.57 +  static final private int Z_STREAM_ERROR=-2;
   33.58 +  static final private int Z_DATA_ERROR=-3;
   33.59 +  static final private int Z_MEM_ERROR=-4;
   33.60 +  static final private int Z_BUF_ERROR=-5;
   33.61 +  static final private int Z_VERSION_ERROR=-6;
   33.62 +
   33.63 +  public JzLibInflater() {
   33.64 +    super();
   33.65 +    init();
   33.66 +  }
   33.67 +
   33.68 +  public JzLibInflater(int w)  {
   33.69 +    this(w, false);
   33.70 +  }
   33.71 +
   33.72 +  public JzLibInflater(int w, boolean nowrap)  {
   33.73 +    super();
   33.74 +    int ret = init(w, nowrap);
   33.75 +    if(ret!=Z_OK)
   33.76 +      throw new IllegalStateException(ret+": "+msg);
   33.77 +  }
   33.78 +
   33.79 +  private boolean finished = false;
   33.80 +
   33.81 +  public int init(){
   33.82 +    return init(DEF_WBITS);
   33.83 +  }
   33.84 +
   33.85 +  public int init(boolean nowrap){
   33.86 +    return init(DEF_WBITS, nowrap);
   33.87 +  }
   33.88 +
   33.89 +  public int init(int w){
   33.90 +    return init(w, false);
   33.91 +  }
   33.92 +
   33.93 +  public int init(int w, boolean nowrap){
   33.94 +    finished = false;
   33.95 +    istate=new Inflate(this);
   33.96 +    return istate.inflateInit(nowrap?-w:w);
   33.97 +  }
   33.98 +
   33.99 +  public int inflate(int f){
  33.100 +    if(istate==null) return Z_STREAM_ERROR;
  33.101 +    int ret = istate.inflate(f);
  33.102 +    if(ret == Z_STREAM_END) 
  33.103 +      finished = true;
  33.104 +    return ret;
  33.105 +  }
  33.106 +
  33.107 +  public int end(){
  33.108 +    finished = true;
  33.109 +    if(istate==null) return Z_STREAM_ERROR;
  33.110 +    int ret=istate.inflateEnd();
  33.111 +//    istate = null;
  33.112 +    return ret;
  33.113 +  }
  33.114 +
  33.115 +  public int sync(){
  33.116 +    if(istate == null)
  33.117 +      return Z_STREAM_ERROR;
  33.118 +    return istate.inflateSync();
  33.119 +  }
  33.120 +
  33.121 +  public int syncPoint(){
  33.122 +    if(istate == null)
  33.123 +      return Z_STREAM_ERROR;
  33.124 +    return istate.inflateSyncPoint();
  33.125 +  }
  33.126 +
  33.127 +  public int setDictionary(byte[] dictionary, int dictLength){
  33.128 +    if(istate == null)
  33.129 +      return Z_STREAM_ERROR;
  33.130 +    return istate.inflateSetDictionary(dictionary, dictLength);
  33.131 +  }
  33.132 +
  33.133 +  public boolean finished(){
  33.134 +    return istate.mode==12 /*DONE*/;
  33.135 +  }
  33.136 +
  33.137 +  public boolean needDict() {
  33.138 +    return istate == null ? false : istate.mode == Inflate.DICT0;
  33.139 +  }
  33.140 +}
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/ZStream.java	Tue Feb 19 15:59:27 2013 +0100
    34.3 @@ -0,0 +1,253 @@
    34.4 +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
    34.5 +/*
    34.6 +Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved.
    34.7 +
    34.8 +Redistribution and use in source and binary forms, with or without
    34.9 +modification, are permitted provided that the following conditions are met:
   34.10 +
   34.11 +  1. Redistributions of source code must retain the above copyright notice,
   34.12 +     this list of conditions and the following disclaimer.
   34.13 +
   34.14 +  2. Redistributions in binary form must reproduce the above copyright 
   34.15 +     notice, this list of conditions and the following disclaimer in 
   34.16 +     the documentation and/or other materials provided with the distribution.
   34.17 +
   34.18 +  3. The names of the authors may not be used to endorse or promote products
   34.19 +     derived from this software without specific prior written permission.
   34.20 +
   34.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   34.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   34.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
   34.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
   34.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   34.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
   34.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   34.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   34.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   34.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   34.31 + */
   34.32 +/*
   34.33 + * This program is based on zlib-1.1.3, so all credit should go authors
   34.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
   34.35 + * and contributors of zlib.
   34.36 + */
   34.37 +
   34.38 +package org.apidesign.bck2brwsr.emul.zip;
   34.39 +
   34.40 +import org.apidesign.bck2brwsr.emul.lang.System;
   34.41 +
   34.42 +/**
   34.43 + * ZStream
   34.44 + *
   34.45 + * @deprecated  Not for public use in the future.
   34.46 + */
   34.47 +@Deprecated
   34.48 +class ZStream{
   34.49 +
   34.50 +  static final private int MAX_WBITS=15;        // 32K LZ77 window
   34.51 +  static final private int DEF_WBITS=MAX_WBITS;
   34.52 +
   34.53 +  static final private int Z_NO_FLUSH=0;
   34.54 +  static final private int Z_PARTIAL_FLUSH=1;
   34.55 +  static final private int Z_SYNC_FLUSH=2;
   34.56 +  static final private int Z_FULL_FLUSH=3;
   34.57 +  static final private int Z_FINISH=4;
   34.58 +
   34.59 +  static final private int MAX_MEM_LEVEL=9;
   34.60 +
   34.61 +  static final private int Z_OK=0;
   34.62 +  static final private int Z_STREAM_END=1;
   34.63 +  static final private int Z_NEED_DICT=2;
   34.64 +  static final private int Z_ERRNO=-1;
   34.65 +  static final private int Z_STREAM_ERROR=-2;
   34.66 +  static final private int Z_DATA_ERROR=-3;
   34.67 +  static final private int Z_MEM_ERROR=-4;
   34.68 +  static final private int Z_BUF_ERROR=-5;
   34.69 +  static final private int Z_VERSION_ERROR=-6;
   34.70 +
   34.71 +  public byte[] next_in;     // next input byte
   34.72 +  public int next_in_index;
   34.73 +  public int avail_in;       // number of bytes available at next_in
   34.74 +  public long total_in;      // total nb of input bytes read so far
   34.75 +
   34.76 +  public byte[] next_out;    // next output byte should be put there
   34.77 +  public int next_out_index;
   34.78 +  public int avail_out;      // remaining free space at next_out
   34.79 +  public long total_out;     // total nb of bytes output so far
   34.80 +
   34.81 +  public String msg;
   34.82 +
   34.83 +  Inflate istate; 
   34.84 +
   34.85 +  int data_type; // best guess about the data type: ascii or binary
   34.86 +
   34.87 +  Checksum adler;
   34.88 +
   34.89 +  public ZStream(){
   34.90 +    this(new Adler32());
   34.91 +  }
   34.92 +
   34.93 +  public ZStream(Checksum adler){
   34.94 +    this.adler=adler;
   34.95 +  }
   34.96 +
   34.97 +  public int inflateInit(){
   34.98 +    return inflateInit(DEF_WBITS);
   34.99 +  }
  34.100 +  public int inflateInit(boolean nowrap){
  34.101 +    return inflateInit(DEF_WBITS, nowrap);
  34.102 +  }
  34.103 +  public int inflateInit(int w){
  34.104 +    return inflateInit(w, false);
  34.105 +  }
  34.106 +
  34.107 +  public int inflateInit(int w, boolean nowrap){
  34.108 +    istate=new Inflate(this);
  34.109 +    return istate.inflateInit(nowrap?-w:w);
  34.110 +  }
  34.111 +
  34.112 +  public int inflate(int f){
  34.113 +    if(istate==null) return Z_STREAM_ERROR;
  34.114 +    return istate.inflate(f);
  34.115 +  }
  34.116 +  public int inflateEnd(){
  34.117 +    if(istate==null) return Z_STREAM_ERROR;
  34.118 +    int ret=istate.inflateEnd();
  34.119 +//    istate = null;
  34.120 +    return ret;
  34.121 +  }
  34.122 +  
  34.123 +  public int inflateSync(){
  34.124 +    if(istate == null)
  34.125 +      return Z_STREAM_ERROR;
  34.126 +    return istate.inflateSync();
  34.127 +  }
  34.128 +  public int inflateSyncPoint(){
  34.129 +    if(istate == null)
  34.130 +      return Z_STREAM_ERROR;
  34.131 +    return istate.inflateSyncPoint();
  34.132 +  }
  34.133 +  public int inflateSetDictionary(byte[] dictionary, int dictLength){
  34.134 +    if(istate == null)
  34.135 +      return Z_STREAM_ERROR;
  34.136 +    return istate.inflateSetDictionary(dictionary, dictLength);
  34.137 +  }
  34.138 +  public boolean inflateFinished(){
  34.139 +    return istate.mode==12 /*DONE*/;
  34.140 +  }
  34.141 +
  34.142 +
  34.143 +  public long getAdler(){
  34.144 +    return adler.getValue();
  34.145 +  }
  34.146 +
  34.147 +  public void free(){
  34.148 +    next_in=null;
  34.149 +    next_out=null;
  34.150 +    msg=null;
  34.151 +  }
  34.152 +
  34.153 +  public void setOutput(byte[] buf){
  34.154 +    setOutput(buf, 0, buf.length); 
  34.155 +  }
  34.156 +
  34.157 +  public void setOutput(byte[] buf, int off, int len){
  34.158 +    next_out = buf;
  34.159 +    next_out_index = off;
  34.160 +    avail_out = len;
  34.161 +  }
  34.162 +
  34.163 +  public void setInput(byte[] buf){
  34.164 +    setInput(buf, 0, buf.length, false); 
  34.165 +  }
  34.166 +
  34.167 +  public void setInput(byte[] buf, boolean append){
  34.168 +    setInput(buf, 0, buf.length, append); 
  34.169 +  }
  34.170 +
  34.171 +  public void setInput(byte[] buf, int off, int len, boolean append){
  34.172 +    if(len<=0 && append && next_in!=null) return;
  34.173 +
  34.174 +    if(avail_in>0 && append){  
  34.175 +      byte[] tmp = new byte[avail_in+len];
  34.176 +      System.arraycopy(next_in, next_in_index, tmp, 0, avail_in);
  34.177 +      System.arraycopy(buf, off, tmp, avail_in, len);
  34.178 +      next_in=tmp;
  34.179 +      next_in_index=0;
  34.180 +      avail_in+=len;
  34.181 +    }
  34.182 +    else{
  34.183 +      next_in=buf;
  34.184 +      next_in_index=off;
  34.185 +      avail_in=len;
  34.186 +    }
  34.187 +  }
  34.188 +
  34.189 +  public byte[] getNextIn(){
  34.190 +    return next_in;
  34.191 +  }
  34.192 +
  34.193 +  public void setNextIn(byte[] next_in){
  34.194 +    this.next_in = next_in;
  34.195 +  }
  34.196 +
  34.197 +  public int getNextInIndex(){
  34.198 +    return next_in_index;
  34.199 +  }
  34.200 +
  34.201 +  public void setNextInIndex(int next_in_index){
  34.202 +    this.next_in_index = next_in_index;
  34.203 +  }
  34.204 +
  34.205 +  public int getAvailIn(){
  34.206 +    return avail_in;
  34.207 +  }
  34.208 +
  34.209 +  public void setAvailIn(int avail_in){
  34.210 +    this.avail_in = avail_in;
  34.211 +  }
  34.212 +
  34.213 +  public byte[] getNextOut(){
  34.214 +    return next_out;
  34.215 +  }
  34.216 +
  34.217 +  public void setNextOut(byte[] next_out){
  34.218 +    this.next_out = next_out;
  34.219 +  }
  34.220 +
  34.221 +  public int getNextOutIndex(){
  34.222 +    return next_out_index;
  34.223 +  }
  34.224 +
  34.225 +  public void setNextOutIndex(int next_out_index){
  34.226 +    this.next_out_index = next_out_index;
  34.227 +  }
  34.228 +
  34.229 +  public int getAvailOut(){
  34.230 +    return avail_out;
  34.231 +
  34.232 +  }
  34.233 +
  34.234 +  public void setAvailOut(int avail_out){
  34.235 +    this.avail_out = avail_out;
  34.236 +  }
  34.237 +
  34.238 +  public long getTotalOut(){
  34.239 +    return total_out;
  34.240 +  }
  34.241 +
  34.242 +  public long getTotalIn(){
  34.243 +    return total_in;
  34.244 +  }
  34.245 +
  34.246 +  public String getMessage(){
  34.247 +    return msg;
  34.248 +  }
  34.249 +
  34.250 +  /**
  34.251 +   * Those methods are expected to be override by Inflater and Deflater.
  34.252 +   * In the future, they will become abstract methods.
  34.253 +   */ 
  34.254 +  public int end(){ return Z_OK; }
  34.255 +  public boolean finished(){ return false; }
  34.256 +}
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/ZipConstants64.java	Tue Feb 19 15:59:27 2013 +0100
    35.3 @@ -0,0 +1,84 @@
    35.4 +/*
    35.5 + * Copyright (c) 1995, 1996, 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 org.apidesign.bck2brwsr.emul.zip;
   35.30 +
   35.31 +/*
   35.32 + * This class defines the constants that are used by the classes
   35.33 + * which manipulate Zip64 files.
   35.34 + */
   35.35 +
   35.36 +public class ZipConstants64 {
   35.37 +
   35.38 +    /*
   35.39 +     * ZIP64 constants
   35.40 +     */
   35.41 +    static final long ZIP64_ENDSIG = 0x06064b50L;  // "PK\006\006"
   35.42 +    static final long ZIP64_LOCSIG = 0x07064b50L;  // "PK\006\007"
   35.43 +    static final int  ZIP64_ENDHDR = 56;           // ZIP64 end header size
   35.44 +    static final int  ZIP64_LOCHDR = 20;           // ZIP64 end loc header size
   35.45 +    static final int  ZIP64_EXTHDR = 24;           // EXT header size
   35.46 +    static final int  ZIP64_EXTID  = 0x0001;       // Extra field Zip64 header ID
   35.47 +
   35.48 +    static final int  ZIP64_MAGICCOUNT = 0xFFFF;
   35.49 +    static final long ZIP64_MAGICVAL = 0xFFFFFFFFL;
   35.50 +
   35.51 +    /*
   35.52 +     * Zip64 End of central directory (END) header field offsets
   35.53 +     */
   35.54 +    static final int  ZIP64_ENDLEN = 4;       // size of zip64 end of central dir
   35.55 +    static final int  ZIP64_ENDVEM = 12;      // version made by
   35.56 +    static final int  ZIP64_ENDVER = 14;      // version needed to extract
   35.57 +    static final int  ZIP64_ENDNMD = 16;      // number of this disk
   35.58 +    static final int  ZIP64_ENDDSK = 20;      // disk number of start
   35.59 +    static final int  ZIP64_ENDTOD = 24;      // total number of entries on this disk
   35.60 +    static final int  ZIP64_ENDTOT = 32;      // total number of entries
   35.61 +    static final int  ZIP64_ENDSIZ = 40;      // central directory size in bytes
   35.62 +    static final int  ZIP64_ENDOFF = 48;      // offset of first CEN header
   35.63 +    static final int  ZIP64_ENDEXT = 56;      // zip64 extensible data sector
   35.64 +
   35.65 +    /*
   35.66 +     * Zip64 End of central directory locator field offsets
   35.67 +     */
   35.68 +    static final int  ZIP64_LOCDSK = 4;       // disk number start
   35.69 +    static final int  ZIP64_LOCOFF = 8;       // offset of zip64 end
   35.70 +    static final int  ZIP64_LOCTOT = 16;      // total number of disks
   35.71 +
   35.72 +    /*
   35.73 +     * Zip64 Extra local (EXT) header field offsets
   35.74 +     */
   35.75 +    static final int  ZIP64_EXTCRC = 4;       // uncompressed file crc-32 value
   35.76 +    static final int  ZIP64_EXTSIZ = 8;       // compressed size, 8-byte
   35.77 +    static final int  ZIP64_EXTLEN = 16;      // uncompressed size, 8-byte
   35.78 +
   35.79 +    /*
   35.80 +     * Language encoding flag EFS
   35.81 +     */
   35.82 +    static final int EFS = 0x800;       // If this bit is set the filename and
   35.83 +                                        // comment fields for this file must be
   35.84 +                                        // encoded using UTF-8.
   35.85 +
   35.86 +    private ZipConstants64() {}
   35.87 +}
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/ZipInputStream.java	Tue Feb 19 15:59:27 2013 +0100
    36.3 @@ -0,0 +1,468 @@
    36.4 +/*
    36.5 + * Copyright (c) 1996, 2009, 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 org.apidesign.bck2brwsr.emul.zip;
   36.30 +
   36.31 +import java.util.zip.*;
   36.32 +import java.io.InputStream;
   36.33 +import java.io.IOException;
   36.34 +import java.io.EOFException;
   36.35 +import java.io.PushbackInputStream;
   36.36 +import static org.apidesign.bck2brwsr.emul.zip.ZipConstants64.*;
   36.37 +import static java.util.zip.ZipInputStream.*;
   36.38 +
   36.39 +/**
   36.40 + * This class implements an input stream filter for reading files in the
   36.41 + * ZIP file format. Includes support for both compressed and uncompressed
   36.42 + * entries.
   36.43 + *
   36.44 + * @author      David Connelly
   36.45 + */
   36.46 +public
   36.47 +class ZipInputStream extends InflaterInputStream  {
   36.48 +    private ZipEntry entry;
   36.49 +    private int flag;
   36.50 +    private CRC32 crc = new CRC32();
   36.51 +    private long remaining;
   36.52 +    private byte[] tmpbuf = new byte[512];
   36.53 +
   36.54 +    private static final int STORED = ZipEntry.STORED;
   36.55 +    private static final int DEFLATED = ZipEntry.DEFLATED;
   36.56 +
   36.57 +    private boolean closed = false;
   36.58 +    // this flag is set to true after EOF has reached for
   36.59 +    // one entry
   36.60 +    private boolean entryEOF = false;
   36.61 +
   36.62 +    /**
   36.63 +     * Check to make sure that this stream has not been closed
   36.64 +     */
   36.65 +    private void ensureOpen() throws IOException {
   36.66 +        if (closed) {
   36.67 +            throw new IOException("Stream closed");
   36.68 +        }
   36.69 +    }
   36.70 +
   36.71 +    /**
   36.72 +     * Creates a new ZIP input stream.
   36.73 +     *
   36.74 +     * <p>The UTF-8 {@link java.nio.charset.Charset charset} is used to
   36.75 +     * decode the entry names.
   36.76 +     *
   36.77 +     * @param in the actual input stream
   36.78 +     */
   36.79 +    public ZipInputStream(InputStream in) {
   36.80 +//        this(in, "UTF-8");
   36.81 +        super(new PushbackInputStream(in, 512), new Inflater(true), 512);
   36.82 +        //usesDefaultInflater = true;
   36.83 +        if(in == null) {
   36.84 +            throw new NullPointerException("in is null");
   36.85 +        }
   36.86 +    }
   36.87 +
   36.88 +    /**
   36.89 +     * Creates a new ZIP input stream.
   36.90 +     *
   36.91 +     * @param in the actual input stream
   36.92 +     *
   36.93 +     * @param charset
   36.94 +     *        The {@linkplain java.nio.charset.Charset charset} to be
   36.95 +     *        used to decode the ZIP entry name (ignored if the
   36.96 +     *        <a href="package-summary.html#lang_encoding"> language
   36.97 +     *        encoding bit</a> of the ZIP entry's general purpose bit
   36.98 +     *        flag is set).
   36.99 +     *
  36.100 +     * @since 1.7
  36.101 +     *
  36.102 +    public ZipInputStream(InputStream in, Charset charset) {
  36.103 +        super(new PushbackInputStream(in, 512), new Inflater(true), 512);
  36.104 +        usesDefaultInflater = true;
  36.105 +        if(in == null) {
  36.106 +            throw new NullPointerException("in is null");
  36.107 +        }
  36.108 +        if (charset == null)
  36.109 +            throw new NullPointerException("charset is null");
  36.110 +        this.zc = ZipCoder.get(charset);
  36.111 +    }
  36.112 +    */
  36.113 +
  36.114 +    /**
  36.115 +     * Reads the next ZIP file entry and positions the stream at the
  36.116 +     * beginning of the entry data.
  36.117 +     * @return the next ZIP file entry, or null if there are no more entries
  36.118 +     * @exception ZipException if a ZIP file error has occurred
  36.119 +     * @exception IOException if an I/O error has occurred
  36.120 +     */
  36.121 +    public ZipEntry getNextEntry() throws IOException {
  36.122 +        ensureOpen();
  36.123 +        if (entry != null) {
  36.124 +            closeEntry();
  36.125 +        }
  36.126 +        crc.reset();
  36.127 +        inf.reset();
  36.128 +        if ((entry = readLOC()) == null) {
  36.129 +            return null;
  36.130 +        }
  36.131 +        if (entry.getMethod() == STORED) {
  36.132 +            remaining = entry.getSize();
  36.133 +        }
  36.134 +        entryEOF = false;
  36.135 +        return entry;
  36.136 +    }
  36.137 +
  36.138 +    /**
  36.139 +     * Closes the current ZIP entry and positions the stream for reading the
  36.140 +     * next entry.
  36.141 +     * @exception ZipException if a ZIP file error has occurred
  36.142 +     * @exception IOException if an I/O error has occurred
  36.143 +     */
  36.144 +    public void closeEntry() throws IOException {
  36.145 +        ensureOpen();
  36.146 +        while (read(tmpbuf, 0, tmpbuf.length) != -1) ;
  36.147 +        entryEOF = true;
  36.148 +    }
  36.149 +
  36.150 +    /**
  36.151 +     * Returns 0 after EOF has reached for the current entry data,
  36.152 +     * otherwise always return 1.
  36.153 +     * <p>
  36.154 +     * Programs should not count on this method to return the actual number
  36.155 +     * of bytes that could be read without blocking.
  36.156 +     *
  36.157 +     * @return     1 before EOF and 0 after EOF has reached for current entry.
  36.158 +     * @exception  IOException  if an I/O error occurs.
  36.159 +     *
  36.160 +     */
  36.161 +    public int available() throws IOException {
  36.162 +        ensureOpen();
  36.163 +        if (entryEOF) {
  36.164 +            return 0;
  36.165 +        } else {
  36.166 +            return 1;
  36.167 +        }
  36.168 +    }
  36.169 +
  36.170 +    /**
  36.171 +     * Reads from the current ZIP entry into an array of bytes.
  36.172 +     * If <code>len</code> is not zero, the method
  36.173 +     * blocks until some input is available; otherwise, no
  36.174 +     * bytes are read and <code>0</code> is returned.
  36.175 +     * @param b the buffer into which the data is read
  36.176 +     * @param off the start offset in the destination array <code>b</code>
  36.177 +     * @param len the maximum number of bytes read
  36.178 +     * @return the actual number of bytes read, or -1 if the end of the
  36.179 +     *         entry is reached
  36.180 +     * @exception  NullPointerException if <code>b</code> is <code>null</code>.
  36.181 +     * @exception  IndexOutOfBoundsException if <code>off</code> is negative,
  36.182 +     * <code>len</code> is negative, or <code>len</code> is greater than
  36.183 +     * <code>b.length - off</code>
  36.184 +     * @exception ZipException if a ZIP file error has occurred
  36.185 +     * @exception IOException if an I/O error has occurred
  36.186 +     */
  36.187 +    public int read(byte[] b, int off, int len) throws IOException {
  36.188 +        ensureOpen();
  36.189 +        if (off < 0 || len < 0 || off > b.length - len) {
  36.190 +            throw new IndexOutOfBoundsException();
  36.191 +        } else if (len == 0) {
  36.192 +            return 0;
  36.193 +        }
  36.194 +
  36.195 +        if (entry == null) {
  36.196 +            return -1;
  36.197 +        }
  36.198 +        switch (entry.getMethod()) {
  36.199 +        case DEFLATED:
  36.200 +            len = super.read(b, off, len);
  36.201 +            if (len == -1) {
  36.202 +                readEnd(entry);
  36.203 +                entryEOF = true;
  36.204 +                entry = null;
  36.205 +            } else {
  36.206 +                crc.update(b, off, len);
  36.207 +            }
  36.208 +            return len;
  36.209 +        case STORED:
  36.210 +            if (remaining <= 0) {
  36.211 +                entryEOF = true;
  36.212 +                entry = null;
  36.213 +                return -1;
  36.214 +            }
  36.215 +            if (len > remaining) {
  36.216 +                len = (int)remaining;
  36.217 +            }
  36.218 +            len = in.read(b, off, len);
  36.219 +            if (len == -1) {
  36.220 +                throw new ZipException("unexpected EOF");
  36.221 +            }
  36.222 +            crc.update(b, off, len);
  36.223 +            remaining -= len;
  36.224 +            if (remaining == 0 && entry.getCrc() != crc.getValue()) {
  36.225 +                throw new ZipException(
  36.226 +                    "invalid entry CRC (expected 0x" + Long.toHexString(entry.getCrc()) +
  36.227 +                    " but got 0x" + Long.toHexString(crc.getValue()) + ")");
  36.228 +            }
  36.229 +            return len;
  36.230 +        default:
  36.231 +            throw new ZipException("invalid compression method");
  36.232 +        }
  36.233 +    }
  36.234 +
  36.235 +    /**
  36.236 +     * Skips specified number of bytes in the current ZIP entry.
  36.237 +     * @param n the number of bytes to skip
  36.238 +     * @return the actual number of bytes skipped
  36.239 +     * @exception ZipException if a ZIP file error has occurred
  36.240 +     * @exception IOException if an I/O error has occurred
  36.241 +     * @exception IllegalArgumentException if n < 0
  36.242 +     */
  36.243 +    public long skip(long n) throws IOException {
  36.244 +        if (n < 0) {
  36.245 +            throw new IllegalArgumentException("negative skip length");
  36.246 +        }
  36.247 +        ensureOpen();
  36.248 +        int max = (int)Math.min(n, Integer.MAX_VALUE);
  36.249 +        int total = 0;
  36.250 +        while (total < max) {
  36.251 +            int len = max - total;
  36.252 +            if (len > tmpbuf.length) {
  36.253 +                len = tmpbuf.length;
  36.254 +            }
  36.255 +            len = read(tmpbuf, 0, len);
  36.256 +            if (len == -1) {
  36.257 +                entryEOF = true;
  36.258 +                break;
  36.259 +            }
  36.260 +            total += len;
  36.261 +        }
  36.262 +        return total;
  36.263 +    }
  36.264 +
  36.265 +    /**
  36.266 +     * Closes this input stream and releases any system resources associated
  36.267 +     * with the stream.
  36.268 +     * @exception IOException if an I/O error has occurred
  36.269 +     */
  36.270 +    public void close() throws IOException {
  36.271 +        if (!closed) {
  36.272 +            super.close();
  36.273 +            closed = true;
  36.274 +        }
  36.275 +    }
  36.276 +
  36.277 +    private byte[] b = new byte[256];
  36.278 +
  36.279 +    /*
  36.280 +     * Reads local file (LOC) header for next entry.
  36.281 +     */
  36.282 +    private ZipEntry readLOC() throws IOException {
  36.283 +        try {
  36.284 +            readFully(tmpbuf, 0, LOCHDR);
  36.285 +        } catch (EOFException e) {
  36.286 +            return null;
  36.287 +        }
  36.288 +        if (get32(tmpbuf, 0) != LOCSIG) {
  36.289 +            return null;
  36.290 +        }
  36.291 +        // get flag first, we need check EFS.
  36.292 +        flag = get16(tmpbuf, LOCFLG);
  36.293 +        // get the entry name and create the ZipEntry first
  36.294 +        int len = get16(tmpbuf, LOCNAM);
  36.295 +        int blen = b.length;
  36.296 +        if (len > blen) {
  36.297 +            do
  36.298 +                blen = blen * 2;
  36.299 +            while (len > blen);
  36.300 +            b = new byte[blen];
  36.301 +        }
  36.302 +        readFully(b, 0, len);
  36.303 +        // Force to use UTF-8 if the EFS bit is ON, even the cs is NOT UTF-8
  36.304 +        ZipEntry e = createZipEntry(((flag & EFS) != 0)
  36.305 +                                    ? toStringUTF8(b, len)
  36.306 +                                    : toString(b, len));
  36.307 +        // now get the remaining fields for the entry
  36.308 +        if ((flag & 1) == 1) {
  36.309 +            throw new ZipException("encrypted ZIP entry not supported");
  36.310 +        }
  36.311 +        e.setMethod(get16(tmpbuf, LOCHOW));
  36.312 +        e.setTime(get32(tmpbuf, LOCTIM));
  36.313 +        if ((flag & 8) == 8) {
  36.314 +            /* "Data Descriptor" present */
  36.315 +            if (e.getMethod() != DEFLATED) {
  36.316 +                throw new ZipException(
  36.317 +                        "only DEFLATED entries can have EXT descriptor");
  36.318 +            }
  36.319 +        } else {
  36.320 +            e.setCrc(get32(tmpbuf, LOCCRC));
  36.321 +            e.setCompressedSize(get32(tmpbuf, LOCSIZ));
  36.322 +            e.setSize(get32(tmpbuf, LOCLEN));
  36.323 +        }
  36.324 +        len = get16(tmpbuf, LOCEXT);
  36.325 +        if (len > 0) {
  36.326 +            byte[] bb = new byte[len];
  36.327 +            readFully(bb, 0, len);
  36.328 +            e.setExtra(bb);
  36.329 +            // extra fields are in "HeaderID(2)DataSize(2)Data... format
  36.330 +            if (e.getCompressedSize() == ZIP64_MAGICVAL || e.getCompressedSize() == ZIP64_MAGICVAL) {
  36.331 +                int off = 0;
  36.332 +                while (off + 4 < len) {
  36.333 +                    int sz = get16(bb, off + 2);
  36.334 +                    if (get16(bb, off) == ZIP64_EXTID) {
  36.335 +                        off += 4;
  36.336 +                        // LOC extra zip64 entry MUST include BOTH original and
  36.337 +                        // compressed file size fields
  36.338 +                        if (sz < 16 || (off + sz) > len ) {
  36.339 +                            // Invalid zip64 extra fields, simply skip. Even it's
  36.340 +                            // rare, it's possible the entry size happens to be
  36.341 +                            // the magic value and it "accidnetly" has some bytes
  36.342 +                            // in extra match the id.
  36.343 +                            return e;
  36.344 +                        }
  36.345 +                        e.setSize(get64(bb, off));
  36.346 +                        e.setCompressedSize(get64(bb, off + 8));
  36.347 +                        break;
  36.348 +                    }
  36.349 +                    off += (sz + 4);
  36.350 +                }
  36.351 +            }
  36.352 +        }
  36.353 +        return e;
  36.354 +    }
  36.355 +
  36.356 +    /**
  36.357 +     * Creates a new <code>ZipEntry</code> object for the specified
  36.358 +     * entry name.
  36.359 +     *
  36.360 +     * @param name the ZIP file entry name
  36.361 +     * @return the ZipEntry just created
  36.362 +     */
  36.363 +    protected ZipEntry createZipEntry(String name) {
  36.364 +        return new ZipEntry(name);
  36.365 +    }
  36.366 +
  36.367 +    /*
  36.368 +     * Reads end of deflated entry as well as EXT descriptor if present.
  36.369 +     */
  36.370 +    private void readEnd(ZipEntry e) throws IOException {
  36.371 +        int n = inf.getRemaining();
  36.372 +        if (n > 0) {
  36.373 +            ((PushbackInputStream)in).unread(buf, len - n, n);
  36.374 +        }
  36.375 +        if ((flag & 8) == 8) {
  36.376 +            /* "Data Descriptor" present */
  36.377 +            if (inf.getBytesWritten() > ZIP64_MAGICVAL ||
  36.378 +                inf.getBytesRead() > ZIP64_MAGICVAL) {
  36.379 +                // ZIP64 format
  36.380 +                readFully(tmpbuf, 0, ZIP64_EXTHDR);
  36.381 +                long sig = get32(tmpbuf, 0);
  36.382 +                if (sig != EXTSIG) { // no EXTSIG present
  36.383 +                    e.setCrc(sig);
  36.384 +                    e.setCompressedSize(get64(tmpbuf, ZIP64_EXTSIZ - ZIP64_EXTCRC));
  36.385 +                    e.setSize(get64(tmpbuf, ZIP64_EXTLEN - ZIP64_EXTCRC));
  36.386 +                    ((PushbackInputStream)in).unread(
  36.387 +                        tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC - 1, ZIP64_EXTCRC);
  36.388 +                } else {
  36.389 +                    e.setCrc(get32(tmpbuf, ZIP64_EXTCRC));
  36.390 +                    e.setCompressedSize(get64(tmpbuf, ZIP64_EXTSIZ));
  36.391 +                    e.setSize(get64(tmpbuf, ZIP64_EXTLEN));
  36.392 +                }
  36.393 +            } else {
  36.394 +                readFully(tmpbuf, 0, EXTHDR);
  36.395 +                long sig = get32(tmpbuf, 0);
  36.396 +                if (sig != EXTSIG) { // no EXTSIG present
  36.397 +                    e.setCrc(sig);
  36.398 +                    e.setCompressedSize(get32(tmpbuf, EXTSIZ - EXTCRC));
  36.399 +                    e.setSize(get32(tmpbuf, EXTLEN - EXTCRC));
  36.400 +                    ((PushbackInputStream)in).unread(
  36.401 +                                               tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC);
  36.402 +                } else {
  36.403 +                    e.setCrc(get32(tmpbuf, EXTCRC));
  36.404 +                    e.setCompressedSize(get32(tmpbuf, EXTSIZ));
  36.405 +                    e.setSize(get32(tmpbuf, EXTLEN));
  36.406 +                }
  36.407 +            }
  36.408 +        }
  36.409 +        if (e.getSize() != inf.getBytesWritten()) {
  36.410 +            throw new ZipException(
  36.411 +                "invalid entry size (expected " + e.getSize() +
  36.412 +                " but got " + inf.getBytesWritten() + " bytes)");
  36.413 +        }
  36.414 +        if (e.getCompressedSize() != inf.getBytesRead()) {
  36.415 +            throw new ZipException(
  36.416 +                "invalid entry compressed size (expected " + e.getCompressedSize() +
  36.417 +                " but got " + inf.getBytesRead() + " bytes)");
  36.418 +        }
  36.419 +        if (e.getCrc() != crc.getValue()) {
  36.420 +            throw new ZipException(
  36.421 +                "invalid entry CRC (expected 0x" + Long.toHexString(e.getCrc()) +
  36.422 +                " but got 0x" + Long.toHexString(crc.getValue()) + ")");
  36.423 +        }
  36.424 +    }
  36.425 +
  36.426 +    /*
  36.427 +     * Reads bytes, blocking until all bytes are read.
  36.428 +     */
  36.429 +    private void readFully(byte[] b, int off, int len) throws IOException {
  36.430 +        while (len > 0) {
  36.431 +            int n = in.read(b, off, len);
  36.432 +            if (n == -1) {
  36.433 +                throw new EOFException();
  36.434 +            }
  36.435 +            off += n;
  36.436 +            len -= n;
  36.437 +        }
  36.438 +    }
  36.439 +
  36.440 +    /*
  36.441 +     * Fetches unsigned 16-bit value from byte array at specified offset.
  36.442 +     * The bytes are assumed to be in Intel (little-endian) byte order.
  36.443 +     */
  36.444 +    private static final int get16(byte b[], int off) {
  36.445 +        return (b[off] & 0xff) | ((b[off+1] & 0xff) << 8);
  36.446 +    }
  36.447 +
  36.448 +    /*
  36.449 +     * Fetches unsigned 32-bit value from byte array at specified offset.
  36.450 +     * The bytes are assumed to be in Intel (little-endian) byte order.
  36.451 +     */
  36.452 +    private static final long get32(byte b[], int off) {
  36.453 +        return (get16(b, off) | ((long)get16(b, off+2) << 16)) & 0xffffffffL;
  36.454 +    }
  36.455 +
  36.456 +    /*
  36.457 +     * Fetches signed 64-bit value from byte array at specified offset.
  36.458 +     * The bytes are assumed to be in Intel (little-endian) byte order.
  36.459 +     */
  36.460 +    private static final long get64(byte b[], int off) {
  36.461 +        return get32(b, off) | (get32(b, off+4) << 32);
  36.462 +    }
  36.463 +
  36.464 +    private static String toStringUTF8(byte[] arr, int len) {
  36.465 +        return new String(arr, 0, len);
  36.466 +    }
  36.467 +    
  36.468 +    private static String toString(byte[] b, int len) {
  36.469 +        return new String(b, 0, len);
  36.470 +    }
  36.471 +}
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/emul/mini/src/test/java/org/apidesign/bck2brwsr/emul/reflect/MethodImplTest.java	Tue Feb 19 15:59:27 2013 +0100
    37.3 @@ -0,0 +1,49 @@
    37.4 +/**
    37.5 + * Back 2 Browser Bytecode Translator
    37.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    37.7 + *
    37.8 + * This program is free software: you can redistribute it and/or modify
    37.9 + * it under the terms of the GNU General Public License as published by
   37.10 + * the Free Software Foundation, version 2 of the License.
   37.11 + *
   37.12 + * This program is distributed in the hope that it will be useful,
   37.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   37.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   37.15 + * GNU General Public License for more details.
   37.16 + *
   37.17 + * You should have received a copy of the GNU General Public License
   37.18 + * along with this program. Look for COPYING file in the top folder.
   37.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   37.20 + */
   37.21 +package org.apidesign.bck2brwsr.emul.reflect;
   37.22 +
   37.23 +import java.lang.reflect.Method;
   37.24 +import java.util.Enumeration;
   37.25 +import org.testng.annotations.Test;
   37.26 +
   37.27 +/**
   37.28 + *
   37.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   37.30 + */
   37.31 +public class MethodImplTest {
   37.32 +    
   37.33 +    public MethodImplTest() {
   37.34 +    }
   37.35 +    
   37.36 +    public static String[] arr(String... arr) {
   37.37 +        return arr;
   37.38 +    }
   37.39 +
   37.40 +    @Test
   37.41 +    public void testSignatureForMethodWithAnArray() throws NoSuchMethodException {
   37.42 +        Method m = MethodImplTest.class.getMethod("arr", String[].class);
   37.43 +        String sig = MethodImpl.toSignature(m);
   37.44 +        int sep = sig.indexOf("__");
   37.45 +        assert sep > 0 : "Separator found " + sig;
   37.46 +        
   37.47 +        Enumeration<Class> en = MethodImpl.signatureParser(sig.substring(sep + 2));
   37.48 +        
   37.49 +        assert en.nextElement() == m.getReturnType() : "Return type is the same";
   37.50 +        assert en.nextElement() == m.getParameterTypes()[0] : "1st param type is the same";
   37.51 +    }
   37.52 +}
   37.53 \ No newline at end of file
    38.1 --- a/javap/src/main/java/org/apidesign/javap/AnnotationParser.java	Tue Feb 19 15:33:32 2013 +0100
    38.2 +++ b/javap/src/main/java/org/apidesign/javap/AnnotationParser.java	Tue Feb 19 15:59:27 2013 +0100
    38.3 @@ -35,22 +35,37 @@
    38.4   */
    38.5  public class AnnotationParser {
    38.6      private final boolean textual;
    38.7 +    private final boolean iterateArray;
    38.8      
    38.9 -    protected AnnotationParser(boolean textual) {
   38.10 +    protected AnnotationParser(boolean textual, boolean iterateArray) {
   38.11          this.textual = textual;
   38.12 +        this.iterateArray = iterateArray;
   38.13      }
   38.14  
   38.15 -    protected void visitAnnotationStart(String type) throws IOException {
   38.16 +    protected void visitAnnotationStart(String type, boolean top) throws IOException {
   38.17      }
   38.18  
   38.19 -    protected void visitAnnotationEnd(String type) throws IOException {
   38.20 +    protected void visitAnnotationEnd(String type, boolean top) throws IOException {
   38.21      }
   38.22 +
   38.23 +    protected void visitValueStart(String attrName, char type) throws IOException {
   38.24 +    }
   38.25 +
   38.26 +    protected void visitValueEnd(String attrName, char type) throws IOException {
   38.27 +    }
   38.28 +
   38.29      
   38.30      protected void visitAttr(
   38.31          String annoType, String attr, String attrType, String value
   38.32      ) throws IOException {
   38.33      }
   38.34      
   38.35 +    protected void visitEnumAttr(
   38.36 +        String annoType, String attr, String attrType, String value
   38.37 +    ) throws IOException {
   38.38 +        visitAttr(annoType, attr, attrType, value);
   38.39 +    }
   38.40 +    
   38.41      /** Initialize the parsing with constant pool from <code>cd</code>.
   38.42       * 
   38.43       * @param attr the attribute defining annotations
   38.44 @@ -70,30 +85,32 @@
   38.45      private void read(DataInputStream dis, ClassData cd) throws IOException {
   38.46      	int cnt = dis.readUnsignedShort();
   38.47          for (int i = 0; i < cnt; i++) {
   38.48 -            readAnno(dis, cd);
   38.49 +            readAnno(dis, cd, true);
   38.50          }
   38.51      }
   38.52  
   38.53 -    private void readAnno(DataInputStream dis, ClassData cd) throws IOException {
   38.54 +    private void readAnno(DataInputStream dis, ClassData cd, boolean top) throws IOException {
   38.55          int type = dis.readUnsignedShort();
   38.56          String typeName = cd.StringValue(type);
   38.57 -        visitAnnotationStart(typeName);
   38.58 +        visitAnnotationStart(typeName, top);
   38.59      	int cnt = dis.readUnsignedShort();
   38.60      	for (int i = 0; i < cnt; i++) {
   38.61              String attrName = cd.StringValue(dis.readUnsignedShort());
   38.62              readValue(dis, cd, typeName, attrName);
   38.63          }
   38.64 -        visitAnnotationEnd(typeName);
   38.65 +        visitAnnotationEnd(typeName, top);
   38.66          if (cnt == 0) {
   38.67              visitAttr(typeName, null, null, null);
   38.68          }
   38.69      }
   38.70  
   38.71 -    private void readValue(DataInputStream dis, ClassData cd, String typeName, String attrName) 
   38.72 -    throws IOException {
   38.73 +    private void readValue(
   38.74 +        DataInputStream dis, ClassData cd, String typeName, String attrName
   38.75 +    ) throws IOException {
   38.76          char type = (char)dis.readByte();
   38.77 +        visitValueStart(attrName, type);
   38.78          if (type == '@') {
   38.79 -            readAnno(dis, cd);
   38.80 +            readAnno(dis, cd, false);
   38.81          } else if ("CFJZsSIDB".indexOf(type) >= 0) { // NOI18N
   38.82              int primitive = dis.readUnsignedShort();
   38.83              String val = cd.stringValue(primitive, textual);
   38.84 @@ -112,13 +129,17 @@
   38.85          } else if (type == '[') {
   38.86              int cnt = dis.readUnsignedShort();
   38.87              for (int i = 0; i < cnt; i++) {
   38.88 -                readValue(dis, cd, typeName, attrName);
   38.89 +                readValue(dis, cd, typeName, iterateArray ? attrName : null);
   38.90              }
   38.91          } else if (type == 'e') {
   38.92              int enumT = dis.readUnsignedShort();
   38.93 +            String attrType = cd.stringValue(enumT, textual);
   38.94              int enumN = dis.readUnsignedShort();
   38.95 +            String val = cd.stringValue(enumN, textual);
   38.96 +            visitEnumAttr(typeName, attrName, attrType, val);
   38.97          } else {
   38.98              throw new IOException("Unknown type " + type);
   38.99          }
  38.100 +        visitValueEnd(attrName, type);
  38.101      }
  38.102  }
    39.1 --- a/javaquery/api/pom.xml	Tue Feb 19 15:33:32 2013 +0100
    39.2 +++ b/javaquery/api/pom.xml	Tue Feb 19 15:59:27 2013 +0100
    39.3 @@ -47,21 +47,16 @@
    39.4      </dependency>
    39.5      <dependency>
    39.6        <groupId>org.apidesign.bck2brwsr</groupId>
    39.7 -      <artifactId>core</artifactId>
    39.8 -      <version>0.3-SNAPSHOT</version>
    39.9 +      <artifactId>emul</artifactId>
   39.10 +      <version>${project.version}</version>
   39.11 +      <classifier>rt</classifier>
   39.12        <type>jar</type>
   39.13 -    </dependency>
   39.14 -    <dependency>
   39.15 -      <groupId>org.apidesign.bck2brwsr</groupId>
   39.16 -      <artifactId>emul.mini</artifactId>
   39.17 -      <version>0.3-SNAPSHOT</version>
   39.18 -      <type>jar</type>
   39.19 -      <scope>runtime</scope>
   39.20 +      <scope>compile</scope>
   39.21      </dependency>
   39.22      <dependency>
   39.23        <groupId>org.apidesign.bck2brwsr</groupId>
   39.24        <artifactId>vm4brwsr</artifactId>
   39.25 -      <version>0.3-SNAPSHOT</version>
   39.26 +      <version>${project.version}</version>
   39.27        <type>jar</type>
   39.28        <scope>test</scope>
   39.29      </dependency>
    40.1 --- a/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ProcessPageTest.java	Tue Feb 19 15:33:32 2013 +0100
    40.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ProcessPageTest.java	Tue Feb 19 15:59:27 2013 +0100
    40.3 @@ -128,6 +128,8 @@
    40.4              sb = new StringBuilder();
    40.5          }
    40.6          Bck2Brwsr.generate(sb, ProcessPageTest.class.getClassLoader(), names);
    40.7 +        sb.append("var vm = this.bck2brwsr();\n");
    40.8 +        
    40.9          ScriptEngineManager sem = new ScriptEngineManager();
   40.10          ScriptEngine js = sem.getEngineByExtension("js");
   40.11          try {
    41.1 --- a/javaquery/demo-calculator-dynamic/pom.xml	Tue Feb 19 15:33:32 2013 +0100
    41.2 +++ b/javaquery/demo-calculator-dynamic/pom.xml	Tue Feb 19 15:59:27 2013 +0100
    41.3 @@ -40,22 +40,54 @@
    41.4                 <target>1.7</target>
    41.5              </configuration>
    41.6           </plugin>
    41.7 -        <plugin>
    41.8 +         <plugin>
    41.9 +             <groupId>org.apache.maven.plugins</groupId>
   41.10 +             <artifactId>maven-jar-plugin</artifactId>
   41.11 +             <version>2.4</version>
   41.12 +             <configuration>
   41.13 +                 <archive>
   41.14 +                     <manifest>
   41.15 +                         <addClasspath>true</addClasspath>
   41.16 +                         <classpathPrefix>lib/</classpathPrefix>
   41.17 +                     </manifest>
   41.18 +                 </archive>
   41.19 +             </configuration>
   41.20 +         </plugin>
   41.21 +         <plugin>
   41.22             <groupId>org.apache.maven.plugins</groupId>
   41.23             <artifactId>maven-deploy-plugin</artifactId>
   41.24             <version>2.7</version>
   41.25             <configuration>
   41.26               <skip>true</skip>
   41.27             </configuration>
   41.28 -         </plugin>      
   41.29 +         </plugin>
   41.30 +         <plugin>
   41.31 +            <artifactId>maven-assembly-plugin</artifactId>
   41.32 +                <version>2.4</version>
   41.33 +                <executions>
   41.34 +                    <execution>
   41.35 +                        <id>distro-assembly</id>
   41.36 +                        <phase>package</phase>
   41.37 +                        <goals>
   41.38 +                            <goal>single</goal>
   41.39 +                        </goals>
   41.40 +                        <configuration>
   41.41 +                            <descriptors>
   41.42 +                                <descriptor>src/main/assembly/bck2brwsr.xml</descriptor>
   41.43 +                            </descriptors>
   41.44 +                        </configuration>
   41.45 +                    </execution>
   41.46 +                </executions>                
   41.47 +            </plugin>      
   41.48        </plugins>
   41.49    </build>
   41.50  
   41.51    <dependencies>
   41.52      <dependency>
   41.53        <groupId>org.apidesign.bck2brwsr</groupId>
   41.54 -      <artifactId>emul.mini</artifactId>
   41.55 +      <artifactId>emul</artifactId>
   41.56        <version>0.3-SNAPSHOT</version>
   41.57 +      <classifier>rt</classifier>
   41.58      </dependency>
   41.59      <dependency>
   41.60        <groupId>org.apidesign.bck2brwsr</groupId>
   41.61 @@ -68,5 +100,13 @@
   41.62        <version>6.5.2</version>
   41.63        <scope>test</scope>
   41.64      </dependency>
   41.65 +    <dependency>
   41.66 +      <groupId>org.apidesign.bck2brwsr</groupId>
   41.67 +      <artifactId>vm4brwsr</artifactId>
   41.68 +      <classifier>js</classifier>
   41.69 +      <type>zip</type>
   41.70 +      <version>0.3-SNAPSHOT</version>
   41.71 +      <scope>provided</scope>
   41.72 +    </dependency>
   41.73    </dependencies>
   41.74  </project>
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/javaquery/demo-calculator-dynamic/src/main/assembly/bck2brwsr.xml	Tue Feb 19 15:59:27 2013 +0100
    42.3 @@ -0,0 +1,62 @@
    42.4 +<?xml version="1.0"?>
    42.5 +<!--
    42.6 +
    42.7 +    Back 2 Browser Bytecode Translator
    42.8 +    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    42.9 +
   42.10 +    This program is free software: you can redistribute it and/or modify
   42.11 +    it under the terms of the GNU General Public License as published by
   42.12 +    the Free Software Foundation, version 2 of the License.
   42.13 +
   42.14 +    This program is distributed in the hope that it will be useful,
   42.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   42.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   42.17 +    GNU General Public License for more details.
   42.18 +
   42.19 +    You should have received a copy of the GNU General Public License
   42.20 +    along with this program. Look for COPYING file in the top folder.
   42.21 +    If not, see http://opensource.org/licenses/GPL-2.0.
   42.22 +
   42.23 +-->
   42.24 +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   42.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">
   42.26 +  
   42.27 +  <id>bck2brwsr</id>
   42.28 +  <formats>
   42.29 +      <format>zip</format>
   42.30 +      <format>dir</format>
   42.31 +  </formats>
   42.32 +  <baseDirectory>public_html</baseDirectory>
   42.33 +  <dependencySets>
   42.34 +    <dependencySet>
   42.35 +        <useProjectArtifact>false</useProjectArtifact>
   42.36 +        <scope>runtime</scope>
   42.37 +        <outputDirectory>lib</outputDirectory>
   42.38 +        <includes>
   42.39 +            <include>*:jar</include>
   42.40 +            <include>*:rt</include>
   42.41 +        </includes>
   42.42 +    </dependencySet>
   42.43 +    <dependencySet>
   42.44 +        <useProjectArtifact>false</useProjectArtifact>
   42.45 +        <scope>provided</scope>
   42.46 +        <includes>
   42.47 +            <include>*:js</include>
   42.48 +        </includes>
   42.49 +        <unpack>true</unpack>
   42.50 +        <outputDirectory>/</outputDirectory>
   42.51 +    </dependencySet>
   42.52 +  </dependencySets> 
   42.53 +  <files>
   42.54 +    <file>
   42.55 +      <source>${project.build.directory}/${project.build.finalName}.jar</source>
   42.56 +      <outputDirectory>/</outputDirectory>
   42.57 +    </file>
   42.58 +    <file>
   42.59 +      <source>${project.build.directory}/classes/org/apidesign/bck2brwsr/demo/calc/Calculator.xhtml</source>
   42.60 +      <outputDirectory>/</outputDirectory>
   42.61 +      <destName>index.xhtml</destName>
   42.62 +    </file>
   42.63 +  </files>
   42.64 +
   42.65 +</assembly>
   42.66 \ No newline at end of file
    43.1 --- a/javaquery/demo-calculator-dynamic/src/main/resources/org/apidesign/bck2brwsr/demo/calc/Calculator.xhtml	Tue Feb 19 15:33:32 2013 +0100
    43.2 +++ b/javaquery/demo-calculator-dynamic/src/main/resources/org/apidesign/bck2brwsr/demo/calc/Calculator.xhtml	Tue Feb 19 15:59:27 2013 +0100
    43.3 @@ -78,9 +78,9 @@
    43.4          </table>
    43.5          <div data-bind="text: displayPreview"></div>
    43.6          
    43.7 -        <script src="/bck2brwsr.js"></script>
    43.8 -        <script src="/vm.js"></script>
    43.9 +        <script src="bck2brwsr.js"></script>
   43.10          <script type="text/javascript">
   43.11 +            var vm = bck2brwsr('demo.calculator-0.3-SNAPSHOT.jar');
   43.12              vm.loadClass('org.apidesign.bck2brwsr.demo.calc.Calc');
   43.13          </script>
   43.14          
    44.1 --- a/javaquery/demo-calculator/nbactions.xml	Tue Feb 19 15:33:32 2013 +0100
    44.2 +++ b/javaquery/demo-calculator/nbactions.xml	Tue Feb 19 15:59:27 2013 +0100
    44.3 @@ -22,8 +22,11 @@
    44.4          <action>
    44.5              <actionName>run</actionName>
    44.6              <goals>
    44.7 -                <goal>process-classes</goal>
    44.8 +                <goal>package</goal>
    44.9                  <goal>org.apidesign.bck2brwsr:mojo:0.3-SNAPSHOT:brwsr</goal>
   44.10              </goals>
   44.11 +            <properties>
   44.12 +                <skipTests>true</skipTests>
   44.13 +            </properties>
   44.14          </action>
   44.15 -    </actions>
   44.16 +</actions>
    45.1 --- a/javaquery/demo-calculator/pom.xml	Tue Feb 19 15:33:32 2013 +0100
    45.2 +++ b/javaquery/demo-calculator/pom.xml	Tue Feb 19 15:59:27 2013 +0100
    45.3 @@ -23,7 +23,6 @@
    45.4                  <executions>
    45.5                      <execution>
    45.6                          <goals>
    45.7 -                            <goal>j2js</goal>
    45.8                              <goal>brwsr</goal>
    45.9                          </goals>
   45.10                      </execution>
   45.11 @@ -43,6 +42,19 @@
   45.12              </configuration>
   45.13           </plugin>
   45.14           <plugin>
   45.15 +             <groupId>org.apache.maven.plugins</groupId>
   45.16 +             <artifactId>maven-jar-plugin</artifactId>
   45.17 +             <version>2.4</version>
   45.18 +             <configuration>
   45.19 +                 <archive>
   45.20 +                     <manifest>
   45.21 +                         <addClasspath>true</addClasspath>
   45.22 +                         <classpathPrefix>lib/</classpathPrefix>
   45.23 +                     </manifest>
   45.24 +                 </archive>
   45.25 +             </configuration>
   45.26 +         </plugin>
   45.27 +         <plugin>
   45.28              <artifactId>maven-assembly-plugin</artifactId>
   45.29                  <version>2.4</version>
   45.30                  <executions>
   45.31 @@ -74,13 +86,22 @@
   45.32    <dependencies>
   45.33      <dependency>
   45.34        <groupId>org.apidesign.bck2brwsr</groupId>
   45.35 -      <artifactId>emul.mini</artifactId>
   45.36 +      <artifactId>emul</artifactId>
   45.37        <version>0.3-SNAPSHOT</version>
   45.38 +      <classifier>rt</classifier>
   45.39      </dependency>
   45.40      <dependency>
   45.41        <groupId>org.apidesign.bck2brwsr</groupId>
   45.42        <artifactId>javaquery.api</artifactId>
   45.43        <version>0.3-SNAPSHOT</version>
   45.44      </dependency>
   45.45 +    <dependency>
   45.46 +      <groupId>org.apidesign.bck2brwsr</groupId>
   45.47 +      <artifactId>vm4brwsr</artifactId>
   45.48 +      <classifier>js</classifier>
   45.49 +      <type>zip</type>
   45.50 +      <version>0.3-SNAPSHOT</version>
   45.51 +      <scope>provided</scope>
   45.52 +    </dependency>
   45.53    </dependencies>
   45.54  </project>
    46.1 --- a/javaquery/demo-calculator/src/main/assembly/bck2brwsr.xml	Tue Feb 19 15:33:32 2013 +0100
    46.2 +++ b/javaquery/demo-calculator/src/main/assembly/bck2brwsr.xml	Tue Feb 19 15:59:27 2013 +0100
    46.3 @@ -32,6 +32,19 @@
    46.4          <useProjectArtifact>false</useProjectArtifact>
    46.5          <scope>runtime</scope>
    46.6          <outputDirectory>lib</outputDirectory>
    46.7 +        <includes>
    46.8 +            <include>*:jar</include>
    46.9 +            <include>*:rt</include>
   46.10 +        </includes>
   46.11 +    </dependencySet>
   46.12 +    <dependencySet>
   46.13 +        <useProjectArtifact>false</useProjectArtifact>
   46.14 +        <scope>provided</scope>
   46.15 +        <includes>
   46.16 +            <include>*:js</include>
   46.17 +        </includes>
   46.18 +        <unpack>true</unpack>
   46.19 +        <outputDirectory>/</outputDirectory>
   46.20      </dependencySet>
   46.21    </dependencySets> 
   46.22    <files>
   46.23 @@ -44,11 +57,6 @@
   46.24        <outputDirectory>/</outputDirectory>
   46.25        <destName>index.xhtml</destName>
   46.26      </file>
   46.27 -    <file>
   46.28 -      <source>${project.build.directory}/classes/org/apidesign/bck2brwsr/demo/calc/staticcompilation/bootjava.js</source>
   46.29 -      <outputDirectory>/</outputDirectory>
   46.30 -      <destName>bck2brwsr.js</destName>
   46.31 -    </file>
   46.32    </files>
   46.33  
   46.34  </assembly>
   46.35 \ No newline at end of file
    47.1 --- a/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml	Tue Feb 19 15:33:32 2013 +0100
    47.2 +++ b/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml	Tue Feb 19 15:59:27 2013 +0100
    47.3 @@ -78,5 +78,9 @@
    47.4          </table>
    47.5          <div data-bind="text: displayPreview"></div>
    47.6          <script src="bck2brwsr.js"/>
    47.7 +        <script>
    47.8 +            var vm = bck2brwsr('demo.static.calculator-0.3-SNAPSHOT.jar');
    47.9 +            vm.loadClass('org.apidesign.bck2brwsr.demo.calc.staticcompilation.Calc');
   47.10 +        </script>
   47.11      </body>
   47.12  </html>
    48.1 --- a/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java	Tue Feb 19 15:33:32 2013 +0100
    48.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java	Tue Feb 19 15:59:27 2013 +0100
    48.3 @@ -39,6 +39,7 @@
    48.4  import java.util.concurrent.TimeUnit;
    48.5  import java.util.logging.Level;
    48.6  import java.util.logging.Logger;
    48.7 +import org.apidesign.bck2brwsr.launcher.InvocationContext.Resource;
    48.8  import org.apidesign.vm4brwsr.Bck2Brwsr;
    48.9  import org.glassfish.grizzly.PortRange;
   48.10  import org.glassfish.grizzly.http.server.HttpHandler;
   48.11 @@ -47,6 +48,7 @@
   48.12  import org.glassfish.grizzly.http.server.Request;
   48.13  import org.glassfish.grizzly.http.server.Response;
   48.14  import org.glassfish.grizzly.http.server.ServerConfiguration;
   48.15 +import org.glassfish.grizzly.http.util.HttpStatus;
   48.16  
   48.17  /**
   48.18   * Lightweight server to launch Bck2Brwsr applications and tests.
   48.19 @@ -94,9 +96,12 @@
   48.20              startpage = "/" + startpage;
   48.21          }
   48.22          HttpServer s = initServer(".", true);
   48.23 +        int last = startpage.lastIndexOf('/');
   48.24 +        String simpleName = startpage.substring(last);
   48.25 +        s.getServerConfiguration().addHttpHandler(new Page(resources, startpage), simpleName);
   48.26          s.getServerConfiguration().addHttpHandler(new Page(resources, null), "/");
   48.27          try {
   48.28 -            launchServerAndBrwsr(s, startpage);
   48.29 +            launchServerAndBrwsr(s, simpleName);
   48.30          } catch (URISyntaxException | InterruptedException ex) {
   48.31              throw new IOException(ex);
   48.32          }
   48.33 @@ -138,7 +143,7 @@
   48.34  
   48.35          final ServerConfiguration conf = s.getServerConfiguration();
   48.36          if (addClasses) {
   48.37 -            conf.addHttpHandler(new VM(resources), "/vm.js");
   48.38 +            conf.addHttpHandler(new VM(resources), "/bck2brwsr.js");
   48.39              conf.addHttpHandler(new Classes(resources), "/classes/");
   48.40          }
   48.41          return s;
   48.42 @@ -152,11 +157,13 @@
   48.43          class DynamicResourceHandler extends HttpHandler {
   48.44              private final InvocationContext ic;
   48.45              public DynamicResourceHandler(InvocationContext ic) {
   48.46 -                if (ic == null || ic.httpPath == null) {
   48.47 +                if (ic == null || ic.resources.isEmpty()) {
   48.48                      throw new NullPointerException();
   48.49                  }
   48.50                  this.ic = ic;
   48.51 -                conf.addHttpHandler(this, ic.httpPath);
   48.52 +                for (Resource r : ic.resources) {
   48.53 +                    conf.addHttpHandler(this, r.httpPath);
   48.54 +                }
   48.55              }
   48.56  
   48.57              public void close() {
   48.58 @@ -165,10 +172,12 @@
   48.59              
   48.60              @Override
   48.61              public void service(Request request, Response response) throws Exception {
   48.62 -                if (ic.httpPath.equals(request.getRequestURI())) {
   48.63 -                    LOG.log(Level.INFO, "Serving HttpResource for {0}", request.getRequestURI());
   48.64 -                    response.setContentType(ic.httpType);
   48.65 -                    copyStream(ic.httpContent, response.getOutputStream(), null);
   48.66 +                for (Resource r : ic.resources) {
   48.67 +                    if (r.httpPath.equals(request.getRequestURI())) {
   48.68 +                        LOG.log(Level.INFO, "Serving HttpResource for {0}", request.getRequestURI());
   48.69 +                        response.setContentType(r.httpType);
   48.70 +                        copyStream(r.httpContent, response.getOutputStream(), null);
   48.71 +                    }
   48.72                  }
   48.73              }
   48.74          }
   48.75 @@ -186,10 +195,26 @@
   48.76                  String id = request.getParameter("request");
   48.77                  String value = request.getParameter("result");
   48.78                  
   48.79 +                
   48.80 +                InvocationContext mi = null;
   48.81 +                int caseNmbr = -1;
   48.82 +                
   48.83                  if (id != null && value != null) {
   48.84                      LOG.log(Level.INFO, "Received result for case {0} = {1}", new Object[]{id, value});
   48.85                      value = decodeURL(value);
   48.86 -                    cases.get(Integer.parseInt(id)).result(value, null);
   48.87 +                    int indx = Integer.parseInt(id);
   48.88 +                    cases.get(indx).result(value, null);
   48.89 +                    if (++indx < cases.size()) {
   48.90 +                        mi = cases.get(indx);
   48.91 +                        LOG.log(Level.INFO, "Re-executing case {0}", indx);
   48.92 +                        caseNmbr = indx;
   48.93 +                    }
   48.94 +                } else {
   48.95 +                    if (!cases.isEmpty()) {
   48.96 +                        LOG.info("Re-executing test cases");
   48.97 +                        mi = cases.get(0);
   48.98 +                        caseNmbr = 0;
   48.99 +                    }
  48.100                  }
  48.101                  
  48.102                  if (prev != null) {
  48.103 @@ -197,7 +222,10 @@
  48.104                      prev = null;
  48.105                  }
  48.106                  
  48.107 -                InvocationContext mi = methods.take();
  48.108 +                if (mi == null) {
  48.109 +                    mi = methods.take();
  48.110 +                    caseNmbr = cnt++;
  48.111 +                }
  48.112                  if (mi == END) {
  48.113                      response.getWriter().write("");
  48.114                      wait.countDown();
  48.115 @@ -206,18 +234,18 @@
  48.116                      return;
  48.117                  }
  48.118                  
  48.119 -                if (mi.httpPath != null) {
  48.120 +                if (!mi.resources.isEmpty()) {
  48.121                      prev = new DynamicResourceHandler(mi);
  48.122                  }
  48.123                  
  48.124                  cases.add(mi);
  48.125                  final String cn = mi.clazz.getName();
  48.126                  final String mn = mi.methodName;
  48.127 -                LOG.log(Level.INFO, "Request for {0} case. Sending {1}.{2}", new Object[]{cnt, cn, mn});
  48.128 +                LOG.log(Level.INFO, "Request for {0} case. Sending {1}.{2}", new Object[]{caseNmbr, cn, mn});
  48.129                  response.getWriter().write("{"
  48.130                      + "className: '" + cn + "', "
  48.131                      + "methodName: '" + mn + "', "
  48.132 -                    + "request: " + cnt
  48.133 +                    + "request: " + caseNmbr
  48.134                  );
  48.135                  if (mi.html != null) {
  48.136                      response.getWriter().write(", html: '");
  48.137 @@ -225,7 +253,6 @@
  48.138                      response.getWriter().write("'");
  48.139                  }
  48.140                  response.getWriter().write("}");
  48.141 -                cnt++;
  48.142              }
  48.143          }, "/data");
  48.144  
  48.145 @@ -427,9 +454,9 @@
  48.146              String r = resource;
  48.147              if (r == null) {
  48.148                  r = request.getHttpHandlerPath();
  48.149 -                if (r.startsWith("/")) {
  48.150 -                    r = r.substring(1);
  48.151 -                }
  48.152 +            }
  48.153 +            if (r.startsWith("/")) {
  48.154 +                r = r.substring(1);
  48.155              }
  48.156              String[] replace = {};
  48.157              if (r.endsWith(".html")) {
  48.158 @@ -460,14 +487,22 @@
  48.159              StringBuilder sb = new StringBuilder();
  48.160              Bck2Brwsr.generate(sb, loader);
  48.161              sb.append(
  48.162 -                "function ldCls(res) {\n"
  48.163 -                + "  var request = new XMLHttpRequest();\n"
  48.164 -                + "  request.open('GET', '/classes/' + res, false);\n"
  48.165 -                + "  request.send();\n"
  48.166 -                + "  var arr = eval('(' + request.responseText + ')');\n"
  48.167 -                + "  return arr;\n"
  48.168 -                + "}\n"
  48.169 -                + "var vm = new bck2brwsr(ldCls);\n"
  48.170 +                  "(function WrapperVM(global) {"
  48.171 +                + "  function ldCls(res) {\n"
  48.172 +                + "    var request = new XMLHttpRequest();\n"
  48.173 +                + "    request.open('GET', '/classes/' + res, false);\n"
  48.174 +                + "    request.send();\n"
  48.175 +                + "    if (request.status !== 200) return null;\n"
  48.176 +                + "    var arr = eval('(' + request.responseText + ')');\n"
  48.177 +                + "    return arr;\n"
  48.178 +                + "  }\n"
  48.179 +                + "  var prevvm = global.bck2brwsr;\n"
  48.180 +                + "  global.bck2brwsr = function() {\n"
  48.181 +                + "    var args = Array.prototype.slice.apply(arguments);\n"
  48.182 +                + "    args.unshift(ldCls);\n"
  48.183 +                + "    return prevvm.apply(null, args);\n"
  48.184 +                + "  };\n"
  48.185 +                + "})(this);\n"
  48.186              );
  48.187              this.bck2brwsr = sb.toString();
  48.188          }
  48.189 @@ -515,6 +550,7 @@
  48.190                  }
  48.191                  w.append("\n]");
  48.192              } catch (IOException ex) {
  48.193 +                response.setStatus(HttpStatus.NOT_FOUND_404);
  48.194                  response.setError();
  48.195                  response.setDetailMessage(ex.getMessage());
  48.196              }
    49.1 --- a/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/InvocationContext.java	Tue Feb 19 15:33:32 2013 +0100
    49.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/InvocationContext.java	Tue Feb 19 15:59:27 2013 +0100
    49.3 @@ -19,6 +19,8 @@
    49.4  
    49.5  import java.io.IOException;
    49.6  import java.io.InputStream;
    49.7 +import java.util.ArrayList;
    49.8 +import java.util.List;
    49.9  import java.util.concurrent.CountDownLatch;
   49.10  import java.util.concurrent.TimeUnit;
   49.11  
   49.12 @@ -34,9 +36,7 @@
   49.13      private String result;
   49.14      private Throwable exception;
   49.15      String html;
   49.16 -    InputStream httpContent;
   49.17 -    String httpType;
   49.18 -    String httpPath;
   49.19 +    final List<Resource> resources = new ArrayList<>();
   49.20  
   49.21      InvocationContext(Launcher launcher, Class<?> clazz, String methodName) {
   49.22          this.launcher = launcher;
   49.23 @@ -55,13 +55,11 @@
   49.24      /** HTTP resource to be available during execution. An invocation may
   49.25       * perform an HTTP query and obtain a resource relative to the page.
   49.26       */
   49.27 -    public void setHttpResource(String relativePath, String mimeType, InputStream content) {
   49.28 +    public void addHttpResource(String relativePath, String mimeType, InputStream content) {
   49.29          if (relativePath == null || mimeType == null || content == null) {
   49.30              throw new NullPointerException();
   49.31          }
   49.32 -        this.httpPath = relativePath;
   49.33 -        this.httpType = mimeType;
   49.34 -        this.httpContent = content;
   49.35 +        resources.add(new Resource(content, mimeType, relativePath));
   49.36      }
   49.37      
   49.38      /** Invokes the associated method. 
   49.39 @@ -97,5 +95,16 @@
   49.40          wait.countDown();
   49.41      }
   49.42  
   49.43 -    
   49.44 +
   49.45 +    static final class Resource {
   49.46 +        final InputStream httpContent;
   49.47 +        final String httpType;
   49.48 +        final String httpPath;
   49.49 +
   49.50 +        Resource(InputStream httpContent, String httpType, String httpPath) {
   49.51 +            this.httpContent = httpContent;
   49.52 +            this.httpType = httpType;
   49.53 +            this.httpPath = httpPath;
   49.54 +        }
   49.55 +    }
   49.56  }
    50.1 --- a/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/impl/Console.java	Tue Feb 19 15:33:32 2013 +0100
    50.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/impl/Console.java	Tue Feb 19 15:59:27 2013 +0100
    50.3 @@ -125,7 +125,7 @@
    50.4                  loadText(u, this, arr);
    50.5                  
    50.6              } catch (Exception ex) {
    50.7 -                log(ex.getMessage());
    50.8 +                log(ex.getClass().getName() + ":" + ex.getMessage());
    50.9              }
   50.10          }
   50.11      }
    51.1 --- a/launcher/src/main/resources/org/apidesign/bck2brwsr/launcher/harness.xhtml	Tue Feb 19 15:33:32 2013 +0100
    51.2 +++ b/launcher/src/main/resources/org/apidesign/bck2brwsr/launcher/harness.xhtml	Tue Feb 19 15:59:27 2013 +0100
    51.3 @@ -24,7 +24,10 @@
    51.4          <title>Bck2Brwsr Harness</title>
    51.5      </head>
    51.6      <body>
    51.7 -        <script src="/vm.js"></script>
    51.8 +        <script src="/bck2brwsr.js"></script>
    51.9 +        <script>
   51.10 +            var vm = bck2brwsr();
   51.11 +        </script>
   51.12          
   51.13          <h1>Bck2Brwsr Execution Harness</h1>
   51.14          
    52.1 --- a/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Bck2BrswrMojo.java	Tue Feb 19 15:33:32 2013 +0100
    52.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.3 @@ -1,122 +0,0 @@
    52.4 -/**
    52.5 - * Back 2 Browser Bytecode Translator
    52.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    52.7 - *
    52.8 - * This program is free software: you can redistribute it and/or modify
    52.9 - * it under the terms of the GNU General Public License as published by
   52.10 - * the Free Software Foundation, version 2 of the License.
   52.11 - *
   52.12 - * This program is distributed in the hope that it will be useful,
   52.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   52.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   52.15 - * GNU General Public License for more details.
   52.16 - *
   52.17 - * You should have received a copy of the GNU General Public License
   52.18 - * along with this program. Look for COPYING file in the top folder.
   52.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
   52.20 - */
   52.21 -package org.apidesign.bck2brwsr.mojo;
   52.22 -
   52.23 -import org.apache.maven.plugin.AbstractMojo;
   52.24 -
   52.25 -import java.io.File;
   52.26 -import java.io.FileWriter;
   52.27 -import java.io.IOException;
   52.28 -import java.net.MalformedURLException;
   52.29 -import java.net.URL;
   52.30 -import java.net.URLClassLoader;
   52.31 -import java.util.ArrayList;
   52.32 -import java.util.Collection;
   52.33 -import java.util.List;
   52.34 -import org.apache.maven.artifact.Artifact;
   52.35 -import org.apache.maven.plugin.MojoExecutionException;
   52.36 -import org.apache.maven.plugins.annotations.LifecyclePhase;
   52.37 -import org.apache.maven.plugins.annotations.Mojo;
   52.38 -import org.apache.maven.plugins.annotations.Parameter;
   52.39 -import org.apache.maven.project.MavenProject;
   52.40 -import org.apidesign.vm4brwsr.Bck2Brwsr;
   52.41 -
   52.42 -/** Compiles classes into JavaScript. */
   52.43 -@Mojo(name="j2js", defaultPhase=LifecyclePhase.PROCESS_CLASSES)
   52.44 -public class Bck2BrswrMojo extends AbstractMojo {
   52.45 -    public Bck2BrswrMojo() {
   52.46 -    }
   52.47 -    /** Root of the class files */
   52.48 -    @Parameter(defaultValue="${project.build.directory}/classes")
   52.49 -    private File classes;
   52.50 -    /** File to generate. Defaults bootjava.js in the first non-empty 
   52.51 -     package under the classes directory */
   52.52 -    @Parameter
   52.53 -    private File javascript;
   52.54 -    
   52.55 -    @Parameter(defaultValue="${project}")
   52.56 -    private MavenProject prj;
   52.57 -    
   52.58 -    
   52.59 -
   52.60 -    @Override
   52.61 -    public void execute() throws MojoExecutionException {
   52.62 -        if (!classes.isDirectory()) {
   52.63 -            throw new MojoExecutionException("Can't find " + classes);
   52.64 -        }
   52.65 -
   52.66 -        if (javascript == null) {
   52.67 -            javascript = new File(findNonEmptyFolder(classes), "bootjava.js");
   52.68 -        }
   52.69 -
   52.70 -        List<String> arr = new ArrayList<String>();
   52.71 -        long newest = collectAllClasses("", classes, arr);
   52.72 -        
   52.73 -        if (javascript.lastModified() > newest) {
   52.74 -            return;
   52.75 -        }
   52.76 -
   52.77 -        try {
   52.78 -            URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts());
   52.79 -            FileWriter w = new FileWriter(javascript);
   52.80 -            Bck2Brwsr.generate(w, url, arr.toArray(new String[0]));
   52.81 -            w.close();
   52.82 -        } catch (IOException ex) {
   52.83 -            throw new MojoExecutionException("Can't compile", ex);
   52.84 -        }
   52.85 -    }
   52.86 -
   52.87 -    private static File findNonEmptyFolder(File dir) throws MojoExecutionException {
   52.88 -        if (!dir.isDirectory()) {
   52.89 -            throw new MojoExecutionException("Not a directory " + dir);
   52.90 -        }
   52.91 -        File[] arr = dir.listFiles();
   52.92 -        if (arr.length == 1 && arr[0].isDirectory()) {
   52.93 -            return findNonEmptyFolder(arr[0]);
   52.94 -        }
   52.95 -        return dir;
   52.96 -    }
   52.97 -
   52.98 -    private static long collectAllClasses(String prefix, File toCheck, List<String> arr) {
   52.99 -        File[] files = toCheck.listFiles();
  52.100 -        if (files != null) {
  52.101 -            long newest = 0L;
  52.102 -            for (File f : files) {
  52.103 -                long lastModified = collectAllClasses(prefix + f.getName() + "/", f, arr);
  52.104 -                if (newest < lastModified) {
  52.105 -                    newest = lastModified;
  52.106 -                }
  52.107 -            }
  52.108 -            return newest;
  52.109 -        } else if (toCheck.getName().endsWith(".class")) {
  52.110 -            arr.add(prefix.substring(0, prefix.length() - 7));
  52.111 -            return toCheck.lastModified();
  52.112 -        } else {
  52.113 -            return 0L;
  52.114 -        }
  52.115 -    }
  52.116 -
  52.117 -    private static URLClassLoader buildClassLoader(File root, Collection<Artifact> deps) throws MalformedURLException {
  52.118 -        List<URL> arr = new ArrayList<URL>();
  52.119 -        arr.add(root.toURI().toURL());
  52.120 -        for (Artifact a : deps) {
  52.121 -            arr.add(a.getFile().toURI().toURL());
  52.122 -        }
  52.123 -        return new URLClassLoader(arr.toArray(new URL[0]), Bck2BrswrMojo.class.getClassLoader());
  52.124 -    }
  52.125 -}
    53.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.2 +++ b/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Java2JavaScript.java	Tue Feb 19 15:59:27 2013 +0100
    53.3 @@ -0,0 +1,122 @@
    53.4 +/**
    53.5 + * Back 2 Browser Bytecode Translator
    53.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    53.7 + *
    53.8 + * This program is free software: you can redistribute it and/or modify
    53.9 + * it under the terms of the GNU General Public License as published by
   53.10 + * the Free Software Foundation, version 2 of the License.
   53.11 + *
   53.12 + * This program is distributed in the hope that it will be useful,
   53.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   53.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   53.15 + * GNU General Public License for more details.
   53.16 + *
   53.17 + * You should have received a copy of the GNU General Public License
   53.18 + * along with this program. Look for COPYING file in the top folder.
   53.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   53.20 + */
   53.21 +package org.apidesign.bck2brwsr.mojo;
   53.22 +
   53.23 +import org.apache.maven.plugin.AbstractMojo;
   53.24 +
   53.25 +import java.io.File;
   53.26 +import java.io.FileWriter;
   53.27 +import java.io.IOException;
   53.28 +import java.net.MalformedURLException;
   53.29 +import java.net.URL;
   53.30 +import java.net.URLClassLoader;
   53.31 +import java.util.ArrayList;
   53.32 +import java.util.Collection;
   53.33 +import java.util.List;
   53.34 +import org.apache.maven.artifact.Artifact;
   53.35 +import org.apache.maven.plugin.MojoExecutionException;
   53.36 +import org.apache.maven.plugins.annotations.LifecyclePhase;
   53.37 +import org.apache.maven.plugins.annotations.Mojo;
   53.38 +import org.apache.maven.plugins.annotations.Parameter;
   53.39 +import org.apache.maven.project.MavenProject;
   53.40 +import org.apidesign.vm4brwsr.Bck2Brwsr;
   53.41 +
   53.42 +/** Compiles classes into JavaScript. */
   53.43 +@Mojo(name="j2js", defaultPhase=LifecyclePhase.PROCESS_CLASSES)
   53.44 +public class Java2JavaScript extends AbstractMojo {
   53.45 +    public Java2JavaScript() {
   53.46 +    }
   53.47 +    /** Root of the class files */
   53.48 +    @Parameter(defaultValue="${project.build.directory}/classes")
   53.49 +    private File classes;
   53.50 +    /** File to generate. Defaults bootjava.js in the first non-empty 
   53.51 +     package under the classes directory */
   53.52 +    @Parameter
   53.53 +    private File javascript;
   53.54 +    
   53.55 +    @Parameter(defaultValue="${project}")
   53.56 +    private MavenProject prj;
   53.57 +    
   53.58 +    
   53.59 +
   53.60 +    @Override
   53.61 +    public void execute() throws MojoExecutionException {
   53.62 +        if (!classes.isDirectory()) {
   53.63 +            throw new MojoExecutionException("Can't find " + classes);
   53.64 +        }
   53.65 +
   53.66 +        if (javascript == null) {
   53.67 +            javascript = new File(findNonEmptyFolder(classes), "bootjava.js");
   53.68 +        }
   53.69 +
   53.70 +        List<String> arr = new ArrayList<String>();
   53.71 +        long newest = collectAllClasses("", classes, arr);
   53.72 +        
   53.73 +        if (javascript.lastModified() > newest) {
   53.74 +            return;
   53.75 +        }
   53.76 +
   53.77 +        try {
   53.78 +            URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts());
   53.79 +            FileWriter w = new FileWriter(javascript);
   53.80 +            Bck2Brwsr.generate(w, url, arr.toArray(new String[0]));
   53.81 +            w.close();
   53.82 +        } catch (IOException ex) {
   53.83 +            throw new MojoExecutionException("Can't compile", ex);
   53.84 +        }
   53.85 +    }
   53.86 +
   53.87 +    private static File findNonEmptyFolder(File dir) throws MojoExecutionException {
   53.88 +        if (!dir.isDirectory()) {
   53.89 +            throw new MojoExecutionException("Not a directory " + dir);
   53.90 +        }
   53.91 +        File[] arr = dir.listFiles();
   53.92 +        if (arr.length == 1 && arr[0].isDirectory()) {
   53.93 +            return findNonEmptyFolder(arr[0]);
   53.94 +        }
   53.95 +        return dir;
   53.96 +    }
   53.97 +
   53.98 +    private static long collectAllClasses(String prefix, File toCheck, List<String> arr) {
   53.99 +        File[] files = toCheck.listFiles();
  53.100 +        if (files != null) {
  53.101 +            long newest = 0L;
  53.102 +            for (File f : files) {
  53.103 +                long lastModified = collectAllClasses(prefix + f.getName() + "/", f, arr);
  53.104 +                if (newest < lastModified) {
  53.105 +                    newest = lastModified;
  53.106 +                }
  53.107 +            }
  53.108 +            return newest;
  53.109 +        } else if (toCheck.getName().endsWith(".class")) {
  53.110 +            arr.add(prefix.substring(0, prefix.length() - 7));
  53.111 +            return toCheck.lastModified();
  53.112 +        } else {
  53.113 +            return 0L;
  53.114 +        }
  53.115 +    }
  53.116 +
  53.117 +    private static URLClassLoader buildClassLoader(File root, Collection<Artifact> deps) throws MalformedURLException {
  53.118 +        List<URL> arr = new ArrayList<URL>();
  53.119 +        arr.add(root.toURI().toURL());
  53.120 +        for (Artifact a : deps) {
  53.121 +            arr.add(a.getFile().toURI().toURL());
  53.122 +        }
  53.123 +        return new URLClassLoader(arr.toArray(new URL[0]), Java2JavaScript.class.getClassLoader());
  53.124 +    }
  53.125 +}
    54.1 --- a/mojo/src/main/resources/META-INF/maven/archetype-metadata.xml	Tue Feb 19 15:33:32 2013 +0100
    54.2 +++ b/mojo/src/main/resources/META-INF/maven/archetype-metadata.xml	Tue Feb 19 15:59:27 2013 +0100
    54.3 @@ -30,6 +30,7 @@
    54.4        <directory>src/main/resources</directory>
    54.5        <includes>
    54.6          <include>**/*.xhtml</include>
    54.7 +        <include>**/*.html</include>
    54.8        </includes>
    54.9      </fileSet>
   54.10      <fileSet filtered="true" packaged="true">
   54.11 @@ -44,5 +45,11 @@
   54.12          <include>nbactions.xml</include>
   54.13        </includes>
   54.14      </fileSet>
   54.15 +    <fileSet filtered="true" packaged="false">
   54.16 +      <directory></directory>
   54.17 +      <includes>
   54.18 +        <include>bck2brwsr-assembly.xml</include>
   54.19 +      </includes>
   54.20 +    </fileSet>
   54.21    </fileSets>    
   54.22  </archetype-descriptor>
   54.23 \ No newline at end of file
    55.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.2 +++ b/mojo/src/main/resources/archetype-resources/bck2brwsr-assembly.xml	Tue Feb 19 15:59:27 2013 +0100
    55.3 @@ -0,0 +1,61 @@
    55.4 +<?xml version="1.0"?>
    55.5 +<!--
    55.6 +
    55.7 +    Back 2 Browser Bytecode Translator
    55.8 +    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    55.9 +
   55.10 +    This program is free software: you can redistribute it and/or modify
   55.11 +    it under the terms of the GNU General Public License as published by
   55.12 +    the Free Software Foundation, version 2 of the License.
   55.13 +
   55.14 +    This program is distributed in the hope that it will be useful,
   55.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   55.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   55.17 +    GNU General Public License for more details.
   55.18 +
   55.19 +    You should have received a copy of the GNU General Public License
   55.20 +    along with this program. Look for COPYING file in the top folder.
   55.21 +    If not, see http://opensource.org/licenses/GPL-2.0.
   55.22 +
   55.23 +-->
   55.24 +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   55.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">
   55.26 +  
   55.27 +  <id>bck2brwsr</id>
   55.28 +  <formats>
   55.29 +      <format>zip</format>
   55.30 +  </formats>
   55.31 +  <baseDirectory>public_html</baseDirectory>
   55.32 +  <dependencySets>
   55.33 +    <dependencySet>
   55.34 +        <useProjectArtifact>false</useProjectArtifact>
   55.35 +        <scope>runtime</scope>
   55.36 +        <outputDirectory>lib</outputDirectory>
   55.37 +        <includes>
   55.38 +            <include>*:jar</include>
   55.39 +            <include>*:rt</include>
   55.40 +        </includes>
   55.41 +    </dependencySet>
   55.42 +    <dependencySet>
   55.43 +        <useProjectArtifact>false</useProjectArtifact>
   55.44 +        <scope>provided</scope>
   55.45 +        <includes>
   55.46 +            <include>*:js</include>
   55.47 +        </includes>
   55.48 +        <unpack>true</unpack>
   55.49 +        <outputDirectory>/</outputDirectory>
   55.50 +    </dependencySet>
   55.51 +  </dependencySets> 
   55.52 +  <files>
   55.53 +    <file>
   55.54 +      <source>${project.build.directory}/${project.build.finalName}.jar</source>
   55.55 +      <outputDirectory>/</outputDirectory>
   55.56 +    </file>
   55.57 +    <file>
   55.58 +      <source>${project.build.directory}/classes/${package.replace('.','/')}/index.html</source>
   55.59 +      <outputDirectory>/</outputDirectory>
   55.60 +      <destName>index.html</destName>
   55.61 +    </file>
   55.62 +  </files>
   55.63 +
   55.64 +</assembly>
   55.65 \ No newline at end of file
    56.1 --- a/mojo/src/main/resources/archetype-resources/pom.xml	Tue Feb 19 15:33:32 2013 +0100
    56.2 +++ b/mojo/src/main/resources/archetype-resources/pom.xml	Tue Feb 19 15:59:27 2013 +0100
    56.3 @@ -53,7 +53,7 @@
    56.4                      </execution>
    56.5                  </executions>
    56.6                  <configuration>
    56.7 -                    <startpage>${package.replace('.','/')}/index.xhtml</startpage>
    56.8 +                    <startpage>${package.replace('.','/')}/index.html</startpage>
    56.9                  </configuration>
   56.10              </plugin>
   56.11           <plugin>
   56.12 @@ -65,14 +65,46 @@
   56.13                 <target>1.7</target>
   56.14              </configuration>
   56.15           </plugin>
   56.16 +         <plugin>
   56.17 +             <groupId>org.apache.maven.plugins</groupId>
   56.18 +             <artifactId>maven-jar-plugin</artifactId>
   56.19 +             <version>2.4</version>
   56.20 +             <configuration>
   56.21 +                 <archive>
   56.22 +                     <manifest>
   56.23 +                         <addClasspath>true</addClasspath>
   56.24 +                         <classpathPrefix>lib/</classpathPrefix>
   56.25 +                     </manifest>
   56.26 +                 </archive>
   56.27 +             </configuration>
   56.28 +         </plugin>
   56.29 +         <plugin>
   56.30 +             <artifactId>maven-assembly-plugin</artifactId>
   56.31 +             <version>2.4</version>
   56.32 +             <executions>
   56.33 +                 <execution>
   56.34 +                     <id>distro-assembly</id>
   56.35 +                     <phase>package</phase>
   56.36 +                     <goals>
   56.37 +                         <goal>single</goal>
   56.38 +                     </goals>
   56.39 +                     <configuration>
   56.40 +                         <descriptors>
   56.41 +                             <descriptor>bck2brwsr-assembly.xml</descriptor>
   56.42 +                         </descriptors>
   56.43 +                     </configuration>
   56.44 +                 </execution>
   56.45 +             </executions>                
   56.46 +         </plugin>      
   56.47        </plugins>
   56.48    </build>
   56.49  
   56.50    <dependencies>
   56.51      <dependency>
   56.52        <groupId>org.apidesign.bck2brwsr</groupId>
   56.53 -      <artifactId>emul.mini</artifactId>
   56.54 +      <artifactId>emul</artifactId>
   56.55        <version>0.3-SNAPSHOT</version>
   56.56 +      <classifier>rt</classifier>
   56.57      </dependency>
   56.58      <dependency>
   56.59        <groupId>org.apidesign.bck2brwsr</groupId>
   56.60 @@ -87,6 +119,14 @@
   56.61      </dependency>
   56.62      <dependency>
   56.63        <groupId>org.apidesign.bck2brwsr</groupId>
   56.64 +      <artifactId>vm4brwsr</artifactId>
   56.65 +      <classifier>js</classifier>
   56.66 +      <type>zip</type>
   56.67 +      <version>0.3-SNAPSHOT</version>
   56.68 +      <scope>provided</scope>
   56.69 +    </dependency>
   56.70 +    <dependency>
   56.71 +      <groupId>org.apidesign.bck2brwsr</groupId>
   56.72        <artifactId>vmtest</artifactId>
   56.73        <version>0.3-SNAPSHOT</version>
   56.74        <scope>test</scope>
    57.1 --- a/mojo/src/main/resources/archetype-resources/src/main/java/App.java	Tue Feb 19 15:33:32 2013 +0100
    57.2 +++ b/mojo/src/main/resources/archetype-resources/src/main/java/App.java	Tue Feb 19 15:59:27 2013 +0100
    57.3 @@ -9,7 +9,7 @@
    57.4  /** Edit the index.xhtml file. Use 'id' to name certain HTML elements.
    57.5   * Use this class to define behavior of the elements.
    57.6   */
    57.7 -@Page(xhtml="index.xhtml", className="Index", properties={
    57.8 +@Page(xhtml="index.html", className="Index", properties={
    57.9      @Property(name="name", type=String.class)
   57.10  })
   57.11  public class App {
    58.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.2 +++ b/mojo/src/main/resources/archetype-resources/src/main/resources/index.html	Tue Feb 19 15:59:27 2013 +0100
    58.3 @@ -0,0 +1,22 @@
    58.4 +<?xml version="1.0" encoding="UTF-8"?>
    58.5 +<!DOCTYPE html>
    58.6 +<html xmlns="http://www.w3.org/1999/xhtml">
    58.7 +    <head>
    58.8 +        <title>Bck2Brwsr's Hello World</title>
    58.9 +    </head>
   58.10 +    <body>
   58.11 +        <h1 data-bind="text: helloMessage">Loading Bck2Brwsr's Hello World...</h1>
   58.12 +        Your name: <input id='input' data-bind="value: name, valueUpdate: 'afterkeydown'"></input>
   58.13 +        <button id="hello">Say Hello!</button>
   58.14 +        <p>
   58.15 +            <canvas id="canvas" width="300" height="50">
   58.16 +            </canvas>
   58.17 +        </p>
   58.18 +
   58.19 +        <script src="bck2brwsr.js"></script>
   58.20 +        <script type="text/javascript">
   58.21 +            var vm = bck2brwsr('${artifactId}-${version}.jar');
   58.22 +            vm.loadClass('${package}.App');
   58.23 +        </script>
   58.24 +    </body>
   58.25 +</html>
    59.1 --- a/mojo/src/main/resources/archetype-resources/src/main/resources/index.xhtml	Tue Feb 19 15:33:32 2013 +0100
    59.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    59.3 @@ -1,22 +0,0 @@
    59.4 -<?xml version="1.0" encoding="UTF-8"?>
    59.5 -<!DOCTYPE html>
    59.6 -<html xmlns="http://www.w3.org/1999/xhtml">
    59.7 -    <head>
    59.8 -        <title>Bck2Brwsr's Hello World</title>
    59.9 -    </head>
   59.10 -    <body>
   59.11 -        <h1 data-bind="text: helloMessage">Loading Bck2Brwsr's Hello World...</h1>
   59.12 -        Your name: <input id='input' data-bind="value: name, valueUpdate: 'afterkeydown'"></input>
   59.13 -        <button id="hello">Say Hello!</button>
   59.14 -        <p>
   59.15 -            <canvas id="canvas" width="300" height="50">
   59.16 -            </canvas>
   59.17 -        </p>
   59.18 -
   59.19 -        <script src="/bck2brwsr.js"></script>
   59.20 -        <script src="/vm.js"></script>
   59.21 -        <script type="text/javascript">
   59.22 -            vm.loadClass('${package}.App');
   59.23 -        </script>
   59.24 -    </body>
   59.25 -</html>
    60.1 --- a/pom.xml	Tue Feb 19 15:33:32 2013 +0100
    60.2 +++ b/pom.xml	Tue Feb 19 15:59:27 2013 +0100
    60.3 @@ -93,6 +93,15 @@
    60.4                </configuration>
    60.5            </plugin>
    60.6        </plugins>
    60.7 +      <pluginManagement>
    60.8 +          <plugins>
    60.9 +              <plugin>
   60.10 +                <groupId>org.apache.maven.plugins</groupId>
   60.11 +                <artifactId>maven-surefire-plugin</artifactId>
   60.12 +                <version>2.13</version>
   60.13 +              </plugin>
   60.14 +          </plugins>
   60.15 +      </pluginManagement>
   60.16    </build>
   60.17    <dependencyManagement>
   60.18        <dependencies>
    61.1 --- a/vm/pom.xml	Tue Feb 19 15:33:32 2013 +0100
    61.2 +++ b/vm/pom.xml	Tue Feb 19 15:59:27 2013 +0100
    61.3 @@ -12,7 +12,7 @@
    61.4    <version>0.3-SNAPSHOT</version>
    61.5    <packaging>jar</packaging>
    61.6  
    61.7 -  <name>Java VM for Browser</name>
    61.8 +  <name>Virtual Machine for Browser</name>
    61.9    <url>http://bck2brwsr.apidesign.org</url>
   61.10  
   61.11    <properties>
   61.12 @@ -68,6 +68,45 @@
   61.13                 <target>1.7</target>
   61.14              </configuration>
   61.15           </plugin>
   61.16 +         <plugin>
   61.17 +             <groupId>org.codehaus.mojo</groupId>
   61.18 +             <artifactId>exec-maven-plugin</artifactId>
   61.19 +             <version>1.2.1</version>
   61.20 +             <executions>
   61.21 +                 <execution>
   61.22 +                     <id>generate-js</id>
   61.23 +                     <phase>process-classes</phase>
   61.24 +                     <goals>
   61.25 +                         <goal>java</goal>
   61.26 +                     </goals>
   61.27 +                 </execution>
   61.28 +             </executions>
   61.29 +             <configuration>
   61.30 +                 <mainClass>org.apidesign.vm4brwsr.Main</mainClass>
   61.31 +                 <arguments>
   61.32 +                     <argument>${project.build.directory}/bck2brwsr.js</argument>
   61.33 +                     <argument>org/apidesign/vm4brwsr/Bck2Brwsr</argument>
   61.34 +                 </arguments>
   61.35 +             </configuration>
   61.36 +         </plugin>
   61.37 +         <plugin>
   61.38 +             <artifactId>maven-assembly-plugin</artifactId>
   61.39 +             <version>2.4</version>
   61.40 +             <executions>
   61.41 +                 <execution>
   61.42 +                     <id>js</id>
   61.43 +                     <phase>package</phase>
   61.44 +                     <goals>
   61.45 +                         <goal>single</goal>
   61.46 +                     </goals>
   61.47 +                     <configuration>
   61.48 +                         <descriptors>
   61.49 +                             <descriptor>src/main/assembly/bck2brwsr.xml</descriptor>
   61.50 +                         </descriptors>
   61.51 +                     </configuration>
   61.52 +                 </execution>
   61.53 +             </executions>                
   61.54 +         </plugin>      
   61.55        </plugins>
   61.56    </build>
   61.57    <dependencies>
   61.58 @@ -85,19 +124,20 @@
   61.59      <dependency>
   61.60        <groupId>${project.groupId}</groupId>
   61.61        <artifactId>core</artifactId>
   61.62 -      <version>0.3-SNAPSHOT</version>
   61.63 +      <version>${project.version}</version>
   61.64        <type>jar</type>
   61.65      </dependency>
   61.66      <dependency>
   61.67        <groupId>${project.groupId}</groupId>
   61.68        <artifactId>emul.mini</artifactId>
   61.69 -      <version>0.3-SNAPSHOT</version>
   61.70 -      <scope>test</scope>
   61.71 +      <version>${project.version}</version>
   61.72 +      <scope>compile</scope>
   61.73      </dependency>
   61.74      <dependency>
   61.75        <groupId>${project.groupId}</groupId>
   61.76        <artifactId>javap</artifactId>
   61.77 -      <version>0.3-SNAPSHOT</version>
   61.78 +      <version>${project.version}</version>
   61.79 +      <scope>compile</scope>
   61.80      </dependency>
   61.81    </dependencies>
   61.82  </project>
    62.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.2 +++ b/vm/src/main/assembly/bck2brwsr.xml	Tue Feb 19 15:59:27 2013 +0100
    62.3 @@ -0,0 +1,36 @@
    62.4 +<?xml version="1.0"?>
    62.5 +<!--
    62.6 +
    62.7 +    Back 2 Browser Bytecode Translator
    62.8 +    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    62.9 +
   62.10 +    This program is free software: you can redistribute it and/or modify
   62.11 +    it under the terms of the GNU General Public License as published by
   62.12 +    the Free Software Foundation, version 2 of the License.
   62.13 +
   62.14 +    This program is distributed in the hope that it will be useful,
   62.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   62.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   62.17 +    GNU General Public License for more details.
   62.18 +
   62.19 +    You should have received a copy of the GNU General Public License
   62.20 +    along with this program. Look for COPYING file in the top folder.
   62.21 +    If not, see http://opensource.org/licenses/GPL-2.0.
   62.22 +
   62.23 +-->
   62.24 +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   62.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">
   62.26 +  
   62.27 +  <id>js</id>
   62.28 +  <formats>
   62.29 +      <format>zip</format>
   62.30 +  </formats>
   62.31 +  <baseDirectory>/</baseDirectory>
   62.32 +  <files>
   62.33 +    <file>
   62.34 +      <source>${project.build.directory}/bck2brwsr.js</source>
   62.35 +      <outputDirectory>/</outputDirectory>
   62.36 +    </file>
   62.37 +  </files>
   62.38 +
   62.39 +</assembly>
   62.40 \ No newline at end of file
    63.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java	Tue Feb 19 15:33:32 2013 +0100
    63.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java	Tue Feb 19 15:59:27 2013 +0100
    63.3 @@ -40,6 +40,16 @@
    63.4   * In this scenario, when a request for an unknown class is made, the loader
    63.5   * function is asked for its byte code and the system dynamically transforms
    63.6   * it to JavaScript.
    63.7 + * <p>
    63.8 + * Instead of a loader function, one can also provide a URL to a JAR file.
    63.9 + * The <code>bck2brwsr</code> system will do its best to download the file
   63.10 + * and provide loader function for it automatically.
   63.11 + * <p>
   63.12 + * One can provide as many loader functions and JAR URL references as necessary.
   63.13 + * Then the initialization code would look like:<pre>
   63.14 + * var vm = bck2brwsr(url1, url2, fnctn1, url3, functn2);
   63.15 + * </pre>
   63.16 + * The provided URLs and loader functions will be consulted one by one.
   63.17   *
   63.18   * @author Jaroslav Tulach <jtulach@netbeans.org>
   63.19   */
    64.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Tue Feb 19 15:33:32 2013 +0100
    64.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Tue Feb 19 15:59:27 2013 +0100
    64.3 @@ -113,7 +113,7 @@
    64.4          final String className = className(jc);
    64.5          out.append("\n\n").append(assignClass(className));
    64.6          out.append("function CLS() {");
    64.7 -        out.append("\n  if (!CLS.prototype.$instOf_").append(className).append(") {");
    64.8 +        out.append("\n  if (!CLS.$class) {");
    64.9          if (proto == null) {
   64.10              String sc = jc.getSuperClassName(); // with _
   64.11              out.append("\n    var pp = ").
   64.12 @@ -175,12 +175,14 @@
   64.13                  out.append("\n    };");
   64.14              }
   64.15              out.append(prefix).append(mn).append(".access = " + m.getAccess()).append(";");
   64.16 +            out.append(prefix).append(mn).append(".cls = CLS;");
   64.17          }
   64.18          out.append("\n    c.constructor = CLS;");
   64.19          out.append("\n    c.$instOf_").append(className).append(" = true;");
   64.20          for (String superInterface : jc.getSuperInterfaces()) {
   64.21              out.append("\n    c.$instOf_").append(superInterface.replace('/', '_')).append(" = true;");
   64.22          }
   64.23 +        out.append("\n    CLS.$class = 'temp';");
   64.24          out.append("\n    CLS.$class = ");
   64.25          out.append(accessClass("java_lang_Class(true);"));
   64.26          out.append("\n    CLS.$class.jvmName = '").append(jc.getClassName()).append("';");
   64.27 @@ -1620,7 +1622,7 @@
   64.28          final String jvmType = "Lorg/apidesign/bck2brwsr/core/JavaScriptBody;";
   64.29          class P extends AnnotationParser {
   64.30              public P() {
   64.31 -                super(false);
   64.32 +                super(false, true);
   64.33              }
   64.34              
   64.35              int cnt;
   64.36 @@ -1676,7 +1678,7 @@
   64.37          final String[] values = new String[attrNames.length];
   64.38          final boolean[] found = { false };
   64.39          final String jvmType = "L" + className.replace('.', '/') + ";";
   64.40 -        AnnotationParser ap = new AnnotationParser(false) {
   64.41 +        AnnotationParser ap = new AnnotationParser(false, true) {
   64.42              @Override
   64.43              protected void visitAttr(String type, String attr, String at, String value) {
   64.44                  if (type.equals(jvmType)) {
   64.45 @@ -1713,35 +1715,71 @@
   64.46          return " = null;";
   64.47      }
   64.48  
   64.49 -    private static void generateAnno(ClassData cd, final Appendable out, byte[] data) throws IOException {
   64.50 -        AnnotationParser ap = new AnnotationParser(true) {
   64.51 -            int anno;
   64.52 -            int cnt;
   64.53 +    private void generateAnno(ClassData cd, final Appendable out, byte[] data) throws IOException {
   64.54 +        AnnotationParser ap = new AnnotationParser(true, false) {
   64.55 +            int[] cnt = new int[32];
   64.56 +            int depth;
   64.57              
   64.58              @Override
   64.59 -            protected void visitAnnotationStart(String type) throws IOException {
   64.60 -                if (anno++ > 0) {
   64.61 +            protected void visitAnnotationStart(String attrType, boolean top) throws IOException {
   64.62 +                final String slashType = attrType.substring(1, attrType.length() - 1);
   64.63 +                requireReference(slashType);
   64.64 +                
   64.65 +                if (cnt[depth]++ > 0) {
   64.66                      out.append(",");
   64.67                  }
   64.68 -                out.append('"').append(type).append("\" : {\n");
   64.69 -                cnt = 0;
   64.70 +                if (top) {
   64.71 +                    out.append('"').append(attrType).append("\" : ");
   64.72 +                }
   64.73 +                out.append("{\n");
   64.74 +                cnt[++depth] = 0;
   64.75              }
   64.76  
   64.77              @Override
   64.78 -            protected void visitAnnotationEnd(String type) throws IOException {
   64.79 +            protected void visitAnnotationEnd(String type, boolean top) throws IOException {
   64.80                  out.append("\n}\n");
   64.81 +                depth--;
   64.82 +            }
   64.83 +
   64.84 +            @Override
   64.85 +            protected void visitValueStart(String attrName, char type) throws IOException {
   64.86 +                if (cnt[depth]++ > 0) {
   64.87 +                    out.append(",\n");
   64.88 +                }
   64.89 +                cnt[++depth] = 0;
   64.90 +                if (attrName != null) {
   64.91 +                    out.append(attrName).append(" : ");
   64.92 +                }
   64.93 +                if (type == '[') {
   64.94 +                    out.append("[");
   64.95 +                }
   64.96 +            }
   64.97 +
   64.98 +            @Override
   64.99 +            protected void visitValueEnd(String attrName, char type) throws IOException {
  64.100 +                if (type == '[') {
  64.101 +                    out.append("]");
  64.102 +                }
  64.103 +                depth--;
  64.104              }
  64.105              
  64.106              @Override
  64.107              protected void visitAttr(String type, String attr, String attrType, String value) 
  64.108              throws IOException {
  64.109 -                if (attr == null) {
  64.110 +                if (attr == null && value == null) {
  64.111                      return;
  64.112                  }
  64.113 -                if (cnt++ > 0) {
  64.114 -                    out.append(",\n");
  64.115 -                }
  64.116 -                out.append(attr).append("__").append(attrType).append(" : ").append(value);
  64.117 +                out.append(value);
  64.118 +            }
  64.119 +
  64.120 +            @Override
  64.121 +            protected void visitEnumAttr(String type, String attr, String attrType, String value) 
  64.122 +            throws IOException {
  64.123 +                final String slashType = attrType.substring(1, attrType.length() - 1);
  64.124 +                requireReference(slashType);
  64.125 +                
  64.126 +                out.append(accessClass(slashType.replace('/', '_')))
  64.127 +                   .append("(false).constructor.").append(value);
  64.128              }
  64.129          };
  64.130          ap.parse(data, cd);
    65.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    65.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ParseMan.java	Tue Feb 19 15:59:27 2013 +0100
    65.3 @@ -0,0 +1,57 @@
    65.4 +/**
    65.5 + * Back 2 Browser Bytecode Translator
    65.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    65.7 + *
    65.8 + * This program is free software: you can redistribute it and/or modify
    65.9 + * it under the terms of the GNU General Public License as published by
   65.10 + * the Free Software Foundation, version 2 of the License.
   65.11 + *
   65.12 + * This program is distributed in the hope that it will be useful,
   65.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   65.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   65.15 + * GNU General Public License for more details.
   65.16 + *
   65.17 + * You should have received a copy of the GNU General Public License
   65.18 + * along with this program. Look for COPYING file in the top folder.
   65.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   65.20 + */
   65.21 +package org.apidesign.vm4brwsr;
   65.22 +
   65.23 +import java.io.IOException;
   65.24 +import java.io.InputStream;
   65.25 +import org.apidesign.bck2brwsr.emul.lang.ManifestInputStream;
   65.26 +
   65.27 +/**
   65.28 + *
   65.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   65.30 + */
   65.31 +final class ParseMan extends ManifestInputStream {
   65.32 +    private String cp;
   65.33 +    private String mc;
   65.34 +
   65.35 +    public ParseMan(InputStream is) throws IOException {
   65.36 +        super(is);
   65.37 +        readAttributes(new byte[512]);
   65.38 +    }
   65.39 +
   65.40 +    @Override
   65.41 +    protected String putValue(String key, String value) {
   65.42 +        if ("Class-Path".equals(key)) {
   65.43 +            cp = value;
   65.44 +        }
   65.45 +        if ("Main-Class".equals(key)) {
   65.46 +            mc = value;
   65.47 +        }
   65.48 +        return null;
   65.49 +    }
   65.50 +    
   65.51 +    String getMainClass() {
   65.52 +        return mc;
   65.53 +    }
   65.54 +
   65.55 +    @Override
   65.56 +    public String toString() {
   65.57 +        return cp;
   65.58 +    }
   65.59 +    
   65.60 +}
    66.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/VM.java	Tue Feb 19 15:33:32 2013 +0100
    66.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/VM.java	Tue Feb 19 15:59:27 2013 +0100
    66.3 @@ -31,8 +31,12 @@
    66.4      
    66.5      static {
    66.6          // uses VMLazy to load dynamic classes
    66.7 -        VMLazy.init();
    66.8 -        Zips.init();
    66.9 +        boolean assertsOn = false;
   66.10 +        assert assertsOn = true;
   66.11 +        if (assertsOn) {
   66.12 +            VMLazy.init();
   66.13 +            Zips.init();
   66.14 +        }
   66.15      }
   66.16  
   66.17      @Override
   66.18 @@ -44,8 +48,7 @@
   66.19          new VM(out).doCompile(l, names);
   66.20      }
   66.21      protected void doCompile(Bck2Brwsr.Resources l, StringArray names) throws IOException {
   66.22 -        out.append("(function VM(global) {");
   66.23 -        out.append("\n  var vm = {};");
   66.24 +        out.append("(function VM(global) {var fillInVMSkeleton = function(vm) {");
   66.25          StringArray processed = new StringArray();
   66.26          StringArray initCode = new StringArray();
   66.27          for (String baseClass : names.toArray()) {
   66.28 @@ -113,31 +116,31 @@
   66.29              }
   66.30          }
   66.31          out.append(
   66.32 -              "  global.bck2brwsr = function() {\n"
   66.33 -            + "    var args = arguments;\n"
   66.34 +              "  return vm;\n"
   66.35 +            + "  };\n"
   66.36 +            + "  global.bck2brwsr = function() {\n"
   66.37 +            + "    var args = Array.prototype.slice.apply(arguments);\n"
   66.38 +            + "    var vm = fillInVMSkeleton({});\n"
   66.39              + "    var loader = {};\n"
   66.40              + "    loader.vm = vm;\n"
   66.41 -            + "    if (args.length == 1 && typeof args[0] !== 'function') {;\n"
   66.42 -            + "      var classpath = args[0];\n"
   66.43 -            + "      args[0] = function(name) {\n"
   66.44 -            + "        return vm.org_apidesign_vm4brwsr_Zips(false).loadFromCp___3B_3Ljava_lang_Object_2Ljava_lang_String_2(classpath, name);\n"
   66.45 -            + "      };\n"
   66.46 -            + "    };\n"
   66.47              + "    loader.loadClass = function(name) {\n"
   66.48              + "      var attr = name.replace__Ljava_lang_String_2CC('.','_');\n"
   66.49              + "      var fn = vm[attr];\n"
   66.50              + "      if (fn) return fn(false);\n"
   66.51 -            + "      if (!args[0]) throw 'bck2brwsr initialized without loader function, cannot load ' + name;\n"
   66.52              + "      return vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
   66.53              + "        load__Ljava_lang_Object_2Ljava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, name, args);\n"
   66.54              + "    }\n"
   66.55 -            + "    if (args[0]) {\n"
   66.56 -            + "      vm.loadClass = loader.loadClass;\n"
   66.57 -            + "      vm.loadBytes = function(name) {\n"
   66.58 -            + "        if (!args[0]) throw 'bck2brwsr initialized without loader function, cannot load ' + name;\n"
   66.59 -            + "        return args[0](name);\n"
   66.60 -            + "      }\n"
   66.61 +            + "    if (vm.loadClass) {\n"
   66.62 +            + "      throw 'Cannot initialize the bck2brwsr VM twice!';\n"
   66.63              + "    }\n"
   66.64 +            + "    vm.loadClass = loader.loadClass;\n"
   66.65 +            + "    vm.loadBytes = function(name) {\n"
   66.66 +            + "      return vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
   66.67 +            + "        loadBytes___3BLjava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, name, args);\n"
   66.68 +            + "    }\n"
   66.69 +            + "    vm.java_lang_reflect_Array(false);\n"
   66.70 +            + "    vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
   66.71 +            + "      loadBytes___3BLjava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, null, args);\n"
   66.72              + "    return loader;\n"
   66.73              + "  };\n");
   66.74          out.append("}(this));");
    67.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java	Tue Feb 19 15:33:32 2013 +0100
    67.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java	Tue Feb 19 15:59:27 2013 +0100
    67.3 @@ -20,6 +20,7 @@
    67.4  import java.io.ByteArrayInputStream;
    67.5  import java.io.IOException;
    67.6  import java.io.InputStream;
    67.7 +import java.lang.reflect.Array;
    67.8  import org.apidesign.bck2brwsr.core.JavaScriptBody;
    67.9  
   67.10  /**
   67.11 @@ -38,23 +39,19 @@
   67.12      static void init() {
   67.13      }
   67.14      
   67.15 -    @JavaScriptBody(args={"l", "res", "args" }, body = ""
   67.16 -        + "\ntry {"
   67.17 -        + "\n  return args[0](res.toString());"
   67.18 -        + "\n} catch (x) {"
   67.19 -        + "\n  throw Object.getOwnPropertyNames(l.vm).toString() + x.toString();"
   67.20 -        + "\n}")
   67.21 -    private static native byte[] read(Object l, String res, Object[] args);
   67.22 -    
   67.23      static Object load(Object loader, String name, Object[] arguments) 
   67.24      throws IOException, ClassNotFoundException {
   67.25          return new VMLazy(loader, arguments).load(name, false);
   67.26      }
   67.27      
   67.28 +    static byte[] loadBytes(Object loader, String name, Object[] arguments) throws Exception {
   67.29 +        return Zips.loadFromCp(arguments, name);
   67.30 +    }
   67.31 +    
   67.32      private Object load(String name, boolean instance)
   67.33      throws IOException, ClassNotFoundException {
   67.34          String res = name.replace('.', '/') + ".class";
   67.35 -        byte[] arr = read(loader, res, args);
   67.36 +        byte[] arr = Zips.loadFromCp(args, res);
   67.37          if (arr == null) {
   67.38              throw new ClassNotFoundException(name);
   67.39          }
    68.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/Zips.java	Tue Feb 19 15:33:32 2013 +0100
    68.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/Zips.java	Tue Feb 19 15:59:27 2013 +0100
    68.3 @@ -17,81 +17,171 @@
    68.4   */
    68.5  package org.apidesign.vm4brwsr;
    68.6  
    68.7 +import java.io.ByteArrayInputStream;
    68.8  import java.io.IOException;
    68.9 +import java.io.InputStream;
   68.10  import java.net.URL;
   68.11 -import java.util.zip.ZipEntry;
   68.12 -import java.util.zip.ZipInputStream;
   68.13  import org.apidesign.bck2brwsr.core.JavaScriptBody;
   68.14 +import org.apidesign.bck2brwsr.emul.zip.FastJar;
   68.15  
   68.16  /** Conversion from classpath to load function.
   68.17   *
   68.18   * @author Jaroslav Tulach <jtulach@netbeans.org>
   68.19   */
   68.20  final class Zips {
   68.21 -    private Zips() {
   68.22 +    private final FastJar fj;
   68.23 +
   68.24 +    private Zips(String path, byte[] zipData) throws IOException {
   68.25 +        long bef = timeNow();
   68.26 +        fj = new FastJar(zipData);
   68.27 +        for (FastJar.Entry e : fj.list()) {
   68.28 +            putRes(e.name, e);
   68.29 +        }
   68.30 +        log("Iterating thru " + path + " took " + (timeNow() - bef) + "ms");
   68.31      }
   68.32      
   68.33      public static void init() {
   68.34      }
   68.35 +    @JavaScriptBody(args = { "arr" }, body = "return arr.length;")
   68.36 +    private static native int length(Object arr);
   68.37 +    @JavaScriptBody(args = { "arr", "index" }, body = "return arr[index];")
   68.38 +    private static native Object at(Object arr, int index);
   68.39 +    @JavaScriptBody(args = { "arr", "index", "value" }, body = "arr[index] = value; return value;")
   68.40 +    private static native Object set(Object arr, int index, Object value);
   68.41      
   68.42 -    public static byte[] loadFromCp(Object[] classpath, String res) {
   68.43 -        for (int i = 0; i < classpath.length; i++) {
   68.44 -            Object c = classpath[i];
   68.45 +    public static byte[] loadFromCp(Object classpath, String res) 
   68.46 +    throws IOException, ClassNotFoundException {
   68.47 +        for (int i = 0; i < length(classpath); i++) {
   68.48 +            Object c = at(classpath, i);
   68.49              if (c instanceof String) {
   68.50                  try {
   68.51 -                    c = classpath[i] = toZip((String)c);
   68.52 +                    String url = (String)c;
   68.53 +                    final Zips z = toZip(url);
   68.54 +                    c = set(classpath, i, z);
   68.55 +                    final byte[] man = z.findRes("META-INF/MANIFEST.MF");
   68.56 +                    if (man != null) {
   68.57 +                        String mainClass = processClassPathAttr(man, url, classpath);
   68.58 +//                        if (mainClass != null) {
   68.59 +//                            Class.forName(mainClass);
   68.60 +//                        }
   68.61 +                    }
   68.62                  } catch (IOException ex) {
   68.63 -                    classpath[i] = ex;
   68.64 +                    set(classpath, i, ex);
   68.65 +                    log("Cannot load " + c + " - " + ex.getClass().getName() + ":" + ex.getMessage());
   68.66                  }
   68.67              }
   68.68 -            if (c instanceof Zips) {
   68.69 -                Object checkRes = ((Zips)c).findRes(res);
   68.70 -                if (checkRes instanceof byte[]) {
   68.71 -                    return (byte[])checkRes;
   68.72 +            if (res != null) {
   68.73 +                byte[] checkRes;
   68.74 +                if (c instanceof Zips) {
   68.75 +                    checkRes = ((Zips)c).findRes(res);
   68.76 +                } else {
   68.77 +                    checkRes = callFunction(c, res);
   68.78 +                }
   68.79 +                if (checkRes != null) {
   68.80 +                    return checkRes;
   68.81                  }
   68.82              }
   68.83          }
   68.84          return null;
   68.85      }
   68.86 +    
   68.87 +    @JavaScriptBody(args = { "fn", "res" }, body = 
   68.88 +        "if (typeof fn === 'function') return fn(res);\n"
   68.89 +      + "return null;"
   68.90 +    )
   68.91 +    private static native byte[] callFunction(Object fn, String res);
   68.92 +    
   68.93 +    @JavaScriptBody(args = { "msg" }, body = "console.log(msg.toString());")
   68.94 +    private static native void log(String msg);
   68.95 +
   68.96 +    private byte[] findRes(String res) throws IOException {
   68.97 +        Object arr = findResImpl(res);
   68.98 +        if (arr instanceof FastJar.Entry) {
   68.99 +            long bef = timeNow();
  68.100 +            InputStream zip = fj.getInputStream((FastJar.Entry)arr);
  68.101 +            arr = readFully(new byte[512], zip);
  68.102 +            putRes(res, arr);
  68.103 +            log("Reading " + res + " took " + (timeNow() - bef) + "ms");
  68.104 +        }
  68.105 +        return (byte[]) arr;
  68.106 +    }
  68.107  
  68.108      @JavaScriptBody(args = { "res" }, body = "var r = this[res]; return r ? r : null;")
  68.109 -    private native byte[] findRes(String res);
  68.110 +    private native Object findResImpl(String res);
  68.111  
  68.112      @JavaScriptBody(args = { "res", "arr" }, body = "this[res] = arr;")
  68.113 -    private native void putRes(String res, byte[] arr);
  68.114 +    private native void putRes(String res, Object arr);
  68.115      
  68.116      private static Zips toZip(String path) throws IOException {
  68.117          URL u = new URL(path);
  68.118 -        ZipInputStream zip = new ZipInputStream(u.openStream());
  68.119 -        Zips z = new Zips();
  68.120 -        for (;;) {
  68.121 -            ZipEntry entry = zip.getNextEntry();
  68.122 -            if (entry == null) {
  68.123 -                break;
  68.124 -            }
  68.125 -            byte[] arr = new byte[4096];
  68.126 -            int offset = 0;
  68.127 -            for (;;) {
  68.128 -                int len = zip.read(arr, offset, arr.length - offset);
  68.129 -                if (len == -1) {
  68.130 -                    break;
  68.131 -                }
  68.132 -                offset += len;
  68.133 -                if (offset == arr.length) {
  68.134 -                    enlargeArray(arr, arr.length + 4096);
  68.135 +        byte[] zipData = (byte[]) u.getContent(new Class[] { byte[].class });
  68.136 +        return new Zips(path, zipData);
  68.137 +    }
  68.138 +
  68.139 +    private static String processClassPathAttr(final byte[] man, String url, Object classpath) throws IOException {
  68.140 +        try (ParseMan is = new ParseMan(new ByteArrayInputStream(man))) {
  68.141 +            String cp = is.toString();
  68.142 +            if (cp != null) {
  68.143 +                cp = cp.trim();
  68.144 +                for (int p = 0; p < cp.length();) {
  68.145 +                    int n = cp.indexOf(' ', p);
  68.146 +                    if (n == -1) {
  68.147 +                        n = cp.length();
  68.148 +                    }
  68.149 +                    String el = cp.substring(p, n);
  68.150 +                    URL u = new URL(new URL(url), el);
  68.151 +                    classpath = addToArray(classpath, u.toString());
  68.152 +                    p = n + 1;
  68.153                  }
  68.154              }
  68.155 -            sliceArray(arr, offset);
  68.156 -            z.putRes(entry.getName(), arr);
  68.157 +            return is.getMainClass();
  68.158          }
  68.159 -        return z;
  68.160      }
  68.161  
  68.162 +    private static Object addToArray(Object arr, String value) {
  68.163 +        final int last = length(arr);
  68.164 +        Object ret = enlargeArray(arr, last + 1);
  68.165 +        set(ret, last, value);
  68.166 +        return ret;
  68.167 +    }
  68.168 +
  68.169 +    @JavaScriptBody(args = { "arr", "len" }, body = "while (arr.length < len) arr.push(null); return arr;")
  68.170 +    private static native Object enlargeArray(Object arr, int len);
  68.171      @JavaScriptBody(args = { "arr", "len" }, body = "while (arr.length < len) arr.push(0);")
  68.172 -    private static native void enlargeArray(byte[] arr, int len);
  68.173 +    private static native void enlargeBytes(byte[] arr, int len);
  68.174  
  68.175      @JavaScriptBody(args = { "arr", "len" }, body = "arr.splice(len, arr.length - len);")
  68.176      private static native void sliceArray(byte[] arr, int len);
  68.177 +
  68.178 +    private static Object readFully(byte[] arr, InputStream zip) throws IOException {
  68.179 +        int offset = 0;
  68.180 +        for (;;) {
  68.181 +            int len = zip.read(arr, offset, arr.length - offset);
  68.182 +            if (len == -1) {
  68.183 +                break;
  68.184 +            }
  68.185 +            offset += len;
  68.186 +            if (offset == arr.length) {
  68.187 +                enlargeBytes(arr, arr.length + 4096);
  68.188 +            }
  68.189 +        }
  68.190 +        sliceArray(arr, offset);
  68.191 +        return arr;
  68.192 +    }
  68.193 +
  68.194 +    private static long timeNow() {
  68.195 +        double time = m();
  68.196 +        if (time >= 0) {
  68.197 +            return (long)time;
  68.198 +        }
  68.199 +        return org.apidesign.bck2brwsr.emul.lang.System.currentTimeMillis();
  68.200 +    }
  68.201 +    @JavaScriptBody(args = {}, body = 
  68.202 +        "if (typeof window.performance === 'undefined') return -1;\n"
  68.203 +      + "if (typeof window.performance.now === 'undefined') return -1;\n"
  68.204 +      + "return window.performance.now();"
  68.205 +    )
  68.206 +    private static native double m();
  68.207      
  68.208      
  68.209  }
    69.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java	Tue Feb 19 15:33:32 2013 +0100
    69.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java	Tue Feb 19 15:59:27 2013 +0100
    69.3 @@ -17,7 +17,6 @@
    69.4   */
    69.5  package org.apidesign.vm4brwsr;
    69.6  
    69.7 -import javax.script.Invocable;
    69.8  import static org.testng.Assert.*;
    69.9  import org.testng.annotations.BeforeClass;
   69.10  import org.testng.annotations.Test;
   69.11 @@ -76,18 +75,13 @@
   69.12          assertExec("Returns 'false'", Array.class, "instanceOfArray__ZLjava_lang_Object_2", Double.valueOf(0), "non-array");
   69.13      }
   69.14      
   69.15 -    private static CharSequence codeSeq;
   69.16 -    private static Invocable code;
   69.17 +    private static TestVM code;
   69.18      
   69.19      @BeforeClass 
   69.20      public void compileTheCode() throws Exception {
   69.21 -        StringBuilder sb = new StringBuilder();
   69.22 -        code = StaticMethodTest.compileClass(sb, 
   69.23 -            "org/apidesign/vm4brwsr/Array"
   69.24 -        );
   69.25 -        codeSeq = sb;
   69.26 +        code = TestVM.compileClass("org/apidesign/vm4brwsr/Array");
   69.27      }
   69.28      private static void assertExec(String msg, Class clazz, String method, Object expRes, Object... args) throws Exception {
   69.29 -        StaticMethodTest.assertExec(code, codeSeq, msg, clazz, method, expRes, args);
   69.30 +        code.assertExec(msg, clazz, method, expRes, args);
   69.31      }
   69.32  }
    70.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java	Tue Feb 19 15:33:32 2013 +0100
    70.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java	Tue Feb 19 15:59:27 2013 +0100
    70.3 @@ -17,7 +17,6 @@
    70.4   */
    70.5  package org.apidesign.vm4brwsr;
    70.6  
    70.7 -import javax.script.Invocable;
    70.8  import org.testng.annotations.Test;
    70.9  import static org.testng.Assert.*;
   70.10  import org.testng.annotations.BeforeClass;
   70.11 @@ -87,12 +86,27 @@
   70.12      @Test public void jsAnnotation() throws Exception {
   70.13          assertExec("Check class annotation", Classes.class, "getMarker__I", Double.valueOf(10));
   70.14      }
   70.15 +    @Test public void jsArrayAnnotation() throws Exception {
   70.16 +        assertExec("Check array annotation", Classes.class, "getMarkerNicknames__Ljava_lang_String_2", Classes.getMarkerNicknames());
   70.17 +    }
   70.18 +    @Test public void jsEnumAnnotation() throws Exception {
   70.19 +        assertExec("Check enum annotation", Classes.class, "getMarkerE__Ljava_lang_String_2", Classes.getMarkerE());
   70.20 +    }
   70.21 +    @Test public void jsRetentionAnnotation() throws Exception {
   70.22 +        assertExec("Check enum annotation", Classes.class, "getRetention__Ljava_lang_String_2", Classes.getRetention());
   70.23 +    }
   70.24      @Test public void jsStringAnnotation() throws Exception {
   70.25          assertExec("Check class annotation", Classes.class, "getNamer__Ljava_lang_String_2Z", "my text", true);
   70.26      }
   70.27      @Test public void jsStringAnnotationFromArray() throws Exception {
   70.28          assertExec("Check class annotation", Classes.class, "getNamer__Ljava_lang_String_2Z", "my text", false);
   70.29      }
   70.30 +    @Test public void jsInnerAnnotation() throws Exception {
   70.31 +        assertExec("Check inner annotation", Classes.class, "getInnerNamer__I", Double.valueOf(Classes.getInnerNamer()));
   70.32 +    }
   70.33 +    @Test public void jsInnerAnnotationFromArray() throws Exception {
   70.34 +        assertExec("Check inner annotation", Classes.class, "getInnerNamers__I", Double.valueOf(Classes.getInnerNamers()));
   70.35 +    }
   70.36      @Test public void javaInvokeMethod() throws Exception {
   70.37          assertEquals(Classes.reflectiveMethodCall(true, "name"), "java.io.IOException", "Calls the name() method via reflection");
   70.38      }
   70.39 @@ -102,6 +116,14 @@
   70.40              "java.io.IOException", true, "name"
   70.41          );
   70.42      }
   70.43 +    
   70.44 +    @Test public void jsMethodDeclaredInObject() throws Exception {
   70.45 +        assertExec("Defined in Object", Classes.class, 
   70.46 +            "objectName__Ljava_lang_String_2", 
   70.47 +            "java.lang.Object"
   70.48 +        );
   70.49 +    }
   70.50 +    
   70.51      @Test public void jsInvokeParamMethod() throws Exception {
   70.52          assertExec("sums two numbers via reflection", Classes.class, 
   70.53              "reflectiveSum__III", Double.valueOf(5), 2, 3
   70.54 @@ -149,14 +171,12 @@
   70.55              0.0, "java.lang.String"
   70.56          );
   70.57      }
   70.58 -    /*
   70.59      @Test public void isInterface() throws Exception {
   70.60          assertExec("Calls Class.isInterface", Classes.class, 
   70.61              "isInterface__ZLjava_lang_String_2", 
   70.62              1.0, "java.lang.Runnable"
   70.63          );
   70.64      }
   70.65 -    */
   70.66      @Test public void integerType() throws Exception {
   70.67          assertExec("Computes the type", Classes.class, 
   70.68              "intType__Ljava_lang_String_2", 
   70.69 @@ -164,22 +184,17 @@
   70.70          );
   70.71      }
   70.72      
   70.73 -    private static CharSequence codeSeq;
   70.74 -    private static Invocable code;
   70.75 +    private static TestVM code;
   70.76      
   70.77      @BeforeClass
   70.78      public void compileTheCode() throws Exception {
   70.79 -        if (codeSeq == null) {
   70.80 -            StringBuilder sb = new StringBuilder();
   70.81 -            code = StaticMethodTest.compileClass(sb, "org/apidesign/vm4brwsr/Classes");
   70.82 -            codeSeq = sb;
   70.83 -        }
   70.84 +        code = TestVM.compileClass("org/apidesign/vm4brwsr/Classes");
   70.85      }
   70.86      
   70.87      private void assertExec(
   70.88          String msg, Class clazz, String method, Object expRes, Object... args
   70.89      ) throws Exception {
   70.90 -        StaticMethodTest.assertExec(code, codeSeq, msg, clazz, method, expRes, args);
   70.91 +        code.assertExec(msg, clazz, method, expRes, args);
   70.92      }
   70.93      @Test public void isClassAssignable() throws Exception {
   70.94          assertExec("isAssignable works on subclasses", Classes.class, 
    71.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java	Tue Feb 19 15:33:32 2013 +0100
    71.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java	Tue Feb 19 15:59:27 2013 +0100
    71.3 @@ -19,6 +19,8 @@
    71.4  
    71.5  import java.io.IOException;
    71.6  import java.lang.annotation.Annotation;
    71.7 +import java.lang.annotation.Retention;
    71.8 +import java.lang.annotation.RetentionPolicy;
    71.9  import java.lang.reflect.Method;
   71.10  import java.net.MalformedURLException;
   71.11  import org.apidesign.bck2brwsr.core.JavaScriptBody;
   71.12 @@ -27,8 +29,11 @@
   71.13   *
   71.14   * @author Jaroslav Tulach <jtulach@netbeans.org>
   71.15   */
   71.16 -@ClassesMarker(number = 10)
   71.17 -@ClassesNamer(name = "my text")
   71.18 +@ClassesMarker(number = 10, nicknames = { "Ten", "Deset" }, count = ClassesMarker.E.TWO, subs = {
   71.19 +    @ClassesMarker.Anno(Integer.SIZE),
   71.20 +    @ClassesMarker.Anno(Integer.MIN_VALUE)
   71.21 +})
   71.22 +@ClassesNamer(name = "my text", anno = @ClassesMarker.Anno(333))
   71.23  public class Classes {
   71.24      public static String nameOfIO() {
   71.25          return nameFor(IOException.class);
   71.26 @@ -38,6 +43,8 @@
   71.27          return c.getName();
   71.28      }
   71.29      
   71.30 +    private static final Class<?> PRELOAD = Runnable.class;
   71.31 +    
   71.32      public static boolean isInterface(String s) throws ClassNotFoundException {
   71.33          return Class.forName(s).isInterface();
   71.34      }
   71.35 @@ -55,7 +62,7 @@
   71.36          return new IOException().getClass().getName().toString();
   71.37      }
   71.38      
   71.39 -    @ClassesMarker(number = 1)
   71.40 +    @ClassesMarker(number = 1, nicknames = { "One", "Jedna" } )
   71.41      public static String name() {
   71.42          return IOException.class.getName().toString();
   71.43      }
   71.44 @@ -65,6 +72,11 @@
   71.45      public static String canonicalName() {
   71.46          return IOException.class.getCanonicalName();
   71.47      }
   71.48 +    
   71.49 +    public static String objectName() throws NoSuchMethodException {
   71.50 +        return IOException.class.getMethod("wait").getDeclaringClass().getName();
   71.51 +    }
   71.52 +    
   71.53      public static boolean newInstance() throws Exception {
   71.54          IOException ioe = IOException.class.newInstance();
   71.55          if (ioe instanceof IOException) {
   71.56 @@ -85,8 +97,45 @@
   71.57              return -2;
   71.58          }
   71.59          ClassesMarker cm = Classes.class.getAnnotation(ClassesMarker.class);
   71.60 +        assert cm instanceof Object : "Is object " + cm;
   71.61 +        assert cm instanceof Annotation : "Is annotation " + cm;
   71.62 +        assert !((Object)cm instanceof Class) : "Is not Class " + cm;
   71.63          return cm == null ? -1 : cm.number();
   71.64      }
   71.65 +    public static String getMarkerNicknames() {
   71.66 +        ClassesMarker cm = Classes.class.getAnnotation(ClassesMarker.class);
   71.67 +        if (cm == null) {
   71.68 +            return null;
   71.69 +        }
   71.70 +        
   71.71 +        final Object[] arr = cm.nicknames();
   71.72 +        assert arr instanceof Object[] : "Instance of Object array: " + arr;
   71.73 +        assert arr instanceof String[] : "Instance of String array: " + arr;
   71.74 +        assert !(arr instanceof Integer[]) : "Not instance of Integer array: " + arr;
   71.75 +        
   71.76 +        StringBuilder sb = new StringBuilder();
   71.77 +        for (String s : cm.nicknames()) {
   71.78 +            sb.append(s).append("\n");
   71.79 +        }
   71.80 +        return sb.toString().toString();
   71.81 +    }
   71.82 +    @Retention(RetentionPolicy.CLASS)
   71.83 +    @interface Ann {
   71.84 +    }
   71.85 +    
   71.86 +    public static String getRetention() throws Exception {
   71.87 +        Retention r = Ann.class.getAnnotation(Retention.class);
   71.88 +        assert r != null : "Annotation is present";
   71.89 +        assert r.value() == RetentionPolicy.CLASS : "Policy value is OK: " + r.value();
   71.90 +        return r.annotationType().getName();
   71.91 +    }
   71.92 +    public static String getMarkerE() {
   71.93 +        ClassesMarker cm = Classes.class.getAnnotation(ClassesMarker.class);
   71.94 +        if (cm == null) {
   71.95 +            return null;
   71.96 +        }
   71.97 +        return cm.count().name();
   71.98 +    }
   71.99      public static String getNamer(boolean direct) {
  71.100          if (direct) {
  71.101              ClassesNamer cm = Classes.class.getAnnotation(ClassesNamer.class);
  71.102 @@ -99,6 +148,20 @@
  71.103          }
  71.104          return null;
  71.105      }
  71.106 +    public static int getInnerNamer() {
  71.107 +        ClassesNamer cm = Classes.class.getAnnotation(ClassesNamer.class);
  71.108 +        assert cm != null : "ClassesNamer is present";
  71.109 +        return cm.anno().value();
  71.110 +    }
  71.111 +    public static int getInnerNamers() {
  71.112 +        ClassesMarker cm = Classes.class.getAnnotation(ClassesMarker.class);
  71.113 +        assert cm != null : "ClassesNamer is present";
  71.114 +        int sum = 0;
  71.115 +        for (ClassesMarker.Anno anno : cm.subs()) {
  71.116 +            sum += anno.value();
  71.117 +        }
  71.118 +        return sum;
  71.119 +    }
  71.120      
  71.121      public static String intType() {
  71.122          return Integer.TYPE.getName();
    72.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ClassesMarker.java	Tue Feb 19 15:33:32 2013 +0100
    72.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassesMarker.java	Tue Feb 19 15:59:27 2013 +0100
    72.3 @@ -27,4 +27,16 @@
    72.4  @Retention(RetentionPolicy.RUNTIME)
    72.5  public @interface ClassesMarker {
    72.6      int number();
    72.7 +    String[] nicknames();
    72.8 +    E count() default E.ONE;
    72.9 +    
   72.10 +    enum E {
   72.11 +        ONE, TWO;
   72.12 +    }
   72.13 +    
   72.14 +    Anno[] subs() default {};
   72.15 +    
   72.16 +    public @interface Anno {
   72.17 +        int value();
   72.18 +    }
   72.19  }
    73.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ClassesNamer.java	Tue Feb 19 15:33:32 2013 +0100
    73.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassesNamer.java	Tue Feb 19 15:59:27 2013 +0100
    73.3 @@ -27,4 +27,5 @@
    73.4  @Retention(RetentionPolicy.RUNTIME)
    73.5  public @interface ClassesNamer {
    73.6      String name();
    73.7 +    ClassesMarker.Anno anno();
    73.8  }
    74.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ExceptionsTest.java	Tue Feb 19 15:33:32 2013 +0100
    74.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ExceptionsTest.java	Tue Feb 19 15:59:27 2013 +0100
    74.3 @@ -17,7 +17,6 @@
    74.4   */
    74.5  package org.apidesign.vm4brwsr;
    74.6  
    74.7 -import javax.script.Invocable;
    74.8  import javax.script.ScriptException;
    74.9  import static org.testng.Assert.*;
   74.10  import org.testng.annotations.BeforeClass;
   74.11 @@ -81,8 +80,7 @@
   74.12      }
   74.13      
   74.14      @Test public void testThreeCalls() throws Exception {
   74.15 -        Object vm = code.invokeFunction("bck2brwsr");
   74.16 -        Object clazz = code.invokeMethod(vm, "loadClass", Exceptions.class.getName());
   74.17 +        Object clazz = code.loadClass("loadClass", Exceptions.class.getName());
   74.18          
   74.19          String method = "readCounter__ILjava_lang_String_2";
   74.20          
   74.21 @@ -104,18 +102,13 @@
   74.22          }
   74.23      }
   74.24      
   74.25 -    private static CharSequence codeSeq;
   74.26 -    private static Invocable code;
   74.27 +    private static TestVM code;
   74.28      
   74.29      @BeforeClass 
   74.30      public void compileTheCode() throws Exception {
   74.31 -        StringBuilder sb = new StringBuilder();
   74.32 -        code = StaticMethodTest.compileClass(sb, 
   74.33 -            "org/apidesign/vm4brwsr/Exceptions"
   74.34 -        );
   74.35 -        codeSeq = sb;
   74.36 +        code = TestVM.compileClass("org/apidesign/vm4brwsr/Exceptions");
   74.37      }
   74.38      private static void assertExec(String msg, Class clazz, String method, Object expRes, Object... args) throws Exception {
   74.39 -        StaticMethodTest.assertExec(code, codeSeq, msg, clazz, method, expRes, args);
   74.40 +        code.assertExec(msg, clazz, method, expRes, args);
   74.41      }
   74.42  }
    75.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/InstanceTest.java	Tue Feb 19 15:33:32 2013 +0100
    75.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/InstanceTest.java	Tue Feb 19 15:59:27 2013 +0100
    75.3 @@ -17,7 +17,6 @@
    75.4   */
    75.5  package org.apidesign.vm4brwsr;
    75.6  
    75.7 -import javax.script.Invocable;
    75.8  import org.testng.annotations.Test;
    75.9  import org.testng.annotations.BeforeClass;
   75.10  
   75.11 @@ -151,22 +150,17 @@
   75.12          return "org/apidesign/vm4brwsr/Instance";
   75.13      }
   75.14      
   75.15 -    private static CharSequence codeSeq;
   75.16 -    private static Invocable code;
   75.17 +    private static TestVM code;
   75.18      
   75.19      @BeforeClass
   75.20      public void compileTheCode() throws Exception {
   75.21 -        if (codeSeq == null) {
   75.22 -            StringBuilder sb = new StringBuilder();
   75.23 -            code = StaticMethodTest.compileClass(sb, startCompilationWith());
   75.24 -            codeSeq = sb;
   75.25 -        }
   75.26 +        code = TestVM.compileClass(startCompilationWith());
   75.27      }
   75.28      
   75.29      private void assertExec(
   75.30          String msg, Class clazz, String method, Object expRes, Object... args
   75.31      ) throws Exception {
   75.32 -        StaticMethodTest.assertExec(code, codeSeq, msg, clazz, method, expRes, args);
   75.33 +        code.assertExec(msg, clazz, method, expRes, args);
   75.34      }
   75.35      
   75.36  }
    76.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java	Tue Feb 19 15:33:32 2013 +0100
    76.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java	Tue Feb 19 15:59:27 2013 +0100
    76.3 @@ -17,8 +17,6 @@
    76.4   */
    76.5  package org.apidesign.vm4brwsr;
    76.6  
    76.7 -import javax.script.Invocable;
    76.8 -import javax.script.ScriptException;
    76.9  import static org.testng.Assert.*;
   76.10  import org.testng.annotations.BeforeClass;
   76.11  import org.testng.annotations.Test;
   76.12 @@ -144,22 +142,17 @@
   76.13          );
   76.14      }
   76.15  
   76.16 -    private static CharSequence codeSeq;
   76.17 -    private static Invocable code;
   76.18 +    private static TestVM code;
   76.19  
   76.20      @BeforeClass
   76.21      public void compileTheCode() throws Exception {
   76.22 -        if (codeSeq == null) {
   76.23 -            StringBuilder sb = new StringBuilder();
   76.24 -            code = StaticMethodTest.compileClass(sb, "org/apidesign/vm4brwsr/Numbers");
   76.25 -            codeSeq = sb;
   76.26 -        }
   76.27 +        code = TestVM.compileClass("org/apidesign/vm4brwsr/Numbers");
   76.28      }
   76.29  
   76.30      private static void assertExec(
   76.31          String msg, Class<?> clazz, String method, Object expRes, Object... args) throws Exception
   76.32      {
   76.33 -        Object ret = TestUtils.execCode(code, codeSeq, msg, clazz, method, expRes, args);
   76.34 +        Object ret = code.execCode(msg, clazz, method, expRes, args);
   76.35          if (ret == null) {
   76.36              return;
   76.37          }
   76.38 @@ -167,10 +160,10 @@
   76.39              double expD = ((Double)expRes).doubleValue();
   76.40              double retD = ((Double)ret).doubleValue();
   76.41              assertEquals(retD, expD, 0.000004, msg + " "
   76.42 -                    + StaticMethodTest.dumpJS(codeSeq));
   76.43 +                    + code.toString());
   76.44              return;
   76.45          }
   76.46 -        assertEquals(ret, expRes, msg + " " + StaticMethodTest.dumpJS(codeSeq));
   76.47 +        assertEquals(ret, expRes, msg + " " + code.toString());
   76.48      }
   76.49      
   76.50  }
    77.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethodTest.java	Tue Feb 19 15:33:32 2013 +0100
    77.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethodTest.java	Tue Feb 19 15:59:27 2013 +0100
    77.3 @@ -17,16 +17,6 @@
    77.4   */
    77.5  package org.apidesign.vm4brwsr;
    77.6  
    77.7 -import java.io.File;
    77.8 -import java.io.FileWriter;
    77.9 -import java.io.IOException;
   77.10 -import java.io.InputStream;
   77.11 -import java.net.URL;
   77.12 -import java.util.Enumeration;
   77.13 -import javax.script.Invocable;
   77.14 -import javax.script.ScriptEngine;
   77.15 -import javax.script.ScriptEngineManager;
   77.16 -import javax.script.ScriptException;
   77.17  import static org.testng.Assert.*;
   77.18  import org.testng.annotations.BeforeClass;
   77.19  import org.testng.annotations.Test;
   77.20 @@ -331,88 +321,18 @@
   77.21          );
   77.22      }
   77.23      
   77.24 -    private static CharSequence codeSeq;
   77.25 -    private static Invocable code;
   77.26 +    private static TestVM code;
   77.27      
   77.28      @BeforeClass 
   77.29      public void compileTheCode() throws Exception {
   77.30          StringBuilder sb = new StringBuilder();
   77.31 -        code = compileClass(sb, "org/apidesign/vm4brwsr/StaticMethod");
   77.32 -        codeSeq = sb;
   77.33 -    }
   77.34 -    
   77.35 -    
   77.36 -    private static void assertExec(
   77.37 -        String msg, Class clazz, String method, 
   77.38 -        Object expRes, Object... args
   77.39 -    ) throws Exception {
   77.40 -        assertExec(code, codeSeq, msg, clazz, method, expRes, args);
   77.41 -    }
   77.42 -    static void assertExec(
   77.43 -        Invocable toRun, CharSequence theCode,
   77.44 -        String msg, Class clazz, String method, 
   77.45 -        Object expRes, Object... args
   77.46 -    ) throws Exception {
   77.47 -        Object ret = TestUtils.execCode(toRun, theCode, msg, clazz, method, expRes, args);
   77.48 -        if (ret == null) {
   77.49 -            return;
   77.50 -        }
   77.51 -        if (expRes != null && expRes.equals(ret)) {
   77.52 -            return;
   77.53 -        }
   77.54 -        assertEquals(ret, expRes, msg + "was: " + ret + "\n" + dumpJS(theCode));
   77.55 -        
   77.56 +        code = TestVM.compileClass(sb, "org/apidesign/vm4brwsr/StaticMethod");
   77.57      }
   77.58  
   77.59 -    static Invocable compileClass(StringBuilder sb, String... names) throws ScriptException, IOException {
   77.60 -        return compileClass(sb, null, names);
   77.61 -    }
   77.62 -    static Invocable compileClass(
   77.63 -        StringBuilder sb, ScriptEngine[] eng, String... names
   77.64 -    ) throws ScriptException, IOException {
   77.65 -        if (sb == null) {
   77.66 -            sb = new StringBuilder();
   77.67 -        }
   77.68 -        Bck2Brwsr.generate(sb, new EmulationResources(), names);
   77.69 -        ScriptEngineManager sem = new ScriptEngineManager();
   77.70 -        ScriptEngine js = sem.getEngineByExtension("js");
   77.71 -        if (eng != null) {
   77.72 -            eng[0] = js;
   77.73 -        }
   77.74 -        try {
   77.75 -            Object res = js.eval(sb.toString());
   77.76 -            assertTrue(js instanceof Invocable, "It is invocable object: " + res);
   77.77 -            return (Invocable)js;
   77.78 -        } catch (Exception ex) {
   77.79 -            if (sb.length() > 2000) {
   77.80 -                sb = dumpJS(sb);
   77.81 -            }
   77.82 -            fail("Could not evaluate:\n" + sb, ex);
   77.83 -            return null;
   77.84 -        }
   77.85 -    }
   77.86 -    static StringBuilder dumpJS(CharSequence sb) throws IOException {
   77.87 -        File f = File.createTempFile("execution", ".js");
   77.88 -        FileWriter w = new FileWriter(f);
   77.89 -        w.append(sb);
   77.90 -        w.close();
   77.91 -        return new StringBuilder(f.getPath());
   77.92 -    }
   77.93 -    private static class EmulationResources implements Bck2Brwsr.Resources {
   77.94 -        @Override
   77.95 -        public InputStream get(String name) throws IOException {
   77.96 -            Enumeration<URL> en = StaticMethodTest.class.getClassLoader().getResources(name);
   77.97 -            URL u = null;
   77.98 -            while (en.hasMoreElements()) {
   77.99 -                u = en.nextElement();
  77.100 -            }
  77.101 -            if (u == null) {
  77.102 -                throw new IOException("Can't find " + name);
  77.103 -            }
  77.104 -            if (u.toExternalForm().contains("rt.jar!")) {
  77.105 -                throw new IOException("No emulation for " + u);
  77.106 -            }
  77.107 -            return u.openStream();
  77.108 -        }
  77.109 +    private void assertExec(
  77.110 +        String msg, Class<?> clazz, String method, 
  77.111 +        Object ret, Object... args
  77.112 +    ) throws Exception {
  77.113 +        code.assertExec(msg, clazz, method, ret, args);
  77.114      }
  77.115  }
    78.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/StringTest.java	Tue Feb 19 15:33:32 2013 +0100
    78.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StringTest.java	Tue Feb 19 15:59:27 2013 +0100
    78.3 @@ -17,7 +17,6 @@
    78.4   */
    78.5  package org.apidesign.vm4brwsr;
    78.6  
    78.7 -import javax.script.Invocable;
    78.8  import org.testng.annotations.Test;
    78.9  import static org.testng.Assert.*;
   78.10  import org.testng.annotations.BeforeClass;
   78.11 @@ -194,23 +193,20 @@
   78.12          
   78.13      }
   78.14      
   78.15 -    private static CharSequence codeSeq;
   78.16 -    private static Invocable code;
   78.17 +    private static TestVM code;
   78.18      
   78.19      @BeforeClass 
   78.20      public void compileTheCode() throws Exception {
   78.21 -        StringBuilder sb = new StringBuilder();
   78.22 -        code = StaticMethodTest.compileClass(sb, 
   78.23 +        code = TestVM.compileClass(
   78.24              "org/apidesign/vm4brwsr/StringSample",
   78.25              "java/lang/String"
   78.26          );
   78.27 -        codeSeq = sb;
   78.28      }
   78.29      
   78.30      private static void assertExec(String msg, 
   78.31          Class<?> clazz, String method, Object expRes, Object... args
   78.32      ) throws Exception {
   78.33 -        StaticMethodTest.assertExec(code, codeSeq, msg, clazz, method, expRes, args);
   78.34 +        code.assertExec(msg, clazz, method, expRes, args);
   78.35      }
   78.36      
   78.37  }
    79.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/SystemTest.java	Tue Feb 19 15:33:32 2013 +0100
    79.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/SystemTest.java	Tue Feb 19 15:59:27 2013 +0100
    79.3 @@ -17,10 +17,8 @@
    79.4   */
    79.5  package org.apidesign.vm4brwsr;
    79.6  
    79.7 -import javax.script.Invocable;
    79.8  import org.testng.annotations.BeforeClass;
    79.9  import static org.testng.Assert.*;
   79.10 -import org.testng.annotations.BeforeMethod;
   79.11  import org.testng.annotations.Test;
   79.12  
   79.13  /**
   79.14 @@ -28,10 +26,12 @@
   79.15   * @author Jaroslav Tulach <jtulach@netbeans.org>
   79.16   */
   79.17  public class SystemTest {
   79.18 +    private static TestVM code;
   79.19 +    
   79.20      @Test public void verifyJSTime() throws Exception {
   79.21          long now = System.currentTimeMillis();
   79.22          
   79.23 -        Object js = TestUtils.execCode(code, codeSeq, "Get js time", 
   79.24 +        Object js = code.execCode("Get js time", 
   79.25              org.apidesign.bck2brwsr.emul.lang.System.class, "currentTimeMillis__J",
   79.26              null
   79.27          );
   79.28 @@ -45,14 +45,11 @@
   79.29          assertTrue(time <= later, "Upper bound is OK: " + time + " <= " + later);
   79.30      }
   79.31      
   79.32 -    private static CharSequence codeSeq;
   79.33 -    private static Invocable code;
   79.34      
   79.35      @BeforeClass 
   79.36 -    public void compileTheCode() throws Exception {
   79.37 -        StringBuilder sb = new StringBuilder();
   79.38 -        code = StaticMethodTest.compileClass(sb, "org/apidesign/bck2brwsr/emul/lang/System");
   79.39 -        codeSeq = sb;
   79.40 +    public static void compileTheCode() throws Exception {
   79.41 +        code = TestVM.compileClass(
   79.42 +            "org/apidesign/bck2brwsr/emul/lang/System");
   79.43      }
   79.44      
   79.45  }
    80.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/TestUtils.java	Tue Feb 19 15:33:32 2013 +0100
    80.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    80.3 @@ -1,60 +0,0 @@
    80.4 -/**
    80.5 - * Back 2 Browser Bytecode Translator
    80.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    80.7 - *
    80.8 - * This program is free software: you can redistribute it and/or modify
    80.9 - * it under the terms of the GNU General Public License as published by
   80.10 - * the Free Software Foundation, version 2 of the License.
   80.11 - *
   80.12 - * This program is distributed in the hope that it will be useful,
   80.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   80.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   80.15 - * GNU General Public License for more details.
   80.16 - *
   80.17 - * You should have received a copy of the GNU General Public License
   80.18 - * along with this program. Look for COPYING file in the top folder.
   80.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
   80.20 - */
   80.21 -package org.apidesign.vm4brwsr;
   80.22 -
   80.23 -import javax.script.Invocable;
   80.24 -import javax.script.ScriptException;
   80.25 -import static org.testng.Assert.*;
   80.26 -
   80.27 -class TestUtils {
   80.28 -
   80.29 -    static Object execCode(Invocable code, CharSequence codeSeq,
   80.30 -        String msg, Class<?> clazz, String method, Object expRes, Object... args) 
   80.31 -            throws Exception
   80.32 -    {
   80.33 -        Object ret = null;
   80.34 -        try {
   80.35 -            ret = code.invokeFunction("bck2brwsr");
   80.36 -            ret = code.invokeMethod(ret, "loadClass", clazz.getName());
   80.37 -            ret = code.invokeMethod(ret, method, args);
   80.38 -        } catch (ScriptException ex) {
   80.39 -            fail("Execution failed in " + StaticMethodTest.dumpJS(codeSeq), ex);
   80.40 -        } catch (NoSuchMethodException ex) {
   80.41 -            fail("Cannot find method in " + StaticMethodTest.dumpJS(codeSeq), ex);
   80.42 -        }
   80.43 -        if (ret == null && expRes == null) {
   80.44 -            return null;
   80.45 -        }
   80.46 -        if (expRes != null && expRes.equals(ret)) {
   80.47 -            return null;
   80.48 -        }
   80.49 -        if (expRes instanceof Number) {
   80.50 -            // in case of Long it is necessary convert it to number
   80.51 -            // since the Long is represented by two numbers in JavaScript
   80.52 -            try {
   80.53 -                ret = code.invokeMethod(ret, "toFP");
   80.54 -                ret = code.invokeFunction("Number", ret);
   80.55 -            } catch (ScriptException ex) {
   80.56 -                fail("Conversion to number failed in " + StaticMethodTest.dumpJS(codeSeq), ex);
   80.57 -            } catch (NoSuchMethodException ex) {
   80.58 -                fail("Cannot find global Number(x) function in " + StaticMethodTest.dumpJS(codeSeq), ex);
   80.59 -            }
   80.60 -        }
   80.61 -        return ret;
   80.62 -    }
   80.63 -}
    81.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    81.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/TestVM.java	Tue Feb 19 15:59:27 2013 +0100
    81.3 @@ -0,0 +1,170 @@
    81.4 +/**
    81.5 + * Back 2 Browser Bytecode Translator
    81.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    81.7 + *
    81.8 + * This program is free software: you can redistribute it and/or modify
    81.9 + * it under the terms of the GNU General Public License as published by
   81.10 + * the Free Software Foundation, version 2 of the License.
   81.11 + *
   81.12 + * This program is distributed in the hope that it will be useful,
   81.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   81.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   81.15 + * GNU General Public License for more details.
   81.16 + *
   81.17 + * You should have received a copy of the GNU General Public License
   81.18 + * along with this program. Look for COPYING file in the top folder.
   81.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   81.20 + */
   81.21 +package org.apidesign.vm4brwsr;
   81.22 +
   81.23 +import java.io.File;
   81.24 +import java.io.FileWriter;
   81.25 +import java.io.IOException;
   81.26 +import java.io.InputStream;
   81.27 +import java.net.URL;
   81.28 +import java.util.Enumeration;
   81.29 +import javax.script.Invocable;
   81.30 +import javax.script.ScriptEngine;
   81.31 +import javax.script.ScriptEngineManager;
   81.32 +import javax.script.ScriptException;
   81.33 +import static org.testng.Assert.*;
   81.34 +
   81.35 +final class TestVM {
   81.36 +    private final Invocable code;
   81.37 +    private final CharSequence codeSeq;
   81.38 +    private final Object bck2brwsr;
   81.39 +    
   81.40 +    
   81.41 +    private TestVM(Invocable code, CharSequence codeSeq) throws ScriptException, NoSuchMethodException {
   81.42 +        this.code = code;
   81.43 +        this.codeSeq = codeSeq;
   81.44 +        this.bck2brwsr = code.invokeFunction("bck2brwsr");
   81.45 +    }
   81.46 +    
   81.47 +
   81.48 +    public Object execCode(
   81.49 +        String msg, Class<?> clazz, String method, 
   81.50 +        Object expRes, Object... args
   81.51 +    ) throws Exception {
   81.52 +        Object ret = null;
   81.53 +        try {
   81.54 +            ret = code.invokeMethod(bck2brwsr, "loadClass", clazz.getName());
   81.55 +            ret = code.invokeMethod(ret, method, args);
   81.56 +        } catch (ScriptException ex) {
   81.57 +            fail("Execution failed in " + dumpJS(codeSeq), ex);
   81.58 +        } catch (NoSuchMethodException ex) {
   81.59 +            fail("Cannot find method in " + dumpJS(codeSeq), ex);
   81.60 +        }
   81.61 +        if (ret == null && expRes == null) {
   81.62 +            return null;
   81.63 +        }
   81.64 +        if (expRes != null && expRes.equals(ret)) {
   81.65 +            return null;
   81.66 +        }
   81.67 +        if (expRes instanceof Number) {
   81.68 +            // in case of Long it is necessary convert it to number
   81.69 +            // since the Long is represented by two numbers in JavaScript
   81.70 +            try {
   81.71 +                ret = code.invokeMethod(ret, "toFP");
   81.72 +                ret = code.invokeFunction("Number", ret);
   81.73 +            } catch (ScriptException ex) {
   81.74 +                fail("Conversion to number failed in " + dumpJS(codeSeq), ex);
   81.75 +            } catch (NoSuchMethodException ex) {
   81.76 +                fail("Cannot find global Number(x) function in " + dumpJS(codeSeq), ex);
   81.77 +            }
   81.78 +        }
   81.79 +        return ret;
   81.80 +    }
   81.81 +    
   81.82 +    void assertExec(
   81.83 +        String msg, Class clazz, String method, Object expRes, Object... args
   81.84 +    ) throws Exception {
   81.85 +        Object ret = execCode(msg, clazz, method, expRes, args);
   81.86 +        if (ret == null) {
   81.87 +            return;
   81.88 +        }
   81.89 +        if (expRes != null && expRes.equals(ret)) {
   81.90 +            return;
   81.91 +        }
   81.92 +        assertEquals(ret, expRes, msg + "was: " + ret + "\n" + dumpJS(codeSeq));
   81.93 +    }    
   81.94 +
   81.95 +    static TestVM compileClass(String... names) throws ScriptException, IOException {
   81.96 +        return compileClass(null, names);
   81.97 +    }
   81.98 +    
   81.99 +    static TestVM compileClass(StringBuilder sb, String... names) throws ScriptException, IOException {
  81.100 +        return compileClass(sb, null, names);
  81.101 +    }
  81.102 +
  81.103 +    static TestVM compileClass(StringBuilder sb, ScriptEngine[] eng, String... names) throws ScriptException, IOException {
  81.104 +        if (sb == null) {
  81.105 +            sb = new StringBuilder();
  81.106 +        }
  81.107 +        Bck2Brwsr.generate(sb, new EmulationResources(), names);
  81.108 +        ScriptEngineManager sem = new ScriptEngineManager();
  81.109 +        ScriptEngine js = sem.getEngineByExtension("js");
  81.110 +        if (eng != null) {
  81.111 +            eng[0] = js;
  81.112 +        }
  81.113 +        try {
  81.114 +            Object res = js.eval(sb.toString());
  81.115 +            assertTrue(js instanceof Invocable, "It is invocable object: " + res);
  81.116 +            return new TestVM((Invocable) js, sb);
  81.117 +        } catch (Exception ex) {
  81.118 +            if (sb.length() > 2000) {
  81.119 +                sb = dumpJS(sb);
  81.120 +            }
  81.121 +            fail("Could not evaluate:\n" + sb, ex);
  81.122 +            return null;
  81.123 +        }
  81.124 +    }
  81.125 +
  81.126 +    Object loadClass(String loadClass, String name) throws ScriptException, NoSuchMethodException {
  81.127 +        return code.invokeMethod(bck2brwsr, "loadClass", Exceptions.class.getName());
  81.128 +    }
  81.129 +    
  81.130 +    Object invokeMethod(Object obj, String method, Object... params) throws ScriptException, NoSuchMethodException {
  81.131 +        return code.invokeMethod(obj, method, params);
  81.132 +    }
  81.133 +
  81.134 +    Object invokeFunction(String methodName, Object... args) throws ScriptException, NoSuchMethodException {
  81.135 +        return code.invokeFunction(methodName, args);
  81.136 +    }
  81.137 +
  81.138 +    static StringBuilder dumpJS(CharSequence sb) throws IOException {
  81.139 +        File f = File.createTempFile("execution", ".js");
  81.140 +        FileWriter w = new FileWriter(f);
  81.141 +        w.append(sb);
  81.142 +        w.close();
  81.143 +        return new StringBuilder(f.getPath());
  81.144 +    }
  81.145 +
  81.146 +    @Override
  81.147 +    public String toString() {
  81.148 +        try {
  81.149 +            return dumpJS(codeSeq).toString();
  81.150 +        } catch (IOException ex) {
  81.151 +            return ex.toString();
  81.152 +        }
  81.153 +    }
  81.154 +    
  81.155 +    
  81.156 +    private static class EmulationResources implements Bck2Brwsr.Resources {
  81.157 +        @Override
  81.158 +        public InputStream get(String name) throws IOException {
  81.159 +            Enumeration<URL> en = StaticMethodTest.class.getClassLoader().getResources(name);
  81.160 +            URL u = null;
  81.161 +            while (en.hasMoreElements()) {
  81.162 +                u = en.nextElement();
  81.163 +            }
  81.164 +            if (u == null) {
  81.165 +                throw new IOException("Can't find " + name);
  81.166 +            }
  81.167 +            if (u.toExternalForm().contains("rt.jar!")) {
  81.168 +                throw new IOException("No emulation for " + u);
  81.169 +            }
  81.170 +            return u.openStream();
  81.171 +        }
  81.172 +    }
  81.173 +}
    82.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/VMLazyTest.java	Tue Feb 19 15:33:32 2013 +0100
    82.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/VMLazyTest.java	Tue Feb 19 15:59:27 2013 +0100
    82.3 @@ -17,7 +17,6 @@
    82.4   */
    82.5  package org.apidesign.vm4brwsr;
    82.6  
    82.7 -import javax.script.Invocable;
    82.8  import javax.script.ScriptContext;
    82.9  import javax.script.ScriptEngine;
   82.10  import javax.script.ScriptException;
   82.11 @@ -30,10 +29,7 @@
   82.12   * @author Jaroslav Tulach <jtulach@netbeans.org>
   82.13   */
   82.14  public class VMLazyTest {
   82.15 -
   82.16 -    
   82.17 -    private static CharSequence codeSeq;
   82.18 -    private static Invocable code;
   82.19 +    private static TestVM code;
   82.20  
   82.21      @BeforeClass
   82.22      public void compileTheCode() throws Exception {
   82.23 @@ -50,11 +46,10 @@
   82.24          sb.append("\n}");
   82.25         
   82.26          ScriptEngine[] arr = { null };
   82.27 -        code = StaticMethodTest.compileClass(sb, arr,
   82.28 +        code = TestVM.compileClass(sb, arr,
   82.29              new String[]{"org/apidesign/vm4brwsr/VM", "org/apidesign/vm4brwsr/StaticMethod"}
   82.30          );
   82.31          arr[0].getContext().setAttribute("loader", new BytesLoader(), ScriptContext.ENGINE_SCOPE);
   82.32 -        codeSeq = sb;
   82.33      }
   82.34      
   82.35      @Test public void invokeStaticMethod() throws Exception {
   82.36 @@ -83,9 +78,9 @@
   82.37          try {
   82.38              ret = code.invokeFunction(methodName, args);
   82.39          } catch (ScriptException ex) {
   82.40 -            fail("Execution failed in\n" + StaticMethodTest.dumpJS(codeSeq), ex);
   82.41 +            fail("Execution failed in\n" + code.toString(), ex);
   82.42          } catch (NoSuchMethodException ex) {
   82.43 -            fail("Cannot find method in\n" + StaticMethodTest.dumpJS(codeSeq), ex);
   82.44 +            fail("Cannot find method in\n" + code.toString(), ex);
   82.45          }
   82.46          if (ret == null && expRes == null) {
   82.47              return;
   82.48 @@ -93,6 +88,6 @@
   82.49          if (expRes.equals(ret)) {
   82.50              return;
   82.51          }
   82.52 -        assertEquals(ret, expRes, msg + "was: " + ret + "\n" + StaticMethodTest.dumpJS(codeSeq));
   82.53 +        assertEquals(ret, expRes, msg + "was: " + ret + "\n" + code.toString());
   82.54      }
   82.55  }
    83.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/VMinVMTest.java	Tue Feb 19 15:33:32 2013 +0100
    83.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/VMinVMTest.java	Tue Feb 19 15:59:27 2013 +0100
    83.3 @@ -21,7 +21,6 @@
    83.4  import java.io.FileWriter;
    83.5  import java.io.IOException;
    83.6  import static org.testng.Assert.*;
    83.7 -import javax.script.Invocable;
    83.8  import org.testng.annotations.BeforeClass;
    83.9  import org.testng.annotations.Test;
   83.10  
   83.11 @@ -30,9 +29,7 @@
   83.12   * @author Jaroslav Tulach <jtulach@netbeans.org>
   83.13   */
   83.14  public class VMinVMTest {
   83.15 -
   83.16 -    private static CharSequence codeSeq;
   83.17 -    private static Invocable code;
   83.18 +    private static TestVM code;
   83.19      
   83.20      @Test public void compareGeneratedCodeForArrayClass() throws Exception {
   83.21          compareCode("org/apidesign/vm4brwsr/Array.class");
   83.22 @@ -44,11 +41,7 @@
   83.23  
   83.24      @BeforeClass
   83.25      public void compileTheCode() throws Exception {
   83.26 -        StringBuilder sb = new StringBuilder();
   83.27 -        code = StaticMethodTest.compileClass(sb, 
   83.28 -            "org/apidesign/vm4brwsr/VMinVM"
   83.29 -        );
   83.30 -        codeSeq = sb;
   83.31 +        code = TestVM.compileClass("org/apidesign/vm4brwsr/VMinVM");
   83.32      }
   83.33      
   83.34      private void compareCode(final String nm) throws Exception, IOException {
   83.35 @@ -73,7 +66,7 @@
   83.36                  }
   83.37              }
   83.38              w.append("\n];\n");
   83.39 -            w.append(codeSeq);
   83.40 +            w.append(code.toString());
   83.41              w.close();
   83.42              throw new Exception(ex.getMessage() + " file: " + f, ex);
   83.43          }
   83.44 @@ -83,11 +76,11 @@
   83.45          
   83.46          if (!ret1.toString().equals(ret)) {
   83.47              StringBuilder msg = new StringBuilder("Difference found between ");
   83.48 -            msg.append(StaticMethodTest.dumpJS(ret1));
   83.49 +            msg.append(TestVM.dumpJS(ret1));
   83.50              msg.append(" ");
   83.51 -            msg.append(StaticMethodTest.dumpJS((CharSequence) ret));
   83.52 +            msg.append(TestVM.dumpJS((CharSequence) ret));
   83.53              msg.append(" compiled by ");
   83.54 -            msg.append(StaticMethodTest.dumpJS(codeSeq));
   83.55 +            msg.append(code.toString());
   83.56              fail(msg.toString());
   83.57          }
   83.58      }
    84.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    84.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/Http.java	Tue Feb 19 15:59:27 2013 +0100
    84.3 @@ -0,0 +1,56 @@
    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.vmtest;
   84.22 +
   84.23 +import java.lang.annotation.ElementType;
   84.24 +import java.lang.annotation.Retention;
   84.25 +import java.lang.annotation.RetentionPolicy;
   84.26 +import java.lang.annotation.Target;
   84.27 +
   84.28 +/**
   84.29 + * Exposes HTTP page or pages to the running {@link BrwsrTest}, so it can access under
   84.30 + * the relative path.
   84.31 + *
   84.32 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   84.33 + */
   84.34 +@Retention(RetentionPolicy.RUNTIME)
   84.35 +@Target({ElementType.METHOD, ElementType.TYPE})
   84.36 +public @interface Http {
   84.37 +    /** Set of pages to make available */
   84.38 +    public Resource[] value();
   84.39 +    
   84.40 +    /** Exposes an HTTP page to the running {@link BrwsrTest}, so it can access
   84.41 +     * under the relative path.
   84.42 +     *
   84.43 +     * @author Jaroslav Tulach <jtulach@netbeans.org>
   84.44 +     */
   84.45 +    @Retention(RetentionPolicy.RUNTIME)
   84.46 +    @Target({})
   84.47 +    public @interface Resource {
   84.48 +        /** path on the server that the test can use to access the exposed resource */
   84.49 +        String path();
   84.50 +        /** the content of the HttpResource */
   84.51 +        String content();
   84.52 +        /** resource relative to the class that should be used instead of <code>content</code>.
   84.53 +         * Leave content equal to empty string.
   84.54 +         */
   84.55 +        String resource() default "";
   84.56 +        /** mime type of the resource */
   84.57 +        String mimeType();
   84.58 +    }
   84.59 +}
    85.1 --- a/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/HttpResource.java	Tue Feb 19 15:33:32 2013 +0100
    85.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    85.3 @@ -1,43 +0,0 @@
    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.vmtest;
   85.22 -
   85.23 -import java.lang.annotation.ElementType;
   85.24 -import java.lang.annotation.Retention;
   85.25 -import java.lang.annotation.RetentionPolicy;
   85.26 -import java.lang.annotation.Target;
   85.27 -
   85.28 -/** Exposes an HTTP page to the running {@link BrwsrTest}, so it can access
   85.29 - * under the relative path.
   85.30 - *
   85.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   85.32 - */
   85.33 -@Retention(RetentionPolicy.RUNTIME)
   85.34 -@Target({ ElementType.METHOD, ElementType.TYPE})
   85.35 -public @interface HttpResource {
   85.36 -    /** path on the server that the test can use to access the exposed resource */
   85.37 -    String path();
   85.38 -    /** the content of the HttpResource */
   85.39 -    String content();
   85.40 -    /** resource relative to the class that should be used instead of <code>content</code>.
   85.41 -     * Leave content equal to empty string.
   85.42 -     */
   85.43 -    String resource() default "";
   85.44 -    /** mime type of the resource */
   85.45 -    String mimeType();
   85.46 -}
    86.1 --- a/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java	Tue Feb 19 15:33:32 2013 +0100
    86.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java	Tue Feb 19 15:59:27 2013 +0100
    86.3 @@ -28,7 +28,7 @@
    86.4  import org.apidesign.bck2brwsr.launcher.Launcher;
    86.5  import org.apidesign.bck2brwsr.launcher.InvocationContext;
    86.6  import org.apidesign.bck2brwsr.vmtest.HtmlFragment;
    86.7 -import org.apidesign.bck2brwsr.vmtest.HttpResource;
    86.8 +import org.apidesign.bck2brwsr.vmtest.Http;
    86.9  import org.testng.ITest;
   86.10  import org.testng.annotations.Test;
   86.11  
   86.12 @@ -42,10 +42,10 @@
   86.13      private final String type;
   86.14      private final boolean fail;
   86.15      private final HtmlFragment html;
   86.16 -    private final HttpResource http;
   86.17 +    private final Http.Resource[] http;
   86.18      Object value;
   86.19  
   86.20 -    Bck2BrwsrCase(Method m, String type, Launcher l, boolean fail, HtmlFragment html, HttpResource http) {
   86.21 +    Bck2BrwsrCase(Method m, String type, Launcher l, boolean fail, HtmlFragment html, Http.Resource[] http) {
   86.22          this.l = l;
   86.23          this.m = m;
   86.24          this.type = type;
   86.25 @@ -62,12 +62,14 @@
   86.26                  c.setHtmlFragment(html.value());
   86.27              }
   86.28              if (http != null) {
   86.29 -                if (!http.content().isEmpty()) {
   86.30 -                    InputStream is = new ByteArrayInputStream(http.content().getBytes("UTF-8"));
   86.31 -                    c.setHttpResource(http.path(), http.mimeType(), is);
   86.32 -                } else {
   86.33 -                    InputStream is = m.getDeclaringClass().getResourceAsStream(http.resource());
   86.34 -                    c.setHttpResource(http.path(), http.mimeType(), is);
   86.35 +                for (Http.Resource r : http) {
   86.36 +                    if (!r.content().isEmpty()) {
   86.37 +                        InputStream is = new ByteArrayInputStream(r.content().getBytes("UTF-8"));
   86.38 +                        c.addHttpResource(r.path(), r.mimeType(), is);
   86.39 +                    } else {
   86.40 +                        InputStream is = m.getDeclaringClass().getResourceAsStream(r.resource());
   86.41 +                        c.addHttpResource(r.path(), r.mimeType(), is);
   86.42 +                    }
   86.43                  }
   86.44              }
   86.45              String res = c.invoke();
    87.1 --- a/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java	Tue Feb 19 15:33:32 2013 +0100
    87.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java	Tue Feb 19 15:59:27 2013 +0100
    87.3 @@ -135,9 +135,15 @@
    87.4          if (f == null) {
    87.5              f = m.getDeclaringClass().getAnnotation(HtmlFragment.class);
    87.6          }
    87.7 -        HttpResource r = m.getAnnotation(HttpResource.class);
    87.8 -        if (r == null) {
    87.9 -            r = m.getDeclaringClass().getAnnotation(HttpResource.class);
   87.10 +        Http.Resource[] r = {};
   87.11 +        Http h = m.getAnnotation(Http.class);
   87.12 +        if (h == null) {
   87.13 +            h = m.getDeclaringClass().getAnnotation(Http.class);
   87.14 +            if (h != null) {
   87.15 +                r = h.value();
   87.16 +            }
   87.17 +        } else {
   87.18 +            r = h.value();
   87.19          }
   87.20          if (brwsr.length == 0) {
   87.21              final Launcher s = l.brwsr(null);
    88.1 --- a/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/GenerateZipProcessor.java	Tue Feb 19 15:33:32 2013 +0100
    88.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/GenerateZipProcessor.java	Tue Feb 19 15:59:27 2013 +0100
    88.3 @@ -25,6 +25,7 @@
    88.4  import java.util.jar.JarOutputStream;
    88.5  import java.util.jar.Manifest;
    88.6  import javax.annotation.processing.AbstractProcessor;
    88.7 +import javax.annotation.processing.Filer;
    88.8  import javax.annotation.processing.Processor;
    88.9  import javax.annotation.processing.RoundEnvironment;
   88.10  import javax.annotation.processing.SupportedAnnotationTypes;
   88.11 @@ -73,7 +74,8 @@
   88.12      }
   88.13  
   88.14      private void generateJar(PackageElement pe, GenerateZip gz, Element e) throws IOException {
   88.15 -        FileObject res = processingEnv.getFiler().createResource(
   88.16 +        final Filer filer = processingEnv.getFiler();
   88.17 +        FileObject res = filer.createResource(
   88.18              StandardLocation.CLASS_OUTPUT, 
   88.19              pe.getQualifiedName().toString(), 
   88.20              gz.name(), e
   88.21 @@ -93,6 +95,7 @@
   88.22              jar.write(arr[i + 1].getBytes("UTF-8"));
   88.23              jar.closeEntry();
   88.24          }
   88.25 +        jar.close();
   88.26      }
   88.27 -    
   88.28 +
   88.29  }
    89.1 --- a/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java	Tue Feb 19 15:33:32 2013 +0100
    89.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java	Tue Feb 19 15:59:27 2013 +0100
    89.3 @@ -47,6 +47,19 @@
    89.4          return "Ahoj".equals(null);
    89.5      }
    89.6      
    89.7 +    @Compare public int highByteLenght() {
    89.8 +        byte[] arr= { 77,97,110,105,102,101,115,116,45,86,101,114,115,105,111,110 };
    89.9 +        return new String(arr, 0).length();
   89.10 +    }
   89.11 +    
   89.12 +    @Compare public String highByte() {
   89.13 +        byte[] arr= { 77,97,110,105,102,101,115,116,45,86,101,114,115,105,111,110 };
   89.14 +        StringBuilder sb = new StringBuilder();
   89.15 +        sb.append("pref:");
   89.16 +        sb.append(new String(arr, 0));
   89.17 +        return sb.toString();
   89.18 +    }
   89.19 +    
   89.20      @Compare public static Object compareURLs() throws MalformedURLException {
   89.21          return new URL("http://apidesign.org:8080/wiki/").toExternalForm().toString();
   89.22      }
    90.1 --- a/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/HttpResourceTest.java	Tue Feb 19 15:33:32 2013 +0100
    90.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/HttpResourceTest.java	Tue Feb 19 15:59:27 2013 +0100
    90.3 @@ -21,7 +21,7 @@
    90.4  import java.net.URL;
    90.5  import org.apidesign.bck2brwsr.core.JavaScriptBody;
    90.6  import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
    90.7 -import org.apidesign.bck2brwsr.vmtest.HttpResource;
    90.8 +import org.apidesign.bck2brwsr.vmtest.Http;
    90.9  import org.apidesign.bck2brwsr.vmtest.VMTest;
   90.10  import org.testng.annotations.Factory;
   90.11  
   90.12 @@ -31,15 +31,21 @@
   90.13   */
   90.14  public class HttpResourceTest {
   90.15      
   90.16 -    @HttpResource(path = "/xhr", content = "Hello Brwsr!", mimeType = "text/plain")
   90.17 +    @Http({
   90.18 +        @Http.Resource(path = "/xhr", content = "Hello Brwsr!", mimeType = "text/plain")
   90.19 +    })
   90.20      @BrwsrTest
   90.21 +    
   90.22 +    
   90.23      public String testReadContentViaXHR() throws Exception {
   90.24          String msg = read("/xhr");
   90.25          assert "Hello Brwsr!".equals(msg) : "The message was " + msg;
   90.26          return msg;
   90.27      }
   90.28  
   90.29 -    @HttpResource(path = "/url", content = "Hello via URL!", mimeType = "text/plain")
   90.30 +    @Http({
   90.31 +        @Http.Resource(path = "/url", content = "Hello via URL!", mimeType = "text/plain")
   90.32 +    })
   90.33      @BrwsrTest
   90.34      public String testReadContentViaURL() throws Exception {
   90.35          URL url = new URL("http:/url");
   90.36 @@ -47,7 +53,9 @@
   90.37          assert "Hello via URL!".equals(msg) : "The message was " + msg;
   90.38          return msg;
   90.39      }
   90.40 -    @HttpResource(path = "/url", content = "Hello via URL!", mimeType = "text/plain")
   90.41 +    @Http({
   90.42 +        @Http.Resource(path = "/url", content = "Hello via URL!", mimeType = "text/plain")
   90.43 +    })
   90.44      @BrwsrTest
   90.45      public String testReadContentViaURLWithStringParam() throws Exception {
   90.46          URL url = new URL("http:/url");
   90.47 @@ -56,7 +64,9 @@
   90.48          return msg;
   90.49      }
   90.50  
   90.51 -    @HttpResource(path = "/bytes", content = "", resource = "0xfe", mimeType = "x-application/binary")
   90.52 +    @Http({
   90.53 +        @Http.Resource(path = "/bytes", content = "", resource = "0xfe", mimeType = "x-application/binary")
   90.54 +    })
   90.55      @BrwsrTest
   90.56      public void testReadByte() throws Exception {
   90.57          URL url = new URL("http:/bytes");
   90.58 @@ -67,7 +77,9 @@
   90.59          assert arr[0] == 0xfe : "It is 0xfe: " + Integer.toHexString(arr[0]);
   90.60      }
   90.61  
   90.62 -    @HttpResource(path = "/bytes", content = "", resource = "0xfe", mimeType = "x-application/binary")
   90.63 +    @Http({
   90.64 +        @Http.Resource(path = "/bytes", content = "", resource = "0xfe", mimeType = "x-application/binary")
   90.65 +    })
   90.66      @BrwsrTest
   90.67      public void testReadByteViaInputStream() throws Exception {
   90.68          URL url = new URL("http:/bytes");
    91.1 --- a/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java	Tue Feb 19 15:33:32 2013 +0100
    91.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java	Tue Feb 19 15:59:27 2013 +0100
    91.3 @@ -17,6 +17,8 @@
    91.4   */
    91.5  package org.apidesign.bck2brwsr.tck;
    91.6  
    91.7 +import java.lang.annotation.Retention;
    91.8 +import java.lang.annotation.RetentionPolicy;
    91.9  import java.lang.reflect.Method;
   91.10  import java.util.Arrays;
   91.11  import java.util.Collections;
   91.12 @@ -47,6 +49,14 @@
   91.13          return long.class.toString();
   91.14      }
   91.15      
   91.16 +    @Compare public boolean isRunnableInterface() {
   91.17 +        return Runnable.class.isInterface();
   91.18 +    }
   91.19 +
   91.20 +    @Compare public String isRunnableHasRunMethod() throws NoSuchMethodException {
   91.21 +        return Runnable.class.getMethod("run").getName();
   91.22 +    }
   91.23 +    
   91.24      @Compare public String namesOfMethods() {
   91.25          StringBuilder sb = new StringBuilder();
   91.26          String[] arr = new String[20];
   91.27 @@ -59,6 +69,19 @@
   91.28          }
   91.29          return sb.toString();
   91.30      }
   91.31 +
   91.32 +    @Compare public String namesOfDeclaringClassesOfMethods() {
   91.33 +        StringBuilder sb = new StringBuilder();
   91.34 +        String[] arr = new String[20];
   91.35 +        int i = 0;
   91.36 +        for (Method m : StaticUse.class.getMethods()) {
   91.37 +            arr[i++] = m.getName() + "@" + m.getDeclaringClass().getName();
   91.38 +        }
   91.39 +        for (String s : sort(arr, i)) {
   91.40 +            sb.append(s).append("\n");
   91.41 +        }
   91.42 +        return sb.toString();
   91.43 +    }
   91.44      
   91.45      @Compare public String cannotCallNonStaticMethodWithNull() throws Exception {
   91.46          StaticUse.class.getMethod("instanceMethod").invoke(null);
   91.47 @@ -69,6 +92,26 @@
   91.48          return StaticUse.class.getMethod("instanceMethod").getReturnType();
   91.49      }
   91.50      
   91.51 +    @Retention(RetentionPolicy.RUNTIME)
   91.52 +    @interface Ann {
   91.53 +    }
   91.54 +    
   91.55 +    @Compare public String annoClass() throws Exception {
   91.56 +        Retention r = Ann.class.getAnnotation(Retention.class);
   91.57 +        assert r != null : "Annotation is present";
   91.58 +        assert r.value() == RetentionPolicy.RUNTIME : "Policy value is OK: " + r.value();
   91.59 +        return r.annotationType().getName();
   91.60 +    }
   91.61 +    
   91.62 +    @Compare public boolean isAnnotation() {
   91.63 +        return Ann.class.isAnnotation();
   91.64 +    }
   91.65 +    @Compare public boolean isNotAnnotation() {
   91.66 +        return String.class.isAnnotation();
   91.67 +    }
   91.68 +    @Compare public boolean isNotAnnotationEnum() {
   91.69 +        return E.class.isAnnotation();
   91.70 +    }
   91.71      enum E { A, B };
   91.72      @Compare public boolean isEnum() {
   91.73          return E.A.getClass().isEnum();
    92.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    92.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipEntryTest.java	Tue Feb 19 15:59:27 2013 +0100
    92.3 @@ -0,0 +1,67 @@
    92.4 +/**
    92.5 + * Back 2 Browser Bytecode Translator
    92.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    92.7 + *
    92.8 + * This program is free software: you can redistribute it and/or modify
    92.9 + * it under the terms of the GNU General Public License as published by
   92.10 + * the Free Software Foundation, version 2 of the License.
   92.11 + *
   92.12 + * This program is distributed in the hope that it will be useful,
   92.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   92.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   92.15 + * GNU General Public License for more details.
   92.16 + *
   92.17 + * You should have received a copy of the GNU General Public License
   92.18 + * along with this program. Look for COPYING file in the top folder.
   92.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   92.20 + */
   92.21 +package org.apidesign.bck2brwsr.vmtest.impl;
   92.22 +
   92.23 +import java.io.ByteArrayInputStream;
   92.24 +import java.io.IOException;
   92.25 +import java.io.InputStream;
   92.26 +import org.apidesign.bck2brwsr.emul.zip.FastJar;
   92.27 +import org.testng.annotations.Test;
   92.28 +import static org.testng.Assert.*;
   92.29 +
   92.30 +/**
   92.31 + *
   92.32 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   92.33 + */
   92.34 +@GenerateZip(name = "five.zip", contents = {
   92.35 +    "1.txt", "one",
   92.36 +    "2.txt", "duo",
   92.37 +    "3.txt", "three",
   92.38 +    "4.txt", "four",
   92.39 +    "5.txt", "five"
   92.40 +})
   92.41 +public class ZipEntryTest {
   92.42 +    @Test
   92.43 +    public void readEntriesEffectively() throws IOException {
   92.44 +        InputStream is = ZipEntryTest.class.getResourceAsStream("five.zip");
   92.45 +        byte[] arr = new byte[is.available()];
   92.46 +        int len = is.read(arr);
   92.47 +        assertEquals(len, arr.length, "Read fully");
   92.48 +        
   92.49 +        FastJar fj = new FastJar(arr);
   92.50 +        FastJar.Entry[] entrs = fj.list();
   92.51 +        
   92.52 +        assertEquals(5, entrs.length, "Five entries");
   92.53 +        
   92.54 +        for (int i = 1; i <= 5; i++) {
   92.55 +            FastJar.Entry en = entrs[i - 1];
   92.56 +            assertEquals(en.name, i + ".txt");
   92.57 +//            assertEquals(cis.cnt, 0, "Content of the file should be skipped, not read");
   92.58 +        }
   92.59 +        
   92.60 +        assertContent("three", fj.getInputStream(entrs[3 - 1]), "read OK");
   92.61 +        assertContent("five", fj.getInputStream(entrs[5 - 1]), "read OK");
   92.62 +    }
   92.63 +
   92.64 +    private static void assertContent(String exp, InputStream is, String msg) throws IOException {
   92.65 +        byte[] arr = new byte[512];
   92.66 +        int len = is.read(arr);
   92.67 +        String s = new String(arr, 0, len);
   92.68 +        assertEquals(exp, s, msg);
   92.69 +    }
   92.70 +}
    93.1 --- a/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java	Tue Feb 19 15:33:32 2013 +0100
    93.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java	Tue Feb 19 15:59:27 2013 +0100
    93.3 @@ -25,7 +25,7 @@
    93.4  import org.apidesign.bck2brwsr.core.JavaScriptBody;
    93.5  import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
    93.6  import org.apidesign.bck2brwsr.vmtest.Compare;
    93.7 -import org.apidesign.bck2brwsr.vmtest.HttpResource;
    93.8 +import org.apidesign.bck2brwsr.vmtest.Http;
    93.9  import org.apidesign.bck2brwsr.vmtest.VMTest;
   93.10  import org.testng.annotations.Factory;
   93.11  
   93.12 @@ -54,13 +54,15 @@
   93.13      }
   93.14      
   93.15      @JavaScriptBody(args = { "res", "path" }, body = 
   93.16 -          "var myvm = new bck2brwsr(path);\n"
   93.17 +          "var myvm = bck2brwsr.apply(null, path);\n"
   93.18          + "var cls = myvm.loadClass('java.lang.String');\n"
   93.19          + "return cls.getClass__Ljava_lang_Class_2().getResourceAsStream__Ljava_io_InputStream_2Ljava_lang_String_2(res);\n"
   93.20      )
   93.21      private static native Object loadVMResource(String res, String...path);
   93.22  
   93.23 -    @HttpResource(path = "/readAnEntry.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip")
   93.24 +    @Http({
   93.25 +        @Http.Resource(path = "/readAnEntry.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip")
   93.26 +    })
   93.27      @BrwsrTest  public void canVmLoadResourceFromZip() throws IOException {
   93.28          Object res = loadVMResource("/my/main/file.txt", "/readAnEntry.jar");
   93.29          assert res instanceof InputStream : "Got array of bytes: " + res;
   93.30 @@ -74,6 +76,28 @@
   93.31          assertEquals(ret, "Hello World!", "Can read the bytes");
   93.32      }
   93.33      
   93.34 +    @GenerateZip(name = "cpattr.zip", contents = { 
   93.35 +        "META-INF/MANIFEST.MF", "Manifest-Version: 1.0\n"
   93.36 +        + "Created-By: hand\n"
   93.37 +        + "Class-Path: realJar.jar\n\n\n"
   93.38 +    })
   93.39 +    @Http({
   93.40 +        @Http.Resource(path = "/readComplexEntry.jar", mimeType = "x-application/zip", content = "", resource="cpattr.zip"),
   93.41 +        @Http.Resource(path = "/realJar.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip"),
   93.42 +    })
   93.43 +    @BrwsrTest  public void understandsClassPathAttr() throws IOException {
   93.44 +        Object res = loadVMResource("/my/main/file.txt", "/readComplexEntry.jar");
   93.45 +        assert res instanceof InputStream : "Got array of bytes: " + res;
   93.46 +        InputStream is = (InputStream)res;
   93.47 +        
   93.48 +        byte[] arr = new byte[4096];
   93.49 +        int len = is.read(arr);
   93.50 +        
   93.51 +        final String ret = new String(arr, 0, len, "UTF-8");
   93.52 +
   93.53 +        assertEquals(ret, "Hello World!", "Can read the bytes from secondary JAR");
   93.54 +    }
   93.55 +    
   93.56      private static void assertEquals(Object real, Object exp, String msg) {
   93.57          assert Objects.equals(exp, real) : msg + " exp: " + exp + " real: " + real;
   93.58      }