Programming Tutorials Browser Tutorials Articles Struts Tutorials Hibernate Tutorials

  Tutorial: Java Tip 83: Use filters to access resources in Java archives - JavaWorld

Java Tip 83: Use filters to access resources in Java archives - JavaWorld

Tutorial Details:

Java Tip 83: Use filters to access resources in Java archives
Java Tip 83: Use filters to access resources in Java archives
By: By Cleveland Gibbon
Roll your own zip filters and cache resources to create application-specific views on Java archives
tarting with JDK 1.1, archive files were used to bundle together such arbitrary Java resources as class files, image files, and sound files. They are now used to shrink-wrap logically related resources that collectively define applications (for example, Web applications), libraries (Java 2 platform), beans (EJB), and applets.
The java.util.jar and java.util.zip packages let Java applications programmatically access archive files. With the diverse set of resource types that an archive file can store, there is a need for better tools that read, query, and load these resources from Java applications. The figure below illustrates the classes and interfaces that I implement in this article, and which provide a code foundation for such tools.
Classes and interfaces implemented in this article
John Mitchell, Arthur Choi, and Todd Sundsted have demonstrated how to extract data from archive files in previous JavaWorld articles (see the Resources section below for links). For the purposes of this article, I'm assuming that you're familiar with these basic concepts. I'll start by explaining what a Java archive filter is and walk through some example source code. Next, I'll implement the JarClassTable class. JarClassTable demonstrates how you can combine archive filters with a simple caching system to create simple, easy-to-define views of resources in Java archive files. You'll see how easy this all is in Java.
What is a Java archive filter?
An archive file is simply a zip file with entries of various types. You want to be able to load archive files of varying sizes and apply filters to them. The JDK provides ways in which you can access and load the complete contents of an archive, but does not supply code with which you can access specific resources within the file. In order to do that, or create application-defined views of zip files, you'll need an archive filter.
You implement archive filters in much the same way that you would pass a java.io.FileFilter to the list() method of java.io.File in order to get specific files in a directory. In the following example, SuffixZipEntryFilter , a zip filter, is used by JarInfo to provide a view of an archive file. The full source code for SuffixZipEntryFilter and JarInfo is packaged in the jar file in Resources .
ZipEntryFilter classFilter = new SuffixZipEntryFilter(".class");
JarInfo jinfo = new JarInfo("yourarchive.jar", classFilter);
System.out.println( jinfo );
The code above displays all entries within yourarchive.jar whose zip entry names end with .class . Like java.io.FileFilter , ZipEntryFilter is an interface that has a single accept() method; however, it filters on ZipEntry , not java.io.File .
public interface ZipEntryFilter
{
public boolean accept( ZipEntry ze );
}
SuffixZipEntryFilter implements ZipEntryFilter , placing the filter logic inside the accept() method.
public class SuffixZipEntryFilter implements ZipEntryFilter
{
private String fSuffix;
public SuffixZipEntryFilter(String suffix)
{
fSuffix = suffix;
}
public boolean accept( ZipEntry ze )
{
if( ze == null || fSuffix == null )
return false;
return ze.getName().endsWith(fSuffix);
}
}
JarInfo uses zip entry filters to weed out unacceptable resources. The following example demonstrates how JarInfo 's constructor takes both a zip file and a zip entry filter to determine which zip entries it should extract from the archive:
public JarInfo(String fileName, ZipEntryFilter filter)
throws JarInfoException
{
if( fileName == null )
throw new JarInfoException("supplied filename to JarInfo was null");
if( filter == null )
throw new JarInfoException("supplied filter to JarInfo was null");
fEntries = new Hashtable();
ZipFile zipFile = null;
try
{
// create a ZipFile for the supplied 'fileName'
zipFile = new ZipFile(fileName);
// cycle through the header information with the zipFile
Enumeration e = zipFile.entries();
while( e.hasMoreElements() )
{
ZipEntry ze = (ZipEntry)e.nextElement();
// apply filter and store zip entry if accepted
if( filter.accept(ze) == true )
fEntries.put( ze.getName(), ze );
}
}
catch( ZipException zipe )
{
throw new JarInfoException( "Zip format problems reading " + fileName
+ "\n" + zipe.getMessage() );
}
catch( IOException ioe )
{
throw new JarInfoException( ioe.getMessage() );
}
catch( SecurityException se )
{
throw new JarInfoException( "Security problems reading " + fileName
+ "\n" + se.getMessage() );
}
finally
{
if( zipFile != null )
try { zipFile.close(); } catch(IOException ioe) {}
}
}
If you want JarInfo to extract and store all zip entries in an archive, just pass it a filter whose accept() method always returns true .
The ZipEntryFilter interface provides a simple, extensible mechanism by which developers can implement zip entry filters. JarInfo takes these filters and applies them to create a lightweight view of a Java archive. In the next section, I'll demonstrate how to use JarInfo to create a simple cache for class resources.
Using JarInfo
JarInfo provides you with the header information for filtered resources, but not the actual data. The next step is to load the data from a ZipEntry and make it available to your applications. The pros and cons of caching now come into play. Does the cost of storing data for these resources in memory outweigh the cost of repeatedly loading them from an archive file? This decision is dependent on the application. In our example, JarClassTable implements a simple cache for the bytes of Java class files loaded from a named archive file. JarClassTable uses JarInfo to provide a convenient, class-only view of an archive by filtering all resources that end in .class :
public JarClassTable(String zipFile) throws JarInfoException
{
// creates a JarInfo object that contains zip entries for Java Classes only
fInfo = new JarInfo( zipFile, new SuffixZipEntryFilter(kCLASS_SUFFIX) );
fClassTable = new Hashtable(); // maps class names to class bytes
fZipTable = new Hashtable(); // maps class names to ZipEntry
fZipFileName = zipFile; // holds copy of zip file name
init();
}
getClassBytes() is the only public method in JarClassTable . For a named class, it retrieves the bytes that make up the class file. getClassBytes() first consults the cache to see if it already has the required class bytes. If so, these are returned; otherwise, the bytes for the named class are fetched from the archive file using the loadBytes() method. This method is well commented in the source code; a full explanation of loading bytes from archive files is given in Mitchell and Choi's article, "Java Tip 49: How to extract Java resources from jar and zip archives" (see Resources ).
public byte[] getClassBytes( String className ) throws JarInfoException
{
if( className == null )
return 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;
}
Incidentally, the init() method in JarClassTable creates a hashtable of zip entries keyed by their class name. It does this by converting the zip entry name, /com/ack/jar/JarClassTable.class , into its appropriate Java class name, com.ack.jar.JarClassTable . You may prefer to do this name mangling as calls are made to getClassBytes() instead of creating such a hashtable.
Using JarClassTable
So far, we have created a general-purpose utility class, JarInfo , that lets you effortlessly create your own views of an archive file by implementing filters. We then implemented JarClassTable , which made direct use of JarInfo to provide a load-on-demand cache of class
bytes. However, JarClassTable only lets you retrieve the bytes for a class. The following code demonstrates how the customized JarInfoClassLoader uses JarClassTable to load classes from an archive file and make them available as Class objects within Java applications.
public class JarInfoClassLoader extends SecureClassLoader
{
private JarClassTable fClassTable;
public JarInfoClassLoader(String zipFile, ClassLoader cl) throws JarInfoException
{
super( cl );
fClassTable = new JarClassTable(zipFile);
}
Java 2 uses the delegation model for class loading. Under this model, loading a class is attempted first by the parent ClassLoader and then by JarInfoClassLoader .
The only other method in JarInfoClassLoader is findClass() , which is implemented as follows:
public Class findClass( String className ) throws ClassNotFoundException
{
// get the bytes for a class from the class table
byte[] b = null;
try
{
b = fClassTable.getClassBytes(className);
}
catch(JarInfoException jie) {}
// and if there are some, use the inherited method defineClass
// to convert these bytes into an instance of a Class
if( b != null )
return defineClass(className, b, 0, b.length);
// otherwise if there is no such class
return null;
}
findClass() also participates in the ClassLoader delegation model, and will only be called if all efforts by the Java Virtual Machine to find the class in question have failed. Putting this all together, you can now use JarInfoClassLoader to load classes from an archive that does not appear in the application's CLASSPATH or Java extension directory.
Using JarInfoClassLoader
The test harness, TestApp , demonstrates how to use JarInfoClassLoader :
// create a jar class loader to read from kJARNAME
JarInfoClassLoader jcl = new JarInfoClassLoader(kJARNAME);
// and load a class from that class loader
Class c = jcl.loadClass("co


 

Read Tutorial at: Click here to view the tutorial

Rate Tutorial:
Java Tip 83: Use filters to access resources in Java archives - JavaWorld

View Tutorial:
Java Tip 83: Use filters to access resources in Java archives - JavaWorld

Related Tutorials:

Applet to Applet Communication
Applet to Applet Communication
 
Java Tip 72: Press Escape to close your Swing dialog windows
Java Tip 72: Press Escape to close your Swing dialog windows
 
Master Merlin's new I/O classes
Master Merlin's new I/O classes
 
Make a statement with javac!
Make a statement with javac!
 
Quickly access files and directories you use repeatedly
Quickly access files and directories you use repeatedly
 
Back to your Class roots
Back to your Class roots
 
Once again, only introduction
Once again, only introduction
 
good design pattern
good design pattern
 
Java and Security, Part 1
Java and Security WebLogic provides a comprehensive suite of security services that can be used to protect all aspects of a domain and its deployments. These security services affect all aspects of your domain: from the lowest level provided by the Jav
 
Filtering and Transforming Digital Images
Filtering and Transforming Digital Images In this Issue Welcome to the Core Java Technologies Tech Tips for April 7, 2004. Here you\'ll get tips on using core Java technologies and APIs, such as those in Java 2 Platform, Standard Edition (J2SE).
 
Writing Ant Tasks
Writing Ant Tasks A nice feature of Ant is that it is designed to allow you to add your own tasks and use them in an build. This article shows you the basics of writing an Ant task and how to get a task to work.
 
PrEd
PrEd is a Java based graphical utility to find and edit Java property files in JAR, WAR, EAR and other kind of ZIP archives. It is the perfect tool for customizing Java applications, which use XML and Property files for their configuration.
 
Application Integration: Sun Java System Access Manager 2004Q2 and JDBC Authentication Module
Today, most user authentication solutions for Web applications are ad hoc and are based on proprietary schema definitions in relational databases. So, if you have multiple Web applications, you may have a separate user database for each of your applicatio
 
Smokescreen Introduction
Smokescreen is a Java obfuscator. Aside from being able to change symbolic names, it can also modify the bytecode instructions in methods thereby obfuscating control flow. This makes the resulting obfuscated classes much more difficult to decompile.
 
Create Intelligent E-mail Filters with JavaMail and Classifier4j
Create Intelligent E-mail Filters with JavaMail and Classifier4j Tired of the limitations and annoying false positives with commercial spam filters? Classifier4J is an open source Java library that will let you build custom applications that read e-mails
 
Clean Up Your Mess: Managing Temp Files in Java Apps
Clean Up Your Mess: Managing Temp Files in Java Apps Creating and managing temporary files in a Java application can be a little tricky due to some open JVM bugs. Develop a workaround with some custom code and a clever design.
 
Smokescreen 3.4 has been released
Smokescreen is a Java obfuscator. Aside from being able to change symbolic names, it can also modify the bytecode instructions in methods thereby obfuscating control flow. This makes the resulting obfuscated classes much more difficult to decompile.
 
Tag Libraries Tutorial
This tutorial describes how to use and develop JavaServer Pages tag libraries. The tutorial assumes that you know how to develop servlets and JSP pages and are familiar with packaging servlets and JSP pages into Web application archives.
 
Getting Started With Bluetooth
JSR-82 brings Bluetooth API's to the J2ME environment. Read the tech tip and begin experimenting with Bluetooth today using the Wireless Toolkit 2.2 Beta.
 
The J2EE Architecture allows the programmers to divide their work into two major categories Business Logic Presentation
The J2EE Architecture allows the programmers to divide their work into two major categories Business Logic Presentation Logic J2EE Architecture The J2EE Architecture allows the programmers to divide their work into two major categories: Business
 
Site navigation
 

 

Send your comments, Suggestions or Queries regarding this site at roseindia_net@yahoo.com.

Copyright © 2006. All rights reserved.