Compare commits

...

79 Commits

Author SHA1 Message Date
Spring Buildmaster 62b8f97f0f Release version 4.3.2.RELEASE 2016-07-28 08:25:35 +00:00
Juergen Hoeller ff878ea9dc ConfigurationClassParser uses unified ImportStack with chained import analysis
Issue: SPR-14517
(cherry picked from commit d96a66a)
2016-07-28 00:13:05 +02:00
Juergen Hoeller 7021a4be44 JndiPropertySource defensively skips invalid JNDI lookup for property name with colon in resource-ref mode
Issue: SPR-14518
(cherry picked from commit 328e04f)
2016-07-28 00:12:50 +02:00
Juergen Hoeller 5c4737c3d0 Upgrade to Netty 4.1.4 2016-07-27 16:49:37 +02:00
Juergen Hoeller fbf3807af1 Polishing
(cherry picked from commit 5db4495)
2016-07-27 16:49:18 +02:00
Juergen Hoeller 703c37ec88 Isolated circular import detection for scanned configuration classes
Issue: SPR-14517
(cherry picked from commit 316244d)
2016-07-27 16:49:04 +02:00
Juergen Hoeller 96440878bb Polishing 2016-07-27 13:00:30 +02:00
Juergen Hoeller b5c11ffb1c Expose DefaultSubscriptionRegistry's cache limit through SimpleBrokerMessageHandler and MessageBrokerRegistry
Issue: SPR-14516
(cherry picked from commit 6d5af60)
2016-07-27 12:34:28 +02:00
Juergen Hoeller 7f5b323d50 Upgrade to Jetty 9.3.11 (includes fixed Quartz javadoc URL) 2016-07-26 22:19:56 +02:00
Juergen Hoeller 67176e2b75 TransactionAspectSupport avoids hard references to transaction manager beans
Issue: SPR-14511
(cherry picked from commit 02374d7)
2016-07-26 21:46:49 +02:00
Juergen Hoeller 79f3cf3263 Build against Undertow 1.3.x in 4.3.x branch (retaining runtime compatibility Undertow 1.4)
Issue: SPR-14328
2016-07-26 10:08:06 +02:00
Juergen Hoeller 9ee1dc79fd Deprecate JpaSystemException(PersistenceException) constructor to prepare for removal in Spring 5
Issue: SPR-13827
2016-07-26 01:29:51 +02:00
Juergen Hoeller 9e2c34dfa6 Fixed ConcurrentMap declaration
(cherry picked from commit 23135b1)
2016-07-26 00:28:40 +02:00
Juergen Hoeller cc93c2a559 Polishing 2016-07-26 00:03:21 +02:00
Juergen Hoeller 15c7044c4d Upgrade to EhCache 3.1.1 and OkHttp 3.4.1 2016-07-25 15:20:08 +02:00
Juergen Hoeller 0ef80d3579 JasperReportsMultiFormatViewTests does not check for CUSTOM_COMPILATION anymore
Issue: SPR-10423
2016-07-25 15:19:50 +02:00
Juergen Hoeller 95c2e0a996 Upgrade JiBX (and BCEL) towards support of 1.8 bytecode level
This commit also drops the now-unused CUSTOM_COMPILATION test group and the outdated JavaVersion class.

