2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4 * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
6 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7 * Other names may be trademarks of their respective owners.
9 * The contents of this file are subject to the terms of either the GNU
10 * General Public License Version 2 only ("GPL") or the Common
11 * Development and Distribution License("CDDL") (collectively, the
12 * "License"). You may not use this file except in compliance with the
13 * License. You can obtain a copy of the License at
14 * http://www.netbeans.org/cddl-gplv2.html
15 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16 * specific language governing permissions and limitations under the
17 * License. When distributing the software, include this License Header
18 * Notice in each file and include the License file at
19 * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
20 * particular file as subject to the "Classpath" exception as provided
21 * by Oracle in the GPL Version 2 section of the License file that
22 * accompanied this code. If applicable, add the following below the
23 * License Header, with the fields enclosed by brackets [] replaced by
24 * your own identifying information:
25 * "Portions Copyrighted [year] [name of copyright owner]"
29 * Portions Copyrighted 2007 Sun Microsystems, Inc.
31 package org.apidesign.bck2brwsr.emul.zip;
33 import java.io.ByteArrayInputStream;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.lang.reflect.Method;
37 import java.util.zip.ZipEntry;
38 import java.util.zip.ZipInputStream;
39 import org.apidesign.bck2brwsr.core.JavaScriptBody;
43 * @author Tomas Zezula
45 public final class FastJar {
46 private final byte[] arr;
48 public FastJar(byte[] arr) {
53 private static final int GIVE_UP = 1<<16;
55 public static final class Entry {
57 public final String name;
59 private final long dosTime;
61 Entry (String name, long offset, long time) {
68 public long getTime () {
69 Date d = new Date((int)(((dosTime >> 25) & 0x7f) + 80),
70 (int)(((dosTime >> 21) & 0x0f) - 1),
71 (int)((dosTime >> 16) & 0x1f),
72 (int)((dosTime >> 11) & 0x1f),
73 (int)((dosTime >> 5) & 0x3f),
74 (int)((dosTime << 1) & 0x3e));
80 public InputStream getInputStream (final Entry e) throws IOException {
81 return getInputStream(arr, e.offset);
84 private static InputStream getInputStream (byte[] arr, final long offset) throws IOException {
85 ByteArrayInputStream is = new ByteArrayInputStream(arr);
87 ZipInputStream in = new ZipInputStream (is);
88 ZipEntry e = in.getNextEntry();
89 if (e != null && e.getCrc() == 0L && e.getMethod() == ZipEntry.STORED) {
90 int cp = arr.length - is.available();
91 return new ByteArrayInputStream(arr, cp, (int)e.getSize());
96 public Entry[] list() throws IOException {
97 final int size = arr.length;
99 int at = size - ZipInputStream.ENDHDR;
101 byte[] data = new byte[ZipInputStream.ENDHDR];
105 FastJar.arraycopy(arr, at, data, 0, data.length);
108 if (giveup > GIVE_UP) {
109 throw new IOException ();
111 } while (getsig(data) != ZipInputStream.ENDSIG);
114 final long censize = endsiz(data);
115 final long cenoff = endoff(data);
118 Entry[] result = new Entry[0];
120 data = new byte[ZipInputStream.CENHDR];
121 while (cenread < censize) {
122 FastJar.arraycopy(arr, at, data, 0, data.length);
124 if (getsig(data) != ZipInputStream.CENSIG) {
125 throw new IOException("No central table"); //NOI18N
127 int cennam = cennam(data);
128 int cenext = cenext(data);
129 int cencom = cencom(data);
130 long lhoff = cenoff(data);
131 long centim = centim(data);
132 String name = new String(arr, at, cennam, "UTF-8");
134 int seekby = cenext+cencom;
135 int cendatalen = ZipInputStream.CENHDR + cennam + seekby;
137 result = addEntry(result, new Entry(name,lhoff, centim));
143 private Entry[] addEntry(Entry[] result, Entry entry) {
144 Entry[] e = new Entry[result.length + 1];
145 e[result.length] = entry;
146 FastJar.arraycopy(result, 0, e, 0, result.length);
150 private static final long getsig(final byte[] b) throws IOException {return get32(b,0);}
151 private static final long endsiz(final byte[] b) throws IOException {return get32(b,ZipInputStream.ENDSIZ);}
152 private static final long endoff(final byte[] b) throws IOException {return get32(b,ZipInputStream.ENDOFF);}
153 private static final long cenlen(final byte[] b) throws IOException {return get32(b,ZipInputStream.CENLEN);}
154 private static final long censiz(final byte[] b) throws IOException {return get32(b,ZipInputStream.CENSIZ);}
155 private static final long centim(final byte[] b) throws IOException {return get32(b,ZipInputStream.CENTIM);}
156 private static final int cennam(final byte[] b) throws IOException {return get16(b,ZipInputStream.CENNAM);}
157 private static final int cenext(final byte[] b) throws IOException {return get16(b,ZipInputStream.CENEXT);}
158 private static final int cencom(final byte[] b) throws IOException {return get16(b,ZipInputStream.CENCOM);}
159 private static final long cenoff (final byte[] b) throws IOException {return get32(b,ZipInputStream.CENOFF);}
160 private static final int lochow(final byte[] b) throws IOException {return get16(b,ZipInputStream.LOCHOW);}
161 private static final int locname(final byte[] b) throws IOException {return get16(b,ZipInputStream.LOCNAM);}
162 private static final int locext(final byte[] b) throws IOException {return get16(b,ZipInputStream.LOCEXT);}
163 private static final long locsiz(final byte[] b) throws IOException {return get32(b,ZipInputStream.LOCSIZ);}
165 private static final int get16(final byte[] b, int off) throws IOException {
166 final int b1 = b[off];
167 final int b2 = b[off+1];
168 return (b1 & 0xff) | ((b2 & 0xff) << 8);
171 private static final long get32(final byte[] b, int off) throws IOException {
172 final int s1 = get16(b, off);
173 final int s2 = get16(b, off+2);
174 return s1 | ((long)s2 << 16);
177 @JavaScriptBody(args = {"value", "srcBegin", "dst", "dstBegin", "count"}, body
178 = "if (srcBegin < dstBegin) {\n"
179 + " while (count-- > 0) {\n"
180 + " dst[dstBegin + count] = value[srcBegin + count];\n"
183 + " while (count-- > 0) {\n"
184 + " dst[dstBegin++] = value[srcBegin++];\n"
188 static void arraycopy(Object src, int srcBegin, Object dst, int dstBegin, int count) {
190 Class<?> system = Class.forName("java.lang.System");
191 Method m = system.getMethod("arraycopy", Object.class, int.class, Object.class, int.class, int.class);
192 m.invoke(null, src, srcBegin, dst, dstBegin, count);
193 } catch (Exception ex) {
194 throw new IllegalStateException(ex);