001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.vfs;
031:
032: import java.io.*;
033: import java.util.logging.*;
034:
035: /**
036: * Scans a zip file, returning the names
037: */
038: public class ZipScanner {
039: private static Logger _log;
040:
041: private char[] _cbuf = new char[256];
042:
043: private Path _path;
044: private ReadStream _is;
045:
046: private boolean _isValid;
047:
048: private int _entries;
049: private int _offset;
050:
051: private int _index;
052:
053: private String _name;
054:
055: /**
056: * Creates a new Jar.
057: *
058: * @param path canonical path
059: */
060: public ZipScanner(Path path) {
061: try {
062: _path = path;
063:
064: int length = (int) path.getLength();
065:
066: ReadStream is = path.openRead();
067:
068: try {
069: // PACK200 is a standard comment, so try skipping it first
070: is.skip(length - 22 - 7);
071:
072: if (is.read() != 0x50) {
073: is.skip(6);
074:
075: if (is.read() != 0x50)
076: return;
077:
078: }
079:
080: if (is.read() == 0x4b && is.read() == 0x05
081: && is.read() == 0x06) {
082: _isValid = true;
083: }
084:
085: if (_isValid) {
086: is.skip(6);
087:
088: _entries = is.read() + (is.read() << 8);
089: is.skip(4);
090: _offset = (is.read() + (is.read() << 8)
091: + (is.read() << 16) + (is.read() << 24));
092: }
093: } finally {
094: is.close();
095: }
096: } catch (Exception e) {
097: log().log(Level.FINER, e.toString(), e);
098: }
099: }
100:
101: public boolean open() throws IOException {
102: if (!_isValid)
103: return false;
104:
105: _is = _path.openRead();
106: _is.skip(_offset);
107: _index = 0;
108:
109: return true;
110: }
111:
112: public boolean next() throws IOException {
113: if (_entries <= _index)
114: return false;
115:
116: _index++;
117:
118: ReadStream is = _is;
119:
120: if (is.read() != 0x50 || is.read() != 0x4b || is.read() != 0x01
121: || is.read() != 0x02) {
122: throw new IOException("illegal zip format");
123: }
124:
125: is.skip(2 + 2 + 2 + 2 + 2 + 2 + 4 + 4 + 4);
126:
127: int nameLen = is.read() + (is.read() << 8);
128: int extraLen = is.read() + (is.read() << 8);
129: int commentLen = is.read() + (is.read() << 8);
130:
131: is.skip(2 + 2 + 4 + 4);
132:
133: if (_cbuf.length < nameLen)
134: _cbuf = new char[nameLen];
135:
136: char[] cbuf = _cbuf;
137:
138: int k = 0;
139: for (int i = 0; i < nameLen; i++) {
140: int ch = is.read();
141:
142: if (ch < 0x80)
143: cbuf[k++] = (char) ch;
144: else if ((ch & 0xe0) == 0xc0) {
145: int c2 = is.read();
146: i += 1;
147: cbuf[k++] = (char) (((ch & 0x1f) << 6) + (c2 & 0x3f));
148: } else {
149: int c2 = is.read();
150: int c3 = is.read();
151:
152: i += 2;
153: cbuf[k++] = (char) (((ch & 0x1f) << 12)
154: + ((c2 & 0x3f) << 6) + ((c3 & 0x3f)));
155: }
156: }
157:
158: _name = new String(cbuf, 0, k);
159:
160: is.skip(extraLen);
161: is.skip(commentLen);
162:
163: return true;
164: }
165:
166: public String getName() {
167: return _name;
168: }
169:
170: public void close() {
171: InputStream is = _is;
172: _is = null;
173:
174: if (is != null) {
175: try {
176: is.close();
177: } catch (Exception e) {
178: throw new RuntimeException(e);
179: }
180: }
181: }
182:
183: private static Logger log() {
184: if (_log == null)
185: _log = Logger.getLogger(ZipScanner.class.getName());
186:
187: return _log;
188: }
189: }
|