You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

126 lines
4.0 KiB
Java

Jar class byte cache
package com.ack.tools.jarinfo;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.zip.ZipEntry;
import com.ack.tools.jarinfo.SuffixZipEntryFilter;
import com.ack.tools.jarinfo.JarInfo;
import com.ack.tools.jarinfo.JarInfoException;
/**
* This class provides an abstraction for classes within
* a jar/zip file. It simply returns the bytes for named
* classes that live within the supplied jar/zip file.
* Once retrieved from the jar/zip file, the bytes for
* a class are cached within the JarClassByteCache.
*
* <p>JarClassByteCache demonstrates of how easy it is
* to create your own cache of resources using JarInfo
* and JarByteLoader classes.
*
* @see com.ack.tools.jarinfo.JarInfo
* @see com.ack.tools.jarinfo.JarByteLoader
*/
public class JarClassByteCache {
private static final String kCLASS_SUFFIX = ".class";
private Hashtable fClassTable;
private Hashtable fZipTable;
private JarByteLoader fLoader;
/**
* Create a JarClassByteCache for classes in the zip file
*
* @exception reports problems reading the zip file
* @param the jar/zip file holding the classes
*/
public JarClassByteCache( String zipFile ) throws JarInfoException {
// creates a JarInfo object that contains zip entries for Java Classes only
fLoader = new JarByteLoader( zipFile, new SuffixZipEntryFilter( kCLASS_SUFFIX ) );
init();
}
/**
* accessor method to the byte cache's class names
* @return list of class names that will/have been cached
*/
public Enumeration getClassNames() {
return fZipTable.keys();
}
/**
* accessor method to get the JarInfo
* @return the jar info
*/
public JarInfo getJarInfo() {
return fLoader.getJarInfo();
}
/**
* get the class bytes for the named class. this will first
* look in its internal cache for the bytes for the named class
* and if it is not found in there load it from the underlying
* jar/zip file.
*
* @param the class name
* @return bytes for the named class. if it can't be found
* this method returns null
*/
public byte[] getClassBytes( String className ) throws JarInfoException {
if( className == null )
throw new JarInfoException( "supplied className to getClassBytes() was null" );
// first check to see if bytes for this class are cached
byte[] b = (byte[]) fClassTable.get( className );
// if not
if( b == null ) {
// get classes bytes from archive and cache them
if( ( b = loadBytes( className ) ) != null )
fClassTable.put( className, b );
else
throw new JarInfoException( "Unable to load class bytes for -> " + className );
}
return b;
}
/**
* Called from the constructor to create a cache of
* named classes against the actual ZipEntry in the
* jar/zip file.
*/
private void init() {
fClassTable = new Hashtable(); // maps class names to class bytes
fZipTable = new Hashtable(); // maps class names to ZipEntry
// cycle through all zip entries within fInfo
// which are all zip entries for java classes
Enumeration e = fLoader.getJarInfo().zipEntries();
while( e.hasMoreElements() ) {
ZipEntry ze = (ZipEntry) e.nextElement();
String className = ze.getName();
int index = className.lastIndexOf( '.' );
className = className.substring( 0, index ).replace( '/', '.' );
fZipTable.put( className, ze );
}
}
/**
* Extract the bytes for a class from the jar/zip file
* based on the supplied class name
*
* @exception reports any problem trying to get the
* the class bytes from the ZipEntry
* @param the full pathname of the class
* @return the bytes for the named class
*/
private byte[] loadBytes( String className ) throws JarInfoException {
return fLoader.getResourceAsBytes( (ZipEntry) fZipTable.get( className ) );
}
}