Issue: SPR-10423
(cherry picked from commit 01110f6)
2016-07-25 14:58:43 +02:00
Juergen Hoeller da3e8611e1 Upgrade JiBX (and BCEL) towards support of 1.8 bytecode level
Issue: SPR-10423
2016-07-25 13:08:46 +02:00
Juergen Hoeller 64595597f3 LinkedCaseInsensitiveMap properly overrides HashMap.clone()
Issue: SPR-14509
(cherry picked from commit dd65f7a)
2016-07-25 12:14:51 +02:00
Juergen Hoeller 82f2983cd4 Consistent throwing of BeanNotOfRequiredTypeException even for existing proxy
Issue: SPR-14504
(cherry picked from commit 4a85309)
2016-07-24 15:47:06 +02:00
Juergen Hoeller 9451177c35 Polishing
(cherry picked from commit 382a931)
2016-07-22 22:45:14 +02:00
Juergen Hoeller 9ed087d5da Consistent support for multiple Accept headers
Issue: SPR-14506
(cherry picked from commit e59a599)
2016-07-22 22:45:04 +02:00
Juergen Hoeller 77f22e9674 DataSource adapters expose setCatalog/setSchema next to setUsername/setPassword
Issue: SPR-14501
(cherry picked from commit 610bdf1)
2016-07-21 14:13:37 +02:00
Juergen Hoeller 8ccfdbbcf9 ResourcePatternUtils.getResourcePatternResolver actually accepts null argument
Issue: SPR-14500
(cherry picked from commit e756a5b)
2016-07-21 14:09:32 +02:00
Juergen Hoeller 5a92aa4e06 Polishing
(cherry picked from commit a39276a)
2016-07-20 23:23:30 +02:00
Juergen Hoeller 7b1010cf61 Polishing 2016-07-20 22:31:45 +02:00
Juergen Hoeller 45b2f5bac4 Upgrade to Jackson 2.8.1 2016-07-20 22:31:25 +02:00
Juergen Hoeller 36e1c82ef5 Backported refinements and polishing 2016-07-20 21:46:25 +02:00
Juergen Hoeller 503d65d570 Avoid JDK proxy against CGLIB Factory interface and assert required type when resolving dependency
Issue: SPR-14478
(cherry picked from commit 0e3f0bd)
2016-07-20 21:45:41 +02:00
Juergen Hoeller fe17f8da41 BeanWrapperImpl.setBeanInstance correctly exposes root object
Issue: SPR-14474
(cherry picked from commit 938b56c)
2016-07-20 21:44:46 +02:00
Juergen Hoeller b583aa1579 Avoid dependency on WebUtils for extracting file extension
Issue: SPR-14479
(cherry picked from commit adc595b)
2016-07-20 21:44:37 +02:00
Juergen Hoeller e0d81b97bb SerializableTypeWrapper reobtains type accessors from declaring interface
Issue: SPR-14487
(cherry picked from commit 8580483)
2016-07-20 21:41:42 +02:00
Juergen Hoeller 90752f9d87 Deprecate mock.staticmock package
Issue: SPR-14485
2016-07-20 21:41:30 +02:00
Juergen Hoeller 3663aa675a GenericSqlQuery configured with RowMapper instance
Issue: SPR-14489
(cherry picked from commit 7287bae)
2016-07-20 21:40:48 +02:00
Juergen Hoeller 1ca4b81856 Reinstated tests for implicit aliases
Issue: SPR-14437
(cherry picked from commit 5ea8c26)
2016-07-20 21:40:33 +02:00
Juergen Hoeller 4e7e06f549 Reliably pass CurrentTenantIdentifierResolver to SessionFactory
Issue: SPR-14476
2016-07-20 21:40:26 +02:00
Sebastien Deleuze b2f0bdb0f4 Polishing
Issue: SPR-14470
2016-07-20 09:16:50 +02:00
Rossen Stoyanchev d98bd34200 Remove isAsyncStarted assertion
Issue: SPR-14444
2016-07-19 16:44:46 -04:00
Sebastien Deleuze 940bdd878e Fix ParameterizedType + contextClass support in Jackson converter
Issue: SPR-14470
2016-07-19 18:10:51 +02:00
Vladimir L df556333a8 Add StreamingResponseBody MockMvc sample tests
Issue: SPR-14456
(cherry picked from 7da63c)
2016-07-19 10:48:29 -04:00
Stephane Nicoll 116f05eda6 Revert "Upgrade to EJB 3.1" 2016-07-18 13:37:43 +02:00
Stephane Nicoll b187bbeca3 Upgrade to EJB 3.1 2016-07-18 13:22:54 +02:00
Do Nhu Vy 479a83b628 Fix broken hyperlink
Closes gh-1114
2016-07-18 08:17:49 +02:00
Fredrik Sundberg 1c18100143 Fix javadoc reference
Method is called nextBackOff() and not nextBackOffMillis().

