ZipOutputStream.java (level): Initial value is Deflater.DEFAULT_COMPRESSION.

* 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.

From-SVN: r26996
This commit is contained in:
Tom Tromey 1999-05-18 15:33:03 +00:00 committed by Tom Tromey
parent 5a9e5c6fb6
commit 0ffac8322f
19 changed files with 1555 additions and 80 deletions

View File

@ -1,3 +1,47 @@
1999-05-18 Tom Tromey <tromey@cygnus.com>
* 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.
1999-05-17 Tom Tromey <tromey@cygnus.com>
* java/lang/natSystem.cc (init_properties): URL now points to

View File

@ -654,9 +654,15 @@ java/util/TooManyListenersException.java \
java/util/Vector.java \
java/util/zip/Adler32.java \
java/util/zip/CRC32.java \
java/util/zip/CheckedInputStream.java \
java/util/zip/CheckedOutputStream.java \
java/util/zip/Checksum.java \
java/util/zip/DataFormatException.java \
java/util/zip/Deflater.java \
java/util/zip/DeflaterOutputStream.java \
java/util/zip/GZIPInputStream.java \
java/util/zip/GZIPOutputStream.java \
java/util/zip/Inflater.java \
java/util/zip/InflaterInputStream.java \
java/util/zip/ZipConstants.java \
java/util/zip/ZipEntry.java \
@ -715,7 +721,9 @@ java/net/natInetAddress.cc \
java/net/natPlainSocketImpl.cc \
java/text/natCollator.cc \
java/util/natDate.cc \
java/util/natGregorianCalendar.cc
java/util/natGregorianCalendar.cc \
java/util/zip/natDeflater.cc \
java/util/zip/natInflater.cc
## ################################################################

View File

@ -203,7 +203,7 @@ jv_convert_LINK = $(LIBTOOL) --mode=link $(GCJ) $(JC1FLAGS) $(LDFLAGS) \
-o jv-convert
jv_convert_LDADD = $(convert_source_files:.java=.lo) libgcj.la \
$(GCLIBS) $(THREADLIBS) $(ZLIBS)
$(GCLIBS) $(THREADLIBS) $(ZLIBS) -L$(here)/.libs
jv_convert_DEPENDENCIES = $(convert_source_files:.java=.lo) \
$(GCDEPS) $(THREADDEPS) $(ZDEPS) libgcj.la libgcj.spec
@ -505,9 +505,15 @@ java/util/TooManyListenersException.java \
java/util/Vector.java \
java/util/zip/Adler32.java \
java/util/zip/CRC32.java \
java/util/zip/CheckedInputStream.java \
java/util/zip/CheckedOutputStream.java \
java/util/zip/Checksum.java \
java/util/zip/DataFormatException.java \
java/util/zip/Deflater.java \
java/util/zip/DeflaterOutputStream.java \
java/util/zip/GZIPInputStream.java \
java/util/zip/GZIPOutputStream.java \
java/util/zip/Inflater.java \
java/util/zip/InflaterInputStream.java \
java/util/zip/ZipConstants.java \
java/util/zip/ZipEntry.java \
@ -566,7 +572,9 @@ java/net/natInetAddress.cc \
java/net/natPlainSocketImpl.cc \
java/text/natCollator.cc \
java/util/natDate.cc \
java/util/natGregorianCalendar.cc
java/util/natGregorianCalendar.cc \
java/util/zip/natDeflater.cc \
java/util/zip/natInflater.cc
# Work around what appears to be a GNU make bug handling MAKEFLAGS
@ -832,9 +840,14 @@ DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
.deps/java/util/Stack.P .deps/java/util/StringTokenizer.P \
.deps/java/util/TimeZone.P .deps/java/util/TooManyListenersException.P \
.deps/java/util/Vector.P .deps/java/util/zip/Adler32.P \
.deps/java/util/zip/CRC32.P .deps/java/util/zip/Checksum.P \
.deps/java/util/zip/CRC32.P .deps/java/util/zip/CheckedInputStream.P \
.deps/java/util/zip/CheckedOutputStream.P \
.deps/java/util/zip/Checksum.P \
.deps/java/util/zip/DataFormatException.P \
.deps/java/util/zip/Deflater.P \
.deps/java/util/zip/DeflaterOutputStream.P \
.deps/java/util/zip/GZIPInputStream.P \
.deps/java/util/zip/GZIPOutputStream.P .deps/java/util/zip/Inflater.P \
.deps/java/util/zip/InflaterInputStream.P \
.deps/java/util/zip/ZipConstants.P .deps/java/util/zip/ZipEntry.P \
.deps/java/util/zip/ZipException.P .deps/java/util/zip/ZipFile.P \

