From 6cb45f714e8d4b6b38501ed6356ced59362d8df2 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Mon, 28 Apr 2014 00:26:18 +0200 Subject: [PATCH] General defensiveness about the bootstrap ClassLoader (i.e. null ClassLoader) Issue: SPR-11721 (cherry picked from commit 59cef3c) --- .../beans/TypeConverterDelegate.java | 8 ++-- .../AutowiredAnnotationBeanPostProcessor.java | 6 +-- ...erAnnotationAutowireCandidateResolver.java | 6 +-- .../support/DefaultListableBeanFactory.java | 4 +- .../support/DisposableBeanAdapter.java | 5 ++- .../annotation/AnnotationConfigUtils.java | 4 +- ...athScanningCandidateComponentProvider.java | 6 +-- .../CommonAnnotationBeanPostProcessor.java | 9 ++-- .../annotation/AsyncAnnotationAdvisor.java | 5 ++- .../PathMatchingResourcePatternResolver.java | 43 ++++++++++--------- .../io/support/PropertiesLoaderUtils.java | 2 +- .../io/support/SpringFactoriesLoader.java | 4 +- .../type/filter/AnnotationTypeFilter.java | 9 ++-- .../type/filter/AssignableTypeFilter.java | 10 +++-- .../spel/support/StandardTypeLocator.java | 6 +-- .../core/SqlRowSetResultSetExtractor.java | 19 ++++---- .../metadata/OracleTableMetaDataProvider.java | 16 ++++--- .../test/context/TestContextManager.java | 35 ++++++++------- .../AbstractTestContextBootstrapper.java | 42 +++++++----------- .../standard/ServerEndpointExporter.java | 12 +++--- 20 files changed, 123 insertions(+), 128 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/TypeConverterDelegate.java b/spring-beans/src/main/java/org/springframework/beans/TypeConverterDelegate.java index 1f904c406ca..d8b3eda2fd1 100644 --- a/spring-beans/src/main/java/org/springframework/beans/TypeConverterDelegate.java +++ b/spring-beans/src/main/java/org/springframework/beans/TypeConverterDelegate.java @@ -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. @@ -289,15 +289,15 @@ class TypeConverterDelegate { if (index > - 1) { String enumType = trimmedValue.substring(0, index); String fieldName = trimmedValue.substring(index + 1); - ClassLoader loader = this.targetObject.getClass().getClassLoader(); + ClassLoader cl = this.targetObject.getClass().getClassLoader(); try { - Class enumValueType = loader.loadClass(enumType); + Class enumValueType = ClassUtils.forName(enumType, cl); Field enumField = enumValueType.getField(fieldName); convertedValue = enumField.get(null); } catch (ClassNotFoundException ex) { if(logger.isTraceEnabled()) { - logger.trace("Enum class [" + enumType + "] cannot be loaded from [" + loader + "]", ex); + logger.trace("Enum class [" + enumType + "] cannot be loaded", ex); } } catch (Throwable ex) { diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java index d366a36e8f8..189a76c81e2 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java @@ -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. @@ -135,9 +135,9 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean public AutowiredAnnotationBeanPostProcessor() { this.autowiredAnnotationTypes.add(Autowired.class); this.autowiredAnnotationTypes.add(Value.class); - ClassLoader cl = AutowiredAnnotationBeanPostProcessor.class.getClassLoader(); try { - this.autowiredAnnotationTypes.add((Class) cl.loadClass("javax.inject.Inject")); + this.autowiredAnnotationTypes.add((Class) + ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader())); logger.info("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring"); } catch (ClassNotFoundException ex) { diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/QualifierAnnotationAutowireCandidateResolver.java b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/QualifierAnnotationAutowireCandidateResolver.java index 89df2d9ebe0..b2bdd5de1e6 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/QualifierAnnotationAutowireCandidateResolver.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/QualifierAnnotationAutowireCandidateResolver.java @@ -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. @@ -66,9 +66,9 @@ public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwa @SuppressWarnings("unchecked") public QualifierAnnotationAutowireCandidateResolver() { this.qualifierTypes.add(Qualifier.class); - ClassLoader cl = QualifierAnnotationAutowireCandidateResolver.class.getClassLoader(); try { - this.qualifierTypes.add((Class) cl.loadClass("javax.inject.Qualifier")); + this.qualifierTypes.add((Class) + ClassUtils.forName("javax.inject.Qualifier", QualifierAnnotationAutowireCandidateResolver.class.getClassLoader())); } catch (ClassNotFoundException ex) { // JSR-330 API not available - simply skip. diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java index 82b97d31005..d7110db5948 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java @@ -107,9 +107,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto private static Class javaxInjectProviderClass = null; static { - ClassLoader cl = DefaultListableBeanFactory.class.getClassLoader(); try { - javaxInjectProviderClass = cl.loadClass("javax.inject.Provider"); + javaxInjectProviderClass = + ClassUtils.forName("javax.inject.Provider", DefaultListableBeanFactory.class.getClassLoader()); } catch (ClassNotFoundException ex) { // JSR-330 API not available - Provider interface simply not supported then. diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java index 9b85f73ae9f..39721647a34 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java @@ -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. @@ -69,7 +69,8 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { static { try { - closeableInterface = DisposableBeanAdapter.class.getClassLoader().loadClass("java.lang.AutoCloseable"); + closeableInterface = ClassUtils.forName("java.lang.AutoCloseable", + DisposableBeanAdapter.class.getClassLoader()); } catch (ClassNotFoundException ex) { closeableInterface = Closeable.class; diff --git a/spring-context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java b/spring-context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java index c876f3d704d..e7d6d8f8ffc 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java @@ -281,8 +281,8 @@ public class AnnotationConfigUtils { if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(); try { - ClassLoader cl = AnnotationConfigUtils.class.getClassLoader(); - def.setBeanClass(cl.loadClass(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME)); + def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, + AnnotationConfigUtils.class.getClassLoader())); } catch (ClassNotFoundException ex) { throw new IllegalStateException( diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ClassPathScanningCandidateComponentProvider.java b/spring-context/src/main/java/org/springframework/context/annotation/ClassPathScanningCandidateComponentProvider.java index c8c0dc15b65..71ebcf03959 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ClassPathScanningCandidateComponentProvider.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ClassPathScanningCandidateComponentProvider.java @@ -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. @@ -238,7 +238,7 @@ public class ClassPathScanningCandidateComponentProvider implements EnvironmentC ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader(); try { this.includeFilters.add(new AnnotationTypeFilter( - ((Class) cl.loadClass("javax.annotation.ManagedBean")), false)); + ((Class) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false)); logger.debug("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning"); } catch (ClassNotFoundException ex) { @@ -246,7 +246,7 @@ public class ClassPathScanningCandidateComponentProvider implements EnvironmentC } try { this.includeFilters.add(new AnnotationTypeFilter( - ((Class) cl.loadClass("javax.inject.Named")), false)); + ((Class) ClassUtils.forName("javax.inject.Named", cl)), false)); logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning"); } catch (ClassNotFoundException ex) { diff --git a/spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java b/spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java index c973a01b08e..3e38a3f4b8e 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java @@ -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. @@ -142,10 +142,10 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean private static Class ejbRefClass = null; static { - ClassLoader cl = CommonAnnotationBeanPostProcessor.class.getClassLoader(); try { @SuppressWarnings("unchecked") - Class clazz = (Class) cl.loadClass("javax.xml.ws.WebServiceRef"); + Class clazz = (Class) + ClassUtils.forName("javax.xml.ws.WebServiceRef", CommonAnnotationBeanPostProcessor.class.getClassLoader()); webServiceRefClass = clazz; } catch (ClassNotFoundException ex) { @@ -153,7 +153,8 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean } try { @SuppressWarnings("unchecked") - Class clazz = (Class) cl.loadClass("javax.ejb.EJB"); + Class clazz = (Class) + ClassUtils.forName("javax.ejb.EJB", CommonAnnotationBeanPostProcessor.class.getClassLoader()); ejbRefClass = clazz; } catch (ClassNotFoundException ex) { diff --git a/spring-context/src/main/java/org/springframework/scheduling/annotation/AsyncAnnotationAdvisor.java b/spring-context/src/main/java/org/springframework/scheduling/annotation/AsyncAnnotationAdvisor.java index 6a731ff2358..02208114757 100644 --- a/spring-context/src/main/java/org/springframework/scheduling/annotation/AsyncAnnotationAdvisor.java +++ b/spring-context/src/main/java/org/springframework/scheduling/annotation/AsyncAnnotationAdvisor.java @@ -34,6 +34,7 @@ import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.core.task.SimpleAsyncTaskExecutor; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; /** * Advisor that activates asynchronous method execution through the {@link Async} @@ -79,9 +80,9 @@ public class AsyncAnnotationAdvisor extends AbstractPointcutAdvisor implements B public AsyncAnnotationAdvisor(Executor executor, AsyncUncaughtExceptionHandler exceptionHandler) { Set> asyncAnnotationTypes = new LinkedHashSet>(2); asyncAnnotationTypes.add(Async.class); - ClassLoader cl = AsyncAnnotationAdvisor.class.getClassLoader(); try { - asyncAnnotationTypes.add((Class) cl.loadClass("javax.ejb.Asynchronous")); + asyncAnnotationTypes.add((Class) + ClassUtils.forName("javax.ejb.Asynchronous", AsyncAnnotationAdvisor.class.getClassLoader())); } catch (ClassNotFoundException ex) { // If EJB 3.1 API not present, simply ignore. diff --git a/spring-core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java b/spring-core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java index 6eeef892706..9118f62d78b 100644 --- a/spring-core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java +++ b/spring-core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java @@ -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; @@ -143,11 +144,15 @@ import org.springframework.util.StringUtils; * *

WARNING: 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

+ * in multiple class path locations. This is because a resource such as
+ * 
  *     com/mycompany/package1/service-context.xml
- * 
may be in only one location, but when a path such as
+ * 
+ * may be in only one location, but when a path such as + *
  *     classpath:com/mycompany/**/service-context.xml
- * 
is used to try to resolve it, the resolver will work off the (first) URL + *
+ * 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,6 +203,17 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol this.resourceLoader = new DefaultResourceLoader(); } + /** + * Create a new PathMatchingResourcePatternResolver. + *

ClassLoader access will happen via the thread context class loader. + * @param resourceLoader the ResourceLoader to load root directories and + * actual resources with + */ + public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) { + Assert.notNull(resourceLoader, "ResourceLoader must not be null"); + this.resourceLoader = resourceLoader; + } + /** * Create a new PathMatchingResourcePatternResolver with a DefaultResourceLoader. * @param classLoader the ClassLoader to load classpath resources with, @@ -209,16 +225,6 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol this.resourceLoader = new DefaultResourceLoader(classLoader); } - /** - * Create a new PathMatchingResourcePatternResolver. - *

ClassLoader access will happen via the thread context class loader. - * @param resourceLoader the ResourceLoader to load root directories and - * actual resources with - */ - public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) { - Assert.notNull(resourceLoader, "ResourceLoader must not be null"); - this.resourceLoader = resourceLoader; - } /** * Return the ResourceLoader that this pattern resolver works with. @@ -227,11 +233,6 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol return this.resourceLoader; } - /** - * Return the ClassLoader that this pattern resolver works with - * (only {@code null} if even the system ClassLoader isn't accessible). - * @see org.springframework.util.ClassUtils#getDefaultClassLoader() - */ @Override public ClassLoader getClassLoader() { return getResourceLoader().getClassLoader(); diff --git a/spring-core/src/main/java/org/springframework/core/io/support/PropertiesLoaderUtils.java b/spring-core/src/main/java/org/springframework/core/io/support/PropertiesLoaderUtils.java index b9789557dfe..c501a52fe6a 100644 --- a/spring-core/src/main/java/org/springframework/core/io/support/PropertiesLoaderUtils.java +++ b/spring-core/src/main/java/org/springframework/core/io/support/PropertiesLoaderUtils.java @@ -174,9 +174,9 @@ public abstract class PropertiesLoaderUtils { if (classLoaderToUse == null) { classLoaderToUse = ClassUtils.getDefaultClassLoader(); } - Properties props = new Properties(); Enumeration urls = (classLoaderToUse != null ? classLoaderToUse.getResources(resourceName) : ClassLoader.getSystemResources(resourceName)); + Properties props = new Properties(); while (urls.hasMoreElements()) { URL url = urls.nextElement(); URLConnection con = url.openConnection(); diff --git a/spring-core/src/main/java/org/springframework/core/io/support/SpringFactoriesLoader.java b/spring-core/src/main/java/org/springframework/core/io/support/SpringFactoriesLoader.java index 358366815e7..9125716580d 100644 --- a/spring-core/src/main/java/org/springframework/core/io/support/SpringFactoriesLoader.java +++ b/spring-core/src/main/java/org/springframework/core/io/support/SpringFactoriesLoader.java @@ -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. @@ -86,9 +86,9 @@ public abstract class SpringFactoriesLoader { public static List loadFactoryNames(Class factoryClass, ClassLoader classLoader) { String factoryClassName = factoryClass.getName(); try { - List result = new ArrayList(); Enumeration urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) : ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION)); + List result = new ArrayList(); while (urls.hasMoreElements()) { URL url = urls.nextElement(); Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url)); diff --git a/spring-core/src/main/java/org/springframework/core/type/filter/AnnotationTypeFilter.java b/spring-core/src/main/java/org/springframework/core/type/filter/AnnotationTypeFilter.java index a2655adfb22..7d2d674c7c3 100644 --- a/spring-core/src/main/java/org/springframework/core/type/filter/AnnotationTypeFilter.java +++ b/spring-core/src/main/java/org/springframework/core/type/filter/AnnotationTypeFilter.java @@ -22,6 +22,7 @@ import java.lang.annotation.Inherited; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.classreading.MetadataReader; +import org.springframework.util.ClassUtils; /** * A simple filter which matches classes with a given annotation, @@ -97,14 +98,14 @@ public class AnnotationTypeFilter extends AbstractTypeHierarchyTraversingFilter if (Object.class.getName().equals(typeName)) { return false; } - else if (typeName.startsWith("java.")) { + else if (typeName.startsWith("java")) { try { - Class clazz = getClass().getClassLoader().loadClass(typeName); + Class clazz = ClassUtils.forName(typeName, getClass().getClassLoader()); return ((this.considerMetaAnnotations ? AnnotationUtils.getAnnotation(clazz, this.annotationType) : clazz.getAnnotation(this.annotationType)) != null); } - 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; diff --git a/spring-core/src/main/java/org/springframework/core/type/filter/AssignableTypeFilter.java b/spring-core/src/main/java/org/springframework/core/type/filter/AssignableTypeFilter.java index ac037d03a6c..63653046278 100644 --- a/spring-core/src/main/java/org/springframework/core/type/filter/AssignableTypeFilter.java +++ b/spring-core/src/main/java/org/springframework/core/type/filter/AssignableTypeFilter.java @@ -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. * @@ -61,13 +63,13 @@ public class AssignableTypeFilter extends AbstractTypeHierarchyTraversingFilter else if (Object.class.getName().equals(typeName)) { return false; } - else if (typeName.startsWith("java.")) { + else if (typeName.startsWith("java")) { try { - Class clazz = getClass().getClassLoader().loadClass(typeName); + 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; diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/support/StandardTypeLocator.java b/spring-expression/src/main/java/org/springframework/expression/spel/support/StandardTypeLocator.java index 14fa767c1e9..9c5b0af5b2b 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/support/StandardTypeLocator.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/support/StandardTypeLocator.java @@ -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. @@ -98,7 +98,7 @@ public class StandardTypeLocator implements TypeLocator { public Class findType(String typeName) throws EvaluationException { String nameToLookup = typeName; try { - return this.classLoader.loadClass(nameToLookup); + return ClassUtils.forName(nameToLookup, this.classLoader); } catch (ClassNotFoundException ey) { // try any registered prefixes before giving up @@ -106,7 +106,7 @@ public class StandardTypeLocator implements TypeLocator { for (String prefix : this.knownPackagePrefixes) { try { nameToLookup = prefix + "." + typeName; - return this.classLoader.loadClass(nameToLookup); + return ClassUtils.forName(nameToLookup, this.classLoader); } catch (ClassNotFoundException ex) { // might be a different prefix diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/SqlRowSetResultSetExtractor.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/SqlRowSetResultSetExtractor.java index dd0f94a66e1..7a69f2c44ab 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/SqlRowSetResultSetExtractor.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/SqlRowSetResultSetExtractor.java @@ -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. @@ -18,7 +18,6 @@ package org.springframework.jdbc.core; import java.sql.ResultSet; import java.sql.SQLException; - import javax.sql.rowset.CachedRowSet; import javax.sql.rowset.RowSetFactory; import javax.sql.rowset.RowSetProvider; @@ -26,6 +25,7 @@ import javax.sql.rowset.RowSetProvider; import org.springframework.core.JdkVersion; import org.springframework.jdbc.support.rowset.ResultSetWrappingSqlRowSet; import org.springframework.jdbc.support.rowset.SqlRowSet; +import org.springframework.util.ClassUtils; /** * {@link ResultSetExtractor} implementation that returns a Spring {@link SqlRowSet} @@ -134,12 +134,14 @@ public class SqlRowSetResultSetExtractor implements ResultSetExtractor IMPLEMENTATION_CLASS; + private static final Class implementationClass; + static { try { - IMPLEMENTATION_CLASS = Class.forName("com.sun.rowset.CachedRowSetImpl"); + implementationClass = ClassUtils.forName("com.sun.rowset.CachedRowSetImpl", + SqlRowSetResultSetExtractor.class.getClassLoader()); } - catch (ClassNotFoundException ex) { + catch (Throwable ex) { throw new IllegalStateException(ex); } } @@ -147,12 +149,9 @@ public class SqlRowSetResultSetExtractor implements ResultSetExtractor oracleConClass = getClass().getClassLoader().loadClass("oracle.jdbc.OracleConnection"); + Class oracleConClass = con.getClass().getClassLoader().loadClass("oracle.jdbc.OracleConnection"); isOracleCon = oracleConClass.isInstance(con); } catch (ClassNotFoundException ex) { @@ -107,7 +108,7 @@ public class OracleTableMetaDataProvider extends GenericTableMetaDataProvider { ReflectionUtils.makeAccessible(getIncludeSynonyms); originalValueForIncludeSynonyms = (Boolean) getIncludeSynonyms.invoke(con); - setIncludeSynonyms = con.getClass().getMethod("setIncludeSynonyms", new Class[] {boolean.class}); + setIncludeSynonyms = con.getClass().getMethod("setIncludeSynonyms", boolean.class); ReflectionUtils.makeAccessible(setIncludeSynonyms); setIncludeSynonyms.invoke(con, Boolean.TRUE); } @@ -126,8 +127,7 @@ public class OracleTableMetaDataProvider extends GenericTableMetaDataProvider { } /* - * Oracle implementation for detecting current schema - * + * Oracle-based implementation for detecting the current schema. * @param databaseMetaData */ private void lookupDefaultSchema(DatabaseMetaData databaseMetaData) { @@ -144,7 +144,9 @@ public class OracleTableMetaDataProvider extends GenericTableMetaDataProvider { cstmt.close(); } } - } catch (Exception ignore) {} + } + catch (Exception ignore) { + } } } diff --git a/spring-test/src/main/java/org/springframework/test/context/TestContextManager.java b/spring-test/src/main/java/org/springframework/test/context/TestContextManager.java index 75e22ab16c9..cdfcda91d55 100644 --- a/spring-test/src/main/java/org/springframework/test/context/TestContextManager.java +++ b/spring-test/src/main/java/org/springframework/test/context/TestContextManager.java @@ -23,6 +23,7 @@ import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.springframework.util.Assert; /** @@ -96,8 +97,7 @@ public class TestContextManager { * @see #registerTestExecutionListeners(List) */ public TestContextManager(Class testClass) { - CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate = new DefaultCacheAwareContextLoaderDelegate( - contextCache); + CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate = new DefaultCacheAwareContextLoaderDelegate(contextCache); BootstrapContext bootstrapContext = new DefaultBootstrapContext(testClass, cacheAwareContextLoaderDelegate); this.testContextBootstrapper = BootstrapUtils.resolveTestContextBootstrapper(bootstrapContext); this.testContext = new DefaultTestContext(testContextBootstrapper); @@ -148,8 +148,7 @@ public class TestContextManager { * registered for this {@code TestContextManager} in reverse order. */ private List getReversedTestExecutionListeners() { - List listenersReversed = new ArrayList( - getTestExecutionListeners()); + List listenersReversed = new ArrayList(getTestExecutionListeners()); Collections.reverse(listenersReversed); return listenersReversed; } @@ -168,7 +167,7 @@ public class TestContextManager { * @see #getTestExecutionListeners() */ public void beforeTestClass() throws Exception { - final Class testClass = getTestContext().getTestClass(); + Class testClass = getTestContext().getTestClass(); if (logger.isTraceEnabled()) { logger.trace("beforeTestClass(): class [" + testClass + "]"); } @@ -179,8 +178,8 @@ public class TestContextManager { testExecutionListener.beforeTestClass(getTestContext()); } catch (Exception ex) { - logger.warn("Caught exception while allowing TestExecutionListener [" + testExecutionListener - + "] to process 'before class' callback for test class [" + testClass + "]", ex); + logger.warn("Caught exception while allowing TestExecutionListener [" + testExecutionListener + + "] to process 'before class' callback for test class [" + testClass + "]", ex); throw ex; } } @@ -212,8 +211,8 @@ public class TestContextManager { testExecutionListener.prepareTestInstance(getTestContext()); } catch (Exception ex) { - logger.error("Caught exception while allowing TestExecutionListener [" + testExecutionListener - + "] to prepare test instance [" + testInstance + "]", ex); + logger.error("Caught exception while allowing TestExecutionListener [" + testExecutionListener + + "] to prepare test instance [" + testInstance + "]", ex); throw ex; } } @@ -249,9 +248,9 @@ public class TestContextManager { testExecutionListener.beforeTestMethod(getTestContext()); } catch (Exception ex) { - logger.warn("Caught exception while allowing TestExecutionListener [" + testExecutionListener - + "] to process 'before' execution of test method [" + testMethod + "] for test instance [" - + testInstance + "]", ex); + logger.warn("Caught exception while allowing TestExecutionListener [" + testExecutionListener + + "] to process 'before' execution of test method [" + testMethod + "] for test instance [" + + testInstance + "]", ex); throw ex; } } @@ -297,9 +296,9 @@ public class TestContextManager { testExecutionListener.afterTestMethod(getTestContext()); } catch (Exception ex) { - logger.warn("Caught exception while allowing TestExecutionListener [" + testExecutionListener - + "] to process 'after' execution for test: method [" + testMethod + "], instance [" - + testInstance + "], exception [" + exception + "]", ex); + logger.warn("Caught exception while allowing TestExecutionListener [" + testExecutionListener + + "] to process 'after' execution for test: method [" + testMethod + "], instance [" + + testInstance + "], exception [" + exception + "]", ex); if (afterTestMethodException == null) { afterTestMethodException = ex; } @@ -325,7 +324,7 @@ public class TestContextManager { * @see #getTestExecutionListeners() */ public void afterTestClass() throws Exception { - final Class testClass = getTestContext().getTestClass(); + Class testClass = getTestContext().getTestClass(); if (logger.isTraceEnabled()) { logger.trace("afterTestClass(): class [" + testClass + "]"); } @@ -339,8 +338,8 @@ public class TestContextManager { testExecutionListener.afterTestClass(getTestContext()); } catch (Exception ex) { - logger.warn("Caught exception while allowing TestExecutionListener [" + testExecutionListener - + "] to process 'after class' callback for test class [" + testClass + "]", ex); + logger.warn("Caught exception while allowing TestExecutionListener [" + testExecutionListener + + "] to process 'after class' callback for test class [" + testClass + "]", ex); if (afterTestClassException == null) { afterTestClassException = ex; } diff --git a/spring-test/src/main/java/org/springframework/test/context/support/AbstractTestContextBootstrapper.java b/spring-test/src/main/java/org/springframework/test/context/support/AbstractTestContextBootstrapper.java index 0a6f472fec6..68a302c3e42 100644 --- a/spring-test/src/main/java/org/springframework/test/context/support/AbstractTestContextBootstrapper.java +++ b/spring-test/src/main/java/org/springframework/test/context/support/AbstractTestContextBootstrapper.java @@ -26,6 +26,7 @@ import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.springframework.beans.BeanUtils; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; @@ -122,8 +123,8 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot Class[] listenerClasses = (Class[]) annAttrs.getClassArray("listeners"); if (!ObjectUtils.isEmpty(valueListenerClasses) && !ObjectUtils.isEmpty(listenerClasses)) { String msg = String.format( - "Class [%s] has been configured with @TestExecutionListeners' 'value' [%s] " - + "and 'listeners' [%s] attributes. Use one or the other, but not both.", + "Class [%s] has been configured with @TestExecutionListeners' 'value' [%s] " + + "and 'listeners' [%s] attributes. Use one or the other, but not both.", declaringClass, ObjectUtils.nullSafeToString(valueListenerClasses), ObjectUtils.nullSafeToString(listenerClasses)); logger.error(msg); @@ -149,9 +150,9 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot } catch (NoClassDefFoundError err) { if (logger.isInfoEnabled()) { - logger.info(String.format("Could not instantiate TestExecutionListener [%s]. " - + "Specify custom listener classes or make the default listener classes " - + "(and their dependencies) available.", listenerClass.getName())); + logger.info(String.format("Could not instantiate TestExecutionListener [%s]. " + + "Specify custom listener classes or make the default listener classes " + + "(and their dependencies) available.", listenerClass.getName())); } } } @@ -169,15 +170,15 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot @SuppressWarnings("unchecked") protected Set> getDefaultTestExecutionListenerClasses() { Set> defaultListenerClasses = new LinkedHashSet>(); + ClassLoader cl = getClass().getClassLoader(); for (String className : getDefaultTestExecutionListenerClassNames()) { try { - defaultListenerClasses.add((Class) getClass().getClassLoader().loadClass( - className)); + defaultListenerClasses.add((Class) ClassUtils.forName(className, cl)); } - catch (Throwable t) { + catch (Throwable ex) { if (logger.isDebugEnabled()) { - logger.debug("Could not load default TestExecutionListener class [" + className - + "]. Specify custom listener classes or make the default listener classes available.", t); + logger.debug("Could not load default TestExecutionListener class [" + className + + "]. Specify custom listener classes or make the default listener classes available.", ex); } } } @@ -187,7 +188,7 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot /** * {@inheritDoc} */ - @SuppressWarnings({ "unchecked" }) + @SuppressWarnings("unchecked") @Override public final MergedContextConfiguration buildMergedContextConfiguration() { Class testClass = getBootstrapContext().getTestClass(); @@ -238,7 +239,6 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot * Build the {@link MergedContextConfiguration merged context configuration} * for the supplied {@link Class testClass}, context configuration attributes, * and parent context configuration. - * * @param testClass the test class for which the {@code MergedContextConfiguration} * should be built (must not be {@code null}) * @param configAttributesList the list of context configuration attributes for the @@ -303,13 +303,11 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot * Resolve the {@link ContextLoader} {@linkplain Class class} to use for the * supplied list of {@link ContextConfigurationAttributes} and then instantiate * and return that {@code ContextLoader}. - * *

If the user has not explicitly declared which loader to use, the value * returned from {@link #getDefaultContextLoaderClass} will be used as the * default context loader class. For details on the class resolution process, * see {@link #resolveExplicitContextLoaderClass} and * {@link #getDefaultContextLoaderClass}. - * * @param testClass the test class for which the {@code ContextLoader} should be * resolved; must not be {@code null} * @param configAttributesList the list of configuration attributes to process; must @@ -320,6 +318,7 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot */ private ContextLoader resolveContextLoader(Class testClass, List configAttributesList) { + Assert.notNull(testClass, "Class must not be null"); Assert.notEmpty(configAttributesList, "ContextConfigurationAttributes list must not be empty"); @@ -327,21 +326,17 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot if (contextLoaderClass == null) { contextLoaderClass = getDefaultContextLoaderClass(testClass); } - if (logger.isTraceEnabled()) { logger.trace(String.format("Using ContextLoader class [%s] for test class [%s]", contextLoaderClass.getName(), testClass.getName())); } - return BeanUtils.instantiateClass(contextLoaderClass, ContextLoader.class); } /** * Resolve the {@link ContextLoader} {@linkplain Class class} to use for the supplied * list of {@link ContextConfigurationAttributes}. - * *

Beginning with the first level in the context configuration attributes hierarchy: - * *

    *
  1. If the {@link ContextConfigurationAttributes#getContextLoaderClass() * contextLoaderClass} property of {@link ContextConfigurationAttributes} is @@ -350,7 +345,6 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot * level in the hierarchy, traverse to the next level in the hierarchy and return to * step #1.
  2. *
- * * @param configAttributesList the list of configuration attributes to process; * must not be {@code null} or empty; must be ordered bottom-up * (i.e., as if we were traversing up the class hierarchy) @@ -361,14 +355,13 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot */ private Class resolveExplicitContextLoaderClass( List configAttributesList) { - Assert.notEmpty(configAttributesList, "ContextConfigurationAttributes list must not be empty"); + Assert.notEmpty(configAttributesList, "ContextConfigurationAttributes list must not be empty"); for (ContextConfigurationAttributes configAttributes : configAttributesList) { if (logger.isTraceEnabled()) { logger.trace(String.format("Resolving ContextLoader for context configuration attributes %s", configAttributes)); } - Class contextLoaderClass = configAttributes.getContextLoaderClass(); if (!ContextLoader.class.equals(contextLoaderClass)) { if (logger.isDebugEnabled()) { @@ -379,7 +372,6 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot return contextLoaderClass; } } - return null; } @@ -405,12 +397,10 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot /** * Build a {@link MergedContextConfiguration} instance from the supplied, * merged values. - * *

Concrete subclasses typically will only need to instantiate * {@link MergedContextConfiguration} (or a specialized subclass thereof) * from the provided values; further processing and merging of values is likely * unnecessary. - * * @param testClass the test class for which the {@code MergedContextConfiguration} * should be built (must not be {@code null}) * @param locations the merged resource locations @@ -425,9 +415,7 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot * @return the fully initialized {@code MergedContextConfiguration} */ protected abstract MergedContextConfiguration buildMergedContextConfiguration( - Class testClass, - String[] locations, - Class[] classes, + Class testClass, String[] locations, Class[] classes, Set>> initializerClasses, String[] activeProfiles, ContextLoader contextLoader, CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate, MergedContextConfiguration parentConfig); diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/server/standard/ServerEndpointExporter.java b/spring-websocket/src/main/java/org/springframework/web/socket/server/standard/ServerEndpointExporter.java index 3171f1f6ce4..f5e9f17691c 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/server/standard/ServerEndpointExporter.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/server/standard/ServerEndpointExporter.java @@ -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. @@ -35,6 +35,7 @@ import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; /** @@ -50,7 +51,6 @@ import org.springframework.util.ReflectionUtils; * * @author Rossen Stoyanchev * @since 4.0 - * * @see ServerEndpointRegistration * @see SpringConfigurator * @see ServletServerContainerFactoryBean @@ -97,9 +97,9 @@ public class ServerEndpointExporter implements InitializingBean, BeanPostProcess protected ServerContainer getServerContainer() { Class servletContextClass; try { - servletContextClass = Class.forName("javax.servlet.ServletContext"); + servletContextClass = ClassUtils.forName("javax.servlet.ServletContext", getClass().getClassLoader()); } - catch (Throwable e) { + catch (Throwable ex) { return null; } @@ -139,8 +139,8 @@ public class ServerEndpointExporter implements InitializingBean, BeanPostProcess ServerEndpointConfig sec = (ServerEndpointConfig) bean; try { if (logger.isInfoEnabled()) { - logger.info("Registering bean '" + beanName - + "' as javax.websocket.Endpoint under path " + sec.getPath()); + logger.info("Registering bean '" + beanName + + "' as javax.websocket.Endpoint under path " + sec.getPath()); } getServerContainer().addEndpoint(sec); }