Modified: incubator/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipFile.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipFile.java?view=diff&rev=446478&r1=446477&r2=446478
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipFile.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipFile.java Thu Sep 14 19:40:33 2006
@@ -1,258 +1,258 @@
-/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.util.zip;
-
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.Enumeration;
-import java.util.NoSuchElementException;
-
-import org.apache.harmony.luni.util.Msg;
-import org.apache.harmony.luni.util.Util;
-
-/**
- * ZipFile is used to read zip entries and their associated data from zip files.
- *
- * @see ZipInputStream
- * @see ZipEntry
- */
-
-public class ZipFile implements ZipConstants {
-
- private String fileName;
-
- long descriptor = -1;
-
- private int size = -1;
-
- private int mode;
- static {
- ntvinit();
- }
-
- /**
- * Open zip file for read.
- */
- public static final int OPEN_READ = 1;
-
- /**
- * Delete zip file when closed.
- */
- public static final int OPEN_DELETE = 4;
-
- /**
- * Constructs a new ZipFile opened on the specified File.
- *
- * @param file
- * the File
- */
- public ZipFile(File file) throws ZipException, IOException {
- this(file.getPath());
- }
-
- /**
- * Constructs a new ZipFile opened on the specified File using the specified
- * mode.
- *
- * @param file
- * the File
- * @param mode
- * the mode to use, either OPEN_READ or OPEN_READ | OPEN_DELETE
- */
- public ZipFile(File file, int mode) throws IOException {
- if (mode == OPEN_READ || mode == (OPEN_READ | OPEN_DELETE)) {
- fileName = file.getPath();
- SecurityManager security = System.getSecurityManager();
- if (security != null) {
- security.checkRead(fileName);
- if ((mode & OPEN_DELETE) != 0) {
- security.checkDelete(fileName);
- }
- }
- this.mode = mode;
- openZip(fileName);
- } else
- throw new IllegalArgumentException();
- }
-
- /**
- * Constructs a new ZipFile opened on the specified file path name.
- *
- * @param filename
- * the file path name
- */
- public ZipFile(String filename) throws IOException {
- SecurityManager security = System.getSecurityManager();
- if (security != null) {
- security.checkRead(filename);
- }
- fileName = filename;
- openZip(fileName);
- }
-
- private void openZip(String filename) throws IOException {
- int result = openZipImpl(Util.getBytes(fileName));
- if (result != 0) {
- switch (result) {
- case 1:
- throw new ZipException(Msg.getString("K01c3", fileName));
- case 2:
- throw new ZipException(Msg.getString("K01c4", fileName));
- default:
- throw new OutOfMemoryError();
- }
- }
- }
-
- protected void finalize() throws IOException {
- close();
- }
-
- /**
- * Closes this ZipFile.
- */
- public void close() throws IOException {
- if (fileName != null) {
- // Only close initialized instances
- closeZipImpl();
- if ((mode & OPEN_DELETE) != 0) {
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- new File(fileName).delete();
- return null;
- }
- });
- }
- }
-}
-
- /**
- * Answers all of the zip entries contained in this ZipFile.
- *
- * @return an Enumeration of the zip entries
- */
- public Enumeration<? extends ZipEntry> entries() {
- return new ZFEnum<ZipEntry>();
- }
-
- /**
- * Gets the zip entry with the specified name from this ZipFile.
- *
- * @param entryName
- * the name of the entry in the zip file
- * @return a ZipEntry or null if the entry name does not exist in the zip
- * file
- */
- public ZipEntry getEntry(String entryName) {
- if (entryName != null) {
- ZipEntry entry = getEntryImpl(descriptor, entryName);
- return entry;
- }
- throw new NullPointerException();
- }
-
- /**
- * Answers an input stream on the data of the specified ZipEntry.
- *
- * @param entry
- * the ZipEntry
- * @return an input stream on the ZipEntry data
- */
- public InputStream getInputStream(ZipEntry entry) throws IOException {
- if(descriptor == -1) {
- /* the descriptor is set to -1 by native code to indicate the zip was closed */
- throw new IllegalStateException();
- }
- byte[] buf = inflateEntryImpl2(descriptor, entry.getName());
- if (buf == null) return null;
- return new ByteArrayInputStream(buf);
-}
-
- /**
- * Gets the file name of this ZipFile.
- *
- * @return the file name of this ZipFile
- */
- public String getName() {
- return fileName;
- }
-
- private synchronized native int openZipImpl(byte[] fileName1);
-
- private synchronized native void closeZipImpl() throws IOException;
-
- private native ZipEntry getEntryImpl(long descriptor1, String entryName);
-
- private native byte[] inflateEntryImpl2(long descriptor1, String entryName)
- throws ZipException;
-
- /**
- * Returns the number of ZipEntries in this ZipFile.
- *
- * @return Number of entries in this file
- */
- public int size() {
- if (size != -1)
- return size;
-
- size = 0;
- Enumeration<?> e = entries();
- while (e.hasMoreElements()) {
- size++;
- e.nextElement();
- }
- return size;
-
- }
-
- private static native void ntvinit();
-
- class ZFEnum<T extends ZipEntry> implements Enumeration<T> {
- private long nextEntryPointer;
-
- private T current;
-
- ZFEnum() {
- nextEntryPointer = resetZip(descriptor);
- current = getNextEntry(descriptor, nextEntryPointer);
- }
-
- private native long resetZip(long descriptor1);
-
- private native T getNextEntry(long descriptor1, long nextEntryPointer1);
-
- public boolean hasMoreElements() {
- if(descriptor == -1) {
- /* the descriptor is set to -1 by native code to indicate the zip was closed */
- throw new IllegalStateException();
- }
- return current != null;
- }
-
- public T nextElement() {
- if (current == null)
- throw new NoSuchElementException();
- T ze = current;
- current = getNextEntry(descriptor, nextEntryPointer);
- return ze;
- }
- }
-}
+/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util.zip;
+
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
+
+import org.apache.harmony.luni.util.Msg;
+import org.apache.harmony.luni.util.Util;
+
+/**
+ * ZipFile is used to read zip entries and their associated data from zip files.
+ *
+ * @see ZipInputStream
+ * @see ZipEntry
+ */
+
+public class ZipFile implements ZipConstants {
+
+ private String fileName;
+
+ long descriptor = -1;
+
+ private int size = -1;
+
+ private int mode;
+ static {
+ ntvinit();
+ }
+
+ /**
+ * Open zip file for read.
+ */
+ public static final int OPEN_READ = 1;
+
+ /**
+ * Delete zip file when closed.
+ */
+ public static final int OPEN_DELETE = 4;
+
+ /**
+ * Constructs a new ZipFile opened on the specified File.
+ *
+ * @param file
+ * the File
+ */
+ public ZipFile(File file) throws ZipException, IOException {
+ this(file.getPath());
+ }
+
+ /**
+ * Constructs a new ZipFile opened on the specified File using the specified
+ * mode.
+ *
+ * @param file
+ * the File
+ * @param mode
+ * the mode to use, either OPEN_READ or OPEN_READ | OPEN_DELETE
+ */
+ public ZipFile(File file, int mode) throws IOException {
+ if (mode == OPEN_READ || mode == (OPEN_READ | OPEN_DELETE)) {
+ fileName = file.getPath();
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ security.checkRead(fileName);
+ if ((mode & OPEN_DELETE) != 0) {
+ security.checkDelete(fileName);
+ }
+ }
+ this.mode = mode;
+ openZip(fileName);
+ } else
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Constructs a new ZipFile opened on the specified file path name.
+ *
+ * @param filename
+ * the file path name
+ */
+ public ZipFile(String filename) throws IOException {
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ security.checkRead(filename);
+ }
+ fileName = filename;
+ openZip(fileName);
+ }
+
+ private void openZip(String filename) throws IOException {
+ int result = openZipImpl(Util.getBytes(fileName));
+ if (result != 0) {
+ switch (result) {
+ case 1:
+ throw new ZipException(Msg.getString("K01c3", fileName));
+ case 2:
+ throw new ZipException(Msg.getString("K01c4", fileName));
+ default:
+ throw new OutOfMemoryError();
+ }
+ }
+ }
+
+ protected void finalize() throws IOException {
+ close();
+ }
+
+ /**
+ * Closes this ZipFile.
+ */
+ public void close() throws IOException {
+ if (fileName != null) {
+ // Only close initialized instances
+ closeZipImpl();
+ if ((mode & OPEN_DELETE) != 0) {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ new File(fileName).delete();
+ return null;
+ }
+ });
+ }
+ }
+}
+
+ /**
+ * Answers all of the zip entries contained in this ZipFile.
+ *
+ * @return an Enumeration of the zip entries
+ */
+ public Enumeration<? extends ZipEntry> entries() {
+ return new ZFEnum<ZipEntry>();
+ }
+
+ /**
+ * Gets the zip entry with the specified name from this ZipFile.
+ *
+ * @param entryName
+ * the name of the entry in the zip file
+ * @return a ZipEntry or null if the entry name does not exist in the zip
+ * file
+ */
+ public ZipEntry getEntry(String entryName) {
+ if (entryName != null) {
+ ZipEntry entry = getEntryImpl(descriptor, entryName);
+ return entry;
+ }
+ throw new NullPointerException();
+ }
+
+ /**
+ * Answers an input stream on the data of the specified ZipEntry.
+ *
+ * @param entry
+ * the ZipEntry
+ * @return an input stream on the ZipEntry data
+ */
+ public InputStream getInputStream(ZipEntry entry) throws IOException {
+ if(descriptor == -1) {
+ /* the descriptor is set to -1 by native code to indicate the zip was closed */
+ throw new IllegalStateException();
+ }
+ byte[] buf = inflateEntryImpl2(descriptor, entry.getName());
+ if (buf == null) return null;
+ return new ByteArrayInputStream(buf);
+}
+
+ /**
+ * Gets the file name of this ZipFile.
+ *
+ * @return the file name of this ZipFile
+ */
+ public String getName() {
+ return fileName;
+ }
+
+ private synchronized native int openZipImpl(byte[] fileName1);
+
+ private synchronized native void closeZipImpl() throws IOException;
+
+ private native ZipEntry getEntryImpl(long descriptor1, String entryName);
+
+ private native byte[] inflateEntryImpl2(long descriptor1, String entryName)
+ throws ZipException;
+
+ /**
+ * Returns the number of ZipEntries in this ZipFile.
+ *
+ * @return Number of entries in this file
+ */
+ public int size() {
+ if (size != -1)
+ return size;
+
+ size = 0;
+ Enumeration<?> e = entries();
+ while (e.hasMoreElements()) {
+ size++;
+ e.nextElement();
+ }
+ return size;
+
+ }
+
+ private static native void ntvinit();
+
+ class ZFEnum<T extends ZipEntry> implements Enumeration<T> {
+ private long nextEntryPointer;
+
+ private T current;
+
+ ZFEnum() {
+ nextEntryPointer = resetZip(descriptor);
+ current = getNextEntry(descriptor, nextEntryPointer);
+ }
+
+ private native long resetZip(long descriptor1);
+
+ private native T getNextEntry(long descriptor1, long nextEntryPointer1);
+
+ public boolean hasMoreElements() {
+ if(descriptor == -1) {
+ /* the descriptor is set to -1 by native code to indicate the zip was closed */
+ throw new IllegalStateException();
+ }
+ return current != null;
+ }
+
+ public T nextElement() {
+ if (current == null)
+ throw new NoSuchElementException();
+ T ze = current;
+ current = getNextEntry(descriptor, nextEntryPointer);
+ return ze;
+ }
+ }
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipFile.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: incubator/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipInputStream.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipInputStream.java?view=diff&rev=446478&r1=446477&r2=446478
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipInputStream.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipInputStream.java Thu Sep 14 19:40:33 2006
@@ -1,335 +1,335 @@
-/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.util.zip;
-
-
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PushbackInputStream;
-import java.util.jar.Attributes;
-import java.util.jar.JarEntry;
-
-import org.apache.harmony.luni.util.Msg;
-import org.apache.harmony.luni.util.Util;
-
-/**
- * ZipInputStream is an input stream for reading zip files.
- *
- * @see ZipEntry
- * @see ZipFile
- */
-public class ZipInputStream extends InflaterInputStream implements ZipConstants {
- static final int DEFLATED = 8;
-
- static final int STORED = 0;
-
- static final int ZIPDataDescriptorFlag = 8;
-
- static final int ZIPLocalHeaderVersionNeeded = 20;
-
- private boolean zipClosed = false;
-
- private boolean entriesEnd = false;
-
- private boolean hasDD = false;
-
- private int entryIn = 0;
-
- private int inRead, lastRead = 0;
-
- ZipEntry currentEntry;
-
- private byte[] hdrBuf = new byte[LOCHDR - LOCVER];
-
- private CRC32 crc = new CRC32();
-
- private byte[] nameBuf = new byte[256];
-
- private char[] charBuf = new char[256];
-
- /**
- * Constructs a new ZipInputStream on the specified input stream.
- *
- * @param stream
- * the input stream
- */
- public ZipInputStream(InputStream stream) {
- super(new PushbackInputStream(stream, BUF_SIZE), new Inflater(true));
- if (stream == null)
- throw new NullPointerException();
- }
-
- /**
- * Closes this ZipInputStream.
- */
- public void close() throws IOException {
- if (zipClosed != true) {
- closeEntry(); // Close the current entry
- zipClosed = true;
- super.close();
- }
- }
-
- /**
- * Closes the current zip entry and positions to read the next entry.
- */
- public void closeEntry() throws IOException {
- if (zipClosed)
- throw new IOException(Msg.getString("K0059"));
- if (currentEntry == null)
- return;
- if (currentEntry instanceof java.util.jar.JarEntry) {
- Attributes temp = ((JarEntry) currentEntry).getAttributes();
- if (temp != null && temp.containsKey("hidden"))
- return;
- }
- // Ensure all entry bytes are read
- skip(Long.MAX_VALUE);
- int inB, out;
- if (currentEntry.compressionMethod == DEFLATED) {
- inB = inf.getTotalIn();
- out = inf.getTotalOut();
- } else {
- inB = inRead;
- out = inRead;
- }
- int diff = 0;
- // Pushback any required bytes
- if ((diff = entryIn - inB) != 0)
- ((PushbackInputStream) in).unread(buf, len - diff, diff);
-
- if (hasDD) {
- in.read(hdrBuf, 0, EXTHDR);
- if (getLong(hdrBuf, 0) != EXTSIG)
- throw new ZipException(Msg.getString("K0020"));
- currentEntry.crc = getLong(hdrBuf, EXTCRC);
- currentEntry.compressedSize = getLong(hdrBuf, EXTSIZ);
- currentEntry.size = getLong(hdrBuf, EXTLEN);
- }
- if (currentEntry.crc != crc.getValue())
- throw new ZipException(Msg.getString("K0077"));
- if (currentEntry.compressedSize != inB || currentEntry.size != out)
- throw new ZipException(Msg.getString("K00ae"));
-
- inf.reset();
- lastRead = inRead = entryIn = len = 0;
- crc.reset();
- currentEntry = null;
- }
-
- /**
- * Reads the next zip entry from this ZipInputStream.
- */
- public ZipEntry getNextEntry() throws IOException {
- if (currentEntry != null)
- closeEntry();
- if (entriesEnd)
- return null;
-
- int x = 0, count = 0;
- while (count != 4) {
- count += x = in.read(hdrBuf, count, 4 - count);
- if (x == -1)
- return null;
- }
- long hdr = getLong(hdrBuf, 0);
- if (hdr == CENSIG) {
- entriesEnd = true;
- return null;
- }
- if (hdr != LOCSIG)
- return null;
-
- // Read the local header
- count = 0;
- while (count != (LOCHDR - LOCVER)) {
- count += x = in.read(hdrBuf, count, (LOCHDR - LOCVER) - count);
- if (x == -1)
- throw new EOFException();
- }
- int version = getShort(hdrBuf, 0) & 0xff;
- if (version > ZIPLocalHeaderVersionNeeded)
- throw new ZipException(Msg.getString("K0008"));
- int flags = getShort(hdrBuf, LOCFLG - LOCVER);
- hasDD = ((flags & ZIPDataDescriptorFlag) == ZIPDataDescriptorFlag);
- int cetime = getShort(hdrBuf, LOCTIM - LOCVER);
- int cemodDate = getShort(hdrBuf, LOCTIM - LOCVER + 2);
- int cecompressionMethod = getShort(hdrBuf, LOCHOW - LOCVER);
- long cecrc = 0, cecompressedSize = 0, cesize = -1;
- if (!hasDD) {
- cecrc = getLong(hdrBuf, LOCCRC - LOCVER);
- cecompressedSize = getLong(hdrBuf, LOCSIZ - LOCVER);
- cesize = getLong(hdrBuf, LOCLEN - LOCVER);
- }
- int flen = getShort(hdrBuf, LOCNAM - LOCVER);
- if (flen == 0)
- throw new ZipException(Msg.getString("K000a"));
- int elen = getShort(hdrBuf, LOCEXT - LOCVER);
-
- count = 0;
- if (flen > nameBuf.length) {
- nameBuf = new byte[flen];
- charBuf = new char[flen];
- }
- while (count != flen) {
- count += x = in.read(nameBuf, count, flen - count);
- if (x == -1)
- throw new EOFException();
- }
- currentEntry = createZipEntry(Util.convertUTF8WithBuf(nameBuf, charBuf,
- 0, flen));
- currentEntry.time = cetime;
- currentEntry.modDate = cemodDate;
- currentEntry.setMethod(cecompressionMethod);
- if (cesize != -1) {
- currentEntry.setCrc(cecrc);
- currentEntry.setSize(cesize);
- currentEntry.setCompressedSize(cecompressedSize);
- }
- if (elen > 0) {
- count = 0;
- byte[] e = new byte[elen];
- while (count != elen) {
- count += x = in.read(e, count, elen - count);
- if (x == -1)
- throw new EOFException();
- }
- currentEntry.setExtra(e);
- }
- return currentEntry;
- }
-
- /* Read 4 bytes from the buffer and store it as an int */
-
- /**
- * Reads up to the specified number of uncompressed bytes into the buffer
- * starting at the offset.
- *
- * @param buffer
- * a byte array
- * @param start
- * the starting offset into the buffer
- * @param length
- * the number of bytes to read
- * @return the number of bytes read
- */
- public int read(byte[] buffer, int start, int length) throws IOException {
- if (zipClosed)
- throw new IOException(Msg.getString("K0059"));
- if (inf.finished() || currentEntry == null)
- return -1;
- // avoid int overflow, check null buffer
- if (start <= buffer.length && length >= 0 && start >= 0
- && buffer.length - start >= length) {
- if (currentEntry.compressionMethod == STORED) {
- int csize = (int) currentEntry.size;
- if (inRead >= csize)
- return -1;
- if (lastRead >= len) {
- lastRead = 0;
- if ((len = in.read(buf)) == -1)
- return -1;
- entryIn += len;
- }
- int toRead = length > len ? len - lastRead : length;
- if ((csize - inRead) < toRead)
- toRead = csize - inRead;
- System.arraycopy(buf, lastRead, buffer, start, toRead);
- lastRead += toRead;
- inRead += toRead;
- crc.update(buffer, start, toRead);
- return toRead;
- }
- if (inf.needsInput()) {
- fill();
- if (len > 0)
- entryIn += len;
- }
- int read = 0;
- try {
- read = inf.inflate(buffer, start, length);
- } catch (DataFormatException e) {
- throw new ZipException(e.getMessage());
- }
- if (read == 0 && inf.finished())
- return -1;
- crc.update(buffer, start, read);
- return read;
- }
- throw new ArrayIndexOutOfBoundsException();
- }
-
- /**
- * Skips up to the specified number of bytes in the current zip entry.
- *
- * @param value
- * the number of bytes to skip
- * @return the number of bytes skipped
- */
- public long skip(long value) throws IOException {
- if (value >= 0) {
- long skipped = 0;
- byte[] b = new byte[1024];
- while (skipped != value) {
- long rem = value - skipped;
- int x = read(b, 0, (int) (b.length > rem ? rem : b.length));
- if (x == -1)
- return skipped;
- skipped += x;
- }
- return skipped;
- } else
- throw new IllegalArgumentException();
-}
-
- /**
- * Answers 1 if the EOF has been reached, otherwise returns 0.
- *
- * @return 0 after EOF of current entry, 1 otherwise
- */
- public int available() throws IOException {
- if (zipClosed)
- throw new IOException(Msg.getString("K0059"));
- if (currentEntry == null)
- return 1;
- if (currentEntry.compressionMethod == STORED) {
- if (inRead >= currentEntry.size)
- return 0;
- } else {
- if (inf.finished())
- return 0;
- }
- return 1;
- }
-
- protected ZipEntry createZipEntry(String name) {
- return new ZipEntry(name);
- }
-
- private int getShort(byte[] buffer, int off) {
- return (buffer[off] & 0xFF) | ((buffer[off + 1] & 0xFF) << 8);
- }
-
- private long getLong(byte[] buffer, int off) {
- long l = 0;
- l |= (buffer[off] & 0xFF);
- l |= (buffer[off + 1] & 0xFF) << 8;
- l |= (buffer[off + 2] & 0xFF) << 16;
- l |= ((long) (buffer[off + 3] & 0xFF)) << 24;
- return l;
- }
-}
+/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util.zip;
+
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PushbackInputStream;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+
+import org.apache.harmony.luni.util.Msg;
+import org.apache.harmony.luni.util.Util;
+
+/**
+ * ZipInputStream is an input stream for reading zip files.
+ *
+ * @see ZipEntry
+ * @see ZipFile
+ */
+public class ZipInputStream extends InflaterInputStream implements ZipConstants {
+ static final int DEFLATED = 8;
+
+ static final int STORED = 0;
+
+ static final int ZIPDataDescriptorFlag = 8;
+
+ static final int ZIPLocalHeaderVersionNeeded = 20;
+
+ private boolean zipClosed = false;
+
+ private boolean entriesEnd = false;
+
+ private boolean hasDD = false;
+
+ private int entryIn = 0;
+
+ private int inRead, lastRead = 0;
+
+ ZipEntry currentEntry;
+
+ private byte[] hdrBuf = new byte[LOCHDR - LOCVER];
+
+ private CRC32 crc = new CRC32();
+
+ private byte[] nameBuf = new byte[256];
+
+ private char[] charBuf = new char[256];
+
+ /**
+ * Constructs a new ZipInputStream on the specified input stream.
+ *
+ * @param stream
+ * the input stream
+ */
+ public ZipInputStream(InputStream stream) {
+ super(new PushbackInputStream(stream, BUF_SIZE), new Inflater(true));
+ if (stream == null)
+ throw new NullPointerException();
+ }
+
+ /**
+ * Closes this ZipInputStream.
+ */
+ public void close() throws IOException {
+ if (zipClosed != true) {
+ closeEntry(); // Close the current entry
+ zipClosed = true;
+ super.close();
+ }
+ }
+
+ /**
+ * Closes the current zip entry and positions to read the next entry.
+ */
+ public void closeEntry() throws IOException {
+ if (zipClosed)
+ throw new IOException(Msg.getString("K0059"));
+ if (currentEntry == null)
+ return;
+ if (currentEntry instanceof java.util.jar.JarEntry) {
+ Attributes temp = ((JarEntry) currentEntry).getAttributes();
+ if (temp != null && temp.containsKey("hidden"))
+ return;
+ }
+ // Ensure all entry bytes are read
+ skip(Long.MAX_VALUE);
+ int inB, out;
+ if (currentEntry.compressionMethod == DEFLATED) {
+ inB = inf.getTotalIn();
+ out = inf.getTotalOut();
+ } else {
+ inB = inRead;
+ out = inRead;
+ }
+ int diff = 0;
+ // Pushback any required bytes
+ if ((diff = entryIn - inB) != 0)
+ ((PushbackInputStream) in).unread(buf, len - diff, diff);
+
+ if (hasDD) {
+ in.read(hdrBuf, 0, EXTHDR);
+ if (getLong(hdrBuf, 0) != EXTSIG)
+ throw new ZipException(Msg.getString("K0020"));
+ currentEntry.crc = getLong(hdrBuf, EXTCRC);
+ currentEntry.compressedSize = getLong(hdrBuf, EXTSIZ);
+ currentEntry.size = getLong(hdrBuf, EXTLEN);
+ }
+ if (currentEntry.crc != crc.getValue())
+ throw new ZipException(Msg.getString("K0077"));
+ if (currentEntry.compressedSize != inB || currentEntry.size != out)
+ throw new ZipException(Msg.getString("K00ae"));
+
+ inf.reset();
+ lastRead = inRead = entryIn = len = 0;
+ crc.reset();
+ currentEntry = null;
+ }
+
+ /**
+ * Reads the next zip entry from this ZipInputStream.
+ */
+ public ZipEntry getNextEntry() throws IOException {
+ if (currentEntry != null)
+ closeEntry();
+ if (entriesEnd)
+ return null;
+
+ int x = 0, count = 0;
+ while (count != 4) {
+ count += x = in.read(hdrBuf, count, 4 - count);
+ if (x == -1)
+ return null;
+ }
+ long hdr = getLong(hdrBuf, 0);
+ if (hdr == CENSIG) {
+ entriesEnd = true;
+ return null;
+ }
+ if (hdr != LOCSIG)
+ return null;
+
+ // Read the local header
+ count = 0;
+ while (count != (LOCHDR - LOCVER)) {
+ count += x = in.read(hdrBuf, count, (LOCHDR - LOCVER) - count);
+ if (x == -1)
+ throw new EOFException();
+ }
+ int version = getShort(hdrBuf, 0) & 0xff;
+ if (version > ZIPLocalHeaderVersionNeeded)
+ throw new ZipException(Msg.getString("K0008"));
+ int flags = getShort(hdrBuf, LOCFLG - LOCVER);
+ hasDD = ((flags & ZIPDataDescriptorFlag) == ZIPDataDescriptorFlag);
+ int cetime = getShort(hdrBuf, LOCTIM - LOCVER);
+ int cemodDate = getShort(hdrBuf, LOCTIM - LOCVER + 2);
+ int cecompressionMethod = getShort(hdrBuf, LOCHOW - LOCVER);
+ long cecrc = 0, cecompressedSize = 0, cesize = -1;
+ if (!hasDD) {
+ cecrc = getLong(hdrBuf, LOCCRC - LOCVER);
+ cecompressedSize = getLong(hdrBuf, LOCSIZ - LOCVER);
+ cesize = getLong(hdrBuf, LOCLEN - LOCVER);
+ }
+ int flen = getShort(hdrBuf, LOCNAM - LOCVER);
+ if (flen == 0)
+ throw new ZipException(Msg.getString("K000a"));
+ int elen = getShort(hdrBuf, LOCEXT - LOCVER);
+
+ count = 0;
+ if (flen > nameBuf.length) {
+ nameBuf = new byte[flen];
+ charBuf = new char[flen];
+ }
+ while (count != flen) {
+ count += x = in.read(nameBuf, count, flen - count);
+ if (x == -1)
+ throw new EOFException();
+ }
+ currentEntry = createZipEntry(Util.convertUTF8WithBuf(nameBuf, charBuf,
+ 0, flen));
+ currentEntry.time = cetime;
+ currentEntry.modDate = cemodDate;
+ currentEntry.setMethod(cecompressionMethod);
+ if (cesize != -1) {
+ currentEntry.setCrc(cecrc);
+ currentEntry.setSize(cesize);
+ currentEntry.setCompressedSize(cecompressedSize);
+ }
+ if (elen > 0) {
+ count = 0;
+ byte[] e = new byte[elen];
+ while (count != elen) {
+ count += x = in.read(e, count, elen - count);
+ if (x == -1)
+ throw new EOFException();
+ }
+ currentEntry.setExtra(e);
+ }
+ return currentEntry;
+ }
+
+ /* Read 4 bytes from the buffer and store it as an int */
+
+ /**
+ * Reads up to the specified number of uncompressed bytes into the buffer
+ * starting at the offset.
+ *
+ * @param buffer
+ * a byte array
+ * @param start
+ * the starting offset into the buffer
+ * @param length
+ * the number of bytes to read
+ * @return the number of bytes read
+ */
+ public int read(byte[] buffer, int start, int length) throws IOException {
+ if (zipClosed)
+ throw new IOException(Msg.getString("K0059"));
+ if (inf.finished() || currentEntry == null)
+ return -1;
+ // avoid int overflow, check null buffer
+ if (start <= buffer.length && length >= 0 && start >= 0
+ && buffer.length - start >= length) {
+ if (currentEntry.compressionMethod == STORED) {
+ int csize = (int) currentEntry.size;
+ if (inRead >= csize)
+ return -1;
+ if (lastRead >= len) {
+ lastRead = 0;
+ if ((len = in.read(buf)) == -1)
+ return -1;
+ entryIn += len;
+ }
+ int toRead = length > len ? len - lastRead : length;
+ if ((csize - inRead) < toRead)
+ toRead = csize - inRead;
+ System.arraycopy(buf, lastRead, buffer, start, toRead);
+ lastRead += toRead;
+ inRead += toRead;
+ crc.update(buffer, start, toRead);
+ return toRead;
+ }
+ if (inf.needsInput()) {
+ fill();
+ if (len > 0)
+ entryIn += len;
+ }
+ int read = 0;
+ try {
+ read = inf.inflate(buffer, start, length);
+ } catch (DataFormatException e) {
+ throw new ZipException(e.getMessage());
+ }
+ if (read == 0 && inf.finished())
+ return -1;
+ crc.update(buffer, start, read);
+ return read;
+ }
+ throw new ArrayIndexOutOfBoundsException();
+ }
+
+ /**
+ * Skips up to the specified number of bytes in the current zip entry.
+ *
+ * @param value
+ * the number of bytes to skip
+ * @return the number of bytes skipped
+ */
+ public long skip(long value) throws IOException {
+ if (value >= 0) {
+ long skipped = 0;
+ byte[] b = new byte[1024];
+ while (skipped != value) {
+ long rem = value - skipped;
+ int x = read(b, 0, (int) (b.length > rem ? rem : b.length));
+ if (x == -1)
+ return skipped;
+ skipped += x;
+ }
+ return skipped;
+ } else
+ throw new IllegalArgumentException();
+}
+
+ /**
+ * Answers 1 if the EOF has been reached, otherwise returns 0.
+ *
+ * @return 0 after EOF of current entry, 1 otherwise
+ */
+ public int available() throws IOException {
+ if (zipClosed)
+ throw new IOException(Msg.getString("K0059"));
+ if (currentEntry == null)
+ return 1;
+ if (currentEntry.compressionMethod == STORED) {
+ if (inRead >= currentEntry.size)
+ return 0;
+ } else {
+ if (inf.finished())
+ return 0;
+ }
+ return 1;
+ }
+
+ protected ZipEntry createZipEntry(String name) {
+ return new ZipEntry(name);
+ }
+
+ private int getShort(byte[] buffer, int off) {
+ return (buffer[off] & 0xFF) | ((buffer[off + 1] & 0xFF) << 8);
+ }
+
+ private long getLong(byte[] buffer, int off) {
+ long l = 0;
+ l |= (buffer[off] & 0xFF);
+ l |= (buffer[off + 1] & 0xFF) << 8;
+ l |= (buffer[off + 2] & 0xFF) << 16;
+ l |= ((long) (buffer[off + 3] & 0xFF)) << 24;
+ return l;
+ }
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipInputStream.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: incubator/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipOutputStream.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipOutputStream.java?view=diff&rev=446478&r1=446477&r2=446478
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipOutputStream.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipOutputStream.java Thu Sep 14 19:40:33 2006
@@ -1,389 +1,389 @@
-/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.util.zip;
-
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Vector;
-
-import org.apache.harmony.luni.util.Msg;
-
-/**
- * ZipOuputStream is used to write ZipEntries to the underlying stream. Output
- * from ZipOutputStream conforms to the ZipFile file format.
- *
- * @see ZipInputStream
- * @see ZipEntry
- */
-public class ZipOutputStream extends DeflaterOutputStream implements
- ZipConstants {
-
- public static final int DEFLATED = 8;
-
- public static final int STORED = 0;
-
- static final int ZIPDataDescriptorFlag = 8;
-
- static final int ZIPLocalHeaderVersionNeeded = 20;
-
- private String comment;
-
- private Vector<String> entries = new Vector<String>();
-
- private int compressMethod = DEFLATED;
-
- private int compressLevel = Deflater.DEFAULT_COMPRESSION;
-
- private ByteArrayOutputStream cDir = new ByteArrayOutputStream();
-
- private ZipEntry currentEntry;
-
- private CRC32 crc = new CRC32();
-
- private int offset = 0, curOffset = 0, nameLength;
-
- private byte[] nameBytes;
-
- /**
- * Constructs a new ZipOutputStream on p1
- *
- * @param p1
- * OutputStream The InputStream to output to
- */
- public ZipOutputStream(OutputStream p1) {
- super(p1, new Deflater(Deflater.DEFAULT_COMPRESSION, true));
- }
-
- /**
- * Closes the current ZipEntry if any. Closes the underlying output stream.
- * If the stream is already closed this method does nothing.
- *
- * @exception IOException
- * If an error occurs closing the stream
- */
- public void close() throws IOException {
- if (out != null) {
- finish();
- out.close();
- out = null;
- }
- }
-
- /**
- * Closes the current ZipEntry. Any entry terminal data is written to the
- * underlying stream.
- *
- * @exception IOException
- * If an error occurs closing the entry
- */
- public void closeEntry() throws IOException {
- if (cDir == null)
- throw new IOException(Msg.getString("K0059"));
- if (currentEntry == null)
- return;
- if (currentEntry.getMethod() == DEFLATED) {
- super.finish();
- }
-
- // Verify values for STORED types
- if (currentEntry.getMethod() == STORED) {
- if (crc.getValue() != currentEntry.crc)
- throw new ZipException(Msg.getString("K0077"));
- if (currentEntry.size != crc.tbytes)
- throw new ZipException(Msg.getString("K00ae"));
- }
- curOffset = LOCHDR;
-
- // Write the DataDescriptor
- if (currentEntry.getMethod() != STORED) {
- curOffset += EXTHDR;
- writeLong(out, EXTSIG);
- writeLong(out, currentEntry.crc = crc.getValue());
- writeLong(out, currentEntry.compressedSize = def.getTotalOut());
- writeLong(out, currentEntry.size = def.getTotalIn());
- }
- // Update the CentralDirectory
- writeLong(cDir, CENSIG);
- writeShort(cDir, ZIPLocalHeaderVersionNeeded); // Version created
- writeShort(cDir, ZIPLocalHeaderVersionNeeded); // Version to extract
- writeShort(cDir, currentEntry.getMethod() == STORED ? 0
- : ZIPDataDescriptorFlag);
- writeShort(cDir, currentEntry.getMethod());
- writeShort(cDir, currentEntry.time);
- writeShort(cDir, currentEntry.modDate);
- writeLong(cDir, crc.getValue());
- if (currentEntry.getMethod() == DEFLATED) {
- curOffset += writeLong(cDir, def.getTotalOut());
- writeLong(cDir, def.getTotalIn());
- } else {
- curOffset += writeLong(cDir, crc.tbytes);
- writeLong(cDir, crc.tbytes);
- }
- curOffset += writeShort(cDir, nameLength);
- if (currentEntry.extra != null)
- curOffset += writeShort(cDir, currentEntry.extra.length);
- else
- writeShort(cDir, 0);
- String c;
- if ((c = currentEntry.getComment()) != null)
- writeShort(cDir, c.length());
- else
- writeShort(cDir, 0);
- writeShort(cDir, 0); // Disk Start
- writeShort(cDir, 0); // Internal File Attributes
- writeLong(cDir, 0); // External File Attributes
- writeLong(cDir, offset);
- cDir.write(nameBytes);
- nameBytes = null;
- if (currentEntry.extra != null)
- cDir.write(currentEntry.extra);
- offset += curOffset;
- if (c != null)
- cDir.write(c.getBytes());
- currentEntry = null;
- crc.reset();
- def.reset();
- done = false;
- }
-
- /**
- * Indicates that all entries have been written to the stream. Any terminal
- * ZipFile information is written to the underlying stream.
- *
- * @exception IOException
- * If an error occurs while finishing
- */
- public void finish() throws IOException {
- if (out == null)
- throw new IOException(Msg.getString("K0059"));
- if (cDir == null)
- return;
- if (entries.size() == 0)
- throw new ZipException(Msg.getString("K00b6"));
- if (currentEntry != null)
- closeEntry();
- int cdirSize = cDir.size();
- // Write Central Dir End
- writeLong(cDir, ENDSIG);
- writeShort(cDir, 0); // Disk Number
- writeShort(cDir, 0); // Start Disk
- writeShort(cDir, entries.size()); // Number of entries
- writeShort(cDir, entries.size()); // Number of entries
- writeLong(cDir, cdirSize); // Size of central dir
- writeLong(cDir, offset); // Offset of central dir
- if (comment != null) {
- writeShort(cDir, comment.length());
- cDir.write(comment.getBytes());
- } else
- writeShort(cDir, 0);
- // Write the central dir
- out.write(cDir.toByteArray());
- cDir = null;
-
- }
-
- /**
- * Writes entry information for ze to the underlying stream. Data associated
- * with the entry can then be written using write(). After data is written
- * closeEntry() must be called to complete the storing of ze on the
- * underlying stream.
- *
- * @param ze
- * ZipEntry to store
- * @exception IOException
- * If an error occurs storing the entry
- * @see #write
- */
- public void putNextEntry(ZipEntry ze) throws java.io.IOException {
- if (currentEntry != null)
- closeEntry();
- if (ze.getMethod() == STORED
- || (compressMethod == STORED && ze.getMethod() == -1)) {
- if (ze.crc == -1)
- /* [MSG "K0077", "Crc mismatch"] */
- throw new ZipException(Msg.getString("K0077"));
- if (ze.size == -1 && ze.compressedSize == -1)
- /* [MSG "K00ae", "Size mismatch"] */
- throw new ZipException(Msg.getString("K00ae"));
- if (ze.size != ze.compressedSize && ze.compressedSize != -1
- && ze.size != -1)
- /* [MSG "K00ae", "Size mismatch"] */
- throw new ZipException(Msg.getString("K00ae"));
- }
- /* [MSG "K0059", "Stream is closed"] */
- if (cDir == null)
- throw new IOException(Msg.getString("K0059"));
- if (entries.contains(ze.name))
- /* [MSG "K0066", "Entry already exists: {0}"] */
- throw new ZipException(Msg.getString("K0066", ze.name));
- nameLength = utf8Count(ze.name);
- if (nameLength > 0xffff)
- /* [MSG "K01a7", "Name too long: {0}"] */
- throw new IllegalArgumentException(Msg.getString("K01a7", ze.name));
-
- def.setLevel(compressLevel);
- currentEntry = ze;
- entries.add(currentEntry.name);
- if (currentEntry.getMethod() == -1)
- currentEntry.setMethod(compressMethod);
- writeLong(out, LOCSIG); // Entry header
- writeShort(out, ZIPLocalHeaderVersionNeeded); // Extraction version
- writeShort(out, currentEntry.getMethod() == STORED ? 0
- : ZIPDataDescriptorFlag);
- writeShort(out, currentEntry.getMethod());
- if (currentEntry.getTime() == -1)
- currentEntry.setTime(System.currentTimeMillis());
- writeShort(out, currentEntry.time);
- writeShort(out, currentEntry.modDate);
-
- if (currentEntry.getMethod() == STORED) {
- if (currentEntry.size == -1)
- currentEntry.size = currentEntry.compressedSize;
- else if (currentEntry.compressedSize == -1)
- currentEntry.compressedSize = currentEntry.size;
- writeLong(out, currentEntry.crc);
- writeLong(out, currentEntry.size);
- writeLong(out, currentEntry.size);
- } else {
- writeLong(out, 0);
- writeLong(out, 0);
- writeLong(out, 0);
- }
- writeShort(out, nameLength);
- if (currentEntry.extra != null)
- writeShort(out, currentEntry.extra.length);
- else
- writeShort(out, 0);
- nameBytes = toUTF8Bytes(currentEntry.name, nameLength);
- out.write(nameBytes);
- if (currentEntry.extra != null)
- out.write(currentEntry.extra);
- }
-
- /**
- * Sets the ZipFile comment associated with the file being written.
- *
- */
- public void setComment(String comment) {
- if (comment.length() > 0xFFFF)
- throw new IllegalArgumentException(Msg.getString("K0068"));
- this.comment = comment;
- }
-
- /**
- * Sets the compression level to be used for writing entry data. This level
- * may be set on a per entry basis. level must have a value between 0 and
- * 10.
- *
- */
- public void setLevel(int level) {
- if (level < Deflater.DEFAULT_COMPRESSION
- || level > Deflater.BEST_COMPRESSION)
- throw new IllegalArgumentException();
- compressLevel = level;
- }
-
- /**
- * Sets the compression method to be used when compressing entry data.
- * method must be one of STORED or DEFLATED.
- *
- * @param method
- * Compression method to use
- */
- public void setMethod(int method) {
- if (method != STORED && method != DEFLATED)
- throw new IllegalArgumentException();
- compressMethod = method;
-
- }
-
- private long writeLong(OutputStream os, long i) throws java.io.IOException {
- // Write out the long value as an unsigned int
- os.write((int) (i & 0xFF));
- os.write((int) (i >> 8) & 0xFF);
- os.write((int) (i >> 16) & 0xFF);
- os.write((int) (i >> 24) & 0xFF);
- return i;
- }
-
- private int writeShort(OutputStream os, int i) throws java.io.IOException {
- os.write(i & 0xFF);
- os.write((i >> 8) & 0xFF);
- return i;
-
- }
-
- /**
- * Writes data for the current entry to the underlying stream.
- *
- * @exception IOException
- * If an error occurs writing to the stream
- */
- public void write(byte[] buffer, int off, int nbytes)
- throws java.io.IOException {
- // avoid int overflow, check null buf
- if ((off > buffer.length) || (nbytes < 0) || (off < 0)
- || (buffer.length - off < nbytes)) {
- throw new IndexOutOfBoundsException();
- }
-
- if (currentEntry == null) {
- /* [MSG "K00ab", "No active entry"] */
- throw new ZipException(Msg.getString("K00ab"));
- }
-
- if (currentEntry.getMethod() == STORED)
- out.write(buffer, off, nbytes);
- else
- super.write(buffer, off, nbytes);
- crc.update(buffer, off, nbytes);
- }
-
- static int utf8Count(String value) {
- int total = 0;
- for (int i = value.length(); --i >= 0;) {
- char ch = value.charAt(i);
- if (ch < 0x80)
- total++;
- else if (ch < 0x800)
- total += 2;
- else
- total += 3;
- }
- return total;
- }
-
- static byte[] toUTF8Bytes(String value, int length) {
- byte[] result = new byte[length];
- int pos = result.length;
- for (int i = value.length(); --i >= 0;) {
- char ch = value.charAt(i);
- if (ch < 0x80)
- result[--pos] = (byte) ch;
- else if (ch < 0x800) {
- result[--pos] = (byte) (0x80 | (ch & 0x3f));
- result[--pos] = (byte) (0xc0 | (ch >> 6));
- } else {
- result[--pos] = (byte) (0x80 | (ch & 0x3f));
- result[--pos] = (byte) (0x80 | ((ch >> 6) & 0x3f));
- result[--pos] = (byte) (0xe0 | (ch >> 12));
- }
- }
- return result;
- }
-}
+/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util.zip;
+
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Vector;
+
+import org.apache.harmony.luni.util.Msg;
+
+/**
+ * ZipOuputStream is used to write ZipEntries to the underlying stream. Output
+ * from ZipOutputStream conforms to the ZipFile file format.
+ *
+ * @see ZipInputStream
+ * @see ZipEntry
+ */
+public class ZipOutputStream extends DeflaterOutputStream implements
+ ZipConstants {
+
+ public static final int DEFLATED = 8;
+
+ public static final int STORED = 0;
+
+ static final int ZIPDataDescriptorFlag = 8;
+
+ static final int ZIPLocalHeaderVersionNeeded = 20;
+
+ private String comment;
+
+ private Vector<String> entries = new Vector<String>();
+
+ private int compressMethod = DEFLATED;
+
+ private int compressLevel = Deflater.DEFAULT_COMPRESSION;
+
+ private ByteArrayOutputStream cDir = new ByteArrayOutputStream();
+
+ private ZipEntry currentEntry;
+
+ private CRC32 crc = new CRC32();
+
+ private int offset = 0, curOffset = 0, nameLength;
+
+ private byte[] nameBytes;
+
+ /**
+ * Constructs a new ZipOutputStream on p1
+ *
+ * @param p1
+ * OutputStream The InputStream to output to
+ */
+ public ZipOutputStream(OutputStream p1) {
+ super(p1, new Deflater(Deflater.DEFAULT_COMPRESSION, true));
+ }
+
+ /**
+ * Closes the current ZipEntry if any. Closes the underlying output stream.
+ * If the stream is already closed this method does nothing.
+ *
+ * @exception IOException
+ * If an error occurs closing the stream
+ */
+ public void close() throws IOException {
+ if (out != null) {
+ finish();
+ out.close();
+ out = null;
+ }
+ }
+
+ /**
+ * Closes the current ZipEntry. Any entry terminal data is written to the
+ * underlying stream.
+ *
+ * @exception IOException
+ * If an error occurs closing the entry
+ */
+ public void closeEntry() throws IOException {
+ if (cDir == null)
+ throw new IOException(Msg.getString("K0059"));
+ if (currentEntry == null)
+ return;
+ if (currentEntry.getMethod() == DEFLATED) {
+ super.finish();
+ }
+
+ // Verify values for STORED types
+ if (currentEntry.getMethod() == STORED) {
+ if (crc.getValue() != currentEntry.crc)
+ throw new ZipException(Msg.getString("K0077"));
+ if (currentEntry.size != crc.tbytes)
+ throw new ZipException(Msg.getString("K00ae"));
+ }
+ curOffset = LOCHDR;
+
+ // Write the DataDescriptor
+ if (currentEntry.getMethod() != STORED) {
+ curOffset += EXTHDR;
+ writeLong(out, EXTSIG);
+ writeLong(out, currentEntry.crc = crc.getValue());
+ writeLong(out, currentEntry.compressedSize = def.getTotalOut());
+ writeLong(out, currentEntry.size = def.getTotalIn());
+ }
+ // Update the CentralDirectory
+ writeLong(cDir, CENSIG);
+ writeShort(cDir, ZIPLocalHeaderVersionNeeded); // Version created
+ writeShort(cDir, ZIPLocalHeaderVersionNeeded); // Version to extract
+ writeShort(cDir, currentEntry.getMethod() == STORED ? 0
+ : ZIPDataDescriptorFlag);
+ writeShort(cDir, currentEntry.getMethod());
+ writeShort(cDir, currentEntry.time);
+ writeShort(cDir, currentEntry.modDate);
+ writeLong(cDir, crc.getValue());
+ if (currentEntry.getMethod() == DEFLATED) {
+ curOffset += writeLong(cDir, def.getTotalOut());
+ writeLong(cDir, def.getTotalIn());
+ } else {
+ curOffset += writeLong(cDir, crc.tbytes);
+ writeLong(cDir, crc.tbytes);
+ }
+ curOffset += writeShort(cDir, nameLength);
+ if (currentEntry.extra != null)
+ curOffset += writeShort(cDir, currentEntry.extra.length);
+ else
+ writeShort(cDir, 0);
+ String c;
+ if ((c = currentEntry.getComment()) != null)
+ writeShort(cDir, c.length());
+ else
+ writeShort(cDir, 0);
+ writeShort(cDir, 0); // Disk Start
+ writeShort(cDir, 0); // Internal File Attributes
+ writeLong(cDir, 0); // External File Attributes
+ writeLong(cDir, offset);
+ cDir.write(nameBytes);
+ nameBytes = null;
+ if (currentEntry.extra != null)
+ cDir.write(currentEntry.extra);
+ offset += curOffset;
+ if (c != null)
+ cDir.write(c.getBytes());
+ currentEntry = null;
+ crc.reset();
+ def.reset();
+ done = false;
+ }
+
+ /**
+ * Indicates that all entries have been written to the stream. Any terminal
+ * ZipFile information is written to the underlying stream.
+ *
+ * @exception IOException
+ * If an error occurs while finishing
+ */
+ public void finish() throws IOException {
+ if (out == null)
+ throw new IOException(Msg.getString("K0059"));
+ if (cDir == null)
+ return;
+ if (entries.size() == 0)
+ throw new ZipException(Msg.getString("K00b6"));
+ if (currentEntry != null)
+ closeEntry();
+ int cdirSize = cDir.size();
+ // Write Central Dir End
+ writeLong(cDir, ENDSIG);
+ writeShort(cDir, 0); // Disk Number
+ writeShort(cDir, 0); // Start Disk
+ writeShort(cDir, entries.size()); // Number of entries
+ writeShort(cDir, entries.size()); // Number of entries
+ writeLong(cDir, cdirSize); // Size of central dir
+ writeLong(cDir, offset); // Offset of central dir
+ if (comment != null) {
+ writeShort(cDir, comment.length());
+ cDir.write(comment.getBytes());
+ } else
+ writeShort(cDir, 0);
+ // Write the central dir
+ out.write(cDir.toByteArray());
+ cDir = null;
+
+ }
+
+ /**
+ * Writes entry information for ze to the underlying stream. Data associated
+ * with the entry can then be written using write(). After data is written
+ * closeEntry() must be called to complete the storing of ze on the
+ * underlying stream.
+ *
+ * @param ze
+ * ZipEntry to store
+ * @exception IOException
+ * If an error occurs storing the entry
+ * @see #write
+ */
+ public void putNextEntry(ZipEntry ze) throws java.io.IOException {
+ if (currentEntry != null)
+ closeEntry();
+ if (ze.getMethod() == STORED
+ || (compressMethod == STORED && ze.getMethod() == -1)) {
+ if (ze.crc == -1)
+ /* [MSG "K0077", "Crc mismatch"] */
+ throw new ZipException(Msg.getString("K0077"));
+ if (ze.size == -1 && ze.compressedSize == -1)
+ /* [MSG "K00ae", "Size mismatch"] */
+ throw new ZipException(Msg.getString("K00ae"));
+ if (ze.size != ze.compressedSize && ze.compressedSize != -1
+ && ze.size != -1)
+ /* [MSG "K00ae", "Size mismatch"] */
+ throw new ZipException(Msg.getString("K00ae"));
+ }
+ /* [MSG "K0059", "Stream is closed"] */
+ if (cDir == null)
+ throw new IOException(Msg.getString("K0059"));
+ if (entries.contains(ze.name))
+ /* [MSG "K0066", "Entry already exists: {0}"] */
+ throw new ZipException(Msg.getString("K0066", ze.name));
+ nameLength = utf8Count(ze.name);
+ if (nameLength > 0xffff)
+ /* [MSG "K01a7", "Name too long: {0}"] */
+ throw new IllegalArgumentException(Msg.getString("K01a7", ze.name));
+
+ def.setLevel(compressLevel);
+ currentEntry = ze;
+ entries.add(currentEntry.name);
+ if (currentEntry.getMethod() == -1)
+ currentEntry.setMethod(compressMethod);
+ writeLong(out, LOCSIG); // Entry header
+ writeShort(out, ZIPLocalHeaderVersionNeeded); // Extraction version
+ writeShort(out, currentEntry.getMethod() == STORED ? 0
+ : ZIPDataDescriptorFlag);
+ writeShort(out, currentEntry.getMethod());
+ if (currentEntry.getTime() == -1)
+ currentEntry.setTime(System.currentTimeMillis());
+ writeShort(out, currentEntry.time);
+ writeShort(out, currentEntry.modDate);
+
+ if (currentEntry.getMethod() == STORED) {
+ if (currentEntry.size == -1)
+ currentEntry.size = currentEntry.compressedSize;
+ else if (currentEntry.compressedSize == -1)
+ currentEntry.compressedSize = currentEntry.size;
+ writeLong(out, currentEntry.crc);
+ writeLong(out, currentEntry.size);
+ writeLong(out, currentEntry.size);
+ } else {
+ writeLong(out, 0);
+ writeLong(out, 0);
+ writeLong(out, 0);
+ }
+ writeShort(out, nameLength);
+ if (currentEntry.extra != null)
+ writeShort(out, currentEntry.extra.length);
+ else
+ writeShort(out, 0);
+ nameBytes = toUTF8Bytes(currentEntry.name, nameLength);
+ out.write(nameBytes);
+ if (currentEntry.extra != null)
+ out.write(currentEntry.extra);
+ }
+
+ /**
+ * Sets the ZipFile comment associated with the file being written.
+ *
+ */
+ public void setComment(String comment) {
+ if (comment.length() > 0xFFFF)
+ throw new IllegalArgumentException(Msg.getString("K0068"));
+ this.comment = comment;
+ }
+
+ /**
+ * Sets the compression level to be used for writing entry data. This level
+ * may be set on a per entry basis. level must have a value between 0 and
+ * 10.
+ *
+ */
+ public void setLevel(int level) {
+ if (level < Deflater.DEFAULT_COMPRESSION
+ || level > Deflater.BEST_COMPRESSION)
+ throw new IllegalArgumentException();
+ compressLevel = level;
+ }
+
+ /**
+ * Sets the compression method to be used when compressing entry data.
+ * method must be one of STORED or DEFLATED.
+ *
+ * @param method
+ * Compression method to use
+ */
+ public void setMethod(int method) {
+ if (method != STORED && method != DEFLATED)
+ throw new IllegalArgumentException();
+ compressMethod = method;
+
+ }
+
+ private long writeLong(OutputStream os, long i) throws java.io.IOException {
+ // Write out the long value as an unsigned int
+ os.write((int) (i & 0xFF));
+ os.write((int) (i >> 8) & 0xFF);
+ os.write((int) (i >> 16) & 0xFF);
+ os.write((int) (i >> 24) & 0xFF);
+ return i;
+ }
+
+ private int writeShort(OutputStream os, int i) throws java.io.IOException {
+ os.write(i & 0xFF);
+ os.write((i >> 8) & 0xFF);
+ return i;
+
+ }
+
+ /**
+ * Writes data for the current entry to the underlying stream.
+ *
+ * @exception IOException
+ * If an error occurs writing to the stream
+ */
+ public void write(byte[] buffer, int off, int nbytes)
+ throws java.io.IOException {
+ // avoid int overflow, check null buf
+ if ((off > buffer.length) || (nbytes < 0) || (off < 0)
+ || (buffer.length - off < nbytes)) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ if (currentEntry == null) {
+ /* [MSG "K00ab", "No active entry"] */
+ throw new ZipException(Msg.getString("K00ab"));
+ }
+
+ if (currentEntry.getMethod() == STORED)
+ out.write(buffer, off, nbytes);
+ else
+ super.write(buffer, off, nbytes);
+ crc.update(buffer, off, nbytes);
+ }
+
+ static int utf8Count(String value) {
+ int total = 0;
+ for (int i = value.length(); --i >= 0;) {
+ char ch = value.charAt(i);
+ if (ch < 0x80)
+ total++;
+ else if (ch < 0x800)
+ total += 2;
+ else
+ total += 3;
+ }
+ return total;
+ }
+
+ static byte[] toUTF8Bytes(String value, int length) {
+ byte[] result = new byte[length];
+ int pos = result.length;
+ for (int i = value.length(); --i >= 0;) {
+ char ch = value.charAt(i);
+ if (ch < 0x80)
+ result[--pos] = (byte) ch;
+ else if (ch < 0x800) {
+ result[--pos] = (byte) (0x80 | (ch & 0x3f));
+ result[--pos] = (byte) (0xc0 | (ch >> 6));
+ } else {
+ result[--pos] = (byte) (0x80 | (ch & 0x3f));
+ result[--pos] = (byte) (0x80 | ((ch >> 6) & 0x3f));
+ result[--pos] = (byte) (0xe0 | (ch >> 12));
+ }
+ }
+ return result;
+ }
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipOutputStream.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: incubator/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/BHSDCodec.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/BHSDCodec.java?view=diff&rev=446478&r1=446477&r2=446478
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/BHSDCodec.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/BHSDCodec.java Thu Sep 14 19:40:33 2006
@@ -1,283 +1,283 @@
-/*
- * Copyright 2006 The Apache Software Foundation or its licensors,
- * as applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.harmony.archive.internal.pack200;
-
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * TODO Comment -- quite a lot can be nicked from Codec, since this was created
- * from it
- *
- * @author Alex Blewitt
- *
- */
-public final class BHSDCodec extends Codec {
-
- /**
- * The maximum number of bytes in each coding word
- */
- private int b;
-
- /**
- * Whether delta encoding is used (0=false,1=true)
- */
- private int d;
-
- /**
- * The radix of the encoding
- */
- private int h;
-
- /**
- * The co-parameter of h; h-256
- */
- private int l;
-
- /**
- * Represents signed numbers or not (0=unsigned,1/2=signed)
- */
- private int s;
-
- /**
- * Constructs an unsigned, non-delta Codec with the given B and H values.
- *
- * @param b
- * the maximum number of bytes that a value can be encoded as
- * [1..5]
- * @param h
- * the radix of the encoding [1..256]
- */
- public BHSDCodec(int b, int h) {
- this(b, h, 0);
- }
-
- /**
- * Constructs a non-delta Codec with the given B, H and S values.
- *
- * @param b
- * the maximum number of bytes that a value can be encoded as
- * [1..5]
- * @param h
- * the radix of the encoding [1..256]
- * @param s
- * whether the encoding represents signed numbers (s=0 is
- * unsigned; s=1 is signed with 1s complement; s=2 is signed with ?)
- */
- public BHSDCodec(int b, int h, int s) {
- this(b, h, s, 0);
- }
-
- /**
- * Constructs a Codec with the given B, H, S and D values.
- *
- * @param b
- * the maximum number of bytes that a value can be encoded as
- * [1..5]
- * @param h
- * the radix of the encoding [1..256]
- * @param s
- * whether the encoding represents signed numbers (s=0 is
- * unsigned; s=1 is signed with 1s complement; s=2 is signed with ?)
- * @param d
- * whether this is a delta encoding (d=0 is non-delta; d=1 is
- * delta)
- */
- public BHSDCodec(int b, int h, int s, int d) {
- if (b < 1 || b > 5)
- throw new IllegalArgumentException("1<=b<=5");
- if (h < 1 || h > 256)
- throw new IllegalArgumentException("1<=h<=256");
- if (s < 0 || s > 2)
- throw new IllegalArgumentException("0<=s<=2");
- if (d < 0 || d > 1)
- throw new IllegalArgumentException("0<=d<=1");
- if (b == 1 && h != 256)
- throw new IllegalArgumentException("b=1 -> h=256");
- if (h == 256 && b == 5)
- throw new IllegalArgumentException("h=256 -> b!=5");
- this.b = b;
- this.h = h;
- this.s = s;
- this.d = d;
- this.l = 256 - h;
- }
-
- /**
- * Returns the cardinality of this codec; that is, the number of distinct
- * values that it can contain.
- *
- * @return the cardinality of this codec
- */
- public long cardinality() {
- if (h > 1) {
- return (long) (l * Math.pow(1 - h, b) / (1 - h) + Math.pow(h, b));
- } else {
- return (b * 255) + 1;
- }
- }
-
- @Override
- public long decode(InputStream in) throws IOException, Pack200Exception {
- if (d != 0)
- throw new Pack200Exception(
- "Delta encoding used without passing in last value; this is a coding error");
- return decode(in, 0);
- }
-
- @Override
- public long decode(InputStream in, long last) throws IOException,
- Pack200Exception {
- int n = 0;
- long z = 0;
- long x;
- do {
- x = in.read();
- if (x == -1)
- throw new EOFException("End of stream reached whilst decoding");
- z += x * Math.pow(h, n);
- } while (++n < b && x >= l);
- // This looks more complicated than it is
- // When s=0, {1,2,3,4} is mapped to {1,2,3,4}
- // When s=1, {1,2,3,4} is mapped to {-1,1,-2,2...}
- // When s=2, {1,2,3,4} is mapped to {1,2,3,-1...}
- if (isSigned()) {
- int u = ((1 << s) - 1);
- if ((z & u) == u) {
- z = z >>> s ^ -1L;
- } else {
- z = z - (z >>> s);
- }
- }
- if (isDelta())
- z += last;
- return z;
- }
-
- /**
- * True if this encoding can code the given value
- *
- * @param value
- * the value to check
- * @return <code>true</code> if the encoding can encode this value
- */
- public boolean encodes(long value) {
- return (value >= smallest() && value <= largest());
- }
-
- /**
- * Returns true if this codec is a delta codec
- * @return true if this codec is a delta codec
- */
- public boolean isDelta() {
- return d != 0;
- }
-
- /**
- * Returns true if this codec is a signed codec
- * @return true if this codec is a signed codec
- */
- public boolean isSigned() {
- return s != 0;
- }
-
- /**
- * Returns the largest value that this codec can represent.
- *
- * @eturn the largest value that this codec can represent.
- */
- public long largest() {
- long result;
- if (isDelta()) {
- result = Long.MAX_VALUE;
- } else {
- // TODO This can probably be optimised into a better mathematical statement
- if (s == 0) {
- result = cardinality() - 1;
- } else if (s == 1) {
- result = cardinality() / 2 - 1;
- } else if (s == 2) {
- result = (3L * cardinality()) / 4 - 1;
- } else {
- throw new Error("Unknown s value");
- }
- }
- return Math.min((s == 0 ? ((long) Integer.MAX_VALUE) << 1
- : Integer.MAX_VALUE) - 1, result);
- }
- /**
- * Returns the smallest value that this codec can represent.
- *
- * @eturn the smallest value that this codec can represent.
- */
- public long smallest() {
- long result;
- if (isDelta()) {
- result = Integer.MIN_VALUE;
- } else {
- if (isSigned()) {
- result = -cardinality() / (1 << s);
- } else {
- result = 0;
- }
- }
- return Math.max(Integer.MIN_VALUE, result);
- }
- /**
- * Returns the codec in the form (1,256) or (1,64,1,1). Note that trailing
- * zero fields are not shown.
- */
- public String toString() {
- StringBuffer buffer = new StringBuffer(11);
- buffer.append('(');
- buffer.append(b);
- buffer.append(',');
- buffer.append(h);
- if (s != 0 || d != 0) {
- buffer.append(",");
- buffer.append(s);
- }
- if (d != 0) {
- buffer.append(",");
- buffer.append(d);
- }
- buffer.append(')');
- return buffer.toString();
- }
-
- /**
- * @return the b
- */
- public int getB() {
- return b;
- }
-
- /**
- * @return the h
- */
- public int getH() {
- return h;
- }
-
- /**
- * @return the l
- */
- public int getL() {
- return l;
- }
-}
+/*
+ * Copyright 2006 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.archive.internal.pack200;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * TODO Comment -- quite a lot can be nicked from Codec, since this was created
+ * from it
+ *
+ * @author Alex Blewitt
+ *
+ */
+public final class BHSDCodec extends Codec {
+
+ /**
+ * The maximum number of bytes in each coding word
+ */
+ private int b;
+
+ /**
+ * Whether delta encoding is used (0=false,1=true)
+ */
+ private int d;
+
+ /**
+ * The radix of the encoding
+ */
+ private int h;
+
+ /**
+ * The co-parameter of h; h-256
+ */
+ private int l;
+
+ /**
+ * Represents signed numbers or not (0=unsigned,1/2=signed)
+ */
+ private int s;
+
+ /**
+ * Constructs an unsigned, non-delta Codec with the given B and H values.
+ *
+ * @param b
+ * the maximum number of bytes that a value can be encoded as
+ * [1..5]
+ * @param h
+ * the radix of the encoding [1..256]
+ */
+ public BHSDCodec(int b, int h) {
+ this(b, h, 0);
+ }
+
+ /**
+ * Constructs a non-delta Codec with the given B, H and S values.
+ *
+ * @param b
+ * the maximum number of bytes that a value can be encoded as
+ * [1..5]
+ * @param h
+ * the radix of the encoding [1..256]
+ * @param s
+ * whether the encoding represents signed numbers (s=0 is
+ * unsigned; s=1 is signed with 1s complement; s=2 is signed with ?)
+ */
+ public BHSDCodec(int b, int h, int s) {
+ this(b, h, s, 0);
+ }
+
+ /**
+ * Constructs a Codec with the given B, H, S and D values.
+ *
+ * @param b
+ * the maximum number of bytes that a value can be encoded as
+ * [1..5]
+ * @param h
+ * the radix of the encoding [1..256]
+ * @param s
+ * whether the encoding represents signed numbers (s=0 is
+ * unsigned; s=1 is signed with 1s complement; s=2 is signed with ?)
+ * @param d
+ * whether this is a delta encoding (d=0 is non-delta; d=1 is
+ * delta)
+ */
+ public BHSDCodec(int b, int h, int s, int d) {
+ if (b < 1 || b > 5)
+ throw new IllegalArgumentException("1<=b<=5");
+ if (h < 1 || h > 256)
+ throw new IllegalArgumentException("1<=h<=256");
+ if (s < 0 || s > 2)
+ throw new IllegalArgumentException("0<=s<=2");
+ if (d < 0 || d > 1)
+ throw new IllegalArgumentException("0<=d<=1");
+ if (b == 1 && h != 256)
+ throw new IllegalArgumentException("b=1 -> h=256");
+ if (h == 256 && b == 5)
+ throw new IllegalArgumentException("h=256 -> b!=5");
+ this.b = b;
+ this.h = h;
+ this.s = s;
+ this.d = d;
+ this.l = 256 - h;
+ }
+
+ /**
+ * Returns the cardinality of this codec; that is, the number of distinct
+ * values that it can contain.
+ *
+ * @return the cardinality of this codec
+ */
+ public long cardinality() {
+ if (h > 1) {
+ return (long) (l * Math.pow(1 - h, b) / (1 - h) + Math.pow(h, b));
+ } else {
+ return (b * 255) + 1;
+ }
+ }
+
+ @Override
+ public long decode(InputStream in) throws IOException, Pack200Exception {
+ if (d != 0)
+ throw new Pack200Exception(
+ "Delta encoding used without passing in last value; this is a coding error");
+ return decode(in, 0);
+ }
+
+ @Override
+ public long decode(InputStream in, long last) throws IOException,
+ Pack200Exception {
+ int n = 0;
+ long z = 0;
+ long x;
+ do {
+ x = in.read();
+ if (x == -1)
+ throw new EOFException("End of stream reached whilst decoding");
+ z += x * Math.pow(h, n);
+ } while (++n < b && x >= l);
+ // This looks more complicated than it is
+ // When s=0, {1,2,3,4} is mapped to {1,2,3,4}
+ // When s=1, {1,2,3,4} is mapped to {-1,1,-2,2...}
+ // When s=2, {1,2,3,4} is mapped to {1,2,3,-1...}
+ if (isSigned()) {
+ int u = ((1 << s) - 1);
+ if ((z & u) == u) {
+ z = z >>> s ^ -1L;
+ } else {
+ z = z - (z >>> s);
+ }
+ }
+ if (isDelta())
+ z += last;
+ return z;
+ }
+
+ /**
+ * True if this encoding can code the given value
+ *
+ * @param value
+ * the value to check
+ * @return <code>true</code> if the encoding can encode this value
+ */
+ public boolean encodes(long value) {
+ return (value >= smallest() && value <= largest());
+ }
+
+ /**
+ * Returns true if this codec is a delta codec
+ * @return true if this codec is a delta codec
+ */
+ public boolean isDelta() {
+ return d != 0;
+ }
+
+ /**
+ * Returns true if this codec is a signed codec
+ * @return true if this codec is a signed codec
+ */
+ public boolean isSigned() {
+ return s != 0;
+ }
+
+ /**
+ * Returns the largest value that this codec can represent.
+ *
+ * @eturn the largest value that this codec can represent.
+ */
+ public long largest() {
+ long result;
+ if (isDelta()) {
+ result = Long.MAX_VALUE;
+ } else {
+ // TODO This can probably be optimised into a better mathematical statement
+ if (s == 0) {
+ result = cardinality() - 1;
+ } else if (s == 1) {
+ result = cardinality() / 2 - 1;
+ } else if (s == 2) {
+ result = (3L * cardinality()) / 4 - 1;
+ } else {
+ throw new Error("Unknown s value");
+ }
+ }
+ return Math.min((s == 0 ? ((long) Integer.MAX_VALUE) << 1
+ : Integer.MAX_VALUE) - 1, result);
+ }
+ /**
+ * Returns the smallest value that this codec can represent.
+ *
+ * @eturn the smallest value that this codec can represent.
+ */
+ public long smallest() {
+ long result;
+ if (isDelta()) {
+ result = Integer.MIN_VALUE;
+ } else {
+ if (isSigned()) {
+ result = -cardinality() / (1 << s);
+ } else {
+ result = 0;
+ }
+ }
+ return Math.max(Integer.MIN_VALUE, result);
+ }
+ /**
+ * Returns the codec in the form (1,256) or (1,64,1,1). Note that trailing
+ * zero fields are not shown.
+ */
+ public String toString() {
+ StringBuffer buffer = new StringBuffer(11);
+ buffer.append('(');
+ buffer.append(b);
+ buffer.append(',');
+ buffer.append(h);
+ if (s != 0 || d != 0) {
+ buffer.append(",");
+ buffer.append(s);
+ }
+ if (d != 0) {
+ buffer.append(",");
+ buffer.append(d);
+ }
+ buffer.append(')');
+ return buffer.toString();
+ }
+
+ /**
+ * @return the b
+ */
+ public int getB() {
+ return b;
+ }
+
+ /**
+ * @return the h
+ */
+ public int getH() {
+ return h;
+ }
+
+ /**
+ * @return the l
+ */
+ public int getL() {
+ return l;
+ }
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/BHSDCodec.java
------------------------------------------------------------------------------
svn:eol-style = native
|