1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/FastJar.java Sun Feb 10 09:51:22 2013 +0100
1.3 @@ -0,0 +1,256 @@
1.4 +/*
1.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
1.6 + *
1.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
1.8 + *
1.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
1.10 + * Other names may be trademarks of their respective owners.
1.11 + *
1.12 + * The contents of this file are subject to the terms of either the GNU
1.13 + * General Public License Version 2 only ("GPL") or the Common
1.14 + * Development and Distribution License("CDDL") (collectively, the
1.15 + * "License"). You may not use this file except in compliance with the
1.16 + * License. You can obtain a copy of the License at
1.17 + * http://www.netbeans.org/cddl-gplv2.html
1.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
1.19 + * specific language governing permissions and limitations under the
1.20 + * License. When distributing the software, include this License Header
1.21 + * Notice in each file and include the License file at
1.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
1.23 + * particular file as subject to the "Classpath" exception as provided
1.24 + * by Oracle in the GPL Version 2 section of the License file that
1.25 + * accompanied this code. If applicable, add the following below the
1.26 + * License Header, with the fields enclosed by brackets [] replaced by
1.27 + * your own identifying information:
1.28 + * "Portions Copyrighted [year] [name of copyright owner]"
1.29 + *
1.30 + * Contributor(s):
1.31 + *
1.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
1.33 + */
1.34 +package org.netbeans.modules.java.source.parsing;
1.35 +
1.36 +import java.io.File;
1.37 +import java.io.IOException;
1.38 +import java.io.InputStream;
1.39 +import java.io.RandomAccessFile;
1.40 +import java.util.Date;
1.41 +import java.util.LinkedList;
1.42 +import java.util.List;
1.43 +import java.util.zip.ZipEntry;
1.44 +import java.util.zip.ZipFile;
1.45 +import java.util.zip.ZipInputStream;
1.46 +
1.47 +/**
1.48 + *
1.49 + * @author Tomas Zezula
1.50 + */
1.51 +public final class FastJar {
1.52 +
1.53 + private FastJar() {
1.54 + }
1.55 +
1.56 +
1.57 + private static final int GIVE_UP = 1<<16;
1.58 +
1.59 +
1.60 + private static class RandomAccessFileInputStream extends InputStream {
1.61 +
1.62 + private final RandomAccessFile b;
1.63 + private final long len;
1.64 +
1.65 + public RandomAccessFileInputStream (RandomAccessFile b) throws IOException {
1.66 + assert b != null;
1.67 + this.b = b;
1.68 + this.len = b.length();
1.69 + }
1.70 +
1.71 + public RandomAccessFileInputStream (RandomAccessFile b, long len) throws IOException {
1.72 + assert b != null;
1.73 + assert len >=0;
1.74 + this.b = b;
1.75 + this.len = b.getFilePointer()+len;
1.76 + }
1.77 +
1.78 + public int read (byte[] data, int offset, int size) throws IOException {
1.79 + int rem = available();
1.80 + if (rem == 0) {
1.81 + return -1;
1.82 + }
1.83 + int rlen;
1.84 + if (size<rem) {
1.85 + rlen = size;
1.86 + }
1.87 + else {
1.88 + rlen = rem;
1.89 + }
1.90 + return this.b.read(data, offset, rlen);
1.91 + }
1.92 +
1.93 + public int read() throws java.io.IOException {
1.94 + if (available()==0) {
1.95 + return -1;
1.96 + }
1.97 + else {
1.98 + return b.readByte();
1.99 + }
1.100 + }
1.101 +
1.102 + public int available () throws IOException {
1.103 + return (int) (len - this.b.getFilePointer());
1.104 + }
1.105 +
1.106 + public void close () throws IOException {
1.107 + b.close ();
1.108 + }
1.109 + }
1.110 +
1.111 + public static final class Entry {
1.112 +
1.113 + public final String name;
1.114 + final long offset;
1.115 + private final long dosTime;
1.116 +
1.117 + public Entry (String name, long offset, long time) {
1.118 + assert name != null;
1.119 + this.name = name;
1.120 + this.offset = offset;
1.121 + this.dosTime = time;
1.122 + }
1.123 +
1.124 + public long getTime () {
1.125 + Date d = new Date((int)(((dosTime >> 25) & 0x7f) + 80),
1.126 + (int)(((dosTime >> 21) & 0x0f) - 1),
1.127 + (int)((dosTime >> 16) & 0x1f),
1.128 + (int)((dosTime >> 11) & 0x1f),
1.129 + (int)((dosTime >> 5) & 0x3f),
1.130 + (int)((dosTime << 1) & 0x3e));
1.131 + return d.getTime();
1.132 + }
1.133 + }
1.134 +
1.135 + public static InputStream getInputStream (final File file, final Entry e) throws IOException {
1.136 + return getInputStream(file, e.offset);
1.137 + }
1.138 +
1.139 + static InputStream getInputStream (final File file, final long offset) throws IOException {
1.140 + RandomAccessFile f = new RandomAccessFile (file, "r"); //NOI18N
1.141 + f.seek (offset);
1.142 + ZipInputStream in = new ZipInputStream (new RandomAccessFileInputStream (f));
1.143 + ZipEntry e = in.getNextEntry();
1.144 + if (e != null && e.getCrc() == 0L && e.getMethod() == ZipEntry.STORED) {
1.145 + long cp = f.getFilePointer();
1.146 + in.close();
1.147 + f = new RandomAccessFile (file, "r"); //NOI18N
1.148 + f.seek (cp);
1.149 + return new RandomAccessFileInputStream (f, e.getSize());
1.150 + }
1.151 + return in;
1.152 + }
1.153 +
1.154 + static ZipEntry getZipEntry (final File file, final long offset) throws IOException {
1.155 + RandomAccessFile f = new RandomAccessFile (file, "r"); //NOI18N
1.156 + try {
1.157 + f.seek (offset);
1.158 + ZipInputStream in = new ZipInputStream (new RandomAccessFileInputStream (f));
1.159 + try {
1.160 + return in.getNextEntry();
1.161 + } finally {
1.162 + in.close();
1.163 + }
1.164 + } finally {
1.165 + f.close ();
1.166 + }
1.167 + }
1.168 +
1.169 + public static Iterable<? extends Entry> list(File f) throws IOException {
1.170 + RandomAccessFile b = new RandomAccessFile (f,"r"); //NOI18N
1.171 + try {
1.172 + final long size = (int) b.length();
1.173 + b.seek (size-ZipFile.ENDHDR);
1.174 +
1.175 + byte[] data = new byte[ZipFile.ENDHDR];
1.176 + int giveup = 0;
1.177 +
1.178 + do {
1.179 + if (b.read(data, 0, ZipFile.ENDHDR)!=ZipFile.ENDHDR) {
1.180 + throw new IOException ();
1.181 + }
1.182 + b.seek(b.getFilePointer()-(ZipFile.ENDHDR+1));
1.183 + giveup++;
1.184 + if (giveup > GIVE_UP) {
1.185 + throw new IOException ();
1.186 + }
1.187 + } while (getsig(data) != ZipFile.ENDSIG);
1.188 +
1.189 +
1.190 + final long censize = endsiz(data);
1.191 + final long cenoff = endoff(data);
1.192 + b.seek (cenoff);
1.193 +
1.194 + List<Entry> result = new LinkedList<Entry>();
1.195 + int cenread = 0;
1.196 + data = new byte[ZipFile.CENHDR];
1.197 + while (cenread < censize) {
1.198 + if (b.read(data, 0, ZipFile.CENHDR)!=ZipFile.CENHDR) {
1.199 + throw new IOException ("No central table"); //NOI18N
1.200 + }
1.201 + if (getsig(data) != ZipFile.CENSIG) {
1.202 + throw new IOException("No central table"); //NOI18N
1.203 + }
1.204 + int cennam = cennam(data);
1.205 + int cenext = cenext(data);
1.206 + int cencom = cencom(data);
1.207 + long lhoff = cenoff(data);
1.208 + long centim = centim(data);
1.209 + String name = name(b, cennam);
1.210 + int seekby = cenext+cencom;
1.211 + int cendatalen = ZipFile.CENHDR + cennam + seekby;
1.212 + cenread+=cendatalen;
1.213 + result.add(new Entry(name,lhoff, centim));
1.214 + seekBy(b,seekby);
1.215 + }
1.216 + return result;
1.217 + } finally {
1.218 + b.close();
1.219 + }
1.220 + }
1.221 +
1.222 + private static final String name(final RandomAccessFile b, final int cennam) throws IOException {
1.223 + byte[] name = new byte[cennam];
1.224 + b.read(name, 0, cennam);
1.225 + return new String(name, "UTF-8"); //NOI18N
1.226 + }
1.227 +
1.228 + private static final long getsig(final byte[] b) throws IOException {return get32(b,0);}
1.229 + private static final long endsiz(final byte[] b) throws IOException {return get32(b,ZipFile.ENDSIZ);}
1.230 + private static final long endoff(final byte[] b) throws IOException {return get32(b,ZipFile.ENDOFF);}
1.231 + private static final long cenlen(final byte[] b) throws IOException {return get32(b,ZipFile.CENLEN);}
1.232 + private static final long censiz(final byte[] b) throws IOException {return get32(b,ZipFile.CENSIZ);}
1.233 + private static final long centim(final byte[] b) throws IOException {return get32(b,ZipFile.CENTIM);}
1.234 + private static final int cennam(final byte[] b) throws IOException {return get16(b,ZipFile.CENNAM);}
1.235 + private static final int cenext(final byte[] b) throws IOException {return get16(b,ZipFile.CENEXT);}
1.236 + private static final int cencom(final byte[] b) throws IOException {return get16(b,ZipFile.CENCOM);}
1.237 + private static final long cenoff (final byte[] b) throws IOException {return get32(b,ZipFile.CENOFF);}
1.238 + private static final int lochow(final byte[] b) throws IOException {return get16(b,ZipFile.LOCHOW);}
1.239 + private static final int locname(final byte[] b) throws IOException {return get16(b,ZipFile.LOCNAM);}
1.240 + private static final int locext(final byte[] b) throws IOException {return get16(b,ZipFile.LOCEXT);}
1.241 + private static final long locsiz(final byte[] b) throws IOException {return get32(b,ZipFile.LOCSIZ);}
1.242 +
1.243 + private static final void seekBy(final RandomAccessFile b, int offset) throws IOException {
1.244 + b.seek(b.getFilePointer() + offset);
1.245 + }
1.246 +
1.247 + private static final int get16(final byte[] b, int off) throws IOException {
1.248 + final int b1 = b[off];
1.249 + final int b2 = b[off+1];
1.250 + return (b1 & 0xff) | ((b2 & 0xff) << 8);
1.251 + }
1.252 +
1.253 + private static final long get32(final byte[] b, int off) throws IOException {
1.254 + final int s1 = get16(b, off);
1.255 + final int s2 = get16(b, off+2);
1.256 + return s1 | ((long)s2 << 16);
1.257 + }
1.258 +
1.259 +}