Closes gh-1115
2016-07-18 08:15:41 +02:00
Juergen Hoeller 5d3c0f33f6 Upgrade to Netty 4.1.3 and Tomcat 8.5.4 2016-07-15 22:47:22 +02:00
Juergen Hoeller afe106e254 Polishing 2016-07-15 22:47:12 +02:00
Juergen Hoeller 69dd40ec89 Javadoc fixes and pruning of deprecated references 2016-07-15 22:47:05 +02:00
Sam Brannen dee50d5e28 Polish annotation utils
(cherry picked from commit 177f4ec)
2016-07-15 22:21:23 +02:00
Juergen Hoeller 9e93403857 ConfigurationClassParser load annotations through source class loader
Issue: SPR-10343
2016-07-15 16:02:06 +02:00
Juergen Hoeller 12bff6b3a0 Velocity deprecation note in reference documentation
Issue: SPR-14460
2016-07-15 15:44:13 +02:00
Juergen Hoeller 70e666b4a3 MultipartResolutionDelegate's resolveMultipartArgument properly operates on Servlet 2.5
Issue: SPR-14461
2016-07-15 15:42:32 +02:00
Juergen Hoeller 29f980ec72 Unwrap JPA PersistenceException on flush failure (for Hibernate 5.2)
Issue: SPR-14457
2016-07-15 15:40:38 +02:00
Juergen Hoeller 1d39d762f0 HibernateExceptionTranslator converts JPA exceptions as well (for Hibernate 5.2)
Issue: SPR-14455
2016-07-15 15:40:26 +02:00
Juergen Hoeller 4d6d5e0ddd Consistent alias processing behind AnnotatedTypeMetadata abstraction (also for ASM)
Issue: SPR-14427
(cherry picked from commit 3d3407c)
2016-07-15 15:40:01 +02:00
Juergen Hoeller 4ea5f070a4 MessageHeaderAccessor properly removes header even in case of null value
Issue: SPR-14468
(cherry picked from commit b166358)
2016-07-15 15:39:33 +02:00
Juergen Hoeller da59b4da9b CronSequenceGenerator prevents stack overflow in case of inverted range
Issue: SPR-14462
(cherry picked from commit e431624)
2016-07-15 15:39:17 +02:00
Juergen Hoeller 0065a160cc StandardTypeConverter initializes default ConversionService against volatile field
Issue: SPR-14465
(cherry picked from commit 6d91d54)
2016-07-15 15:39:09 +02:00
Juergen Hoeller 52f46c7fea Aspect actually applies in PersistenceExceptionTranslationPostProcessorTests
Issue: SPR-14457
(cherry picked from commit 04e9c2b)
2016-07-15 15:38:44 +02:00
Juergen Hoeller f0a826ec0c AbstractHandlerMethodMapping adds type+method info to getMappingForMethod exceptions
Issue: SPR-14452
(cherry picked from commit 8ccd727)
2016-07-15 15:38:23 +02:00
Juergen Hoeller 5c3c0f73c1 Configurable UrlPathHelper in PathExtensionContentNegotiationStrategy
This commit also aligns ResourceUrlProvider's and RequestMappingInfo's UrlPathHelper setter/getter signatures.

Issue: SPR-14454
(cherry picked from commit 84afc60)
2016-07-15 15:37:56 +02:00
Juergen Hoeller be0b71ce31 Fixed typo: "occured"->"occurred"
(cherry picked from commit c43e749)
2016-07-15 15:37:11 +02:00
Juergen Hoeller f85d48dd31 Added PathEditor for NIO file system resolution
Issue: SPR-14436
(cherry picked from commit 23c2b6a)
2016-07-15 15:37:02 +02:00
Juergen Hoeller a1b58ee601 DigestUtils processes InputStream with buffered read instead of full copy
Issue: SPR-14427
(cherry picked from commit 61db8e9)
2016-07-15 15:34:36 +02:00
Juergen Hoeller e30429051d Polishing
(cherry picked from commit 6aa5931)
2016-07-15 15:34:27 +02:00
fisache 942ead75e2 Polish doc
Closes gh-1108
2016-07-14 19:16:20 +02:00
nkjackzhang 453688f6df Polish doc
Closes gh-1110
2016-07-14 11:57:41 +02:00
Stephane Nicoll 7d7a161102 Polish contribution
Closes gh-1070
2016-07-14 11:26:31 +02:00
spodgurskiy aaa223ae66 Fix MethodBasedEvaluationContext.lazyLoadArguments
This commit fix a potential `ArrayIndexOutOfBoundsException` if
`lazyLoadArguments` is called with an empty variable argument.

