General defensiveness about the bootstrap ClassLoader (i.e. null ClassLoader)
Issue: SPR-11721
This commit is contained in:
@@ -34,6 +34,7 @@ import java.util.TreeSet;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.LinkedCaseInsensitiveMap;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
@@ -73,8 +74,8 @@ public abstract class CollectionFactory {
|
||||
// New Java 6 collection interfaces
|
||||
ClassLoader cl = CollectionFactory.class.getClassLoader();
|
||||
try {
|
||||
navigableSetClass = cl.loadClass("java.util.NavigableSet");
|
||||
navigableMapClass = cl.loadClass("java.util.NavigableMap");
|
||||
navigableSetClass = ClassUtils.forName("java.util.NavigableSet", cl);
|
||||
navigableMapClass = ClassUtils.forName("java.util.NavigableMap", cl);
|
||||
approximableCollectionTypes.add(navigableSetClass);
|
||||
approximableMapTypes.add(navigableMapClass);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -50,9 +50,9 @@ public class ClassPathResource extends AbstractFileResolvingResource {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new ClassPathResource for ClassLoader usage.
|
||||
* A leading slash will be removed, as the ClassLoader
|
||||
* resource access methods will not accept it.
|
||||
* Create a new {@code ClassPathResource} for {@code ClassLoader} usage.
|
||||
* A leading slash will be removed, as the ClassLoader resource access
|
||||
* methods will not accept it.
|
||||
* <p>The thread context class loader will be used for
|
||||
* loading the resource.
|
||||
* @param path the absolute path within the class path
|
||||
@@ -64,9 +64,9 @@ public class ClassPathResource extends AbstractFileResolvingResource {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ClassPathResource for ClassLoader usage.
|
||||
* A leading slash will be removed, as the ClassLoader
|
||||
* resource access methods will not accept it.
|
||||
* Create a new {@code ClassPathResource} for {@code ClassLoader} usage.
|
||||
* A leading slash will be removed, as the ClassLoader resource access
|
||||
* methods will not accept it.
|
||||
* @param path the absolute path within the classpath
|
||||
* @param classLoader the class loader to load the resource with,
|
||||
* or {@code null} for the thread context class loader
|
||||
@@ -83,9 +83,9 @@ public class ClassPathResource extends AbstractFileResolvingResource {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ClassPathResource for Class usage.
|
||||
* The path can be relative to the given class,
|
||||
* or absolute within the classpath via a leading slash.
|
||||
* Create a new {@code ClassPathResource} for {@code Class} usage.
|
||||
* The path can be relative to the given class, or absolute within
|
||||
* the classpath via a leading slash.
|
||||
* @param path relative or absolute path within the class path
|
||||
* @param clazz the class to load resources with
|
||||
* @see java.lang.Class#getResourceAsStream
|
||||
@@ -97,8 +97,8 @@ public class ClassPathResource extends AbstractFileResolvingResource {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ClassPathResource with optional ClassLoader and Class.
|
||||
* Only for internal usage.
|
||||
* Create a new {@code ClassPathResource} with optional {@code ClassLoader}
|
||||
* and {@code Class}. Only for internal usage.
|
||||
* @param path relative or absolute path within the classpath
|
||||
* @param classLoader the class loader to load the resource with, if any
|
||||
* @param clazz the class to load resources with, if any
|
||||
@@ -109,6 +109,7 @@ public class ClassPathResource extends AbstractFileResolvingResource {
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the path for this resource (as resource path within the class path).
|
||||
*/
|
||||
@@ -120,9 +121,10 @@ public class ClassPathResource extends AbstractFileResolvingResource {
|
||||
* Return the ClassLoader that this resource will be obtained from.
|
||||
*/
|
||||
public final ClassLoader getClassLoader() {
|
||||
return (this.classLoader != null ? this.classLoader : this.clazz.getClassLoader());
|
||||
return (this.clazz != null ? this.clazz.getClassLoader() : this.classLoader);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This implementation checks for the resolution of a resource URL.
|
||||
* @see java.lang.ClassLoader#getResource(String)
|
||||
@@ -130,14 +132,23 @@ public class ClassPathResource extends AbstractFileResolvingResource {
|
||||
*/
|
||||
@Override
|
||||
public boolean exists() {
|
||||
URL url;
|
||||
return (resolveURL() != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a URL for the underlying class path resource.
|
||||
* @return the resolved URL, or {@code null} if not resolvable
|
||||
*/
|
||||
protected URL resolveURL() {
|
||||
if (this.clazz != null) {
|
||||
url = this.clazz.getResource(this.path);
|
||||
return this.clazz.getResource(this.path);
|
||||
}
|
||||
else if (this.classLoader != null) {
|
||||
return this.classLoader.getResource(this.path);
|
||||
}
|
||||
else {
|
||||
url = this.classLoader.getResource(this.path);
|
||||
return ClassLoader.getSystemResource(this.path);
|
||||
}
|
||||
return (url != null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,9 +161,12 @@ public class ClassPathResource extends AbstractFileResolvingResource {
|
||||
if (this.clazz != null) {
|
||||
is = this.clazz.getResourceAsStream(this.path);
|
||||
}
|
||||
else {
|
||||
else if (this.classLoader != null) {
|
||||
is = this.classLoader.getResourceAsStream(this.path);
|
||||
}
|
||||
else {
|
||||
is = ClassLoader.getSystemResourceAsStream(this.path);
|
||||
}
|
||||
if (is == null) {
|
||||
throw new FileNotFoundException(getDescription() + " cannot be opened because it does not exist");
|
||||
}
|
||||
@@ -160,19 +174,14 @@ public class ClassPathResource extends AbstractFileResolvingResource {
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation returns a URL for the underlying class path resource.
|
||||
* This implementation returns a URL for the underlying class path resource,
|
||||
* if available.
|
||||
* @see java.lang.ClassLoader#getResource(String)
|
||||
* @see java.lang.Class#getResource(String)
|
||||
*/
|
||||
@Override
|
||||
public URL getURL() throws IOException {
|
||||
URL url;
|
||||
if (this.clazz != null) {
|
||||
url = this.clazz.getResource(this.path);
|
||||
}
|
||||
else {
|
||||
url = this.classLoader.getResource(this.path);
|
||||
}
|
||||
URL url = resolveURL();
|
||||
if (url == null) {
|
||||
throw new FileNotFoundException(getDescription() + " cannot be resolved to URL because it does not exist");
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -70,7 +70,9 @@ public interface ResourceLoader {
|
||||
* <p>Clients which need to access the ClassLoader directly can do so
|
||||
* in a uniform manner with the ResourceLoader, rather than relying
|
||||
* on the thread context ClassLoader.
|
||||
* @return the ClassLoader (never {@code null})
|
||||
* @return the ClassLoader (only {@code null} if even the system
|
||||
* ClassLoader isn't accessible)
|
||||
* @see org.springframework.util.ClassUtils#getDefaultClassLoader()
|
||||
*/
|
||||
ClassLoader getClassLoader();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -42,6 +42,7 @@ import org.springframework.core.io.UrlResource;
|
||||
import org.springframework.core.io.VfsResource;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
@@ -72,7 +73,7 @@ import org.springframework.util.StringUtils;
|
||||
* <p><b>Ant-style Patterns:</b>
|
||||
*
|
||||
* <p>When the path location contains an Ant-style pattern, e.g.:
|
||||
* <pre>
|
||||
* <pre class="code">
|
||||
* /WEB-INF/*-context.xml
|
||||
* com/mycompany/**/applicationContext.xml
|
||||
* file:C:/some/path/*-context.xml
|
||||
@@ -143,11 +144,15 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* <p><b>WARNING:</b> Ant-style patterns with "classpath:" resources are not
|
||||
* guaranteed to find matching resources if the root package to search is available
|
||||
* in multiple class path locations. This is because a resource such as<pre>
|
||||
* in multiple class path locations. This is because a resource such as
|
||||
* <pre class="code">
|
||||
* com/mycompany/package1/service-context.xml
|
||||
* </pre>may be in only one location, but when a path such as<pre>
|
||||
* </pre>
|
||||
* may be in only one location, but when a path such as
|
||||
* <pre class="code">
|
||||
* classpath:com/mycompany/**/service-context.xml
|
||||
* </pre>is used to try to resolve it, the resolver will work off the (first) URL
|
||||
* </pre>
|
||||
* is used to try to resolve it, the resolver will work off the (first) URL
|
||||
* returned by {@code getResource("com/mycompany");}. If this base package
|
||||
* node exists in multiple classloader locations, the actual end resource may
|
||||
* not be underneath. Therefore, preferably, use "{@code classpath*:}" with the same
|
||||
@@ -171,10 +176,10 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
private static Method equinoxResolveMethod;
|
||||
|
||||
static {
|
||||
// Detect Equinox OSGi (e.g. on WebSphere 6.1)
|
||||
try {
|
||||
Class<?> fileLocatorClass = PathMatchingResourcePatternResolver.class.getClassLoader().loadClass(
|
||||
"org.eclipse.core.runtime.FileLocator");
|
||||
// Detect Equinox OSGi (e.g. on WebSphere 6.1)
|
||||
Class<?> fileLocatorClass = ClassUtils.forName("org.eclipse.core.runtime.FileLocator",
|
||||
PathMatchingResourcePatternResolver.class.getClassLoader());
|
||||
equinoxResolveMethod = fileLocatorClass.getMethod("resolve", URL.class);
|
||||
logger.debug("Found Equinox FileLocator for OSGi bundle URL resolution");
|
||||
}
|
||||
@@ -198,17 +203,6 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
this.resourceLoader = new DefaultResourceLoader();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new PathMatchingResourcePatternResolver with a DefaultResourceLoader.
|
||||
* @param classLoader the ClassLoader to load classpath resources with,
|
||||
* or {@code null} for using the thread context class loader
|
||||
* at the time of actual resource access
|
||||
* @see org.springframework.core.io.DefaultResourceLoader
|
||||
*/
|
||||
public PathMatchingResourcePatternResolver(ClassLoader classLoader) {
|
||||
this.resourceLoader = new DefaultResourceLoader(classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new PathMatchingResourcePatternResolver.
|
||||
* <p>ClassLoader access will happen via the thread context class loader.
|
||||
@@ -220,6 +214,18 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
this.resourceLoader = resourceLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new PathMatchingResourcePatternResolver with a DefaultResourceLoader.
|
||||
* @param classLoader the ClassLoader to load classpath resources with,
|
||||
* or {@code null} for using the thread context class loader
|
||||
* at the time of actual resource access
|
||||
* @see org.springframework.core.io.DefaultResourceLoader
|
||||
*/
|
||||
public PathMatchingResourcePatternResolver(ClassLoader classLoader) {
|
||||
this.resourceLoader = new DefaultResourceLoader(classLoader);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the ResourceLoader that this pattern resolver works with.
|
||||
*/
|
||||
@@ -227,10 +233,6 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
return this.resourceLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ClassLoader that this pattern resolver works with
|
||||
* (never {@code null}).
|
||||
*/
|
||||
public ClassLoader getClassLoader() {
|
||||
return getResourceLoader().getClassLoader();
|
||||
}
|
||||
@@ -298,7 +300,8 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
if (path.startsWith("/")) {
|
||||
path = path.substring(1);
|
||||
}
|
||||
Enumeration<URL> resourceUrls = getClassLoader().getResources(path);
|
||||
ClassLoader cl = getClassLoader();
|
||||
Enumeration<URL> resourceUrls = (cl != null ? cl.getResources(path) : ClassLoader.getSystemResources(path));
|
||||
Set<Resource> result = new LinkedHashSet<Resource>(16);
|
||||
while (resourceUrls.hasMoreElements()) {
|
||||
URL url = resourceUrls.nextElement();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -170,14 +170,15 @@ public abstract class PropertiesLoaderUtils {
|
||||
*/
|
||||
public static Properties loadAllProperties(String resourceName, ClassLoader classLoader) throws IOException {
|
||||
Assert.notNull(resourceName, "Resource name must not be null");
|
||||
ClassLoader clToUse = classLoader;
|
||||
if (clToUse == null) {
|
||||
clToUse = ClassUtils.getDefaultClassLoader();
|
||||
ClassLoader classLoaderToUse = classLoader;
|
||||
if (classLoaderToUse == null) {
|
||||
classLoaderToUse = ClassUtils.getDefaultClassLoader();
|
||||
}
|
||||
Enumeration<URL> urls = (classLoaderToUse != null ? classLoaderToUse.getResources(resourceName) :
|
||||
ClassLoader.getSystemResources(resourceName));
|
||||
Properties props = new Properties();
|
||||
Enumeration urls = clToUse.getResources(resourceName);
|
||||
while (urls.hasMoreElements()) {
|
||||
URL url = (URL) urls.nextElement();
|
||||
URL url = urls.nextElement();
|
||||
URLConnection con = url.openConnection();
|
||||
ResourceUtils.useCachesIfNecessary(con);
|
||||
InputStream is = con.getInputStream();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -67,16 +67,17 @@ public abstract class SpringFactoriesLoader {
|
||||
*/
|
||||
public static <T> List<T> loadFactories(Class<T> factoryClass, ClassLoader classLoader) {
|
||||
Assert.notNull(factoryClass, "'factoryClass' must not be null");
|
||||
if (classLoader == null) {
|
||||
classLoader = SpringFactoriesLoader.class.getClassLoader();
|
||||
ClassLoader classLoaderToUse = classLoader;
|
||||
if (classLoaderToUse == null) {
|
||||
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
|
||||
}
|
||||
List<String> factoryNames = loadFactoryNames(factoryClass, classLoader);
|
||||
List<String> factoryNames = loadFactoryNames(factoryClass, classLoaderToUse);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Loaded [" + factoryClass.getName() + "] names: " + factoryNames);
|
||||
}
|
||||
List<T> result = new ArrayList<T>(factoryNames.size());
|
||||
for (String factoryName : factoryNames) {
|
||||
result.add(instantiateFactory(factoryName, factoryClass, classLoader));
|
||||
result.add(instantiateFactory(factoryName, factoryClass, classLoaderToUse));
|
||||
}
|
||||
OrderComparator.sort(result);
|
||||
return result;
|
||||
@@ -85,8 +86,9 @@ public abstract class SpringFactoriesLoader {
|
||||
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
|
||||
String factoryClassName = factoryClass.getName();
|
||||
try {
|
||||
Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
|
||||
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
|
||||
List<String> result = new ArrayList<String>();
|
||||
Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
|
||||
while (urls.hasMoreElements()) {
|
||||
URL url = urls.nextElement();
|
||||
Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.core.type.filter;
|
||||
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* A simple filter which matches classes that are assignable to a given type.
|
||||
*
|
||||
@@ -26,14 +28,14 @@ package org.springframework.core.type.filter;
|
||||
*/
|
||||
public class AssignableTypeFilter extends AbstractTypeHierarchyTraversingFilter {
|
||||
|
||||
private final Class targetType;
|
||||
private final Class<?> targetType;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new AssignableTypeFilter for the given type.
|
||||
* @param targetType the type to match
|
||||
*/
|
||||
public AssignableTypeFilter(Class targetType) {
|
||||
public AssignableTypeFilter(Class<?> targetType) {
|
||||
super(true, true);
|
||||
this.targetType = targetType;
|
||||
}
|
||||
@@ -59,15 +61,15 @@ public class AssignableTypeFilter extends AbstractTypeHierarchyTraversingFilter
|
||||
return true;
|
||||
}
|
||||
else if (Object.class.getName().equals(typeName)) {
|
||||
return Boolean.FALSE;
|
||||
return false;
|
||||
}
|
||||
else if (typeName.startsWith("java.")) {
|
||||
else if (typeName.startsWith("java")) {
|
||||
try {
|
||||
Class clazz = getClass().getClassLoader().loadClass(typeName);
|
||||
return Boolean.valueOf(this.targetType.isAssignableFrom(clazz));
|
||||
Class<?> clazz = ClassUtils.forName(typeName, getClass().getClassLoader());
|
||||
return this.targetType.isAssignableFrom(clazz);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// Class not found - can't determine a match that way.
|
||||
catch (Throwable ex) {
|
||||
// Class not regularly loadable - can't determine a match that way.
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -142,12 +142,14 @@ public abstract class ClassUtils {
|
||||
* ClassLoader, if available; the ClassLoader that loaded the ClassUtils
|
||||
* class will be used as fallback.
|
||||
* <p>Call this method if you intend to use the thread context ClassLoader
|
||||
* in a scenario where you absolutely need a non-null ClassLoader reference:
|
||||
* in a scenario where you clearly prefer a non-null ClassLoader reference:
|
||||
* for example, for class path resource loading (but not necessarily for
|
||||
* {@code Class.forName}, which accepts a {@code null} ClassLoader
|
||||
* reference as well).
|
||||
* @return the default ClassLoader (never {@code null})
|
||||
* @return the default ClassLoader (only {@code null} if even the system
|
||||
* ClassLoader isn't accessible)
|
||||
* @see Thread#getContextClassLoader()
|
||||
* @see ClassLoader#getSystemClassLoader()
|
||||
*/
|
||||
public static ClassLoader getDefaultClassLoader() {
|
||||
ClassLoader cl = null;
|
||||
@@ -155,11 +157,20 @@ public abstract class ClassUtils {
|
||||
cl = Thread.currentThread().getContextClassLoader();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// Cannot access thread context ClassLoader - falling back to system class loader...
|
||||
// Cannot access thread context ClassLoader - falling back...
|
||||
}
|
||||
if (cl == null) {
|
||||
// No thread context class loader -> use class loader of this class.
|
||||
cl = ClassUtils.class.getClassLoader();
|
||||
if (cl == null) {
|
||||
// getClassLoader() returning null indicates the bootstrap ClassLoader
|
||||
try {
|
||||
cl = ClassLoader.getSystemClassLoader();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// Cannot access system ClassLoader - oh well, maybe the caller can live with null...
|
||||
}
|
||||
}
|
||||
}
|
||||
return cl;
|
||||
}
|
||||
@@ -247,19 +258,19 @@ public abstract class ClassUtils {
|
||||
return Array.newInstance(elementClass, 0).getClass();
|
||||
}
|
||||
|
||||
ClassLoader classLoaderToUse = classLoader;
|
||||
if (classLoaderToUse == null) {
|
||||
classLoaderToUse = getDefaultClassLoader();
|
||||
ClassLoader clToUse = classLoader;
|
||||
if (clToUse == null) {
|
||||
clToUse = getDefaultClassLoader();
|
||||
}
|
||||
try {
|
||||
return classLoaderToUse.loadClass(name);
|
||||
return (clToUse != null ? clToUse.loadClass(name) : Class.forName(name));
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
int lastDotIndex = name.lastIndexOf('.');
|
||||
if (lastDotIndex != -1) {
|
||||
String innerClassName = name.substring(0, lastDotIndex) + '$' + name.substring(lastDotIndex + 1);
|
||||
try {
|
||||
return classLoaderToUse.loadClass(innerClassName);
|
||||
return (clToUse != null ? clToUse.loadClass(innerClassName) : Class.forName(innerClassName));
|
||||
}
|
||||
catch (ClassNotFoundException ex2) {
|
||||
// swallow - let original exception get through
|
||||
|
||||
@@ -119,7 +119,8 @@ public abstract class ResourceUtils {
|
||||
Assert.notNull(resourceLocation, "Resource location must not be null");
|
||||
if (resourceLocation.startsWith(CLASSPATH_URL_PREFIX)) {
|
||||
String path = resourceLocation.substring(CLASSPATH_URL_PREFIX.length());
|
||||
URL url = ClassUtils.getDefaultClassLoader().getResource(path);
|
||||
ClassLoader cl = ClassUtils.getDefaultClassLoader();
|
||||
URL url = (cl != null ? cl.getResource(path) : ClassLoader.getSystemResource(path));
|
||||
if (url == null) {
|
||||
String description = "class path resource [" + path + "]";
|
||||
throw new FileNotFoundException(
|
||||
@@ -159,7 +160,8 @@ public abstract class ResourceUtils {
|
||||
if (resourceLocation.startsWith(CLASSPATH_URL_PREFIX)) {
|
||||
String path = resourceLocation.substring(CLASSPATH_URL_PREFIX.length());
|
||||
String description = "class path resource [" + path + "]";
|
||||
URL url = ClassUtils.getDefaultClassLoader().getResource(path);
|
||||
ClassLoader cl = ClassUtils.getDefaultClassLoader();
|
||||
URL url = (cl != null ? cl.getResource(path) : ClassLoader.getSystemResource(path));
|
||||
if (url == null) {
|
||||
throw new FileNotFoundException(
|
||||
description + " cannot be resolved to absolute file path " +
|
||||
|
||||
Reference in New Issue
Block a user