mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
131 Commits
6.2.x
...
v4.1.6.RELEASE
| Author | SHA1 | Date | |
|---|---|---|---|
| c734ee12b3 | |||
| 97f779674f | |||
| 5f6ae13002 | |||
| 52ed9b7106 | |||
| ca09eb2c59 | |||
| 13a87453b6 | |||
| 673dac5620 | |||
| 6892ad42d6 | |||
| 1d5128ed1b | |||
| 34aac078b1 | |||
| f52702ea3c | |||
| d2d006b68f | |||
| 8d14e7736a | |||
| 2de5faf56c | |||
| 5f95ff6bfd | |||
| 4446b5fe8a | |||
| 76649a4455 | |||
| 98d00ea698 | |||
| ce84fafde4 | |||
| b352dbfdeb | |||
| f42c53d9be | |||
| 151e96cac4 | |||
| a522fa36af | |||
| 5c463a1680 | |||
| 0280a2a994 | |||
| b455626ce1 | |||
| cb6459c271 | |||
| 6b9e89118f | |||
| f2b9a0a117 | |||
| 406adb3381 | |||
| bac012f3e8 | |||
| f93394171a | |||
| ebe45cf079 | |||
| 7ed7f981c9 | |||
| f01a0303f1 | |||
| f2691901bb | |||
| 5f305759fa | |||
| 410fc6d763 | |||
| 3783591083 | |||
| 1259671f3f | |||
| 590b23ccb3 | |||
| 2d98988d5c | |||
| 364210b0e7 | |||
| b6f22aa514 | |||
| 522c1b1b3d | |||
| 55eb5b622c | |||
| 6c93745f35 | |||
| ca9f6a1e1e | |||
| 3570a9a94a | |||
| 91c47a9eb8 | |||
| 7eb4679f28 | |||
| 0f95c81712 | |||
| 2c47098b35 | |||
| b4d9fb9e6e | |||
| 4a332bd0b2 | |||
| 772552b9ef | |||
| 6be554cba5 | |||
| ce085a606f | |||
| c0e550cfb4 | |||
| 7a5b2e6a75 | |||
| d7dcf8d6f4 | |||
| d77af71e9c | |||
| 5db4e4bab0 | |||
| 7cc56e1630 | |||
| b5e80390de | |||
| 55a14eb684 | |||
| d8269dd9fe | |||
| aae7583141 | |||
| 6fafe63311 | |||
| f1e406c63b | |||
| c8a4d1649f | |||
| 8dbe753963 | |||
| 23fa37b08b | |||
| cc78d40c6b | |||
| 1dc39324b9 | |||
| 2a240b0dc8 | |||
| 3b8d878285 | |||
| d98f626be1 | |||
| b8dbf2345c | |||
| 2b135f0d51 | |||
| e5d41d91d5 | |||
| f398dd03a7 | |||
| f82c6635d7 | |||
| 9499e4166c | |||
| bf442c093c | |||
| fab8dd3d0b | |||
| 1646f62700 | |||
| c8d9bfadad | |||
| 0706889222 | |||
| 25644dbdb9 | |||
| 181b35243e | |||
| 6c47b5f5d3 | |||
| 4a423e50a8 | |||
| 0225a7776c | |||
| d57f7f8783 | |||
| 4550b4a254 | |||
| f902fb911c | |||
| 77c8aa53ae | |||
| bb5da15e1c | |||
| 0c8d07fcff | |||
| 47fdac9214 | |||
| 7ffa845aa8 | |||
| 09bd7037e9 | |||
| 49c21a0a06 | |||
| d9d8a79c30 | |||
| 04840166af | |||
| 6fce6d4668 | |||
| 0c856b3d22 | |||
| d63cfc8eeb | |||
| 7621cc787d | |||
| 2c1682af34 | |||
| dcaa0987ee | |||
| 14a3bf3941 | |||
| 23b09015fe | |||
| b82e9c4d46 | |||
| c158874d82 | |||
| 87b7cd6368 | |||
| 901d7d07db | |||
| bfba988a0d | |||
| a7975c685d | |||
| cdaf4497b6 | |||
| 84807c5d61 | |||
| a76a6509e5 | |||
| 7d171e6722 | |||
| 36da551280 | |||
| ed665a12a3 | |||
| adec0265a4 | |||
| 8c700b19da | |||
| 9542313710 | |||
| dcb821edb5 | |||
| daa4adf2ed |
+31
-29
@@ -27,34 +27,34 @@ configure(allprojects) { project ->
|
||||
group = "org.springframework"
|
||||
version = qualifyVersionIfNecessary(version)
|
||||
|
||||
ext.aspectjVersion = "1.8.4"
|
||||
ext.aspectjVersion = "1.8.5"
|
||||
ext.eclipseLinkVersion = "2.4.2"
|
||||
ext.ehcacheVersion = "2.9.0"
|
||||
ext.ehcacheJCacheVersion = "1.0.0"
|
||||
ext.groovyVersion = "2.3.9"
|
||||
ext.ehcacheVersion = "2.9.1"
|
||||
ext.ehcacheJCacheVersion = "1.0.1"
|
||||
ext.groovyVersion = "2.3.11"
|
||||
ext.gsonVersion = "2.3.1"
|
||||
ext.hibernate3Version = "3.6.10.Final"
|
||||
ext.hibernate4Version = "4.3.7.Final"
|
||||
ext.hibernate4Version = "4.3.8.Final"
|
||||
ext.hibVal4Version = "4.3.2.Final"
|
||||
ext.hibVal5Version = "5.1.3.Final"
|
||||
ext.hsqldbVersion = "2.3.2"
|
||||
ext.jackson2Version = "2.4.4"
|
||||
ext.jasperReportsVersion = "6.0.0"
|
||||
ext.jettyVersion = "9.2.6.v20141205"
|
||||
ext.jodaVersion = "2.6"
|
||||
ext.jackson2Version = "2.4.5"
|
||||
ext.jasperReportsVersion = "6.0.3"
|
||||
ext.jettyVersion = "9.2.10.v20150310"
|
||||
ext.jodaVersion = "2.7"
|
||||
ext.junitVersion = "4.12"
|
||||
ext.nettyVersion = "4.0.24.Final"
|
||||
ext.nettyVersion = "4.0.26.Final"
|
||||
ext.openJpaVersion = "2.2.2" // 2.3.0 not Java 8 compatible (based on ASM 4)
|
||||
ext.protobufVersion = "2.6.1"
|
||||
ext.reactorVersion = "1.1.5.RELEASE"
|
||||
ext.slf4jVersion = "1.7.9"
|
||||
ext.snakeYamlVersion = "1.14"
|
||||
ext.slf4jVersion = "1.7.10"
|
||||
ext.snakeYamlVersion = "1.15"
|
||||
ext.snifferVersion = "1.11"
|
||||
ext.tiles2Version = "2.2.2"
|
||||
ext.tiles3Version = "3.0.5"
|
||||
ext.tomcatVersion = "8.0.15"
|
||||
ext.tomcatVersion = "8.0.20"
|
||||
ext.tyrusVersion = "1.3.5" // constrained by WebLogic 12.1.3 support
|
||||
ext.undertowVersion = "1.1.1.Final"
|
||||
ext.undertowVersion = "1.1.3.Final"
|
||||
ext.woodstoxVersion = "4.4.1"
|
||||
ext.xstreamVersion = "1.4.7"
|
||||
|
||||
@@ -143,7 +143,6 @@ configure(allprojects) { project ->
|
||||
|
||||
inputs.dir sourceSets.main.output.classesDir
|
||||
inputs.dir copyJavaApiSignature.to
|
||||
outputs.upToDateWhen { true }
|
||||
|
||||
doLast {
|
||||
ant.taskdef(
|
||||
@@ -334,7 +333,7 @@ project("spring-core") {
|
||||
optional("net.sf.jopt-simple:jopt-simple:4.8")
|
||||
optional("log4j:log4j:1.2.17")
|
||||
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
|
||||
testCompile("xmlunit:xmlunit:1.5")
|
||||
testCompile("xmlunit:xmlunit:1.6")
|
||||
testCompile("org.codehaus.woodstox:woodstox-core-asl:${woodstoxVersion}") {
|
||||
exclude group: "stax", module: "stax-api"
|
||||
}
|
||||
@@ -405,7 +404,7 @@ project("spring-aop") {
|
||||
compile("aopalliance:aopalliance:1.0")
|
||||
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
optional("commons-pool:commons-pool:1.6")
|
||||
optional("com.jamonapi:jamon:2.79")
|
||||
optional("com.jamonapi:jamon:2.81")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -460,7 +459,7 @@ project("spring-context") {
|
||||
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
|
||||
optional("org.beanshell:bsh:2.0b4")
|
||||
optional("org.jruby:jruby:1.7.17")
|
||||
optional("org.jruby:jruby:1.7.19")
|
||||
testCompile("javax.inject:javax.inject-tck:1")
|
||||
testCompile("commons-dbcp:commons-dbcp:1.4")
|
||||
testCompile("org.slf4j:slf4j-api:${slf4jVersion}")
|
||||
@@ -552,9 +551,9 @@ project("spring-oxm") {
|
||||
exclude group: 'xpp3', module: 'xpp3_min'
|
||||
exclude group: 'xmlpull', module: 'xmlpull'
|
||||
}
|
||||
optional("org.jibx:jibx-run:1.2.5")
|
||||
optional("org.jibx:jibx-run:1.2.6")
|
||||
testCompile(project(":spring-context"))
|
||||
testCompile("xmlunit:xmlunit:1.5")
|
||||
testCompile("xmlunit:xmlunit:1.6")
|
||||
testCompile("xpp3:xpp3:1.1.4c")
|
||||
testCompile("org.codehaus.jettison:jettison:1.3.7") {
|
||||
exclude group: 'stax', module: 'stax-api'
|
||||
@@ -595,7 +594,7 @@ project("spring-jdbc") {
|
||||
optional("javax.transaction:javax.transaction-api:1.2")
|
||||
optional("com.mchange:c3p0:0.9.2.1")
|
||||
optional("org.hsqldb:hsqldb:${hsqldbVersion}")
|
||||
optional("com.h2database:h2:1.4.182")
|
||||
optional("com.h2database:h2:1.4.186")
|
||||
optional("org.apache.derby:derby:10.11.1.1")
|
||||
optional("org.apache.derby:derbyclient:10.11.1.1")
|
||||
}
|
||||
@@ -617,7 +616,7 @@ project("spring-context-support") {
|
||||
optional("org.quartz-scheduler:quartz:2.2.1")
|
||||
optional("org.codehaus.fabric3.api:commonj:1.1.0")
|
||||
optional("org.apache.velocity:velocity:1.7")
|
||||
optional("org.freemarker:freemarker:2.3.21")
|
||||
optional("org.freemarker:freemarker:2.3.22")
|
||||
optional("com.lowagie:itext:2.1.7")
|
||||
optional("net.sf.jasperreports:jasperreports:$jasperReportsVersion") {
|
||||
exclude group: "com.fasterxml.jackson.core", module: "jackson-annotations"
|
||||
@@ -625,9 +624,10 @@ project("spring-context-support") {
|
||||
exclude group: "com.fasterxml.jackson.core", module: "jackson-databind"
|
||||
exclude group: "org.olap4j", module: "olap4j"
|
||||
exclude group: "xml-apis", module: "xml-apis"
|
||||
exclude group: "org.springframework", module: "spring-context"
|
||||
}
|
||||
testCompile(project(":spring-context"))
|
||||
testCompile("org.apache.poi:poi:3.10.1")
|
||||
testCompile("org.apache.poi:poi:3.11")
|
||||
testCompile("commons-beanutils:commons-beanutils:1.8.0") // for Velocity/JasperReports
|
||||
testCompile("commons-digester:commons-digester:1.8.1") // for Velocity/JasperReports
|
||||
testCompile("org.hsqldb:hsqldb:${hsqldbVersion}")
|
||||
@@ -692,11 +692,12 @@ project("spring-web") {
|
||||
optional("com.google.protobuf:protobuf-java:${protobufVersion}")
|
||||
optional("javax.mail:javax.mail-api:1.5.2")
|
||||
testCompile(project(":spring-context-support")) // for JafMediaTypeFactory
|
||||
testCompile("xmlunit:xmlunit:1.5")
|
||||
testCompile("xmlunit:xmlunit:1.6")
|
||||
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
|
||||
testCompile("org.apache.taglibs:taglibs-standard-jstlel:1.2.1") {
|
||||
exclude group: "org.apache.taglibs", module: "taglibs-standard-spec"
|
||||
}
|
||||
testCompile("com.fasterxml.jackson.datatype:jackson-datatype-joda:${jackson2Version}")
|
||||
testRuntime("com.sun.mail:javax.mail:1.5.2")
|
||||
}
|
||||
|
||||
@@ -826,10 +827,10 @@ project("spring-webmvc") {
|
||||
optional("javax.servlet.jsp:javax.servlet.jsp-api:2.2.1")
|
||||
optional("javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:1.2.1")
|
||||
optional("net.sourceforge.jexcelapi:jxl:2.6.12")
|
||||
optional("org.apache.poi:poi:3.10.1")
|
||||
optional("org.apache.poi:poi:3.11")
|
||||
optional("org.apache.velocity:velocity:1.7")
|
||||
optional("velocity-tools:velocity-tools-view:1.4")
|
||||
optional("org.freemarker:freemarker:2.3.20")
|
||||
optional("org.freemarker:freemarker:2.3.22")
|
||||
optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
|
||||
optional("com.lowagie:itext:2.1.7")
|
||||
optional("net.sf.jasperreports:jasperreports:$jasperReportsVersion") {
|
||||
@@ -838,6 +839,7 @@ project("spring-webmvc") {
|
||||
exclude group: "com.fasterxml.jackson.core", module: "jackson-databind"
|
||||
exclude group: "org.olap4j", module: "olap4j"
|
||||
exclude group: "xml-apis", module: "xml-apis"
|
||||
exclude group: "org.springframework", module: "spring-context"
|
||||
}
|
||||
optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
|
||||
optional("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:${jackson2Version}")
|
||||
@@ -862,7 +864,7 @@ project("spring-webmvc") {
|
||||
}
|
||||
testCompile(project(":spring-aop"))
|
||||
testCompile("rhino:js:1.7R1")
|
||||
testCompile("xmlunit:xmlunit:1.5")
|
||||
testCompile("xmlunit:xmlunit:1.6")
|
||||
testCompile("dom4j:dom4j:1.6.1") {
|
||||
exclude group: "xml-apis", module: "xml-apis"
|
||||
}
|
||||
@@ -967,9 +969,9 @@ project("spring-test") {
|
||||
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
|
||||
optional("org.hamcrest:hamcrest-core:1.3")
|
||||
optional("com.jayway.jsonpath:json-path:1.1.0")
|
||||
optional("com.jayway.jsonpath:json-path:1.2.0")
|
||||
optional("org.skyscreamer:jsonassert:1.2.3")
|
||||
optional("xmlunit:xmlunit:1.5")
|
||||
optional("xmlunit:xmlunit:1.6")
|
||||
testCompile(project(":spring-context-support"))
|
||||
testCompile(project(":spring-oxm"))
|
||||
testCompile("javax.mail:javax.mail-api:1.5.2")
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
version=4.1.4.BUILD-SNAPSHOT
|
||||
version=4.1.6.RELEASE
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -165,7 +165,7 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
* @param params the parameters used to invoke the method
|
||||
*/
|
||||
protected void handleError(Throwable ex, Method method, Object... params) throws Exception {
|
||||
if (method.getReturnType().isAssignableFrom(Future.class)) {
|
||||
if (Future.class.isAssignableFrom(method.getReturnType())) {
|
||||
ReflectionUtils.rethrowException(ex);
|
||||
}
|
||||
else {
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ public class CommonsPoolTargetSource extends AbstractPoolingTargetSource impleme
|
||||
private byte whenExhaustedAction = GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION;
|
||||
|
||||
/**
|
||||
* The Jakarta Commons {@code ObjectPool} used to pool target objects
|
||||
* The Apache Commons {@code ObjectPool} used to pool target objects
|
||||
*/
|
||||
private ObjectPool pool;
|
||||
|
||||
|
||||
+38
-33
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -32,50 +32,55 @@ import static org.mockito.BDDMockito.*;
|
||||
*/
|
||||
public class JamonPerformanceMonitorInterceptorTests {
|
||||
|
||||
private JamonPerformanceMonitorInterceptor interceptor = new JamonPerformanceMonitorInterceptor();
|
||||
private final JamonPerformanceMonitorInterceptor interceptor = new JamonPerformanceMonitorInterceptor();
|
||||
|
||||
private MethodInvocation mi = mock(MethodInvocation.class);
|
||||
private final MethodInvocation mi = mock(MethodInvocation.class);
|
||||
|
||||
private Log log = mock(Log.class);
|
||||
private final Log log = mock(Log.class);
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MonitorFactory.reset();
|
||||
}
|
||||
@Before
|
||||
public void setUp() {
|
||||
MonitorFactory.reset();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
MonitorFactory.reset();
|
||||
}
|
||||
@After
|
||||
public void tearDown() {
|
||||
MonitorFactory.reset();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testInvokeUnderTraceWithNormalProcessing() throws Throwable {
|
||||
given(mi.getMethod()).willReturn(String.class.getMethod("toString"));
|
||||
@Test
|
||||
public void testInvokeUnderTraceWithNormalProcessing() throws Throwable {
|
||||
given(mi.getMethod()).willReturn(String.class.getMethod("toString"));
|
||||
|
||||
interceptor.invokeUnderTrace(mi, log);
|
||||
interceptor.invokeUnderTrace(mi, log);
|
||||
|
||||
assertEquals("jamon must track the method being invoked", 1, MonitorFactory.getNumRows());
|
||||
assertTrue("The jamon report must contain the toString method that was invoked", MonitorFactory.getReport().contains("toString"));
|
||||
}
|
||||
assertTrue("jamon must track the method being invoked", MonitorFactory.getNumRows() > 0);
|
||||
assertTrue("The jamon report must contain the toString method that was invoked",
|
||||
MonitorFactory.getReport().contains("toString"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvokeUnderTraceWithExceptionTracking() throws Throwable {
|
||||
given(mi.getMethod()).willReturn(String.class.getMethod("toString"));
|
||||
given(mi.proceed()).willThrow(new IllegalArgumentException());
|
||||
@Test
|
||||
public void testInvokeUnderTraceWithExceptionTracking() throws Throwable {
|
||||
given(mi.getMethod()).willReturn(String.class.getMethod("toString"));
|
||||
given(mi.proceed()).willThrow(new IllegalArgumentException());
|
||||
|
||||
try {
|
||||
interceptor.invokeUnderTrace(mi, log);
|
||||
fail("Must have propagated the IllegalArgumentException");
|
||||
}
|
||||
try {
|
||||
interceptor.invokeUnderTrace(mi, log);
|
||||
fail("Must have propagated the IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals("Monitors must exist for the method invocation and 2 exceptions", 3, MonitorFactory.getNumRows());
|
||||
assertTrue("The jamon report must contain the toString method that was invoked", MonitorFactory.getReport().contains("toString"));
|
||||
assertTrue("The jamon report must contain the generic exception: " + MonitorFactory.EXCEPTIONS_LABEL, MonitorFactory.getReport().contains(MonitorFactory.EXCEPTIONS_LABEL));
|
||||
assertTrue("The jamon report must contain the specific exception: IllegalArgumentException'", MonitorFactory.getReport().contains("IllegalArgumentException"));
|
||||
}
|
||||
assertEquals("Monitors must exist for the method invocation and 2 exceptions",
|
||||
3, MonitorFactory.getNumRows());
|
||||
assertTrue("The jamon report must contain the toString method that was invoked",
|
||||
MonitorFactory.getReport().contains("toString"));
|
||||
assertTrue("The jamon report must contain the generic exception: " + MonitorFactory.EXCEPTIONS_LABEL,
|
||||
MonitorFactory.getReport().contains(MonitorFactory.EXCEPTIONS_LABEL));
|
||||
assertTrue("The jamon report must contain the specific exception: IllegalArgumentException'",
|
||||
MonitorFactory.getReport().contains("IllegalArgumentException"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2015 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,9 +28,9 @@ import org.springframework.context.annotation.Role;
|
||||
* annotated with @{@link org.springframework.beans.factory.annotation.Configurable
|
||||
* Configurable}.
|
||||
*
|
||||
* <p>This configuration class is automatically imported when using the @{@link
|
||||
* EnableSpringConfigured} annotation. See {@code @EnableSpringConfigured} Javadoc for
|
||||
* complete usage details.
|
||||
* <p>This configuration class is automatically imported when using the
|
||||
* @{@link EnableSpringConfigured} annotation. See {@code @EnableSpringConfigured}'s
|
||||
* javadoc for complete usage details.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
@@ -42,9 +42,10 @@ public class SpringConfiguredConfiguration {
|
||||
public static final String BEAN_CONFIGURER_ASPECT_BEAN_NAME =
|
||||
"org.springframework.context.config.internalBeanConfigurerAspect";
|
||||
|
||||
@Bean(name=BEAN_CONFIGURER_ASPECT_BEAN_NAME)
|
||||
@Bean(name = BEAN_CONFIGURER_ASPECT_BEAN_NAME)
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public AnnotationBeanConfigurerAspect beanConfigurerAspect() {
|
||||
return AnnotationBeanConfigurerAspect.aspectOf();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+64
-47
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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,6 +31,7 @@ import groovy.lang.GroovyObjectSupport;
|
||||
import groovy.lang.GroovyShell;
|
||||
import groovy.lang.GroovySystem;
|
||||
import groovy.lang.MetaClass;
|
||||
|
||||
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
|
||||
import org.codehaus.groovy.runtime.InvokerHelper;
|
||||
|
||||
@@ -58,8 +59,17 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A Groovy-based reader for Spring bean definitions: like a Groovy builder,
|
||||
* but more of a DSL for Spring configuration. Allows syntax like:
|
||||
* but more of a DSL for Spring configuration.
|
||||
*
|
||||
* <p>This bean definition reader also understands XML bean definition files,
|
||||
* allowing for seamless mixing and matching with Groovy bean definition files.
|
||||
*
|
||||
* <p>Typically applied to a
|
||||
* {@link org.springframework.beans.factory.support.DefaultListableBeanFactory}
|
||||
* or a {@link org.springframework.context.support.GenericApplicationContext},
|
||||
* but can be used against any {@link BeanDefinitionRegistry} implementation.
|
||||
*
|
||||
* <h3>Example Syntax</h3>
|
||||
* <pre class="code">
|
||||
* import org.hibernate.SessionFactory
|
||||
* import org.apache.commons.dbcp.BasicDataSource
|
||||
@@ -84,8 +94,9 @@ import org.springframework.util.StringUtils;
|
||||
* }</pre>
|
||||
*
|
||||
* <p>You can also load resources containing beans defined in a Groovy script using
|
||||
* either the {@link #loadBeanDefinitions(org.springframework.core.io.Resource...)}
|
||||
* or {@link #loadBeanDefinitions(String...)} method, with a script looking as follows:
|
||||
* either the {@link #loadBeanDefinitions(Resource...)} or
|
||||
* {@link #loadBeanDefinitions(String...)} method, with a script looking similar to
|
||||
* the following.
|
||||
*
|
||||
* <pre class="code">
|
||||
* import org.hibernate.SessionFactory
|
||||
@@ -109,17 +120,10 @@ import org.springframework.util.StringUtils;
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* <p><b>This bean definition reader also understands XML bean definition files,
|
||||
* allowing for seamless mixing and matching with Groovy bean definition files.</b>
|
||||
*
|
||||
* <p>Typically applied to a
|
||||
* {@link org.springframework.beans.factory.support.DefaultListableBeanFactory}
|
||||
* or a {@link org.springframework.context.support.GenericApplicationContext},
|
||||
* but can be used against any {@link BeanDefinitionRegistry} implementation.
|
||||
*
|
||||
* @author Jeff Brown
|
||||
* @author Graeme Rocher
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @since 4.0
|
||||
* @see BeanDefinitionRegistry
|
||||
* @see org.springframework.beans.factory.support.DefaultListableBeanFactory
|
||||
@@ -128,7 +132,21 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader implements GroovyObject {
|
||||
|
||||
private final XmlBeanDefinitionReader xmlBeanDefinitionReader;
|
||||
/**
|
||||
* Standard {@code XmlBeanDefinitionReader} created with default
|
||||
* settings for loading bean definitions from XML files.
|
||||
*/
|
||||
private final XmlBeanDefinitionReader standardXmlBeanDefinitionReader;
|
||||
|
||||
/**
|
||||
* Groovy DSL {@code XmlBeanDefinitionReader} for loading bean definitions
|
||||
* via the Groovy DSL, typically configured with XML validation disabled.
|
||||
*/
|
||||
private final XmlBeanDefinitionReader groovyDslXmlBeanDefinitionReader;
|
||||
|
||||
private final Map<String, String> namespaces = new HashMap<String, String>();
|
||||
|
||||
private final Map<String, DeferredProperty> deferredProperties = new HashMap<String, DeferredProperty>();
|
||||
|
||||
private MetaClass metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(getClass());
|
||||
|
||||
@@ -136,31 +154,28 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
|
||||
private GroovyBeanDefinitionWrapper currentBeanDefinition;
|
||||
|
||||
private final Map <String, String> namespaces = new HashMap<String, String>();
|
||||
|
||||
private final Map<String, DeferredProperty> deferredProperties = new HashMap<String, DeferredProperty>();
|
||||
|
||||
|
||||
/**
|
||||
* Create new GroovyBeanDefinitionReader for the given bean factory.
|
||||
* @param registry the BeanFactory to load bean definitions into,
|
||||
* in the form of a BeanDefinitionRegistry
|
||||
* Create a new {@code GroovyBeanDefinitionReader} for the given {@link BeanDefinitionRegistry}.
|
||||
* @param registry the {@code BeanDefinitionRegistry} to load bean definitions into
|
||||
*/
|
||||
public GroovyBeanDefinitionReader(BeanDefinitionRegistry registry) {
|
||||
super(registry);
|
||||
this.xmlBeanDefinitionReader = new XmlBeanDefinitionReader(registry);
|
||||
this.xmlBeanDefinitionReader.setValidating(false);
|
||||
this.standardXmlBeanDefinitionReader = new XmlBeanDefinitionReader(registry);
|
||||
this.groovyDslXmlBeanDefinitionReader = new XmlBeanDefinitionReader(registry);
|
||||
this.groovyDslXmlBeanDefinitionReader.setValidating(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new GroovyBeanDefinitionReader based on the given XmlBeanDefinitionReader,
|
||||
* using the same registry and delegating XML loading to it.
|
||||
* @param xmlBeanDefinitionReader the XmlBeanDefinitionReader to derive the registry
|
||||
* Create a new {@code GroovyBeanDefinitionReader} based on the given {@link XmlBeanDefinitionReader},
|
||||
* using its {@code BeanDefinitionRegistry} and delegating Groovy DSL loading to it.
|
||||
* @param xmlBeanDefinitionReader the {@code XmlBeanDefinitionReader} to derive the registry
|
||||
* from and to delegate XML loading to
|
||||
*/
|
||||
public GroovyBeanDefinitionReader(XmlBeanDefinitionReader xmlBeanDefinitionReader) {
|
||||
super(xmlBeanDefinitionReader.getRegistry());
|
||||
this.xmlBeanDefinitionReader = xmlBeanDefinitionReader;
|
||||
this.standardXmlBeanDefinitionReader = new XmlBeanDefinitionReader(xmlBeanDefinitionReader.getRegistry());
|
||||
this.groovyDslXmlBeanDefinitionReader = xmlBeanDefinitionReader;
|
||||
}
|
||||
|
||||
|
||||
@@ -174,7 +189,7 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
|
||||
/**
|
||||
* Set the binding, i.e. the Groovy variables available in the scope
|
||||
* of a GroovyBeanDefinitionReader closure.
|
||||
* of a {@code GroovyBeanDefinitionReader} closure.
|
||||
*/
|
||||
public void setBinding(Binding binding) {
|
||||
this.binding = binding;
|
||||
@@ -192,9 +207,9 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
|
||||
/**
|
||||
* Load bean definitions from the specified Groovy script or XML file.
|
||||
* <p>Note that ".xml" files will be parsed as XML content; all other kinds
|
||||
* <p>Note that {@code ".xml"} files will be parsed as XML content; all other kinds
|
||||
* of resources will be parsed as Groovy scripts.
|
||||
* @param resource the resource descriptor for the Groovy script
|
||||
* @param resource the resource descriptor for the Groovy script or XML file
|
||||
* @return the number of bean definitions found
|
||||
* @throws BeanDefinitionStoreException in case of loading or parsing errors
|
||||
*/
|
||||
@@ -204,18 +219,18 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
|
||||
/**
|
||||
* Load bean definitions from the specified Groovy script or XML file.
|
||||
* <p>Note that ".xml" files will be parsed as XML content; all other kinds
|
||||
* <p>Note that {@code ".xml"} files will be parsed as XML content; all other kinds
|
||||
* of resources will be parsed as Groovy scripts.
|
||||
* @param encodedResource the resource descriptor for the Groovy script,
|
||||
* allowing to specify an encoding to use for parsing the file
|
||||
* @param encodedResource the resource descriptor for the Groovy script or XML file,
|
||||
* allowing specification of an encoding to use for parsing the file
|
||||
* @return the number of bean definitions found
|
||||
* @throws BeanDefinitionStoreException in case of loading or parsing errors
|
||||
*/
|
||||
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
|
||||
// Check for XML files and redirect them to the XmlBeanDefinitionReader
|
||||
// Check for XML files and redirect them to the "standard" XmlBeanDefinitionReader
|
||||
String filename = encodedResource.getResource().getFilename();
|
||||
if (StringUtils.endsWithIgnoreCase(filename, ".xml")) {
|
||||
return this.xmlBeanDefinitionReader.loadBeanDefinitions(encodedResource);
|
||||
return this.standardXmlBeanDefinitionReader.loadBeanDefinitions(encodedResource);
|
||||
}
|
||||
|
||||
Closure beans = new Closure(this) {
|
||||
@@ -255,14 +270,14 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
/**
|
||||
* Defines a set of beans for the given block or closure.
|
||||
* @param closure the block or closure
|
||||
* @return this GroovyBeanDefinitionReader instance
|
||||
* @return this {@code GroovyBeanDefinitionReader} instance
|
||||
*/
|
||||
public GroovyBeanDefinitionReader beans(Closure closure) {
|
||||
return invokeBeanDefiningClosure(closure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines an inner bean definition.
|
||||
* Define an inner bean definition.
|
||||
* @param type the bean type
|
||||
* @return the bean definition
|
||||
*/
|
||||
@@ -307,7 +322,7 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a Spring namespace definition to use.
|
||||
* Define a Spring XML namespace definition to use.
|
||||
* @param definition the namespace definition
|
||||
*/
|
||||
public void xmlns(Map<String, String> definition) {
|
||||
@@ -318,7 +333,8 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
if (uri == null) {
|
||||
throw new IllegalArgumentException("Namespace definition must supply a non-null URI");
|
||||
}
|
||||
NamespaceHandler namespaceHandler = this.xmlBeanDefinitionReader.getNamespaceHandlerResolver().resolve(uri);
|
||||
NamespaceHandler namespaceHandler = this.groovyDslXmlBeanDefinitionReader.getNamespaceHandlerResolver().resolve(
|
||||
uri);
|
||||
if (namespaceHandler == null) {
|
||||
throw new BeanDefinitionParsingException(new Problem("No namespace handler found for URI: " + uri,
|
||||
new Location(new DescriptiveResource(("Groovy")))));
|
||||
@@ -419,7 +435,7 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
/**
|
||||
* When a method argument is only a closure it is a set of bean definitions.
|
||||
* @param callable the closure argument
|
||||
* @return this GroovyBeanDefinitionReader instance
|
||||
* @return this {@code GroovyBeanDefinitionReader} instance
|
||||
*/
|
||||
protected GroovyBeanDefinitionReader invokeBeanDefiningClosure(Closure callable) {
|
||||
callable.setDelegate(this);
|
||||
@@ -534,8 +550,8 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether there are any {@link RuntimeBeanReference}s inside the Map
|
||||
* and converts it to a ManagedMap if necessary.
|
||||
* Checks whether there are any {@link RuntimeBeanReference}s inside the {@link Map}
|
||||
* and converts it to a {@link ManagedMap} if necessary.
|
||||
* @param map the original Map
|
||||
* @return either the original map or a managed copy of it
|
||||
*/
|
||||
@@ -556,8 +572,8 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether there are any {@link RuntimeBeanReference}s inside the List
|
||||
* and converts it to a ManagedList if necessary.
|
||||
* Checks whether there are any {@link RuntimeBeanReference}s inside the {@link List}
|
||||
* and converts it to a {@link ManagedList} if necessary.
|
||||
* @param list the original List
|
||||
* @return either the original list or a managed copy of it
|
||||
*/
|
||||
@@ -578,7 +594,7 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
}
|
||||
|
||||
/**
|
||||
* This method overrides property setting in the scope of the GroovyBeanDefinitionReader
|
||||
* This method overrides property setting in the scope of the {@code GroovyBeanDefinitionReader}
|
||||
* to set properties on the current bean definition.
|
||||
*/
|
||||
public void setProperty(String name, Object value) {
|
||||
@@ -619,12 +635,12 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
|
||||
/**
|
||||
* This method overrides property retrieval in the scope of the
|
||||
* GroovyBeanDefinitionReader to either:
|
||||
* {@code GroovyBeanDefinitionReader} to either:
|
||||
* <ul>
|
||||
* <li>Retrieve a variable from the bean builder's binding if it exists
|
||||
* <li>Retrieve a RuntimeBeanReference for a specific bean if it exists
|
||||
* <li>Otherwise just delegate to MetaClass.getProperty which will resolve
|
||||
* properties from the GroovyBeanDefinitionReader itself
|
||||
* properties from the {@code GroovyBeanDefinitionReader} itself
|
||||
* </ul>
|
||||
*/
|
||||
public Object getProperty(String name) {
|
||||
@@ -670,7 +686,8 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
}
|
||||
|
||||
private GroovyDynamicElementReader createDynamicElementReader(String namespace) {
|
||||
XmlReaderContext readerContext = this.xmlBeanDefinitionReader.createReaderContext(new DescriptiveResource("Groovy"));
|
||||
XmlReaderContext readerContext = this.groovyDslXmlBeanDefinitionReader.createReaderContext(new DescriptiveResource(
|
||||
"Groovy"));
|
||||
BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
|
||||
boolean decorating = (this.currentBeanDefinition != null);
|
||||
if (!decorating) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Rob Harrop
|
||||
* @author Stephane Nicoll
|
||||
* @since 15 April 2001
|
||||
* @see #registerCustomEditor
|
||||
* @see #setPropertyValues
|
||||
@@ -978,6 +979,14 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
}
|
||||
Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(),
|
||||
requiredType, TypeDescriptor.nested(property(pd), tokens.keys.length));
|
||||
int length = Array.getLength(propValue);
|
||||
if (arrayIndex >= length && arrayIndex < this.autoGrowCollectionLimit) {
|
||||
Class<?> componentType = propValue.getClass().getComponentType();
|
||||
Object newArray = Array.newInstance(componentType, arrayIndex + 1);
|
||||
System.arraycopy(propValue, 0, newArray, 0, length);
|
||||
setPropertyValue(actualName, newArray);
|
||||
propValue = getPropertyValue(actualName);
|
||||
}
|
||||
Array.set(propValue, arrayIndex, convertedValue);
|
||||
}
|
||||
catch (IndexOutOfBoundsException ex) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -114,6 +114,7 @@ public interface BeanFactory {
|
||||
*/
|
||||
String FACTORY_BEAN_PREFIX = "&";
|
||||
|
||||
|
||||
/**
|
||||
* Return an instance, which may be shared or independent, of the specified bean.
|
||||
* <p>This method allows a Spring BeanFactory to be used as a replacement for the
|
||||
@@ -202,6 +203,7 @@ public interface BeanFactory {
|
||||
*/
|
||||
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
|
||||
|
||||
|
||||
/**
|
||||
* Does this bean factory contain a bean definition or externally registered singleton
|
||||
* instance with the given name?
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.beans.factory;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -219,8 +219,7 @@ public class PropertyPlaceholderConfigurer extends PlaceholderConfigurerSupport
|
||||
throws BeansException {
|
||||
|
||||
StringValueResolver valueResolver = new PlaceholderResolvingStringValueResolver(props);
|
||||
|
||||
this.doProcessProperties(beanFactoryToProcess, valueResolver);
|
||||
doProcessProperties(beanFactoryToProcess, valueResolver);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+12
-4
@@ -130,9 +130,10 @@ public abstract class YamlProcessor {
|
||||
* Properties. Depending on the {@link #setResolutionMethod(ResolutionMethod)} not all
|
||||
* of the documents will be parsed.
|
||||
* @param callback a callback to delegate to once matching documents are found
|
||||
* @see #createYaml()
|
||||
*/
|
||||
protected void process(MatchCallback callback) {
|
||||
Yaml yaml = new Yaml(new StrictMapAppenderConstructor());
|
||||
Yaml yaml = createYaml();
|
||||
for (Resource resource : this.resources) {
|
||||
boolean found = process(callback, yaml, resource);
|
||||
if (this.resolutionMethod == ResolutionMethod.FIRST_FOUND && found) {
|
||||
@@ -141,6 +142,13 @@ public abstract class YamlProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the {@link Yaml} instance to use.
|
||||
*/
|
||||
protected Yaml createYaml() {
|
||||
return new Yaml(new StrictMapAppenderConstructor());
|
||||
}
|
||||
|
||||
private boolean process(MatchCallback callback, Yaml yaml, Resource resource) {
|
||||
int count = 0;
|
||||
try {
|
||||
@@ -331,7 +339,7 @@ public abstract class YamlProcessor {
|
||||
/**
|
||||
* Status returned from {@link DocumentMatcher#matches(java.util.Properties)}
|
||||
*/
|
||||
public static enum MatchStatus {
|
||||
public enum MatchStatus {
|
||||
|
||||
/**
|
||||
* A match was found.
|
||||
@@ -360,7 +368,7 @@ public abstract class YamlProcessor {
|
||||
/**
|
||||
* Method to use for resolving resources.
|
||||
*/
|
||||
public static enum ResolutionMethod {
|
||||
public enum ResolutionMethod {
|
||||
|
||||
/**
|
||||
* Replace values from earlier in the list.
|
||||
@@ -382,7 +390,7 @@ public abstract class YamlProcessor {
|
||||
/**
|
||||
* A specialized {@link Constructor} that checks for duplicate keys.
|
||||
*/
|
||||
private static class StrictMapAppenderConstructor extends Constructor {
|
||||
protected static class StrictMapAppenderConstructor extends Constructor {
|
||||
|
||||
public StrictMapAppenderConstructor() {
|
||||
super();
|
||||
|
||||
+8
@@ -897,6 +897,14 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
instance = bw.getWrappedInstance();
|
||||
}
|
||||
}
|
||||
catch (BeanCreationException ex) {
|
||||
// Can only happen when getting a FactoryBean.
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Bean creation exception on non-singleton FactoryBean type check: " + ex);
|
||||
}
|
||||
onSuppressedException(ex);
|
||||
return null;
|
||||
}
|
||||
finally {
|
||||
// Finished partial creation of this bean.
|
||||
afterPrototypeCreation(beanName);
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 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,7 +279,7 @@ public class BeanDefinitionBuilder {
|
||||
*/
|
||||
public BeanDefinitionBuilder addDependsOn(String beanName) {
|
||||
if (this.beanDefinition.getDependsOn() == null) {
|
||||
this.beanDefinition.setDependsOn(new String[] {beanName});
|
||||
this.beanDefinition.setDependsOn(beanName);
|
||||
}
|
||||
else {
|
||||
String[] added = ObjectUtils.addObjectToArray(this.beanDefinition.getDependsOn(), beanName);
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -150,8 +150,8 @@ public class BeanDefinitionReaderUtils {
|
||||
// Register aliases for bean name, if any.
|
||||
String[] aliases = definitionHolder.getAliases();
|
||||
if (aliases != null) {
|
||||
for (String aliase : aliases) {
|
||||
registry.registerAlias(beanName, aliase);
|
||||
for (String alias : aliases) {
|
||||
registry.registerAlias(beanName, alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-15
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -323,7 +323,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Implementation of ListableBeanFactory interface
|
||||
// Implementation of remaining BeanFactory methods
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
@@ -562,17 +562,10 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) {
|
||||
Map<String, Object> results = new LinkedHashMap<String, Object>();
|
||||
for (String beanName : this.beanDefinitionNames) {
|
||||
BeanDefinition beanDefinition = getBeanDefinition(beanName);
|
||||
if (!beanDefinition.isAbstract() && findAnnotationOnBean(beanName, annotationType) != null) {
|
||||
results.put(beanName, getBean(beanName));
|
||||
}
|
||||
}
|
||||
for (String beanName : this.manualSingletonNames) {
|
||||
if (!results.containsKey(beanName) && findAnnotationOnBean(beanName, annotationType) != null) {
|
||||
results.put(beanName, getBean(beanName));
|
||||
}
|
||||
String[] beanNames = getBeanNamesForAnnotation(annotationType);
|
||||
Map<String, Object> results = new LinkedHashMap<String, Object>(beanNames.length);
|
||||
for (String beanName : beanNames) {
|
||||
results.put(beanName, getBean(beanName));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
@@ -811,7 +804,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
|
||||
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
|
||||
if (oldBeanDefinition != null) {
|
||||
if (!this.allowBeanDefinitionOverriding) {
|
||||
if (!isAllowBeanDefinitionOverriding()) {
|
||||
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
|
||||
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
|
||||
"': There is already [" + oldBeanDefinition + "] bound.");
|
||||
@@ -820,7 +813,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
|
||||
if (this.logger.isWarnEnabled()) {
|
||||
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
|
||||
" with a framework-generated bean definition ': replacing [" +
|
||||
"' with a framework-generated bean definition: replacing [" +
|
||||
oldBeanDefinition + "] with [" + beanDefinition + "]");
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -607,13 +607,13 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose the singleton mutex to subclasses.
|
||||
* Exposes the singleton mutex to subclasses and external collaborators.
|
||||
* <p>Subclasses should synchronize on the given Object if they perform
|
||||
* any sort of extended singleton creation phase. In particular, subclasses
|
||||
* should <i>not</i> have their own mutexes involved in singleton creation,
|
||||
* to avoid the potential for deadlocks in lazy-init situations.
|
||||
*/
|
||||
protected final Object getSingletonMutex() {
|
||||
public final Object getSingletonMutex() {
|
||||
return this.singletonObjects;
|
||||
}
|
||||
|
||||
|
||||
+22
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -49,12 +49,13 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public abstract class AbstractBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
/** Constant for the id attribute */
|
||||
/** Constant for the "id" attribute */
|
||||
public static final String ID_ATTRIBUTE = "id";
|
||||
|
||||
/** Constant for the name attribute */
|
||||
/** Constant for the "name" attribute */
|
||||
public static final String NAME_ATTRIBUTE = "name";
|
||||
|
||||
|
||||
@Override
|
||||
public final BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
AbstractBeanDefinition definition = parseInternal(element, parserContext);
|
||||
@@ -66,10 +67,12 @@ public abstract class AbstractBeanDefinitionParser implements BeanDefinitionPars
|
||||
"Id is required for element '" + parserContext.getDelegate().getLocalName(element)
|
||||
+ "' when used as a top-level tag", element);
|
||||
}
|
||||
String[] aliases = new String[0];
|
||||
String name = element.getAttribute(NAME_ATTRIBUTE);
|
||||
if (StringUtils.hasLength(name)) {
|
||||
aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name));
|
||||
String[] aliases = null;
|
||||
if (shouldParseNameAsAliases()) {
|
||||
String name = element.getAttribute(NAME_ATTRIBUTE);
|
||||
if (StringUtils.hasLength(name)) {
|
||||
aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name));
|
||||
}
|
||||
}
|
||||
BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases);
|
||||
registerBeanDefinition(holder, parserContext.getRegistry());
|
||||
@@ -170,7 +173,18 @@ public abstract class AbstractBeanDefinitionParser implements BeanDefinitionPars
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls whether this parser is supposed to fire a
|
||||
* Determine whether the element's "name" attribute should get parsed as
|
||||
* bean definition aliases, i.e. alternative bean definition names.
|
||||
* <p>The default implementation returns {@code true}.
|
||||
* @return whether the parser should evaluate the "name" attribute as aliases
|
||||
* @since 4.1.5
|
||||
*/
|
||||
protected boolean shouldParseNameAsAliases() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether this parser is supposed to fire a
|
||||
* {@link org.springframework.beans.factory.parsing.BeanComponentDefinition}
|
||||
* event after parsing the bean definition.
|
||||
* <p>This implementation returns {@code true} by default; that is,
|
||||
|
||||
+26
-27
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2015 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.beans.factory.xml;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -45,7 +44,9 @@ public class BeansDtdResolver implements EntityResolver {
|
||||
|
||||
private static final String DTD_EXTENSION = ".dtd";
|
||||
|
||||
private static final String[] DTD_NAMES = {"spring-beans-2.0", "spring-beans"};
|
||||
private static final String DTD_FILENAME = "spring-beans-2.0";
|
||||
|
||||
private static final String DTD_NAME = "spring-beans";
|
||||
|
||||
private static final Log logger = LogFactory.getLog(BeansDtdResolver.class);
|
||||
|
||||
@@ -58,30 +59,28 @@ public class BeansDtdResolver implements EntityResolver {
|
||||
}
|
||||
if (systemId != null && systemId.endsWith(DTD_EXTENSION)) {
|
||||
int lastPathSeparator = systemId.lastIndexOf("/");
|
||||
for (String DTD_NAME : DTD_NAMES) {
|
||||
int dtdNameStart = systemId.indexOf(DTD_NAME);
|
||||
if (dtdNameStart > lastPathSeparator) {
|
||||
String dtdFile = systemId.substring(dtdNameStart);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Trying to locate [" + dtdFile + "] in Spring jar");
|
||||
}
|
||||
try {
|
||||
Resource resource = new ClassPathResource(dtdFile, getClass());
|
||||
InputSource source = new InputSource(resource.getInputStream());
|
||||
source.setPublicId(publicId);
|
||||
source.setSystemId(systemId);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Found beans DTD [" + systemId + "] in classpath: " + dtdFile);
|
||||
}
|
||||
return source;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Could not resolve beans DTD [" + systemId + "]: not found in class path", ex);
|
||||
}
|
||||
}
|
||||
|
||||
int dtdNameStart = systemId.indexOf(DTD_NAME);
|
||||
if (dtdNameStart > lastPathSeparator) {
|
||||
String dtdFile = DTD_FILENAME + DTD_EXTENSION;
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Trying to locate [" + dtdFile + "] in Spring jar on classpath");
|
||||
}
|
||||
try {
|
||||
Resource resource = new ClassPathResource(dtdFile, getClass());
|
||||
InputSource source = new InputSource(resource.getInputStream());
|
||||
source.setPublicId(publicId);
|
||||
source.setSystemId(systemId);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Found beans DTD [" + systemId + "] in classpath: " + dtdFile);
|
||||
}
|
||||
return source;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Could not resolve beans DTD [" + systemId + "]: not found in classpath", ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +91,7 @@ public class BeansDtdResolver implements EntityResolver {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EntityResolver for DTDs " + Arrays.toString(DTD_NAMES);
|
||||
return "EntityResolver for spring-beans DTD";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -518,6 +518,36 @@ public final class BeanWrapperTests extends AbstractConfigurablePropertyAccessor
|
||||
assertTrue("correct values", pt.stringArray[0].equals("a1") && pt.stringArray[1].equals("b2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringArrayAutoGrow() throws Exception {
|
||||
StringArrayBean target = new StringArrayBean();
|
||||
BeanWrapper bw = new BeanWrapperImpl(target);
|
||||
bw.setAutoGrowNestedPaths(true);
|
||||
|
||||
bw.setPropertyValue("array[0]", "Test0");
|
||||
assertEquals(1, target.getArray().length);
|
||||
|
||||
bw.setPropertyValue("array[2]", "Test2");
|
||||
assertEquals(3, target.getArray().length);
|
||||
assertTrue("correct values", target.getArray()[0].equals("Test0") && target.getArray()[1] == null &&
|
||||
target.getArray()[2].equals("Test2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrimitiveArrayAutoGrow() throws Exception {
|
||||
PrimitiveArrayBean target = new PrimitiveArrayBean();
|
||||
BeanWrapper bw = new BeanWrapperImpl(target);
|
||||
bw.setAutoGrowNestedPaths(true);
|
||||
|
||||
bw.setPropertyValue("array[0]", 1);
|
||||
assertEquals(1, target.getArray().length);
|
||||
|
||||
bw.setPropertyValue("array[2]", 3);
|
||||
assertEquals(3, target.getArray().length);
|
||||
assertTrue("correct values", target.getArray()[0] == 1 && target.getArray()[1] == 0 &&
|
||||
target.getArray()[2] == 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringPropertyWithCustomEditor() throws Exception {
|
||||
TestBean tb = new TestBean();
|
||||
@@ -1723,6 +1753,20 @@ public final class BeanWrapperTests extends AbstractConfigurablePropertyAccessor
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class StringArrayBean {
|
||||
|
||||
private String[] array;
|
||||
|
||||
public String[] getArray() {
|
||||
return array;
|
||||
}
|
||||
|
||||
public void setArray(String[] array) {
|
||||
this.array = array;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class NumberPropertyBean {
|
||||
|
||||
@@ -841,19 +841,24 @@ public class ExtendedBeanInfoTests {
|
||||
public String getAddress(int index){ return null; }
|
||||
}
|
||||
|
||||
{ // baseline. ExtendedBeanInfo needs to behave exactly like the following
|
||||
// Baseline: ExtendedBeanInfo needs to behave exactly like the following...
|
||||
boolean hasReadMethod;
|
||||
boolean hasWriteMethod;
|
||||
boolean hasIndexedReadMethod;
|
||||
boolean hasIndexedWriteMethod;
|
||||
{
|
||||
BeanInfo bi = Introspector.getBeanInfo(A.class);
|
||||
assertThat(hasReadMethodForProperty(bi, "address"), is(false));
|
||||
assertThat(hasWriteMethodForProperty(bi, "address"), is(false));
|
||||
assertThat(hasIndexedReadMethodForProperty(bi, "address"), is(true));
|
||||
assertThat(hasIndexedWriteMethodForProperty(bi, "address"), is(true));
|
||||
hasReadMethod = hasReadMethodForProperty(bi, "address");
|
||||
hasWriteMethod = hasWriteMethodForProperty(bi, "address");
|
||||
hasIndexedReadMethod = hasIndexedReadMethodForProperty(bi, "address");
|
||||
hasIndexedWriteMethod = hasIndexedWriteMethodForProperty(bi, "address");
|
||||
}
|
||||
{
|
||||
BeanInfo bi = new ExtendedBeanInfo(Introspector.getBeanInfo(A.class));
|
||||
assertThat(hasReadMethodForProperty(bi, "address"), is(false));
|
||||
assertThat(hasWriteMethodForProperty(bi, "address"), is(false));
|
||||
assertThat(hasIndexedReadMethodForProperty(bi, "address"), is(true));
|
||||
assertThat(hasIndexedWriteMethodForProperty(bi, "address"), is(true));
|
||||
assertEquals(hasReadMethodForProperty(bi, "address"), hasReadMethod);
|
||||
assertEquals(hasWriteMethodForProperty(bi, "address"), hasWriteMethod);
|
||||
assertEquals(hasIndexedReadMethodForProperty(bi, "address"), hasIndexedReadMethod);
|
||||
assertEquals(hasIndexedWriteMethodForProperty(bi, "address"), hasIndexedWriteMethod);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+29
-34
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 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,8 +23,6 @@ import java.util.Map;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.StaticListableBeanFactory;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
@@ -53,16 +51,16 @@ public final class BeanFactoryUtilsTests {
|
||||
private static final Resource LEAF_CONTEXT = qualifiedResource(CLASS, "leaf.xml");
|
||||
private static final Resource DEPENDENT_BEANS_CONTEXT = qualifiedResource(CLASS, "dependentBeans.xml");
|
||||
|
||||
private ConfigurableListableBeanFactory listableBeanFactory;
|
||||
private DefaultListableBeanFactory listableBeanFactory;
|
||||
|
||||
private DefaultListableBeanFactory dependentBeansFactory;
|
||||
|
||||
private ConfigurableListableBeanFactory dependentBeansBF;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
// Interesting hierarchical factory to test counts.
|
||||
// Slow to read so we cache it.
|
||||
|
||||
|
||||
DefaultListableBeanFactory grandParent = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(grandParent).loadBeanDefinitions(ROOT_CONTEXT);
|
||||
DefaultListableBeanFactory parent = new DefaultListableBeanFactory(grandParent);
|
||||
@@ -70,12 +68,13 @@ public final class BeanFactoryUtilsTests {
|
||||
DefaultListableBeanFactory child = new DefaultListableBeanFactory(parent);
|
||||
new XmlBeanDefinitionReader(child).loadBeanDefinitions(LEAF_CONTEXT);
|
||||
|
||||
this.dependentBeansBF = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader((BeanDefinitionRegistry) this.dependentBeansBF).loadBeanDefinitions(DEPENDENT_BEANS_CONTEXT);
|
||||
dependentBeansBF.preInstantiateSingletons();
|
||||
this.dependentBeansFactory = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(this.dependentBeansFactory).loadBeanDefinitions(DEPENDENT_BEANS_CONTEXT);
|
||||
dependentBeansFactory.preInstantiateSingletons();
|
||||
this.listableBeanFactory = child;
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testHierarchicalCountBeansWithNonHierarchicalFactory() {
|
||||
StaticListableBeanFactory lbf = new StaticListableBeanFactory();
|
||||
@@ -92,22 +91,21 @@ public final class BeanFactoryUtilsTests {
|
||||
// Leaf count
|
||||
assertTrue(this.listableBeanFactory.getBeanDefinitionCount() == 1);
|
||||
// Count minus duplicate
|
||||
assertTrue("Should count 7 beans, not "
|
||||
+ BeanFactoryUtils.countBeansIncludingAncestors(this.listableBeanFactory),
|
||||
BeanFactoryUtils.countBeansIncludingAncestors(this.listableBeanFactory) == 7);
|
||||
assertTrue("Should count 7 beans, not " + BeanFactoryUtils.countBeansIncludingAncestors(this.listableBeanFactory),
|
||||
BeanFactoryUtils.countBeansIncludingAncestors(this.listableBeanFactory) == 7);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHierarchicalNamesWithNoMatch() throws Exception {
|
||||
List<String> names = Arrays.asList(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.listableBeanFactory,
|
||||
NoOp.class));
|
||||
List<String> names = Arrays.asList(
|
||||
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.listableBeanFactory, NoOp.class));
|
||||
assertEquals(0, names.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHierarchicalNamesWithMatchOnlyInRoot() throws Exception {
|
||||
List<String> names = Arrays.asList(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.listableBeanFactory,
|
||||
IndexedTestBean.class));
|
||||
List<String> names = Arrays.asList(
|
||||
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.listableBeanFactory, IndexedTestBean.class));
|
||||
assertEquals(1, names.size());
|
||||
assertTrue(names.contains("indexedBean"));
|
||||
// Distinguish from default ListableBeanFactory behavior
|
||||
@@ -116,8 +114,8 @@ public final class BeanFactoryUtilsTests {
|
||||
|
||||
@Test
|
||||
public void testGetBeanNamesForTypeWithOverride() throws Exception {
|
||||
List<String> names = Arrays.asList(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.listableBeanFactory,
|
||||
ITestBean.class));
|
||||
List<String> names = Arrays.asList(
|
||||
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.listableBeanFactory, ITestBean.class));
|
||||
// includes 2 TestBeans from FactoryBeans (DummyFactory definitions)
|
||||
assertEquals(4, names.size());
|
||||
assertTrue(names.contains("test"));
|
||||
@@ -130,7 +128,7 @@ public final class BeanFactoryUtilsTests {
|
||||
public void testNoBeansOfType() {
|
||||
StaticListableBeanFactory lbf = new StaticListableBeanFactory();
|
||||
lbf.addBean("foo", new Object());
|
||||
Map<?, ?> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(lbf, ITestBean.class, true, false);
|
||||
Map<String, ?> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(lbf, ITestBean.class, true, false);
|
||||
assertTrue(beans.isEmpty());
|
||||
}
|
||||
|
||||
@@ -147,7 +145,7 @@ public final class BeanFactoryUtilsTests {
|
||||
lbf.addBean("t3", t3);
|
||||
lbf.addBean("t4", t4);
|
||||
|
||||
Map<?, ?> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(lbf, ITestBean.class, true, false);
|
||||
Map<String, ?> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(lbf, ITestBean.class, true, false);
|
||||
assertEquals(2, beans.size());
|
||||
assertEquals(t1, beans.get("t1"));
|
||||
assertEquals(t2, beans.get("t2"));
|
||||
@@ -191,8 +189,8 @@ public final class BeanFactoryUtilsTests {
|
||||
this.listableBeanFactory.registerSingleton("t3", t3);
|
||||
this.listableBeanFactory.registerSingleton("t4", t4);
|
||||
|
||||
Map<?, ?> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.listableBeanFactory, ITestBean.class, true,
|
||||
false);
|
||||
Map<String, ?> beans =
|
||||
BeanFactoryUtils.beansOfTypeIncludingAncestors(this.listableBeanFactory, ITestBean.class, true, false);
|
||||
assertEquals(6, beans.size());
|
||||
assertEquals(test3, beans.get("test3"));
|
||||
assertEquals(test, beans.get("test"));
|
||||
@@ -200,12 +198,9 @@ public final class BeanFactoryUtilsTests {
|
||||
assertEquals(t2, beans.get("t2"));
|
||||
assertEquals(t3.getObject(), beans.get("t3"));
|
||||
assertTrue(beans.get("t4") instanceof TestBean);
|
||||
// t3 and t4 are found here as of Spring 2.0, since they are
|
||||
// pre-registered
|
||||
// singleton instances, while testFactory1 and testFactory are *not*
|
||||
// found
|
||||
// because they are FactoryBean definitions that haven't been
|
||||
// initialized yet.
|
||||
// t3 and t4 are found here as of Spring 2.0, since they are pre-registered
|
||||
// singleton instances, while testFactory1 and testFactory are *not* found
|
||||
// because they are FactoryBean definitions that haven't been initialized yet.
|
||||
|
||||
beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.listableBeanFactory, ITestBean.class, false, true);
|
||||
Object testFactory1 = this.listableBeanFactory.getBean("testFactory1");
|
||||
@@ -247,8 +242,8 @@ public final class BeanFactoryUtilsTests {
|
||||
Object test3 = this.listableBeanFactory.getBean("test3");
|
||||
Object test = this.listableBeanFactory.getBean("test");
|
||||
|
||||
Map<?, ?> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.listableBeanFactory, ITestBean.class, true,
|
||||
false);
|
||||
Map<String, ?> beans =
|
||||
BeanFactoryUtils.beansOfTypeIncludingAncestors(this.listableBeanFactory, ITestBean.class, true, false);
|
||||
assertEquals(2, beans.size());
|
||||
assertEquals(test3, beans.get("test3"));
|
||||
assertEquals(test, beans.get("test"));
|
||||
@@ -283,25 +278,25 @@ public final class BeanFactoryUtilsTests {
|
||||
|
||||
@Test
|
||||
public void testADependencies() {
|
||||
String[] deps = this.dependentBeansBF.getDependentBeans("a");
|
||||
String[] deps = this.dependentBeansFactory.getDependentBeans("a");
|
||||
assertTrue(ObjectUtils.isEmpty(deps));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBDependencies() {
|
||||
String[] deps = this.dependentBeansBF.getDependentBeans("b");
|
||||
String[] deps = this.dependentBeansFactory.getDependentBeans("b");
|
||||
assertTrue(Arrays.equals(new String[] { "c" }, deps));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCDependencies() {
|
||||
String[] deps = this.dependentBeansBF.getDependentBeans("c");
|
||||
String[] deps = this.dependentBeansFactory.getDependentBeans("c");
|
||||
assertTrue(Arrays.equals(new String[] { "int", "long" }, deps));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntDependencies() {
|
||||
String[] deps = this.dependentBeansBF.getDependentBeans("int");
|
||||
String[] deps = this.dependentBeansFactory.getDependentBeans("int");
|
||||
assertTrue(Arrays.equals(new String[] { "buffer" }, deps));
|
||||
}
|
||||
|
||||
|
||||
+40
-21
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -200,7 +200,7 @@ public class DefaultListableBeanFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrototypeSingletonFactoryBeanIgnoredByNonEagerTypeMatching() {
|
||||
public void testSingletonFactoryBeanIgnoredByNonEagerTypeMatching() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
Properties p = new Properties();
|
||||
p.setProperty("x1.(class)", DummyFactory.class.getName());
|
||||
@@ -1340,10 +1340,10 @@ public class DefaultListableBeanFactoryTests {
|
||||
public void testDependsOnCycle() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
|
||||
bd1.setDependsOn(new String[] {"tb2"});
|
||||
bd1.setDependsOn("tb2");
|
||||
lbf.registerBeanDefinition("tb1", bd1);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
|
||||
bd2.setDependsOn(new String[] {"tb1"});
|
||||
bd2.setDependsOn("tb1");
|
||||
lbf.registerBeanDefinition("tb2", bd2);
|
||||
try {
|
||||
lbf.preInstantiateSingletons();
|
||||
@@ -1361,13 +1361,13 @@ public class DefaultListableBeanFactoryTests {
|
||||
public void testImplicitDependsOnCycle() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
|
||||
bd1.setDependsOn(new String[] {"tb2"});
|
||||
bd1.setDependsOn("tb2");
|
||||
lbf.registerBeanDefinition("tb1", bd1);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
|
||||
bd2.setDependsOn(new String[] {"tb3"});
|
||||
bd2.setDependsOn("tb3");
|
||||
lbf.registerBeanDefinition("tb2", bd2);
|
||||
RootBeanDefinition bd3 = new RootBeanDefinition(TestBean.class);
|
||||
bd3.setDependsOn(new String[] {"tb1"});
|
||||
bd3.setDependsOn("tb1");
|
||||
lbf.registerBeanDefinition("tb3", bd3);
|
||||
try {
|
||||
lbf.preInstantiateSingletons();
|
||||
@@ -1381,7 +1381,7 @@ public class DefaultListableBeanFactoryTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected=NoSuchBeanDefinitionException.class)
|
||||
@Test(expected = NoSuchBeanDefinitionException.class)
|
||||
public void testGetBeanByTypeWithNoneFound() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
lbf.getBean(TestBean.class);
|
||||
@@ -1397,7 +1397,7 @@ public class DefaultListableBeanFactoryTests {
|
||||
assertThat(bean.getBeanName(), equalTo("bd1"));
|
||||
}
|
||||
|
||||
@Test(expected=NoUniqueBeanDefinitionException.class)
|
||||
@Test(expected = NoUniqueBeanDefinitionException.class)
|
||||
public void testGetBeanByTypeWithAmbiguity() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
|
||||
@@ -1540,7 +1540,7 @@ public class DefaultListableBeanFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBeanByTypeInstanceWithPrimary() throws Exception {
|
||||
public void testGetBeanByTypeInstanceWithPrimary() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd1 = createConstructorDependencyBeanDefinition(99);
|
||||
RootBeanDefinition bd2 = createConstructorDependencyBeanDefinition(43);
|
||||
@@ -1553,7 +1553,7 @@ public class DefaultListableBeanFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBeanByTypeInstanceWithMultiplePrimary() throws Exception {
|
||||
public void testGetBeanByTypeInstanceWithMultiplePrimary() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd1 = createConstructorDependencyBeanDefinition(99);
|
||||
RootBeanDefinition bd2 = createConstructorDependencyBeanDefinition(43);
|
||||
@@ -1584,16 +1584,35 @@ public class DefaultListableBeanFactoryTests {
|
||||
try {
|
||||
lbf.getBean(TestBean.class, 67);
|
||||
fail("Should have thrown NoSuchBeanDefinitionException");
|
||||
} catch (NoSuchBeanDefinitionException ex) {
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
private RootBeanDefinition createConstructorDependencyBeanDefinition(int age) {
|
||||
@Test
|
||||
public void testGetBeanWithArgsNotCreatedForFactoryBeanChecking() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd1 = new RootBeanDefinition(ConstructorDependency.class);
|
||||
bd1.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
|
||||
bd1.getConstructorArgumentValues().addGenericArgumentValue(String.valueOf(age));
|
||||
return bd1;
|
||||
lbf.registerBeanDefinition("bd1", bd1);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(ConstructorDependencyFactoryBean.class);
|
||||
bd2.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
|
||||
lbf.registerBeanDefinition("bd2", bd2);
|
||||
|
||||
ConstructorDependency bean = lbf.getBean(ConstructorDependency.class, 42);
|
||||
assertThat(bean.beanName, equalTo("bd1"));
|
||||
assertThat(bean.spouseAge, equalTo(42));
|
||||
|
||||
assertEquals(1, lbf.getBeanNamesForType(ConstructorDependency.class).length);
|
||||
assertEquals(1, lbf.getBeanNamesForType(ConstructorDependencyFactoryBean.class).length);
|
||||
}
|
||||
|
||||
private RootBeanDefinition createConstructorDependencyBeanDefinition(int age) {
|
||||
RootBeanDefinition bd = new RootBeanDefinition(ConstructorDependency.class);
|
||||
bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
|
||||
bd.getConstructorArgumentValues().addGenericArgumentValue(String.valueOf(age));
|
||||
return bd;
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1641,7 +1660,7 @@ public class DefaultListableBeanFactoryTests {
|
||||
* Java method names. In other words, you can't name a method
|
||||
* {@code set&FactoryBean(...)}.
|
||||
*/
|
||||
@Test(expected=TypeMismatchException.class)
|
||||
@Test(expected = TypeMismatchException.class)
|
||||
public void testAutowireBeanWithFactoryBeanByName() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(LazyInitFactory.class);
|
||||
@@ -1664,8 +1683,8 @@ public class DefaultListableBeanFactoryTests {
|
||||
}
|
||||
catch (UnsatisfiedDependencyException ex) {
|
||||
// expected
|
||||
assertTrue(ex.getMessage().indexOf("test") != -1);
|
||||
assertTrue(ex.getMessage().indexOf("spouse") != -1);
|
||||
assertTrue(ex.getMessage().contains("test"));
|
||||
assertTrue(ex.getMessage().contains("spouse"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1682,8 +1701,8 @@ public class DefaultListableBeanFactoryTests {
|
||||
}
|
||||
catch (UnsatisfiedDependencyException ex) {
|
||||
// expected
|
||||
assertTrue(ex.getMessage().indexOf("test") != -1);
|
||||
assertTrue(ex.getMessage().indexOf("spouse") != -1);
|
||||
assertTrue(ex.getMessage().contains("test"));
|
||||
assertTrue(ex.getMessage().contains("spouse"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2518,7 +2537,7 @@ public class DefaultListableBeanFactoryTests {
|
||||
assertEquals(expectedNameFromArgs, tb2.getName());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testScopingBeanToUnregisteredScopeResultsInAnException() throws Exception {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(TestBean.class);
|
||||
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
|
||||
|
||||
+88
-127
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 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,7 +27,6 @@ import java.util.prefs.BackingStoreException;
|
||||
import java.util.prefs.Preferences;
|
||||
import java.util.prefs.PreferencesFactory;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
@@ -53,13 +52,13 @@ import static org.springframework.tests.TestResourceUtils.*;
|
||||
* {@link PropertyPlaceholderConfigurer}, {@link PropertyOverrideConfigurer} and
|
||||
* {@link PreferencesPlaceholderConfigurer}.
|
||||
*
|
||||
* @see PropertyPlaceholderConfigurerTests
|
||||
* @since 02.10.2003
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
* @author Phillip Webb
|
||||
* @since 02.10.2003
|
||||
* @see PropertyPlaceholderConfigurerTests
|
||||
*/
|
||||
public final class PropertyResourceConfigurerTests {
|
||||
public class PropertyResourceConfigurerTests {
|
||||
|
||||
static {
|
||||
System.setProperty("java.util.prefs.PreferencesFactory", MockPreferencesFactory.class.getName());
|
||||
@@ -70,23 +69,15 @@ public final class PropertyResourceConfigurerTests {
|
||||
private static final Resource XTEST_PROPS = qualifiedResource(CLASS, "xtest.properties"); // does not exist
|
||||
private static final Resource TEST_PROPS_XML = qualifiedResource(CLASS, "test.properties.xml");
|
||||
|
||||
private DefaultListableBeanFactory factory;
|
||||
private final DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
factory = new DefaultListableBeanFactory();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropertyOverrideConfigurer() {
|
||||
BeanDefinition def1 = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(TestBean.class)
|
||||
.getBeanDefinition();
|
||||
BeanDefinition def1 = BeanDefinitionBuilder.genericBeanDefinition(TestBean.class).getBeanDefinition();
|
||||
factory.registerBeanDefinition("tb1", def1);
|
||||
|
||||
BeanDefinition def2 = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(TestBean.class)
|
||||
.getBeanDefinition();
|
||||
BeanDefinition def2 = BeanDefinitionBuilder.genericBeanDefinition(TestBean.class).getBeanDefinition();
|
||||
factory.registerBeanDefinition("tb2", def2);
|
||||
|
||||
PropertyOverrideConfigurer poc1;
|
||||
@@ -123,9 +114,7 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyOverrideConfigurerWithNestedProperty() {
|
||||
BeanDefinition def = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(IndexedTestBean.class)
|
||||
.getBeanDefinition();
|
||||
BeanDefinition def = BeanDefinitionBuilder.genericBeanDefinition(IndexedTestBean.class).getBeanDefinition();
|
||||
factory.registerBeanDefinition("tb", def);
|
||||
|
||||
PropertyOverrideConfigurer poc;
|
||||
@@ -143,9 +132,7 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyOverrideConfigurerWithNestedPropertyAndDotInBeanName() {
|
||||
BeanDefinition def = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(IndexedTestBean.class)
|
||||
.getBeanDefinition();
|
||||
BeanDefinition def = BeanDefinitionBuilder.genericBeanDefinition(IndexedTestBean.class).getBeanDefinition();
|
||||
factory.registerBeanDefinition("my.tb", def);
|
||||
|
||||
PropertyOverrideConfigurer poc;
|
||||
@@ -164,9 +151,7 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyOverrideConfigurerWithNestedMapPropertyAndDotInMapKey() {
|
||||
BeanDefinition def = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(IndexedTestBean.class)
|
||||
.getBeanDefinition();
|
||||
BeanDefinition def = BeanDefinitionBuilder.genericBeanDefinition(IndexedTestBean.class).getBeanDefinition();
|
||||
factory.registerBeanDefinition("tb", def);
|
||||
|
||||
PropertyOverrideConfigurer poc;
|
||||
@@ -184,9 +169,7 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyOverrideConfigurerWithHeldProperties() {
|
||||
BeanDefinition def = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(PropertiesHolder.class)
|
||||
.getBeanDefinition();
|
||||
BeanDefinition def = BeanDefinitionBuilder.genericBeanDefinition(PropertiesHolder.class).getBeanDefinition();
|
||||
factory.registerBeanDefinition("tb", def);
|
||||
|
||||
PropertyOverrideConfigurer poc;
|
||||
@@ -200,23 +183,9 @@ public final class PropertyResourceConfigurerTests {
|
||||
assertEquals("true", tb.getHeldProperties().getProperty("mail.smtp.auth"));
|
||||
}
|
||||
|
||||
static class PropertiesHolder {
|
||||
private Properties props = new Properties();
|
||||
|
||||
public Properties getHeldProperties() {
|
||||
return props;
|
||||
}
|
||||
|
||||
public void setHeldProperties(Properties props) {
|
||||
this.props = props;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropertyOverrideConfigurerWithPropertiesFile() {
|
||||
BeanDefinition def = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(IndexedTestBean.class)
|
||||
.getBeanDefinition();
|
||||
BeanDefinition def = BeanDefinitionBuilder.genericBeanDefinition(IndexedTestBean.class).getBeanDefinition();
|
||||
factory.registerBeanDefinition("tb", def);
|
||||
|
||||
PropertyOverrideConfigurer poc = new PropertyOverrideConfigurer();
|
||||
@@ -230,13 +199,11 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyOverrideConfigurerWithInvalidPropertiesFile() {
|
||||
BeanDefinition def = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(IndexedTestBean.class)
|
||||
.getBeanDefinition();
|
||||
BeanDefinition def = BeanDefinitionBuilder.genericBeanDefinition(IndexedTestBean.class).getBeanDefinition();
|
||||
factory.registerBeanDefinition("tb", def);
|
||||
|
||||
PropertyOverrideConfigurer poc = new PropertyOverrideConfigurer();
|
||||
poc.setLocations(new Resource[] { TEST_PROPS, XTEST_PROPS });
|
||||
poc.setLocations(TEST_PROPS, XTEST_PROPS);
|
||||
poc.setIgnoreResourceNotFound(true);
|
||||
poc.postProcessBeanFactory(factory);
|
||||
|
||||
@@ -247,9 +214,7 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyOverrideConfigurerWithPropertiesXmlFile() {
|
||||
BeanDefinition def = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(IndexedTestBean.class)
|
||||
.getBeanDefinition();
|
||||
BeanDefinition def = BeanDefinitionBuilder.genericBeanDefinition(IndexedTestBean.class).getBeanDefinition();
|
||||
factory.registerBeanDefinition("tb", def);
|
||||
|
||||
PropertyOverrideConfigurer poc = new PropertyOverrideConfigurer();
|
||||
@@ -263,9 +228,7 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyOverrideConfigurerWithConvertProperties() {
|
||||
BeanDefinition def = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(IndexedTestBean.class)
|
||||
.getBeanDefinition();
|
||||
BeanDefinition def = BeanDefinitionBuilder.genericBeanDefinition(IndexedTestBean.class).getBeanDefinition();
|
||||
factory.registerBeanDefinition("tb", def);
|
||||
|
||||
ConvertingOverrideConfigurer bfpp = new ConvertingOverrideConfigurer();
|
||||
@@ -389,7 +352,6 @@ public final class PropertyResourceConfigurerTests {
|
||||
cas.addGenericArgumentValue("${var}name${age}");
|
||||
|
||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||
|
||||
pvs.add("stringArray", new String[] {"${os.name}", "${age}"});
|
||||
|
||||
List<Object> friends = new ManagedList<Object>();
|
||||
@@ -409,7 +371,7 @@ public final class PropertyResourceConfigurerTests {
|
||||
someMap.put("key1", new RuntimeBeanReference("${ref}"));
|
||||
someMap.put("key2", "${age}name");
|
||||
MutablePropertyValues innerPvs = new MutablePropertyValues();
|
||||
innerPvs.add("touchy", "${os.name}");
|
||||
innerPvs.add("country", "${os.name}");
|
||||
RootBeanDefinition innerBd = new RootBeanDefinition(TestBean.class);
|
||||
innerBd.setPropertyValues(innerPvs);
|
||||
someMap.put("key3", innerBd);
|
||||
@@ -459,30 +421,28 @@ public final class PropertyResourceConfigurerTests {
|
||||
TestBean inner2 = (TestBean) tb2.getSomeMap().get("mykey4");
|
||||
assertEquals(0, inner1.getAge());
|
||||
assertEquals(null, inner1.getName());
|
||||
assertEquals(System.getProperty("os.name"), inner1.getTouchy());
|
||||
assertEquals(System.getProperty("os.name"), inner1.getCountry());
|
||||
assertEquals(98, inner2.getAge());
|
||||
assertEquals("namemyvarmyvar${", inner2.getName());
|
||||
assertEquals(System.getProperty("os.name"), inner2.getTouchy());
|
||||
assertEquals(System.getProperty("os.name"), inner2.getCountry());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithSystemPropertyFallback() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("touchy", "${os.name}").getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("country", "${os.name}").getBeanDefinition());
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
ppc.postProcessBeanFactory(factory);
|
||||
|
||||
TestBean tb = (TestBean) factory.getBean("tb");
|
||||
assertEquals(System.getProperty("os.name"), tb.getTouchy());
|
||||
assertEquals(System.getProperty("os.name"), tb.getCountry());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithSystemPropertyNotUsed() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("touchy", "${os.name}").getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("country", "${os.name}").getBeanDefinition());
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
Properties props = new Properties();
|
||||
@@ -491,14 +451,13 @@ public final class PropertyResourceConfigurerTests {
|
||||
ppc.postProcessBeanFactory(factory);
|
||||
|
||||
TestBean tb = (TestBean) factory.getBean("tb");
|
||||
assertEquals("myos", tb.getTouchy());
|
||||
assertEquals("myos", tb.getCountry());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithOverridingSystemProperty() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("touchy", "${os.name}").getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("country", "${os.name}").getBeanDefinition());
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
Properties props = new Properties();
|
||||
@@ -508,14 +467,13 @@ public final class PropertyResourceConfigurerTests {
|
||||
ppc.postProcessBeanFactory(factory);
|
||||
|
||||
TestBean tb = (TestBean) factory.getBean("tb");
|
||||
assertEquals(System.getProperty("os.name"), tb.getTouchy());
|
||||
assertEquals(System.getProperty("os.name"), tb.getCountry());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithUnresolvableSystemProperty() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("touchy", "${user.dir}").getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("touchy", "${user.dir}").getBeanDefinition());
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
ppc.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_NEVER);
|
||||
@@ -532,9 +490,8 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithUnresolvablePlaceholder() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${ref}").getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${ref}").getBeanDefinition());
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
|
||||
@@ -550,9 +507,8 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithIgnoreUnresolvablePlaceholder() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${ref}").getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${ref}").getBeanDefinition());
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
ppc.setIgnoreUnresolvablePlaceholders(true);
|
||||
@@ -564,9 +520,8 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithEmptyStringAsNull() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "").getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "").getBeanDefinition());
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
ppc.setNullValue("");
|
||||
@@ -578,9 +533,8 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithEmptyStringInPlaceholderAsNull() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${ref}").getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${ref}").getBeanDefinition());
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
ppc.setNullValue("");
|
||||
@@ -595,9 +549,8 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithNestedPlaceholderInKey() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${my${key}key}").getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${my${key}key}").getBeanDefinition());
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
Properties props = new Properties();
|
||||
@@ -612,8 +565,7 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithPlaceholderInAlias() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class).getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class).getBeanDefinition());
|
||||
factory.registerAlias("tb", "${alias}");
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
@@ -629,8 +581,7 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithSelfReferencingPlaceholderInAlias() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class).getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class).getBeanDefinition());
|
||||
factory.registerAlias("tb", "${alias}");
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
@@ -646,11 +597,10 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithCircularReference() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("age", "${age}")
|
||||
.addPropertyValue("name", "name${var}")
|
||||
.getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("age", "${age}")
|
||||
.addPropertyValue("name", "name${var}")
|
||||
.getBeanDefinition());
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
Properties props = new Properties();
|
||||
@@ -670,9 +620,8 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithDefaultProperties() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("touchy", "${test}").getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("touchy", "${test}").getBeanDefinition());
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
Properties props = new Properties();
|
||||
@@ -686,9 +635,8 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithInlineDefault() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("touchy", "${test:mytest}").getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("touchy", "${test:mytest}").getBeanDefinition());
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
ppc.postProcessBeanFactory(factory);
|
||||
@@ -699,9 +647,8 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithAliases() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("touchy", "${test}").getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("touchy", "${test}").getBeanDefinition());
|
||||
|
||||
factory.registerAlias("tb", "${myAlias}");
|
||||
factory.registerAlias("${myTarget}", "alias2");
|
||||
@@ -724,12 +671,11 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPreferencesPlaceholderConfigurer() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${myName}")
|
||||
.addPropertyValue("age", "${myAge}")
|
||||
.addPropertyValue("touchy", "${myTouchy}")
|
||||
.getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${myName}")
|
||||
.addPropertyValue("age", "${myAge}")
|
||||
.addPropertyValue("touchy", "${myTouchy}")
|
||||
.getBeanDefinition());
|
||||
|
||||
PreferencesPlaceholderConfigurer ppc = new PreferencesPlaceholderConfigurer();
|
||||
Properties props = new Properties();
|
||||
@@ -752,12 +698,11 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPreferencesPlaceholderConfigurerWithCustomTreePaths() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${myName}")
|
||||
.addPropertyValue("age", "${myAge}")
|
||||
.addPropertyValue("touchy", "${myTouchy}")
|
||||
.getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${myName}")
|
||||
.addPropertyValue("age", "${myAge}")
|
||||
.addPropertyValue("touchy", "${myTouchy}")
|
||||
.getBeanDefinition());
|
||||
|
||||
PreferencesPlaceholderConfigurer ppc = new PreferencesPlaceholderConfigurer();
|
||||
Properties props = new Properties();
|
||||
@@ -782,12 +727,11 @@ public final class PropertyResourceConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testPreferencesPlaceholderConfigurerWithPathInPlaceholder() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${mypath/myName}")
|
||||
.addPropertyValue("age", "${myAge}")
|
||||
.addPropertyValue("touchy", "${myotherpath/myTouchy}")
|
||||
.getBeanDefinition());
|
||||
factory.registerBeanDefinition("tb", genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${mypath/myName}")
|
||||
.addPropertyValue("age", "${myAge}")
|
||||
.addPropertyValue("touchy", "${myotherpath/myTouchy}")
|
||||
.getBeanDefinition());
|
||||
|
||||
PreferencesPlaceholderConfigurer ppc = new PreferencesPlaceholderConfigurer();
|
||||
Properties props = new Properties();
|
||||
@@ -811,6 +755,20 @@ public final class PropertyResourceConfigurerTests {
|
||||
}
|
||||
|
||||
|
||||
static class PropertiesHolder {
|
||||
|
||||
private Properties props = new Properties();
|
||||
|
||||
public Properties getHeldProperties() {
|
||||
return props;
|
||||
}
|
||||
|
||||
public void setHeldProperties(Properties props) {
|
||||
this.props = props;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class ConvertingOverrideConfigurer extends PropertyOverrideConfigurer {
|
||||
|
||||
@Override
|
||||
@@ -819,26 +777,28 @@ public final class PropertyResourceConfigurerTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@link PreferencesFactory} to create {@link MockPreferences}.
|
||||
*/
|
||||
public static class MockPreferencesFactory implements PreferencesFactory {
|
||||
|
||||
private Preferences systemRoot = new MockPreferences();
|
||||
private final Preferences userRoot = new MockPreferences();
|
||||
|
||||
private Preferences userRoot = new MockPreferences();
|
||||
private final Preferences systemRoot = new MockPreferences();
|
||||
|
||||
@Override
|
||||
public Preferences systemRoot() {
|
||||
return systemRoot;
|
||||
return this.systemRoot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Preferences userRoot() {
|
||||
return userRoot;
|
||||
return this.userRoot;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mock implementation of {@link Preferences} that behaves the same regardless of the
|
||||
* underlying operating system and will never throw security exceptions.
|
||||
@@ -904,4 +864,5 @@ public final class PropertyResourceConfigurerTests {
|
||||
protected void flushSpi() throws BackingStoreException {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+27
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -770,7 +770,7 @@ public class BeanFactoryGenericsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpr11250() {
|
||||
public void testGenericMatchingWithBeanNameDifferentiation() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.setAutowireCandidateResolver(new GenericTypeAwareAutowireCandidateResolver());
|
||||
|
||||
@@ -780,8 +780,23 @@ public class BeanFactoryGenericsTests {
|
||||
new RootBeanDefinition(NumberBean.class, RootBeanDefinition.AUTOWIRE_CONSTRUCTOR, false));
|
||||
|
||||
NumberBean nb = bf.getBean(NumberBean.class);
|
||||
assertNotNull(nb.getDoubleStore());
|
||||
assertNotNull(nb.getFloatStore());
|
||||
assertSame(bf.getBean("doubleStore"), nb.getDoubleStore());
|
||||
assertSame(bf.getBean("floatStore"), nb.getFloatStore());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenericMatchingWithFullTypeDifferentiation() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.setAutowireCandidateResolver(new GenericTypeAwareAutowireCandidateResolver());
|
||||
|
||||
bf.registerBeanDefinition("store1", new RootBeanDefinition(DoubleStore.class));
|
||||
bf.registerBeanDefinition("store2", new RootBeanDefinition(FloatStore.class));
|
||||
bf.registerBeanDefinition("numberBean",
|
||||
new RootBeanDefinition(NumberBean.class, RootBeanDefinition.AUTOWIRE_CONSTRUCTOR, false));
|
||||
|
||||
NumberBean nb = bf.getBean(NumberBean.class);
|
||||
assertSame(bf.getBean("store1"), nb.getDoubleStore());
|
||||
assertSame(bf.getBean("store2"), nb.getFloatStore());
|
||||
}
|
||||
|
||||
|
||||
@@ -851,6 +866,14 @@ public class BeanFactoryGenericsTests {
|
||||
}
|
||||
|
||||
|
||||
public static class DoubleStore extends NumberStore<Double> {
|
||||
}
|
||||
|
||||
|
||||
public static class FloatStore extends NumberStore<Float> {
|
||||
}
|
||||
|
||||
|
||||
public static class NumberBean {
|
||||
|
||||
private final NumberStore<Double> doubleStore;
|
||||
|
||||
@@ -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-2.0.dtd">
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
|
||||
+14
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -20,6 +20,9 @@ import java.io.Serializable;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.util.concurrent.UncheckedExecutionException;
|
||||
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.support.SimpleValueWrapper;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -88,8 +91,16 @@ public class GuavaCache implements Cache {
|
||||
|
||||
@Override
|
||||
public ValueWrapper get(Object key) {
|
||||
Object value = this.cache.getIfPresent(key);
|
||||
return toWrapper(value);
|
||||
if (this.cache instanceof LoadingCache) {
|
||||
try {
|
||||
Object value = ((LoadingCache<Object, Object>) this.cache).get(key);
|
||||
return toWrapper(value);
|
||||
}
|
||||
catch (ExecutionException ex) {
|
||||
throw new UncheckedExecutionException(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
return toWrapper(this.cache.getIfPresent(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+7
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,7 @@ package org.springframework.cache.jcache.config;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.cache.annotation.AbstractCachingConfiguration;
|
||||
import org.springframework.cache.annotation.CachingConfigurer;
|
||||
import org.springframework.cache.interceptor.CacheResolver;
|
||||
import org.springframework.cache.jcache.interceptor.DefaultJCacheOperationSource;
|
||||
import org.springframework.cache.jcache.interceptor.JCacheOperationSource;
|
||||
@@ -34,14 +35,16 @@ import org.springframework.context.annotation.Role;
|
||||
* @see JCacheConfigurer
|
||||
*/
|
||||
@Configuration
|
||||
public class AbstractJCacheConfiguration extends AbstractCachingConfiguration<JCacheConfigurer> {
|
||||
public class AbstractJCacheConfiguration extends AbstractCachingConfiguration {
|
||||
|
||||
protected CacheResolver exceptionCacheResolver;
|
||||
|
||||
@Override
|
||||
protected void useCachingConfigurer(JCacheConfigurer config) {
|
||||
protected void useCachingConfigurer(CachingConfigurer config) {
|
||||
super.useCachingConfigurer(config);
|
||||
this.exceptionCacheResolver = config.exceptionCacheResolver();
|
||||
if (config instanceof JCacheConfigurer) {
|
||||
this.exceptionCacheResolver = ((JCacheConfigurer) config).exceptionCacheResolver();
|
||||
}
|
||||
}
|
||||
|
||||
@Bean(name = "jCacheOperationSource")
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -128,9 +128,9 @@ public class DefaultJCacheOperationSource extends AnnotationJCacheOperationSourc
|
||||
|
||||
@Override
|
||||
public void afterSingletonsInstantiated() {
|
||||
// Make sure those are initialized on startup...
|
||||
// Make sure that the cache resolver is initialized. An exception cache resolver is only
|
||||
// required if the exceptionCacheName attribute is set on an operation
|
||||
Assert.notNull(getDefaultCacheResolver(), "Cache resolver should have been initialized");
|
||||
Assert.notNull(getDefaultExceptionCacheResolver(), "Exception cache resolver should have been initialized");
|
||||
}
|
||||
|
||||
|
||||
|
||||
+6
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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,21 +28,21 @@ import org.springframework.cache.interceptor.CacheResolver;
|
||||
* <p>A cache operation can be statically cached as it does not contain
|
||||
* any runtime operation of a specific cache invocation.
|
||||
*
|
||||
* @param <A> the type of the JSR-107 annotation
|
||||
* @author Stephane Nicoll
|
||||
* @since 4.1
|
||||
* @param <A> the type of the JSR-107 annotation
|
||||
*/
|
||||
public interface JCacheOperation<A extends Annotation> extends BasicOperation, CacheMethodDetails<A> {
|
||||
|
||||
/**
|
||||
* Return the {@link CacheResolver} instance to use to resolve the cache to
|
||||
* use for this operation.
|
||||
* Return the {@link CacheResolver} instance to use to resolve the cache
|
||||
* to use for this operation.
|
||||
*/
|
||||
CacheResolver getCacheResolver();
|
||||
|
||||
/**
|
||||
* Return the {@link CacheInvocationParameter} instances based on the specified
|
||||
* method arguments.
|
||||
* Return the {@link CacheInvocationParameter} instances based on the
|
||||
* specified method arguments.
|
||||
* <p>The method arguments must match the signature of the related method invocation
|
||||
* @param values the parameters value for a particular invocation
|
||||
*/
|
||||
|
||||
Vendored
+29
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,7 +18,10 @@ package org.springframework.cache.guava;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.util.concurrent.UncheckedExecutionException;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
@@ -32,6 +35,9 @@ import static org.mockito.Mockito.*;
|
||||
*/
|
||||
public class GuavaCacheManagerTests {
|
||||
|
||||
@Rule
|
||||
public final ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void testDynamicMode() {
|
||||
CacheManager cm = new GuavaCacheManager();
|
||||
@@ -150,6 +156,28 @@ public class GuavaCacheManagerTests {
|
||||
assertNotNull(cm.getCache("someCache"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cacheLoaderUseLoadingCache() {
|
||||
GuavaCacheManager cm = new GuavaCacheManager("c1");
|
||||
cm.setCacheLoader(new CacheLoader<Object, Object>() {
|
||||
@Override
|
||||
public Object load(Object key) throws Exception {
|
||||
if ("ping".equals(key)) {
|
||||
return "pong";
|
||||
}
|
||||
throw new IllegalArgumentException("I only know ping");
|
||||
}
|
||||
});
|
||||
Cache cache1 = cm.getCache("c1");
|
||||
Cache.ValueWrapper value = cache1.get("ping");
|
||||
assertNotNull(value);
|
||||
assertEquals("pong", value.get());
|
||||
|
||||
thrown.expect(UncheckedExecutionException.class);
|
||||
thrown.expectMessage("I only know ping");
|
||||
assertNull(cache1.get("foo"));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private CacheLoader<Object, Object> mockCacheLoader() {
|
||||
return mock(CacheLoader.class);
|
||||
|
||||
+46
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,12 +18,15 @@ package org.springframework.cache.jcache.config;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.concurrent.ConcurrentMapCache;
|
||||
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
|
||||
import org.springframework.cache.config.SomeKeyGenerator;
|
||||
import org.springframework.cache.interceptor.CacheErrorHandler;
|
||||
import org.springframework.cache.interceptor.CacheResolver;
|
||||
@@ -35,7 +38,6 @@ import org.springframework.cache.interceptor.SimpleKeyGenerator;
|
||||
import org.springframework.cache.jcache.interceptor.AnnotatedJCacheableService;
|
||||
import org.springframework.cache.jcache.interceptor.DefaultJCacheOperationSource;
|
||||
import org.springframework.cache.jcache.interceptor.JCacheInterceptor;
|
||||
import org.springframework.cache.jcache.interceptor.SimpleExceptionCacheResolver;
|
||||
import org.springframework.cache.support.NoOpCacheManager;
|
||||
import org.springframework.cache.support.SimpleCacheManager;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
@@ -51,6 +53,9 @@ import static org.junit.Assert.*;
|
||||
*/
|
||||
public class JCacheJavaConfigTests extends AbstractJCacheAnnotationTests {
|
||||
|
||||
@Rule
|
||||
public final ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Override
|
||||
protected ApplicationContext getApplicationContext() {
|
||||
return new AnnotationConfigApplicationContext(EnableCachingConfig.class);
|
||||
@@ -80,10 +85,7 @@ public class JCacheJavaConfigTests extends AbstractJCacheAnnotationTests {
|
||||
assertEquals(SimpleCacheResolver.class, cos.getCacheResolver().getClass());
|
||||
assertSame(context.getBean(CacheManager.class),
|
||||
((SimpleCacheResolver) cos.getCacheResolver()).getCacheManager());
|
||||
assertNotNull(cos.getExceptionCacheResolver());
|
||||
assertEquals(SimpleExceptionCacheResolver.class, cos.getExceptionCacheResolver().getClass());
|
||||
assertSame(context.getBean(CacheManager.class),
|
||||
((SimpleExceptionCacheResolver) cos.getExceptionCacheResolver()).getCacheManager());
|
||||
assertNull(cos.getExceptionCacheResolver());
|
||||
context.close();
|
||||
}
|
||||
|
||||
@@ -99,6 +101,28 @@ public class JCacheJavaConfigTests extends AbstractJCacheAnnotationTests {
|
||||
context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exceptionCacheResolverFallbacksToMainOne() {
|
||||
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
|
||||
NoExceptionCacheResolverConfig.class);
|
||||
try {
|
||||
DefaultJCacheOperationSource cos = context.getBean(DefaultJCacheOperationSource.class);
|
||||
assertSame(context.getBean("cacheResolver"), cos.getCacheResolver());
|
||||
assertNull(cos.getExceptionCacheResolver());
|
||||
|
||||
JCacheableService<?> service = context.getBean(JCacheableService.class);
|
||||
|
||||
service.cache("id");
|
||||
|
||||
// This call requires the cache manager to be set
|
||||
thrown.expect(IllegalStateException.class);
|
||||
service.cacheWithException("test", false);
|
||||
}
|
||||
finally {
|
||||
context.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
@@ -200,4 +224,20 @@ public class JCacheJavaConfigTests extends AbstractJCacheAnnotationTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
static class NoExceptionCacheResolverConfig extends JCacheConfigurerSupport {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
public CacheResolver cacheResolver() {
|
||||
return new NamedCacheResolver(new ConcurrentMapCacheManager(), "default");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JCacheableService<?> cacheableService() {
|
||||
return new AnnotatedJCacheableService(new ConcurrentMapCache("default"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-2
@@ -381,17 +381,20 @@ public class QuartzSupportTests {
|
||||
|
||||
/**
|
||||
* SPR-6038: detect HSQL and stop illegal locks being taken.
|
||||
* TODO: Against Quartz 2.2, this test's job doesn't actually execute anymore...
|
||||
*/
|
||||
@Test
|
||||
public void schedulerWithHsqlDataSource() throws Exception {
|
||||
Assume.group(TestGroup.PERFORMANCE);
|
||||
// Assume.group(TestGroup.PERFORMANCE);
|
||||
|
||||
DummyJob.param = 0;
|
||||
DummyJob.count = 0;
|
||||
|
||||
ClassPathXmlApplicationContext ctx = context("databasePersistence.xml");
|
||||
JdbcTemplate jdbcTemplate = new JdbcTemplate(ctx.getBean(DataSource.class));
|
||||
assertTrue("No triggers were persisted", jdbcTemplate.queryForList("SELECT * FROM qrtz_triggers").size()>0);
|
||||
assertFalse("No triggers were persisted", jdbcTemplate.queryForList("SELECT * FROM qrtz_triggers").isEmpty());
|
||||
|
||||
/*
|
||||
Thread.sleep(3000);
|
||||
try {
|
||||
assertTrue(DummyJob.count > 0);
|
||||
@@ -399,6 +402,7 @@ public class QuartzSupportTests {
|
||||
finally {
|
||||
ctx.close();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
private ClassPathXmlApplicationContext context(String path) {
|
||||
|
||||
Vendored
+12
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.cache.annotation;
|
||||
|
||||
import java.util.Collection;
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.CacheManager;
|
||||
@@ -28,12 +27,11 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportAware;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Abstract base {@code @Configuration} class providing common structure for enabling
|
||||
* Spring's annotation-driven cache management capability.
|
||||
* Abstract base {@code @Configuration} class providing common structure
|
||||
* for enabling Spring's annotation-driven cache management capability.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Stephane Nicoll
|
||||
@@ -41,7 +39,7 @@ import org.springframework.util.CollectionUtils;
|
||||
* @see EnableCaching
|
||||
*/
|
||||
@Configuration
|
||||
public abstract class AbstractCachingConfiguration<C extends CachingConfigurer> implements ImportAware {
|
||||
public abstract class AbstractCachingConfiguration implements ImportAware {
|
||||
|
||||
protected AnnotationAttributes enableCaching;
|
||||
|
||||
@@ -53,17 +51,19 @@ public abstract class AbstractCachingConfiguration<C extends CachingConfigurer>
|
||||
|
||||
protected CacheErrorHandler errorHandler;
|
||||
|
||||
|
||||
@Override
|
||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||
this.enableCaching = AnnotationAttributes.fromMap(
|
||||
importMetadata.getAnnotationAttributes(EnableCaching.class.getName(), false));
|
||||
Assert.notNull(this.enableCaching,
|
||||
"@EnableCaching is not present on importing class " +
|
||||
importMetadata.getClassName());
|
||||
if (this.enableCaching == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"@EnableCaching is not present on importing class " + importMetadata.getClassName());
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
void setConfigurers(Collection<C> configurers) {
|
||||
void setConfigurers(Collection<CachingConfigurer> configurers) {
|
||||
if (CollectionUtils.isEmpty(configurers)) {
|
||||
return;
|
||||
}
|
||||
@@ -73,14 +73,14 @@ public abstract class AbstractCachingConfiguration<C extends CachingConfigurer>
|
||||
"Refactor the configuration such that CachingConfigurer is " +
|
||||
"implemented only once or not at all.");
|
||||
}
|
||||
C configurer = configurers.iterator().next();
|
||||
CachingConfigurer configurer = configurers.iterator().next();
|
||||
useCachingConfigurer(configurer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the configuration from the nominated {@link CachingConfigurer}.
|
||||
*/
|
||||
protected void useCachingConfigurer(C config) {
|
||||
protected void useCachingConfigurer(CachingConfigurer config) {
|
||||
this.cacheManager = config.cacheManager();
|
||||
this.cacheResolver = config.cacheResolver();
|
||||
this.keyGenerator = config.keyGenerator();
|
||||
|
||||
Vendored
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,7 +35,7 @@ import org.springframework.context.annotation.Role;
|
||||
* @see CachingConfigurationSelector
|
||||
*/
|
||||
@Configuration
|
||||
public class ProxyCachingConfiguration extends AbstractCachingConfiguration<CachingConfigurer> {
|
||||
public class ProxyCachingConfiguration extends AbstractCachingConfiguration {
|
||||
|
||||
@Bean(name = CacheManagementConfigUtils.CACHE_ADVISOR_BEAN_NAME)
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
|
||||
+3
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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,7 +23,7 @@ import org.springframework.cache.Cache;
|
||||
/**
|
||||
* Determine the {@link Cache} instance(s) to use for an intercepted method invocation.
|
||||
*
|
||||
* <p>Implementations MUST be thread-safe.
|
||||
* <p>Implementations must be thread-safe.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 4.1
|
||||
@@ -32,9 +32,8 @@ public interface CacheResolver {
|
||||
|
||||
/**
|
||||
* Return the cache(s) to use for the specified invocation.
|
||||
*
|
||||
* @param context the context of the particular invocation
|
||||
* @return the cache(s) to use (never null)
|
||||
* @return the cache(s) to use (never {@code null})
|
||||
*/
|
||||
Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
/*
|
||||
* Copyright 2002-2015 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,9 +28,9 @@ import org.springframework.util.Assert;
|
||||
* based on an {@link AdviceMode} value from an annotation (such as the {@code @Enable*}
|
||||
* annotations).
|
||||
*
|
||||
* @param <A> Annotation containing {@linkplain #getAdviceModeAttributeName() AdviceMode attribute}
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
* @param <A> annotation containing {@linkplain #getAdviceModeAttributeName() AdviceMode attribute}
|
||||
*/
|
||||
public abstract class AdviceModeImportSelector<A extends Annotation> implements ImportSelector {
|
||||
|
||||
|
||||
+4
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
@@ -63,6 +64,8 @@ final class ConfigurationClass {
|
||||
private final Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> importBeanDefinitionRegistrars =
|
||||
new LinkedHashMap<ImportBeanDefinitionRegistrar, AnnotationMetadata>();
|
||||
|
||||
final Set<String> skippedBeanMethods = new HashSet<String>();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@link ConfigurationClass} with the given name.
|
||||
|
||||
+28
-19
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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,33 +182,25 @@ class ConfigurationClassBeanDefinitionReader {
|
||||
* with the BeanDefinitionRegistry based on its contents.
|
||||
*/
|
||||
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
|
||||
if (this.conditionEvaluator.shouldSkip(beanMethod.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ConfigurationClass configClass = beanMethod.getConfigurationClass();
|
||||
MethodMetadata metadata = beanMethod.getMetadata();
|
||||
String methodName = metadata.getMethodName();
|
||||
|
||||
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
|
||||
beanDef.setResource(configClass.getResource());
|
||||
beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
|
||||
if (metadata.isStatic()) {
|
||||
// static @Bean method
|
||||
beanDef.setBeanClassName(configClass.getMetadata().getClassName());
|
||||
beanDef.setFactoryMethodName(metadata.getMethodName());
|
||||
// Do we need to mark the bean as skipped by its condition?
|
||||
if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
|
||||
configClass.skippedBeanMethods.add(methodName);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// instance @Bean method
|
||||
beanDef.setFactoryBeanName(configClass.getBeanName());
|
||||
beanDef.setUniqueFactoryMethodName(metadata.getMethodName());
|
||||
if (configClass.skippedBeanMethods.contains(methodName)) {
|
||||
return;
|
||||
}
|
||||
beanDef.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
|
||||
beanDef.setAttribute(RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);
|
||||
|
||||
// Consider name and any aliases
|
||||
AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
|
||||
List<String> names = new ArrayList<String>(Arrays.asList(bean.getStringArray("name")));
|
||||
String beanName = (names.size() > 0 ? names.remove(0) : beanMethod.getMetadata().getMethodName());
|
||||
String beanName = (names.size() > 0 ? names.remove(0) : methodName);
|
||||
|
||||
// Register aliases even when overridden
|
||||
for (String alias : names) {
|
||||
this.registry.registerAlias(beanName, alias);
|
||||
}
|
||||
@@ -218,6 +210,23 @@ class ConfigurationClassBeanDefinitionReader {
|
||||
return;
|
||||
}
|
||||
|
||||
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
|
||||
beanDef.setResource(configClass.getResource());
|
||||
beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
|
||||
|
||||
if (metadata.isStatic()) {
|
||||
// static @Bean method
|
||||
beanDef.setBeanClassName(configClass.getMetadata().getClassName());
|
||||
beanDef.setFactoryMethodName(methodName);
|
||||
}
|
||||
else {
|
||||
// instance @Bean method
|
||||
beanDef.setFactoryBeanName(configClass.getBeanName());
|
||||
beanDef.setUniqueFactoryMethodName(methodName);
|
||||
}
|
||||
beanDef.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
|
||||
beanDef.setAttribute(RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);
|
||||
|
||||
AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);
|
||||
|
||||
Autowire autowire = bean.getEnum("autowire");
|
||||
|
||||
+16
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -133,7 +133,7 @@ class ConfigurationClassParser {
|
||||
|
||||
private final ImportStack importStack = new ImportStack();
|
||||
|
||||
private final List<DeferredImportSelectorHolder> deferredImportSelectors = new LinkedList<DeferredImportSelectorHolder>();
|
||||
private List<DeferredImportSelectorHolder> deferredImportSelectors;
|
||||
|
||||
|
||||
/**
|
||||
@@ -156,6 +156,8 @@ class ConfigurationClassParser {
|
||||
|
||||
|
||||
public void parse(Set<BeanDefinitionHolder> configCandidates) {
|
||||
this.deferredImportSelectors = new LinkedList<DeferredImportSelectorHolder>();
|
||||
|
||||
for (BeanDefinitionHolder holder : configCandidates) {
|
||||
BeanDefinition bd = holder.getBeanDefinition();
|
||||
try {
|
||||
@@ -177,6 +179,7 @@ class ConfigurationClassParser {
|
||||
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
|
||||
}
|
||||
}
|
||||
|
||||
processDeferredImportSelectors();
|
||||
}
|
||||
|
||||
@@ -269,7 +272,7 @@ class ConfigurationClassParser {
|
||||
}
|
||||
|
||||
// Process any @Import annotations
|
||||
processImports(configClass, sourceClass, getImports(sourceClass), true, false);
|
||||
processImports(configClass, sourceClass, getImports(sourceClass), true);
|
||||
|
||||
// Process any @ImportResource annotations
|
||||
if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {
|
||||
@@ -416,12 +419,15 @@ class ConfigurationClassParser {
|
||||
}
|
||||
|
||||
private void processDeferredImportSelectors() {
|
||||
Collections.sort(this.deferredImportSelectors, DEFERRED_IMPORT_COMPARATOR);
|
||||
for (DeferredImportSelectorHolder deferredImport : this.deferredImportSelectors) {
|
||||
List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
|
||||
this.deferredImportSelectors = null;
|
||||
Collections.sort(deferredImports, DEFERRED_IMPORT_COMPARATOR);
|
||||
|
||||
for (DeferredImportSelectorHolder deferredImport : deferredImports) {
|
||||
ConfigurationClass configClass = deferredImport.getConfigurationClass();
|
||||
try {
|
||||
String[] imports = deferredImport.getImportSelector().selectImports(configClass.getMetadata());
|
||||
processImports(configClass, asSourceClass(configClass), asSourceClasses(imports), false, true);
|
||||
processImports(configClass, asSourceClass(configClass), asSourceClasses(imports), false);
|
||||
}
|
||||
catch (BeanDefinitionStoreException ex) {
|
||||
throw ex;
|
||||
@@ -431,11 +437,10 @@ class ConfigurationClassParser {
|
||||
configClass.getMetadata().getClassName() + "]", ex);
|
||||
}
|
||||
}
|
||||
this.deferredImportSelectors.clear();
|
||||
}
|
||||
|
||||
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
|
||||
Collection<SourceClass> importCandidates, boolean checkForCircularImports, boolean deferred) throws IOException {
|
||||
Collection<SourceClass> importCandidates, boolean checkForCircularImports) throws IOException {
|
||||
|
||||
if (importCandidates.isEmpty()) {
|
||||
return;
|
||||
@@ -453,14 +458,14 @@ class ConfigurationClassParser {
|
||||
Class<?> candidateClass = candidate.loadClass();
|
||||
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
|
||||
invokeAwareMethods(selector);
|
||||
if (!deferred && selector instanceof DeferredImportSelector) {
|
||||
if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
|
||||
this.deferredImportSelectors.add(
|
||||
new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
|
||||
}
|
||||
else {
|
||||
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
|
||||
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
|
||||
processImports(configClass, currentSourceClass, importSourceClasses, false, false);
|
||||
processImports(configClass, currentSourceClass, importSourceClasses, false);
|
||||
}
|
||||
}
|
||||
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
|
||||
@@ -474,7 +479,7 @@ class ConfigurationClassParser {
|
||||
}
|
||||
else {
|
||||
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
|
||||
// process it as a @Configuration class
|
||||
// process it as an @Configuration class
|
||||
this.importStack.registerImport(
|
||||
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
|
||||
processConfigurationClass(candidate.asConfigClass(configClass));
|
||||
|
||||
+12
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 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,9 +26,6 @@ import org.springframework.context.weaving.DefaultContextLoadTimeWeaver;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.instrument.classloading.LoadTimeWeaver;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import static org.springframework.context.weaving.AspectJWeavingEnabler.*;
|
||||
|
||||
/**
|
||||
* {@code @Configuration} class that registers a {@link LoadTimeWeaver} bean.
|
||||
@@ -47,7 +44,6 @@ public class LoadTimeWeavingConfiguration implements ImportAware, BeanClassLoade
|
||||
|
||||
private AnnotationAttributes enableLTW;
|
||||
|
||||
@Autowired(required=false)
|
||||
private LoadTimeWeavingConfigurer ltwConfigurer;
|
||||
|
||||
private ClassLoader beanClassLoader;
|
||||
@@ -56,8 +52,15 @@ public class LoadTimeWeavingConfiguration implements ImportAware, BeanClassLoade
|
||||
@Override
|
||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||
this.enableLTW = AnnotationConfigUtils.attributesFor(importMetadata, EnableLoadTimeWeaving.class);
|
||||
Assert.notNull(this.enableLTW,
|
||||
"@EnableLoadTimeWeaving is not present on importing class " + importMetadata.getClassName());
|
||||
if (this.enableLTW == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"@EnableLoadTimeWeaving is not present on importing class " + importMetadata.getClassName());
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
public void setLoadTimeWeavingConfigurer(LoadTimeWeavingConfigurer ltwConfigurer) {
|
||||
this.ltwConfigurer = ltwConfigurer;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,7 +69,7 @@ public class LoadTimeWeavingConfiguration implements ImportAware, BeanClassLoade
|
||||
}
|
||||
|
||||
|
||||
@Bean(name=ConfigurableApplicationContext.LOAD_TIME_WEAVER_BEAN_NAME)
|
||||
@Bean(name = ConfigurableApplicationContext.LOAD_TIME_WEAVER_BEAN_NAME)
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public LoadTimeWeaver loadTimeWeaver() {
|
||||
LoadTimeWeaver loadTimeWeaver = null;
|
||||
@@ -87,7 +90,7 @@ public class LoadTimeWeavingConfiguration implements ImportAware, BeanClassLoade
|
||||
// AJ weaving is disabled -> do nothing
|
||||
break;
|
||||
case AUTODETECT:
|
||||
if (this.beanClassLoader.getResource(ASPECTJ_AOP_XML_RESOURCE) == null) {
|
||||
if (this.beanClassLoader.getResource(AspectJWeavingEnabler.ASPECTJ_AOP_XML_RESOURCE) == null) {
|
||||
// No aop.xml present on the classpath -> treat as 'disabled'
|
||||
break;
|
||||
}
|
||||
|
||||
+7
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -51,7 +51,7 @@ public class MBeanExportConfiguration implements ImportAware, EnvironmentAware,
|
||||
|
||||
private static final String MBEAN_EXPORTER_BEAN_NAME = "mbeanExporter";
|
||||
|
||||
private AnnotationAttributes attributes;
|
||||
private AnnotationAttributes enableMBeanExport;
|
||||
|
||||
private Environment environment;
|
||||
|
||||
@@ -61,8 +61,8 @@ public class MBeanExportConfiguration implements ImportAware, EnvironmentAware,
|
||||
@Override
|
||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||
Map<String, Object> map = importMetadata.getAnnotationAttributes(EnableMBeanExport.class.getName());
|
||||
this.attributes = AnnotationAttributes.fromMap(map);
|
||||
if (this.attributes == null) {
|
||||
this.enableMBeanExport = AnnotationAttributes.fromMap(map);
|
||||
if (this.enableMBeanExport == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"@EnableMBeanExport is not present on importing class " + importMetadata.getClassName());
|
||||
}
|
||||
@@ -90,7 +90,7 @@ public class MBeanExportConfiguration implements ImportAware, EnvironmentAware,
|
||||
}
|
||||
|
||||
private void setupDomain(AnnotationMBeanExporter exporter) {
|
||||
String defaultDomain = this.attributes.getString("defaultDomain");
|
||||
String defaultDomain = this.enableMBeanExport.getString("defaultDomain");
|
||||
if (defaultDomain != null && this.environment != null) {
|
||||
defaultDomain = this.environment.resolvePlaceholders(defaultDomain);
|
||||
}
|
||||
@@ -100,7 +100,7 @@ public class MBeanExportConfiguration implements ImportAware, EnvironmentAware,
|
||||
}
|
||||
|
||||
private void setupServer(AnnotationMBeanExporter exporter) {
|
||||
String server = this.attributes.getString("server");
|
||||
String server = this.enableMBeanExport.getString("server");
|
||||
if (server != null && this.environment != null) {
|
||||
server = this.environment.resolvePlaceholders(server);
|
||||
}
|
||||
@@ -116,7 +116,7 @@ public class MBeanExportConfiguration implements ImportAware, EnvironmentAware,
|
||||
}
|
||||
|
||||
private void setupRegistrationPolicy(AnnotationMBeanExporter exporter) {
|
||||
RegistrationPolicy registrationPolicy = this.attributes.getEnum("registration");
|
||||
RegistrationPolicy registrationPolicy = this.enableMBeanExport.getEnum("registration");
|
||||
exporter.setRegistrationPolicy(registrationPolicy);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2015 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,16 +28,16 @@ import org.springframework.beans.factory.config.BeanDefinition;
|
||||
* Indicates the 'role' hint for a given bean.
|
||||
*
|
||||
* <p>May be used on any class directly or indirectly annotated with
|
||||
* {@link org.springframework.stereotype.Component} or on methods annotated with
|
||||
* {@link Bean}.
|
||||
* {@link org.springframework.stereotype.Component} or on methods
|
||||
* annotated with {@link Bean}.
|
||||
*
|
||||
* <p>If this annotation is not present on a Component or Bean definition, the
|
||||
* default value of {@link BeanDefinition#ROLE_APPLICATION} will apply.
|
||||
* <p>If this annotation is not present on a Component or Bean definition,
|
||||
* the default value of {@link BeanDefinition#ROLE_APPLICATION} will apply.
|
||||
*
|
||||
* <p>If Role is present on a {@link Configuration @Configuration} class, this
|
||||
* indicates the role of the configuration class bean definition and does not
|
||||
* cascade to all @{@code Bean} methods defined within. This behavior is
|
||||
* different than that of the @{@link Lazy} annotation, for example.
|
||||
* <p>If Role is present on a {@link Configuration @Configuration} class,
|
||||
* this indicates the role of the configuration class bean definition and
|
||||
* does not cascade to all @{@code Bean} methods defined within. This behavior
|
||||
* is different than that of the @{@link Lazy} annotation, for example.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
|
||||
+53
-45
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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,6 +28,7 @@ import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.support.AbstractBeanFactory;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.core.OrderComparator;
|
||||
@@ -65,47 +66,8 @@ public abstract class AbstractApplicationEventMulticaster
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private Object retrievalMutex = this.defaultRetriever;
|
||||
|
||||
@Override
|
||||
public void addApplicationListener(ApplicationListener<?> listener) {
|
||||
synchronized (this.defaultRetriever) {
|
||||
this.defaultRetriever.applicationListeners.add(listener);
|
||||
this.retrieverCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addApplicationListenerBean(String listenerBeanName) {
|
||||
synchronized (this.defaultRetriever) {
|
||||
this.defaultRetriever.applicationListenerBeans.add(listenerBeanName);
|
||||
this.retrieverCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeApplicationListener(ApplicationListener<?> listener) {
|
||||
synchronized (this.defaultRetriever) {
|
||||
this.defaultRetriever.applicationListeners.remove(listener);
|
||||
this.retrieverCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeApplicationListenerBean(String listenerBeanName) {
|
||||
synchronized (this.defaultRetriever) {
|
||||
this.defaultRetriever.applicationListenerBeans.remove(listenerBeanName);
|
||||
this.retrieverCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAllListeners() {
|
||||
synchronized (this.defaultRetriever) {
|
||||
this.defaultRetriever.applicationListeners.clear();
|
||||
this.defaultRetriever.applicationListenerBeans.clear();
|
||||
this.retrieverCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
@@ -118,6 +80,9 @@ public abstract class AbstractApplicationEventMulticaster
|
||||
if (this.beanClassLoader == null && beanFactory instanceof ConfigurableBeanFactory) {
|
||||
this.beanClassLoader = ((ConfigurableBeanFactory) beanFactory).getBeanClassLoader();
|
||||
}
|
||||
if (beanFactory instanceof AbstractBeanFactory) {
|
||||
this.retrievalMutex = ((AbstractBeanFactory) beanFactory).getSingletonMutex();
|
||||
}
|
||||
}
|
||||
|
||||
private BeanFactory getBeanFactory() {
|
||||
@@ -129,13 +94,55 @@ public abstract class AbstractApplicationEventMulticaster
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addApplicationListener(ApplicationListener<?> listener) {
|
||||
synchronized (this.retrievalMutex) {
|
||||
this.defaultRetriever.applicationListeners.add(listener);
|
||||
this.retrieverCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addApplicationListenerBean(String listenerBeanName) {
|
||||
synchronized (this.retrievalMutex) {
|
||||
this.defaultRetriever.applicationListenerBeans.add(listenerBeanName);
|
||||
this.retrieverCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeApplicationListener(ApplicationListener<?> listener) {
|
||||
synchronized (this.retrievalMutex) {
|
||||
this.defaultRetriever.applicationListeners.remove(listener);
|
||||
this.retrieverCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeApplicationListenerBean(String listenerBeanName) {
|
||||
synchronized (this.retrievalMutex) {
|
||||
this.defaultRetriever.applicationListenerBeans.remove(listenerBeanName);
|
||||
this.retrieverCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAllListeners() {
|
||||
synchronized (this.retrievalMutex) {
|
||||
this.defaultRetriever.applicationListeners.clear();
|
||||
this.defaultRetriever.applicationListenerBeans.clear();
|
||||
this.retrieverCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a Collection containing all ApplicationListeners.
|
||||
* @return a Collection of ApplicationListeners
|
||||
* @see org.springframework.context.ApplicationListener
|
||||
*/
|
||||
protected Collection<ApplicationListener<?>> getApplicationListeners() {
|
||||
synchronized (this.defaultRetriever) {
|
||||
synchronized (this.retrievalMutex) {
|
||||
return this.defaultRetriever.getApplicationListeners();
|
||||
}
|
||||
}
|
||||
@@ -163,13 +170,14 @@ public abstract class AbstractApplicationEventMulticaster
|
||||
(ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&
|
||||
(sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
|
||||
// Fully synchronized building and caching of a ListenerRetriever
|
||||
synchronized (this.defaultRetriever) {
|
||||
synchronized (this.retrievalMutex) {
|
||||
retriever = this.retrieverCache.get(cacheKey);
|
||||
if (retriever != null) {
|
||||
return retriever.getApplicationListeners();
|
||||
}
|
||||
retriever = new ListenerRetriever(true);
|
||||
Collection<ApplicationListener<?>> listeners = retrieveApplicationListeners(event, sourceType, retriever);
|
||||
Collection<ApplicationListener<?>> listeners =
|
||||
retrieveApplicationListeners(event, sourceType, retriever);
|
||||
this.retrieverCache.put(cacheKey, retriever);
|
||||
return listeners;
|
||||
}
|
||||
@@ -193,7 +201,7 @@ public abstract class AbstractApplicationEventMulticaster
|
||||
LinkedList<ApplicationListener<?>> allListeners = new LinkedList<ApplicationListener<?>>();
|
||||
Set<ApplicationListener<?>> listeners;
|
||||
Set<String> listenerBeans;
|
||||
synchronized (this.defaultRetriever) {
|
||||
synchronized (this.retrievalMutex) {
|
||||
listeners = new LinkedHashSet<ApplicationListener<?>>(this.defaultRetriever.applicationListeners);
|
||||
listenerBeans = new LinkedHashSet<String>(this.defaultRetriever.applicationListenerBeans);
|
||||
}
|
||||
|
||||
+8
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -152,7 +152,7 @@ public class ResourceBundleMessageSource extends AbstractMessageSource implement
|
||||
* Set the default charset to use for parsing resource bundle files.
|
||||
* <p>Default is none, using the {@code java.util.ResourceBundle}
|
||||
* default encoding: ISO-8859-1.
|
||||
* and more flexibility in setting of an encoding per file.
|
||||
* @since 3.1.3
|
||||
*/
|
||||
public void setDefaultEncoding(String defaultEncoding) {
|
||||
this.defaultEncoding = defaultEncoding;
|
||||
@@ -167,6 +167,7 @@ public class ResourceBundleMessageSource extends AbstractMessageSource implement
|
||||
* {@code java.util.ResourceBundle}. However, this is often not desirable
|
||||
* in an application server environment, where the system Locale is not relevant
|
||||
* to the application at all: Set this flag to "false" in such a scenario.
|
||||
* @since 3.1.3
|
||||
*/
|
||||
public void setFallbackToSystemLocale(boolean fallbackToSystemLocale) {
|
||||
this.fallbackToSystemLocale = fallbackToSystemLocale;
|
||||
@@ -188,6 +189,7 @@ public class ResourceBundleMessageSource extends AbstractMessageSource implement
|
||||
* Consider {@link ReloadableResourceBundleMessageSource} in combination
|
||||
* with resource bundle files in a non-classpath location.
|
||||
* </ul>
|
||||
* @since 3.1.3
|
||||
*/
|
||||
public void setCacheSeconds(int cacheSeconds) {
|
||||
this.cacheMillis = (cacheSeconds * 1000);
|
||||
@@ -304,7 +306,7 @@ public class ResourceBundleMessageSource extends AbstractMessageSource implement
|
||||
* @param locale the Locale to look for
|
||||
* @return the corresponding ResourceBundle
|
||||
* @throws MissingResourceException if no matching bundle could be found
|
||||
* @see java.util.ResourceBundle#getBundle(String, java.util.Locale, ClassLoader)
|
||||
* @see java.util.ResourceBundle#getBundle(String, Locale, ClassLoader)
|
||||
* @see #getBundleClassLoader()
|
||||
*/
|
||||
protected ResourceBundle doGetBundle(String basename, Locale locale) throws MissingResourceException {
|
||||
@@ -394,6 +396,8 @@ public class ResourceBundleMessageSource extends AbstractMessageSource implement
|
||||
@Override
|
||||
public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload)
|
||||
throws IllegalAccessException, InstantiationException, IOException {
|
||||
|
||||
// Special handling of default encoding
|
||||
if (format.equals("java.properties")) {
|
||||
String bundleName = toBundleName(baseName, locale);
|
||||
final String resourceName = toResourceName(bundleName, "properties");
|
||||
@@ -441,6 +445,7 @@ public class ResourceBundleMessageSource extends AbstractMessageSource implement
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Delegate handling of "java.class" format to standard Control
|
||||
return super.newBundle(baseName, locale, format, loader, reload);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.format.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -28,19 +29,19 @@ import java.lang.annotation.Target;
|
||||
* Can be applied to {@code java.util.Date}, {@code java.util.Calendar}, {@code java.long.Long},
|
||||
* Joda-Time value types; and as of Spring 4 and JDK 8, to JSR-310 <code>java.time</code> types too.
|
||||
*
|
||||
* <p>For style-based formatting, set the {@link #style()} attribute to be the style pattern code.
|
||||
* <p>For style-based formatting, set the {@link #style} attribute to be the style pattern code.
|
||||
* The first character of the code is the date style, and the second character is the time style.
|
||||
* Specify a character of 'S' for short style, 'M' for medium, 'L' for long, and 'F' for full.
|
||||
* A date or time may be omitted by specifying the style character '-'.
|
||||
*
|
||||
* <p>For ISO-based formatting, set the {@link #iso()} attribute to be the desired {@link ISO} format,
|
||||
* such as {@link ISO#DATE}. For custom formatting, set the {@link #pattern()} attribute to be the
|
||||
* <p>For ISO-based formatting, set the {@link #iso} attribute to be the desired {@link ISO} format,
|
||||
* such as {@link ISO#DATE}. For custom formatting, set the {@link #pattern} attribute to be the
|
||||
* DateTime pattern, such as {@code yyyy/MM/dd hh:mm:ss a}.
|
||||
*
|
||||
* <p>Each attribute is mutually exclusive, so only set one attribute per annotation instance
|
||||
* (the one most convenient one for your formatting needs).
|
||||
* (the most convenient one for your formatting needs).
|
||||
* When the pattern attribute is specified, it takes precedence over both the style and ISO attribute.
|
||||
* When the iso attribute is specified, if takes precedence over the style attribute.
|
||||
* When the iso attribute is specified, it takes precedence over the style attribute.
|
||||
* When no annotation attributes are specified, the default format applied is style-based
|
||||
* with a style code of 'SS' (short date, short time).
|
||||
*
|
||||
@@ -49,8 +50,9 @@ import java.lang.annotation.Target;
|
||||
* @since 3.0
|
||||
* @see org.joda.time.format.DateTimeFormat
|
||||
*/
|
||||
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
|
||||
public @interface DateTimeFormat {
|
||||
|
||||
/**
|
||||
|
||||
+13
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.format.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -23,23 +24,27 @@ import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Declares that a field should be formatted as a number.
|
||||
* Supports formatting by style or custom pattern string.
|
||||
*
|
||||
* <p>Supports formatting by style or custom pattern string.
|
||||
* Can be applied to any JDK {@code java.lang.Number} type.
|
||||
*
|
||||
* <p>For style-based formatting, set the {@link #style()} attribute to be the desired {@link Style}.
|
||||
* For custom formatting, set the {@link #pattern()} attribute to be the number pattern, such as {@code #, ###.##}.
|
||||
* <p>For style-based formatting, set the {@link #style} attribute to be the
|
||||
* desired {@link Style}. For custom formatting, set the {@link #pattern}
|
||||
* attribute to be the number pattern, such as {@code #, ###.##}.
|
||||
*
|
||||
* <p>Each attribute is mutually exclusive, so only set one attribute per annotation instance
|
||||
* (the one most convenient one for your formatting needs). When the pattern attribute is specified,
|
||||
* it takes precedence over the style attribute. When no annotation attributes are specified,
|
||||
* <p>Each attribute is mutually exclusive, so only set one attribute per
|
||||
* annotation instance (the one most convenient one for your formatting needs).
|
||||
* When the {@link #pattern} attribute is specified, it takes precedence over
|
||||
* the {@link #style} attribute. When no annotation attributes are specified,
|
||||
* the default format applied is style-based with a style of {@link Style#NUMBER}.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @since 3.0
|
||||
* @see java.text.NumberFormat
|
||||
*/
|
||||
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
|
||||
public @interface NumberFormat {
|
||||
|
||||
/**
|
||||
|
||||
@@ -161,7 +161,7 @@ public class MBeanExporter extends MBeanRegistrationSupport implements MBeanExpo
|
||||
private boolean exposeManagedResourceClassLoader = true;
|
||||
|
||||
/** A set of bean names that should be excluded from autodetection */
|
||||
private Set<String> excludedBeans;
|
||||
private Set<String> excludedBeans = new HashSet<String>();
|
||||
|
||||
/** The MBeanExporterListeners registered with this exporter. */
|
||||
private MBeanExporterListener[] listeners;
|
||||
@@ -314,7 +314,18 @@ public class MBeanExporter extends MBeanRegistrationSupport implements MBeanExpo
|
||||
* Set the list of names for beans that should be excluded from autodetection.
|
||||
*/
|
||||
public void setExcludedBeans(String... excludedBeans) {
|
||||
this.excludedBeans = (excludedBeans != null ? new HashSet<String>(Arrays.asList(excludedBeans)) : null);
|
||||
this.excludedBeans.clear();
|
||||
if (excludedBeans != null) {
|
||||
this.excludedBeans.addAll(Arrays.asList(excludedBeans));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the name of bean that should be excluded from autodetection.
|
||||
*/
|
||||
public void addExcludedBean(String excludedBean) {
|
||||
Assert.notNull(excludedBean, "ExcludedBean must not be null");
|
||||
this.excludedBeans.add(excludedBean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -922,10 +933,9 @@ public class MBeanExporter extends MBeanRegistrationSupport implements MBeanExpo
|
||||
* Indicates whether or not a particular bean name is present in the excluded beans list.
|
||||
*/
|
||||
private boolean isExcluded(String beanName) {
|
||||
return (this.excludedBeans != null &&
|
||||
(this.excludedBeans.contains(beanName) ||
|
||||
(beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX) &&
|
||||
this.excludedBeans.contains(beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length())))));
|
||||
return (this.excludedBeans.contains(beanName) ||
|
||||
(beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX) &&
|
||||
this.excludedBeans.contains(beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length()))));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+7
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -25,7 +25,6 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportAware;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
@@ -43,6 +42,7 @@ public abstract class AbstractAsyncConfiguration implements ImportAware {
|
||||
protected AnnotationAttributes enableAsync;
|
||||
|
||||
protected Executor executor;
|
||||
|
||||
protected AsyncUncaughtExceptionHandler exceptionHandler;
|
||||
|
||||
|
||||
@@ -50,14 +50,16 @@ public abstract class AbstractAsyncConfiguration implements ImportAware {
|
||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||
this.enableAsync = AnnotationAttributes.fromMap(
|
||||
importMetadata.getAnnotationAttributes(EnableAsync.class.getName(), false));
|
||||
Assert.notNull(this.enableAsync,
|
||||
"@EnableAsync is not present on importing class " + importMetadata.getClassName());
|
||||
if (this.enableAsync == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"@EnableAsync is not present on importing class " + importMetadata.getClassName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect any {@link AsyncConfigurer} beans through autowiring.
|
||||
*/
|
||||
@Autowired(required=false)
|
||||
@Autowired(required = false)
|
||||
void setConfigurers(Collection<AsyncConfigurer> configurers) {
|
||||
if (CollectionUtils.isEmpty(configurers)) {
|
||||
return;
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ public class ProxyAsyncConfiguration extends AbstractAsyncConfiguration {
|
||||
public AsyncAnnotationBeanPostProcessor asyncAdvisor() {
|
||||
Assert.notNull(this.enableAsync, "@EnableAsync annotation metadata was not injected");
|
||||
AsyncAnnotationBeanPostProcessor bpp = new AsyncAnnotationBeanPostProcessor();
|
||||
Class<? extends Annotation> customAsyncAnnotation = enableAsync.getClass("annotation");
|
||||
Class<? extends Annotation> customAsyncAnnotation = this.enableAsync.getClass("annotation");
|
||||
if (customAsyncAnnotation != AnnotationUtils.getDefaultValue(EnableAsync.class, "annotation")) {
|
||||
bpp.setAsyncAnnotationType(customAsyncAnnotation);
|
||||
}
|
||||
|
||||
+38
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -39,7 +39,10 @@ import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
|
||||
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.EmbeddedValueResolverAware;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
@@ -61,12 +64,12 @@ import org.springframework.util.StringValueResolver;
|
||||
* to the "fixedRate", "fixedDelay", or "cron" expression provided via the annotation.
|
||||
*
|
||||
* <p>This post-processor is automatically registered by Spring's
|
||||
* {@code <task:annotation-driven>} XML element, and also by the @{@link EnableScheduling}
|
||||
* annotation.
|
||||
* {@code <task:annotation-driven>} XML element, and also by the
|
||||
* @{@link EnableScheduling} annotation.
|
||||
*
|
||||
* <p>Auto-detects any {@link SchedulingConfigurer} instances in the container,
|
||||
* allowing for customization of the scheduler to be used or for fine-grained control
|
||||
* over task registration (e.g. registration of {@link Trigger} tasks.
|
||||
* <p>Autodetects any {@link SchedulingConfigurer} instances in the container,
|
||||
* allowing for customization of the scheduler to be used or for fine-grained
|
||||
* control over task registration (e.g. registration of {@link Trigger} tasks.
|
||||
* See the @{@link EnableScheduling} javadocs for complete usage details.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
@@ -80,7 +83,8 @@ import org.springframework.util.StringValueResolver;
|
||||
* @see org.springframework.scheduling.config.ScheduledTaskRegistrar
|
||||
*/
|
||||
public class ScheduledAnnotationBeanPostProcessor implements BeanPostProcessor, Ordered,
|
||||
EmbeddedValueResolverAware, BeanFactoryAware, SmartInitializingSingleton, DisposableBean {
|
||||
EmbeddedValueResolverAware, BeanFactoryAware, ApplicationContextAware,
|
||||
SmartInitializingSingleton, ApplicationListener<ContextRefreshedEvent>, DisposableBean {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
@@ -90,6 +94,8 @@ public class ScheduledAnnotationBeanPostProcessor implements BeanPostProcessor,
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private final ScheduledTaskRegistrar registrar = new ScheduledTaskRegistrar();
|
||||
|
||||
private final Set<Class<?>> nonAnnotatedClasses =
|
||||
@@ -126,10 +132,13 @@ public class ScheduledAnnotationBeanPostProcessor implements BeanPostProcessor,
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated as of Spring 4.1, in favor of {@link #setBeanFactory}
|
||||
* Setting an {@link ApplicationContext} is optional: If set, registered
|
||||
* tasks will be activated in the {@link ContextRefreshedEvent} phase;
|
||||
* if not set, it will happen at {@link #afterSingletonsInstantiated} time.
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) {
|
||||
this.applicationContext = applicationContext;
|
||||
if (this.beanFactory == null) {
|
||||
this.beanFactory = applicationContext;
|
||||
}
|
||||
@@ -138,6 +147,23 @@ public class ScheduledAnnotationBeanPostProcessor implements BeanPostProcessor,
|
||||
|
||||
@Override
|
||||
public void afterSingletonsInstantiated() {
|
||||
if (this.applicationContext == null) {
|
||||
// Not running in an ApplicationContext -> register tasks early...
|
||||
finishRegistration();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
if (event.getApplicationContext() == this.applicationContext) {
|
||||
// Running in an ApplicationContext -> register tasks this late...
|
||||
// giving other ContextRefreshedEvent listeners a chance to perform
|
||||
// their work at the same time (e.g. Spring Batch's job registration).
|
||||
finishRegistration();
|
||||
}
|
||||
}
|
||||
|
||||
private void finishRegistration() {
|
||||
if (this.scheduler != null) {
|
||||
this.registrar.setScheduler(this.scheduler);
|
||||
}
|
||||
@@ -190,9 +216,9 @@ public class ScheduledAnnotationBeanPostProcessor implements BeanPostProcessor,
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(final Object bean, String beanName) {
|
||||
if (!this.nonAnnotatedClasses.contains(bean.getClass())) {
|
||||
Class<?> targetClass = AopUtils.getTargetClass(bean);
|
||||
if (!this.nonAnnotatedClasses.contains(targetClass)) {
|
||||
final Set<Method> annotatedMethods = new LinkedHashSet<Method>(1);
|
||||
Class<?> targetClass = AopUtils.getTargetClass(bean);
|
||||
ReflectionUtils.doWithMethods(targetClass, new MethodCallback() {
|
||||
@Override
|
||||
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
|
||||
@@ -204,7 +230,7 @@ public class ScheduledAnnotationBeanPostProcessor implements BeanPostProcessor,
|
||||
}
|
||||
});
|
||||
if (annotatedMethods.isEmpty()) {
|
||||
this.nonAnnotatedClasses.add(bean.getClass());
|
||||
this.nonAnnotatedClasses.add(targetClass);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("No @Scheduled annotations found on bean class: " + bean.getClass());
|
||||
}
|
||||
|
||||
+17
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -32,11 +32,14 @@ import org.springframework.jndi.JndiTemplate;
|
||||
* for JSR-236's "java:comp/DefaultManagedThreadFactory" in a Java EE 7 environment,
|
||||
* falling back to the local {@link CustomizableThreadFactory} setup if not found.
|
||||
*
|
||||
* <p>This is a convenient way to use managed threads when running in a Java EE 7 environment,
|
||||
* simply using regular local threads otherwise - without conditional setup (like profiles).
|
||||
* <p>This is a convenient way to use managed threads when running in a Java EE 7
|
||||
* environment, simply using regular local threads otherwise - without conditional
|
||||
* setup (i.e. without profiles).
|
||||
*
|
||||
* <p>Note: This class is not strictly JSR-236 based; it can work with any regular
|
||||
* {@link java.util.concurrent.ThreadFactory} that can be found in JNDI.
|
||||
* {@link java.util.concurrent.ThreadFactory} that can be found in JNDI. Therefore,
|
||||
* the default JNDI name "java:comp/DefaultManagedThreadFactory" can be customized
|
||||
* through the {@link #setJndiName "jndiName"} bean property.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.0
|
||||
@@ -50,7 +53,7 @@ public class DefaultManagedAwareThreadFactory extends CustomizableThreadFactory
|
||||
|
||||
private String jndiName = "java:comp/DefaultManagedThreadFactory";
|
||||
|
||||
private ThreadFactory threadFactory = this;
|
||||
private ThreadFactory threadFactory;
|
||||
|
||||
|
||||
/**
|
||||
@@ -98,12 +101,10 @@ public class DefaultManagedAwareThreadFactory extends CustomizableThreadFactory
|
||||
}
|
||||
catch (NamingException ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Failed to find [java:comp/DefaultManagedThreadFactory] in JNDI", ex);
|
||||
}
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Could not find default managed thread factory in JNDI - " +
|
||||
"proceeding with default local thread factory");
|
||||
logger.debug("Failed to retrieve [" + this.jndiName + "] from JNDI", ex);
|
||||
}
|
||||
logger.info("Could not find default managed thread factory in JNDI - " +
|
||||
"proceeding with default local thread factory");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,7 +112,12 @@ public class DefaultManagedAwareThreadFactory extends CustomizableThreadFactory
|
||||
|
||||
@Override
|
||||
public Thread newThread(Runnable runnable) {
|
||||
return this.threadFactory.newThread(runnable);
|
||||
if (this.threadFactory != null) {
|
||||
return this.threadFactory.newThread(runnable);
|
||||
}
|
||||
else {
|
||||
return super.newThread(runnable);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+79
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -20,6 +20,7 @@ import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -39,6 +40,7 @@ import static org.junit.Assert.*;
|
||||
* Test for {@link Conditional} beans.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
@SuppressWarnings("resource")
|
||||
public class ConfigurationClassWithConditionTests {
|
||||
@@ -117,6 +119,29 @@ public class ConfigurationClassWithConditionTests {
|
||||
ctx.refresh();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void conditionOnOverriddenMethodHonored() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigWithBeanSkipped.class);
|
||||
assertEquals(0, context.getBeansOfType(ExampleBean.class).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noConditionOnOverriddenMethodHonored() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigWithBeanReactivated.class);
|
||||
Map<String, ExampleBean> beans = context.getBeansOfType(ExampleBean.class);
|
||||
assertEquals(1, beans.size());
|
||||
assertEquals("baz", beans.keySet().iterator().next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configWithAlternativeBeans() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigWithAlternativeBeans.class);
|
||||
Map<String, ExampleBean> beans = context.getBeansOfType(ExampleBean.class);
|
||||
assertEquals(1, beans.size());
|
||||
assertEquals("baz", beans.keySet().iterator().next());
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class BeanOneConfiguration {
|
||||
@Bean
|
||||
@@ -197,12 +222,21 @@ public class ConfigurationClassWithConditionTests {
|
||||
}
|
||||
|
||||
static class NeverCondition implements Condition {
|
||||
|
||||
@Override
|
||||
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static class AlwaysCondition implements Condition {
|
||||
|
||||
@Override
|
||||
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
@Never
|
||||
static class NonConfigurationClass {
|
||||
@@ -261,4 +295,48 @@ public class ConfigurationClassWithConditionTests {
|
||||
static class ExampleBean {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class ConfigWithBeanActive {
|
||||
|
||||
@Bean
|
||||
public ExampleBean baz() {
|
||||
return new ExampleBean();
|
||||
}
|
||||
}
|
||||
|
||||
static class ConfigWithBeanSkipped extends ConfigWithBeanActive {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
@Conditional(NeverCondition.class)
|
||||
public ExampleBean baz() {
|
||||
return new ExampleBean();
|
||||
}
|
||||
}
|
||||
|
||||
static class ConfigWithBeanReactivated extends ConfigWithBeanSkipped {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
public ExampleBean baz() {
|
||||
return new ExampleBean();
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class ConfigWithAlternativeBeans {
|
||||
|
||||
@Bean(name = "baz")
|
||||
@Conditional(AlwaysCondition.class)
|
||||
public ExampleBean baz1() {
|
||||
return new ExampleBean();
|
||||
}
|
||||
|
||||
@Bean(name = "baz")
|
||||
@Conditional(NeverCondition.class)
|
||||
public ExampleBean baz2() {
|
||||
return new ExampleBean();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<bean id="foo" class="java.lang.String">
|
||||
<constructor-arg value="hello"/>
|
||||
<qualifier value="foo" />
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
||||
+20
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 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,6 +28,7 @@ import java.util.Properties;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -48,6 +49,7 @@ import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.format.Formatter;
|
||||
import org.springframework.format.Printer;
|
||||
import org.springframework.format.annotation.NumberFormat;
|
||||
import org.springframework.format.datetime.joda.DateTimeParser;
|
||||
import org.springframework.format.datetime.joda.JodaDateTimeFormatAnnotationFormatterFactory;
|
||||
import org.springframework.format.datetime.joda.ReadablePartialPrinter;
|
||||
@@ -58,6 +60,8 @@ import static org.junit.Assert.*;
|
||||
/**
|
||||
* @author Keith Donald
|
||||
* @author Juergen Hoeller
|
||||
* @author Kazuki Shimizu
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
public class FormattingConversionServiceTests {
|
||||
|
||||
@@ -101,6 +105,7 @@ public class FormattingConversionServiceTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("resource")
|
||||
public void testFormatFieldForValueInjection() {
|
||||
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
|
||||
ac.registerBeanDefinition("valueBean", new RootBeanDefinition(ValueBean.class));
|
||||
@@ -111,6 +116,7 @@ public class FormattingConversionServiceTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("resource")
|
||||
public void testFormatFieldForValueInjectionUsingMetaAnnotations() {
|
||||
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(MetaValueBean.class);
|
||||
@@ -120,12 +126,15 @@ public class FormattingConversionServiceTests {
|
||||
ac.registerBeanDefinition("ppc", new RootBeanDefinition(PropertyPlaceholderConfigurer.class));
|
||||
ac.refresh();
|
||||
System.setProperty("myDate", "10-31-09");
|
||||
System.setProperty("myNumber", "99.99%");
|
||||
try {
|
||||
MetaValueBean valueBean = ac.getBean(MetaValueBean.class);
|
||||
assertEquals(new LocalDate(2009, 10, 31), new LocalDate(valueBean.date));
|
||||
assertEquals(Double.valueOf(0.9999), valueBean.number);
|
||||
}
|
||||
finally {
|
||||
System.clearProperty("myDate");
|
||||
System.clearProperty("myNumber");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,6 +151,7 @@ public class FormattingConversionServiceTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("resource")
|
||||
public void testFormatFieldForAnnotationWithPlaceholders() throws Exception {
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
@@ -157,6 +167,7 @@ public class FormattingConversionServiceTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("resource")
|
||||
public void testFormatFieldForAnnotationWithPlaceholdersAndFactoryBean() throws Exception {
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
@@ -336,13 +347,14 @@ public class FormattingConversionServiceTests {
|
||||
public Date date;
|
||||
}
|
||||
|
||||
|
||||
public static class MetaValueBean {
|
||||
|
||||
@MyDateAnn
|
||||
public Date date;
|
||||
}
|
||||
|
||||
@MyNumberAnn
|
||||
public Double number;
|
||||
}
|
||||
|
||||
@Value("${myDate}")
|
||||
@org.springframework.format.annotation.DateTimeFormat(pattern="MM-d-yy")
|
||||
@@ -350,6 +362,11 @@ public class FormattingConversionServiceTests {
|
||||
public static @interface MyDateAnn {
|
||||
}
|
||||
|
||||
@Value("${myNumber}")
|
||||
@NumberFormat(style = NumberFormat.Style.PERCENT)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public static @interface MyNumberAnn {
|
||||
}
|
||||
|
||||
public static class Model {
|
||||
|
||||
@@ -368,7 +385,6 @@ public class FormattingConversionServiceTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class ModelWithPlaceholders {
|
||||
|
||||
@org.springframework.format.annotation.DateTimeFormat(style="${dateStyle}")
|
||||
@@ -386,13 +402,11 @@ public class FormattingConversionServiceTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@org.springframework.format.annotation.DateTimeFormat(pattern="${datePattern}")
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public static @interface MyDatePattern {
|
||||
}
|
||||
|
||||
|
||||
public static class NullReturningFormatter implements Formatter<Integer> {
|
||||
|
||||
@Override
|
||||
@@ -407,12 +421,10 @@ public class FormattingConversionServiceTests {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public static class MyDate extends Date {
|
||||
}
|
||||
|
||||
|
||||
private static class ModelWithSubclassField {
|
||||
|
||||
@org.springframework.format.annotation.DateTimeFormat(style = "S-")
|
||||
|
||||
+28
-4
@@ -17,6 +17,8 @@
|
||||
package org.springframework.jmx.export;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -643,6 +645,28 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
ObjectNameManager.getInstance(objectName2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIgnoreBeanName() throws MalformedObjectNameException {
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
String firstBeanName = "spring:type=TestBean";
|
||||
factory.registerSingleton(firstBeanName, new TestBean("test"));
|
||||
String secondBeanName = "spring:type=TestBean2";
|
||||
factory.registerSingleton(secondBeanName, new TestBean("test2"));
|
||||
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
exporter.setServer(getServer());
|
||||
exporter.setAssembler(new NamedBeanAutodetectCapableMBeanInfoAssemblerStub(firstBeanName, secondBeanName));
|
||||
exporter.setBeanFactory(factory);
|
||||
exporter.setAutodetectMode(MBeanExporter.AUTODETECT_ALL);
|
||||
exporter.addExcludedBean(secondBeanName);
|
||||
|
||||
start(exporter);
|
||||
assertIsRegistered("Bean not autodetected in (AUTODETECT_ALL) mode",
|
||||
ObjectNameManager.getInstance(firstBeanName));
|
||||
assertIsNotRegistered("Bean should have been excluded",
|
||||
ObjectNameManager.getInstance(secondBeanName));
|
||||
}
|
||||
|
||||
private ConfigurableApplicationContext load(String context) {
|
||||
return new ClassPathXmlApplicationContext(context, getClass());
|
||||
}
|
||||
@@ -763,15 +787,15 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
private static final class NamedBeanAutodetectCapableMBeanInfoAssemblerStub extends
|
||||
SimpleReflectiveMBeanInfoAssembler implements AutodetectCapableMBeanInfoAssembler {
|
||||
|
||||
private String namedBean;
|
||||
private Collection<String> namedBeans;
|
||||
|
||||
public NamedBeanAutodetectCapableMBeanInfoAssemblerStub(String namedBean) {
|
||||
this.namedBean = namedBean;
|
||||
public NamedBeanAutodetectCapableMBeanInfoAssemblerStub(String... namedBeans) {
|
||||
this.namedBeans = Arrays.asList(namedBeans);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean includeBean(Class<?> beanClass, String beanName) {
|
||||
return this.namedBean.equals(beanName);
|
||||
return this.namedBeans.contains(beanName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+64
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -25,15 +25,20 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.support.GenericXmlApplicationContext;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.concurrent.ListenableFuture;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@@ -106,10 +111,32 @@ public class AsyncAnnotationBeanPostProcessorTests {
|
||||
|
||||
@Test
|
||||
public void handleExceptionWithFuture() {
|
||||
ConfigurableApplicationContext context = initContext(
|
||||
new RootBeanDefinition(AsyncAnnotationBeanPostProcessor.class));
|
||||
ConfigurableApplicationContext context =
|
||||
new AnnotationConfigApplicationContext(ConfigWithExceptionHandler.class);
|
||||
ITestBean testBean = context.getBean("target", ITestBean.class);
|
||||
final Future<Object> result = testBean.failWithFuture();
|
||||
|
||||
TestableAsyncUncaughtExceptionHandler exceptionHandler =
|
||||
context.getBean("exceptionHandler", TestableAsyncUncaughtExceptionHandler.class);
|
||||
assertFalse("handler should not have been called yet", exceptionHandler.isCalled());
|
||||
Future<Object> result = testBean.failWithFuture();
|
||||
assertFutureWithException(result, exceptionHandler);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleExceptionWithListenableFuture() {
|
||||
ConfigurableApplicationContext context =
|
||||
new AnnotationConfigApplicationContext(ConfigWithExceptionHandler.class);
|
||||
ITestBean testBean = context.getBean("target", ITestBean.class);
|
||||
|
||||
TestableAsyncUncaughtExceptionHandler exceptionHandler =
|
||||
context.getBean("exceptionHandler", TestableAsyncUncaughtExceptionHandler.class);
|
||||
assertFalse("handler should not have been called yet", exceptionHandler.isCalled());
|
||||
Future<Object> result = testBean.failWithListenableFuture();
|
||||
assertFutureWithException(result, exceptionHandler);
|
||||
}
|
||||
|
||||
private void assertFutureWithException(Future<Object> result,
|
||||
TestableAsyncUncaughtExceptionHandler exceptionHandler) {
|
||||
|
||||
try {
|
||||
result.get();
|
||||
@@ -121,6 +148,7 @@ public class AsyncAnnotationBeanPostProcessorTests {
|
||||
// expected
|
||||
assertEquals("Wrong exception cause", UnsupportedOperationException.class, ex.getCause().getClass());
|
||||
}
|
||||
assertFalse("handler should never be called with Future return type", exceptionHandler.isCalled());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -173,7 +201,7 @@ public class AsyncAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
|
||||
private static interface ITestBean {
|
||||
private interface ITestBean {
|
||||
|
||||
Thread getThread();
|
||||
|
||||
@@ -181,6 +209,8 @@ public class AsyncAnnotationBeanPostProcessorTests {
|
||||
|
||||
Future<Object> failWithFuture();
|
||||
|
||||
ListenableFuture<Object> failWithListenableFuture();
|
||||
|
||||
void failWithVoid();
|
||||
|
||||
void await(long timeout);
|
||||
@@ -206,11 +236,19 @@ public class AsyncAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
@Async
|
||||
@Override
|
||||
public Future<Object> failWithFuture() {
|
||||
throw new UnsupportedOperationException("failWithFuture");
|
||||
}
|
||||
|
||||
@Async
|
||||
@Override
|
||||
public ListenableFuture<Object> failWithListenableFuture() {
|
||||
throw new UnsupportedOperationException("failWithListenableFuture");
|
||||
}
|
||||
|
||||
@Async
|
||||
@Override
|
||||
public void failWithVoid() {
|
||||
throw new UnsupportedOperationException("failWithVoid");
|
||||
}
|
||||
@@ -234,4 +272,25 @@ public class AsyncAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAsync
|
||||
static class ConfigWithExceptionHandler extends AsyncConfigurerSupport {
|
||||
|
||||
@Bean
|
||||
public ITestBean target() {
|
||||
return new TestBean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
|
||||
return exceptionHandler();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TestableAsyncUncaughtExceptionHandler exceptionHandler() {
|
||||
return new TestableAsyncUncaughtExceptionHandler();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -309,6 +309,7 @@ public class MethodParameter {
|
||||
/**
|
||||
* Return the generic type of the method/constructor parameter.
|
||||
* @return the parameter type (never {@code null})
|
||||
* @since 3.0
|
||||
*/
|
||||
public Type getGenericParameterType() {
|
||||
if (this.genericParameterType == null) {
|
||||
@@ -324,6 +325,12 @@ public class MethodParameter {
|
||||
return this.genericParameterType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the nested type of the method/constructor parameter.
|
||||
* @return the parameter type (never {@code null})
|
||||
* @see #getNestingLevel()
|
||||
* @since 3.1
|
||||
*/
|
||||
public Class<?> getNestedParameterType() {
|
||||
if (this.nestingLevel > 1) {
|
||||
Type type = getGenericParameterType();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -122,6 +122,17 @@ public final class ResolvableType implements Serializable {
|
||||
private ResolvableType[] generics;
|
||||
|
||||
|
||||
/**
|
||||
* Private constructor used to create a new {@link ResolvableType} for cache key purposes.
|
||||
*/
|
||||
private ResolvableType(Type type, TypeProvider typeProvider, VariableResolver variableResolver) {
|
||||
this.type = type;
|
||||
this.typeProvider = typeProvider;
|
||||
this.variableResolver = variableResolver;
|
||||
this.componentType = null;
|
||||
this.resolved = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor used to create a new {@link ResolvableType} for resolution purposes.
|
||||
*/
|
||||
@@ -135,17 +146,6 @@ public final class ResolvableType implements Serializable {
|
||||
this.resolved = resolveClass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor used to create a new {@link ResolvableType} for cache key purposes.
|
||||
*/
|
||||
private ResolvableType(Type type, TypeProvider typeProvider, VariableResolver variableResolver) {
|
||||
this.type = type;
|
||||
this.typeProvider = typeProvider;
|
||||
this.variableResolver = variableResolver;
|
||||
this.componentType = null;
|
||||
this.resolved = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the underling Java {@link Type} being managed. With the exception of
|
||||
@@ -156,7 +156,7 @@ public final class ResolvableType implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the underlying Java {@link Class} being managed, if available;
|
||||
* Return the underlying Java {@link Class} being managed, if available;
|
||||
* otherwise {@code null}.
|
||||
*/
|
||||
public Class<?> getRawClass() {
|
||||
@@ -598,7 +598,7 @@ public final class ResolvableType implements Serializable {
|
||||
return EMPTY_TYPES_ARRAY;
|
||||
}
|
||||
if (this.generics == null) {
|
||||
if (this.type instanceof Class<?>) {
|
||||
if (this.type instanceof Class) {
|
||||
Class<?> typeClass = (Class<?>) this.type;
|
||||
this.generics = forTypes(SerializableTypeWrapper.forTypeParameters(typeClass), this.variableResolver);
|
||||
}
|
||||
@@ -691,7 +691,7 @@ public final class ResolvableType implements Serializable {
|
||||
}
|
||||
|
||||
private Class<?> resolveClass() {
|
||||
if (this.type instanceof Class<?> || this.type == null) {
|
||||
if (this.type instanceof Class || this.type == null) {
|
||||
return (Class<?>) this.type;
|
||||
}
|
||||
if (this.type instanceof GenericArrayType) {
|
||||
@@ -762,6 +762,66 @@ public final class ResolvableType implements Serializable {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof ResolvableType)) {
|
||||
return false;
|
||||
}
|
||||
ResolvableType otherType = (ResolvableType) other;
|
||||
return (ObjectUtils.nullSafeEquals(this.type, otherType.type) &&
|
||||
ObjectUtils.nullSafeEquals(getSource(), otherType.getSource()) &&
|
||||
variableResolverSourceEquals(otherType.variableResolver) &&
|
||||
ObjectUtils.nullSafeEquals(this.componentType, otherType.componentType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hashCode = ObjectUtils.nullSafeHashCode(this.type);
|
||||
hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(getSource());
|
||||
hashCode = 31 * hashCode + variableResolverSourceHashCode();
|
||||
hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(this.componentType);
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
private boolean variableResolverSourceEquals(VariableResolver other) {
|
||||
if (this.variableResolver == null) {
|
||||
return (other == null);
|
||||
}
|
||||
if (other == null) {
|
||||
return false;
|
||||
}
|
||||
return ObjectUtils.nullSafeEquals(this.variableResolver.getSource(), other.getSource());
|
||||
}
|
||||
|
||||
private int variableResolverSourceHashCode() {
|
||||
int hashCode = 0;
|
||||
if (this.variableResolver != null) {
|
||||
hashCode = ObjectUtils.nullSafeHashCode(this.variableResolver.getSource());
|
||||
}
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapts this {@link ResolvableType} to a {@link VariableResolver}.
|
||||
*/
|
||||
VariableResolver asVariableResolver() {
|
||||
if (this == NONE) {
|
||||
return null;
|
||||
}
|
||||
return new DefaultVariableResolver();
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom serialization support for {@link #NONE}.
|
||||
*/
|
||||
private Object readResolve() throws ObjectStreamException {
|
||||
return (this.type == null ? NONE : this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a String representation of this type in its fully resolved form
|
||||
* (including any generic parameters).
|
||||
@@ -791,76 +851,13 @@ public final class ResolvableType implements Serializable {
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof ResolvableType)) {
|
||||
return false;
|
||||
}
|
||||
ResolvableType other = (ResolvableType) obj;
|
||||
return (ObjectUtils.nullSafeEquals(this.type, other.type) &&
|
||||
ObjectUtils.nullSafeEquals(getSource(), other.getSource()) &&
|
||||
variableResolverSourceEquals(other.variableResolver) &&
|
||||
ObjectUtils.nullSafeEquals(this.componentType, other.componentType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hashCode = ObjectUtils.nullSafeHashCode(this.type);
|
||||
hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(getSource());
|
||||
hashCode = 31 * hashCode + variableResolverSourceHashCode();
|
||||
hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(this.componentType);
|
||||
return hashCode;
|
||||
}
|
||||
// Factory methods
|
||||
|
||||
/**
|
||||
* Custom serialization support for {@link #NONE}.
|
||||
*/
|
||||
private Object readResolve() throws ObjectStreamException {
|
||||
return (this.type == null ? NONE : this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapts this {@link ResolvableType} to a {@link VariableResolver}.
|
||||
*/
|
||||
VariableResolver asVariableResolver() {
|
||||
if (this == NONE) {
|
||||
return null;
|
||||
}
|
||||
return new DefaultVariableResolver();
|
||||
}
|
||||
|
||||
private boolean variableResolverSourceEquals(VariableResolver other) {
|
||||
if (this.variableResolver == null) {
|
||||
return (other == null);
|
||||
}
|
||||
if (other == null) {
|
||||
return false;
|
||||
}
|
||||
return ObjectUtils.nullSafeEquals(this.variableResolver.getSource(), other.getSource());
|
||||
}
|
||||
|
||||
private int variableResolverSourceHashCode() {
|
||||
int hashCode = 0;
|
||||
if (this.variableResolver != null) {
|
||||
hashCode = ObjectUtils.nullSafeHashCode(this.variableResolver.getSource());
|
||||
}
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
private static ResolvableType[] forTypes(Type[] types, VariableResolver owner) {
|
||||
ResolvableType[] result = new ResolvableType[types.length];
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
result[i] = forType(types[i], owner);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@link ResolvableType} for the specified {@link Class}. For example
|
||||
* {@code ResolvableType.forClass(MyArrayList.class)}.
|
||||
* Return a {@link ResolvableType} for the specified {@link Class},
|
||||
* using the full generic type information for assignability checks.
|
||||
* For example: {@code ResolvableType.forClass(MyArrayList.class)}.
|
||||
* @param sourceClass the source class (must not be {@code null}
|
||||
* @return a {@link ResolvableType} for the specified class
|
||||
* @see #forClass(Class, Class)
|
||||
@@ -872,9 +869,9 @@ public final class ResolvableType implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@link ResolvableType} for the specified {@link Class} with a given
|
||||
* implementation. For example
|
||||
* {@code ResolvableType.forClass(List.class, MyArrayList.class)}.
|
||||
* Return a {@link ResolvableType} for the specified {@link Class}
|
||||
* with a given implementation.
|
||||
* For example: {@code ResolvableType.forClass(List.class, MyArrayList.class)}.
|
||||
* @param sourceClass the source class (must not be {@code null}
|
||||
* @param implementationClass the implementation class
|
||||
* @return a {@link ResolvableType} for the specified class backed by the given
|
||||
@@ -888,6 +885,38 @@ public final class ResolvableType implements Serializable {
|
||||
return (asType == NONE ? forType(sourceClass) : asType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@link ResolvableType} for the specified {@link Class} with pre-declared generics.
|
||||
* @param sourceClass the source class
|
||||
* @param generics the generics of the class
|
||||
* @return a {@link ResolvableType} for the specific class and generics
|
||||
* @see #forClassWithGenerics(Class, ResolvableType...)
|
||||
*/
|
||||
public static ResolvableType forClassWithGenerics(Class<?> sourceClass, Class<?>... generics) {
|
||||
Assert.notNull(sourceClass, "Source class must not be null");
|
||||
Assert.notNull(generics, "Generics must not be null");
|
||||
ResolvableType[] resolvableGenerics = new ResolvableType[generics.length];
|
||||
for (int i = 0; i < generics.length; i++) {
|
||||
resolvableGenerics[i] = forClass(generics[i]);
|
||||
}
|
||||
return forClassWithGenerics(sourceClass, resolvableGenerics);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@link ResolvableType} for the specified {@link Class} with pre-declared generics.
|
||||
* @param sourceClass the source class
|
||||
* @param generics the generics of the class
|
||||
* @return a {@link ResolvableType} for the specific class and generics
|
||||
* @see #forClassWithGenerics(Class, Class...)
|
||||
*/
|
||||
public static ResolvableType forClassWithGenerics(Class<?> sourceClass, ResolvableType... generics) {
|
||||
Assert.notNull(sourceClass, "Source class must not be null");
|
||||
Assert.notNull(generics, "Generics must not be null");
|
||||
TypeVariable<?>[] variables = sourceClass.getTypeParameters();
|
||||
Assert.isTrue(variables.length == generics.length, "Mismatched number of generics specified");
|
||||
return forType(sourceClass, new TypeVariablesVariableResolver(variables, generics));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@link ResolvableType} for the specified {@link Field}.
|
||||
* @param field the source field
|
||||
@@ -1092,9 +1121,8 @@ public final class ResolvableType implements Serializable {
|
||||
public static ResolvableType forMethodParameter(MethodParameter methodParameter, Type targetType) {
|
||||
Assert.notNull(methodParameter, "MethodParameter must not be null");
|
||||
ResolvableType owner = forType(methodParameter.getContainingClass()).as(methodParameter.getDeclaringClass());
|
||||
return forType(targetType, new MethodParameterTypeProvider(methodParameter),
|
||||
owner.asVariableResolver()).getNested(methodParameter.getNestingLevel(),
|
||||
methodParameter.typeIndexesPerLevel);
|
||||
return forType(targetType, new MethodParameterTypeProvider(methodParameter), owner.asVariableResolver()).
|
||||
getNested(methodParameter.getNestingLevel(), methodParameter.typeIndexesPerLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1103,40 +1131,17 @@ public final class ResolvableType implements Serializable {
|
||||
* @return a {@link ResolvableType} as an array of the specified component type
|
||||
*/
|
||||
public static ResolvableType forArrayComponent(ResolvableType componentType) {
|
||||
Assert.notNull(componentType, "ComponentType must not be null");
|
||||
Assert.notNull(componentType, "componentType must not be null");
|
||||
Class<?> arrayClass = Array.newInstance(componentType.resolve(), 0).getClass();
|
||||
return new ResolvableType(arrayClass, null, null, componentType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@link ResolvableType} for the specified {@link Class} with pre-declared generics.
|
||||
* @param sourceClass the source class
|
||||
* @param generics the generics of the class
|
||||
* @return a {@link ResolvableType} for the specific class and generics
|
||||
* @see #forClassWithGenerics(Class, ResolvableType...)
|
||||
*/
|
||||
public static ResolvableType forClassWithGenerics(Class<?> sourceClass, Class<?>... generics) {
|
||||
Assert.notNull(sourceClass, "Source class must not be null");
|
||||
Assert.notNull(generics, "Generics must not be null");
|
||||
ResolvableType[] resolvableGenerics = new ResolvableType[generics.length];
|
||||
for (int i = 0; i < generics.length; i++) {
|
||||
resolvableGenerics[i] = forClass(generics[i]);
|
||||
private static ResolvableType[] forTypes(Type[] types, VariableResolver owner) {
|
||||
ResolvableType[] result = new ResolvableType[types.length];
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
result[i] = forType(types[i], owner);
|
||||
}
|
||||
return forClassWithGenerics(sourceClass, resolvableGenerics);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@link ResolvableType} for the specified {@link Class} with pre-declared generics.
|
||||
* @param sourceClass the source class
|
||||
* @param generics the generics of the class
|
||||
* @return a {@link ResolvableType} for the specific class and generics
|
||||
* @see #forClassWithGenerics(Class, Class...)
|
||||
*/
|
||||
public static ResolvableType forClassWithGenerics(Class<?> sourceClass, ResolvableType... generics) {
|
||||
Assert.notNull(sourceClass, "Source class must not be null");
|
||||
Assert.notNull(generics, "Generics must not be null");
|
||||
TypeVariable<?>[] typeVariables = sourceClass.getTypeParameters();
|
||||
return forType(sourceClass, new TypeVariablesVariableResolver(typeVariables, generics));
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1198,7 +1203,7 @@ public final class ResolvableType implements Serializable {
|
||||
|
||||
// For simple Class references, build the wrapper right away -
|
||||
// no expensive resolution necessary, so not worth caching...
|
||||
if (type instanceof Class<?>) {
|
||||
if (type instanceof Class) {
|
||||
return new ResolvableType(type, typeProvider, variableResolver, null);
|
||||
}
|
||||
|
||||
@@ -1250,20 +1255,19 @@ public final class ResolvableType implements Serializable {
|
||||
@SuppressWarnings("serial")
|
||||
private static class TypeVariablesVariableResolver implements VariableResolver {
|
||||
|
||||
private final TypeVariable<?>[] typeVariables;
|
||||
private final TypeVariable<?>[] variables;
|
||||
|
||||
private final ResolvableType[] generics;
|
||||
|
||||
public TypeVariablesVariableResolver(TypeVariable<?>[] typeVariables, ResolvableType[] generics) {
|
||||
Assert.isTrue(typeVariables.length == generics.length, "Mismatched number of generics specified");
|
||||
this.typeVariables = typeVariables;
|
||||
public TypeVariablesVariableResolver(TypeVariable<?>[] variables, ResolvableType[] generics) {
|
||||
this.variables = variables;
|
||||
this.generics = generics;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResolvableType resolveVariable(TypeVariable<?> variable) {
|
||||
for (int i = 0; i < this.typeVariables.length; i++) {
|
||||
if (SerializableTypeWrapper.unwrap(this.typeVariables[i]).equals(
|
||||
for (int i = 0; i < this.variables.length; i++) {
|
||||
if (SerializableTypeWrapper.unwrap(this.variables[i]).equals(
|
||||
SerializableTypeWrapper.unwrap(variable))) {
|
||||
return this.generics[i];
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.ConcurrentReferenceHashMap;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* General utility methods for working with annotations, handling bridge methods
|
||||
@@ -654,6 +655,9 @@ public abstract class AnnotationUtils {
|
||||
* @see #getValue(Annotation)
|
||||
*/
|
||||
public static Object getValue(Annotation annotation, String attributeName) {
|
||||
if (annotation == null || !StringUtils.hasLength(attributeName)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
Method method = annotation.annotationType().getDeclaredMethod(attributeName);
|
||||
ReflectionUtils.makeAccessible(method);
|
||||
@@ -683,6 +687,9 @@ public abstract class AnnotationUtils {
|
||||
* @see #getDefaultValue(Class, String)
|
||||
*/
|
||||
public static Object getDefaultValue(Annotation annotation, String attributeName) {
|
||||
if (annotation == null) {
|
||||
return null;
|
||||
}
|
||||
return getDefaultValue(annotation.annotationType(), attributeName);
|
||||
}
|
||||
|
||||
@@ -706,6 +713,9 @@ public abstract class AnnotationUtils {
|
||||
* @see #getDefaultValue(Annotation, String)
|
||||
*/
|
||||
public static Object getDefaultValue(Class<? extends Annotation> annotationType, String attributeName) {
|
||||
if (annotationType == null || !StringUtils.hasLength(attributeName)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return annotationType.getDeclaredMethod(attributeName).getDefaultValue();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2015 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,7 +24,6 @@ package org.springframework.core.convert.converter;
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @since 3.0
|
||||
* @see ConditionalConverter
|
||||
* @param <S> The source type
|
||||
* @param <T> The target type
|
||||
*/
|
||||
@@ -32,8 +31,8 @@ public interface Converter<S, T> {
|
||||
|
||||
/**
|
||||
* Convert the source of type S to target type T.
|
||||
* @param source the source object to convert, which must be an instance of S
|
||||
* @return the converted object, which must be an instance of T
|
||||
* @param source the source object to convert, which must be an instance of S (never {@code null})
|
||||
* @return the converted object, which must be an instance of T (potentially {@code null})
|
||||
* @throws IllegalArgumentException if the source could not be converted to the desired target type
|
||||
*/
|
||||
T convert(S source);
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2015 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,8 +24,8 @@ package org.springframework.core.convert.converter;
|
||||
* @author Keith Donald
|
||||
* @since 3.0
|
||||
* @see ConditionalConverter
|
||||
* @param <S> The source type converters created by this factory can convert from
|
||||
* @param <R> The target range (or base) type converters created by this factory can convert to;
|
||||
* @param <S> the source type converters created by this factory can convert from
|
||||
* @param <R> the target range (or base) type converters created by this factory can convert to;
|
||||
* for example {@link Number} for a set of number subtypes.
|
||||
*/
|
||||
public interface ConverterFactory<S, R> {
|
||||
|
||||
+8
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2015 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,9 +29,9 @@ import org.springframework.util.comparator.ComparableComparator;
|
||||
* {@code Comparator}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 3.2
|
||||
* @param <S> the source type
|
||||
* @param <T> the target type
|
||||
* @since 3.2
|
||||
*/
|
||||
public class ConvertingComparator<S, T> implements Comparator<S> {
|
||||
|
||||
@@ -42,7 +42,6 @@ public class ConvertingComparator<S, T> implements Comparator<S> {
|
||||
|
||||
/**
|
||||
* Create a new {@link ConvertingComparator} instance.
|
||||
*
|
||||
* @param converter the converter
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -52,7 +51,6 @@ public class ConvertingComparator<S, T> implements Comparator<S> {
|
||||
|
||||
/**
|
||||
* Create a new {@link ConvertingComparator} instance.
|
||||
*
|
||||
* @param comparator the underlying comparator used to compare the converted values
|
||||
* @param converter the converter
|
||||
*/
|
||||
@@ -65,15 +63,14 @@ public class ConvertingComparator<S, T> implements Comparator<S> {
|
||||
|
||||
/**
|
||||
* Create a new {@link ComparableComparator} instance.
|
||||
*
|
||||
* @param comparator the underlying comparator
|
||||
* @param conversionService the conversion service
|
||||
* @param targetType the target type
|
||||
*/
|
||||
public ConvertingComparator(Comparator<T> comparator,
|
||||
ConversionService conversionService, Class<? extends T> targetType) {
|
||||
this(comparator, new ConversionServiceConverter<S, T>(
|
||||
conversionService, targetType));
|
||||
public ConvertingComparator(
|
||||
Comparator<T> comparator, ConversionService conversionService, Class<? extends T> targetType) {
|
||||
|
||||
this(comparator, new ConversionServiceConverter<S, T>(conversionService, targetType));
|
||||
}
|
||||
|
||||
|
||||
@@ -87,14 +84,11 @@ public class ConvertingComparator<S, T> implements Comparator<S> {
|
||||
/**
|
||||
* Create a new {@link ConvertingComparator} that compares {@link java.util.Map.Entry
|
||||
* map * entries} based on their {@link java.util.Map.Entry#getKey() keys}.
|
||||
*
|
||||
* @param comparator the underlying comparator used to compare keys
|
||||
* @return a new {@link ConvertingComparator} instance
|
||||
*/
|
||||
public static <K, V> ConvertingComparator<Map.Entry<K, V>, K> mapEntryKeys(
|
||||
Comparator<K> comparator) {
|
||||
public static <K, V> ConvertingComparator<Map.Entry<K, V>, K> mapEntryKeys(Comparator<K> comparator) {
|
||||
return new ConvertingComparator<Map.Entry<K,V>, K>(comparator, new Converter<Map.Entry<K, V>, K>() {
|
||||
|
||||
@Override
|
||||
public K convert(Map.Entry<K, V> source) {
|
||||
return source.getKey();
|
||||
@@ -105,14 +99,11 @@ public class ConvertingComparator<S, T> implements Comparator<S> {
|
||||
/**
|
||||
* Create a new {@link ConvertingComparator} that compares {@link java.util.Map.Entry
|
||||
* map entries} based on their {@link java.util.Map.Entry#getValue() values}.
|
||||
*
|
||||
* @param comparator the underlying comparator used to compare values
|
||||
* @return a new {@link ConvertingComparator} instance
|
||||
*/
|
||||
public static <K, V> ConvertingComparator<Map.Entry<K, V>, V> mapEntryValues(
|
||||
Comparator<V> comparator) {
|
||||
public static <K, V> ConvertingComparator<Map.Entry<K, V>, V> mapEntryValues(Comparator<V> comparator) {
|
||||
return new ConvertingComparator<Map.Entry<K,V>, V>(comparator, new Converter<Map.Entry<K, V>, V>() {
|
||||
|
||||
@Override
|
||||
public V convert(Map.Entry<K, V> source) {
|
||||
return source.getValue();
|
||||
|
||||
+13
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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,9 +27,9 @@ import org.springframework.util.Assert;
|
||||
* <p>This is the most flexible of the Converter SPI interfaces, but also the most complex.
|
||||
* It is flexible in that a GenericConverter may support converting between multiple source/target
|
||||
* type pairs (see {@link #getConvertibleTypes()}. In addition, GenericConverter implementations
|
||||
* have access to source/target {@link TypeDescriptor field context} during the type conversion process.
|
||||
* This allows for resolving source and target field metadata such as annotations and generics
|
||||
* information, which can be used influence the conversion logic.
|
||||
* have access to source/target {@link TypeDescriptor field context} during the type conversion
|
||||
* process. This allows for resolving source and target field metadata such as annotations and
|
||||
* generics information, which can be used influence the conversion logic.
|
||||
*
|
||||
* <p>This interface should generally not be used when the simpler {@link Converter} or
|
||||
* {@link ConverterFactory} interfaces are sufficient.
|
||||
@@ -49,9 +49,8 @@ public interface GenericConverter {
|
||||
/**
|
||||
* Return the source and target types which this converter can convert between. Each
|
||||
* entry is a convertible source-to-target type pair.
|
||||
* <p>
|
||||
* For {@link ConditionalConverter conditional} converters this method may return
|
||||
* {@code null} to indicate all source-to-target pairs should be considered. *
|
||||
* <p>For {@link ConditionalConverter conditional} converters this method may return
|
||||
* {@code null} to indicate all source-to-target pairs should be considered.
|
||||
*/
|
||||
Set<ConvertiblePair> getConvertibleTypes();
|
||||
|
||||
@@ -95,25 +94,25 @@ public interface GenericConverter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null || obj.getClass() != ConvertiblePair.class) {
|
||||
if (other == null || other.getClass() != ConvertiblePair.class) {
|
||||
return false;
|
||||
}
|
||||
ConvertiblePair other = (ConvertiblePair) obj;
|
||||
return this.sourceType.equals(other.sourceType) && this.targetType.equals(other.targetType);
|
||||
ConvertiblePair otherPair = (ConvertiblePair) other;
|
||||
return (this.sourceType.equals(otherPair.sourceType) && this.targetType.equals(otherPair.targetType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.sourceType.hashCode() * 31 + this.targetType.hashCode();
|
||||
return (this.sourceType.hashCode() * 31 + this.targetType.hashCode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.sourceType.getName() + " -> " + this.targetType.getName();
|
||||
return (this.sourceType.getName() + " -> " + this.targetType.getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+42
-39
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -92,7 +92,7 @@ public class GenericConversionService implements ConfigurableConversionService {
|
||||
new ConcurrentHashMap<ConverterCacheKey, GenericConverter>(64);
|
||||
|
||||
|
||||
// implementing ConverterRegistry
|
||||
// ConverterRegistry implementation
|
||||
|
||||
@Override
|
||||
public void addConverter(Converter<?, ?> converter) {
|
||||
@@ -104,7 +104,8 @@ public class GenericConversionService implements ConfigurableConversionService {
|
||||
|
||||
@Override
|
||||
public void addConverter(Class<?> sourceType, Class<?> targetType, Converter<?, ?> converter) {
|
||||
addConverter(new ConverterAdapter(converter, ResolvableType.forClass(sourceType), ResolvableType.forClass(targetType)));
|
||||
addConverter(new ConverterAdapter(
|
||||
converter, ResolvableType.forClass(sourceType), ResolvableType.forClass(targetType)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -116,7 +117,7 @@ public class GenericConversionService implements ConfigurableConversionService {
|
||||
@Override
|
||||
public void addConverterFactory(ConverterFactory<?, ?> converterFactory) {
|
||||
ResolvableType[] typeInfo = getRequiredTypeInfo(converterFactory, ConverterFactory.class);
|
||||
Assert.notNull("Unable to the determine sourceType <S> and targetRangeType R which your " +
|
||||
Assert.notNull(typeInfo, "Unable to the determine source type <S> and target range type R which your " +
|
||||
"ConverterFactory<S, R> converts between; declare these generic types.");
|
||||
addConverter(new ConverterFactoryAdapter(converterFactory,
|
||||
new ConvertiblePair(typeInfo[0].resolve(), typeInfo[1].resolve())));
|
||||
@@ -128,7 +129,8 @@ public class GenericConversionService implements ConfigurableConversionService {
|
||||
invalidateCache();
|
||||
}
|
||||
|
||||
// implementing ConversionService
|
||||
|
||||
// ConversionService implementation
|
||||
|
||||
@Override
|
||||
public boolean canConvert(Class<?> sourceType, Class<?> targetType) {
|
||||
@@ -148,17 +150,18 @@ public class GenericConversionService implements ConfigurableConversionService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if conversion between the sourceType and targetType can be bypassed.
|
||||
* More precisely this method will return true if objects of sourceType can be
|
||||
* Return whether conversion between the sourceType and targetType can be bypassed.
|
||||
* <p>More precisely, this method will return true if objects of sourceType can be
|
||||
* converted to the targetType by returning the source object unchanged.
|
||||
* @param sourceType context about the source type to convert from (may be null if source is null)
|
||||
* @param sourceType context about the source type to convert from
|
||||
* (may be {@code null} if source is {@code null})
|
||||
* @param targetType context about the target type to convert to (required)
|
||||
* @return true if conversion can be bypassed
|
||||
* @throws IllegalArgumentException if targetType is null
|
||||
* @return {@code true} if conversion can be bypassed; {@code false} otherwise
|
||||
* @throws IllegalArgumentException if targetType is {@code null}
|
||||
* @since 3.2
|
||||
*/
|
||||
public boolean canBypassConvert(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
Assert.notNull(targetType, "The targetType to convert to cannot be null");
|
||||
Assert.notNull(targetType, "targetType to convert to cannot be null");
|
||||
if (sourceType == null) {
|
||||
return true;
|
||||
}
|
||||
@@ -169,19 +172,19 @@ public class GenericConversionService implements ConfigurableConversionService {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T convert(Object source, Class<T> targetType) {
|
||||
Assert.notNull(targetType,"The targetType to convert to cannot be null");
|
||||
Assert.notNull(targetType, "targetType to convert to cannot be null");
|
||||
return (T) convert(source, TypeDescriptor.forObject(source), TypeDescriptor.valueOf(targetType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
Assert.notNull(targetType,"The targetType to convert to cannot be null");
|
||||
Assert.notNull(targetType, "targetType to convert to cannot be null");
|
||||
if (sourceType == null) {
|
||||
Assert.isTrue(source == null, "The source must be [null] if sourceType == [null]");
|
||||
return handleResult(sourceType, targetType, convertNullSource(sourceType, targetType));
|
||||
Assert.isTrue(source == null, "source must be [null] if sourceType == [null]");
|
||||
return handleResult(null, targetType, convertNullSource(null, targetType));
|
||||
}
|
||||
if (source != null && !sourceType.getObjectType().isInstance(source)) {
|
||||
throw new IllegalArgumentException("The source to convert from must be an instance of " +
|
||||
throw new IllegalArgumentException("source to convert from must be an instance of " +
|
||||
sourceType + "; instead it was a " + source.getClass().getName());
|
||||
}
|
||||
GenericConverter converter = getConverter(sourceType, targetType);
|
||||
@@ -202,8 +205,8 @@ public class GenericConversionService implements ConfigurableConversionService {
|
||||
* @param targetType the target type
|
||||
* @return the converted value
|
||||
* @throws ConversionException if a conversion exception occurred
|
||||
* @throws IllegalArgumentException if targetType is null,
|
||||
* or sourceType is null but source is not null
|
||||
* @throws IllegalArgumentException if targetType is {@code null},
|
||||
* or sourceType is {@code null} but source is not {@code null}
|
||||
*/
|
||||
public Object convert(Object source, TypeDescriptor targetType) {
|
||||
return convert(source, TypeDescriptor.forObject(source), targetType);
|
||||
@@ -218,11 +221,11 @@ public class GenericConversionService implements ConfigurableConversionService {
|
||||
// Protected template methods
|
||||
|
||||
/**
|
||||
* Template method to convert a null source.
|
||||
* <p>Default implementation returns {@code null} or the Java 8
|
||||
* Template method to convert a {@code null} source.
|
||||
* <p>The default implementation returns {@code null} or the Java 8
|
||||
* {@link java.util.Optional#empty()} instance if the target type is
|
||||
* {@code java.uti.Optional}.
|
||||
* Subclasses may override to return custom null objects for specific target types.
|
||||
* {@code java.util.Optional}. Subclasses may override this to return
|
||||
* custom {@code null} objects for specific target types.
|
||||
* @param sourceType the sourceType to convert from
|
||||
* @param targetType the targetType to convert to
|
||||
* @return the converted null object
|
||||
@@ -239,11 +242,10 @@ public class GenericConversionService implements ConfigurableConversionService {
|
||||
* First queries this ConversionService's converter cache.
|
||||
* On a cache miss, then performs an exhaustive search for a matching converter.
|
||||
* If no converter matches, returns the default converter.
|
||||
* Subclasses may override.
|
||||
* @param sourceType the source type to convert from
|
||||
* @param targetType the target type to convert to
|
||||
* @return the generic converter that will perform the conversion, or {@code null} if
|
||||
* no suitable converter was found
|
||||
* @return the generic converter that will perform the conversion,
|
||||
* or {@code null} if no suitable converter was found
|
||||
* @see #getDefaultConverter(TypeDescriptor, TypeDescriptor)
|
||||
*/
|
||||
protected GenericConverter getConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
@@ -269,9 +271,8 @@ public class GenericConversionService implements ConfigurableConversionService {
|
||||
|
||||
/**
|
||||
* Return the default converter if no converter is found for the given sourceType/targetType pair.
|
||||
* Returns a NO_OP Converter if the sourceType is assignable to the targetType.
|
||||
* <p>Returns a NO_OP Converter if the sourceType is assignable to the targetType.
|
||||
* Returns {@code null} otherwise, indicating no suitable converter could be found.
|
||||
* Subclasses may override.
|
||||
* @param sourceType the source type to convert from
|
||||
* @param targetType the target type to convert to
|
||||
* @return the default generic converter that will perform the conversion
|
||||
@@ -280,7 +281,8 @@ public class GenericConversionService implements ConfigurableConversionService {
|
||||
return (sourceType.isAssignableTo(targetType) ? NO_OP_CONVERTER : null);
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
||||
// Internal helpers
|
||||
|
||||
private ResolvableType[] getRequiredTypeInfo(Object converter, Class<?> genericIfc) {
|
||||
ResolvableType resolvableType = ResolvableType.forClass(converter.getClass()).as(genericIfc);
|
||||
@@ -303,7 +305,7 @@ public class GenericConversionService implements ConfigurableConversionService {
|
||||
private Object handleConverterNotFound(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (source == null) {
|
||||
assertNotPrimitiveTargetType(sourceType, targetType);
|
||||
return source;
|
||||
return null;
|
||||
}
|
||||
if (sourceType.isAssignableTo(targetType) && targetType.getObjectType().isInstance(source)) {
|
||||
return source;
|
||||
@@ -375,7 +377,7 @@ public class GenericConversionService implements ConfigurableConversionService {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.typeInfo + " : " + this.converter;
|
||||
return (this.typeInfo + " : " + this.converter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -425,7 +427,7 @@ public class GenericConversionService implements ConfigurableConversionService {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.typeInfo + " : " + this.converterFactory;
|
||||
return (this.typeInfo + " : " + this.converterFactory);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -453,20 +455,20 @@ public class GenericConversionService implements ConfigurableConversionService {
|
||||
return false;
|
||||
}
|
||||
ConverterCacheKey otherKey = (ConverterCacheKey) other;
|
||||
return ObjectUtils.nullSafeEquals(this.sourceType, otherKey.sourceType) &&
|
||||
ObjectUtils.nullSafeEquals(this.targetType, otherKey.targetType);
|
||||
return (ObjectUtils.nullSafeEquals(this.sourceType, otherKey.sourceType) &&
|
||||
ObjectUtils.nullSafeEquals(this.targetType, otherKey.targetType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(this.sourceType) * 29 +
|
||||
ObjectUtils.nullSafeHashCode(this.targetType);
|
||||
return (ObjectUtils.nullSafeHashCode(this.sourceType) * 29 +
|
||||
ObjectUtils.nullSafeHashCode(this.targetType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ConverterCacheKey [sourceType = " + this.sourceType +
|
||||
", targetType = " + this.targetType + "]";
|
||||
return ("ConverterCacheKey [sourceType = " + this.sourceType +
|
||||
", targetType = " + this.targetType + "]");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -544,9 +546,9 @@ public class GenericConversionService implements ConfigurableConversionService {
|
||||
return converter;
|
||||
}
|
||||
}
|
||||
// Check ConditionalGenericConverter that match all types
|
||||
// Check ConditionalConverters for a dynamic match
|
||||
for (GenericConverter globalConverter : this.globalConverters) {
|
||||
if (((ConditionalConverter)globalConverter).matches(sourceType, targetType)) {
|
||||
if (((ConditionalConverter) globalConverter).matches(sourceType, targetType)) {
|
||||
return globalConverter;
|
||||
}
|
||||
}
|
||||
@@ -563,6 +565,7 @@ public class GenericConversionService implements ConfigurableConversionService {
|
||||
Set<Class<?>> visited = new HashSet<Class<?>>(20);
|
||||
addToClassHierarchy(0, ClassUtils.resolvePrimitiveIfNecessary(type), false, hierarchy, visited);
|
||||
boolean array = type.isArray();
|
||||
|
||||
int i = 0;
|
||||
while (i < hierarchy.size()) {
|
||||
Class<?> candidate = hierarchy.get(i);
|
||||
|
||||
+7
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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,6 +31,7 @@ import org.springframework.lang.UsesJava8;
|
||||
* of Optional when known.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.1
|
||||
*/
|
||||
@UsesJava8
|
||||
@@ -64,12 +65,15 @@ final class ObjectToOptionalConverter implements ConditionalGenericConverter {
|
||||
if (source == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
if (targetType.getResolvableType() == null) {
|
||||
else if (source instanceof Optional) {
|
||||
return source;
|
||||
}
|
||||
else if (targetType.getResolvableType() == null) {
|
||||
return Optional.of(source);
|
||||
}
|
||||
else {
|
||||
Object target = this.conversionService.convert(source, sourceType, new GenericTypeDescriptor(targetType));
|
||||
return Optional.of(target);
|
||||
return Optional.ofNullable(target);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+47
-39
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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,69 +27,73 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Holder that combines a {@link org.springframework.core.io.Resource}
|
||||
* with a specific encoding to be used for reading from the resource.
|
||||
* Holder that combines a {@link Resource} descriptor with a specific encoding
|
||||
* or {@code Charset} to be used for reading from the resource.
|
||||
*
|
||||
* <p>Used as argument for operations that support to read content with
|
||||
* a specific encoding (usually through a {@code java.io.Reader}).
|
||||
* <p>Used as an argument for operations that support reading content with
|
||||
* a specific encoding, typically via a {@code java.io.Reader}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @since 1.2.6
|
||||
* @see java.io.Reader
|
||||
* @see java.nio.charset.Charset
|
||||
*/
|
||||
public class EncodedResource {
|
||||
|
||||
private final Resource resource;
|
||||
|
||||
private String encoding;
|
||||
private final String encoding;
|
||||
|
||||
private Charset charset;
|
||||
private final Charset charset;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new EncodedResource for the given Resource,
|
||||
* not specifying a specific encoding.
|
||||
* @param resource the Resource to hold
|
||||
* Create a new {@code EncodedResource} for the given {@code Resource},
|
||||
* not specifying an explicit encoding or {@code Charset}.
|
||||
* @param resource the {@code Resource} to hold; never {@code null}
|
||||
*/
|
||||
public EncodedResource(Resource resource) {
|
||||
Assert.notNull(resource, "Resource must not be null");
|
||||
this.resource = resource;
|
||||
this(resource, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new EncodedResource for the given Resource,
|
||||
* using the specified encoding.
|
||||
* @param resource the Resource to hold
|
||||
* Create a new {@code EncodedResource} for the given {@code Resource},
|
||||
* using the specified {@code encoding}.
|
||||
* @param resource the {@code Resource} to hold; never {@code null}
|
||||
* @param encoding the encoding to use for reading from the resource
|
||||
*/
|
||||
public EncodedResource(Resource resource, String encoding) {
|
||||
this(resource, encoding, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code EncodedResource} for the given {@code Resource},
|
||||
* using the specified {@code Charset}.
|
||||
* @param resource the {@code Resource} to hold; never {@code null}
|
||||
* @param charset the {@code Charset} to use for reading from the resource
|
||||
*/
|
||||
public EncodedResource(Resource resource, Charset charset) {
|
||||
this(resource, null, charset);
|
||||
}
|
||||
|
||||
private EncodedResource(Resource resource, String encoding, Charset charset) {
|
||||
super();
|
||||
Assert.notNull(resource, "Resource must not be null");
|
||||
this.resource = resource;
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new EncodedResource for the given Resource,
|
||||
* using the specified encoding.
|
||||
* @param resource the Resource to hold
|
||||
* @param charset the charset to use for reading from the resource
|
||||
*/
|
||||
public EncodedResource(Resource resource, Charset charset) {
|
||||
Assert.notNull(resource, "Resource must not be null");
|
||||
this.resource = resource;
|
||||
this.charset = charset;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the Resource held.
|
||||
* Return the {@code Resource} held by this {@code EncodedResource}.
|
||||
*/
|
||||
public final Resource getResource() {
|
||||
return this.resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the encoding to use for reading from the resource,
|
||||
* Return the encoding to use for reading from the {@linkplain #getResource() resource},
|
||||
* or {@code null} if none specified.
|
||||
*/
|
||||
public final String getEncoding() {
|
||||
@@ -97,17 +101,17 @@ public class EncodedResource {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the charset to use for reading from the resource,
|
||||
* Return the {@code Charset} to use for reading from the {@linkplain #getResource() resource},
|
||||
* or {@code null} if none specified.
|
||||
*/
|
||||
public final Charset getCharset() {
|
||||
return this.charset;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine whether a {@link Reader} is required as opposed to an {@link InputStream},
|
||||
* i.e. whether an encoding or a charset has been specified.
|
||||
* i.e. whether an {@linkplain #getEncoding() encoding} or a {@link #getCharset() Charset}
|
||||
* has been specified.
|
||||
* @see #getReader()
|
||||
* @see #getInputStream()
|
||||
*/
|
||||
@@ -116,10 +120,12 @@ public class EncodedResource {
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a {@code java.io.Reader} for the specified resource,
|
||||
* using the specified encoding (if any).
|
||||
* Open a {@code java.io.Reader} for the specified resource, using the specified
|
||||
* {@link #getCharset() Charset} or {@linkplain #getEncoding() encoding}
|
||||
* (if any).
|
||||
* @throws IOException if opening the Reader failed
|
||||
* @see #requiresReader()
|
||||
* @see #getInputStream()
|
||||
*/
|
||||
public Reader getReader() throws IOException {
|
||||
if (this.charset != null) {
|
||||
@@ -134,10 +140,11 @@ public class EncodedResource {
|
||||
}
|
||||
|
||||
/**
|
||||
* Open an {@code java.io.InputStream} for the specified resource,
|
||||
* typically assuming that there is no specific encoding to use.
|
||||
* Open a {@code java.io.InputStream} for the specified resource, ignoring any
|
||||
* specified {@link #getCharset() Charset} or {@linkplain #getEncoding() encoding}.
|
||||
* @throws IOException if opening the InputStream failed
|
||||
* @see #requiresReader()
|
||||
* @see #getReader()
|
||||
*/
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return this.resource.getInputStream();
|
||||
@@ -150,9 +157,10 @@ public class EncodedResource {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof EncodedResource) {
|
||||
EncodedResource otherRes = (EncodedResource) obj;
|
||||
return (this.resource.equals(otherRes.resource) &&
|
||||
ObjectUtils.nullSafeEquals(this.encoding, otherRes.encoding));
|
||||
EncodedResource that = (EncodedResource) obj;
|
||||
return (this.resource.equals(that.resource) &&
|
||||
ObjectUtils.nullSafeEquals(this.charset, that.charset) &&
|
||||
ObjectUtils.nullSafeEquals(this.encoding, that.encoding));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -22,9 +22,10 @@ import java.util.Random;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* A variation of {@link UUID#randomUUID()} that uses {@link SecureRandom} only for the
|
||||
* initial seed and {@link Random} thereafter. This provides better performance in
|
||||
* exchange for less securely random id's.
|
||||
* An {@link IdGenerator} that uses {@link SecureRandom} for the initial seed and
|
||||
* {@link Random} thereafter, instead of calling {@link UUID#randomUUID()} every
|
||||
* time as {@link org.springframework.util.JdkIdGenerator JdkIdGenerator} does.
|
||||
* This provides a better balance between securely random ids and performance.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Rob Winch
|
||||
@@ -43,8 +44,8 @@ public class AlternativeJdkIdGenerator implements IdGenerator {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public UUID generateId() {
|
||||
|
||||
byte[] randomBytes = new byte[16];
|
||||
this.random.nextBytes(randomBytes);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 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
|
||||
@@ -41,7 +41,7 @@ import java.util.Map;
|
||||
* Assert.notNull(clazz, "The class must not be null");
|
||||
* Assert.isTrue(i > 0, "The value must be greater than zero");</pre>
|
||||
*
|
||||
* Mainly for internal use within the framework; consider Jakarta's Commons Lang
|
||||
* Mainly for internal use within the framework; consider Apache's Commons Lang
|
||||
* >= 2.0 for a more comprehensive suite of assertion utilities.
|
||||
*
|
||||
* @author Keith Donald
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -335,9 +335,10 @@ public abstract class CollectionUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapt a {@code Map<K, List<V>>} to an {@code MultiValueMap<K,V>}.
|
||||
* @param map the map
|
||||
* Adapt a {@code Map<K, List<V>>} to an {@code MultiValueMap<K, V>}.
|
||||
* @param map the original map
|
||||
* @return the multi-value map
|
||||
* @since 3.1
|
||||
*/
|
||||
public static <K, V> MultiValueMap<K, V> toMultiValueMap(Map<K, List<V>> map) {
|
||||
return new MultiValueMapAdapter<K, V>(map);
|
||||
@@ -348,8 +349,9 @@ public abstract class CollectionUtils {
|
||||
* Return an unmodifiable view of the specified multi-value map.
|
||||
* @param map the map for which an unmodifiable view is to be returned.
|
||||
* @return an unmodifiable view of the specified multi-value map.
|
||||
* @since 3.1
|
||||
*/
|
||||
public static <K,V> MultiValueMap<K,V> unmodifiableMultiValueMap(MultiValueMap<? extends K, ? extends V> map) {
|
||||
public static <K, V> MultiValueMap<K, V> unmodifiableMultiValueMap(MultiValueMap<? extends K, ? extends V> map) {
|
||||
Assert.notNull(map, "'map' must not be null");
|
||||
Map<K, List<V>> result = new LinkedHashMap<K, List<V>>(map.size());
|
||||
for (Map.Entry<? extends K, ? extends List<? extends V>> entry : map.entrySet()) {
|
||||
@@ -366,7 +368,7 @@ public abstract class CollectionUtils {
|
||||
*/
|
||||
private static class EnumerationIterator<E> implements Iterator<E> {
|
||||
|
||||
private Enumeration<E> enumeration;
|
||||
private final Enumeration<E> enumeration;
|
||||
|
||||
public EnumerationIterator(Enumeration<E> enumeration) {
|
||||
this.enumeration = enumeration;
|
||||
@@ -476,8 +478,8 @@ public abstract class CollectionUtils {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll(Map<? extends K, ? extends List<V>> m) {
|
||||
this.map.putAll(m);
|
||||
public void putAll(Map<? extends K, ? extends List<V>> map) {
|
||||
this.map.putAll(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -51,10 +51,10 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
* <p>If not explicitly specified, this implementation will use
|
||||
* {@linkplain SoftReference soft entry references}.
|
||||
*
|
||||
* @param <K> The key type
|
||||
* @param <V> The value type
|
||||
* @author Phillip Webb
|
||||
* @since 3.2
|
||||
* @param <K> the key type
|
||||
* @param <V> the value type
|
||||
*/
|
||||
public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V> {
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2002-2015 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.util;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* An {@link IdGenerator} that calls {@link java.util.UUID#randomUUID()}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.1.5
|
||||
*/
|
||||
public class JdkIdGenerator implements IdGenerator {
|
||||
|
||||
@Override
|
||||
public UUID generateId() {
|
||||
return UUID.randomUUID();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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,7 +27,7 @@ import java.util.Set;
|
||||
|
||||
/**
|
||||
* Miscellaneous utility methods for number conversion and parsing.
|
||||
* Mainly for internal use within the framework; consider Jakarta's
|
||||
* Mainly for internal use within the framework; consider Apache's
|
||||
* Commons Lang for a more comprehensive suite of string utilities.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -51,7 +51,7 @@ public abstract class ReflectionUtils {
|
||||
private static final String CGLIB_RENAMED_METHOD_PREFIX = "CGLIB$";
|
||||
|
||||
/**
|
||||
* Cache for {@link Class#getDeclaredMethods()}, allowing for fast resolution.
|
||||
* Cache for {@link Class#getDeclaredMethods()}, allowing for fast iteration.
|
||||
*/
|
||||
private static final Map<Class<?>, Method[]> declaredMethodsCache =
|
||||
new ConcurrentReferenceHashMap<Class<?>, Method[]>(256);
|
||||
@@ -440,8 +440,8 @@ public abstract class ReflectionUtils {
|
||||
* @see java.lang.reflect.Method#setAccessible
|
||||
*/
|
||||
public static void makeAccessible(Method method) {
|
||||
if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) &&
|
||||
!method.isAccessible()) {
|
||||
if ((!Modifier.isPublic(method.getModifiers()) ||
|
||||
!Modifier.isPublic(method.getDeclaringClass().getModifiers())) && !method.isAccessible()) {
|
||||
method.setAccessible(true);
|
||||
}
|
||||
}
|
||||
@@ -455,8 +455,8 @@ public abstract class ReflectionUtils {
|
||||
* @see java.lang.reflect.Constructor#setAccessible
|
||||
*/
|
||||
public static void makeAccessible(Constructor<?> ctor) {
|
||||
if ((!Modifier.isPublic(ctor.getModifiers()) || !Modifier.isPublic(ctor.getDeclaringClass().getModifiers())) &&
|
||||
!ctor.isAccessible()) {
|
||||
if ((!Modifier.isPublic(ctor.getModifiers()) ||
|
||||
!Modifier.isPublic(ctor.getDeclaringClass().getModifiers())) && !ctor.isAccessible()) {
|
||||
ctor.setAccessible(true);
|
||||
}
|
||||
}
|
||||
@@ -466,11 +466,11 @@ public abstract class ReflectionUtils {
|
||||
* class and superclasses.
|
||||
* <p>The same named method occurring on subclass and superclass will appear
|
||||
* twice, unless excluded by a {@link MethodFilter}.
|
||||
* @param clazz class to start looking at
|
||||
* @param clazz the class to introspect
|
||||
* @param mc the callback to invoke for each method
|
||||
* @see #doWithMethods(Class, MethodCallback, MethodFilter)
|
||||
*/
|
||||
public static void doWithMethods(Class<?> clazz, MethodCallback mc) throws IllegalArgumentException {
|
||||
public static void doWithMethods(Class<?> clazz, MethodCallback mc) {
|
||||
doWithMethods(clazz, mc, null);
|
||||
}
|
||||
|
||||
@@ -479,13 +479,11 @@ public abstract class ReflectionUtils {
|
||||
* class and superclasses (or given interface and super-interfaces).
|
||||
* <p>The same named method occurring on subclass and superclass will appear
|
||||
* twice, unless excluded by the specified {@link MethodFilter}.
|
||||
* @param clazz class to start looking at
|
||||
* @param clazz the class to introspect
|
||||
* @param mc the callback to invoke for each method
|
||||
* @param mf the filter that determines the methods to apply the callback to
|
||||
*/
|
||||
public static void doWithMethods(Class<?> clazz, MethodCallback mc, MethodFilter mf)
|
||||
throws IllegalArgumentException {
|
||||
|
||||
public static void doWithMethods(Class<?> clazz, MethodCallback mc, MethodFilter mf) {
|
||||
// Keep backing up the inheritance hierarchy.
|
||||
Method[] methods = getDeclaredMethods(clazz);
|
||||
for (Method method : methods) {
|
||||
@@ -496,7 +494,7 @@ public abstract class ReflectionUtils {
|
||||
mc.doWith(method);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new IllegalStateException("Shouldn't be illegal to access method '" + method.getName() + "': " + ex);
|
||||
throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex);
|
||||
}
|
||||
}
|
||||
if (clazz.getSuperclass() != null) {
|
||||
@@ -510,10 +508,11 @@ public abstract class ReflectionUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all declared methods on the leaf class and all superclasses. Leaf
|
||||
* class methods are included first.
|
||||
* Get all declared methods on the leaf class and all superclasses.
|
||||
* Leaf class methods are included first.
|
||||
* @param leafClass the class to introspect
|
||||
*/
|
||||
public static Method[] getAllDeclaredMethods(Class<?> leafClass) throws IllegalArgumentException {
|
||||
public static Method[] getAllDeclaredMethods(Class<?> leafClass) {
|
||||
final List<Method> methods = new ArrayList<Method>(32);
|
||||
doWithMethods(leafClass, new MethodCallback() {
|
||||
@Override
|
||||
@@ -525,11 +524,12 @@ public abstract class ReflectionUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the unique set of declared methods on the leaf class and all superclasses. Leaf
|
||||
* class methods are included first and while traversing the superclass hierarchy any methods found
|
||||
* with signatures matching a method already included are filtered out.
|
||||
* Get the unique set of declared methods on the leaf class and all superclasses.
|
||||
* Leaf class methods are included first and while traversing the superclass hierarchy
|
||||
* any methods found with signatures matching a method already included are filtered out.
|
||||
* @param leafClass the class to introspect
|
||||
*/
|
||||
public static Method[] getUniqueDeclaredMethods(Class<?> leafClass) throws IllegalArgumentException {
|
||||
public static Method[] getUniqueDeclaredMethods(Class<?> leafClass) {
|
||||
final List<Method> methods = new ArrayList<Method>(32);
|
||||
doWithMethods(leafClass, new MethodCallback() {
|
||||
@Override
|
||||
@@ -562,7 +562,7 @@ public abstract class ReflectionUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method retrieves {@link Class#getDeclaredMethods()} from a local cache
|
||||
* This variant retrieves {@link Class#getDeclaredMethods()} from a local cache
|
||||
* in order to avoid the JVM's SecurityManager check and defensive array copying.
|
||||
*/
|
||||
private static Method[] getDeclaredMethods(Class<?> clazz) {
|
||||
@@ -580,7 +580,7 @@ public abstract class ReflectionUtils {
|
||||
* @param clazz the target class to analyze
|
||||
* @param fc the callback to invoke for each field
|
||||
*/
|
||||
public static void doWithFields(Class<?> clazz, FieldCallback fc) throws IllegalArgumentException {
|
||||
public static void doWithFields(Class<?> clazz, FieldCallback fc) {
|
||||
doWithFields(clazz, fc, null);
|
||||
}
|
||||
|
||||
@@ -591,15 +591,12 @@ public abstract class ReflectionUtils {
|
||||
* @param fc the callback to invoke for each field
|
||||
* @param ff the filter that determines the fields to apply the callback to
|
||||
*/
|
||||
public static void doWithFields(Class<?> clazz, FieldCallback fc, FieldFilter ff)
|
||||
throws IllegalArgumentException {
|
||||
|
||||
public static void doWithFields(Class<?> clazz, FieldCallback fc, FieldFilter ff) {
|
||||
// Keep backing up the inheritance hierarchy.
|
||||
Class<?> targetClass = clazz;
|
||||
do {
|
||||
Field[] fields = targetClass.getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
// Skip static and final fields.
|
||||
if (ff != null && !ff.matches(field)) {
|
||||
continue;
|
||||
}
|
||||
@@ -607,7 +604,7 @@ public abstract class ReflectionUtils {
|
||||
fc.doWith(field);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new IllegalStateException("Shouldn't be illegal to access field '" + field.getName() + "': " + ex);
|
||||
throw new IllegalStateException("Not allowed to access field '" + field.getName() + "': " + ex);
|
||||
}
|
||||
}
|
||||
targetClass = targetClass.getSuperclass();
|
||||
@@ -619,9 +616,8 @@ public abstract class ReflectionUtils {
|
||||
* Given the source object and the destination, which must be the same class
|
||||
* or a subclass, copy all fields, including inherited fields. Designed to
|
||||
* work on objects with public no-arg constructors.
|
||||
* @throws IllegalArgumentException if the arguments are incompatible
|
||||
*/
|
||||
public static void shallowCopyFieldState(final Object src, final Object dest) throws IllegalArgumentException {
|
||||
public static void shallowCopyFieldState(final Object src, final Object dest) {
|
||||
if (src == null) {
|
||||
throw new IllegalArgumentException("Source for field copy cannot be null");
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -38,7 +38,7 @@ public class ResizableByteArrayOutputStream extends ByteArrayOutputStream {
|
||||
|
||||
/**
|
||||
* Create a new <code>ResizableByteArrayOutputStream</code>
|
||||
* with the default initial capacity of 128 bytes.
|
||||
* with the default initial capacity of 256 bytes.
|
||||
*/
|
||||
public ResizableByteArrayOutputStream() {
|
||||
super(DEFAULT_INITIAL_CAPACITY);
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2002-2015 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.util;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* A simple {@link IdGenerator} that starts at 1 and increments by 1 with each call.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.1.5
|
||||
*/
|
||||
public class SimpleIdGenerator implements IdGenerator {
|
||||
|
||||
private final AtomicLong mostSigBits = new AtomicLong(0);
|
||||
|
||||
private final AtomicLong leastSigBits = new AtomicLong(0);
|
||||
|
||||
|
||||
@Override
|
||||
public UUID generateId() {
|
||||
long leastSigBits = this.leastSigBits.incrementAndGet();
|
||||
if (leastSigBits == 0) {
|
||||
this.mostSigBits.incrementAndGet();
|
||||
}
|
||||
return new UUID(this.mostSigBits.get(), leastSigBits);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,7 +35,7 @@ import java.util.TreeSet;
|
||||
* Miscellaneous {@link String} utility methods.
|
||||
*
|
||||
* <p>Mainly for internal use within the framework; consider
|
||||
* <a href="http://jakarta.apache.org/commons/lang/">Jakarta's Commons Lang</a>
|
||||
* <a href="http://jakarta.apache.org/commons/lang/">Apache's Commons Lang</a>
|
||||
* for a more comprehensive suite of String utilities.
|
||||
*
|
||||
* <p>This class delivers some simple functionality that should really
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -32,8 +32,8 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 3.2
|
||||
* @param <T> the type of objects being compared
|
||||
* @see CompoundComparator
|
||||
* @param <T> the type of objects being compared
|
||||
*/
|
||||
public class InstanceComparator<T> implements Comparator<T> {
|
||||
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -25,10 +25,10 @@ import java.util.concurrent.ExecutionException;
|
||||
* and {@link ListenableFutureCallback#onSuccess(Object)} call {@link #adapt(Object)}
|
||||
* on the adaptee's result.
|
||||
*
|
||||
* @param <T> the type of this {@code Future}
|
||||
* @param <S> the type of the adaptee's {@code Future}
|
||||
* @author Arjen Poutsma
|
||||
* @since 4.0
|
||||
* @param <T> the type of this {@code Future}
|
||||
* @param <S> the type of the adaptee's {@code Future}
|
||||
*/
|
||||
public abstract class ListenableFutureAdapter<T, S> extends FutureAdapter<T, S> implements ListenableFuture<T> {
|
||||
|
||||
|
||||
+8
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,6 +35,7 @@ public class ByteBufferConverterTests {
|
||||
|
||||
private GenericConversionService conversionService;
|
||||
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.conversionService = new GenericConversionService();
|
||||
@@ -43,6 +44,7 @@ public class ByteBufferConverterTests {
|
||||
this.conversionService.addConverter(new OtherTypeToByteArrayConverter());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void byteArrayToByteBuffer() throws Exception {
|
||||
byte[] bytes = new byte[] { 1, 2, 3 };
|
||||
@@ -78,6 +80,7 @@ public class ByteBufferConverterTests {
|
||||
assertThat(bytes, equalTo(convert.array()));
|
||||
}
|
||||
|
||||
|
||||
private static class OtherType {
|
||||
|
||||
private byte[] bytes;
|
||||
@@ -88,8 +91,8 @@ public class ByteBufferConverterTests {
|
||||
|
||||
}
|
||||
|
||||
private static class ByteArrayToOtherTypeConverter implements
|
||||
Converter<byte[], OtherType> {
|
||||
|
||||
private static class ByteArrayToOtherTypeConverter implements Converter<byte[], OtherType> {
|
||||
|
||||
@Override
|
||||
public OtherType convert(byte[] source) {
|
||||
@@ -97,8 +100,8 @@ public class ByteBufferConverterTests {
|
||||
}
|
||||
}
|
||||
|
||||
private static class OtherTypeToByteArrayConverter implements
|
||||
Converter<OtherType, byte[]> {
|
||||
|
||||
private static class OtherTypeToByteArrayConverter implements Converter<OtherType, byte[]> {
|
||||
|
||||
@Override
|
||||
public byte[] convert(OtherType source) {
|
||||
|
||||
+37
-30
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -69,7 +69,7 @@ public class DefaultConversionTests {
|
||||
assertEquals(null, conversionService.convert("", Character.class));
|
||||
}
|
||||
|
||||
@Test(expected=ConversionFailedException.class)
|
||||
@Test(expected = ConversionFailedException.class)
|
||||
public void testStringToCharacterInvalidString() {
|
||||
conversionService.convert("invalid", Character.class);
|
||||
}
|
||||
@@ -106,7 +106,7 @@ public class DefaultConversionTests {
|
||||
assertEquals(null, conversionService.convert("", Boolean.class));
|
||||
}
|
||||
|
||||
@Test(expected=ConversionFailedException.class)
|
||||
@Test(expected = ConversionFailedException.class)
|
||||
public void testStringToBooleanInvalidString() {
|
||||
conversionService.convert("invalid", Boolean.class);
|
||||
}
|
||||
@@ -265,36 +265,11 @@ public class DefaultConversionTests {
|
||||
assertEquals(Long.valueOf(1), conversionService.convert(Integer.valueOf(1), Long.class));
|
||||
}
|
||||
|
||||
@Test(expected=ConversionFailedException.class)
|
||||
@Test(expected = ConversionFailedException.class)
|
||||
public void testNumberToNumberNotSupportedNumber() {
|
||||
conversionService.convert(Integer.valueOf(1), CustomNumber.class);
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public static class CustomNumber extends Number {
|
||||
|
||||
@Override
|
||||
public double doubleValue() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float floatValue() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int intValue() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long longValue() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNumberToCharacter() {
|
||||
assertEquals(Character.valueOf('A'), conversionService.convert(Integer.valueOf(65), Character.class));
|
||||
@@ -798,7 +773,7 @@ public class DefaultConversionTests {
|
||||
TypeDescriptor descriptor = new TypeDescriptor(parameter);
|
||||
Object actual = conversionService.convert("1,2,3", TypeDescriptor.valueOf(String.class), descriptor);
|
||||
assertEquals(Optional.class, actual.getClass());
|
||||
assertEquals(Arrays.asList(1,2,3), ((Optional<List<Integer>>) actual).get());
|
||||
assertEquals(Arrays.asList(1, 2, 3), ((Optional<List<Integer>>) actual).get());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -807,6 +782,38 @@ public class DefaultConversionTests {
|
||||
assertSame(Optional.empty(), conversionService.convert(null, Optional.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertExistingOptional() {
|
||||
assertSame(Optional.empty(), conversionService.convert(Optional.empty(), TypeDescriptor.valueOf(Object.class),
|
||||
TypeDescriptor.valueOf(Optional.class)));
|
||||
assertSame(Optional.empty(), conversionService.convert(Optional.empty(), Optional.class));
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public static class CustomNumber extends Number {
|
||||
|
||||
@Override
|
||||
public double doubleValue() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float floatValue() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int intValue() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long longValue() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class TestEntity {
|
||||
|
||||
|
||||
+12
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -113,17 +113,17 @@ public class GenericConversionServiceTests {
|
||||
assertEquals(null, conversionService.convert(null, Integer.class));
|
||||
}
|
||||
|
||||
@Test(expected=ConversionFailedException.class)
|
||||
@Test(expected = ConversionFailedException.class)
|
||||
public void convertNullSourcePrimitiveTarget() {
|
||||
assertEquals(null, conversionService.convert(null, int.class));
|
||||
}
|
||||
|
||||
@Test(expected=ConversionFailedException.class)
|
||||
@Test(expected = ConversionFailedException.class)
|
||||
public void convertNullSourcePrimitiveTargetTypeDescriptor() {
|
||||
conversionService.convert(null, TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(int.class));
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void convertNotNullSourceNullSourceTypeDescriptor() {
|
||||
conversionService.convert("3", null, TypeDescriptor.valueOf(int.class));
|
||||
}
|
||||
@@ -177,18 +177,18 @@ public class GenericConversionServiceTests {
|
||||
assertNull(conversionService.convert(null, Integer.class));
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void convertNullTargetClass() {
|
||||
assertNull(conversionService.convert("3", (Class<?>) null));
|
||||
assertNull(conversionService.convert("3", TypeDescriptor.valueOf(String.class), null));
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void convertNullTypeDescriptor() {
|
||||
assertNull(conversionService.convert("3", TypeDescriptor.valueOf(String.class), null));
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void convertWrongSourceTypeDescriptor() {
|
||||
conversionService.convert("3", TypeDescriptor.valueOf(Integer.class), TypeDescriptor.valueOf(Long.class));
|
||||
}
|
||||
@@ -218,8 +218,7 @@ public class GenericConversionServiceTests {
|
||||
}
|
||||
|
||||
// SPR-8718
|
||||
|
||||
@Test(expected=ConverterNotFoundException.class)
|
||||
@Test(expected = ConverterNotFoundException.class)
|
||||
public void convertSuperTarget() {
|
||||
conversionService.addConverter(new ColorConverter());
|
||||
conversionService.convert("#000000", SystemColor.class);
|
||||
@@ -295,7 +294,7 @@ public class GenericConversionServiceTests {
|
||||
@Test
|
||||
public void testInterfaceToString() {
|
||||
GenericConversionService conversionService = new GenericConversionService();
|
||||
conversionService.addConverter(new MyBaseInterfaceConverter());
|
||||
conversionService.addConverter(new MyBaseInterfaceToStringConverter());
|
||||
conversionService.addConverter(new ObjectToStringConverter());
|
||||
Object converted = conversionService.convert(new MyInterfaceImplementer(), String.class);
|
||||
assertEquals("RESULT", converted);
|
||||
@@ -304,7 +303,7 @@ public class GenericConversionServiceTests {
|
||||
@Test
|
||||
public void testInterfaceArrayToStringArray() {
|
||||
GenericConversionService conversionService = new GenericConversionService();
|
||||
conversionService.addConverter(new MyBaseInterfaceConverter());
|
||||
conversionService.addConverter(new MyBaseInterfaceToStringConverter());
|
||||
conversionService.addConverter(new ArrayToArrayConverter(conversionService));
|
||||
String[] converted = conversionService.convert(new MyInterface[] {new MyInterfaceImplementer()}, String[].class);
|
||||
assertEquals("RESULT", converted[0]);
|
||||
@@ -313,7 +312,7 @@ public class GenericConversionServiceTests {
|
||||
@Test
|
||||
public void testObjectArrayToStringArray() {
|
||||
GenericConversionService conversionService = new GenericConversionService();
|
||||
conversionService.addConverter(new MyBaseInterfaceConverter());
|
||||
conversionService.addConverter(new MyBaseInterfaceToStringConverter());
|
||||
conversionService.addConverter(new ArrayToArrayConverter(conversionService));
|
||||
String[] converted = conversionService.convert(new MyInterfaceImplementer[] {new MyInterfaceImplementer()}, String[].class);
|
||||
assertEquals("RESULT", converted[0]);
|
||||
@@ -813,7 +812,7 @@ public class GenericConversionServiceTests {
|
||||
}
|
||||
|
||||
|
||||
private static class MyBaseInterfaceConverter implements Converter<MyBaseInterface, String> {
|
||||
private static class MyBaseInterfaceToStringConverter implements Converter<MyBaseInterface, String> {
|
||||
|
||||
@Override
|
||||
public String convert(MyBaseInterface source) {
|
||||
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2002-2015 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.core.io.support;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.io.DescriptiveResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link EncodedResource}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 3.2.14
|
||||
*/
|
||||
public class EncodedResourceTests {
|
||||
|
||||
private static final String UTF8 = "UTF-8";
|
||||
private static final String UTF16 = "UTF-16";
|
||||
private static final Charset UTF8_CS = Charset.forName(UTF8);
|
||||
private static final Charset UTF16_CS = Charset.forName(UTF16);
|
||||
|
||||
private final Resource resource = new DescriptiveResource("test");
|
||||
|
||||
|
||||
@Test
|
||||
public void equalsWithNullOtherObject() {
|
||||
assertFalse(new EncodedResource(resource).equals(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equalsWithSameEncoding() {
|
||||
EncodedResource er1 = new EncodedResource(resource, UTF8);
|
||||
EncodedResource er2 = new EncodedResource(resource, UTF8);
|
||||
assertEquals(er1, er2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equalsWithDifferentEncoding() {
|
||||
EncodedResource er1 = new EncodedResource(resource, UTF8);
|
||||
EncodedResource er2 = new EncodedResource(resource, UTF16);
|
||||
assertNotEquals(er1, er2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equalsWithSameCharset() {
|
||||
EncodedResource er1 = new EncodedResource(resource, UTF8_CS);
|
||||
EncodedResource er2 = new EncodedResource(resource, UTF8_CS);
|
||||
assertEquals(er1, er2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equalsWithDifferentCharset() {
|
||||
EncodedResource er1 = new EncodedResource(resource, UTF8_CS);
|
||||
EncodedResource er2 = new EncodedResource(resource, UTF16_CS);
|
||||
assertNotEquals(er1, er2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equalsWithEncodingAndCharset() {
|
||||
EncodedResource er1 = new EncodedResource(resource, UTF8);
|
||||
EncodedResource er2 = new EncodedResource(resource, UTF8_CS);
|
||||
assertNotEquals(er1, er2);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 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,6 @@ import static java.lang.String.*;
|
||||
*/
|
||||
public enum TestGroup {
|
||||
|
||||
|
||||
/**
|
||||
* Tests that take a considerable amount of time to run. Any test lasting longer than
|
||||
* 500ms should be considered a candidate in order to avoid making the overall test
|
||||
@@ -68,6 +67,7 @@ public enum TestGroup {
|
||||
*/
|
||||
CUSTOM_COMPILATION;
|
||||
|
||||
|
||||
/**
|
||||
* Parse the specified comma separated string of groups.
|
||||
* @param value the comma separated string of groups
|
||||
@@ -102,4 +102,5 @@ public enum TestGroup {
|
||||
}
|
||||
return groups;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -66,8 +66,8 @@ public class ReflectionUtilsTests {
|
||||
|
||||
@Test
|
||||
public void setField() {
|
||||
final TestObjectSubclassWithNewField testBean = new TestObjectSubclassWithNewField();
|
||||
final Field field = ReflectionUtils.findField(TestObjectSubclassWithNewField.class, "name", String.class);
|
||||
TestObjectSubclassWithNewField testBean = new TestObjectSubclassWithNewField();
|
||||
Field field = ReflectionUtils.findField(TestObjectSubclassWithNewField.class, "name", String.class);
|
||||
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
|
||||
@@ -79,13 +79,6 @@ public class ReflectionUtilsTests {
|
||||
assertNull(testBean.getName());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void setFieldIllegal() {
|
||||
final TestObjectSubclassWithNewField testBean = new TestObjectSubclassWithNewField();
|
||||
final Field field = ReflectionUtils.findField(TestObjectSubclassWithNewField.class, "name", String.class);
|
||||
ReflectionUtils.setField(field, testBean, "FooBar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invokeMethod() throws Exception {
|
||||
String rob = "Rob Harrop";
|
||||
@@ -94,65 +87,50 @@ public class ReflectionUtilsTests {
|
||||
bean.setName(rob);
|
||||
|
||||
Method getName = TestObject.class.getMethod("getName", (Class[]) null);
|
||||
Method setName = TestObject.class.getMethod("setName", new Class[] { String.class });
|
||||
Method setName = TestObject.class.getMethod("setName", String.class);
|
||||
|
||||
Object name = ReflectionUtils.invokeMethod(getName, bean);
|
||||
assertEquals("Incorrect name returned", rob, name);
|
||||
|
||||
String juergen = "Juergen Hoeller";
|
||||
ReflectionUtils.invokeMethod(setName, bean, new Object[] { juergen });
|
||||
ReflectionUtils.invokeMethod(setName, bean, juergen);
|
||||
assertEquals("Incorrect name set", juergen, bean.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void declaresException() throws Exception {
|
||||
Method remoteExMethod = A.class.getDeclaredMethod("foo", new Class[] { Integer.class });
|
||||
Method remoteExMethod = A.class.getDeclaredMethod("foo", Integer.class);
|
||||
assertTrue(ReflectionUtils.declaresException(remoteExMethod, RemoteException.class));
|
||||
assertTrue(ReflectionUtils.declaresException(remoteExMethod, ConnectException.class));
|
||||
assertFalse(ReflectionUtils.declaresException(remoteExMethod, NoSuchMethodException.class));
|
||||
assertFalse(ReflectionUtils.declaresException(remoteExMethod, Exception.class));
|
||||
|
||||
Method illegalExMethod = B.class.getDeclaredMethod("bar", new Class[] { String.class });
|
||||
Method illegalExMethod = B.class.getDeclaredMethod("bar", String.class);
|
||||
assertTrue(ReflectionUtils.declaresException(illegalExMethod, IllegalArgumentException.class));
|
||||
assertTrue(ReflectionUtils.declaresException(illegalExMethod, NumberFormatException.class));
|
||||
assertFalse(ReflectionUtils.declaresException(illegalExMethod, IllegalStateException.class));
|
||||
assertFalse(ReflectionUtils.declaresException(illegalExMethod, Exception.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void copySrcToDestinationOfIncorrectClass() {
|
||||
TestObject src = new TestObject();
|
||||
String dest = new String();
|
||||
try {
|
||||
ReflectionUtils.shallowCopyFieldState(src, dest);
|
||||
fail();
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// Ok
|
||||
}
|
||||
ReflectionUtils.shallowCopyFieldState(src, dest);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullSrc() {
|
||||
TestObject src = null;
|
||||
String dest = new String();
|
||||
try {
|
||||
ReflectionUtils.shallowCopyFieldState(src, dest);
|
||||
fail();
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// Ok
|
||||
}
|
||||
ReflectionUtils.shallowCopyFieldState(src, dest);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullDest() {
|
||||
TestObject src = new TestObject();
|
||||
String dest = null;
|
||||
try {
|
||||
ReflectionUtils.shallowCopyFieldState(src, dest);
|
||||
fail();
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// Ok
|
||||
}
|
||||
ReflectionUtils.shallowCopyFieldState(src, dest);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+19
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.expression.spel.ast;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
@@ -27,15 +29,20 @@ import org.springframework.expression.spel.SpelMessage;
|
||||
import org.springframework.expression.spel.support.BooleanTypedValue;
|
||||
|
||||
/**
|
||||
* Implements the matches operator. Matches takes two operands. The first is a string and
|
||||
* the second is a java regex. It will return true when getValue() is called if the first
|
||||
* operand matches the regex.
|
||||
* Implements the matches operator. Matches takes two operands:
|
||||
* The first is a String and the second is a Java regex.
|
||||
* It will return {@code true} when {@link #getValue} is called
|
||||
* if the first operand matches the regex.
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
public class OperatorMatches extends Operator {
|
||||
|
||||
private final ConcurrentMap<String, Pattern> patternCache = new ConcurrentHashMap<String, Pattern>();
|
||||
|
||||
|
||||
public OperatorMatches(int pos, SpelNodeImpl... operands) {
|
||||
super("matches", pos, operands);
|
||||
}
|
||||
@@ -66,8 +73,14 @@ public class OperatorMatches extends Operator {
|
||||
}
|
||||
|
||||
try {
|
||||
Pattern pattern = Pattern.compile((String) right);
|
||||
Matcher matcher = pattern.matcher((String) left);
|
||||
String leftString = (String) left;
|
||||
String rightString = (String) right;
|
||||
Pattern pattern = this.patternCache.get(rightString);
|
||||
if (pattern == null) {
|
||||
pattern = Pattern.compile(rightString);
|
||||
this.patternCache.putIfAbsent(rightString, pattern);
|
||||
}
|
||||
Matcher matcher = pattern.matcher(leftString);
|
||||
return BooleanTypedValue.forValue(matcher.matches());
|
||||
}
|
||||
catch (PatternSyntaxException ex) {
|
||||
|
||||
+29
-23
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -40,13 +40,14 @@ import org.springframework.util.MethodInvoker;
|
||||
public class ReflectionHelper {
|
||||
|
||||
/**
|
||||
* Compare argument arrays and return information about whether they match. A supplied
|
||||
* type converter and conversionAllowed flag allow for matches to take into account
|
||||
* that a type may be transformed into a different type by the converter.
|
||||
* @param expectedArgTypes the array of types the method/constructor is expecting
|
||||
* @param suppliedArgTypes the array of types that are being supplied at the point of invocation
|
||||
* Compare argument arrays and return information about whether they match.
|
||||
* A supplied type converter and conversionAllowed flag allow for matches to take
|
||||
* into account that a type may be transformed into a different type by the converter.
|
||||
* @param expectedArgTypes the types the method/constructor is expecting
|
||||
* @param suppliedArgTypes the types that are being supplied at the point of invocation
|
||||
* @param typeConverter a registered type converter
|
||||
* @return a MatchInfo object indicating what kind of match it was or null if it was not a match
|
||||
* @return a MatchInfo object indicating what kind of match it was,
|
||||
* or {@code null} if it was not a match
|
||||
*/
|
||||
static ArgumentsMatchInfo compareArguments(
|
||||
List<TypeDescriptor> expectedArgTypes, List<TypeDescriptor> suppliedArgTypes, TypeConverter typeConverter) {
|
||||
@@ -90,7 +91,7 @@ public class ReflectionHelper {
|
||||
int result = 0;
|
||||
for (int i = 0; i < paramTypes.size(); i++) {
|
||||
TypeDescriptor paramType = paramTypes.get(i);
|
||||
TypeDescriptor argType = argTypes.get(i);
|
||||
TypeDescriptor argType = (i < argTypes.size() ? argTypes.get(i) : null);
|
||||
if (argType == null) {
|
||||
if (paramType.isPrimitive()) {
|
||||
return Integer.MAX_VALUE;
|
||||
@@ -127,13 +128,15 @@ public class ReflectionHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare argument arrays and return information about whether they match. A supplied type converter and
|
||||
* conversionAllowed flag allow for matches to take into account that a type may be transformed into a different
|
||||
* type by the converter. This variant of compareArguments also allows for a varargs match.
|
||||
* @param expectedArgTypes the array of types the method/constructor is expecting
|
||||
* @param suppliedArgTypes the array of types that are being supplied at the point of invocation
|
||||
* Compare argument arrays and return information about whether they match.
|
||||
* A supplied type converter and conversionAllowed flag allow for matches to
|
||||
* take into account that a type may be transformed into a different type by the
|
||||
* converter. This variant of compareArguments also allows for a varargs match.
|
||||
* @param expectedArgTypes the types the method/constructor is expecting
|
||||
* @param suppliedArgTypes the types that are being supplied at the point of invocation
|
||||
* @param typeConverter a registered type converter
|
||||
* @return a MatchInfo object indicating what kind of match it was or null if it was not a match
|
||||
* @return a MatchInfo object indicating what kind of match it was,
|
||||
* or {@code null} if it was not a match
|
||||
*/
|
||||
static ArgumentsMatchInfo compareArgumentsVarargs(
|
||||
List<TypeDescriptor> expectedArgTypes, List<TypeDescriptor> suppliedArgTypes, TypeConverter typeConverter) {
|
||||
@@ -246,12 +249,14 @@ public class ReflectionHelper {
|
||||
* @param converter the type converter to use for attempting conversions
|
||||
* @param arguments the actual arguments that need conversion
|
||||
* @param methodOrCtor the target Method or Constructor
|
||||
* @param varargsPosition the known position of the varargs argument, if any (null if not varargs)
|
||||
* @return true if some kind of conversion occurred on an argument
|
||||
* @param varargsPosition the known position of the varargs argument, if any
|
||||
* ({@code null} if not varargs)
|
||||
* @return {@code true} if some kind of conversion occurred on an argument
|
||||
* @throws EvaluationException if a problem occurs during conversion
|
||||
*/
|
||||
static boolean convertArguments(TypeConverter converter, Object[] arguments, Object methodOrCtor,
|
||||
Integer varargsPosition) throws EvaluationException {
|
||||
|
||||
boolean conversionOccurred = false;
|
||||
if (varargsPosition == null) {
|
||||
for (int i = 0; i < arguments.length; i++) {
|
||||
@@ -320,9 +325,9 @@ public class ReflectionHelper {
|
||||
|
||||
/**
|
||||
* Package up the arguments so that they correctly match what is expected in parameterTypes.
|
||||
* For example, if parameterTypes is (int, String[]) because the second parameter was declared String...
|
||||
* then if arguments is [1,"a","b"] then it must be repackaged as [1,new String[]{"a","b"}] in order to
|
||||
* match the expected parameterTypes.
|
||||
* For example, if parameterTypes is {@code (int, String[])} because the second parameter
|
||||
* was declared {@code String...}, then if arguments is {@code [1,"a","b"]} then it must be
|
||||
* repackaged as {@code [1,new String[]{"a","b"}]} in order to match the expected types.
|
||||
* @param requiredParameterTypes the types of the parameters for the invocation
|
||||
* @param args the arguments to be setup ready for the invocation
|
||||
* @return a repackaged array of arguments where any varargs setup has been done
|
||||
@@ -374,10 +379,11 @@ public class ReflectionHelper {
|
||||
|
||||
|
||||
/**
|
||||
* An instance of ArgumentsMatchInfo describes what kind of match was achieved between two sets of arguments -
|
||||
* the set that a method/constructor is expecting and the set that are being supplied at the point of invocation.
|
||||
* If the kind indicates that conversion is required for some of the arguments then the arguments that require
|
||||
* conversion are listed in the argsRequiringConversion array.
|
||||
* An instance of ArgumentsMatchInfo describes what kind of match was achieved
|
||||
* between two sets of arguments - the set that a method/constructor is expecting
|
||||
* and the set that are being supplied at the point of invocation. If the kind
|
||||
* indicates that conversion is required for some of the arguments then the arguments
|
||||
* that require conversion are listed in the argsRequiringConversion array.
|
||||
*/
|
||||
static class ArgumentsMatchInfo {
|
||||
|
||||
|
||||
+16
-15
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -66,13 +66,14 @@ public class ReflectiveMethodResolver implements MethodResolver {
|
||||
}
|
||||
|
||||
/**
|
||||
* This constructors allows the ReflectiveMethodResolver to be configured such that it will
|
||||
* use a distance computation to check which is the better of two close matches (when there
|
||||
* are multiple matches). Using the distance computation is intended to ensure matches
|
||||
* are more closely representative of what a Java compiler would do when taking into
|
||||
* account boxing/unboxing and whether the method candidates are declared to handle a
|
||||
* supertype of the type (of the argument) being passed in.
|
||||
* @param useDistance true if distance computation should be used when calculating matches
|
||||
* This constructor allows the ReflectiveMethodResolver to be configured such that it
|
||||
* will use a distance computation to check which is the better of two close matches
|
||||
* (when there are multiple matches). Using the distance computation is intended to
|
||||
* ensure matches are more closely representative of what a Java compiler would do
|
||||
* when taking into account boxing/unboxing and whether the method candidates are
|
||||
* declared to handle a supertype of the type (of the argument) being passed in.
|
||||
* @param useDistance {@code true} if distance computation should be used when
|
||||
* calculating matches; {@code false} otherwise
|
||||
*/
|
||||
public ReflectiveMethodResolver(boolean useDistance) {
|
||||
this.useDistance = useDistance;
|
||||
@@ -175,17 +176,17 @@ public class ReflectiveMethodResolver implements MethodResolver {
|
||||
return new ReflectiveMethodExecutor(method);
|
||||
}
|
||||
else if (matchInfo.isCloseMatch()) {
|
||||
if (!this.useDistance) {
|
||||
// Take this as a close match if there isn't one already
|
||||
if (closeMatch == null) {
|
||||
if (this.useDistance) {
|
||||
int matchDistance = ReflectionHelper.getTypeDifferenceWeight(paramDescriptors, argumentTypes);
|
||||
if (closeMatch == null || matchDistance < closeMatchDistance) {
|
||||
// This is a better match...
|
||||
closeMatch = method;
|
||||
closeMatchDistance = matchDistance;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int matchDistance = ReflectionHelper.getTypeDifferenceWeight(paramDescriptors, argumentTypes);
|
||||
if (matchDistance < closeMatchDistance) {
|
||||
// This is a better match...
|
||||
closeMatchDistance = matchDistance;
|
||||
// Take this as a close match if there isn't one already
|
||||
if (closeMatch == null) {
|
||||
closeMatch = method;
|
||||
}
|
||||
}
|
||||
|
||||
+124
-200
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,196 +35,146 @@ import static org.junit.Assert.*;
|
||||
*/
|
||||
public abstract class AbstractExpressionTests {
|
||||
|
||||
private final static boolean DEBUG = false;
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
protected static final boolean SHOULD_BE_WRITABLE = true;
|
||||
|
||||
protected static final boolean SHOULD_NOT_BE_WRITABLE = false;
|
||||
|
||||
protected final static boolean SHOULD_BE_WRITABLE = true;
|
||||
protected final static boolean SHOULD_NOT_BE_WRITABLE = false;
|
||||
|
||||
protected final ExpressionParser parser = new SpelExpressionParser();
|
||||
|
||||
protected final StandardEvaluationContext eContext = TestScenarioCreator.getTestEvaluationContext();
|
||||
|
||||
|
||||
/**
|
||||
* Evaluate an expression and check that the actual result matches the expectedValue and the class of the result
|
||||
* matches the expectedClassOfResult.
|
||||
* @param expression The expression to evaluate
|
||||
* Evaluate an expression and check that the actual result matches the
|
||||
* expectedValue and the class of the result matches the expectedClassOfResult.
|
||||
* @param expression the expression to evaluate
|
||||
* @param expectedValue the expected result for evaluating the expression
|
||||
* @param expectedResultType the expected class of the evaluation result
|
||||
*/
|
||||
protected void evaluate(String expression, Object expectedValue, Class<?> expectedResultType) {
|
||||
try {
|
||||
Expression expr = parser.parseExpression(expression);
|
||||
if (expr == null) {
|
||||
fail("Parser returned null for expression");
|
||||
public void evaluate(String expression, Object expectedValue, Class<?> expectedResultType) {
|
||||
Expression expr = parser.parseExpression(expression);
|
||||
if (expr == null) {
|
||||
fail("Parser returned null for expression");
|
||||
}
|
||||
if (DEBUG) {
|
||||
SpelUtilities.printAbstractSyntaxTree(System.out, expr);
|
||||
}
|
||||
|
||||
Object value = expr.getValue(eContext);
|
||||
|
||||
// Check the return value
|
||||
if (value == null) {
|
||||
if (expectedValue == null) {
|
||||
return; // no point doing other checks
|
||||
}
|
||||
if (DEBUG) {
|
||||
SpelUtilities.printAbstractSyntaxTree(System.out, expr);
|
||||
}
|
||||
// Class<?> expressionType = expr.getValueType();
|
||||
// assertEquals("Type of the expression is not as expected. Should be '" +
|
||||
// expectedResultType + "' but is '"
|
||||
// + expressionType + "'", expectedResultType, expressionType);
|
||||
assertEquals("Expression returned null value, but expected '" + expectedValue + "'", expectedValue, null);
|
||||
}
|
||||
|
||||
Object value = expr.getValue(eContext);
|
||||
Class<?> resultType = value.getClass();
|
||||
assertEquals("Type of the actual result was not as expected. Expected '" + expectedResultType +
|
||||
"' but result was of type '" + resultType + "'", expectedResultType, resultType);
|
||||
|
||||
// Check the return value
|
||||
if (value == null) {
|
||||
if (expectedValue == null) {
|
||||
return; // no point doing other checks
|
||||
}
|
||||
assertEquals("Expression returned null value, but expected '" + expectedValue + "'", expectedValue,
|
||||
null);
|
||||
}
|
||||
|
||||
Class<?> resultType = value.getClass();
|
||||
assertEquals("Type of the actual result was not as expected. Expected '" + expectedResultType
|
||||
+ "' but result was of type '" + resultType + "'", expectedResultType, resultType);
|
||||
// .equals/* isAssignableFrom */(resultType), truers);
|
||||
|
||||
// TODO isAssignableFrom would allow some room for compatibility
|
||||
// in the above expression...
|
||||
|
||||
if (expectedValue instanceof String) {
|
||||
assertEquals("Did not get expected value for expression '" + expression + "'.", expectedValue,
|
||||
if (expectedValue instanceof String) {
|
||||
assertEquals("Did not get expected value for expression '" + expression + "'.", expectedValue,
|
||||
AbstractExpressionTests.stringValueOf(value));
|
||||
}
|
||||
else {
|
||||
assertEquals("Did not get expected value for expression '" + expression + "'.", expectedValue, value);
|
||||
}
|
||||
}
|
||||
catch (EvaluationException ee) {
|
||||
ee.printStackTrace();
|
||||
fail("Unexpected Exception: " + ee.getMessage());
|
||||
}
|
||||
catch (ParseException pe) {
|
||||
pe.printStackTrace();
|
||||
fail("Unexpected Exception: " + pe.getMessage());
|
||||
else {
|
||||
assertEquals("Did not get expected value for expression '" + expression + "'.", expectedValue, value);
|
||||
}
|
||||
}
|
||||
|
||||
protected void evaluateAndAskForReturnType(String expression, Object expectedValue, Class<?> expectedResultType) {
|
||||
try {
|
||||
Expression expr = parser.parseExpression(expression);
|
||||
if (expr == null) {
|
||||
fail("Parser returned null for expression");
|
||||
}
|
||||
if (DEBUG) {
|
||||
SpelUtilities.printAbstractSyntaxTree(System.out, expr);
|
||||
}
|
||||
// Class<?> expressionType = expr.getValueType();
|
||||
// assertEquals("Type of the expression is not as expected. Should be '" +
|
||||
// expectedResultType + "' but is '"
|
||||
// + expressionType + "'", expectedResultType, expressionType);
|
||||
public void evaluateAndAskForReturnType(String expression, Object expectedValue, Class<?> expectedResultType) {
|
||||
Expression expr = parser.parseExpression(expression);
|
||||
if (expr == null) {
|
||||
fail("Parser returned null for expression");
|
||||
}
|
||||
if (DEBUG) {
|
||||
SpelUtilities.printAbstractSyntaxTree(System.out, expr);
|
||||
}
|
||||
|
||||
Object value = expr.getValue(eContext, expectedResultType);
|
||||
if (value == null) {
|
||||
if (expectedValue == null)
|
||||
return; // no point doing other checks
|
||||
assertEquals("Expression returned null value, but expected '" + expectedValue + "'", expectedValue,
|
||||
null);
|
||||
Object value = expr.getValue(eContext, expectedResultType);
|
||||
if (value == null) {
|
||||
if (expectedValue == null) {
|
||||
return; // no point doing other checks
|
||||
}
|
||||
assertEquals("Expression returned null value, but expected '" + expectedValue + "'", expectedValue, null);
|
||||
}
|
||||
|
||||
Class<?> resultType = value.getClass();
|
||||
assertEquals("Type of the actual result was not as expected. Expected '" + expectedResultType
|
||||
+ "' but result was of type '" + resultType + "'", expectedResultType, resultType);
|
||||
// .equals/* isAssignableFrom */(resultType), truers);
|
||||
assertEquals("Did not get expected value for expression '" + expression + "'.", expectedValue, value);
|
||||
// isAssignableFrom would allow some room for compatibility
|
||||
// in the above expression...
|
||||
}
|
||||
catch (EvaluationException ee) {
|
||||
SpelEvaluationException ex = (SpelEvaluationException) ee;
|
||||
ex.printStackTrace();
|
||||
fail("Unexpected EvaluationException: " + ex.getMessage());
|
||||
}
|
||||
catch (ParseException pe) {
|
||||
fail("Unexpected ParseException: " + pe.getMessage());
|
||||
}
|
||||
Class<?> resultType = value.getClass();
|
||||
assertEquals("Type of the actual result was not as expected. Expected '" + expectedResultType +
|
||||
"' but result was of type '" + resultType + "'", expectedResultType, resultType);
|
||||
assertEquals("Did not get expected value for expression '" + expression + "'.", expectedValue, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate an expression and check that the actual result matches the expectedValue and the class of the result
|
||||
* matches the expectedClassOfResult. This method can also check if the expression is writable (for example, it is a
|
||||
* variable or property reference).
|
||||
*
|
||||
* @param expression The expression to evaluate
|
||||
* Evaluate an expression and check that the actual result matches the
|
||||
* expectedValue and the class of the result matches the expectedClassOfResult.
|
||||
* This method can also check if the expression is writable (for example,
|
||||
* it is a variable or property reference).
|
||||
* @param expression the expression to evaluate
|
||||
* @param expectedValue the expected result for evaluating the expression
|
||||
* @param expectedClassOfResult the expected class of the evaluation result
|
||||
* @param shouldBeWritable should the parsed expression be writable?
|
||||
*/
|
||||
protected void evaluate(String expression, Object expectedValue, Class<?> expectedClassOfResult,
|
||||
boolean shouldBeWritable) {
|
||||
try {
|
||||
Expression e = parser.parseExpression(expression);
|
||||
if (e == null) {
|
||||
fail("Parser returned null for expression");
|
||||
public void evaluate(String expression, Object expectedValue, Class<?> expectedClassOfResult, boolean shouldBeWritable) {
|
||||
Expression expr = parser.parseExpression(expression);
|
||||
if (expr == null) {
|
||||
fail("Parser returned null for expression");
|
||||
}
|
||||
if (DEBUG) {
|
||||
SpelUtilities.printAbstractSyntaxTree(System.out, expr);
|
||||
}
|
||||
Object value = expr.getValue(eContext);
|
||||
if (value == null) {
|
||||
if (expectedValue == null) {
|
||||
return; // no point doing other checks
|
||||
}
|
||||
if (DEBUG) {
|
||||
SpelUtilities.printAbstractSyntaxTree(System.out, e);
|
||||
}
|
||||
Object value = e.getValue(eContext);
|
||||
if (value == null) {
|
||||
if (expectedValue == null)
|
||||
return; // no point doing other
|
||||
// checks
|
||||
assertEquals("Expression returned null value, but expected '" + expectedValue + "'", expectedValue,
|
||||
null);
|
||||
}
|
||||
Class<? extends Object> resultType = value.getClass();
|
||||
if (expectedValue instanceof String) {
|
||||
assertEquals("Did not get expected value for expression '" + expression + "'.", expectedValue,
|
||||
assertEquals("Expression returned null value, but expected '" + expectedValue + "'", expectedValue, null);
|
||||
}
|
||||
Class<? extends Object> resultType = value.getClass();
|
||||
if (expectedValue instanceof String) {
|
||||
assertEquals("Did not get expected value for expression '" + expression + "'.", expectedValue,
|
||||
AbstractExpressionTests.stringValueOf(value));
|
||||
}
|
||||
else {
|
||||
assertEquals("Did not get expected value for expression '" + expression + "'.", expectedValue, value);
|
||||
}
|
||||
// assertEquals("Did not get expected value for expression '" + expression +
|
||||
// "'.", expectedValue, stringValueOf(value));
|
||||
assertEquals("Type of the result was not as expected. Expected '" + expectedClassOfResult
|
||||
+ "' but result was of type '" + resultType + "'",
|
||||
expectedClassOfResult.equals/* isAssignableFrom */(resultType), true);
|
||||
// TODO isAssignableFrom would allow some room for compatibility
|
||||
// in the above expression...
|
||||
}
|
||||
else {
|
||||
assertEquals("Did not get expected value for expression '" + expression + "'.", expectedValue, value);
|
||||
}
|
||||
assertEquals("Type of the result was not as expected. Expected '" + expectedClassOfResult +
|
||||
"' but result was of type '" + resultType + "'", expectedClassOfResult.equals(resultType), true);
|
||||
|
||||
boolean isWritable = e.isWritable(eContext);
|
||||
if (isWritable != shouldBeWritable) {
|
||||
if (shouldBeWritable)
|
||||
fail("Expected the expression to be writable but it is not");
|
||||
else
|
||||
fail("Expected the expression to be readonly but it is not");
|
||||
}
|
||||
}
|
||||
catch (EvaluationException ee) {
|
||||
ee.printStackTrace();
|
||||
fail("Unexpected Exception: " + ee.getMessage());
|
||||
}
|
||||
catch (ParseException pe) {
|
||||
pe.printStackTrace();
|
||||
fail("Unexpected Exception: " + pe.getMessage());
|
||||
boolean isWritable = expr.isWritable(eContext);
|
||||
if (isWritable != shouldBeWritable) {
|
||||
if (shouldBeWritable)
|
||||
fail("Expected the expression to be writable but it is not");
|
||||
else
|
||||
fail("Expected the expression to be readonly but it is not");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the specified expression and ensure the expected message comes out. The message may have inserts and
|
||||
* they will be checked if otherProperties is specified. The first entry in otherProperties should always be the
|
||||
* position.
|
||||
* @param expression The expression to evaluate
|
||||
* @param expectedMessage The expected message
|
||||
* @param otherProperties The expected inserts within the message
|
||||
* Evaluate the specified expression and ensure the expected message comes out.
|
||||
* The message may have inserts and they will be checked if otherProperties is specified.
|
||||
* The first entry in otherProperties should always be the position.
|
||||
* @param expression the expression to evaluate
|
||||
* @param expectedMessage the expected message
|
||||
* @param otherProperties the expected inserts within the message
|
||||
*/
|
||||
protected void evaluateAndCheckError(String expression, SpelMessage expectedMessage, Object... otherProperties) {
|
||||
evaluateAndCheckError(expression, null, expectedMessage, otherProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the specified expression and ensure the expected message comes out. The message may have inserts and
|
||||
* they will be checked if otherProperties is specified. The first entry in otherProperties should always be the
|
||||
* position.
|
||||
* @param expression The expression to evaluate
|
||||
* @param expectedReturnType Ask the expression return value to be of this type if possible (null indicates don't
|
||||
* ask for conversion)
|
||||
* @param expectedMessage The expected message
|
||||
* @param otherProperties The expected inserts within the message
|
||||
* Evaluate the specified expression and ensure the expected message comes out.
|
||||
* The message may have inserts and they will be checked if otherProperties is specified.
|
||||
* The first entry in otherProperties should always be the position.
|
||||
* @param expression the expression to evaluate
|
||||
* @param expectedReturnType ask the expression return value to be of this type if possible
|
||||
* ({@code null} indicates don't ask for conversion)
|
||||
* @param expectedMessage the expected message
|
||||
* @param otherProperties the expected inserts within the message
|
||||
*/
|
||||
protected void evaluateAndCheckError(String expression, Class<?> expectedReturnType, SpelMessage expectedMessage,
|
||||
Object... otherProperties) {
|
||||
@@ -234,19 +184,16 @@ public abstract class AbstractExpressionTests {
|
||||
fail("Parser returned null for expression");
|
||||
}
|
||||
if (expectedReturnType != null) {
|
||||
@SuppressWarnings("unused")
|
||||
Object value = expr.getValue(eContext, expectedReturnType);
|
||||
expr.getValue(eContext, expectedReturnType);
|
||||
}
|
||||
else {
|
||||
@SuppressWarnings("unused")
|
||||
Object value = expr.getValue(eContext);
|
||||
expr.getValue(eContext);
|
||||
}
|
||||
fail("Should have failed with message " + expectedMessage);
|
||||
}
|
||||
catch (EvaluationException ee) {
|
||||
SpelEvaluationException ex = (SpelEvaluationException) ee;
|
||||
if (ex.getMessageCode() != expectedMessage) {
|
||||
ex.printStackTrace();
|
||||
assertEquals("Failed to get expected message", expectedMessage, ex.getMessageCode());
|
||||
}
|
||||
if (otherProperties != null && otherProperties.length != 0) {
|
||||
@@ -260,47 +207,39 @@ public abstract class AbstractExpressionTests {
|
||||
inserts = new Object[0];
|
||||
}
|
||||
if (inserts.length < otherProperties.length - 1) {
|
||||
ex.printStackTrace();
|
||||
fail("Cannot check " + (otherProperties.length - 1)
|
||||
+ " properties of the exception, it only has " + inserts.length + " inserts");
|
||||
fail("Cannot check " + (otherProperties.length - 1) +
|
||||
" properties of the exception, it only has " + inserts.length + " inserts");
|
||||
}
|
||||
for (int i = 1; i < otherProperties.length; i++) {
|
||||
if (otherProperties[i] == null) {
|
||||
if (inserts[i - 1] != null) {
|
||||
ex.printStackTrace();
|
||||
fail("Insert does not match, expected 'null' but insert value was '" + inserts[i - 1]
|
||||
+ "'");
|
||||
fail("Insert does not match, expected 'null' but insert value was '" +
|
||||
inserts[i - 1] + "'");
|
||||
}
|
||||
}
|
||||
else if (inserts[i - 1] == null) {
|
||||
if (otherProperties[i] != null) {
|
||||
ex.printStackTrace();
|
||||
fail("Insert does not match, expected '" + otherProperties[i]
|
||||
+ "' but insert value was 'null'");
|
||||
fail("Insert does not match, expected '" + otherProperties[i] +
|
||||
"' but insert value was 'null'");
|
||||
}
|
||||
}
|
||||
else if (!inserts[i - 1].equals(otherProperties[i])) {
|
||||
ex.printStackTrace();
|
||||
fail("Insert does not match, expected '" + otherProperties[i] + "' but insert value was '"
|
||||
+ inserts[i - 1] + "'");
|
||||
fail("Insert does not match, expected '" + otherProperties[i] +
|
||||
"' but insert value was '" + inserts[i - 1] + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ParseException pe) {
|
||||
pe.printStackTrace();
|
||||
fail("Unexpected Exception: " + pe.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the specified expression and ensure the expected message comes out. The message may have inserts and they
|
||||
* will be checked if otherProperties is specified. The first entry in otherProperties should always be the
|
||||
* position.
|
||||
* @param expression The expression to evaluate
|
||||
* @param expectedMessage The expected message
|
||||
* @param otherProperties The expected inserts within the message
|
||||
* Parse the specified expression and ensure the expected message comes out.
|
||||
* The message may have inserts and they will be checked if otherProperties is specified.
|
||||
* The first entry in otherProperties should always be the position.
|
||||
* @param expression the expression to evaluate
|
||||
* @param expectedMessage the expected message
|
||||
* @param otherProperties the expected inserts within the message
|
||||
*/
|
||||
protected void parseAndCheckError(String expression, SpelMessage expectedMessage, Object... otherProperties) {
|
||||
try {
|
||||
@@ -309,21 +248,8 @@ public abstract class AbstractExpressionTests {
|
||||
fail("Parsing should have failed!");
|
||||
}
|
||||
catch (ParseException pe) {
|
||||
// pe.printStackTrace();
|
||||
// Throwable t = pe.getCause();
|
||||
// if (t == null) {
|
||||
// fail("ParseException caught with no defined cause");
|
||||
// }
|
||||
// if (!(t instanceof SpelEvaluationException)) {
|
||||
// t.printStackTrace();
|
||||
// fail("Cause of parse exception is not a SpelException");
|
||||
// }
|
||||
// SpelEvaluationException ex = (SpelEvaluationException) t;
|
||||
// pe.printStackTrace();
|
||||
SpelParseException ex = (SpelParseException) pe;
|
||||
SpelParseException ex = (SpelParseException)pe;
|
||||
if (ex.getMessageCode() != expectedMessage) {
|
||||
// System.out.println(ex.getMessage());
|
||||
ex.printStackTrace();
|
||||
assertEquals("Failed to get expected message", expectedMessage, ex.getMessageCode());
|
||||
}
|
||||
if (otherProperties != null && otherProperties.length != 0) {
|
||||
@@ -337,15 +263,13 @@ public abstract class AbstractExpressionTests {
|
||||
inserts = new Object[0];
|
||||
}
|
||||
if (inserts.length < otherProperties.length - 1) {
|
||||
ex.printStackTrace();
|
||||
fail("Cannot check " + (otherProperties.length - 1)
|
||||
+ " properties of the exception, it only has " + inserts.length + " inserts");
|
||||
fail("Cannot check " + (otherProperties.length - 1) +
|
||||
" properties of the exception, it only has " + inserts.length + " inserts");
|
||||
}
|
||||
for (int i = 1; i < otherProperties.length; i++) {
|
||||
if (!inserts[i - 1].equals(otherProperties[i])) {
|
||||
ex.printStackTrace();
|
||||
fail("Insert does not match, expected '" + otherProperties[i] + "' but insert value was '"
|
||||
+ inserts[i - 1] + "'");
|
||||
fail("Insert does not match, expected '" + otherProperties[i] +
|
||||
"' but insert value was '" + inserts[i - 1] + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -353,13 +277,13 @@ public abstract class AbstractExpressionTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected static String stringValueOf(Object value) {
|
||||
return stringValueOf(value, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a nice string representation of the input object.
|
||||
*
|
||||
* @param value object to be formatted
|
||||
* @return a nice string
|
||||
*/
|
||||
@@ -395,8 +319,8 @@ public abstract class AbstractExpressionTests {
|
||||
sb.append("}");
|
||||
}
|
||||
else {
|
||||
throw new RuntimeException("Please implement support for type " + primitiveType.getName()
|
||||
+ " in ExpressionTestCase.stringValueOf()");
|
||||
throw new RuntimeException("Please implement support for type " + primitiveType.getName() +
|
||||
" in ExpressionTestCase.stringValueOf()");
|
||||
}
|
||||
}
|
||||
else if (value.getClass().getComponentType().isArray()) {
|
||||
|
||||
+100
-112
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -54,17 +54,6 @@ public class MethodInvocationTests extends AbstractExpressionTests {
|
||||
evaluate("getPlaceOfBirth().getCity()", "SmilJan", String.class);
|
||||
}
|
||||
|
||||
// public void testBuiltInProcessors() {
|
||||
// evaluate("new int[]{1,2,3,4}.count()", 4, Integer.class);
|
||||
// evaluate("new int[]{4,3,2,1}.sort()[3]", 4, Integer.class);
|
||||
// evaluate("new int[]{4,3,2,1}.average()", 2, Integer.class);
|
||||
// evaluate("new int[]{4,3,2,1}.max()", 4, Integer.class);
|
||||
// evaluate("new int[]{4,3,2,1}.min()", 1, Integer.class);
|
||||
// evaluate("new int[]{4,3,2,1,2,3}.distinct().count()", 4, Integer.class);
|
||||
// evaluate("{1,2,3,null}.nonnull().count()", 3, Integer.class);
|
||||
// evaluate("new int[]{4,3,2,1,2,3}.distinct().count()", 4, Integer.class);
|
||||
// }
|
||||
|
||||
@Test
|
||||
public void testStringClass() {
|
||||
evaluate("new java.lang.String('hello').charAt(2)", 'l', Character.class);
|
||||
@@ -107,7 +96,7 @@ public class MethodInvocationTests extends AbstractExpressionTests {
|
||||
|
||||
// Normal exit
|
||||
StandardEvaluationContext eContext = TestScenarioCreator.getTestEvaluationContext();
|
||||
eContext.setVariable("bar",3);
|
||||
eContext.setVariable("bar", 3);
|
||||
Object o = expr.getValue(eContext);
|
||||
assertEquals(o, 3);
|
||||
assertEquals(1, parser.parseExpression("counter").getValue(eContext));
|
||||
@@ -115,46 +104,44 @@ public class MethodInvocationTests extends AbstractExpressionTests {
|
||||
// Now the expression has cached that throwException(int) is the right thing to call
|
||||
// Let's change 'bar' to be a PlaceOfBirth which indicates the cached reference is
|
||||
// out of date.
|
||||
eContext.setVariable("bar",new PlaceOfBirth("London"));
|
||||
eContext.setVariable("bar", new PlaceOfBirth("London"));
|
||||
o = expr.getValue(eContext);
|
||||
assertEquals("London", o);
|
||||
// That confirms the logic to mark the cached reference stale and retry is working
|
||||
|
||||
|
||||
// Now let's cause the method to exit via exception and ensure it doesn't cause
|
||||
// a retry.
|
||||
// Now let's cause the method to exit via exception and ensure it doesn't cause a retry.
|
||||
|
||||
// First, switch back to throwException(int)
|
||||
eContext.setVariable("bar",3);
|
||||
eContext.setVariable("bar", 3);
|
||||
o = expr.getValue(eContext);
|
||||
assertEquals(3, o);
|
||||
assertEquals(2, parser.parseExpression("counter").getValue(eContext));
|
||||
|
||||
|
||||
// Now cause it to throw an exception:
|
||||
eContext.setVariable("bar",1);
|
||||
eContext.setVariable("bar", 1);
|
||||
try {
|
||||
o = expr.getValue(eContext);
|
||||
fail();
|
||||
} catch (Exception e) {
|
||||
if (e instanceof SpelEvaluationException) {
|
||||
e.printStackTrace();
|
||||
fail("Should not be a SpelEvaluationException");
|
||||
}
|
||||
catch (Exception ex) {
|
||||
if (ex instanceof SpelEvaluationException) {
|
||||
fail("Should not be a SpelEvaluationException: " + ex);
|
||||
}
|
||||
// normal
|
||||
}
|
||||
// If counter is 4 then the method got called twice!
|
||||
assertEquals(3, parser.parseExpression("counter").getValue(eContext));
|
||||
|
||||
eContext.setVariable("bar",4);
|
||||
eContext.setVariable("bar", 4);
|
||||
try {
|
||||
o = expr.getValue(eContext);
|
||||
fail();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception ex) {
|
||||
// 4 means it will throw a checked exception - this will be wrapped
|
||||
if (!(e instanceof ExpressionInvocationTargetException)) {
|
||||
e.printStackTrace();
|
||||
fail("Should have been wrapped");
|
||||
if (!(ex instanceof ExpressionInvocationTargetException)) {
|
||||
fail("Should have been wrapped: " + ex);
|
||||
}
|
||||
// normal
|
||||
}
|
||||
@@ -176,14 +163,14 @@ public class MethodInvocationTests extends AbstractExpressionTests {
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
Expression expr = parser.parseExpression("throwException(#bar)");
|
||||
|
||||
eContext.setVariable("bar",2);
|
||||
eContext.setVariable("bar", 2);
|
||||
try {
|
||||
expr.getValue(eContext);
|
||||
fail();
|
||||
} catch (Exception e) {
|
||||
if (e instanceof SpelEvaluationException) {
|
||||
e.printStackTrace();
|
||||
fail("Should not be a SpelEvaluationException");
|
||||
}
|
||||
catch (Exception ex) {
|
||||
if (ex instanceof SpelEvaluationException) {
|
||||
fail("Should not be a SpelEvaluationException: " + ex);
|
||||
}
|
||||
// normal
|
||||
}
|
||||
@@ -200,18 +187,16 @@ public class MethodInvocationTests extends AbstractExpressionTests {
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
Expression expr = parser.parseExpression("throwException(#bar)");
|
||||
|
||||
eContext.setVariable("bar",4);
|
||||
eContext.setVariable("bar", 4);
|
||||
try {
|
||||
expr.getValue(eContext);
|
||||
fail();
|
||||
} catch (ExpressionInvocationTargetException e) {
|
||||
Throwable t = e.getCause();
|
||||
assertEquals(
|
||||
"org.springframework.expression.spel.testresources.Inventor$TestException",
|
||||
t.getClass().getName());
|
||||
return;
|
||||
}
|
||||
fail("Should not be a SpelEvaluationException");
|
||||
catch (ExpressionInvocationTargetException ex) {
|
||||
Throwable cause = ex.getCause();
|
||||
assertEquals("org.springframework.expression.spel.testresources.Inventor$TestException",
|
||||
cause.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -224,7 +209,7 @@ public class MethodInvocationTests extends AbstractExpressionTests {
|
||||
|
||||
// Filter will be called but not do anything, so first doit() will be invoked
|
||||
SpelExpression expr = (SpelExpression) parser.parseExpression("doit(1)");
|
||||
String result = expr.getValue(context,String.class);
|
||||
String result = expr.getValue(context, String.class);
|
||||
assertEquals("1", result);
|
||||
assertTrue(filter.filterCalled);
|
||||
|
||||
@@ -232,15 +217,15 @@ public class MethodInvocationTests extends AbstractExpressionTests {
|
||||
filter.removeIfNotAnnotated = true;
|
||||
filter.filterCalled = false;
|
||||
expr = (SpelExpression) parser.parseExpression("doit(1)");
|
||||
result = expr.getValue(context,String.class);
|
||||
result = expr.getValue(context, String.class);
|
||||
assertEquals("double 1.0", result);
|
||||
assertTrue(filter.filterCalled);
|
||||
|
||||
// check not called for other types
|
||||
filter.filterCalled=false;
|
||||
filter.filterCalled = false;
|
||||
context.setRootObject(new String("abc"));
|
||||
expr = (SpelExpression) parser.parseExpression("charAt(0)");
|
||||
result = expr.getValue(context,String.class);
|
||||
result = expr.getValue(context, String.class);
|
||||
assertEquals("a", result);
|
||||
assertFalse(filter.filterCalled);
|
||||
|
||||
@@ -249,64 +234,11 @@ public class MethodInvocationTests extends AbstractExpressionTests {
|
||||
context.registerMethodFilter(TestObject.class,null);//clear filter
|
||||
context.setRootObject(new TestObject());
|
||||
expr = (SpelExpression) parser.parseExpression("doit(1)");
|
||||
result = expr.getValue(context,String.class);
|
||||
result = expr.getValue(context, String.class);
|
||||
assertEquals("1", result);
|
||||
assertFalse(filter.filterCalled);
|
||||
}
|
||||
|
||||
// Simple filter
|
||||
static class LocalFilter implements MethodFilter {
|
||||
|
||||
public boolean removeIfNotAnnotated = false;
|
||||
|
||||
public boolean filterCalled = false;
|
||||
|
||||
private boolean isAnnotated(Method m) {
|
||||
Annotation[] annos = m.getAnnotations();
|
||||
if (annos==null) {
|
||||
return false;
|
||||
}
|
||||
for (Annotation anno: annos) {
|
||||
String s = anno.annotationType().getName();
|
||||
if (s.endsWith("Anno")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Method> filter(List<Method> methods) {
|
||||
filterCalled = true;
|
||||
List<Method> forRemoval = new ArrayList<Method>();
|
||||
for (Method m: methods) {
|
||||
if (removeIfNotAnnotated && !isAnnotated(m)) {
|
||||
forRemoval.add(m);
|
||||
}
|
||||
}
|
||||
for (Method m: forRemoval) {
|
||||
methods.remove(m);
|
||||
}
|
||||
return methods;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface Anno {}
|
||||
|
||||
class TestObject {
|
||||
public int doit(int i) {
|
||||
return i;
|
||||
}
|
||||
|
||||
@Anno
|
||||
public String doit(double d) {
|
||||
return "double "+d;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddingMethodResolvers() {
|
||||
StandardEvaluationContext ctx = new StandardEvaluationContext();
|
||||
@@ -329,17 +261,6 @@ public class MethodInvocationTests extends AbstractExpressionTests {
|
||||
assertEquals(2, ctx.getMethodResolvers().size());
|
||||
}
|
||||
|
||||
static class DummyMethodResolver implements MethodResolver {
|
||||
|
||||
@Override
|
||||
public MethodExecutor resolve(EvaluationContext context, Object targetObject, String name,
|
||||
List<TypeDescriptor> argumentTypes) throws AccessException {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testVarargsInvocation01() {
|
||||
// Calling 'public int aVarargsMethod(String... strings)'
|
||||
@@ -383,8 +304,7 @@ public class MethodInvocationTests extends AbstractExpressionTests {
|
||||
StandardEvaluationContext context = new StandardEvaluationContext(bytes);
|
||||
context.setBeanResolver(new BeanResolver() {
|
||||
@Override
|
||||
public Object resolve(EvaluationContext context, String beanName)
|
||||
throws AccessException {
|
||||
public Object resolve(EvaluationContext context, String beanName) throws AccessException {
|
||||
if ("service".equals(beanName)) {
|
||||
return service;
|
||||
}
|
||||
@@ -396,10 +316,78 @@ public class MethodInvocationTests extends AbstractExpressionTests {
|
||||
assertSame(bytes, outBytes);
|
||||
}
|
||||
|
||||
|
||||
// Simple filter
|
||||
static class LocalFilter implements MethodFilter {
|
||||
|
||||
public boolean removeIfNotAnnotated = false;
|
||||
|
||||
public boolean filterCalled = false;
|
||||
|
||||
private boolean isAnnotated(Method method) {
|
||||
Annotation[] anns = method.getAnnotations();
|
||||
if (anns == null) {
|
||||
return false;
|
||||
}
|
||||
for (Annotation ann : anns) {
|
||||
String name = ann.annotationType().getName();
|
||||
if (name.endsWith("Anno")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Method> filter(List<Method> methods) {
|
||||
filterCalled = true;
|
||||
List<Method> forRemoval = new ArrayList<Method>();
|
||||
for (Method method: methods) {
|
||||
if (removeIfNotAnnotated && !isAnnotated(method)) {
|
||||
forRemoval.add(method);
|
||||
}
|
||||
}
|
||||
for (Method method: forRemoval) {
|
||||
methods.remove(method);
|
||||
}
|
||||
return methods;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface Anno {
|
||||
}
|
||||
|
||||
|
||||
class TestObject {
|
||||
|
||||
public int doit(int i) {
|
||||
return i;
|
||||
}
|
||||
|
||||
@Anno
|
||||
public String doit(double d) {
|
||||
return "double "+d;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class DummyMethodResolver implements MethodResolver {
|
||||
|
||||
@Override
|
||||
public MethodExecutor resolve(EvaluationContext context, Object targetObject, String name,
|
||||
List<TypeDescriptor> argumentTypes) throws AccessException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class BytesService {
|
||||
|
||||
public byte[] handleBytes(byte[] bytes) {
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+22
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -1895,6 +1895,15 @@ public class SpelReproTests extends AbstractExpressionTests {
|
||||
assertTrue(((List) value).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void SPR12803() throws Exception {
|
||||
StandardEvaluationContext sec = new StandardEvaluationContext();
|
||||
sec.setVariable("iterable", Collections.emptyList());
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
Expression expression = parser.parseExpression("T(org.springframework.expression.spel.SpelReproTests.GuavaLists).newArrayList(#iterable)");
|
||||
assertTrue(expression.getValue(sec) instanceof ArrayList);
|
||||
}
|
||||
|
||||
|
||||
private static enum ABC { A, B, C }
|
||||
|
||||
@@ -2180,4 +2189,16 @@ public class SpelReproTests extends AbstractExpressionTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class GuavaLists {
|
||||
|
||||
public static <T> List<T> newArrayList(Iterable<T> iterable) {
|
||||
return new ArrayList<T>();
|
||||
}
|
||||
|
||||
public static <T> List<T> newArrayList(Object... elements) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+22
-22
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -22,9 +22,9 @@ import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.expression.spel.testresources.Inventor;
|
||||
import org.springframework.expression.spel.testresources.PlaceOfBirth;
|
||||
|
||||
///CLOVER:OFF
|
||||
/**
|
||||
* Builds an evaluation context for test expressions. Features of the test evaluation context are:
|
||||
* Builds an evaluation context for test expressions.
|
||||
* Features of the test evaluation context are:
|
||||
* <ul>
|
||||
* <li>The root context object is an Inventor instance {@link Inventor}
|
||||
* </ul>
|
||||
@@ -45,21 +45,19 @@ public class TestScenarioCreator {
|
||||
*/
|
||||
private static void populateFunctions(StandardEvaluationContext testContext) {
|
||||
try {
|
||||
testContext.registerFunction("isEven", TestScenarioCreator.class.getDeclaredMethod("isEven",
|
||||
new Class[] { Integer.TYPE }));
|
||||
testContext.registerFunction("reverseInt", TestScenarioCreator.class.getDeclaredMethod("reverseInt",
|
||||
new Class[] { Integer.TYPE, Integer.TYPE, Integer.TYPE }));
|
||||
testContext.registerFunction("reverseString", TestScenarioCreator.class.getDeclaredMethod("reverseString",
|
||||
new Class[] { String.class }));
|
||||
testContext.registerFunction("varargsFunctionReverseStringsAndMerge", TestScenarioCreator.class
|
||||
.getDeclaredMethod("varargsFunctionReverseStringsAndMerge", new Class[] { String[].class }));
|
||||
testContext.registerFunction("varargsFunctionReverseStringsAndMerge2", TestScenarioCreator.class
|
||||
.getDeclaredMethod("varargsFunctionReverseStringsAndMerge2", new Class[] { Integer.TYPE,
|
||||
String[].class }));
|
||||
} catch (SecurityException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
testContext.registerFunction("isEven",
|
||||
TestScenarioCreator.class.getDeclaredMethod("isEven", Integer.TYPE));
|
||||
testContext.registerFunction("reverseInt",
|
||||
TestScenarioCreator.class.getDeclaredMethod("reverseInt", Integer.TYPE, Integer.TYPE, Integer.TYPE));
|
||||
testContext.registerFunction("reverseString",
|
||||
TestScenarioCreator.class.getDeclaredMethod("reverseString", String.class));
|
||||
testContext.registerFunction("varargsFunctionReverseStringsAndMerge",
|
||||
TestScenarioCreator.class.getDeclaredMethod("varargsFunctionReverseStringsAndMerge", String[].class));
|
||||
testContext.registerFunction("varargsFunctionReverseStringsAndMerge2",
|
||||
TestScenarioCreator.class.getDeclaredMethod("varargsFunctionReverseStringsAndMerge2", Integer.TYPE, String[].class));
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,9 +70,8 @@ public class TestScenarioCreator {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the root context object, an Inventor instance. Non-qualified property and method references will be
|
||||
* resolved against this context object.
|
||||
*
|
||||
* Create the root context object, an Inventor instance. Non-qualified property
|
||||
* and method references will be resolved against this context object.
|
||||
* @param testContext the evaluation context in which to set the root object
|
||||
*/
|
||||
private static void setupRootContextObject(StandardEvaluationContext testContext) {
|
||||
@@ -88,12 +85,14 @@ public class TestScenarioCreator {
|
||||
testContext.setRootObject(tesla);
|
||||
}
|
||||
|
||||
|
||||
// These methods are registered in the test context and therefore accessible through function calls
|
||||
// in test expressions
|
||||
|
||||
public static String isEven(int i) {
|
||||
if ((i % 2) == 0)
|
||||
if ((i % 2) == 0) {
|
||||
return "y";
|
||||
}
|
||||
return "n";
|
||||
}
|
||||
|
||||
@@ -129,4 +128,5 @@ public class TestScenarioCreator {
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -83,7 +83,7 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
|
||||
* <p>This transaction manager can be used as a replacement for the
|
||||
* {@link org.springframework.transaction.jta.JtaTransactionManager} in the single
|
||||
* resource case, as it does not require a container that supports JTA, typically
|
||||
* in combination with a locally defined JDBC DataSource (e.g. a Jakarta Commons
|
||||
* in combination with a locally defined JDBC DataSource (e.g. an Apache Commons
|
||||
* DBCP connection pool). Switching between this local strategy and a JTA
|
||||
* environment is just a matter of configuration!
|
||||
*
|
||||
@@ -126,8 +126,8 @@ public class DataSourceTransactionManager extends AbstractPlatformTransactionMan
|
||||
|
||||
/**
|
||||
* Set the JDBC DataSource that this instance should manage transactions for.
|
||||
* <p>This will typically be a locally defined DataSource, for example a
|
||||
* Jakarta Commons DBCP connection pool. Alternatively, you can also drive
|
||||
* <p>This will typically be a locally defined DataSource, for example an
|
||||
* Apache Commons DBCP connection pool. Alternatively, you can also drive
|
||||
* transactions for a non-XA J2EE DataSource fetched from JNDI. For an XA
|
||||
* DataSource, use JtaTransactionManager.
|
||||
* <p>The DataSource specified here should be the target DataSource to manage
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -53,7 +53,7 @@ import org.springframework.util.ClassUtils;
|
||||
* bean definition to a local DataSource (which is simpler and thus recommended).
|
||||
*
|
||||
* <p>If you need a "real" connection pool outside of a J2EE container, consider
|
||||
* <a href="http://jakarta.apache.org/commons/dbcp">Apache's Jakarta Commons DBCP</a>
|
||||
* <a href="http://commons.apache.org/proper/commons-dbcp">Apache Commons DBCP</a>
|
||||
* or <a href="http://sourceforge.net/projects/c3p0">C3P0</a>.
|
||||
* Commons DBCP's BasicDataSource and C3P0's ComboPooledDataSource are full
|
||||
* connection pool beans, supporting the same basic properties as this class
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2015 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,8 +26,8 @@ import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Simple implementation of the standard JDBC {@link javax.sql.DataSource} interface,
|
||||
* configuring a plain old JDBC {@link java.sql.Driver} via bean properties, and returning
|
||||
* a new {@link java.sql.Connection} from every {@code getConnection} call.
|
||||
* configuring a plain old JDBC {@link java.sql.Driver} via bean properties, and
|
||||
* returning a new {@link java.sql.Connection} from every {@code getConnection} call.
|
||||
*
|
||||
* <p><b>NOTE: This class is not an actual connection pool; it does not actually
|
||||
* pool Connections.</b> It just serves as simple replacement for a full-blown
|
||||
@@ -40,7 +40,7 @@ import org.springframework.util.Assert;
|
||||
* for seamless switching to and from a local DataSource bean like this class.
|
||||
*
|
||||
* <p>If you need a "real" connection pool outside of a J2EE container, consider
|
||||
* <a href="http://jakarta.apache.org/commons/dbcp">Apache's Jakarta Commons DBCP</a>
|
||||
* <a href="http://commons.apache.org/proper/commons-dbcp">Apache Commons DBCP</a>
|
||||
* or <a href="http://sourceforge.net/projects/c3p0">C3P0</a>.
|
||||
* Commons DBCP's BasicDataSource and C3P0's ComboPooledDataSource are full
|
||||
* connection pool beans, supporting the same basic properties as this class
|
||||
|
||||
+6
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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,14 +31,14 @@ public class ScriptStatementFailedException extends ScriptException {
|
||||
|
||||
/**
|
||||
* Construct a new {@code ScriptStatementFailedException}.
|
||||
* @param statement the actual SQL statement that failed
|
||||
* @param lineNumber the line number in the SQL script
|
||||
* @param stmt the actual SQL statement that failed
|
||||
* @param stmtNumber the statement number in the SQL script (i.e.,
|
||||
* the nth statement present in the resource)
|
||||
* @param resource the resource from which the SQL statement was read
|
||||
* @param cause the underlying cause of the failure
|
||||
*/
|
||||
public ScriptStatementFailedException(String statement, int lineNumber, EncodedResource resource, Throwable cause) {
|
||||
super("Failed to execute SQL script statement at line " + lineNumber + " of resource " + resource + ": "
|
||||
+ statement, cause);
|
||||
public ScriptStatementFailedException(String stmt, int stmtNumber, EncodedResource resource, Throwable cause) {
|
||||
super("Failed to execute SQL script statement #" + stmtNumber + " of resource " + resource + ": " + stmt, cause);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+15
-19
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -48,8 +48,6 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public abstract class ScriptUtils {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(ScriptUtils.class);
|
||||
|
||||
/**
|
||||
* Default statement separator within SQL scripts: {@code ";"}.
|
||||
*/
|
||||
@@ -89,12 +87,8 @@ public abstract class ScriptUtils {
|
||||
public static final String DEFAULT_BLOCK_COMMENT_END_DELIMITER = "*/";
|
||||
|
||||
|
||||
/**
|
||||
* Prevent instantiation of this utility class.
|
||||
*/
|
||||
private ScriptUtils() {
|
||||
/* no-op */
|
||||
}
|
||||
private static final Log logger = LogFactory.getLog(ScriptUtils.class);
|
||||
|
||||
|
||||
/**
|
||||
* Split an SQL script into separate statements delimited by the provided
|
||||
@@ -140,7 +134,7 @@ public abstract class ScriptUtils {
|
||||
*/
|
||||
public static void splitSqlScript(String script, String separator, List<String> statements) throws ScriptException {
|
||||
splitSqlScript(null, script, separator, DEFAULT_COMMENT_PREFIX, DEFAULT_BLOCK_COMMENT_START_DELIMITER,
|
||||
DEFAULT_BLOCK_COMMENT_END_DELIMITER, statements);
|
||||
DEFAULT_BLOCK_COMMENT_END_DELIMITER, statements);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -276,6 +270,7 @@ public abstract class ScriptUtils {
|
||||
*/
|
||||
private static String readScript(EncodedResource resource, String commentPrefix, String separator)
|
||||
throws IOException {
|
||||
|
||||
LineNumberReader lnr = new LineNumberReader(resource.getReader());
|
||||
try {
|
||||
return readScript(lnr, commentPrefix, separator);
|
||||
@@ -302,6 +297,7 @@ public abstract class ScriptUtils {
|
||||
*/
|
||||
public static String readScript(LineNumberReader lineNumberReader, String commentPrefix, String separator)
|
||||
throws IOException {
|
||||
|
||||
String currentStatement = lineNumberReader.readLine();
|
||||
StringBuilder scriptBuilder = new StringBuilder();
|
||||
while (currentStatement != null) {
|
||||
@@ -431,9 +427,8 @@ public abstract class ScriptUtils {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Executing SQL script from " + resource);
|
||||
}
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
List<String> statements = new LinkedList<String>();
|
||||
|
||||
String script;
|
||||
try {
|
||||
script = readScript(resource, commentPrefix, separator);
|
||||
@@ -449,13 +444,15 @@ public abstract class ScriptUtils {
|
||||
separator = FALLBACK_STATEMENT_SEPARATOR;
|
||||
}
|
||||
|
||||
List<String> statements = new LinkedList<String>();
|
||||
splitSqlScript(resource, script, separator, commentPrefix, blockCommentStartDelimiter,
|
||||
blockCommentEndDelimiter, statements);
|
||||
int lineNumber = 0;
|
||||
blockCommentEndDelimiter, statements);
|
||||
|
||||
int stmtNumber = 0;
|
||||
Statement stmt = connection.createStatement();
|
||||
try {
|
||||
for (String statement : statements) {
|
||||
lineNumber++;
|
||||
stmtNumber++;
|
||||
try {
|
||||
stmt.execute(statement);
|
||||
int rowsAffected = stmt.getUpdateCount();
|
||||
@@ -467,12 +464,12 @@ public abstract class ScriptUtils {
|
||||
boolean dropStatement = StringUtils.startsWithIgnoreCase(statement.trim(), "drop");
|
||||
if (continueOnError || (dropStatement && ignoreFailedDrops)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Failed to execute SQL script statement at line " + lineNumber
|
||||
+ " of resource " + resource + ": " + statement, ex);
|
||||
logger.debug("Failed to execute SQL script statement #" + stmtNumber +
|
||||
" of resource " + resource + ": " + statement, ex);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new ScriptStatementFailedException(statement, lineNumber, resource, ex);
|
||||
throw new ScriptStatementFailedException(statement, stmtNumber, resource, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -495,7 +492,6 @@ public abstract class ScriptUtils {
|
||||
if (ex instanceof ScriptException) {
|
||||
throw (ScriptException) ex;
|
||||
}
|
||||
|
||||
throw new UncategorizedScriptException(
|
||||
"Failed to execute database script from resource [" + resource + "]", ex);
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2015 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,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* Implementation of the {@link NativeJdbcExtractor} interface for the
|
||||
* Jakarta Commons DBCP connection pool, version 1.1 or higher.
|
||||
* Apache Commons DBCP connection pool, version 1.1 or higher.
|
||||
*
|
||||
* <p>Returns the underlying native Connection, Statement, etc to application
|
||||
* code instead of DBCP's wrapper implementations. The returned JDBC classes
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -42,7 +42,7 @@ import java.sql.Statement;
|
||||
*
|
||||
* <p>When working with a simple connection pool that wraps Connections but not
|
||||
* Statements, a {@link SimpleNativeJdbcExtractor} is often sufficient. However,
|
||||
* some pools (like Jakarta's Commons DBCP) wrap <i>all</i> JDBC objects that they
|
||||
* some pools (like Apache's Commons DBCP) wrap <i>all</i> JDBC objects that they
|
||||
* return: Therefore, you need to use a specific {@code NativeJdbcExtractor}
|
||||
* (like {@link CommonsDbcpNativeJdbcExtractor}) with them.
|
||||
*
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user