See gh-1070
2016-07-14 11:26:20 +02:00
Brian Clozel d11c624fb0 Polish AntPathMatcher.setTrimTokens javadoc
Issue: SPR-14247
Cherry-picked from 147a35f
2016-07-12 14:50:00 +02:00
nkjackzhang 275e51b19d Polish doc
Closes gh-1107
2016-07-12 08:51:35 +02:00
Stephane Nicoll ab62edeeaa Fix NoOpCache handling of get(key,callable)
This commit fixes the method that takes a Callable to actually always
invoke it rather than returning null.

Issue: SPR-14445
2016-07-11 10:36:51 +02:00
Sam Brannen 813108a928 Ensure TestContextManager always tracks after-class exception
This commit fixes a minor bug introduced in 0adc4921ed.

Issue: SPR-14447
2016-07-10 16:00:30 +02:00
Juergen Hoeller 3c14911401 Polishing 2016-07-06 17:59:49 +02:00
Juergen Hoeller 4337f14627 Upgrade to Jackson 2.8 GA 2016-07-06 17:42:10 +02:00
Juergen Hoeller 92d78c10a2 Polishing (backported from master) 2016-07-06 17:13:18 +02:00
Juergen Hoeller 16d5ba9b3a Restored binary compatibility with Hibernate 5.0/5.1's Query type
Issue: SPR-14425
2016-07-06 16:11:15 +02:00
Juergen Hoeller 52065a736b Avoid canonicalName call for already-seen bean name
Issue: SPR-14433
(cherry picked from commit 5890758)
2016-07-06 16:09:32 +02:00
Stephane Nicoll 11cb109114 Upgrade copyright 2016-07-04 12:45:34 +02:00
Stephane Nicoll d7eadd41d6 Switch to 4.3.2.BUILD-SNAPSHOT 2016-07-04 12:28:13 +02:00
280 changed files with 2703 additions and 2122 deletions
+14 -23
View File
@@ -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
View File
@@ -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
@@ -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);
}
}
@@ -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"));
}
}
@@ -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();
@@ -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 {
@@ -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 {
@@ -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());
}
@@ -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.
*/
@@ -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;
}
}
@@ -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
*/
@@ -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;
@@ -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);
}
}
@@ -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;
@@ -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.
@@ -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 {
@@ -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 {
@@ -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];
@@ -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);
@@ -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;
@@ -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);
}
}
@@ -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);
}
}
@@ -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) {
@@ -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) {
@@ -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 {
@@ -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() : "");
}
}
@@ -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();
@@ -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));
@@ -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));
}
}
@@ -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
@@ -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));
}
}
@@ -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
@@ -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());
}
}
@@ -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>
@@ -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;
@@ -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()]);
@@ -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);
}
}
@@ -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
*/
@@ -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
@@ -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;
@@ -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;
@@ -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 " +
@@ -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);
@@ -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;
}
@@ -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;
@@ -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);
}
@@ -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) {
@@ -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]);
}
}
@@ -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
@@ -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;
}
@@ -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));
}
@@ -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()) {
@@ -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 {
@@ -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)) {
@@ -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(
@@ -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(
@@ -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());
@@ -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();
}
}
@@ -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();
@@ -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
*/
@@ -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 {
}
@@ -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 {};
}
@@ -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){
}
}
}
@@ -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 {
}
}
@@ -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 {
}
}
@@ -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());
}
@@ -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);
@@ -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");
@@ -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"));
}
}
@@ -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 {
@@ -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 * * *"));
@@ -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);
@@ -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);
}
}
@@ -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());
}
}
@@ -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)));
}
@@ -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.
@@ -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);
@@ -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;
}
/**
@@ -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);
}
@@ -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;
}
@@ -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,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;
@@ -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