/********************************************************************************* * TotalCross Software Development Kit * * Copyright (C) 2000-2012 SuperWaba Ltda. * * All Rights Reserved * * * * This library and virtual machine 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. * * * * This file is covered by the GNU LESSER GENERAL PUBLIC LICENSE VERSION 3.0 * * A copy of this license is located in file license.txt at the root of this * * SDK or can be downloaded here: * * http://www.gnu.org/licenses/lgpl-3.0.txt * * * *********************************************************************************/ package totalcross.util.zip; import totalcross.Launcher; import totalcross.io.IOException; import totalcross.io.RandomAccessStream; import totalcross.io.Stream; /** * This class implements a stream filter for reading and writing files in the ZIP file format. Currently supports only * compressed entries.<br> * <br> * See the sammple TotalCross3/src/tc/samples/util/zip/zip. * * @since TotalCross 1.20 */ public class ZipStream extends CompressedStream { int defaultMethod = DEFLATED; /** Compression method for uncompressed (STORED) entries. */ public final static int STORED = 0; /** Compression method for compressed (DEFLATED) entries. */ public final static int DEFLATED = 8; /** * Creates a new ZIP stream that may be used to read compressed data from the given stream, or to write compressed * data to the given stream.<br> * * @param stream * input stream. * @param mode * its value must be either DEFLATE or INFLATE. * * @since TotalCross 1.20 */ public ZipStream(RandomAccessStream stream, int mode) { super(stream, mode); } protected Object createDeflate(Stream stream) { Launcher.S2OS os = new Launcher.S2OS(stream, false); return new java.util.zip.ZipOutputStream(os); } protected Object createInflate(Stream stream) { Launcher.S2IS is = new Launcher.S2IS(stream, -1, false); return new java.util.zip.ZipInputStream(is); } /** * Returns 0 after EOF has reached for the current entry data, otherwise always return 1.<br> * Programs should not count on this method to return the actual number of bytes that could be read without blocking. * * @return 1 before EOF and 0 after EOF has reached for current entry. * @throws IOException * if an I/O error occurs. * * @since TotalCross 1.20 */ public int available() throws IOException { if (mode != INFLATE) throw new IOException("This operation can only be performed in INFLATE mode."); try { return ((java.io.InputStream) this.compressedStream).available(); } catch (java.io.IOException e) { throw new IOException(e.getMessage()); } } /** * Reads the next ZIP file entry and positions the stream at the beginning of the entry data. * * @return the next ZIP file entry, or null if there are no more entries * @throws IOException * if an I/O error has occurred * * @since TotalCross 1.20 */ public ZipEntry getNextEntry() throws IOException { if (mode != INFLATE) throw new IOException("This operation can only be performed in INFLATE mode."); java.util.zip.ZipInputStream zis = (java.util.zip.ZipInputStream) this.compressedStream; try { Object zipEntry = zis.getNextEntry(); if (zipEntry == null) return null; return new ZipEntry(zipEntry); } catch (java.io.EOFException e) { return null; } catch (java.io.IOException e) { throw new IOException(e.getMessage()); } } /** * Begins writing a new ZIP file entry and positions the stream to the start of the entry data. Closes the current * entry if still active. * * @param entry * the ZIP entry to be written * @throws IOException * if an I/O error has occurred * * @since TotalCross 1.20 */ public void putNextEntry(ZipEntry entry) throws IOException, ZipException { if (mode != DEFLATE) throw new IOException("This operation can only be performed in DEFLATE mode."); java.util.zip.ZipOutputStream zos = (java.util.zip.ZipOutputStream) this.compressedStream; try { zos.putNextEntry((java.util.zip.ZipEntry) entry.zipEntry); } catch (java.io.IOException e) { throw new IOException(e.getMessage()); } } /** * Closes the current ZIP entry and positions the stream for reading (INFLATE) or writing (DEFLATE) the next entry. * * @throws IOException * if an I/O error has occurred * * @since TotalCross 1.20 */ public void closeEntry() throws IOException, ZipException { try { if (mode == DEFLATE) { java.util.zip.ZipOutputStream zos = (java.util.zip.ZipOutputStream) this.compressedStream; zos.closeEntry(); } else { java.util.zip.ZipInputStream zis = (java.util.zip.ZipInputStream) this.compressedStream; zis.closeEntry(); } } catch (java.io.IOException e) { throw new IOException(e.getMessage()); } } public void close() throws IOException { try { switch (mode) { case DEFLATE: ((java.util.zip.ZipOutputStream) compressedStream).finish(); break; case INFLATE: ((java.util.zip.ZipInputStream) compressedStream).close(); break; default: throw new IOException("Invalid object."); } } catch (java.io.IOException e) { throw new IOException(e.getMessage()); } finally { mode = 0; } } }