package com.idega.core.ldap.client.cbutil;
import java.awt.Image;
import java.awt.Toolkit;
import java.io.InputStream;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Vector;
import java.util.zip.ZipException;
/**
* This Class provides access to a group of zip files. In the case of namespace conflicts between
* Zip files, the first zip file registered has priority. The zip files are accessed through CBJarResource.
*
*
* @author Chris Betts
* @see com.ca.od.util.CBJarResource
*/
public class CBResourceLoader
{
/**
* a cached list of 'unknown' resources that have been (unsuccessfully) looked up before.
*/
protected HashSet unknownResources = new HashSet();
/**
* A list of CBJarResources objects that may be searched for packaged resources.
*/
protected CBJarResource[] resourceFiles = null;
/**
* Whether to print out shtuff on the way.
*/
protected static boolean debug = false;
/**
* Constructor - note that that the class is useless until at least one resource file has been
* registered with it using the addResource() method.
*/
public CBResourceLoader()
{
CBUtility.log("Started CBResourceLoader",7);
}
/**
* Adds a new zip/jar resource file to the list of files to be examined for resources.
*/
public void addResource(CBJarResource resource)
{
int size = (this.resourceFiles == null)?0:(this.resourceFiles.length);
// The clumsiness of using an array is balanced by the need for quick
// access, and the fact that normally only a small number of resources are added,
// and only at the start of program operation.
CBJarResource[] newArray = new CBJarResource[size+1];
for (int i=0; i<size; i++) {
newArray[i] = this.resourceFiles[i];
}
newArray[size] = resource;
this.resourceFiles = newArray;
CBUtility.log("Added CBJarResource: " + resource.toString(), 7);
}
/**
* Search all registered zip files for a particular file, and return an input stream to that
* file.
*/
public InputStream getInputStream(String resourceName) throws ZipException
{
CBJarResource resourceFile = getJarContainingResource(resourceName);
if (resourceFile != null) {
return resourceFile.getInputStream(resourceName);
}
throw new ZipException("File: '" + resourceName + "' not found");
}
/**
* Search all registered zip files for a particular Image, and return an awt Image
* object.
*/
public Image getImage(String imageName, Toolkit imageCreator) throws ZipException
{
CBJarResource resourceFile = getJarContainingResource(imageName);
if (resourceFile != null) {
return resourceFile.getImage(imageName, imageCreator);
}
throw new ZipException("Image File: '" + imageName + "' not found");
}
/**
* Search all registered zip files for a particular file, and return the data within that
* file as a byte array. (This might be used to initialise a String object if the file is
* a text file, for instance.)
*/
public byte[] getResource(String resourceName) throws ZipException
{
CBUtility.log(" $$ getting resource '" + resourceName + "' from CBResourceLoader", 8);
CBJarResource resourceFile = getJarContainingResource(resourceName);
if (resourceFile != null)
{
CBUtility.log(" $$ found resource '" + resourceName + "' in zip file '" + resourceFile.getZipFileName() + "' - extracting", 8);
return resourceFile.getResource(resourceName);
}
throw new ZipException("File: '" + resourceName + "' not found");
}
public long getLastModified(String resourceName) throws ZipException
{
CBJarResource resourceFile = getJarContainingResource(resourceName);
if (resourceFile != null)
{
return resourceFile.getLastModified();
}
throw new ZipException("File: '" + resourceName + "' not found");
}
/**
* Searches an internal hash, followed by all Jar files, for a particular resource.
*/
public CBJarResource getJarContainingResource(String resourceName)
{
if (this.resourceFiles == null) {
return null; // we don't have any resources...
}
// check to see if we've already looked for this resource.
if (this.unknownResources.contains(resourceName)) {
return null;
}
for (int i=0; i<this.resourceFiles.length; i++) {
if (this.resourceFiles[i].hasResource(resourceName)) {
return this.resourceFiles[i];
}
}
// nothing found! Add an entry to the unknownResources hashset so that we don't look for
// it again.
this.unknownResources.add(resourceName);
return null; // nothing found
}
/**
* Returns all resources with the given prefix.
* @param prefix a string to match the start of resources against, e.g. 'icons/'
*/
public String[] getPrefixedResources(String prefix)
{
if (this.resourceFiles == null) {
return new String[] {}; // don't have anything.
}
Vector resources = new Vector();
// cycle through all resource files, gathering prefixed resources.
// name clashes are simply included twice :-)
for (int i=0; i<this.resourceFiles.length; i++)
{
resources.addAll(Arrays.asList(this.resourceFiles[i].getPrefixedResources(prefix)));
}
// cast stuff back to string for return.
if (resources.size() == 0)
{
return new String[] {};
}
else
{
return (String[]) resources.toArray(new String[resources.size()]);
}
}
/**
* This is a very PRIMATIVE wildcard matching routine - it allows
* only ONE wildcard, and that wildcard MUST be a '*' character.
* (So in effect this is simply a prefix + suffix match).
* @param exp a SIMPLE wildcard expression to match, e.g. 'templates/plain*.html'
*/
public String[] getWildCardResources(String exp)
{
if (this.resourceFiles == null) {
return new String[] {}; // don't have anything.to search
}
int wildpos = exp.indexOf('*');
if (wildpos == -1) {
return new String[] {exp};
}
if (wildpos == exp.length()-1) {
return getPrefixedResources(exp.substring(0,exp.length()-1));
}
//String prefix = exp.substring(0,wildpos);
//String suffix = exp.substring(wildpos+1);
Vector resources = new Vector();
// cycle through all resource files, gathering prefixed resources.
// name clashes are simply included twice :-)
for (int i=0; i<this.resourceFiles.length; i++)
{
// resources.addAll(Arrays.asList(resourceFiles[i].getBoundedResources(prefix, suffix)));
}
// cast stuff back to string for return.
if (resources.size() == 0)
{
return new String[] {};
}
else
{
return (String[]) resources.toArray(new String[resources.size()]);
}
}
}