/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.virtual.plugins.context.zip;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import org.jboss.logging.Logger;
/**
* ZipWrapper represents abstracted access to zip archive
*
* @author <a href="strukelj@parsek.net">Marko Strukelj</a>
* @version $Revision: 1.0 $
*/
abstract class ZipWrapper
{
/** the log */
protected static final Logger log = Logger.getLogger(ZipWrapper.class);
/** last known modifyTime of the zip source */
protected long lastModified;
/** timestamp of last call to getLastModified()
* it's an expensive call - we don't do it more then once every second */
private long lastChecked;
/** last known activity */
private long lastUsed;
/** number of streams currently open on this wrapper */
private int refCount = 0;
/**
* Returns true if underlying source's lastModified time has changed since previous call.
*
* @return true if modified, false othwewise
*/
boolean hasBeenModified()
{
long now = System.currentTimeMillis();
if (now - lastChecked < 1000)
return false;
lastChecked = now;
long lm = getLastModified();
if (lm != lastModified)
{
lastModified = lm;
return true;
}
return false;
}
/**
* get lastUsed timestamp
*
* @return
*/
long getLastUsed()
{
return lastUsed;
}
/**
* Returns the number of streams currently open
*
* @return
*/
int getReferenceCount()
{
return refCount;
}
/**
* Increment usage count by one
*/
void incrementRef()
{
refCount++;
lastUsed = System.currentTimeMillis();
}
/**
* Decrement usage count by one
*/
synchronized void release()
{
refCount--;
if (refCount <= 0)
{
lastUsed = System.currentTimeMillis();
}
}
/**
* Acquire lock.
*
* @throws IOException for any error
*/
abstract void acquire() throws IOException;
/**
* Get lastModified of this archive
*
* @return lastModified timestamp
*/
abstract long getLastModified();
/**
* Get the name of this archive
*
* @return name
*/
abstract String getName();
/**
* Check if archive exists
*
* @return true if archive exists
*/
abstract boolean exists();
/**
* Get the size of the archive
*
* @return size in bytes
*/
abstract long getSize();
/**
* Enumerate contents of this archive
*
* @return enumeration of ZipEntries
* @throws IOException for any error
*/
abstract Enumeration<? extends ZipEntry> entries() throws IOException;
/**
* Get the contents of a given entry as stream
*
* @param ent zip entry
* @return InputStream with entry's contents
* @throws IOException for any error
*/
abstract InputStream openStream(ZipEntryInfo ent) throws IOException;
/**
* Get raw bytes of this archive in its compressed form
*
* @return InputStream containing raw archive
* @throws FileNotFoundException if archive doesn't exist
*/
abstract InputStream getRootAsStream() throws FileNotFoundException;
/**
* Close this archive
*/
abstract void close();
/**
* Delete this archive
*
* @param gracePeriod maximum time to wait for any locks
* @return true if file was deleted, false otherwise
* @throws IOException for any error
*/
abstract boolean delete(int gracePeriod) throws IOException;
/**
* Recompose an input stream as having <em>path</em> entry for its root.
* All entries' names have to be shifted accordingly.
*
* @param path root path
* @return InputStream containing a new ZIP archive
* @throws FileNotFoundException for any error that prevented recomposition
*/
protected InputStream recomposeZipAsInputStream(String path) throws FileNotFoundException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try
{
recomposeZip(baos, path);
return new ByteArrayInputStream(baos.toByteArray());
}
catch (IOException ex)
{
FileNotFoundException e = new FileNotFoundException("Failed to recompose inflated nested archive " + getName());
e.initCause(ex);
throw e;
}
}
/**
* Recompose an input streamas having <em>path</em> entry for its root, and write it to a given OutputStream.
* All entries' names have to be shifted accordingly.
*
* @param os OutputStream that will contain newly create archive
* @param path root path
* @throws IOException for any error
*/
protected void recomposeZip(OutputStream os, String path) throws IOException
{
// do nothing
}
}