View File

@ -211,9 +211,15 @@ extern "Java"
{
class Adler32;
class CRC32;
class CheckedInputStream;
class CheckedOutputStream;
class Checksum;
class DataFormatException;
class Deflater;
class DeflaterOutputStream;
class GZIPInputStream;
class GZIPOutputStream;
class Inflater;
class InflaterInputStream;
class ZipConstants;
class ZipEntry;

View File

@ -0,0 +1,80 @@
// CheckedInputStream.java - Compute checksum of data being read.
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.util.zip;
import java.io.FilterInputStream;
import java.io.InputStream;
import java.io.IOException;
/**
* @author Tom Tromey
* @date May 17, 1999
*/
/* Written using on-line Java Platform 1.2 API Specification
* and JCL book.
* Believed complete and correct.
*/
public class CheckedInputStream extends FilterInputStream
{
public CheckedInputStream (InputStream in, Checksum sum)
{
super (in);
this.sum = sum;
}
public Checksum getChecksum ()
{
return sum;
}
public int read () throws IOException
{
int x = in.read();
if (x != -1)
sum.update(x);
return x;
}
public int read (byte[] buf, int off, int len) throws IOException
{
int r = in.read(buf, off, len);
if (r != -1)
sum.update(buf, off, r);
return r;
}
public long skip (long n) throws IOException
{
if (n == 0)
return 0;
int min = (int) Math.min(n, 1024);
byte[] buf = new byte[min];
long s = 0;
while (n > 0)
{
int r = in.read(buf, 0, min);
if (r == -1)
break;
n -= r;
s += r;
sum.update(buf, 0, r);
}
return s;
}
// The checksum object.
private Checksum sum;
}

View File

@ -0,0 +1,54 @@
// CheckedOutputStream.java - Compute checksum of data being written.
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.util.zip;
import java.io.FilterOutputStream;
import java.io.OutputStream;
import java.io.IOException;
/**
* @author Tom Tromey
* @date May 17, 1999
*/
/* Written using on-line Java Platform 1.2 API Specification
* and JCL book.
* Believed complete and correct.
*/
public class CheckedOutputStream extends FilterOutputStream
{
public CheckedOutputStream (OutputStream out, Checksum cksum)
{
super (out);
this.sum = cksum;
}
public Checksum getChecksum ()
{
return sum;
}
public void write (int bval) throws IOException
{
out.write(bval);
sum.update(bval);
}
public void write (byte[] buf, int off, int len) throws IOException
{
out.write(buf, off, len);
sum.update(buf, off, len);
}
// The checksum object.
private Checksum sum;
}

View File

@ -0,0 +1,33 @@
// DataFormatException.java
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libjava.
This software is copyrighted work licensed under the terms of the
Libjava License. Please consult the file "LIBJAVA_LICENSE" for
details. */
package java.util.zip;
/**
* @author Tom Tromey
* @date May 17, 1999
*/
/* Written using on-line Java Platform 1.2 API Specification.
* Believed complete and correct.
*/
public class DataFormatException extends java.io.IOException
{
public DataFormatException ()
{
super();
}
public DataFormatException (String msg)
{
super(msg);
}
}

View File

@ -1,3 +1,5 @@
// Deflater.java - Compress a data stream.
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
@ -8,6 +10,123 @@ details. */
package java.util.zip;
import gnu.gcj.RawData;
/**
* @author Tom Tromey
* @date May 17, 1999
*/
/* Written using on-line Java Platform 1.2 API Specification
* and JCL book.
* Believed complete and correct.
*/
public class Deflater
{
public static final int BEST_COMPRESSION = 9;
public static final int BEST_SPEED = 1;
public static final int DEFAULT_COMPRESSION = -1;
public static final int NO_COMPRESSION = 0;
public static final int DEFAULT_STRATEGY = 0;
public static final int FILTERED = 1;
public static final int HUFFMAN_ONLY = 2;
public static final int DEFLATED = 8;
public int deflate (byte[] buf)
{
return deflate (buf, 0, buf.length);
}
public native int deflate (byte[] buf, int off, int len);
public native void init (int level, boolean noHeader);
public native void update ();
public Deflater ()
{
this (DEFAULT_COMPRESSION, false);
}
public Deflater (int lvl)
{
this (lvl, false);
}
public Deflater (int lvl, boolean noHeader)
{
this.strategy = DEFAULT_STRATEGY;
init (lvl, noHeader);
setLevel (lvl);
}
public native void end ();
public void finalize ()
{
end ();
}
public native void finish ();
public synchronized boolean finished ()
{
return is_finished;
}
public native int getAdler ();
public native int getTotalIn ();
public native int getTotalOut ();
public native boolean needsInput ();
public native void reset ();
public void setDictionary (byte[] buf)
{
setDictionary (buf, 0, buf.length);
}
public native void setDictionary (byte[] buf, int off, int len);
public void setInput (byte[] buf)
{
setInput (buf, 0, buf.length);
}
public native void setInput (byte[] buf, int off, int len);
public synchronized void setLevel (int lvl)
{
if (lvl != -1 && (lvl < 0 || lvl > 9))
throw new IllegalArgumentException ();
level = (lvl == -1) ? 6 : lvl;
update ();
}
public synchronized void setStrategy (int stgy)
{
if (stgy != DEFAULT_STRATEGY && stgy != FILTERED
&& stgy != HUFFMAN_ONLY)
throw new IllegalArgumentException ();
strategy = stgy;
update ();
}
// Compression level.
private int level;
// Compression strategy.
private int strategy;
// The zlib stream.
private RawData zstream;
// True if finished.
private boolean is_finished;
// Total number of bytes made available at last setInput.
private int last_input_count;
// `Flush' flag to pass to next call to deflate.
private int flush_flag;
}

View File

@ -1,3 +1,5 @@
// DeflaterOutputStream.java - Output filter for compressing.
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
@ -7,40 +9,79 @@ Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.util.zip;
import java.io.*;
/** JUST AN INCOMPLETE STUB! */
import java.io.FilterOutputStream;
import java.io.OutputStream;
import java.io.IOException;
/**
* @author Tom Tromey
* @date May 17, 1999
*/
/* Written using on-line Java Platform 1.2 API Specification
* and JCL book.
* Believed complete and correct.
*/
public class DeflaterOutputStream extends FilterOutputStream
{
protected byte[] buf;
protected Deflater def;
public DeflaterOutputStream(OutputStream out)
public void close () throws IOException
{
this(out, null, 512);
finish ();
out.close();
}
public DeflaterOutputStream(OutputStream out, Deflater defl)
protected void deflate () throws IOException
{
this(out, defl, 512);
while (true)
{
int len = def.deflate(buf, 0, buf.length);
if (len == 0 || len == -1)
break;
out.write(buf, 0, len);
}
}
public DeflaterOutputStream (OutputStream out)
{
this (out, new Deflater (), 512);
}
public DeflaterOutputStream (OutputStream out, Deflater defl)
{
this (out, defl, 512);
}
public DeflaterOutputStream(OutputStream out, Deflater defl, int bufsize)
{
super(out);
super (out);
buf = new byte[bufsize];
def = defl;
}
public void finish () throws IOException
{
def.finish();
deflate ();
}
public void close () throws IOException
public void write (int bval) throws IOException
{
finish();
out.close();
byte[] b = new byte[1];
b[0] = (byte) bval;
write (b, 0, 1);
}
public void write (byte[] buf, int off, int len) throws IOException
{
def.setInput (buf, off, len);
deflate ();
}
// The retrieval buffer.
protected byte[] buf;
// Deflater used to compress data.
protected Deflater def;
}

View File

@ -0,0 +1,154 @@
// GZIPInputStream.java - Input tiler for reading gzip file.
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.util.zip;
import java.io.InputStream;
import java.io.IOException;
/**
* @author Tom Tromey
* @date May 17, 1999
*/
/* Written using on-line Java Platform 1.2 API Specification
* and JCL book.
* Believed complete and correct.
*/
public class GZIPInputStream extends InflaterInputStream
{
public static final int GZIP_MAGIC = 0x8b1f;
public void close () throws IOException
{
// Nothing to do here.
super.close();
}
public GZIPInputStream (InputStream istream) throws IOException
{
this (istream, 512);
}
private final int eof_read () throws IOException
{
int r = in.read();
if (r == -1)
throw new ZipException ("gzip header corrupted");
return r & 0xff;
}
public GZIPInputStream (InputStream istream, int readsize)
throws IOException
{
super (istream, new Inflater (true), readsize);
// NOTE: header reading code taken from zlib's gzio.c.
// Read the magic number.
int magic = eof_read () | (eof_read () << 8);
if (magic != GZIP_MAGIC)
throw new ZipException ("gzip header corrupted");
int method = eof_read ();
int flags = eof_read ();
// Test from zlib.
if (method != Z_DEFLATED || (flags & RESERVED) != 0)
throw new ZipException ("gzip header corrupted");
// Discard time, xflags, OS code.
for (int i = 0; i < 6; ++i)
eof_read ();
// Skip the extra field.
if ((flags & EXTRA_FIELD) != 0)
{
int len = eof_read () | (eof_read () << 8);
while (len-- != 0)
eof_read ();
}
if ((flags & ORIG_NAME) != 0)
{
while (true)
{
int c = eof_read ();
if (c == 0)
break;
}
}
if ((flags & COMMENT) != 0)
{
while (true)
{
int c = eof_read ();
if (c == 0)
break;
}
}
if ((flags & HEAD_CRC) != 0)
{
// FIXME: consider checking CRC of the header.
eof_read ();
eof_read ();
}
crc = new CRC32 ();
}
public int read (byte[] buf, int off, int len) throws IOException
{
if (eos)
return -1;
int r = super.read(buf, off, len);
if (r == -1)
{
eos = true;
int header_crc = read4 ();
if (crc.getValue() != header_crc)
throw new ZipException ("corrupted gzip file");
// Read final `ISIZE' field.
// FIXME: should we check this length?
read4 ();
return -1;
}
crc.update(buf, off, r);
return r;
}
private final int read4 () throws IOException
{
int byte0 = in.read();
int byte1 = in.read();
int byte2 = in.read();
int byte3 = in.read();
if (byte3 < 0)
throw new ZipException (".zip archive ended prematurely");
return ((byte3 & 0xFF) << 24) + ((byte2 & 0xFF) << 16)
+ ((byte1 & 0xFF) << 8) + (byte0 & 0xFF);
}
// Checksum used by this input stream.
protected CRC32 crc;
// Indicates whether end-of-stream has been reached.
protected boolean eos;
// Some constants from zlib.
static final int Z_DEFLATED = 8;
static final int HEAD_CRC = 0x02;
static final int EXTRA_FIELD = 0x04;
static final int ORIG_NAME = 0x08;
static final int COMMENT = 0x10;
static final int RESERVED = 0xe0;
}

View File

@ -0,0 +1,88 @@
// GZIPOutputStream.java - Create a file in gzip format.
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.util.zip;
import java.io.IOException;
import java.io.OutputStream;
/**
* @author Tom Tromey
* @date May 17, 1999
*/
/* Written using on-line Java Platform 1.2 API Specification
* and JCL book.
* Believed complete and correct.
*/
public class GZIPOutputStream extends DeflaterOutputStream
{
public void close () throws IOException
{
finish ();
out.close ();
}
public void finish () throws IOException
{
super.finish();
put4 ((int) crc.getValue());
put4 (def.getTotalIn());
}
public GZIPOutputStream (OutputStream out) throws IOException
{
this (out, 512);
}
public GZIPOutputStream (OutputStream out, int readsize) throws IOException
{
super (out, new Deflater (Deflater.DEFAULT_COMPRESSION, true), readsize);
put2 (GZIPInputStream.GZIP_MAGIC);
out.write (GZIPInputStream.Z_DEFLATED);
// No flags for now.
out.write (0);
// No time either.
put2 (0);
put2 (0);
// No xflags either.
out.write (0);
// FIXME: unknown OS.
out.write (255);
crc = new CRC32 ();
}
public synchronized void write (byte[] buf, int off, int len)
throws IOException
{
super.write(buf, off, len);
crc.update(buf, off, len);
}
private final void put2 (int i) throws IOException
{
out.write (i);
out.write (i >> 8);
}
private final void put4 (int i) throws IOException
{
out.write (i);
out.write (i >> 8);
out.write (i >> 16);
out.write (i >> 24);
}
// Checksum used by this stream.
protected CRC32 crc;
}

View File

@ -0,0 +1,101 @@
// Inflater.java - Decompress a data stream.
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.util.zip;
import gnu.gcj.RawData;
/**
* @author Tom Tromey
* @date May 17, 1999
*/
/* Written using on-line Java Platform 1.2 API Specification
* and JCL book.
* Believed complete and correct.
*/
public class Inflater
{
public native void end ();
protected void finalize ()
{
end ();
}
public synchronized boolean finished ()
{
return is_finished;
}
public native int getAdler ();
public native int getRemaining ();
public native int getTotalIn ();
public native int getTotalOut ();
public int inflate (byte[] buf) throws DataFormatException
{
return inflate (buf, 0, buf.length);
}
public native int inflate (byte[] buf, int off, int len)
throws DataFormatException;
private native void init (boolean noHeader);
public Inflater ()
{
this (false);
}
public Inflater (boolean noHeader)
{
init (noHeader);
}
public synchronized boolean needsDictionary ()
{
return dict_needed;
}
public synchronized boolean needsInput ()
{
return getRemaining () == 0;
}
public native void reset ();
public void setDictionary (byte[] buf)
{
setDictionary (buf, 0, buf.length);
}
public native void setDictionary (byte[] buf, int off, int len);
public void setInput (byte[] buf)
{
setInput (buf, 0, buf.length);
}
public native void setInput (byte[] buf, int off, int len);
// The zlib stream.
private RawData zstream;
// True if finished.
private boolean is_finished;
// True if dictionary needed.
private boolean dict_needed;
// Total number of bytes made available at last setInput.
private int last_input_count;
}

View File

@ -1,3 +1,5 @@
// InflaterInputStream.java - Input stream filter for decompressing.
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
@ -7,14 +9,94 @@ Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.util.zip;
import java.io.*;
/** Placefolder - very incomplete. */
import java.io.FilterInputStream;
import java.io.InputStream;
import java.io.IOException;
/**
* @author Tom Tromey
* @date May 17, 1999
*/
/* Written using on-line Java Platform 1.2 API Specification
* and JCL book.
* Believed complete and correct.
*/
public class InflaterInputStream extends FilterInputStream
{
public InflaterInputStream(InputStream in)
protected void fill () throws IOException
{
super(in);
len = in.read(buf, 0, buf.length);
if (len != -1)
inf.setInput(buf, 0, len);
}
public InflaterInputStream (InputStream in)
{
this (in, new Inflater (), 512);
}
public InflaterInputStream (InputStream in, Inflater infl)
{
this (in, infl, 512);
}
public InflaterInputStream (InputStream in, Inflater infl, int bufsize)
{
super (in);
this.inf = infl;
this.buf = new byte[bufsize];
}
public int read () throws IOException
{
byte[] buf = new byte[1];
int r = read (buf, 0, 1);
if (r != -1)
r = buf[0] & 0xff;
return r;
}
public int read (byte[] buf, int off, int len) throws IOException
{
if (inf.finished())
return -1;
if (inf.needsInput())
fill ();
if (inf.needsDictionary())
return -1;
return inf.inflate(buf, off, len);
}
public long skip (long n) throws IOException
{
if (n == 0)
return 0;
int min = (int) Math.min(n, 1024);
byte[] buf = new byte[min];
long s = 0;
while (n > 0)
{
int r = read (buf, 0, min);
if (r == -1)
break;
n -= r;
s += r;
}
return s;
}
// Buffer for delivering uncompressed data to inflater.
protected byte[] buf;
// Inflater used to decompress data.
protected Inflater inf;
// Number of read bytes in buf.
protected int len;
}

View File

@ -39,6 +39,10 @@ public class ZipEntry
public ZipEntry (String name)
{
if (name == null)
throw new NullPointerException ();
if (name.length() > 65535)
throw new IllegalArgumentException ();
this.name = name;
}
@ -69,17 +73,45 @@ public class ZipEntry
return false;
}
public void setComment (String comment) { this.comment = comment; }
public void setComment (String comment)
{
if (comment != null && comment.length() > 65535)
throw new IllegalArgumentException ();
this.comment = comment;
}
public void setCrc (long crc) { this.crc = crc; }
public void setCrc (long crc)
{
if (crc < 0 || crc > 0xffffffff)
throw new IllegalArgumentException ();
this.crc = crc;
}
public void setExtra (byte[] extra) { this.extra = extra; }
public void setExtra (byte[] extra)
{
if (extra != null && extra.length > 65535)
throw new IllegalArgumentException ();
this.extra = extra;
}
public void setMethod(int method) { this.method = method; }
public void setMethod (int method)
{
if (method != DEFLATED && method != STORED)
throw new IllegalArgumentException ();
this.method = method;
}
public void setSize (long size) { this.size = size; }
public void setSize (long size)
{
if (size < 0 || size > 0xffffffff)
throw new IllegalArgumentException ();
this.size = size;
}
public void setTime (long time) { this.time = time; }
public void setTime (long time)
{
this.time = time;
}
private final static short[] daysToMonthStart = {
//Jan Feb Mar Apr May Jun Jul

View File

@ -1,3 +1,5 @@
// ZipFile.java - Read contents of a ZIP file.
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
@ -9,16 +11,13 @@ details. */
package java.util.zip;
import java.io.*;
/** UNFINISHED, but can read non-comrepssed .zip archives. */
/* Written using on-line Java Platform 1.2 API Specification
* and JCL book.
* Believed complete and correct.
*/
public class ZipFile implements ZipConstants
{
ZipEntry entries;
int numEntries;
RandomAccessFile file;
String name;
public ZipFile (String fname) throws IOException
{
file = new RandomAccessFile(fname, "r");
@ -35,7 +34,7 @@ public class ZipFile implements ZipConstants
{
long size = file.length ();
if (size < ZipConstants.END_CENTRAL_DIR_SIZE)
throw new IOException ("zipfile too short");
throw new ZipException ("zipfile too short");
// We do not handle a "zipfile comment", which the appnote says can
// be at the end of a .zip file. We could handle this by seeking
// to the beginning and reading forwards.
@ -44,7 +43,7 @@ public class ZipFile implements ZipConstants
|| file.read() != 'K'
|| file.read() != '\005'
|| file.read() != '\006')
throw new IOException("not a valid zipfile");
throw new ZipException("not a valid zipfile");
file.skipBytes(6);
numEntries = readu2();
int dir_size = read4 (); // Read "size of the central directory".
@ -103,7 +102,6 @@ public class ZipFile implements ZipConstants
public void close() throws IOException
{
// FIXME - check this
file.close();
entries = null;
numEntries = 0;
@ -121,14 +119,17 @@ public class ZipFile implements ZipConstants
public InputStream getInputStream(ZipEntry ze) throws IOException
{
// FIXME - does not handle compression!
byte[] buffer = new byte[(int) ze.getSize()];
int data_offset = ZipConstants.LOCAL_FILE_HEADER_SIZE + name.length();
if (ze.extra != null)
data_offset += ze.extra.length;
file.seek(ze.relativeOffset + data_offset);
file.readFully(buffer);
return new ByteArrayInputStream(buffer);
InputStream is = new ByteArrayInputStream (buffer);
if (ze.getMethod() == ZipEntry.DEFLATED)
is = new InflaterInputStream (is);
return is;
}
public String getName () { return name; }
@ -138,7 +139,7 @@ public class ZipFile implements ZipConstants
int byte0 = file.read();
int byte1 = file.read();
if (byte0 < 0 || byte1 < 0)
throw new EOFException(".zip archive ended prematurely");
throw new ZipException (".zip archive ended prematurely");
return ((byte1 & 0xFF) << 8) | (byte0 & 0xFF);
}
@ -149,10 +150,15 @@ public class ZipFile implements ZipConstants
int byte2 = file.read();
int byte3 = file.read();
if (byte3 < 0)
throw new EOFException(".zip archive ended prematurely");
throw new ZipException (".zip archive ended prematurely");
return ((byte3 & 0xFF) << 24) + ((byte2 & 0xFF) << 16)
+ ((byte1 & 0xFF) << 8) + (byte0 & 0xFF);
}
ZipEntry entries;
int numEntries;
RandomAccessFile file;
String name;
}
class ZipEnumeration implements java.util.Enumeration

View File

@ -168,14 +168,14 @@ public class ZipInputStream extends InflaterInputStream
{
int sig = read4();
if (sig != 0x04034b50)
throw new IOException("bad/missing magic number at end of .zip entry");
throw new ZipException("bad/missing magic number at end of .zip entry");
int crc = read4();
int compressedSize = read4();
int uncompressedSize = read4();
if (current.compressedSize != compressedSize
|| current.size != uncompressedSize
|| current.crc != crc)
throw new IOException("bad data descriptor at end of .zip entry");
throw new ZipException("bad data descriptor at end of .zip entry");
}
current = null;
avail = 0;

View File

@ -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);
}
public void setLevel (int level) { this.level = level; }
public void setMethod (int method) { this.method = method; }
public void setComment(String comment) { this.comment = comment; }
public void putNextEntry (ZipEntry entry) throws IOException
{
put4(0x04034b50);
put2(0); // version - FIXME
put2(0); // bits - FIXME
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");
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;
}
private void put2 (int i) throws IOException
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);
}
// 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
{
if (current != null)
closeEntry ();
if (entry.method < 0 )
entry.method = method;
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 setLevel (int level)
{
if (level != Deflater.DEFAULT_COMPRESSION
&& (level < Deflater.NO_COMPRESSION
|| level > Deflater.BEST_COMPRESSION))
throw new IllegalArgumentException ();
this.level = level;
}
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;
}

