com.opensymphony.xwork2.util.ClassLoaderUtil 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.
/*
* Copyright (c) 2002-2003 by OpenSymphony
* All rights reserved.
*/
package com.opensymphony.xwork2.util;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;
/**
* This class is extremely useful for loading resources and classes in a fault tolerant manner
* that works across different applications servers.
*
* It has come out of many months of frustrating use of multiple application servers at Atlassian,
* please don't change things unless you're sure they're not going to break in one server or another!
*
* It was brought in from oscore trunk revision 147.
*
* @author $Author: hani $
* @version $Revision: 117 $
*/
public class ClassLoaderUtil {
//~ Methods ////////////////////////////////////////////////////////////////
/**
* Load all resources with a given name, potentially aggregating all results
* from the searched classloaders. If no results are found, the resource name
* is prepended by '/' and tried again.
*
* This method will try to load the resources using the following methods (in order):
*
* - From Thread.currentThread().getContextClassLoader()
*
- From ClassLoaderUtil.class.getClassLoader()
*
- callingClass.getClassLoader()
*
*
* @param resourceName The name of the resources to load
* @param callingClass The Class object of the calling object
*/
public static Iterator getResources(String resourceName, Class callingClass, boolean aggregate) throws IOException {
AggregateIterator iterator = new AggregateIterator();
iterator.addEnumeration(Thread.currentThread().getContextClassLoader().getResources(resourceName));
if (!iterator.hasNext() || aggregate) {
iterator.addEnumeration(ClassLoaderUtil.class.getClassLoader().getResources(resourceName));
}
if (!iterator.hasNext() || aggregate) {
ClassLoader cl = callingClass.getClassLoader();
if (cl != null) {
iterator.addEnumeration(cl.getResources(resourceName));
}
}
if (!iterator.hasNext() && (resourceName != null) && (resourceName.charAt(0) != '/')) {
return getResources('/' + resourceName, callingClass, aggregate);
}
return iterator;
}
/**
* Load a given resource.
*
* This method will try to load the resource using the following methods (in order):
*
* - From Thread.currentThread().getContextClassLoader()
*
- From ClassLoaderUtil.class.getClassLoader()
*
- callingClass.getClassLoader()
*
*
* @param resourceName The name IllegalStateException("Unable to call ")of the resource to load
* @param callingClass The Class object of the calling object
*/
public static URL getResource(String resourceName, Class callingClass) {
URL url = Thread.currentThread().getContextClassLoader().getResource(resourceName);
if (url == null) {
url = ClassLoaderUtil.class.getClassLoader().getResource(resourceName);
}
if (url == null) {
ClassLoader cl = callingClass.getClassLoader();
if (cl != null) {
url = cl.getResource(resourceName);
}
}
if ((url == null) && (resourceName != null) && (resourceName.charAt(0) != '/')) {
return getResource('/' + resourceName, callingClass);
}
return url;
}
/**
* This is a convenience method to load a resource as a stream.
*
* The algorithm used to find the resource is given in getResource()
*
* @param resourceName The name of the resource to load
* @param callingClass The Class object of the calling object
*/
public static InputStream getResourceAsStream(String resourceName, Class callingClass) {
URL url = getResource(resourceName, callingClass);
try {
return (url != null) ? url.openStream() : null;
} catch (IOException e) {
return null;
}
}
/**
* Load a class with a given name.
*
* It will try to load the class in the following order:
*
* - From Thread.currentThread().getContextClassLoader()
*
- Using the basic Class.forName()
*
- From ClassLoaderUtil.class.getClassLoader()
*
- From the callingClass.getClassLoader()
*
*
* @param className The name of the class to load
* @param callingClass The Class object of the calling object
* @throws ClassNotFoundException If the class cannot be found anywhere.
*/
public static Class loadClass(String className, Class callingClass) throws ClassNotFoundException {
try {
return Thread.currentThread().getContextClassLoader().loadClass(className);
} catch (ClassNotFoundException e) {
try {
return Class.forName(className);
} catch (ClassNotFoundException ex) {
try {
return ClassLoaderUtil.class.getClassLoader().loadClass(className);
} catch (ClassNotFoundException exc) {
return callingClass.getClassLoader().loadClass(className);
}
}
}
}
/**
* Aggregates Enumeration instances into one iterator and filters out duplicates. Always keeps one
* ahead of the enumerator to protect against returning duplicates.
*/
protected static class AggregateIterator implements Iterator {
LinkedList> enums = new LinkedList>();
Enumeration cur = null;
E next = null;
Set loaded = new HashSet();
public AggregateIterator addEnumeration(Enumeration e) {
if (e.hasMoreElements()) {
if (cur == null) {
cur = e;
next = e.nextElement();
loaded.add(next);
} else {
enums.add(e);
}
}
return this;
}
public boolean hasNext() {
return (next != null);
}
public E next() {
if (next != null) {
E prev = next;
next = loadNext();
return prev;
} else {
throw new NoSuchElementException();
}
}
private Enumeration determineCurrentEnumeration() {
if (cur != null && !cur.hasMoreElements()) {
if (enums.size() > 0) {
cur = enums.removeLast();
} else {
cur = null;
}
}
return cur;
}
private E loadNext() {
if (determineCurrentEnumeration() != null) {
E tmp = cur.nextElement();
while (loaded.contains(tmp)) {
tmp = loadNext();
if (tmp == null) {
break;
}
}
if (tmp != null) {
loaded.add(tmp);
}
return tmp;
}
return null;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
}