Original version of NetBeans FastJar from release73 branch emul
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Sun, 10 Feb 2013 09:51:22 +0100
branchemul
changeset 7056de8252246b5
parent 702 fa42b3d8cbbc
child 706 a48961ff3e6b
Original version of NetBeans FastJar from release73 branch
emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/FastJar.java
     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 +}