diff options
author | tromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4> | 1999-05-18 15:33:03 +0000 |
---|---|---|
committer | tromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4> | 1999-05-18 15:33:03 +0000 |
commit | e3b4a43d3b394f8009bdae0960c9e3240f8cf736 (patch) | |
tree | c538fe74824c64ba74944a357c354f0c77e93be5 /libjava/java/util/zip/ZipOutputStream.java | |
parent | addd693c880eb9310e8229fbbb4a37df4f550367 (diff) | |
download | ppe42-gcc-e3b4a43d3b394f8009bdae0960c9e3240f8cf736.tar.gz ppe42-gcc-e3b4a43d3b394f8009bdae0960c9e3240f8cf736.zip |
* java/util/zip/ZipOutputStream.java (level): Initial value is
Deflater.DEFAULT_COMPRESSION.
(close): New method.
(closeEntry): Likewise.
(finish): Likewise.
(put_version): Likewise.
(write_entry): Likewise.
(put2, put4): Now return `int'.
(comment): Default to empty string.
(bytes_written): New instance variable.
(chain): Likewise.
* java/util/zip/ZipEntry.java (setComment): Limit length of
comment string.
(setCrc): Check CRC validity.
(setExtra): Check argument validity.
(setMethod): Likewise.
(setSize): Likewise.
(ZipEntry): Likewise.
* include/javaprims.h: Updated namespace declarations.
* Makefile.in: Rebuilt.
* Makefile.am (ordinary_java_source_files): Mention new files.
(nat_source_files): Likewise.
* java/util/zip/ZipFile.java (readu2): Throw ZipException, not
EOFException.
(read4): Likewise.
(getInputStream): Handle compressed entries.
* java/util/zip/GZIPOutputStream.java: New file.
* java/util/zip/GZIPInputStream.java: New file.
* java/util/zip/DataFormatException.java: New file.
* java/util/zip/CheckedInputStream.java: New file.
* java/util/zip/CheckedOutputStream.java: New file.
* java/util/zip/InflaterInputStream.java: Implemented.
* java/util/zip/natInflater.cc: New file.
* java/util/zip/Deflater.java: Implemented.
* java/util/zip/natDeflater.cc: New file.
* java/util/zip/DeflaterOutputStream.java: Implemented.
* java/util/zip/ZipInputStream.java (closeZipEntry): Throw
ZipException, not IOException.
* java/util/zip/ZipFile.java (readDirectory): Throw ZipException,
not IOException.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@26996 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava/java/util/zip/ZipOutputStream.java')
-rw-r--r-- | libjava/java/util/zip/ZipOutputStream.java | 263 |
1 files changed, 233 insertions, 30 deletions
diff --git a/libjava/java/util/zip/ZipOutputStream.java b/libjava/java/util/zip/ZipOutputStream.java index 18f4d388652..f4ce7accc01 100644 --- a/libjava/java/util/zip/ZipOutputStream.java +++ b/libjava/java/util/zip/ZipOutputStream.java @@ -9,65 +9,268 @@ details. */ package java.util.zip; import java.io.*; -/** JUST AN INCOMPLETE STUB! */ +/* Written using on-line Java Platform 1.2 API Specification + * and JCL book. + * Believed complete and correct. + */ public class ZipOutputStream extends DeflaterOutputStream implements ZipConstants { - ZipEntry current; - int method = DEFLATED; - int level = 3; // FIXME - should be DEFAULT_COMPRESSION - String comment; - public static final int STORED = 0; public static final int DEFLATED = 8; - public ZipOutputStream (OutputStream out) + public void close () throws IOException { - super(out); + finish (); + out.close(); + } + + public void closeEntry () throws IOException + { + int uncompressed_size = def.getTotalIn(); + int compressed_size = def.getTotalOut(); + int crc = (int) (filter.getChecksum().getValue()); + + bytes_written += compressed_size; + + bytes_written += put4 (0x08074b50); + if (current.getCrc() == -1 || current.getCompressedSize() == -1 + || current.getSize() == -1) + { + current.setCrc(crc); + current.compressedSize = compressed_size; + current.setSize(uncompressed_size); + } + else + { + if (current.getCrc() != crc + || current.getCompressedSize() != compressed_size + || current.getSize() != uncompressed_size) + throw new ZipException ("zip entry field incorrect"); + } + bytes_written += put4 ((int) (current.getCrc())); + bytes_written += put4 ((int) (current.getCompressedSize())); + bytes_written += put4 ((int) (current.getSize())); + + current.next = chain; + chain = current; + current = null; + filter = null; + } + + public void finish () throws IOException + { + if (current != null) + closeEntry (); + + // Write the central directory. + long offset = bytes_written; + int count = 0; + int bytes = 0; + while (chain != null) + { + bytes += write_entry (chain, false); + ++count; + chain = chain.next; + } + + // Write the end of the central directory record. + put4 (0x06054b50); + // Disk number. + put2 (0); + // Another disk number. + put2 (0); + put2 (count); + put4 (bytes); + put4 ((int) offset); + + byte[] c = comment.getBytes("8859_1"); + put2 (c.length); + out.write(c); + out.write((byte) 0); } - public void setLevel (int level) { this.level = level; } - public void setMethod (int method) { this.method = method; } - public void setComment(String comment) { this.comment = comment; } + // Helper for finish and putNextEntry. + private int write_entry (ZipEntry entry, boolean is_local) + throws IOException + { + long offset = bytes_written; + + int bytes = put4 (is_local ? 0x04034b50 : 0x02014b50); + if (! is_local) + bytes += put_version (); + bytes += put_version (); + + boolean crc_after = false; + if (is_local + && (current.getCrc() == -1 || current.getCompressedSize() == -1 + || current.getSize() == -1)) + crc_after = true; + // For the bits field we always indicate `normal' compression, + // even if that isn't true. + bytes += put2 (crc_after ? (1 << 3) : 0); + bytes += put2 (entry.method); + + bytes += put2(0); // time - FIXME + bytes += put2(0); // date - FIXME + + if (crc_after) + { + // CRC, compressedSize, and Size are always 0 in this header. + // The actual values are given after the entry. + bytes += put4 (0); + bytes += put4 (0); + bytes += put4 (0); + } + else + { + bytes += put4 ((int) (entry.getCrc())); + bytes += put4 ((int) (entry.getCompressedSize())); + bytes += put4 ((int) (entry.getSize())); + } + + byte[] name = entry.name.getBytes("8859_1"); + bytes += put2 (name.length); + bytes += put2 (entry.extra == null ? 0 : entry.extra.length); + + byte[] comment = null; + if (! is_local) + { + if (entry.getComment() == null) + bytes += put2 (0); + else + { + comment = entry.getComment().getBytes("8859_1"); + bytes += put2 (comment.length); + } + + // Disk number start. + bytes += put2 (0); + // Internal file attributes. + bytes += put2 (0); + // External file attributes. + bytes += put2 (0); + // Relative offset of local header. + bytes += put2 ((int) offset); + } + + out.write (name); + out.write ((byte) 0); + bytes += name.length + 1; + if (entry.extra != null) + { + out.write(entry.extra); + out.write((byte) 0); + bytes += entry.extra.length + 1; + } + if (comment != null) + { + out.write(comment); + out.write((byte) 0); + bytes += comment.length + 1; + } + + bytes_written += bytes; + return bytes; + } public void putNextEntry (ZipEntry entry) throws IOException { - put4(0x04034b50); - put2(0); // version - FIXME - put2(0); // bits - FIXME + if (current != null) + closeEntry (); + if (entry.method < 0 ) entry.method = method; - put2(entry.method); - put2(0); // time - FIXME - put2(0); // date - FIXME - put4((int) entry.crc); - put4((int) entry.compressedSize); // FIXME - put4((int) entry.size); // FIXME - put2(entry.name.length()); - put2(entry.extra == null ? 0 : entry.extra.length); - byte[] name = entry.name.getBytes("8859_1"); - out.write(name); - if (entry.extra != null) - out.write(entry.extra); - throw new Error ("java.util.zip.ZipOutputStream.putNextEntry: not implemented"); + if (entry.method == STORED) + { + if (entry.getSize() == -1 || entry.getCrc() == -1) + throw new ZipException ("required entry not set"); + // Just in case. + entry.compressedSize = entry.getSize(); + } + write_entry (entry, true); + current = entry; + int compr = (method == STORED) ? Deflater.NO_COMPRESSION : level; + def.reset(); + def.setLevel(compr); + filter = new CheckedOutputStream (new DeflaterOutputStream (out, def), + new CRC32 ()); } - public void closeEntry () throws IOException + public void setLevel (int level) { + if (level != Deflater.DEFAULT_COMPRESSION + && (level < Deflater.NO_COMPRESSION + || level > Deflater.BEST_COMPRESSION)) + throw new IllegalArgumentException (); + this.level = level; } - private void put2 (int i) throws IOException + public void setMethod (int method) + { + if (method != DEFLATED && method != STORED) + throw new IllegalArgumentException (); + this.method = method; + } + + public void setComment (String comment) + { + if (comment.length() > 65535) + throw new IllegalArgumentException (); + this.comment = comment; + } + + public synchronized void write (byte[] buf, int off, int len) + throws IOException + { + if (filter == null) + throw new ZipException ("no open zip entry"); + filter.write(buf, off, len); + } + + public ZipOutputStream (OutputStream out) + { + super (out); + def = new Deflater (level, true); + } + + private int put2 (int i) throws IOException { out.write (i); out.write (i >> 8); + return 2; } - private void put4 (int i) throws IOException + private int put4 (int i) throws IOException { out.write (i); out.write (i >> 8); out.write (i >> 16); out.write (i >> 24); + return 4; } + + private int put_version () throws IOException + { + // FIXME: for now we assume Unix, and we ignore the version + // number. + return put2 (3 << 8); + } + + // The entry we are currently writing, or null if we've called + // closeEntry. + private ZipEntry current; + // The chain of entries which have been written to this file. + private ZipEntry chain; + // The output stream to which data should be sent. + private CheckedOutputStream filter; + + private int method = DEFLATED; + private int level = Deflater.DEFAULT_COMPRESSION; + private String comment = ""; + private long bytes_written; + + // The Deflater we use. + private Deflater def; } |