diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/classpath/java/util/zip/ZipOutputStream.java | |
download | cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2 cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'libjava/classpath/java/util/zip/ZipOutputStream.java')
-rw-r--r-- | libjava/classpath/java/util/zip/ZipOutputStream.java | 440 |
1 files changed, 440 insertions, 0 deletions
diff --git a/libjava/classpath/java/util/zip/ZipOutputStream.java b/libjava/classpath/java/util/zip/ZipOutputStream.java new file mode 100644 index 000000000..bc1c3e99c --- /dev/null +++ b/libjava/classpath/java/util/zip/ZipOutputStream.java @@ -0,0 +1,440 @@ +/* ZipOutputStream.java -- + Copyright (C) 2001, 2004, 2005, 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.util.zip; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.util.Enumeration; +import java.util.Vector; + +/** + * This is a FilterOutputStream that writes the files into a zip + * archive one after another. It has a special method to start a new + * zip entry. The zip entries contains information about the file name + * size, compressed size, CRC, etc. + * + * It includes support for STORED and DEFLATED entries. + * + * This class is not thread safe. + * + * @author Jochen Hoenicke + */ +public class ZipOutputStream extends DeflaterOutputStream implements ZipConstants +{ + private Vector entries = new Vector(); + private CRC32 crc = new CRC32(); + private ZipEntry curEntry = null; + + private int curMethod; + private int size; + private int offset = 0; + + private byte[] zipComment = new byte[0]; + private int defaultMethod = DEFLATED; + + /** + * Our Zip version is hard coded to 1.0 resp. 2.0 + */ + private static final int ZIP_STORED_VERSION = 10; + private static final int ZIP_DEFLATED_VERSION = 20; + + /** + * Compression method. This method doesn't compress at all. + */ + public static final int STORED = 0; + + /** + * Compression method. This method uses the Deflater. + */ + public static final int DEFLATED = 8; + + /** + * Creates a new Zip output stream, writing a zip archive. + * @param out the output stream to which the zip archive is written. + */ + public ZipOutputStream(OutputStream out) + { + super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true)); + } + + /** + * Set the zip file comment. + * @param comment the comment. + * @exception IllegalArgumentException if encoding of comment is + * longer than 0xffff bytes. + */ + public void setComment(String comment) + { + byte[] commentBytes; + try + { + commentBytes = comment.getBytes("UTF-8"); + } + catch (UnsupportedEncodingException uee) + { + throw new AssertionError(uee); + } + if (commentBytes.length > 0xffff) + throw new IllegalArgumentException("Comment too long."); + zipComment = commentBytes; + } + + /** + * Sets default compression method. If the Zip entry specifies + * another method its method takes precedence. + * @param method the method. + * @exception IllegalArgumentException if method is not supported. + * @see #STORED + * @see #DEFLATED + */ + public void setMethod(int method) + { + if (method != STORED && method != DEFLATED) + throw new IllegalArgumentException("Method not supported."); + defaultMethod = method; + } + + /** + * Sets default compression level. The new level will be activated + * immediately. + * @exception IllegalArgumentException if level is not supported. + * @see Deflater + */ + public void setLevel(int level) + { + def.setLevel(level); + } + + /** + * Write an unsigned short in little endian byte order. + */ + private void writeLeShort(int value) throws IOException + { + out.write(value & 0xff); + out.write((value >> 8) & 0xff); + } + + /** + * Write an int in little endian byte order. + */ + private void writeLeInt(int value) throws IOException + { + writeLeShort(value); + writeLeShort(value >> 16); + } + + /** + * Write a long value as an int. Some of the zip constants + * are declared as longs even though they fit perfectly well + * into integers. + */ + private void writeLeInt(long value) throws IOException + { + writeLeInt((int) value); + } + + /** + * Starts a new Zip entry. It automatically closes the previous + * entry if present. If the compression method is stored, the entry + * must have a valid size and crc, otherwise all elements (except + * name) are optional, but must be correct if present. If the time + * is not set in the entry, the current time is used. + * @param entry the entry. + * @exception IOException if an I/O error occured. + * @exception ZipException if stream was finished. + */ + public void putNextEntry(ZipEntry entry) throws IOException + { + if (entries == null) + throw new ZipException("ZipOutputStream was finished"); + + int method = entry.getMethod(); + int flags = 0; + if (method == -1) + method = defaultMethod; + + if (method == STORED) + { + if (entry.getCompressedSize() >= 0) + { + if (entry.getSize() < 0) + entry.setSize(entry.getCompressedSize()); + else if (entry.getSize() != entry.getCompressedSize()) + throw new ZipException + ("Method STORED, but compressed size != size"); + } + else + entry.setCompressedSize(entry.getSize()); + + if (entry.getSize() < 0) + throw new ZipException("Method STORED, but size not set"); + if (entry.getCrc() < 0) + throw new ZipException("Method STORED, but crc not set"); + } + else if (method == DEFLATED) + { + if (entry.getCompressedSize() < 0 + || entry.getSize() < 0 || entry.getCrc() < 0) + flags |= 8; + } + + if (curEntry != null) + closeEntry(); + + if (entry.getTime() < 0) + entry.setTime(System.currentTimeMillis()); + + entry.flags = flags; + entry.offset = offset; + entry.setMethod(method); + curMethod = method; + /* Write the local file header */ + writeLeInt(LOCSIG); + writeLeShort(method == STORED + ? ZIP_STORED_VERSION : ZIP_DEFLATED_VERSION); + writeLeShort(flags); + writeLeShort(method); + writeLeInt(entry.getDOSTime()); + if ((flags & 8) == 0) + { + writeLeInt((int)entry.getCrc()); + writeLeInt((int)entry.getCompressedSize()); + writeLeInt((int)entry.getSize()); + } + else + { + writeLeInt(0); + writeLeInt(0); + writeLeInt(0); + } + byte[] name; + try + { + name = entry.getName().getBytes("UTF-8"); + } + catch (UnsupportedEncodingException uee) + { + throw new AssertionError(uee); + } + if (name.length > 0xffff) + throw new ZipException("Name too long."); + byte[] extra = entry.getExtra(); + if (extra == null) + extra = new byte[0]; + writeLeShort(name.length); + writeLeShort(extra.length); + out.write(name); + out.write(extra); + + offset += LOCHDR + name.length + extra.length; + + /* Activate the entry. */ + + curEntry = entry; + crc.reset(); + if (method == DEFLATED) + def.reset(); + size = 0; + } + + /** + * Closes the current entry. + * @exception IOException if an I/O error occured. + * @exception ZipException if no entry is active. + */ + public void closeEntry() throws IOException + { + if (curEntry == null) + throw new ZipException("No open entry"); + + /* First finish the deflater, if appropriate */ + if (curMethod == DEFLATED) + super.finish(); + + int csize = curMethod == DEFLATED ? def.getTotalOut() : size; + + if (curEntry.getSize() < 0) + curEntry.setSize(size); + else if (curEntry.getSize() != size) + throw new ZipException("size was "+size + +", but I expected "+curEntry.getSize()); + + if (curEntry.getCompressedSize() < 0) + curEntry.setCompressedSize(csize); + else if (curEntry.getCompressedSize() != csize) + throw new ZipException("compressed size was "+csize + +", but I expected "+curEntry.getSize()); + + if (curEntry.getCrc() < 0) + curEntry.setCrc(crc.getValue()); + else if (curEntry.getCrc() != crc.getValue()) + throw new ZipException("crc was " + Long.toHexString(crc.getValue()) + + ", but I expected " + + Long.toHexString(curEntry.getCrc())); + + offset += csize; + + /* Now write the data descriptor entry if needed. */ + if (curMethod == DEFLATED && (curEntry.flags & 8) != 0) + { + writeLeInt(EXTSIG); + writeLeInt((int)curEntry.getCrc()); + writeLeInt((int)curEntry.getCompressedSize()); + writeLeInt((int)curEntry.getSize()); + offset += EXTHDR; + } + + entries.addElement(curEntry); + curEntry = null; + } + + /** + * Writes the given buffer to the current entry. + * @exception IOException if an I/O error occured. + * @exception ZipException if no entry is active. + */ + public void write(byte[] b, int off, int len) throws IOException + { + if (curEntry == null) + throw new ZipException("No open entry."); + + switch (curMethod) + { + case DEFLATED: + super.write(b, off, len); + break; + + case STORED: + out.write(b, off, len); + break; + } + + crc.update(b, off, len); + size += len; + } + + /** + * Finishes the stream. This will write the central directory at the + * end of the zip file and flush the stream. + * @exception IOException if an I/O error occured. + */ + public void finish() throws IOException + { + if (entries == null) + return; + if (curEntry != null) + closeEntry(); + + int numEntries = 0; + int sizeEntries = 0; + + Enumeration e = entries.elements(); + while (e.hasMoreElements()) + { + ZipEntry entry = (ZipEntry) e.nextElement(); + + int method = entry.getMethod(); + writeLeInt(CENSIG); + writeLeShort(method == STORED + ? ZIP_STORED_VERSION : ZIP_DEFLATED_VERSION); + writeLeShort(method == STORED + ? ZIP_STORED_VERSION : ZIP_DEFLATED_VERSION); + writeLeShort(entry.flags); + writeLeShort(method); + writeLeInt(entry.getDOSTime()); + writeLeInt((int)entry.getCrc()); + writeLeInt((int)entry.getCompressedSize()); + writeLeInt((int)entry.getSize()); + + byte[] name; + try + { + name = entry.getName().getBytes("UTF-8"); + } + catch (UnsupportedEncodingException uee) + { + throw new AssertionError(uee); + } + if (name.length > 0xffff) + throw new ZipException("Name too long."); + byte[] extra = entry.getExtra(); + if (extra == null) + extra = new byte[0]; + String str = entry.getComment(); + byte[] comment; + try + { + comment = str != null ? str.getBytes("UTF-8") : new byte[0]; + } + catch (UnsupportedEncodingException uee) + { + throw new AssertionError(uee); + } + if (comment.length > 0xffff) + throw new ZipException("Comment too long."); + + writeLeShort(name.length); + writeLeShort(extra.length); + writeLeShort(comment.length); + writeLeShort(0); /* disk number */ + writeLeShort(0); /* internal file attr */ + writeLeInt(0); /* external file attr */ + writeLeInt(entry.offset); + + out.write(name); + out.write(extra); + out.write(comment); + numEntries++; + sizeEntries += CENHDR + name.length + extra.length + comment.length; + } + + writeLeInt(ENDSIG); + writeLeShort(0); /* disk number */ + writeLeShort(0); /* disk with start of central dir */ + writeLeShort(numEntries); + writeLeShort(numEntries); + writeLeInt(sizeEntries); + writeLeInt(offset); + writeLeShort(zipComment.length); + out.write(zipComment); + out.flush(); + entries = null; + } +} |