com.opensymphony.xwork2.util.finder.ResourceFinder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xwork Show documentation
Show all versions of xwork Show documentation
XWork is an command-pattern framework that is used to power WebWork
as well as other applications. XWork provides an Inversion of Control
container, a powerful expression language, data type conversion,
validation, and pluggable configuration.
The newest version!
/*
* Copyright (c) 2002-2003 by OpenSymphony
* All rights reserved.
*/
package com.opensymphony.xwork2.util.finder;
import org.apache.commons.lang.StringUtils;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.*;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
/**
* @author David Blevins
* @version $Rev$ $Date$
*/
public class ResourceFinder {
private static final Logger LOG = LoggerFactory.getLogger(ResourceFinder.class);
private final URL[] urls;
private final String path;
private final ClassLoaderInterface classLoaderInterface;
private final List resourcesNotLoaded = new ArrayList();
public ResourceFinder(URL... urls) {
this(null, new ClassLoaderInterfaceDelegate(Thread.currentThread().getContextClassLoader()), urls);
}
public ResourceFinder(String path) {
this(path, new ClassLoaderInterfaceDelegate(Thread.currentThread().getContextClassLoader()), null);
}
public ResourceFinder(String path, URL... urls) {
this(path, new ClassLoaderInterfaceDelegate(Thread.currentThread().getContextClassLoader()), urls);
}
public ResourceFinder(String path, ClassLoaderInterface classLoaderInterface) {
this(path, classLoaderInterface, null);
}
public ResourceFinder(String path, ClassLoaderInterface classLoaderInterface, URL... urls) {
if (path == null){
path = "";
} else if (path.length() > 0 && !path.endsWith("/")) {
path += "/";
}
this.path = path;
this.classLoaderInterface = classLoaderInterface == null ? new ClassLoaderInterfaceDelegate(Thread.currentThread().getContextClassLoader()) : classLoaderInterface ;
for (int i = 0; urls != null && i < urls.length; i++) {
URL url = urls[i];
if (url == null || isDirectory(url) || "jar".equals(url.getProtocol())) {
continue;
}
try {
urls[i] = new URL("jar", "", -1, url.toString() + "!/");
} catch (MalformedURLException e) {
}
}
this.urls = (urls == null || urls.length == 0)? null : urls;
}
private static boolean isDirectory(URL url) {
String file = url.getFile();
return (file.length() > 0 && file.charAt(file.length() - 1) == '/');
}
/**
* Returns a list of resources that could not be loaded in the last invoked findAvailable* or
* mapAvailable* methods.
*
* The list will only contain entries of resources that match the requirements
* of the last invoked findAvailable* or mapAvailable* methods, but were unable to be
* loaded and included in their results.
*
* The list returned is unmodifiable and the results of this method will change
* after each invocation of a findAvailable* or mapAvailable* methods.
*
* This method is not thread safe.
*/
public List getResourcesNotLoaded() {
return Collections.unmodifiableList(resourcesNotLoaded);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
//
// Find
//
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
public URL find(String uri) throws IOException {
String fullUri = path + uri;
return getResource(fullUri);
}
public List findAll(String uri) throws IOException {
String fullUri = path + uri;
Enumeration resources = getResources(fullUri);
List list = new ArrayList();
while (resources.hasMoreElements()) {
URL url = resources.nextElement();
list.add(url);
}
return list;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
//
// Find String
//
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/**
* Reads the contents of the URL as a {@link String}'s and returns it.
*
* @param uri
* @return a stringified content of a resource
* @throws IOException if a resource pointed out by the uri param could not be find
* @see ClassLoader#getResource(String)
*/
public String findString(String uri) throws IOException {
String fullUri = path + uri;
URL resource = getResource(fullUri);
if (resource == null) {
throw new IOException("Could not find a resource in : " + fullUri);
}
return readContents(resource);
}
/**
* Reads the contents of the found URLs as a list of {@link String}'s and returns them.
*
* @param uri
* @return a list of the content of each resource URL found
* @throws IOException if any of the found URLs are unable to be read.
*/
public List findAllStrings(String uri) throws IOException {
String fulluri = path + uri;
List strings = new ArrayList();
Enumeration resources = getResources(fulluri);
while (resources.hasMoreElements()) {
URL url = resources.nextElement();
String string = readContents(url);
strings.add(string);
}
return strings;
}
/**
* Reads the contents of the found URLs as a Strings and returns them.
* Individual URLs that cannot be read are skipped and added to the
* list of 'resourcesNotLoaded'
*
* @param uri
* @return a list of the content of each resource URL found
* @throws IOException if classLoader.getResources throws an exception
*/
public List findAvailableStrings(String uri) throws IOException {
resourcesNotLoaded.clear();
String fulluri = path + uri;
List strings = new ArrayList();
Enumeration resources = getResources(fulluri);
while (resources.hasMoreElements()) {
URL url = resources.nextElement();
try {
String string = readContents(url);
strings.add(string);
} catch (IOException notAvailable) {
resourcesNotLoaded.add(url.toExternalForm());
}
}
return strings;
}
/**
* Reads the contents of all non-directory URLs immediately under the specified
* location and returns them in a map keyed by the file name.
*
* Any URLs that cannot be read will cause an exception to be thrown.
*
* Example classpath:
*
* META-INF/serializables/one
* META-INF/serializables/two
* META-INF/serializables/three
* META-INF/serializables/four/foo.txt
*
* ResourceFinder finder = new ResourceFinder("META-INF/");
* Map map = finder.mapAvailableStrings("serializables");
* map.contains("one"); // true
* map.contains("two"); // true
* map.contains("three"); // true
* map.contains("four"); // false
*
* @param uri
* @return a list of the content of each resource URL found
* @throws IOException if any of the urls cannot be read
*/
public Map mapAllStrings(String uri) throws IOException {
Map strings = new HashMap();
Map resourcesMap = getResourcesMap(uri);
for (Map.Entry entry : resourcesMap.entrySet()) {
String name = entry.getKey();
URL url = entry.getValue();
String value = readContents(url);
strings.put(name, value);
}
return strings;
}
/**
* Reads the contents of all non-directory URLs immediately under the specified
* location and returns them in a map keyed by the file name.
*
* Individual URLs that cannot be read are skipped and added to the
* list of 'resourcesNotLoaded'
*
* Example classpath:
*
* META-INF/serializables/one
* META-INF/serializables/two # not readable
* META-INF/serializables/three
* META-INF/serializables/four/foo.txt
*
* ResourceFinder finder = new ResourceFinder("META-INF/");
* Map map = finder.mapAvailableStrings("serializables");
* map.contains("one"); // true
* map.contains("two"); // false
* map.contains("three"); // true
* map.contains("four"); // false
*
* @param uri
* @return a list of the content of each resource URL found
* @throws IOException if classLoader.getResources throws an exception
*/
public Map mapAvailableStrings(String uri) throws IOException {
resourcesNotLoaded.clear();
Map strings = new HashMap();
Map resourcesMap = getResourcesMap(uri);
for (Map.Entry entry : resourcesMap.entrySet()) {
String name = entry.getKey();
URL url = entry.getValue();
try {
String value = readContents(url);
strings.put(name, value);
} catch (IOException notAvailable) {
resourcesNotLoaded.add(url.toExternalForm());
}
}
return strings;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
//
// Find Class
//
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/**
* Executes {@link #findString(String)} assuming the contents URL found is the name of
* a class that should be loaded and returned.
*
* @param uri
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public Class findClass(String uri) throws IOException, ClassNotFoundException {
String className = findString(uri);
return (Class) classLoaderInterface.loadClass(className);
}
/**
* Executes findAllStrings assuming the strings are
* the names of a classes that should be loaded and returned.
*
* Any URL or class that cannot be loaded will cause an exception to be thrown.
*
* @param uri
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public List findAllClasses(String uri) throws IOException, ClassNotFoundException {
List classes = new ArrayList();
List strings = findAllStrings(uri);
for (String className : strings) {
Class clazz = classLoaderInterface.loadClass(className);
classes.add(clazz);
}
return classes;
}
/**
* Executes findAvailableStrings assuming the strings are
* the names of a classes that should be loaded and returned.
*
* Any class that cannot be loaded will be skipped and placed in the
* 'resourcesNotLoaded' collection.
*
* @param uri
* @return
* @throws IOException if classLoader.getResources throws an exception
*/
public List findAvailableClasses(String uri) throws IOException {
resourcesNotLoaded.clear();
List classes = new ArrayList();
List strings = findAvailableStrings(uri);
for (String className : strings) {
try {
Class clazz = classLoaderInterface.loadClass(className);
classes.add(clazz);
} catch (Exception notAvailable) {
resourcesNotLoaded.add(className);
}
}
return classes;
}
/**
* Executes mapAllStrings assuming the value of each entry in the
* map is the name of a class that should be loaded.
*
* Any class that cannot be loaded will be cause an exception to be thrown.
*
* Example classpath:
*
* META-INF/xmlparsers/xerces
* META-INF/xmlparsers/crimson
*
* ResourceFinder finder = new ResourceFinder("META-INF/");
* Map map = finder.mapAvailableStrings("xmlparsers");
* map.contains("xerces"); // true
* map.contains("crimson"); // true
* Class xercesClass = map.get("xerces");
* Class crimsonClass = map.get("crimson");
*
* @param uri
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public Map mapAllClasses(String uri) throws IOException, ClassNotFoundException {
Map classes = new HashMap();
Map map = mapAllStrings(uri);
for (Map.Entry entry : map.entrySet()) {
String string = entry.getKey();
String className = entry.getValue();
Class clazz = classLoaderInterface.loadClass(className);
classes.put(string, clazz);
}
return classes;
}
/**
* Executes mapAvailableStrings assuming the value of each entry in the
* map is the name of a class that should be loaded.
*
* Any class that cannot be loaded will be skipped and placed in the
* 'resourcesNotLoaded' collection.
*
* Example classpath:
*
* META-INF/xmlparsers/xerces
* META-INF/xmlparsers/crimson
*
* ResourceFinder finder = new ResourceFinder("META-INF/");
* Map map = finder.mapAvailableStrings("xmlparsers");
* map.contains("xerces"); // true
* map.contains("crimson"); // true
* Class xercesClass = map.get("xerces");
* Class crimsonClass = map.get("crimson");
*
* @param uri
* @return
* @throws IOException if classLoader.getResources throws an exception
*/
public Map mapAvailableClasses(String uri) throws IOException {
resourcesNotLoaded.clear();
Map classes = new HashMap();
Map map = mapAvailableStrings(uri);
for (Map.Entry entry : map.entrySet()) {
String string = entry.getKey();
String className = entry.getValue();
try {
Class clazz = classLoaderInterface.loadClass(className);
classes.put(string, clazz);
} catch (Exception notAvailable) {
resourcesNotLoaded.add(className);
}
}
return classes;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
//
// Find Implementation
//
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/**
* Assumes the class specified points to a file in the classpath that contains
* the name of a class that implements or is a subclass of the specfied class.
*
* Any class that cannot be loaded will be cause an exception to be thrown.
*
* Example classpath:
*
* META-INF/java.io.InputStream # contains the classname org.acme.AcmeInputStream
* META-INF/java.io.OutputStream
*
* ResourceFinder finder = new ResourceFinder("META-INF/");
* Class clazz = finder.findImplementation(java.io.InputStream.class);
* clazz.getName(); // returns "org.acme.AcmeInputStream"
*
* @param interfase a superclass or interface
* @return
* @throws IOException if the URL cannot be read
* @throws ClassNotFoundException if the class found is not loadable
* @throws ClassCastException if the class found is not assignable to the specified superclass or interface
*/
public Class findImplementation(Class interfase) throws IOException, ClassNotFoundException {
String className = findString(interfase.getName());
Class impl = classLoaderInterface.loadClass(className);
if (!interfase.isAssignableFrom(impl)) {
throw new ClassCastException("Class not of type: " + interfase.getName());
}
return impl;
}
/**
* Assumes the class specified points to a file in the classpath that contains
* the name of a class that implements or is a subclass of the specfied class.
*
* Any class that cannot be loaded or assigned to the specified interface will be cause
* an exception to be thrown.
*
* Example classpath:
*
* META-INF/java.io.InputStream # contains the classname org.acme.AcmeInputStream
* META-INF/java.io.InputStream # contains the classname org.widget.NeatoInputStream
* META-INF/java.io.InputStream # contains the classname com.foo.BarInputStream
*
* ResourceFinder finder = new ResourceFinder("META-INF/");
* List classes = finder.findAllImplementations(java.io.InputStream.class);
* classes.contains("org.acme.AcmeInputStream"); // true
* classes.contains("org.widget.NeatoInputStream"); // true
* classes.contains("com.foo.BarInputStream"); // true
*
* @param interfase a superclass or interface
* @return
* @throws IOException if the URL cannot be read
* @throws ClassNotFoundException if the class found is not loadable
* @throws ClassCastException if the class found is not assignable to the specified superclass or interface
*/
public List findAllImplementations(Class interfase) throws IOException, ClassNotFoundException {
List implementations = new ArrayList();
List strings = findAllStrings(interfase.getName());
for (String className : strings) {
Class impl = classLoaderInterface.loadClass(className);
if (!interfase.isAssignableFrom(impl)) {
throw new ClassCastException("Class not of type: " + interfase.getName());
}
implementations.add(impl);
}
return implementations;
}
/**
* Assumes the class specified points to a file in the classpath that contains
* the name of a class that implements or is a subclass of the specfied class.
*
* Any class that cannot be loaded or are not assignable to the specified class will be
* skipped and placed in the 'resourcesNotLoaded' collection.
*
* Example classpath:
*
* META-INF/java.io.InputStream # contains the classname org.acme.AcmeInputStream
* META-INF/java.io.InputStream # contains the classname org.widget.NeatoInputStream
* META-INF/java.io.InputStream # contains the classname com.foo.BarInputStream
*
* ResourceFinder finder = new ResourceFinder("META-INF/");
* List classes = finder.findAllImplementations(java.io.InputStream.class);
* classes.contains("org.acme.AcmeInputStream"); // true
* classes.contains("org.widget.NeatoInputStream"); // true
* classes.contains("com.foo.BarInputStream"); // true
*
* @param interfase a superclass or interface
* @return
* @throws IOException if classLoader.getResources throws an exception
*/
public List findAvailableImplementations(Class interfase) throws IOException {
resourcesNotLoaded.clear();
List implementations = new ArrayList();
List strings = findAvailableStrings(interfase.getName());
for (String className : strings) {
try {
Class impl = classLoaderInterface.loadClass(className);
if (interfase.isAssignableFrom(impl)) {
implementations.add(impl);
} else {
resourcesNotLoaded.add(className);
}
} catch (Exception notAvailable) {
resourcesNotLoaded.add(className);
}
}
return implementations;
}
/**
* Assumes the class specified points to a directory in the classpath that holds files
* containing the name of a class that implements or is a subclass of the specfied class.
*
* Any class that cannot be loaded or assigned to the specified interface will be cause
* an exception to be thrown.
*
* Example classpath:
*
* META-INF/java.net.URLStreamHandler/jar
* META-INF/java.net.URLStreamHandler/file
* META-INF/java.net.URLStreamHandler/http
*
* ResourceFinder finder = new ResourceFinder("META-INF/");
* Map map = finder.mapAllImplementations(java.net.URLStreamHandler.class);
* Class jarUrlHandler = map.get("jar");
* Class fileUrlHandler = map.get("file");
* Class httpUrlHandler = map.get("http");
*
* @param interfase a superclass or interface
* @return
* @throws IOException if the URL cannot be read
* @throws ClassNotFoundException if the class found is not loadable
* @throws ClassCastException if the class found is not assignable to the specified superclass or interface
*/
public Map mapAllImplementations(Class interfase) throws IOException, ClassNotFoundException {
Map implementations = new HashMap();
Map map = mapAllStrings(interfase.getName());
for (Map.Entry entry : map.entrySet()) {
String string = entry.getKey();
String className = entry.getValue();
Class impl = classLoaderInterface.loadClass(className);
if (!interfase.isAssignableFrom(impl)) {
throw new ClassCastException("Class not of type: " + interfase.getName());
}
implementations.put(string, impl);
}
return implementations;
}
/**
* Assumes the class specified points to a directory in the classpath that holds files
* containing the name of a class that implements or is a subclass of the specfied class.
*
* Any class that cannot be loaded or are not assignable to the specified class will be
* skipped and placed in the 'resourcesNotLoaded' collection.
*
* Example classpath:
*
* META-INF/java.net.URLStreamHandler/jar
* META-INF/java.net.URLStreamHandler/file
* META-INF/java.net.URLStreamHandler/http
*
* ResourceFinder finder = new ResourceFinder("META-INF/");
* Map map = finder.mapAllImplementations(java.net.URLStreamHandler.class);
* Class jarUrlHandler = map.get("jar");
* Class fileUrlHandler = map.get("file");
* Class httpUrlHandler = map.get("http");
*
* @param interfase a superclass or interface
* @return
* @throws IOException if classLoader.getResources throws an exception
*/
public Map mapAvailableImplementations(Class interfase) throws IOException {
resourcesNotLoaded.clear();
Map implementations = new HashMap();
Map map = mapAvailableStrings(interfase.getName());
for (Map.Entry entry : map.entrySet()) {
String string = entry.getKey();
String className = entry.getValue();
try {
Class impl = classLoaderInterface.loadClass(className);
if (interfase.isAssignableFrom(impl)) {
implementations.put(string, impl);
} else {
resourcesNotLoaded.add(className);
}
} catch (Exception notAvailable) {
resourcesNotLoaded.add(className);
}
}
return implementations;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
//
// Find Properties
//
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/**
* Finds the corresponding resource and reads it in as a properties file
*
* Example classpath:
*
* META-INF/widget.properties
*
* ResourceFinder finder = new ResourceFinder("META-INF/");
* Properties widgetProps = finder.findProperties("widget.properties");
*
* @param uri
* @return
* @throws IOException if the URL cannot be read or is not in properties file format
*/
public Properties findProperties(String uri) throws IOException {
String fulluri = path + uri;
URL resource = getResource(fulluri);
if (resource == null) {
throw new IOException("Could not find command in : " + fulluri);
}
return loadProperties(resource);
}
/**
* Finds the corresponding resources and reads them in as a properties files
*
* Any URL that cannot be read in as a properties file will cause an exception to be thrown.
*
* Example classpath:
*
* META-INF/app.properties
* META-INF/app.properties
* META-INF/app.properties
*
* ResourceFinder finder = new ResourceFinder("META-INF/");
* List appProps = finder.findAllProperties("app.properties");
*
* @param uri
* @return
* @throws IOException if the URL cannot be read or is not in properties file format
*/
public List findAllProperties(String uri) throws IOException {
String fulluri = path + uri;
List properties = new ArrayList();
Enumeration resources = getResources(fulluri);
while (resources.hasMoreElements()) {
URL url = resources.nextElement();
Properties props = loadProperties(url);
properties.add(props);
}
return properties;
}
/**
* Finds the corresponding resources and reads them in as a properties files
*
* Any URL that cannot be read in as a properties file will be added to the
* 'resourcesNotLoaded' collection.
*
* Example classpath:
*
* META-INF/app.properties
* META-INF/app.properties
* META-INF/app.properties
*
* ResourceFinder finder = new ResourceFinder("META-INF/");
* List appProps = finder.findAvailableProperties("app.properties");
*
* @param uri
* @return
* @throws IOException if classLoader.getResources throws an exception
*/
public List findAvailableProperties(String uri) throws IOException {
resourcesNotLoaded.clear();
String fulluri = path + uri;
List properties = new ArrayList();
Enumeration resources = getResources(fulluri);
while (resources.hasMoreElements()) {
URL url = resources.nextElement();
try {
Properties props = loadProperties(url);
properties.add(props);
} catch (Exception notAvailable) {
resourcesNotLoaded.add(url.toExternalForm());
}
}
return properties;
}
/**
* Finds the corresponding resources and reads them in as a properties files
*
* Any URL that cannot be read in as a properties file will cause an exception to be thrown.
*
* Example classpath:
*
* META-INF/jdbcDrivers/oracle.properties
* META-INF/jdbcDrivers/mysql.props
* META-INF/jdbcDrivers/derby
*
* ResourceFinder finder = new ResourceFinder("META-INF/");
* List driversList = finder.findAvailableProperties("jdbcDrivers");
* Properties oracleProps = driversList.get("oracle.properties");
* Properties mysqlProps = driversList.get("mysql.props");
* Properties derbyProps = driversList.get("derby");
*
* @param uri
* @return
* @throws IOException if the URL cannot be read or is not in properties file format
*/
public Map mapAllProperties(String uri) throws IOException {
Map propertiesMap = new HashMap();
Map map = getResourcesMap(uri);
for (Map.Entry entry : map.entrySet()) {
String string = entry.getKey();
URL url = entry.getValue();
Properties properties = loadProperties(url);
propertiesMap.put(string, properties);
}
return propertiesMap;
}
/**
* Finds the corresponding resources and reads them in as a properties files
*
* Any URL that cannot be read in as a properties file will be added to the
* 'resourcesNotLoaded' collection.
*
* Example classpath:
*
* META-INF/jdbcDrivers/oracle.properties
* META-INF/jdbcDrivers/mysql.props
* META-INF/jdbcDrivers/derby
*
* ResourceFinder finder = new ResourceFinder("META-INF/");
* List driversList = finder.findAvailableProperties("jdbcDrivers");
* Properties oracleProps = driversList.get("oracle.properties");
* Properties mysqlProps = driversList.get("mysql.props");
* Properties derbyProps = driversList.get("derby");
*
* @param uri
* @return
* @throws IOException if classLoader.getResources throws an exception
*/
public Map mapAvailableProperties(String uri) throws IOException {
resourcesNotLoaded.clear();
Map propertiesMap = new HashMap();
Map map = getResourcesMap(uri);
for (Map.Entry entry : map.entrySet()) {
String string = entry.getKey();
URL url = entry.getValue();
try {
Properties properties = loadProperties(url);
propertiesMap.put(string, properties);
} catch (Exception notAvailable) {
resourcesNotLoaded.add(url.toExternalForm());
}
}
return propertiesMap;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
//
// Map Resources
//
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
public Map getResourcesMap(String uri) throws IOException {
String basePath = path + uri;
Map resources = new HashMap();
if (!basePath.endsWith("/")) {
basePath += "/";
}
Enumeration urls = getResources(basePath);
while (urls.hasMoreElements()) {
URL location = urls.nextElement();
try {
if ("jar".equals(location.getProtocol())) {
readJarEntries(location, basePath, resources);
} else if ("file".equals(location.getProtocol())) {
readDirectoryEntries(location, resources);
}
} catch (Exception e) {
}
}
return resources;
}
/**
* Gets a list of subpckages from jars or dirs
*/
public Set findPackages(String uri) throws IOException {
String basePath = path + uri;
Set resources = new HashSet();
if (!basePath.endsWith("/")) {
basePath += "/";
}
Enumeration urls = getResources(basePath);
while (urls.hasMoreElements()) {
URL location = urls.nextElement();
try {
if ("jar".equals(location.getProtocol())) {
readJarDirectoryEntries(location, basePath, resources);
} else if ("file".equals(location.getProtocol())) {
readSubDirectories(new File(location.toURI()), uri, resources);
}
} catch (Exception e) {
}
}
return convertPathsToPackages(resources);
}
/**
* Gets a list of subpckages from jars or dirs
*/
public Map> findPackagesMap(String uri) throws IOException {
String basePath = path + uri;
if (!basePath.endsWith("/")) {
basePath += "/";
}
Enumeration urls = getResources(basePath);
Map> result = new HashMap>();
while (urls.hasMoreElements()) {
URL location = urls.nextElement();
try {
if ("jar".equals(location.getProtocol())) {
Set resources = new HashSet();
readJarDirectoryEntries(location, basePath, resources);
result.put(location, convertPathsToPackages(resources));
} else if ("file".equals(location.getProtocol())) {
Set resources = new HashSet();
readSubDirectories(new File(location.toURI()), uri, resources);
result.put(location, convertPathsToPackages(resources));
}
} catch (Exception e) {
}
}
return result;
}
private Set convertPathsToPackages(Set resources) {
Set packageNames = new HashSet(resources.size());
for(String resource : resources) {
packageNames.add(StringUtils.chomp(StringUtils.replace(resource, "/", "."), "."));
}
return packageNames;
}
private static void readDirectoryEntries(URL location, Map resources) throws MalformedURLException {
File dir = new File(URLDecoder.decode(location.getPath()));
if (dir.isDirectory()) {
File[] files = dir.listFiles();
for (File file : files) {
if (!file.isDirectory()) {
String name = file.getName();
URL url = file.toURL();
resources.put(name, url);
}
}
}
}
/**
* Reads subdirectories of a file. The output is a list of subdirectories, relative to the basepath
*/
private static void readSubDirectories(File dir, String basePath, Set resources) throws MalformedURLException {
if (dir.isDirectory()) {
File[] files = dir.listFiles();
for (File file : files) {
if (file.isDirectory()) {
String name = file.getName();
String subName = StringUtils.chomp(basePath, "/") + "/" + name;
resources.add(subName);
readSubDirectories(file, subName, resources);
}
}
}
}
private static void readJarEntries(URL location, String basePath, Map resources) throws IOException {
JarURLConnection conn = (JarURLConnection) location.openConnection();
JarFile jarfile = null;
jarfile = conn.getJarFile();
Enumeration entries = jarfile.entries();
while (entries != null && entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
String name = entry.getName();
if (entry.isDirectory() || !name.startsWith(basePath) || name.length() == basePath.length()) {
continue;
}
name = name.substring(basePath.length());
if (name.contains("/")) {
continue;
}
URL resource = new URL(location, name);
resources.put(name, resource);
}
}
//read directories in the jar that start with the basePath
private static void readJarDirectoryEntries(URL location, String basePath, Set resources) throws IOException {
JarURLConnection conn = (JarURLConnection) location.openConnection();
JarFile jarfile = null;
jarfile = conn.getJarFile();
Enumeration entries = jarfile.entries();
while (entries != null && entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
String name = entry.getName();
if (entry.isDirectory() && StringUtils.startsWith(name, basePath)) {
resources.add(name);
}
}
}
private Properties loadProperties(URL resource) throws IOException {
InputStream in = resource.openStream();
BufferedInputStream reader = null;
try {
reader = new BufferedInputStream(in);
Properties properties = new Properties();
properties.load(reader);
return properties;
} finally {
try {
in.close();
reader.close();
} catch (Exception e) {
}
}
}
private String readContents(URL resource) throws IOException {
InputStream in = resource.openStream();
BufferedInputStream reader = null;
StringBuilder sb = new StringBuilder();
try {
reader = new BufferedInputStream(in);
int b = reader.read();
while (b != -1) {
sb.append((char) b);
b = reader.read();
}
return sb.toString().trim();
} finally {
try {
in.close();
reader.close();
} catch (Exception e) {
}
}
}
private URL getResource(String fullUri) {
if (urls == null){
return classLoaderInterface.getResource(fullUri);
}
return findResource(fullUri, urls);
}
private Enumeration getResources(String fulluri) throws IOException {
if (urls == null) {
return classLoaderInterface.getResources(fulluri);
}
Vector resources = new Vector();
for (URL url : urls) {
URL resource = findResource(fulluri, url);
if (resource != null){
resources.add(resource);
}
}
return resources.elements();
}
private URL findResource(String resourceName, URL... search) {
for (int i = 0; i < search.length; i++) {
URL currentUrl = search[i];
if (currentUrl == null) {
continue;
}
JarFile jarFile = null;
try {
String protocol = currentUrl.getProtocol();
if ("jar".equals(protocol)) {
/*
* If the connection for currentUrl or resURL is
* used, getJarFile() will throw an exception if the
* entry doesn't exist.
*/
URL jarURL = ((JarURLConnection) currentUrl.openConnection()).getJarFileURL();
try {
JarURLConnection juc = (JarURLConnection) new URL("jar", "", jarURL.toExternalForm() + "!/").openConnection();
jarFile = juc.getJarFile();
} catch (IOException e) {
// Don't look for this jar file again
search[i] = null;
throw e;
}
String entryName;
if (currentUrl.getFile().endsWith("!/")) {
entryName = resourceName;
} else {
String file = currentUrl.getFile();
int sepIdx = file.lastIndexOf("!/");
if (sepIdx == -1) {
// Invalid URL, don't look here again
search[i] = null;
continue;
}
sepIdx += 2;
StringBuilder sb = new StringBuilder(file.length() - sepIdx + resourceName.length());
sb.append(file.substring(sepIdx));
sb.append(resourceName);
entryName = sb.toString();
}
if ("META-INF/".equals(entryName) && jarFile.getEntry("META-INF/MANIFEST.MF") != null){
return targetURL(currentUrl, "META-INF/MANIFEST.MF");
}
if (jarFile.getEntry(entryName) != null) {
return targetURL(currentUrl, resourceName);
}
} else if ("file".equals(protocol)) {
String baseFile = currentUrl.getFile();
String host = currentUrl.getHost();
int hostLength = 0;
if (host != null) {
hostLength = host.length();
}
StringBuilder buf = new StringBuilder(2 + hostLength + baseFile.length() + resourceName.length());
if (hostLength > 0) {
buf.append("//").append(host);
}
// baseFile always ends with '/'
buf.append(baseFile);
String fixedResName = resourceName;
// Do not create a UNC path, i.e. \\host
while (fixedResName.startsWith("/") || fixedResName.startsWith("\\")) {
fixedResName = fixedResName.substring(1);
}
buf.append(fixedResName);
String filename = buf.toString();
File file = new File(filename);
File file2 = new File(URLDecoder.decode(filename));
if (file.exists() || file2.exists()) {
return targetURL(currentUrl, fixedResName);
}
} else {
URL resourceURL = targetURL(currentUrl, resourceName);
URLConnection urlConnection = resourceURL.openConnection();
try {
urlConnection.getInputStream().close();
} catch (SecurityException e) {
return null;
}
// HTTP can return a stream on a non-existent file
// So check for the return code;
if (!"http".equals(resourceURL.getProtocol())) {
return resourceURL;
}
int code = ((HttpURLConnection) urlConnection).getResponseCode();
if (code >= 200 && code < 300) {
return resourceURL;
}
}
} catch (MalformedURLException e) {
// Keep iterating through the URL list
} catch (IOException e) {
} catch (SecurityException e) {
}
}
return null;
}
private URL targetURL(URL base, String name) throws MalformedURLException {
StringBuilder sb = new StringBuilder(base.getFile().length() + name.length());
sb.append(base.getFile());
sb.append(name);
String file = sb.toString();
return new URL(base.getProtocol(), base.getHost(), base.getPort(), file, null);
}
}