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.Exported;
40 import org.apidesign.bck2brwsr.core.JavaScriptBody;
44 * @author Tomas Zezula
46 public final class FastJar {
47 private final byte[] arr;
49 public FastJar(byte[] arr) {
54 private static final int GIVE_UP = 1<<16;
56 public static final class Entry {
58 public final String name;
60 private final long dosTime;
62 Entry (String name, long offset, long time) {
69 public long getTime () {
70 Date d = new Date((int)(((dosTime >> 25) & 0x7f) + 80),
71 (int)(((dosTime >> 21) & 0x0f) - 1),
72 (int)((dosTime >> 16) & 0x1f),
73 (int)((dosTime >> 11) & 0x1f),
74 (int)((dosTime >> 5) & 0x3f),
75 (int)((dosTime << 1) & 0x3e));
81 public InputStream getInputStream (final Entry e) throws IOException {
82 return getInputStream(arr, e.offset);
85 private static InputStream getInputStream (byte[] arr, final long offset) throws IOException {
86 ByteArrayInputStream is = new ByteArrayInputStream(arr);
88 ZipInputStream in = new ZipInputStream (is);
89 ZipEntry e = in.getNextEntry();
90 if (e != null && e.getCrc() == 0L && e.getMethod() == ZipEntry.STORED) {
91 int cp = arr.length - is.available();
92 return new ByteArrayInputStream(arr, cp, (int)e.getSize());
97 public Entry[] list() throws IOException {
98 final int size = arr.length;
100 int at = size - ZipInputStream.ENDHDR;
102 byte[] data = new byte[ZipInputStream.ENDHDR];
106 FastJar.arraycopy(arr, at, data, 0, data.length);
109 if (giveup > GIVE_UP) {
110 throw new IOException ();
112 } while (getsig(data) != ZipInputStream.ENDSIG);
115 final long censize = endsiz(data);
116 final long cenoff = endoff(data);
119 Entry[] result = new Entry[0];
121 data = new byte[ZipInputStream.CENHDR];
122 while (cenread < censize) {
123 FastJar.arraycopy(arr, at, data, 0, data.length);
125 if (getsig(data) != ZipInputStream.CENSIG) {
126 throw new IOException("No central table"); //NOI18N
128 int cennam = cennam(data);
129 int cenext = cenext(data);
130 int cencom = cencom(data);
131 long lhoff = cenoff(data);
132 long centim = centim(data);
133 String name = new String(arr, at, cennam, "UTF-8");
135 int seekby = cenext+cencom;
136 int cendatalen = ZipInputStream.CENHDR + cennam + seekby;
138 result = addEntry(result, new Entry(name,lhoff, centim));
144 private Entry[] addEntry(Entry[] result, Entry entry) {
145 Entry[] e = new Entry[result.length + 1];
146 e[result.length] = entry;
147 FastJar.arraycopy(result, 0, e, 0, result.length);
151 private static final long getsig(final byte[] b) throws IOException {return get32(b,0);}
152 private static final long endsiz(final byte[] b) throws IOException {return get32(b,ZipInputStream.ENDSIZ);}
153 private static final long endoff(final byte[] b) throws IOException {return get32(b,ZipInputStream.ENDOFF);}
154 private static final long cenlen(final byte[] b) throws IOException {return get32(b,ZipInputStream.CENLEN);}
155 private static final long censiz(final byte[] b) throws IOException {return get32(b,ZipInputStream.CENSIZ);}
156 private static final long centim(final byte[] b) throws IOException {return get32(b,ZipInputStream.CENTIM);}
157 private static final int cennam(final byte[] b) throws IOException {return get16(b,ZipInputStream.CENNAM);}
158 private static final int cenext(final byte[] b) throws IOException {return get16(b,ZipInputStream.CENEXT);}
159 private static final int cencom(final byte[] b) throws IOException {return get16(b,ZipInputStream.CENCOM);}
160 private static final long cenoff (final byte[] b) throws IOException {return get32(b,ZipInputStream.CENOFF);}
161 private static final int lochow(final byte[] b) throws IOException {return get16(b,ZipInputStream.LOCHOW);}
162 private static final int locname(final byte[] b) throws IOException {return get16(b,ZipInputStream.LOCNAM);}
163 private static final int locext(final byte[] b) throws IOException {return get16(b,ZipInputStream.LOCEXT);}
164 private static final long locsiz(final byte[] b) throws IOException {return get32(b,ZipInputStream.LOCSIZ);}
166 private static final int get16(final byte[] b, int off) throws IOException {
167 final int b1 = b[off];
168 final int b2 = b[off+1];
169 return (b1 & 0xff) | ((b2 & 0xff) << 8);
172 private static final long get32(final byte[] b, int off) throws IOException {
173 final int s1 = get16(b, off);
174 final int s2 = get16(b, off+2);
175 return s1 | ((long)s2 << 16);
178 @JavaScriptBody(args = {"value", "srcBegin", "dst", "dstBegin", "count"}, body
179 = "if (srcBegin < dstBegin) {\n"
180 + " while (count-- > 0) {\n"
181 + " dst[dstBegin + count] = value[srcBegin + count];\n"
184 + " while (count-- > 0) {\n"
185 + " dst[dstBegin++] = value[srcBegin++];\n"
191 static void arraycopy(Object src, int srcBegin, Object dst, int dstBegin, int count) {
193 Class<?> system = Class.forName("java.lang.System");
194 Method m = system.getMethod("arraycopy", Object.class, int.class, Object.class, int.class, int.class);
195 m.invoke(null, src, srcBegin, dst, dstBegin, count);
196 } catch (Exception ex) {
197 throw new IllegalStateException(ex);