View File

@ -0,0 +1,209 @@
// natDeflater.cc - Implementation of Deflater native methods.
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
// Written by Tom Tromey <tromey@cygnus.com>
#include <config.h>
#include <zlib.h>
#include <cni.h>
#include <jvm.h>
#include <java/util/zip/Deflater.h>
#include <java/util/zip/DataFormatException.h>
#include <java/lang/InternalError.h>
#include <java/lang/NullPointerException.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h>
extern void *_Jv_ZMalloc (void *, uInt nitems, uInt size);
extern void _Jv_ZFree (void *, void *addr);
jint
java::util::zip::Deflater::deflate (jbyteArray buf, jint off, jint len)
{
JvSynchronize sync (this);
z_streamp s = (z_streamp) zstream;
if (! buf)
_Jv_Throw (new java::lang::NullPointerException);
if (off < 0 || len < 0 || off + len > buf->length)
_Jv_Throw (new java::lang::ArrayIndexOutOfBoundsException);
s->next_out = (Bytef *) (elements (buf) + off);
s->avail_out = len;
switch (::deflate (s, flush_flag))
{
case Z_STREAM_END:
is_finished = true;
if (s->avail_out == len)
return -1;
break;
case Z_STREAM_ERROR:
case Z_BUF_ERROR:
// FIXME?
_Jv_Throw (new java::lang::InternalError);
break;
case Z_OK:
break;
}
return len - s->avail_out;
}
void
java::util::zip::Deflater::end ()
{
JvSynchronize sync (this);
// Just ignore errors.
deflateEnd ((z_streamp) zstream);
_Jv_Free (zstream);
zstream = NULL;
}
void
java::util::zip::Deflater::finish ()
{
JvSynchronize sync (this);
flush_flag = Z_FINISH;
}
jint
java::util::zip::Deflater::getAdler ()
{
JvSynchronize sync (this);
z_streamp s = (z_streamp) zstream;
return s->adler;
}
jint
java::util::zip::Deflater::getTotalIn ()
{
JvSynchronize sync (this);
z_streamp s = (z_streamp) zstream;
return s->total_in;
}
jint
java::util::zip::Deflater::getTotalOut ()
{
JvSynchronize sync (this);
z_streamp s = (z_streamp) zstream;
return s->total_out;
}
jboolean
java::util::zip::Deflater::needsInput ()
{
JvSynchronize sync (this);
z_streamp s = (z_streamp) zstream;
return s->avail_in - last_input_count == 0;
}
void
java::util::zip::Deflater::reset ()
{
JvSynchronize sync (this);
z_streamp s = (z_streamp) zstream;
// Just ignore errors.
deflateReset (s);
flush_flag = 0;
}
void
java::util::zip::Deflater::setDictionary (jbyteArray buf, jint off, jint len)
{
JvSynchronize sync (this);
z_streamp s = (z_streamp) zstream;
if (! buf)
_Jv_Throw (new java::lang::NullPointerException);
if (off < 0 || len < 0 || off + len > buf->length)
_Jv_Throw (new java::lang::ArrayIndexOutOfBoundsException);
// Ignore errors.
deflateSetDictionary (s, (Bytef *) (elements (buf) + off), len);
}
void
java::util::zip::Deflater::setInput (jbyteArray buf, jint off, jint len)
{
JvSynchronize sync (this);
z_streamp s = (z_streamp) zstream;
if (! buf)
_Jv_Throw (new java::lang::NullPointerException);
if (off < 0 || len < 0 || off + len > buf->length)
_Jv_Throw (new java::lang::ArrayIndexOutOfBoundsException);
last_input_count = len;
s->next_in = (Bytef *) (elements (buf) + off);
s->avail_in = len;
}
void
java::util::zip::Deflater::update ()
{
JvSynchronize sync (this);
z_streamp s = (z_streamp) zstream;
int strat;
switch (strategy)
{
case DEFAULT_STRATEGY:
strat = Z_DEFAULT_STRATEGY;
break;
case FILTERED:
strat = Z_FILTERED;
break;
case HUFFMAN_ONLY:
strat = Z_HUFFMAN_ONLY;
break;
}
// Ignore errors.
deflateParams (s, level, strat);
}
void
java::util::zip::Deflater::init (jint level, jboolean no_header)
{
z_stream_s *stream = (z_stream_s *) _Jv_Malloc (sizeof (z_stream_s));
stream->next_in = Z_NULL;
stream->avail_in = 0;
stream->zalloc = _Jv_ZMalloc;
stream->zfree = _Jv_ZFree;
stream->opaque = NULL;
// Handle NO_HEADER using undocumented zlib feature.
int wbits = MAX_WBITS;
if (no_header)
wbits = - wbits;
#define DEFAULT_MEM_LEVEL 8
if (deflateInit2 (stream, level, Z_DEFLATED, wbits,
DEFAULT_MEM_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK)
{
jstring msg = NULL;
if (stream->msg != NULL)
msg = JvNewStringLatin1 (stream->msg);
_Jv_Throw (new java::lang::InternalError (msg));
}
zstream = reinterpret_cast<gnu::gcj::RawData *> (stream);
is_finished = false;
flush_flag = 0;
}

View File

@ -0,0 +1,202 @@
// natInflater.cc - Implementation of Inflater native methods.
/* Copyright (C) 1999 Cygnus Solutions
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
// Written by Tom Tromey <tromey@cygnus.com>
#include <config.h>
#include <zlib.h>
#include <cni.h>
#include <jvm.h>
#include <java/util/zip/Inflater.h>
#include <java/util/zip/DataFormatException.h>
#include <java/lang/InternalError.h>
#include <java/lang/NullPointerException.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h>
#include <java/lang/OutOfMemoryError.h>
// A couple of helper functions used to interface with zlib's
// allocation.
void *
_Jv_ZMalloc (void *, uInt nitems, uInt size)
{
return _Jv_Malloc (nitems * size);
}
void
_Jv_ZFree (void *, void *addr)
{
_Jv_Free (addr);
}
void
java::util::zip::Inflater::end ()
{
JvSynchronize sync (this);
// Just ignore errors.
inflateEnd ((z_streamp) zstream);
_Jv_Free (zstream);
zstream = NULL;
}
jint
java::util::zip::Inflater::getAdler ()
{
JvSynchronize sync (this);
z_streamp s = (z_streamp) zstream;
return s->adler;
}
jint
java::util::zip::Inflater::getRemaining ()
{
JvSynchronize sync (this);
z_streamp s = (z_streamp) zstream;
return s->avail_in - last_input_count;
}
jint
java::util::zip::Inflater::getTotalIn ()
{
JvSynchronize sync (this);
z_streamp s = (z_streamp) zstream;
return s->total_in;
}
jint
java::util::zip::Inflater::getTotalOut ()
{
JvSynchronize sync (this);
z_streamp s = (z_streamp) zstream;
return s->total_out;
}
jint
java::util::zip::Inflater::inflate (jbyteArray buf, jint off, jint len)
{
JvSynchronize sync (this);
z_streamp s = (z_streamp) zstream;
if (! buf)
_Jv_Throw (new java::lang::NullPointerException);
if (off < 0 || len < 0 || off + len > buf->length)
_Jv_Throw (new java::lang::ArrayIndexOutOfBoundsException);
s->next_out = (Bytef *) (elements (buf) + off);
s->avail_out = len;
switch (::inflate (s, Z_SYNC_FLUSH))
{
case Z_STREAM_END:
is_finished = true;
if (s->avail_out == len)
return -1;
break;
case Z_NEED_DICT:
dict_needed = true;
break;
case Z_DATA_ERROR:
_Jv_Throw (new java::util::zip::DataFormatException);
break;
case Z_MEM_ERROR:
_Jv_Throw (new java::lang::OutOfMemoryError);
break;
case Z_BUF_ERROR:
// FIXME?
_Jv_Throw (new java::lang::InternalError);
break;
case Z_OK:
break;
}
return len - s->avail_out;
}
void
java::util::zip::Inflater::reset ()
{
JvSynchronize sync (this);
z_streamp s = (z_streamp) zstream;
// Just ignore errors.
inflateReset (s);
}
void
java::util::zip::Inflater::setDictionary (jbyteArray buf, jint off, jint len)
{
JvSynchronize sync (this);
z_streamp s = (z_streamp) zstream;
if (! buf)
_Jv_Throw (new java::lang::NullPointerException);
if (off < 0 || len < 0 || off + len > buf->length)
_Jv_Throw (new java::lang::ArrayIndexOutOfBoundsException);
// Ignore errors.
inflateSetDictionary (s, (Bytef *) (elements (buf) + off), len);
dict_needed = false;
}
void
java::util::zip::Inflater::setInput (jbyteArray buf, jint off, jint len)
{
JvSynchronize sync (this);
z_streamp s = (z_streamp) zstream;
if (! buf)
_Jv_Throw (new java::lang::NullPointerException);
if (off < 0 || len < 0 || off + len > buf->length)
_Jv_Throw (new java::lang::ArrayIndexOutOfBoundsException);
last_input_count = len;
s->next_in = (Bytef *) (elements (buf) + off);
s->avail_in = len;
}
void
java::util::zip::Inflater::init (jboolean no_header)
{
z_stream_s *stream = (z_stream_s *) _Jv_Malloc (sizeof (z_stream_s));
stream->next_in = Z_NULL;
stream->avail_in = 0;
stream->zalloc = _Jv_ZMalloc;
stream->zfree = _Jv_ZFree;
stream->opaque = NULL;
// Handle NO_HEADER using undocumented zlib feature.
int wbits = MAX_WBITS;
if (no_header)
wbits = - wbits;
if (inflateInit2 (stream, wbits) != Z_OK)
{
jstring msg = NULL;
if (stream->msg != NULL)
msg = JvNewStringLatin1 (stream->msg);
_Jv_Throw (new java::lang::InternalError (msg));
}
zstream = reinterpret_cast<gnu::gcj::RawData *> (stream);
is_finished = false;
dict_needed = false;
}