Time to merge emul branch to default: Archetype now generates static ZIP on deploy
1.1 --- a/dew/src/main/java/org/apidesign/bck2brwsr/dew/Dew.java Fri Feb 15 11:54:45 2013 +0100
1.2 +++ b/dew/src/main/java/org/apidesign/bck2brwsr/dew/Dew.java Fri Feb 15 21:16:05 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 Fri Feb 15 11:54:45 2013 +0100
2.2 +++ b/dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/app.js Fri Feb 15 21:16:05 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 Fri Feb 15 11:54:45 2013 +0100
3.2 +++ b/emul/compact/pom.xml Fri Feb 15 21:16:05 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 Fri Feb 15 21:16:05 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 Fri Feb 15 21:16:05 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 <= 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 Fri Feb 15 21:16:05 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 & 0xff) << 8) | (b & 0xff))
6.246 + * </pre></blockquote>
6.247 + *
6.248 + * @deprecated This method does not properly convert bytes into characters.
6.249 + * As of JDK 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 Fri Feb 15 21:16:05 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 + * @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 Fri Feb 15 21:16:05 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 Fri Feb 15 21:16:05 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 Fri Feb 15 21:16:05 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 Fri Feb 15 11:54:45 2013 +0100
12.2 +++ b/emul/mini/pom.xml Fri Feb 15 21:16:05 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 Fri Feb 15 11:54:45 2013 +0100
13.2 +++ b/emul/mini/src/main/java/java/lang/Class.java Fri Feb 15 21:16:05 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/String.java Fri Feb 15 11:54:45 2013 +0100
14.2 +++ b/emul/mini/src/main/java/java/lang/String.java Fri Feb 15 21:16:05 2013 +0100
14.3 @@ -335,7 +335,7 @@
14.4 value[i] = (char) (hibyte | (ascii[i + offset] & 0xff));
14.5 }
14.6 }
14.7 - this.r = new String(value, 0, count);
14.8 + initFromCharArray(value, offset, count);
14.9 }
14.10
14.11 /**
15.1 --- a/emul/mini/src/main/java/java/util/zip/Inflater.java Fri Feb 15 11:54:45 2013 +0100
15.2 +++ b/emul/mini/src/main/java/java/util/zip/Inflater.java Fri Feb 15 21:16:05 2013 +0100
15.3 @@ -1,44 +1,30 @@
15.4 -/* Inflater.java - Decompress a data stream
15.5 - Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
15.6 -
15.7 -This file is part of GNU Classpath.
15.8 -
15.9 -GNU Classpath is free software; you can redistribute it and/or modify
15.10 -it under the terms of the GNU General Public License as published by
15.11 -the Free Software Foundation; either version 2, or (at your option)
15.12 -any later version.
15.13 -
15.14 -GNU Classpath is distributed in the hope that it will be useful, but
15.15 -WITHOUT ANY WARRANTY; without even the implied warranty of
15.16 -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15.17 -General Public License for more details.
15.18 -
15.19 -You should have received a copy of the GNU General Public License
15.20 -along with GNU Classpath; see the file COPYING. If not, write to the
15.21 -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
15.22 -02111-1307 USA.
15.23 -
15.24 -Linking this library statically or dynamically with other modules is
15.25 -making a combined work based on this library. Thus, the terms and
15.26 -conditions of the GNU General Public License cover the whole
15.27 -combination.
15.28 -
15.29 -As a special exception, the copyright holders of this library give you
15.30 -permission to link this library with independent modules to produce an
15.31 -executable, regardless of the license terms of these independent
15.32 -modules, and to copy and distribute the resulting executable under
15.33 -terms of your choice, provided that you also meet, for each linked
15.34 -independent module, the terms and conditions of the license of that
15.35 -module. An independent module is a module which is not derived from
15.36 -or based on this library. If you modify this library, you may extend
15.37 -this exception to your version of the library, but you are not
15.38 -obligated to do so. If you do not wish to do so, delete this
15.39 -exception statement from your version. */
15.40 +/*
15.41 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
15.42 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
15.43 + *
15.44 + * This code is free software; you can redistribute it and/or modify it
15.45 + * under the terms of the GNU General Public License version 2 only, as
15.46 + * published by the Free Software Foundation. Oracle designates this
15.47 + * particular file as subject to the "Classpath" exception as provided
15.48 + * by Oracle in the LICENSE file that accompanied this code.
15.49 + *
15.50 + * This code is distributed in the hope that it will be useful, but WITHOUT
15.51 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15.52 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15.53 + * version 2 for more details (a copy is included in the LICENSE file that
15.54 + * accompanied this code).
15.55 + *
15.56 + * You should have received a copy of the GNU General Public License version
15.57 + * 2 along with this work; if not, write to the Free Software Foundation,
15.58 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
15.59 + *
15.60 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
15.61 + * or visit www.oracle.com if you need additional information or have any
15.62 + * questions.
15.63 + */
15.64
15.65 package java.util.zip;
15.66
15.67 -import org.apidesign.bck2brwsr.emul.lang.System;
15.68 -
15.69 /**
15.70 * This class provides support for general purpose decompression using the
15.71 * popular ZLIB compression library. The ZLIB compression library was
15.72 @@ -84,1392 +70,241 @@
15.73 * @author David Connelly
15.74 *
15.75 */
15.76 +public
15.77 +class Inflater {
15.78 + private final org.apidesign.bck2brwsr.emul.zip.Inflater impl;
15.79 +
15.80 + /**
15.81 + * Creates a new decompressor. If the parameter 'nowrap' is true then
15.82 + * the ZLIB header and checksum fields will not be used. This provides
15.83 + * compatibility with the compression format used by both GZIP and PKZIP.
15.84 + * <p>
15.85 + * Note: When using the 'nowrap' option it is also necessary to provide
15.86 + * an extra "dummy" byte as input. This is required by the ZLIB native
15.87 + * library in order to support certain optimizations.
15.88 + *
15.89 + * @param nowrap if true then support GZIP compatible compression
15.90 + */
15.91 + public Inflater(boolean nowrap) {
15.92 + if (getClass() == org.apidesign.bck2brwsr.emul.zip.Inflater.class) {
15.93 + impl = null;
15.94 + } else {
15.95 + impl = new org.apidesign.bck2brwsr.emul.zip.Inflater(nowrap);
15.96 + }
15.97 + }
15.98
15.99 -/* Written using on-line Java Platform 1.2 API Specification
15.100 - * and JCL book.
15.101 - * Believed complete and correct.
15.102 - */
15.103 + /**
15.104 + * Creates a new decompressor.
15.105 + */
15.106 + public Inflater() {
15.107 + this(false);
15.108 + }
15.109
15.110 -/**
15.111 - * Inflater is used to decompress data that has been compressed according
15.112 - * to the "deflate" standard described in rfc1950.
15.113 - *
15.114 - * The usage is as following. First you have to set some input with
15.115 - * <code>setInput()</code>, then inflate() it. If inflate doesn't
15.116 - * inflate any bytes there may be three reasons:
15.117 - * <ul>
15.118 - * <li>needsInput() returns true because the input buffer is empty.
15.119 - * You have to provide more input with <code>setInput()</code>.
15.120 - * NOTE: needsInput() also returns true when, the stream is finished.
15.121 - * </li>
15.122 - * <li>needsDictionary() returns true, you have to provide a preset
15.123 - * dictionary with <code>setDictionary()</code>.</li>
15.124 - * <li>finished() returns true, the inflater has finished.</li>
15.125 - * </ul>
15.126 - * Once the first output byte is produced, a dictionary will not be
15.127 - * needed at a later stage.
15.128 - *
15.129 - * @author John Leuner, Jochen Hoenicke
15.130 - * @author Tom Tromey
15.131 - * @date May 17, 1999
15.132 - * @since JDK 1.1
15.133 - */
15.134 -public class Inflater
15.135 -{
15.136 - /* Copy lengths for literal codes 257..285 */
15.137 - private static final int CPLENS[] =
15.138 - {
15.139 - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
15.140 - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
15.141 - };
15.142 -
15.143 - /* Extra bits for literal codes 257..285 */
15.144 - private static final int CPLEXT[] =
15.145 - {
15.146 - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
15.147 - 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
15.148 - };
15.149 + /**
15.150 + * Sets input data for decompression. Should be called whenever
15.151 + * needsInput() returns true indicating that more input data is
15.152 + * required.
15.153 + * @param b the input data bytes
15.154 + * @param off the start offset of the input data
15.155 + * @param len the length of the input data
15.156 + * @see Inflater#needsInput
15.157 + */
15.158 + public void setInput(byte[] b, int off, int len) {
15.159 + impl.setInput(b, off, len);
15.160 + }
15.161
15.162 - /* Copy offsets for distance codes 0..29 */
15.163 - private static final int CPDIST[] = {
15.164 - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
15.165 - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
15.166 - 8193, 12289, 16385, 24577
15.167 - };
15.168 -
15.169 - /* Extra bits for distance codes */
15.170 - private static final int CPDEXT[] = {
15.171 - 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
15.172 - 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
15.173 - 12, 12, 13, 13
15.174 - };
15.175 + /**
15.176 + * Sets input data for decompression. Should be called whenever
15.177 + * needsInput() returns true indicating that more input data is
15.178 + * required.
15.179 + * @param b the input data bytes
15.180 + * @see Inflater#needsInput
15.181 + */
15.182 + public void setInput(byte[] b) {
15.183 + impl.setInput(b);
15.184 + }
15.185
15.186 - /* This are the state in which the inflater can be. */
15.187 - private static final int DECODE_HEADER = 0;
15.188 - private static final int DECODE_DICT = 1;
15.189 - private static final int DECODE_BLOCKS = 2;
15.190 - private static final int DECODE_STORED_LEN1 = 3;
15.191 - private static final int DECODE_STORED_LEN2 = 4;
15.192 - private static final int DECODE_STORED = 5;
15.193 - private static final int DECODE_DYN_HEADER = 6;
15.194 - private static final int DECODE_HUFFMAN = 7;
15.195 - private static final int DECODE_HUFFMAN_LENBITS = 8;
15.196 - private static final int DECODE_HUFFMAN_DIST = 9;
15.197 - private static final int DECODE_HUFFMAN_DISTBITS = 10;
15.198 - private static final int DECODE_CHKSUM = 11;
15.199 - private static final int FINISHED = 12;
15.200 + /**
15.201 + * Sets the preset dictionary to the given array of bytes. Should be
15.202 + * called when inflate() returns 0 and needsDictionary() returns true
15.203 + * indicating that a preset dictionary is required. The method getAdler()
15.204 + * can be used to get the Adler-32 value of the dictionary needed.
15.205 + * @param b the dictionary data bytes
15.206 + * @param off the start offset of the data
15.207 + * @param len the length of the data
15.208 + * @see Inflater#needsDictionary
15.209 + * @see Inflater#getAdler
15.210 + */
15.211 + public void setDictionary(byte[] b, int off, int len) {
15.212 + impl.setDictionary(b, off, len);
15.213 + }
15.214
15.215 - /** This variable contains the current state. */
15.216 - private int mode;
15.217 + /**
15.218 + * Sets the preset dictionary to the given array of bytes. Should be
15.219 + * called when inflate() returns 0 and needsDictionary() returns true
15.220 + * indicating that a preset dictionary is required. The method getAdler()
15.221 + * can be used to get the Adler-32 value of the dictionary needed.
15.222 + * @param b the dictionary data bytes
15.223 + * @see Inflater#needsDictionary
15.224 + * @see Inflater#getAdler
15.225 + */
15.226 + public void setDictionary(byte[] b) {
15.227 + impl.setDictionary(b);
15.228 + }
15.229
15.230 - /**
15.231 - * The adler checksum of the dictionary or of the decompressed
15.232 - * stream, as it is written in the header resp. footer of the
15.233 - * compressed stream. <br>
15.234 - *
15.235 - * Only valid if mode is DECODE_DICT or DECODE_CHKSUM.
15.236 - */
15.237 - private int readAdler;
15.238 - /**
15.239 - * The number of bits needed to complete the current state. This
15.240 - * is valid, if mode is DECODE_DICT, DECODE_CHKSUM,
15.241 - * DECODE_HUFFMAN_LENBITS or DECODE_HUFFMAN_DISTBITS.
15.242 - */
15.243 - private int neededBits;
15.244 - private int repLength, repDist;
15.245 - private int uncomprLen;
15.246 - /**
15.247 - * True, if the last block flag was set in the last block of the
15.248 - * inflated stream. This means that the stream ends after the
15.249 - * current block.
15.250 - */
15.251 - private boolean isLastBlock;
15.252 + /**
15.253 + * Returns the total number of bytes remaining in the input buffer.
15.254 + * This can be used to find out what bytes still remain in the input
15.255 + * buffer after decompression has finished.
15.256 + * @return the total number of bytes remaining in the input buffer
15.257 + */
15.258 + public int getRemaining() {
15.259 + return impl.getRemaining();
15.260 + }
15.261
15.262 - /**
15.263 - * The total number of inflated bytes.
15.264 - */
15.265 - private long totalOut;
15.266 - /**
15.267 - * The total number of bytes set with setInput(). This is not the
15.268 - * value returned by getTotalIn(), since this also includes the
15.269 - * unprocessed input.
15.270 - */
15.271 - private long totalIn;
15.272 - /**
15.273 - * This variable stores the nowrap flag that was given to the constructor.
15.274 - * True means, that the inflated stream doesn't contain a header nor the
15.275 - * checksum in the footer.
15.276 - */
15.277 - private boolean nowrap;
15.278 + /**
15.279 + * Returns true if no data remains in the input buffer. This can
15.280 + * be used to determine if #setInput should be called in order
15.281 + * to provide more input.
15.282 + * @return true if no data remains in the input buffer
15.283 + */
15.284 + public boolean needsInput() {
15.285 + return impl.needsInput();
15.286 + }
15.287
15.288 - private StreamManipulator input;
15.289 - private OutputWindow outputWindow;
15.290 - private InflaterDynHeader dynHeader;
15.291 - private InflaterHuffmanTree litlenTree, distTree;
15.292 - private Adler32 adler;
15.293 + /**
15.294 + * Returns true if a preset dictionary is needed for decompression.
15.295 + * @return true if a preset dictionary is needed for decompression
15.296 + * @see Inflater#setDictionary
15.297 + */
15.298 + public boolean needsDictionary() {
15.299 + return impl.needsDictionary();
15.300 + }
15.301
15.302 - /**
15.303 - * Creates a new inflater.
15.304 - */
15.305 - public Inflater ()
15.306 - {
15.307 - this (false);
15.308 - }
15.309 + /**
15.310 + * Returns true if the end of the compressed data stream has been
15.311 + * reached.
15.312 + * @return true if the end of the compressed data stream has been
15.313 + * reached
15.314 + */
15.315 + public boolean finished() {
15.316 + return impl.finished();
15.317 + }
15.318
15.319 - /**
15.320 - * Creates a new inflater.
15.321 - * @param nowrap true if no header and checksum field appears in the
15.322 - * stream. This is used for GZIPed input. For compatibility with
15.323 - * Sun JDK you should provide one byte of input more than needed in
15.324 - * this case.
15.325 - */
15.326 - public Inflater (boolean nowrap)
15.327 - {
15.328 - this.nowrap = nowrap;
15.329 - this.adler = new Adler32();
15.330 - input = new StreamManipulator();
15.331 - outputWindow = new OutputWindow();
15.332 - mode = nowrap ? DECODE_BLOCKS : DECODE_HEADER;
15.333 - }
15.334 + /**
15.335 + * Uncompresses bytes into specified buffer. Returns actual number
15.336 + * of bytes uncompressed. A return value of 0 indicates that
15.337 + * needsInput() or needsDictionary() should be called in order to
15.338 + * determine if more input data or a preset dictionary is required.
15.339 + * In the latter case, getAdler() can be used to get the Adler-32
15.340 + * value of the dictionary required.
15.341 + * @param b the buffer for the uncompressed data
15.342 + * @param off the start offset of the data
15.343 + * @param len the maximum number of uncompressed bytes
15.344 + * @return the actual number of uncompressed bytes
15.345 + * @exception DataFormatException if the compressed data format is invalid
15.346 + * @see Inflater#needsInput
15.347 + * @see Inflater#needsDictionary
15.348 + */
15.349 + public int inflate(byte[] b, int off, int len)
15.350 + throws DataFormatException
15.351 + {
15.352 + return impl.inflate(b, off, len);
15.353 + }
15.354
15.355 - /**
15.356 - * Finalizes this object.
15.357 - */
15.358 - protected void finalize ()
15.359 - {
15.360 - /* Exists only for compatibility */
15.361 - }
15.362 + /**
15.363 + * Uncompresses bytes into specified buffer. Returns actual number
15.364 + * of bytes uncompressed. A return value of 0 indicates that
15.365 + * needsInput() or needsDictionary() should be called in order to
15.366 + * determine if more input data or a preset dictionary is required.
15.367 + * In the latter case, getAdler() can be used to get the Adler-32
15.368 + * value of the dictionary required.
15.369 + * @param b the buffer for the uncompressed data
15.370 + * @return the actual number of uncompressed bytes
15.371 + * @exception DataFormatException if the compressed data format is invalid
15.372 + * @see Inflater#needsInput
15.373 + * @see Inflater#needsDictionary
15.374 + */
15.375 + public int inflate(byte[] b) throws DataFormatException {
15.376 + return impl.inflate(b);
15.377 + }
15.378
15.379 - /**
15.380 - * Frees all objects allocated by the inflater. There's no reason
15.381 - * to call this, since you can just rely on garbage collection (even
15.382 - * for the Sun implementation). Exists only for compatibility
15.383 - * with Sun's JDK, where the compressor allocates native memory.
15.384 - * If you call any method (even reset) afterwards the behaviour is
15.385 - * <i>undefined</i>.
15.386 - * @deprecated Just clear all references to inflater instead.
15.387 - */
15.388 - public void end ()
15.389 - {
15.390 - outputWindow = null;
15.391 - input = null;
15.392 - dynHeader = null;
15.393 - litlenTree = null;
15.394 - distTree = null;
15.395 - adler = null;
15.396 - }
15.397 + /**
15.398 + * Returns the ADLER-32 value of the uncompressed data.
15.399 + * @return the ADLER-32 value of the uncompressed data
15.400 + */
15.401 + public int getAdler() {
15.402 + return impl.getAdler();
15.403 + }
15.404
15.405 - /**
15.406 - * Returns true, if the inflater has finished. This means, that no
15.407 - * input is needed and no output can be produced.
15.408 - */
15.409 - public boolean finished()
15.410 - {
15.411 - return mode == FINISHED && outputWindow.getAvailable() == 0;
15.412 - }
15.413 + /**
15.414 + * Returns the total number of compressed bytes input so far.
15.415 + *
15.416 + * <p>Since the number of bytes may be greater than
15.417 + * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now
15.418 + * the preferred means of obtaining this information.</p>
15.419 + *
15.420 + * @return the total number of compressed bytes input so far
15.421 + */
15.422 + public int getTotalIn() {
15.423 + return impl.getTotalIn();
15.424 + }
15.425
15.426 - /**
15.427 - * Gets the adler checksum. This is either the checksum of all
15.428 - * uncompressed bytes returned by inflate(), or if needsDictionary()
15.429 - * returns true (and thus no output was yet produced) this is the
15.430 - * adler checksum of the expected dictionary.
15.431 - * @returns the adler checksum.
15.432 - */
15.433 - public int getAdler()
15.434 - {
15.435 - return needsDictionary() ? readAdler : (int) adler.getValue();
15.436 - }
15.437 -
15.438 - /**
15.439 - * Gets the number of unprocessed input. Useful, if the end of the
15.440 - * stream is reached and you want to further process the bytes after
15.441 - * the deflate stream.
15.442 - * @return the number of bytes of the input which were not processed.
15.443 - */
15.444 - public int getRemaining()
15.445 - {
15.446 - return input.getAvailableBytes();
15.447 - }
15.448 -
15.449 - /**
15.450 - * Gets the total number of processed compressed input bytes.
15.451 - * @return the total number of bytes of processed input bytes.
15.452 - */
15.453 - public int getTotalIn()
15.454 - {
15.455 - return (int)getBytesRead();
15.456 - }
15.457 -
15.458 - /**
15.459 - * Gets the total number of output bytes returned by inflate().
15.460 - * @return the total number of output bytes.
15.461 - */
15.462 - public int getTotalOut()
15.463 - {
15.464 - return (int)totalOut;
15.465 - }
15.466 -
15.467 - public long getBytesWritten() {
15.468 - return totalOut;
15.469 - }
15.470 + /**
15.471 + * Returns the total number of compressed bytes input so far.</p>
15.472 + *
15.473 + * @return the total (non-negative) number of compressed bytes input so far
15.474 + * @since 1.5
15.475 + */
15.476 + public long getBytesRead() {
15.477 + return impl.getBytesRead();
15.478 + }
15.479
15.480 - public long getBytesRead() {
15.481 - return totalIn - getRemaining();
15.482 - }
15.483 -
15.484 + /**
15.485 + * Returns the total number of uncompressed bytes output so far.
15.486 + *
15.487 + * <p>Since the number of bytes may be greater than
15.488 + * Integer.MAX_VALUE, the {@link #getBytesWritten()} method is now
15.489 + * the preferred means of obtaining this information.</p>
15.490 + *
15.491 + * @return the total number of uncompressed bytes output so far
15.492 + */
15.493 + public int getTotalOut() {
15.494 + return impl.getTotalOut();
15.495 + }
15.496
15.497 - /**
15.498 - * Inflates the compressed stream to the output buffer. If this
15.499 - * returns 0, you should check, whether needsDictionary(),
15.500 - * needsInput() or finished() returns true, to determine why no
15.501 - * further output is produced.
15.502 - * @param buffer the output buffer.
15.503 - * @return the number of bytes written to the buffer, 0 if no further
15.504 - * output can be produced.
15.505 - * @exception DataFormatException if deflated stream is invalid.
15.506 - * @exception IllegalArgumentException if buf has length 0.
15.507 - */
15.508 - public int inflate (byte[] buf) throws DataFormatException
15.509 - {
15.510 - return inflate (buf, 0, buf.length);
15.511 - }
15.512 + /**
15.513 + * Returns the total number of uncompressed bytes output so far.</p>
15.514 + *
15.515 + * @return the total (non-negative) number of uncompressed bytes output so far
15.516 + * @since 1.5
15.517 + */
15.518 + public long getBytesWritten() {
15.519 + return impl.getBytesWritten();
15.520 + }
15.521
15.522 - /**
15.523 - * Inflates the compressed stream to the output buffer. If this
15.524 - * returns 0, you should check, whether needsDictionary(),
15.525 - * needsInput() or finished() returns true, to determine why no
15.526 - * further output is produced.
15.527 - * @param buffer the output buffer.
15.528 - * @param off the offset into buffer where the output should start.
15.529 - * @param len the maximum length of the output.
15.530 - * @return the number of bytes written to the buffer, 0 if no further
15.531 - * output can be produced.
15.532 - * @exception DataFormatException if deflated stream is invalid.
15.533 - * @exception IndexOutOfBoundsException if the off and/or len are wrong.
15.534 - */
15.535 - public int inflate (byte[] buf, int off, int len) throws DataFormatException
15.536 - {
15.537 - /* Special case: len may be zero */
15.538 - if (len == 0)
15.539 - return 0;
15.540 - /* Check for correct buff, off, len triple */
15.541 - if (0 > off || off > off + len || off + len > buf.length)
15.542 - throw new ArrayIndexOutOfBoundsException();
15.543 - int count = 0;
15.544 - int more;
15.545 - do
15.546 - {
15.547 - if (mode != DECODE_CHKSUM)
15.548 - {
15.549 - /* Don't give away any output, if we are waiting for the
15.550 - * checksum in the input stream.
15.551 - *
15.552 - * With this trick we have always:
15.553 - * needsInput() and not finished()
15.554 - * implies more output can be produced.
15.555 - */
15.556 - more = outputWindow.copyOutput(buf, off, len);
15.557 - adler.update(buf, off, more);
15.558 - off += more;
15.559 - count += more;
15.560 - totalOut += more;
15.561 - len -= more;
15.562 - if (len == 0)
15.563 - return count;
15.564 - }
15.565 - }
15.566 - while (decode() || (outputWindow.getAvailable() > 0
15.567 - && mode != DECODE_CHKSUM));
15.568 - return count;
15.569 - }
15.570 + /**
15.571 + * Resets inflater so that a new set of input data can be processed.
15.572 + */
15.573 + public void reset() {
15.574 + impl.reset();
15.575 + }
15.576
15.577 - /**
15.578 - * Returns true, if a preset dictionary is needed to inflate the input.
15.579 - */
15.580 - public boolean needsDictionary ()
15.581 - {
15.582 - return mode == DECODE_DICT && neededBits == 0;
15.583 - }
15.584 + /**
15.585 + * Closes the decompressor and discards any unprocessed input.
15.586 + * This method should be called when the decompressor is no longer
15.587 + * being used, but will also be called automatically by the finalize()
15.588 + * method. Once this method is called, the behavior of the Inflater
15.589 + * object is undefined.
15.590 + */
15.591 + public void end() {
15.592 + impl.end();
15.593 + }
15.594
15.595 - /**
15.596 - * Returns true, if the input buffer is empty.
15.597 - * You should then call setInput(). <br>
15.598 - *
15.599 - * <em>NOTE</em>: This method also returns true when the stream is finished.
15.600 - */
15.601 - public boolean needsInput ()
15.602 - {
15.603 - return input.needsInput ();
15.604 - }
15.605 -
15.606 - /**
15.607 - * Resets the inflater so that a new stream can be decompressed. All
15.608 - * pending input and output will be discarded.
15.609 - */
15.610 - public void reset ()
15.611 - {
15.612 - mode = nowrap ? DECODE_BLOCKS : DECODE_HEADER;
15.613 - totalIn = totalOut = 0;
15.614 - input.reset();
15.615 - outputWindow.reset();
15.616 - dynHeader = null;
15.617 - litlenTree = null;
15.618 - distTree = null;
15.619 - isLastBlock = false;
15.620 - adler.reset();
15.621 - }
15.622 -
15.623 - /**
15.624 - * Sets the preset dictionary. This should only be called, if
15.625 - * needsDictionary() returns true and it should set the same
15.626 - * dictionary, that was used for deflating. The getAdler()
15.627 - * function returns the checksum of the dictionary needed.
15.628 - * @param buffer the dictionary.
15.629 - * @exception IllegalStateException if no dictionary is needed.
15.630 - * @exception IllegalArgumentException if the dictionary checksum is
15.631 - * wrong.
15.632 - */
15.633 - public void setDictionary (byte[] buffer)
15.634 - {
15.635 - setDictionary(buffer, 0, buffer.length);
15.636 - }
15.637 -
15.638 - /**
15.639 - * Sets the preset dictionary. This should only be called, if
15.640 - * needsDictionary() returns true and it should set the same
15.641 - * dictionary, that was used for deflating. The getAdler()
15.642 - * function returns the checksum of the dictionary needed.
15.643 - * @param buffer the dictionary.
15.644 - * @param off the offset into buffer where the dictionary starts.
15.645 - * @param len the length of the dictionary.
15.646 - * @exception IllegalStateException if no dictionary is needed.
15.647 - * @exception IllegalArgumentException if the dictionary checksum is
15.648 - * wrong.
15.649 - * @exception IndexOutOfBoundsException if the off and/or len are wrong.
15.650 - */
15.651 - public void setDictionary (byte[] buffer, int off, int len)
15.652 - {
15.653 - if (!needsDictionary())
15.654 - throw new IllegalStateException();
15.655 -
15.656 - adler.update(buffer, off, len);
15.657 - if ((int) adler.getValue() != readAdler)
15.658 - throw new IllegalArgumentException("Wrong adler checksum");
15.659 - adler.reset();
15.660 - outputWindow.copyDict(buffer, off, len);
15.661 - mode = DECODE_BLOCKS;
15.662 - }
15.663 -
15.664 - /**
15.665 - * Sets the input. This should only be called, if needsInput()
15.666 - * returns true.
15.667 - * @param buffer the input.
15.668 - * @exception IllegalStateException if no input is needed.
15.669 - */
15.670 - public void setInput (byte[] buf)
15.671 - {
15.672 - setInput (buf, 0, buf.length);
15.673 - }
15.674 -
15.675 - /**
15.676 - * Sets the input. This should only be called, if needsInput()
15.677 - * returns true.
15.678 - * @param buffer the input.
15.679 - * @param off the offset into buffer where the input starts.
15.680 - * @param len the length of the input.
15.681 - * @exception IllegalStateException if no input is needed.
15.682 - * @exception IndexOutOfBoundsException if the off and/or len are wrong.
15.683 - */
15.684 - public void setInput (byte[] buf, int off, int len)
15.685 - {
15.686 - input.setInput (buf, off, len);
15.687 - totalIn += len;
15.688 - }
15.689 - private static final int DEFLATED = 8;
15.690 - /**
15.691 - * Decodes the deflate header.
15.692 - * @return false if more input is needed.
15.693 - * @exception DataFormatException if header is invalid.
15.694 - */
15.695 - private boolean decodeHeader () throws DataFormatException
15.696 - {
15.697 - int header = input.peekBits(16);
15.698 - if (header < 0)
15.699 - return false;
15.700 - input.dropBits(16);
15.701 -
15.702 - /* The header is written in "wrong" byte order */
15.703 - header = ((header << 8) | (header >> 8)) & 0xffff;
15.704 - if (header % 31 != 0)
15.705 - throw new DataFormatException("Header checksum illegal");
15.706 -
15.707 - if ((header & 0x0f00) != (DEFLATED << 8))
15.708 - throw new DataFormatException("Compression Method unknown");
15.709 -
15.710 - /* Maximum size of the backwards window in bits.
15.711 - * We currently ignore this, but we could use it to make the
15.712 - * inflater window more space efficient. On the other hand the
15.713 - * full window (15 bits) is needed most times, anyway.
15.714 - int max_wbits = ((header & 0x7000) >> 12) + 8;
15.715 + /**
15.716 + * Closes the decompressor when garbage is collected.
15.717 */
15.718 -
15.719 - if ((header & 0x0020) == 0) // Dictionary flag?
15.720 - {
15.721 - mode = DECODE_BLOCKS;
15.722 - }
15.723 - else
15.724 - {
15.725 - mode = DECODE_DICT;
15.726 - neededBits = 32;
15.727 - }
15.728 - return true;
15.729 - }
15.730 -
15.731 - /**
15.732 - * Decodes the dictionary checksum after the deflate header.
15.733 - * @return false if more input is needed.
15.734 - */
15.735 - private boolean decodeDict ()
15.736 - {
15.737 - while (neededBits > 0)
15.738 - {
15.739 - int dictByte = input.peekBits(8);
15.740 - if (dictByte < 0)
15.741 - return false;
15.742 - input.dropBits(8);
15.743 - readAdler = (readAdler << 8) | dictByte;
15.744 - neededBits -= 8;
15.745 - }
15.746 - return false;
15.747 - }
15.748 -
15.749 - /**
15.750 - * Decodes the huffman encoded symbols in the input stream.
15.751 - * @return false if more input is needed, true if output window is
15.752 - * full or the current block ends.
15.753 - * @exception DataFormatException if deflated stream is invalid.
15.754 - */
15.755 - private boolean decodeHuffman () throws DataFormatException
15.756 - {
15.757 - int free = outputWindow.getFreeSpace();
15.758 - while (free >= 258)
15.759 - {
15.760 - int symbol;
15.761 - switch (mode)
15.762 - {
15.763 - case DECODE_HUFFMAN:
15.764 - /* This is the inner loop so it is optimized a bit */
15.765 - while (((symbol = litlenTree.getSymbol(input)) & ~0xff) == 0)
15.766 - {
15.767 - outputWindow.write(symbol);
15.768 - if (--free < 258)
15.769 - return true;
15.770 - }
15.771 - if (symbol < 257)
15.772 - {
15.773 - if (symbol < 0)
15.774 - return false;
15.775 - else
15.776 - {
15.777 - /* symbol == 256: end of block */
15.778 - distTree = null;
15.779 - litlenTree = null;
15.780 - mode = DECODE_BLOCKS;
15.781 - return true;
15.782 - }
15.783 - }
15.784 -
15.785 - try
15.786 - {
15.787 - repLength = CPLENS[symbol - 257];
15.788 - neededBits = CPLEXT[symbol - 257];
15.789 - }
15.790 - catch (ArrayIndexOutOfBoundsException ex)
15.791 - {
15.792 - throw new DataFormatException("Illegal rep length code");
15.793 - }
15.794 - /* fall through */
15.795 - case DECODE_HUFFMAN_LENBITS:
15.796 - if (neededBits > 0)
15.797 - {
15.798 - mode = DECODE_HUFFMAN_LENBITS;
15.799 - int i = input.peekBits(neededBits);
15.800 - if (i < 0)
15.801 - return false;
15.802 - input.dropBits(neededBits);
15.803 - repLength += i;
15.804 - }
15.805 - mode = DECODE_HUFFMAN_DIST;
15.806 - /* fall through */
15.807 - case DECODE_HUFFMAN_DIST:
15.808 - symbol = distTree.getSymbol(input);
15.809 - if (symbol < 0)
15.810 - return false;
15.811 - try
15.812 - {
15.813 - repDist = CPDIST[symbol];
15.814 - neededBits = CPDEXT[symbol];
15.815 - }
15.816 - catch (ArrayIndexOutOfBoundsException ex)
15.817 - {
15.818 - throw new DataFormatException("Illegal rep dist code");
15.819 - }
15.820 - /* fall through */
15.821 - case DECODE_HUFFMAN_DISTBITS:
15.822 - if (neededBits > 0)
15.823 - {
15.824 - mode = DECODE_HUFFMAN_DISTBITS;
15.825 - int i = input.peekBits(neededBits);
15.826 - if (i < 0)
15.827 - return false;
15.828 - input.dropBits(neededBits);
15.829 - repDist += i;
15.830 - }
15.831 - outputWindow.repeat(repLength, repDist);
15.832 - free -= repLength;
15.833 - mode = DECODE_HUFFMAN;
15.834 - break;
15.835 - default:
15.836 - throw new IllegalStateException();
15.837 - }
15.838 - }
15.839 - return true;
15.840 - }
15.841 -
15.842 - /**
15.843 - * Decodes the adler checksum after the deflate stream.
15.844 - * @return false if more input is needed.
15.845 - * @exception DataFormatException if checksum doesn't match.
15.846 - */
15.847 - private boolean decodeChksum () throws DataFormatException
15.848 - {
15.849 - while (neededBits > 0)
15.850 - {
15.851 - int chkByte = input.peekBits(8);
15.852 - if (chkByte < 0)
15.853 - return false;
15.854 - input.dropBits(8);
15.855 - readAdler = (readAdler << 8) | chkByte;
15.856 - neededBits -= 8;
15.857 - }
15.858 - if ((int) adler.getValue() != readAdler)
15.859 - throw new DataFormatException("Adler chksum doesn't match: "
15.860 - +Integer.toHexString((int)adler.getValue())
15.861 - +" vs. "+Integer.toHexString(readAdler));
15.862 - mode = FINISHED;
15.863 - return false;
15.864 - }
15.865 -
15.866 - /**
15.867 - * Decodes the deflated stream.
15.868 - * @return false if more input is needed, or if finished.
15.869 - * @exception DataFormatException if deflated stream is invalid.
15.870 - */
15.871 - private boolean decode () throws DataFormatException
15.872 - {
15.873 - switch (mode)
15.874 - {
15.875 - case DECODE_HEADER:
15.876 - return decodeHeader();
15.877 - case DECODE_DICT:
15.878 - return decodeDict();
15.879 - case DECODE_CHKSUM:
15.880 - return decodeChksum();
15.881 -
15.882 - case DECODE_BLOCKS:
15.883 - if (isLastBlock)
15.884 - {
15.885 - if (nowrap)
15.886 - {
15.887 - mode = FINISHED;
15.888 - return false;
15.889 - }
15.890 - else
15.891 - {
15.892 - input.skipToByteBoundary();
15.893 - neededBits = 32;
15.894 - mode = DECODE_CHKSUM;
15.895 - return true;
15.896 - }
15.897 - }
15.898 -
15.899 - int type = input.peekBits(3);
15.900 - if (type < 0)
15.901 - return false;
15.902 - input.dropBits(3);
15.903 -
15.904 - if ((type & 1) != 0)
15.905 - isLastBlock = true;
15.906 - switch (type >> 1)
15.907 - {
15.908 - case DeflaterConstants.STORED_BLOCK:
15.909 - input.skipToByteBoundary();
15.910 - mode = DECODE_STORED_LEN1;
15.911 - break;
15.912 - case DeflaterConstants.STATIC_TREES:
15.913 - litlenTree = InflaterHuffmanTree.defLitLenTree;
15.914 - distTree = InflaterHuffmanTree.defDistTree;
15.915 - mode = DECODE_HUFFMAN;
15.916 - break;
15.917 - case DeflaterConstants.DYN_TREES:
15.918 - dynHeader = new InflaterDynHeader();
15.919 - mode = DECODE_DYN_HEADER;
15.920 - break;
15.921 - default:
15.922 - throw new DataFormatException("Unknown block type "+type);
15.923 - }
15.924 - return true;
15.925 -
15.926 - case DECODE_STORED_LEN1:
15.927 - {
15.928 - if ((uncomprLen = input.peekBits(16)) < 0)
15.929 - return false;
15.930 - input.dropBits(16);
15.931 - mode = DECODE_STORED_LEN2;
15.932 - }
15.933 - /* fall through */
15.934 - case DECODE_STORED_LEN2:
15.935 - {
15.936 - int nlen = input.peekBits(16);
15.937 - if (nlen < 0)
15.938 - return false;
15.939 - input.dropBits(16);
15.940 - if (nlen != (uncomprLen ^ 0xffff))
15.941 - throw new DataFormatException("broken uncompressed block");
15.942 - mode = DECODE_STORED;
15.943 - }
15.944 - /* fall through */
15.945 - case DECODE_STORED:
15.946 - {
15.947 - int more = outputWindow.copyStored(input, uncomprLen);
15.948 - uncomprLen -= more;
15.949 - if (uncomprLen == 0)
15.950 - {
15.951 - mode = DECODE_BLOCKS;
15.952 - return true;
15.953 - }
15.954 - return !input.needsInput();
15.955 - }
15.956 -
15.957 - case DECODE_DYN_HEADER:
15.958 - if (!dynHeader.decode(input))
15.959 - return false;
15.960 - litlenTree = dynHeader.buildLitLenTree();
15.961 - distTree = dynHeader.buildDistTree();
15.962 - mode = DECODE_HUFFMAN;
15.963 - /* fall through */
15.964 - case DECODE_HUFFMAN:
15.965 - case DECODE_HUFFMAN_LENBITS:
15.966 - case DECODE_HUFFMAN_DIST:
15.967 - case DECODE_HUFFMAN_DISTBITS:
15.968 - return decodeHuffman();
15.969 - case FINISHED:
15.970 - return false;
15.971 - default:
15.972 - throw new IllegalStateException();
15.973 - }
15.974 - }
15.975 -
15.976 -
15.977 - interface DeflaterConstants {
15.978 - final static boolean DEBUGGING = false;
15.979 -
15.980 - final static int STORED_BLOCK = 0;
15.981 - final static int STATIC_TREES = 1;
15.982 - final static int DYN_TREES = 2;
15.983 - final static int PRESET_DICT = 0x20;
15.984 -
15.985 - final static int DEFAULT_MEM_LEVEL = 8;
15.986 -
15.987 - final static int MAX_MATCH = 258;
15.988 - final static int MIN_MATCH = 3;
15.989 -
15.990 - final static int MAX_WBITS = 15;
15.991 - final static int WSIZE = 1 << MAX_WBITS;
15.992 - final static int WMASK = WSIZE - 1;
15.993 -
15.994 - final static int HASH_BITS = DEFAULT_MEM_LEVEL + 7;
15.995 - final static int HASH_SIZE = 1 << HASH_BITS;
15.996 - final static int HASH_MASK = HASH_SIZE - 1;
15.997 - final static int HASH_SHIFT = (HASH_BITS + MIN_MATCH - 1) / MIN_MATCH;
15.998 -
15.999 - final static int MIN_LOOKAHEAD = MAX_MATCH + MIN_MATCH + 1;
15.1000 - final static int MAX_DIST = WSIZE - MIN_LOOKAHEAD;
15.1001 -
15.1002 - final static int PENDING_BUF_SIZE = 1 << (DEFAULT_MEM_LEVEL + 8);
15.1003 - final static int MAX_BLOCK_SIZE = Math.min(65535, PENDING_BUF_SIZE-5);
15.1004 -
15.1005 - final static int DEFLATE_STORED = 0;
15.1006 - final static int DEFLATE_FAST = 1;
15.1007 - final static int DEFLATE_SLOW = 2;
15.1008 -
15.1009 - final static int GOOD_LENGTH[] = { 0,4, 4, 4, 4, 8, 8, 8, 32, 32 };
15.1010 - final static int MAX_LAZY[] = { 0,4, 5, 6, 4,16, 16, 32, 128, 258 };
15.1011 - final static int NICE_LENGTH[] = { 0,8,16,32,16,32,128,128, 258, 258 };
15.1012 - final static int MAX_CHAIN[] = { 0,4, 8,32,16,32,128,256,1024,4096 };
15.1013 - final static int COMPR_FUNC[] = { 0,1, 1, 1, 1, 2, 2, 2, 2, 2 };
15.1014 + protected void finalize() {
15.1015 + end();
15.1016 }
15.1017 - private static class InflaterHuffmanTree {
15.1018 - private final static int MAX_BITLEN = 15;
15.1019 - private short[] tree;
15.1020 -
15.1021 - public static InflaterHuffmanTree defLitLenTree, defDistTree;
15.1022 -
15.1023 - static
15.1024 - {
15.1025 - try
15.1026 - {
15.1027 - byte[] codeLengths = new byte[288];
15.1028 - int i = 0;
15.1029 - while (i < 144)
15.1030 - codeLengths[i++] = 8;
15.1031 - while (i < 256)
15.1032 - codeLengths[i++] = 9;
15.1033 - while (i < 280)
15.1034 - codeLengths[i++] = 7;
15.1035 - while (i < 288)
15.1036 - codeLengths[i++] = 8;
15.1037 - defLitLenTree = new InflaterHuffmanTree(codeLengths);
15.1038 -
15.1039 - codeLengths = new byte[32];
15.1040 - i = 0;
15.1041 - while (i < 32)
15.1042 - codeLengths[i++] = 5;
15.1043 - defDistTree = new InflaterHuffmanTree(codeLengths);
15.1044 - }
15.1045 - catch (DataFormatException ex)
15.1046 - {
15.1047 - throw new IllegalStateException
15.1048 - ("InflaterHuffmanTree: static tree length illegal");
15.1049 - }
15.1050 - }
15.1051 -
15.1052 - /**
15.1053 - * Constructs a Huffman tree from the array of code lengths.
15.1054 - *
15.1055 - * @param codeLengths the array of code lengths
15.1056 - */
15.1057 - public InflaterHuffmanTree(byte[] codeLengths) throws DataFormatException
15.1058 - {
15.1059 - buildTree(codeLengths);
15.1060 - }
15.1061 -
15.1062 - private void buildTree(byte[] codeLengths) throws DataFormatException
15.1063 - {
15.1064 - int[] blCount = new int[MAX_BITLEN+1];
15.1065 - int[] nextCode = new int[MAX_BITLEN+1];
15.1066 - for (int i = 0; i < codeLengths.length; i++)
15.1067 - {
15.1068 - int bits = codeLengths[i];
15.1069 - if (bits > 0)
15.1070 - blCount[bits]++;
15.1071 - }
15.1072 -
15.1073 - int code = 0;
15.1074 - int treeSize = 512;
15.1075 - for (int bits = 1; bits <= MAX_BITLEN; bits++)
15.1076 - {
15.1077 - nextCode[bits] = code;
15.1078 - code += blCount[bits] << (16 - bits);
15.1079 - if (bits >= 10)
15.1080 - {
15.1081 - /* We need an extra table for bit lengths >= 10. */
15.1082 - int start = nextCode[bits] & 0x1ff80;
15.1083 - int end = code & 0x1ff80;
15.1084 - treeSize += (end - start) >> (16 - bits);
15.1085 - }
15.1086 - }
15.1087 - if (code != 65536)
15.1088 - throw new DataFormatException("Code lengths don't add up properly.");
15.1089 -
15.1090 - /* Now create and fill the extra tables from longest to shortest
15.1091 - * bit len. This way the sub trees will be aligned.
15.1092 - */
15.1093 - tree = new short[treeSize];
15.1094 - int treePtr = 512;
15.1095 - for (int bits = MAX_BITLEN; bits >= 10; bits--)
15.1096 - {
15.1097 - int end = code & 0x1ff80;
15.1098 - code -= blCount[bits] << (16 - bits);
15.1099 - int start = code & 0x1ff80;
15.1100 - for (int i = start; i < end; i += 1 << 7)
15.1101 - {
15.1102 - tree[bitReverse(i)]
15.1103 - = (short) ((-treePtr << 4) | bits);
15.1104 - treePtr += 1 << (bits-9);
15.1105 - }
15.1106 - }
15.1107 -
15.1108 - for (int i = 0; i < codeLengths.length; i++)
15.1109 - {
15.1110 - int bits = codeLengths[i];
15.1111 - if (bits == 0)
15.1112 - continue;
15.1113 - code = nextCode[bits];
15.1114 - int revcode = bitReverse(code);
15.1115 - if (bits <= 9)
15.1116 - {
15.1117 - do
15.1118 - {
15.1119 - tree[revcode] = (short) ((i << 4) | bits);
15.1120 - revcode += 1 << bits;
15.1121 - }
15.1122 - while (revcode < 512);
15.1123 - }
15.1124 - else
15.1125 - {
15.1126 - int subTree = tree[revcode & 511];
15.1127 - int treeLen = 1 << (subTree & 15);
15.1128 - subTree = -(subTree >> 4);
15.1129 - do
15.1130 - {
15.1131 - tree[subTree | (revcode >> 9)] = (short) ((i << 4) | bits);
15.1132 - revcode += 1 << bits;
15.1133 - }
15.1134 - while (revcode < treeLen);
15.1135 - }
15.1136 - nextCode[bits] = code + (1 << (16 - bits));
15.1137 - }
15.1138 - }
15.1139 - private final static String bit4Reverse =
15.1140 - "\000\010\004\014\002\012\006\016\001\011\005\015\003\013\007\017";
15.1141 - static short bitReverse(int value) {
15.1142 - return (short) (bit4Reverse.charAt(value & 0xf) << 12
15.1143 - | bit4Reverse.charAt((value >> 4) & 0xf) << 8
15.1144 - | bit4Reverse.charAt((value >> 8) & 0xf) << 4
15.1145 - | bit4Reverse.charAt(value >> 12));
15.1146 - }
15.1147 -
15.1148 - /**
15.1149 - * Reads the next symbol from input. The symbol is encoded using the
15.1150 - * huffman tree.
15.1151 - * @param input the input source.
15.1152 - * @return the next symbol, or -1 if not enough input is available.
15.1153 - */
15.1154 - public int getSymbol(StreamManipulator input) throws DataFormatException
15.1155 - {
15.1156 - int lookahead, symbol;
15.1157 - if ((lookahead = input.peekBits(9)) >= 0)
15.1158 - {
15.1159 - if ((symbol = tree[lookahead]) >= 0)
15.1160 - {
15.1161 - input.dropBits(symbol & 15);
15.1162 - return symbol >> 4;
15.1163 - }
15.1164 - int subtree = -(symbol >> 4);
15.1165 - int bitlen = symbol & 15;
15.1166 - if ((lookahead = input.peekBits(bitlen)) >= 0)
15.1167 - {
15.1168 - symbol = tree[subtree | (lookahead >> 9)];
15.1169 - input.dropBits(symbol & 15);
15.1170 - return symbol >> 4;
15.1171 - }
15.1172 - else
15.1173 - {
15.1174 - int bits = input.getAvailableBits();
15.1175 - lookahead = input.peekBits(bits);
15.1176 - symbol = tree[subtree | (lookahead >> 9)];
15.1177 - if ((symbol & 15) <= bits)
15.1178 - {
15.1179 - input.dropBits(symbol & 15);
15.1180 - return symbol >> 4;
15.1181 - }
15.1182 - else
15.1183 - return -1;
15.1184 - }
15.1185 - }
15.1186 - else
15.1187 - {
15.1188 - int bits = input.getAvailableBits();
15.1189 - lookahead = input.peekBits(bits);
15.1190 - symbol = tree[lookahead];
15.1191 - if (symbol >= 0 && (symbol & 15) <= bits)
15.1192 - {
15.1193 - input.dropBits(symbol & 15);
15.1194 - return symbol >> 4;
15.1195 - }
15.1196 - else
15.1197 - return -1;
15.1198 - }
15.1199 - }
15.1200 - }
15.1201 - private static class InflaterDynHeader
15.1202 - {
15.1203 - private static final int LNUM = 0;
15.1204 - private static final int DNUM = 1;
15.1205 - private static final int BLNUM = 2;
15.1206 - private static final int BLLENS = 3;
15.1207 - private static final int LENS = 4;
15.1208 - private static final int REPS = 5;
15.1209 -
15.1210 - private static final int repMin[] = { 3, 3, 11 };
15.1211 - private static final int repBits[] = { 2, 3, 7 };
15.1212 -
15.1213 -
15.1214 - private byte[] blLens;
15.1215 - private byte[] litdistLens;
15.1216 -
15.1217 - private InflaterHuffmanTree blTree;
15.1218 -
15.1219 - private int mode;
15.1220 - private int lnum, dnum, blnum, num;
15.1221 - private int repSymbol;
15.1222 - private byte lastLen;
15.1223 - private int ptr;
15.1224 -
15.1225 - private static final int[] BL_ORDER =
15.1226 - { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
15.1227 -
15.1228 - public InflaterDynHeader()
15.1229 - {
15.1230 - }
15.1231 -
15.1232 - public boolean decode(StreamManipulator input) throws DataFormatException
15.1233 - {
15.1234 - decode_loop:
15.1235 - for (;;)
15.1236 - {
15.1237 - switch (mode)
15.1238 - {
15.1239 - case LNUM:
15.1240 - lnum = input.peekBits(5);
15.1241 - if (lnum < 0)
15.1242 - return false;
15.1243 - lnum += 257;
15.1244 - input.dropBits(5);
15.1245 - // System.err.println("LNUM: "+lnum);
15.1246 - mode = DNUM;
15.1247 - /* fall through */
15.1248 - case DNUM:
15.1249 - dnum = input.peekBits(5);
15.1250 - if (dnum < 0)
15.1251 - return false;
15.1252 - dnum++;
15.1253 - input.dropBits(5);
15.1254 - // System.err.println("DNUM: "+dnum);
15.1255 - num = lnum+dnum;
15.1256 - litdistLens = new byte[num];
15.1257 - mode = BLNUM;
15.1258 - /* fall through */
15.1259 - case BLNUM:
15.1260 - blnum = input.peekBits(4);
15.1261 - if (blnum < 0)
15.1262 - return false;
15.1263 - blnum += 4;
15.1264 - input.dropBits(4);
15.1265 - blLens = new byte[19];
15.1266 - ptr = 0;
15.1267 - // System.err.println("BLNUM: "+blnum);
15.1268 - mode = BLLENS;
15.1269 - /* fall through */
15.1270 - case BLLENS:
15.1271 - while (ptr < blnum)
15.1272 - {
15.1273 - int len = input.peekBits(3);
15.1274 - if (len < 0)
15.1275 - return false;
15.1276 - input.dropBits(3);
15.1277 - // System.err.println("blLens["+BL_ORDER[ptr]+"]: "+len);
15.1278 - blLens[BL_ORDER[ptr]] = (byte) len;
15.1279 - ptr++;
15.1280 - }
15.1281 - blTree = new InflaterHuffmanTree(blLens);
15.1282 - blLens = null;
15.1283 - ptr = 0;
15.1284 - mode = LENS;
15.1285 - /* fall through */
15.1286 - case LENS:
15.1287 - {
15.1288 - int symbol;
15.1289 - while (((symbol = blTree.getSymbol(input)) & ~15) == 0)
15.1290 - {
15.1291 - /* Normal case: symbol in [0..15] */
15.1292 -
15.1293 - // System.err.println("litdistLens["+ptr+"]: "+symbol);
15.1294 - litdistLens[ptr++] = lastLen = (byte) symbol;
15.1295 -
15.1296 - if (ptr == num)
15.1297 - {
15.1298 - /* Finished */
15.1299 - return true;
15.1300 - }
15.1301 - }
15.1302 -
15.1303 - /* need more input ? */
15.1304 - if (symbol < 0)
15.1305 - return false;
15.1306 -
15.1307 - /* otherwise repeat code */
15.1308 - if (symbol >= 17)
15.1309 - {
15.1310 - /* repeat zero */
15.1311 - // System.err.println("repeating zero");
15.1312 - lastLen = 0;
15.1313 - }
15.1314 - else
15.1315 - {
15.1316 - if (ptr == 0)
15.1317 - throw new DataFormatException();
15.1318 - }
15.1319 - repSymbol = symbol-16;
15.1320 - mode = REPS;
15.1321 - }
15.1322 - /* fall through */
15.1323 -
15.1324 - case REPS:
15.1325 - {
15.1326 - int bits = repBits[repSymbol];
15.1327 - int count = input.peekBits(bits);
15.1328 - if (count < 0)
15.1329 - return false;
15.1330 - input.dropBits(bits);
15.1331 - count += repMin[repSymbol];
15.1332 - // System.err.println("litdistLens repeated: "+count);
15.1333 -
15.1334 - if (ptr + count > num)
15.1335 - throw new DataFormatException();
15.1336 - while (count-- > 0)
15.1337 - litdistLens[ptr++] = lastLen;
15.1338 -
15.1339 - if (ptr == num)
15.1340 - {
15.1341 - /* Finished */
15.1342 - return true;
15.1343 - }
15.1344 - }
15.1345 - mode = LENS;
15.1346 - continue decode_loop;
15.1347 - }
15.1348 - }
15.1349 - }
15.1350 -
15.1351 - public InflaterHuffmanTree buildLitLenTree() throws DataFormatException
15.1352 - {
15.1353 - byte[] litlenLens = new byte[lnum];
15.1354 - System.arraycopy(litdistLens, 0, litlenLens, 0, lnum);
15.1355 - return new InflaterHuffmanTree(litlenLens);
15.1356 - }
15.1357 -
15.1358 - public InflaterHuffmanTree buildDistTree() throws DataFormatException
15.1359 - {
15.1360 - byte[] distLens = new byte[dnum];
15.1361 - System.arraycopy(litdistLens, lnum, distLens, 0, dnum);
15.1362 - return new InflaterHuffmanTree(distLens);
15.1363 - }
15.1364 - }
15.1365 - /**
15.1366 - * This class allows us to retrieve a specified amount of bits from
15.1367 - * the input buffer, as well as copy big byte blocks.
15.1368 - *
15.1369 - * It uses an int buffer to store up to 31 bits for direct
15.1370 - * manipulation. This guarantees that we can get at least 16 bits,
15.1371 - * but we only need at most 15, so this is all safe.
15.1372 - *
15.1373 - * There are some optimizations in this class, for example, you must
15.1374 - * never peek more then 8 bits more than needed, and you must first
15.1375 - * peek bits before you may drop them. This is not a general purpose
15.1376 - * class but optimized for the behaviour of the Inflater.
15.1377 - *
15.1378 - * @author John Leuner, Jochen Hoenicke
15.1379 - */
15.1380 -
15.1381 - private static class StreamManipulator
15.1382 - {
15.1383 - private byte[] window;
15.1384 - private int window_start = 0;
15.1385 - private int window_end = 0;
15.1386 -
15.1387 - private int buffer = 0;
15.1388 - private int bits_in_buffer = 0;
15.1389 -
15.1390 - /**
15.1391 - * Get the next n bits but don't increase input pointer. n must be
15.1392 - * less or equal 16 and if you if this call succeeds, you must drop
15.1393 - * at least n-8 bits in the next call.
15.1394 - *
15.1395 - * @return the value of the bits, or -1 if not enough bits available. */
15.1396 - public final int peekBits(int n)
15.1397 - {
15.1398 - if (bits_in_buffer < n)
15.1399 - {
15.1400 - if (window_start == window_end)
15.1401 - return -1;
15.1402 - buffer |= (window[window_start++] & 0xff
15.1403 - | (window[window_start++] & 0xff) << 8) << bits_in_buffer;
15.1404 - bits_in_buffer += 16;
15.1405 - }
15.1406 - return buffer & ((1 << n) - 1);
15.1407 - }
15.1408 -
15.1409 - /* Drops the next n bits from the input. You should have called peekBits
15.1410 - * with a bigger or equal n before, to make sure that enough bits are in
15.1411 - * the bit buffer.
15.1412 - */
15.1413 - public final void dropBits(int n)
15.1414 - {
15.1415 - buffer >>>= n;
15.1416 - bits_in_buffer -= n;
15.1417 - }
15.1418 -
15.1419 - /**
15.1420 - * Gets the next n bits and increases input pointer. This is equivalent
15.1421 - * to peekBits followed by dropBits, except for correct error handling.
15.1422 - * @return the value of the bits, or -1 if not enough bits available.
15.1423 - */
15.1424 - public final int getBits(int n)
15.1425 - {
15.1426 - int bits = peekBits(n);
15.1427 - if (bits >= 0)
15.1428 - dropBits(n);
15.1429 - return bits;
15.1430 - }
15.1431 - /**
15.1432 - * Gets the number of bits available in the bit buffer. This must be
15.1433 - * only called when a previous peekBits() returned -1.
15.1434 - * @return the number of bits available.
15.1435 - */
15.1436 - public final int getAvailableBits()
15.1437 - {
15.1438 - return bits_in_buffer;
15.1439 - }
15.1440 -
15.1441 - /**
15.1442 - * Gets the number of bytes available.
15.1443 - * @return the number of bytes available.
15.1444 - */
15.1445 - public final int getAvailableBytes()
15.1446 - {
15.1447 - return window_end - window_start + (bits_in_buffer >> 3);
15.1448 - }
15.1449 -
15.1450 - /**
15.1451 - * Skips to the next byte boundary.
15.1452 - */
15.1453 - public void skipToByteBoundary()
15.1454 - {
15.1455 - buffer >>= (bits_in_buffer & 7);
15.1456 - bits_in_buffer &= ~7;
15.1457 - }
15.1458 -
15.1459 - public final boolean needsInput() {
15.1460 - return window_start == window_end;
15.1461 - }
15.1462 -
15.1463 -
15.1464 - /* Copies length bytes from input buffer to output buffer starting
15.1465 - * at output[offset]. You have to make sure, that the buffer is
15.1466 - * byte aligned. If not enough bytes are available, copies fewer
15.1467 - * bytes.
15.1468 - * @param length the length to copy, 0 is allowed.
15.1469 - * @return the number of bytes copied, 0 if no byte is available.
15.1470 - */
15.1471 - public int copyBytes(byte[] output, int offset, int length)
15.1472 - {
15.1473 - if (length < 0)
15.1474 - throw new IllegalArgumentException("length negative");
15.1475 - if ((bits_in_buffer & 7) != 0)
15.1476 - /* bits_in_buffer may only be 0 or 8 */
15.1477 - throw new IllegalStateException("Bit buffer is not aligned!");
15.1478 -
15.1479 - int count = 0;
15.1480 - while (bits_in_buffer > 0 && length > 0)
15.1481 - {
15.1482 - output[offset++] = (byte) buffer;
15.1483 - buffer >>>= 8;
15.1484 - bits_in_buffer -= 8;
15.1485 - length--;
15.1486 - count++;
15.1487 - }
15.1488 - if (length == 0)
15.1489 - return count;
15.1490 -
15.1491 - int avail = window_end - window_start;
15.1492 - if (length > avail)
15.1493 - length = avail;
15.1494 - System.arraycopy(window, window_start, output, offset, length);
15.1495 - window_start += length;
15.1496 -
15.1497 - if (((window_start - window_end) & 1) != 0)
15.1498 - {
15.1499 - /* We always want an even number of bytes in input, see peekBits */
15.1500 - buffer = (window[window_start++] & 0xff);
15.1501 - bits_in_buffer = 8;
15.1502 - }
15.1503 - return count + length;
15.1504 - }
15.1505 -
15.1506 - public StreamManipulator()
15.1507 - {
15.1508 - }
15.1509 -
15.1510 - public void reset()
15.1511 - {
15.1512 - window_start = window_end = buffer = bits_in_buffer = 0;
15.1513 - }
15.1514 -
15.1515 - public void setInput(byte[] buf, int off, int len)
15.1516 - {
15.1517 - if (window_start < window_end)
15.1518 - throw new IllegalStateException
15.1519 - ("Old input was not completely processed");
15.1520 -
15.1521 - int end = off + len;
15.1522 -
15.1523 - /* We want to throw an ArrayIndexOutOfBoundsException early. The
15.1524 - * check is very tricky: it also handles integer wrap around.
15.1525 - */
15.1526 - if (0 > off || off > end || end > buf.length)
15.1527 - throw new ArrayIndexOutOfBoundsException();
15.1528 -
15.1529 - if ((len & 1) != 0)
15.1530 - {
15.1531 - /* We always want an even number of bytes in input, see peekBits */
15.1532 - buffer |= (buf[off++] & 0xff) << bits_in_buffer;
15.1533 - bits_in_buffer += 8;
15.1534 - }
15.1535 -
15.1536 - window = buf;
15.1537 - window_start = off;
15.1538 - window_end = end;
15.1539 - }
15.1540 - }
15.1541 - /*
15.1542 - * Contains the output from the Inflation process.
15.1543 - *
15.1544 - * We need to have a window so that we can refer backwards into the output stream
15.1545 - * to repeat stuff.
15.1546 - *
15.1547 - * @author John Leuner
15.1548 - * @since JDK 1.1
15.1549 - */
15.1550 -
15.1551 - private static class OutputWindow
15.1552 - {
15.1553 - private final int WINDOW_SIZE = 1 << 15;
15.1554 - private final int WINDOW_MASK = WINDOW_SIZE - 1;
15.1555 -
15.1556 - private byte[] window = new byte[WINDOW_SIZE]; //The window is 2^15 bytes
15.1557 - private int window_end = 0;
15.1558 - private int window_filled = 0;
15.1559 -
15.1560 - public void write(int abyte)
15.1561 - {
15.1562 - if (window_filled++ == WINDOW_SIZE)
15.1563 - throw new IllegalStateException("Window full");
15.1564 - window[window_end++] = (byte) abyte;
15.1565 - window_end &= WINDOW_MASK;
15.1566 - }
15.1567 -
15.1568 -
15.1569 - private final void slowRepeat(int rep_start, int len, int dist)
15.1570 - {
15.1571 - while (len-- > 0)
15.1572 - {
15.1573 - window[window_end++] = window[rep_start++];
15.1574 - window_end &= WINDOW_MASK;
15.1575 - rep_start &= WINDOW_MASK;
15.1576 - }
15.1577 - }
15.1578 -
15.1579 - public void repeat(int len, int dist)
15.1580 - {
15.1581 - if ((window_filled += len) > WINDOW_SIZE)
15.1582 - throw new IllegalStateException("Window full");
15.1583 -
15.1584 - int rep_start = (window_end - dist) & WINDOW_MASK;
15.1585 - int border = WINDOW_SIZE - len;
15.1586 - if (rep_start <= border && window_end < border)
15.1587 - {
15.1588 - if (len <= dist)
15.1589 - {
15.1590 - System.arraycopy(window, rep_start, window, window_end, len);
15.1591 - window_end += len;
15.1592 - }
15.1593 - else
15.1594 - {
15.1595 - /* We have to copy manually, since the repeat pattern overlaps.
15.1596 - */
15.1597 - while (len-- > 0)
15.1598 - window[window_end++] = window[rep_start++];
15.1599 - }
15.1600 - }
15.1601 - else
15.1602 - slowRepeat(rep_start, len, dist);
15.1603 - }
15.1604 -
15.1605 - public int copyStored(StreamManipulator input, int len)
15.1606 - {
15.1607 - len = Math.min(Math.min(len, WINDOW_SIZE - window_filled),
15.1608 - input.getAvailableBytes());
15.1609 - int copied;
15.1610 -
15.1611 - int tailLen = WINDOW_SIZE - window_end;
15.1612 - if (len > tailLen)
15.1613 - {
15.1614 - copied = input.copyBytes(window, window_end, tailLen);
15.1615 - if (copied == tailLen)
15.1616 - copied += input.copyBytes(window, 0, len - tailLen);
15.1617 - }
15.1618 - else
15.1619 - copied = input.copyBytes(window, window_end, len);
15.1620 -
15.1621 - window_end = (window_end + copied) & WINDOW_MASK;
15.1622 - window_filled += copied;
15.1623 - return copied;
15.1624 - }
15.1625 -
15.1626 - public void copyDict(byte[] dict, int offset, int len)
15.1627 - {
15.1628 - if (window_filled > 0)
15.1629 - throw new IllegalStateException();
15.1630 -
15.1631 - if (len > WINDOW_SIZE)
15.1632 - {
15.1633 - offset += len - WINDOW_SIZE;
15.1634 - len = WINDOW_SIZE;
15.1635 - }
15.1636 - System.arraycopy(dict, offset, window, 0, len);
15.1637 - window_end = len & WINDOW_MASK;
15.1638 - }
15.1639 -
15.1640 - public int getFreeSpace()
15.1641 - {
15.1642 - return WINDOW_SIZE - window_filled;
15.1643 - }
15.1644 -
15.1645 - public int getAvailable()
15.1646 - {
15.1647 - return window_filled;
15.1648 - }
15.1649 -
15.1650 - public int copyOutput(byte[] output, int offset, int len)
15.1651 - {
15.1652 - int copy_end = window_end;
15.1653 - if (len > window_filled)
15.1654 - len = window_filled;
15.1655 - else
15.1656 - copy_end = (window_end - window_filled + len) & WINDOW_MASK;
15.1657 -
15.1658 - int copied = len;
15.1659 - int tailLen = len - copy_end;
15.1660 -
15.1661 - if (tailLen > 0)
15.1662 - {
15.1663 - System.arraycopy(window, WINDOW_SIZE - tailLen,
15.1664 - output, offset, tailLen);
15.1665 - offset += tailLen;
15.1666 - len = copy_end;
15.1667 - }
15.1668 - System.arraycopy(window, copy_end - len, output, offset, len);
15.1669 - window_filled -= copied;
15.1670 - if (window_filled < 0)
15.1671 - throw new IllegalStateException();
15.1672 - return copied;
15.1673 - }
15.1674 -
15.1675 - public void reset() {
15.1676 - window_filled = window_end = 0;
15.1677 - }
15.1678 - }
15.1679 -
15.1680 }
16.1 --- a/emul/mini/src/main/java/java/util/zip/ZipConstants64.java Fri Feb 15 11:54:45 2013 +0100
16.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
16.3 @@ -1,84 +0,0 @@
16.4 -/*
16.5 - * Copyright (c) 1995, 1996, Oracle and/or its affiliates. All rights reserved.
16.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
16.7 - *
16.8 - * This code is free software; you can redistribute it and/or modify it
16.9 - * under the terms of the GNU General Public License version 2 only, as
16.10 - * published by the Free Software Foundation. Oracle designates this
16.11 - * particular file as subject to the "Classpath" exception as provided
16.12 - * by Oracle in the LICENSE file that accompanied this code.
16.13 - *
16.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
16.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16.17 - * version 2 for more details (a copy is included in the LICENSE file that
16.18 - * accompanied this code).
16.19 - *
16.20 - * You should have received a copy of the GNU General Public License version
16.21 - * 2 along with this work; if not, write to the Free Software Foundation,
16.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
16.23 - *
16.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
16.25 - * or visit www.oracle.com if you need additional information or have any
16.26 - * questions.
16.27 - */
16.28 -
16.29 -package java.util.zip;
16.30 -
16.31 -/*
16.32 - * This class defines the constants that are used by the classes
16.33 - * which manipulate Zip64 files.
16.34 - */
16.35 -
16.36 -class ZipConstants64 {
16.37 -
16.38 - /*
16.39 - * ZIP64 constants
16.40 - */
16.41 - static final long ZIP64_ENDSIG = 0x06064b50L; // "PK\006\006"
16.42 - static final long ZIP64_LOCSIG = 0x07064b50L; // "PK\006\007"
16.43 - static final int ZIP64_ENDHDR = 56; // ZIP64 end header size
16.44 - static final int ZIP64_LOCHDR = 20; // ZIP64 end loc header size
16.45 - static final int ZIP64_EXTHDR = 24; // EXT header size
16.46 - static final int ZIP64_EXTID = 0x0001; // Extra field Zip64 header ID
16.47 -
16.48 - static final int ZIP64_MAGICCOUNT = 0xFFFF;
16.49 - static final long ZIP64_MAGICVAL = 0xFFFFFFFFL;
16.50 -
16.51 - /*
16.52 - * Zip64 End of central directory (END) header field offsets
16.53 - */
16.54 - static final int ZIP64_ENDLEN = 4; // size of zip64 end of central dir
16.55 - static final int ZIP64_ENDVEM = 12; // version made by
16.56 - static final int ZIP64_ENDVER = 14; // version needed to extract
16.57 - static final int ZIP64_ENDNMD = 16; // number of this disk
16.58 - static final int ZIP64_ENDDSK = 20; // disk number of start
16.59 - static final int ZIP64_ENDTOD = 24; // total number of entries on this disk
16.60 - static final int ZIP64_ENDTOT = 32; // total number of entries
16.61 - static final int ZIP64_ENDSIZ = 40; // central directory size in bytes
16.62 - static final int ZIP64_ENDOFF = 48; // offset of first CEN header
16.63 - static final int ZIP64_ENDEXT = 56; // zip64 extensible data sector
16.64 -
16.65 - /*
16.66 - * Zip64 End of central directory locator field offsets
16.67 - */
16.68 - static final int ZIP64_LOCDSK = 4; // disk number start
16.69 - static final int ZIP64_LOCOFF = 8; // offset of zip64 end
16.70 - static final int ZIP64_LOCTOT = 16; // total number of disks
16.71 -
16.72 - /*
16.73 - * Zip64 Extra local (EXT) header field offsets
16.74 - */
16.75 - static final int ZIP64_EXTCRC = 4; // uncompressed file crc-32 value
16.76 - static final int ZIP64_EXTSIZ = 8; // compressed size, 8-byte
16.77 - static final int ZIP64_EXTLEN = 16; // uncompressed size, 8-byte
16.78 -
16.79 - /*
16.80 - * Language encoding flag EFS
16.81 - */
16.82 - static final int EFS = 0x800; // If this bit is set the filename and
16.83 - // comment fields for this file must be
16.84 - // encoded using UTF-8.
16.85 -
16.86 - private ZipConstants64() {}
16.87 -}
17.1 --- a/emul/mini/src/main/java/java/util/zip/ZipInputStream.java Fri Feb 15 11:54:45 2013 +0100
17.2 +++ b/emul/mini/src/main/java/java/util/zip/ZipInputStream.java Fri Feb 15 21:16:05 2013 +0100
17.3 @@ -27,10 +27,6 @@
17.4
17.5 import java.io.InputStream;
17.6 import java.io.IOException;
17.7 -import java.io.EOFException;
17.8 -import java.io.PushbackInputStream;
17.9 -import static java.util.zip.ZipConstants64.*;
17.10 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
17.11
17.12 /**
17.13 * This class implements an input stream filter for reading files in the
17.14 @@ -41,28 +37,7 @@
17.15 */
17.16 public
17.17 class ZipInputStream extends InflaterInputStream implements ZipConstants {
17.18 - private ZipEntry entry;
17.19 - private int flag;
17.20 - private CRC32 crc = new CRC32();
17.21 - private long remaining;
17.22 - private byte[] tmpbuf = new byte[512];
17.23 -
17.24 - private static final int STORED = ZipEntry.STORED;
17.25 - private static final int DEFLATED = ZipEntry.DEFLATED;
17.26 -
17.27 - private boolean closed = false;
17.28 - // this flag is set to true after EOF has reached for
17.29 - // one entry
17.30 - private boolean entryEOF = false;
17.31 -
17.32 - /**
17.33 - * Check to make sure that this stream has not been closed
17.34 - */
17.35 - private void ensureOpen() throws IOException {
17.36 - if (closed) {
17.37 - throw new IOException("Stream closed");
17.38 - }
17.39 - }
17.40 + private final org.apidesign.bck2brwsr.emul.zip.ZipInputStream impl;
17.41
17.42 /**
17.43 * Creates a new ZIP input stream.
17.44 @@ -73,12 +48,8 @@
17.45 * @param in the actual input stream
17.46 */
17.47 public ZipInputStream(InputStream in) {
17.48 -// this(in, "UTF-8");
17.49 - super(new PushbackInputStream(in, 512), new Inflater(true), 512);
17.50 - usesDefaultInflater = true;
17.51 - if(in == null) {
17.52 - throw new NullPointerException("in is null");
17.53 - }
17.54 + super(in);
17.55 + impl = new org.apidesign.bck2brwsr.emul.zip.ZipInputStream(in);
17.56 }
17.57
17.58 /**
17.59 @@ -115,20 +86,7 @@
17.60 * @exception IOException if an I/O error has occurred
17.61 */
17.62 public ZipEntry getNextEntry() throws IOException {
17.63 - ensureOpen();
17.64 - if (entry != null) {
17.65 - closeEntry();
17.66 - }
17.67 - crc.reset();
17.68 - inf.reset();
17.69 - if ((entry = readLOC()) == null) {
17.70 - return null;
17.71 - }
17.72 - if (entry.method == STORED) {
17.73 - remaining = entry.size;
17.74 - }
17.75 - entryEOF = false;
17.76 - return entry;
17.77 + return impl.getNextEntry();
17.78 }
17.79
17.80 /**
17.81 @@ -138,9 +96,7 @@
17.82 * @exception IOException if an I/O error has occurred
17.83 */
17.84 public void closeEntry() throws IOException {
17.85 - ensureOpen();
17.86 - while (read(tmpbuf, 0, tmpbuf.length) != -1) ;
17.87 - entryEOF = true;
17.88 + impl.closeEntry();
17.89 }
17.90
17.91 /**
17.92 @@ -155,12 +111,7 @@
17.93 *
17.94 */
17.95 public int available() throws IOException {
17.96 - ensureOpen();
17.97 - if (entryEOF) {
17.98 - return 0;
17.99 - } else {
17.100 - return 1;
17.101 - }
17.102 + return impl.available();
17.103 }
17.104
17.105 /**
17.106 @@ -181,51 +132,7 @@
17.107 * @exception IOException if an I/O error has occurred
17.108 */
17.109 public int read(byte[] b, int off, int len) throws IOException {
17.110 - ensureOpen();
17.111 - if (off < 0 || len < 0 || off > b.length - len) {
17.112 - throw new IndexOutOfBoundsException();
17.113 - } else if (len == 0) {
17.114 - return 0;
17.115 - }
17.116 -
17.117 - if (entry == null) {
17.118 - return -1;
17.119 - }
17.120 - switch (entry.method) {
17.121 - case DEFLATED:
17.122 - len = super.read(b, off, len);
17.123 - if (len == -1) {
17.124 - readEnd(entry);
17.125 - entryEOF = true;
17.126 - entry = null;
17.127 - } else {
17.128 - crc.update(b, off, len);
17.129 - }
17.130 - return len;
17.131 - case STORED:
17.132 - if (remaining <= 0) {
17.133 - entryEOF = true;
17.134 - entry = null;
17.135 - return -1;
17.136 - }
17.137 - if (len > remaining) {
17.138 - len = (int)remaining;
17.139 - }
17.140 - len = in.read(b, off, len);
17.141 - if (len == -1) {
17.142 - throw new ZipException("unexpected EOF");
17.143 - }
17.144 - crc.update(b, off, len);
17.145 - remaining -= len;
17.146 - if (remaining == 0 && entry.crc != crc.getValue()) {
17.147 - throw new ZipException(
17.148 - "invalid entry CRC (expected 0x" + Long.toHexString(entry.crc) +
17.149 - " but got 0x" + Long.toHexString(crc.getValue()) + ")");
17.150 - }
17.151 - return len;
17.152 - default:
17.153 - throw new ZipException("invalid compression method");
17.154 - }
17.155 + return impl.read(b, off, len);
17.156 }
17.157
17.158 /**
17.159 @@ -237,25 +144,7 @@
17.160 * @exception IllegalArgumentException if n < 0
17.161 */
17.162 public long skip(long n) throws IOException {
17.163 - if (n < 0) {
17.164 - throw new IllegalArgumentException("negative skip length");
17.165 - }
17.166 - ensureOpen();
17.167 - int max = (int)Math.min(n, Integer.MAX_VALUE);
17.168 - int total = 0;
17.169 - while (total < max) {
17.170 - int len = max - total;
17.171 - if (len > tmpbuf.length) {
17.172 - len = tmpbuf.length;
17.173 - }
17.174 - len = read(tmpbuf, 0, len);
17.175 - if (len == -1) {
17.176 - entryEOF = true;
17.177 - break;
17.178 - }
17.179 - total += len;
17.180 - }
17.181 - return total;
17.182 + return impl.skip(n);
17.183 }
17.184
17.185 /**
17.186 @@ -264,89 +153,7 @@
17.187 * @exception IOException if an I/O error has occurred
17.188 */
17.189 public void close() throws IOException {
17.190 - if (!closed) {
17.191 - super.close();
17.192 - closed = true;
17.193 - }
17.194 - }
17.195 -
17.196 - private byte[] b = new byte[256];
17.197 -
17.198 - /*
17.199 - * Reads local file (LOC) header for next entry.
17.200 - */
17.201 - private ZipEntry readLOC() throws IOException {
17.202 - try {
17.203 - readFully(tmpbuf, 0, LOCHDR);
17.204 - } catch (EOFException e) {
17.205 - return null;
17.206 - }
17.207 - if (get32(tmpbuf, 0) != LOCSIG) {
17.208 - return null;
17.209 - }
17.210 - // get flag first, we need check EFS.
17.211 - flag = get16(tmpbuf, LOCFLG);
17.212 - // get the entry name and create the ZipEntry first
17.213 - int len = get16(tmpbuf, LOCNAM);
17.214 - int blen = b.length;
17.215 - if (len > blen) {
17.216 - do
17.217 - blen = blen * 2;
17.218 - while (len > blen);
17.219 - b = new byte[blen];
17.220 - }
17.221 - readFully(b, 0, len);
17.222 - // Force to use UTF-8 if the EFS bit is ON, even the cs is NOT UTF-8
17.223 - ZipEntry e = createZipEntry(((flag & EFS) != 0)
17.224 - ? toStringUTF8(b, len)
17.225 - : toString(b, len));
17.226 - // now get the remaining fields for the entry
17.227 - if ((flag & 1) == 1) {
17.228 - throw new ZipException("encrypted ZIP entry not supported");
17.229 - }
17.230 - e.method = get16(tmpbuf, LOCHOW);
17.231 - e.time = get32(tmpbuf, LOCTIM);
17.232 - if ((flag & 8) == 8) {
17.233 - /* "Data Descriptor" present */
17.234 - if (e.method != DEFLATED) {
17.235 - throw new ZipException(
17.236 - "only DEFLATED entries can have EXT descriptor");
17.237 - }
17.238 - } else {
17.239 - e.crc = get32(tmpbuf, LOCCRC);
17.240 - e.csize = get32(tmpbuf, LOCSIZ);
17.241 - e.size = get32(tmpbuf, LOCLEN);
17.242 - }
17.243 - len = get16(tmpbuf, LOCEXT);
17.244 - if (len > 0) {
17.245 - byte[] bb = new byte[len];
17.246 - readFully(bb, 0, len);
17.247 - e.setExtra(bb);
17.248 - // extra fields are in "HeaderID(2)DataSize(2)Data... format
17.249 - if (e.csize == ZIP64_MAGICVAL || e.size == ZIP64_MAGICVAL) {
17.250 - int off = 0;
17.251 - while (off + 4 < len) {
17.252 - int sz = get16(bb, off + 2);
17.253 - if (get16(bb, off) == ZIP64_EXTID) {
17.254 - off += 4;
17.255 - // LOC extra zip64 entry MUST include BOTH original and
17.256 - // compressed file size fields
17.257 - if (sz < 16 || (off + sz) > len ) {
17.258 - // Invalid zip64 extra fields, simply skip. Even it's
17.259 - // rare, it's possible the entry size happens to be
17.260 - // the magic value and it "accidnetly" has some bytes
17.261 - // in extra match the id.
17.262 - return e;
17.263 - }
17.264 - e.size = get64(bb, off);
17.265 - e.csize = get64(bb, off + 8);
17.266 - break;
17.267 - }
17.268 - off += (sz + 4);
17.269 - }
17.270 - }
17.271 - }
17.272 - return e;
17.273 + impl.close();
17.274 }
17.275
17.276 /**
17.277 @@ -360,108 +167,28 @@
17.278 return new ZipEntry(name);
17.279 }
17.280
17.281 - /*
17.282 - * Reads end of deflated entry as well as EXT descriptor if present.
17.283 - */
17.284 - private void readEnd(ZipEntry e) throws IOException {
17.285 - int n = inf.getRemaining();
17.286 - if (n > 0) {
17.287 - ((PushbackInputStream)in).unread(buf, len - n, n);
17.288 - }
17.289 - if ((flag & 8) == 8) {
17.290 - /* "Data Descriptor" present */
17.291 - if (inf.getBytesWritten() > ZIP64_MAGICVAL ||
17.292 - inf.getBytesRead() > ZIP64_MAGICVAL) {
17.293 - // ZIP64 format
17.294 - readFully(tmpbuf, 0, ZIP64_EXTHDR);
17.295 - long sig = get32(tmpbuf, 0);
17.296 - if (sig != EXTSIG) { // no EXTSIG present
17.297 - e.crc = sig;
17.298 - e.csize = get64(tmpbuf, ZIP64_EXTSIZ - ZIP64_EXTCRC);
17.299 - e.size = get64(tmpbuf, ZIP64_EXTLEN - ZIP64_EXTCRC);
17.300 - ((PushbackInputStream)in).unread(
17.301 - tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC - 1, ZIP64_EXTCRC);
17.302 - } else {
17.303 - e.crc = get32(tmpbuf, ZIP64_EXTCRC);
17.304 - e.csize = get64(tmpbuf, ZIP64_EXTSIZ);
17.305 - e.size = get64(tmpbuf, ZIP64_EXTLEN);
17.306 - }
17.307 - } else {
17.308 - readFully(tmpbuf, 0, EXTHDR);
17.309 - long sig = get32(tmpbuf, 0);
17.310 - if (sig != EXTSIG) { // no EXTSIG present
17.311 - e.crc = sig;
17.312 - e.csize = get32(tmpbuf, EXTSIZ - EXTCRC);
17.313 - e.size = get32(tmpbuf, EXTLEN - EXTCRC);
17.314 - ((PushbackInputStream)in).unread(
17.315 - tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC);
17.316 - } else {
17.317 - e.crc = get32(tmpbuf, EXTCRC);
17.318 - e.csize = get32(tmpbuf, EXTSIZ);
17.319 - e.size = get32(tmpbuf, EXTLEN);
17.320 - }
17.321 - }
17.322 - }
17.323 - if (e.size != inf.getBytesWritten()) {
17.324 - throw new ZipException(
17.325 - "invalid entry size (expected " + e.size +
17.326 - " but got " + inf.getBytesWritten() + " bytes)");
17.327 - }
17.328 - if (e.csize != inf.getBytesRead()) {
17.329 - throw new ZipException(
17.330 - "invalid entry compressed size (expected " + e.csize +
17.331 - " but got " + inf.getBytesRead() + " bytes)");
17.332 - }
17.333 - if (e.crc != crc.getValue()) {
17.334 - throw new ZipException(
17.335 - "invalid entry CRC (expected 0x" + Long.toHexString(e.crc) +
17.336 - " but got 0x" + Long.toHexString(crc.getValue()) + ")");
17.337 - }
17.338 + @Override
17.339 + public int read() throws IOException {
17.340 + return impl.read();
17.341 }
17.342
17.343 - /*
17.344 - * Reads bytes, blocking until all bytes are read.
17.345 - */
17.346 - private void readFully(byte[] b, int off, int len) throws IOException {
17.347 - while (len > 0) {
17.348 - int n = in.read(b, off, len);
17.349 - if (n == -1) {
17.350 - throw new EOFException();
17.351 - }
17.352 - off += n;
17.353 - len -= n;
17.354 - }
17.355 + @Override
17.356 + public boolean markSupported() {
17.357 + return impl.markSupported();
17.358 }
17.359
17.360 - /*
17.361 - * Fetches unsigned 16-bit value from byte array at specified offset.
17.362 - * The bytes are assumed to be in Intel (little-endian) byte order.
17.363 - */
17.364 - private static final int get16(byte b[], int off) {
17.365 - return (b[off] & 0xff) | ((b[off+1] & 0xff) << 8);
17.366 + @Override
17.367 + public void mark(int readlimit) {
17.368 + impl.mark(readlimit);
17.369 }
17.370
17.371 - /*
17.372 - * Fetches unsigned 32-bit value from byte array at specified offset.
17.373 - * The bytes are assumed to be in Intel (little-endian) byte order.
17.374 - */
17.375 - private static final long get32(byte b[], int off) {
17.376 - return (get16(b, off) | ((long)get16(b, off+2) << 16)) & 0xffffffffL;
17.377 + @Override
17.378 + public void reset() throws IOException {
17.379 + impl.reset();
17.380 }
17.381
17.382 - /*
17.383 - * Fetches signed 64-bit value from byte array at specified offset.
17.384 - * The bytes are assumed to be in Intel (little-endian) byte order.
17.385 - */
17.386 - private static final long get64(byte b[], int off) {
17.387 - return get32(b, off) | (get32(b, off+4) << 32);
17.388 - }
17.389 -
17.390 - private static String toStringUTF8(byte[] arr, int len) {
17.391 - return new String(arr, 0, len);
17.392 - }
17.393 -
17.394 - private static String toString(byte[] b, int len) {
17.395 - return new String(b, 0, len);
17.396 + @Override
17.397 + public int read(byte[] b) throws IOException {
17.398 + return impl.read(b);
17.399 }
17.400 }
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
18.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/ManifestInputStream.java Fri Feb 15 21:16:05 2013 +0100
18.3 @@ -0,0 +1,228 @@
18.4 +/*
18.5 + * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
18.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
18.7 + *
18.8 + * This code is free software; you can redistribute it and/or modify it
18.9 + * under the terms of the GNU General Public License version 2 only, as
18.10 + * published by the Free Software Foundation. Oracle designates this
18.11 + * particular file as subject to the "Classpath" exception as provided
18.12 + * by Oracle in the LICENSE file that accompanied this code.
18.13 + *
18.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
18.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18.17 + * version 2 for more details (a copy is included in the LICENSE file that
18.18 + * accompanied this code).
18.19 + *
18.20 + * You should have received a copy of the GNU General Public License version
18.21 + * 2 along with this work; if not, write to the Free Software Foundation,
18.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18.23 + *
18.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
18.25 + * or visit www.oracle.com if you need additional information or have any
18.26 + * questions.
18.27 + */
18.28 +package org.apidesign.bck2brwsr.emul.lang;
18.29 +
18.30 +import java.io.FilterInputStream;
18.31 +import java.io.IOException;
18.32 +import java.io.InputStream;
18.33 +
18.34 +/*
18.35 + * A fast buffered input stream for parsing manifest files.
18.36 + *
18.37 + * Taken from java.util.jar.Manifest.FastInputStream and modified to be
18.38 + * independent of other Manifest functionality.
18.39 + */
18.40 +public abstract class ManifestInputStream extends FilterInputStream {
18.41 + private byte[] buf;
18.42 + private int count = 0;
18.43 + private int pos = 0;
18.44 +
18.45 + protected ManifestInputStream(InputStream in) {
18.46 + this(in, 8192);
18.47 + }
18.48 +
18.49 + protected ManifestInputStream(InputStream in, int size) {
18.50 + super(in);
18.51 + buf = new byte[size];
18.52 + }
18.53 +
18.54 + public int read() throws IOException {
18.55 + if (pos >= count) {
18.56 + fill();
18.57 + if (pos >= count) {
18.58 + return -1;
18.59 + }
18.60 + }
18.61 + return buf[pos++] & 0xff;
18.62 + }
18.63 +
18.64 + public int read(byte[] b, int off, int len) throws IOException {
18.65 + int avail = count - pos;
18.66 + if (avail <= 0) {
18.67 + if (len >= buf.length) {
18.68 + return in.read(b, off, len);
18.69 + }
18.70 + fill();
18.71 + avail = count - pos;
18.72 + if (avail <= 0) {
18.73 + return -1;
18.74 + }
18.75 + }
18.76 + if (len > avail) {
18.77 + len = avail;
18.78 + }
18.79 + System.arraycopy(buf, pos, b, off, len);
18.80 + pos += len;
18.81 + return len;
18.82 + }
18.83 +
18.84 + /*
18.85 + * Reads 'len' bytes from the input stream, or until an end-of-line
18.86 + * is reached. Returns the number of bytes read.
18.87 + */
18.88 + public int readLine(byte[] b, int off, int len) throws IOException {
18.89 + byte[] tbuf = this.buf;
18.90 + int total = 0;
18.91 + while (total < len) {
18.92 + int avail = count - pos;
18.93 + if (avail <= 0) {
18.94 + fill();
18.95 + avail = count - pos;
18.96 + if (avail <= 0) {
18.97 + return -1;
18.98 + }
18.99 + }
18.100 + int n = len - total;
18.101 + if (n > avail) {
18.102 + n = avail;
18.103 + }
18.104 + int tpos = pos;
18.105 + int maxpos = tpos + n;
18.106 + while (tpos < maxpos && tbuf[tpos++] != '\n') {
18.107 + ;
18.108 + }
18.109 + n = tpos - pos;
18.110 + System.arraycopy(tbuf, pos, b, off, n);
18.111 + off += n;
18.112 + total += n;
18.113 + pos = tpos;
18.114 + if (tbuf[tpos - 1] == '\n') {
18.115 + break;
18.116 + }
18.117 + }
18.118 + return total;
18.119 + }
18.120 +
18.121 + public byte peek() throws IOException {
18.122 + if (pos == count) {
18.123 + fill();
18.124 + }
18.125 + if (pos == count) {
18.126 + return -1; // nothing left in buffer
18.127 + }
18.128 + return buf[pos];
18.129 + }
18.130 +
18.131 + public int readLine(byte[] b) throws IOException {
18.132 + return readLine(b, 0, b.length);
18.133 + }
18.134 +
18.135 + public long skip(long n) throws IOException {
18.136 + if (n <= 0) {
18.137 + return 0;
18.138 + }
18.139 + long avail = count - pos;
18.140 + if (avail <= 0) {
18.141 + return in.skip(n);
18.142 + }
18.143 + if (n > avail) {
18.144 + n = avail;
18.145 + }
18.146 + pos += n;
18.147 + return n;
18.148 + }
18.149 +
18.150 + public int available() throws IOException {
18.151 + return (count - pos) + in.available();
18.152 + }
18.153 +
18.154 + public void close() throws IOException {
18.155 + if (in != null) {
18.156 + in.close();
18.157 + in = null;
18.158 + buf = null;
18.159 + }
18.160 + }
18.161 +
18.162 + private void fill() throws IOException {
18.163 + count = pos = 0;
18.164 + int n = in.read(buf, 0, buf.length);
18.165 + if (n > 0) {
18.166 + count = n;
18.167 + }
18.168 + }
18.169 +
18.170 + protected abstract String putValue(String key, String value);
18.171 +
18.172 + public void readAttributes(byte[] lbuf) throws IOException {
18.173 + ManifestInputStream is = this;
18.174 +
18.175 + String name = null;
18.176 + String value = null;
18.177 + byte[] lastline = null;
18.178 + int len;
18.179 + while ((len = is.readLine(lbuf)) != -1) {
18.180 + boolean lineContinued = false;
18.181 + if (lbuf[--len] != '\n') {
18.182 + throw new IOException("line too long");
18.183 + }
18.184 + if (len > 0 && lbuf[len - 1] == '\r') {
18.185 + --len;
18.186 + }
18.187 + if (len == 0) {
18.188 + break;
18.189 + }
18.190 + int i = 0;
18.191 + if (lbuf[0] == ' ') {
18.192 + if (name == null) {
18.193 + throw new IOException("misplaced continuation line");
18.194 + }
18.195 + lineContinued = true;
18.196 + byte[] buf = new byte[lastline.length + len - 1];
18.197 + System.arraycopy(lastline, 0, buf, 0, lastline.length);
18.198 + System.arraycopy(lbuf, 1, buf, lastline.length, len - 1);
18.199 + if (is.peek() == ' ') {
18.200 + lastline = buf;
18.201 + continue;
18.202 + }
18.203 + value = new String(buf, 0, buf.length, "UTF8");
18.204 + lastline = null;
18.205 + } else {
18.206 + while (lbuf[i++] != ':') {
18.207 + if (i >= len) {
18.208 + throw new IOException("invalid header field");
18.209 + }
18.210 + }
18.211 + if (lbuf[i++] != ' ') {
18.212 + throw new IOException("invalid header field");
18.213 + }
18.214 + name = new String(lbuf, 0, 0, i - 2);
18.215 + if (is.peek() == ' ') {
18.216 + lastline = new byte[len - i];
18.217 + System.arraycopy(lbuf, i, lastline, 0, len - i);
18.218 + continue;
18.219 + }
18.220 + value = new String(lbuf, i, len - i, "UTF8");
18.221 + }
18.222 + try {
18.223 + if ((putValue(name, value) != null) && (!lineContinued)) {
18.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.");
18.225 + }
18.226 + } catch (IllegalArgumentException e) {
18.227 + throw new IOException("invalid header field name: " + name);
18.228 + }
18.229 + }
18.230 + }
18.231 +}
19.1 --- a/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/System.java Fri Feb 15 11:54:45 2013 +0100
19.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/System.java Fri Feb 15 21:16:05 2013 +0100
19.3 @@ -17,6 +17,7 @@
19.4 */
19.5 package org.apidesign.bck2brwsr.emul.lang;
19.6
19.7 +import java.lang.reflect.Method;
19.8 import org.apidesign.bck2brwsr.core.JavaScriptBody;
19.9
19.10 /**
19.11 @@ -38,7 +39,15 @@
19.12 " }\n" +
19.13 "}"
19.14 )
19.15 - public static native void arraycopy(Object value, int srcBegin, Object dst, int dstBegin, int count);
19.16 + public static void arraycopy(Object src, int srcBegin, Object dst, int dstBegin, int count) {
19.17 + try {
19.18 + Class<?> system = Class.forName("java.lang.System");
19.19 + Method m = system.getMethod("arraycopy", Object.class, int.class, Object.class, int.class, int.class);
19.20 + m.invoke(null, src, srcBegin, dst, dstBegin, count);
19.21 + } catch (Exception ex) {
19.22 + throw new IllegalStateException(ex);
19.23 + }
19.24 + }
19.25
19.26 @JavaScriptBody(args = { "arr", "expectedSize" }, body =
19.27 "while (expectedSize-- > arr.length) { arr.push(0); }; return arr;"
19.28 @@ -53,5 +62,4 @@
19.29 }
19.30 @JavaScriptBody(args = { "obj" }, body="return vm.java_lang_Object(false).hashCode__I.call(obj);")
19.31 public static native int identityHashCode(Object obj);
19.32 -
19.33 }
20.1 --- a/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/AnnotationImpl.java Fri Feb 15 11:54:45 2013 +0100
20.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/AnnotationImpl.java Fri Feb 15 21:16:05 2013 +0100
20.3 @@ -18,6 +18,8 @@
20.4 package org.apidesign.bck2brwsr.emul.reflect;
20.5
20.6 import java.lang.annotation.Annotation;
20.7 +import java.lang.reflect.Method;
20.8 +import java.lang.reflect.Modifier;
20.9 import org.apidesign.bck2brwsr.core.JavaScriptBody;
20.10
20.11 /**
20.12 @@ -25,39 +27,73 @@
20.13 * @author Jaroslav Tulach <jtulach@netbeans.org>
20.14 */
20.15 public final class AnnotationImpl implements Annotation {
20.16 + private final Class<? extends Annotation> type;
20.17 +
20.18 + public AnnotationImpl(Class<? extends Annotation> type) {
20.19 + this.type = type;
20.20 + }
20.21 +
20.22 public Class<? extends Annotation> annotationType() {
20.23 - return getClass();
20.24 + return type;
20.25 }
20.26
20.27 - @JavaScriptBody(args = { "a", "n", "values" }, body = ""
20.28 - + "function f(v, p) {\n"
20.29 - + " var val = v;\n"
20.30 - + " var prop = p;\n"
20.31 + @JavaScriptBody(args = { "a", "n", "arr", "values" }, body = ""
20.32 + + "function f(val, prop, clazz) {\n"
20.33 + " return function() {\n"
20.34 - + " return val[prop];\n"
20.35 + + " if (clazz == null) return val[prop];\n"
20.36 + + " if (clazz.isArray__Z()) {\n"
20.37 + + " var valarr = val[prop];\n"
20.38 + + " var cmp = clazz.getComponentType__Ljava_lang_Class_2();\n"
20.39 + + " var retarr = vm.java_lang_reflect_Array(false).newInstance__Ljava_lang_Object_2Ljava_lang_Class_2I(cmp, valarr.length);\n"
20.40 + + " for (var i = 0; i < valarr.length; i++) {\n"
20.41 + + " retarr[i] = CLS.prototype.c__Ljava_lang_Object_2Ljava_lang_Class_2Ljava_lang_Object_2(cmp, valarr[i]);\n"
20.42 + + " }\n"
20.43 + + " return retarr;\n"
20.44 + + " }\n"
20.45 + + " return CLS.prototype.c__Ljava_lang_Object_2Ljava_lang_Class_2Ljava_lang_Object_2(clazz, val[prop]);\n"
20.46 + " };\n"
20.47 + "}\n"
20.48 - + "var props = Object.getOwnPropertyNames(values);\n"
20.49 - + "for (var i = 0; i < props.length; i++) {\n"
20.50 - + " var p = props[i];\n"
20.51 - + " a[p] = new f(values, p);\n"
20.52 + + "for (var i = 0; i < arr.length; i += 3) {\n"
20.53 + + " var m = arr[i];\n"
20.54 + + " var p = arr[i + 1];\n"
20.55 + + " var c = arr[i + 2];\n"
20.56 + + " a[m] = f(values, p, c);\n"
20.57 + "}\n"
20.58 + "a['$instOf_' + n] = true;\n"
20.59 + "return a;"
20.60 )
20.61 - private static <T extends Annotation> T create(AnnotationImpl a, String n, Object values) {
20.62 - return null;
20.63 + private static native <T extends Annotation> T create(
20.64 + AnnotationImpl a, String n, Object[] methodsAndProps, Object values
20.65 + );
20.66 +
20.67 + private static Object c(Class<? extends Annotation> a, Object v) {
20.68 + return create(a, v);
20.69 }
20.70 +
20.71 public static <T extends Annotation> T create(Class<T> annoClass, Object values) {
20.72 - return create(new AnnotationImpl(), annoClass.getName().replace('.', '_'), values);
20.73 + return create(new AnnotationImpl(annoClass),
20.74 + annoClass.getName().replace('.', '_'),
20.75 + findProps(annoClass), values
20.76 + );
20.77 }
20.78
20.79 public static Annotation[] create(Object anno) {
20.80 String[] names = findNames(anno);
20.81 Annotation[] ret = new Annotation[names.length];
20.82 for (int i = 0; i < names.length; i++) {
20.83 - String n = names[i].substring(1, names[i].length() - 1).replace('/', '_');
20.84 - ret[i] = create(new AnnotationImpl(), n, findData(anno, names[i]));
20.85 + String annoNameSlash = names[i].substring(1, names[i].length() - 1);
20.86 + Class<? extends Annotation> annoClass;
20.87 + try {
20.88 + annoClass = (Class<? extends Annotation>)Class.forName(annoNameSlash.replace('/', '.'));
20.89 + } catch (ClassNotFoundException ex) {
20.90 + throw new IllegalStateException("Can't find annotation class " + annoNameSlash);
20.91 + }
20.92 + ret[i] = create(
20.93 + new AnnotationImpl(annoClass),
20.94 + annoNameSlash.replace('/', '_'),
20.95 + findProps(annoClass),
20.96 + findData(anno, names[i])
20.97 + );
20.98 }
20.99 return ret;
20.100 }
20.101 @@ -70,12 +106,25 @@
20.102 + "}"
20.103 + "return arr;"
20.104 )
20.105 - private static String[] findNames(Object anno) {
20.106 - throw new UnsupportedOperationException();
20.107 - }
20.108 + private static native String[] findNames(Object anno);
20.109
20.110 @JavaScriptBody(args={ "anno", "p"}, body="return anno[p];")
20.111 - private static Object findData(Object anno, String p) {
20.112 - throw new UnsupportedOperationException();
20.113 + private static native Object findData(Object anno, String p);
20.114 +
20.115 + private static Object[] findProps(Class<?> annoClass) {
20.116 + final Method[] marr = MethodImpl.findMethods(annoClass, Modifier.PUBLIC);
20.117 + Object[] arr = new Object[marr.length * 3];
20.118 + int pos = 0;
20.119 + for (Method m : marr) {
20.120 + arr[pos++] = MethodImpl.toSignature(m);
20.121 + arr[pos++] = m.getName();
20.122 + final Class<?> rt = m.getReturnType();
20.123 + if (rt.isArray()) {
20.124 + arr[pos++] = rt.getComponentType().isAnnotation() ? rt : null;
20.125 + } else {
20.126 + arr[pos++] = rt.isAnnotation() ? rt : null;
20.127 + }
20.128 + }
20.129 + return arr;
20.130 }
20.131 }
21.1 --- a/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/MethodImpl.java Fri Feb 15 11:54:45 2013 +0100
21.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/MethodImpl.java Fri Feb 15 21:16:05 2013 +0100
21.3 @@ -17,6 +17,7 @@
21.4 */
21.5 package org.apidesign.bck2brwsr.emul.reflect;
21.6
21.7 +import java.lang.reflect.Array;
21.8 import java.lang.reflect.Method;
21.9 import java.util.Enumeration;
21.10 import org.apidesign.bck2brwsr.core.JavaScriptBody;
21.11 @@ -34,7 +35,7 @@
21.12 throw new IllegalStateException(ex);
21.13 }
21.14 }
21.15 -
21.16 +
21.17 protected abstract Method create(Class<?> declaringClass, String name, Object data, String sig);
21.18
21.19
21.20 @@ -48,8 +49,10 @@
21.21 + "var arr = new Array();\n"
21.22 + "for (m in c) {\n"
21.23 + " if (m.indexOf(prefix) === 0) {\n"
21.24 + + " if (!c[m].cls) continue;\n"
21.25 + " arr.push(m);\n"
21.26 + " arr.push(c[m]);\n"
21.27 + + " arr.push(c[m].cls.$class);\n"
21.28 + " }"
21.29 + "}\n"
21.30 + "return arr;")
21.31 @@ -59,9 +62,10 @@
21.32 public static Method findMethod(
21.33 Class<?> clazz, String name, Class<?>... parameterTypes) {
21.34 Object[] data = findMethodData(clazz, name + "__");
21.35 - BIG: for (int i = 0; i < data.length; i += 2) {
21.36 - String sig = ((String) data[0]).substring(name.length() + 2);
21.37 - Method tmp = INSTANCE.create(clazz, name, data[1], sig);
21.38 + BIG: for (int i = 0; i < data.length; i += 3) {
21.39 + String sig = ((String) data[i]).substring(name.length() + 2);
21.40 + Class<?> cls = (Class<?>) data[i + 2];
21.41 + Method tmp = INSTANCE.create(cls, name, data[i + 1], sig);
21.42 Class<?>[] tmpParms = tmp.getParameterTypes();
21.43 if (parameterTypes.length != tmpParms.length) {
21.44 continue;
21.45 @@ -79,7 +83,7 @@
21.46 public static Method[] findMethods(Class<?> clazz, int mask) {
21.47 Object[] namesAndData = findMethodData(clazz, "");
21.48 int cnt = 0;
21.49 - for (int i = 0; i < namesAndData.length; i += 2) {
21.50 + for (int i = 0; i < namesAndData.length; i += 3) {
21.51 String sig = (String) namesAndData[i];
21.52 Object data = namesAndData[i + 1];
21.53 int middle = sig.indexOf("__");
21.54 @@ -88,7 +92,8 @@
21.55 }
21.56 String name = sig.substring(0, middle);
21.57 sig = sig.substring(middle + 2);
21.58 - final Method m = INSTANCE.create(clazz, name, data, sig);
21.59 + Class<?> cls = (Class<?>) namesAndData[i + 2];
21.60 + final Method m = INSTANCE.create(cls, name, data, sig);
21.61 if ((m.getModifiers() & mask) == 0) {
21.62 continue;
21.63 }
21.64 @@ -100,6 +105,62 @@
21.65 }
21.66 return arr;
21.67 }
21.68 + static String toSignature(Method m) {
21.69 + StringBuilder sb = new StringBuilder();
21.70 + sb.append(m.getName()).append("__");
21.71 + appendType(sb, m.getReturnType());
21.72 + Class<?>[] arr = m.getParameterTypes();
21.73 + for (int i = 0; i < arr.length; i++) {
21.74 + appendType(sb, arr[i]);
21.75 + }
21.76 + return sb.toString();
21.77 + }
21.78 +
21.79 + private static void appendType(StringBuilder sb, Class<?> type) {
21.80 + if (type == Integer.TYPE) {
21.81 + sb.append('I');
21.82 + return;
21.83 + }
21.84 + if (type == Long.TYPE) {
21.85 + sb.append('J');
21.86 + return;
21.87 + }
21.88 + if (type == Double.TYPE) {
21.89 + sb.append('D');
21.90 + return;
21.91 + }
21.92 + if (type == Float.TYPE) {
21.93 + sb.append('F');
21.94 + return;
21.95 + }
21.96 + if (type == Byte.TYPE) {
21.97 + sb.append('B');
21.98 + return;
21.99 + }
21.100 + if (type == Boolean.TYPE) {
21.101 + sb.append('Z');
21.102 + return;
21.103 + }
21.104 + if (type == Short.TYPE) {
21.105 + sb.append('S');
21.106 + return;
21.107 + }
21.108 + if (type == Void.TYPE) {
21.109 + sb.append('V');
21.110 + return;
21.111 + }
21.112 + if (type == Character.TYPE) {
21.113 + sb.append('C');
21.114 + return;
21.115 + }
21.116 + if (type.isArray()) {
21.117 + sb.append("_3");
21.118 + appendType(sb, type.getComponentType());
21.119 + return;
21.120 + }
21.121 + sb.append('L').append(type.getName().replace('.', '_'));
21.122 + sb.append("_2");
21.123 + }
21.124
21.125 public static int signatureElements(String sig) {
21.126 Enumeration<Class> en = signatureParser(sig);
21.127 @@ -141,13 +202,19 @@
21.128 return Character.TYPE;
21.129 case 'L':
21.130 try {
21.131 - int up = sig.indexOf("_2");
21.132 - String type = sig.substring(1, up);
21.133 + int up = sig.indexOf("_2", pos);
21.134 + String type = sig.substring(pos, up);
21.135 pos = up + 2;
21.136 - return Class.forName(type);
21.137 + return Class.forName(type.replace('_', '.'));
21.138 } catch (ClassNotFoundException ex) {
21.139 - // should not happen
21.140 + throw new IllegalStateException(ex);
21.141 }
21.142 + case '_': {
21.143 + char nch = sig.charAt(pos++);
21.144 + assert nch == '3' : "Can't find '3' at " + sig.substring(pos - 1);
21.145 + final Class compType = nextElement();
21.146 + return Array.newInstance(compType, 0).getClass();
21.147 + }
21.148 }
21.149 throw new UnsupportedOperationException(sig + " at " + pos);
21.150 }
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
22.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/Adler32.java Fri Feb 15 21:16:05 2013 +0100
22.3 @@ -0,0 +1,139 @@
22.4 +/* -*-mode:java; c-basic-offset:2; -*- */
22.5 +/*
22.6 +Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved.
22.7 +
22.8 +Redistribution and use in source and binary forms, with or without
22.9 +modification, are permitted provided that the following conditions are met:
22.10 +
22.11 + 1. Redistributions of source code must retain the above copyright notice,
22.12 + this list of conditions and the following disclaimer.
22.13 +
22.14 + 2. Redistributions in binary form must reproduce the above copyright
22.15 + notice, this list of conditions and the following disclaimer in
22.16 + the documentation and/or other materials provided with the distribution.
22.17 +
22.18 + 3. The names of the authors may not be used to endorse or promote products
22.19 + derived from this software without specific prior written permission.
22.20 +
22.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
22.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
22.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
22.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
22.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
22.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
22.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
22.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22.31 + */
22.32 +/*
22.33 + * This program is based on zlib-1.1.3, so all credit should go authors
22.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
22.35 + * and contributors of zlib.
22.36 + */
22.37 +
22.38 +package org.apidesign.bck2brwsr.emul.zip;
22.39 +
22.40 +final class Adler32 implements Checksum {
22.41 +
22.42 + // largest prime smaller than 65536
22.43 + static final private int BASE=65521;
22.44 + // NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
22.45 + static final private int NMAX=5552;
22.46 +
22.47 + private long s1=1L;
22.48 + private long s2=0L;
22.49 +
22.50 + public void reset(long init){
22.51 + s1=init&0xffff;
22.52 + s2=(init>>16)&0xffff;
22.53 + }
22.54 +
22.55 + public void reset(){
22.56 + s1=1L;
22.57 + s2=0L;
22.58 + }
22.59 +
22.60 + public long getValue(){
22.61 + return ((s2<<16)|s1);
22.62 + }
22.63 +
22.64 + public void update(byte[] buf, int index, int len){
22.65 +
22.66 + if(len==1){
22.67 + s1+=buf[index++]&0xff; s2+=s1;
22.68 + s1%=BASE;
22.69 + s2%=BASE;
22.70 + return;
22.71 + }
22.72 +
22.73 + int len1 = len/NMAX;
22.74 + int len2 = len%NMAX;
22.75 + while(len1-->0) {
22.76 + int k=NMAX;
22.77 + len-=k;
22.78 + while(k-->0){
22.79 + s1+=buf[index++]&0xff; s2+=s1;
22.80 + }
22.81 + s1%=BASE;
22.82 + s2%=BASE;
22.83 + }
22.84 +
22.85 + int k=len2;
22.86 + len-=k;
22.87 + while(k-->0){
22.88 + s1+=buf[index++]&0xff; s2+=s1;
22.89 + }
22.90 + s1%=BASE;
22.91 + s2%=BASE;
22.92 + }
22.93 +
22.94 + public Adler32 copy(){
22.95 + Adler32 foo = new Adler32();
22.96 + foo.s1 = this.s1;
22.97 + foo.s2 = this.s2;
22.98 + return foo;
22.99 + }
22.100 +
22.101 + // The following logic has come from zlib.1.2.
22.102 + static long combine(long adler1, long adler2, long len2){
22.103 + long BASEL = (long)BASE;
22.104 + long sum1;
22.105 + long sum2;
22.106 + long rem; // unsigned int
22.107 +
22.108 + rem = len2 % BASEL;
22.109 + sum1 = adler1 & 0xffffL;
22.110 + sum2 = rem * sum1;
22.111 + sum2 %= BASEL; // MOD(sum2);
22.112 + sum1 += (adler2 & 0xffffL) + BASEL - 1;
22.113 + sum2 += ((adler1 >> 16) & 0xffffL) + ((adler2 >> 16) & 0xffffL) + BASEL - rem;
22.114 + if (sum1 >= BASEL) sum1 -= BASEL;
22.115 + if (sum1 >= BASEL) sum1 -= BASEL;
22.116 + if (sum2 >= (BASEL << 1)) sum2 -= (BASEL << 1);
22.117 + if (sum2 >= BASEL) sum2 -= BASEL;
22.118 + return sum1 | (sum2 << 16);
22.119 + }
22.120 +
22.121 +/*
22.122 + private java.util.zip.Adler32 adler=new java.util.zip.Adler32();
22.123 + public void update(byte[] buf, int index, int len){
22.124 + if(buf==null) {adler.reset();}
22.125 + else{adler.update(buf, index, len);}
22.126 + }
22.127 + public void reset(){
22.128 + adler.reset();
22.129 + }
22.130 + public void reset(long init){
22.131 + if(init==1L){
22.132 + adler.reset();
22.133 + }
22.134 + else{
22.135 + System.err.println("unsupported operation");
22.136 + }
22.137 + }
22.138 + public long getValue(){
22.139 + return adler.getValue();
22.140 + }
22.141 +*/
22.142 +}
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/CRC32.java Fri Feb 15 21:16:05 2013 +0100
23.3 @@ -0,0 +1,181 @@
23.4 +/* -*-mode:java; c-basic-offset:2; -*- */
23.5 +/*
23.6 +Copyright (c) 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 +import org.apidesign.bck2brwsr.emul.lang.System;
23.41 +
23.42 +final class CRC32 implements Checksum {
23.43 +
23.44 + /*
23.45 + * The following logic has come from RFC1952.
23.46 + */
23.47 + private int v = 0;
23.48 + private static int[] crc_table = null;
23.49 + static {
23.50 + crc_table = new int[256];
23.51 + for (int n = 0; n < 256; n++) {
23.52 + int c = n;
23.53 + for (int k = 8; --k >= 0; ) {
23.54 + if ((c & 1) != 0)
23.55 + c = 0xedb88320 ^ (c >>> 1);
23.56 + else
23.57 + c = c >>> 1;
23.58 + }
23.59 + crc_table[n] = c;
23.60 + }
23.61 + }
23.62 +
23.63 + public void update (byte[] buf, int index, int len) {
23.64 + int c = ~v;
23.65 + while (--len >= 0)
23.66 + c = crc_table[(c^buf[index++])&0xff]^(c >>> 8);
23.67 + v = ~c;
23.68 + }
23.69 +
23.70 + public void reset(){
23.71 + v = 0;
23.72 + }
23.73 +
23.74 + public void reset(long vv){
23.75 + v = (int)(vv&0xffffffffL);
23.76 + }
23.77 +
23.78 + public long getValue(){
23.79 + return (long)(v&0xffffffffL);
23.80 + }
23.81 +
23.82 + // The following logic has come from zlib.1.2.
23.83 + private static final int GF2_DIM = 32;
23.84 + static long combine(long crc1, long crc2, long len2){
23.85 + long row;
23.86 + long[] even = new long[GF2_DIM];
23.87 + long[] odd = new long[GF2_DIM];
23.88 +
23.89 + // degenerate case (also disallow negative lengths)
23.90 + if (len2 <= 0)
23.91 + return crc1;
23.92 +
23.93 + // put operator for one zero bit in odd
23.94 + odd[0] = 0xedb88320L; // CRC-32 polynomial
23.95 + row = 1;
23.96 + for (int n = 1; n < GF2_DIM; n++) {
23.97 + odd[n] = row;
23.98 + row <<= 1;
23.99 + }
23.100 +
23.101 + // put operator for two zero bits in even
23.102 + gf2_matrix_square(even, odd);
23.103 +
23.104 + // put operator for four zero bits in odd
23.105 + gf2_matrix_square(odd, even);
23.106 +
23.107 + // apply len2 zeros to crc1 (first square will put the operator for one
23.108 + // zero byte, eight zero bits, in even)
23.109 + do {
23.110 + // apply zeros operator for this bit of len2
23.111 + gf2_matrix_square(even, odd);
23.112 + if ((len2 & 1)!=0)
23.113 + crc1 = gf2_matrix_times(even, crc1);
23.114 + len2 >>= 1;
23.115 +
23.116 + // if no more bits set, then done
23.117 + if (len2 == 0)
23.118 + break;
23.119 +
23.120 + // another iteration of the loop with odd and even swapped
23.121 + gf2_matrix_square(odd, even);
23.122 + if ((len2 & 1)!=0)
23.123 + crc1 = gf2_matrix_times(odd, crc1);
23.124 + len2 >>= 1;
23.125 +
23.126 + // if no more bits set, then done
23.127 + } while (len2 != 0);
23.128 +
23.129 + /* return combined crc */
23.130 + crc1 ^= crc2;
23.131 + return crc1;
23.132 + }
23.133 +
23.134 + private static long gf2_matrix_times(long[] mat, long vec){
23.135 + long sum = 0;
23.136 + int index = 0;
23.137 + while (vec!=0) {
23.138 + if ((vec & 1)!=0)
23.139 + sum ^= mat[index];
23.140 + vec >>= 1;
23.141 + index++;
23.142 + }
23.143 + return sum;
23.144 + }
23.145 +
23.146 + static final void gf2_matrix_square(long[] square, long[] mat) {
23.147 + for (int n = 0; n < GF2_DIM; n++)
23.148 + square[n] = gf2_matrix_times(mat, mat[n]);
23.149 + }
23.150 +
23.151 + /*
23.152 + private java.util.zip.CRC32 crc32 = new java.util.zip.CRC32();
23.153 +
23.154 + public void update(byte[] buf, int index, int len){
23.155 + if(buf==null) {crc32.reset();}
23.156 + else{crc32.update(buf, index, len);}
23.157 + }
23.158 + public void reset(){
23.159 + crc32.reset();
23.160 + }
23.161 + public void reset(long init){
23.162 + if(init==0L){
23.163 + crc32.reset();
23.164 + }
23.165 + else{
23.166 + System.err.println("unsupported operation");
23.167 + }
23.168 + }
23.169 + public long getValue(){
23.170 + return crc32.getValue();
23.171 + }
23.172 +*/
23.173 + public CRC32 copy(){
23.174 + CRC32 foo = new CRC32();
23.175 + foo.v = this.v;
23.176 + return foo;
23.177 + }
23.178 +
23.179 + public static int[] getCRC32Table(){
23.180 + int[] tmp = new int[crc_table.length];
23.181 + System.arraycopy(crc_table, 0, tmp, 0, tmp.length);
23.182 + return tmp;
23.183 + }
23.184 +}
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/Checksum.java Fri Feb 15 21:16:05 2013 +0100
24.3 @@ -0,0 +1,43 @@
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 +interface Checksum {
24.41 + void update(byte[] buf, int index, int len);
24.42 + void reset();
24.43 + void reset(long init);
24.44 + long getValue();
24.45 + Checksum copy();
24.46 +}
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/FastJar.java Fri Feb 15 21:16:05 2013 +0100
25.3 @@ -0,0 +1,175 @@
25.4 +/*
25.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
25.6 + *
25.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
25.8 + *
25.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
25.10 + * Other names may be trademarks of their respective owners.
25.11 + *
25.12 + * The contents of this file are subject to the terms of either the GNU
25.13 + * General Public License Version 2 only ("GPL") or the Common
25.14 + * Development and Distribution License("CDDL") (collectively, the
25.15 + * "License"). You may not use this file except in compliance with the
25.16 + * License. You can obtain a copy of the License at
25.17 + * http://www.netbeans.org/cddl-gplv2.html
25.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
25.19 + * specific language governing permissions and limitations under the
25.20 + * License. When distributing the software, include this License Header
25.21 + * Notice in each file and include the License file at
25.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
25.23 + * particular file as subject to the "Classpath" exception as provided
25.24 + * by Oracle in the GPL Version 2 section of the License file that
25.25 + * accompanied this code. If applicable, add the following below the
25.26 + * License Header, with the fields enclosed by brackets [] replaced by
25.27 + * your own identifying information:
25.28 + * "Portions Copyrighted [year] [name of copyright owner]"
25.29 + *
25.30 + * Contributor(s):
25.31 + *
25.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
25.33 + */
25.34 +package org.apidesign.bck2brwsr.emul.zip;
25.35 +
25.36 +import java.io.ByteArrayInputStream;
25.37 +import java.io.IOException;
25.38 +import java.io.InputStream;
25.39 +import java.util.zip.ZipEntry;
25.40 +import java.util.zip.ZipInputStream;
25.41 +
25.42 +/**
25.43 + *
25.44 + * @author Tomas Zezula
25.45 + */
25.46 +public final class FastJar {
25.47 + private final byte[] arr;
25.48 +
25.49 + public FastJar(byte[] arr) {
25.50 + this.arr = arr;
25.51 + }
25.52 +
25.53 +
25.54 + private static final int GIVE_UP = 1<<16;
25.55 +
25.56 + public static final class Entry {
25.57 +
25.58 + public final String name;
25.59 + final long offset;
25.60 + private final long dosTime;
25.61 +
25.62 + Entry (String name, long offset, long time) {
25.63 + assert name != null;
25.64 + this.name = name;
25.65 + this.offset = offset;
25.66 + this.dosTime = time;
25.67 + }
25.68 +/*
25.69 + public long getTime () {
25.70 + Date d = new Date((int)(((dosTime >> 25) & 0x7f) + 80),
25.71 + (int)(((dosTime >> 21) & 0x0f) - 1),
25.72 + (int)((dosTime >> 16) & 0x1f),
25.73 + (int)((dosTime >> 11) & 0x1f),
25.74 + (int)((dosTime >> 5) & 0x3f),
25.75 + (int)((dosTime << 1) & 0x3e));
25.76 + return d.getTime();
25.77 + }
25.78 + */
25.79 + }
25.80 +
25.81 + public InputStream getInputStream (final Entry e) throws IOException {
25.82 + return getInputStream(arr, e.offset);
25.83 + }
25.84 +
25.85 + private static InputStream getInputStream (byte[] arr, final long offset) throws IOException {
25.86 + ByteArrayInputStream is = new ByteArrayInputStream(arr);
25.87 + is.skip(offset);
25.88 + ZipInputStream in = new ZipInputStream (is);
25.89 + ZipEntry e = in.getNextEntry();
25.90 + if (e != null && e.getCrc() == 0L && e.getMethod() == ZipEntry.STORED) {
25.91 + int cp = arr.length - is.available();
25.92 + return new ByteArrayInputStream(arr, cp, (int)e.getSize());
25.93 + }
25.94 + return in;
25.95 + }
25.96 +
25.97 + public Entry[] list() throws IOException {
25.98 + final int size = arr.length;
25.99 +
25.100 + int at = size - ZipInputStream.ENDHDR;
25.101 +
25.102 + byte[] data = new byte[ZipInputStream.ENDHDR];
25.103 + int giveup = 0;
25.104 +
25.105 + do {
25.106 + org.apidesign.bck2brwsr.emul.lang.System.arraycopy(arr, at, data, 0, data.length);
25.107 + at--;
25.108 + giveup++;
25.109 + if (giveup > GIVE_UP) {
25.110 + throw new IOException ();
25.111 + }
25.112 + } while (getsig(data) != ZipInputStream.ENDSIG);
25.113 +
25.114 +
25.115 + final long censize = endsiz(data);
25.116 + final long cenoff = endoff(data);
25.117 + at = (int) cenoff;
25.118 +
25.119 + Entry[] result = new Entry[0];
25.120 + int cenread = 0;
25.121 + data = new byte[ZipInputStream.CENHDR];
25.122 + while (cenread < censize) {
25.123 + org.apidesign.bck2brwsr.emul.lang.System.arraycopy(arr, at, data, 0, data.length);
25.124 + at += data.length;
25.125 + if (getsig(data) != ZipInputStream.CENSIG) {
25.126 + throw new IOException("No central table"); //NOI18N
25.127 + }
25.128 + int cennam = cennam(data);
25.129 + int cenext = cenext(data);
25.130 + int cencom = cencom(data);
25.131 + long lhoff = cenoff(data);
25.132 + long centim = centim(data);
25.133 + String name = new String(arr, at, cennam, "UTF-8");
25.134 + at += cennam;
25.135 + int seekby = cenext+cencom;
25.136 + int cendatalen = ZipInputStream.CENHDR + cennam + seekby;
25.137 + cenread+=cendatalen;
25.138 + result = addEntry(result, new Entry(name,lhoff, centim));
25.139 + at += seekby;
25.140 + }
25.141 + return result;
25.142 + }
25.143 +
25.144 + private Entry[] addEntry(Entry[] result, Entry entry) {
25.145 + Entry[] e = new Entry[result.length + 1];
25.146 + e[result.length] = entry;
25.147 + org.apidesign.bck2brwsr.emul.lang.System.arraycopy(result, 0, e, 0, result.length);
25.148 + return e;
25.149 + }
25.150 +
25.151 + private static final long getsig(final byte[] b) throws IOException {return get32(b,0);}
25.152 + private static final long endsiz(final byte[] b) throws IOException {return get32(b,ZipInputStream.ENDSIZ);}
25.153 + private static final long endoff(final byte[] b) throws IOException {return get32(b,ZipInputStream.ENDOFF);}
25.154 + private static final long cenlen(final byte[] b) throws IOException {return get32(b,ZipInputStream.CENLEN);}
25.155 + private static final long censiz(final byte[] b) throws IOException {return get32(b,ZipInputStream.CENSIZ);}
25.156 + private static final long centim(final byte[] b) throws IOException {return get32(b,ZipInputStream.CENTIM);}
25.157 + private static final int cennam(final byte[] b) throws IOException {return get16(b,ZipInputStream.CENNAM);}
25.158 + private static final int cenext(final byte[] b) throws IOException {return get16(b,ZipInputStream.CENEXT);}
25.159 + private static final int cencom(final byte[] b) throws IOException {return get16(b,ZipInputStream.CENCOM);}
25.160 + private static final long cenoff (final byte[] b) throws IOException {return get32(b,ZipInputStream.CENOFF);}
25.161 + private static final int lochow(final byte[] b) throws IOException {return get16(b,ZipInputStream.LOCHOW);}
25.162 + private static final int locname(final byte[] b) throws IOException {return get16(b,ZipInputStream.LOCNAM);}
25.163 + private static final int locext(final byte[] b) throws IOException {return get16(b,ZipInputStream.LOCEXT);}
25.164 + private static final long locsiz(final byte[] b) throws IOException {return get32(b,ZipInputStream.LOCSIZ);}
25.165 +
25.166 + private static final int get16(final byte[] b, int off) throws IOException {
25.167 + final int b1 = b[off];
25.168 + final int b2 = b[off+1];
25.169 + return (b1 & 0xff) | ((b2 & 0xff) << 8);
25.170 + }
25.171 +
25.172 + private static final long get32(final byte[] b, int off) throws IOException {
25.173 + final int s1 = get16(b, off);
25.174 + final int s2 = get16(b, off+2);
25.175 + return s1 | ((long)s2 << 16);
25.176 + }
25.177 +
25.178 +}
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/GZIPHeader.java Fri Feb 15 21:16:05 2013 +0100
26.3 @@ -0,0 +1,215 @@
26.4 +/* -*-mode:java; c-basic-offset:2; -*- */
26.5 +/*
26.6 +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
26.7 +
26.8 +Redistribution and use in source and binary forms, with or without
26.9 +modification, are permitted provided that the following conditions are met:
26.10 +
26.11 + 1. Redistributions of source code must retain the above copyright notice,
26.12 + this list of conditions and the following disclaimer.
26.13 +
26.14 + 2. Redistributions in binary form must reproduce the above copyright
26.15 + notice, this list of conditions and the following disclaimer in
26.16 + the documentation and/or other materials provided with the distribution.
26.17 +
26.18 + 3. The names of the authors may not be used to endorse or promote products
26.19 + derived from this software without specific prior written permission.
26.20 +
26.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
26.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
26.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
26.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
26.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
26.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26.31 + */
26.32 +/*
26.33 + * This program is based on zlib-1.1.3, so all credit should go authors
26.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
26.35 + * and contributors of zlib.
26.36 + */
26.37 +
26.38 +package org.apidesign.bck2brwsr.emul.zip;
26.39 +
26.40 +import org.apidesign.bck2brwsr.emul.lang.System;
26.41 +import java.io.UnsupportedEncodingException;
26.42 +
26.43 +/**
26.44 + * @see "http://www.ietf.org/rfc/rfc1952.txt"
26.45 + */
26.46 +final class GZIPHeader implements Cloneable {
26.47 +
26.48 + public static final byte OS_MSDOS = (byte) 0x00;
26.49 + public static final byte OS_AMIGA = (byte) 0x01;
26.50 + public static final byte OS_VMS = (byte) 0x02;
26.51 + public static final byte OS_UNIX = (byte) 0x03;
26.52 + public static final byte OS_ATARI = (byte) 0x05;
26.53 + public static final byte OS_OS2 = (byte) 0x06;
26.54 + public static final byte OS_MACOS = (byte) 0x07;
26.55 + public static final byte OS_TOPS20 = (byte) 0x0a;
26.56 + public static final byte OS_WIN32 = (byte) 0x0b;
26.57 + public static final byte OS_VMCMS = (byte) 0x04;
26.58 + public static final byte OS_ZSYSTEM = (byte) 0x08;
26.59 + public static final byte OS_CPM = (byte) 0x09;
26.60 + public static final byte OS_QDOS = (byte) 0x0c;
26.61 + public static final byte OS_RISCOS = (byte) 0x0d;
26.62 + public static final byte OS_UNKNOWN = (byte) 0xff;
26.63 +
26.64 + boolean text = false;
26.65 + private boolean fhcrc = false;
26.66 + long time;
26.67 + int xflags;
26.68 + int os = 255;
26.69 + byte[] extra;
26.70 + byte[] name;
26.71 + byte[] comment;
26.72 + int hcrc;
26.73 + long crc;
26.74 + boolean done = false;
26.75 + long mtime = 0;
26.76 +
26.77 + public void setModifiedTime(long mtime) {
26.78 + this.mtime = mtime;
26.79 + }
26.80 +
26.81 + public long getModifiedTime() {
26.82 + return mtime;
26.83 + }
26.84 +
26.85 + public void setOS(int os) {
26.86 + if((0<=os && os <=13) || os==255)
26.87 + this.os=os;
26.88 + else
26.89 + throw new IllegalArgumentException("os: "+os);
26.90 + }
26.91 +
26.92 + public int getOS(){
26.93 + return os;
26.94 + }
26.95 +
26.96 + public void setName(String name) {
26.97 + try{
26.98 + this.name=name.getBytes("ISO-8859-1");
26.99 + }
26.100 + catch(UnsupportedEncodingException e){
26.101 + throw new IllegalArgumentException("name must be in ISO-8859-1 "+name);
26.102 + }
26.103 + }
26.104 +
26.105 + public String getName(){
26.106 + if(name==null) return "";
26.107 + try {
26.108 + return new String(name, "ISO-8859-1");
26.109 + }
26.110 + catch (UnsupportedEncodingException e) {
26.111 + throw new IllegalArgumentException(e.toString());
26.112 + }
26.113 + }
26.114 +
26.115 + public void setComment(String comment) {
26.116 + try{
26.117 + this.comment=comment.getBytes("ISO-8859-1");
26.118 + }
26.119 + catch(UnsupportedEncodingException e){
26.120 + throw new IllegalArgumentException("comment must be in ISO-8859-1 "+name);
26.121 + }
26.122 + }
26.123 +
26.124 + public String getComment(){
26.125 + if(comment==null) return "";
26.126 + try {
26.127 + return new String(comment, "ISO-8859-1");
26.128 + }
26.129 + catch (UnsupportedEncodingException e) {
26.130 + throw new IllegalArgumentException(e.toString());
26.131 + }
26.132 + }
26.133 +
26.134 + public void setCRC(long crc){
26.135 + this.crc = crc;
26.136 + }
26.137 +
26.138 + public long getCRC(){
26.139 + return crc;
26.140 + }
26.141 +/*
26.142 + void put(Deflate d){
26.143 + int flag = 0;
26.144 + if(text){
26.145 + flag |= 1; // FTEXT
26.146 + }
26.147 + if(fhcrc){
26.148 + flag |= 2; // FHCRC
26.149 + }
26.150 + if(extra!=null){
26.151 + flag |= 4; // FEXTRA
26.152 + }
26.153 + if(name!=null){
26.154 + flag |= 8; // FNAME
26.155 + }
26.156 + if(comment!=null){
26.157 + flag |= 16; // FCOMMENT
26.158 + }
26.159 + int xfl = 0;
26.160 + if(d.level == JZlib.Z_BEST_SPEED){
26.161 + xfl |= 4;
26.162 + }
26.163 + else if (d.level == JZlib.Z_BEST_COMPRESSION){
26.164 + xfl |= 2;
26.165 + }
26.166 +
26.167 + d.put_short((short)0x8b1f); // ID1 ID2
26.168 + d.put_byte((byte)8); // CM(Compression Method)
26.169 + d.put_byte((byte)flag);
26.170 + d.put_byte((byte)mtime);
26.171 + d.put_byte((byte)(mtime>>8));
26.172 + d.put_byte((byte)(mtime>>16));
26.173 + d.put_byte((byte)(mtime>>24));
26.174 + d.put_byte((byte)xfl);
26.175 + d.put_byte((byte)os);
26.176 +
26.177 + if(extra!=null){
26.178 + d.put_byte((byte)extra.length);
26.179 + d.put_byte((byte)(extra.length>>8));
26.180 + d.put_byte(extra, 0, extra.length);
26.181 + }
26.182 +
26.183 + if(name!=null){
26.184 + d.put_byte(name, 0, name.length);
26.185 + d.put_byte((byte)0);
26.186 + }
26.187 +
26.188 + if(comment!=null){
26.189 + d.put_byte(comment, 0, comment.length);
26.190 + d.put_byte((byte)0);
26.191 + }
26.192 + }
26.193 +*/
26.194 + @Override
26.195 + public Object clone() throws CloneNotSupportedException {
26.196 + GZIPHeader gheader = (GZIPHeader)super.clone();
26.197 + byte[] tmp;
26.198 + if(gheader.extra!=null){
26.199 + tmp=new byte[gheader.extra.length];
26.200 + System.arraycopy(gheader.extra, 0, tmp, 0, tmp.length);
26.201 + gheader.extra = tmp;
26.202 + }
26.203 +
26.204 + if(gheader.name!=null){
26.205 + tmp=new byte[gheader.name.length];
26.206 + System.arraycopy(gheader.name, 0, tmp, 0, tmp.length);
26.207 + gheader.name = tmp;
26.208 + }
26.209 +
26.210 + if(gheader.comment!=null){
26.211 + tmp=new byte[gheader.comment.length];
26.212 + System.arraycopy(gheader.comment, 0, tmp, 0, tmp.length);
26.213 + gheader.comment = tmp;
26.214 + }
26.215 +
26.216 + return gheader;
26.217 + }
26.218 +}
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/InfBlocks.java Fri Feb 15 21:16:05 2013 +0100
27.3 @@ -0,0 +1,616 @@
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 +
27.42 +final class InfBlocks{
27.43 + static final private int MANY=1440;
27.44 +
27.45 + // And'ing with mask[n] masks the lower n bits
27.46 + static final private int[] inflate_mask = {
27.47 + 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
27.48 + 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
27.49 + 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
27.50 + 0x00007fff, 0x0000ffff
27.51 + };
27.52 +
27.53 + // Table for deflate from PKZIP's appnote.txt.
27.54 + static final int[] border = { // Order of the bit length code lengths
27.55 + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
27.56 + };
27.57 +
27.58 + static final private int Z_OK=0;
27.59 + static final private int Z_STREAM_END=1;
27.60 + static final private int Z_NEED_DICT=2;
27.61 + static final private int Z_ERRNO=-1;
27.62 + static final private int Z_STREAM_ERROR=-2;
27.63 + static final private int Z_DATA_ERROR=-3;
27.64 + static final private int Z_MEM_ERROR=-4;
27.65 + static final private int Z_BUF_ERROR=-5;
27.66 + static final private int Z_VERSION_ERROR=-6;
27.67 +
27.68 + static final private int TYPE=0; // get type bits (3, including end bit)
27.69 + static final private int LENS=1; // get lengths for stored
27.70 + static final private int STORED=2;// processing stored block
27.71 + static final private int TABLE=3; // get table lengths
27.72 + static final private int BTREE=4; // get bit lengths tree for a dynamic block
27.73 + static final private int DTREE=5; // get length, distance trees for a dynamic block
27.74 + static final private int CODES=6; // processing fixed or dynamic block
27.75 + static final private int DRY=7; // output remaining window bytes
27.76 + static final private int DONE=8; // finished last block, done
27.77 + static final private int BAD=9; // ot a data error--stuck here
27.78 +
27.79 + int mode; // current inflate_block mode
27.80 +
27.81 + int left; // if STORED, bytes left to copy
27.82 +
27.83 + int table; // table lengths (14 bits)
27.84 + int index; // index into blens (or border)
27.85 + int[] blens; // bit lengths of codes
27.86 + int[] bb=new int[1]; // bit length tree depth
27.87 + int[] tb=new int[1]; // bit length decoding tree
27.88 +
27.89 + int[] bl=new int[1];
27.90 + int[] bd=new int[1];
27.91 +
27.92 + int[][] tl=new int[1][];
27.93 + int[][] td=new int[1][];
27.94 + int[] tli=new int[1]; // tl_index
27.95 + int[] tdi=new int[1]; // td_index
27.96 +
27.97 + private final InfCodes codes; // if CODES, current state
27.98 +
27.99 + int last; // true if this block is the last block
27.100 +
27.101 + // mode independent information
27.102 + int bitk; // bits in bit buffer
27.103 + int bitb; // bit buffer
27.104 + int[] hufts; // single malloc for tree space
27.105 + byte[] window; // sliding window
27.106 + int end; // one byte after sliding window
27.107 + int read; // window read pointer
27.108 + int write; // window write pointer
27.109 + private boolean check;
27.110 +
27.111 + private final InfTree inftree=new InfTree();
27.112 +
27.113 + private final ZStream z;
27.114 +
27.115 + InfBlocks(ZStream z, int w){
27.116 + this.z=z;
27.117 + this.codes=new InfCodes(this.z, this);
27.118 + hufts=new int[MANY*3];
27.119 + window=new byte[w];
27.120 + end=w;
27.121 + this.check = (z.istate.wrap==0) ? false : true;
27.122 + mode = TYPE;
27.123 + reset();
27.124 + }
27.125 +
27.126 + void reset(){
27.127 + if(mode==BTREE || mode==DTREE){
27.128 + }
27.129 + if(mode==CODES){
27.130 + codes.free(z);
27.131 + }
27.132 + mode=TYPE;
27.133 + bitk=0;
27.134 + bitb=0;
27.135 + read=write=0;
27.136 + if(check){
27.137 + z.adler.reset();
27.138 + }
27.139 + }
27.140 +
27.141 + int proc(int r){
27.142 + int t; // temporary storage
27.143 + int b; // bit buffer
27.144 + int k; // bits in bit buffer
27.145 + int p; // input data pointer
27.146 + int n; // bytes available there
27.147 + int q; // output window write pointer
27.148 + int m; // bytes to end of window or read pointer
27.149 +
27.150 + // copy input/output information to locals (UPDATE macro restores)
27.151 + {p=z.next_in_index;n=z.avail_in;b=bitb;k=bitk;}
27.152 + {q=write;m=(int)(q<read?read-q-1:end-q);}
27.153 +
27.154 + // process input based on current state
27.155 + while(true){
27.156 + switch (mode){
27.157 + case TYPE:
27.158 +
27.159 + while(k<(3)){
27.160 + if(n!=0){
27.161 + r=Z_OK;
27.162 + }
27.163 + else{
27.164 + bitb=b; bitk=k;
27.165 + z.avail_in=n;
27.166 + z.total_in+=p-z.next_in_index;z.next_in_index=p;
27.167 + write=q;
27.168 + return inflate_flush(r);
27.169 + };
27.170 + n--;
27.171 + b|=(z.next_in[p++]&0xff)<<k;
27.172 + k+=8;
27.173 + }
27.174 + t = (int)(b & 7);
27.175 + last = t & 1;
27.176 +
27.177 + switch (t >>> 1){
27.178 + case 0: // stored
27.179 + {b>>>=(3);k-=(3);}
27.180 + t = k & 7; // go to byte boundary
27.181 +
27.182 + {b>>>=(t);k-=(t);}
27.183 + mode = LENS; // get length of stored block
27.184 + break;
27.185 + case 1: // fixed
27.186 + InfTree.inflate_trees_fixed(bl, bd, tl, td, z);
27.187 + codes.init(bl[0], bd[0], tl[0], 0, td[0], 0);
27.188 +
27.189 + {b>>>=(3);k-=(3);}
27.190 +
27.191 + mode = CODES;
27.192 + break;
27.193 + case 2: // dynamic
27.194 +
27.195 + {b>>>=(3);k-=(3);}
27.196 +
27.197 + mode = TABLE;
27.198 + break;
27.199 + case 3: // illegal
27.200 +
27.201 + {b>>>=(3);k-=(3);}
27.202 + mode = BAD;
27.203 + z.msg = "invalid block type";
27.204 + r = Z_DATA_ERROR;
27.205 +
27.206 + bitb=b; bitk=k;
27.207 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
27.208 + write=q;
27.209 + return inflate_flush(r);
27.210 + }
27.211 + break;
27.212 + case LENS:
27.213 +
27.214 + while(k<(32)){
27.215 + if(n!=0){
27.216 + r=Z_OK;
27.217 + }
27.218 + else{
27.219 + bitb=b; bitk=k;
27.220 + z.avail_in=n;
27.221 + z.total_in+=p-z.next_in_index;z.next_in_index=p;
27.222 + write=q;
27.223 + return inflate_flush(r);
27.224 + };
27.225 + n--;
27.226 + b|=(z.next_in[p++]&0xff)<<k;
27.227 + k+=8;
27.228 + }
27.229 +
27.230 + if ((((~b) >>> 16) & 0xffff) != (b & 0xffff)){
27.231 + mode = BAD;
27.232 + z.msg = "invalid stored block lengths";
27.233 + r = Z_DATA_ERROR;
27.234 +
27.235 + bitb=b; bitk=k;
27.236 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
27.237 + write=q;
27.238 + return inflate_flush(r);
27.239 + }
27.240 + left = (b & 0xffff);
27.241 + b = k = 0; // dump bits
27.242 + mode = left!=0 ? STORED : (last!=0 ? DRY : TYPE);
27.243 + break;
27.244 + case STORED:
27.245 + if (n == 0){
27.246 + bitb=b; bitk=k;
27.247 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
27.248 + write=q;
27.249 + return inflate_flush(r);
27.250 + }
27.251 +
27.252 + if(m==0){
27.253 + if(q==end&&read!=0){
27.254 + q=0; m=(int)(q<read?read-q-1:end-q);
27.255 + }
27.256 + if(m==0){
27.257 + write=q;
27.258 + r=inflate_flush(r);
27.259 + q=write;m=(int)(q<read?read-q-1:end-q);
27.260 + if(q==end&&read!=0){
27.261 + q=0; m=(int)(q<read?read-q-1:end-q);
27.262 + }
27.263 + if(m==0){
27.264 + bitb=b; bitk=k;
27.265 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
27.266 + write=q;
27.267 + return inflate_flush(r);
27.268 + }
27.269 + }
27.270 + }
27.271 + r=Z_OK;
27.272 +
27.273 + t = left;
27.274 + if(t>n) t = n;
27.275 + if(t>m) t = m;
27.276 + System.arraycopy(z.next_in, p, window, q, t);
27.277 + p += t; n -= t;
27.278 + q += t; m -= t;
27.279 + if ((left -= t) != 0)
27.280 + break;
27.281 + mode = last!=0 ? DRY : TYPE;
27.282 + break;
27.283 + case TABLE:
27.284 +
27.285 + while(k<(14)){
27.286 + if(n!=0){
27.287 + r=Z_OK;
27.288 + }
27.289 + else{
27.290 + bitb=b; bitk=k;
27.291 + z.avail_in=n;
27.292 + z.total_in+=p-z.next_in_index;z.next_in_index=p;
27.293 + write=q;
27.294 + return inflate_flush(r);
27.295 + };
27.296 + n--;
27.297 + b|=(z.next_in[p++]&0xff)<<k;
27.298 + k+=8;
27.299 + }
27.300 +
27.301 + table = t = (b & 0x3fff);
27.302 + if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
27.303 + {
27.304 + mode = BAD;
27.305 + z.msg = "too many length or distance symbols";
27.306 + r = Z_DATA_ERROR;
27.307 +
27.308 + bitb=b; bitk=k;
27.309 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
27.310 + write=q;
27.311 + return inflate_flush(r);
27.312 + }
27.313 + t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
27.314 + if(blens==null || blens.length<t){
27.315 + blens=new int[t];
27.316 + }
27.317 + else{
27.318 + for(int i=0; i<t; i++){blens[i]=0;}
27.319 + }
27.320 +
27.321 + {b>>>=(14);k-=(14);}
27.322 +
27.323 + index = 0;
27.324 + mode = BTREE;
27.325 + case BTREE:
27.326 + while (index < 4 + (table >>> 10)){
27.327 + while(k<(3)){
27.328 + if(n!=0){
27.329 + r=Z_OK;
27.330 + }
27.331 + else{
27.332 + bitb=b; bitk=k;
27.333 + z.avail_in=n;
27.334 + z.total_in+=p-z.next_in_index;z.next_in_index=p;
27.335 + write=q;
27.336 + return inflate_flush(r);
27.337 + };
27.338 + n--;
27.339 + b|=(z.next_in[p++]&0xff)<<k;
27.340 + k+=8;
27.341 + }
27.342 +
27.343 + blens[border[index++]] = b&7;
27.344 +
27.345 + {b>>>=(3);k-=(3);}
27.346 + }
27.347 +
27.348 + while(index < 19){
27.349 + blens[border[index++]] = 0;
27.350 + }
27.351 +
27.352 + bb[0] = 7;
27.353 + t = inftree.inflate_trees_bits(blens, bb, tb, hufts, z);
27.354 + if (t != Z_OK){
27.355 + r = t;
27.356 + if (r == Z_DATA_ERROR){
27.357 + blens=null;
27.358 + mode = BAD;
27.359 + }
27.360 +
27.361 + bitb=b; bitk=k;
27.362 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
27.363 + write=q;
27.364 + return inflate_flush(r);
27.365 + }
27.366 +
27.367 + index = 0;
27.368 + mode = DTREE;
27.369 + case DTREE:
27.370 + while (true){
27.371 + t = table;
27.372 + if(!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))){
27.373 + break;
27.374 + }
27.375 +
27.376 + int[] h;
27.377 + int i, j, c;
27.378 +
27.379 + t = bb[0];
27.380 +
27.381 + while(k<(t)){
27.382 + if(n!=0){
27.383 + r=Z_OK;
27.384 + }
27.385 + else{
27.386 + bitb=b; bitk=k;
27.387 + z.avail_in=n;
27.388 + z.total_in+=p-z.next_in_index;z.next_in_index=p;
27.389 + write=q;
27.390 + return inflate_flush(r);
27.391 + };
27.392 + n--;
27.393 + b|=(z.next_in[p++]&0xff)<<k;
27.394 + k+=8;
27.395 + }
27.396 +
27.397 + if(tb[0]==-1){
27.398 + //System.err.println("null...");
27.399 + }
27.400 +
27.401 + t=hufts[(tb[0]+(b&inflate_mask[t]))*3+1];
27.402 + c=hufts[(tb[0]+(b&inflate_mask[t]))*3+2];
27.403 +
27.404 + if (c < 16){
27.405 + b>>>=(t);k-=(t);
27.406 + blens[index++] = c;
27.407 + }
27.408 + else { // c == 16..18
27.409 + i = c == 18 ? 7 : c - 14;
27.410 + j = c == 18 ? 11 : 3;
27.411 +
27.412 + while(k<(t+i)){
27.413 + if(n!=0){
27.414 + r=Z_OK;
27.415 + }
27.416 + else{
27.417 + bitb=b; bitk=k;
27.418 + z.avail_in=n;
27.419 + z.total_in+=p-z.next_in_index;z.next_in_index=p;
27.420 + write=q;
27.421 + return inflate_flush(r);
27.422 + };
27.423 + n--;
27.424 + b|=(z.next_in[p++]&0xff)<<k;
27.425 + k+=8;
27.426 + }
27.427 +
27.428 + b>>>=(t);k-=(t);
27.429 +
27.430 + j += (b & inflate_mask[i]);
27.431 +
27.432 + b>>>=(i);k-=(i);
27.433 +
27.434 + i = index;
27.435 + t = table;
27.436 + if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
27.437 + (c == 16 && i < 1)){
27.438 + blens=null;
27.439 + mode = BAD;
27.440 + z.msg = "invalid bit length repeat";
27.441 + r = Z_DATA_ERROR;
27.442 +
27.443 + bitb=b; bitk=k;
27.444 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
27.445 + write=q;
27.446 + return inflate_flush(r);
27.447 + }
27.448 +
27.449 + c = c == 16 ? blens[i-1] : 0;
27.450 + do{
27.451 + blens[i++] = c;
27.452 + }
27.453 + while (--j!=0);
27.454 + index = i;
27.455 + }
27.456 + }
27.457 +
27.458 + tb[0]=-1;
27.459 + {
27.460 + bl[0] = 9; // must be <= 9 for lookahead assumptions
27.461 + bd[0] = 6; // must be <= 9 for lookahead assumptions
27.462 + t = table;
27.463 + t = inftree.inflate_trees_dynamic(257 + (t & 0x1f),
27.464 + 1 + ((t >> 5) & 0x1f),
27.465 + blens, bl, bd, tli, tdi, hufts, z);
27.466 +
27.467 + if (t != Z_OK){
27.468 + if (t == Z_DATA_ERROR){
27.469 + blens=null;
27.470 + mode = BAD;
27.471 + }
27.472 + r = t;
27.473 +
27.474 + bitb=b; bitk=k;
27.475 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
27.476 + write=q;
27.477 + return inflate_flush(r);
27.478 + }
27.479 + codes.init(bl[0], bd[0], hufts, tli[0], hufts, tdi[0]);
27.480 + }
27.481 + mode = CODES;
27.482 + case CODES:
27.483 + bitb=b; bitk=k;
27.484 + z.avail_in=n; z.total_in+=p-z.next_in_index;z.next_in_index=p;
27.485 + write=q;
27.486 +
27.487 + if ((r = codes.proc(r)) != Z_STREAM_END){
27.488 + return inflate_flush(r);
27.489 + }
27.490 + r = Z_OK;
27.491 + codes.free(z);
27.492 +
27.493 + p=z.next_in_index; n=z.avail_in;b=bitb;k=bitk;
27.494 + q=write;m=(int)(q<read?read-q-1:end-q);
27.495 +
27.496 + if (last==0){
27.497 + mode = TYPE;
27.498 + break;
27.499 + }
27.500 + mode = DRY;
27.501 + case DRY:
27.502 + write=q;
27.503 + r=inflate_flush(r);
27.504 + q=write; m=(int)(q<read?read-q-1:end-q);
27.505 + if (read != write){
27.506 + bitb=b; bitk=k;
27.507 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
27.508 + write=q;
27.509 + return inflate_flush(r);
27.510 + }
27.511 + mode = DONE;
27.512 + case DONE:
27.513 + r = Z_STREAM_END;
27.514 +
27.515 + bitb=b; bitk=k;
27.516 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
27.517 + write=q;
27.518 + return inflate_flush(r);
27.519 + case BAD:
27.520 + r = Z_DATA_ERROR;
27.521 +
27.522 + bitb=b; bitk=k;
27.523 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
27.524 + write=q;
27.525 + return inflate_flush(r);
27.526 +
27.527 + default:
27.528 + r = Z_STREAM_ERROR;
27.529 +
27.530 + bitb=b; bitk=k;
27.531 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
27.532 + write=q;
27.533 + return inflate_flush(r);
27.534 + }
27.535 + }
27.536 + }
27.537 +
27.538 + void free(){
27.539 + reset();
27.540 + window=null;
27.541 + hufts=null;
27.542 + //ZFREE(z, s);
27.543 + }
27.544 +
27.545 + void set_dictionary(byte[] d, int start, int n){
27.546 + System.arraycopy(d, start, window, 0, n);
27.547 + read = write = n;
27.548 + }
27.549 +
27.550 + // Returns true if inflate is currently at the end of a block generated
27.551 + // by Z_SYNC_FLUSH or Z_FULL_FLUSH.
27.552 + int sync_point(){
27.553 + return mode == LENS ? 1 : 0;
27.554 + }
27.555 +
27.556 + // copy as much as possible from the sliding window to the output area
27.557 + int inflate_flush(int r){
27.558 + int n;
27.559 + int p;
27.560 + int q;
27.561 +
27.562 + // local copies of source and destination pointers
27.563 + p = z.next_out_index;
27.564 + q = read;
27.565 +
27.566 + // compute number of bytes to copy as far as end of window
27.567 + n = (int)((q <= write ? write : end) - q);
27.568 + if(n > z.avail_out) n = z.avail_out;
27.569 + if(n!=0 && r == Z_BUF_ERROR) r = Z_OK;
27.570 +
27.571 + // update counters
27.572 + z.avail_out -= n;
27.573 + z.total_out += n;
27.574 +
27.575 + // update check information
27.576 + if(check && n>0){
27.577 + z.adler.update(window, q, n);
27.578 + }
27.579 +
27.580 + // copy as far as end of window
27.581 + System.arraycopy(window, q, z.next_out, p, n);
27.582 + p += n;
27.583 + q += n;
27.584 +
27.585 + // see if more to copy at beginning of window
27.586 + if (q == end){
27.587 + // wrap pointers
27.588 + q = 0;
27.589 + if (write == end)
27.590 + write = 0;
27.591 +
27.592 + // compute bytes to copy
27.593 + n = write - q;
27.594 + if (n > z.avail_out) n = z.avail_out;
27.595 + if (n!=0 && r == Z_BUF_ERROR) r = Z_OK;
27.596 +
27.597 + // update counters
27.598 + z.avail_out -= n;
27.599 + z.total_out += n;
27.600 +
27.601 + // update check information
27.602 + if(check && n>0){
27.603 + z.adler.update(window, q, n);
27.604 + }
27.605 +
27.606 + // copy
27.607 + System.arraycopy(window, q, z.next_out, p, n);
27.608 + p += n;
27.609 + q += n;
27.610 + }
27.611 +
27.612 + // update pointers
27.613 + z.next_out_index = p;
27.614 + read = q;
27.615 +
27.616 + // done
27.617 + return r;
27.618 + }
27.619 +}
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/InfCodes.java Fri Feb 15 21:16:05 2013 +0100
28.3 @@ -0,0 +1,612 @@
28.4 +/* -*-mode:java; c-basic-offset:2; -*- */
28.5 +/*
28.6 +Copyright (c) 2000,2001,2002,2003 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 InfCodes{
28.43 +
28.44 + static final private int[] inflate_mask = {
28.45 + 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
28.46 + 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
28.47 + 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
28.48 + 0x00007fff, 0x0000ffff
28.49 + };
28.50 +
28.51 + static final private int Z_OK=0;
28.52 + static final private int Z_STREAM_END=1;
28.53 + static final private int Z_NEED_DICT=2;
28.54 + static final private int Z_ERRNO=-1;
28.55 + static final private int Z_STREAM_ERROR=-2;
28.56 + static final private int Z_DATA_ERROR=-3;
28.57 + static final private int Z_MEM_ERROR=-4;
28.58 + static final private int Z_BUF_ERROR=-5;
28.59 + static final private int Z_VERSION_ERROR=-6;
28.60 +
28.61 + // waiting for "i:"=input,
28.62 + // "o:"=output,
28.63 + // "x:"=nothing
28.64 + static final private int START=0; // x: set up for LEN
28.65 + static final private int LEN=1; // i: get length/literal/eob next
28.66 + static final private int LENEXT=2; // i: getting length extra (have base)
28.67 + static final private int DIST=3; // i: get distance next
28.68 + static final private int DISTEXT=4;// i: getting distance extra
28.69 + static final private int COPY=5; // o: copying bytes in window, waiting for space
28.70 + static final private int LIT=6; // o: got literal, waiting for output space
28.71 + static final private int WASH=7; // o: got eob, possibly still output waiting
28.72 + static final private int END=8; // x: got eob and all data flushed
28.73 + static final private int BADCODE=9;// x: got error
28.74 +
28.75 + int mode; // current inflate_codes mode
28.76 +
28.77 + // mode dependent information
28.78 + int len;
28.79 +
28.80 + int[] tree; // pointer into tree
28.81 + int tree_index=0;
28.82 + int need; // bits needed
28.83 +
28.84 + int lit;
28.85 +
28.86 + // if EXT or COPY, where and how much
28.87 + int get; // bits to get for extra
28.88 + int dist; // distance back to copy from
28.89 +
28.90 + byte lbits; // ltree bits decoded per branch
28.91 + byte dbits; // dtree bits decoder per branch
28.92 + int[] ltree; // literal/length/eob tree
28.93 + int ltree_index; // literal/length/eob tree
28.94 + int[] dtree; // distance tree
28.95 + int dtree_index; // distance tree
28.96 +
28.97 + private final ZStream z;
28.98 + private final InfBlocks s;
28.99 + InfCodes(ZStream z, InfBlocks s){
28.100 + this.z=z;
28.101 + this.s=s;
28.102 + }
28.103 +
28.104 + void init(int bl, int bd,
28.105 + int[] tl, int tl_index,
28.106 + int[] td, int td_index){
28.107 + mode=START;
28.108 + lbits=(byte)bl;
28.109 + dbits=(byte)bd;
28.110 + ltree=tl;
28.111 + ltree_index=tl_index;
28.112 + dtree = td;
28.113 + dtree_index=td_index;
28.114 + tree=null;
28.115 + }
28.116 +
28.117 + int proc(int r){
28.118 + int j; // temporary storage
28.119 + int[] t; // temporary pointer
28.120 + int tindex; // temporary pointer
28.121 + int e; // extra bits or operation
28.122 + int b=0; // bit buffer
28.123 + int k=0; // bits in bit buffer
28.124 + int p=0; // input data pointer
28.125 + int n; // bytes available there
28.126 + int q; // output window write pointer
28.127 + int m; // bytes to end of window or read pointer
28.128 + int f; // pointer to copy strings from
28.129 +
28.130 + // copy input/output information to locals (UPDATE macro restores)
28.131 + p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
28.132 + q=s.write;m=q<s.read?s.read-q-1:s.end-q;
28.133 +
28.134 + // process input and output based on current state
28.135 + while (true){
28.136 + switch (mode){
28.137 + // waiting for "i:"=input, "o:"=output, "x:"=nothing
28.138 + case START: // x: set up for LEN
28.139 + if (m >= 258 && n >= 10){
28.140 +
28.141 + s.bitb=b;s.bitk=k;
28.142 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
28.143 + s.write=q;
28.144 + r = inflate_fast(lbits, dbits,
28.145 + ltree, ltree_index,
28.146 + dtree, dtree_index,
28.147 + s, z);
28.148 +
28.149 + p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
28.150 + q=s.write;m=q<s.read?s.read-q-1:s.end-q;
28.151 +
28.152 + if (r != Z_OK){
28.153 + mode = r == Z_STREAM_END ? WASH : BADCODE;
28.154 + break;
28.155 + }
28.156 + }
28.157 + need = lbits;
28.158 + tree = ltree;
28.159 + tree_index=ltree_index;
28.160 +
28.161 + mode = LEN;
28.162 + case LEN: // i: get length/literal/eob next
28.163 + j = need;
28.164 +
28.165 + while(k<(j)){
28.166 + if(n!=0)r=Z_OK;
28.167 + else{
28.168 +
28.169 + s.bitb=b;s.bitk=k;
28.170 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
28.171 + s.write=q;
28.172 + return s.inflate_flush(r);
28.173 + }
28.174 + n--;
28.175 + b|=(z.next_in[p++]&0xff)<<k;
28.176 + k+=8;
28.177 + }
28.178 +
28.179 + tindex=(tree_index+(b&inflate_mask[j]))*3;
28.180 +
28.181 + b>>>=(tree[tindex+1]);
28.182 + k-=(tree[tindex+1]);
28.183 +
28.184 + e=tree[tindex];
28.185 +
28.186 + if(e == 0){ // literal
28.187 + lit = tree[tindex+2];
28.188 + mode = LIT;
28.189 + break;
28.190 + }
28.191 + if((e & 16)!=0 ){ // length
28.192 + get = e & 15;
28.193 + len = tree[tindex+2];
28.194 + mode = LENEXT;
28.195 + break;
28.196 + }
28.197 + if ((e & 64) == 0){ // next table
28.198 + need = e;
28.199 + tree_index = tindex/3+tree[tindex+2];
28.200 + break;
28.201 + }
28.202 + if ((e & 32)!=0){ // end of block
28.203 + mode = WASH;
28.204 + break;
28.205 + }
28.206 + mode = BADCODE; // invalid code
28.207 + z.msg = "invalid literal/length code";
28.208 + r = Z_DATA_ERROR;
28.209 +
28.210 + s.bitb=b;s.bitk=k;
28.211 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
28.212 + s.write=q;
28.213 + return s.inflate_flush(r);
28.214 +
28.215 + case LENEXT: // i: getting length extra (have base)
28.216 + j = get;
28.217 +
28.218 + while(k<(j)){
28.219 + if(n!=0)r=Z_OK;
28.220 + else{
28.221 +
28.222 + s.bitb=b;s.bitk=k;
28.223 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
28.224 + s.write=q;
28.225 + return s.inflate_flush(r);
28.226 + }
28.227 + n--; b|=(z.next_in[p++]&0xff)<<k;
28.228 + k+=8;
28.229 + }
28.230 +
28.231 + len += (b & inflate_mask[j]);
28.232 +
28.233 + b>>=j;
28.234 + k-=j;
28.235 +
28.236 + need = dbits;
28.237 + tree = dtree;
28.238 + tree_index=dtree_index;
28.239 + mode = DIST;
28.240 + case DIST: // i: get distance next
28.241 + j = need;
28.242 +
28.243 + while(k<(j)){
28.244 + if(n!=0)r=Z_OK;
28.245 + else{
28.246 +
28.247 + s.bitb=b;s.bitk=k;
28.248 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
28.249 + s.write=q;
28.250 + return s.inflate_flush(r);
28.251 + }
28.252 + n--; b|=(z.next_in[p++]&0xff)<<k;
28.253 + k+=8;
28.254 + }
28.255 +
28.256 + tindex=(tree_index+(b & inflate_mask[j]))*3;
28.257 +
28.258 + b>>=tree[tindex+1];
28.259 + k-=tree[tindex+1];
28.260 +
28.261 + e = (tree[tindex]);
28.262 + if((e & 16)!=0){ // distance
28.263 + get = e & 15;
28.264 + dist = tree[tindex+2];
28.265 + mode = DISTEXT;
28.266 + break;
28.267 + }
28.268 + if ((e & 64) == 0){ // next table
28.269 + need = e;
28.270 + tree_index = tindex/3 + tree[tindex+2];
28.271 + break;
28.272 + }
28.273 + mode = BADCODE; // invalid code
28.274 + z.msg = "invalid distance code";
28.275 + r = Z_DATA_ERROR;
28.276 +
28.277 + s.bitb=b;s.bitk=k;
28.278 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
28.279 + s.write=q;
28.280 + return s.inflate_flush(r);
28.281 +
28.282 + case DISTEXT: // i: getting distance extra
28.283 + j = get;
28.284 +
28.285 + while(k<(j)){
28.286 + if(n!=0)r=Z_OK;
28.287 + else{
28.288 +
28.289 + s.bitb=b;s.bitk=k;
28.290 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
28.291 + s.write=q;
28.292 + return s.inflate_flush(r);
28.293 + }
28.294 + n--; b|=(z.next_in[p++]&0xff)<<k;
28.295 + k+=8;
28.296 + }
28.297 +
28.298 + dist += (b & inflate_mask[j]);
28.299 +
28.300 + b>>=j;
28.301 + k-=j;
28.302 +
28.303 + mode = COPY;
28.304 + case COPY: // o: copying bytes in window, waiting for space
28.305 + f = q - dist;
28.306 + while(f < 0){ // modulo window size-"while" instead
28.307 + f += s.end; // of "if" handles invalid distances
28.308 + }
28.309 + while (len!=0){
28.310 +
28.311 + if(m==0){
28.312 + if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
28.313 + if(m==0){
28.314 + s.write=q; r=s.inflate_flush(r);
28.315 + q=s.write;m=q<s.read?s.read-q-1:s.end-q;
28.316 +
28.317 + if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
28.318 +
28.319 + if(m==0){
28.320 + s.bitb=b;s.bitk=k;
28.321 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
28.322 + s.write=q;
28.323 + return s.inflate_flush(r);
28.324 + }
28.325 + }
28.326 + }
28.327 +
28.328 + s.window[q++]=s.window[f++]; m--;
28.329 +
28.330 + if (f == s.end)
28.331 + f = 0;
28.332 + len--;
28.333 + }
28.334 + mode = START;
28.335 + break;
28.336 + case LIT: // o: got literal, waiting for output space
28.337 + if(m==0){
28.338 + if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
28.339 + if(m==0){
28.340 + s.write=q; r=s.inflate_flush(r);
28.341 + q=s.write;m=q<s.read?s.read-q-1:s.end-q;
28.342 +
28.343 + if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
28.344 + if(m==0){
28.345 + s.bitb=b;s.bitk=k;
28.346 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
28.347 + s.write=q;
28.348 + return s.inflate_flush(r);
28.349 + }
28.350 + }
28.351 + }
28.352 + r=Z_OK;
28.353 +
28.354 + s.window[q++]=(byte)lit; m--;
28.355 +
28.356 + mode = START;
28.357 + break;
28.358 + case WASH: // o: got eob, possibly more output
28.359 + if (k > 7){ // return unused byte, if any
28.360 + k -= 8;
28.361 + n++;
28.362 + p--; // can always return one
28.363 + }
28.364 +
28.365 + s.write=q; r=s.inflate_flush(r);
28.366 + q=s.write;m=q<s.read?s.read-q-1:s.end-q;
28.367 +
28.368 + if (s.read != s.write){
28.369 + s.bitb=b;s.bitk=k;
28.370 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
28.371 + s.write=q;
28.372 + return s.inflate_flush(r);
28.373 + }
28.374 + mode = END;
28.375 + case END:
28.376 + r = Z_STREAM_END;
28.377 + s.bitb=b;s.bitk=k;
28.378 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
28.379 + s.write=q;
28.380 + return s.inflate_flush(r);
28.381 +
28.382 + case BADCODE: // x: got error
28.383 +
28.384 + r = Z_DATA_ERROR;
28.385 +
28.386 + s.bitb=b;s.bitk=k;
28.387 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
28.388 + s.write=q;
28.389 + return s.inflate_flush(r);
28.390 +
28.391 + default:
28.392 + r = Z_STREAM_ERROR;
28.393 +
28.394 + s.bitb=b;s.bitk=k;
28.395 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
28.396 + s.write=q;
28.397 + return s.inflate_flush(r);
28.398 + }
28.399 + }
28.400 + }
28.401 +
28.402 + void free(ZStream z){
28.403 + // ZFREE(z, c);
28.404 + }
28.405 +
28.406 + // Called with number of bytes left to write in window at least 258
28.407 + // (the maximum string length) and number of input bytes available
28.408 + // at least ten. The ten bytes are six bytes for the longest length/
28.409 + // distance pair plus four bytes for overloading the bit buffer.
28.410 +
28.411 + int inflate_fast(int bl, int bd,
28.412 + int[] tl, int tl_index,
28.413 + int[] td, int td_index,
28.414 + InfBlocks s, ZStream z){
28.415 + int t; // temporary pointer
28.416 + int[] tp; // temporary pointer
28.417 + int tp_index; // temporary pointer
28.418 + int e; // extra bits or operation
28.419 + int b; // bit buffer
28.420 + int k; // bits in bit buffer
28.421 + int p; // input data pointer
28.422 + int n; // bytes available there
28.423 + int q; // output window write pointer
28.424 + int m; // bytes to end of window or read pointer
28.425 + int ml; // mask for literal/length tree
28.426 + int md; // mask for distance tree
28.427 + int c; // bytes to copy
28.428 + int d; // distance back to copy from
28.429 + int r; // copy source pointer
28.430 +
28.431 + int tp_index_t_3; // (tp_index+t)*3
28.432 +
28.433 + // load input, output, bit values
28.434 + p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
28.435 + q=s.write;m=q<s.read?s.read-q-1:s.end-q;
28.436 +
28.437 + // initialize masks
28.438 + ml = inflate_mask[bl];
28.439 + md = inflate_mask[bd];
28.440 +
28.441 + // do until not enough input or output space for fast loop
28.442 + do { // assume called with m >= 258 && n >= 10
28.443 + // get literal/length code
28.444 + while(k<(20)){ // max bits for literal/length code
28.445 + n--;
28.446 + b|=(z.next_in[p++]&0xff)<<k;k+=8;
28.447 + }
28.448 +
28.449 + t= b&ml;
28.450 + tp=tl;
28.451 + tp_index=tl_index;
28.452 + tp_index_t_3=(tp_index+t)*3;
28.453 + if ((e = tp[tp_index_t_3]) == 0){
28.454 + b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
28.455 +
28.456 + s.window[q++] = (byte)tp[tp_index_t_3+2];
28.457 + m--;
28.458 + continue;
28.459 + }
28.460 + do {
28.461 +
28.462 + b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
28.463 +
28.464 + if((e&16)!=0){
28.465 + e &= 15;
28.466 + c = tp[tp_index_t_3+2] + ((int)b & inflate_mask[e]);
28.467 +
28.468 + b>>=e; k-=e;
28.469 +
28.470 + // decode distance base of block to copy
28.471 + while(k<(15)){ // max bits for distance code
28.472 + n--;
28.473 + b|=(z.next_in[p++]&0xff)<<k;k+=8;
28.474 + }
28.475 +
28.476 + t= b&md;
28.477 + tp=td;
28.478 + tp_index=td_index;
28.479 + tp_index_t_3=(tp_index+t)*3;
28.480 + e = tp[tp_index_t_3];
28.481 +
28.482 + do {
28.483 +
28.484 + b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
28.485 +
28.486 + if((e&16)!=0){
28.487 + // get extra bits to add to distance base
28.488 + e &= 15;
28.489 + while(k<(e)){ // get extra bits (up to 13)
28.490 + n--;
28.491 + b|=(z.next_in[p++]&0xff)<<k;k+=8;
28.492 + }
28.493 +
28.494 + d = tp[tp_index_t_3+2] + (b&inflate_mask[e]);
28.495 +
28.496 + b>>=(e); k-=(e);
28.497 +
28.498 + // do the copy
28.499 + m -= c;
28.500 + if (q >= d){ // offset before dest
28.501 + // just copy
28.502 + r=q-d;
28.503 + if(q-r>0 && 2>(q-r)){
28.504 + s.window[q++]=s.window[r++]; // minimum count is three,
28.505 + s.window[q++]=s.window[r++]; // so unroll loop a little
28.506 + c-=2;
28.507 + }
28.508 + else{
28.509 + System.arraycopy(s.window, r, s.window, q, 2);
28.510 + q+=2; r+=2; c-=2;
28.511 + }
28.512 + }
28.513 + else{ // else offset after destination
28.514 + r=q-d;
28.515 + do{
28.516 + r+=s.end; // force pointer in window
28.517 + }while(r<0); // covers invalid distances
28.518 + e=s.end-r;
28.519 + if(c>e){ // if source crosses,
28.520 + c-=e; // wrapped copy
28.521 + if(q-r>0 && e>(q-r)){
28.522 + do{s.window[q++] = s.window[r++];}
28.523 + while(--e!=0);
28.524 + }
28.525 + else{
28.526 + System.arraycopy(s.window, r, s.window, q, e);
28.527 + q+=e; r+=e; e=0;
28.528 + }
28.529 + r = 0; // copy rest from start of window
28.530 + }
28.531 +
28.532 + }
28.533 +
28.534 + // copy all or what's left
28.535 + if(q-r>0 && c>(q-r)){
28.536 + do{s.window[q++] = s.window[r++];}
28.537 + while(--c!=0);
28.538 + }
28.539 + else{
28.540 + System.arraycopy(s.window, r, s.window, q, c);
28.541 + q+=c; r+=c; c=0;
28.542 + }
28.543 + break;
28.544 + }
28.545 + else if((e&64)==0){
28.546 + t+=tp[tp_index_t_3+2];
28.547 + t+=(b&inflate_mask[e]);
28.548 + tp_index_t_3=(tp_index+t)*3;
28.549 + e=tp[tp_index_t_3];
28.550 + }
28.551 + else{
28.552 + z.msg = "invalid distance code";
28.553 +
28.554 + c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
28.555 +
28.556 + s.bitb=b;s.bitk=k;
28.557 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
28.558 + s.write=q;
28.559 +
28.560 + return Z_DATA_ERROR;
28.561 + }
28.562 + }
28.563 + while(true);
28.564 + break;
28.565 + }
28.566 +
28.567 + if((e&64)==0){
28.568 + t+=tp[tp_index_t_3+2];
28.569 + t+=(b&inflate_mask[e]);
28.570 + tp_index_t_3=(tp_index+t)*3;
28.571 + if((e=tp[tp_index_t_3])==0){
28.572 +
28.573 + b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
28.574 +
28.575 + s.window[q++]=(byte)tp[tp_index_t_3+2];
28.576 + m--;
28.577 + break;
28.578 + }
28.579 + }
28.580 + else if((e&32)!=0){
28.581 +
28.582 + c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
28.583 +
28.584 + s.bitb=b;s.bitk=k;
28.585 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
28.586 + s.write=q;
28.587 +
28.588 + return Z_STREAM_END;
28.589 + }
28.590 + else{
28.591 + z.msg="invalid literal/length code";
28.592 +
28.593 + c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
28.594 +
28.595 + s.bitb=b;s.bitk=k;
28.596 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
28.597 + s.write=q;
28.598 +
28.599 + return Z_DATA_ERROR;
28.600 + }
28.601 + }
28.602 + while(true);
28.603 + }
28.604 + while(m>=258 && n>= 10);
28.605 +
28.606 + // not enough input or output--restore pointers and return
28.607 + c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
28.608 +
28.609 + s.bitb=b;s.bitk=k;
28.610 + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
28.611 + s.write=q;
28.612 +
28.613 + return Z_OK;
28.614 + }
28.615 +}
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/InfTree.java Fri Feb 15 21:16:05 2013 +0100
29.3 @@ -0,0 +1,520 @@
29.4 +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
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 InfTree{
29.43 +
29.44 + static final private int MANY=1440;
29.45 +
29.46 + static final private int Z_OK=0;
29.47 + static final private int Z_STREAM_END=1;
29.48 + static final private int Z_NEED_DICT=2;
29.49 + static final private int Z_ERRNO=-1;
29.50 + static final private int Z_STREAM_ERROR=-2;
29.51 + static final private int Z_DATA_ERROR=-3;
29.52 + static final private int Z_MEM_ERROR=-4;
29.53 + static final private int Z_BUF_ERROR=-5;
29.54 + static final private int Z_VERSION_ERROR=-6;
29.55 +
29.56 + static final int fixed_bl = 9;
29.57 + static final int fixed_bd = 5;
29.58 +
29.59 + static final int[] fixed_tl = {
29.60 + 96,7,256, 0,8,80, 0,8,16, 84,8,115,
29.61 + 82,7,31, 0,8,112, 0,8,48, 0,9,192,
29.62 + 80,7,10, 0,8,96, 0,8,32, 0,9,160,
29.63 + 0,8,0, 0,8,128, 0,8,64, 0,9,224,
29.64 + 80,7,6, 0,8,88, 0,8,24, 0,9,144,
29.65 + 83,7,59, 0,8,120, 0,8,56, 0,9,208,
29.66 + 81,7,17, 0,8,104, 0,8,40, 0,9,176,
29.67 + 0,8,8, 0,8,136, 0,8,72, 0,9,240,
29.68 + 80,7,4, 0,8,84, 0,8,20, 85,8,227,
29.69 + 83,7,43, 0,8,116, 0,8,52, 0,9,200,
29.70 + 81,7,13, 0,8,100, 0,8,36, 0,9,168,
29.71 + 0,8,4, 0,8,132, 0,8,68, 0,9,232,
29.72 + 80,7,8, 0,8,92, 0,8,28, 0,9,152,
29.73 + 84,7,83, 0,8,124, 0,8,60, 0,9,216,
29.74 + 82,7,23, 0,8,108, 0,8,44, 0,9,184,
29.75 + 0,8,12, 0,8,140, 0,8,76, 0,9,248,
29.76 + 80,7,3, 0,8,82, 0,8,18, 85,8,163,
29.77 + 83,7,35, 0,8,114, 0,8,50, 0,9,196,
29.78 + 81,7,11, 0,8,98, 0,8,34, 0,9,164,
29.79 + 0,8,2, 0,8,130, 0,8,66, 0,9,228,
29.80 + 80,7,7, 0,8,90, 0,8,26, 0,9,148,
29.81 + 84,7,67, 0,8,122, 0,8,58, 0,9,212,
29.82 + 82,7,19, 0,8,106, 0,8,42, 0,9,180,
29.83 + 0,8,10, 0,8,138, 0,8,74, 0,9,244,
29.84 + 80,7,5, 0,8,86, 0,8,22, 192,8,0,
29.85 + 83,7,51, 0,8,118, 0,8,54, 0,9,204,
29.86 + 81,7,15, 0,8,102, 0,8,38, 0,9,172,
29.87 + 0,8,6, 0,8,134, 0,8,70, 0,9,236,
29.88 + 80,7,9, 0,8,94, 0,8,30, 0,9,156,
29.89 + 84,7,99, 0,8,126, 0,8,62, 0,9,220,
29.90 + 82,7,27, 0,8,110, 0,8,46, 0,9,188,
29.91 + 0,8,14, 0,8,142, 0,8,78, 0,9,252,
29.92 + 96,7,256, 0,8,81, 0,8,17, 85,8,131,
29.93 + 82,7,31, 0,8,113, 0,8,49, 0,9,194,
29.94 + 80,7,10, 0,8,97, 0,8,33, 0,9,162,
29.95 + 0,8,1, 0,8,129, 0,8,65, 0,9,226,
29.96 + 80,7,6, 0,8,89, 0,8,25, 0,9,146,
29.97 + 83,7,59, 0,8,121, 0,8,57, 0,9,210,
29.98 + 81,7,17, 0,8,105, 0,8,41, 0,9,178,
29.99 + 0,8,9, 0,8,137, 0,8,73, 0,9,242,
29.100 + 80,7,4, 0,8,85, 0,8,21, 80,8,258,
29.101 + 83,7,43, 0,8,117, 0,8,53, 0,9,202,
29.102 + 81,7,13, 0,8,101, 0,8,37, 0,9,170,
29.103 + 0,8,5, 0,8,133, 0,8,69, 0,9,234,
29.104 + 80,7,8, 0,8,93, 0,8,29, 0,9,154,
29.105 + 84,7,83, 0,8,125, 0,8,61, 0,9,218,
29.106 + 82,7,23, 0,8,109, 0,8,45, 0,9,186,
29.107 + 0,8,13, 0,8,141, 0,8,77, 0,9,250,
29.108 + 80,7,3, 0,8,83, 0,8,19, 85,8,195,
29.109 + 83,7,35, 0,8,115, 0,8,51, 0,9,198,
29.110 + 81,7,11, 0,8,99, 0,8,35, 0,9,166,
29.111 + 0,8,3, 0,8,131, 0,8,67, 0,9,230,
29.112 + 80,7,7, 0,8,91, 0,8,27, 0,9,150,
29.113 + 84,7,67, 0,8,123, 0,8,59, 0,9,214,
29.114 + 82,7,19, 0,8,107, 0,8,43, 0,9,182,
29.115 + 0,8,11, 0,8,139, 0,8,75, 0,9,246,
29.116 + 80,7,5, 0,8,87, 0,8,23, 192,8,0,
29.117 + 83,7,51, 0,8,119, 0,8,55, 0,9,206,
29.118 + 81,7,15, 0,8,103, 0,8,39, 0,9,174,
29.119 + 0,8,7, 0,8,135, 0,8,71, 0,9,238,
29.120 + 80,7,9, 0,8,95, 0,8,31, 0,9,158,
29.121 + 84,7,99, 0,8,127, 0,8,63, 0,9,222,
29.122 + 82,7,27, 0,8,111, 0,8,47, 0,9,190,
29.123 + 0,8,15, 0,8,143, 0,8,79, 0,9,254,
29.124 + 96,7,256, 0,8,80, 0,8,16, 84,8,115,
29.125 + 82,7,31, 0,8,112, 0,8,48, 0,9,193,
29.126 +
29.127 + 80,7,10, 0,8,96, 0,8,32, 0,9,161,
29.128 + 0,8,0, 0,8,128, 0,8,64, 0,9,225,
29.129 + 80,7,6, 0,8,88, 0,8,24, 0,9,145,
29.130 + 83,7,59, 0,8,120, 0,8,56, 0,9,209,
29.131 + 81,7,17, 0,8,104, 0,8,40, 0,9,177,
29.132 + 0,8,8, 0,8,136, 0,8,72, 0,9,241,
29.133 + 80,7,4, 0,8,84, 0,8,20, 85,8,227,
29.134 + 83,7,43, 0,8,116, 0,8,52, 0,9,201,
29.135 + 81,7,13, 0,8,100, 0,8,36, 0,9,169,
29.136 + 0,8,4, 0,8,132, 0,8,68, 0,9,233,
29.137 + 80,7,8, 0,8,92, 0,8,28, 0,9,153,
29.138 + 84,7,83, 0,8,124, 0,8,60, 0,9,217,
29.139 + 82,7,23, 0,8,108, 0,8,44, 0,9,185,
29.140 + 0,8,12, 0,8,140, 0,8,76, 0,9,249,
29.141 + 80,7,3, 0,8,82, 0,8,18, 85,8,163,
29.142 + 83,7,35, 0,8,114, 0,8,50, 0,9,197,
29.143 + 81,7,11, 0,8,98, 0,8,34, 0,9,165,
29.144 + 0,8,2, 0,8,130, 0,8,66, 0,9,229,
29.145 + 80,7,7, 0,8,90, 0,8,26, 0,9,149,
29.146 + 84,7,67, 0,8,122, 0,8,58, 0,9,213,
29.147 + 82,7,19, 0,8,106, 0,8,42, 0,9,181,
29.148 + 0,8,10, 0,8,138, 0,8,74, 0,9,245,
29.149 + 80,7,5, 0,8,86, 0,8,22, 192,8,0,
29.150 + 83,7,51, 0,8,118, 0,8,54, 0,9,205,
29.151 + 81,7,15, 0,8,102, 0,8,38, 0,9,173,
29.152 + 0,8,6, 0,8,134, 0,8,70, 0,9,237,
29.153 + 80,7,9, 0,8,94, 0,8,30, 0,9,157,
29.154 + 84,7,99, 0,8,126, 0,8,62, 0,9,221,
29.155 + 82,7,27, 0,8,110, 0,8,46, 0,9,189,
29.156 + 0,8,14, 0,8,142, 0,8,78, 0,9,253,
29.157 + 96,7,256, 0,8,81, 0,8,17, 85,8,131,
29.158 + 82,7,31, 0,8,113, 0,8,49, 0,9,195,
29.159 + 80,7,10, 0,8,97, 0,8,33, 0,9,163,
29.160 + 0,8,1, 0,8,129, 0,8,65, 0,9,227,
29.161 + 80,7,6, 0,8,89, 0,8,25, 0,9,147,
29.162 + 83,7,59, 0,8,121, 0,8,57, 0,9,211,
29.163 + 81,7,17, 0,8,105, 0,8,41, 0,9,179,
29.164 + 0,8,9, 0,8,137, 0,8,73, 0,9,243,
29.165 + 80,7,4, 0,8,85, 0,8,21, 80,8,258,
29.166 + 83,7,43, 0,8,117, 0,8,53, 0,9,203,
29.167 + 81,7,13, 0,8,101, 0,8,37, 0,9,171,
29.168 + 0,8,5, 0,8,133, 0,8,69, 0,9,235,
29.169 + 80,7,8, 0,8,93, 0,8,29, 0,9,155,
29.170 + 84,7,83, 0,8,125, 0,8,61, 0,9,219,
29.171 + 82,7,23, 0,8,109, 0,8,45, 0,9,187,
29.172 + 0,8,13, 0,8,141, 0,8,77, 0,9,251,
29.173 + 80,7,3, 0,8,83, 0,8,19, 85,8,195,
29.174 + 83,7,35, 0,8,115, 0,8,51, 0,9,199,
29.175 + 81,7,11, 0,8,99, 0,8,35, 0,9,167,
29.176 + 0,8,3, 0,8,131, 0,8,67, 0,9,231,
29.177 + 80,7,7, 0,8,91, 0,8,27, 0,9,151,
29.178 + 84,7,67, 0,8,123, 0,8,59, 0,9,215,
29.179 + 82,7,19, 0,8,107, 0,8,43, 0,9,183,
29.180 + 0,8,11, 0,8,139, 0,8,75, 0,9,247,
29.181 + 80,7,5, 0,8,87, 0,8,23, 192,8,0,
29.182 + 83,7,51, 0,8,119, 0,8,55, 0,9,207,
29.183 + 81,7,15, 0,8,103, 0,8,39, 0,9,175,
29.184 + 0,8,7, 0,8,135, 0,8,71, 0,9,239,
29.185 + 80,7,9, 0,8,95, 0,8,31, 0,9,159,
29.186 + 84,7,99, 0,8,127, 0,8,63, 0,9,223,
29.187 + 82,7,27, 0,8,111, 0,8,47, 0,9,191,
29.188 + 0,8,15, 0,8,143, 0,8,79, 0,9,255
29.189 + };
29.190 + static final int[] fixed_td = {
29.191 + 80,5,1, 87,5,257, 83,5,17, 91,5,4097,
29.192 + 81,5,5, 89,5,1025, 85,5,65, 93,5,16385,
29.193 + 80,5,3, 88,5,513, 84,5,33, 92,5,8193,
29.194 + 82,5,9, 90,5,2049, 86,5,129, 192,5,24577,
29.195 + 80,5,2, 87,5,385, 83,5,25, 91,5,6145,
29.196 + 81,5,7, 89,5,1537, 85,5,97, 93,5,24577,
29.197 + 80,5,4, 88,5,769, 84,5,49, 92,5,12289,
29.198 + 82,5,13, 90,5,3073, 86,5,193, 192,5,24577
29.199 + };
29.200 +
29.201 + // Tables for deflate from PKZIP's appnote.txt.
29.202 + static final int[] cplens = { // Copy lengths for literal codes 257..285
29.203 + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
29.204 + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
29.205 + };
29.206 +
29.207 + // see note #13 above about 258
29.208 + static final int[] cplext = { // Extra bits for literal codes 257..285
29.209 + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
29.210 + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 // 112==invalid
29.211 + };
29.212 +
29.213 + static final int[] cpdist = { // Copy offsets for distance codes 0..29
29.214 + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
29.215 + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
29.216 + 8193, 12289, 16385, 24577
29.217 + };
29.218 +
29.219 + static final int[] cpdext = { // Extra bits for distance codes
29.220 + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
29.221 + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
29.222 + 12, 12, 13, 13};
29.223 +
29.224 + // If BMAX needs to be larger than 16, then h and x[] should be uLong.
29.225 + static final int BMAX=15; // maximum bit length of any code
29.226 +
29.227 + int[] hn = null; // hufts used in space
29.228 + int[] v = null; // work area for huft_build
29.229 + int[] c = null; // bit length count table
29.230 + int[] r = null; // table entry for structure assignment
29.231 + int[] u = null; // table stack
29.232 + int[] x = null; // bit offsets, then code stack
29.233 +
29.234 + private int huft_build(int[] b, // code lengths in bits (all assumed <= BMAX)
29.235 + int bindex,
29.236 + int n, // number of codes (assumed <= 288)
29.237 + int s, // number of simple-valued codes (0..s-1)
29.238 + int[] d, // list of base values for non-simple codes
29.239 + int[] e, // list of extra bits for non-simple codes
29.240 + int[] t, // result: starting table
29.241 + int[] m, // maximum lookup bits, returns actual
29.242 + int[] hp,// space for trees
29.243 + int[] hn,// hufts used in space
29.244 + int[] v // working area: values in order of bit length
29.245 + ){
29.246 + // Given a list of code lengths and a maximum table size, make a set of
29.247 + // tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
29.248 + // if the given code set is incomplete (the tables are still built in this
29.249 + // case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
29.250 + // lengths), or Z_MEM_ERROR if not enough memory.
29.251 +
29.252 + int a; // counter for codes of length k
29.253 + int f; // i repeats in table every f entries
29.254 + int g; // maximum code length
29.255 + int h; // table level
29.256 + int i; // counter, current code
29.257 + int j; // counter
29.258 + int k; // number of bits in current code
29.259 + int l; // bits per table (returned in m)
29.260 + int mask; // (1 << w) - 1, to avoid cc -O bug on HP
29.261 + int p; // pointer into c[], b[], or v[]
29.262 + int q; // points to current table
29.263 + int w; // bits before this table == (l * h)
29.264 + int xp; // pointer into x
29.265 + int y; // number of dummy codes added
29.266 + int z; // number of entries in current table
29.267 +
29.268 + // Generate counts for each bit length
29.269 +
29.270 + p = 0; i = n;
29.271 + do {
29.272 + c[b[bindex+p]]++; p++; i--; // assume all entries <= BMAX
29.273 + }while(i!=0);
29.274 +
29.275 + if(c[0] == n){ // null input--all zero length codes
29.276 + t[0] = -1;
29.277 + m[0] = 0;
29.278 + return Z_OK;
29.279 + }
29.280 +
29.281 + // Find minimum and maximum length, bound *m by those
29.282 + l = m[0];
29.283 + for (j = 1; j <= BMAX; j++)
29.284 + if(c[j]!=0) break;
29.285 + k = j; // minimum code length
29.286 + if(l < j){
29.287 + l = j;
29.288 + }
29.289 + for (i = BMAX; i!=0; i--){
29.290 + if(c[i]!=0) break;
29.291 + }
29.292 + g = i; // maximum code length
29.293 + if(l > i){
29.294 + l = i;
29.295 + }
29.296 + m[0] = l;
29.297 +
29.298 + // Adjust last length count to fill out codes, if needed
29.299 + for (y = 1 << j; j < i; j++, y <<= 1){
29.300 + if ((y -= c[j]) < 0){
29.301 + return Z_DATA_ERROR;
29.302 + }
29.303 + }
29.304 + if ((y -= c[i]) < 0){
29.305 + return Z_DATA_ERROR;
29.306 + }
29.307 + c[i] += y;
29.308 +
29.309 + // Generate starting offsets into the value table for each length
29.310 + x[1] = j = 0;
29.311 + p = 1; xp = 2;
29.312 + while (--i!=0) { // note that i == g from above
29.313 + x[xp] = (j += c[p]);
29.314 + xp++;
29.315 + p++;
29.316 + }
29.317 +
29.318 + // Make a table of values in order of bit lengths
29.319 + i = 0; p = 0;
29.320 + do {
29.321 + if ((j = b[bindex+p]) != 0){
29.322 + v[x[j]++] = i;
29.323 + }
29.324 + p++;
29.325 + }
29.326 + while (++i < n);
29.327 + n = x[g]; // set n to length of v
29.328 +
29.329 + // Generate the Huffman codes and for each, make the table entries
29.330 + x[0] = i = 0; // first Huffman code is zero
29.331 + p = 0; // grab values in bit order
29.332 + h = -1; // no tables yet--level -1
29.333 + w = -l; // bits decoded == (l * h)
29.334 + u[0] = 0; // just to keep compilers happy
29.335 + q = 0; // ditto
29.336 + z = 0; // ditto
29.337 +
29.338 + // go through the bit lengths (k already is bits in shortest code)
29.339 + for (; k <= g; k++){
29.340 + a = c[k];
29.341 + while (a--!=0){
29.342 + // here i is the Huffman code of length k bits for value *p
29.343 + // make tables up to required level
29.344 + while (k > w + l){
29.345 + h++;
29.346 + w += l; // previous table always l bits
29.347 + // compute minimum size table less than or equal to l bits
29.348 + z = g - w;
29.349 + z = (z > l) ? l : z; // table size upper limit
29.350 + if((f=1<<(j=k-w))>a+1){ // try a k-w bit table
29.351 + // too few codes for k-w bit table
29.352 + f -= a + 1; // deduct codes from patterns left
29.353 + xp = k;
29.354 + if(j < z){
29.355 + while (++j < z){ // try smaller tables up to z bits
29.356 + if((f <<= 1) <= c[++xp])
29.357 + break; // enough codes to use up j bits
29.358 + f -= c[xp]; // else deduct codes from patterns
29.359 + }
29.360 + }
29.361 + }
29.362 + z = 1 << j; // table entries for j-bit table
29.363 +
29.364 + // allocate new table
29.365 + if (hn[0] + z > MANY){ // (note: doesn't matter for fixed)
29.366 + return Z_DATA_ERROR; // overflow of MANY
29.367 + }
29.368 + u[h] = q = /*hp+*/ hn[0]; // DEBUG
29.369 + hn[0] += z;
29.370 +
29.371 + // connect to last table, if there is one
29.372 + if(h!=0){
29.373 + x[h]=i; // save pattern for backing up
29.374 + r[0]=(byte)j; // bits in this table
29.375 + r[1]=(byte)l; // bits to dump before this table
29.376 + j=i>>>(w - l);
29.377 + r[2] = (int)(q - u[h-1] - j); // offset to this table
29.378 + System.arraycopy(r, 0, hp, (u[h-1]+j)*3, 3); // connect to last table
29.379 + }
29.380 + else{
29.381 + t[0] = q; // first table is returned result
29.382 + }
29.383 + }
29.384 +
29.385 + // set up table entry in r
29.386 + r[1] = (byte)(k - w);
29.387 + if (p >= n){
29.388 + r[0] = 128 + 64; // out of values--invalid code
29.389 + }
29.390 + else if (v[p] < s){
29.391 + r[0] = (byte)(v[p] < 256 ? 0 : 32 + 64); // 256 is end-of-block
29.392 + r[2] = v[p++]; // simple code is just the value
29.393 + }
29.394 + else{
29.395 + r[0]=(byte)(e[v[p]-s]+16+64); // non-simple--look up in lists
29.396 + r[2]=d[v[p++] - s];
29.397 + }
29.398 +
29.399 + // fill code-like entries with r
29.400 + f=1<<(k-w);
29.401 + for (j=i>>>w;j<z;j+=f){
29.402 + System.arraycopy(r, 0, hp, (q+j)*3, 3);
29.403 + }
29.404 +
29.405 + // backwards increment the k-bit code i
29.406 + for (j = 1 << (k - 1); (i & j)!=0; j >>>= 1){
29.407 + i ^= j;
29.408 + }
29.409 + i ^= j;
29.410 +
29.411 + // backup over finished tables
29.412 + mask = (1 << w) - 1; // needed on HP, cc -O bug
29.413 + while ((i & mask) != x[h]){
29.414 + h--; // don't need to update q
29.415 + w -= l;
29.416 + mask = (1 << w) - 1;
29.417 + }
29.418 + }
29.419 + }
29.420 + // Return Z_BUF_ERROR if we were given an incomplete table
29.421 + return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
29.422 + }
29.423 +
29.424 + int inflate_trees_bits(int[] c, // 19 code lengths
29.425 + int[] bb, // bits tree desired/actual depth
29.426 + int[] tb, // bits tree result
29.427 + int[] hp, // space for trees
29.428 + ZStream z // for messages
29.429 + ){
29.430 + int result;
29.431 + initWorkArea(19);
29.432 + hn[0]=0;
29.433 + result = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);
29.434 +
29.435 + if(result == Z_DATA_ERROR){
29.436 + z.msg = "oversubscribed dynamic bit lengths tree";
29.437 + }
29.438 + else if(result == Z_BUF_ERROR || bb[0] == 0){
29.439 + z.msg = "incomplete dynamic bit lengths tree";
29.440 + result = Z_DATA_ERROR;
29.441 + }
29.442 + return result;
29.443 + }
29.444 +
29.445 + int inflate_trees_dynamic(int nl, // number of literal/length codes
29.446 + int nd, // number of distance codes
29.447 + int[] c, // that many (total) code lengths
29.448 + int[] bl, // literal desired/actual bit depth
29.449 + int[] bd, // distance desired/actual bit depth
29.450 + int[] tl, // literal/length tree result
29.451 + int[] td, // distance tree result
29.452 + int[] hp, // space for trees
29.453 + ZStream z // for messages
29.454 + ){
29.455 + int result;
29.456 +
29.457 + // build literal/length tree
29.458 + initWorkArea(288);
29.459 + hn[0]=0;
29.460 + result = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);
29.461 + if (result != Z_OK || bl[0] == 0){
29.462 + if(result == Z_DATA_ERROR){
29.463 + z.msg = "oversubscribed literal/length tree";
29.464 + }
29.465 + else if (result != Z_MEM_ERROR){
29.466 + z.msg = "incomplete literal/length tree";
29.467 + result = Z_DATA_ERROR;
29.468 + }
29.469 + return result;
29.470 + }
29.471 +
29.472 + // build distance tree
29.473 + initWorkArea(288);
29.474 + result = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);
29.475 +
29.476 + if (result != Z_OK || (bd[0] == 0 && nl > 257)){
29.477 + if (result == Z_DATA_ERROR){
29.478 + z.msg = "oversubscribed distance tree";
29.479 + }
29.480 + else if (result == Z_BUF_ERROR) {
29.481 + z.msg = "incomplete distance tree";
29.482 + result = Z_DATA_ERROR;
29.483 + }
29.484 + else if (result != Z_MEM_ERROR){
29.485 + z.msg = "empty distance tree with lengths";
29.486 + result = Z_DATA_ERROR;
29.487 + }
29.488 + return result;
29.489 + }
29.490 +
29.491 + return Z_OK;
29.492 + }
29.493 +
29.494 + static int inflate_trees_fixed(int[] bl, //literal desired/actual bit depth
29.495 + int[] bd, //distance desired/actual bit depth
29.496 + int[][] tl,//literal/length tree result
29.497 + int[][] td,//distance tree result
29.498 + ZStream z //for memory allocation
29.499 + ){
29.500 + bl[0]=fixed_bl;
29.501 + bd[0]=fixed_bd;
29.502 + tl[0]=fixed_tl;
29.503 + td[0]=fixed_td;
29.504 + return Z_OK;
29.505 + }
29.506 +
29.507 + private void initWorkArea(int vsize){
29.508 + if(hn==null){
29.509 + hn=new int[1];
29.510 + v=new int[vsize];
29.511 + c=new int[BMAX+1];
29.512 + r=new int[3];
29.513 + u=new int[BMAX];
29.514 + x=new int[BMAX+1];
29.515 + }
29.516 + if(v.length<vsize){ v=new int[vsize]; }
29.517 + for(int i=0; i<vsize; i++){v[i]=0;}
29.518 + for(int i=0; i<BMAX+1; i++){c[i]=0;}
29.519 + for(int i=0; i<3; i++){r[i]=0;}
29.520 + System.arraycopy(c, 0, u, 0, BMAX);
29.521 + System.arraycopy(c, 0, x, 0, BMAX+1);
29.522 + }
29.523 +}
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/Inflate.java Fri Feb 15 21:16:05 2013 +0100
30.3 @@ -0,0 +1,727 @@
30.4 +/* -*-mode:java; c-basic-offset:2; -*- */
30.5 +/*
30.6 +Copyright (c) 2000-2011 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 Inflate{
30.43 +
30.44 + static final private int MAX_WBITS=15; // 32K LZ77 window
30.45 +
30.46 + // preset dictionary flag in zlib header
30.47 + static final private int PRESET_DICT=0x20;
30.48 +
30.49 + static final int Z_NO_FLUSH=0;
30.50 + static final int Z_PARTIAL_FLUSH=1;
30.51 + static final int Z_SYNC_FLUSH=2;
30.52 + static final int Z_FULL_FLUSH=3;
30.53 + static final int Z_FINISH=4;
30.54 +
30.55 + static final private int Z_DEFLATED=8;
30.56 +
30.57 + static final private int Z_OK=0;
30.58 + static final private int Z_STREAM_END=1;
30.59 + static final private int Z_NEED_DICT=2;
30.60 + static final private int Z_ERRNO=-1;
30.61 + static final private int Z_STREAM_ERROR=-2;
30.62 + static final private int Z_DATA_ERROR=-3;
30.63 + static final private int Z_MEM_ERROR=-4;
30.64 + static final private int Z_BUF_ERROR=-5;
30.65 + static final private int Z_VERSION_ERROR=-6;
30.66 +
30.67 + static final private int METHOD=0; // waiting for method byte
30.68 + static final private int FLAG=1; // waiting for flag byte
30.69 + static final private int DICT4=2; // four dictionary check bytes to go
30.70 + static final private int DICT3=3; // three dictionary check bytes to go
30.71 + static final private int DICT2=4; // two dictionary check bytes to go
30.72 + static final private int DICT1=5; // one dictionary check byte to go
30.73 + static final int DICT0=6; // waiting for inflateSetDictionary
30.74 + static final private int BLOCKS=7; // decompressing blocks
30.75 + static final private int CHECK4=8; // four check bytes to go
30.76 + static final private int CHECK3=9; // three check bytes to go
30.77 + static final private int CHECK2=10; // two check bytes to go
30.78 + static final private int CHECK1=11; // one check byte to go
30.79 + static final private int DONE=12; // finished check, done
30.80 + static final private int BAD=13; // got an error--stay here
30.81 +
30.82 + static final private int HEAD=14;
30.83 + static final private int LENGTH=15;
30.84 + static final private int TIME=16;
30.85 + static final private int OS=17;
30.86 + static final private int EXLEN=18;
30.87 + static final private int EXTRA=19;
30.88 + static final private int NAME=20;
30.89 + static final private int COMMENT=21;
30.90 + static final private int HCRC=22;
30.91 + static final private int FLAGS=23;
30.92 +
30.93 + int mode; // current inflate mode
30.94 +
30.95 + // mode dependent information
30.96 + int method; // if FLAGS, method byte
30.97 +
30.98 + // if CHECK, check values to compare
30.99 + long was = -1; // computed check value
30.100 + long need; // stream check value
30.101 +
30.102 + // if BAD, inflateSync's marker bytes count
30.103 + int marker;
30.104 +
30.105 + // mode independent information
30.106 + int wrap; // flag for no wrapper
30.107 + int wbits; // log2(window size) (8..15, defaults to 15)
30.108 +
30.109 + InfBlocks blocks; // current inflate_blocks state
30.110 +
30.111 + private final ZStream z;
30.112 +
30.113 + private int flags;
30.114 +
30.115 + private int need_bytes = -1;
30.116 + private byte[] crcbuf=new byte[4];
30.117 +
30.118 + GZIPHeader gheader = null;
30.119 +
30.120 + int inflateReset(){
30.121 + if(z == null) return Z_STREAM_ERROR;
30.122 +
30.123 + z.total_in = z.total_out = 0;
30.124 + z.msg = null;
30.125 + this.mode = HEAD;
30.126 + this.need_bytes = -1;
30.127 + this.blocks.reset();
30.128 + return Z_OK;
30.129 + }
30.130 +
30.131 + int inflateEnd(){
30.132 + if(blocks != null){
30.133 + blocks.free();
30.134 + }
30.135 + return Z_OK;
30.136 + }
30.137 +
30.138 + Inflate(ZStream z){
30.139 + this.z=z;
30.140 + }
30.141 +
30.142 + int inflateInit(int w){
30.143 + z.msg = null;
30.144 + blocks = null;
30.145 +
30.146 + // handle undocumented wrap option (no zlib header or check)
30.147 + wrap = 0;
30.148 + if(w < 0){
30.149 + w = - w;
30.150 + }
30.151 + else {
30.152 + wrap = (w >> 4) + 1;
30.153 + if(w < 48)
30.154 + w &= 15;
30.155 + }
30.156 +
30.157 + if(w<8 ||w>15){
30.158 + inflateEnd();
30.159 + return Z_STREAM_ERROR;
30.160 + }
30.161 + if(blocks != null && wbits != w){
30.162 + blocks.free();
30.163 + blocks=null;
30.164 + }
30.165 +
30.166 + // set window size
30.167 + wbits=w;
30.168 +
30.169 + this.blocks=new InfBlocks(z, 1<<w);
30.170 +
30.171 + // reset state
30.172 + inflateReset();
30.173 +
30.174 + return Z_OK;
30.175 + }
30.176 +
30.177 + int inflate(int f){
30.178 + int hold = 0;
30.179 +
30.180 + int r;
30.181 + int b;
30.182 +
30.183 + if(z == null || z.next_in == null){
30.184 + if(f == Z_FINISH && this.mode==HEAD)
30.185 + return Z_OK;
30.186 + return Z_STREAM_ERROR;
30.187 + }
30.188 +
30.189 + f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
30.190 + r = Z_BUF_ERROR;
30.191 + while (true){
30.192 +
30.193 + switch (this.mode){
30.194 + case HEAD:
30.195 + if(wrap==0){
30.196 + this.mode = BLOCKS;
30.197 + break;
30.198 + }
30.199 +
30.200 + try { r=readBytes(2, r, f); }
30.201 + catch(Return e){ return e.r; }
30.202 +
30.203 + if((wrap&2)!=0 && this.need == 0x8b1fL) { // gzip header
30.204 + z.adler=new CRC32();
30.205 + checksum(2, this.need);
30.206 +
30.207 + if(gheader==null)
30.208 + gheader=new GZIPHeader();
30.209 +
30.210 + this.mode = FLAGS;
30.211 + break;
30.212 + }
30.213 +
30.214 + flags = 0;
30.215 +
30.216 + this.method = ((int)this.need)&0xff;
30.217 + b=((int)(this.need>>8))&0xff;
30.218 +
30.219 + if((wrap&1)==0 || // check if zlib header allowed
30.220 + (((this.method << 8)+b) % 31)!=0){
30.221 + this.mode = BAD;
30.222 + z.msg = "incorrect header check";
30.223 + // since zlib 1.2, it is allowted to inflateSync for this case.
30.224 + /*
30.225 + this.marker = 5; // can't try inflateSync
30.226 + */
30.227 + break;
30.228 + }
30.229 +
30.230 + if((this.method&0xf)!=Z_DEFLATED){
30.231 + this.mode = BAD;
30.232 + z.msg="unknown compression method";
30.233 + // since zlib 1.2, it is allowted to inflateSync for this case.
30.234 + /*
30.235 + this.marker = 5; // can't try inflateSync
30.236 + */
30.237 + break;
30.238 + }
30.239 +
30.240 + if((this.method>>4)+8>this.wbits){
30.241 + this.mode = BAD;
30.242 + z.msg="invalid window size";
30.243 + // since zlib 1.2, it is allowted to inflateSync for this case.
30.244 + /*
30.245 + this.marker = 5; // can't try inflateSync
30.246 + */
30.247 + break;
30.248 + }
30.249 +
30.250 + z.adler=new Adler32();
30.251 +
30.252 + if((b&PRESET_DICT)==0){
30.253 + this.mode = BLOCKS;
30.254 + break;
30.255 + }
30.256 + this.mode = DICT4;
30.257 + case DICT4:
30.258 +
30.259 + if(z.avail_in==0)return r;r=f;
30.260 +
30.261 + z.avail_in--; z.total_in++;
30.262 + this.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L;
30.263 + this.mode=DICT3;
30.264 + case DICT3:
30.265 +
30.266 + if(z.avail_in==0)return r;r=f;
30.267 +
30.268 + z.avail_in--; z.total_in++;
30.269 + this.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L;
30.270 + this.mode=DICT2;
30.271 + case DICT2:
30.272 +
30.273 + if(z.avail_in==0)return r;r=f;
30.274 +
30.275 + z.avail_in--; z.total_in++;
30.276 + this.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L;
30.277 + this.mode=DICT1;
30.278 + case DICT1:
30.279 +
30.280 + if(z.avail_in==0)return r;r=f;
30.281 +
30.282 + z.avail_in--; z.total_in++;
30.283 + this.need += (z.next_in[z.next_in_index++]&0xffL);
30.284 + z.adler.reset(this.need);
30.285 + this.mode = DICT0;
30.286 + return Z_NEED_DICT;
30.287 + case DICT0:
30.288 + this.mode = BAD;
30.289 + z.msg = "need dictionary";
30.290 + this.marker = 0; // can try inflateSync
30.291 + return Z_STREAM_ERROR;
30.292 + case BLOCKS:
30.293 + r = this.blocks.proc(r);
30.294 + if(r == Z_DATA_ERROR){
30.295 + this.mode = BAD;
30.296 + this.marker = 0; // can try inflateSync
30.297 + break;
30.298 + }
30.299 + if(r == Z_OK){
30.300 + r = f;
30.301 + }
30.302 + if(r != Z_STREAM_END){
30.303 + return r;
30.304 + }
30.305 + r = f;
30.306 + this.was=z.adler.getValue();
30.307 + this.blocks.reset();
30.308 + if(this.wrap==0){
30.309 + this.mode=DONE;
30.310 + break;
30.311 + }
30.312 + this.mode=CHECK4;
30.313 + case CHECK4:
30.314 +
30.315 + if(z.avail_in==0)return r;r=f;
30.316 +
30.317 + z.avail_in--; z.total_in++;
30.318 + this.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L;
30.319 + this.mode=CHECK3;
30.320 + case CHECK3:
30.321 +
30.322 + if(z.avail_in==0)return r;r=f;
30.323 +
30.324 + z.avail_in--; z.total_in++;
30.325 + this.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L;
30.326 + this.mode = CHECK2;
30.327 + case CHECK2:
30.328 +
30.329 + if(z.avail_in==0)return r;r=f;
30.330 +
30.331 + z.avail_in--; z.total_in++;
30.332 + this.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L;
30.333 + this.mode = CHECK1;
30.334 + case CHECK1:
30.335 +
30.336 + if(z.avail_in==0)return r;r=f;
30.337 +
30.338 + z.avail_in--; z.total_in++;
30.339 + this.need+=(z.next_in[z.next_in_index++]&0xffL);
30.340 +
30.341 + if(flags!=0){ // gzip
30.342 + this.need = ((this.need&0xff000000)>>24 |
30.343 + (this.need&0x00ff0000)>>8 |
30.344 + (this.need&0x0000ff00)<<8 |
30.345 + (this.need&0x0000ffff)<<24)&0xffffffffL;
30.346 + }
30.347 +
30.348 + if(((int)(this.was)) != ((int)(this.need))){
30.349 + z.msg = "incorrect data check";
30.350 + // chack is delayed
30.351 + /*
30.352 + this.mode = BAD;
30.353 + this.marker = 5; // can't try inflateSync
30.354 + break;
30.355 + */
30.356 + }
30.357 + else if(flags!=0 && gheader!=null){
30.358 + gheader.crc = this.need;
30.359 + }
30.360 +
30.361 + this.mode = LENGTH;
30.362 + case LENGTH:
30.363 + if (wrap!=0 && flags!=0) {
30.364 +
30.365 + try { r=readBytes(4, r, f); }
30.366 + catch(Return e){ return e.r; }
30.367 +
30.368 + if(z.msg!=null && z.msg.equals("incorrect data check")){
30.369 + this.mode = BAD;
30.370 + this.marker = 5; // can't try inflateSync
30.371 + break;
30.372 + }
30.373 +
30.374 + if (this.need != (z.total_out & 0xffffffffL)) {
30.375 + z.msg = "incorrect length check";
30.376 + this.mode = BAD;
30.377 + break;
30.378 + }
30.379 + z.msg = null;
30.380 + }
30.381 + else {
30.382 + if(z.msg!=null && z.msg.equals("incorrect data check")){
30.383 + this.mode = BAD;
30.384 + this.marker = 5; // can't try inflateSync
30.385 + break;
30.386 + }
30.387 + }
30.388 +
30.389 + this.mode = DONE;
30.390 + case DONE:
30.391 + return Z_STREAM_END;
30.392 + case BAD:
30.393 + return Z_DATA_ERROR;
30.394 +
30.395 + case FLAGS:
30.396 +
30.397 + try { r=readBytes(2, r, f); }
30.398 + catch(Return e){ return e.r; }
30.399 +
30.400 + flags = ((int)this.need)&0xffff;
30.401 +
30.402 + if ((flags & 0xff) != Z_DEFLATED) {
30.403 + z.msg = "unknown compression method";
30.404 + this.mode = BAD;
30.405 + break;
30.406 + }
30.407 + if ((flags & 0xe000)!=0) {
30.408 + z.msg = "unknown header flags set";
30.409 + this.mode = BAD;
30.410 + break;
30.411 + }
30.412 +
30.413 + if ((flags & 0x0200)!=0){
30.414 + checksum(2, this.need);
30.415 + }
30.416 +
30.417 + this.mode = TIME;
30.418 +
30.419 + case TIME:
30.420 + try { r=readBytes(4, r, f); }
30.421 + catch(Return e){ return e.r; }
30.422 + if(gheader!=null)
30.423 + gheader.time = this.need;
30.424 + if ((flags & 0x0200)!=0){
30.425 + checksum(4, this.need);
30.426 + }
30.427 + this.mode = OS;
30.428 + case OS:
30.429 + try { r=readBytes(2, r, f); }
30.430 + catch(Return e){ return e.r; }
30.431 + if(gheader!=null){
30.432 + gheader.xflags = ((int)this.need)&0xff;
30.433 + gheader.os = (((int)this.need)>>8)&0xff;
30.434 + }
30.435 + if ((flags & 0x0200)!=0){
30.436 + checksum(2, this.need);
30.437 + }
30.438 + this.mode = EXLEN;
30.439 + case EXLEN:
30.440 + if ((flags & 0x0400)!=0) {
30.441 + try { r=readBytes(2, r, f); }
30.442 + catch(Return e){ return e.r; }
30.443 + if(gheader!=null){
30.444 + gheader.extra = new byte[((int)this.need)&0xffff];
30.445 + }
30.446 + if ((flags & 0x0200)!=0){
30.447 + checksum(2, this.need);
30.448 + }
30.449 + }
30.450 + else if(gheader!=null){
30.451 + gheader.extra=null;
30.452 + }
30.453 + this.mode = EXTRA;
30.454 +
30.455 + case EXTRA:
30.456 + if ((flags & 0x0400)!=0) {
30.457 + try {
30.458 + r=readBytes(r, f);
30.459 + if(gheader!=null){
30.460 + byte[] foo = tmp_array;
30.461 + tmp_array=null;
30.462 + if(foo.length == gheader.extra.length){
30.463 + System.arraycopy(foo, 0, gheader.extra, 0, foo.length);
30.464 + }
30.465 + else{
30.466 + z.msg = "bad extra field length";
30.467 + this.mode = BAD;
30.468 + break;
30.469 + }
30.470 + }
30.471 + }
30.472 + catch(Return e){ return e.r; }
30.473 + }
30.474 + else if(gheader!=null){
30.475 + gheader.extra=null;
30.476 + }
30.477 + this.mode = NAME;
30.478 + case NAME:
30.479 + if ((flags & 0x0800)!=0) {
30.480 + try {
30.481 + r=readString(r, f);
30.482 + if(gheader!=null){
30.483 + gheader.name=tmp_array;
30.484 + }
30.485 + tmp_array=null;
30.486 + }
30.487 + catch(Return e){ return e.r; }
30.488 + }
30.489 + else if(gheader!=null){
30.490 + gheader.name=null;
30.491 + }
30.492 + this.mode = COMMENT;
30.493 + case COMMENT:
30.494 + if ((flags & 0x1000)!=0) {
30.495 + try {
30.496 + r=readString(r, f);
30.497 + if(gheader!=null){
30.498 + gheader.comment=tmp_array;
30.499 + }
30.500 + tmp_array=null;
30.501 + }
30.502 + catch(Return e){ return e.r; }
30.503 + }
30.504 + else if(gheader!=null){
30.505 + gheader.comment=null;
30.506 + }
30.507 + this.mode = HCRC;
30.508 + case HCRC:
30.509 + if ((flags & 0x0200)!=0) {
30.510 + try { r=readBytes(2, r, f); }
30.511 + catch(Return e){ return e.r; }
30.512 + if(gheader!=null){
30.513 + gheader.hcrc=(int)(this.need&0xffff);
30.514 + }
30.515 + if(this.need != (z.adler.getValue()&0xffffL)){
30.516 + this.mode = BAD;
30.517 + z.msg = "header crc mismatch";
30.518 + this.marker = 5; // can't try inflateSync
30.519 + break;
30.520 + }
30.521 + }
30.522 + z.adler = new CRC32();
30.523 +
30.524 + this.mode = BLOCKS;
30.525 + break;
30.526 + default:
30.527 + return Z_STREAM_ERROR;
30.528 + }
30.529 + }
30.530 + }
30.531 +
30.532 + int inflateSetDictionary(byte[] dictionary, int dictLength){
30.533 + if(z==null || (this.mode != DICT0 && this.wrap != 0)){
30.534 + return Z_STREAM_ERROR;
30.535 + }
30.536 +
30.537 + int index=0;
30.538 + int length = dictLength;
30.539 +
30.540 + if(this.mode==DICT0){
30.541 + long adler_need=z.adler.getValue();
30.542 + z.adler.reset();
30.543 + z.adler.update(dictionary, 0, dictLength);
30.544 + if(z.adler.getValue()!=adler_need){
30.545 + return Z_DATA_ERROR;
30.546 + }
30.547 + }
30.548 +
30.549 + z.adler.reset();
30.550 +
30.551 + if(length >= (1<<this.wbits)){
30.552 + length = (1<<this.wbits)-1;
30.553 + index=dictLength - length;
30.554 + }
30.555 + this.blocks.set_dictionary(dictionary, index, length);
30.556 + this.mode = BLOCKS;
30.557 + return Z_OK;
30.558 + }
30.559 +
30.560 + static private byte[] mark = {(byte)0, (byte)0, (byte)0xff, (byte)0xff};
30.561 +
30.562 + int inflateSync(){
30.563 + int n; // number of bytes to look at
30.564 + int p; // pointer to bytes
30.565 + int m; // number of marker bytes found in a row
30.566 + long r, w; // temporaries to save total_in and total_out
30.567 +
30.568 + // set up
30.569 + if(z == null)
30.570 + return Z_STREAM_ERROR;
30.571 + if(this.mode != BAD){
30.572 + this.mode = BAD;
30.573 + this.marker = 0;
30.574 + }
30.575 + if((n=z.avail_in)==0)
30.576 + return Z_BUF_ERROR;
30.577 +
30.578 + p=z.next_in_index;
30.579 + m=this.marker;
30.580 + // search
30.581 + while (n!=0 && m < 4){
30.582 + if(z.next_in[p] == mark[m]){
30.583 + m++;
30.584 + }
30.585 + else if(z.next_in[p]!=0){
30.586 + m = 0;
30.587 + }
30.588 + else{
30.589 + m = 4 - m;
30.590 + }
30.591 + p++; n--;
30.592 + }
30.593 +
30.594 + // restore
30.595 + z.total_in += p-z.next_in_index;
30.596 + z.next_in_index = p;
30.597 + z.avail_in = n;
30.598 + this.marker = m;
30.599 +
30.600 + // return no joy or set up to restart on a new block
30.601 + if(m != 4){
30.602 + return Z_DATA_ERROR;
30.603 + }
30.604 + r=z.total_in; w=z.total_out;
30.605 + inflateReset();
30.606 + z.total_in=r; z.total_out = w;
30.607 + this.mode = BLOCKS;
30.608 +
30.609 + return Z_OK;
30.610 + }
30.611 +
30.612 + // Returns true if inflate is currently at the end of a block generated
30.613 + // by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
30.614 + // implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
30.615 + // but removes the length bytes of the resulting empty stored block. When
30.616 + // decompressing, PPP checks that at the end of input packet, inflate is
30.617 + // waiting for these length bytes.
30.618 + int inflateSyncPoint(){
30.619 + if(z == null || this.blocks == null)
30.620 + return Z_STREAM_ERROR;
30.621 + return this.blocks.sync_point();
30.622 + }
30.623 +
30.624 + private int readBytes(int n, int r, int f) throws Return{
30.625 + if(need_bytes == -1){
30.626 + need_bytes=n;
30.627 + this.need=0;
30.628 + }
30.629 + while(need_bytes>0){
30.630 + if(z.avail_in==0){ throw new Return(r); }; r=f;
30.631 + z.avail_in--; z.total_in++;
30.632 + this.need = this.need |
30.633 + ((z.next_in[z.next_in_index++]&0xff)<<((n-need_bytes)*8));
30.634 + need_bytes--;
30.635 + }
30.636 + if(n==2){
30.637 + this.need&=0xffffL;
30.638 + }
30.639 + else if(n==4) {
30.640 + this.need&=0xffffffffL;
30.641 + }
30.642 + need_bytes=-1;
30.643 + return r;
30.644 + }
30.645 + class Return extends Exception{
30.646 + int r;
30.647 + Return(int r){this.r=r; }
30.648 + }
30.649 +
30.650 + private byte[] tmp_array;
30.651 + private int readString(int r, int f) throws Return{
30.652 + int b=0;
30.653 + byte[] arr = new byte[4092];
30.654 + int at = 0;
30.655 + do {
30.656 + if(z.avail_in==0){ throw new Return(r); }; r=f;
30.657 + z.avail_in--; z.total_in++;
30.658 + b = z.next_in[z.next_in_index];
30.659 + if(b!=0) arr = append(arr, z.next_in[z.next_in_index], at++);
30.660 + z.adler.update(z.next_in, z.next_in_index, 1);
30.661 + z.next_in_index++;
30.662 + }while(b!=0);
30.663 +
30.664 + tmp_array = copy(arr, at);
30.665 +
30.666 + return r;
30.667 + }
30.668 +
30.669 + private int readBytes(int r, int f) throws Return{
30.670 + int b=0;
30.671 + byte[] arr = new byte[4092];
30.672 + int at = 0;
30.673 + while(this.need>0){
30.674 + if(z.avail_in==0){ throw new Return(r); }; r=f;
30.675 + z.avail_in--; z.total_in++;
30.676 + b = z.next_in[z.next_in_index];
30.677 + arr = append(arr, z.next_in[z.next_in_index], at++);
30.678 + z.adler.update(z.next_in, z.next_in_index, 1);
30.679 + z.next_in_index++;
30.680 + this.need--;
30.681 + }
30.682 +
30.683 + tmp_array = copy(arr, at);
30.684 +
30.685 + return r;
30.686 + }
30.687 +
30.688 + private static byte[] copy(byte[] arr, int len) {
30.689 + byte[] ret = new byte[len];
30.690 + org.apidesign.bck2brwsr.emul.lang.System.arraycopy(arr, 0, ret, 0, len);
30.691 + return ret;
30.692 + }
30.693 + private static byte[] append(byte[] arr, byte b, int index) {
30.694 + arr[index] = b;
30.695 + return arr;
30.696 + }
30.697 +
30.698 + private void checksum(int n, long v){
30.699 + for(int i=0; i<n; i++){
30.700 + crcbuf[i]=(byte)(v&0xff);
30.701 + v>>=8;
30.702 + }
30.703 + z.adler.update(crcbuf, 0, n);
30.704 + }
30.705 +
30.706 + public GZIPHeader getGZIPHeader(){
30.707 + return gheader;
30.708 + }
30.709 +
30.710 + boolean inParsingHeader(){
30.711 + switch(mode){
30.712 + case HEAD:
30.713 + case DICT4:
30.714 + case DICT3:
30.715 + case DICT2:
30.716 + case DICT1:
30.717 + case FLAGS:
30.718 + case TIME:
30.719 + case OS:
30.720 + case EXLEN:
30.721 + case EXTRA:
30.722 + case NAME:
30.723 + case COMMENT:
30.724 + case HCRC:
30.725 + return true;
30.726 + default:
30.727 + return false;
30.728 + }
30.729 + }
30.730 +}
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/Inflater.java Fri Feb 15 21:16:05 2013 +0100
31.3 @@ -0,0 +1,338 @@
31.4 +/*
31.5 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
31.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
31.7 + *
31.8 + * This code is free software; you can redistribute it and/or modify it
31.9 + * under the terms of the GNU General Public License version 2 only, as
31.10 + * published by the Free Software Foundation. Oracle designates this
31.11 + * particular file as subject to the "Classpath" exception as provided
31.12 + * by Oracle in the LICENSE file that accompanied this code.
31.13 + *
31.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
31.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
31.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
31.17 + * version 2 for more details (a copy is included in the LICENSE file that
31.18 + * accompanied this code).
31.19 + *
31.20 + * You should have received a copy of the GNU General Public License version
31.21 + * 2 along with this work; if not, write to the Free Software Foundation,
31.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
31.23 + *
31.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
31.25 + * or visit www.oracle.com if you need additional information or have any
31.26 + * questions.
31.27 + */
31.28 +
31.29 +package org.apidesign.bck2brwsr.emul.zip;
31.30 +
31.31 +import java.util.zip.*;
31.32 +import java.io.IOException;
31.33 +
31.34 +/**
31.35 + * This class provides support for general purpose decompression using the
31.36 + * popular ZLIB compression library. The ZLIB compression library was
31.37 + * initially developed as part of the PNG graphics standard and is not
31.38 + * protected by patents. It is fully described in the specifications at
31.39 + * the <a href="package-summary.html#package_description">java.util.zip
31.40 + * package description</a>.
31.41 + *
31.42 + * <p>The following code fragment demonstrates a trivial compression
31.43 + * and decompression of a string using <tt>Deflater</tt> and
31.44 + * <tt>Inflater</tt>.
31.45 + *
31.46 + * <blockquote><pre>
31.47 + * try {
31.48 + * // Encode a String into bytes
31.49 + * String inputString = "blahblahblah\u20AC\u20AC";
31.50 + * byte[] input = inputString.getBytes("UTF-8");
31.51 + *
31.52 + * // Compress the bytes
31.53 + * byte[] output = new byte[100];
31.54 + * Deflater compresser = new Deflater();
31.55 + * compresser.setInput(input);
31.56 + * compresser.finish();
31.57 + * int compressedDataLength = compresser.deflate(output);
31.58 + *
31.59 + * // Decompress the bytes
31.60 + * Inflater decompresser = new Inflater();
31.61 + * decompresser.setInput(output, 0, compressedDataLength);
31.62 + * byte[] result = new byte[100];
31.63 + * int resultLength = decompresser.inflate(result);
31.64 + * decompresser.end();
31.65 + *
31.66 + * // Decode the bytes into a String
31.67 + * String outputString = new String(result, 0, resultLength, "UTF-8");
31.68 + * } catch(java.io.UnsupportedEncodingException ex) {
31.69 + * // handle
31.70 + * } catch (java.util.zip.DataFormatException ex) {
31.71 + * // handle
31.72 + * }
31.73 + * </pre></blockquote>
31.74 + *
31.75 + * @see Deflater
31.76 + * @author David Connelly
31.77 + *
31.78 + */
31.79 +public
31.80 +class Inflater extends java.util.zip.Inflater {
31.81 + private final boolean nowrap;
31.82 + private JzLibInflater impl;
31.83 +
31.84 + /**
31.85 + * Creates a new decompressor. If the parameter 'nowrap' is true then
31.86 + * the ZLIB header and checksum fields will not be used. This provides
31.87 + * compatibility with the compression format used by both GZIP and PKZIP.
31.88 + * <p>
31.89 + * Note: When using the 'nowrap' option it is also necessary to provide
31.90 + * an extra "dummy" byte as input. This is required by the ZLIB native
31.91 + * library in order to support certain optimizations.
31.92 + *
31.93 + * @param nowrap if true then support GZIP compatible compression
31.94 + */
31.95 + public Inflater(boolean nowrap) {
31.96 + this.nowrap = nowrap;
31.97 + reset();
31.98 + }
31.99 +
31.100 + /**
31.101 + * Creates a new decompressor.
31.102 + */
31.103 + public Inflater() {
31.104 + this(false);
31.105 + }
31.106 +
31.107 + /**
31.108 + * Sets input data for decompression. Should be called whenever
31.109 + * needsInput() returns true indicating that more input data is
31.110 + * required.
31.111 + * @param b the input data bytes
31.112 + * @param off the start offset of the input data
31.113 + * @param len the length of the input data
31.114 + * @see Inflater#needsInput
31.115 + */
31.116 + public void setInput(byte[] b, int off, int len) {
31.117 + if (b == null) {
31.118 + throw new NullPointerException();
31.119 + }
31.120 + if (off < 0 || len < 0 || off > b.length - len) {
31.121 + throw new ArrayIndexOutOfBoundsException();
31.122 + }
31.123 + impl.setInput(b, off, len, false);
31.124 + }
31.125 +
31.126 + /**
31.127 + * Sets input data for decompression. Should be called whenever
31.128 + * needsInput() returns true indicating that more input data is
31.129 + * required.
31.130 + * @param b the input data bytes
31.131 + * @see Inflater#needsInput
31.132 + */
31.133 + public void setInput(byte[] b) {
31.134 + setInput(b, 0, b.length);
31.135 + }
31.136 +
31.137 + /**
31.138 + * Sets the preset dictionary to the given array of bytes. Should be
31.139 + * called when inflate() returns 0 and needsDictionary() returns true
31.140 + * indicating that a preset dictionary is required. The method getAdler()
31.141 + * can be used to get the Adler-32 value of the dictionary needed.
31.142 + * @param b the dictionary data bytes
31.143 + * @param off the start offset of the data
31.144 + * @param len the length of the data
31.145 + * @see Inflater#needsDictionary
31.146 + * @see Inflater#getAdler
31.147 + */
31.148 + public void setDictionary(byte[] b, int off, int len) {
31.149 + if (b == null) {
31.150 + throw new NullPointerException();
31.151 + }
31.152 + if (off < 0 || len < 0 || off > b.length - len) {
31.153 + throw new ArrayIndexOutOfBoundsException();
31.154 + }
31.155 + byte[] arr;
31.156 + if (off == 0) {
31.157 + arr = b;
31.158 + } else {
31.159 + arr = new byte[len];
31.160 + org.apidesign.bck2brwsr.emul.lang.System.arraycopy(b, off, arr, 0, len);
31.161 + }
31.162 + impl.setDictionary(arr, len);
31.163 + }
31.164 +
31.165 + /**
31.166 + * Sets the preset dictionary to the given array of bytes. Should be
31.167 + * called when inflate() returns 0 and needsDictionary() returns true
31.168 + * indicating that a preset dictionary is required. The method getAdler()
31.169 + * can be used to get the Adler-32 value of the dictionary needed.
31.170 + * @param b the dictionary data bytes
31.171 + * @see Inflater#needsDictionary
31.172 + * @see Inflater#getAdler
31.173 + */
31.174 + public void setDictionary(byte[] b) {
31.175 + impl.setDictionary(b, b.length);
31.176 + }
31.177 +
31.178 + /**
31.179 + * Returns the total number of bytes remaining in the input buffer.
31.180 + * This can be used to find out what bytes still remain in the input
31.181 + * buffer after decompression has finished.
31.182 + * @return the total number of bytes remaining in the input buffer
31.183 + */
31.184 + public int getRemaining() {
31.185 + return impl.getAvailIn();
31.186 + }
31.187 +
31.188 + /**
31.189 + * Returns true if no data remains in the input buffer. This can
31.190 + * be used to determine if #setInput should be called in order
31.191 + * to provide more input.
31.192 + * @return true if no data remains in the input buffer
31.193 + */
31.194 + public boolean needsInput() {
31.195 + return getRemaining() <= 0;
31.196 + }
31.197 +
31.198 + /**
31.199 + * Returns true if a preset dictionary is needed for decompression.
31.200 + * @return true if a preset dictionary is needed for decompression
31.201 + * @see Inflater#setDictionary
31.202 + */
31.203 + public boolean needsDictionary() {
31.204 + return impl.needDict();
31.205 + }
31.206 +
31.207 + /**
31.208 + * Returns true if the end of the compressed data stream has been
31.209 + * reached.
31.210 + * @return true if the end of the compressed data stream has been
31.211 + * reached
31.212 + */
31.213 + public boolean finished() {
31.214 + return impl.finished();
31.215 + }
31.216 +
31.217 + /**
31.218 + * Uncompresses bytes into specified buffer. Returns actual number
31.219 + * of bytes uncompressed. A return value of 0 indicates that
31.220 + * needsInput() or needsDictionary() should be called in order to
31.221 + * determine if more input data or a preset dictionary is required.
31.222 + * In the latter case, getAdler() can be used to get the Adler-32
31.223 + * value of the dictionary required.
31.224 + * @param b the buffer for the uncompressed data
31.225 + * @param off the start offset of the data
31.226 + * @param len the maximum number of uncompressed bytes
31.227 + * @return the actual number of uncompressed bytes
31.228 + * @exception DataFormatException if the compressed data format is invalid
31.229 + * @see Inflater#needsInput
31.230 + * @see Inflater#needsDictionary
31.231 + */
31.232 + public int inflate(byte[] b, int off, int len)
31.233 + throws DataFormatException
31.234 + {
31.235 + if (b == null) {
31.236 + throw new NullPointerException();
31.237 + }
31.238 + if (off < 0 || len < 0 || off > b.length - len) {
31.239 + throw new ArrayIndexOutOfBoundsException();
31.240 + }
31.241 + impl.setOutput(b, off, len);
31.242 + int err = impl.inflate(JzLibInflater.Z_NO_FLUSH);
31.243 + return impl.next_out_index - off;
31.244 + }
31.245 +
31.246 + /**
31.247 + * Uncompresses bytes into specified buffer. Returns actual number
31.248 + * of bytes uncompressed. A return value of 0 indicates that
31.249 + * needsInput() or needsDictionary() should be called in order to
31.250 + * determine if more input data or a preset dictionary is required.
31.251 + * In the latter case, getAdler() can be used to get the Adler-32
31.252 + * value of the dictionary required.
31.253 + * @param b the buffer for the uncompressed data
31.254 + * @return the actual number of uncompressed bytes
31.255 + * @exception DataFormatException if the compressed data format is invalid
31.256 + * @see Inflater#needsInput
31.257 + * @see Inflater#needsDictionary
31.258 + */
31.259 + public int inflate(byte[] b) throws DataFormatException {
31.260 + return inflate(b, 0, b.length);
31.261 + }
31.262 +
31.263 + /**
31.264 + * Returns the ADLER-32 value of the uncompressed data.
31.265 + * @return the ADLER-32 value of the uncompressed data
31.266 + */
31.267 + public int getAdler() {
31.268 + return (int) impl.getAdler();
31.269 + }
31.270 +
31.271 + /**
31.272 + * Returns the total number of compressed bytes input so far.
31.273 + *
31.274 + * <p>Since the number of bytes may be greater than
31.275 + * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now
31.276 + * the preferred means of obtaining this information.</p>
31.277 + *
31.278 + * @return the total number of compressed bytes input so far
31.279 + */
31.280 + public int getTotalIn() {
31.281 + return (int) getBytesRead();
31.282 + }
31.283 +
31.284 + /**
31.285 + * Returns the total number of compressed bytes input so far.</p>
31.286 + *
31.287 + * @return the total (non-negative) number of compressed bytes input so far
31.288 + * @since 1.5
31.289 + */
31.290 + public long getBytesRead() {
31.291 + return impl.total_in;
31.292 + }
31.293 +
31.294 + /**
31.295 + * Returns the total number of uncompressed bytes output so far.
31.296 + *
31.297 + * <p>Since the number of bytes may be greater than
31.298 + * Integer.MAX_VALUE, the {@link #getBytesWritten()} method is now
31.299 + * the preferred means of obtaining this information.</p>
31.300 + *
31.301 + * @return the total number of uncompressed bytes output so far
31.302 + */
31.303 + public int getTotalOut() {
31.304 + return (int) getBytesWritten();
31.305 + }
31.306 +
31.307 + /**
31.308 + * Returns the total number of uncompressed bytes output so far.</p>
31.309 + *
31.310 + * @return the total (non-negative) number of uncompressed bytes output so far
31.311 + * @since 1.5
31.312 + */
31.313 + public long getBytesWritten() {
31.314 + return impl.total_out;
31.315 + }
31.316 +
31.317 + /**
31.318 + * Resets inflater so that a new set of input data can be processed.
31.319 + */
31.320 + public void reset() {
31.321 + impl = new JzLibInflater(15, nowrap);
31.322 + }
31.323 +
31.324 + /**
31.325 + * Closes the decompressor and discards any unprocessed input.
31.326 + * This method should be called when the decompressor is no longer
31.327 + * being used, but will also be called automatically by the finalize()
31.328 + * method. Once this method is called, the behavior of the Inflater
31.329 + * object is undefined.
31.330 + */
31.331 + public void end() {
31.332 + impl.end();
31.333 + }
31.334 +
31.335 + /**
31.336 + * Closes the decompressor when garbage is collected.
31.337 + */
31.338 + protected void finalize() {
31.339 + end();
31.340 + }
31.341 +}
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/JzLibInflater.java Fri Feb 15 21:16:05 2013 +0100
32.3 @@ -0,0 +1,137 @@
32.4 +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
32.5 +/*
32.6 +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
32.7 +
32.8 +Redistribution and use in source and binary forms, with or without
32.9 +modification, are permitted provided that the following conditions are met:
32.10 +
32.11 + 1. Redistributions of source code must retain the above copyright notice,
32.12 + this list of conditions and the following disclaimer.
32.13 +
32.14 + 2. Redistributions in binary form must reproduce the above copyright
32.15 + notice, this list of conditions and the following disclaimer in
32.16 + the documentation and/or other materials provided with the distribution.
32.17 +
32.18 + 3. The names of the authors may not be used to endorse or promote products
32.19 + derived from this software without specific prior written permission.
32.20 +
32.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
32.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
32.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
32.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
32.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
32.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
32.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32.31 + */
32.32 +/*
32.33 + * This program is based on zlib-1.1.3, so all credit should go authors
32.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
32.35 + * and contributors of zlib.
32.36 + */
32.37 +
32.38 +package org.apidesign.bck2brwsr.emul.zip;
32.39 +
32.40 +final class JzLibInflater extends ZStream{
32.41 +
32.42 + static final private int MAX_WBITS=15; // 32K LZ77 window
32.43 + static final private int DEF_WBITS=MAX_WBITS;
32.44 +
32.45 + public static final int Z_NO_FLUSH=0;
32.46 + static final private int Z_PARTIAL_FLUSH=1;
32.47 + static final private int Z_SYNC_FLUSH=2;
32.48 + static final private int Z_FULL_FLUSH=3;
32.49 + static final private int Z_FINISH=4;
32.50 +
32.51 + static final private int MAX_MEM_LEVEL=9;
32.52 +
32.53 + static final private int Z_OK=0;
32.54 + static final private int Z_STREAM_END=1;
32.55 + static final private int Z_NEED_DICT=2;
32.56 + static final private int Z_ERRNO=-1;
32.57 + static final private int Z_STREAM_ERROR=-2;
32.58 + static final private int Z_DATA_ERROR=-3;
32.59 + static final private int Z_MEM_ERROR=-4;
32.60 + static final private int Z_BUF_ERROR=-5;
32.61 + static final private int Z_VERSION_ERROR=-6;
32.62 +
32.63 + public JzLibInflater() {
32.64 + super();
32.65 + init();
32.66 + }
32.67 +
32.68 + public JzLibInflater(int w) {
32.69 + this(w, false);
32.70 + }
32.71 +
32.72 + public JzLibInflater(int w, boolean nowrap) {
32.73 + super();
32.74 + int ret = init(w, nowrap);
32.75 + if(ret!=Z_OK)
32.76 + throw new IllegalStateException(ret+": "+msg);
32.77 + }
32.78 +
32.79 + private boolean finished = false;
32.80 +
32.81 + public int init(){
32.82 + return init(DEF_WBITS);
32.83 + }
32.84 +
32.85 + public int init(boolean nowrap){
32.86 + return init(DEF_WBITS, nowrap);
32.87 + }
32.88 +
32.89 + public int init(int w){
32.90 + return init(w, false);
32.91 + }
32.92 +
32.93 + public int init(int w, boolean nowrap){
32.94 + finished = false;
32.95 + istate=new Inflate(this);
32.96 + return istate.inflateInit(nowrap?-w:w);
32.97 + }
32.98 +
32.99 + public int inflate(int f){
32.100 + if(istate==null) return Z_STREAM_ERROR;
32.101 + int ret = istate.inflate(f);
32.102 + if(ret == Z_STREAM_END)
32.103 + finished = true;
32.104 + return ret;
32.105 + }
32.106 +
32.107 + public int end(){
32.108 + finished = true;
32.109 + if(istate==null) return Z_STREAM_ERROR;
32.110 + int ret=istate.inflateEnd();
32.111 +// istate = null;
32.112 + return ret;
32.113 + }
32.114 +
32.115 + public int sync(){
32.116 + if(istate == null)
32.117 + return Z_STREAM_ERROR;
32.118 + return istate.inflateSync();
32.119 + }
32.120 +
32.121 + public int syncPoint(){
32.122 + if(istate == null)
32.123 + return Z_STREAM_ERROR;
32.124 + return istate.inflateSyncPoint();
32.125 + }
32.126 +
32.127 + public int setDictionary(byte[] dictionary, int dictLength){
32.128 + if(istate == null)
32.129 + return Z_STREAM_ERROR;
32.130 + return istate.inflateSetDictionary(dictionary, dictLength);
32.131 + }
32.132 +
32.133 + public boolean finished(){
32.134 + return istate.mode==12 /*DONE*/;
32.135 + }
32.136 +
32.137 + public boolean needDict() {
32.138 + return istate == null ? false : istate.mode == Inflate.DICT0;
32.139 + }
32.140 +}
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/ZStream.java Fri Feb 15 21:16:05 2013 +0100
33.3 @@ -0,0 +1,253 @@
33.4 +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
33.5 +/*
33.6 +Copyright (c) 2000-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 +import org.apidesign.bck2brwsr.emul.lang.System;
33.41 +
33.42 +/**
33.43 + * ZStream
33.44 + *
33.45 + * @deprecated Not for public use in the future.
33.46 + */
33.47 +@Deprecated
33.48 +class ZStream{
33.49 +
33.50 + static final private int MAX_WBITS=15; // 32K LZ77 window
33.51 + static final private int DEF_WBITS=MAX_WBITS;
33.52 +
33.53 + static final private int Z_NO_FLUSH=0;
33.54 + static final private int Z_PARTIAL_FLUSH=1;
33.55 + static final private int Z_SYNC_FLUSH=2;
33.56 + static final private int Z_FULL_FLUSH=3;
33.57 + static final private int Z_FINISH=4;
33.58 +
33.59 + static final private int MAX_MEM_LEVEL=9;
33.60 +
33.61 + static final private int Z_OK=0;
33.62 + static final private int Z_STREAM_END=1;
33.63 + static final private int Z_NEED_DICT=2;
33.64 + static final private int Z_ERRNO=-1;
33.65 + static final private int Z_STREAM_ERROR=-2;
33.66 + static final private int Z_DATA_ERROR=-3;
33.67 + static final private int Z_MEM_ERROR=-4;
33.68 + static final private int Z_BUF_ERROR=-5;
33.69 + static final private int Z_VERSION_ERROR=-6;
33.70 +
33.71 + public byte[] next_in; // next input byte
33.72 + public int next_in_index;
33.73 + public int avail_in; // number of bytes available at next_in
33.74 + public long total_in; // total nb of input bytes read so far
33.75 +
33.76 + public byte[] next_out; // next output byte should be put there
33.77 + public int next_out_index;
33.78 + public int avail_out; // remaining free space at next_out
33.79 + public long total_out; // total nb of bytes output so far
33.80 +
33.81 + public String msg;
33.82 +
33.83 + Inflate istate;
33.84 +
33.85 + int data_type; // best guess about the data type: ascii or binary
33.86 +
33.87 + Checksum adler;
33.88 +
33.89 + public ZStream(){
33.90 + this(new Adler32());
33.91 + }
33.92 +
33.93 + public ZStream(Checksum adler){
33.94 + this.adler=adler;
33.95 + }
33.96 +
33.97 + public int inflateInit(){
33.98 + return inflateInit(DEF_WBITS);
33.99 + }
33.100 + public int inflateInit(boolean nowrap){
33.101 + return inflateInit(DEF_WBITS, nowrap);
33.102 + }
33.103 + public int inflateInit(int w){
33.104 + return inflateInit(w, false);
33.105 + }
33.106 +
33.107 + public int inflateInit(int w, boolean nowrap){
33.108 + istate=new Inflate(this);
33.109 + return istate.inflateInit(nowrap?-w:w);
33.110 + }
33.111 +
33.112 + public int inflate(int f){
33.113 + if(istate==null) return Z_STREAM_ERROR;
33.114 + return istate.inflate(f);
33.115 + }
33.116 + public int inflateEnd(){
33.117 + if(istate==null) return Z_STREAM_ERROR;
33.118 + int ret=istate.inflateEnd();
33.119 +// istate = null;
33.120 + return ret;
33.121 + }
33.122 +
33.123 + public int inflateSync(){
33.124 + if(istate == null)
33.125 + return Z_STREAM_ERROR;
33.126 + return istate.inflateSync();
33.127 + }
33.128 + public int inflateSyncPoint(){
33.129 + if(istate == null)
33.130 + return Z_STREAM_ERROR;
33.131 + return istate.inflateSyncPoint();
33.132 + }
33.133 + public int inflateSetDictionary(byte[] dictionary, int dictLength){
33.134 + if(istate == null)
33.135 + return Z_STREAM_ERROR;
33.136 + return istate.inflateSetDictionary(dictionary, dictLength);
33.137 + }
33.138 + public boolean inflateFinished(){
33.139 + return istate.mode==12 /*DONE*/;
33.140 + }
33.141 +
33.142 +
33.143 + public long getAdler(){
33.144 + return adler.getValue();
33.145 + }
33.146 +
33.147 + public void free(){
33.148 + next_in=null;
33.149 + next_out=null;
33.150 + msg=null;
33.151 + }
33.152 +
33.153 + public void setOutput(byte[] buf){
33.154 + setOutput(buf, 0, buf.length);
33.155 + }
33.156 +
33.157 + public void setOutput(byte[] buf, int off, int len){
33.158 + next_out = buf;
33.159 + next_out_index = off;
33.160 + avail_out = len;
33.161 + }
33.162 +
33.163 + public void setInput(byte[] buf){
33.164 + setInput(buf, 0, buf.length, false);
33.165 + }
33.166 +
33.167 + public void setInput(byte[] buf, boolean append){
33.168 + setInput(buf, 0, buf.length, append);
33.169 + }
33.170 +
33.171 + public void setInput(byte[] buf, int off, int len, boolean append){
33.172 + if(len<=0 && append && next_in!=null) return;
33.173 +
33.174 + if(avail_in>0 && append){
33.175 + byte[] tmp = new byte[avail_in+len];
33.176 + System.arraycopy(next_in, next_in_index, tmp, 0, avail_in);
33.177 + System.arraycopy(buf, off, tmp, avail_in, len);
33.178 + next_in=tmp;
33.179 + next_in_index=0;
33.180 + avail_in+=len;
33.181 + }
33.182 + else{
33.183 + next_in=buf;
33.184 + next_in_index=off;
33.185 + avail_in=len;
33.186 + }
33.187 + }
33.188 +
33.189 + public byte[] getNextIn(){
33.190 + return next_in;
33.191 + }
33.192 +
33.193 + public void setNextIn(byte[] next_in){
33.194 + this.next_in = next_in;
33.195 + }
33.196 +
33.197 + public int getNextInIndex(){
33.198 + return next_in_index;
33.199 + }
33.200 +
33.201 + public void setNextInIndex(int next_in_index){
33.202 + this.next_in_index = next_in_index;
33.203 + }
33.204 +
33.205 + public int getAvailIn(){
33.206 + return avail_in;
33.207 + }
33.208 +
33.209 + public void setAvailIn(int avail_in){
33.210 + this.avail_in = avail_in;
33.211 + }
33.212 +
33.213 + public byte[] getNextOut(){
33.214 + return next_out;
33.215 + }
33.216 +
33.217 + public void setNextOut(byte[] next_out){
33.218 + this.next_out = next_out;
33.219 + }
33.220 +
33.221 + public int getNextOutIndex(){
33.222 + return next_out_index;
33.223 + }
33.224 +
33.225 + public void setNextOutIndex(int next_out_index){
33.226 + this.next_out_index = next_out_index;
33.227 + }
33.228 +
33.229 + public int getAvailOut(){
33.230 + return avail_out;
33.231 +
33.232 + }
33.233 +
33.234 + public void setAvailOut(int avail_out){
33.235 + this.avail_out = avail_out;
33.236 + }
33.237 +
33.238 + public long getTotalOut(){
33.239 + return total_out;
33.240 + }
33.241 +
33.242 + public long getTotalIn(){
33.243 + return total_in;
33.244 + }
33.245 +
33.246 + public String getMessage(){
33.247 + return msg;
33.248 + }
33.249 +
33.250 + /**
33.251 + * Those methods are expected to be override by Inflater and Deflater.
33.252 + * In the future, they will become abstract methods.
33.253 + */
33.254 + public int end(){ return Z_OK; }
33.255 + public boolean finished(){ return false; }
33.256 +}
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/ZipConstants64.java Fri Feb 15 21:16:05 2013 +0100
34.3 @@ -0,0 +1,84 @@
34.4 +/*
34.5 + * Copyright (c) 1995, 1996, Oracle and/or its affiliates. All rights reserved.
34.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
34.7 + *
34.8 + * This code is free software; you can redistribute it and/or modify it
34.9 + * under the terms of the GNU General Public License version 2 only, as
34.10 + * published by the Free Software Foundation. Oracle designates this
34.11 + * particular file as subject to the "Classpath" exception as provided
34.12 + * by Oracle in the LICENSE file that accompanied this code.
34.13 + *
34.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
34.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
34.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
34.17 + * version 2 for more details (a copy is included in the LICENSE file that
34.18 + * accompanied this code).
34.19 + *
34.20 + * You should have received a copy of the GNU General Public License version
34.21 + * 2 along with this work; if not, write to the Free Software Foundation,
34.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
34.23 + *
34.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
34.25 + * or visit www.oracle.com if you need additional information or have any
34.26 + * questions.
34.27 + */
34.28 +
34.29 +package org.apidesign.bck2brwsr.emul.zip;
34.30 +
34.31 +/*
34.32 + * This class defines the constants that are used by the classes
34.33 + * which manipulate Zip64 files.
34.34 + */
34.35 +
34.36 +public class ZipConstants64 {
34.37 +
34.38 + /*
34.39 + * ZIP64 constants
34.40 + */
34.41 + static final long ZIP64_ENDSIG = 0x06064b50L; // "PK\006\006"
34.42 + static final long ZIP64_LOCSIG = 0x07064b50L; // "PK\006\007"
34.43 + static final int ZIP64_ENDHDR = 56; // ZIP64 end header size
34.44 + static final int ZIP64_LOCHDR = 20; // ZIP64 end loc header size
34.45 + static final int ZIP64_EXTHDR = 24; // EXT header size
34.46 + static final int ZIP64_EXTID = 0x0001; // Extra field Zip64 header ID
34.47 +
34.48 + static final int ZIP64_MAGICCOUNT = 0xFFFF;
34.49 + static final long ZIP64_MAGICVAL = 0xFFFFFFFFL;
34.50 +
34.51 + /*
34.52 + * Zip64 End of central directory (END) header field offsets
34.53 + */
34.54 + static final int ZIP64_ENDLEN = 4; // size of zip64 end of central dir
34.55 + static final int ZIP64_ENDVEM = 12; // version made by
34.56 + static final int ZIP64_ENDVER = 14; // version needed to extract
34.57 + static final int ZIP64_ENDNMD = 16; // number of this disk
34.58 + static final int ZIP64_ENDDSK = 20; // disk number of start
34.59 + static final int ZIP64_ENDTOD = 24; // total number of entries on this disk
34.60 + static final int ZIP64_ENDTOT = 32; // total number of entries
34.61 + static final int ZIP64_ENDSIZ = 40; // central directory size in bytes
34.62 + static final int ZIP64_ENDOFF = 48; // offset of first CEN header
34.63 + static final int ZIP64_ENDEXT = 56; // zip64 extensible data sector
34.64 +
34.65 + /*
34.66 + * Zip64 End of central directory locator field offsets
34.67 + */
34.68 + static final int ZIP64_LOCDSK = 4; // disk number start
34.69 + static final int ZIP64_LOCOFF = 8; // offset of zip64 end
34.70 + static final int ZIP64_LOCTOT = 16; // total number of disks
34.71 +
34.72 + /*
34.73 + * Zip64 Extra local (EXT) header field offsets
34.74 + */
34.75 + static final int ZIP64_EXTCRC = 4; // uncompressed file crc-32 value
34.76 + static final int ZIP64_EXTSIZ = 8; // compressed size, 8-byte
34.77 + static final int ZIP64_EXTLEN = 16; // uncompressed size, 8-byte
34.78 +
34.79 + /*
34.80 + * Language encoding flag EFS
34.81 + */
34.82 + static final int EFS = 0x800; // If this bit is set the filename and
34.83 + // comment fields for this file must be
34.84 + // encoded using UTF-8.
34.85 +
34.86 + private ZipConstants64() {}
34.87 +}
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/ZipInputStream.java Fri Feb 15 21:16:05 2013 +0100
35.3 @@ -0,0 +1,468 @@
35.4 +/*
35.5 + * Copyright (c) 1996, 2009, 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 +import java.util.zip.*;
35.32 +import java.io.InputStream;
35.33 +import java.io.IOException;
35.34 +import java.io.EOFException;
35.35 +import java.io.PushbackInputStream;
35.36 +import static org.apidesign.bck2brwsr.emul.zip.ZipConstants64.*;
35.37 +import static java.util.zip.ZipInputStream.*;
35.38 +
35.39 +/**
35.40 + * This class implements an input stream filter for reading files in the
35.41 + * ZIP file format. Includes support for both compressed and uncompressed
35.42 + * entries.
35.43 + *
35.44 + * @author David Connelly
35.45 + */
35.46 +public
35.47 +class ZipInputStream extends InflaterInputStream {
35.48 + private ZipEntry entry;
35.49 + private int flag;
35.50 + private CRC32 crc = new CRC32();
35.51 + private long remaining;
35.52 + private byte[] tmpbuf = new byte[512];
35.53 +
35.54 + private static final int STORED = ZipEntry.STORED;
35.55 + private static final int DEFLATED = ZipEntry.DEFLATED;
35.56 +
35.57 + private boolean closed = false;
35.58 + // this flag is set to true after EOF has reached for
35.59 + // one entry
35.60 + private boolean entryEOF = false;
35.61 +
35.62 + /**
35.63 + * Check to make sure that this stream has not been closed
35.64 + */
35.65 + private void ensureOpen() throws IOException {
35.66 + if (closed) {
35.67 + throw new IOException("Stream closed");
35.68 + }
35.69 + }
35.70 +
35.71 + /**
35.72 + * Creates a new ZIP input stream.
35.73 + *
35.74 + * <p>The UTF-8 {@link java.nio.charset.Charset charset} is used to
35.75 + * decode the entry names.
35.76 + *
35.77 + * @param in the actual input stream
35.78 + */
35.79 + public ZipInputStream(InputStream in) {
35.80 +// this(in, "UTF-8");
35.81 + super(new PushbackInputStream(in, 512), new Inflater(true), 512);
35.82 + //usesDefaultInflater = true;
35.83 + if(in == null) {
35.84 + throw new NullPointerException("in is null");
35.85 + }
35.86 + }
35.87 +
35.88 + /**
35.89 + * Creates a new ZIP input stream.
35.90 + *
35.91 + * @param in the actual input stream
35.92 + *
35.93 + * @param charset
35.94 + * The {@linkplain java.nio.charset.Charset charset} to be
35.95 + * used to decode the ZIP entry name (ignored if the
35.96 + * <a href="package-summary.html#lang_encoding"> language
35.97 + * encoding bit</a> of the ZIP entry's general purpose bit
35.98 + * flag is set).
35.99 + *
35.100 + * @since 1.7
35.101 + *
35.102 + public ZipInputStream(InputStream in, Charset charset) {
35.103 + super(new PushbackInputStream(in, 512), new Inflater(true), 512);
35.104 + usesDefaultInflater = true;
35.105 + if(in == null) {
35.106 + throw new NullPointerException("in is null");
35.107 + }
35.108 + if (charset == null)
35.109 + throw new NullPointerException("charset is null");
35.110 + this.zc = ZipCoder.get(charset);
35.111 + }
35.112 + */
35.113 +
35.114 + /**
35.115 + * Reads the next ZIP file entry and positions the stream at the
35.116 + * beginning of the entry data.
35.117 + * @return the next ZIP file entry, or null if there are no more entries
35.118 + * @exception ZipException if a ZIP file error has occurred
35.119 + * @exception IOException if an I/O error has occurred
35.120 + */
35.121 + public ZipEntry getNextEntry() throws IOException {
35.122 + ensureOpen();
35.123 + if (entry != null) {
35.124 + closeEntry();
35.125 + }
35.126 + crc.reset();
35.127 + inf.reset();
35.128 + if ((entry = readLOC()) == null) {
35.129 + return null;
35.130 + }
35.131 + if (entry.getMethod() == STORED) {
35.132 + remaining = entry.getSize();
35.133 + }
35.134 + entryEOF = false;
35.135 + return entry;
35.136 + }
35.137 +
35.138 + /**
35.139 + * Closes the current ZIP entry and positions the stream for reading the
35.140 + * next entry.
35.141 + * @exception ZipException if a ZIP file error has occurred
35.142 + * @exception IOException if an I/O error has occurred
35.143 + */
35.144 + public void closeEntry() throws IOException {
35.145 + ensureOpen();
35.146 + while (read(tmpbuf, 0, tmpbuf.length) != -1) ;
35.147 + entryEOF = true;
35.148 + }
35.149 +
35.150 + /**
35.151 + * Returns 0 after EOF has reached for the current entry data,
35.152 + * otherwise always return 1.
35.153 + * <p>
35.154 + * Programs should not count on this method to return the actual number
35.155 + * of bytes that could be read without blocking.
35.156 + *
35.157 + * @return 1 before EOF and 0 after EOF has reached for current entry.
35.158 + * @exception IOException if an I/O error occurs.
35.159 + *
35.160 + */
35.161 + public int available() throws IOException {
35.162 + ensureOpen();
35.163 + if (entryEOF) {
35.164 + return 0;
35.165 + } else {
35.166 + return 1;
35.167 + }
35.168 + }
35.169 +
35.170 + /**
35.171 + * Reads from the current ZIP entry into an array of bytes.
35.172 + * If <code>len</code> is not zero, the method
35.173 + * blocks until some input is available; otherwise, no
35.174 + * bytes are read and <code>0</code> is returned.
35.175 + * @param b the buffer into which the data is read
35.176 + * @param off the start offset in the destination array <code>b</code>
35.177 + * @param len the maximum number of bytes read
35.178 + * @return the actual number of bytes read, or -1 if the end of the
35.179 + * entry is reached
35.180 + * @exception NullPointerException if <code>b</code> is <code>null</code>.
35.181 + * @exception IndexOutOfBoundsException if <code>off</code> is negative,
35.182 + * <code>len</code> is negative, or <code>len</code> is greater than
35.183 + * <code>b.length - off</code>
35.184 + * @exception ZipException if a ZIP file error has occurred
35.185 + * @exception IOException if an I/O error has occurred
35.186 + */
35.187 + public int read(byte[] b, int off, int len) throws IOException {
35.188 + ensureOpen();
35.189 + if (off < 0 || len < 0 || off > b.length - len) {
35.190 + throw new IndexOutOfBoundsException();
35.191 + } else if (len == 0) {
35.192 + return 0;
35.193 + }
35.194 +
35.195 + if (entry == null) {
35.196 + return -1;
35.197 + }
35.198 + switch (entry.getMethod()) {
35.199 + case DEFLATED:
35.200 + len = super.read(b, off, len);
35.201 + if (len == -1) {
35.202 + readEnd(entry);
35.203 + entryEOF = true;
35.204 + entry = null;
35.205 + } else {
35.206 + crc.update(b, off, len);
35.207 + }
35.208 + return len;
35.209 + case STORED:
35.210 + if (remaining <= 0) {
35.211 + entryEOF = true;
35.212 + entry = null;
35.213 + return -1;
35.214 + }
35.215 + if (len > remaining) {
35.216 + len = (int)remaining;
35.217 + }
35.218 + len = in.read(b, off, len);
35.219 + if (len == -1) {
35.220 + throw new ZipException("unexpected EOF");
35.221 + }
35.222 + crc.update(b, off, len);
35.223 + remaining -= len;
35.224 + if (remaining == 0 && entry.getCrc() != crc.getValue()) {
35.225 + throw new ZipException(
35.226 + "invalid entry CRC (expected 0x" + Long.toHexString(entry.getCrc()) +
35.227 + " but got 0x" + Long.toHexString(crc.getValue()) + ")");
35.228 + }
35.229 + return len;
35.230 + default:
35.231 + throw new ZipException("invalid compression method");
35.232 + }
35.233 + }
35.234 +
35.235 + /**
35.236 + * Skips specified number of bytes in the current ZIP entry.
35.237 + * @param n the number of bytes to skip
35.238 + * @return the actual number of bytes skipped
35.239 + * @exception ZipException if a ZIP file error has occurred
35.240 + * @exception IOException if an I/O error has occurred
35.241 + * @exception IllegalArgumentException if n < 0
35.242 + */
35.243 + public long skip(long n) throws IOException {
35.244 + if (n < 0) {
35.245 + throw new IllegalArgumentException("negative skip length");
35.246 + }
35.247 + ensureOpen();
35.248 + int max = (int)Math.min(n, Integer.MAX_VALUE);
35.249 + int total = 0;
35.250 + while (total < max) {
35.251 + int len = max - total;
35.252 + if (len > tmpbuf.length) {
35.253 + len = tmpbuf.length;
35.254 + }
35.255 + len = read(tmpbuf, 0, len);
35.256 + if (len == -1) {
35.257 + entryEOF = true;
35.258 + break;
35.259 + }
35.260 + total += len;
35.261 + }
35.262 + return total;
35.263 + }
35.264 +
35.265 + /**
35.266 + * Closes this input stream and releases any system resources associated
35.267 + * with the stream.
35.268 + * @exception IOException if an I/O error has occurred
35.269 + */
35.270 + public void close() throws IOException {
35.271 + if (!closed) {
35.272 + super.close();
35.273 + closed = true;
35.274 + }
35.275 + }
35.276 +
35.277 + private byte[] b = new byte[256];
35.278 +
35.279 + /*
35.280 + * Reads local file (LOC) header for next entry.
35.281 + */
35.282 + private ZipEntry readLOC() throws IOException {
35.283 + try {
35.284 + readFully(tmpbuf, 0, LOCHDR);
35.285 + } catch (EOFException e) {
35.286 + return null;
35.287 + }
35.288 + if (get32(tmpbuf, 0) != LOCSIG) {
35.289 + return null;
35.290 + }
35.291 + // get flag first, we need check EFS.
35.292 + flag = get16(tmpbuf, LOCFLG);
35.293 + // get the entry name and create the ZipEntry first
35.294 + int len = get16(tmpbuf, LOCNAM);
35.295 + int blen = b.length;
35.296 + if (len > blen) {
35.297 + do
35.298 + blen = blen * 2;
35.299 + while (len > blen);
35.300 + b = new byte[blen];
35.301 + }
35.302 + readFully(b, 0, len);
35.303 + // Force to use UTF-8 if the EFS bit is ON, even the cs is NOT UTF-8
35.304 + ZipEntry e = createZipEntry(((flag & EFS) != 0)
35.305 + ? toStringUTF8(b, len)
35.306 + : toString(b, len));
35.307 + // now get the remaining fields for the entry
35.308 + if ((flag & 1) == 1) {
35.309 + throw new ZipException("encrypted ZIP entry not supported");
35.310 + }
35.311 + e.setMethod(get16(tmpbuf, LOCHOW));
35.312 + e.setTime(get32(tmpbuf, LOCTIM));
35.313 + if ((flag & 8) == 8) {
35.314 + /* "Data Descriptor" present */
35.315 + if (e.getMethod() != DEFLATED) {
35.316 + throw new ZipException(
35.317 + "only DEFLATED entries can have EXT descriptor");
35.318 + }
35.319 + } else {
35.320 + e.setCrc(get32(tmpbuf, LOCCRC));
35.321 + e.setCompressedSize(get32(tmpbuf, LOCSIZ));
35.322 + e.setSize(get32(tmpbuf, LOCLEN));
35.323 + }
35.324 + len = get16(tmpbuf, LOCEXT);
35.325 + if (len > 0) {
35.326 + byte[] bb = new byte[len];
35.327 + readFully(bb, 0, len);
35.328 + e.setExtra(bb);
35.329 + // extra fields are in "HeaderID(2)DataSize(2)Data... format
35.330 + if (e.getCompressedSize() == ZIP64_MAGICVAL || e.getCompressedSize() == ZIP64_MAGICVAL) {
35.331 + int off = 0;
35.332 + while (off + 4 < len) {
35.333 + int sz = get16(bb, off + 2);
35.334 + if (get16(bb, off) == ZIP64_EXTID) {
35.335 + off += 4;
35.336 + // LOC extra zip64 entry MUST include BOTH original and
35.337 + // compressed file size fields
35.338 + if (sz < 16 || (off + sz) > len ) {
35.339 + // Invalid zip64 extra fields, simply skip. Even it's
35.340 + // rare, it's possible the entry size happens to be
35.341 + // the magic value and it "accidnetly" has some bytes
35.342 + // in extra match the id.
35.343 + return e;
35.344 + }
35.345 + e.setSize(get64(bb, off));
35.346 + e.setCompressedSize(get64(bb, off + 8));
35.347 + break;
35.348 + }
35.349 + off += (sz + 4);
35.350 + }
35.351 + }
35.352 + }
35.353 + return e;
35.354 + }
35.355 +
35.356 + /**
35.357 + * Creates a new <code>ZipEntry</code> object for the specified
35.358 + * entry name.
35.359 + *
35.360 + * @param name the ZIP file entry name
35.361 + * @return the ZipEntry just created
35.362 + */
35.363 + protected ZipEntry createZipEntry(String name) {
35.364 + return new ZipEntry(name);
35.365 + }
35.366 +
35.367 + /*
35.368 + * Reads end of deflated entry as well as EXT descriptor if present.
35.369 + */
35.370 + private void readEnd(ZipEntry e) throws IOException {
35.371 + int n = inf.getRemaining();
35.372 + if (n > 0) {
35.373 + ((PushbackInputStream)in).unread(buf, len - n, n);
35.374 + }
35.375 + if ((flag & 8) == 8) {
35.376 + /* "Data Descriptor" present */
35.377 + if (inf.getBytesWritten() > ZIP64_MAGICVAL ||
35.378 + inf.getBytesRead() > ZIP64_MAGICVAL) {
35.379 + // ZIP64 format
35.380 + readFully(tmpbuf, 0, ZIP64_EXTHDR);
35.381 + long sig = get32(tmpbuf, 0);
35.382 + if (sig != EXTSIG) { // no EXTSIG present
35.383 + e.setCrc(sig);
35.384 + e.setCompressedSize(get64(tmpbuf, ZIP64_EXTSIZ - ZIP64_EXTCRC));
35.385 + e.setSize(get64(tmpbuf, ZIP64_EXTLEN - ZIP64_EXTCRC));
35.386 + ((PushbackInputStream)in).unread(
35.387 + tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC - 1, ZIP64_EXTCRC);
35.388 + } else {
35.389 + e.setCrc(get32(tmpbuf, ZIP64_EXTCRC));
35.390 + e.setCompressedSize(get64(tmpbuf, ZIP64_EXTSIZ));
35.391 + e.setSize(get64(tmpbuf, ZIP64_EXTLEN));
35.392 + }
35.393 + } else {
35.394 + readFully(tmpbuf, 0, EXTHDR);
35.395 + long sig = get32(tmpbuf, 0);
35.396 + if (sig != EXTSIG) { // no EXTSIG present
35.397 + e.setCrc(sig);
35.398 + e.setCompressedSize(get32(tmpbuf, EXTSIZ - EXTCRC));
35.399 + e.setSize(get32(tmpbuf, EXTLEN - EXTCRC));
35.400 + ((PushbackInputStream)in).unread(
35.401 + tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC);
35.402 + } else {
35.403 + e.setCrc(get32(tmpbuf, EXTCRC));
35.404 + e.setCompressedSize(get32(tmpbuf, EXTSIZ));
35.405 + e.setSize(get32(tmpbuf, EXTLEN));
35.406 + }
35.407 + }
35.408 + }
35.409 + if (e.getSize() != inf.getBytesWritten()) {
35.410 + throw new ZipException(
35.411 + "invalid entry size (expected " + e.getSize() +
35.412 + " but got " + inf.getBytesWritten() + " bytes)");
35.413 + }
35.414 + if (e.getCompressedSize() != inf.getBytesRead()) {
35.415 + throw new ZipException(
35.416 + "invalid entry compressed size (expected " + e.getCompressedSize() +
35.417 + " but got " + inf.getBytesRead() + " bytes)");
35.418 + }
35.419 + if (e.getCrc() != crc.getValue()) {
35.420 + throw new ZipException(
35.421 + "invalid entry CRC (expected 0x" + Long.toHexString(e.getCrc()) +
35.422 + " but got 0x" + Long.toHexString(crc.getValue()) + ")");
35.423 + }
35.424 + }
35.425 +
35.426 + /*
35.427 + * Reads bytes, blocking until all bytes are read.
35.428 + */
35.429 + private void readFully(byte[] b, int off, int len) throws IOException {
35.430 + while (len > 0) {
35.431 + int n = in.read(b, off, len);
35.432 + if (n == -1) {
35.433 + throw new EOFException();
35.434 + }
35.435 + off += n;
35.436 + len -= n;
35.437 + }
35.438 + }
35.439 +
35.440 + /*
35.441 + * Fetches unsigned 16-bit value from byte array at specified offset.
35.442 + * The bytes are assumed to be in Intel (little-endian) byte order.
35.443 + */
35.444 + private static final int get16(byte b[], int off) {
35.445 + return (b[off] & 0xff) | ((b[off+1] & 0xff) << 8);
35.446 + }
35.447 +
35.448 + /*
35.449 + * Fetches unsigned 32-bit value from byte array at specified offset.
35.450 + * The bytes are assumed to be in Intel (little-endian) byte order.
35.451 + */
35.452 + private static final long get32(byte b[], int off) {
35.453 + return (get16(b, off) | ((long)get16(b, off+2) << 16)) & 0xffffffffL;
35.454 + }
35.455 +
35.456 + /*
35.457 + * Fetches signed 64-bit value from byte array at specified offset.
35.458 + * The bytes are assumed to be in Intel (little-endian) byte order.
35.459 + */
35.460 + private static final long get64(byte b[], int off) {
35.461 + return get32(b, off) | (get32(b, off+4) << 32);
35.462 + }
35.463 +
35.464 + private static String toStringUTF8(byte[] arr, int len) {
35.465 + return new String(arr, 0, len);
35.466 + }
35.467 +
35.468 + private static String toString(byte[] b, int len) {
35.469 + return new String(b, 0, len);
35.470 + }
35.471 +}
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
36.2 +++ b/emul/mini/src/test/java/org/apidesign/bck2brwsr/emul/reflect/MethodImplTest.java Fri Feb 15 21:16:05 2013 +0100
36.3 @@ -0,0 +1,49 @@
36.4 +/**
36.5 + * Back 2 Browser Bytecode Translator
36.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
36.7 + *
36.8 + * This program is free software: you can redistribute it and/or modify
36.9 + * it under the terms of the GNU General Public License as published by
36.10 + * the Free Software Foundation, version 2 of the License.
36.11 + *
36.12 + * This program is distributed in the hope that it will be useful,
36.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
36.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36.15 + * GNU General Public License for more details.
36.16 + *
36.17 + * You should have received a copy of the GNU General Public License
36.18 + * along with this program. Look for COPYING file in the top folder.
36.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
36.20 + */
36.21 +package org.apidesign.bck2brwsr.emul.reflect;
36.22 +
36.23 +import java.lang.reflect.Method;
36.24 +import java.util.Enumeration;
36.25 +import org.testng.annotations.Test;
36.26 +
36.27 +/**
36.28 + *
36.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
36.30 + */
36.31 +public class MethodImplTest {
36.32 +
36.33 + public MethodImplTest() {
36.34 + }
36.35 +
36.36 + public static String[] arr(String... arr) {
36.37 + return arr;
36.38 + }
36.39 +
36.40 + @Test
36.41 + public void testSignatureForMethodWithAnArray() throws NoSuchMethodException {
36.42 + Method m = MethodImplTest.class.getMethod("arr", String[].class);
36.43 + String sig = MethodImpl.toSignature(m);
36.44 + int sep = sig.indexOf("__");
36.45 + assert sep > 0 : "Separator found " + sig;
36.46 +
36.47 + Enumeration<Class> en = MethodImpl.signatureParser(sig.substring(sep + 2));
36.48 +
36.49 + assert en.nextElement() == m.getReturnType() : "Return type is the same";
36.50 + assert en.nextElement() == m.getParameterTypes()[0] : "1st param type is the same";
36.51 + }
36.52 +}
36.53 \ No newline at end of file
37.1 --- a/javap/src/main/java/org/apidesign/javap/AnnotationParser.java Fri Feb 15 11:54:45 2013 +0100
37.2 +++ b/javap/src/main/java/org/apidesign/javap/AnnotationParser.java Fri Feb 15 21:16:05 2013 +0100
37.3 @@ -35,22 +35,37 @@
37.4 */
37.5 public class AnnotationParser {
37.6 private final boolean textual;
37.7 + private final boolean iterateArray;
37.8
37.9 - protected AnnotationParser(boolean textual) {
37.10 + protected AnnotationParser(boolean textual, boolean iterateArray) {
37.11 this.textual = textual;
37.12 + this.iterateArray = iterateArray;
37.13 }
37.14
37.15 - protected void visitAnnotationStart(String type) throws IOException {
37.16 + protected void visitAnnotationStart(String type, boolean top) throws IOException {
37.17 }
37.18
37.19 - protected void visitAnnotationEnd(String type) throws IOException {
37.20 + protected void visitAnnotationEnd(String type, boolean top) throws IOException {
37.21 }
37.22 +
37.23 + protected void visitValueStart(String attrName, char type) throws IOException {
37.24 + }
37.25 +
37.26 + protected void visitValueEnd(String attrName, char type) throws IOException {
37.27 + }
37.28 +
37.29
37.30 protected void visitAttr(
37.31 String annoType, String attr, String attrType, String value
37.32 ) throws IOException {
37.33 }
37.34
37.35 + protected void visitEnumAttr(
37.36 + String annoType, String attr, String attrType, String value
37.37 + ) throws IOException {
37.38 + visitAttr(annoType, attr, attrType, value);
37.39 + }
37.40 +
37.41 /** Initialize the parsing with constant pool from <code>cd</code>.
37.42 *
37.43 * @param attr the attribute defining annotations
37.44 @@ -70,30 +85,32 @@
37.45 private void read(DataInputStream dis, ClassData cd) throws IOException {
37.46 int cnt = dis.readUnsignedShort();
37.47 for (int i = 0; i < cnt; i++) {
37.48 - readAnno(dis, cd);
37.49 + readAnno(dis, cd, true);
37.50 }
37.51 }
37.52
37.53 - private void readAnno(DataInputStream dis, ClassData cd) throws IOException {
37.54 + private void readAnno(DataInputStream dis, ClassData cd, boolean top) throws IOException {
37.55 int type = dis.readUnsignedShort();
37.56 String typeName = cd.StringValue(type);
37.57 - visitAnnotationStart(typeName);
37.58 + visitAnnotationStart(typeName, top);
37.59 int cnt = dis.readUnsignedShort();
37.60 for (int i = 0; i < cnt; i++) {
37.61 String attrName = cd.StringValue(dis.readUnsignedShort());
37.62 readValue(dis, cd, typeName, attrName);
37.63 }
37.64 - visitAnnotationEnd(typeName);
37.65 + visitAnnotationEnd(typeName, top);
37.66 if (cnt == 0) {
37.67 visitAttr(typeName, null, null, null);
37.68 }
37.69 }
37.70
37.71 - private void readValue(DataInputStream dis, ClassData cd, String typeName, String attrName)
37.72 - throws IOException {
37.73 + private void readValue(
37.74 + DataInputStream dis, ClassData cd, String typeName, String attrName
37.75 + ) throws IOException {
37.76 char type = (char)dis.readByte();
37.77 + visitValueStart(attrName, type);
37.78 if (type == '@') {
37.79 - readAnno(dis, cd);
37.80 + readAnno(dis, cd, false);
37.81 } else if ("CFJZsSIDB".indexOf(type) >= 0) { // NOI18N
37.82 int primitive = dis.readUnsignedShort();
37.83 String val = cd.stringValue(primitive, textual);
37.84 @@ -112,13 +129,17 @@
37.85 } else if (type == '[') {
37.86 int cnt = dis.readUnsignedShort();
37.87 for (int i = 0; i < cnt; i++) {
37.88 - readValue(dis, cd, typeName, attrName);
37.89 + readValue(dis, cd, typeName, iterateArray ? attrName : null);
37.90 }
37.91 } else if (type == 'e') {
37.92 int enumT = dis.readUnsignedShort();
37.93 + String attrType = cd.stringValue(enumT, textual);
37.94 int enumN = dis.readUnsignedShort();
37.95 + String val = cd.stringValue(enumN, textual);
37.96 + visitEnumAttr(typeName, attrName, attrType, val);
37.97 } else {
37.98 throw new IOException("Unknown type " + type);
37.99 }
37.100 + visitValueEnd(attrName, type);
37.101 }
37.102 }
38.1 --- a/javaquery/api/pom.xml Fri Feb 15 11:54:45 2013 +0100
38.2 +++ b/javaquery/api/pom.xml Fri Feb 15 21:16:05 2013 +0100
38.3 @@ -47,21 +47,16 @@
38.4 </dependency>
38.5 <dependency>
38.6 <groupId>org.apidesign.bck2brwsr</groupId>
38.7 - <artifactId>core</artifactId>
38.8 - <version>0.3-SNAPSHOT</version>
38.9 + <artifactId>emul</artifactId>
38.10 + <version>${project.version}</version>
38.11 + <classifier>rt</classifier>
38.12 <type>jar</type>
38.13 - </dependency>
38.14 - <dependency>
38.15 - <groupId>org.apidesign.bck2brwsr</groupId>
38.16 - <artifactId>emul.mini</artifactId>
38.17 - <version>0.3-SNAPSHOT</version>
38.18 - <type>jar</type>
38.19 - <scope>runtime</scope>
38.20 + <scope>compile</scope>
38.21 </dependency>
38.22 <dependency>
38.23 <groupId>org.apidesign.bck2brwsr</groupId>
38.24 <artifactId>vm4brwsr</artifactId>
38.25 - <version>0.3-SNAPSHOT</version>
38.26 + <version>${project.version}</version>
38.27 <type>jar</type>
38.28 <scope>test</scope>
38.29 </dependency>
39.1 --- a/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ProcessPageTest.java Fri Feb 15 11:54:45 2013 +0100
39.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ProcessPageTest.java Fri Feb 15 21:16:05 2013 +0100
39.3 @@ -128,6 +128,8 @@
39.4 sb = new StringBuilder();
39.5 }
39.6 Bck2Brwsr.generate(sb, ProcessPageTest.class.getClassLoader(), names);
39.7 + sb.append("var vm = this.bck2brwsr();\n");
39.8 +
39.9 ScriptEngineManager sem = new ScriptEngineManager();
39.10 ScriptEngine js = sem.getEngineByExtension("js");
39.11 try {
40.1 --- a/javaquery/demo-calculator-dynamic/pom.xml Fri Feb 15 11:54:45 2013 +0100
40.2 +++ b/javaquery/demo-calculator-dynamic/pom.xml Fri Feb 15 21:16:05 2013 +0100
40.3 @@ -40,22 +40,54 @@
40.4 <target>1.7</target>
40.5 </configuration>
40.6 </plugin>
40.7 - <plugin>
40.8 + <plugin>
40.9 + <groupId>org.apache.maven.plugins</groupId>
40.10 + <artifactId>maven-jar-plugin</artifactId>
40.11 + <version>2.4</version>
40.12 + <configuration>
40.13 + <archive>
40.14 + <manifest>
40.15 + <addClasspath>true</addClasspath>
40.16 + <classpathPrefix>lib/</classpathPrefix>
40.17 + </manifest>
40.18 + </archive>
40.19 + </configuration>
40.20 + </plugin>
40.21 + <plugin>
40.22 <groupId>org.apache.maven.plugins</groupId>
40.23 <artifactId>maven-deploy-plugin</artifactId>
40.24 <version>2.7</version>
40.25 <configuration>
40.26 <skip>true</skip>
40.27 </configuration>
40.28 - </plugin>
40.29 + </plugin>
40.30 + <plugin>
40.31 + <artifactId>maven-assembly-plugin</artifactId>
40.32 + <version>2.4</version>
40.33 + <executions>
40.34 + <execution>
40.35 + <id>distro-assembly</id>
40.36 + <phase>package</phase>
40.37 + <goals>
40.38 + <goal>single</goal>
40.39 + </goals>
40.40 + <configuration>
40.41 + <descriptors>
40.42 + <descriptor>src/main/assembly/bck2brwsr.xml</descriptor>
40.43 + </descriptors>
40.44 + </configuration>
40.45 + </execution>
40.46 + </executions>
40.47 + </plugin>
40.48 </plugins>
40.49 </build>
40.50
40.51 <dependencies>
40.52 <dependency>
40.53 <groupId>org.apidesign.bck2brwsr</groupId>
40.54 - <artifactId>emul.mini</artifactId>
40.55 + <artifactId>emul</artifactId>
40.56 <version>0.3-SNAPSHOT</version>
40.57 + <classifier>rt</classifier>
40.58 </dependency>
40.59 <dependency>
40.60 <groupId>org.apidesign.bck2brwsr</groupId>
40.61 @@ -68,5 +100,13 @@
40.62 <version>6.5.2</version>
40.63 <scope>test</scope>
40.64 </dependency>
40.65 + <dependency>
40.66 + <groupId>org.apidesign.bck2brwsr</groupId>
40.67 + <artifactId>vm4brwsr</artifactId>
40.68 + <classifier>js</classifier>
40.69 + <type>zip</type>
40.70 + <version>0.3-SNAPSHOT</version>
40.71 + <scope>provided</scope>
40.72 + </dependency>
40.73 </dependencies>
40.74 </project>
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
41.2 +++ b/javaquery/demo-calculator-dynamic/src/main/assembly/bck2brwsr.xml Fri Feb 15 21:16:05 2013 +0100
41.3 @@ -0,0 +1,62 @@
41.4 +<?xml version="1.0"?>
41.5 +<!--
41.6 +
41.7 + Back 2 Browser Bytecode Translator
41.8 + Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
41.9 +
41.10 + This program is free software: you can redistribute it and/or modify
41.11 + it under the terms of the GNU General Public License as published by
41.12 + the Free Software Foundation, version 2 of the License.
41.13 +
41.14 + This program is distributed in the hope that it will be useful,
41.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of
41.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41.17 + GNU General Public License for more details.
41.18 +
41.19 + You should have received a copy of the GNU General Public License
41.20 + along with this program. Look for COPYING file in the top folder.
41.21 + If not, see http://opensource.org/licenses/GPL-2.0.
41.22 +
41.23 +-->
41.24 +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
41.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">
41.26 +
41.27 + <id>bck2brwsr</id>
41.28 + <formats>
41.29 + <format>zip</format>
41.30 + <format>dir</format>
41.31 + </formats>
41.32 + <baseDirectory>public_html</baseDirectory>
41.33 + <dependencySets>
41.34 + <dependencySet>
41.35 + <useProjectArtifact>false</useProjectArtifact>
41.36 + <scope>runtime</scope>
41.37 + <outputDirectory>lib</outputDirectory>
41.38 + <includes>
41.39 + <include>*:jar</include>
41.40 + <include>*:rt</include>
41.41 + </includes>
41.42 + </dependencySet>
41.43 + <dependencySet>
41.44 + <useProjectArtifact>false</useProjectArtifact>
41.45 + <scope>provided</scope>
41.46 + <includes>
41.47 + <include>*:js</include>
41.48 + </includes>
41.49 + <unpack>true</unpack>
41.50 + <outputDirectory>/</outputDirectory>
41.51 + </dependencySet>
41.52 + </dependencySets>
41.53 + <files>
41.54 + <file>
41.55 + <source>${project.build.directory}/${project.build.finalName}.jar</source>
41.56 + <outputDirectory>/</outputDirectory>
41.57 + </file>
41.58 + <file>
41.59 + <source>${project.build.directory}/classes/org/apidesign/bck2brwsr/demo/calc/Calculator.xhtml</source>
41.60 + <outputDirectory>/</outputDirectory>
41.61 + <destName>index.xhtml</destName>
41.62 + </file>
41.63 + </files>
41.64 +
41.65 +</assembly>
41.66 \ No newline at end of file
42.1 --- a/javaquery/demo-calculator-dynamic/src/main/resources/org/apidesign/bck2brwsr/demo/calc/Calculator.xhtml Fri Feb 15 11:54:45 2013 +0100
42.2 +++ b/javaquery/demo-calculator-dynamic/src/main/resources/org/apidesign/bck2brwsr/demo/calc/Calculator.xhtml Fri Feb 15 21:16:05 2013 +0100
42.3 @@ -78,9 +78,9 @@
42.4 </table>
42.5 <div data-bind="text: displayPreview"></div>
42.6
42.7 - <script src="/bck2brwsr.js"></script>
42.8 - <script src="/vm.js"></script>
42.9 + <script src="bck2brwsr.js"></script>
42.10 <script type="text/javascript">
42.11 + var vm = bck2brwsr('demo.calculator-0.3-SNAPSHOT.jar');
42.12 vm.loadClass('org.apidesign.bck2brwsr.demo.calc.Calc');
42.13 </script>
42.14
43.1 --- a/javaquery/demo-calculator/nbactions.xml Fri Feb 15 11:54:45 2013 +0100
43.2 +++ b/javaquery/demo-calculator/nbactions.xml Fri Feb 15 21:16:05 2013 +0100
43.3 @@ -22,8 +22,11 @@
43.4 <action>
43.5 <actionName>run</actionName>
43.6 <goals>
43.7 - <goal>process-classes</goal>
43.8 + <goal>package</goal>
43.9 <goal>org.apidesign.bck2brwsr:mojo:0.3-SNAPSHOT:brwsr</goal>
43.10 </goals>
43.11 + <properties>
43.12 + <skipTests>true</skipTests>
43.13 + </properties>
43.14 </action>
43.15 - </actions>
43.16 +</actions>
44.1 --- a/javaquery/demo-calculator/pom.xml Fri Feb 15 11:54:45 2013 +0100
44.2 +++ b/javaquery/demo-calculator/pom.xml Fri Feb 15 21:16:05 2013 +0100
44.3 @@ -23,7 +23,6 @@
44.4 <executions>
44.5 <execution>
44.6 <goals>
44.7 - <goal>j2js</goal>
44.8 <goal>brwsr</goal>
44.9 </goals>
44.10 </execution>
44.11 @@ -43,6 +42,19 @@
44.12 </configuration>
44.13 </plugin>
44.14 <plugin>
44.15 + <groupId>org.apache.maven.plugins</groupId>
44.16 + <artifactId>maven-jar-plugin</artifactId>
44.17 + <version>2.4</version>
44.18 + <configuration>
44.19 + <archive>
44.20 + <manifest>
44.21 + <addClasspath>true</addClasspath>
44.22 + <classpathPrefix>lib/</classpathPrefix>
44.23 + </manifest>
44.24 + </archive>
44.25 + </configuration>
44.26 + </plugin>
44.27 + <plugin>
44.28 <artifactId>maven-assembly-plugin</artifactId>
44.29 <version>2.4</version>
44.30 <executions>
44.31 @@ -74,13 +86,22 @@
44.32 <dependencies>
44.33 <dependency>
44.34 <groupId>org.apidesign.bck2brwsr</groupId>
44.35 - <artifactId>emul.mini</artifactId>
44.36 + <artifactId>emul</artifactId>
44.37 <version>0.3-SNAPSHOT</version>
44.38 + <classifier>rt</classifier>
44.39 </dependency>
44.40 <dependency>
44.41 <groupId>org.apidesign.bck2brwsr</groupId>
44.42 <artifactId>javaquery.api</artifactId>
44.43 <version>0.3-SNAPSHOT</version>
44.44 </dependency>
44.45 + <dependency>
44.46 + <groupId>org.apidesign.bck2brwsr</groupId>
44.47 + <artifactId>vm4brwsr</artifactId>
44.48 + <classifier>js</classifier>
44.49 + <type>zip</type>
44.50 + <version>0.3-SNAPSHOT</version>
44.51 + <scope>provided</scope>
44.52 + </dependency>
44.53 </dependencies>
44.54 </project>
45.1 --- a/javaquery/demo-calculator/src/main/assembly/bck2brwsr.xml Fri Feb 15 11:54:45 2013 +0100
45.2 +++ b/javaquery/demo-calculator/src/main/assembly/bck2brwsr.xml Fri Feb 15 21:16:05 2013 +0100
45.3 @@ -32,6 +32,19 @@
45.4 <useProjectArtifact>false</useProjectArtifact>
45.5 <scope>runtime</scope>
45.6 <outputDirectory>lib</outputDirectory>
45.7 + <includes>
45.8 + <include>*:jar</include>
45.9 + <include>*:rt</include>
45.10 + </includes>
45.11 + </dependencySet>
45.12 + <dependencySet>
45.13 + <useProjectArtifact>false</useProjectArtifact>
45.14 + <scope>provided</scope>
45.15 + <includes>
45.16 + <include>*:js</include>
45.17 + </includes>
45.18 + <unpack>true</unpack>
45.19 + <outputDirectory>/</outputDirectory>
45.20 </dependencySet>
45.21 </dependencySets>
45.22 <files>
45.23 @@ -44,11 +57,6 @@
45.24 <outputDirectory>/</outputDirectory>
45.25 <destName>index.xhtml</destName>
45.26 </file>
45.27 - <file>
45.28 - <source>${project.build.directory}/classes/org/apidesign/bck2brwsr/demo/calc/staticcompilation/bootjava.js</source>
45.29 - <outputDirectory>/</outputDirectory>
45.30 - <destName>bck2brwsr.js</destName>
45.31 - </file>
45.32 </files>
45.33
45.34 </assembly>
45.35 \ No newline at end of file
46.1 --- a/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml Fri Feb 15 11:54:45 2013 +0100
46.2 +++ b/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml Fri Feb 15 21:16:05 2013 +0100
46.3 @@ -78,5 +78,9 @@
46.4 </table>
46.5 <div data-bind="text: displayPreview"></div>
46.6 <script src="bck2brwsr.js"/>
46.7 + <script>
46.8 + var vm = bck2brwsr('demo.static.calculator-0.3-SNAPSHOT.jar');
46.9 + vm.loadClass('org.apidesign.bck2brwsr.demo.calc.staticcompilation.Calc');
46.10 + </script>
46.11 </body>
46.12 </html>
47.1 --- a/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java Fri Feb 15 11:54:45 2013 +0100
47.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java Fri Feb 15 21:16:05 2013 +0100
47.3 @@ -39,6 +39,7 @@
47.4 import java.util.concurrent.TimeUnit;
47.5 import java.util.logging.Level;
47.6 import java.util.logging.Logger;
47.7 +import org.apidesign.bck2brwsr.launcher.InvocationContext.Resource;
47.8 import org.apidesign.vm4brwsr.Bck2Brwsr;
47.9 import org.glassfish.grizzly.PortRange;
47.10 import org.glassfish.grizzly.http.server.HttpHandler;
47.11 @@ -47,6 +48,7 @@
47.12 import org.glassfish.grizzly.http.server.Request;
47.13 import org.glassfish.grizzly.http.server.Response;
47.14 import org.glassfish.grizzly.http.server.ServerConfiguration;
47.15 +import org.glassfish.grizzly.http.util.HttpStatus;
47.16
47.17 /**
47.18 * Lightweight server to launch Bck2Brwsr applications and tests.
47.19 @@ -94,9 +96,12 @@
47.20 startpage = "/" + startpage;
47.21 }
47.22 HttpServer s = initServer(".", true);
47.23 + int last = startpage.lastIndexOf('/');
47.24 + String simpleName = startpage.substring(last);
47.25 + s.getServerConfiguration().addHttpHandler(new Page(resources, startpage), simpleName);
47.26 s.getServerConfiguration().addHttpHandler(new Page(resources, null), "/");
47.27 try {
47.28 - launchServerAndBrwsr(s, startpage);
47.29 + launchServerAndBrwsr(s, simpleName);
47.30 } catch (URISyntaxException | InterruptedException ex) {
47.31 throw new IOException(ex);
47.32 }
47.33 @@ -138,7 +143,7 @@
47.34
47.35 final ServerConfiguration conf = s.getServerConfiguration();
47.36 if (addClasses) {
47.37 - conf.addHttpHandler(new VM(resources), "/vm.js");
47.38 + conf.addHttpHandler(new VM(resources), "/bck2brwsr.js");
47.39 conf.addHttpHandler(new Classes(resources), "/classes/");
47.40 }
47.41 return s;
47.42 @@ -152,11 +157,13 @@
47.43 class DynamicResourceHandler extends HttpHandler {
47.44 private final InvocationContext ic;
47.45 public DynamicResourceHandler(InvocationContext ic) {
47.46 - if (ic == null || ic.httpPath == null) {
47.47 + if (ic == null || ic.resources.isEmpty()) {
47.48 throw new NullPointerException();
47.49 }
47.50 this.ic = ic;
47.51 - conf.addHttpHandler(this, ic.httpPath);
47.52 + for (Resource r : ic.resources) {
47.53 + conf.addHttpHandler(this, r.httpPath);
47.54 + }
47.55 }
47.56
47.57 public void close() {
47.58 @@ -165,10 +172,12 @@
47.59
47.60 @Override
47.61 public void service(Request request, Response response) throws Exception {
47.62 - if (ic.httpPath.equals(request.getRequestURI())) {
47.63 - LOG.log(Level.INFO, "Serving HttpResource for {0}", request.getRequestURI());
47.64 - response.setContentType(ic.httpType);
47.65 - copyStream(ic.httpContent, response.getOutputStream(), null);
47.66 + for (Resource r : ic.resources) {
47.67 + if (r.httpPath.equals(request.getRequestURI())) {
47.68 + LOG.log(Level.INFO, "Serving HttpResource for {0}", request.getRequestURI());
47.69 + response.setContentType(r.httpType);
47.70 + copyStream(r.httpContent, response.getOutputStream(), null);
47.71 + }
47.72 }
47.73 }
47.74 }
47.75 @@ -186,10 +195,26 @@
47.76 String id = request.getParameter("request");
47.77 String value = request.getParameter("result");
47.78
47.79 +
47.80 + InvocationContext mi = null;
47.81 + int caseNmbr = -1;
47.82 +
47.83 if (id != null && value != null) {
47.84 LOG.log(Level.INFO, "Received result for case {0} = {1}", new Object[]{id, value});
47.85 value = decodeURL(value);
47.86 - cases.get(Integer.parseInt(id)).result(value, null);
47.87 + int indx = Integer.parseInt(id);
47.88 + cases.get(indx).result(value, null);
47.89 + if (++indx < cases.size()) {
47.90 + mi = cases.get(indx);
47.91 + LOG.log(Level.INFO, "Re-executing case {0}", indx);
47.92 + caseNmbr = indx;
47.93 + }
47.94 + } else {
47.95 + if (!cases.isEmpty()) {
47.96 + LOG.info("Re-executing test cases");
47.97 + mi = cases.get(0);
47.98 + caseNmbr = 0;
47.99 + }
47.100 }
47.101
47.102 if (prev != null) {
47.103 @@ -197,7 +222,10 @@
47.104 prev = null;
47.105 }
47.106
47.107 - InvocationContext mi = methods.take();
47.108 + if (mi == null) {
47.109 + mi = methods.take();
47.110 + caseNmbr = cnt++;
47.111 + }
47.112 if (mi == END) {
47.113 response.getWriter().write("");
47.114 wait.countDown();
47.115 @@ -206,18 +234,18 @@
47.116 return;
47.117 }
47.118
47.119 - if (mi.httpPath != null) {
47.120 + if (!mi.resources.isEmpty()) {
47.121 prev = new DynamicResourceHandler(mi);
47.122 }
47.123
47.124 cases.add(mi);
47.125 final String cn = mi.clazz.getName();
47.126 final String mn = mi.methodName;
47.127 - LOG.log(Level.INFO, "Request for {0} case. Sending {1}.{2}", new Object[]{cnt, cn, mn});
47.128 + LOG.log(Level.INFO, "Request for {0} case. Sending {1}.{2}", new Object[]{caseNmbr, cn, mn});
47.129 response.getWriter().write("{"
47.130 + "className: '" + cn + "', "
47.131 + "methodName: '" + mn + "', "
47.132 - + "request: " + cnt
47.133 + + "request: " + caseNmbr
47.134 );
47.135 if (mi.html != null) {
47.136 response.getWriter().write(", html: '");
47.137 @@ -225,7 +253,6 @@
47.138 response.getWriter().write("'");
47.139 }
47.140 response.getWriter().write("}");
47.141 - cnt++;
47.142 }
47.143 }, "/data");
47.144
47.145 @@ -427,9 +454,9 @@
47.146 String r = resource;
47.147 if (r == null) {
47.148 r = request.getHttpHandlerPath();
47.149 - if (r.startsWith("/")) {
47.150 - r = r.substring(1);
47.151 - }
47.152 + }
47.153 + if (r.startsWith("/")) {
47.154 + r = r.substring(1);
47.155 }
47.156 String[] replace = {};
47.157 if (r.endsWith(".html")) {
47.158 @@ -460,14 +487,22 @@
47.159 StringBuilder sb = new StringBuilder();
47.160 Bck2Brwsr.generate(sb, loader);
47.161 sb.append(
47.162 - "function ldCls(res) {\n"
47.163 - + " var request = new XMLHttpRequest();\n"
47.164 - + " request.open('GET', '/classes/' + res, false);\n"
47.165 - + " request.send();\n"
47.166 - + " var arr = eval('(' + request.responseText + ')');\n"
47.167 - + " return arr;\n"
47.168 - + "}\n"
47.169 - + "var vm = new bck2brwsr(ldCls);\n"
47.170 + "(function WrapperVM(global) {"
47.171 + + " function ldCls(res) {\n"
47.172 + + " var request = new XMLHttpRequest();\n"
47.173 + + " request.open('GET', '/classes/' + res, false);\n"
47.174 + + " request.send();\n"
47.175 + + " if (request.status !== 200) return null;\n"
47.176 + + " var arr = eval('(' + request.responseText + ')');\n"
47.177 + + " return arr;\n"
47.178 + + " }\n"
47.179 + + " var prevvm = global.bck2brwsr;\n"
47.180 + + " global.bck2brwsr = function() {\n"
47.181 + + " var args = Array.prototype.slice.apply(arguments);\n"
47.182 + + " args.unshift(ldCls);\n"
47.183 + + " return prevvm.apply(null, args);\n"
47.184 + + " };\n"
47.185 + + "})(this);\n"
47.186 );
47.187 this.bck2brwsr = sb.toString();
47.188 }
47.189 @@ -515,6 +550,7 @@
47.190 }
47.191 w.append("\n]");
47.192 } catch (IOException ex) {
47.193 + response.setStatus(HttpStatus.NOT_FOUND_404);
47.194 response.setError();
47.195 response.setDetailMessage(ex.getMessage());
47.196 }
48.1 --- a/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/InvocationContext.java Fri Feb 15 11:54:45 2013 +0100
48.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/InvocationContext.java Fri Feb 15 21:16:05 2013 +0100
48.3 @@ -19,6 +19,8 @@
48.4
48.5 import java.io.IOException;
48.6 import java.io.InputStream;
48.7 +import java.util.ArrayList;
48.8 +import java.util.List;
48.9 import java.util.concurrent.CountDownLatch;
48.10 import java.util.concurrent.TimeUnit;
48.11
48.12 @@ -34,9 +36,7 @@
48.13 private String result;
48.14 private Throwable exception;
48.15 String html;
48.16 - InputStream httpContent;
48.17 - String httpType;
48.18 - String httpPath;
48.19 + final List<Resource> resources = new ArrayList<>();
48.20
48.21 InvocationContext(Launcher launcher, Class<?> clazz, String methodName) {
48.22 this.launcher = launcher;
48.23 @@ -55,13 +55,11 @@
48.24 /** HTTP resource to be available during execution. An invocation may
48.25 * perform an HTTP query and obtain a resource relative to the page.
48.26 */
48.27 - public void setHttpResource(String relativePath, String mimeType, InputStream content) {
48.28 + public void addHttpResource(String relativePath, String mimeType, InputStream content) {
48.29 if (relativePath == null || mimeType == null || content == null) {
48.30 throw new NullPointerException();
48.31 }
48.32 - this.httpPath = relativePath;
48.33 - this.httpType = mimeType;
48.34 - this.httpContent = content;
48.35 + resources.add(new Resource(content, mimeType, relativePath));
48.36 }
48.37
48.38 /** Invokes the associated method.
48.39 @@ -97,5 +95,16 @@
48.40 wait.countDown();
48.41 }
48.42
48.43 -
48.44 +
48.45 + static final class Resource {
48.46 + final InputStream httpContent;
48.47 + final String httpType;
48.48 + final String httpPath;
48.49 +
48.50 + Resource(InputStream httpContent, String httpType, String httpPath) {
48.51 + this.httpContent = httpContent;
48.52 + this.httpType = httpType;
48.53 + this.httpPath = httpPath;
48.54 + }
48.55 + }
48.56 }
49.1 --- a/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/impl/Console.java Fri Feb 15 11:54:45 2013 +0100
49.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/impl/Console.java Fri Feb 15 21:16:05 2013 +0100
49.3 @@ -125,7 +125,7 @@
49.4 loadText(u, this, arr);
49.5
49.6 } catch (Exception ex) {
49.7 - log(ex.getMessage());
49.8 + log(ex.getClass().getName() + ":" + ex.getMessage());
49.9 }
49.10 }
49.11 }
50.1 --- a/launcher/src/main/resources/org/apidesign/bck2brwsr/launcher/harness.xhtml Fri Feb 15 11:54:45 2013 +0100
50.2 +++ b/launcher/src/main/resources/org/apidesign/bck2brwsr/launcher/harness.xhtml Fri Feb 15 21:16:05 2013 +0100
50.3 @@ -24,7 +24,10 @@
50.4 <title>Bck2Brwsr Harness</title>
50.5 </head>
50.6 <body>
50.7 - <script src="/vm.js"></script>
50.8 + <script src="/bck2brwsr.js"></script>
50.9 + <script>
50.10 + var vm = bck2brwsr();
50.11 + </script>
50.12
50.13 <h1>Bck2Brwsr Execution Harness</h1>
50.14
51.1 --- a/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Bck2BrswrMojo.java Fri Feb 15 11:54:45 2013 +0100
51.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
51.3 @@ -1,122 +0,0 @@
51.4 -/**
51.5 - * Back 2 Browser Bytecode Translator
51.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
51.7 - *
51.8 - * This program is free software: you can redistribute it and/or modify
51.9 - * it under the terms of the GNU General Public License as published by
51.10 - * the Free Software Foundation, version 2 of the License.
51.11 - *
51.12 - * This program is distributed in the hope that it will be useful,
51.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
51.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
51.15 - * GNU General Public License for more details.
51.16 - *
51.17 - * You should have received a copy of the GNU General Public License
51.18 - * along with this program. Look for COPYING file in the top folder.
51.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
51.20 - */
51.21 -package org.apidesign.bck2brwsr.mojo;
51.22 -
51.23 -import org.apache.maven.plugin.AbstractMojo;
51.24 -
51.25 -import java.io.File;
51.26 -import java.io.FileWriter;
51.27 -import java.io.IOException;
51.28 -import java.net.MalformedURLException;
51.29 -import java.net.URL;
51.30 -import java.net.URLClassLoader;
51.31 -import java.util.ArrayList;
51.32 -import java.util.Collection;
51.33 -import java.util.List;
51.34 -import org.apache.maven.artifact.Artifact;
51.35 -import org.apache.maven.plugin.MojoExecutionException;
51.36 -import org.apache.maven.plugins.annotations.LifecyclePhase;
51.37 -import org.apache.maven.plugins.annotations.Mojo;
51.38 -import org.apache.maven.plugins.annotations.Parameter;
51.39 -import org.apache.maven.project.MavenProject;
51.40 -import org.apidesign.vm4brwsr.Bck2Brwsr;
51.41 -
51.42 -/** Compiles classes into JavaScript. */
51.43 -@Mojo(name="j2js", defaultPhase=LifecyclePhase.PROCESS_CLASSES)
51.44 -public class Bck2BrswrMojo extends AbstractMojo {
51.45 - public Bck2BrswrMojo() {
51.46 - }
51.47 - /** Root of the class files */
51.48 - @Parameter(defaultValue="${project.build.directory}/classes")
51.49 - private File classes;
51.50 - /** File to generate. Defaults bootjava.js in the first non-empty
51.51 - package under the classes directory */
51.52 - @Parameter
51.53 - private File javascript;
51.54 -
51.55 - @Parameter(defaultValue="${project}")
51.56 - private MavenProject prj;
51.57 -
51.58 -
51.59 -
51.60 - @Override
51.61 - public void execute() throws MojoExecutionException {
51.62 - if (!classes.isDirectory()) {
51.63 - throw new MojoExecutionException("Can't find " + classes);
51.64 - }
51.65 -
51.66 - if (javascript == null) {
51.67 - javascript = new File(findNonEmptyFolder(classes), "bootjava.js");
51.68 - }
51.69 -
51.70 - List<String> arr = new ArrayList<String>();
51.71 - long newest = collectAllClasses("", classes, arr);
51.72 -
51.73 - if (javascript.lastModified() > newest) {
51.74 - return;
51.75 - }
51.76 -
51.77 - try {
51.78 - URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts());
51.79 - FileWriter w = new FileWriter(javascript);
51.80 - Bck2Brwsr.generate(w, url, arr.toArray(new String[0]));
51.81 - w.close();
51.82 - } catch (IOException ex) {
51.83 - throw new MojoExecutionException("Can't compile", ex);
51.84 - }
51.85 - }
51.86 -
51.87 - private static File findNonEmptyFolder(File dir) throws MojoExecutionException {
51.88 - if (!dir.isDirectory()) {
51.89 - throw new MojoExecutionException("Not a directory " + dir);
51.90 - }
51.91 - File[] arr = dir.listFiles();
51.92 - if (arr.length == 1 && arr[0].isDirectory()) {
51.93 - return findNonEmptyFolder(arr[0]);
51.94 - }
51.95 - return dir;
51.96 - }
51.97 -
51.98 - private static long collectAllClasses(String prefix, File toCheck, List<String> arr) {
51.99 - File[] files = toCheck.listFiles();
51.100 - if (files != null) {
51.101 - long newest = 0L;
51.102 - for (File f : files) {
51.103 - long lastModified = collectAllClasses(prefix + f.getName() + "/", f, arr);
51.104 - if (newest < lastModified) {
51.105 - newest = lastModified;
51.106 - }
51.107 - }
51.108 - return newest;
51.109 - } else if (toCheck.getName().endsWith(".class")) {
51.110 - arr.add(prefix.substring(0, prefix.length() - 7));
51.111 - return toCheck.lastModified();
51.112 - } else {
51.113 - return 0L;
51.114 - }
51.115 - }
51.116 -
51.117 - private static URLClassLoader buildClassLoader(File root, Collection<Artifact> deps) throws MalformedURLException {
51.118 - List<URL> arr = new ArrayList<URL>();
51.119 - arr.add(root.toURI().toURL());
51.120 - for (Artifact a : deps) {
51.121 - arr.add(a.getFile().toURI().toURL());
51.122 - }
51.123 - return new URLClassLoader(arr.toArray(new URL[0]), Bck2BrswrMojo.class.getClassLoader());
51.124 - }
51.125 -}
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
52.2 +++ b/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Java2JavaScript.java Fri Feb 15 21:16:05 2013 +0100
52.3 @@ -0,0 +1,122 @@
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 Java2JavaScript extends AbstractMojo {
52.45 + public Java2JavaScript() {
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]), Java2JavaScript.class.getClassLoader());
52.124 + }
52.125 +}
53.1 --- a/mojo/src/main/resources/META-INF/maven/archetype-metadata.xml Fri Feb 15 11:54:45 2013 +0100
53.2 +++ b/mojo/src/main/resources/META-INF/maven/archetype-metadata.xml Fri Feb 15 21:16:05 2013 +0100
53.3 @@ -30,6 +30,7 @@
53.4 <directory>src/main/resources</directory>
53.5 <includes>
53.6 <include>**/*.xhtml</include>
53.7 + <include>**/*.html</include>
53.8 </includes>
53.9 </fileSet>
53.10 <fileSet filtered="true" packaged="true">
53.11 @@ -44,5 +45,11 @@
53.12 <include>nbactions.xml</include>
53.13 </includes>
53.14 </fileSet>
53.15 + <fileSet filtered="true" packaged="false">
53.16 + <directory></directory>
53.17 + <includes>
53.18 + <include>bck2brwsr-assembly.xml</include>
53.19 + </includes>
53.20 + </fileSet>
53.21 </fileSets>
53.22 </archetype-descriptor>
53.23 \ No newline at end of file
54.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
54.2 +++ b/mojo/src/main/resources/archetype-resources/bck2brwsr-assembly.xml Fri Feb 15 21:16:05 2013 +0100
54.3 @@ -0,0 +1,61 @@
54.4 +<?xml version="1.0"?>
54.5 +<!--
54.6 +
54.7 + Back 2 Browser Bytecode Translator
54.8 + Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
54.9 +
54.10 + This program is free software: you can redistribute it and/or modify
54.11 + it under the terms of the GNU General Public License as published by
54.12 + the Free Software Foundation, version 2 of the License.
54.13 +
54.14 + This program is distributed in the hope that it will be useful,
54.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of
54.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
54.17 + GNU General Public License for more details.
54.18 +
54.19 + You should have received a copy of the GNU General Public License
54.20 + along with this program. Look for COPYING file in the top folder.
54.21 + If not, see http://opensource.org/licenses/GPL-2.0.
54.22 +
54.23 +-->
54.24 +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
54.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">
54.26 +
54.27 + <id>bck2brwsr</id>
54.28 + <formats>
54.29 + <format>zip</format>
54.30 + </formats>
54.31 + <baseDirectory>public_html</baseDirectory>
54.32 + <dependencySets>
54.33 + <dependencySet>
54.34 + <useProjectArtifact>false</useProjectArtifact>
54.35 + <scope>runtime</scope>
54.36 + <outputDirectory>lib</outputDirectory>
54.37 + <includes>
54.38 + <include>*:jar</include>
54.39 + <include>*:rt</include>
54.40 + </includes>
54.41 + </dependencySet>
54.42 + <dependencySet>
54.43 + <useProjectArtifact>false</useProjectArtifact>
54.44 + <scope>provided</scope>
54.45 + <includes>
54.46 + <include>*:js</include>
54.47 + </includes>
54.48 + <unpack>true</unpack>
54.49 + <outputDirectory>/</outputDirectory>
54.50 + </dependencySet>
54.51 + </dependencySets>
54.52 + <files>
54.53 + <file>
54.54 + <source>${project.build.directory}/${project.build.finalName}.jar</source>
54.55 + <outputDirectory>/</outputDirectory>
54.56 + </file>
54.57 + <file>
54.58 + <source>${project.build.directory}/classes/${package.replace('.','/')}/index.html</source>
54.59 + <outputDirectory>/</outputDirectory>
54.60 + <destName>index.html</destName>
54.61 + </file>
54.62 + </files>
54.63 +
54.64 +</assembly>
54.65 \ No newline at end of file
55.1 --- a/mojo/src/main/resources/archetype-resources/pom.xml Fri Feb 15 11:54:45 2013 +0100
55.2 +++ b/mojo/src/main/resources/archetype-resources/pom.xml Fri Feb 15 21:16:05 2013 +0100
55.3 @@ -53,7 +53,7 @@
55.4 </execution>
55.5 </executions>
55.6 <configuration>
55.7 - <startpage>${package.replace('.','/')}/index.xhtml</startpage>
55.8 + <startpage>${package.replace('.','/')}/index.html</startpage>
55.9 </configuration>
55.10 </plugin>
55.11 <plugin>
55.12 @@ -65,14 +65,46 @@
55.13 <target>1.7</target>
55.14 </configuration>
55.15 </plugin>
55.16 + <plugin>
55.17 + <groupId>org.apache.maven.plugins</groupId>
55.18 + <artifactId>maven-jar-plugin</artifactId>
55.19 + <version>2.4</version>
55.20 + <configuration>
55.21 + <archive>
55.22 + <manifest>
55.23 + <addClasspath>true</addClasspath>
55.24 + <classpathPrefix>lib/</classpathPrefix>
55.25 + </manifest>
55.26 + </archive>
55.27 + </configuration>
55.28 + </plugin>
55.29 + <plugin>
55.30 + <artifactId>maven-assembly-plugin</artifactId>
55.31 + <version>2.4</version>
55.32 + <executions>
55.33 + <execution>
55.34 + <id>distro-assembly</id>
55.35 + <phase>package</phase>
55.36 + <goals>
55.37 + <goal>single</goal>
55.38 + </goals>
55.39 + <configuration>
55.40 + <descriptors>
55.41 + <descriptor>bck2brwsr-assembly.xml</descriptor>
55.42 + </descriptors>
55.43 + </configuration>
55.44 + </execution>
55.45 + </executions>
55.46 + </plugin>
55.47 </plugins>
55.48 </build>
55.49
55.50 <dependencies>
55.51 <dependency>
55.52 <groupId>org.apidesign.bck2brwsr</groupId>
55.53 - <artifactId>emul.mini</artifactId>
55.54 + <artifactId>emul</artifactId>
55.55 <version>0.3-SNAPSHOT</version>
55.56 + <classifier>rt</classifier>
55.57 </dependency>
55.58 <dependency>
55.59 <groupId>org.apidesign.bck2brwsr</groupId>
55.60 @@ -87,6 +119,14 @@
55.61 </dependency>
55.62 <dependency>
55.63 <groupId>org.apidesign.bck2brwsr</groupId>
55.64 + <artifactId>vm4brwsr</artifactId>
55.65 + <classifier>js</classifier>
55.66 + <type>zip</type>
55.67 + <version>0.3-SNAPSHOT</version>
55.68 + <scope>provided</scope>
55.69 + </dependency>
55.70 + <dependency>
55.71 + <groupId>org.apidesign.bck2brwsr</groupId>
55.72 <artifactId>vmtest</artifactId>
55.73 <version>0.3-SNAPSHOT</version>
55.74 <scope>test</scope>
56.1 --- a/mojo/src/main/resources/archetype-resources/src/main/java/App.java Fri Feb 15 11:54:45 2013 +0100
56.2 +++ b/mojo/src/main/resources/archetype-resources/src/main/java/App.java Fri Feb 15 21:16:05 2013 +0100
56.3 @@ -9,7 +9,7 @@
56.4 /** Edit the index.xhtml file. Use 'id' to name certain HTML elements.
56.5 * Use this class to define behavior of the elements.
56.6 */
56.7 -@Page(xhtml="index.xhtml", className="Index", properties={
56.8 +@Page(xhtml="index.html", className="Index", properties={
56.9 @Property(name="name", type=String.class)
56.10 })
56.11 public class App {
57.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
57.2 +++ b/mojo/src/main/resources/archetype-resources/src/main/resources/index.html Fri Feb 15 21:16:05 2013 +0100
57.3 @@ -0,0 +1,22 @@
57.4 +<?xml version="1.0" encoding="UTF-8"?>
57.5 +<!DOCTYPE html>
57.6 +<html xmlns="http://www.w3.org/1999/xhtml">
57.7 + <head>
57.8 + <title>Bck2Brwsr's Hello World</title>
57.9 + </head>
57.10 + <body>
57.11 + <h1 data-bind="text: helloMessage">Loading Bck2Brwsr's Hello World...</h1>
57.12 + Your name: <input id='input' data-bind="value: name, valueUpdate: 'afterkeydown'"></input>
57.13 + <button id="hello">Say Hello!</button>
57.14 + <p>
57.15 + <canvas id="canvas" width="300" height="50">
57.16 + </canvas>
57.17 + </p>
57.18 +
57.19 + <script src="bck2brwsr.js"></script>
57.20 + <script type="text/javascript">
57.21 + var vm = bck2brwsr('${artifactId}-${version}.jar');
57.22 + vm.loadClass('${package}.App');
57.23 + </script>
57.24 + </body>
57.25 +</html>
58.1 --- a/mojo/src/main/resources/archetype-resources/src/main/resources/index.xhtml Fri Feb 15 11:54:45 2013 +0100
58.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
58.3 @@ -1,22 +0,0 @@
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 src="/vm.js"></script>
58.21 - <script type="text/javascript">
58.22 - vm.loadClass('${package}.App');
58.23 - </script>
58.24 - </body>
58.25 -</html>
59.1 --- a/vm/pom.xml Fri Feb 15 11:54:45 2013 +0100
59.2 +++ b/vm/pom.xml Fri Feb 15 21:16:05 2013 +0100
59.3 @@ -12,7 +12,7 @@
59.4 <version>0.3-SNAPSHOT</version>
59.5 <packaging>jar</packaging>
59.6
59.7 - <name>Java VM for Browser</name>
59.8 + <name>Virtual Machine for Browser</name>
59.9 <url>http://bck2brwsr.apidesign.org</url>
59.10
59.11 <properties>
59.12 @@ -68,6 +68,45 @@
59.13 <target>1.7</target>
59.14 </configuration>
59.15 </plugin>
59.16 + <plugin>
59.17 + <groupId>org.codehaus.mojo</groupId>
59.18 + <artifactId>exec-maven-plugin</artifactId>
59.19 + <version>1.2.1</version>
59.20 + <executions>
59.21 + <execution>
59.22 + <id>generate-js</id>
59.23 + <phase>process-classes</phase>
59.24 + <goals>
59.25 + <goal>java</goal>
59.26 + </goals>
59.27 + </execution>
59.28 + </executions>
59.29 + <configuration>
59.30 + <mainClass>org.apidesign.vm4brwsr.Main</mainClass>
59.31 + <arguments>
59.32 + <argument>${project.build.directory}/bck2brwsr.js</argument>
59.33 + <argument>org/apidesign/vm4brwsr/Bck2Brwsr</argument>
59.34 + </arguments>
59.35 + </configuration>
59.36 + </plugin>
59.37 + <plugin>
59.38 + <artifactId>maven-assembly-plugin</artifactId>
59.39 + <version>2.4</version>
59.40 + <executions>
59.41 + <execution>
59.42 + <id>js</id>
59.43 + <phase>package</phase>
59.44 + <goals>
59.45 + <goal>single</goal>
59.46 + </goals>
59.47 + <configuration>
59.48 + <descriptors>
59.49 + <descriptor>src/main/assembly/bck2brwsr.xml</descriptor>
59.50 + </descriptors>
59.51 + </configuration>
59.52 + </execution>
59.53 + </executions>
59.54 + </plugin>
59.55 </plugins>
59.56 </build>
59.57 <dependencies>
59.58 @@ -85,19 +124,20 @@
59.59 <dependency>
59.60 <groupId>${project.groupId}</groupId>
59.61 <artifactId>core</artifactId>
59.62 - <version>0.3-SNAPSHOT</version>
59.63 + <version>${project.version}</version>
59.64 <type>jar</type>
59.65 </dependency>
59.66 <dependency>
59.67 <groupId>${project.groupId}</groupId>
59.68 <artifactId>emul.mini</artifactId>
59.69 - <version>0.3-SNAPSHOT</version>
59.70 - <scope>test</scope>
59.71 + <version>${project.version}</version>
59.72 + <scope>compile</scope>
59.73 </dependency>
59.74 <dependency>
59.75 <groupId>${project.groupId}</groupId>
59.76 <artifactId>javap</artifactId>
59.77 - <version>0.3-SNAPSHOT</version>
59.78 + <version>${project.version}</version>
59.79 + <scope>compile</scope>
59.80 </dependency>
59.81 </dependencies>
59.82 </project>
60.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
60.2 +++ b/vm/src/main/assembly/bck2brwsr.xml Fri Feb 15 21:16:05 2013 +0100
60.3 @@ -0,0 +1,36 @@
60.4 +<?xml version="1.0"?>
60.5 +<!--
60.6 +
60.7 + Back 2 Browser Bytecode Translator
60.8 + Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
60.9 +
60.10 + This program is free software: you can redistribute it and/or modify
60.11 + it under the terms of the GNU General Public License as published by
60.12 + the Free Software Foundation, version 2 of the License.
60.13 +
60.14 + This program is distributed in the hope that it will be useful,
60.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of
60.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
60.17 + GNU General Public License for more details.
60.18 +
60.19 + You should have received a copy of the GNU General Public License
60.20 + along with this program. Look for COPYING file in the top folder.
60.21 + If not, see http://opensource.org/licenses/GPL-2.0.
60.22 +
60.23 +-->
60.24 +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
60.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">
60.26 +
60.27 + <id>js</id>
60.28 + <formats>
60.29 + <format>zip</format>
60.30 + </formats>
60.31 + <baseDirectory>/</baseDirectory>
60.32 + <files>
60.33 + <file>
60.34 + <source>${project.build.directory}/bck2brwsr.js</source>
60.35 + <outputDirectory>/</outputDirectory>
60.36 + </file>
60.37 + </files>
60.38 +
60.39 +</assembly>
60.40 \ No newline at end of file
61.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java Fri Feb 15 11:54:45 2013 +0100
61.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java Fri Feb 15 21:16:05 2013 +0100
61.3 @@ -40,6 +40,16 @@
61.4 * In this scenario, when a request for an unknown class is made, the loader
61.5 * function is asked for its byte code and the system dynamically transforms
61.6 * it to JavaScript.
61.7 + * <p>
61.8 + * Instead of a loader function, one can also provide a URL to a JAR file.
61.9 + * The <code>bck2brwsr</code> system will do its best to download the file
61.10 + * and provide loader function for it automatically.
61.11 + * <p>
61.12 + * One can provide as many loader functions and JAR URL references as necessary.
61.13 + * Then the initialization code would look like:<pre>
61.14 + * var vm = bck2brwsr(url1, url2, fnctn1, url3, functn2);
61.15 + * </pre>
61.16 + * The provided URLs and loader functions will be consulted one by one.
61.17 *
61.18 * @author Jaroslav Tulach <jtulach@netbeans.org>
61.19 */
62.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Fri Feb 15 11:54:45 2013 +0100
62.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Fri Feb 15 21:16:05 2013 +0100
62.3 @@ -113,7 +113,7 @@
62.4 final String className = className(jc);
62.5 out.append("\n\n").append(assignClass(className));
62.6 out.append("function CLS() {");
62.7 - out.append("\n if (!CLS.prototype.$instOf_").append(className).append(") {");
62.8 + out.append("\n if (!CLS.$class) {");
62.9 if (proto == null) {
62.10 String sc = jc.getSuperClassName(); // with _
62.11 out.append("\n var pp = ").
62.12 @@ -175,12 +175,14 @@
62.13 out.append("\n };");
62.14 }
62.15 out.append(prefix).append(mn).append(".access = " + m.getAccess()).append(";");
62.16 + out.append(prefix).append(mn).append(".cls = CLS;");
62.17 }
62.18 out.append("\n c.constructor = CLS;");
62.19 out.append("\n c.$instOf_").append(className).append(" = true;");
62.20 for (String superInterface : jc.getSuperInterfaces()) {
62.21 out.append("\n c.$instOf_").append(superInterface.replace('/', '_')).append(" = true;");
62.22 }
62.23 + out.append("\n CLS.$class = 'temp';");
62.24 out.append("\n CLS.$class = ");
62.25 out.append(accessClass("java_lang_Class(true);"));
62.26 out.append("\n CLS.$class.jvmName = '").append(jc.getClassName()).append("';");
62.27 @@ -1619,7 +1621,7 @@
62.28 final String jvmType = "Lorg/apidesign/bck2brwsr/core/JavaScriptBody;";
62.29 class P extends AnnotationParser {
62.30 public P() {
62.31 - super(false);
62.32 + super(false, true);
62.33 }
62.34
62.35 int cnt;
62.36 @@ -1675,7 +1677,7 @@
62.37 final String[] values = new String[attrNames.length];
62.38 final boolean[] found = { false };
62.39 final String jvmType = "L" + className.replace('.', '/') + ";";
62.40 - AnnotationParser ap = new AnnotationParser(false) {
62.41 + AnnotationParser ap = new AnnotationParser(false, true) {
62.42 @Override
62.43 protected void visitAttr(String type, String attr, String at, String value) {
62.44 if (type.equals(jvmType)) {
62.45 @@ -1712,35 +1714,71 @@
62.46 return " = null;";
62.47 }
62.48
62.49 - private static void generateAnno(ClassData cd, final Appendable out, byte[] data) throws IOException {
62.50 - AnnotationParser ap = new AnnotationParser(true) {
62.51 - int anno;
62.52 - int cnt;
62.53 + private void generateAnno(ClassData cd, final Appendable out, byte[] data) throws IOException {
62.54 + AnnotationParser ap = new AnnotationParser(true, false) {
62.55 + int[] cnt = new int[32];
62.56 + int depth;
62.57
62.58 @Override
62.59 - protected void visitAnnotationStart(String type) throws IOException {
62.60 - if (anno++ > 0) {
62.61 + protected void visitAnnotationStart(String attrType, boolean top) throws IOException {
62.62 + final String slashType = attrType.substring(1, attrType.length() - 1);
62.63 + requireReference(slashType);
62.64 +
62.65 + if (cnt[depth]++ > 0) {
62.66 out.append(",");
62.67 }
62.68 - out.append('"').append(type).append("\" : {\n");
62.69 - cnt = 0;
62.70 + if (top) {
62.71 + out.append('"').append(attrType).append("\" : ");
62.72 + }
62.73 + out.append("{\n");
62.74 + cnt[++depth] = 0;
62.75 }
62.76
62.77 @Override
62.78 - protected void visitAnnotationEnd(String type) throws IOException {
62.79 + protected void visitAnnotationEnd(String type, boolean top) throws IOException {
62.80 out.append("\n}\n");
62.81 + depth--;
62.82 + }
62.83 +
62.84 + @Override
62.85 + protected void visitValueStart(String attrName, char type) throws IOException {
62.86 + if (cnt[depth]++ > 0) {
62.87 + out.append(",\n");
62.88 + }
62.89 + cnt[++depth] = 0;
62.90 + if (attrName != null) {
62.91 + out.append(attrName).append(" : ");
62.92 + }
62.93 + if (type == '[') {
62.94 + out.append("[");
62.95 + }
62.96 + }
62.97 +
62.98 + @Override
62.99 + protected void visitValueEnd(String attrName, char type) throws IOException {
62.100 + if (type == '[') {
62.101 + out.append("]");
62.102 + }
62.103 + depth--;
62.104 }
62.105
62.106 @Override
62.107 protected void visitAttr(String type, String attr, String attrType, String value)
62.108 throws IOException {
62.109 - if (attr == null) {
62.110 + if (attr == null && value == null) {
62.111 return;
62.112 }
62.113 - if (cnt++ > 0) {
62.114 - out.append(",\n");
62.115 - }
62.116 - out.append(attr).append("__").append(attrType).append(" : ").append(value);
62.117 + out.append(value);
62.118 + }
62.119 +
62.120 + @Override
62.121 + protected void visitEnumAttr(String type, String attr, String attrType, String value)
62.122 + throws IOException {
62.123 + final String slashType = attrType.substring(1, attrType.length() - 1);
62.124 + requireReference(slashType);
62.125 +
62.126 + out.append(accessClass(slashType.replace('/', '_')))
62.127 + .append("(false).constructor.").append(value);
62.128 }
62.129 };
62.130 ap.parse(data, cd);
63.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
63.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ParseMan.java Fri Feb 15 21:16:05 2013 +0100
63.3 @@ -0,0 +1,57 @@
63.4 +/**
63.5 + * Back 2 Browser Bytecode Translator
63.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
63.7 + *
63.8 + * This program is free software: you can redistribute it and/or modify
63.9 + * it under the terms of the GNU General Public License as published by
63.10 + * the Free Software Foundation, version 2 of the License.
63.11 + *
63.12 + * This program is distributed in the hope that it will be useful,
63.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
63.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
63.15 + * GNU General Public License for more details.
63.16 + *
63.17 + * You should have received a copy of the GNU General Public License
63.18 + * along with this program. Look for COPYING file in the top folder.
63.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
63.20 + */
63.21 +package org.apidesign.vm4brwsr;
63.22 +
63.23 +import java.io.IOException;
63.24 +import java.io.InputStream;
63.25 +import org.apidesign.bck2brwsr.emul.lang.ManifestInputStream;
63.26 +
63.27 +/**
63.28 + *
63.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
63.30 + */
63.31 +final class ParseMan extends ManifestInputStream {
63.32 + private String cp;
63.33 + private String mc;
63.34 +
63.35 + public ParseMan(InputStream is) throws IOException {
63.36 + super(is);
63.37 + readAttributes(new byte[512]);
63.38 + }
63.39 +
63.40 + @Override
63.41 + protected String putValue(String key, String value) {
63.42 + if ("Class-Path".equals(key)) {
63.43 + cp = value;
63.44 + }
63.45 + if ("Main-Class".equals(key)) {
63.46 + mc = value;
63.47 + }
63.48 + return null;
63.49 + }
63.50 +
63.51 + String getMainClass() {
63.52 + return mc;
63.53 + }
63.54 +
63.55 + @Override
63.56 + public String toString() {
63.57 + return cp;
63.58 + }
63.59 +
63.60 +}
64.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Fri Feb 15 11:54:45 2013 +0100
64.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Fri Feb 15 21:16:05 2013 +0100
64.3 @@ -31,8 +31,12 @@
64.4
64.5 static {
64.6 // uses VMLazy to load dynamic classes
64.7 - VMLazy.init();
64.8 - Zips.init();
64.9 + boolean assertsOn = false;
64.10 + assert assertsOn = true;
64.11 + if (assertsOn) {
64.12 + VMLazy.init();
64.13 + Zips.init();
64.14 + }
64.15 }
64.16
64.17 @Override
64.18 @@ -44,8 +48,7 @@
64.19 new VM(out).doCompile(l, names);
64.20 }
64.21 protected void doCompile(Bck2Brwsr.Resources l, StringArray names) throws IOException {
64.22 - out.append("(function VM(global) {");
64.23 - out.append("\n var vm = {};");
64.24 + out.append("(function VM(global) {var fillInVMSkeleton = function(vm) {");
64.25 StringArray processed = new StringArray();
64.26 StringArray initCode = new StringArray();
64.27 for (String baseClass : names.toArray()) {
64.28 @@ -113,31 +116,31 @@
64.29 }
64.30 }
64.31 out.append(
64.32 - " global.bck2brwsr = function() {\n"
64.33 - + " var args = arguments;\n"
64.34 + " return vm;\n"
64.35 + + " };\n"
64.36 + + " global.bck2brwsr = function() {\n"
64.37 + + " var args = Array.prototype.slice.apply(arguments);\n"
64.38 + + " var vm = fillInVMSkeleton({});\n"
64.39 + " var loader = {};\n"
64.40 + " loader.vm = vm;\n"
64.41 - + " if (args.length == 1 && typeof args[0] !== 'function') {;\n"
64.42 - + " var classpath = args[0];\n"
64.43 - + " args[0] = function(name) {\n"
64.44 - + " return vm.org_apidesign_vm4brwsr_Zips(false).loadFromCp___3B_3Ljava_lang_Object_2Ljava_lang_String_2(classpath, name);\n"
64.45 - + " };\n"
64.46 - + " };\n"
64.47 + " loader.loadClass = function(name) {\n"
64.48 + " var attr = name.replace__Ljava_lang_String_2CC('.','_');\n"
64.49 + " var fn = vm[attr];\n"
64.50 + " if (fn) return fn(false);\n"
64.51 - + " if (!args[0]) throw 'bck2brwsr initialized without loader function, cannot load ' + name;\n"
64.52 + " return vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
64.53 + " load__Ljava_lang_Object_2Ljava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, name, args);\n"
64.54 + " }\n"
64.55 - + " if (args[0]) {\n"
64.56 - + " vm.loadClass = loader.loadClass;\n"
64.57 - + " vm.loadBytes = function(name) {\n"
64.58 - + " if (!args[0]) throw 'bck2brwsr initialized without loader function, cannot load ' + name;\n"
64.59 - + " return args[0](name);\n"
64.60 - + " }\n"
64.61 + + " if (vm.loadClass) {\n"
64.62 + + " throw 'Cannot initialize the bck2brwsr VM twice!';\n"
64.63 + " }\n"
64.64 + + " vm.loadClass = loader.loadClass;\n"
64.65 + + " vm.loadBytes = function(name) {\n"
64.66 + + " return vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
64.67 + + " loadBytes___3BLjava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, name, args);\n"
64.68 + + " }\n"
64.69 + + " vm.java_lang_reflect_Array(false);\n"
64.70 + + " vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
64.71 + + " loadBytes___3BLjava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, null, args);\n"
64.72 + " return loader;\n"
64.73 + " };\n");
64.74 out.append("}(this));");
65.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java Fri Feb 15 11:54:45 2013 +0100
65.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java Fri Feb 15 21:16:05 2013 +0100
65.3 @@ -20,6 +20,7 @@
65.4 import java.io.ByteArrayInputStream;
65.5 import java.io.IOException;
65.6 import java.io.InputStream;
65.7 +import java.lang.reflect.Array;
65.8 import org.apidesign.bck2brwsr.core.JavaScriptBody;
65.9
65.10 /**
65.11 @@ -38,23 +39,19 @@
65.12 static void init() {
65.13 }
65.14
65.15 - @JavaScriptBody(args={"l", "res", "args" }, body = ""
65.16 - + "\ntry {"
65.17 - + "\n return args[0](res.toString());"
65.18 - + "\n} catch (x) {"
65.19 - + "\n throw Object.getOwnPropertyNames(l.vm).toString() + x.toString();"
65.20 - + "\n}")
65.21 - private static native byte[] read(Object l, String res, Object[] args);
65.22 -
65.23 static Object load(Object loader, String name, Object[] arguments)
65.24 throws IOException, ClassNotFoundException {
65.25 return new VMLazy(loader, arguments).load(name, false);
65.26 }
65.27
65.28 + static byte[] loadBytes(Object loader, String name, Object[] arguments) throws Exception {
65.29 + return Zips.loadFromCp(arguments, name);
65.30 + }
65.31 +
65.32 private Object load(String name, boolean instance)
65.33 throws IOException, ClassNotFoundException {
65.34 String res = name.replace('.', '/') + ".class";
65.35 - byte[] arr = read(loader, res, args);
65.36 + byte[] arr = Zips.loadFromCp(args, res);
65.37 if (arr == null) {
65.38 throw new ClassNotFoundException(name);
65.39 }
66.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/Zips.java Fri Feb 15 11:54:45 2013 +0100
66.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/Zips.java Fri Feb 15 21:16:05 2013 +0100
66.3 @@ -17,81 +17,171 @@
66.4 */
66.5 package org.apidesign.vm4brwsr;
66.6
66.7 +import java.io.ByteArrayInputStream;
66.8 import java.io.IOException;
66.9 +import java.io.InputStream;
66.10 import java.net.URL;
66.11 -import java.util.zip.ZipEntry;
66.12 -import java.util.zip.ZipInputStream;
66.13 import org.apidesign.bck2brwsr.core.JavaScriptBody;
66.14 +import org.apidesign.bck2brwsr.emul.zip.FastJar;
66.15
66.16 /** Conversion from classpath to load function.
66.17 *
66.18 * @author Jaroslav Tulach <jtulach@netbeans.org>
66.19 */
66.20 final class Zips {
66.21 - private Zips() {
66.22 + private final FastJar fj;
66.23 +
66.24 + private Zips(String path, byte[] zipData) throws IOException {
66.25 + long bef = timeNow();
66.26 + fj = new FastJar(zipData);
66.27 + for (FastJar.Entry e : fj.list()) {
66.28 + putRes(e.name, e);
66.29 + }
66.30 + log("Iterating thru " + path + " took " + (timeNow() - bef) + "ms");
66.31 }
66.32
66.33 public static void init() {
66.34 }
66.35 + @JavaScriptBody(args = { "arr" }, body = "return arr.length;")
66.36 + private static native int length(Object arr);
66.37 + @JavaScriptBody(args = { "arr", "index" }, body = "return arr[index];")
66.38 + private static native Object at(Object arr, int index);
66.39 + @JavaScriptBody(args = { "arr", "index", "value" }, body = "arr[index] = value; return value;")
66.40 + private static native Object set(Object arr, int index, Object value);
66.41
66.42 - public static byte[] loadFromCp(Object[] classpath, String res) {
66.43 - for (int i = 0; i < classpath.length; i++) {
66.44 - Object c = classpath[i];
66.45 + public static byte[] loadFromCp(Object classpath, String res)
66.46 + throws IOException, ClassNotFoundException {
66.47 + for (int i = 0; i < length(classpath); i++) {
66.48 + Object c = at(classpath, i);
66.49 if (c instanceof String) {
66.50 try {
66.51 - c = classpath[i] = toZip((String)c);
66.52 + String url = (String)c;
66.53 + final Zips z = toZip(url);
66.54 + c = set(classpath, i, z);
66.55 + final byte[] man = z.findRes("META-INF/MANIFEST.MF");
66.56 + if (man != null) {
66.57 + String mainClass = processClassPathAttr(man, url, classpath);
66.58 +// if (mainClass != null) {
66.59 +// Class.forName(mainClass);
66.60 +// }
66.61 + }
66.62 } catch (IOException ex) {
66.63 - classpath[i] = ex;
66.64 + set(classpath, i, ex);
66.65 + log("Cannot load " + c + " - " + ex.getClass().getName() + ":" + ex.getMessage());
66.66 }
66.67 }
66.68 - if (c instanceof Zips) {
66.69 - Object checkRes = ((Zips)c).findRes(res);
66.70 - if (checkRes instanceof byte[]) {
66.71 - return (byte[])checkRes;
66.72 + if (res != null) {
66.73 + byte[] checkRes;
66.74 + if (c instanceof Zips) {
66.75 + checkRes = ((Zips)c).findRes(res);
66.76 + } else {
66.77 + checkRes = callFunction(c, res);
66.78 + }
66.79 + if (checkRes != null) {
66.80 + return checkRes;
66.81 }
66.82 }
66.83 }
66.84 return null;
66.85 }
66.86 +
66.87 + @JavaScriptBody(args = { "fn", "res" }, body =
66.88 + "if (typeof fn === 'function') return fn(res);\n"
66.89 + + "return null;"
66.90 + )
66.91 + private static native byte[] callFunction(Object fn, String res);
66.92 +
66.93 + @JavaScriptBody(args = { "msg" }, body = "console.log(msg.toString());")
66.94 + private static native void log(String msg);
66.95 +
66.96 + private byte[] findRes(String res) throws IOException {
66.97 + Object arr = findResImpl(res);
66.98 + if (arr instanceof FastJar.Entry) {
66.99 + long bef = timeNow();
66.100 + InputStream zip = fj.getInputStream((FastJar.Entry)arr);
66.101 + arr = readFully(new byte[512], zip);
66.102 + putRes(res, arr);
66.103 + log("Reading " + res + " took " + (timeNow() - bef) + "ms");
66.104 + }
66.105 + return (byte[]) arr;
66.106 + }
66.107
66.108 @JavaScriptBody(args = { "res" }, body = "var r = this[res]; return r ? r : null;")
66.109 - private native byte[] findRes(String res);
66.110 + private native Object findResImpl(String res);
66.111
66.112 @JavaScriptBody(args = { "res", "arr" }, body = "this[res] = arr;")
66.113 - private native void putRes(String res, byte[] arr);
66.114 + private native void putRes(String res, Object arr);
66.115
66.116 private static Zips toZip(String path) throws IOException {
66.117 URL u = new URL(path);
66.118 - ZipInputStream zip = new ZipInputStream(u.openStream());
66.119 - Zips z = new Zips();
66.120 - for (;;) {
66.121 - ZipEntry entry = zip.getNextEntry();
66.122 - if (entry == null) {
66.123 - break;
66.124 - }
66.125 - byte[] arr = new byte[4096];
66.126 - int offset = 0;
66.127 - for (;;) {
66.128 - int len = zip.read(arr, offset, arr.length - offset);
66.129 - if (len == -1) {
66.130 - break;
66.131 - }
66.132 - offset += len;
66.133 - if (offset == arr.length) {
66.134 - enlargeArray(arr, arr.length + 4096);
66.135 + byte[] zipData = (byte[]) u.getContent(new Class[] { byte[].class });
66.136 + return new Zips(path, zipData);
66.137 + }
66.138 +
66.139 + private static String processClassPathAttr(final byte[] man, String url, Object classpath) throws IOException {
66.140 + try (ParseMan is = new ParseMan(new ByteArrayInputStream(man))) {
66.141 + String cp = is.toString();
66.142 + if (cp != null) {
66.143 + cp = cp.trim();
66.144 + for (int p = 0; p < cp.length();) {
66.145 + int n = cp.indexOf(' ', p);
66.146 + if (n == -1) {
66.147 + n = cp.length();
66.148 + }
66.149 + String el = cp.substring(p, n);
66.150 + URL u = new URL(new URL(url), el);
66.151 + classpath = addToArray(classpath, u.toString());
66.152 + p = n + 1;
66.153 }
66.154 }
66.155 - sliceArray(arr, offset);
66.156 - z.putRes(entry.getName(), arr);
66.157 + return is.getMainClass();
66.158 }
66.159 - return z;
66.160 }
66.161
66.162 + private static Object addToArray(Object arr, String value) {
66.163 + final int last = length(arr);
66.164 + Object ret = enlargeArray(arr, last + 1);
66.165 + set(ret, last, value);
66.166 + return ret;
66.167 + }
66.168 +
66.169 + @JavaScriptBody(args = { "arr", "len" }, body = "while (arr.length < len) arr.push(null); return arr;")
66.170 + private static native Object enlargeArray(Object arr, int len);
66.171 @JavaScriptBody(args = { "arr", "len" }, body = "while (arr.length < len) arr.push(0);")
66.172 - private static native void enlargeArray(byte[] arr, int len);
66.173 + private static native void enlargeBytes(byte[] arr, int len);
66.174
66.175 @JavaScriptBody(args = { "arr", "len" }, body = "arr.splice(len, arr.length - len);")
66.176 private static native void sliceArray(byte[] arr, int len);
66.177 +
66.178 + private static Object readFully(byte[] arr, InputStream zip) throws IOException {
66.179 + int offset = 0;
66.180 + for (;;) {
66.181 + int len = zip.read(arr, offset, arr.length - offset);
66.182 + if (len == -1) {
66.183 + break;
66.184 + }
66.185 + offset += len;
66.186 + if (offset == arr.length) {
66.187 + enlargeBytes(arr, arr.length + 4096);
66.188 + }
66.189 + }
66.190 + sliceArray(arr, offset);
66.191 + return arr;
66.192 + }
66.193 +
66.194 + private static long timeNow() {
66.195 + double time = m();
66.196 + if (time >= 0) {
66.197 + return (long)time;
66.198 + }
66.199 + return org.apidesign.bck2brwsr.emul.lang.System.currentTimeMillis();
66.200 + }
66.201 + @JavaScriptBody(args = {}, body =
66.202 + "if (typeof window.performance === 'undefined') return -1;\n"
66.203 + + "if (typeof window.performance.now === 'undefined') return -1;\n"
66.204 + + "return window.performance.now();"
66.205 + )
66.206 + private static native double m();
66.207
66.208
66.209 }
67.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java Fri Feb 15 11:54:45 2013 +0100
67.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java Fri Feb 15 21:16:05 2013 +0100
67.3 @@ -17,7 +17,6 @@
67.4 */
67.5 package org.apidesign.vm4brwsr;
67.6
67.7 -import javax.script.Invocable;
67.8 import static org.testng.Assert.*;
67.9 import org.testng.annotations.BeforeClass;
67.10 import org.testng.annotations.Test;
67.11 @@ -76,18 +75,13 @@
67.12 assertExec("Returns 'false'", Array.class, "instanceOfArray__ZLjava_lang_Object_2", Double.valueOf(0), "non-array");
67.13 }
67.14
67.15 - private static CharSequence codeSeq;
67.16 - private static Invocable code;
67.17 + private static TestVM code;
67.18
67.19 @BeforeClass
67.20 public void compileTheCode() throws Exception {
67.21 - StringBuilder sb = new StringBuilder();
67.22 - code = StaticMethodTest.compileClass(sb,
67.23 - "org/apidesign/vm4brwsr/Array"
67.24 - );
67.25 - codeSeq = sb;
67.26 + code = TestVM.compileClass("org/apidesign/vm4brwsr/Array");
67.27 }
67.28 private static void assertExec(String msg, Class clazz, String method, Object expRes, Object... args) throws Exception {
67.29 - StaticMethodTest.assertExec(code, codeSeq, msg, clazz, method, expRes, args);
67.30 + code.assertExec(msg, clazz, method, expRes, args);
67.31 }
67.32 }
68.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java Fri Feb 15 11:54:45 2013 +0100
68.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java Fri Feb 15 21:16:05 2013 +0100
68.3 @@ -17,7 +17,6 @@
68.4 */
68.5 package org.apidesign.vm4brwsr;
68.6
68.7 -import javax.script.Invocable;
68.8 import org.testng.annotations.Test;
68.9 import static org.testng.Assert.*;
68.10 import org.testng.annotations.BeforeClass;
68.11 @@ -87,12 +86,27 @@
68.12 @Test public void jsAnnotation() throws Exception {
68.13 assertExec("Check class annotation", Classes.class, "getMarker__I", Double.valueOf(10));
68.14 }
68.15 + @Test public void jsArrayAnnotation() throws Exception {
68.16 + assertExec("Check array annotation", Classes.class, "getMarkerNicknames__Ljava_lang_String_2", Classes.getMarkerNicknames());
68.17 + }
68.18 + @Test public void jsEnumAnnotation() throws Exception {
68.19 + assertExec("Check enum annotation", Classes.class, "getMarkerE__Ljava_lang_String_2", Classes.getMarkerE());
68.20 + }
68.21 + @Test public void jsRetentionAnnotation() throws Exception {
68.22 + assertExec("Check enum annotation", Classes.class, "getRetention__Ljava_lang_String_2", Classes.getRetention());
68.23 + }
68.24 @Test public void jsStringAnnotation() throws Exception {
68.25 assertExec("Check class annotation", Classes.class, "getNamer__Ljava_lang_String_2Z", "my text", true);
68.26 }
68.27 @Test public void jsStringAnnotationFromArray() throws Exception {
68.28 assertExec("Check class annotation", Classes.class, "getNamer__Ljava_lang_String_2Z", "my text", false);
68.29 }
68.30 + @Test public void jsInnerAnnotation() throws Exception {
68.31 + assertExec("Check inner annotation", Classes.class, "getInnerNamer__I", Double.valueOf(Classes.getInnerNamer()));
68.32 + }
68.33 + @Test public void jsInnerAnnotationFromArray() throws Exception {
68.34 + assertExec("Check inner annotation", Classes.class, "getInnerNamers__I", Double.valueOf(Classes.getInnerNamers()));
68.35 + }
68.36 @Test public void javaInvokeMethod() throws Exception {
68.37 assertEquals(Classes.reflectiveMethodCall(true, "name"), "java.io.IOException", "Calls the name() method via reflection");
68.38 }
68.39 @@ -102,6 +116,14 @@
68.40 "java.io.IOException", true, "name"
68.41 );
68.42 }
68.43 +
68.44 + @Test public void jsMethodDeclaredInObject() throws Exception {
68.45 + assertExec("Defined in Object", Classes.class,
68.46 + "objectName__Ljava_lang_String_2",
68.47 + "java.lang.Object"
68.48 + );
68.49 + }
68.50 +
68.51 @Test public void jsInvokeParamMethod() throws Exception {
68.52 assertExec("sums two numbers via reflection", Classes.class,
68.53 "reflectiveSum__III", Double.valueOf(5), 2, 3
68.54 @@ -149,14 +171,12 @@
68.55 0.0, "java.lang.String"
68.56 );
68.57 }
68.58 - /*
68.59 @Test public void isInterface() throws Exception {
68.60 assertExec("Calls Class.isInterface", Classes.class,
68.61 "isInterface__ZLjava_lang_String_2",
68.62 1.0, "java.lang.Runnable"
68.63 );
68.64 }
68.65 - */
68.66 @Test public void integerType() throws Exception {
68.67 assertExec("Computes the type", Classes.class,
68.68 "intType__Ljava_lang_String_2",
68.69 @@ -164,22 +184,17 @@
68.70 );
68.71 }
68.72
68.73 - private static CharSequence codeSeq;
68.74 - private static Invocable code;
68.75 + private static TestVM code;
68.76
68.77 @BeforeClass
68.78 public void compileTheCode() throws Exception {
68.79 - if (codeSeq == null) {
68.80 - StringBuilder sb = new StringBuilder();
68.81 - code = StaticMethodTest.compileClass(sb, "org/apidesign/vm4brwsr/Classes");
68.82 - codeSeq = sb;
68.83 - }
68.84 + code = TestVM.compileClass("org/apidesign/vm4brwsr/Classes");
68.85 }
68.86
68.87 private void assertExec(
68.88 String msg, Class clazz, String method, Object expRes, Object... args
68.89 ) throws Exception {
68.90 - StaticMethodTest.assertExec(code, codeSeq, msg, clazz, method, expRes, args);
68.91 + code.assertExec(msg, clazz, method, expRes, args);
68.92 }
68.93 @Test public void isClassAssignable() throws Exception {
68.94 assertExec("isAssignable works on subclasses", Classes.class,
69.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java Fri Feb 15 11:54:45 2013 +0100
69.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java Fri Feb 15 21:16:05 2013 +0100
69.3 @@ -19,6 +19,8 @@
69.4
69.5 import java.io.IOException;
69.6 import java.lang.annotation.Annotation;
69.7 +import java.lang.annotation.Retention;
69.8 +import java.lang.annotation.RetentionPolicy;
69.9 import java.lang.reflect.Method;
69.10 import java.net.MalformedURLException;
69.11 import org.apidesign.bck2brwsr.core.JavaScriptBody;
69.12 @@ -27,8 +29,11 @@
69.13 *
69.14 * @author Jaroslav Tulach <jtulach@netbeans.org>
69.15 */
69.16 -@ClassesMarker(number = 10)
69.17 -@ClassesNamer(name = "my text")
69.18 +@ClassesMarker(number = 10, nicknames = { "Ten", "Deset" }, count = ClassesMarker.E.TWO, subs = {
69.19 + @ClassesMarker.Anno(Integer.SIZE),
69.20 + @ClassesMarker.Anno(Integer.MIN_VALUE)
69.21 +})
69.22 +@ClassesNamer(name = "my text", anno = @ClassesMarker.Anno(333))
69.23 public class Classes {
69.24 public static String nameOfIO() {
69.25 return nameFor(IOException.class);
69.26 @@ -38,6 +43,8 @@
69.27 return c.getName();
69.28 }
69.29
69.30 + private static final Class<?> PRELOAD = Runnable.class;
69.31 +
69.32 public static boolean isInterface(String s) throws ClassNotFoundException {
69.33 return Class.forName(s).isInterface();
69.34 }
69.35 @@ -55,7 +62,7 @@
69.36 return new IOException().getClass().getName().toString();
69.37 }
69.38
69.39 - @ClassesMarker(number = 1)
69.40 + @ClassesMarker(number = 1, nicknames = { "One", "Jedna" } )
69.41 public static String name() {
69.42 return IOException.class.getName().toString();
69.43 }
69.44 @@ -65,6 +72,11 @@
69.45 public static String canonicalName() {
69.46 return IOException.class.getCanonicalName();
69.47 }
69.48 +
69.49 + public static String objectName() throws NoSuchMethodException {
69.50 + return IOException.class.getMethod("wait").getDeclaringClass().getName();
69.51 + }
69.52 +
69.53 public static boolean newInstance() throws Exception {
69.54 IOException ioe = IOException.class.newInstance();
69.55 if (ioe instanceof IOException) {
69.56 @@ -85,8 +97,45 @@
69.57 return -2;
69.58 }
69.59 ClassesMarker cm = Classes.class.getAnnotation(ClassesMarker.class);
69.60 + assert cm instanceof Object : "Is object " + cm;
69.61 + assert cm instanceof Annotation : "Is annotation " + cm;
69.62 + assert !((Object)cm instanceof Class) : "Is not Class " + cm;
69.63 return cm == null ? -1 : cm.number();
69.64 }
69.65 + public static String getMarkerNicknames() {
69.66 + ClassesMarker cm = Classes.class.getAnnotation(ClassesMarker.class);
69.67 + if (cm == null) {
69.68 + return null;
69.69 + }
69.70 +
69.71 + final Object[] arr = cm.nicknames();
69.72 + assert arr instanceof Object[] : "Instance of Object array: " + arr;
69.73 + assert arr instanceof String[] : "Instance of String array: " + arr;
69.74 + assert !(arr instanceof Integer[]) : "Not instance of Integer array: " + arr;
69.75 +
69.76 + StringBuilder sb = new StringBuilder();
69.77 + for (String s : cm.nicknames()) {
69.78 + sb.append(s).append("\n");
69.79 + }
69.80 + return sb.toString().toString();
69.81 + }
69.82 + @Retention(RetentionPolicy.CLASS)
69.83 + @interface Ann {
69.84 + }
69.85 +
69.86 + public static String getRetention() throws Exception {
69.87 + Retention r = Ann.class.getAnnotation(Retention.class);
69.88 + assert r != null : "Annotation is present";
69.89 + assert r.value() == RetentionPolicy.CLASS : "Policy value is OK: " + r.value();
69.90 + return r.annotationType().getName();
69.91 + }
69.92 + public static String getMarkerE() {
69.93 + ClassesMarker cm = Classes.class.getAnnotation(ClassesMarker.class);
69.94 + if (cm == null) {
69.95 + return null;
69.96 + }
69.97 + return cm.count().name();
69.98 + }
69.99 public static String getNamer(boolean direct) {
69.100 if (direct) {
69.101 ClassesNamer cm = Classes.class.getAnnotation(ClassesNamer.class);
69.102 @@ -99,6 +148,20 @@
69.103 }
69.104 return null;
69.105 }
69.106 + public static int getInnerNamer() {
69.107 + ClassesNamer cm = Classes.class.getAnnotation(ClassesNamer.class);
69.108 + assert cm != null : "ClassesNamer is present";
69.109 + return cm.anno().value();
69.110 + }
69.111 + public static int getInnerNamers() {
69.112 + ClassesMarker cm = Classes.class.getAnnotation(ClassesMarker.class);
69.113 + assert cm != null : "ClassesNamer is present";
69.114 + int sum = 0;
69.115 + for (ClassesMarker.Anno anno : cm.subs()) {
69.116 + sum += anno.value();
69.117 + }
69.118 + return sum;
69.119 + }
69.120
69.121 public static String intType() {
69.122 return Integer.TYPE.getName();
70.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ClassesMarker.java Fri Feb 15 11:54:45 2013 +0100
70.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassesMarker.java Fri Feb 15 21:16:05 2013 +0100
70.3 @@ -27,4 +27,16 @@
70.4 @Retention(RetentionPolicy.RUNTIME)
70.5 public @interface ClassesMarker {
70.6 int number();
70.7 + String[] nicknames();
70.8 + E count() default E.ONE;
70.9 +
70.10 + enum E {
70.11 + ONE, TWO;
70.12 + }
70.13 +
70.14 + Anno[] subs() default {};
70.15 +
70.16 + public @interface Anno {
70.17 + int value();
70.18 + }
70.19 }
71.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ClassesNamer.java Fri Feb 15 11:54:45 2013 +0100
71.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassesNamer.java Fri Feb 15 21:16:05 2013 +0100
71.3 @@ -27,4 +27,5 @@
71.4 @Retention(RetentionPolicy.RUNTIME)
71.5 public @interface ClassesNamer {
71.6 String name();
71.7 + ClassesMarker.Anno anno();
71.8 }
72.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ExceptionsTest.java Fri Feb 15 11:54:45 2013 +0100
72.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ExceptionsTest.java Fri Feb 15 21:16:05 2013 +0100
72.3 @@ -17,7 +17,6 @@
72.4 */
72.5 package org.apidesign.vm4brwsr;
72.6
72.7 -import javax.script.Invocable;
72.8 import javax.script.ScriptException;
72.9 import static org.testng.Assert.*;
72.10 import org.testng.annotations.BeforeClass;
72.11 @@ -81,8 +80,7 @@
72.12 }
72.13
72.14 @Test public void testThreeCalls() throws Exception {
72.15 - Object vm = code.invokeFunction("bck2brwsr");
72.16 - Object clazz = code.invokeMethod(vm, "loadClass", Exceptions.class.getName());
72.17 + Object clazz = code.loadClass("loadClass", Exceptions.class.getName());
72.18
72.19 String method = "readCounter__ILjava_lang_String_2";
72.20
72.21 @@ -104,18 +102,13 @@
72.22 }
72.23 }
72.24
72.25 - private static CharSequence codeSeq;
72.26 - private static Invocable code;
72.27 + private static TestVM code;
72.28
72.29 @BeforeClass
72.30 public void compileTheCode() throws Exception {
72.31 - StringBuilder sb = new StringBuilder();
72.32 - code = StaticMethodTest.compileClass(sb,
72.33 - "org/apidesign/vm4brwsr/Exceptions"
72.34 - );
72.35 - codeSeq = sb;
72.36 + code = TestVM.compileClass("org/apidesign/vm4brwsr/Exceptions");
72.37 }
72.38 private static void assertExec(String msg, Class clazz, String method, Object expRes, Object... args) throws Exception {
72.39 - StaticMethodTest.assertExec(code, codeSeq, msg, clazz, method, expRes, args);
72.40 + code.assertExec(msg, clazz, method, expRes, args);
72.41 }
72.42 }
73.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/InstanceTest.java Fri Feb 15 11:54:45 2013 +0100
73.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/InstanceTest.java Fri Feb 15 21:16:05 2013 +0100
73.3 @@ -17,7 +17,6 @@
73.4 */
73.5 package org.apidesign.vm4brwsr;
73.6
73.7 -import javax.script.Invocable;
73.8 import org.testng.annotations.Test;
73.9 import org.testng.annotations.BeforeClass;
73.10
73.11 @@ -151,22 +150,17 @@
73.12 return "org/apidesign/vm4brwsr/Instance";
73.13 }
73.14
73.15 - private static CharSequence codeSeq;
73.16 - private static Invocable code;
73.17 + private static TestVM code;
73.18
73.19 @BeforeClass
73.20 public void compileTheCode() throws Exception {
73.21 - if (codeSeq == null) {
73.22 - StringBuilder sb = new StringBuilder();
73.23 - code = StaticMethodTest.compileClass(sb, startCompilationWith());
73.24 - codeSeq = sb;
73.25 - }
73.26 + code = TestVM.compileClass(startCompilationWith());
73.27 }
73.28
73.29 private void assertExec(
73.30 String msg, Class clazz, String method, Object expRes, Object... args
73.31 ) throws Exception {
73.32 - StaticMethodTest.assertExec(code, codeSeq, msg, clazz, method, expRes, args);
73.33 + code.assertExec(msg, clazz, method, expRes, args);
73.34 }
73.35
73.36 }
74.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java Fri Feb 15 11:54:45 2013 +0100
74.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java Fri Feb 15 21:16:05 2013 +0100
74.3 @@ -17,8 +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 import org.testng.annotations.Test;
74.12 @@ -144,22 +142,17 @@
74.13 );
74.14 }
74.15
74.16 - private static CharSequence codeSeq;
74.17 - private static Invocable code;
74.18 + private static TestVM code;
74.19
74.20 @BeforeClass
74.21 public void compileTheCode() throws Exception {
74.22 - if (codeSeq == null) {
74.23 - StringBuilder sb = new StringBuilder();
74.24 - code = StaticMethodTest.compileClass(sb, "org/apidesign/vm4brwsr/Numbers");
74.25 - codeSeq = sb;
74.26 - }
74.27 + code = TestVM.compileClass("org/apidesign/vm4brwsr/Numbers");
74.28 }
74.29
74.30 private static void assertExec(
74.31 String msg, Class<?> clazz, String method, Object expRes, Object... args) throws Exception
74.32 {
74.33 - Object ret = TestUtils.execCode(code, codeSeq, msg, clazz, method, expRes, args);
74.34 + Object ret = code.execCode(msg, clazz, method, expRes, args);
74.35 if (ret == null) {
74.36 return;
74.37 }
74.38 @@ -167,10 +160,10 @@
74.39 double expD = ((Double)expRes).doubleValue();
74.40 double retD = ((Double)ret).doubleValue();
74.41 assertEquals(retD, expD, 0.000004, msg + " "
74.42 - + StaticMethodTest.dumpJS(codeSeq));
74.43 + + code.toString());
74.44 return;
74.45 }
74.46 - assertEquals(ret, expRes, msg + " " + StaticMethodTest.dumpJS(codeSeq));
74.47 + assertEquals(ret, expRes, msg + " " + code.toString());
74.48 }
74.49
74.50 }
75.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethodTest.java Fri Feb 15 11:54:45 2013 +0100
75.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethodTest.java Fri Feb 15 21:16:05 2013 +0100
75.3 @@ -17,16 +17,6 @@
75.4 */
75.5 package org.apidesign.vm4brwsr;
75.6
75.7 -import java.io.File;
75.8 -import java.io.FileWriter;
75.9 -import java.io.IOException;
75.10 -import java.io.InputStream;
75.11 -import java.net.URL;
75.12 -import java.util.Enumeration;
75.13 -import javax.script.Invocable;
75.14 -import javax.script.ScriptEngine;
75.15 -import javax.script.ScriptEngineManager;
75.16 -import javax.script.ScriptException;
75.17 import static org.testng.Assert.*;
75.18 import org.testng.annotations.BeforeClass;
75.19 import org.testng.annotations.Test;
75.20 @@ -331,88 +321,18 @@
75.21 );
75.22 }
75.23
75.24 - private static CharSequence codeSeq;
75.25 - private static Invocable code;
75.26 + private static TestVM code;
75.27
75.28 @BeforeClass
75.29 public void compileTheCode() throws Exception {
75.30 StringBuilder sb = new StringBuilder();
75.31 - code = compileClass(sb, "org/apidesign/vm4brwsr/StaticMethod");
75.32 - codeSeq = sb;
75.33 - }
75.34 -
75.35 -
75.36 - private static void assertExec(
75.37 - String msg, Class clazz, String method,
75.38 - Object expRes, Object... args
75.39 - ) throws Exception {
75.40 - assertExec(code, codeSeq, msg, clazz, method, expRes, args);
75.41 - }
75.42 - static void assertExec(
75.43 - Invocable toRun, CharSequence theCode,
75.44 - String msg, Class clazz, String method,
75.45 - Object expRes, Object... args
75.46 - ) throws Exception {
75.47 - Object ret = TestUtils.execCode(toRun, theCode, msg, clazz, method, expRes, args);
75.48 - if (ret == null) {
75.49 - return;
75.50 - }
75.51 - if (expRes != null && expRes.equals(ret)) {
75.52 - return;
75.53 - }
75.54 - assertEquals(ret, expRes, msg + "was: " + ret + "\n" + dumpJS(theCode));
75.55 -
75.56 + code = TestVM.compileClass(sb, "org/apidesign/vm4brwsr/StaticMethod");
75.57 }
75.58
75.59 - static Invocable compileClass(StringBuilder sb, String... names) throws ScriptException, IOException {
75.60 - return compileClass(sb, null, names);
75.61 - }
75.62 - static Invocable compileClass(
75.63 - StringBuilder sb, ScriptEngine[] eng, String... names
75.64 - ) throws ScriptException, IOException {
75.65 - if (sb == null) {
75.66 - sb = new StringBuilder();
75.67 - }
75.68 - Bck2Brwsr.generate(sb, new EmulationResources(), names);
75.69 - ScriptEngineManager sem = new ScriptEngineManager();
75.70 - ScriptEngine js = sem.getEngineByExtension("js");
75.71 - if (eng != null) {
75.72 - eng[0] = js;
75.73 - }
75.74 - try {
75.75 - Object res = js.eval(sb.toString());
75.76 - assertTrue(js instanceof Invocable, "It is invocable object: " + res);
75.77 - return (Invocable)js;
75.78 - } catch (Exception ex) {
75.79 - if (sb.length() > 2000) {
75.80 - sb = dumpJS(sb);
75.81 - }
75.82 - fail("Could not evaluate:\n" + sb, ex);
75.83 - return null;
75.84 - }
75.85 - }
75.86 - static StringBuilder dumpJS(CharSequence sb) throws IOException {
75.87 - File f = File.createTempFile("execution", ".js");
75.88 - FileWriter w = new FileWriter(f);
75.89 - w.append(sb);
75.90 - w.close();
75.91 - return new StringBuilder(f.getPath());
75.92 - }
75.93 - private static class EmulationResources implements Bck2Brwsr.Resources {
75.94 - @Override
75.95 - public InputStream get(String name) throws IOException {
75.96 - Enumeration<URL> en = StaticMethodTest.class.getClassLoader().getResources(name);
75.97 - URL u = null;
75.98 - while (en.hasMoreElements()) {
75.99 - u = en.nextElement();
75.100 - }
75.101 - if (u == null) {
75.102 - throw new IOException("Can't find " + name);
75.103 - }
75.104 - if (u.toExternalForm().contains("rt.jar!")) {
75.105 - throw new IOException("No emulation for " + u);
75.106 - }
75.107 - return u.openStream();
75.108 - }
75.109 + private void assertExec(
75.110 + String msg, Class<?> clazz, String method,
75.111 + Object ret, Object... args
75.112 + ) throws Exception {
75.113 + code.assertExec(msg, clazz, method, ret, args);
75.114 }
75.115 }
76.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/StringTest.java Fri Feb 15 11:54:45 2013 +0100
76.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StringTest.java Fri Feb 15 21:16:05 2013 +0100
76.3 @@ -17,7 +17,6 @@
76.4 */
76.5 package org.apidesign.vm4brwsr;
76.6
76.7 -import javax.script.Invocable;
76.8 import org.testng.annotations.Test;
76.9 import static org.testng.Assert.*;
76.10 import org.testng.annotations.BeforeClass;
76.11 @@ -194,23 +193,20 @@
76.12
76.13 }
76.14
76.15 - private static CharSequence codeSeq;
76.16 - private static Invocable code;
76.17 + private static TestVM code;
76.18
76.19 @BeforeClass
76.20 public void compileTheCode() throws Exception {
76.21 - StringBuilder sb = new StringBuilder();
76.22 - code = StaticMethodTest.compileClass(sb,
76.23 + code = TestVM.compileClass(
76.24 "org/apidesign/vm4brwsr/StringSample",
76.25 "java/lang/String"
76.26 );
76.27 - codeSeq = sb;
76.28 }
76.29
76.30 private static void assertExec(String msg,
76.31 Class<?> clazz, String method, Object expRes, Object... args
76.32 ) throws Exception {
76.33 - StaticMethodTest.assertExec(code, codeSeq, msg, clazz, method, expRes, args);
76.34 + code.assertExec(msg, clazz, method, expRes, args);
76.35 }
76.36
76.37 }
77.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/SystemTest.java Fri Feb 15 11:54:45 2013 +0100
77.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/SystemTest.java Fri Feb 15 21:16:05 2013 +0100
77.3 @@ -17,10 +17,8 @@
77.4 */
77.5 package org.apidesign.vm4brwsr;
77.6
77.7 -import javax.script.Invocable;
77.8 import org.testng.annotations.BeforeClass;
77.9 import static org.testng.Assert.*;
77.10 -import org.testng.annotations.BeforeMethod;
77.11 import org.testng.annotations.Test;
77.12
77.13 /**
77.14 @@ -28,10 +26,12 @@
77.15 * @author Jaroslav Tulach <jtulach@netbeans.org>
77.16 */
77.17 public class SystemTest {
77.18 + private static TestVM code;
77.19 +
77.20 @Test public void verifyJSTime() throws Exception {
77.21 long now = System.currentTimeMillis();
77.22
77.23 - Object js = TestUtils.execCode(code, codeSeq, "Get js time",
77.24 + Object js = code.execCode("Get js time",
77.25 org.apidesign.bck2brwsr.emul.lang.System.class, "currentTimeMillis__J",
77.26 null
77.27 );
77.28 @@ -45,14 +45,11 @@
77.29 assertTrue(time <= later, "Upper bound is OK: " + time + " <= " + later);
77.30 }
77.31
77.32 - private static CharSequence codeSeq;
77.33 - private static Invocable code;
77.34
77.35 @BeforeClass
77.36 - public void compileTheCode() throws Exception {
77.37 - StringBuilder sb = new StringBuilder();
77.38 - code = StaticMethodTest.compileClass(sb, "org/apidesign/bck2brwsr/emul/lang/System");
77.39 - codeSeq = sb;
77.40 + public static void compileTheCode() throws Exception {
77.41 + code = TestVM.compileClass(
77.42 + "org/apidesign/bck2brwsr/emul/lang/System");
77.43 }
77.44
77.45 }
78.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/TestUtils.java Fri Feb 15 11:54:45 2013 +0100
78.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
78.3 @@ -1,60 +0,0 @@
78.4 -/**
78.5 - * Back 2 Browser Bytecode Translator
78.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
78.7 - *
78.8 - * This program is free software: you can redistribute it and/or modify
78.9 - * it under the terms of the GNU General Public License as published by
78.10 - * the Free Software Foundation, version 2 of the License.
78.11 - *
78.12 - * This program is distributed in the hope that it will be useful,
78.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
78.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
78.15 - * GNU General Public License for more details.
78.16 - *
78.17 - * You should have received a copy of the GNU General Public License
78.18 - * along with this program. Look for COPYING file in the top folder.
78.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
78.20 - */
78.21 -package org.apidesign.vm4brwsr;
78.22 -
78.23 -import javax.script.Invocable;
78.24 -import javax.script.ScriptException;
78.25 -import static org.testng.Assert.*;
78.26 -
78.27 -class TestUtils {
78.28 -
78.29 - static Object execCode(Invocable code, CharSequence codeSeq,
78.30 - String msg, Class<?> clazz, String method, Object expRes, Object... args)
78.31 - throws Exception
78.32 - {
78.33 - Object ret = null;
78.34 - try {
78.35 - ret = code.invokeFunction("bck2brwsr");
78.36 - ret = code.invokeMethod(ret, "loadClass", clazz.getName());
78.37 - ret = code.invokeMethod(ret, method, args);
78.38 - } catch (ScriptException ex) {
78.39 - fail("Execution failed in " + StaticMethodTest.dumpJS(codeSeq), ex);
78.40 - } catch (NoSuchMethodException ex) {
78.41 - fail("Cannot find method in " + StaticMethodTest.dumpJS(codeSeq), ex);
78.42 - }
78.43 - if (ret == null && expRes == null) {
78.44 - return null;
78.45 - }
78.46 - if (expRes != null && expRes.equals(ret)) {
78.47 - return null;
78.48 - }
78.49 - if (expRes instanceof Number) {
78.50 - // in case of Long it is necessary convert it to number
78.51 - // since the Long is represented by two numbers in JavaScript
78.52 - try {
78.53 - ret = code.invokeMethod(ret, "toFP");
78.54 - ret = code.invokeFunction("Number", ret);
78.55 - } catch (ScriptException ex) {
78.56 - fail("Conversion to number failed in " + StaticMethodTest.dumpJS(codeSeq), ex);
78.57 - } catch (NoSuchMethodException ex) {
78.58 - fail("Cannot find global Number(x) function in " + StaticMethodTest.dumpJS(codeSeq), ex);
78.59 - }
78.60 - }
78.61 - return ret;
78.62 - }
78.63 -}
79.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
79.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/TestVM.java Fri Feb 15 21:16:05 2013 +0100
79.3 @@ -0,0 +1,170 @@
79.4 +/**
79.5 + * Back 2 Browser Bytecode Translator
79.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
79.7 + *
79.8 + * This program is free software: you can redistribute it and/or modify
79.9 + * it under the terms of the GNU General Public License as published by
79.10 + * the Free Software Foundation, version 2 of the License.
79.11 + *
79.12 + * This program is distributed in the hope that it will be useful,
79.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
79.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
79.15 + * GNU General Public License for more details.
79.16 + *
79.17 + * You should have received a copy of the GNU General Public License
79.18 + * along with this program. Look for COPYING file in the top folder.
79.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
79.20 + */
79.21 +package org.apidesign.vm4brwsr;
79.22 +
79.23 +import java.io.File;
79.24 +import java.io.FileWriter;
79.25 +import java.io.IOException;
79.26 +import java.io.InputStream;
79.27 +import java.net.URL;
79.28 +import java.util.Enumeration;
79.29 +import javax.script.Invocable;
79.30 +import javax.script.ScriptEngine;
79.31 +import javax.script.ScriptEngineManager;
79.32 +import javax.script.ScriptException;
79.33 +import static org.testng.Assert.*;
79.34 +
79.35 +final class TestVM {
79.36 + private final Invocable code;
79.37 + private final CharSequence codeSeq;
79.38 + private final Object bck2brwsr;
79.39 +
79.40 +
79.41 + private TestVM(Invocable code, CharSequence codeSeq) throws ScriptException, NoSuchMethodException {
79.42 + this.code = code;
79.43 + this.codeSeq = codeSeq;
79.44 + this.bck2brwsr = code.invokeFunction("bck2brwsr");
79.45 + }
79.46 +
79.47 +
79.48 + public Object execCode(
79.49 + String msg, Class<?> clazz, String method,
79.50 + Object expRes, Object... args
79.51 + ) throws Exception {
79.52 + Object ret = null;
79.53 + try {
79.54 + ret = code.invokeMethod(bck2brwsr, "loadClass", clazz.getName());
79.55 + ret = code.invokeMethod(ret, method, args);
79.56 + } catch (ScriptException ex) {
79.57 + fail("Execution failed in " + dumpJS(codeSeq), ex);
79.58 + } catch (NoSuchMethodException ex) {
79.59 + fail("Cannot find method in " + dumpJS(codeSeq), ex);
79.60 + }
79.61 + if (ret == null && expRes == null) {
79.62 + return null;
79.63 + }
79.64 + if (expRes != null && expRes.equals(ret)) {
79.65 + return null;
79.66 + }
79.67 + if (expRes instanceof Number) {
79.68 + // in case of Long it is necessary convert it to number
79.69 + // since the Long is represented by two numbers in JavaScript
79.70 + try {
79.71 + ret = code.invokeMethod(ret, "toFP");
79.72 + ret = code.invokeFunction("Number", ret);
79.73 + } catch (ScriptException ex) {
79.74 + fail("Conversion to number failed in " + dumpJS(codeSeq), ex);
79.75 + } catch (NoSuchMethodException ex) {
79.76 + fail("Cannot find global Number(x) function in " + dumpJS(codeSeq), ex);
79.77 + }
79.78 + }
79.79 + return ret;
79.80 + }
79.81 +
79.82 + void assertExec(
79.83 + String msg, Class clazz, String method, Object expRes, Object... args
79.84 + ) throws Exception {
79.85 + Object ret = execCode(msg, clazz, method, expRes, args);
79.86 + if (ret == null) {
79.87 + return;
79.88 + }
79.89 + if (expRes != null && expRes.equals(ret)) {
79.90 + return;
79.91 + }
79.92 + assertEquals(ret, expRes, msg + "was: " + ret + "\n" + dumpJS(codeSeq));
79.93 + }
79.94 +
79.95 + static TestVM compileClass(String... names) throws ScriptException, IOException {
79.96 + return compileClass(null, names);
79.97 + }
79.98 +
79.99 + static TestVM compileClass(StringBuilder sb, String... names) throws ScriptException, IOException {
79.100 + return compileClass(sb, null, names);
79.101 + }
79.102 +
79.103 + static TestVM compileClass(StringBuilder sb, ScriptEngine[] eng, String... names) throws ScriptException, IOException {
79.104 + if (sb == null) {
79.105 + sb = new StringBuilder();
79.106 + }
79.107 + Bck2Brwsr.generate(sb, new EmulationResources(), names);
79.108 + ScriptEngineManager sem = new ScriptEngineManager();
79.109 + ScriptEngine js = sem.getEngineByExtension("js");
79.110 + if (eng != null) {
79.111 + eng[0] = js;
79.112 + }
79.113 + try {
79.114 + Object res = js.eval(sb.toString());
79.115 + assertTrue(js instanceof Invocable, "It is invocable object: " + res);
79.116 + return new TestVM((Invocable) js, sb);
79.117 + } catch (Exception ex) {
79.118 + if (sb.length() > 2000) {
79.119 + sb = dumpJS(sb);
79.120 + }
79.121 + fail("Could not evaluate:\n" + sb, ex);
79.122 + return null;
79.123 + }
79.124 + }
79.125 +
79.126 + Object loadClass(String loadClass, String name) throws ScriptException, NoSuchMethodException {
79.127 + return code.invokeMethod(bck2brwsr, "loadClass", Exceptions.class.getName());
79.128 + }
79.129 +
79.130 + Object invokeMethod(Object obj, String method, Object... params) throws ScriptException, NoSuchMethodException {
79.131 + return code.invokeMethod(obj, method, params);
79.132 + }
79.133 +
79.134 + Object invokeFunction(String methodName, Object... args) throws ScriptException, NoSuchMethodException {
79.135 + return code.invokeFunction(methodName, args);
79.136 + }
79.137 +
79.138 + static StringBuilder dumpJS(CharSequence sb) throws IOException {
79.139 + File f = File.createTempFile("execution", ".js");
79.140 + FileWriter w = new FileWriter(f);
79.141 + w.append(sb);
79.142 + w.close();
79.143 + return new StringBuilder(f.getPath());
79.144 + }
79.145 +
79.146 + @Override
79.147 + public String toString() {
79.148 + try {
79.149 + return dumpJS(codeSeq).toString();
79.150 + } catch (IOException ex) {
79.151 + return ex.toString();
79.152 + }
79.153 + }
79.154 +
79.155 +
79.156 + private static class EmulationResources implements Bck2Brwsr.Resources {
79.157 + @Override
79.158 + public InputStream get(String name) throws IOException {
79.159 + Enumeration<URL> en = StaticMethodTest.class.getClassLoader().getResources(name);
79.160 + URL u = null;
79.161 + while (en.hasMoreElements()) {
79.162 + u = en.nextElement();
79.163 + }
79.164 + if (u == null) {
79.165 + throw new IOException("Can't find " + name);
79.166 + }
79.167 + if (u.toExternalForm().contains("rt.jar!")) {
79.168 + throw new IOException("No emulation for " + u);
79.169 + }
79.170 + return u.openStream();
79.171 + }
79.172 + }
79.173 +}
80.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/VMLazyTest.java Fri Feb 15 11:54:45 2013 +0100
80.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/VMLazyTest.java Fri Feb 15 21:16:05 2013 +0100
80.3 @@ -17,7 +17,6 @@
80.4 */
80.5 package org.apidesign.vm4brwsr;
80.6
80.7 -import javax.script.Invocable;
80.8 import javax.script.ScriptContext;
80.9 import javax.script.ScriptEngine;
80.10 import javax.script.ScriptException;
80.11 @@ -30,10 +29,7 @@
80.12 * @author Jaroslav Tulach <jtulach@netbeans.org>
80.13 */
80.14 public class VMLazyTest {
80.15 -
80.16 -
80.17 - private static CharSequence codeSeq;
80.18 - private static Invocable code;
80.19 + private static TestVM code;
80.20
80.21 @BeforeClass
80.22 public void compileTheCode() throws Exception {
80.23 @@ -50,11 +46,10 @@
80.24 sb.append("\n}");
80.25
80.26 ScriptEngine[] arr = { null };
80.27 - code = StaticMethodTest.compileClass(sb, arr,
80.28 + code = TestVM.compileClass(sb, arr,
80.29 new String[]{"org/apidesign/vm4brwsr/VM", "org/apidesign/vm4brwsr/StaticMethod"}
80.30 );
80.31 arr[0].getContext().setAttribute("loader", new BytesLoader(), ScriptContext.ENGINE_SCOPE);
80.32 - codeSeq = sb;
80.33 }
80.34
80.35 @Test public void invokeStaticMethod() throws Exception {
80.36 @@ -83,9 +78,9 @@
80.37 try {
80.38 ret = code.invokeFunction(methodName, args);
80.39 } catch (ScriptException ex) {
80.40 - fail("Execution failed in\n" + StaticMethodTest.dumpJS(codeSeq), ex);
80.41 + fail("Execution failed in\n" + code.toString(), ex);
80.42 } catch (NoSuchMethodException ex) {
80.43 - fail("Cannot find method in\n" + StaticMethodTest.dumpJS(codeSeq), ex);
80.44 + fail("Cannot find method in\n" + code.toString(), ex);
80.45 }
80.46 if (ret == null && expRes == null) {
80.47 return;
80.48 @@ -93,6 +88,6 @@
80.49 if (expRes.equals(ret)) {
80.50 return;
80.51 }
80.52 - assertEquals(ret, expRes, msg + "was: " + ret + "\n" + StaticMethodTest.dumpJS(codeSeq));
80.53 + assertEquals(ret, expRes, msg + "was: " + ret + "\n" + code.toString());
80.54 }
80.55 }
81.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/VMinVMTest.java Fri Feb 15 11:54:45 2013 +0100
81.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/VMinVMTest.java Fri Feb 15 21:16:05 2013 +0100
81.3 @@ -21,7 +21,6 @@
81.4 import java.io.FileWriter;
81.5 import java.io.IOException;
81.6 import static org.testng.Assert.*;
81.7 -import javax.script.Invocable;
81.8 import org.testng.annotations.BeforeClass;
81.9 import org.testng.annotations.Test;
81.10
81.11 @@ -30,9 +29,7 @@
81.12 * @author Jaroslav Tulach <jtulach@netbeans.org>
81.13 */
81.14 public class VMinVMTest {
81.15 -
81.16 - private static CharSequence codeSeq;
81.17 - private static Invocable code;
81.18 + private static TestVM code;
81.19
81.20 @Test public void compareGeneratedCodeForArrayClass() throws Exception {
81.21 compareCode("org/apidesign/vm4brwsr/Array.class");
81.22 @@ -44,11 +41,7 @@
81.23
81.24 @BeforeClass
81.25 public void compileTheCode() throws Exception {
81.26 - StringBuilder sb = new StringBuilder();
81.27 - code = StaticMethodTest.compileClass(sb,
81.28 - "org/apidesign/vm4brwsr/VMinVM"
81.29 - );
81.30 - codeSeq = sb;
81.31 + code = TestVM.compileClass("org/apidesign/vm4brwsr/VMinVM");
81.32 }
81.33
81.34 private void compareCode(final String nm) throws Exception, IOException {
81.35 @@ -73,7 +66,7 @@
81.36 }
81.37 }
81.38 w.append("\n];\n");
81.39 - w.append(codeSeq);
81.40 + w.append(code.toString());
81.41 w.close();
81.42 throw new Exception(ex.getMessage() + " file: " + f, ex);
81.43 }
81.44 @@ -83,11 +76,11 @@
81.45
81.46 if (!ret1.toString().equals(ret)) {
81.47 StringBuilder msg = new StringBuilder("Difference found between ");
81.48 - msg.append(StaticMethodTest.dumpJS(ret1));
81.49 + msg.append(TestVM.dumpJS(ret1));
81.50 msg.append(" ");
81.51 - msg.append(StaticMethodTest.dumpJS((CharSequence) ret));
81.52 + msg.append(TestVM.dumpJS((CharSequence) ret));
81.53 msg.append(" compiled by ");
81.54 - msg.append(StaticMethodTest.dumpJS(codeSeq));
81.55 + msg.append(code.toString());
81.56 fail(msg.toString());
81.57 }
81.58 }
82.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
82.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/Http.java Fri Feb 15 21:16:05 2013 +0100
82.3 @@ -0,0 +1,56 @@
82.4 +/**
82.5 + * Back 2 Browser Bytecode Translator
82.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
82.7 + *
82.8 + * This program is free software: you can redistribute it and/or modify
82.9 + * it under the terms of the GNU General Public License as published by
82.10 + * the Free Software Foundation, version 2 of the License.
82.11 + *
82.12 + * This program is distributed in the hope that it will be useful,
82.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
82.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
82.15 + * GNU General Public License for more details.
82.16 + *
82.17 + * You should have received a copy of the GNU General Public License
82.18 + * along with this program. Look for COPYING file in the top folder.
82.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
82.20 + */
82.21 +package org.apidesign.bck2brwsr.vmtest;
82.22 +
82.23 +import java.lang.annotation.ElementType;
82.24 +import java.lang.annotation.Retention;
82.25 +import java.lang.annotation.RetentionPolicy;
82.26 +import java.lang.annotation.Target;
82.27 +
82.28 +/**
82.29 + * Exposes HTTP page or pages to the running {@link BrwsrTest}, so it can access under
82.30 + * the relative path.
82.31 + *
82.32 + * @author Jaroslav Tulach <jtulach@netbeans.org>
82.33 + */
82.34 +@Retention(RetentionPolicy.RUNTIME)
82.35 +@Target({ElementType.METHOD, ElementType.TYPE})
82.36 +public @interface Http {
82.37 + /** Set of pages to make available */
82.38 + public Resource[] value();
82.39 +
82.40 + /** Exposes an HTTP page to the running {@link BrwsrTest}, so it can access
82.41 + * under the relative path.
82.42 + *
82.43 + * @author Jaroslav Tulach <jtulach@netbeans.org>
82.44 + */
82.45 + @Retention(RetentionPolicy.RUNTIME)
82.46 + @Target({})
82.47 + public @interface Resource {
82.48 + /** path on the server that the test can use to access the exposed resource */
82.49 + String path();
82.50 + /** the content of the HttpResource */
82.51 + String content();
82.52 + /** resource relative to the class that should be used instead of <code>content</code>.
82.53 + * Leave content equal to empty string.
82.54 + */
82.55 + String resource() default "";
82.56 + /** mime type of the resource */
82.57 + String mimeType();
82.58 + }
82.59 +}
83.1 --- a/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/HttpResource.java Fri Feb 15 11:54:45 2013 +0100
83.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
83.3 @@ -1,43 +0,0 @@
83.4 -/**
83.5 - * Back 2 Browser Bytecode Translator
83.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
83.7 - *
83.8 - * This program is free software: you can redistribute it and/or modify
83.9 - * it under the terms of the GNU General Public License as published by
83.10 - * the Free Software Foundation, version 2 of the License.
83.11 - *
83.12 - * This program is distributed in the hope that it will be useful,
83.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
83.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
83.15 - * GNU General Public License for more details.
83.16 - *
83.17 - * You should have received a copy of the GNU General Public License
83.18 - * along with this program. Look for COPYING file in the top folder.
83.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
83.20 - */
83.21 -package org.apidesign.bck2brwsr.vmtest;
83.22 -
83.23 -import java.lang.annotation.ElementType;
83.24 -import java.lang.annotation.Retention;
83.25 -import java.lang.annotation.RetentionPolicy;
83.26 -import java.lang.annotation.Target;
83.27 -
83.28 -/** Exposes an HTTP page to the running {@link BrwsrTest}, so it can access
83.29 - * under the relative path.
83.30 - *
83.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
83.32 - */
83.33 -@Retention(RetentionPolicy.RUNTIME)
83.34 -@Target({ ElementType.METHOD, ElementType.TYPE})
83.35 -public @interface HttpResource {
83.36 - /** path on the server that the test can use to access the exposed resource */
83.37 - String path();
83.38 - /** the content of the HttpResource */
83.39 - String content();
83.40 - /** resource relative to the class that should be used instead of <code>content</code>.
83.41 - * Leave content equal to empty string.
83.42 - */
83.43 - String resource() default "";
83.44 - /** mime type of the resource */
83.45 - String mimeType();
83.46 -}
84.1 --- a/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java Fri Feb 15 11:54:45 2013 +0100
84.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java Fri Feb 15 21:16:05 2013 +0100
84.3 @@ -28,7 +28,7 @@
84.4 import org.apidesign.bck2brwsr.launcher.Launcher;
84.5 import org.apidesign.bck2brwsr.launcher.InvocationContext;
84.6 import org.apidesign.bck2brwsr.vmtest.HtmlFragment;
84.7 -import org.apidesign.bck2brwsr.vmtest.HttpResource;
84.8 +import org.apidesign.bck2brwsr.vmtest.Http;
84.9 import org.testng.ITest;
84.10 import org.testng.annotations.Test;
84.11
84.12 @@ -42,10 +42,10 @@
84.13 private final String type;
84.14 private final boolean fail;
84.15 private final HtmlFragment html;
84.16 - private final HttpResource http;
84.17 + private final Http.Resource[] http;
84.18 Object value;
84.19
84.20 - Bck2BrwsrCase(Method m, String type, Launcher l, boolean fail, HtmlFragment html, HttpResource http) {
84.21 + Bck2BrwsrCase(Method m, String type, Launcher l, boolean fail, HtmlFragment html, Http.Resource[] http) {
84.22 this.l = l;
84.23 this.m = m;
84.24 this.type = type;
84.25 @@ -62,12 +62,14 @@
84.26 c.setHtmlFragment(html.value());
84.27 }
84.28 if (http != null) {
84.29 - if (!http.content().isEmpty()) {
84.30 - InputStream is = new ByteArrayInputStream(http.content().getBytes("UTF-8"));
84.31 - c.setHttpResource(http.path(), http.mimeType(), is);
84.32 - } else {
84.33 - InputStream is = m.getDeclaringClass().getResourceAsStream(http.resource());
84.34 - c.setHttpResource(http.path(), http.mimeType(), is);
84.35 + for (Http.Resource r : http) {
84.36 + if (!r.content().isEmpty()) {
84.37 + InputStream is = new ByteArrayInputStream(r.content().getBytes("UTF-8"));
84.38 + c.addHttpResource(r.path(), r.mimeType(), is);
84.39 + } else {
84.40 + InputStream is = m.getDeclaringClass().getResourceAsStream(r.resource());
84.41 + c.addHttpResource(r.path(), r.mimeType(), is);
84.42 + }
84.43 }
84.44 }
84.45 String res = c.invoke();
85.1 --- a/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java Fri Feb 15 11:54:45 2013 +0100
85.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java Fri Feb 15 21:16:05 2013 +0100
85.3 @@ -135,9 +135,15 @@
85.4 if (f == null) {
85.5 f = m.getDeclaringClass().getAnnotation(HtmlFragment.class);
85.6 }
85.7 - HttpResource r = m.getAnnotation(HttpResource.class);
85.8 - if (r == null) {
85.9 - r = m.getDeclaringClass().getAnnotation(HttpResource.class);
85.10 + Http.Resource[] r = {};
85.11 + Http h = m.getAnnotation(Http.class);
85.12 + if (h == null) {
85.13 + h = m.getDeclaringClass().getAnnotation(Http.class);
85.14 + if (h != null) {
85.15 + r = h.value();
85.16 + }
85.17 + } else {
85.18 + r = h.value();
85.19 }
85.20 if (brwsr.length == 0) {
85.21 final Launcher s = l.brwsr(null);
86.1 --- a/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/GenerateZipProcessor.java Fri Feb 15 11:54:45 2013 +0100
86.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/GenerateZipProcessor.java Fri Feb 15 21:16:05 2013 +0100
86.3 @@ -25,6 +25,7 @@
86.4 import java.util.jar.JarOutputStream;
86.5 import java.util.jar.Manifest;
86.6 import javax.annotation.processing.AbstractProcessor;
86.7 +import javax.annotation.processing.Filer;
86.8 import javax.annotation.processing.Processor;
86.9 import javax.annotation.processing.RoundEnvironment;
86.10 import javax.annotation.processing.SupportedAnnotationTypes;
86.11 @@ -73,7 +74,8 @@
86.12 }
86.13
86.14 private void generateJar(PackageElement pe, GenerateZip gz, Element e) throws IOException {
86.15 - FileObject res = processingEnv.getFiler().createResource(
86.16 + final Filer filer = processingEnv.getFiler();
86.17 + FileObject res = filer.createResource(
86.18 StandardLocation.CLASS_OUTPUT,
86.19 pe.getQualifiedName().toString(),
86.20 gz.name(), e
86.21 @@ -93,6 +95,7 @@
86.22 jar.write(arr[i + 1].getBytes("UTF-8"));
86.23 jar.closeEntry();
86.24 }
86.25 + jar.close();
86.26 }
86.27 -
86.28 +
86.29 }
87.1 --- a/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java Fri Feb 15 11:54:45 2013 +0100
87.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java Fri Feb 15 21:16:05 2013 +0100
87.3 @@ -47,6 +47,19 @@
87.4 return "Ahoj".equals(null);
87.5 }
87.6
87.7 + @Compare public int highByteLenght() {
87.8 + byte[] arr= { 77,97,110,105,102,101,115,116,45,86,101,114,115,105,111,110 };
87.9 + return new String(arr, 0).length();
87.10 + }
87.11 +
87.12 + @Compare public String highByte() {
87.13 + byte[] arr= { 77,97,110,105,102,101,115,116,45,86,101,114,115,105,111,110 };
87.14 + StringBuilder sb = new StringBuilder();
87.15 + sb.append("pref:");
87.16 + sb.append(new String(arr, 0));
87.17 + return sb.toString();
87.18 + }
87.19 +
87.20 @Compare public static Object compareURLs() throws MalformedURLException {
87.21 return new URL("http://apidesign.org:8080/wiki/").toExternalForm().toString();
87.22 }
88.1 --- a/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/HttpResourceTest.java Fri Feb 15 11:54:45 2013 +0100
88.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/HttpResourceTest.java Fri Feb 15 21:16:05 2013 +0100
88.3 @@ -21,7 +21,7 @@
88.4 import java.net.URL;
88.5 import org.apidesign.bck2brwsr.core.JavaScriptBody;
88.6 import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
88.7 -import org.apidesign.bck2brwsr.vmtest.HttpResource;
88.8 +import org.apidesign.bck2brwsr.vmtest.Http;
88.9 import org.apidesign.bck2brwsr.vmtest.VMTest;
88.10 import org.testng.annotations.Factory;
88.11
88.12 @@ -31,15 +31,21 @@
88.13 */
88.14 public class HttpResourceTest {
88.15
88.16 - @HttpResource(path = "/xhr", content = "Hello Brwsr!", mimeType = "text/plain")
88.17 + @Http({
88.18 + @Http.Resource(path = "/xhr", content = "Hello Brwsr!", mimeType = "text/plain")
88.19 + })
88.20 @BrwsrTest
88.21 +
88.22 +
88.23 public String testReadContentViaXHR() throws Exception {
88.24 String msg = read("/xhr");
88.25 assert "Hello Brwsr!".equals(msg) : "The message was " + msg;
88.26 return msg;
88.27 }
88.28
88.29 - @HttpResource(path = "/url", content = "Hello via URL!", mimeType = "text/plain")
88.30 + @Http({
88.31 + @Http.Resource(path = "/url", content = "Hello via URL!", mimeType = "text/plain")
88.32 + })
88.33 @BrwsrTest
88.34 public String testReadContentViaURL() throws Exception {
88.35 URL url = new URL("http:/url");
88.36 @@ -47,7 +53,9 @@
88.37 assert "Hello via URL!".equals(msg) : "The message was " + msg;
88.38 return msg;
88.39 }
88.40 - @HttpResource(path = "/url", content = "Hello via URL!", mimeType = "text/plain")
88.41 + @Http({
88.42 + @Http.Resource(path = "/url", content = "Hello via URL!", mimeType = "text/plain")
88.43 + })
88.44 @BrwsrTest
88.45 public String testReadContentViaURLWithStringParam() throws Exception {
88.46 URL url = new URL("http:/url");
88.47 @@ -56,7 +64,9 @@
88.48 return msg;
88.49 }
88.50
88.51 - @HttpResource(path = "/bytes", content = "", resource = "0xfe", mimeType = "x-application/binary")
88.52 + @Http({
88.53 + @Http.Resource(path = "/bytes", content = "", resource = "0xfe", mimeType = "x-application/binary")
88.54 + })
88.55 @BrwsrTest
88.56 public void testReadByte() throws Exception {
88.57 URL url = new URL("http:/bytes");
88.58 @@ -67,7 +77,9 @@
88.59 assert arr[0] == 0xfe : "It is 0xfe: " + Integer.toHexString(arr[0]);
88.60 }
88.61
88.62 - @HttpResource(path = "/bytes", content = "", resource = "0xfe", mimeType = "x-application/binary")
88.63 + @Http({
88.64 + @Http.Resource(path = "/bytes", content = "", resource = "0xfe", mimeType = "x-application/binary")
88.65 + })
88.66 @BrwsrTest
88.67 public void testReadByteViaInputStream() throws Exception {
88.68 URL url = new URL("http:/bytes");
89.1 --- a/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java Fri Feb 15 11:54:45 2013 +0100
89.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java Fri Feb 15 21:16:05 2013 +0100
89.3 @@ -17,6 +17,8 @@
89.4 */
89.5 package org.apidesign.bck2brwsr.tck;
89.6
89.7 +import java.lang.annotation.Retention;
89.8 +import java.lang.annotation.RetentionPolicy;
89.9 import java.lang.reflect.Method;
89.10 import java.util.Arrays;
89.11 import java.util.Collections;
89.12 @@ -47,6 +49,14 @@
89.13 return long.class.toString();
89.14 }
89.15
89.16 + @Compare public boolean isRunnableInterface() {
89.17 + return Runnable.class.isInterface();
89.18 + }
89.19 +
89.20 + @Compare public String isRunnableHasRunMethod() throws NoSuchMethodException {
89.21 + return Runnable.class.getMethod("run").getName();
89.22 + }
89.23 +
89.24 @Compare public String namesOfMethods() {
89.25 StringBuilder sb = new StringBuilder();
89.26 String[] arr = new String[20];
89.27 @@ -59,6 +69,19 @@
89.28 }
89.29 return sb.toString();
89.30 }
89.31 +
89.32 + @Compare public String namesOfDeclaringClassesOfMethods() {
89.33 + StringBuilder sb = new StringBuilder();
89.34 + String[] arr = new String[20];
89.35 + int i = 0;
89.36 + for (Method m : StaticUse.class.getMethods()) {
89.37 + arr[i++] = m.getName() + "@" + m.getDeclaringClass().getName();
89.38 + }
89.39 + for (String s : sort(arr, i)) {
89.40 + sb.append(s).append("\n");
89.41 + }
89.42 + return sb.toString();
89.43 + }
89.44
89.45 @Compare public String cannotCallNonStaticMethodWithNull() throws Exception {
89.46 StaticUse.class.getMethod("instanceMethod").invoke(null);
89.47 @@ -69,6 +92,26 @@
89.48 return StaticUse.class.getMethod("instanceMethod").getReturnType();
89.49 }
89.50
89.51 + @Retention(RetentionPolicy.RUNTIME)
89.52 + @interface Ann {
89.53 + }
89.54 +
89.55 + @Compare public String annoClass() throws Exception {
89.56 + Retention r = Ann.class.getAnnotation(Retention.class);
89.57 + assert r != null : "Annotation is present";
89.58 + assert r.value() == RetentionPolicy.RUNTIME : "Policy value is OK: " + r.value();
89.59 + return r.annotationType().getName();
89.60 + }
89.61 +
89.62 + @Compare public boolean isAnnotation() {
89.63 + return Ann.class.isAnnotation();
89.64 + }
89.65 + @Compare public boolean isNotAnnotation() {
89.66 + return String.class.isAnnotation();
89.67 + }
89.68 + @Compare public boolean isNotAnnotationEnum() {
89.69 + return E.class.isAnnotation();
89.70 + }
89.71 enum E { A, B };
89.72 @Compare public boolean isEnum() {
89.73 return E.A.getClass().isEnum();
90.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
90.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipEntryTest.java Fri Feb 15 21:16:05 2013 +0100
90.3 @@ -0,0 +1,67 @@
90.4 +/**
90.5 + * Back 2 Browser Bytecode Translator
90.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
90.7 + *
90.8 + * This program is free software: you can redistribute it and/or modify
90.9 + * it under the terms of the GNU General Public License as published by
90.10 + * the Free Software Foundation, version 2 of the License.
90.11 + *
90.12 + * This program is distributed in the hope that it will be useful,
90.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
90.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
90.15 + * GNU General Public License for more details.
90.16 + *
90.17 + * You should have received a copy of the GNU General Public License
90.18 + * along with this program. Look for COPYING file in the top folder.
90.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
90.20 + */
90.21 +package org.apidesign.bck2brwsr.vmtest.impl;
90.22 +
90.23 +import java.io.ByteArrayInputStream;
90.24 +import java.io.IOException;
90.25 +import java.io.InputStream;
90.26 +import org.apidesign.bck2brwsr.emul.zip.FastJar;
90.27 +import org.testng.annotations.Test;
90.28 +import static org.testng.Assert.*;
90.29 +
90.30 +/**
90.31 + *
90.32 + * @author Jaroslav Tulach <jtulach@netbeans.org>
90.33 + */
90.34 +@GenerateZip(name = "five.zip", contents = {
90.35 + "1.txt", "one",
90.36 + "2.txt", "duo",
90.37 + "3.txt", "three",
90.38 + "4.txt", "four",
90.39 + "5.txt", "five"
90.40 +})
90.41 +public class ZipEntryTest {
90.42 + @Test
90.43 + public void readEntriesEffectively() throws IOException {
90.44 + InputStream is = ZipEntryTest.class.getResourceAsStream("five.zip");
90.45 + byte[] arr = new byte[is.available()];
90.46 + int len = is.read(arr);
90.47 + assertEquals(len, arr.length, "Read fully");
90.48 +
90.49 + FastJar fj = new FastJar(arr);
90.50 + FastJar.Entry[] entrs = fj.list();
90.51 +
90.52 + assertEquals(5, entrs.length, "Five entries");
90.53 +
90.54 + for (int i = 1; i <= 5; i++) {
90.55 + FastJar.Entry en = entrs[i - 1];
90.56 + assertEquals(en.name, i + ".txt");
90.57 +// assertEquals(cis.cnt, 0, "Content of the file should be skipped, not read");
90.58 + }
90.59 +
90.60 + assertContent("three", fj.getInputStream(entrs[3 - 1]), "read OK");
90.61 + assertContent("five", fj.getInputStream(entrs[5 - 1]), "read OK");
90.62 + }
90.63 +
90.64 + private static void assertContent(String exp, InputStream is, String msg) throws IOException {
90.65 + byte[] arr = new byte[512];
90.66 + int len = is.read(arr);
90.67 + String s = new String(arr, 0, len);
90.68 + assertEquals(exp, s, msg);
90.69 + }
90.70 +}
91.1 --- a/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java Fri Feb 15 11:54:45 2013 +0100
91.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java Fri Feb 15 21:16:05 2013 +0100
91.3 @@ -25,7 +25,7 @@
91.4 import org.apidesign.bck2brwsr.core.JavaScriptBody;
91.5 import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
91.6 import org.apidesign.bck2brwsr.vmtest.Compare;
91.7 -import org.apidesign.bck2brwsr.vmtest.HttpResource;
91.8 +import org.apidesign.bck2brwsr.vmtest.Http;
91.9 import org.apidesign.bck2brwsr.vmtest.VMTest;
91.10 import org.testng.annotations.Factory;
91.11
91.12 @@ -54,13 +54,15 @@
91.13 }
91.14
91.15 @JavaScriptBody(args = { "res", "path" }, body =
91.16 - "var myvm = new bck2brwsr(path);\n"
91.17 + "var myvm = bck2brwsr.apply(null, path);\n"
91.18 + "var cls = myvm.loadClass('java.lang.String');\n"
91.19 + "return cls.getClass__Ljava_lang_Class_2().getResourceAsStream__Ljava_io_InputStream_2Ljava_lang_String_2(res);\n"
91.20 )
91.21 private static native Object loadVMResource(String res, String...path);
91.22
91.23 - @HttpResource(path = "/readAnEntry.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip")
91.24 + @Http({
91.25 + @Http.Resource(path = "/readAnEntry.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip")
91.26 + })
91.27 @BrwsrTest public void canVmLoadResourceFromZip() throws IOException {
91.28 Object res = loadVMResource("/my/main/file.txt", "/readAnEntry.jar");
91.29 assert res instanceof InputStream : "Got array of bytes: " + res;
91.30 @@ -74,6 +76,28 @@
91.31 assertEquals(ret, "Hello World!", "Can read the bytes");
91.32 }
91.33
91.34 + @GenerateZip(name = "cpattr.zip", contents = {
91.35 + "META-INF/MANIFEST.MF", "Manifest-Version: 1.0\n"
91.36 + + "Created-By: hand\n"
91.37 + + "Class-Path: realJar.jar\n\n\n"
91.38 + })
91.39 + @Http({
91.40 + @Http.Resource(path = "/readComplexEntry.jar", mimeType = "x-application/zip", content = "", resource="cpattr.zip"),
91.41 + @Http.Resource(path = "/realJar.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip"),
91.42 + })
91.43 + @BrwsrTest public void understandsClassPathAttr() throws IOException {
91.44 + Object res = loadVMResource("/my/main/file.txt", "/readComplexEntry.jar");
91.45 + assert res instanceof InputStream : "Got array of bytes: " + res;
91.46 + InputStream is = (InputStream)res;
91.47 +
91.48 + byte[] arr = new byte[4096];
91.49 + int len = is.read(arr);
91.50 +
91.51 + final String ret = new String(arr, 0, len, "UTF-8");
91.52 +
91.53 + assertEquals(ret, "Hello World!", "Can read the bytes from secondary JAR");
91.54 + }
91.55 +
91.56 private static void assertEquals(Object real, Object exp, String msg) {
91.57 assert Objects.equals(exp, real) : msg + " exp: " + exp + " real: " + real;
91.58 }