jaroslav@705
|
1 |
/*
|
jaroslav@705
|
2 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
jaroslav@705
|
3 |
*
|
jaroslav@705
|
4 |
* Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
jaroslav@705
|
5 |
*
|
jaroslav@705
|
6 |
* Oracle and Java are registered trademarks of Oracle and/or its affiliates.
|
jaroslav@705
|
7 |
* Other names may be trademarks of their respective owners.
|
jaroslav@705
|
8 |
*
|
jaroslav@705
|
9 |
* The contents of this file are subject to the terms of either the GNU
|
jaroslav@705
|
10 |
* General Public License Version 2 only ("GPL") or the Common
|
jaroslav@705
|
11 |
* Development and Distribution License("CDDL") (collectively, the
|
jaroslav@705
|
12 |
* "License"). You may not use this file except in compliance with the
|
jaroslav@705
|
13 |
* License. You can obtain a copy of the License at
|
jaroslav@705
|
14 |
* http://www.netbeans.org/cddl-gplv2.html
|
jaroslav@705
|
15 |
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
|
jaroslav@705
|
16 |
* specific language governing permissions and limitations under the
|
jaroslav@705
|
17 |
* License. When distributing the software, include this License Header
|
jaroslav@705
|
18 |
* Notice in each file and include the License file at
|
jaroslav@705
|
19 |
* nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
|
jaroslav@705
|
20 |
* particular file as subject to the "Classpath" exception as provided
|
jaroslav@705
|
21 |
* by Oracle in the GPL Version 2 section of the License file that
|
jaroslav@705
|
22 |
* accompanied this code. If applicable, add the following below the
|
jaroslav@705
|
23 |
* License Header, with the fields enclosed by brackets [] replaced by
|
jaroslav@705
|
24 |
* your own identifying information:
|
jaroslav@705
|
25 |
* "Portions Copyrighted [year] [name of copyright owner]"
|
jaroslav@705
|
26 |
*
|
jaroslav@705
|
27 |
* Contributor(s):
|
jaroslav@705
|
28 |
*
|
jaroslav@705
|
29 |
* Portions Copyrighted 2007 Sun Microsystems, Inc.
|
jaroslav@705
|
30 |
*/
|
jaroslav@706
|
31 |
package org.apidesign.bck2brwsr.emul.zip;
|
jaroslav@705
|
32 |
|
jaroslav@706
|
33 |
import java.io.ByteArrayInputStream;
|
jaroslav@705
|
34 |
import java.io.IOException;
|
jaroslav@705
|
35 |
import java.io.InputStream;
|
jaroslav@705
|
36 |
import java.util.zip.ZipEntry;
|
jaroslav@705
|
37 |
import java.util.zip.ZipInputStream;
|
jaroslav@705
|
38 |
|
jaroslav@705
|
39 |
/**
|
jaroslav@705
|
40 |
*
|
jaroslav@705
|
41 |
* @author Tomas Zezula
|
jaroslav@705
|
42 |
*/
|
jaroslav@705
|
43 |
public final class FastJar {
|
jaroslav@706
|
44 |
private final byte[] arr;
|
jaroslav@705
|
45 |
|
jaroslav@706
|
46 |
public FastJar(byte[] arr) {
|
jaroslav@706
|
47 |
this.arr = arr;
|
jaroslav@705
|
48 |
}
|
jaroslav@705
|
49 |
|
jaroslav@705
|
50 |
|
jaroslav@705
|
51 |
private static final int GIVE_UP = 1<<16;
|
jaroslav@705
|
52 |
|
jaroslav@705
|
53 |
public static final class Entry {
|
jaroslav@705
|
54 |
|
jaroslav@705
|
55 |
public final String name;
|
jaroslav@705
|
56 |
final long offset;
|
jaroslav@705
|
57 |
private final long dosTime;
|
jaroslav@705
|
58 |
|
jaroslav@706
|
59 |
Entry (String name, long offset, long time) {
|
jaroslav@705
|
60 |
assert name != null;
|
jaroslav@705
|
61 |
this.name = name;
|
jaroslav@705
|
62 |
this.offset = offset;
|
jaroslav@705
|
63 |
this.dosTime = time;
|
jaroslav@705
|
64 |
}
|
jaroslav@706
|
65 |
/*
|
jaroslav@705
|
66 |
public long getTime () {
|
jaroslav@705
|
67 |
Date d = new Date((int)(((dosTime >> 25) & 0x7f) + 80),
|
jaroslav@705
|
68 |
(int)(((dosTime >> 21) & 0x0f) - 1),
|
jaroslav@705
|
69 |
(int)((dosTime >> 16) & 0x1f),
|
jaroslav@705
|
70 |
(int)((dosTime >> 11) & 0x1f),
|
jaroslav@705
|
71 |
(int)((dosTime >> 5) & 0x3f),
|
jaroslav@705
|
72 |
(int)((dosTime << 1) & 0x3e));
|
jaroslav@705
|
73 |
return d.getTime();
|
jaroslav@705
|
74 |
}
|
jaroslav@706
|
75 |
*/
|
jaroslav@705
|
76 |
}
|
jaroslav@705
|
77 |
|
jaroslav@706
|
78 |
public InputStream getInputStream (final Entry e) throws IOException {
|
jaroslav@706
|
79 |
return getInputStream(arr, e.offset);
|
jaroslav@705
|
80 |
}
|
jaroslav@705
|
81 |
|
jaroslav@706
|
82 |
private static InputStream getInputStream (byte[] arr, final long offset) throws IOException {
|
jaroslav@706
|
83 |
ByteArrayInputStream is = new ByteArrayInputStream(arr);
|
jaroslav@706
|
84 |
is.skip(offset);
|
jaroslav@706
|
85 |
ZipInputStream in = new ZipInputStream (is);
|
jaroslav@705
|
86 |
ZipEntry e = in.getNextEntry();
|
jaroslav@705
|
87 |
if (e != null && e.getCrc() == 0L && e.getMethod() == ZipEntry.STORED) {
|
jaroslav@706
|
88 |
int cp = arr.length - is.available();
|
jaroslav@706
|
89 |
return new ByteArrayInputStream(arr, cp, (int)e.getSize());
|
jaroslav@705
|
90 |
}
|
jaroslav@705
|
91 |
return in;
|
jaroslav@705
|
92 |
}
|
jaroslav@705
|
93 |
|
jaroslav@706
|
94 |
public Entry[] list() throws IOException {
|
jaroslav@706
|
95 |
final int size = arr.length;
|
jaroslav@706
|
96 |
|
jaroslav@706
|
97 |
int at = size - ZipInputStream.ENDHDR;
|
jaroslav@706
|
98 |
|
jaroslav@706
|
99 |
byte[] data = new byte[ZipInputStream.ENDHDR];
|
jaroslav@706
|
100 |
int giveup = 0;
|
jaroslav@706
|
101 |
|
jaroslav@706
|
102 |
do {
|
jaroslav@706
|
103 |
org.apidesign.bck2brwsr.emul.lang.System.arraycopy(arr, at, data, 0, data.length);
|
jaroslav@706
|
104 |
at--;
|
jaroslav@706
|
105 |
giveup++;
|
jaroslav@706
|
106 |
if (giveup > GIVE_UP) {
|
jaroslav@706
|
107 |
throw new IOException ();
|
jaroslav@705
|
108 |
}
|
jaroslav@706
|
109 |
} while (getsig(data) != ZipInputStream.ENDSIG);
|
jaroslav@706
|
110 |
|
jaroslav@706
|
111 |
|
jaroslav@706
|
112 |
final long censize = endsiz(data);
|
jaroslav@706
|
113 |
final long cenoff = endoff(data);
|
jaroslav@706
|
114 |
at = (int) cenoff;
|
jaroslav@706
|
115 |
|
jaroslav@706
|
116 |
Entry[] result = new Entry[0];
|
jaroslav@706
|
117 |
int cenread = 0;
|
jaroslav@706
|
118 |
data = new byte[ZipInputStream.CENHDR];
|
jaroslav@706
|
119 |
while (cenread < censize) {
|
jaroslav@706
|
120 |
org.apidesign.bck2brwsr.emul.lang.System.arraycopy(arr, at, data, 0, data.length);
|
jaroslav@706
|
121 |
at += data.length;
|
jaroslav@706
|
122 |
if (getsig(data) != ZipInputStream.CENSIG) {
|
jaroslav@706
|
123 |
throw new IOException("No central table"); //NOI18N
|
jaroslav@706
|
124 |
}
|
jaroslav@706
|
125 |
int cennam = cennam(data);
|
jaroslav@706
|
126 |
int cenext = cenext(data);
|
jaroslav@706
|
127 |
int cencom = cencom(data);
|
jaroslav@706
|
128 |
long lhoff = cenoff(data);
|
jaroslav@706
|
129 |
long centim = centim(data);
|
jaroslav@706
|
130 |
String name = new String(arr, at, cennam, "UTF-8");
|
jaroslav@706
|
131 |
at += cennam;
|
jaroslav@706
|
132 |
int seekby = cenext+cencom;
|
jaroslav@706
|
133 |
int cendatalen = ZipInputStream.CENHDR + cennam + seekby;
|
jaroslav@706
|
134 |
cenread+=cendatalen;
|
jaroslav@706
|
135 |
result = addEntry(result, new Entry(name,lhoff, centim));
|
jaroslav@706
|
136 |
at += seekby;
|
jaroslav@705
|
137 |
}
|
jaroslav@706
|
138 |
return result;
|
jaroslav@705
|
139 |
}
|
jaroslav@705
|
140 |
|
jaroslav@706
|
141 |
private Entry[] addEntry(Entry[] result, Entry entry) {
|
jaroslav@706
|
142 |
Entry[] e = new Entry[result.length + 1];
|
jaroslav@706
|
143 |
e[result.length] = entry;
|
jaroslav@706
|
144 |
org.apidesign.bck2brwsr.emul.lang.System.arraycopy(result, 0, e, 0, result.length);
|
jaroslav@706
|
145 |
return e;
|
jaroslav@705
|
146 |
}
|
jaroslav@705
|
147 |
|
jaroslav@705
|
148 |
private static final long getsig(final byte[] b) throws IOException {return get32(b,0);}
|
jaroslav@706
|
149 |
private static final long endsiz(final byte[] b) throws IOException {return get32(b,ZipInputStream.ENDSIZ);}
|
jaroslav@706
|
150 |
private static final long endoff(final byte[] b) throws IOException {return get32(b,ZipInputStream.ENDOFF);}
|
jaroslav@706
|
151 |
private static final long cenlen(final byte[] b) throws IOException {return get32(b,ZipInputStream.CENLEN);}
|
jaroslav@706
|
152 |
private static final long censiz(final byte[] b) throws IOException {return get32(b,ZipInputStream.CENSIZ);}
|
jaroslav@706
|
153 |
private static final long centim(final byte[] b) throws IOException {return get32(b,ZipInputStream.CENTIM);}
|
jaroslav@706
|
154 |
private static final int cennam(final byte[] b) throws IOException {return get16(b,ZipInputStream.CENNAM);}
|
jaroslav@706
|
155 |
private static final int cenext(final byte[] b) throws IOException {return get16(b,ZipInputStream.CENEXT);}
|
jaroslav@706
|
156 |
private static final int cencom(final byte[] b) throws IOException {return get16(b,ZipInputStream.CENCOM);}
|
jaroslav@706
|
157 |
private static final long cenoff (final byte[] b) throws IOException {return get32(b,ZipInputStream.CENOFF);}
|
jaroslav@706
|
158 |
private static final int lochow(final byte[] b) throws IOException {return get16(b,ZipInputStream.LOCHOW);}
|
jaroslav@706
|
159 |
private static final int locname(final byte[] b) throws IOException {return get16(b,ZipInputStream.LOCNAM);}
|
jaroslav@706
|
160 |
private static final int locext(final byte[] b) throws IOException {return get16(b,ZipInputStream.LOCEXT);}
|
jaroslav@706
|
161 |
private static final long locsiz(final byte[] b) throws IOException {return get32(b,ZipInputStream.LOCSIZ);}
|
jaroslav@705
|
162 |
|
jaroslav@705
|
163 |
private static final int get16(final byte[] b, int off) throws IOException {
|
jaroslav@705
|
164 |
final int b1 = b[off];
|
jaroslav@705
|
165 |
final int b2 = b[off+1];
|
jaroslav@705
|
166 |
return (b1 & 0xff) | ((b2 & 0xff) << 8);
|
jaroslav@705
|
167 |
}
|
jaroslav@705
|
168 |
|
jaroslav@705
|
169 |
private static final long get32(final byte[] b, int off) throws IOException {
|
jaroslav@705
|
170 |
final int s1 = get16(b, off);
|
jaroslav@705
|
171 |
final int s2 = get16(b, off+2);
|
jaroslav@705
|
172 |
return s1 | ((long)s2 << 16);
|
jaroslav@705
|
173 |
}
|
jaroslav@705
|
174 |
|
jaroslav@705
|
175 |
}
|