blob: f282a22c434630e924c892e5ab844c69300a7b14 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.wss4j.common.util;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.AccessController;
import java.security.PrivilegedAction;
import org.apache.wss4j.common.ext.WSSecurityException;
/**
* Load resources (or images) from various sources.
* <p/>
*/
public final class Loader {
private static final org.slf4j.Logger LOG =
org.slf4j.LoggerFactory.getLogger(Loader.class);
private Loader() {
// complete
}
public static InputStream loadInputStream(ClassLoader loader, String resource)
throws WSSecurityException, IOException {
InputStream is = null;
if (resource != null) {
URL url = null;
// First see if it's a URL
try {
url = new URL(resource);
} catch (MalformedURLException ex) { //NOPMD
// skip
}
// If not a URL, then try to load the resource
if (url == null) {
url = Loader.getResource(loader, resource);
}
if (url != null) {
is = url.openStream();
}
//
// If we don't find it, then look on the file system.
//
if (is == null) {
try {
is = Files.newInputStream(Paths.get(resource));
} catch (Exception e) {
LOG.debug(e.getMessage(), e);
throw new WSSecurityException(
WSSecurityException.ErrorCode.FAILURE, e, "resourceNotFound", new Object[] {resource}
);
}
}
}
return is;
}
/**
* This method will search for <code>resource</code> in different
* places. The search order is as follows:
* <ol>
* <p><li>Search for <code>resource</code> using the thread context
* class loader under Java2.
* <p><li>Try one last time with
* <code>ClassLoader.getSystemResource(resource)</code>, that is is
* using the system class loader in JDK 1.2 and virtual machine's
* built-in class loader in JDK 1.1.
* </ol>
* <p/>
*
* @param resource
* @return the url to the resource or null if not found
*/
public static URL getResource(String resource) {
URL url = null;
try {
ClassLoader classLoader = getTCL();
if (classLoader != null) {
if (LOG.isDebugEnabled()) {
LOG.debug("Trying to find [" + resource + "] using " + classLoader + " class loader.");
}
url = classLoader.getResource(resource);
if (url == null && resource.startsWith("/")) {
//certain classloaders need it without the leading /
url = classLoader.getResource(resource.substring(1));
}
if (url != null) {
return url;
}
}
} catch (Exception e) {
LOG.warn("Caught Exception while in Loader.getResource. This may be innocuous.", e);
}
ClassLoader cluClassloader = Loader.class.getClassLoader();
if (cluClassloader == null) {
cluClassloader = ClassLoader.getSystemClassLoader();
}
url = cluClassloader.getResource(resource);
if (url == null && resource.startsWith("/")) {
//certain classloaders need it without the leading /
url = cluClassloader.getResource(resource.substring(1));
}
if (url != null) {
return url;
}
// Last ditch attempt: get the resource from the class path. It
// may be the case that clazz was loaded by the Extension class
// loader which the parent of the system class loader. Hence the
// code below.
LOG.debug("Trying to find [{}] using ClassLoader.getSystemResource().", resource);
return ClassLoader.getSystemResource(resource);
}
/**
* This method will search for <code>resource</code> in different
* places. The search order is as follows:
* <ol>
* <p><li>Search for <code>resource</code> using the supplied class loader.
* If that fails, search for <code>resource</code> using the thread context
* class loader.
* <p><li>Try one last time with
* <code>ClassLoader.getSystemResource(resource)</code>, that is is
* using the system class loader in JDK 1.2 and virtual machine's
* built-in class loader in JDK 1.1.
* </ol>
* <p/>
*
* @param resource
* @return the url to the resource or null if not found
*/
public static URL getResource(ClassLoader loader, String resource) {
URL url = null;
try {
if (loader != null) {
if (LOG.isDebugEnabled()) {
LOG.debug("Trying to find [" + resource + "] using " + loader + " class loader.");
}
url = loader.getResource(resource);
if (url == null && resource.startsWith("/")) {
//certain classloaders need it without the leading /
url = loader.getResource(resource.substring(1));
}
if (url != null) {
return url;
}
}
} catch (Exception e) {
LOG.warn("Caught Exception while in Loader.getResource. This may be innocuous.", e);
}
return getResource(resource);
}
/**
* This is a convenience method to load a resource as a stream. <p/> The
* algorithm used to find the resource is given in getResource()
*
* @param resourceName The name of the resource to load
*/
public static InputStream getResourceAsStream(String resourceName) {
URL url = getResource(resourceName);
try {
return (url != null) ? url.openStream() : null;
} catch (IOException e) {
LOG.debug(e.getMessage(), e);
return null;
}
}
/**
* Get the Thread context class loader.
* <p/>
*
* @return the Thread context class loader
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
public static ClassLoader getTCL() throws IllegalAccessException, InvocationTargetException {
return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
return Thread.currentThread().getContextClassLoader();
}
});
}
/**
* Get the class loader of the class argument
* <p/>
*
* @return the class loader of the argument
*/
public static ClassLoader getClassLoader(final Class<?> clazz) {
return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
return clazz.getClassLoader();
}
});
}
/**
* Try the specified classloader and then fall back to the loadClass
* <p/>
*
* @param loader
* @param clazz
* @return Class
* @throws ClassNotFoundException
*/
public static Class<?> loadClass(ClassLoader loader, String clazz) throws ClassNotFoundException {
try {
if (loader != null) {
Class<?> c = loader.loadClass(clazz);
if (c != null) {
return c;
}
}
} catch (Exception e) {
LOG.warn(e.getMessage(), e);
}
return loadClass(clazz, true);
}
/**
* Try the specified classloader and then fall back to the loadClass
* <p/>
*
* @param loader
* @param clazz
* @param type
* @return Class
* @throws ClassNotFoundException
*/
public static <T> Class<? extends T> loadClass(ClassLoader loader,
String clazz,
Class<T> type) throws ClassNotFoundException {
try {
if (loader != null) {
Class<?> c = loader.loadClass(clazz);
if (c != null) {
return c.asSubclass(type);
}
}
} catch (Exception e) {
LOG.warn(e.getMessage(), e);
}
return loadClass(clazz, true, type);
}
/**
* If running under JDK 1.2 load the specified class using the
* <code>Thread</code> <code>contextClassLoader</code> if that
* fails try Class.forname.
* <p/>
*
* @param clazz
* @return the class
* @throws ClassNotFoundException
*/
public static Class<?> loadClass(String clazz) throws ClassNotFoundException {
return loadClass(clazz, true);
}
/**
* If running under JDK 1.2 load the specified class using the
* <code>Thread</code> <code>contextClassLoader</code> if that
* fails try Class.forname.
* <p/>
*
* @param clazz
* @param type Type to cast it to
* @return the class
* @throws ClassNotFoundException
*/
public static <T> Class<? extends T> loadClass(String clazz, Class<T> type)
throws ClassNotFoundException {
return loadClass(clazz, true, type);
}
public static <T> Class<? extends T> loadClass(String clazz,
boolean warn,
Class<T> type) throws ClassNotFoundException {
return loadClass(clazz, warn).asSubclass(type);
}
public static Class<?> loadClass(String clazz, boolean warn) throws ClassNotFoundException {
try {
ClassLoader tcl = getTCL();
if (tcl != null) {
Class<?> c = tcl.loadClass(clazz);
if (c != null) {
return c;
}
}
} catch (Exception e) {
if (warn) {
LOG.warn(e.getMessage(), e);
} else {
LOG.debug(e.getMessage(), e);
}
}
return loadClass2(clazz, null);
}
private static Class<?> loadClass2(String className, Class<?> callingClass)
throws ClassNotFoundException {
try {
return Class.forName(className);
} catch (ClassNotFoundException ex) {
try {
if (Loader.class.getClassLoader() != null) {
return Loader.class.getClassLoader().loadClass(className);
}
} catch (ClassNotFoundException exc) {
if (callingClass != null && callingClass.getClassLoader() != null) {
return callingClass.getClassLoader().loadClass(className);
}
}
throw ex;
}
}
}