mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
79 Commits
v7.0.6
...
v4.3.2.RELEASE
| Author | SHA1 | Date | |
|---|---|---|---|
| 62b8f97f0f | |||
| ff878ea9dc | |||
| 7021a4be44 | |||
| 5c4737c3d0 | |||
| fbf3807af1 | |||
| 703c37ec88 | |||
| 96440878bb | |||
| b5c11ffb1c | |||
| 7f5b323d50 | |||
| 67176e2b75 | |||
| 79f3cf3263 | |||
| 9ee1dc79fd | |||
| 9e2c34dfa6 | |||
| cc93c2a559 | |||
| 15c7044c4d | |||
| 0ef80d3579 | |||
| 95c2e0a996 | |||
| da3e8611e1 | |||
| 64595597f3 | |||
| 82f2983cd4 | |||
| 9451177c35 | |||
| 9ed087d5da | |||
| 77f22e9674 | |||
| 8ccfdbbcf9 | |||
| 5a92aa4e06 | |||
| 7b1010cf61 | |||
| 45b2f5bac4 | |||
| 36e1c82ef5 | |||
| 503d65d570 | |||
| fe17f8da41 | |||
| b583aa1579 | |||
| e0d81b97bb | |||
| 90752f9d87 | |||
| 3663aa675a | |||
| 1ca4b81856 | |||
| 4e7e06f549 | |||
| b2f0bdb0f4 | |||
| d98bd34200 | |||
| 940bdd878e | |||
| df556333a8 | |||
| 116f05eda6 | |||
| b187bbeca3 | |||
| 479a83b628 | |||
| 1c18100143 | |||
| 5d3c0f33f6 | |||
| afe106e254 | |||
| 69dd40ec89 | |||
| dee50d5e28 | |||
| 9e93403857 | |||
| 12bff6b3a0 | |||
| 70e666b4a3 | |||
| 29f980ec72 | |||
| 1d39d762f0 | |||
| 4d6d5e0ddd | |||
| 4ea5f070a4 | |||
| da59b4da9b | |||
| 0065a160cc | |||
| 52f46c7fea | |||
| f0a826ec0c | |||
| 5c3c0f73c1 | |||
| be0b71ce31 | |||
| f85d48dd31 | |||
| a1b58ee601 | |||
| e30429051d | |||
| 942ead75e2 | |||
| 453688f6df | |||
| 7d7a161102 | |||
| aaa223ae66 | |||
| d11c624fb0 | |||
| 275e51b19d | |||
| ab62edeeaa | |||
| 813108a928 | |||
| 3c14911401 | |||
| 4337f14627 | |||
| 92d78c10a2 | |||
| 16d5ba9b3a | |||
| 52065a736b | |||
| 11cb109114 | |||
| d7eadd41d6 |
+14
-23
@@ -36,7 +36,7 @@ configure(allprojects) { project ->
|
||||
ext.eclipselinkVersion = "2.4.2"
|
||||
ext.ehcacheVersion = "2.10.2"
|
||||
ext.ehcachejcacheVersion = "1.0.1"
|
||||
ext.ehcache3Version = "3.1.0"
|
||||
ext.ehcache3Version = "3.1.1"
|
||||
ext.ejbVersion = "3.0"
|
||||
ext.fileuploadVersion = "1.3.2"
|
||||
ext.freemarkerVersion = "2.3.23"
|
||||
@@ -52,18 +52,18 @@ configure(allprojects) { project ->
|
||||
ext.hsqldbVersion = "2.3.4"
|
||||
ext.httpasyncVersion = "4.1.2"
|
||||
ext.httpclientVersion = "4.5.2"
|
||||
ext.jackson2Version = "2.8.0.rc2"
|
||||
ext.jackson2Version = "2.8.1"
|
||||
ext.jasperreportsVersion = "6.2.1" // our tests fail with JR-internal NPEs against 6.2.2 and higher
|
||||
ext.javamailVersion = "1.5.5"
|
||||
ext.jettyVersion = "9.3.10.v20160621"
|
||||
ext.jettyVersion = "9.3.11.v20160721"
|
||||
ext.jodaVersion = "2.9.4"
|
||||
ext.jrubyVersion = "1.7.25" // JRuby 9000 only supported through JSR-223 (StandardScriptFactory)
|
||||
ext.jtaVersion = "1.2"
|
||||
ext.junitVersion = "4.12"
|
||||
ext.log4jVersion = "1.2.17"
|
||||
ext.nettyVersion = "4.1.1.Final"
|
||||
ext.nettyVersion = "4.1.4.Final"
|
||||
ext.okhttpVersion = "2.7.5"
|
||||
ext.okhttp3Version = "3.3.1"
|
||||
ext.okhttp3Version = "3.4.1"
|
||||
ext.openjpaVersion = "2.4.1"
|
||||
ext.poiVersion = "3.14"
|
||||
ext.reactorVersion = "2.0.8.RELEASE"
|
||||
@@ -74,9 +74,9 @@ configure(allprojects) { project ->
|
||||
ext.testngVersion = "6.9.10"
|
||||
ext.tiles2Version = "2.2.2"
|
||||
ext.tiles3Version = "3.0.5"
|
||||
ext.tomcatVersion = "8.5.3"
|
||||
ext.tomcatVersion = "8.5.4"
|
||||
ext.tyrusVersion = "1.3.5" // constrained by WebLogic 12.1.3 support
|
||||
ext.undertowVersion = "1.4.0.CR2"
|
||||
ext.undertowVersion = "1.3.23.Final"
|
||||
ext.xmlunitVersion = "1.6"
|
||||
ext.xstreamVersion = "1.4.9"
|
||||
|
||||
@@ -199,7 +199,7 @@ configure(allprojects) { project ->
|
||||
"http://www.eclipse.org/aspectj/doc/released/aspectj5rt-api/",
|
||||
"http://ehcache.org/apidocs/${ehcacheVersion}",
|
||||
"http://ehcache.org/apidocs/${ehcache3Version}",
|
||||
"http://quartz-scheduler.org/api/2.2.0/",
|
||||
"http://quartz-scheduler.org/api/2.2.1/",
|
||||
"http://fasterxml.github.io/jackson-core/javadoc/2.7/",
|
||||
"http://fasterxml.github.io/jackson-databind/javadoc/2.7/",
|
||||
"http://fasterxml.github.io/jackson-dataformat-xml/javadoc/2.7/",
|
||||
@@ -556,13 +556,6 @@ project("spring-oxm") {
|
||||
description = "Spring Object/XML Marshalling"
|
||||
apply from: "oxm.gradle"
|
||||
|
||||
compileTestJava {
|
||||
// necessary to avoid java.lang.VerifyError on jibx compilation
|
||||
// see http://jira.codehaus.org/browse/JIBX-465
|
||||
sourceCompatibility = 1.6
|
||||
targetCompatibility = 1.6
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-beans"))
|
||||
compile(project(":spring-core"))
|
||||
@@ -584,11 +577,9 @@ project("spring-oxm") {
|
||||
testCompile("org.codehaus.jettison:jettison:1.3.7") {
|
||||
exclude group: 'stax', module: 'stax-api'
|
||||
}
|
||||
if (compileTestJava.enabled) {
|
||||
testCompile(files(genCastor.classesDir).builtBy(genCastor))
|
||||
testCompile(files(genJaxb.classesDir).builtBy(genJaxb))
|
||||
testCompile(files(genXmlbeans.classesDir).builtBy(genXmlbeans))
|
||||
}
|
||||
testCompile(files(genCastor.classesDir).builtBy(genCastor))
|
||||
testCompile(files(genJaxb.classesDir).builtBy(genJaxb))
|
||||
testCompile(files(genXmlbeans.classesDir).builtBy(genXmlbeans))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -879,10 +870,10 @@ project("spring-webmvc") {
|
||||
testCompile("commons-io:commons-io:1.3")
|
||||
testCompile("joda-time:joda-time:${jodaVersion}")
|
||||
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
|
||||
testCompile("org.jruby:jruby:${jrubyVersion}")
|
||||
testCompile("org.python:jython-standalone:2.5.3")
|
||||
testCompile("org.mozilla:rhino:1.7.7.1")
|
||||
testCompile("org.webjars:underscorejs:1.8.3")
|
||||
testRuntime("org.jruby:jruby:${jrubyVersion}")
|
||||
testRuntime("org.python:jython-standalone:2.5.3")
|
||||
testRuntime("org.webjars:underscorejs:1.8.3")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
version=4.3.1.BUILD-SNAPSHOT
|
||||
version=4.3.2.RELEASE
|
||||
|
||||
@@ -46,7 +46,7 @@ public interface MethodInterceptor extends Interceptor {
|
||||
* after the invocation. Polite implementations would certainly
|
||||
* like to invoke {@link Joinpoint#proceed()}.
|
||||
* @param invocation the method invocation joinpoint
|
||||
* @return the result of the call to {@link Joinpoint#proceed();
|
||||
* @return the result of the call to {@link Joinpoint#proceed()};
|
||||
* might be intercepted by the interceptor
|
||||
* @throws Throwable if the interceptors or the target object
|
||||
* throws an exception
|
||||
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -55,10 +55,12 @@ public class SimpleAspectInstanceFactory implements AspectInstanceFactory {
|
||||
return this.aspectClass.newInstance();
|
||||
}
|
||||
catch (InstantiationException ex) {
|
||||
throw new AopConfigException("Unable to instantiate aspect class [" + this.aspectClass.getName() + "]", ex);
|
||||
throw new AopConfigException(
|
||||
"Unable to instantiate aspect class: " + this.aspectClass.getName(), ex);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new AopConfigException("Cannot access element class [" + this.aspectClass.getName() + "]", ex);
|
||||
throw new AopConfigException(
|
||||
"Could not access aspect constructor: " + this.aspectClass.getName(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -139,7 +139,8 @@ public class ProxyProcessorSupport extends ProxyConfig implements Ordered, BeanC
|
||||
* @return whether the given interface is an internal language interface
|
||||
*/
|
||||
protected boolean isInternalLanguageInterface(Class<?> ifc) {
|
||||
return ifc.getName().equals("groovy.lang.GroovyObject");
|
||||
return (ifc.getName().equals("groovy.lang.GroovyObject") ||
|
||||
ifc.getName().endsWith(".cglib.proxy.Factory"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
@@ -36,7 +36,9 @@ import org.springframework.util.ObjectUtils;
|
||||
* @author Rod Johnson
|
||||
* @author Ramnivas Laddad
|
||||
* @author Sam Brannen
|
||||
* @deprecated as of Spring 4.3, in favor of a custom aspect for such purposes
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMethod()) {
|
||||
|
||||
private final Expectations expectations = new Expectations();
|
||||
|
||||
+2
@@ -59,7 +59,9 @@ import org.aspectj.lang.annotation.SuppressAjWarnings;
|
||||
* @author Ramnivas Laddad
|
||||
* @author Sam Brannen
|
||||
* @see MockStaticEntityMethods
|
||||
* @deprecated as of Spring 4.3, in favor of a custom aspect for such purposes
|
||||
*/
|
||||
@Deprecated
|
||||
@RequiredTypes("javax.persistence.Entity")
|
||||
public aspect AnnotationDrivenStaticEntityMockingControl extends AbstractMethodMockingControl {
|
||||
|
||||
|
||||
+2
@@ -29,7 +29,9 @@ import java.lang.annotation.Target;
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Sam Brannen
|
||||
* @deprecated as of Spring 4.3, in favor of a custom aspect for such purposes
|
||||
*/
|
||||
@Deprecated
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface MockStaticEntityMethods {
|
||||
|
||||
+3
-5
@@ -94,7 +94,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
|
||||
|
||||
private String nestedPath = "";
|
||||
|
||||
private Object rootObject;
|
||||
Object rootObject;
|
||||
|
||||
/**
|
||||
* Map with cached nested Accessors: nested path -> Accessor instance.
|
||||
@@ -914,11 +914,9 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
|
||||
return BeanUtils.instantiate(type);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
// TODO: Root cause exception context is lost here; just exception message preserved.
|
||||
// Should we throw another exception type that preserves context instead?
|
||||
catch (Throwable ex) {
|
||||
throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + name,
|
||||
"Could not instantiate property type [" + type.getName() + "] to auto-grow nested property path: " + ex);
|
||||
"Could not instantiate property type [" + type.getName() + "] to auto-grow nested property path", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -148,7 +148,7 @@ public abstract class AbstractPropertyAccessor extends TypeConverterSupport impl
|
||||
* @throws InvalidPropertyException if there is no such property or
|
||||
* if the property isn't writable
|
||||
* @throws PropertyAccessException if the property was valid but the
|
||||
* accessor method failed or a type mismatch occured
|
||||
* accessor method failed or a type mismatch occurred
|
||||
*/
|
||||
@Override
|
||||
public abstract void setPropertyValue(String propertyName, Object value) throws BeansException;
|
||||
|
||||
@@ -63,11 +63,10 @@ public abstract class BeanUtils {
|
||||
|
||||
/**
|
||||
* Convenience method to instantiate a class using its no-arg constructor.
|
||||
* As this method doesn't try to load classes by name, it should avoid
|
||||
* class-loading issues.
|
||||
* @param clazz class to instantiate
|
||||
* @return the new instance
|
||||
* @throws BeanInstantiationException if the bean cannot be instantiated
|
||||
* @see Class#newInstance()
|
||||
*/
|
||||
public static <T> T instantiate(Class<T> clazz) throws BeanInstantiationException {
|
||||
Assert.notNull(clazz, "Class must not be null");
|
||||
@@ -87,13 +86,12 @@ public abstract class BeanUtils {
|
||||
|
||||
/**
|
||||
* Instantiate a class using its no-arg constructor.
|
||||
* As this method doesn't try to load classes by name, it should avoid
|
||||
* class-loading issues.
|
||||
* <p>Note that this method tries to set the constructor accessible
|
||||
* if given a non-accessible (that is, non-public) constructor.
|
||||
* @param clazz class to instantiate
|
||||
* @return the new instance
|
||||
* @throws BeanInstantiationException if the bean cannot be instantiated
|
||||
* @see Constructor#newInstance
|
||||
*/
|
||||
public static <T> T instantiateClass(Class<T> clazz) throws BeanInstantiationException {
|
||||
Assert.notNull(clazz, "Class must not be null");
|
||||
@@ -111,17 +109,15 @@ public abstract class BeanUtils {
|
||||
/**
|
||||
* Instantiate a class using its no-arg constructor and return the new instance
|
||||
* as the specified assignable type.
|
||||
* <p>Useful in cases where
|
||||
* the type of the class to instantiate (clazz) is not available, but the type
|
||||
* desired (assignableTo) is known.
|
||||
* <p>As this method doesn't try to load classes by name, it should avoid
|
||||
* class-loading issues.
|
||||
* <p>Note that this method tries to set the constructor accessible
|
||||
* if given a non-accessible (that is, non-public) constructor.
|
||||
* <p>Useful in cases where the type of the class to instantiate (clazz) is not
|
||||
* available, but the type desired (assignableTo) is known.
|
||||
* <p>Note that this method tries to set the constructor accessible if given a
|
||||
* non-accessible (that is, non-public) constructor.
|
||||
* @param clazz class to instantiate
|
||||
* @param assignableTo type that clazz must be assignableTo
|
||||
* @return the new instance
|
||||
* @throws BeanInstantiationException if the bean cannot be instantiated
|
||||
* @see Constructor#newInstance
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T instantiateClass(Class<?> clazz, Class<T> assignableTo) throws BeanInstantiationException {
|
||||
@@ -131,14 +127,13 @@ public abstract class BeanUtils {
|
||||
|
||||
/**
|
||||
* Convenience method to instantiate a class using the given constructor.
|
||||
* As this method doesn't try to load classes by name, it should avoid
|
||||
* class-loading issues.
|
||||
* <p>Note that this method tries to set the constructor accessible
|
||||
* if given a non-accessible (that is, non-public) constructor.
|
||||
* <p>Note that this method tries to set the constructor accessible if given a
|
||||
* non-accessible (that is, non-public) constructor.
|
||||
* @param ctor the constructor to instantiate
|
||||
* @param args the constructor arguments to apply
|
||||
* @return the new instance
|
||||
* @throws BeanInstantiationException if the bean cannot be instantiated
|
||||
* @see Constructor#newInstance
|
||||
*/
|
||||
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
|
||||
Assert.notNull(ctor, "Constructor must not be null");
|
||||
|
||||
@@ -141,6 +141,7 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
|
||||
*/
|
||||
public void setBeanInstance(Object object) {
|
||||
this.wrappedObject = object;
|
||||
this.rootObject = object;
|
||||
this.typeConverterDelegate = new TypeConverterDelegate(this, this.wrappedObject);
|
||||
setIntrospectionClass(object.getClass());
|
||||
}
|
||||
|
||||
+14
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -24,6 +24,7 @@ package org.springframework.beans;
|
||||
* spouse property of the target object has a null value.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class NullValueInNestedPathException extends InvalidPropertyException {
|
||||
@@ -47,4 +48,16 @@ public class NullValueInNestedPathException extends InvalidPropertyException {
|
||||
super(beanClass, propertyName, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new NullValueInNestedPathException.
|
||||
* @param beanClass the offending bean class
|
||||
* @param propertyName the offending property
|
||||
* @param msg the detail message
|
||||
* @param cause the root cause
|
||||
* @since 4.3.2
|
||||
*/
|
||||
public NullValueInNestedPathException(Class<?> beanClass, String propertyName, String msg, Throwable cause) {
|
||||
super(beanClass, propertyName, msg, cause);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -120,7 +120,7 @@ public interface PropertyAccessor {
|
||||
* @throws InvalidPropertyException if there is no such property or
|
||||
* if the property isn't writable
|
||||
* @throws PropertyAccessException if the property was valid but the
|
||||
* accessor method failed or a type mismatch occured
|
||||
* accessor method failed or a type mismatch occurred
|
||||
*/
|
||||
void setPropertyValue(String propertyName, Object value) throws BeansException;
|
||||
|
||||
@@ -130,7 +130,7 @@ public interface PropertyAccessor {
|
||||
* @throws InvalidPropertyException if there is no such property or
|
||||
* if the property isn't writable
|
||||
* @throws PropertyAccessException if the property was valid but the
|
||||
* accessor method failed or a type mismatch occured
|
||||
* accessor method failed or a type mismatch occurred
|
||||
*/
|
||||
void setPropertyValue(PropertyValue pv) throws BeansException;
|
||||
|
||||
@@ -144,7 +144,7 @@ public interface PropertyAccessor {
|
||||
* @throws InvalidPropertyException if there is no such property or
|
||||
* if the property isn't writable
|
||||
* @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions
|
||||
* occured for specific properties during the batch update. This exception bundles
|
||||
* occurred for specific properties during the batch update. This exception bundles
|
||||
* all individual PropertyAccessExceptions. All other properties will have been
|
||||
* successfully updated.
|
||||
*/
|
||||
@@ -164,7 +164,7 @@ public interface PropertyAccessor {
|
||||
* @throws InvalidPropertyException if there is no such property or
|
||||
* if the property isn't writable
|
||||
* @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions
|
||||
* occured for specific properties during the batch update. This exception bundles
|
||||
* occurred for specific properties during the batch update. This exception bundles
|
||||
* all individual PropertyAccessExceptions. All other properties will have been
|
||||
* successfully updated.
|
||||
* @see #setPropertyValues(PropertyValues, boolean, boolean)
|
||||
@@ -185,7 +185,7 @@ public interface PropertyAccessor {
|
||||
* @throws InvalidPropertyException if there is no such property or
|
||||
* if the property isn't writable
|
||||
* @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions
|
||||
* occured for specific properties during the batch update. This exception bundles
|
||||
* occurred for specific properties during the batch update. This exception bundles
|
||||
* all individual PropertyAccessExceptions. All other properties will have been
|
||||
* successfully updated.
|
||||
* @see #setPropertyValues(PropertyValues, boolean, boolean)
|
||||
@@ -208,7 +208,7 @@ public interface PropertyAccessor {
|
||||
* @throws InvalidPropertyException if there is no such property or
|
||||
* if the property isn't writable
|
||||
* @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions
|
||||
* occured for specific properties during the batch update. This exception bundles
|
||||
* occurred for specific properties during the batch update. This exception bundles
|
||||
* all individual PropertyAccessExceptions. All other properties will have been
|
||||
* successfully updated.
|
||||
*/
|
||||
|
||||
+15
-1
@@ -59,6 +59,7 @@ import org.springframework.beans.propertyeditors.FileEditor;
|
||||
import org.springframework.beans.propertyeditors.InputSourceEditor;
|
||||
import org.springframework.beans.propertyeditors.InputStreamEditor;
|
||||
import org.springframework.beans.propertyeditors.LocaleEditor;
|
||||
import org.springframework.beans.propertyeditors.PathEditor;
|
||||
import org.springframework.beans.propertyeditors.PatternEditor;
|
||||
import org.springframework.beans.propertyeditors.PropertiesEditor;
|
||||
import org.springframework.beans.propertyeditors.ReaderEditor;
|
||||
@@ -87,11 +88,21 @@ import org.springframework.util.ClassUtils;
|
||||
*/
|
||||
public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
|
||||
|
||||
private static Class<?> pathClass;
|
||||
|
||||
private static Class<?> zoneIdClass;
|
||||
|
||||
static {
|
||||
ClassLoader cl = PropertyEditorRegistrySupport.class.getClassLoader();
|
||||
try {
|
||||
zoneIdClass = ClassUtils.forName("java.time.ZoneId", PropertyEditorRegistrySupport.class.getClassLoader());
|
||||
pathClass = ClassUtils.forName("java.nio.file.Path", cl);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// Java 7 Path class not available
|
||||
pathClass = null;
|
||||
}
|
||||
try {
|
||||
zoneIdClass = ClassUtils.forName("java.time.ZoneId", cl);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// Java 8 ZoneId class not available
|
||||
@@ -211,6 +222,9 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
|
||||
this.defaultEditors.put(InputStream.class, new InputStreamEditor());
|
||||
this.defaultEditors.put(InputSource.class, new InputSourceEditor());
|
||||
this.defaultEditors.put(Locale.class, new LocaleEditor());
|
||||
if (pathClass != null) {
|
||||
this.defaultEditors.put(pathClass, new PathEditor());
|
||||
}
|
||||
this.defaultEditors.put(Pattern.class, new PatternEditor());
|
||||
this.defaultEditors.put(Properties.class, new PropertiesEditor());
|
||||
this.defaultEditors.put(Reader.class, new ReaderEditor());
|
||||
|
||||
@@ -269,7 +269,7 @@ class TypeConverterDelegate {
|
||||
}
|
||||
else {
|
||||
// convertedValue == null
|
||||
if (javaUtilOptionalEmpty != null && requiredType.equals(javaUtilOptionalEmpty.getClass())) {
|
||||
if (javaUtilOptionalEmpty != null && requiredType == javaUtilOptionalEmpty.getClass()) {
|
||||
convertedValue = javaUtilOptionalEmpty;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -123,7 +123,7 @@ public class BeanCreationException extends FatalBeanException {
|
||||
|
||||
/**
|
||||
* Add a related cause to this bean creation exception,
|
||||
* not being a direct cause of the failure but having occured
|
||||
* not being a direct cause of the failure but having occurred
|
||||
* earlier in the creation of the same bean instance.
|
||||
* @param ex the related cause to add
|
||||
*/
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -45,8 +45,8 @@ public class BeanNotOfRequiredTypeException extends BeansException {
|
||||
* the expected type
|
||||
*/
|
||||
public BeanNotOfRequiredTypeException(String beanName, Class<?> requiredType, Class<?> actualType) {
|
||||
super("Bean named '" + beanName + "' must be of type [" + requiredType.getName() +
|
||||
"], but was actually of type [" + actualType.getName() + "]");
|
||||
super("Bean named '" + beanName + "' is expected to be of type [" + requiredType.getName() +
|
||||
"] but was actually of type [" + actualType.getName() + "]");
|
||||
this.beanName = beanName;
|
||||
this.requiredType = requiredType;
|
||||
this.actualType = actualType;
|
||||
|
||||
+11
-7
@@ -577,7 +577,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
String autowiredBeanName = autowiredBeanNames.iterator().next();
|
||||
if (beanFactory.containsBean(autowiredBeanName)) {
|
||||
if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
|
||||
this.cachedFieldValue = new ShortcutDependencyDescriptor(desc, autowiredBeanName);
|
||||
this.cachedFieldValue = new ShortcutDependencyDescriptor(
|
||||
desc, autowiredBeanName, field.getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -661,8 +662,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
String autowiredBeanName = it.next();
|
||||
if (beanFactory.containsBean(autowiredBeanName)) {
|
||||
if (beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
|
||||
this.cachedMethodArguments[i] =
|
||||
new ShortcutDependencyDescriptor(descriptors[i], autowiredBeanName);
|
||||
this.cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
|
||||
descriptors[i], autowiredBeanName, paramTypes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -705,16 +706,19 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
@SuppressWarnings("serial")
|
||||
private static class ShortcutDependencyDescriptor extends DependencyDescriptor {
|
||||
|
||||
private final String shortcutBeanName;
|
||||
private final String shortcutName;
|
||||
|
||||
public ShortcutDependencyDescriptor(DependencyDescriptor original, String shortcutBeanName) {
|
||||
private final Class<?> requiredType;
|
||||
|
||||
public ShortcutDependencyDescriptor(DependencyDescriptor original, String shortcutName, Class<?> requiredType) {
|
||||
super(original);
|
||||
this.shortcutBeanName = shortcutBeanName;
|
||||
this.shortcutName = shortcutName;
|
||||
this.requiredType = requiredType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveShortcut(BeanFactory beanFactory) {
|
||||
return resolveCandidate(this.shortcutBeanName, beanFactory);
|
||||
return resolveCandidate(this.shortcutName, this.requiredType, beanFactory);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -208,7 +208,7 @@ public abstract class AbstractFactoryBean<T>
|
||||
* <p>Invoked on initialization of this FactoryBean in case of
|
||||
* a singleton; else, on each {@link #getObject()} call.
|
||||
* @return the object returned by this factory
|
||||
* @throws Exception if an exception occured during object creation
|
||||
* @throws Exception if an exception occurred during object creation
|
||||
* @see #getObject()
|
||||
*/
|
||||
protected abstract T createInstance() throws Exception;
|
||||
|
||||
+21
-16
@@ -172,21 +172,6 @@ public class DependencyDescriptor extends InjectionPoint implements Serializable
|
||||
throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the specified bean name, as a candidate result of the matching
|
||||
* algorithm for this dependency, to a bean instance from the given factory.
|
||||
* <p>The default implementation calls {@link BeanFactory#getBean(String)}.
|
||||
* Subclasses may provide additional arguments or other customizations.
|
||||
* @param beanName the bean name, as a candidate result for this dependency
|
||||
* @param beanFactory the associated factory
|
||||
* @return the bean instance (never {@code null})
|
||||
* @since 4.3
|
||||
* @see BeanFactory#getBean(String)
|
||||
*/
|
||||
public Object resolveCandidate(String beanName, BeanFactory beanFactory) {
|
||||
return beanFactory.getBean(beanName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a shortcut for this dependency against the given factory, for example
|
||||
* taking some pre-resolved information into account.
|
||||
@@ -196,12 +181,32 @@ public class DependencyDescriptor extends InjectionPoint implements Serializable
|
||||
* pre-cached information while still receiving {@link InjectionPoint} exposure etc.
|
||||
* @param beanFactory the associated factory
|
||||
* @return the shortcut result if any, or {@code null} if none
|
||||
* @throws BeansException if the shortcut could not be obtained
|
||||
* @since 4.3.1
|
||||
*/
|
||||
public Object resolveShortcut(BeanFactory beanFactory) {
|
||||
public Object resolveShortcut(BeanFactory beanFactory) throws BeansException {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the specified bean name, as a candidate result of the matching
|
||||
* algorithm for this dependency, to a bean instance from the given factory.
|
||||
* <p>The default implementation calls {@link BeanFactory#getBean(String)}.
|
||||
* Subclasses may provide additional arguments or other customizations.
|
||||
* @param beanName the bean name, as a candidate result for this dependency
|
||||
* @param requiredType the expected type of the bean (as an assertion)
|
||||
* @param beanFactory the associated factory
|
||||
* @return the bean instance (never {@code null})
|
||||
* @throws BeansException if the bean could not be obtained
|
||||
* @since 4.3.2
|
||||
* @see BeanFactory#getBean(String)
|
||||
*/
|
||||
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
|
||||
throws BeansException {
|
||||
|
||||
return beanFactory.getBean(beanName, requiredType);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Increase this descriptor's nesting level.
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -95,7 +95,7 @@ public class PropertiesFactoryBean extends PropertiesLoaderSupport
|
||||
* <p>Invoked on initialization of this FactoryBean in case of a
|
||||
* shared singleton; else, on each {@link #getObject()} call.
|
||||
* @return the object returned by this factory
|
||||
* @throws IOException if an exception occured during properties loading
|
||||
* @throws IOException if an exception occurred during properties loading
|
||||
* @see #mergeProperties()
|
||||
*/
|
||||
protected Properties createProperties() throws IOException {
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -115,7 +115,7 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
|
||||
Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
|
||||
Object instance;
|
||||
if (ctor == null) {
|
||||
instance = BeanUtils.instantiate(subclass);
|
||||
instance = BeanUtils.instantiateClass(subclass);
|
||||
}
|
||||
else {
|
||||
try {
|
||||
|
||||
+9
-8
@@ -609,8 +609,8 @@ class ConstructorResolver {
|
||||
private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
|
||||
ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {
|
||||
|
||||
TypeConverter converter = (this.beanFactory.getCustomTypeConverter() != null ?
|
||||
this.beanFactory.getCustomTypeConverter() : bw);
|
||||
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
|
||||
TypeConverter converter = (customConverter != null ? customConverter : bw);
|
||||
BeanDefinitionValueResolver valueResolver =
|
||||
new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
|
||||
|
||||
@@ -665,8 +665,8 @@ class ConstructorResolver {
|
||||
BeanWrapper bw, Class<?>[] paramTypes, String[] paramNames, Object methodOrCtor,
|
||||
boolean autowiring) throws UnsatisfiedDependencyException {
|
||||
|
||||
TypeConverter converter = (this.beanFactory.getCustomTypeConverter() != null ?
|
||||
this.beanFactory.getCustomTypeConverter() : bw);
|
||||
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
|
||||
TypeConverter converter = (customConverter != null ? customConverter : bw);
|
||||
|
||||
ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
|
||||
Set<ConstructorArgumentValues.ValueHolder> usedValueHolders =
|
||||
@@ -769,12 +769,13 @@ class ConstructorResolver {
|
||||
private Object[] resolvePreparedArguments(
|
||||
String beanName, RootBeanDefinition mbd, BeanWrapper bw, Member methodOrCtor, Object[] argsToResolve) {
|
||||
|
||||
Class<?>[] paramTypes = (methodOrCtor instanceof Method ?
|
||||
((Method) methodOrCtor).getParameterTypes() : ((Constructor<?>) methodOrCtor).getParameterTypes());
|
||||
TypeConverter converter = (this.beanFactory.getCustomTypeConverter() != null ?
|
||||
this.beanFactory.getCustomTypeConverter() : bw);
|
||||
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
|
||||
TypeConverter converter = (customConverter != null ? customConverter : bw);
|
||||
BeanDefinitionValueResolver valueResolver =
|
||||
new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
|
||||
Class<?>[] paramTypes = (methodOrCtor instanceof Method ?
|
||||
((Method) methodOrCtor).getParameterTypes() : ((Constructor<?>) methodOrCtor).getParameterTypes());
|
||||
|
||||
Object[] resolvedArgs = new Object[argsToResolve.length];
|
||||
for (int argIndex = 0; argIndex < argsToResolve.length; argIndex++) {
|
||||
Object argValue = argsToResolve[argIndex];
|
||||
|
||||
+41
-14
@@ -52,6 +52,7 @@ import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
|
||||
import org.springframework.beans.factory.CannotLoadBeanClassException;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InjectionPoint;
|
||||
@@ -1002,7 +1003,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
|
||||
|
||||
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
|
||||
if (descriptor.getDependencyType().equals(javaUtilOptionalClass)) {
|
||||
if (javaUtilOptionalClass == descriptor.getDependencyType()) {
|
||||
return new OptionalDependencyFactory().createOptionalDependency(descriptor, beanName);
|
||||
}
|
||||
else if (ObjectFactory.class == descriptor.getDependencyType() ||
|
||||
@@ -1053,7 +1054,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
|
||||
if (matchingBeans.isEmpty()) {
|
||||
if (descriptor.isRequired()) {
|
||||
raiseNoSuchBeanDefinitionException(type, descriptor.getResolvableType().toString(), descriptor);
|
||||
raiseNoMatchingBeanFound(type, descriptor.getResolvableType().toString(), descriptor);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -1210,7 +1211,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
}
|
||||
for (String candidateName : candidateNames) {
|
||||
if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, descriptor)) {
|
||||
result.put(candidateName, descriptor.resolveCandidate(candidateName, this));
|
||||
result.put(candidateName, descriptor.resolveCandidate(candidateName, requiredType, this));
|
||||
}
|
||||
}
|
||||
if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) {
|
||||
@@ -1218,14 +1219,14 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
|
||||
for (String candidateName : candidateNames) {
|
||||
if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, fallbackDescriptor)) {
|
||||
result.put(candidateName, descriptor.resolveCandidate(candidateName, this));
|
||||
result.put(candidateName, descriptor.resolveCandidate(candidateName, requiredType, this));
|
||||
}
|
||||
}
|
||||
if (result.isEmpty()) {
|
||||
// Consider self references before as a final pass
|
||||
for (String candidateName : candidateNames) {
|
||||
if (isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, fallbackDescriptor)) {
|
||||
result.put(candidateName, descriptor.resolveCandidate(candidateName, this));
|
||||
result.put(candidateName, descriptor.resolveCandidate(candidateName, requiredType, this));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1392,17 +1393,43 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
}
|
||||
|
||||
/**
|
||||
* Raise a NoSuchBeanDefinitionException for an unresolvable dependency.
|
||||
* Raise a NoSuchBeanDefinitionException or BeanNotOfRequiredTypeException
|
||||
* for an unresolvable dependency.
|
||||
*/
|
||||
private void raiseNoSuchBeanDefinitionException(
|
||||
Class<?> type, String dependencyDescription, DependencyDescriptor descriptor)
|
||||
throws NoSuchBeanDefinitionException {
|
||||
private void raiseNoMatchingBeanFound(
|
||||
Class<?> type, String dependencyDescription, DependencyDescriptor descriptor) throws BeansException {
|
||||
|
||||
checkBeanNotOfRequiredType(type, descriptor);
|
||||
|
||||
throw new NoSuchBeanDefinitionException(type, dependencyDescription,
|
||||
"expected at least 1 bean which qualifies as autowire candidate for this dependency. " +
|
||||
"Dependency annotations: " + ObjectUtils.nullSafeToString(descriptor.getAnnotations()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Raise a BeanNotOfRequiredTypeException for an unresolvable dependency, if applicable,
|
||||
* i.e. if the target type of the bean would match but an exposed proxy doesn't.
|
||||
*/
|
||||
private void checkBeanNotOfRequiredType(Class<?> type, DependencyDescriptor descriptor) {
|
||||
for (String beanName : this.beanDefinitionNames) {
|
||||
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
|
||||
Class<?> targetType = mbd.getTargetType();
|
||||
if (targetType != null && type.isAssignableFrom(targetType) &&
|
||||
isAutowireCandidate(beanName, mbd, descriptor, getAutowireCandidateResolver())) {
|
||||
// Probably a poxy interfering with target type match -> throw meaningful exception.
|
||||
Object beanInstance = getSingleton(beanName, false);
|
||||
Class<?> beanType = (beanInstance != null ? beanInstance.getClass() : predictBeanType(beanName, mbd));
|
||||
if (type != beanType) {
|
||||
throw new BeanNotOfRequiredTypeException(beanName, type, beanType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (getParentBeanFactory() instanceof DefaultListableBeanFactory) {
|
||||
((DefaultListableBeanFactory) getParentBeanFactory()).checkBeanNotOfRequiredType(type, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
@@ -1479,9 +1506,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public Object resolveCandidate(String beanName, BeanFactory beanFactory) {
|
||||
return (!ObjectUtils.isEmpty(args) ? beanFactory.getBean(beanName, args) :
|
||||
super.resolveCandidate(beanName, beanFactory));
|
||||
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory) {
|
||||
return (!ObjectUtils.isEmpty(args) ? beanFactory.getBean(beanName, requiredType, args) :
|
||||
super.resolveCandidate(beanName, requiredType, beanFactory));
|
||||
}
|
||||
};
|
||||
descriptorToUse.increaseNestingLevel();
|
||||
@@ -1526,8 +1553,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
else {
|
||||
DependencyDescriptor descriptorToUse = new DependencyDescriptor(descriptor) {
|
||||
@Override
|
||||
public Object resolveCandidate(String beanName, BeanFactory beanFactory) {
|
||||
return beanFactory.getBean(beanName, args);
|
||||
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory) {
|
||||
return ((AbstractBeanFactory) beanFactory).getBean(beanName, requiredType, args);
|
||||
}
|
||||
};
|
||||
return doResolveDependency(descriptorToUse, this.beanName, null, null);
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -449,10 +449,10 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
|
||||
}
|
||||
|
||||
private boolean isDependent(String beanName, String dependentBeanName, Set<String> alreadySeen) {
|
||||
String canonicalName = canonicalName(beanName);
|
||||
if (alreadySeen != null && alreadySeen.contains(beanName)) {
|
||||
return false;
|
||||
}
|
||||
String canonicalName = canonicalName(beanName);
|
||||
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
|
||||
if (dependentBeans == null) {
|
||||
return false;
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -125,7 +125,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
setBeanClass(beanClass);
|
||||
setAutowireMode(autowireMode);
|
||||
if (dependencyCheck && getResolvedAutowireMode() != AUTOWIRE_CONSTRUCTOR) {
|
||||
setDependencyCheck(RootBeanDefinition.DEPENDENCY_CHECK_OBJECTS);
|
||||
setDependencyCheck(DEPENDENCY_CHECK_OBJECTS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -81,7 +81,7 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
|
||||
}
|
||||
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Throwable ex) {
|
||||
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -154,9 +154,9 @@ public class CustomCollectionEditor extends PropertyEditorSupport {
|
||||
try {
|
||||
return collectionType.newInstance();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalArgumentException(
|
||||
"Could not instantiate collection class [" + collectionType.getName() + "]: " + ex.getMessage());
|
||||
"Could not instantiate collection class: " + collectionType.getName(), ex);
|
||||
}
|
||||
}
|
||||
else if (List.class == collectionType) {
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -132,9 +132,9 @@ public class CustomMapEditor extends PropertyEditorSupport {
|
||||
try {
|
||||
return mapType.newInstance();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalArgumentException(
|
||||
"Could not instantiate map class [" + mapType.getName() + "]: " + ex.getMessage());
|
||||
"Could not instantiate map class: " + mapType.getName(), ex);
|
||||
}
|
||||
}
|
||||
else if (SortedMap.class == mapType) {
|
||||
|
||||
+4
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -59,16 +59,14 @@ public class FileEditor extends PropertyEditorSupport {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new FileEditor,
|
||||
* using the default ResourceEditor underneath.
|
||||
* Create a new FileEditor, using a default ResourceEditor underneath.
|
||||
*/
|
||||
public FileEditor() {
|
||||
this.resourceEditor = new ResourceEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new FileEditor,
|
||||
* using the given ResourceEditor underneath.
|
||||
* Create a new FileEditor, using the given ResourceEditor underneath.
|
||||
* @param resourceEditor the ResourceEditor to use
|
||||
*/
|
||||
public FileEditor(ResourceEditor resourceEditor) {
|
||||
@@ -105,7 +103,7 @@ public class FileEditor extends PropertyEditorSupport {
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalArgumentException(
|
||||
"Could not retrieve File for " + resource + ": " + ex.getMessage());
|
||||
"Could not retrieve file for " + resource + ": " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
+3
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -47,16 +47,14 @@ public class InputStreamEditor extends PropertyEditorSupport {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new InputStreamEditor,
|
||||
* using the default ResourceEditor underneath.
|
||||
* Create a new InputStreamEditor, using the default ResourceEditor underneath.
|
||||
*/
|
||||
public InputStreamEditor() {
|
||||
this.resourceEditor = new ResourceEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new InputStreamEditor,
|
||||
* using the given ResourceEditor underneath.
|
||||
* Create a new InputStreamEditor, using the given ResourceEditor underneath.
|
||||
* @param resourceEditor the ResourceEditor to use
|
||||
*/
|
||||
public InputStreamEditor(ResourceEditor resourceEditor) {
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2002-2016 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.
|
||||
* 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.springframework.beans.propertyeditors;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.FileSystemNotFoundException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceEditor;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.lang.UsesJava7;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Editor for {@code java.nio.file.Path}, to directly populate a Path
|
||||
* property instead of using a String property as bridge.
|
||||
*
|
||||
* <p>Based on {@link Paths#get(URI)}'s resolution algorithm, checking
|
||||
* registered NIO file system providers, including the default file system
|
||||
* for "file:..." paths. Also supports Spring-style URL notation: any fully
|
||||
* qualified standard URL and Spring's special "classpath:" pseudo-URL,
|
||||
* as well as Spring's context-specific relative file paths.
|
||||
*
|
||||
* <p>Note that, in contrast to {@link FileEditor}, relative paths are only
|
||||
* supported by Spring's resource abstraction here. Direct {@code Paths.get}
|
||||
* resolution in a file system always has to go through the corresponding
|
||||
* file system provider's scheme, i.e. "file" for the default file system.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.3.2
|
||||
* @see java.nio.file.Path
|
||||
* @see Paths#get(URI)
|
||||
* @see ResourceEditor
|
||||
* @see org.springframework.core.io.ResourceLoader
|
||||
* @see FileEditor
|
||||
* @see URLEditor
|
||||
*/
|
||||
@UsesJava7
|
||||
public class PathEditor extends PropertyEditorSupport {
|
||||
|
||||
private final ResourceEditor resourceEditor;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new PathEditor, using the default ResourceEditor underneath.
|
||||
*/
|
||||
public PathEditor() {
|
||||
this.resourceEditor = new ResourceEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new PathEditor, using the given ResourceEditor underneath.
|
||||
* @param resourceEditor the ResourceEditor to use
|
||||
*/
|
||||
public PathEditor(ResourceEditor resourceEditor) {
|
||||
Assert.notNull(resourceEditor, "ResourceEditor must not be null");
|
||||
this.resourceEditor = resourceEditor;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setAsText(String text) throws IllegalArgumentException {
|
||||
if (!text.startsWith("/") && !text.startsWith(ResourceLoader.CLASSPATH_URL_PREFIX)) {
|
||||
try {
|
||||
URI uri = new URI(text);
|
||||
if (uri.getScheme() != null) {
|
||||
// Let's try NIO file system providers via Paths.get(URI)
|
||||
setValue(Paths.get(uri).normalize());
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (URISyntaxException ex) {
|
||||
// Not a valid URI: Let's try as Spring resource location.
|
||||
}
|
||||
catch (FileSystemNotFoundException ex) {
|
||||
// URI scheme not registered for NIO:
|
||||
// Let's try URL protocol handlers via Spring's resource mechanism.
|
||||
}
|
||||
}
|
||||
|
||||
this.resourceEditor.setAsText(text);
|
||||
Resource resource = (Resource) this.resourceEditor.getValue();
|
||||
try {
|
||||
setValue(resource != null ? resource.getFile().toPath() : null);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalArgumentException("Failed to retrieve file for " + resource, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsText() {
|
||||
Path value = (Path) getValue();
|
||||
return (value != null ? value.toString() : "");
|
||||
}
|
||||
|
||||
}
|
||||
+3
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -47,16 +47,14 @@ public class ReaderEditor extends PropertyEditorSupport {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new ReaderEditor,
|
||||
* using the default ResourceEditor underneath.
|
||||
* Create a new ReaderEditor, using the default ResourceEditor underneath.
|
||||
*/
|
||||
public ReaderEditor() {
|
||||
this.resourceEditor = new ResourceEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ReaderEditor,
|
||||
* using the given ResourceEditor underneath.
|
||||
* Create a new ReaderEditor, using the given ResourceEditor underneath.
|
||||
* @param resourceEditor the ResourceEditor to use
|
||||
*/
|
||||
public ReaderEditor(ResourceEditor resourceEditor) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -60,8 +60,7 @@ public class URIEditor extends PropertyEditorSupport {
|
||||
* standard URIs (not trying to resolve them into physical resources).
|
||||
*/
|
||||
public URIEditor() {
|
||||
this.classLoader = null;
|
||||
this.encode = true;
|
||||
this(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,7 +73,6 @@ public class URIEditor extends PropertyEditorSupport {
|
||||
this.encode = encode;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new URIEditor, using the given ClassLoader to resolve
|
||||
* "classpath:" locations into physical resource URLs.
|
||||
@@ -82,8 +80,7 @@ public class URIEditor extends PropertyEditorSupport {
|
||||
* (may be {@code null} to indicate the default ClassLoader)
|
||||
*/
|
||||
public URIEditor(ClassLoader classLoader) {
|
||||
this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
|
||||
this.encode = true;
|
||||
this(classLoader, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 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,7 +50,7 @@ public class URLEditor extends PropertyEditorSupport {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new URLEditor, using the default ResourceEditor underneath.
|
||||
* Create a new URLEditor, using a default ResourceEditor underneath.
|
||||
*/
|
||||
public URLEditor() {
|
||||
this.resourceEditor = new ResourceEditor();
|
||||
|
||||
+19
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -33,6 +33,7 @@ import org.springframework.beans.propertyeditors.ClassEditor;
|
||||
import org.springframework.beans.propertyeditors.FileEditor;
|
||||
import org.springframework.beans.propertyeditors.InputSourceEditor;
|
||||
import org.springframework.beans.propertyeditors.InputStreamEditor;
|
||||
import org.springframework.beans.propertyeditors.PathEditor;
|
||||
import org.springframework.beans.propertyeditors.ReaderEditor;
|
||||
import org.springframework.beans.propertyeditors.URIEditor;
|
||||
import org.springframework.beans.propertyeditors.URLEditor;
|
||||
@@ -43,6 +44,7 @@ import org.springframework.core.io.ResourceEditor;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.support.ResourceArrayPropertyEditor;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* PropertyEditorRegistrar implementation that populates a given
|
||||
@@ -58,6 +60,19 @@ import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
*/
|
||||
public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
|
||||
|
||||
private static Class<?> pathClass;
|
||||
|
||||
static {
|
||||
try {
|
||||
pathClass = ClassUtils.forName("java.nio.file.Path", ResourceEditorRegistrar.class.getClassLoader());
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// Java 7 Path class not available
|
||||
pathClass = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private final PropertyResolver propertyResolver;
|
||||
|
||||
private final ResourceLoader resourceLoader;
|
||||
@@ -103,6 +118,9 @@ public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
|
||||
doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor));
|
||||
doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor));
|
||||
doRegisterEditor(registry, File.class, new FileEditor(baseEditor));
|
||||
if (pathClass != null) {
|
||||
doRegisterEditor(registry, pathClass, new PathEditor(baseEditor));
|
||||
}
|
||||
doRegisterEditor(registry, Reader.class, new ReaderEditor(baseEditor));
|
||||
doRegisterEditor(registry, URL.class, new URLEditor(baseEditor));
|
||||
|
||||
|
||||
+10
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -29,20 +29,20 @@ import static org.junit.Assert.*;
|
||||
* @author Thomas Risberg
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class FileEditorTests {
|
||||
public class FileEditorTests {
|
||||
|
||||
@Test
|
||||
public void testClasspathFileName() throws Exception {
|
||||
PropertyEditor fileEditor = new FileEditor();
|
||||
fileEditor.setAsText("classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) + "/"
|
||||
+ ClassUtils.getShortName(getClass()) + ".class");
|
||||
fileEditor.setAsText("classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
|
||||
ClassUtils.getShortName(getClass()) + ".class");
|
||||
Object value = fileEditor.getValue();
|
||||
assertTrue(value instanceof File);
|
||||
File file = (File) value;
|
||||
assertTrue(file.exists());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testWithNonExistentResource() throws Exception {
|
||||
PropertyEditor propertyEditor = new FileEditor();
|
||||
propertyEditor.setAsText("classpath:no_way_this_file_is_found.doc");
|
||||
@@ -71,8 +71,8 @@ public final class FileEditorTests {
|
||||
@Test
|
||||
public void testUnqualifiedFileNameFound() throws Exception {
|
||||
PropertyEditor fileEditor = new FileEditor();
|
||||
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" + ClassUtils.getShortName(getClass())
|
||||
+ ".class";
|
||||
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
|
||||
ClassUtils.getShortName(getClass()) + ".class";
|
||||
fileEditor.setAsText(fileName);
|
||||
Object value = fileEditor.getValue();
|
||||
assertTrue(value instanceof File);
|
||||
@@ -88,8 +88,8 @@ public final class FileEditorTests {
|
||||
@Test
|
||||
public void testUnqualifiedFileNameNotFound() throws Exception {
|
||||
PropertyEditor fileEditor = new FileEditor();
|
||||
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" + ClassUtils.getShortName(getClass())
|
||||
+ ".clazz";
|
||||
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
|
||||
ClassUtils.getShortName(getClass()) + ".clazz";
|
||||
fileEditor.setAsText(fileName);
|
||||
Object value = fileEditor.getValue();
|
||||
assertTrue(value instanceof File);
|
||||
@@ -101,4 +101,5 @@ public final class FileEditorTests {
|
||||
}
|
||||
assertTrue(absolutePath.endsWith(fileName));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -60,9 +60,8 @@ public class InputStreamEditorTests {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testWhenResourceDoesNotExist() throws Exception {
|
||||
String resource = "classpath:bingo!";
|
||||
InputStreamEditor editor = new InputStreamEditor();
|
||||
editor.setAsText(resource);
|
||||
editor.setAsText("classpath:bingo!");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2002-2016 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.
|
||||
* 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.springframework.beans.propertyeditors;
|
||||
|
||||
import java.beans.PropertyEditor;
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.3.2
|
||||
*/
|
||||
public class PathEditorTests {
|
||||
|
||||
@Test
|
||||
public void testClasspathPathName() throws Exception {
|
||||
PropertyEditor pathEditor = new PathEditor();
|
||||
pathEditor.setAsText("classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
|
||||
ClassUtils.getShortName(getClass()) + ".class");
|
||||
Object value = pathEditor.getValue();
|
||||
assertTrue(value instanceof Path);
|
||||
Path path = (Path) value;
|
||||
assertTrue(path.toFile().exists());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testWithNonExistentResource() throws Exception {
|
||||
PropertyEditor propertyEditor = new PathEditor();
|
||||
propertyEditor.setAsText("classpath:/no_way_this_file_is_found.doc");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithNonExistentPath() throws Exception {
|
||||
PropertyEditor pathEditor = new PathEditor();
|
||||
pathEditor.setAsText("file:/no_way_this_file_is_found.doc");
|
||||
Object value = pathEditor.getValue();
|
||||
assertTrue(value instanceof Path);
|
||||
Path path = (Path) value;
|
||||
assertTrue(!path.toFile().exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnqualifiedPathNameFound() throws Exception {
|
||||
PropertyEditor pathEditor = new PathEditor();
|
||||
String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" +
|
||||
ClassUtils.getShortName(getClass()) + ".class";
|
||||
pathEditor.setAsText(fileName);
|
||||
Object value = pathEditor.getValue();
|
||||
assertTrue(value instanceof Path);
|
||||
Path path = (Path) value;
|
||||
File file = path.toFile();
|
||||
assertTrue(file.exists());
|
||||
String absolutePath = file.getAbsolutePath();
|
||||
if (File.separatorChar == '\\') {
|
||||
absolutePath = absolutePath.replace('\\', '/');
|
||||
}
|
||||
assertTrue(absolutePath.endsWith(fileName));
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -34,7 +34,7 @@ public class ReaderEditorTests {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testCtorWithNullResourceEditor() throws Exception {
|
||||
new InputStreamEditor(null);
|
||||
new ReaderEditor(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+11
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -31,15 +31,6 @@ import static org.junit.Assert.*;
|
||||
*/
|
||||
public class URIEditorTests {
|
||||
|
||||
private void doTestURI(String uriSpec) {
|
||||
PropertyEditor uriEditor = new URIEditor();
|
||||
uriEditor.setAsText(uriSpec);
|
||||
Object value = uriEditor.getValue();
|
||||
assertTrue(value instanceof URI);
|
||||
URI uri = (URI) value;
|
||||
assertEquals(uriSpec, uri.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void standardURI() throws Exception {
|
||||
doTestURI("mailto:juergen.hoeller@interface21.com");
|
||||
@@ -141,4 +132,14 @@ public class URIEditorTests {
|
||||
assertEquals("http://example.com/spaces%20and%20%E2%82%AC", uri.toASCIIString());
|
||||
}
|
||||
|
||||
|
||||
private void doTestURI(String uriSpec) {
|
||||
PropertyEditor uriEditor = new URIEditor();
|
||||
uriEditor.setAsText(uriSpec);
|
||||
Object value = uriEditor.getValue();
|
||||
assertTrue(value instanceof URI);
|
||||
URI uri = (URI) value;
|
||||
assertEquals(uriSpec, uri.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+8
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -29,7 +29,12 @@ import static org.junit.Assert.*;
|
||||
* @author Rick Evans
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class URLEditorTests {
|
||||
public class URLEditorTests {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testCtorWithNullResourceEditor() throws Exception {
|
||||
new URLEditor(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStandardURI() throws Exception {
|
||||
@@ -63,7 +68,7 @@ public final class URLEditorTests {
|
||||
assertTrue(!url.getProtocol().startsWith("classpath"));
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testWithNonExistentResource() throws Exception {
|
||||
PropertyEditor urlEditor = new URLEditor();
|
||||
urlEditor.setAsText("gonna:/freak/in/the/morning/freak/in/the.evening");
|
||||
@@ -83,9 +88,4 @@ public final class URLEditorTests {
|
||||
assertEquals("", urlEditor.getAsText());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testCtorWithNullResourceEditor() throws Exception {
|
||||
new URLEditor(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
|
||||
+1
-1
@@ -7,6 +7,6 @@
|
||||
* <p>Note: EhCache 3.x lives in a different package namespace
|
||||
* and is not covered by the traditional support classes here.
|
||||
* Instead, consider using it through JCache (JSR-107), with
|
||||
* Spring's support in {@link org.springframework.cache.jcache}.
|
||||
* Spring's support in {@code org.springframework.cache.jcache}.
|
||||
*/
|
||||
package org.springframework.cache.ehcache;
|
||||
|
||||
Vendored
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -52,7 +52,7 @@ public class CachingConfigurationSelector extends AdviceModeImportSelector<Enabl
|
||||
private static final boolean jsr107Present = ClassUtils.isPresent(
|
||||
"javax.cache.Cache", CachingConfigurationSelector.class.getClassLoader());
|
||||
|
||||
private static final boolean jCacheImplPresent = ClassUtils.isPresent(
|
||||
private static final boolean jcacheImplPresent = ClassUtils.isPresent(
|
||||
PROXY_JCACHE_CONFIGURATION_CLASS, CachingConfigurationSelector.class.getClassLoader());
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ public class CachingConfigurationSelector extends AdviceModeImportSelector<Enabl
|
||||
List<String> result = new ArrayList<String>();
|
||||
result.add(AutoProxyRegistrar.class.getName());
|
||||
result.add(ProxyCachingConfiguration.class.getName());
|
||||
if (jsr107Present && jCacheImplPresent) {
|
||||
if (jsr107Present && jcacheImplPresent) {
|
||||
result.add(PROXY_JCACHE_CONFIGURATION_CLASS);
|
||||
}
|
||||
return result.toArray(new String[result.size()]);
|
||||
@@ -94,7 +94,7 @@ public class CachingConfigurationSelector extends AdviceModeImportSelector<Enabl
|
||||
private String[] getAspectJImports() {
|
||||
List<String> result = new ArrayList<String>();
|
||||
result.add(CACHE_ASPECT_CONFIGURATION_CLASS_NAME);
|
||||
if (jsr107Present && jCacheImplPresent) {
|
||||
if (jsr107Present && jcacheImplPresent) {
|
||||
result.add(JCACHE_ASPECT_CONFIGURATION_CLASS_NAME);
|
||||
}
|
||||
return result.toArray(new String[result.size()]);
|
||||
|
||||
+4
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -60,11 +60,10 @@ class AnnotationDrivenCacheBeanDefinitionParser implements BeanDefinitionParser
|
||||
private static final String JCACHE_ASPECT_CLASS_NAME =
|
||||
"org.springframework.cache.aspectj.JCacheCacheAspect";
|
||||
|
||||
|
||||
private static final boolean jsr107Present = ClassUtils.isPresent(
|
||||
"javax.cache.Cache", AnnotationDrivenCacheBeanDefinitionParser.class.getClassLoader());
|
||||
|
||||
private static final boolean jCacheImplPresent = ClassUtils.isPresent(
|
||||
private static final boolean jcacheImplPresent = ClassUtils.isPresent(
|
||||
"org.springframework.cache.jcache.interceptor.DefaultJCacheOperationSource",
|
||||
AnnotationDrivenCacheBeanDefinitionParser.class.getClassLoader());
|
||||
|
||||
@@ -91,7 +90,7 @@ class AnnotationDrivenCacheBeanDefinitionParser implements BeanDefinitionParser
|
||||
|
||||
private void registerCacheAspect(Element element, ParserContext parserContext) {
|
||||
SpringCachingConfigurer.registerCacheAspect(element, parserContext);
|
||||
if (jsr107Present && jCacheImplPresent) { // Register JCache aspect
|
||||
if (jsr107Present && jcacheImplPresent) {
|
||||
JCacheCachingConfigurer.registerCacheAspect(element, parserContext);
|
||||
}
|
||||
}
|
||||
@@ -99,7 +98,7 @@ class AnnotationDrivenCacheBeanDefinitionParser implements BeanDefinitionParser
|
||||
private void registerCacheAdvisor(Element element, ParserContext parserContext) {
|
||||
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
|
||||
SpringCachingConfigurer.registerCacheAdvisor(element, parserContext);
|
||||
if (jsr107Present && jCacheImplPresent) { // Register JCache advisor
|
||||
if (jsr107Present && jcacheImplPresent) {
|
||||
JCacheCachingConfigurer.registerCacheAdvisor(element, parserContext);
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+2
-3
@@ -30,9 +30,8 @@ package org.springframework.cache.interceptor;
|
||||
public interface CacheOperationInvoker {
|
||||
|
||||
/**
|
||||
* Invoke the cache operation defined by this instance. Wraps any
|
||||
* exception that is thrown during the invocation in a
|
||||
* {@link ThrowableWrapper}.
|
||||
* Invoke the cache operation defined by this instance. Wraps any exception
|
||||
* that is thrown during the invocation in a {@link ThrowableWrapper}.
|
||||
* @return the result of the operation
|
||||
* @throws ThrowableWrapper if an error occurred while invoking the operation
|
||||
*/
|
||||
|
||||
+6
-1
@@ -102,7 +102,12 @@ public class NoOpCacheManager implements CacheManager {
|
||||
|
||||
@Override
|
||||
public <T> T get(Object key, Callable<T> valueLoader) {
|
||||
return null;
|
||||
try {
|
||||
return valueLoader.call();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new ValueRetrievalException(key, valueLoader, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+5
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -127,15 +127,13 @@ public class AnnotatedBeanDefinitionReader {
|
||||
registerBean(annotatedClass, null, (Class<? extends Annotation>[]) null);
|
||||
}
|
||||
|
||||
public void registerBean(Class<?> annotatedClass,
|
||||
@SuppressWarnings("unchecked") Class<? extends Annotation>... qualifiers) {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void registerBean(Class<?> annotatedClass, Class<? extends Annotation>... qualifiers) {
|
||||
registerBean(annotatedClass, null, qualifiers);
|
||||
}
|
||||
|
||||
public void registerBean(Class<?> annotatedClass, String name,
|
||||
@SuppressWarnings("unchecked") Class<? extends Annotation>... qualifiers) {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>... qualifiers) {
|
||||
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
|
||||
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
|
||||
return;
|
||||
|
||||
+4
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -79,9 +79,10 @@ public class AnnotationScopeMetadataResolver implements ScopeMetadataResolver {
|
||||
ScopeMetadata metadata = new ScopeMetadata();
|
||||
if (definition instanceof AnnotatedBeanDefinition) {
|
||||
AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
|
||||
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(annDef.getMetadata(), this.scopeAnnotationType);
|
||||
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
|
||||
annDef.getMetadata(), this.scopeAnnotationType);
|
||||
if (attributes != null) {
|
||||
metadata.setScopeName(attributes.getAliasedString("value", this.scopeAnnotationType, definition.getSource()));
|
||||
metadata.setScopeName(attributes.getString("value"));
|
||||
ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
|
||||
if (proxyMode == null || proxyMode == ScopedProxyMode.DEFAULT) {
|
||||
proxyMode = this.defaultProxyMode;
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -79,7 +79,7 @@ public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
|
||||
logger.warn(String.format("%s was imported but no annotations were found " +
|
||||
"having both 'mode' and 'proxyTargetClass' attributes of type " +
|
||||
"AdviceMode and boolean respectively. This means that auto proxy " +
|
||||
"creator registration and configuration may not have occured as " +
|
||||
"creator registration and configuration may not have occurred as " +
|
||||
"intended, and components may not be proxied as expected. Check to " +
|
||||
"ensure that %s has been @Import'ed on the same class where these " +
|
||||
"annotations are declared; otherwise remove the import of %s " +
|
||||
|
||||
+4
-4
@@ -122,7 +122,7 @@ class ComponentScanAnnotationParser {
|
||||
}
|
||||
|
||||
Set<String> basePackages = new LinkedHashSet<String>();
|
||||
String[] basePackagesArray = componentScan.getAliasedStringArray("basePackages", ComponentScan.class, declaringClass);
|
||||
String[] basePackagesArray = componentScan.getStringArray("basePackages");
|
||||
for (String pkg : basePackagesArray) {
|
||||
String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
|
||||
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
|
||||
@@ -148,11 +148,11 @@ class ComponentScanAnnotationParser {
|
||||
List<TypeFilter> typeFilters = new ArrayList<TypeFilter>();
|
||||
FilterType filterType = filterAttributes.getEnum("type");
|
||||
|
||||
for (Class<?> filterClass : filterAttributes.getAliasedClassArray("classes", ComponentScan.Filter.class, null)) {
|
||||
for (Class<?> filterClass : filterAttributes.getClassArray("classes")) {
|
||||
switch (filterType) {
|
||||
case ANNOTATION:
|
||||
Assert.isAssignable(Annotation.class, filterClass,
|
||||
"An error occured while processing a @ComponentScan ANNOTATION type filter: ");
|
||||
"An error occurred while processing a @ComponentScan ANNOTATION type filter: ");
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<Annotation> annotationType = (Class<Annotation>) filterClass;
|
||||
typeFilters.add(new AnnotationTypeFilter(annotationType));
|
||||
@@ -162,7 +162,7 @@ class ComponentScanAnnotationParser {
|
||||
break;
|
||||
case CUSTOM:
|
||||
Assert.isAssignable(TypeFilter.class, filterClass,
|
||||
"An error occured while processing a @ComponentScan CUSTOM type filter: ");
|
||||
"An error occurred while processing a @ComponentScan CUSTOM type filter: ");
|
||||
TypeFilter filter = BeanUtils.instantiateClass(filterClass, TypeFilter.class);
|
||||
invokeAwareMethods(filter);
|
||||
typeFilters.add(filter);
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -233,7 +233,7 @@ final class ConfigurationClass {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ConfigurationClass:beanName=" + this.beanName + ",resource=" + this.resource;
|
||||
return "ConfigurationClass: beanName '" + this.beanName + "', " + this.resource;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -236,7 +236,7 @@ class ConfigurationClassBeanDefinitionReader {
|
||||
ScopedProxyMode proxyMode = ScopedProxyMode.NO;
|
||||
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
|
||||
if (attributes != null) {
|
||||
beanDef.setScope(attributes.getAliasedString("value", Scope.class, configClass.getResource()));
|
||||
beanDef.setScope(attributes.getString("value"));
|
||||
proxyMode = attributes.getEnum("proxyMode");
|
||||
if (proxyMode == ScopedProxyMode.DEFAULT) {
|
||||
proxyMode = ScopedProxyMode.NO;
|
||||
|
||||
+1
-1
@@ -466,7 +466,7 @@ class ConfigurationClassEnhancer {
|
||||
try {
|
||||
fbProxy = fbClass.newInstance();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalStateException("Unable to instantiate enhanced FactoryBean using Objenesis, " +
|
||||
"and regular FactoryBean instantiation via default constructor fails as well", ex);
|
||||
}
|
||||
|
||||
+23
-8
@@ -182,7 +182,7 @@ class ConfigurationClassParser {
|
||||
catch (BeanDefinitionStoreException ex) {
|
||||
throw ex;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Throwable ex) {
|
||||
throw new BeanDefinitionStoreException(
|
||||
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
|
||||
}
|
||||
@@ -287,8 +287,9 @@ class ConfigurationClassParser {
|
||||
|
||||
// Process any @ImportResource annotations
|
||||
if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {
|
||||
AnnotationAttributes importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
|
||||
String[] resources = importResource.getAliasedStringArray("locations", ImportResource.class, sourceClass);
|
||||
AnnotationAttributes importResource =
|
||||
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
|
||||
String[] resources = importResource.getStringArray("locations");
|
||||
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
|
||||
for (String resource : resources) {
|
||||
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
|
||||
@@ -378,7 +379,7 @@ class ConfigurationClassParser {
|
||||
|
||||
Class<? extends PropertySourceFactory> factoryClass = propertySource.getClass("factory");
|
||||
PropertySourceFactory factory = (factoryClass == PropertySourceFactory.class ?
|
||||
DEFAULT_PROPERTY_SOURCE_FACTORY : BeanUtils.instantiate(factoryClass));
|
||||
DEFAULT_PROPERTY_SOURCE_FACTORY : BeanUtils.instantiateClass(factoryClass));
|
||||
|
||||
for (String location : locations) {
|
||||
try {
|
||||
@@ -483,7 +484,7 @@ class ConfigurationClassParser {
|
||||
catch (BeanDefinitionStoreException ex) {
|
||||
throw ex;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Throwable ex) {
|
||||
throw new BeanDefinitionStoreException("Failed to process import candidates for configuration class [" +
|
||||
configClass.getMetadata().getClassName() + "]", ex);
|
||||
}
|
||||
@@ -497,7 +498,7 @@ class ConfigurationClassParser {
|
||||
return;
|
||||
}
|
||||
|
||||
if (checkForCircularImports && this.importStack.contains(configClass)) {
|
||||
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
|
||||
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
|
||||
}
|
||||
else {
|
||||
@@ -540,7 +541,7 @@ class ConfigurationClassParser {
|
||||
catch (BeanDefinitionStoreException ex) {
|
||||
throw ex;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Throwable ex) {
|
||||
throw new BeanDefinitionStoreException("Failed to process import candidates for configuration class [" +
|
||||
configClass.getMetadata().getClassName() + "]", ex);
|
||||
}
|
||||
@@ -550,6 +551,20 @@ class ConfigurationClassParser {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isChainedImportOnStack(ConfigurationClass configClass) {
|
||||
if (this.importStack.contains(configClass)) {
|
||||
String configClassName = configClass.getMetadata().getClassName();
|
||||
AnnotationMetadata importingClass = this.importStack.getImportingClassFor(configClassName);
|
||||
while (importingClass != null) {
|
||||
if (configClassName.equals(importingClass.getClassName())) {
|
||||
return true;
|
||||
}
|
||||
importingClass = this.importStack.getImportingClassFor(importingClass.getClassName());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke {@link ResourceLoaderAware}, {@link BeanClassLoaderAware} and
|
||||
* {@link BeanFactoryAware} contracts if implemented by the given {@code bean}.
|
||||
@@ -856,7 +871,7 @@ class ConfigurationClassParser {
|
||||
private SourceClass getRelated(String className) throws IOException {
|
||||
if (this.source instanceof Class<?>) {
|
||||
try {
|
||||
Class<?> clazz = resourceLoader.getClassLoader().loadClass(className);
|
||||
Class<?> clazz = ((Class<?>) this.source).getClassLoader().loadClass(className);
|
||||
return asSourceClass(clazz);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
|
||||
+2
-1
@@ -34,6 +34,7 @@ import org.springframework.util.ObjectUtils;
|
||||
* </ol>
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Sergey Podgurskiy
|
||||
* @since 4.2
|
||||
*/
|
||||
public class MethodBasedEvaluationContext extends StandardEvaluationContext {
|
||||
@@ -89,7 +90,7 @@ public class MethodBasedEvaluationContext extends StandardEvaluationContext {
|
||||
String[] parameterNames = this.paramDiscoverer.getParameterNames(this.method);
|
||||
// save parameter names (if discovered)
|
||||
if (parameterNames != null) {
|
||||
for (int i = 0; i < parameterNames.length; i++) {
|
||||
for (int i = 0; i < this.args.length; i++) {
|
||||
setVariable(parameterNames[i], this.args[i]);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -26,8 +26,8 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.instrument.classloading.LoadTimeWeaver} implementation for Tomcat's
|
||||
* new {@link org.apache.tomcat.InstrumentableClassLoader InstrumentableClassLoader}.
|
||||
* {@link org.springframework.instrument.classloading.LoadTimeWeaver} implementation
|
||||
* for Tomcat's new {@code org.apache.tomcat.InstrumentableClassLoader}.
|
||||
* Also capable of handling Spring's TomcatInstrumentableClassLoader when encountered.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
|
||||
+1
-1
@@ -135,7 +135,7 @@ public class AnnotationJmxAttributeSource implements JmxAttributeSource, BeanFac
|
||||
if (ann == null) {
|
||||
return null;
|
||||
}
|
||||
T bean = BeanUtils.instantiate(beanClass);
|
||||
T bean = BeanUtils.instantiateClass(beanClass);
|
||||
AnnotationBeanUtils.copyPropertiesToBean(ann, bean);
|
||||
return bean;
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -72,7 +72,7 @@ public class MethodNameBasedMBeanInfoAssembler extends AbstractConfigurableMBean
|
||||
* @param methodNames an array of method names indicating the methods to use
|
||||
* @see #setMethodMappings
|
||||
*/
|
||||
public void setManagedMethods(String[] methodNames) {
|
||||
public void setManagedMethods(String... methodNames) {
|
||||
this.managedMethods = new HashSet<String>(Arrays.asList(methodNames));
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -138,7 +138,7 @@ public class ConnectorServerFactoryBean extends MBeanRegistrationSupport
|
||||
* the {@code JMXConnectorServer} will be started in a separate thread.
|
||||
* If the {@code daemon} flag is set to {@code true}, that thread will be
|
||||
* started as a daemon thread.
|
||||
* @throws JMException if a problem occured when registering the connector server
|
||||
* @throws JMException if a problem occurred when registering the connector server
|
||||
* with the {@code MBeanServer}
|
||||
* @throws IOException if there is a problem starting the connector server
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -78,6 +78,15 @@ public class JndiPropertySource extends PropertySource<JndiLocatorDelegate> {
|
||||
*/
|
||||
@Override
|
||||
public Object getProperty(String name) {
|
||||
if (getSource().isResourceRef() && name.indexOf(':') != -1) {
|
||||
// We're in resource-ref (prefixing with "java:comp/env") mode. Let's not bother
|
||||
// with property names with a colon it since they're probably just containing a
|
||||
// default value clause, very unlikely to match including the colon part even in
|
||||
// a textual property source, and effectively never meant to match that way in
|
||||
// JNDI where a colon indicates a separator between JNDI scheme and actual name.
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
Object value = this.source.lookup(name);
|
||||
if (logger.isDebugEnabled()) {
|
||||
|
||||
+6
@@ -95,6 +95,7 @@ public class CronSequenceGenerator {
|
||||
parse(expression);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the cron pattern that this sequence generator has been built for.
|
||||
*/
|
||||
@@ -378,6 +379,10 @@ public class CronSequenceGenerator {
|
||||
throw new IllegalArgumentException("Range less than minimum (" + min + "): '" +
|
||||
field + "' in expression \"" + this.expression + "\"");
|
||||
}
|
||||
if (result[0] > result[1]) {
|
||||
throw new IllegalArgumentException("Invalid inverted range: '" + field +
|
||||
"' in expression \"" + this.expression + "\"");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -388,6 +393,7 @@ public class CronSequenceGenerator {
|
||||
* fields separated by single spaces.
|
||||
* @param expression the expression to evaluate
|
||||
* @return {@code true} if the given expression is a valid cron expression
|
||||
* @since 4.3
|
||||
*/
|
||||
public static boolean isValidExpression(String expression) {
|
||||
String[] fields = StringUtils.tokenizeToStringArray(expression, " ");
|
||||
|
||||
@@ -94,8 +94,7 @@ public abstract class BshScriptUtils {
|
||||
return clazz.newInstance();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalStateException("Could not instantiate script class [" +
|
||||
clazz.getName() + "]. Root cause is " + ex);
|
||||
throw new IllegalStateException("Could not instantiate script class: " + clazz.getName(), ex);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -28,7 +28,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Mark Fisher
|
||||
* @since 2.5
|
||||
*/
|
||||
public class ScriptingDefaultsParser implements BeanDefinitionParser {
|
||||
class ScriptingDefaultsParser implements BeanDefinitionParser {
|
||||
|
||||
private static final String REFRESH_CHECK_DELAY_ATTRIBUTE = "refresh-check-delay";
|
||||
|
||||
@@ -41,7 +41,7 @@ public class ScriptingDefaultsParser implements BeanDefinitionParser {
|
||||
LangNamespaceUtils.registerScriptFactoryPostProcessorIfNecessary(parserContext.getRegistry());
|
||||
String refreshCheckDelay = element.getAttribute(REFRESH_CHECK_DELAY_ATTRIBUTE);
|
||||
if (StringUtils.hasText(refreshCheckDelay)) {
|
||||
bd.getPropertyValues().add("defaultRefreshCheckDelay", new Long(refreshCheckDelay));
|
||||
bd.getPropertyValues().add("defaultRefreshCheckDelay", Long.valueOf(refreshCheckDelay));
|
||||
}
|
||||
String proxyTargetClass = element.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE);
|
||||
if (StringUtils.hasText(proxyTargetClass)) {
|
||||
|
||||
+1
-1
@@ -266,7 +266,7 @@ public class GroovyScriptFactory implements ScriptFactory, BeanFactoryAware, Bea
|
||||
}
|
||||
catch (InstantiationException ex) {
|
||||
throw new ScriptCompilationException(
|
||||
scriptSource, "Could not instantiate Groovy script class: " + scriptClass.getName(), ex);
|
||||
scriptSource, "Unable to instantiate Groovy script class: " + scriptClass.getName(), ex);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new ScriptCompilationException(
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -154,7 +154,7 @@ public class StandardScriptFactory implements ScriptFactory, BeanClassLoaderAwar
|
||||
}
|
||||
catch (InstantiationException ex) {
|
||||
throw new ScriptCompilationException(
|
||||
scriptSource, "Could not instantiate script class: " + scriptClass.getName(), ex);
|
||||
scriptSource, "Unable to instantiate script class: " + scriptClass.getName(), ex);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new ScriptCompilationException(
|
||||
|
||||
+5
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -27,18 +27,19 @@ import static org.junit.Assert.*;
|
||||
* @author Adrian Colyer
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class AnnotationBindingTests {
|
||||
public class AnnotationBindingTests {
|
||||
|
||||
private AnnotatedTestBean testBean;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
ClassPathXmlApplicationContext ctx =
|
||||
new ClassPathXmlApplicationContext(getClass().getSimpleName() + "-context.xml", getClass());
|
||||
|
||||
new ClassPathXmlApplicationContext(getClass().getSimpleName() + "-context.xml", getClass());
|
||||
testBean = (AnnotatedTestBean) ctx.getBean("testBean");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAnnotationBindingInAroundAdvice() {
|
||||
assertEquals("this value", testBean.doThis());
|
||||
|
||||
+43
-14
@@ -18,33 +18,33 @@ package org.springframework.cache;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.cache.support.NoOpCacheManager;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Tests for {@link NoOpCacheManager}.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class NoOpCacheManagerTests {
|
||||
|
||||
private CacheManager manager;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
manager = new NoOpCacheManager();
|
||||
}
|
||||
private final CacheManager manager = new NoOpCacheManager();
|
||||
|
||||
@Test
|
||||
public void testGetCache() throws Exception {
|
||||
Cache cache = manager.getCache("bucket");
|
||||
Cache cache = this.manager.getCache("bucket");
|
||||
assertNotNull(cache);
|
||||
assertSame(cache, manager.getCache("bucket"));
|
||||
assertSame(cache, this.manager.getCache("bucket"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoOpCache() throws Exception {
|
||||
String name = UUID.randomUUID().toString();
|
||||
Cache cache = manager.getCache(name);
|
||||
String name = createRandomKey();
|
||||
Cache cache = this.manager.getCache(name);
|
||||
assertEquals(name, cache.getName());
|
||||
Object key = new Object();
|
||||
cache.put(key, new Object());
|
||||
@@ -56,8 +56,37 @@ public class NoOpCacheManagerTests {
|
||||
@Test
|
||||
public void testCacheName() throws Exception {
|
||||
String name = "bucket";
|
||||
assertFalse(manager.getCacheNames().contains(name));
|
||||
manager.getCache(name);
|
||||
assertTrue(manager.getCacheNames().contains(name));
|
||||
assertFalse(this.manager.getCacheNames().contains(name));
|
||||
this.manager.getCache(name);
|
||||
assertTrue(this.manager.getCacheNames().contains(name));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCacheCallable() throws Exception {
|
||||
String name = createRandomKey();
|
||||
Cache cache = this.manager.getCache(name);
|
||||
Object returnValue = new Object();
|
||||
Object value = cache.get(new Object(), () -> returnValue);
|
||||
assertEquals(returnValue, value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCacheGetCallableFail() {
|
||||
Cache cache = this.manager.getCache(createRandomKey());
|
||||
String key = createRandomKey();
|
||||
try {
|
||||
cache.get(key, () -> {
|
||||
throw new UnsupportedOperationException("Expected exception");
|
||||
});
|
||||
}
|
||||
catch (Cache.ValueRetrievalException ex) {
|
||||
assertNotNull(ex.getCause());
|
||||
assertEquals(UnsupportedOperationException.class, ex.getCause().getClass());
|
||||
}
|
||||
}
|
||||
|
||||
private String createRandomKey() {
|
||||
return UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+16
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -72,58 +72,71 @@ public abstract class AbstractCircularImportDetectionTests {
|
||||
@Configuration
|
||||
@Import(B.class)
|
||||
static class A {
|
||||
|
||||
@Bean
|
||||
TestBean b1() {
|
||||
return new TestBean();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@Import(A.class)
|
||||
static class B {
|
||||
|
||||
@Bean
|
||||
TestBean b2() {
|
||||
return new TestBean();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@Import( { Y.class, Z.class })
|
||||
@Import({Y.class, Z.class})
|
||||
class X {
|
||||
|
||||
@Bean
|
||||
TestBean x() {
|
||||
return new TestBean();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
class Y {
|
||||
|
||||
@Bean
|
||||
TestBean y() {
|
||||
return new TestBean();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@Import( { Z1.class, Z2.class })
|
||||
@Import({Z1.class, Z2.class})
|
||||
class Z {
|
||||
|
||||
@Bean
|
||||
TestBean z() {
|
||||
return new TestBean();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
class Z1 {
|
||||
|
||||
@Bean
|
||||
TestBean z1() {
|
||||
return new TestBean();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@Import(Z.class)
|
||||
class Z2 {
|
||||
|
||||
@Bean
|
||||
TestBean z2() {
|
||||
return new TestBean();
|
||||
|
||||
+3
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -23,12 +23,8 @@ import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
|
||||
|
||||
/**
|
||||
* Unit test proving that ASM-based {@link ConfigurationClassParser} correctly detects circular
|
||||
* use of the {@link Import @Import} annotation.
|
||||
*
|
||||
* <p>While this test is the only subclass of {@link AbstractCircularImportDetectionTests},
|
||||
* the hierarchy remains in place in case a JDT-based ConfigurationParser implementation
|
||||
* needs to be developed.
|
||||
* Unit test proving that ASM-based {@link ConfigurationClassParser} correctly detects
|
||||
* circular use of the {@link Import @Import} annotation.
|
||||
*
|
||||
* @author Chris Beams
|
||||
*/
|
||||
|
||||
+12
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.context.annotation;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.annotation.componentscan.importing.ImportingConfig;
|
||||
import org.springframework.context.annotation.componentscan.simple.SimpleComponent;
|
||||
|
||||
/**
|
||||
@@ -58,7 +59,7 @@ public class ComponentScanAndImportAnnotationInteractionTests {
|
||||
@Test
|
||||
public void componentScanViaImportUsingAsm() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.registerBeanDefinition("config4", new RootBeanDefinition(Config3.class.getName()));
|
||||
ctx.registerBeanDefinition("config", new RootBeanDefinition(Config3.class.getName()));
|
||||
ctx.refresh();
|
||||
ctx.getBean(SimpleComponent.class);
|
||||
}
|
||||
@@ -71,6 +72,14 @@ public class ComponentScanAndImportAnnotationInteractionTests {
|
||||
ctx.getBean(SimpleComponent.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void circularImportViaComponentScan() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.registerBeanDefinition("config", new RootBeanDefinition(ImportingConfig.class.getName()));
|
||||
ctx.refresh();
|
||||
ctx.getBean(SimpleComponent.class);
|
||||
}
|
||||
|
||||
|
||||
@ComponentScan("org.springframework.context.annotation.componentscan.simple")
|
||||
static final class Config1 {
|
||||
@@ -88,6 +97,7 @@ public class ComponentScanAndImportAnnotationInteractionTests {
|
||||
|
||||
|
||||
@ComponentScan("org.springframework.context.annotation.componentscan.simple")
|
||||
@ComponentScan("org.springframework.context.annotation.componentscan.importing")
|
||||
public static final class ImportedConfig {
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -955,7 +955,7 @@ public class ConfigurationClassPostProcessorTests {
|
||||
@ComponentScan(basePackages = "org.springframework.context.annotation.componentscan.simple")
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public static @interface ComposedConfiguration {
|
||||
public @interface ComposedConfiguration {
|
||||
}
|
||||
|
||||
@ComposedConfiguration
|
||||
@@ -966,7 +966,7 @@ public class ConfigurationClassPostProcessorTests {
|
||||
@ComponentScan
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public static @interface ComposedConfigurationWithAttributeOverrides {
|
||||
public @interface ComposedConfigurationWithAttributeOverrides {
|
||||
|
||||
String[] basePackages() default {};
|
||||
|
||||
@@ -985,7 +985,7 @@ public class ConfigurationClassPostProcessorTests {
|
||||
@ComposedConfigurationWithAttributeOverrides
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public static @interface ComposedComposedConfigurationWithAttributeOverrides {
|
||||
public @interface ComposedComposedConfigurationWithAttributeOverrides {
|
||||
|
||||
String[] basePackages() default {};
|
||||
}
|
||||
@@ -997,14 +997,14 @@ public class ConfigurationClassPostProcessorTests {
|
||||
@ComponentScan
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public static @interface MetaComponentScan {
|
||||
public @interface MetaComponentScan {
|
||||
}
|
||||
|
||||
@MetaComponentScan
|
||||
@Configuration
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public static @interface MetaComponentScanConfigurationWithAttributeOverrides {
|
||||
public @interface MetaComponentScanConfigurationWithAttributeOverrides {
|
||||
|
||||
String[] basePackages() default {};
|
||||
}
|
||||
|
||||
+43
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -30,6 +30,7 @@ import static org.junit.Assert.*;
|
||||
* Unit tests for {@link MethodBasedEvaluationContext}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Sergey Podgurskiy
|
||||
*/
|
||||
public class MethodBasedEvaluationContextTests {
|
||||
|
||||
@@ -62,6 +63,43 @@ public class MethodBasedEvaluationContextTests {
|
||||
assertNull(context.lookupVariable("p0"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void varArgEmpty() {
|
||||
Method method = ReflectionUtils.findMethod(SampleMethods.class, "hello", Boolean.class, String[].class);
|
||||
MethodBasedEvaluationContext context = createEvaluationContext(method, new Object[] {null});
|
||||
|
||||
assertNull(context.lookupVariable("p0"));
|
||||
assertNull(context.lookupVariable("p1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void varArgNull() {
|
||||
Method method = ReflectionUtils.findMethod(SampleMethods.class, "hello", Boolean.class, String[].class);
|
||||
MethodBasedEvaluationContext context = createEvaluationContext(method, new Object[] {null, null});
|
||||
|
||||
assertNull(context.lookupVariable("p0"));
|
||||
assertNull(context.lookupVariable("p1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void varArgSingle() {
|
||||
Method method = ReflectionUtils.findMethod(SampleMethods.class, "hello", Boolean.class, String[].class);
|
||||
MethodBasedEvaluationContext context = createEvaluationContext(method, new Object[] {null, "hello"});
|
||||
|
||||
assertNull(context.lookupVariable("p0"));
|
||||
assertEquals("hello", context.lookupVariable("p1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void varArgMultiple() {
|
||||
Method method = ReflectionUtils.findMethod(SampleMethods.class, "hello", Boolean.class, String[].class);
|
||||
MethodBasedEvaluationContext context = createEvaluationContext(method,
|
||||
new Object[] {null, new String[]{"hello", "hi"}});
|
||||
|
||||
assertNull(context.lookupVariable("p0"));
|
||||
assertArrayEquals(new String[]{"hello", "hi"}, (String[]) context.lookupVariable("p1"));
|
||||
}
|
||||
|
||||
private MethodBasedEvaluationContext createEvaluationContext(Method method, Object[] args) {
|
||||
return new MethodBasedEvaluationContext(this, method, args, this.paramDiscover);
|
||||
}
|
||||
@@ -73,6 +111,10 @@ public class MethodBasedEvaluationContextTests {
|
||||
private void hello(String foo, Boolean flag) {
|
||||
}
|
||||
|
||||
private void hello(Boolean flag, String... vararg){
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -182,19 +182,19 @@ public class LocalStatelessSessionProxyFactoryBeanTests {
|
||||
}
|
||||
|
||||
|
||||
public static interface MyHome extends EJBLocalHome {
|
||||
public interface MyHome extends EJBLocalHome {
|
||||
|
||||
MyBusinessMethods create() throws CreateException;
|
||||
}
|
||||
|
||||
|
||||
public static interface MyBusinessMethods {
|
||||
public interface MyBusinessMethods {
|
||||
|
||||
int getValue();
|
||||
}
|
||||
|
||||
|
||||
public static interface MyEjb extends EJBLocalObject, MyBusinessMethods {
|
||||
public interface MyEjb extends EJBLocalObject, MyBusinessMethods {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -279,26 +279,25 @@ public class SimpleRemoteStatelessSessionProxyFactoryBeanTests extends SimpleRem
|
||||
}
|
||||
|
||||
|
||||
protected static interface MyHome extends EJBHome {
|
||||
protected interface MyHome extends EJBHome {
|
||||
|
||||
MyBusinessMethods create() throws CreateException, RemoteException;
|
||||
}
|
||||
|
||||
|
||||
protected static interface MyBusinessMethods {
|
||||
protected interface MyBusinessMethods {
|
||||
|
||||
int getValue() throws RemoteException;
|
||||
}
|
||||
|
||||
|
||||
protected static interface MyLocalBusinessMethods {
|
||||
protected interface MyLocalBusinessMethods {
|
||||
|
||||
int getValue();
|
||||
}
|
||||
|
||||
|
||||
protected static interface MyEjb extends EJBObject, MyBusinessMethods {
|
||||
|
||||
protected interface MyEjb extends EJBObject, MyBusinessMethods {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -124,7 +124,7 @@ public class DateTimeFormattingTests {
|
||||
@Test
|
||||
public void testBindLocalDateArray() {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("localDate", new String[]{"10/31/09"});
|
||||
propertyValues.add("localDate", new String[] {"10/31/09"});
|
||||
binder.bind(propertyValues);
|
||||
assertEquals(0, binder.getBindingResult().getErrorCount());
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -218,7 +218,7 @@ public class FormattingConversionServiceTests {
|
||||
assertEquals(new LocalDate(2009, 11, 1), new LocalDate(dates.get(1)));
|
||||
assertEquals(new LocalDate(2009, 11, 2), new LocalDate(dates.get(2)));
|
||||
|
||||
Object model = BeanUtils.instantiate(modelClass);
|
||||
Object model = modelClass.newInstance();
|
||||
ConfigurablePropertyAccessor accessor = directFieldAccess ? PropertyAccessorFactory.forDirectFieldAccess(model) :
|
||||
PropertyAccessorFactory.forBeanPropertyAccess(model);
|
||||
accessor.setConversionService(formattingService);
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ public class MethodNameBasedMBeanInfoAssemblerMappedTests extends AbstractJmxAss
|
||||
public void testWithFallThrough() throws Exception {
|
||||
MethodNameBasedMBeanInfoAssembler assembler =
|
||||
getWithMapping("foobar", "add,myOperation,getName,setName,getAge");
|
||||
assembler.setManagedMethods(new String[]{"getNickName", "setNickName"});
|
||||
assembler.setManagedMethods("getNickName", "setNickName");
|
||||
|
||||
ModelMBeanInfo inf = assembler.getMBeanInfo(getBean(), getObjectName());
|
||||
MBeanAttributeInfo attr = inf.getAttribute("NickName");
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ public class MethodNameBasedMBeanInfoAssemblerTests extends AbstractJmxAssembler
|
||||
@Override
|
||||
protected MBeanInfoAssembler getAssembler() {
|
||||
MethodNameBasedMBeanInfoAssembler assembler = new MethodNameBasedMBeanInfoAssembler();
|
||||
assembler.setManagedMethods(new String[] {"add", "myOperation", "getName", "setName", "getAge"});
|
||||
assembler.setManagedMethods("add", "myOperation", "getName", "setName", "getAge");
|
||||
return assembler;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -30,6 +30,7 @@ import static org.junit.Assert.*;
|
||||
* Unit tests for {@link JndiPropertySource}.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
*/
|
||||
public class JndiPropertySourceTests {
|
||||
@@ -56,7 +57,7 @@ public class JndiPropertySourceTests {
|
||||
jndiLocator.setJndiTemplate(jndiTemplate);
|
||||
|
||||
JndiPropertySource ps = new JndiPropertySource("jndiProperties", jndiLocator);
|
||||
assertThat((String)ps.getProperty("p1"), equalTo("v1"));
|
||||
assertThat(ps.getProperty("p1"), equalTo("v1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -75,7 +76,36 @@ public class JndiPropertySourceTests {
|
||||
jndiLocator.setJndiTemplate(jndiTemplate);
|
||||
|
||||
JndiPropertySource ps = new JndiPropertySource("jndiProperties", jndiLocator);
|
||||
assertThat((String)ps.getProperty("p1"), equalTo("v1"));
|
||||
assertThat(ps.getProperty("p1"), equalTo("v1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertyWithDefaultClauseInResourceRefMode() {
|
||||
JndiLocatorDelegate jndiLocator = new JndiLocatorDelegate() {
|
||||
@Override
|
||||
public Object lookup(String jndiName) throws NamingException {
|
||||
throw new IllegalStateException("Should not get called");
|
||||
}
|
||||
};
|
||||
jndiLocator.setResourceRef(true);
|
||||
|
||||
JndiPropertySource ps = new JndiPropertySource("jndiProperties", jndiLocator);
|
||||
assertThat(ps.getProperty("propertyKey:defaultValue"), nullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertyWithColonInNonResourceRefMode() {
|
||||
JndiLocatorDelegate jndiLocator = new JndiLocatorDelegate() {
|
||||
@Override
|
||||
public Object lookup(String jndiName) throws NamingException {
|
||||
assertEquals("my:key", jndiName);
|
||||
return "my:value";
|
||||
}
|
||||
};
|
||||
jndiLocator.setResourceRef(false);
|
||||
|
||||
JndiPropertySource ps = new JndiPropertySource("jndiProperties", jndiLocator);
|
||||
assertThat(ps.getProperty("my:key"), equalTo("my:value"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+82
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -26,19 +26,24 @@ import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
|
||||
import org.springframework.beans.factory.UnsatisfiedDependencyException;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.AdviceMode;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.anyOf;
|
||||
@@ -67,6 +72,48 @@ public class EnableAsyncTests {
|
||||
asyncBean.work();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void proxyingOccursWithMockitoStub() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(AsyncConfigWithMockito.class, AsyncBeanUser.class);
|
||||
ctx.refresh();
|
||||
|
||||
AsyncBeanUser asyncBeanUser = ctx.getBean(AsyncBeanUser.class);
|
||||
AsyncBean asyncBean = asyncBeanUser.getAsyncBean();
|
||||
assertThat(AopUtils.isAopProxy(asyncBean), is(true));
|
||||
asyncBean.work();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void properExceptionForExistingProxyDependencyMismatch() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(AsyncConfig.class, AsyncBeanWithInterface.class, AsyncBeanUser.class);
|
||||
|
||||
try {
|
||||
ctx.refresh();
|
||||
fail("Should have thrown UnsatisfiedDependencyException");
|
||||
}
|
||||
catch (UnsatisfiedDependencyException ex) {
|
||||
ex.printStackTrace();
|
||||
assertTrue(ex.getCause() instanceof BeanNotOfRequiredTypeException);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void properExceptionForResolvedProxyDependencyMismatch() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(AsyncConfig.class, AsyncBeanUser.class, AsyncBeanWithInterface.class);
|
||||
|
||||
try {
|
||||
ctx.refresh();
|
||||
fail("Should have thrown UnsatisfiedDependencyException");
|
||||
}
|
||||
catch (UnsatisfiedDependencyException ex) {
|
||||
ex.printStackTrace();
|
||||
assertTrue(ex.getCause() instanceof BeanNotOfRequiredTypeException);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withAsyncBeanWithExecutorQualifiedByName() throws ExecutionException, InterruptedException {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
@@ -200,6 +247,29 @@ public class EnableAsyncTests {
|
||||
}
|
||||
|
||||
|
||||
@Component("asyncBean")
|
||||
static class AsyncBeanWithInterface extends AsyncBean implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class AsyncBeanUser {
|
||||
|
||||
private final AsyncBean asyncBean;
|
||||
|
||||
public AsyncBeanUser(AsyncBean asyncBean) {
|
||||
this.asyncBean = asyncBean;
|
||||
}
|
||||
|
||||
public AsyncBean getAsyncBean() {
|
||||
return asyncBean;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@EnableAsync(annotation = CustomAsync.class)
|
||||
static class CustomAsyncAnnotationConfig {
|
||||
}
|
||||
@@ -252,6 +322,17 @@ public class EnableAsyncTests {
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableAsync
|
||||
static class AsyncConfigWithMockito {
|
||||
|
||||
@Bean @Lazy
|
||||
public AsyncBean asyncBean() {
|
||||
return Mockito.mock(AsyncBean.class);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableAsync
|
||||
static class CustomExecutorAsyncConfig implements AsyncConfigurer {
|
||||
|
||||
+20
@@ -56,6 +56,26 @@ public class CronSequenceGeneratorTests {
|
||||
new CronSequenceGenerator("*/-1 * * * * *").next(new Date(2012, 6, 1, 9, 0));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void withInvertedMinuteRange() {
|
||||
new CronSequenceGenerator("* 6-5 * * * *").next(new Date(2012, 6, 1, 9, 0));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void withInvertedHourRange() {
|
||||
new CronSequenceGenerator("* * 6-5 * * *").next(new Date(2012, 6, 1, 9, 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withSameMinuteRange() {
|
||||
new CronSequenceGenerator("* 6-6 * * * *").next(new Date(2012, 6, 1, 9, 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withSameHourRange() {
|
||||
new CronSequenceGenerator("* * 6-6 * * *").next(new Date(2012, 6, 1, 9, 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validExpression() {
|
||||
assertTrue(CronSequenceGenerator.isValidExpression("0 */2 1-4 * * *"));
|
||||
|
||||
+5
-6
@@ -268,7 +268,7 @@ public class GroovyScriptFactoryTests {
|
||||
@Test
|
||||
public void testScriptedClassThatDoesNotHaveANoArgCtor() throws Exception {
|
||||
ScriptSource script = mock(ScriptSource.class);
|
||||
final String badScript = "class Foo { public Foo(String foo) {}}";
|
||||
String badScript = "class Foo { public Foo(String foo) {}}";
|
||||
given(script.getScriptAsString()).willReturn(badScript);
|
||||
given(script.suggestedClassName()).willReturn("someName");
|
||||
GroovyScriptFactory factory = new GroovyScriptFactory(ScriptFactoryPostProcessor.INLINE_SCRIPT_PREFIX
|
||||
@@ -285,11 +285,10 @@ public class GroovyScriptFactoryTests {
|
||||
@Test
|
||||
public void testScriptedClassThatHasNoPublicNoArgCtor() throws Exception {
|
||||
ScriptSource script = mock(ScriptSource.class);
|
||||
final String badScript = "class Foo { protected Foo() {}}";
|
||||
String badScript = "class Foo { protected Foo() {} \n String toString() { 'X' }}";
|
||||
given(script.getScriptAsString()).willReturn(badScript);
|
||||
given(script.suggestedClassName()).willReturn("someName");
|
||||
GroovyScriptFactory factory = new GroovyScriptFactory(ScriptFactoryPostProcessor.INLINE_SCRIPT_PREFIX
|
||||
+ badScript);
|
||||
GroovyScriptFactory factory = new GroovyScriptFactory(ScriptFactoryPostProcessor.INLINE_SCRIPT_PREFIX + badScript);
|
||||
try {
|
||||
factory.getScriptedObject(script);
|
||||
fail("Must have thrown a ScriptCompilationException (no oublic no-arg ctor in scripted class).");
|
||||
@@ -466,7 +465,7 @@ public class GroovyScriptFactoryTests {
|
||||
@Test // SPR-6268
|
||||
public void testProxyTargetClassNotAllowedIfNotGroovy() throws Exception {
|
||||
try {
|
||||
new ClassPathXmlApplicationContext("jruby-with-xsd-proxy-target-class.xml", getClass());
|
||||
new ClassPathXmlApplicationContext("groovy-with-xsd-proxy-target-class.xml", getClass());
|
||||
}
|
||||
catch (BeanCreationException ex) {
|
||||
assertTrue(ex.getMessage().contains("Cannot use proxyTargetClass=true"));
|
||||
@@ -562,7 +561,7 @@ public class GroovyScriptFactoryTests {
|
||||
testMetaClass("org/springframework/scripting/groovy/calculators-with-xsd.xml");
|
||||
}
|
||||
|
||||
private void testMetaClass(final String xmlFile) {
|
||||
private void testMetaClass(String xmlFile) {
|
||||
// expect the exception we threw in the custom metaclass to show it got invoked
|
||||
try {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext(xmlFile);
|
||||
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:lang="http://www.springframework.org/schema/lang"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
|
||||
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.1.xsd">
|
||||
|
||||
<lang:defaults proxy-target-class="true"/>
|
||||
|
||||
<lang:jruby id="refreshableMessenger" refresh-check-delay="1000"
|
||||
script-source="classpath:org/springframework/scripting/jruby/Messenger.rb"
|
||||
script-interfaces="org.springframework.scripting.Messenger">
|
||||
<lang:property name="message" value="Hello World!"/>
|
||||
</lang:jruby>
|
||||
|
||||
</beans>
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -203,7 +203,7 @@ public abstract class CollectionFactory {
|
||||
try {
|
||||
return (Collection<E>) collectionType.newInstance();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalArgumentException(
|
||||
"Could not instantiate Collection type: " + collectionType.getName(), ex);
|
||||
}
|
||||
@@ -318,7 +318,7 @@ public abstract class CollectionFactory {
|
||||
try {
|
||||
return (Map<K, V>) mapType.newInstance();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalArgumentException("Could not instantiate Map type: " + mapType.getName(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -21,7 +21,6 @@ import java.io.InputStream;
|
||||
import java.io.NotSerializableException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectStreamClass;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@@ -101,7 +100,7 @@ public class ConfigurableObjectInputStream extends ObjectInputStream {
|
||||
}
|
||||
}
|
||||
try {
|
||||
return Proxy.getProxyClass(this.classLoader, resolvedInterfaces);
|
||||
return ClassUtils.createCompositeInterface(resolvedInterfaces, this.classLoader);
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
throw new ClassNotFoundException(null, ex);
|
||||
@@ -117,7 +116,7 @@ public class ConfigurableObjectInputStream extends ObjectInputStream {
|
||||
for (int i = 0; i < interfaces.length; i++) {
|
||||
resolvedInterfaces[i] = resolveFallbackIfPossible(interfaces[i], ex);
|
||||
}
|
||||
return Proxy.getProxyClass(getFallbackClassLoader(), resolvedInterfaces);
|
||||
return ClassUtils.createCompositeInterface(resolvedInterfaces, getFallbackClassLoader());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -139,8 +138,9 @@ public class ConfigurableObjectInputStream extends ObjectInputStream {
|
||||
|
||||
/**
|
||||
* Return the fallback ClassLoader to use when no ClassLoader was specified
|
||||
* and ObjectInputStream's own default ClassLoader failed.
|
||||
* <p>The default implementation simply returns {@code null}.
|
||||
* and ObjectInputStream's own default class loader failed.
|
||||
* <p>The default implementation simply returns {@code null}, indicating
|
||||
* that no specific fallback is available.
|
||||
*/
|
||||
protected ClassLoader getFallbackClassLoader() throws IOException {
|
||||
return null;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -85,10 +85,9 @@ public abstract class MethodIntrospector {
|
||||
|
||||
/**
|
||||
* Select methods on the given target type based on a filter.
|
||||
* <p>Callers define methods of interest through the
|
||||
* {@link ReflectionUtils.MethodFilter} parameter.
|
||||
* <p>Callers define methods of interest through the {@code MethodFilter} parameter.
|
||||
* @param targetType the target type to search methods on
|
||||
* @param methodFilter a {@link ReflectionUtils.MethodFilter} to help
|
||||
* @param methodFilter a {@code MethodFilter} to help
|
||||
* recognize handler methods of interest
|
||||
* @return the selected methods, or an empty set in case of no match
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -372,6 +372,8 @@ abstract class SerializableTypeWrapper {
|
||||
|
||||
private final String methodName;
|
||||
|
||||
private final Class<?> declaringClass;
|
||||
|
||||
private final int index;
|
||||
|
||||
private transient Method method;
|
||||
@@ -381,6 +383,7 @@ abstract class SerializableTypeWrapper {
|
||||
public MethodInvokeTypeProvider(TypeProvider provider, Method method, int index) {
|
||||
this.provider = provider;
|
||||
this.methodName = method.getName();
|
||||
this.declaringClass = method.getDeclaringClass();
|
||||
this.index = index;
|
||||
this.method = method;
|
||||
}
|
||||
@@ -404,7 +407,7 @@ abstract class SerializableTypeWrapper {
|
||||
|
||||
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
|
||||
inputStream.defaultReadObject();
|
||||
this.method = ReflectionUtils.findMethod(this.provider.getType().getClass(), this.methodName);
|
||||
this.method = ReflectionUtils.findMethod(this.declaringClass, this.methodName);
|
||||
Assert.state(Type.class == this.method.getReturnType() || Type[].class == this.method.getReturnType());
|
||||
}
|
||||
}
|
||||
|
||||
+8
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.core.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -35,13 +34,13 @@ import org.springframework.util.ObjectUtils;
|
||||
* @param <S> the type of source supported by this extractor
|
||||
* @see Annotation
|
||||
* @see AliasFor
|
||||
* @see AnnotationUtils#synthesizeAnnotation(Annotation, AnnotatedElement)
|
||||
* @see AnnotationUtils#synthesizeAnnotation(Annotation, Object)
|
||||
*/
|
||||
abstract class AbstractAliasAwareAnnotationAttributeExtractor<S> implements AnnotationAttributeExtractor<S> {
|
||||
|
||||
private final Class<? extends Annotation> annotationType;
|
||||
|
||||
private final AnnotatedElement annotatedElement;
|
||||
private final Object annotatedElement;
|
||||
|
||||
private final S source;
|
||||
|
||||
@@ -56,7 +55,7 @@ abstract class AbstractAliasAwareAnnotationAttributeExtractor<S> implements Anno
|
||||
* @param source the underlying source of annotation attributes; never {@code null}
|
||||
*/
|
||||
AbstractAliasAwareAnnotationAttributeExtractor(
|
||||
Class<? extends Annotation> annotationType, AnnotatedElement annotatedElement, S source) {
|
||||
Class<? extends Annotation> annotationType, Object annotatedElement, S source) {
|
||||
|
||||
Assert.notNull(annotationType, "annotationType must not be null");
|
||||
Assert.notNull(source, "source must not be null");
|
||||
@@ -73,7 +72,7 @@ abstract class AbstractAliasAwareAnnotationAttributeExtractor<S> implements Anno
|
||||
}
|
||||
|
||||
@Override
|
||||
public final AnnotatedElement getAnnotatedElement() {
|
||||
public final Object getAnnotatedElement() {
|
||||
return this.annotatedElement;
|
||||
}
|
||||
|
||||
@@ -89,18 +88,18 @@ abstract class AbstractAliasAwareAnnotationAttributeExtractor<S> implements Anno
|
||||
|
||||
List<String> aliasNames = this.attributeAliasMap.get(attributeName);
|
||||
if (aliasNames != null) {
|
||||
Object defaultValue = AnnotationUtils.getDefaultValue(getAnnotationType(), attributeName);
|
||||
Object defaultValue = AnnotationUtils.getDefaultValue(this.annotationType, attributeName);
|
||||
for (String aliasName : aliasNames) {
|
||||
Object aliasValue = getRawAttributeValue(aliasName);
|
||||
|
||||
if (!ObjectUtils.nullSafeEquals(attributeValue, aliasValue) &&
|
||||
!ObjectUtils.nullSafeEquals(attributeValue, defaultValue) &&
|
||||
!ObjectUtils.nullSafeEquals(aliasValue, defaultValue)) {
|
||||
String elementName = (getAnnotatedElement() != null ? getAnnotatedElement().toString() : "unknown element");
|
||||
String elementName = (this.annotatedElement != null ? this.annotatedElement.toString() : "unknown element");
|
||||
throw new AnnotationConfigurationException(String.format(
|
||||
"In annotation [%s] declared on %s and synthesized from [%s], attribute '%s' and its " +
|
||||
"alias '%s' are present with values of [%s] and [%s], but only one is permitted.",
|
||||
getAnnotationType().getName(), elementName, getSource(), attributeName, aliasName,
|
||||
this.annotationType.getName(), elementName, this.source, attributeName, aliasName,
|
||||
ObjectUtils.nullSafeToString(attributeValue), ObjectUtils.nullSafeToString(aliasValue)));
|
||||
}
|
||||
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.core.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
@@ -44,7 +43,7 @@ interface AnnotationAttributeExtractor<S> {
|
||||
* type supported by this extractor.
|
||||
* @return the annotated element, or {@code null} if unknown
|
||||
*/
|
||||
AnnotatedElement getAnnotatedElement();
|
||||
Object getAnnotatedElement();
|
||||
|
||||
/**
|
||||
* Get the underlying source of annotation attributes.
|
||||
|
||||
+81
-31
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -36,8 +36,7 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* <p>Provides 'pseudo-reification' to avoid noisy Map generics in the calling
|
||||
* code as well as convenience methods for looking up annotation attributes
|
||||
* in a type-safe fashion, including support for attribute aliases configured
|
||||
* via {@link AliasFor @AliasFor}.
|
||||
* in a type-safe fashion.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Sam Brannen
|
||||
@@ -45,35 +44,25 @@ import org.springframework.util.StringUtils;
|
||||
* @since 3.1.1
|
||||
* @see AnnotationUtils#getAnnotationAttributes
|
||||
* @see AnnotatedElementUtils
|
||||
* @see AliasFor
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
||||
|
||||
private static final String UNKNOWN = "unknown";
|
||||
|
||||
private final Class<? extends Annotation> annotationType;
|
||||
|
||||
private final String displayName;
|
||||
|
||||
boolean validated = false;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new, empty {@link AnnotationAttributes} instance.
|
||||
*/
|
||||
public AnnotationAttributes() {
|
||||
this.annotationType = null;
|
||||
this.displayName = "unknown";
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new, empty {@link AnnotationAttributes} instance for the
|
||||
* specified {@code annotationType}.
|
||||
* @param annotationType the type of annotation represented by this
|
||||
* {@code AnnotationAttributes} instance; never {@code null}
|
||||
* @since 4.2
|
||||
*/
|
||||
public AnnotationAttributes(Class<? extends Annotation> annotationType) {
|
||||
Assert.notNull(annotationType, "annotationType must not be null");
|
||||
this.annotationType = annotationType;
|
||||
this.displayName = annotationType.getName();
|
||||
this.displayName = UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,20 +73,73 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
||||
public AnnotationAttributes(int initialCapacity) {
|
||||
super(initialCapacity);
|
||||
this.annotationType = null;
|
||||
this.displayName = "unknown";
|
||||
this.displayName = UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link AnnotationAttributes} instance, wrapping the
|
||||
* provided map and all its <em>key-value</em> pairs.
|
||||
* @param map original source of annotation attribute <em>key-value</em>
|
||||
* pairs
|
||||
* Create a new, empty {@link AnnotationAttributes} instance for the
|
||||
* specified {@code annotationType}.
|
||||
* @param annotationType the type of annotation represented by this
|
||||
* {@code AnnotationAttributes} instance; never {@code null}
|
||||
* @since 4.2
|
||||
*/
|
||||
public AnnotationAttributes(Class<? extends Annotation> annotationType) {
|
||||
Assert.notNull(annotationType, "'annotationType' must not be null");
|
||||
this.annotationType = annotationType;
|
||||
this.displayName = annotationType.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new, empty {@link AnnotationAttributes} instance for the
|
||||
* specified {@code annotationType}.
|
||||
* @param annotationType the annotation type name represented by this
|
||||
* {@code AnnotationAttributes} instance; never {@code null}
|
||||
* @param classLoader the ClassLoader to try to load the annotation type on,
|
||||
* or {@code null} to just store the annotation type name
|
||||
* @since 4.3.2
|
||||
*/
|
||||
public AnnotationAttributes(String annotationType, ClassLoader classLoader) {
|
||||
Assert.notNull(annotationType, "'annotationType' must not be null");
|
||||
this.annotationType = getAnnotationType(annotationType, classLoader);
|
||||
this.displayName = annotationType;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Class<? extends Annotation> getAnnotationType(String annotationType, ClassLoader classLoader) {
|
||||
if (classLoader != null) {
|
||||
try {
|
||||
return (Class<? extends Annotation>) classLoader.loadClass(annotationType);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// Annotation Class not resolvable
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link AnnotationAttributes} instance, wrapping the provided
|
||||
* map and all its <em>key-value</em> pairs.
|
||||
* @param map original source of annotation attribute <em>key-value</em> pairs
|
||||
* @see #fromMap(Map)
|
||||
*/
|
||||
public AnnotationAttributes(Map<String, Object> map) {
|
||||
super(map);
|
||||
this.annotationType = null;
|
||||
this.displayName = "unknown";
|
||||
this.displayName = UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link AnnotationAttributes} instance, wrapping the provided
|
||||
* map and all its <em>key-value</em> pairs.
|
||||
* @param other original source of annotation attribute <em>key-value</em> pairs
|
||||
* @see #fromMap(Map)
|
||||
*/
|
||||
public AnnotationAttributes(AnnotationAttributes other) {
|
||||
super(other);
|
||||
this.annotationType = other.annotationType;
|
||||
this.displayName = other.displayName;
|
||||
this.validated = other.validated;
|
||||
}
|
||||
|
||||
|
||||
@@ -144,8 +186,10 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
||||
* @throws AnnotationConfigurationException if the attribute and its
|
||||
* alias are both present with different non-empty values
|
||||
* @since 4.2
|
||||
* @see ObjectUtils#isEmpty(Object)
|
||||
* @deprecated as of Spring 4.3.2, in favor of built-in alias resolution
|
||||
* in {@link #getString} itself
|
||||
*/
|
||||
@Deprecated
|
||||
public String getAliasedString(String attributeName, Class<? extends Annotation> annotationType,
|
||||
Object annotationSource) {
|
||||
|
||||
@@ -188,7 +232,10 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
||||
* @throws AnnotationConfigurationException if the attribute and its
|
||||
* alias are both present with different non-empty values
|
||||
* @since 4.2
|
||||
* @deprecated as of Spring 4.3.2, in favor of built-in alias resolution
|
||||
* in {@link #getStringArray} itself
|
||||
*/
|
||||
@Deprecated
|
||||
public String[] getAliasedStringArray(String attributeName, Class<? extends Annotation> annotationType,
|
||||
Object annotationSource) {
|
||||
|
||||
@@ -286,7 +333,10 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
||||
* @throws AnnotationConfigurationException if the attribute and its
|
||||
* alias are both present with different non-empty values
|
||||
* @since 4.2
|
||||
* @deprecated as of Spring 4.3.2, in favor of built-in alias resolution
|
||||
* in {@link #getClassArray} itself
|
||||
*/
|
||||
@Deprecated
|
||||
public Class<?>[] getAliasedClassArray(String attributeName, Class<? extends Annotation> annotationType,
|
||||
Object annotationSource) {
|
||||
|
||||
@@ -378,7 +428,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T getRequiredAttribute(String attributeName, Class<T> expectedType) {
|
||||
Assert.hasText(attributeName, "attributeName must not be null or empty");
|
||||
Assert.hasText(attributeName, "'attributeName' must not be null or empty");
|
||||
Object value = get(attributeName);
|
||||
assertAttributePresence(attributeName, value);
|
||||
assertNotException(attributeName, value);
|
||||
@@ -418,9 +468,9 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
||||
private <T> T getRequiredAttributeWithAlias(String attributeName, Class<? extends Annotation> annotationType,
|
||||
Object annotationSource, Class<T> expectedType) {
|
||||
|
||||
Assert.hasText(attributeName, "attributeName must not be null or empty");
|
||||
Assert.notNull(annotationType, "annotationType must not be null");
|
||||
Assert.notNull(expectedType, "expectedType must not be null");
|
||||
Assert.hasText(attributeName, "'attributeName' must not be null or empty");
|
||||
Assert.notNull(annotationType, "'annotationType' must not be null");
|
||||
Assert.notNull(expectedType, "'expectedType' must not be null");
|
||||
|
||||
T attributeValue = getAttribute(attributeName, expectedType);
|
||||
|
||||
@@ -433,8 +483,8 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
||||
|
||||
if (!attributeEmpty && !aliasEmpty && !ObjectUtils.nullSafeEquals(attributeValue, aliasValue)) {
|
||||
String elementName = (annotationSource == null ? "unknown element" : annotationSource.toString());
|
||||
String msg = String.format("In annotation [%s] declared on [%s], attribute [%s] and its alias [%s] " +
|
||||
"are present with values of [%s] and [%s], but only one is permitted.",
|
||||
String msg = String.format("In annotation [%s] declared on [%s], attribute [%s] and its " +
|
||||
"alias [%s] are present with values of [%s] and [%s], but only one is permitted.",
|
||||
annotationType.getName(), elementName, attributeName, aliasName,
|
||||
ObjectUtils.nullSafeToString(attributeValue), ObjectUtils.nullSafeToString(aliasValue));
|
||||
throw new AnnotationConfigurationException(msg);
|
||||
|
||||
+125
-52
@@ -22,6 +22,7 @@ import java.lang.reflect.Array;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -621,7 +622,7 @@ public abstract class AnnotationUtils {
|
||||
static boolean isInterfaceWithAnnotatedMethods(Class<?> iface) {
|
||||
Boolean found = annotatedInterfaceCache.get(iface);
|
||||
if (found != null) {
|
||||
return found.booleanValue();
|
||||
return found;
|
||||
}
|
||||
found = Boolean.FALSE;
|
||||
for (Method ifcMethod : iface.getMethods()) {
|
||||
@@ -636,7 +637,7 @@ public abstract class AnnotationUtils {
|
||||
}
|
||||
}
|
||||
annotatedInterfaceCache.put(iface, found);
|
||||
return found.booleanValue();
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -888,14 +889,14 @@ public abstract class AnnotationUtils {
|
||||
AnnotationCacheKey cacheKey = new AnnotationCacheKey(annotationType, metaAnnotationType);
|
||||
Boolean metaPresent = metaPresentCache.get(cacheKey);
|
||||
if (metaPresent != null) {
|
||||
return metaPresent.booleanValue();
|
||||
return metaPresent;
|
||||
}
|
||||
metaPresent = Boolean.FALSE;
|
||||
if (findAnnotation(annotationType, metaAnnotationType, false) != null) {
|
||||
metaPresent = Boolean.TRUE;
|
||||
}
|
||||
metaPresentCache.put(cacheKey, metaPresent);
|
||||
return metaPresent.booleanValue();
|
||||
return metaPresent;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1018,6 +1019,13 @@ public abstract class AnnotationUtils {
|
||||
public static AnnotationAttributes getAnnotationAttributes(AnnotatedElement annotatedElement,
|
||||
Annotation annotation, boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
|
||||
|
||||
return getAnnotationAttributes(
|
||||
(Object) annotatedElement, annotation, classValuesAsString, nestedAnnotationsAsMap);
|
||||
}
|
||||
|
||||
private static AnnotationAttributes getAnnotationAttributes(Object annotatedElement,
|
||||
Annotation annotation, boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
|
||||
|
||||
AnnotationAttributes attributes =
|
||||
retrieveAnnotationAttributes(annotatedElement, annotation, classValuesAsString, nestedAnnotationsAsMap);
|
||||
postProcessAnnotationAttributes(annotatedElement, attributes, classValuesAsString, nestedAnnotationsAsMap);
|
||||
@@ -1052,7 +1060,7 @@ public abstract class AnnotationUtils {
|
||||
* @since 4.2
|
||||
* @see #postProcessAnnotationAttributes
|
||||
*/
|
||||
static AnnotationAttributes retrieveAnnotationAttributes(AnnotatedElement annotatedElement, Annotation annotation,
|
||||
static AnnotationAttributes retrieveAnnotationAttributes(Object annotatedElement, Annotation annotation,
|
||||
boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
|
||||
|
||||
Class<? extends Annotation> annotationType = annotation.annotationType();
|
||||
@@ -1096,14 +1104,14 @@ public abstract class AnnotationUtils {
|
||||
* {@code Annotation} instances
|
||||
* @return the adapted value, or the original value if no adaptation is needed
|
||||
*/
|
||||
static Object adaptValue(AnnotatedElement annotatedElement, Object value, boolean classValuesAsString,
|
||||
static Object adaptValue(Object annotatedElement, Object value, boolean classValuesAsString,
|
||||
boolean nestedAnnotationsAsMap) {
|
||||
|
||||
if (classValuesAsString) {
|
||||
if (value instanceof Class) {
|
||||
if (value instanceof Class<?>) {
|
||||
return ((Class<?>) value).getName();
|
||||
}
|
||||
else if (value instanceof Class[]) {
|
||||
else if (value instanceof Class<?>[]) {
|
||||
Class<?>[] clazzArray = (Class<?>[]) value;
|
||||
String[] classNames = new String[clazzArray.length];
|
||||
for (int i = 0; i < clazzArray.length; i++) {
|
||||
@@ -1142,6 +1150,63 @@ public abstract class AnnotationUtils {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the annotation-declared default values for the given attributes,
|
||||
* if available.
|
||||
* @param attributes the annotation attributes to process
|
||||
* @since 4.3.2
|
||||
*/
|
||||
public static void registerDefaultValues(AnnotationAttributes attributes) {
|
||||
// Only do defaults scanning for public annotations; we'd run into
|
||||
// IllegalAccessExceptions otherwise, and we don't want to mess with
|
||||
// accessibility in a SecurityManager environment.
|
||||
Class<? extends Annotation> annotationType = attributes.annotationType();
|
||||
if (annotationType != null && Modifier.isPublic(annotationType.getModifiers())) {
|
||||
// Check declared default values of attributes in the annotation type.
|
||||
for (Method annotationAttribute : getAttributeMethods(annotationType)) {
|
||||
String attributeName = annotationAttribute.getName();
|
||||
Object defaultValue = annotationAttribute.getDefaultValue();
|
||||
if (defaultValue != null && !attributes.containsKey(attributeName)) {
|
||||
if (defaultValue instanceof Annotation) {
|
||||
defaultValue = getAnnotationAttributes((Annotation) defaultValue, false, true);
|
||||
}
|
||||
else if (defaultValue instanceof Annotation[]) {
|
||||
Annotation[] realAnnotations = (Annotation[]) defaultValue;
|
||||
AnnotationAttributes[] mappedAnnotations = new AnnotationAttributes[realAnnotations.length];
|
||||
for (int i = 0; i < realAnnotations.length; i++) {
|
||||
mappedAnnotations[i] = getAnnotationAttributes(realAnnotations[i], false, true);
|
||||
}
|
||||
defaultValue = mappedAnnotations;
|
||||
}
|
||||
attributes.put(attributeName, new DefaultValueHolder(defaultValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-process the supplied {@link AnnotationAttributes}, preserving nested
|
||||
* annotations as {@code Annotation} instances.
|
||||
* <p>Specifically, this method enforces <em>attribute alias</em> semantics
|
||||
* for annotation attributes that are annotated with {@link AliasFor @AliasFor}
|
||||
* and replaces default value placeholders with their original default values.
|
||||
* @param annotatedElement the element that is annotated with an annotation or
|
||||
* annotation hierarchy from which the supplied attributes were created;
|
||||
* may be {@code null} if unknown
|
||||
* @param attributes the annotation attributes to post-process
|
||||
* @param classValuesAsString whether to convert Class references into Strings (for
|
||||
* compatibility with {@link org.springframework.core.type.AnnotationMetadata})
|
||||
* or to preserve them as Class references
|
||||
* @since 4.3.2
|
||||
* @see #postProcessAnnotationAttributes(Object, AnnotationAttributes, boolean, boolean)
|
||||
* @see #getDefaultValue(Class, String)
|
||||
*/
|
||||
public static void postProcessAnnotationAttributes(Object annotatedElement,
|
||||
AnnotationAttributes attributes, boolean classValuesAsString) {
|
||||
|
||||
postProcessAnnotationAttributes(annotatedElement, attributes, classValuesAsString, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-process the supplied {@link AnnotationAttributes}.
|
||||
* <p>Specifically, this method enforces <em>attribute alias</em> semantics
|
||||
@@ -1159,10 +1224,10 @@ public abstract class AnnotationUtils {
|
||||
* {@link org.springframework.core.type.AnnotationMetadata}) or to preserve them as
|
||||
* {@code Annotation} instances
|
||||
* @since 4.2
|
||||
* @see #retrieveAnnotationAttributes(AnnotatedElement, Annotation, boolean, boolean)
|
||||
* @see #retrieveAnnotationAttributes(Object, Annotation, boolean, boolean)
|
||||
* @see #getDefaultValue(Class, String)
|
||||
*/
|
||||
static void postProcessAnnotationAttributes(AnnotatedElement annotatedElement,
|
||||
static void postProcessAnnotationAttributes(Object annotatedElement,
|
||||
AnnotationAttributes attributes, boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
|
||||
|
||||
// Abort?
|
||||
@@ -1176,51 +1241,55 @@ public abstract class AnnotationUtils {
|
||||
// circuit the search algorithms.
|
||||
Set<String> valuesAlreadyReplaced = new HashSet<String>();
|
||||
|
||||
// Validate @AliasFor configuration
|
||||
Map<String, List<String>> aliasMap = getAttributeAliasMap(annotationType);
|
||||
for (String attributeName : aliasMap.keySet()) {
|
||||
if (valuesAlreadyReplaced.contains(attributeName)) {
|
||||
continue;
|
||||
}
|
||||
Object value = attributes.get(attributeName);
|
||||
boolean valuePresent = (value != null && !(value instanceof DefaultValueHolder));
|
||||
|
||||
for (String aliasedAttributeName : aliasMap.get(attributeName)) {
|
||||
if (valuesAlreadyReplaced.contains(aliasedAttributeName)) {
|
||||
if (!attributes.validated) {
|
||||
// Validate @AliasFor configuration
|
||||
Map<String, List<String>> aliasMap = getAttributeAliasMap(annotationType);
|
||||
for (String attributeName : aliasMap.keySet()) {
|
||||
if (valuesAlreadyReplaced.contains(attributeName)) {
|
||||
continue;
|
||||
}
|
||||
Object value = attributes.get(attributeName);
|
||||
boolean valuePresent = (value != null && !(value instanceof DefaultValueHolder));
|
||||
|
||||
Object aliasedValue = attributes.get(aliasedAttributeName);
|
||||
boolean aliasPresent = (aliasedValue != null && !(aliasedValue instanceof DefaultValueHolder));
|
||||
for (String aliasedAttributeName : aliasMap.get(attributeName)) {
|
||||
if (valuesAlreadyReplaced.contains(aliasedAttributeName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Something to validate or replace with an alias?
|
||||
if (valuePresent || aliasPresent) {
|
||||
if (valuePresent && aliasPresent) {
|
||||
// Since annotation attributes can be arrays, we must use ObjectUtils.nullSafeEquals().
|
||||
if (!ObjectUtils.nullSafeEquals(value, aliasedValue)) {
|
||||
String elementAsString = (annotatedElement != null ? annotatedElement.toString() : "unknown element");
|
||||
throw new AnnotationConfigurationException(String.format(
|
||||
"In AnnotationAttributes for annotation [%s] declared on %s, " +
|
||||
"attribute '%s' and its alias '%s' are declared with values of [%s] and [%s], " +
|
||||
"but only one is permitted.", annotationType.getName(), elementAsString,
|
||||
attributeName, aliasedAttributeName, ObjectUtils.nullSafeToString(value),
|
||||
ObjectUtils.nullSafeToString(aliasedValue)));
|
||||
Object aliasedValue = attributes.get(aliasedAttributeName);
|
||||
boolean aliasPresent = (aliasedValue != null && !(aliasedValue instanceof DefaultValueHolder));
|
||||
|
||||
// Something to validate or replace with an alias?
|
||||
if (valuePresent || aliasPresent) {
|
||||
if (valuePresent && aliasPresent) {
|
||||
// Since annotation attributes can be arrays, we must use ObjectUtils.nullSafeEquals().
|
||||
if (!ObjectUtils.nullSafeEquals(value, aliasedValue)) {
|
||||
String elementAsString =
|
||||
(annotatedElement != null ? annotatedElement.toString() : "unknown element");
|
||||
throw new AnnotationConfigurationException(String.format(
|
||||
"In AnnotationAttributes for annotation [%s] declared on %s, " +
|
||||
"attribute '%s' and its alias '%s' are declared with values of [%s] and [%s], " +
|
||||
"but only one is permitted.", annotationType.getName(), elementAsString,
|
||||
attributeName, aliasedAttributeName, ObjectUtils.nullSafeToString(value),
|
||||
ObjectUtils.nullSafeToString(aliasedValue)));
|
||||
}
|
||||
}
|
||||
else if (aliasPresent) {
|
||||
// Replace value with aliasedValue
|
||||
attributes.put(attributeName,
|
||||
adaptValue(annotatedElement, aliasedValue, classValuesAsString, nestedAnnotationsAsMap));
|
||||
valuesAlreadyReplaced.add(attributeName);
|
||||
}
|
||||
else {
|
||||
// Replace aliasedValue with value
|
||||
attributes.put(aliasedAttributeName,
|
||||
adaptValue(annotatedElement, value, classValuesAsString, nestedAnnotationsAsMap));
|
||||
valuesAlreadyReplaced.add(aliasedAttributeName);
|
||||
}
|
||||
}
|
||||
else if (aliasPresent) {
|
||||
// Replace value with aliasedValue
|
||||
attributes.put(attributeName,
|
||||
adaptValue(annotatedElement, aliasedValue, classValuesAsString, nestedAnnotationsAsMap));
|
||||
valuesAlreadyReplaced.add(attributeName);
|
||||
}
|
||||
else {
|
||||
// Replace aliasedValue with value
|
||||
attributes.put(aliasedAttributeName,
|
||||
adaptValue(annotatedElement, value, classValuesAsString, nestedAnnotationsAsMap));
|
||||
valuesAlreadyReplaced.add(aliasedAttributeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
attributes.validated = true;
|
||||
}
|
||||
|
||||
// Replace any remaining placeholders with actual default values
|
||||
@@ -1360,8 +1429,12 @@ public abstract class AnnotationUtils {
|
||||
* @see #synthesizeAnnotation(Map, Class, AnnotatedElement)
|
||||
* @see #synthesizeAnnotation(Class)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <A extends Annotation> A synthesizeAnnotation(A annotation, AnnotatedElement annotatedElement) {
|
||||
return synthesizeAnnotation(annotation, (Object) annotatedElement);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static <A extends Annotation> A synthesizeAnnotation(A annotation, Object annotatedElement) {
|
||||
if (annotation == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -1466,7 +1539,7 @@ public abstract class AnnotationUtils {
|
||||
* @see #synthesizeAnnotation(Annotation, AnnotatedElement)
|
||||
* @see #synthesizeAnnotation(Map, Class, AnnotatedElement)
|
||||
*/
|
||||
public static Annotation[] synthesizeAnnotationArray(Annotation[] annotations, AnnotatedElement annotatedElement) {
|
||||
static Annotation[] synthesizeAnnotationArray(Annotation[] annotations, Object annotatedElement) {
|
||||
if (annotations == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -1494,7 +1567,7 @@ public abstract class AnnotationUtils {
|
||||
* {@code @AliasFor} is detected
|
||||
* @since 4.2.1
|
||||
* @see #synthesizeAnnotation(Map, Class, AnnotatedElement)
|
||||
* @see #synthesizeAnnotationArray(Annotation[], AnnotatedElement)
|
||||
* @see #synthesizeAnnotationArray(Annotation[], Object)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
static <A extends Annotation> A[] synthesizeAnnotationArray(Map<String, Object>[] maps, Class<A> annotationType) {
|
||||
@@ -1582,7 +1655,7 @@ public abstract class AnnotationUtils {
|
||||
private static boolean isSynthesizable(Class<? extends Annotation> annotationType) {
|
||||
Boolean synthesizable = synthesizableCache.get(annotationType);
|
||||
if (synthesizable != null) {
|
||||
return synthesizable.booleanValue();
|
||||
return synthesizable;
|
||||
}
|
||||
|
||||
synthesizable = Boolean.FALSE;
|
||||
@@ -1610,7 +1683,7 @@ public abstract class AnnotationUtils {
|
||||
}
|
||||
|
||||
synthesizableCache.put(annotationType, synthesizable);
|
||||
return synthesizable.booleanValue();
|
||||
return synthesizable;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.core.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
@@ -32,7 +31,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
* @see AliasFor
|
||||
* @see AbstractAliasAwareAnnotationAttributeExtractor
|
||||
* @see MapAnnotationAttributeExtractor
|
||||
* @see AnnotationUtils#synthesizeAnnotation(Annotation, AnnotatedElement)
|
||||
* @see AnnotationUtils#synthesizeAnnotation
|
||||
*/
|
||||
class DefaultAnnotationAttributeExtractor extends AbstractAliasAwareAnnotationAttributeExtractor<Annotation> {
|
||||
|
||||
@@ -42,7 +41,7 @@ class DefaultAnnotationAttributeExtractor extends AbstractAliasAwareAnnotationAt
|
||||
* @param annotatedElement the element that is annotated with the supplied
|
||||
* annotation; may be {@code null} if unknown
|
||||
*/
|
||||
DefaultAnnotationAttributeExtractor(Annotation annotation, AnnotatedElement annotatedElement) {
|
||||
DefaultAnnotationAttributeExtractor(Annotation annotation, Object annotatedElement) {
|
||||
super(annotation.annotationType(), annotatedElement, annotation);
|
||||
}
|
||||
|
||||
|
||||
+6
-7
@@ -24,10 +24,9 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import static org.springframework.core.annotation.AnnotationUtils.*;
|
||||
|
||||
/**
|
||||
* Implementation of the {@link AnnotationAttributeExtractor} strategy that
|
||||
* is backed by a {@link Map}.
|
||||
@@ -89,9 +88,9 @@ class MapAnnotationAttributeExtractor extends AbstractAliasAwareAnnotationAttrib
|
||||
Map<String, Object> originalAttributes, Class<? extends Annotation> annotationType) {
|
||||
|
||||
Map<String, Object> attributes = new LinkedHashMap<String, Object>(originalAttributes);
|
||||
Map<String, List<String>> attributeAliasMap = getAttributeAliasMap(annotationType);
|
||||
Map<String, List<String>> attributeAliasMap = AnnotationUtils.getAttributeAliasMap(annotationType);
|
||||
|
||||
for (Method attributeMethod : getAttributeMethods(annotationType)) {
|
||||
for (Method attributeMethod : AnnotationUtils.getAttributeMethods(annotationType)) {
|
||||
String attributeName = attributeMethod.getName();
|
||||
Object attributeValue = attributes.get(attributeName);
|
||||
|
||||
@@ -112,7 +111,7 @@ class MapAnnotationAttributeExtractor extends AbstractAliasAwareAnnotationAttrib
|
||||
|
||||
// if aliases not present, check default
|
||||
if (attributeValue == null) {
|
||||
Object defaultValue = getDefaultValue(annotationType, attributeName);
|
||||
Object defaultValue = AnnotationUtils.getDefaultValue(annotationType, attributeName);
|
||||
if (defaultValue != null) {
|
||||
attributeValue = defaultValue;
|
||||
attributes.put(attributeName, attributeValue);
|
||||
@@ -147,7 +146,7 @@ class MapAnnotationAttributeExtractor extends AbstractAliasAwareAnnotationAttrib
|
||||
Class<? extends Annotation> nestedAnnotationType =
|
||||
(Class<? extends Annotation>) requiredReturnType;
|
||||
Map<String, Object> map = (Map<String, Object>) attributeValue;
|
||||
attributes.put(attributeName, synthesizeAnnotation(map, nestedAnnotationType, null));
|
||||
attributes.put(attributeName, AnnotationUtils.synthesizeAnnotation(map, nestedAnnotationType, null));
|
||||
converted = true;
|
||||
}
|
||||
|
||||
@@ -158,7 +157,7 @@ class MapAnnotationAttributeExtractor extends AbstractAliasAwareAnnotationAttrib
|
||||
Class<? extends Annotation> nestedAnnotationType =
|
||||
(Class<? extends Annotation>) requiredReturnType.getComponentType();
|
||||
Map<String, Object>[] maps = (Map<String, Object>[]) attributeValue;
|
||||
attributes.put(attributeName, synthesizeAnnotationArray(maps, nestedAnnotationType));
|
||||
attributes.put(attributeName, AnnotationUtils.synthesizeAnnotationArray(maps, nestedAnnotationType));
|
||||
converted = true;
|
||||
}
|
||||
|
||||
|
||||
+14
-17
@@ -27,11 +27,9 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.springframework.core.annotation.AnnotationUtils.*;
|
||||
import static org.springframework.util.ReflectionUtils.*;
|
||||
|
||||
/**
|
||||
* {@link InvocationHandler} for an {@link Annotation} that Spring has
|
||||
* <em>synthesized</em> (i.e., wrapped in a dynamic proxy) with additional
|
||||
@@ -63,22 +61,21 @@ class SynthesizedAnnotationInvocationHandler implements InvocationHandler {
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
if (isEqualsMethod(method)) {
|
||||
if (ReflectionUtils.isEqualsMethod(method)) {
|
||||
return annotationEquals(args[0]);
|
||||
}
|
||||
if (isHashCodeMethod(method)) {
|
||||
if (ReflectionUtils.isHashCodeMethod(method)) {
|
||||
return annotationHashCode();
|
||||
}
|
||||
if (isToStringMethod(method)) {
|
||||
if (ReflectionUtils.isToStringMethod(method)) {
|
||||
return annotationToString();
|
||||
}
|
||||
if (isAnnotationTypeMethod(method)) {
|
||||
if (AnnotationUtils.isAnnotationTypeMethod(method)) {
|
||||
return annotationType();
|
||||
}
|
||||
if (!isAttributeMethod(method)) {
|
||||
String msg = String.format("Method [%s] is unsupported for synthesized annotation type [%s]",
|
||||
method, annotationType());
|
||||
throw new AnnotationConfigurationException(msg);
|
||||
if (!AnnotationUtils.isAttributeMethod(method)) {
|
||||
throw new AnnotationConfigurationException(String.format(
|
||||
"Method [%s] is unsupported for synthesized annotation type [%s]", method, annotationType()));
|
||||
}
|
||||
return getAttributeValue(method);
|
||||
}
|
||||
@@ -100,10 +97,10 @@ class SynthesizedAnnotationInvocationHandler implements InvocationHandler {
|
||||
|
||||
// Synthesize nested annotations before returning them.
|
||||
if (value instanceof Annotation) {
|
||||
value = synthesizeAnnotation((Annotation) value, this.attributeExtractor.getAnnotatedElement());
|
||||
value = AnnotationUtils.synthesizeAnnotation((Annotation) value, this.attributeExtractor.getAnnotatedElement());
|
||||
}
|
||||
else if (value instanceof Annotation[]) {
|
||||
value = synthesizeAnnotationArray((Annotation[]) value, this.attributeExtractor.getAnnotatedElement());
|
||||
value = AnnotationUtils.synthesizeAnnotationArray((Annotation[]) value, this.attributeExtractor.getAnnotatedElement());
|
||||
}
|
||||
|
||||
this.valueCache.put(attributeName, value);
|
||||
@@ -164,9 +161,9 @@ class SynthesizedAnnotationInvocationHandler implements InvocationHandler {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Method attributeMethod : getAttributeMethods(annotationType())) {
|
||||
for (Method attributeMethod : AnnotationUtils.getAttributeMethods(annotationType())) {
|
||||
Object thisValue = getAttributeValue(attributeMethod);
|
||||
Object otherValue = invokeMethod(attributeMethod, other);
|
||||
Object otherValue = ReflectionUtils.invokeMethod(attributeMethod, other);
|
||||
if (!ObjectUtils.nullSafeEquals(thisValue, otherValue)) {
|
||||
return false;
|
||||
}
|
||||
@@ -181,7 +178,7 @@ class SynthesizedAnnotationInvocationHandler implements InvocationHandler {
|
||||
private int annotationHashCode() {
|
||||
int result = 0;
|
||||
|
||||
for (Method attributeMethod : getAttributeMethods(annotationType())) {
|
||||
for (Method attributeMethod : AnnotationUtils.getAttributeMethods(annotationType())) {
|
||||
Object value = getAttributeValue(attributeMethod);
|
||||
int hashCode;
|
||||
if (value.getClass().isArray()) {
|
||||
@@ -239,7 +236,7 @@ class SynthesizedAnnotationInvocationHandler implements InvocationHandler {
|
||||
private String annotationToString() {
|
||||
StringBuilder sb = new StringBuilder("@").append(annotationType().getName()).append("(");
|
||||
|
||||
Iterator<Method> iterator = getAttributeMethods(annotationType()).iterator();
|
||||
Iterator<Method> iterator = AnnotationUtils.getAttributeMethods(annotationType()).iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Method attributeMethod = iterator.next();
|
||||
sb.append(attributeMethod.getName());
|
||||
|
||||
@@ -343,7 +343,7 @@ public class TypeDescriptor implements Serializable {
|
||||
if (streamAvailable && StreamDelegate.isStream(this.type)) {
|
||||
return StreamDelegate.getStreamElementType(this);
|
||||
}
|
||||
return getRelatedIfResolvable(this, this.resolvableType.asCollection().getGeneric());
|
||||
return getRelatedIfResolvable(this, this.resolvableType.asCollection().getGeneric(0));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -706,7 +706,7 @@ public class TypeDescriptor implements Serializable {
|
||||
}
|
||||
|
||||
public static TypeDescriptor getStreamElementType(TypeDescriptor source) {
|
||||
return getRelatedIfResolvable(source, source.resolvableType.as(Stream.class).getGeneric());
|
||||
return getRelatedIfResolvable(source, source.resolvableType.as(Stream.class).getGeneric(0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -185,9 +185,6 @@ final class ObjectToObjectConverter implements ConditionalGenericConverter {
|
||||
method = ClassUtils.getStaticMethod(targetClass, "of", sourceClass);
|
||||
if (method == null) {
|
||||
method = ClassUtils.getStaticMethod(targetClass, "from", sourceClass);
|
||||
if (method == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return method;
|
||||
|
||||
+10
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -19,10 +19,10 @@ package org.springframework.core.env;
|
||||
import org.springframework.core.convert.support.ConfigurableConversionService;
|
||||
|
||||
/**
|
||||
* Configuration interface to be implemented by most if not all {@link PropertyResolver
|
||||
* PropertyResolver} types. Provides facilities for accessing and customizing the
|
||||
* {@link org.springframework.core.convert.ConversionService ConversionService} used when
|
||||
* converting property values from one type to another.
|
||||
* Configuration interface to be implemented by most if not all {@link PropertyResolver}
|
||||
* types. Provides facilities for accessing and customizing the
|
||||
* {@link org.springframework.core.convert.ConversionService ConversionService}
|
||||
* used when converting property values from one type to another.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
@@ -30,7 +30,7 @@ import org.springframework.core.convert.support.ConfigurableConversionService;
|
||||
public interface ConfigurablePropertyResolver extends PropertyResolver {
|
||||
|
||||
/**
|
||||
* @return the {@link ConfigurableConversionService} used when performing type
|
||||
* Return the {@link ConfigurableConversionService} used when performing type
|
||||
* conversions on properties.
|
||||
* <p>The configurable nature of the returned conversion service allows for
|
||||
* the convenient addition and removal of individual {@code Converter} instances:
|
||||
@@ -46,10 +46,10 @@ public interface ConfigurablePropertyResolver extends PropertyResolver {
|
||||
/**
|
||||
* Set the {@link ConfigurableConversionService} to be used when performing type
|
||||
* conversions on properties.
|
||||
* <p><strong>Note:</strong> as an alternative to fully replacing the {@code
|
||||
* ConversionService}, consider adding or removing individual {@code Converter}
|
||||
* instances by drilling into {@link #getConversionService()} and calling methods
|
||||
* such as {@code #addConverter}.
|
||||
* <p><strong>Note:</strong> as an alternative to fully replacing the
|
||||
* {@code ConversionService}, consider adding or removing individual
|
||||
* {@code Converter} instances by drilling into {@link #getConversionService()}
|
||||
* and calling methods such as {@code #addConverter}.
|
||||
* @see PropertyResolver#getProperty(String, Class)
|
||||
* @see #getConversionService()
|
||||
* @see org.springframework.core.convert.converter.ConverterRegistry#addConverter
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user