/******************************************************************************* * Copyright (c) 2009 Zhao and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Zhao - initial API and implementation *******************************************************************************/ package org.eclipse.php.internal.core.tar; import java.io.IOException; import java.io.InputStream; import java.util.zip.CRC32; import java.util.zip.Inflater; import java.util.zip.InflaterInputStream; import org.eclipse.php.internal.core.phar.PharEntryBufferedRandomInputStream; /** * This class implements a stream filter for reading compressed data in the GZIP * file format. * * @see InflaterInputStream * @version 1.33, 04/07/06 * @author David Connelly * */ public class GZIPInputStreamForPhar extends InflaterInputStream { /** * CRC-32 for uncompressed data. */ protected CRC32 crc = new CRC32(); /** * Indicates end of input stream. */ protected boolean eos; private boolean closed = false; /** * Check to make sure that this stream has not been closed */ private void ensureOpen() throws IOException { if (closed) { throw new IOException("Stream closed"); //$NON-NLS-1$ } } /** * Creates a new input stream with the specified buffer size. * * @param in * the input stream * @param size * the input buffer size * @exception IOException * if an I/O error has occurred * @exception IllegalArgumentException * if size is <= 0 */ public GZIPInputStreamForPhar(InputStream in, int size) throws IOException { super(in, new Inflater(true), size); // usesDefaultInflater = true; // readHeader(); crc.reset(); } /** * Creates a new input stream with a default buffer size. * * @param in * the input stream * @exception IOException * if an I/O error has occurred */ public GZIPInputStreamForPhar(InputStream in) throws IOException { this(in, 512); } /** * Reads uncompressed data into an array of bytes. If <code>len</code> is * not zero, the method will block until some input can be decompressed; * otherwise, no bytes are read and <code>0</code> is returned. * * @param buf * the buffer into which the data is read * @param off * the start offset in the destination array <code>b</code> * @param len * the maximum number of bytes read * @return the actual number of bytes read, or -1 if the end of the * compressed input stream is reached * @exception NullPointerException * If <code>buf</code> is <code>null</code>. * @exception IndexOutOfBoundsException * If <code>off</code> is negative, <code>len</code> is * negative, or <code>len</code> is greater than * <code>buf.length - off</code> * @exception IOException * if an I/O error has occurred or the compressed input data * is corrupt */ public int read(byte[] buf, int off, int len) throws IOException { ensureOpen(); if (eos) { return -1; } // if reach the end and still read here will throw an exception // nomally this will not happen,but it happens when run unit tests // so add an isEnd method to class PharEntryBufferedRandomInputStream if (in instanceof PharEntryBufferedRandomInputStream && ((PharEntryBufferedRandomInputStream) in).isEnd()) { len = -1; } else { len = super.read(buf, off, len); } if (len == -1) { // readTrailer(); eos = true; } else { crc.update(buf, off, len); } return len; } /** * Closes this input stream and releases any system resources associated * with the stream. * * @exception IOException * if an I/O error has occurred */ public void close() throws IOException { if (!closed) { inf.end(); super.close(); eos = true; closed = true; } } }