com.tangosol.engarde.JarStorage Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of coherence Show documentation
Show all versions of coherence Show documentation
Oracle Coherence Community Edition
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates.
*
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
package com.tangosol.engarde;
import com.tangosol.util.Base;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.jar.JarFile;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
/**
* Jar file that contains a Java application components.
*
* @version 1.00 10/08/01
* @author gg
*/
public class JarStorage
extends Base
implements ApplicationReader, ApplicationWriter
{
/**
* Construct a new JarStorage reader
*
* @param jarFile JarFile object wrapped by this JarStorage
*/
public JarStorage(JarFile jarFile)
throws IOException
{
azzert(jarFile != null);
m_jar = jarFile;
m_fAllowRead = true;
}
/**
* Construct a new JarStorage writer
*
* @param fileJar file object this JarStorage writer is writing to
* @param manifest manifest to use while creating a new jar
*/
public JarStorage(File fileJar, Manifest manifest)
throws IOException
{
FileOutputStream stream = new FileOutputStream(fileJar);
m_fileOut = fileJar;
m_jarOut = manifest == null ?
new JarOutputStream(stream) : new JarOutputStream(stream, manifest);
m_fAllowWrite = true;
}
/**
* Get the JarFile object for the Java archive (reader) represented
* by this JarStorage
*/
public JarFile getJar()
{
return m_jar;
}
/**
* Get the JarOutputStream object for the Java archive (writer) represented
* by this JarStorage
*/
public JarOutputStream getJarOut()
{
return m_jarOut;
}
/**
* Provide a human-readable description of the storage.
*
* @return a string describing the property
*/
public String toString()
{
return "JarStorage" +
(m_jar != null ? " Reader: " + m_jar .getName() : "") +
(m_fileOut != null ? " Writer: " + m_fileOut.getName() : "");
}
// ---- ApplicationReader interface ---------------------------------------
/**
* Return an input stream for reading the content of the specified
* application entry.
*
* @param entry the application entry
*
* @return an input stream for reading the content of the specified
* application entry or null if not found
*
* @exception IOException if an I/O error has occurred
*/
public InputStream getInputStream(ApplicationEntry entry)
throws IOException
{
if (!m_fAllowRead)
{
throw new IllegalStateException(
"ApplicationReader operation is not allowed at: " + this);
}
JarEntry je = entry instanceof Entry ?
((Entry) entry).getJarEntry() : m_jar.getJarEntry(entry.getName());
return je == null ? null : m_jar.getInputStream(je);
}
/**
* Return an ApplicationReader that represents an application containted
* within this application as a specified application entry
*
* Note: caller is responsible for removing the extracted jar file
*
* @param sName name of the application entry
*
* @return an ApplicationReader object for reading the content of
* the contained application or null if not found
*
* @exception IOException if an I/O error has occurred
*/
public ApplicationReader extractApplication(String sName)
throws IOException
{
if (!m_fAllowRead)
{
throw new IllegalStateException(
"ApplicationReader operation is not allowed at: " + this);
}
JarFile jar = com.tangosol.dev.component.JarStorage.extractJar(m_jar, sName);
return jar == null ? null : new JarStorage(jar);
}
/**
* Return an ApplicationEntry object for the given name
*
* @param sName name of the application entry
*
* @return ApplicationEntry object for the given entry name or
* null if not found
*/
public ApplicationEntry getEntry(String sName)
{
if (!m_fAllowRead)
{
throw new IllegalStateException(
"ApplicationReader operation is not allowed at: " + this);
}
JarEntry je = m_jar.getJarEntry(sName);
return je == null ? null : new Entry(je);
}
/**
* Return an enumeration of the application entries
*
* @return Enumeration of ApplicationEntry objects
*/
public Enumeration entries()
{
if (!m_fAllowRead)
{
throw new IllegalStateException(
"ApplicationReader operation is not allowed at: " + this);
}
final Enumeration enmr = m_jar.entries();
return new Enumeration()
{
public boolean hasMoreElements()
{
return enmr.hasMoreElements();
}
public Object nextElement()
{
return new Entry((JarEntry) enmr.nextElement());
}
};
}
/**
* Close the application reader and release all used resources
*/
public void close()
{
try
{
if (m_fAllowRead)
{
JarFile jar = m_jar;
if (jar != null)
{
jar.close();
m_jar = null;
}
m_fAllowRead = false;
}
if (m_fAllowWrite)
{
closeEntry();
JarOutputStream jarOut = m_jarOut;
if (jarOut != null)
{
jarOut.close();
m_jarOut = null;
m_fileOut = null;
}
m_fAllowWrite = false;
}
}
catch (IOException e) {}
}
// ---- ApplicationWriter interface ---------------------------------------
/**
* Create a new application entry with a given name and prepare to start
* writing the entry data. Close the current entry if still active.
*
* @param sName the application entry name
*
* @return a newly created AppplicationEntry
*
* @exception IOException if an I/O error has occurred
*/
public ApplicationEntry createEntry(String sName)
throws IOException
{
if (!m_fAllowWrite)
{
throw new IllegalStateException(
"ApplicationWriter operation is not allowed at: " + this);
}
Entry entry = m_currEntry;
if (entry != null)
{
closeEntry();
}
JarEntry je = new JarEntry(sName);
m_currEntry = entry = new Entry(je);
return entry;
}
/**
* Create a new application entry with all attributes of the specified
* entry and prepare to start writing the entry data.
* Close the current entry if still active.
*
* @param entry an application entry
*
* @return a newly created AppplicationEntry
*
* @exception IOException if an I/O error has occurred
*/
public ApplicationEntry createEntry(ApplicationEntry entry)
throws IOException
{
if (!m_fAllowWrite)
{
throw new IllegalStateException(
"ApplicationWriter operation is not allowed at: " + this);
}
Entry entryCurr = m_currEntry;
if (entryCurr != null)
{
closeEntry();
}
JarEntry je;
if (entry instanceof Entry)
{
je = new JarEntry(((Entry) entry).getJarEntry());
// the compression algorithm could be different
je.setCompressedSize(-1);
}
else
{
je = new JarEntry(entry.getName());
je.setTime(entry.getTime());
je.setSize(entry.getSize());
je.setMethod(JarOutputStream.DEFLATED);
}
m_currEntry = entryCurr = new Entry(je);
return entryCurr;
}
/**
* Write an array of bytes to the current application entry data.
* This method will block until all the bytes are written.
*
* @param ab the data to be written
* @param of the offset into the array
* @param cb the number of bytes to write
*
* @exception IOException if an I/O error has occurred
*/
public void writeEntryData(byte[] ab, int of, int cb)
throws IOException
{
if (!m_fAllowWrite)
{
throw new IllegalStateException(
"ApplicationWriter operation is not allowed: " + this);
}
Entry entry = m_currEntry;
if (entry == null)
{
throw new IllegalStateException("Request is out of sequence");
}
JarOutputStream jarOut = m_jarOut;
if (!m_fAdded)
{
jarOut.putNextEntry(entry.getJarEntry());
m_fAdded = true;
}
if (cb > 0)
{
jarOut.write(ab, of, cb);
}
}
/**
* Close the current application entry.
*
* @exception IOException if an I/O error has occurred
*/
public void closeEntry()
throws IOException
{
if (!m_fAllowWrite)
{
throw new IllegalStateException(
"ApplicationWriter operation is not allowed: " + this);
}
Entry entry = m_currEntry;
if (entry != null)
{
m_jarOut.closeEntry();
m_currEntry = null;
m_fAdded = false;
}
}
// ---- data fields and constants ----------------------------------------
/**
* Specifies whether or not the "read" operations are allowed
*/
private boolean m_fAllowRead;
/**
* Specifies whether or not the "write" operations are allowed
*/
private boolean m_fAllowWrite;
/**
* Specifies the root directory of this storage
*/
private JarFile m_jar;
/**
* Specifies the currently "active" output file
*/
private File m_fileOut;
/**
* Specifies the currently "active" file output stream
*/
private JarOutputStream m_jarOut;
/**
* Specifies the currently "active" entry
*/
private Entry m_currEntry;
/**
* Specifies whether the currently entry has been added to
* the jar output stream
*/
private boolean m_fAdded;
/**
* ACCESS_READ denotes the read only mode of operations
*/
public static final int ACCESS_READ = 1;
/**
* ACCESS_WRITE denotes the read only mode of operations
*/
public static final int ACCESS_WRITE = 2;
/**
* The name of this class.
*/
private static final String CLASS = "JarStorage";
// ---- inner class -------------------------------------------------------
static public class Entry
implements ApplicationEntry
{
/**
* Construct a new entry backed up by the specified JarEntry
*/
protected Entry(JarEntry entry)
{
azzert(entry != null);
m_entry = entry;
}
/**
* Get the JarEntry object backing up this entry
*/
public JarEntry getJarEntry()
{
return m_entry;
}
// ---- ApplicationEntry interface ------------------------------------
/**
* Return the name of the entry.
*
* @return the name of the entry
*/
public String getName()
{
return m_entry.getName();
}
/**
* Return the modification time of the entry, or -1 if not specified.
*
* @return the modification time of the entry, or -1 if not specified
*/
public long getTime()
{
return m_entry.getTime();
}
/**
* Set the modification time of the entry.
*
* @param lTime the entry modification time in number of milliseconds
* since the epoch
*/
public void setTime(long lTime)
{
m_entry.setTime(lTime);
}
/**
* Return the [uncompressed] size of the entry data, or -1 if not known.
*
* @return the size of the entry data, or -1 if not known
*/
public long getSize()
{
return m_entry.getSize();
}
/**
* Set the [uncompressed] size of the entry data.
*
* @param lSize the size in bytes
*/
public void setSize(long lSize)
{
JarEntry je = m_entry;
je.setMethod(JarOutputStream.DEFLATED);
je.setSize(lSize);
je.setCompressedSize(-1);
}
// ----- Object methods -------------------------------------------
/**
* Provide a human-readable description of the storage.
*
* @return a string describing the property
*/
public String toString()
{
return "JarStorage$Entry: " + getName();
}
// ---- data fields --------------------------------------------------
/**
* File object representing this Entry
*/
private JarEntry m_entry;
}
}