mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
151 Commits
v7.0.2
...
v3.0.7.RELEASE
| Author | SHA1 | Date | |
|---|---|---|---|
| 40015e3de3 | |||
| 5e448af903 | |||
| 1f3ce640c9 | |||
| cca44f411e | |||
| 9b0412f35f | |||
| 7eee3b9926 | |||
| b5a279d2c8 | |||
| 0862a29066 | |||
| 8d83f6966e | |||
| ce5117c9ed | |||
| 836e3c9253 | |||
| 2006eecb18 | |||
| 91287828f7 | |||
| efd2fc7688 | |||
| 74b5487a28 | |||
| 2882ae29b2 | |||
| 4a7b96c4ca | |||
| 7398e0ea97 | |||
| beaad20795 | |||
| 1bd84db56e | |||
| 6316a45927 | |||
| e298c202af | |||
| 288408e89f | |||
| 53a244d408 | |||
| 8213d0cb50 | |||
| b9868a498e | |||
| df7bdfa7c6 | |||
| f8402e9f82 | |||
| 7eeb654eec | |||
| b558c62953 | |||
| d64dd1943f | |||
| bffa50e31a | |||
| 143cb50986 | |||
| b3ccc438af | |||
| 94513c1a28 | |||
| c9607fdaf2 | |||
| 7c108c1e77 | |||
| 77372d7cdb | |||
| 173f307ec9 | |||
| 2c987b0ffb | |||
| 46a4ac9628 | |||
| c2997f4dd9 | |||
| 0150000d8b | |||
| cad5eb836c | |||
| c82dab6497 | |||
| e6f4e16219 | |||
| d0032f43c7 | |||
| 8a43dd172c | |||
| 11aaefffbf | |||
| c6b36cc207 | |||
| 5856db6f72 | |||
| 3c5e02a54a | |||
| db0c921313 | |||
| 641bc35a50 | |||
| c166803d41 | |||
| 12e1784a99 | |||
| bfabd58106 | |||
| 540845e613 | |||
| 8e7982397c | |||
| 84890ebc0d | |||
| a9f28575b1 | |||
| a730bf47df | |||
| b5ec65cef6 | |||
| 965c12b0f8 | |||
| 7187029ef6 | |||
| 6363bb4b5b | |||
| 58ea5a702d | |||
| 97b988ade8 | |||
| 227234288f | |||
| 05a7b65d43 | |||
| cee6cb859d | |||
| 19c6a4e209 | |||
| b9089a8f9d | |||
| 7a20ed7d70 | |||
| 99588950d2 | |||
| a2129a132f | |||
| 0f1c10bc1c | |||
| 585745de32 | |||
| 65077d262c | |||
| da36c2b8b8 | |||
| 8f01770f29 | |||
| c51b9a7be2 | |||
| 3ffc0a2da2 | |||
| acac25b2eb | |||
| cb0c0c503f | |||
| 215ccc2e10 | |||
| d95cbe23ee | |||
| ac1ffff9db | |||
| c0257aba9b | |||
| 79aa661dd6 | |||
| 18540debf6 | |||
| 7605707c18 | |||
| d48c3b5d4f | |||
| b122cf87df | |||
| 183523d045 | |||
| a4f62bb863 | |||
| 80def4b695 | |||
| 42e18e6c4e | |||
| d8767774c9 | |||
| f67e726be7 | |||
| 41b9a461df | |||
| 037497cb4f | |||
| 3ecb6b1a03 | |||
| 6b92f66ebd | |||
| 070a723ef2 | |||
| d4be29e661 | |||
| 3a3f15f144 | |||
| 3edf8566ed | |||
| a2f00f205a | |||
| 340a8b28f9 | |||
| 83c5753ae1 | |||
| 67bb044a6f | |||
| 9ddfb375cb | |||
| 6fc6a9e80c | |||
| f18fa08aa0 | |||
| aa4ecdb79e | |||
| 8041f6abdd | |||
| 210c77ddb0 | |||
| 24cb345b6c | |||
| 0fdd7550b8 | |||
| f1fb0e5330 | |||
| d4c2f63160 | |||
| b167f3f7a6 | |||
| 63fe7bdd34 | |||
| 270db64243 | |||
| 15fd972417 | |||
| 10d9860457 | |||
| 01eab03dca | |||
| eb50eec85b | |||
| 4faa5af3f8 | |||
| 218e64cc80 | |||
| b82edcca04 | |||
| d8a4949faf | |||
| 22739bebf3 | |||
| fece2c1125 | |||
| 8b55b34d79 | |||
| d1e998bedd | |||
| 2ddb14ae5b | |||
| ae74fbdd4b | |||
| 28769e906f | |||
| 47c21bf73b | |||
| 59fda2dbab | |||
| 43f8eca91b | |||
| 6cb6bd751e | |||
| 58d68cef98 | |||
| 5f3f30fdb4 | |||
| 7a6b2cfe1f | |||
| a8ab9af002 | |||
| ca19b14f13 | |||
| 175f6d4bc5 | |||
| 0206845341 |
+8
-3
@@ -1,7 +1,12 @@
|
||||
.springBeans
|
||||
.DS_Store
|
||||
target
|
||||
integration-repo
|
||||
ivy-cache
|
||||
spring-build
|
||||
jmx.log
|
||||
.springBeans
|
||||
.DS_Store
|
||||
jxl.log
|
||||
jmx.log
|
||||
org.springframework.jdbc/derby.log
|
||||
org.springframework.spring-parent/.classpath
|
||||
org.springframework.spring-parent/.project
|
||||
org.springframework.test/test-output/
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
|
||||
<!-- Main targets -->
|
||||
<target name="publish-documentation" depends="publish-documentation.init">
|
||||
<sshexec host="spring02.managed.contegix.com" username="${username}" keyfile="${key.file}" passphrase="${passphrase}"
|
||||
<sshexec host="static.springsource.org" username="${username}" keyfile="${key.file}" passphrase="${passphrase}"
|
||||
command="mkdir /opt/www/domains/springframework.org/www/htdocs/spring/docs/${bundle.version}"/>
|
||||
|
||||
<scp remoteToDir="${username}@spring02.managed.contegix.com:/opt/www/domains/springframework.org/www/htdocs/spring/docs/${bundle.version}"
|
||||
<scp remoteToDir="${username}@static.springsource.org:/opt/www/domains/springframework.org/www/htdocs/spring/docs/${bundle.version}"
|
||||
keyfile="${key.file}" passphrase="${passphrase}" sftp="true" verbose="true">
|
||||
<fileset dir="${package.output.dir}">
|
||||
<include name="changelog.txt" />
|
||||
@@ -16,7 +16,7 @@
|
||||
<fileset dir="${package.docs.dir}" />
|
||||
</scp>
|
||||
|
||||
<sshexec host="spring02.managed.contegix.com" username="${username}" keyfile="${key.file}" passphrase="${passphrase}"
|
||||
<sshexec host="static.springsource.org" username="${username}" keyfile="${key.file}" passphrase="${passphrase}"
|
||||
command="rm /opt/www/domains/springframework.org/www/htdocs/spring/docs/3.0.x ; ln -s /opt/www/domains/springframework.org/www/htdocs/spring/docs/${bundle.version} /opt/www/domains/springframework.org/www/htdocs/spring/docs/3.0.x"/>
|
||||
</target>
|
||||
|
||||
|
||||
@@ -3,6 +3,91 @@ SPRING FRAMEWORK CHANGELOG
|
||||
http://www.springsource.org
|
||||
|
||||
|
||||
Changes in version 3.0.7 (2011-12-22)
|
||||
-------------------------------------
|
||||
|
||||
* fixed GenericTypeResolver to consistently return null if not resolvable
|
||||
* added proper "contentLength()" implementation to ByteArrayResource
|
||||
* refined Resource "exists()" check for HTTP URLs to always return false for 404 status
|
||||
* LocaleEditor and StringToLocaleConverter do not restrict variant part through validation
|
||||
* LinkedCaseInsensitiveMap overrides putAll method as well (for IBM JDK 1.6 compatibility)
|
||||
* ConversionService prevents Converter from trying to convert to a subtype of its actual target type
|
||||
* ConversionService is able to work with "Collections.emptyList()" as target type (again)
|
||||
* CollectionCollection/MapToMapConverter preserve original Collection/Map if no converted elements
|
||||
* fixed nested element conversion with a DataBinder + ConversionService + PropertyEditor
|
||||
* restored DataBinder's ability to bind to an auto-growing List with unknown element type
|
||||
* optimized DefaultListableBeanFactory's PropertyDescriptor caching for concurrent access
|
||||
* context:property-placeholder's "file-encoding" attribute value is being applied correctly
|
||||
* SpringValidatorAdapter accepts non-indexed set paths (for Hibernate Validator compatibility)
|
||||
* fixed AbstractAsyncExecutionAspect's setExecutor method to correctly wrap in a TaskExecutorAdapter
|
||||
* @Transactional qualifiers match against transaction manager definitions in parent contexts as well
|
||||
* TransactionSynchronizationManager eagerly cleans up void ResourceHolders on any access
|
||||
* updated H2 error codes in sql-error-codes.xml
|
||||
* fixed NamedParameterJdbcTemplate to use correct maximum type for queryForInt/Long
|
||||
* SimpleJdbcTestUtils executeSqlScript properly closes its LineNumberReader after use
|
||||
* Hibernate synchronization properly unbinds Session even in case of afterCompletion exception
|
||||
* JDO PersistenceManager synchronization performs close attempt after completion (if necessary)
|
||||
* JPA EntityManagerFactoryUtils silently ignores IllegalArgumentExceptions from setHint calls
|
||||
* added "forwarder" property to ConnectorServerFactoryBean, accepting an MBeanServerForwarder
|
||||
* JmsInvokerClientInterceptor/FactoryBean always uses createConnection/createSession when on JMS 1.1
|
||||
* RmiClientInterceptor detects nested SocketException as connect failure as well
|
||||
* Servlet/PortletContextResource's getFile prefers "file:" URL resolution over calling getRealPath
|
||||
* Portlet session mutex uses global session attribute to be shared among all portlets in the session
|
||||
* fixed ServletServerHttpRequest to reconstruct from "request.getParameterMap()" for form POST only
|
||||
* fixed @RequestMapping header matching to correctly process negated header conditions
|
||||
* added "getObjectMapper()" accessor to MappingJacksonHttpMessageConverter
|
||||
* ResourceHttpRequestHandler sends content without content-type header if no media type found
|
||||
* AbstractCachingViewResolver allows for caching unresolved view names ("cacheUnresolved"=true)
|
||||
* fixed "formMultiSelect"/"formCheckboxes" FreeMarker macros to compare against actual field value
|
||||
|
||||
|
||||
Changes in version 3.0.6 (2011-08-18)
|
||||
-------------------------------------
|
||||
|
||||
* fixed aspects bundle to declare dependencies for @Async aspect as well
|
||||
* ProxyCreationContext uses "ThreadLocal.remove()" over "ThreadLocal.set(null)" as well
|
||||
* DefaultListableBeanFactory is only deserializable through a SerializedBeanFactoryReference
|
||||
* DefaultListableBeanFactory's getBean(name, type) attempts type conversion if necessary
|
||||
* DefaultListableBeanFactory allows for init methods to register further bean definitions (again)
|
||||
* XmlBeanDefinitionReader accepts description subelement within map entry as well (as per the XSD)
|
||||
* ConfigurationClassPostProcessor supports use of same processor instance with several factories
|
||||
* fixed potential InjectionMetadata NPE when using SpringBeanAutowiringInterceptor
|
||||
* SpringBeanAutowiringSupport is able to process @Value annotations on any given target instance
|
||||
* overridden @PersistenceContext annotations on subclass methods are being processed correctly
|
||||
* BeanDefinitionVisitor now actually visits factory method names
|
||||
* restored support for String-to-ContextResource conversion
|
||||
* restored original GenericConversionService behavior with respect to empty collections/maps
|
||||
* restored original FormattingConversionService behavior with respect to the use of subtypes
|
||||
* added "formatters" property to FormattingConversionServiceFactoryBean
|
||||
* collection/array conversion returns original collection if possible (instead of first element)
|
||||
* fixed collection element resolution when using a ConversionService with a DataBinder
|
||||
* DataBinder uses a default limit of 256 for array/collection auto-growing
|
||||
* added "autoGrowNestedPaths" property to ConfigurableWebBindingInitializer
|
||||
* Servlet/PortletRequestDataBinder perform unwrapping for MultipartRequest as well
|
||||
* fixed AbstractBindingResult to avoid NPE in "hashCode()" if target is null
|
||||
* fixed several HttpHeaders issues (charset handling, quoting/unquoting)
|
||||
* SimpleClientHttpRequest uses fixed-length streaming mode (always sets content-length header)
|
||||
* added "connectTimeout" and "readTimeout" properties to Simple/CommonsClientHttpRequestFactory
|
||||
* explicit status code in RedirectView respected in HTTP 1.0 compatibility mode
|
||||
* FormHttpMessageConverter correctly processes POST requests
|
||||
* ResourceHttpRequestHandler does not set Content-Length header for 304 response
|
||||
* ResourceHttpRequestHandler detects invalid directory traversal in given path
|
||||
* LocaleChangeInterceptor validates locale values in order to prevent XSS vulnerability
|
||||
* HtmlUtils properly escapes single quotes as well
|
||||
* added support for web.xml context-param "springJspExpressionSupport" (explicit "true"/"false")
|
||||
* ContextLoader and FrameworkServlet support "contextId" parameter for custom serialization id
|
||||
* RemoteExporter uses an opaque proxy for 'serviceInterface' (no AOP interfaces exposed)
|
||||
* added "acceptProxyClasses" flag to RemoteInvocationSerializingExporter
|
||||
* refined WebLogic RMI descriptor to only mark 'getTargetInterfaceName' method as idempotent
|
||||
* EhCacheManagerFactoryBean properly closes "ehcache.xml" input stream, if any
|
||||
* revised JMS CachedConnectionFactory to avoid unnecessary rollback calls on Session return
|
||||
* fixed JMS CachedConnectionFactory to fully synchronize its Session list
|
||||
* fixed NamedParameterJdbcTemplate's handling of arrays as query parameters
|
||||
* fixed JPA 2.0 timeout hints to correctly specify milliseconds
|
||||
* updated Quartz package to support Quartz 1.8 as well (note: not supporting Quartz 2.0 yet)
|
||||
* fixed @Rule execution order in SpringJUnit4ClassRunner to match standard JUnit 4 behavior
|
||||
|
||||
|
||||
Changes in version 3.0.5 (2010-10-20)
|
||||
-------------------------------------
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
SPRING FRAMEWORK 3.0.5 (October 2010)
|
||||
-------------------------------------
|
||||
http://www.springframework.org
|
||||
SPRING FRAMEWORK 3.0.7 (December 2011)
|
||||
--------------------------------------
|
||||
http://www.springsource.org
|
||||
|
||||
1. INTRODUCTION
|
||||
|
||||
|
||||
+30
-30
@@ -1,30 +1,30 @@
|
||||
version=3.0.5
|
||||
# osgi ranges
|
||||
spring.osgi.range.nq=${version:[=.=.=, =.=.+1)}
|
||||
spring.osgi.range="${spring.osgi.range.nq}"
|
||||
aj.osgi.range="[1.5.4, 2.0.0)"
|
||||
|
||||
#
|
||||
release.type=integration
|
||||
natural.name=spring-framework
|
||||
project.name=Spring Framework
|
||||
project.key=SPR
|
||||
ivy.cache.dir=${basedir}/../ivy-cache
|
||||
integration.repo.dir=${basedir}/../integration-repo
|
||||
license.dir=${basedir}/../build-spring-framework/resources
|
||||
javadoc.exclude.package.names=org/springframework/samples/**
|
||||
javadoc.max.memory=256M
|
||||
test.vm.args=-Xmx1024M -XX:MaxPermSize=512M -XX:+HeapDumpOnOutOfMemoryError
|
||||
compiler.args=-enableJavadoc -warn:none
|
||||
|
||||
# For when releasing
|
||||
#release.type=release
|
||||
#build.stamp=RELEASE
|
||||
|
||||
# For when releasing milestones
|
||||
#release.type=milestone
|
||||
#build.stamp=M1
|
||||
|
||||
# For development in trunk
|
||||
#release.type=integration
|
||||
#build.stamp=BUILD-SNAPSHOT
|
||||
version=3.0.7
|
||||
# osgi ranges
|
||||
spring.osgi.range.nq=${version:[=.=.=, =.=.+1)}
|
||||
spring.osgi.range="${spring.osgi.range.nq}"
|
||||
aj.osgi.range="[1.5.4, 2.0.0)"
|
||||
|
||||
#
|
||||
#release.type=integration
|
||||
natural.name=spring-framework
|
||||
project.name=Spring Framework
|
||||
project.key=SPR
|
||||
ivy.cache.dir=${basedir}/../ivy-cache
|
||||
integration.repo.dir=${basedir}/../integration-repo
|
||||
license.dir=${basedir}/../build-spring-framework/resources
|
||||
javadoc.exclude.package.names=org/springframework/samples/**
|
||||
javadoc.max.memory=256M
|
||||
test.vm.args=-Xmx1024M -XX:MaxPermSize=512M -XX:+HeapDumpOnOutOfMemoryError
|
||||
compiler.args=-enableJavadoc -warn:none
|
||||
|
||||
# For when releasing
|
||||
release.type=release
|
||||
build.stamp=RELEASE
|
||||
|
||||
# For when releasing milestones
|
||||
#release.type=milestone
|
||||
#build.stamp=M1
|
||||
|
||||
# For development in trunk
|
||||
#release.type=integration
|
||||
#build.stamp=BUILD-SNAPSHOT
|
||||
|
||||
+5
-6
@@ -1,6 +1,5 @@
|
||||
#common dependency versions
|
||||
aspectj.version=1.6.8.RELEASE
|
||||
commons.pool.version=1.5.3
|
||||
slf4j.version=1.5.6
|
||||
org.testng.version=5.10.0
|
||||
org.junit.version=4.7.0
|
||||
#common dependency versions
|
||||
aspectj.version=1.6.8.RELEASE
|
||||
slf4j.version=1.5.3
|
||||
junit.version=4.7.0
|
||||
testng.version=5.10.0
|
||||
|
||||
@@ -30,14 +30,14 @@
|
||||
<dependency org="net.sourceforge.cglib" name="com.springsource.net.sf.cglib" rev="2.2.0" conf="optional, bytecode-proxy->compile"/>
|
||||
<dependency org="org.aopalliance" name="com.springsource.org.aopalliance" rev="1.0.0" conf="compile->compile"/>
|
||||
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.logging" rev="1.1.1" conf="compile, commons-logging->compile"/>
|
||||
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.pool" rev="${commons.pool.version}" conf="optional, pooling->compile"/>
|
||||
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.pool" rev="1.5.3" conf="optional, pooling->compile"/>
|
||||
<dependency org="org.aspectj" name="com.springsource.org.aspectj.weaver" rev="${aspectj.version}" conf="optional, aspectj->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.beans" rev="latest.integration" conf="compile->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.core" rev="latest.integration" conf="compile->compile"/>
|
||||
<!-- test dependencies -->
|
||||
<dependency org="org.apache.log4j" name="com.springsource.org.apache.log4j" rev="1.2.15" conf="test->runtime"/>
|
||||
<dependency org="org.easymock" name="com.springsource.org.easymock" rev="2.5.1" conf="test->compile"/>
|
||||
<dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit.version}" conf="test->runtime"/>
|
||||
<dependency org="org.junit" name="com.springsource.org.junit" rev="${junit.version}" conf="test->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.asm" rev="latest.integration" conf="test->runtime"/>
|
||||
</dependencies>
|
||||
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.5.BUILD-SNAPSHOT</version>
|
||||
<version>3.0.7.RELEASE</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.5.BUILD-SNAPSHOT</version>
|
||||
<version>3.0.7.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
+7
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2011 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.
|
||||
@@ -46,7 +46,12 @@ public class ProxyCreationContext {
|
||||
* @param beanName the name of the bean, or <code>null</code> to reset it
|
||||
*/
|
||||
static void setCurrentProxiedBeanName(String beanName) {
|
||||
currentProxiedBeanName.set(beanName);
|
||||
if (beanName != null) {
|
||||
currentProxiedBeanName.set(beanName);
|
||||
}
|
||||
else {
|
||||
currentProxiedBeanName.remove();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -70,8 +70,9 @@ public class ExposeInvocationInterceptor implements MethodInterceptor, Ordered,
|
||||
MethodInvocation mi = invocation.get();
|
||||
if (mi == null)
|
||||
throw new IllegalStateException(
|
||||
"No MethodInvocation found: Check that an AOP invocation is in progress, " +
|
||||
"and that the ExposeInvocationInterceptor is in the interceptor chain.");
|
||||
"No MethodInvocation found: Check that an AOP invocation is in progress, and that the " +
|
||||
"ExposeInvocationInterceptor is upfront in the interceptor chain. Specifically, note that " +
|
||||
"advices with order HIGHEST_PRECEDENCE will execute before ExposeInvocationInterceptor!");
|
||||
return mi;
|
||||
}
|
||||
|
||||
|
||||
+8
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2011 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,9 @@
|
||||
|
||||
package org.springframework.aop.target;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.NotSerializableException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectStreamException;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
@@ -91,6 +93,11 @@ public abstract class AbstractPrototypeBasedTargetSource extends AbstractBeanFac
|
||||
// Serialization support
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
|
||||
throw new NotSerializableException("A prototype-based TargetSource itself is not deserializable - " +
|
||||
"just a disconnected SingletonTargetSource is");
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces this object with a SingletonTargetSource on serialization.
|
||||
* Protected as otherwise it won't be invoked for subclasses.
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-asm</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.5.BUILD-SNAPSHOT</version>
|
||||
<version>3.0.7.RELEASE</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.5.BUILD-SNAPSHOT</version>
|
||||
<version>3.0.7.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<dependency org="org.springframework" name="org.springframework.context" rev="latest.integration" conf="test->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.context.support" rev="latest.integration" conf="test->runtime"/>
|
||||
<dependency org="javax.persistence" name="com.springsource.javax.persistence" rev="1.0.0" conf="optional, orm->compile"/>
|
||||
<dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit.version}" conf="test->compile"/>
|
||||
<dependency org="org.junit" name="com.springsource.org.junit" rev="${junit.version}" conf="test->compile"/>
|
||||
<dependency org="javax.mail" name="com.springsource.javax.mail" rev="1.4.0" conf="optional, test->compile"/>
|
||||
</dependencies>
|
||||
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aspects</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.5.BUILD-SNAPSHOT</version>
|
||||
<version>3.0.7.RELEASE</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.5.BUILD-SNAPSHOT</version>
|
||||
<version>3.0.7.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ public abstract aspect AbstractAsyncExecutionAspect {
|
||||
this.asyncExecutor = (AsyncTaskExecutor) executor;
|
||||
}
|
||||
else {
|
||||
this.asyncExecutor = new TaskExecutorAdapter(asyncExecutor);
|
||||
this.asyncExecutor = new TaskExecutorAdapter(executor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
<dependency org="org.springframework" name="org.springframework.core" rev="latest.integration" conf="compile->compile"/>
|
||||
<!-- test dependencies -->
|
||||
<dependency org="org.apache.log4j" name="com.springsource.org.apache.log4j" rev="1.2.15" conf="test->runtime"/>
|
||||
<dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit.version}" conf="test->runtime"/>
|
||||
<dependency org="org.junit" name="com.springsource.org.junit" rev="${junit.version}" conf="test->runtime"/>
|
||||
<dependency org="org.easymock" name="com.springsource.org.easymock" rev="2.5.1" conf="test->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.asm" rev="latest.integration" conf="compile->compile"/>
|
||||
</dependencies>
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.5.BUILD-SNAPSHOT</version>
|
||||
<version>3.0.7.RELEASE</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.5.BUILD-SNAPSHOT</version>
|
||||
<version>3.0.7.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2011 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,4 +92,15 @@ public interface BeanWrapper extends ConfigurablePropertyAccessor {
|
||||
*/
|
||||
boolean isAutoGrowNestedPaths();
|
||||
|
||||
/**
|
||||
* Specify a limit for array and collection auto-growing.
|
||||
* <p>Default is unlimited on a plain BeanWrapper.
|
||||
*/
|
||||
void setAutoGrowCollectionLimit(int autoGrowCollectionLimit);
|
||||
|
||||
/**
|
||||
* Return the limit for array and collection auto-growing.
|
||||
*/
|
||||
int getAutoGrowCollectionLimit();
|
||||
|
||||
}
|
||||
|
||||
+49
-21
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -120,6 +120,8 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
|
||||
private boolean autoGrowNestedPaths = false;
|
||||
|
||||
private int autoGrowCollectionLimit = Integer.MAX_VALUE;
|
||||
|
||||
|
||||
/**
|
||||
* Create new empty BeanWrapperImpl. Wrapped instance needs to be set afterwards.
|
||||
@@ -184,6 +186,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
setWrappedInstance(object, nestedPath, superBw.getWrappedInstance());
|
||||
setExtractOldValueForEditor(superBw.isExtractOldValueForEditor());
|
||||
setAutoGrowNestedPaths(superBw.isAutoGrowNestedPaths());
|
||||
setAutoGrowCollectionLimit(superBw.getAutoGrowCollectionLimit());
|
||||
setConversionService(superBw.getConversionService());
|
||||
setSecurityContext(superBw.acc);
|
||||
}
|
||||
@@ -251,22 +254,38 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
}
|
||||
|
||||
/**
|
||||
* If this BeanWrapper should "auto grow" nested paths.
|
||||
* When true, auto growth is triggered on nested paths when null values are encountered.
|
||||
* When true, auto growth is triggered on collection properties when out of bounds indexes are accessed.
|
||||
* Default is false.
|
||||
* Set whether this BeanWrapper should attempt to "auto-grow" a nested path that contains a null value.
|
||||
* <p>If "true", a null path location will be populated with a default object value and traversed
|
||||
* instead of resulting in a {@link NullValueInNestedPathException}. Turning this flag on also
|
||||
* enables auto-growth of collection elements when accessing an out-of-bounds index.
|
||||
* <p>Default is "false" on a plain BeanWrapper.
|
||||
*/
|
||||
public void setAutoGrowNestedPaths(boolean autoGrowNestedPaths) {
|
||||
this.autoGrowNestedPaths = autoGrowNestedPaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this BeanWrapper should "auto grow" nested paths.
|
||||
* Return whether "auto-growing" of nested paths has been activated.
|
||||
*/
|
||||
public boolean isAutoGrowNestedPaths() {
|
||||
return this.autoGrowNestedPaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a limit for array and collection auto-growing.
|
||||
* <p>Default is unlimited on a plain BeanWrapper.
|
||||
*/
|
||||
public void setAutoGrowCollectionLimit(int autoGrowCollectionLimit) {
|
||||
this.autoGrowCollectionLimit = autoGrowCollectionLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the limit for array and collection auto-growing.
|
||||
*/
|
||||
public int getAutoGrowCollectionLimit() {
|
||||
return this.autoGrowCollectionLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the security context used during the invocation of the wrapped instance methods.
|
||||
* Can be null.
|
||||
@@ -592,9 +611,9 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
private Object setDefaultValue(PropertyTokenHolder tokens) {
|
||||
PropertyValue pv = createDefaultPropertyValue(tokens);
|
||||
setPropertyValue(tokens, pv);
|
||||
return pv.getValue();
|
||||
return getPropertyValue(tokens);
|
||||
}
|
||||
|
||||
|
||||
private PropertyValue createDefaultPropertyValue(PropertyTokenHolder tokens) {
|
||||
Class type = getPropertyType(tokens.canonicalName);
|
||||
if (type == null) {
|
||||
@@ -604,7 +623,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
Object defaultValue = newValue(type, tokens.canonicalName);
|
||||
return new PropertyValue(tokens.canonicalName, defaultValue);
|
||||
}
|
||||
|
||||
|
||||
private Object newValue(Class<?> type, String name) {
|
||||
try {
|
||||
if (type.isArray()) {
|
||||
@@ -634,7 +653,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
"Could not instantiate property type [" + type.getName() + "] to auto-grow nested property path: " + ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new nested BeanWrapper instance.
|
||||
* <p>Default implementation creates a BeanWrapperImpl instance.
|
||||
@@ -834,15 +853,16 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
return array;
|
||||
}
|
||||
int length = Array.getLength(array);
|
||||
if (index >= length) {
|
||||
if (index >= length && index < this.autoGrowCollectionLimit) {
|
||||
Class<?> componentType = array.getClass().getComponentType();
|
||||
Object newArray = Array.newInstance(componentType, index + 1);
|
||||
System.arraycopy(array, 0, newArray, 0, length);
|
||||
for (int i = length; i < Array.getLength(newArray); i++) {
|
||||
Array.set(newArray, i, newValue(componentType, name));
|
||||
}
|
||||
// TODO this is not efficient because conversion may create a copy ... set directly because we know it is assignable.
|
||||
setPropertyValue(name, newArray);
|
||||
return newArray;
|
||||
return getPropertyValue(name);
|
||||
}
|
||||
else {
|
||||
return array;
|
||||
@@ -856,7 +876,8 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
if (!this.autoGrowNestedPaths) {
|
||||
return;
|
||||
}
|
||||
if (index >= collection.size()) {
|
||||
int size = collection.size();
|
||||
if (index >= size && index < this.autoGrowCollectionLimit) {
|
||||
Class elementType = GenericCollectionTypeResolver.getCollectionReturnType(pd.getReadMethod(), nestingLevel);
|
||||
if (elementType != null) {
|
||||
for (int i = collection.size(); i < index + 1; i++) {
|
||||
@@ -932,13 +953,13 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
"Cannot access indexed value in property referenced " +
|
||||
"in indexed property path '" + propertyName + "': returned null");
|
||||
}
|
||||
else if (propValue.getClass().isArray()) {
|
||||
if (propValue.getClass().isArray()) {
|
||||
PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);
|
||||
Class requiredType = propValue.getClass().getComponentType();
|
||||
int arrayIndex = Integer.parseInt(key);
|
||||
Object oldValue = null;
|
||||
try {
|
||||
if (isExtractOldValueForEditor()) {
|
||||
if (isExtractOldValueForEditor() && arrayIndex < Array.getLength(propValue)) {
|
||||
oldValue = Array.get(propValue, arrayIndex);
|
||||
}
|
||||
Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(), requiredType,
|
||||
@@ -962,23 +983,30 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
}
|
||||
Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(), requiredType,
|
||||
new PropertyTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), requiredType));
|
||||
if (index < list.size()) {
|
||||
list.set(index, convertedValue);
|
||||
}
|
||||
else if (index >= list.size()) {
|
||||
for (int i = list.size(); i < index; i++) {
|
||||
int size = list.size();
|
||||
if (index >= size && index < this.autoGrowCollectionLimit) {
|
||||
for (int i = size; i < index; i++) {
|
||||
try {
|
||||
list.add(null);
|
||||
}
|
||||
catch (NullPointerException ex) {
|
||||
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
||||
"Cannot set element with index " + index + " in List of size " +
|
||||
list.size() + ", accessed using property path '" + propertyName +
|
||||
size + ", accessed using property path '" + propertyName +
|
||||
"': List does not support filling up gaps with null elements");
|
||||
}
|
||||
}
|
||||
list.add(convertedValue);
|
||||
}
|
||||
else {
|
||||
try {
|
||||
list.set(index, convertedValue);
|
||||
}
|
||||
catch (IndexOutOfBoundsException ex) {
|
||||
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
||||
"Invalid list index in property path '" + propertyName + "'", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (propValue instanceof Map) {
|
||||
PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);
|
||||
|
||||
+43
-15
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,6 +21,7 @@ import java.beans.PropertyEditor;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
@@ -136,7 +137,10 @@ class TypeConverterDelegate {
|
||||
ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
|
||||
if (editor == null && conversionService != null && convertedValue != null) {
|
||||
TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(convertedValue);
|
||||
TypeDescriptor targetTypeDesc = typeDescriptor.forElementType(requiredType);
|
||||
TypeDescriptor targetTypeDesc = typeDescriptor;
|
||||
if (requiredType != null && !requiredType.isAssignableFrom(typeDescriptor.getType())) {
|
||||
targetTypeDesc = typeDescriptor.forElementType(requiredType);
|
||||
}
|
||||
if (conversionService.canConvert(sourceTypeDesc, targetTypeDesc)) {
|
||||
return (T) conversionService.convert(convertedValue, sourceTypeDesc, targetTypeDesc);
|
||||
}
|
||||
@@ -223,7 +227,8 @@ class TypeConverterDelegate {
|
||||
}
|
||||
if (editor != null) {
|
||||
msg.append(": PropertyEditor [").append(editor.getClass().getName()).append(
|
||||
"] returned inappropriate value");
|
||||
"] returned inappropriate value of type [").append(
|
||||
ClassUtils.getDescriptiveType(convertedValue)).append("]");
|
||||
throw new IllegalArgumentException(msg.toString());
|
||||
}
|
||||
else {
|
||||
@@ -459,11 +464,20 @@ class TypeConverterDelegate {
|
||||
protected Collection convertToTypedCollection(
|
||||
Collection original, String propertyName, Class requiredType, TypeDescriptor typeDescriptor) {
|
||||
|
||||
boolean originalAllowed = requiredType.isInstance(original);
|
||||
if (!originalAllowed && !Collection.class.isAssignableFrom(requiredType)) {
|
||||
if (!Collection.class.isAssignableFrom(requiredType)) {
|
||||
return original;
|
||||
}
|
||||
|
||||
boolean approximable = CollectionFactory.isApproximableCollectionType(requiredType);
|
||||
if (!approximable && !canCreateCopy(requiredType)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Custom Collection type [" + original.getClass().getName() +
|
||||
"] does not allow for creating a copy - injecting original Collection as-is");
|
||||
}
|
||||
return original;
|
||||
}
|
||||
|
||||
boolean originalAllowed = requiredType.isInstance(original);
|
||||
MethodParameter methodParam = typeDescriptor.getMethodParameter();
|
||||
Class elementType = null;
|
||||
if (methodParam != null) {
|
||||
@@ -488,14 +502,14 @@ class TypeConverterDelegate {
|
||||
catch (Throwable ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Cannot access Collection of type [" + original.getClass().getName() +
|
||||
"] - injecting original Collection as-is", ex);
|
||||
"] - injecting original Collection as-is: " + ex);
|
||||
}
|
||||
return original;
|
||||
}
|
||||
|
||||
Collection convertedCopy;
|
||||
try {
|
||||
if (CollectionFactory.isApproximableCollectionType(requiredType)) {
|
||||
if (approximable) {
|
||||
convertedCopy = CollectionFactory.createApproximateCollection(original, original.size());
|
||||
}
|
||||
else {
|
||||
@@ -505,7 +519,7 @@ class TypeConverterDelegate {
|
||||
catch (Throwable ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Cannot create copy of Collection type [" + original.getClass().getName() +
|
||||
"] - injecting original Collection as-is", ex);
|
||||
"] - injecting original Collection as-is: " + ex);
|
||||
}
|
||||
return original;
|
||||
}
|
||||
@@ -528,7 +542,7 @@ class TypeConverterDelegate {
|
||||
catch (Throwable ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Collection type [" + original.getClass().getName() +
|
||||
"] seems to be read-only - injecting original Collection as-is", ex);
|
||||
"] seems to be read-only - injecting original Collection as-is: " + ex);
|
||||
}
|
||||
return original;
|
||||
}
|
||||
@@ -541,11 +555,20 @@ class TypeConverterDelegate {
|
||||
protected Map convertToTypedMap(
|
||||
Map original, String propertyName, Class requiredType, TypeDescriptor typeDescriptor) {
|
||||
|
||||
boolean originalAllowed = requiredType.isInstance(original);
|
||||
if (!originalAllowed && !Map.class.isAssignableFrom(requiredType)) {
|
||||
if (!Map.class.isAssignableFrom(requiredType)) {
|
||||
return original;
|
||||
}
|
||||
|
||||
boolean approximable = CollectionFactory.isApproximableMapType(requiredType);
|
||||
if (!approximable && !canCreateCopy(requiredType)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Custom Map type [" + original.getClass().getName() +
|
||||
"] does not allow for creating a copy - injecting original Map as-is");
|
||||
}
|
||||
return original;
|
||||
}
|
||||
|
||||
boolean originalAllowed = requiredType.isInstance(original);
|
||||
Class keyType = null;
|
||||
Class valueType = null;
|
||||
MethodParameter methodParam = typeDescriptor.getMethodParameter();
|
||||
@@ -572,14 +595,14 @@ class TypeConverterDelegate {
|
||||
catch (Throwable ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Cannot access Map of type [" + original.getClass().getName() +
|
||||
"] - injecting original Map as-is", ex);
|
||||
"] - injecting original Map as-is: " + ex);
|
||||
}
|
||||
return original;
|
||||
}
|
||||
|
||||
Map convertedCopy;
|
||||
try {
|
||||
if (CollectionFactory.isApproximableMapType(requiredType)) {
|
||||
if (approximable) {
|
||||
convertedCopy = CollectionFactory.createApproximateMap(original, original.size());
|
||||
}
|
||||
else {
|
||||
@@ -589,7 +612,7 @@ class TypeConverterDelegate {
|
||||
catch (Throwable ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Cannot create copy of Map type [" + original.getClass().getName() +
|
||||
"] - injecting original Map as-is", ex);
|
||||
"] - injecting original Map as-is: " + ex);
|
||||
}
|
||||
return original;
|
||||
}
|
||||
@@ -617,7 +640,7 @@ class TypeConverterDelegate {
|
||||
catch (Throwable ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Map type [" + original.getClass().getName() +
|
||||
"] seems to be read-only - injecting original Map as-is", ex);
|
||||
"] seems to be read-only - injecting original Map as-is: " + ex);
|
||||
}
|
||||
return original;
|
||||
}
|
||||
@@ -638,4 +661,9 @@ class TypeConverterDelegate {
|
||||
null);
|
||||
}
|
||||
|
||||
private boolean canCreateCopy(Class requiredType) {
|
||||
return (!requiredType.isInterface() && !Modifier.isAbstract(requiredType.getModifiers()) &&
|
||||
Modifier.isPublic(requiredType.getModifiers()) && ClassUtils.hasConstructor(requiredType));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+13
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2011 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.beans.factory.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -46,16 +47,25 @@ import java.lang.annotation.Target;
|
||||
* declared value type. In case of a Map, the keys must be declared as
|
||||
* type String and will be resolved to the corresponding bean names.
|
||||
*
|
||||
* <p>Please do consult the javadoc for the {@link AutowiredAnnotationBeanPostProcessor}
|
||||
* <p>Note that actual injection is performed through a
|
||||
* {@link org.springframework.beans.factory.config.BeanPostProcessor
|
||||
* BeanPostProcessor} which in turn means that you <em>cannot</em>
|
||||
* use {@code @Autowired} to inject references into
|
||||
* {@link org.springframework.beans.factory.config.BeanPostProcessor
|
||||
* BeanPostProcessor} or {@link BeanFactoryPostProcessor} types. Please
|
||||
* consult the javadoc for the {@link AutowiredAnnotationBeanPostProcessor}
|
||||
* class (which, by default, checks for the presence of this annotation).
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Mark Fisher
|
||||
* @since 2.5
|
||||
* @see AutowiredAnnotationBeanPostProcessor
|
||||
* @see Qualifier
|
||||
* @see Value
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Autowired {
|
||||
|
||||
/**
|
||||
|
||||
+24
-20
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -50,6 +50,7 @@ import org.springframework.beans.factory.config.InstantiationAwareBeanPostProces
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.core.BridgeMethodResolver;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.Ordered;
|
||||
@@ -61,8 +62,11 @@ import org.springframework.util.ReflectionUtils;
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.config.BeanPostProcessor} implementation
|
||||
* that autowires annotated fields, setter methods and arbitrary config methods.
|
||||
* Such members to be injected are detected through a Java 5 annotation:
|
||||
* by default, Spring's {@link Autowired} annotation.
|
||||
* Such members to be injected are detected through a Java 5 annotation: by default,
|
||||
* Spring's {@link Autowired @Autowired} and {@link Value @Value} annotations.
|
||||
*
|
||||
* <p>Also supports JSR-330's {@link javax.inject.Inject @Inject} annotation,
|
||||
* if available, as a direct alternative to Spring's own <code>@Autowired</code>.
|
||||
*
|
||||
* <p>Only one constructor (at max) of any given bean class may carry this
|
||||
* annotation with the 'required' parameter set to <code>true</code>,
|
||||
@@ -77,27 +81,25 @@ import org.springframework.util.ReflectionUtils;
|
||||
* <p>Fields are injected right after construction of a bean, before any
|
||||
* config methods are invoked. Such a config field does not have to be public.
|
||||
*
|
||||
* <p>Config methods may have an arbitrary name and any number of arguments;
|
||||
* each of those arguments will be autowired with a matching bean in the
|
||||
* Spring container. Bean property setter methods are effectively just
|
||||
* a special case of such a general config method. Such config methods
|
||||
* do not have to be public.
|
||||
*
|
||||
* <p>Also supports JSR-330's {@link javax.inject.Inject} annotation, if available.
|
||||
* <p>Config methods may have an arbitrary name and any number of arguments; each of
|
||||
* those arguments will be autowired with a matching bean in the Spring container.
|
||||
* Bean property setter methods are effectively just a special case of such a
|
||||
* general config method. Config methods do not have to be public.
|
||||
*
|
||||
* <p>Note: A default AutowiredAnnotationBeanPostProcessor will be registered
|
||||
* by the "context:annotation-config" and "context:component-scan" XML tags.
|
||||
* Remove or turn off the default annotation configuration there if you intend
|
||||
* to specify a custom AutowiredAnnotationBeanPostProcessor bean definition.
|
||||
* <p><b>NOTE:</b> Annotation injection will be performed <i>before</i> XML injection; thus
|
||||
* the latter configuration will override the former for properties wired through
|
||||
* both approaches.
|
||||
*
|
||||
* <p><b>NOTE:</b> Annotation injection will be performed <i>before</i> XML injection;
|
||||
* thus the latter configuration will override the former for properties wired through
|
||||
* both approaches.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Mark Fisher
|
||||
* @since 2.5
|
||||
* @see #setAutowiredAnnotationType
|
||||
* @see Autowired
|
||||
* @see Value
|
||||
*/
|
||||
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
|
||||
implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
|
||||
@@ -115,8 +117,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
|
||||
private ConfigurableListableBeanFactory beanFactory;
|
||||
|
||||
private final Map<Class<?>, Constructor[]> candidateConstructorsCache =
|
||||
new ConcurrentHashMap<Class<?>, Constructor[]>();
|
||||
private final Map<Class<?>, Constructor<?>[]> candidateConstructorsCache =
|
||||
new ConcurrentHashMap<Class<?>, Constructor<?>[]>();
|
||||
|
||||
private final Map<Class<?>, InjectionMetadata> injectionMetadataCache =
|
||||
new ConcurrentHashMap<Class<?>, InjectionMetadata>();
|
||||
@@ -305,7 +307,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
}
|
||||
|
||||
|
||||
private InjectionMetadata findAutowiringMetadata(Class clazz) {
|
||||
private InjectionMetadata findAutowiringMetadata(Class<?> clazz) {
|
||||
// Quick check on the concurrent map first, with minimal locking.
|
||||
InjectionMetadata metadata = this.injectionMetadataCache.get(clazz);
|
||||
if (metadata == null) {
|
||||
@@ -320,7 +322,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
return metadata;
|
||||
}
|
||||
|
||||
private InjectionMetadata buildAutowiringMetadata(Class clazz) {
|
||||
private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
|
||||
LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();
|
||||
Class<?> targetClass = clazz;
|
||||
|
||||
@@ -340,7 +342,9 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
}
|
||||
}
|
||||
for (Method method : targetClass.getDeclaredMethods()) {
|
||||
Annotation annotation = findAutowiredAnnotation(method);
|
||||
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
|
||||
Annotation annotation = BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod) ?
|
||||
findAutowiredAnnotation(bridgedMethod) : findAutowiredAnnotation(method);
|
||||
if (annotation != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
|
||||
if (Modifier.isStatic(method.getModifiers())) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
@@ -534,7 +538,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
arguments = resolveCachedArguments(beanName);
|
||||
}
|
||||
else {
|
||||
Class[] paramTypes = method.getParameterTypes();
|
||||
Class<?>[] paramTypes = method.getParameterTypes();
|
||||
arguments = new Object[paramTypes.length];
|
||||
DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length];
|
||||
Set<String> autowiredBeanNames = new LinkedHashSet<String>(paramTypes.length);
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2011 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,10 +34,10 @@ import java.lang.annotation.Target;
|
||||
* @author Ramnivas Laddad
|
||||
* @since 2.0
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
public @interface Configurable {
|
||||
|
||||
/**
|
||||
|
||||
+14
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 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.
|
||||
@@ -168,21 +168,23 @@ public class InjectionMetadata {
|
||||
*/
|
||||
protected boolean checkPropertySkipping(PropertyValues pvs) {
|
||||
if (this.skip == null) {
|
||||
synchronized (pvs) {
|
||||
if (this.skip == null) {
|
||||
if (this.pd != null && pvs != null) {
|
||||
if (pvs.contains(this.pd.getName())) {
|
||||
// Explicit value provided as part of the bean definition.
|
||||
this.skip = true;
|
||||
return true;
|
||||
}
|
||||
else if (pvs instanceof MutablePropertyValues) {
|
||||
((MutablePropertyValues) pvs).registerProcessedProperty(this.pd.getName());
|
||||
if (pvs != null) {
|
||||
synchronized (pvs) {
|
||||
if (this.skip == null) {
|
||||
if (this.pd != null) {
|
||||
if (pvs.contains(this.pd.getName())) {
|
||||
// Explicit value provided as part of the bean definition.
|
||||
this.skip = true;
|
||||
return true;
|
||||
}
|
||||
else if (pvs instanceof MutablePropertyValues) {
|
||||
((MutablePropertyValues) pvs).registerProcessedProperty(this.pd.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
this.skip = false;
|
||||
}
|
||||
}
|
||||
this.skip = false;
|
||||
}
|
||||
return this.skip;
|
||||
}
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2011 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,9 +31,10 @@ import java.lang.annotation.Target;
|
||||
* @author Mark Fisher
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.5
|
||||
* @see Autowired
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
public @interface Qualifier {
|
||||
|
||||
+6
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2011 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.
|
||||
@@ -164,8 +164,11 @@ public class RequiredAnnotationBeanPostProcessor extends InstantiationAwareBeanP
|
||||
* @return <code>true</code> to skip the bean; <code>false</code> to process it
|
||||
*/
|
||||
protected boolean shouldSkip(ConfigurableListableBeanFactory beanFactory, String beanName) {
|
||||
return (beanFactory != null && beanFactory.containsBeanDefinition(beanName) &&
|
||||
Boolean.TRUE.equals(beanFactory.getBeanDefinition(beanName).getAttribute(SKIP_REQUIRED_CHECK_ATTRIBUTE)));
|
||||
if (beanFactory == null || !beanFactory.containsBeanDefinition(beanName)) {
|
||||
return false;
|
||||
}
|
||||
Object value = beanFactory.getBeanDefinition(beanName).getAttribute(SKIP_REQUIRED_CHECK_ATTRIBUTE);
|
||||
return (value != null && (Boolean.TRUE.equals(value) || Boolean.valueOf(value.toString())));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+15
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2011 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.beans.factory.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -31,13 +32,25 @@ import java.lang.annotation.Target;
|
||||
* <p>A common use case is to assign default field values using
|
||||
* "#{systemProperties.myProp}" style expressions.
|
||||
*
|
||||
* <p>Note that actual processing of the {@code @Value} annotation is performed
|
||||
* by a {@link org.springframework.beans.factory.config.BeanPostProcessor
|
||||
* BeanPostProcessor} which in turn means that you <em>cannot</em> use
|
||||
* {@code @Value} within
|
||||
* {@link org.springframework.beans.factory.config.BeanPostProcessor
|
||||
* BeanPostProcessor} or {@link BeanFactoryPostProcessor} types. Please
|
||||
* consult the javadoc for the {@link AutowiredAnnotationBeanPostProcessor}
|
||||
* class (which, by default, checks for the presence of this annotation).
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @see AutowiredAnnotationBeanPostProcessor
|
||||
* @see Autowired
|
||||
* @see org.springframework.beans.factory.config.BeanExpressionResolver
|
||||
* @see org.springframework.beans.factory.support.AutowireCandidateResolver#getSuggestedValue
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Value {
|
||||
|
||||
/**
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -115,7 +115,7 @@ public class BeanDefinitionVisitor {
|
||||
}
|
||||
|
||||
protected void visitFactoryMethodName(BeanDefinition beanDefinition) {
|
||||
String factoryMethodName = beanDefinition.getFactoryBeanName();
|
||||
String factoryMethodName = beanDefinition.getFactoryMethodName();
|
||||
if (factoryMethodName != null) {
|
||||
String resolvedName = resolveStringValue(factoryMethodName);
|
||||
if (!factoryMethodName.equals(resolvedName)) {
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2011 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.
|
||||
@@ -173,7 +173,7 @@ public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, Single
|
||||
* @param requiredType type of the property
|
||||
* @param propertyEditorClass the {@link PropertyEditor} class to register
|
||||
*/
|
||||
void registerCustomEditor(Class requiredType, Class<? extends PropertyEditor> propertyEditorClass);
|
||||
void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass);
|
||||
|
||||
/**
|
||||
* Initialize the given PropertyEditorRegistry with the custom editors
|
||||
|
||||
+17
-15
@@ -28,7 +28,6 @@ import java.security.PrivilegedExceptionAction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
@@ -144,7 +143,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
|
||||
/** Cache of filtered PropertyDescriptors: bean Class -> PropertyDescriptor array */
|
||||
private final Map<Class, PropertyDescriptor[]> filteredPropertyDescriptorsCache =
|
||||
new HashMap<Class, PropertyDescriptor[]>();
|
||||
new ConcurrentHashMap<Class, PropertyDescriptor[]>();
|
||||
|
||||
|
||||
/**
|
||||
@@ -567,7 +566,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class predictBeanType(String beanName, RootBeanDefinition mbd, Class[] typesToMatch) {
|
||||
protected Class predictBeanType(String beanName, RootBeanDefinition mbd, Class... typesToMatch) {
|
||||
Class beanClass;
|
||||
if (mbd.getFactoryMethodName() != null) {
|
||||
beanClass = getTypeForFactoryMethod(beanName, mbd, typesToMatch);
|
||||
@@ -1201,22 +1200,25 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
* @see #isExcludedFromDependencyCheck
|
||||
*/
|
||||
protected PropertyDescriptor[] filterPropertyDescriptorsForDependencyCheck(BeanWrapper bw) {
|
||||
synchronized (this.filteredPropertyDescriptorsCache) {
|
||||
PropertyDescriptor[] filtered = this.filteredPropertyDescriptorsCache.get(bw.getWrappedClass());
|
||||
if (filtered == null) {
|
||||
List<PropertyDescriptor> pds =
|
||||
new LinkedList<PropertyDescriptor>(Arrays.asList(bw.getPropertyDescriptors()));
|
||||
for (Iterator<PropertyDescriptor> it = pds.iterator(); it.hasNext();) {
|
||||
PropertyDescriptor pd = it.next();
|
||||
if (isExcludedFromDependencyCheck(pd)) {
|
||||
it.remove();
|
||||
PropertyDescriptor[] filtered = this.filteredPropertyDescriptorsCache.get(bw.getWrappedClass());
|
||||
if (filtered == null) {
|
||||
synchronized (this.filteredPropertyDescriptorsCache) {
|
||||
filtered = this.filteredPropertyDescriptorsCache.get(bw.getWrappedClass());
|
||||
if (filtered == null) {
|
||||
List<PropertyDescriptor> pds =
|
||||
new LinkedList<PropertyDescriptor>(Arrays.asList(bw.getPropertyDescriptors()));
|
||||
for (Iterator<PropertyDescriptor> it = pds.iterator(); it.hasNext();) {
|
||||
PropertyDescriptor pd = it.next();
|
||||
if (isExcludedFromDependencyCheck(pd)) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
filtered = pds.toArray(new PropertyDescriptor[pds.size()]);
|
||||
this.filteredPropertyDescriptorsCache.put(bw.getWrappedClass(), filtered);
|
||||
}
|
||||
filtered = pds.toArray(new PropertyDescriptor[pds.size()]);
|
||||
this.filteredPropertyDescriptorsCache.put(bw.getWrappedClass(), filtered);
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+16
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -42,6 +42,7 @@ import org.springframework.beans.PropertyEditorRegistry;
|
||||
import org.springframework.beans.PropertyEditorRegistrySupport;
|
||||
import org.springframework.beans.SimpleTypeConverter;
|
||||
import org.springframework.beans.TypeConverter;
|
||||
import org.springframework.beans.TypeMismatchException;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.BeanCurrentlyInCreationException;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
@@ -166,6 +167,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
private final ThreadLocal<Object> prototypesCurrentlyInCreation =
|
||||
new NamedThreadLocal<Object>("Prototype beans currently in creation");
|
||||
|
||||
|
||||
/**
|
||||
* Create a new AbstractBeanFactory.
|
||||
*/
|
||||
@@ -189,7 +191,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
public Object getBean(String name) throws BeansException {
|
||||
return doGetBean(name, null, null, false);
|
||||
}
|
||||
|
||||
|
||||
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
|
||||
return doGetBean(name, requiredType, null, false);
|
||||
}
|
||||
@@ -346,7 +348,16 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
|
||||
// Check if required type matches the type of the actual bean instance.
|
||||
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
|
||||
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
|
||||
try {
|
||||
return getTypeConverter().convertIfNecessary(bean, requiredType);
|
||||
}
|
||||
catch (TypeMismatchException ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Failed to convert bean '" + name + "' to required type [" +
|
||||
ClassUtils.getQualifiedName(requiredType) + "]", ex);
|
||||
}
|
||||
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
|
||||
}
|
||||
}
|
||||
return (T) bean;
|
||||
}
|
||||
@@ -682,7 +693,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
return this.propertyEditorRegistrars;
|
||||
}
|
||||
|
||||
public void registerCustomEditor(Class requiredType, Class<? extends PropertyEditor> propertyEditorClass) {
|
||||
public void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass) {
|
||||
Assert.notNull(requiredType, "Required type must not be null");
|
||||
Assert.isAssignable(PropertyEditor.class, propertyEditorClass);
|
||||
this.customEditors.put(requiredType, propertyEditorClass);
|
||||
@@ -1253,7 +1264,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Class doResolveBeanClass(RootBeanDefinition mbd, Class... typesToMatch) throws ClassNotFoundException {
|
||||
if (!ObjectUtils.isEmpty(typesToMatch)) {
|
||||
ClassLoader tempClassLoader = getTempClassLoader();
|
||||
|
||||
+17
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 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,9 @@
|
||||
|
||||
package org.springframework.beans.factory.support;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.NotSerializableException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectStreamException;
|
||||
import java.io.Serializable;
|
||||
import java.lang.annotation.Annotation;
|
||||
@@ -541,7 +543,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
}
|
||||
|
||||
/**
|
||||
* Considers all beans as eligible for metdata caching
|
||||
* Considers all beans as eligible for metadata caching
|
||||
* if the factory's configuration has been marked as frozen.
|
||||
* @see #freezeConfiguration()
|
||||
*/
|
||||
@@ -554,9 +556,11 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
if (this.logger.isInfoEnabled()) {
|
||||
this.logger.info("Pre-instantiating singletons in " + this);
|
||||
}
|
||||
|
||||
synchronized (this.beanDefinitionMap) {
|
||||
for (String beanName : this.beanDefinitionNames) {
|
||||
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
|
||||
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
|
||||
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
|
||||
for (String beanName : beanNames) {
|
||||
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
|
||||
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
|
||||
if (isFactoryBean(beanName)) {
|
||||
@@ -570,7 +574,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
}, getAccessControlContext());
|
||||
}
|
||||
else {
|
||||
isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean) factory).isEagerInit();
|
||||
isEagerInit = (factory instanceof SmartFactoryBean &&
|
||||
((SmartFactoryBean) factory).isEagerInit());
|
||||
}
|
||||
if (isEagerInit) {
|
||||
getBean(beanName);
|
||||
@@ -664,8 +669,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
destroySingleton(beanName);
|
||||
}
|
||||
|
||||
// Reset all bean definitions that have the given bean as parent
|
||||
// (recursively).
|
||||
// Reset all bean definitions that have the given bean as parent (recursively).
|
||||
for (String bdName : this.beanDefinitionNames) {
|
||||
if (!beanName.equals(bdName)) {
|
||||
BeanDefinition bd = this.beanDefinitionMap.get(bdName);
|
||||
@@ -711,7 +715,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
if (value != null) {
|
||||
if (value instanceof String) {
|
||||
String strVal = resolveEmbeddedValue((String) value);
|
||||
BeanDefinition bd = (containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
|
||||
BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
|
||||
value = evaluateBeanDefinitionString(strVal, bd);
|
||||
}
|
||||
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
|
||||
@@ -944,6 +948,11 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
// Serialization support
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
|
||||
throw new NotSerializableException("DefaultListableBeanFactory itself is not deserializable - " +
|
||||
"just a SerializedBeanFactoryReference is");
|
||||
}
|
||||
|
||||
protected Object writeReplace() throws ObjectStreamException {
|
||||
if (this.serializationId != null) {
|
||||
return new SerializedBeanFactoryReference(this.serializationId);
|
||||
|
||||
+6
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 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.
|
||||
@@ -1176,7 +1176,10 @@ public class BeanDefinitionParserDelegate {
|
||||
}
|
||||
else {
|
||||
// Child element is what we're looking for.
|
||||
if (valueEle != null) {
|
||||
if (nodeNameEquals(candidateEle, DESCRIPTION_ELEMENT)) {
|
||||
// the element is a <description> -> ignore it
|
||||
}
|
||||
else if (valueEle != null) {
|
||||
error("<entry> element must not contain more than one value sub-element", entryEle);
|
||||
}
|
||||
else {
|
||||
@@ -1422,7 +1425,7 @@ public class BeanDefinitionParserDelegate {
|
||||
/**
|
||||
* Determine whether the name of the supplied node is equal to the supplied name.
|
||||
* <p>The default implementation checks the supplied desired name against both
|
||||
* {@link Node#getNodeName()) and {@link Node#getLocalName()}.
|
||||
* {@link Node#getNodeName()} and {@link Node#getLocalName()}.
|
||||
* <p>Subclasses may override the default implementation to provide a different
|
||||
* mechanism for comparing node names.
|
||||
* @param node the node to compare
|
||||
|
||||
+1
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2011 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,10 +34,6 @@ public class CurrencyEditor extends PropertyEditorSupport {
|
||||
setValue(Currency.getInstance(text));
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation returns <code>null</code> to indicate that
|
||||
* there is no appropriate text representation.
|
||||
*/
|
||||
@Override
|
||||
public String getAsText() {
|
||||
Currency value = (Currency) getValue();
|
||||
|
||||
+5
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2011 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.
|
||||
@@ -77,7 +77,10 @@ public class CustomDateEditor extends PropertyEditorSupport {
|
||||
* thrown if the String does not exactly match the length specified. This is useful
|
||||
* because SimpleDateFormat does not enforce strict parsing of the year part,
|
||||
* not even with <code>setLenient(false)</code>. Without an "exactDateLength"
|
||||
* specified, the "01/01/05" would get parsed to "01/01/0005".
|
||||
* specified, the "01/01/05" would get parsed to "01/01/0005". However, even
|
||||
* with an "exactDateLength" specified, prepended zeros in the day or month
|
||||
* part may still allow for a shorter year part, so consider this as just
|
||||
* one more assertion that gets you closer to the intended date format.
|
||||
* @param dateFormat DateFormat to use for parsing and rendering
|
||||
* @param allowEmpty if empty strings should be allowed
|
||||
* @param exactDateLength the exact expected length of the date String
|
||||
|
||||
+3
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 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,6 +34,7 @@ import org.springframework.beans.propertyeditors.InputSourceEditor;
|
||||
import org.springframework.beans.propertyeditors.InputStreamEditor;
|
||||
import org.springframework.beans.propertyeditors.URIEditor;
|
||||
import org.springframework.beans.propertyeditors.URLEditor;
|
||||
import org.springframework.core.io.ContextResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceEditor;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
@@ -84,6 +85,7 @@ public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
|
||||
public void registerCustomEditors(PropertyEditorRegistry registry) {
|
||||
ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader);
|
||||
doRegisterEditor(registry, Resource.class, baseEditor);
|
||||
doRegisterEditor(registry, ContextResource.class, baseEditor);
|
||||
doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor));
|
||||
doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor));
|
||||
doRegisterEditor(registry, File.class, new FileEditor(baseEditor));
|
||||
|
||||
+16
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,10 +19,11 @@ package org.springframework.beans;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Keith Donald
|
||||
* @author Juergen Hoeller
|
||||
@@ -117,6 +118,19 @@ public class BeanWrapperAutoGrowingTests {
|
||||
assertNotNull(wrapper.getPropertyValue("list[3]"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPropertyValueAutoGrowListFailsAgainstLimit() {
|
||||
wrapper.setAutoGrowCollectionLimit(2);
|
||||
try {
|
||||
assertNotNull(wrapper.getPropertyValue("list[4]"));
|
||||
fail("Should have thrown InvalidPropertyException");
|
||||
}
|
||||
catch (InvalidPropertyException ex) {
|
||||
// expected
|
||||
assertTrue(ex.getRootCause() instanceof IndexOutOfBoundsException);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPropertyValueAutoGrowMultiDimensionalList() {
|
||||
assertNotNull(wrapper.getPropertyValue("multiList[0][0]"));
|
||||
|
||||
+12
@@ -155,6 +155,18 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- The <description> element below caused parsing exception prior to resolution of SPR-8563 -->
|
||||
<bean id="mapWithDescriptionInEntry" class="org.springframework.beans.factory.xml.HasMap">
|
||||
<property name="map">
|
||||
<map>
|
||||
<entry key="e1">
|
||||
<description>A map entry with a description</description>
|
||||
<value>v1</value>
|
||||
</entry>
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="fooKey" class="java.lang.String">
|
||||
<constructor-arg value="foo"/>
|
||||
</bean>
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
<dependency org="org.hsqldb" name="com.springsource.org.hsqldb" rev="1.8.0.9" conf="test->runtime"/>
|
||||
<dependency org="org.apache.poi" name="com.springsource.org.apache.poi" rev="3.0.2.FINAL" conf="test->compile"/>
|
||||
<dependency org="org.easymock" name="com.springsource.org.easymock" rev="2.5.1" conf="test->compile"/>
|
||||
<dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit.version}" conf="test->runtime"/>
|
||||
<dependency org="org.junit" name="com.springsource.org.junit" rev="${junit.version}" conf="test->runtime"/>
|
||||
</dependencies>
|
||||
|
||||
</ivy-module>
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.5.BUILD-SNAPSHOT</version>
|
||||
<version>3.0.7.RELEASE</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.5.BUILD-SNAPSHOT</version>
|
||||
<version>3.0.7.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
|
||||
|
||||
+9
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2011 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,6 +17,7 @@
|
||||
package org.springframework.cache.ehcache;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import net.sf.ehcache.CacheException;
|
||||
import net.sf.ehcache.CacheManager;
|
||||
@@ -97,23 +98,17 @@ public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, Ini
|
||||
|
||||
public void afterPropertiesSet() throws IOException, CacheException {
|
||||
logger.info("Initializing EHCache CacheManager");
|
||||
if (this.shared) {
|
||||
// Shared CacheManager singleton at the VM level.
|
||||
if (this.configLocation != null) {
|
||||
this.cacheManager = CacheManager.create(this.configLocation.getInputStream());
|
||||
if (this.configLocation != null) {
|
||||
InputStream is = this.configLocation.getInputStream();
|
||||
try {
|
||||
this.cacheManager = (this.shared ? CacheManager.create(is) : new CacheManager(is));
|
||||
}
|
||||
else {
|
||||
this.cacheManager = CacheManager.create();
|
||||
finally {
|
||||
is.close();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Independent CacheManager instance (the default).
|
||||
if (this.configLocation != null) {
|
||||
this.cacheManager = new CacheManager(this.configLocation.getInputStream());
|
||||
}
|
||||
else {
|
||||
this.cacheManager = new CacheManager();
|
||||
}
|
||||
this.cacheManager = (this.shared ? CacheManager.create() : new CacheManager());
|
||||
}
|
||||
if (this.cacheManagerName != null) {
|
||||
this.cacheManager.setName(this.cacheManagerName);
|
||||
|
||||
+8
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2011 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,6 +40,13 @@ public class LocalTaskExecutorThreadPool implements ThreadPool {
|
||||
private Executor taskExecutor;
|
||||
|
||||
|
||||
public void setInstanceId(String schedInstId) {
|
||||
}
|
||||
|
||||
public void setInstanceName(String schedName) {
|
||||
}
|
||||
|
||||
|
||||
public void initialize() throws SchedulerConfigException {
|
||||
// Absolutely needs thread-bound TaskExecutor to initialize.
|
||||
this.taskExecutor = SchedulerFactoryBean.getConfigTimeTaskExecutor();
|
||||
|
||||
+21
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2011 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.scheduling.quartz;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
@@ -34,7 +35,6 @@ import org.quartz.SchedulerListener;
|
||||
import org.quartz.Trigger;
|
||||
import org.quartz.TriggerListener;
|
||||
import org.quartz.spi.ClassLoadHelper;
|
||||
import org.quartz.xml.JobSchedulingDataProcessor;
|
||||
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
@@ -240,9 +240,25 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware {
|
||||
if (this.jobSchedulingDataLocations != null) {
|
||||
ClassLoadHelper clh = new ResourceLoaderClassLoadHelper(this.resourceLoader);
|
||||
clh.initialize();
|
||||
JobSchedulingDataProcessor dataProcessor = new JobSchedulingDataProcessor(clh, true, true);
|
||||
for (String location : this.jobSchedulingDataLocations) {
|
||||
dataProcessor.processFileAndScheduleJobs(location, getScheduler(), this.overwriteExistingJobs);
|
||||
try {
|
||||
// Quartz 1.8 or higher?
|
||||
Class dataProcessorClass = getClass().getClassLoader().loadClass("org.quartz.xml.XMLSchedulingDataProcessor");
|
||||
logger.debug("Using Quartz 1.8 XMLSchedulingDataProcessor");
|
||||
Object dataProcessor = dataProcessorClass.getConstructor(ClassLoadHelper.class).newInstance(clh);
|
||||
Method processFileAndScheduleJobs = dataProcessorClass.getMethod("processFileAndScheduleJobs", String.class, Scheduler.class);
|
||||
for (String location : this.jobSchedulingDataLocations) {
|
||||
processFileAndScheduleJobs.invoke(dataProcessor, location, getScheduler());
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// Quartz 1.6
|
||||
Class dataProcessorClass = getClass().getClassLoader().loadClass("org.quartz.xml.JobSchedulingDataProcessor");
|
||||
logger.debug("Using Quartz 1.6 JobSchedulingDataProcessor");
|
||||
Object dataProcessor = dataProcessorClass.getConstructor(ClassLoadHelper.class, boolean.class, boolean.class).newInstance(clh, true, true);
|
||||
Method processFileAndScheduleJobs = dataProcessorClass.getMethod("processFileAndScheduleJobs", String.class, Scheduler.class, boolean.class);
|
||||
for (String location : this.jobSchedulingDataLocations) {
|
||||
processFileAndScheduleJobs.invoke(dataProcessor, location, getScheduler(), this.overwriteExistingJobs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 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.
|
||||
@@ -74,9 +74,9 @@ import org.springframework.util.CollectionUtils;
|
||||
* automatically apply to Scheduler operations performed within those scopes.
|
||||
* Alternatively, you may add transactional advice for the Scheduler itself.
|
||||
*
|
||||
* <p><b>Note:</b> This version of Spring's SchedulerFactoryBean requires
|
||||
* Quartz 1.5.x or 1.6.x. The "jobSchedulingDataLocation" feature requires
|
||||
* Quartz 1.6.1 or higher (as of Spring 2.5.5).
|
||||
* <p><b>Note:</b> This version of Spring's SchedulerFactoryBean supports Quartz 1.x,
|
||||
* more specifically Quartz 1.5 or higher. The "jobSchedulingDataLocation" feature
|
||||
* requires Quartz 1.6.1 or higher (as of Spring 2.5.5).
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 18.02.2004
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.dbcp" rev="1.2.2.osgi" conf="test->runtime"/>
|
||||
<dependency org="org.apache.log4j" name="com.springsource.org.apache.log4j" rev="1.2.15" conf="test->runtime"/>
|
||||
<dependency org="org.easymock" name="com.springsource.org.easymock" rev="2.5.1" conf="test->compile"/>
|
||||
<dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit.version}" conf="test->runtime"/>
|
||||
<dependency org="org.junit" name="com.springsource.org.junit" rev="${junit.version}" conf="test->runtime"/>
|
||||
<dependency org="org.slf4j" name="com.springsource.slf4j.jcl" rev="${slf4j.version}" conf="test->runtime"/>
|
||||
</dependencies>
|
||||
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.5.BUILD-SNAPSHOT</version>
|
||||
<version>3.0.7.RELEASE</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.5.BUILD-SNAPSHOT</version>
|
||||
<version>3.0.7.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
+37
-35
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2011 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.
|
||||
@@ -58,6 +58,7 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.config.DependencyDescriptor;
|
||||
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.core.BridgeMethodResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.jndi.support.SimpleJndiBeanFactory;
|
||||
@@ -303,7 +304,7 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
|
||||
}
|
||||
|
||||
|
||||
private InjectionMetadata findResourceMetadata(final Class clazz) {
|
||||
private InjectionMetadata findResourceMetadata(final Class<?> clazz) {
|
||||
// Quick check on the concurrent map first, with minimal locking.
|
||||
InjectionMetadata metadata = this.injectionMetadataCache.get(clazz);
|
||||
if (metadata == null) {
|
||||
@@ -338,40 +339,41 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
|
||||
}
|
||||
}
|
||||
for (Method method : targetClass.getDeclaredMethods()) {
|
||||
if (webServiceRefClass != null && method.isAnnotationPresent(webServiceRefClass) &&
|
||||
method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
|
||||
if (Modifier.isStatic(method.getModifiers())) {
|
||||
throw new IllegalStateException("@WebServiceRef annotation is not supported on static methods");
|
||||
}
|
||||
if (method.getParameterTypes().length != 1) {
|
||||
throw new IllegalStateException("@WebServiceRef annotation requires a single-arg method: " + method);
|
||||
}
|
||||
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
|
||||
currElements.add(new WebServiceRefElement(method, pd));
|
||||
}
|
||||
else if (ejbRefClass != null && method.isAnnotationPresent(ejbRefClass) &&
|
||||
method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
|
||||
if (Modifier.isStatic(method.getModifiers())) {
|
||||
throw new IllegalStateException("@EJB annotation is not supported on static methods");
|
||||
}
|
||||
if (method.getParameterTypes().length != 1) {
|
||||
throw new IllegalStateException("@EJB annotation requires a single-arg method: " + method);
|
||||
}
|
||||
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
|
||||
currElements.add(new EjbRefElement(method, pd));
|
||||
}
|
||||
else if (method.isAnnotationPresent(Resource.class) &&
|
||||
method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
|
||||
if (Modifier.isStatic(method.getModifiers())) {
|
||||
throw new IllegalStateException("@Resource annotation is not supported on static methods");
|
||||
}
|
||||
Class[] paramTypes = method.getParameterTypes();
|
||||
if (paramTypes.length != 1) {
|
||||
throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
|
||||
}
|
||||
if (!ignoredResourceTypes.contains(paramTypes[0].getName())) {
|
||||
method = BridgeMethodResolver.findBridgedMethod(method);
|
||||
Method mostSpecificMethod = BridgeMethodResolver.findBridgedMethod(ClassUtils.getMostSpecificMethod(method, clazz));
|
||||
if (method.equals(mostSpecificMethod)) {
|
||||
if (webServiceRefClass != null && method.isAnnotationPresent(webServiceRefClass)) {
|
||||
if (Modifier.isStatic(method.getModifiers())) {
|
||||
throw new IllegalStateException("@WebServiceRef annotation is not supported on static methods");
|
||||
}
|
||||
if (method.getParameterTypes().length != 1) {
|
||||
throw new IllegalStateException("@WebServiceRef annotation requires a single-arg method: " + method);
|
||||
}
|
||||
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
|
||||
currElements.add(new ResourceElement(method, pd));
|
||||
currElements.add(new WebServiceRefElement(method, pd));
|
||||
}
|
||||
else if (ejbRefClass != null && method.isAnnotationPresent(ejbRefClass)) {
|
||||
if (Modifier.isStatic(method.getModifiers())) {
|
||||
throw new IllegalStateException("@EJB annotation is not supported on static methods");
|
||||
}
|
||||
if (method.getParameterTypes().length != 1) {
|
||||
throw new IllegalStateException("@EJB annotation requires a single-arg method: " + method);
|
||||
}
|
||||
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
|
||||
currElements.add(new EjbRefElement(method, pd));
|
||||
}
|
||||
else if (method.isAnnotationPresent(Resource.class)) {
|
||||
if (Modifier.isStatic(method.getModifiers())) {
|
||||
throw new IllegalStateException("@Resource annotation is not supported on static methods");
|
||||
}
|
||||
Class<?>[] paramTypes = method.getParameterTypes();
|
||||
if (paramTypes.length != 1) {
|
||||
throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
|
||||
}
|
||||
if (!ignoredResourceTypes.contains(paramTypes[0].getName())) {
|
||||
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
|
||||
currElements.add(new ResourceElement(method, pd));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 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,6 +17,7 @@
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
@@ -80,9 +81,9 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
|
||||
|
||||
private boolean setMetadataReaderFactoryCalled = false;
|
||||
|
||||
private boolean postProcessBeanDefinitionRegistryCalled = false;
|
||||
private final Set<Integer> registriesPostProcessed = new HashSet<Integer>();
|
||||
|
||||
private boolean postProcessBeanFactoryCalled = false;
|
||||
private final Set<Integer> factoriesPostProcessed = new HashSet<Integer>();
|
||||
|
||||
|
||||
/**
|
||||
@@ -130,15 +131,16 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
|
||||
* Derive further bean definitions from the configuration classes in the registry.
|
||||
*/
|
||||
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
|
||||
if (this.postProcessBeanDefinitionRegistryCalled) {
|
||||
int registryId = System.identityHashCode(registry);
|
||||
if (this.registriesPostProcessed.contains(registryId)) {
|
||||
throw new IllegalStateException(
|
||||
"postProcessBeanDefinitionRegistry already called for this post-processor");
|
||||
"postProcessBeanDefinitionRegistry already called for this post-processor against " + registry);
|
||||
}
|
||||
if (this.postProcessBeanFactoryCalled) {
|
||||
if (this.factoriesPostProcessed.contains(registryId)) {
|
||||
throw new IllegalStateException(
|
||||
"postProcessBeanFactory already called for this post-processor");
|
||||
"postProcessBeanFactory already called for this post-processor against " + registry);
|
||||
}
|
||||
this.postProcessBeanDefinitionRegistryCalled = true;
|
||||
this.registriesPostProcessed.add(registryId);
|
||||
processConfigBeanDefinitions(registry);
|
||||
}
|
||||
|
||||
@@ -147,12 +149,13 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
|
||||
* by replacing them with CGLIB-enhanced subclasses.
|
||||
*/
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
|
||||
if (this.postProcessBeanFactoryCalled) {
|
||||
int factoryId = System.identityHashCode(beanFactory);
|
||||
if (this.factoriesPostProcessed.contains(factoryId)) {
|
||||
throw new IllegalStateException(
|
||||
"postProcessBeanFactory already called for this post-processor");
|
||||
"postProcessBeanFactory already called for this post-processor against " + beanFactory);
|
||||
}
|
||||
this.postProcessBeanFactoryCalled = true;
|
||||
if (!this.postProcessBeanDefinitionRegistryCalled) {
|
||||
this.factoriesPostProcessed.add((factoryId));
|
||||
if (!this.registriesPostProcessed.contains((factoryId))) {
|
||||
// BeanDefinitionRegistryPostProcessor hook apparently not supported...
|
||||
// Simply call processConfigBeanDefinitions lazily at this point then.
|
||||
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2011 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 @@ abstract class AbstractPropertyLoadingBeanDefinitionParser extends AbstractSingl
|
||||
|
||||
String fileEncoding = element.getAttribute("file-encoding");
|
||||
if (StringUtils.hasLength(fileEncoding)) {
|
||||
builder.addPropertyReference("fileEncoding", fileEncoding);
|
||||
builder.addPropertyValue("fileEncoding", fileEncoding);
|
||||
}
|
||||
|
||||
String order = element.getAttribute("order");
|
||||
|
||||
+1
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2011 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,12 +38,9 @@ class PropertyPlaceholderBeanDefinitionParser extends AbstractPropertyLoadingBea
|
||||
|
||||
@Override
|
||||
protected void doParse(Element element, BeanDefinitionBuilder builder) {
|
||||
|
||||
super.doParse(element, builder);
|
||||
|
||||
builder.addPropertyValue("ignoreUnresolvablePlaceholders",
|
||||
Boolean.valueOf(element.getAttribute("ignore-unresolvable")));
|
||||
|
||||
String systemPropertiesModeName = element.getAttribute("system-properties-mode");
|
||||
if (StringUtils.hasLength(systemPropertiesModeName)) {
|
||||
builder.addPropertyValue("systemPropertiesModeName", "SYSTEM_PROPERTIES_MODE_"+systemPropertiesModeName);
|
||||
|
||||
+8
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 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,10 +34,11 @@ import org.springframework.util.StringValueResolver;
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.config.BeanPostProcessor}
|
||||
* implementation that passes the ApplicationContext to beans that
|
||||
* implement the {@link ResourceLoaderAware}, {@link MessageSourceAware},
|
||||
* {@link ApplicationEventPublisherAware} and/or
|
||||
* implement the {@link EmbeddedValueResolverAware}, {@link ResourceLoaderAware},
|
||||
* {@link MessageSourceAware}, {@link ApplicationEventPublisherAware} and/or
|
||||
* {@link ApplicationContextAware} interfaces.
|
||||
* If all of them are implemented, they are satisfied in the given order.
|
||||
*
|
||||
* <p>Implemented interfaces are satisfied in order of their mention above.
|
||||
*
|
||||
* <p>Application contexts will automatically register this with their
|
||||
* underlying bean factory. Applications do not use this directly.
|
||||
@@ -45,6 +46,7 @@ import org.springframework.util.StringValueResolver;
|
||||
* @author Juergen Hoeller
|
||||
* @author Costin Leau
|
||||
* @since 10.10.2003
|
||||
* @see org.springframework.context.EmbeddedValueResolverAware
|
||||
* @see org.springframework.context.ResourceLoaderAware
|
||||
* @see org.springframework.context.MessageSourceAware
|
||||
* @see org.springframework.context.ApplicationEventPublisherAware
|
||||
@@ -68,7 +70,8 @@ class ApplicationContextAwareProcessor implements BeanPostProcessor {
|
||||
AccessControlContext acc = null;
|
||||
|
||||
if (System.getSecurityManager() != null &&
|
||||
(bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
|
||||
(bean instanceof EmbeddedValueResolverAware ||
|
||||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
|
||||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
|
||||
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
|
||||
}
|
||||
|
||||
+6
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 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.instrument.classloading.weblogic.WebLogicLoadTimeWeav
|
||||
* "<code>loadTimeWeaver</code>"; the most convenient way to achieve this is
|
||||
* Spring's <code><context:load-time-weaver></code> XML tag.
|
||||
*
|
||||
* <p>This class implements a runtime environment check for obtaining the
|
||||
* appropriate weaver implementation: As of Spring 2.5, it detects Sun's
|
||||
* GlassFish, Oracle's OC4J, BEA's WebLogic 10,
|
||||
* <p>This class implements a runtime environment check for obtaining
|
||||
* the appropriate weaver implementation: As of Spring 3.0, it detects
|
||||
* Oracle WebLogic 10, Oracle OC4J 10, GlassFish 3, JBoss AS 5 and 6,
|
||||
* {@link InstrumentationSavingAgent Spring's VM agent} and any
|
||||
* {@link ClassLoader} supported by Spring's {@link ReflectiveLoadTimeWeaver}
|
||||
* (for example the
|
||||
* {@link org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader}).
|
||||
* {@link org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader}
|
||||
* for Tomcat 5, 6 and 7).
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Ramnivas Laddad
|
||||
|
||||
+14
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,6 +36,7 @@ import org.springframework.format.Formatter;
|
||||
import org.springframework.format.FormatterRegistry;
|
||||
import org.springframework.format.Parser;
|
||||
import org.springframework.format.Printer;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
|
||||
/**
|
||||
@@ -63,6 +64,15 @@ public class FormattingConversionService extends GenericConversionService
|
||||
}
|
||||
|
||||
|
||||
public void addFormatter(Formatter<?> formatter) {
|
||||
Class<?> fieldType = GenericTypeResolver.resolveTypeArgument(formatter.getClass(), Formatter.class);
|
||||
if (fieldType == null) {
|
||||
throw new IllegalArgumentException("Unable to extract parameterized field type argument from Formatter [" +
|
||||
formatter.getClass().getName() + "]; does the formatter parameterize the <T> generic type?");
|
||||
}
|
||||
addFormatterForFieldType(fieldType, formatter);
|
||||
}
|
||||
|
||||
public void addFormatterForFieldType(Class<?> fieldType, Formatter<?> formatter) {
|
||||
addConverter(new PrinterConverter(fieldType, formatter, this));
|
||||
addConverter(new ParserConverter(fieldType, formatter, this));
|
||||
@@ -95,7 +105,7 @@ public class FormattingConversionService extends GenericConversionService
|
||||
return (sourceType.getAnnotation(annotationType) != null);
|
||||
}
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
FieldFormatterKey key = new FieldFormatterKey(sourceType.getAnnotation(annotationType), fieldType);
|
||||
FieldFormatterKey key = new FieldFormatterKey(sourceType.getAnnotation(annotationType), sourceType.getType());
|
||||
GenericConverter converter = cachedPrinters.get(key);
|
||||
if (converter == null) {
|
||||
Printer<?> printer = annotationFormatterFactory.getPrinter(key.getAnnotation(), key.getFieldType());
|
||||
@@ -117,7 +127,7 @@ public class FormattingConversionService extends GenericConversionService
|
||||
return (targetType.getAnnotation(annotationType) != null);
|
||||
}
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
FieldFormatterKey key = new FieldFormatterKey(targetType.getAnnotation(annotationType), fieldType);
|
||||
FieldFormatterKey key = new FieldFormatterKey(targetType.getAnnotation(annotationType), sourceType.getType());
|
||||
GenericConverter converter = cachedParsers.get(key);
|
||||
if (converter == null) {
|
||||
Parser<?> printer = annotationFormatterFactory.getParser(key.getAnnotation(), key.getFieldType());
|
||||
@@ -228,7 +238,7 @@ public class FormattingConversionService extends GenericConversionService
|
||||
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
String text = (String) source;
|
||||
if (text == null || text.length() == 0) {
|
||||
if (!StringUtils.hasText(text)) {
|
||||
return null;
|
||||
}
|
||||
Object result;
|
||||
|
||||
+48
-22
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 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,6 +27,7 @@ import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.EmbeddedValueResolverAware;
|
||||
import org.springframework.core.convert.support.ConversionServiceFactory;
|
||||
import org.springframework.format.AnnotationFormatterFactory;
|
||||
import org.springframework.format.Formatter;
|
||||
import org.springframework.format.FormatterRegistry;
|
||||
import org.springframework.format.Parser;
|
||||
import org.springframework.format.Printer;
|
||||
@@ -55,35 +56,77 @@ public class FormattingConversionServiceFactoryBean
|
||||
|
||||
private Set<?> converters;
|
||||
|
||||
private Set<?> formatters;
|
||||
|
||||
private StringValueResolver embeddedValueResolver;
|
||||
|
||||
private FormattingConversionService conversionService;
|
||||
|
||||
|
||||
/**
|
||||
* Configure the set of custom converter objects that should be added:
|
||||
* implementing {@link org.springframework.core.convert.converter.Converter},
|
||||
* Configure the set of custom converter objects that should be added.
|
||||
* @param converters instances of any of the following:
|
||||
* {@link org.springframework.core.convert.converter.Converter},
|
||||
* {@link org.springframework.core.convert.converter.ConverterFactory},
|
||||
* or {@link org.springframework.core.convert.converter.GenericConverter}.
|
||||
* {@link org.springframework.core.convert.converter.GenericConverter}
|
||||
*/
|
||||
public void setConverters(Set<?> converters) {
|
||||
this.converters = converters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the set of custom formatter objects that should be added.
|
||||
* @param formatters instances of {@link Formatter} or {@link AnnotationFormatterFactory}
|
||||
*/
|
||||
public void setFormatters(Set<?> formatters) {
|
||||
this.formatters = formatters;
|
||||
}
|
||||
|
||||
public void setEmbeddedValueResolver(StringValueResolver embeddedValueResolver) {
|
||||
this.embeddedValueResolver = embeddedValueResolver;
|
||||
}
|
||||
|
||||
|
||||
public void afterPropertiesSet() {
|
||||
this.conversionService = new FormattingConversionService();
|
||||
this.conversionService.setEmbeddedValueResolver(this.embeddedValueResolver);
|
||||
ConversionServiceFactory.addDefaultConverters(this.conversionService);
|
||||
ConversionServiceFactory.registerConverters(this.converters, this.conversionService);
|
||||
registerFormatters();
|
||||
}
|
||||
|
||||
private void registerFormatters() {
|
||||
if (this.formatters != null) {
|
||||
for (Object formatter : this.formatters) {
|
||||
if (formatter instanceof Formatter<?>) {
|
||||
this.conversionService.addFormatter((Formatter<?>) formatter);
|
||||
}
|
||||
else if (formatter instanceof AnnotationFormatterFactory<?>) {
|
||||
this.conversionService.addFormatterForFieldAnnotation((AnnotationFormatterFactory<?>) formatter);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException(
|
||||
"Custom formatters must be implementations of Formatter or AnnotationFormatterFactory");
|
||||
}
|
||||
}
|
||||
}
|
||||
installFormatters(this.conversionService);
|
||||
}
|
||||
|
||||
/**
|
||||
* Install Formatters and Converters into the new FormattingConversionService using the FormatterRegistry SPI.
|
||||
* Subclasses may override to customize the set of formatters and/or converters that are installed.
|
||||
*/
|
||||
protected void installFormatters(FormatterRegistry registry) {
|
||||
registry.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory());
|
||||
if (jodaTimePresent) {
|
||||
new JodaTimeFormattingConfigurer().installJodaTimeFormatting(registry);
|
||||
}
|
||||
else {
|
||||
registry.addFormatterForFieldAnnotation(new NoJodaDateTimeFormatAnnotationFormatterFactory());
|
||||
}
|
||||
}
|
||||
|
||||
// implementing FactoryBean
|
||||
|
||||
public FormattingConversionService getObject() {
|
||||
return this.conversionService;
|
||||
@@ -98,23 +141,6 @@ public class FormattingConversionServiceFactoryBean
|
||||
}
|
||||
|
||||
|
||||
// subclassing hooks
|
||||
|
||||
/**
|
||||
* Install Formatters and Converters into the new FormattingConversionService using the FormatterRegistry SPI.
|
||||
* Subclasses may override to customize the set of formatters and/or converters that are installed.
|
||||
*/
|
||||
protected void installFormatters(FormatterRegistry registry) {
|
||||
registry.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory());
|
||||
if (jodaTimePresent) {
|
||||
new JodaTimeFormattingConfigurer().installJodaTimeFormatting(registry);
|
||||
}
|
||||
else {
|
||||
registry.addFormatterForFieldAnnotation(new NoJodaDateTimeFormatAnnotationFormatterFactory());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dummy AnnotationFormatterFactory that simply fails if @DateTimeFormat is being used
|
||||
* without the JodaTime library being present.
|
||||
|
||||
+10
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2011 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,14 @@ import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* {@link LoadTimeWeaver} implementation for JBoss's instrumentable ClassLoader.
|
||||
* Supports JBoss AS 5 and 6.
|
||||
*
|
||||
* <p><b>NOTE:</b> Requires JBoss AS version 5.0.0 or higher.
|
||||
*
|
||||
* <p>Thanks to Ales Justin and Marius Bogoevici for the initial prototype.</p>
|
||||
* <p><b>NOTE:</b> On JBoss 6.0, to avoid the container loading the classes before the
|
||||
* application actually starts, one needs to add a <tt>WEB-INF/jboss-scanning.xml</tt>
|
||||
* file to the application archive - with the following content:
|
||||
* <pre><scanning xmlns="urn:jboss:scanning:1.0"/></pre>
|
||||
*
|
||||
* <p>Thanks to Ales Justin and Marius Bogoevici for the initial prototype.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @since 3.0
|
||||
@@ -70,4 +74,5 @@ public class JBossLoadTimeWeaver implements LoadTimeWeaver {
|
||||
public ClassLoader getThrowawayClassLoader() {
|
||||
return new SimpleThrowawayClassLoader(getInstrumentableClassLoader());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+16
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2011 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,6 +27,7 @@ import javax.management.ObjectName;
|
||||
import javax.management.remote.JMXConnectorServer;
|
||||
import javax.management.remote.JMXConnectorServerFactory;
|
||||
import javax.management.remote.JMXServiceURL;
|
||||
import javax.management.remote.MBeanServerForwarder;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
@@ -63,6 +64,8 @@ public class ConnectorServerFactoryBean extends MBeanRegistrationSupport
|
||||
|
||||
private Map<String, Object> environment = new HashMap<String, Object>();
|
||||
|
||||
private MBeanServerForwarder forwarder;
|
||||
|
||||
private ObjectName objectName;
|
||||
|
||||
private boolean threaded = false;
|
||||
@@ -97,6 +100,13 @@ public class ConnectorServerFactoryBean extends MBeanRegistrationSupport
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an MBeanServerForwarder to be applied to the <code>JMXConnectorServer</code>.
|
||||
*/
|
||||
public void setForwarder(MBeanServerForwarder forwarder) {
|
||||
this.forwarder = forwarder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the <code>ObjectName</code> used to register the <code>JMXConnectorServer</code>
|
||||
* itself with the <code>MBeanServer</code>, as <code>ObjectName</code> instance
|
||||
@@ -143,6 +153,11 @@ public class ConnectorServerFactoryBean extends MBeanRegistrationSupport
|
||||
// Create the connector server now.
|
||||
this.connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(url, this.environment, this.server);
|
||||
|
||||
// Set the given MBeanServerForwarder, if any.
|
||||
if (this.forwarder != null) {
|
||||
this.connectorServer.setMBeanServerForwarder(this.forwarder);
|
||||
}
|
||||
|
||||
// Do we want to register the connector with the MBean server?
|
||||
if (this.objectName != null) {
|
||||
doRegister(this.connectorServer, this.objectName);
|
||||
|
||||
+19
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2011 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.
|
||||
@@ -57,7 +57,7 @@ public class CodebaseAwareObjectInputStream extends ConfigurableObjectInputStrea
|
||||
|
||||
/**
|
||||
* Create a new CodebaseAwareObjectInputStream for the given InputStream and codebase.
|
||||
* @param in the InputStream to read from
|
||||
* @param in the InputStream to read from
|
||||
* @param codebaseUrl the codebase URL to load classes from if not found locally
|
||||
* (can consist of multiple URLs, separated by spaces)
|
||||
* @see java.io.ObjectInputStream#ObjectInputStream(java.io.InputStream)
|
||||
@@ -68,7 +68,7 @@ public class CodebaseAwareObjectInputStream extends ConfigurableObjectInputStrea
|
||||
|
||||
/**
|
||||
* Create a new CodebaseAwareObjectInputStream for the given InputStream and codebase.
|
||||
* @param in the InputStream to read from
|
||||
* @param in the InputStream to read from
|
||||
* @param classLoader the ClassLoader to use for loading local classes
|
||||
* (may be <code>null</code> to indicate RMI's default ClassLoader)
|
||||
* @param codebaseUrl the codebase URL to load classes from if not found locally
|
||||
@@ -82,6 +82,22 @@ public class CodebaseAwareObjectInputStream extends ConfigurableObjectInputStrea
|
||||
this.codebaseUrl = codebaseUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new CodebaseAwareObjectInputStream for the given InputStream and codebase.
|
||||
* @param in the InputStream to read from
|
||||
* @param classLoader the ClassLoader to use for loading local classes
|
||||
* (may be <code>null</code> to indicate RMI's default ClassLoader)
|
||||
* @param acceptProxyClasses whether to accept deserialization of proxy classes
|
||||
* (may be deactivated as a security measure)
|
||||
* @see java.io.ObjectInputStream#ObjectInputStream(java.io.InputStream)
|
||||
*/
|
||||
public CodebaseAwareObjectInputStream(
|
||||
InputStream in, ClassLoader classLoader, boolean acceptProxyClasses) throws IOException {
|
||||
|
||||
super(in, classLoader, acceptProxyClasses);
|
||||
this.codebaseUrl = null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Class resolveFallbackIfPossible(String className, ClassNotFoundException ex)
|
||||
|
||||
+20
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2011 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.
|
||||
@@ -57,6 +57,8 @@ public abstract class RemoteInvocationSerializingExporter extends RemoteInvocati
|
||||
|
||||
private String contentType = CONTENT_TYPE_SERIALIZED_OBJECT;
|
||||
|
||||
private boolean acceptProxyClasses = true;
|
||||
|
||||
private Object proxy;
|
||||
|
||||
|
||||
@@ -70,12 +72,27 @@ public abstract class RemoteInvocationSerializingExporter extends RemoteInvocati
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the content type to use for sending remote invocation responses.
|
||||
* Return the content type to use for sending remote invocation responses.
|
||||
*/
|
||||
public String getContentType() {
|
||||
return this.contentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to accept deserialization of proxy classes.
|
||||
* <p>Default is "true". May be deactivated as a security measure.
|
||||
*/
|
||||
public void setAcceptProxyClasses(boolean acceptProxyClasses) {
|
||||
this.acceptProxyClasses = acceptProxyClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether to accept deserialization of proxy classes.
|
||||
*/
|
||||
public boolean isAcceptProxyClasses() {
|
||||
return this.acceptProxyClasses;
|
||||
}
|
||||
|
||||
|
||||
public void afterPropertiesSet() {
|
||||
prepare();
|
||||
@@ -102,7 +119,7 @@ public abstract class RemoteInvocationSerializingExporter extends RemoteInvocati
|
||||
* @throws java.io.IOException if creation of the ObjectInputStream failed
|
||||
*/
|
||||
protected ObjectInputStream createObjectInputStream(InputStream is) throws IOException {
|
||||
return new CodebaseAwareObjectInputStream(is, getBeanClassLoader(), null);
|
||||
return new CodebaseAwareObjectInputStream(is, getBeanClassLoader(), isAcceptProxyClasses());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+4
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2011 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.remoting.rmi;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.SocketException;
|
||||
import java.rmi.ConnectException;
|
||||
import java.rmi.ConnectIOException;
|
||||
import java.rmi.NoSuchObjectException;
|
||||
@@ -211,8 +212,8 @@ public abstract class RmiClientInterceptorUtils {
|
||||
public static boolean isConnectFailure(RemoteException ex) {
|
||||
return (ex instanceof ConnectException || ex instanceof ConnectIOException ||
|
||||
ex instanceof UnknownHostException || ex instanceof NoSuchObjectException ||
|
||||
ex instanceof StubNotFoundException || isCorbaConnectFailure(ex.getCause()) ||
|
||||
ORACLE_CONNECTION_EXCEPTION.equals(ex.getClass().getName()));
|
||||
ex instanceof StubNotFoundException || ex.getCause() instanceof SocketException ||
|
||||
isCorbaConnectFailure(ex.getCause()) || ORACLE_CONNECTION_EXCEPTION.equals(ex.getClass().getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -7,5 +7,5 @@
|
||||
-->
|
||||
<rmi name="org.springframework.remoting.rmi.RmiInvocationWrapper">
|
||||
<cluster clusterable="true"/>
|
||||
<method name="*" idempotent="true"/>
|
||||
<method name="getTargetInterfaceName" idempotent="true"/>
|
||||
</rmi>
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2011 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.
|
||||
@@ -166,6 +166,7 @@ public abstract class RemoteExporter extends RemotingSupport {
|
||||
}
|
||||
}
|
||||
proxyFactory.setTarget(getService());
|
||||
proxyFactory.setOpaque(true);
|
||||
return proxyFactory.getProxy(getBeanClassLoader());
|
||||
}
|
||||
|
||||
|
||||
+12
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,8 +19,8 @@ package org.springframework.validation;
|
||||
import java.beans.PropertyEditor;
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -28,6 +28,7 @@ import java.util.Set;
|
||||
|
||||
import org.springframework.beans.PropertyEditorRegistry;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -130,7 +131,7 @@ public abstract class AbstractBindingResult extends AbstractErrors implements Bi
|
||||
}
|
||||
|
||||
public String[] resolveMessageCodes(String errorCode, String field) {
|
||||
Class fieldType = getFieldType(field);
|
||||
Class<?> fieldType = getFieldType(field);
|
||||
return getMessageCodesResolver().resolveMessageCodes(
|
||||
errorCode, getObjectName(), fixedField(field), fieldType);
|
||||
}
|
||||
@@ -236,7 +237,7 @@ public abstract class AbstractBindingResult extends AbstractErrors implements Bi
|
||||
* @see #getActualFieldValue
|
||||
*/
|
||||
@Override
|
||||
public Class getFieldType(String field) {
|
||||
public Class<?> getFieldType(String field) {
|
||||
Object value = getActualFieldValue(fixedField(field));
|
||||
if (value != null) {
|
||||
return value.getClass();
|
||||
@@ -268,11 +269,11 @@ public abstract class AbstractBindingResult extends AbstractErrors implements Bi
|
||||
* @see org.springframework.web.servlet.mvc.SimpleFormController
|
||||
*/
|
||||
public Map<String, Object> getModel() {
|
||||
Map<String, Object> model = new HashMap<String, Object>(2);
|
||||
// Errors instance, even if no errors.
|
||||
model.put(MODEL_KEY_PREFIX + getObjectName(), this);
|
||||
Map<String, Object> model = new LinkedHashMap<String, Object>(2);
|
||||
// Mapping from name to target object.
|
||||
model.put(getObjectName(), getTarget());
|
||||
// Errors instance, even if no errors.
|
||||
model.put(MODEL_KEY_PREFIX + getObjectName(), this);
|
||||
return model;
|
||||
}
|
||||
|
||||
@@ -285,10 +286,10 @@ public abstract class AbstractBindingResult extends AbstractErrors implements Bi
|
||||
* {@link #getPropertyEditorRegistry() PropertyEditorRegistry}'s
|
||||
* editor lookup facility, if available.
|
||||
*/
|
||||
public PropertyEditor findEditor(String field, Class valueType) {
|
||||
public PropertyEditor findEditor(String field, Class<?> valueType) {
|
||||
PropertyEditorRegistry editorRegistry = getPropertyEditorRegistry();
|
||||
if (editorRegistry != null) {
|
||||
Class valueTypeToUse = valueType;
|
||||
Class<?> valueTypeToUse = valueType;
|
||||
if (valueTypeToUse == null) {
|
||||
valueTypeToUse = getFieldType(field);
|
||||
}
|
||||
@@ -337,13 +338,13 @@ public abstract class AbstractBindingResult extends AbstractErrors implements Bi
|
||||
}
|
||||
BindingResult otherResult = (BindingResult) other;
|
||||
return (getObjectName().equals(otherResult.getObjectName()) &&
|
||||
getTarget().equals(otherResult.getTarget()) &&
|
||||
ObjectUtils.nullSafeEquals(getTarget(), otherResult.getTarget()) &&
|
||||
getAllErrors().equals(otherResult.getAllErrors()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getObjectName().hashCode() * 29 + getTarget().hashCode();
|
||||
return getObjectName().hashCode();
|
||||
}
|
||||
|
||||
|
||||
|
||||
+8
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2011 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.
|
||||
@@ -46,6 +46,8 @@ public class BeanPropertyBindingResult extends AbstractPropertyBindingResult imp
|
||||
|
||||
private final boolean autoGrowNestedPaths;
|
||||
|
||||
private final int autoGrowCollectionLimit;
|
||||
|
||||
private transient BeanWrapper beanWrapper;
|
||||
|
||||
|
||||
@@ -55,7 +57,7 @@ public class BeanPropertyBindingResult extends AbstractPropertyBindingResult imp
|
||||
* @param objectName the name of the target object
|
||||
*/
|
||||
public BeanPropertyBindingResult(Object target, String objectName) {
|
||||
this(target, objectName, true);
|
||||
this(target, objectName, true, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,11 +65,13 @@ public class BeanPropertyBindingResult extends AbstractPropertyBindingResult imp
|
||||
* @param target the target bean to bind onto
|
||||
* @param objectName the name of the target object
|
||||
* @param autoGrowNestedPaths whether to "auto-grow" a nested path that contains a null value
|
||||
* @param autoGrowCollectionLimit the limit for array and collection auto-growing
|
||||
*/
|
||||
public BeanPropertyBindingResult(Object target, String objectName, boolean autoGrowNestedPaths) {
|
||||
public BeanPropertyBindingResult(Object target, String objectName, boolean autoGrowNestedPaths, int autoGrowCollectionLimit) {
|
||||
super(objectName);
|
||||
this.target = target;
|
||||
this.autoGrowNestedPaths = autoGrowNestedPaths;
|
||||
this.autoGrowCollectionLimit = autoGrowCollectionLimit;
|
||||
}
|
||||
|
||||
|
||||
@@ -87,6 +91,7 @@ public class BeanPropertyBindingResult extends AbstractPropertyBindingResult imp
|
||||
this.beanWrapper = createBeanWrapper();
|
||||
this.beanWrapper.setExtractOldValueForEditor(true);
|
||||
this.beanWrapper.setAutoGrowNestedPaths(this.autoGrowNestedPaths);
|
||||
this.beanWrapper.setAutoGrowCollectionLimit(this.autoGrowCollectionLimit);
|
||||
}
|
||||
return this.beanWrapper;
|
||||
}
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@ public interface BindingResult extends Errors {
|
||||
* is given but should be specified in any case for consistency checking)
|
||||
* @return the registered editor, or <code>null</code> if none
|
||||
*/
|
||||
PropertyEditor findEditor(String field, Class valueType);
|
||||
PropertyEditor findEditor(String field, Class<?> valueType);
|
||||
|
||||
/**
|
||||
* Return the underlying PropertyEditorRegistry.
|
||||
|
||||
+25
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 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.
|
||||
@@ -105,6 +105,9 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
|
||||
/** Default object name used for binding: "target" */
|
||||
public static final String DEFAULT_OBJECT_NAME = "target";
|
||||
|
||||
/** Default limit for array and collection growing: 256 */
|
||||
public static final int DEFAULT_AUTO_GROW_COLLECTION_LIMIT = 256;
|
||||
|
||||
|
||||
/**
|
||||
* We'll create a lot of DataBinder instances: Let's use a static logger.
|
||||
@@ -127,6 +130,8 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
|
||||
|
||||
private boolean autoGrowNestedPaths = true;
|
||||
|
||||
private int autoGrowCollectionLimit = DEFAULT_AUTO_GROW_COLLECTION_LIMIT;
|
||||
|
||||
private String[] allowedFields;
|
||||
|
||||
private String[] disallowedFields;
|
||||
@@ -199,6 +204,22 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
|
||||
return this.autoGrowNestedPaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the limit for array and collection auto-growing.
|
||||
* <p>Default is 256, preventing OutOfMemoryErrors in case of large indexes.
|
||||
* Raise this limit if your auto-growing needs are unusually high.
|
||||
*/
|
||||
public void setAutoGrowCollectionLimit(int autoGrowCollectionLimit) {
|
||||
this.autoGrowCollectionLimit = autoGrowCollectionLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current limit for array and collection auto-growing.
|
||||
*/
|
||||
public int getAutoGrowCollectionLimit() {
|
||||
return this.autoGrowCollectionLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize standard JavaBean property access for this DataBinder.
|
||||
* <p>This is the default; an explicit call just leads to eager initialization.
|
||||
@@ -207,7 +228,8 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
|
||||
public void initBeanPropertyAccess() {
|
||||
Assert.state(this.bindingResult == null,
|
||||
"DataBinder is already initialized - call initBeanPropertyAccess before other configuration methods");
|
||||
this.bindingResult = new BeanPropertyBindingResult(getTarget(), getObjectName(), isAutoGrowNestedPaths());
|
||||
this.bindingResult = new BeanPropertyBindingResult(
|
||||
getTarget(), getObjectName(), isAutoGrowNestedPaths(), getAutoGrowCollectionLimit());
|
||||
if (this.conversionService != null) {
|
||||
this.bindingResult.initConversion(this.conversionService);
|
||||
}
|
||||
@@ -509,17 +531,14 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
|
||||
return this.conversionService;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void registerCustomEditor(Class requiredType, PropertyEditor propertyEditor) {
|
||||
getPropertyEditorRegistry().registerCustomEditor(requiredType, propertyEditor);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void registerCustomEditor(Class requiredType, String field, PropertyEditor propertyEditor) {
|
||||
getPropertyEditorRegistry().registerCustomEditor(requiredType, field, propertyEditor);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public PropertyEditor findCustomEditor(Class requiredType, String propertyPath) {
|
||||
return getPropertyEditorRegistry().findCustomEditor(requiredType, propertyPath);
|
||||
}
|
||||
@@ -700,8 +719,7 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
|
||||
* @throws BindException if there were any errors in the bind operation
|
||||
* @see BindingResult#getModel()
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map close() throws BindException {
|
||||
public Map<?, ?> close() throws BindException {
|
||||
if (getBindingResult().hasErrors()) {
|
||||
throw new BindException(getBindingResult());
|
||||
}
|
||||
|
||||
+20
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.beans;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.io.ContextResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
/**
|
||||
@@ -29,6 +30,8 @@ public class ResourceTestBean {
|
||||
|
||||
private Resource resource;
|
||||
|
||||
private ContextResource contextResource;
|
||||
|
||||
private InputStream inputStream;
|
||||
|
||||
private Resource[] resourceArray;
|
||||
@@ -47,22 +50,30 @@ public class ResourceTestBean {
|
||||
}
|
||||
|
||||
|
||||
public void setResource(Resource resource) {
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
public void setInputStream(InputStream inputStream) {
|
||||
this.inputStream = inputStream;
|
||||
}
|
||||
|
||||
public Resource getResource() {
|
||||
return resource;
|
||||
}
|
||||
|
||||
public void setResource(Resource resource) {
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
public ContextResource getContextResource() {
|
||||
return contextResource;
|
||||
}
|
||||
|
||||
public void setContextResource(ContextResource contextResource) {
|
||||
this.contextResource = contextResource;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() {
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
public void setInputStream(InputStream inputStream) {
|
||||
this.inputStream = inputStream;
|
||||
}
|
||||
|
||||
public Resource[] getResourceArray() {
|
||||
return resourceArray;
|
||||
}
|
||||
|
||||
+4
-4
@@ -65,7 +65,7 @@ public class AnnotationProcessorPerformanceTests {
|
||||
}
|
||||
sw.stop();
|
||||
//System.out.println(sw.getTotalTimeMillis());
|
||||
assertTrue("Prototype creation took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 4000);
|
||||
assertTrue("Prototype creation took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 5000);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -92,7 +92,7 @@ public class AnnotationProcessorPerformanceTests {
|
||||
}
|
||||
sw.stop();
|
||||
//System.out.println(sw.getTotalTimeMillis());
|
||||
assertTrue("Prototype creation took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 4000);
|
||||
assertTrue("Prototype creation took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 5000);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -118,7 +118,7 @@ public class AnnotationProcessorPerformanceTests {
|
||||
}
|
||||
sw.stop();
|
||||
//System.out.println(sw.getTotalTimeMillis());
|
||||
assertTrue("Prototype creation took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 4000);
|
||||
assertTrue("Prototype creation took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 5000);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -145,7 +145,7 @@ public class AnnotationProcessorPerformanceTests {
|
||||
}
|
||||
sw.stop();
|
||||
//System.out.println(sw.getTotalTimeMillis());
|
||||
assertTrue("Prototype creation took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 4000);
|
||||
assertTrue("Prototype creation took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 5000);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+15
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 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,7 +22,6 @@ import javax.annotation.PreDestroy;
|
||||
import javax.annotation.Resource;
|
||||
import javax.ejb.EJB;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
@@ -43,6 +42,8 @@ import org.springframework.jndi.support.SimpleJndiBeanFactory;
|
||||
import org.springframework.mock.jndi.ExpectedLookupTemplate;
|
||||
import org.springframework.util.SerializationTestUtils;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
@@ -229,6 +230,7 @@ public class CommonAnnotationBeanPostProcessorTests {
|
||||
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ExtendedResourceInjectionBean.class));
|
||||
bf.registerBeanDefinition("annotatedBean2", new RootBeanDefinition(NamedResourceInjectionBean.class));
|
||||
bf.registerBeanDefinition("annotatedBean3", new RootBeanDefinition(ConvertedResourceInjectionBean.class));
|
||||
TestBean tb = new TestBean();
|
||||
bf.registerSingleton("testBean", tb);
|
||||
TestBean tb2 = new TestBean();
|
||||
@@ -238,6 +240,7 @@ public class CommonAnnotationBeanPostProcessorTests {
|
||||
TestBean tb4 = new TestBean();
|
||||
bf.registerSingleton("testBean4", tb4);
|
||||
NestedTestBean tb6 = new NestedTestBean();
|
||||
bf.registerSingleton("value", "5");
|
||||
bf.registerSingleton("xy", tb6);
|
||||
bf.registerAlias("xy", "testBean9");
|
||||
|
||||
@@ -255,6 +258,9 @@ public class CommonAnnotationBeanPostProcessorTests {
|
||||
NamedResourceInjectionBean bean2 = (NamedResourceInjectionBean) bf.getBean("annotatedBean2");
|
||||
assertSame(tb6, bean2.testBean);
|
||||
|
||||
ConvertedResourceInjectionBean bean3 = (ConvertedResourceInjectionBean) bf.getBean("annotatedBean3");
|
||||
assertSame(5, bean3.value);
|
||||
|
||||
bf.destroySingletons();
|
||||
assertTrue(bean.destroyCalled);
|
||||
assertTrue(bean.destroy2Called);
|
||||
@@ -591,6 +597,13 @@ public class CommonAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
|
||||
private static class ConvertedResourceInjectionBean {
|
||||
|
||||
@Resource(name="value")
|
||||
private int value;
|
||||
}
|
||||
|
||||
|
||||
private static class NullFactory {
|
||||
|
||||
public static Object create() {
|
||||
|
||||
+3
@@ -7,6 +7,9 @@
|
||||
<property name="resource">
|
||||
<value>test.properties</value>
|
||||
</property>
|
||||
<property name="contextResource">
|
||||
<value>testBeans.properties</value>
|
||||
</property>
|
||||
<property name="inputStream">
|
||||
<value>classpath:org/springframework/beans/factory/xml/test.properties</value>
|
||||
</property>
|
||||
|
||||
+14
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 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,9 +18,9 @@ package org.springframework.context.support;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.ResourceTestBean;
|
||||
@@ -33,6 +33,8 @@ import org.springframework.core.convert.converter.GenericConverter;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Keith Donald
|
||||
* @author Juergen Hoeller
|
||||
@@ -123,4 +125,14 @@ public class ConversionServiceFactoryBeanTests {
|
||||
|
||||
public static class Baz {
|
||||
}
|
||||
|
||||
public static class ComplexConstructorArgument {
|
||||
|
||||
public ComplexConstructorArgument(Map<String, Class> map) {
|
||||
assertTrue(!map.isEmpty());
|
||||
assertTrue(map.keySet().iterator().next() instanceof String);
|
||||
assertTrue(map.values().iterator().next() instanceof Class);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+8
@@ -20,4 +20,12 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean class="org.springframework.context.support.ConversionServiceFactoryBeanTests$ComplexConstructorArgument">
|
||||
<constructor-arg>
|
||||
<map>
|
||||
<entry key="mykey" value="java.util.Date"/>
|
||||
</map>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
||||
+8
@@ -24,4 +24,12 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean class="org.springframework.context.support.ConversionServiceFactoryBeanTests$ComplexConstructorArgument">
|
||||
<constructor-arg>
|
||||
<map>
|
||||
<entry key="mykey" value="java.util.Date"/>
|
||||
</map>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright 2002-2011 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.format.support;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.text.ParseException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.format.AnnotationFormatterFactory;
|
||||
import org.springframework.format.Formatter;
|
||||
import org.springframework.format.Parser;
|
||||
import org.springframework.format.Printer;
|
||||
import org.springframework.format.annotation.NumberFormat;
|
||||
import org.springframework.format.annotation.NumberFormat.Style;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class FormattingConversionServiceFactoryBeanTests {
|
||||
|
||||
@Test
|
||||
public void testDefaultFormatters() throws Exception {
|
||||
FormattingConversionServiceFactoryBean factory = new FormattingConversionServiceFactoryBean();
|
||||
factory.afterPropertiesSet();
|
||||
FormattingConversionService fcs = factory.getObject();
|
||||
TypeDescriptor descriptor = new TypeDescriptor(TestBean.class.getDeclaredField("percent"));
|
||||
Object value = fcs.convert("5%", TypeDescriptor.valueOf(String.class), descriptor);
|
||||
assertEquals(.05, value);
|
||||
value = fcs.convert(.05, descriptor, TypeDescriptor.valueOf(String.class));
|
||||
assertEquals("5%", value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomFormatter() throws Exception {
|
||||
FormattingConversionServiceFactoryBean factory = new FormattingConversionServiceFactoryBean();
|
||||
Set<Object> formatters = new HashSet<Object>();
|
||||
formatters.add(new TestBeanFormatter());
|
||||
formatters.add(new SpecialIntAnnotationFormatterFactory());
|
||||
factory.setFormatters(formatters);
|
||||
factory.afterPropertiesSet();
|
||||
FormattingConversionService fcs = factory.getObject();
|
||||
|
||||
TestBean testBean = fcs.convert("5", TestBean.class);
|
||||
assertEquals(5, testBean.getSpecialInt());
|
||||
assertEquals("5", fcs.convert(testBean, String.class));
|
||||
|
||||
TypeDescriptor descriptor = new TypeDescriptor(TestBean.class.getDeclaredField("specialInt"));
|
||||
Object value = fcs.convert(":5", TypeDescriptor.valueOf(String.class), descriptor);
|
||||
assertEquals(5, value);
|
||||
value = fcs.convert(5, descriptor, TypeDescriptor.valueOf(String.class));
|
||||
assertEquals(":5", value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidFormatter() throws Exception {
|
||||
FormattingConversionServiceFactoryBean factory = new FormattingConversionServiceFactoryBean();
|
||||
Set<Object> formatters = new HashSet<Object>();
|
||||
formatters.add(new Object());
|
||||
factory.setFormatters(formatters);
|
||||
try {
|
||||
factory.afterPropertiesSet();
|
||||
fail("Expected formatter to be rejected");
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
private @interface SpecialInt {
|
||||
}
|
||||
|
||||
private static class TestBean {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@NumberFormat(style = Style.PERCENT)
|
||||
private double percent;
|
||||
|
||||
@SpecialInt
|
||||
private int specialInt;
|
||||
|
||||
public int getSpecialInt() {
|
||||
return specialInt;
|
||||
}
|
||||
|
||||
public void setSpecialInt(int field) {
|
||||
this.specialInt = field;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class TestBeanFormatter implements Formatter<TestBean> {
|
||||
|
||||
public String print(TestBean object, Locale locale) {
|
||||
return String.valueOf(object.getSpecialInt());
|
||||
}
|
||||
|
||||
public TestBean parse(String text, Locale locale) throws ParseException {
|
||||
TestBean object = new TestBean();
|
||||
object.setSpecialInt(Integer.parseInt(text));
|
||||
return object;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class SpecialIntAnnotationFormatterFactory implements AnnotationFormatterFactory<SpecialInt> {
|
||||
|
||||
private final Set<Class<?>> fieldTypes = new HashSet<Class<?>>(1);
|
||||
|
||||
public SpecialIntAnnotationFormatterFactory() {
|
||||
fieldTypes.add(Integer.class);
|
||||
}
|
||||
|
||||
public Set<Class<?>> getFieldTypes() {
|
||||
return fieldTypes;
|
||||
}
|
||||
|
||||
public Printer<?> getPrinter(SpecialInt annotation, Class<?> fieldType) {
|
||||
return new Printer<Integer>() {
|
||||
public String print(Integer object, Locale locale) {
|
||||
return ":" + object.toString();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public Parser<?> getParser(SpecialInt annotation, Class<?> fieldType) {
|
||||
return new Parser<Integer>() {
|
||||
public Integer parse(String text, Locale locale) throws ParseException {
|
||||
return Integer.parseInt(text.substring(1));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+65
-22
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 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,12 +27,11 @@ import org.joda.time.DateTime;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.junit.After;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.ConfigurablePropertyAccessor;
|
||||
import org.springframework.beans.PropertyAccessorFactory;
|
||||
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
@@ -41,11 +40,14 @@ import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.support.ConversionServiceFactory;
|
||||
import org.springframework.format.Printer;
|
||||
import org.springframework.format.datetime.joda.DateTimeParser;
|
||||
import org.springframework.format.datetime.joda.JodaDateTimeFormatAnnotationFormatterFactory;
|
||||
import org.springframework.format.datetime.joda.ReadablePartialPrinter;
|
||||
import org.springframework.format.number.NumberFormatter;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Keith Donald
|
||||
* @author Juergen Hoeller
|
||||
@@ -93,7 +95,13 @@ public class FormattingConversionServiceTests {
|
||||
@Test
|
||||
public void testFormatFieldForAnnotation() throws Exception {
|
||||
formattingService.addFormatterForFieldAnnotation(new JodaDateTimeFormatAnnotationFormatterFactory());
|
||||
doTestFormatFieldForAnnotation(Model.class);
|
||||
doTestFormatFieldForAnnotation(Model.class, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFormatFieldForAnnotationWithDirectFieldAccess() throws Exception {
|
||||
formattingService.addFormatterForFieldAnnotation(new JodaDateTimeFormatAnnotationFormatterFactory());
|
||||
doTestFormatFieldForAnnotation(Model.class, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -108,7 +116,7 @@ public class FormattingConversionServiceTests {
|
||||
context.refresh();
|
||||
context.getBeanFactory().initializeBean(formattingService, "formattingService");
|
||||
formattingService.addFormatterForFieldAnnotation(new JodaDateTimeFormatAnnotationFormatterFactory());
|
||||
doTestFormatFieldForAnnotation(ModelWithPlaceholders.class);
|
||||
doTestFormatFieldForAnnotation(ModelWithPlaceholders.class, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -123,10 +131,10 @@ public class FormattingConversionServiceTests {
|
||||
context.getBeanFactory().registerSingleton("ppc", ppc);
|
||||
context.refresh();
|
||||
formattingService = context.getBean("formattingService", FormattingConversionService.class);
|
||||
doTestFormatFieldForAnnotation(ModelWithPlaceholders.class);
|
||||
doTestFormatFieldForAnnotation(ModelWithPlaceholders.class, false);
|
||||
}
|
||||
|
||||
private void doTestFormatFieldForAnnotation(Class<?> modelClass) throws Exception {
|
||||
private void doTestFormatFieldForAnnotation(Class<?> modelClass, boolean directFieldAccess) throws Exception {
|
||||
formattingService.addConverter(new Converter<Date, Long>() {
|
||||
public Long convert(Date source) {
|
||||
return source.getTime();
|
||||
@@ -159,26 +167,30 @@ public class FormattingConversionServiceTests {
|
||||
assertEquals(new LocalDate(2009, 11, 2), new LocalDate(dates.get(2)));
|
||||
|
||||
Object model = BeanUtils.instantiate(modelClass);
|
||||
BeanWrapper accessor = PropertyAccessorFactory.forBeanPropertyAccess(model);
|
||||
ConfigurablePropertyAccessor accessor = directFieldAccess ? PropertyAccessorFactory.forDirectFieldAccess(model) :
|
||||
PropertyAccessorFactory.forBeanPropertyAccess(model);
|
||||
accessor.setConversionService(formattingService);
|
||||
accessor.setPropertyValue("dates", "10-31-09,11-1-09,11-2-09");
|
||||
dates = (List<Date>) accessor.getPropertyValue("dates");
|
||||
assertEquals(new LocalDate(2009, 10, 31), new LocalDate(dates.get(0)));
|
||||
assertEquals(new LocalDate(2009, 11, 1), new LocalDate(dates.get(1)));
|
||||
assertEquals(new LocalDate(2009, 11, 2), new LocalDate(dates.get(2)));
|
||||
accessor.setPropertyValue("dates[0]", "10-30-09");
|
||||
accessor.setPropertyValue("dates[1]", "10-1-09");
|
||||
accessor.setPropertyValue("dates[2]", "10-2-09");
|
||||
dates = (List<Date>) accessor.getPropertyValue("dates");
|
||||
assertEquals(new LocalDate(2009, 10, 30), new LocalDate(dates.get(0)));
|
||||
assertEquals(new LocalDate(2009, 10, 1), new LocalDate(dates.get(1)));
|
||||
assertEquals(new LocalDate(2009, 10, 2), new LocalDate(dates.get(2)));
|
||||
if (!directFieldAccess) {
|
||||
accessor.setPropertyValue("dates[0]", "10-30-09");
|
||||
accessor.setPropertyValue("dates[1]", "10-1-09");
|
||||
accessor.setPropertyValue("dates[2]", "10-2-09");
|
||||
dates = (List<Date>) accessor.getPropertyValue("dates");
|
||||
assertEquals(new LocalDate(2009, 10, 30), new LocalDate(dates.get(0)));
|
||||
assertEquals(new LocalDate(2009, 10, 1), new LocalDate(dates.get(1)));
|
||||
assertEquals(new LocalDate(2009, 10, 2), new LocalDate(dates.get(2)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testPrintNull() throws ParseException {
|
||||
formattingService.addFormatterForFieldType(Number.class, new NumberFormatter());
|
||||
assertEquals("", formattingService.convert(null, TypeDescriptor.valueOf(Integer.class), TypeDescriptor.valueOf(String.class)));
|
||||
assertEquals("", formattingService
|
||||
.convert(null, TypeDescriptor.valueOf(Integer.class), TypeDescriptor.valueOf(String.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -190,7 +202,8 @@ public class FormattingConversionServiceTests {
|
||||
@Test
|
||||
public void testParseEmptyString() throws ParseException {
|
||||
formattingService.addFormatterForFieldType(Number.class, new NumberFormatter());
|
||||
assertNull(formattingService.convert("", TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Integer.class)));
|
||||
assertNull(formattingService
|
||||
.convert("", TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Integer.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -208,14 +221,35 @@ public class FormattingConversionServiceTests {
|
||||
assertNull(formattingService.convert("", TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Integer.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFormatFieldForAnnotationWithSubclassAsFieldType() throws Exception {
|
||||
formattingService.addFormatterForFieldAnnotation(new JodaDateTimeFormatAnnotationFormatterFactory() {
|
||||
public Printer<?> getPrinter(org.springframework.format.annotation.DateTimeFormat annotation, Class<?> fieldType) {
|
||||
assertEquals(MyDate.class, fieldType);
|
||||
return super.getPrinter(annotation, fieldType);
|
||||
}
|
||||
});
|
||||
formattingService.addConverter(new Converter<MyDate, Long>() {
|
||||
public Long convert(MyDate source) {
|
||||
return source.getTime();
|
||||
}
|
||||
});
|
||||
formattingService.addConverter(new Converter<MyDate, Date>() {
|
||||
public Date convert(MyDate source) {
|
||||
return source;
|
||||
}
|
||||
});
|
||||
|
||||
formattingService.convert(new MyDate(), new TypeDescriptor(ModelWithSubclassField.class.getField("date")),
|
||||
TypeDescriptor.valueOf(String.class));
|
||||
}
|
||||
|
||||
|
||||
public static class Model {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@org.springframework.format.annotation.DateTimeFormat(style="S-")
|
||||
public Date date;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@org.springframework.format.annotation.DateTimeFormat(pattern="M-d-yy")
|
||||
public List<Date> dates;
|
||||
|
||||
@@ -231,11 +265,9 @@ public class FormattingConversionServiceTests {
|
||||
|
||||
public static class ModelWithPlaceholders {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@org.springframework.format.annotation.DateTimeFormat(style="${dateStyle}")
|
||||
public Date date;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@org.springframework.format.annotation.DateTimeFormat(pattern="${datePattern}")
|
||||
public List<Date> dates;
|
||||
|
||||
@@ -248,4 +280,15 @@ public class FormattingConversionServiceTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class MyDate extends Date {
|
||||
}
|
||||
|
||||
|
||||
private static class ModelWithSubclassField {
|
||||
|
||||
@org.springframework.format.annotation.DateTimeFormat(style = "S-")
|
||||
public MyDate date;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ import org.junit.Ignore;
|
||||
* @author Rob Harrop
|
||||
*/
|
||||
@Ignore // see https://issuetracker.springsource.com/browse/BRITS-235
|
||||
public class RemoteMBeanClientInterceptorTests extends MBeanClientInterceptorTests {
|
||||
public class RemoteMBeanClientInterceptorTestsIgnore extends MBeanClientInterceptorTests {
|
||||
|
||||
private static final String SERVICE_URL = "service:jmx:jmxmp://localhost:9876";
|
||||
|
||||
+39
-34
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,7 +18,6 @@ package org.springframework.jmx.export;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.management.Attribute;
|
||||
import javax.management.AttributeChangeNotification;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
@@ -27,7 +26,6 @@ import javax.management.NotificationFilter;
|
||||
import javax.management.NotificationListener;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.jmx.AbstractMBeanServerTests;
|
||||
import org.springframework.jmx.JmxTestBean;
|
||||
@@ -38,16 +36,17 @@ import org.springframework.jmx.support.ObjectNameManager;
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Mark Fisher
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
@Ignore // Getting CCEs regarding ObjectName being cast to String
|
||||
public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public void testRegisterNotificationListenerForMBean() throws Exception {
|
||||
ObjectName objectName = ObjectName.getInstance("spring:name=Test");
|
||||
JmxTestBean bean = new JmxTestBean();
|
||||
|
||||
Map beans = new HashMap();
|
||||
beans.put(objectName, bean);
|
||||
Map<String, Object> beans = new HashMap<String, Object>();
|
||||
beans.put(objectName.getCanonicalName(), bean);
|
||||
|
||||
CountingAttributeChangeNotificationListener listener = new CountingAttributeChangeNotificationListener();
|
||||
|
||||
@@ -66,12 +65,13 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
assertEquals("Listener not notified", 1, listener.getCount(attributeName));
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public void testRegisterNotificationListenerWithWildcard() throws Exception {
|
||||
ObjectName objectName = ObjectName.getInstance("spring:name=Test");
|
||||
JmxTestBean bean = new JmxTestBean();
|
||||
|
||||
Map beans = new HashMap();
|
||||
beans.put(objectName, bean);
|
||||
Map<String, Object> beans = new HashMap<String, Object>();
|
||||
beans.put(objectName.getCanonicalName(), bean);
|
||||
|
||||
CountingAttributeChangeNotificationListener listener = new CountingAttributeChangeNotificationListener();
|
||||
|
||||
@@ -94,7 +94,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
String objectName = "spring:name=Test";
|
||||
JmxTestBean bean = new JmxTestBean();
|
||||
|
||||
Map beans = new HashMap();
|
||||
Map<String, Object> beans = new HashMap<String, Object>();
|
||||
beans.put(objectName, bean);
|
||||
|
||||
CountingAttributeChangeNotificationListener listener = new CountingAttributeChangeNotificationListener();
|
||||
@@ -108,12 +108,13 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
exporter.setServer(server);
|
||||
exporter.setBeans(beans);
|
||||
exporter.setNotificationListeners(new NotificationListenerBean[]{listenerBean});
|
||||
exporter.setNotificationListeners(new NotificationListenerBean[] { listenerBean });
|
||||
exporter.afterPropertiesSet();
|
||||
|
||||
// update the attribute
|
||||
String attributeName = "Name";
|
||||
server.setAttribute(ObjectNameManager.getInstance("spring:name=Test"), new Attribute(attributeName, "Rob Harrop"));
|
||||
server.setAttribute(ObjectNameManager.getInstance("spring:name=Test"), new Attribute(attributeName,
|
||||
"Rob Harrop"));
|
||||
|
||||
assertEquals("Listener not notified", 1, listener.getCount(attributeName));
|
||||
assertEquals("Handback object not transmitted correctly", handback, listener.getLastHandback(attributeName));
|
||||
@@ -123,8 +124,8 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
ObjectName objectName = ObjectName.getInstance("spring:name=Test");
|
||||
JmxTestBean bean = new JmxTestBean();
|
||||
|
||||
Map beans = new HashMap();
|
||||
beans.put(objectName, bean);
|
||||
Map<String, Object> beans = new HashMap<String, Object>();
|
||||
beans.put(objectName.getCanonicalName(), bean);
|
||||
|
||||
CountingAttributeChangeNotificationListener listener = new CountingAttributeChangeNotificationListener();
|
||||
|
||||
@@ -134,7 +135,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
exporter.setServer(server);
|
||||
exporter.setBeans(beans);
|
||||
exporter.setNotificationListeners(new NotificationListenerBean[]{listenerBean});
|
||||
exporter.setNotificationListeners(new NotificationListenerBean[] { listenerBean });
|
||||
exporter.afterPropertiesSet();
|
||||
|
||||
// update the attribute
|
||||
@@ -144,12 +145,13 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
assertEquals("Listener not notified", 1, listener.getCount(attributeName));
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public void testRegisterNotificationListenerWithFilter() throws Exception {
|
||||
ObjectName objectName = ObjectName.getInstance("spring:name=Test");
|
||||
JmxTestBean bean = new JmxTestBean();
|
||||
|
||||
Map beans = new HashMap();
|
||||
beans.put(objectName, bean);
|
||||
Map<String, Object> beans = new HashMap<String, Object>();
|
||||
beans.put(objectName.getCanonicalName(), bean);
|
||||
|
||||
CountingAttributeChangeNotificationListener listener = new CountingAttributeChangeNotificationListener();
|
||||
|
||||
@@ -160,8 +162,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
if (notification instanceof AttributeChangeNotification) {
|
||||
AttributeChangeNotification changeNotification = (AttributeChangeNotification) notification;
|
||||
return "Name".equals(changeNotification.getAttributeName());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -170,7 +171,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
exporter.setServer(server);
|
||||
exporter.setBeans(beans);
|
||||
exporter.setNotificationListeners(new NotificationListenerBean[]{listenerBean});
|
||||
exporter.setNotificationListeners(new NotificationListenerBean[] { listenerBean });
|
||||
exporter.afterPropertiesSet();
|
||||
|
||||
// update the attributes
|
||||
@@ -188,11 +189,11 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
try {
|
||||
new NotificationListenerBean().afterPropertiesSet();
|
||||
fail("Must have thrown an IllegalArgumentException (no NotificationListener supplied)");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
} catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public void testRegisterNotificationListenerWithBeanNameAndBeanNameInBeansMap() throws Exception {
|
||||
String beanName = "testBean";
|
||||
ObjectName objectName = ObjectName.getInstance("spring:name=Test");
|
||||
@@ -203,7 +204,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
factory.registerSingleton(beanName, testBean);
|
||||
|
||||
Map beans = new HashMap();
|
||||
Map<String, Object> beans = new HashMap<String, Object>();
|
||||
beans.put(beanName, beanName);
|
||||
|
||||
Map listenerMappings = new HashMap();
|
||||
@@ -222,6 +223,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
assertEquals("Listener not notified", 1, listener.getCount("Age"));
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public void testRegisterNotificationListenerWithBeanNameAndBeanInstanceInBeansMap() throws Exception {
|
||||
String beanName = "testBean";
|
||||
ObjectName objectName = ObjectName.getInstance("spring:name=Test");
|
||||
@@ -232,7 +234,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
factory.registerSingleton(beanName, testBean);
|
||||
|
||||
Map beans = new HashMap();
|
||||
Map<String, Object> beans = new HashMap<String, Object>();
|
||||
beans.put(beanName, testBean);
|
||||
|
||||
Map listenerMappings = new HashMap();
|
||||
@@ -251,6 +253,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
assertEquals("Listener not notified", 1, listener.getCount("Age"));
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public void testRegisterNotificationListenerWithBeanNameBeforeObjectNameMappedToSameBeanInstance() throws Exception {
|
||||
String beanName = "testBean";
|
||||
ObjectName objectName = ObjectName.getInstance("spring:name=Test");
|
||||
@@ -261,7 +264,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
factory.registerSingleton(beanName, testBean);
|
||||
|
||||
Map beans = new HashMap();
|
||||
Map<String, Object> beans = new HashMap<String, Object>();
|
||||
beans.put(beanName, testBean);
|
||||
|
||||
Map listenerMappings = new HashMap();
|
||||
@@ -281,6 +284,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
assertEquals("Listener should have been notified exactly once", 1, listener.getCount("Age"));
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public void testRegisterNotificationListenerWithObjectNameBeforeBeanNameMappedToSameBeanInstance() throws Exception {
|
||||
String beanName = "testBean";
|
||||
ObjectName objectName = ObjectName.getInstance("spring:name=Test");
|
||||
@@ -291,7 +295,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
factory.registerSingleton(beanName, testBean);
|
||||
|
||||
Map beans = new HashMap();
|
||||
Map<String, Object> beans = new HashMap<String, Object>();
|
||||
beans.put(beanName, testBean);
|
||||
|
||||
Map listenerMappings = new HashMap();
|
||||
@@ -311,6 +315,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
assertEquals("Listener should have been notified exactly once", 1, listener.getCount("Age"));
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public void testRegisterNotificationListenerWithTwoBeanNamesMappedToDifferentBeanInstances() throws Exception {
|
||||
String beanName1 = "testBean1";
|
||||
String beanName2 = "testBean2";
|
||||
@@ -328,7 +333,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
factory.registerSingleton(beanName1, testBean1);
|
||||
factory.registerSingleton(beanName2, testBean2);
|
||||
|
||||
Map beans = new HashMap();
|
||||
Map<String, Object> beans = new HashMap<String, Object>();
|
||||
beans.put(beanName1, testBean1);
|
||||
beans.put(beanName2, testBean2);
|
||||
|
||||
@@ -357,8 +362,8 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
ObjectName objectName = ObjectName.getInstance("spring:name=Test");
|
||||
JmxTestBean bean = new JmxTestBean();
|
||||
|
||||
Map beans = new HashMap();
|
||||
beans.put(objectName, bean);
|
||||
Map<String, Object> beans = new HashMap<String, Object>();
|
||||
beans.put(objectName.getCanonicalName(), bean);
|
||||
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
exporter.setServer(server);
|
||||
@@ -391,9 +396,9 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
JmxTestBean bean = new JmxTestBean();
|
||||
JmxTestBean bean2 = new JmxTestBean();
|
||||
|
||||
Map beans = new HashMap();
|
||||
beans.put(objectName, bean);
|
||||
beans.put(objectName2, bean2);
|
||||
Map<String, Object> beans = new HashMap<String, Object>();
|
||||
beans.put(objectName.getCanonicalName(), bean);
|
||||
beans.put(objectName2.getCanonicalName(), bean2);
|
||||
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
exporter.setServer(server);
|
||||
@@ -406,7 +411,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
registrar.setServer(server);
|
||||
registrar.setNotificationListener(listener);
|
||||
//registrar.setMappedObjectNames(new Object[] {objectName, objectName2});
|
||||
registrar.setMappedObjectNames(new String[] {"spring:name=Test", "spring:name=Test2"});
|
||||
registrar.setMappedObjectNames(new String[] { "spring:name=Test", "spring:name=Test2" });
|
||||
registrar.afterPropertiesSet();
|
||||
|
||||
// update the attribute
|
||||
@@ -422,6 +427,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
private static class CountingAttributeChangeNotificationListener implements NotificationListener {
|
||||
|
||||
private Map attributeCounts = new HashMap();
|
||||
@@ -438,8 +444,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
if (currentCount != null) {
|
||||
int count = currentCount.intValue() + 1;
|
||||
this.attributeCounts.put(attributeName, new Integer(count));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.attributeCounts.put(attributeName, new Integer(1));
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ import org.springframework.jmx.AbstractMBeanServerTests;
|
||||
* @author Rob Harrop
|
||||
*/
|
||||
@Ignore // see https://issuetracker.springsource.com/browse/BRITS-235
|
||||
public class ConnectorServerFactoryBeanTests extends AbstractMBeanServerTests {
|
||||
public class ConnectorServerFactoryBeanTestsIgnore extends AbstractMBeanServerTests {
|
||||
|
||||
private static final String OBJECT_NAME = "spring:type=connector,name=test";
|
||||
|
||||
+26
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 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,8 +16,6 @@
|
||||
|
||||
package org.springframework.scheduling.support;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
@@ -30,8 +28,11 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
import org.springframework.scheduling.TriggerContext;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Mark Fisher
|
||||
@@ -670,6 +671,28 @@ public class CronTriggerTests {
|
||||
assertEquals(trigger1, trigger2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMonthSequence() throws Exception {
|
||||
CronTrigger trigger = new CronTrigger("0 30 23 30 1/3 ?", timeZone);
|
||||
calendar.set(2010, 11, 30);
|
||||
Date date = calendar.getTime();
|
||||
// set expected next trigger time
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 23);
|
||||
calendar.set(Calendar.MINUTE, 30);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.add(Calendar.MONTH, 1);
|
||||
TriggerContext context1 = getTriggerContext(date);
|
||||
assertEquals(calendar.getTime(), date = trigger.nextExecutionTime(context1));
|
||||
// Next trigger is 3 months latter
|
||||
calendar.add(Calendar.MONTH, 3);
|
||||
TriggerContext context2 = getTriggerContext(date);
|
||||
assertEquals(calendar.getTime(), date = trigger.nextExecutionTime(context2));
|
||||
// Next trigger is 3 months latter
|
||||
calendar.add(Calendar.MONTH, 3);
|
||||
TriggerContext context3 = getTriggerContext(date);
|
||||
assertEquals(calendar.getTime(), date = trigger.nextExecutionTime(context3));
|
||||
}
|
||||
|
||||
|
||||
private void assertMatchesNextSecond(CronTrigger trigger, Calendar calendar) {
|
||||
Date date = calendar.getTime();
|
||||
|
||||
+192
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 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,7 +22,14 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.text.ParseException;
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -34,6 +41,7 @@ import org.springframework.beans.BeanWithObjectProperty;
|
||||
import org.springframework.beans.DerivedTestBean;
|
||||
import org.springframework.beans.ITestBean;
|
||||
import org.springframework.beans.IndexedTestBean;
|
||||
import org.springframework.beans.InvalidPropertyException;
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.NotWritablePropertyException;
|
||||
import org.springframework.beans.NullValueInNestedPathException;
|
||||
@@ -45,6 +53,7 @@ import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.context.support.ResourceBundleMessageSource;
|
||||
import org.springframework.context.support.StaticMessageSource;
|
||||
import org.springframework.core.convert.support.ConversionServiceFactory;
|
||||
import org.springframework.format.Formatter;
|
||||
import org.springframework.format.number.NumberFormatter;
|
||||
import org.springframework.format.support.FormattingConversionService;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -366,6 +375,28 @@ public class DataBinderTests extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testBindingErrorWithStringFormatter() {
|
||||
TestBean tb = new TestBean();
|
||||
DataBinder binder = new DataBinder(tb);
|
||||
FormattingConversionService conversionService = new FormattingConversionService();
|
||||
ConversionServiceFactory.addDefaultConverters(conversionService);
|
||||
conversionService.addFormatterForFieldType(String.class, new Formatter<String>() {
|
||||
public String parse(String text, Locale locale) throws ParseException {
|
||||
throw new ParseException(text, 0);
|
||||
}
|
||||
public String print(String object, Locale locale) {
|
||||
return object;
|
||||
}
|
||||
});
|
||||
binder.setConversionService(conversionService);
|
||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||
pvs.add("name", "test");
|
||||
|
||||
binder.bind(pvs);
|
||||
assertTrue(binder.getBindingResult().hasFieldErrors("name"));
|
||||
assertEquals("test", binder.getBindingResult().getFieldValue("name"));
|
||||
}
|
||||
|
||||
public void testBindingWithFormatterAgainstList() {
|
||||
BeanWithIntegerList tb = new BeanWithIntegerList();
|
||||
DataBinder binder = new DataBinder(tb);
|
||||
@@ -1486,7 +1517,6 @@ public class DataBinderTests extends TestCase {
|
||||
MutablePropertyValues mpvs = new MutablePropertyValues();
|
||||
mpvs.add("name", name);
|
||||
mpvs.add("beanName", beanName);
|
||||
|
||||
binder.bind(mpvs);
|
||||
|
||||
assertEquals(name, testBean.getName());
|
||||
@@ -1495,6 +1525,76 @@ public class DataBinderTests extends TestCase {
|
||||
assertEquals("beanName", disallowedFields[0]);
|
||||
}
|
||||
|
||||
public void testAutoGrowWithinDefaultLimit() throws Exception {
|
||||
TestBean testBean = new TestBean();
|
||||
DataBinder binder = new DataBinder(testBean, "testBean");
|
||||
|
||||
MutablePropertyValues mpvs = new MutablePropertyValues();
|
||||
mpvs.add("friends[4]", "");
|
||||
binder.bind(mpvs);
|
||||
|
||||
assertEquals(5, testBean.getFriends().size());
|
||||
}
|
||||
|
||||
public void testAutoGrowBeyondDefaultLimit() throws Exception {
|
||||
TestBean testBean = new TestBean();
|
||||
DataBinder binder = new DataBinder(testBean, "testBean");
|
||||
|
||||
MutablePropertyValues mpvs = new MutablePropertyValues();
|
||||
mpvs.add("friends[256]", "");
|
||||
try {
|
||||
binder.bind(mpvs);
|
||||
fail("Should have thrown InvalidPropertyException");
|
||||
}
|
||||
catch (InvalidPropertyException ex) {
|
||||
// expected
|
||||
assertTrue(ex.getRootCause() instanceof IndexOutOfBoundsException);
|
||||
}
|
||||
}
|
||||
|
||||
public void testAutoGrowWithinCustomLimit() throws Exception {
|
||||
TestBean testBean = new TestBean();
|
||||
DataBinder binder = new DataBinder(testBean, "testBean");
|
||||
binder.setAutoGrowCollectionLimit(10);
|
||||
|
||||
MutablePropertyValues mpvs = new MutablePropertyValues();
|
||||
mpvs.add("friends[4]", "");
|
||||
binder.bind(mpvs);
|
||||
|
||||
assertEquals(5, testBean.getFriends().size());
|
||||
}
|
||||
|
||||
public void testAutoGrowBeyondCustomLimit() throws Exception {
|
||||
TestBean testBean = new TestBean();
|
||||
DataBinder binder = new DataBinder(testBean, "testBean");
|
||||
binder.setAutoGrowCollectionLimit(10);
|
||||
|
||||
MutablePropertyValues mpvs = new MutablePropertyValues();
|
||||
mpvs.add("friends[16]", "");
|
||||
try {
|
||||
binder.bind(mpvs);
|
||||
fail("Should have thrown InvalidPropertyException");
|
||||
}
|
||||
catch (InvalidPropertyException ex) {
|
||||
// expected
|
||||
assertTrue(ex.getRootCause() instanceof IndexOutOfBoundsException);
|
||||
}
|
||||
}
|
||||
|
||||
public void testNestedGrowingList() {
|
||||
Form form = new Form();
|
||||
DataBinder binder = new DataBinder(form, "form");
|
||||
MutablePropertyValues mpv = new MutablePropertyValues();
|
||||
mpv.add("f[list][0]", "firstValue");
|
||||
mpv.add("f[list][1]", "secondValue");
|
||||
binder.bind(mpv);
|
||||
assertFalse(binder.getBindingResult().hasErrors());
|
||||
List<Object> list = (List<Object>) form.getF().get("list");
|
||||
assertEquals("firstValue", list.get(0));
|
||||
assertEquals("secondValue", list.get(1));
|
||||
assertEquals(2, list.size());
|
||||
}
|
||||
|
||||
|
||||
private static class BeanWithIntegerList {
|
||||
|
||||
@@ -1589,4 +1689,94 @@ public class DataBinderTests extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class GrowingList<E> extends AbstractList<E> {
|
||||
|
||||
private List<E> list;
|
||||
|
||||
public GrowingList() {
|
||||
this.list = new ArrayList<E>();
|
||||
}
|
||||
|
||||
public List<E> getWrappedList() {
|
||||
return list;
|
||||
}
|
||||
|
||||
public E get(int index) {
|
||||
if (index >= list.size()) {
|
||||
for (int i = list.size(); i < index; i++) {
|
||||
list.add(null);
|
||||
}
|
||||
list.add(null);
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return list.get(index);
|
||||
}
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return list.size();
|
||||
}
|
||||
|
||||
public boolean add(E o) {
|
||||
return list.add(o);
|
||||
}
|
||||
|
||||
public void add(int index, E element) {
|
||||
list.add(index, element);
|
||||
}
|
||||
|
||||
public boolean addAll(int index, Collection<? extends E> c) {
|
||||
return list.addAll(index, c);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
list.clear();
|
||||
}
|
||||
|
||||
public int indexOf(Object o) {
|
||||
return list.indexOf(o);
|
||||
}
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return list.iterator();
|
||||
}
|
||||
|
||||
public int lastIndexOf(Object o) {
|
||||
return list.lastIndexOf(o);
|
||||
}
|
||||
|
||||
public ListIterator<E> listIterator() {
|
||||
return list.listIterator();
|
||||
}
|
||||
|
||||
public ListIterator<E> listIterator(int index) {
|
||||
return list.listIterator(index);
|
||||
}
|
||||
|
||||
public E remove(int index) {
|
||||
return list.remove(index);
|
||||
}
|
||||
|
||||
public E set(int index, E element) {
|
||||
return list.set(index, element);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class Form {
|
||||
|
||||
private final Map<String, Object> f;
|
||||
|
||||
public Form() {
|
||||
f = new HashMap<String, Object>();
|
||||
f.put("list", new GrowingList<Object>());
|
||||
}
|
||||
|
||||
public Map<String, Object> getF() {
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-1
@@ -7,7 +7,8 @@
|
||||
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd">
|
||||
|
||||
<context:property-placeholder
|
||||
location="classpath*:/org/springframework/context/config/test-*.properties,classpath*:/org/springframework/context/config/empty-*.properties,classpath*:/org/springframework/context/config/missing-*.properties" />
|
||||
location="classpath*:/org/springframework/context/config/test-*.properties,classpath*:/org/springframework/context/config/empty-*.properties,classpath*:/org/springframework/context/config/missing-*.properties"
|
||||
file-encoding="ISO-8859-1"/>
|
||||
|
||||
<bean id="foo" class="java.lang.String">
|
||||
<constructor-arg value="${foo}" />
|
||||
|
||||
@@ -27,7 +27,7 @@ Import-Template:
|
||||
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
|
||||
org.aspectj.weaver.*;version=${aj.osgi.range};resolution:=optional,
|
||||
org.codehaus.groovy.*;version="[1.5.0, 2.0.0)";resolution:=optional,
|
||||
org.hibernate.validator.*;version="[4.1.0, 5.0.0)";resolution:=optional,
|
||||
org.hibernate.validator.*;version="[4.0.0, 5.0.0)";resolution:=optional,
|
||||
org.joda.*;version="[1.6.0, 2.0.0)";resolution:=optional,
|
||||
org.jruby.*;version="[1.1.0, 2.0.0)";resolution:=optional,
|
||||
org.omg.CORBA.*;version="0";resolution:=optional,
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
<dependency org="org.springframework" name="org.springframework.asm" rev="latest.integration" conf="optional->compile"/>
|
||||
<!-- test dependencies -->
|
||||
<dependency org="javax.servlet" name="com.springsource.javax.servlet" rev="2.5.0" conf="test->compile"/>
|
||||
<dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit.version}" conf="test->runtime"/>
|
||||
<dependency org="org.junit" name="com.springsource.org.junit" rev="${junit.version}" conf="test->runtime"/>
|
||||
<dependency org="org.easymock" name="com.springsource.org.easymock" rev="2.5.1" conf="test->compile"/>
|
||||
<dependency org="org.custommonkey.xmlunit" name="com.springsource.org.custommonkey.xmlunit" rev="1.2.0" conf="test->compile"/>
|
||||
<dependency org="org.codehaus.woodstox" name="com.springsource.com.ctc.wstx" rev="3.2.7" conf="test->compile"/>
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.5.BUILD-SNAPSHOT</version>
|
||||
<version>3.0.7.RELEASE</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.5.BUILD-SNAPSHOT</version>
|
||||
<version>3.0.7.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2011 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.util.Assert;
|
||||
public abstract class AttributeAccessorSupport implements AttributeAccessor, Serializable {
|
||||
|
||||
/** Map with String keys and Object values */
|
||||
private final Map<String, Object> attributes = new LinkedHashMap<String, Object>();
|
||||
private final Map<String, Object> attributes = new LinkedHashMap<String, Object>(0);
|
||||
|
||||
|
||||
public void setAttribute(String name, Object value) {
|
||||
|
||||
+20
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2011 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,6 +25,7 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
@@ -210,4 +211,22 @@ public abstract class BridgeMethodResolver {
|
||||
return ReflectionUtils.findMethod(type, bridgeMethod.getName(), bridgeMethod.getParameterTypes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare the signatures of the bridge method and the method which it bridges. If
|
||||
* the parameter and return types are the same, it is a 'visibility' bridge method
|
||||
* introduced in Java 6 to fix http://bugs.sun.com/view_bug.do?bug_id=6342411.
|
||||
* See also http://stas-blogspot.blogspot.com/2010/03/java-bridge-methods-explained.html
|
||||
* @return whether signatures match as described
|
||||
*/
|
||||
public static boolean isVisibilityBridgeMethodPair(Method bridgeMethod, Method bridgedMethod) {
|
||||
Assert.isTrue(bridgeMethod != null);
|
||||
Assert.isTrue(bridgedMethod != null);
|
||||
if (bridgeMethod == bridgedMethod) {
|
||||
return true;
|
||||
}
|
||||
return Arrays.equals(bridgeMethod.getParameterTypes(), bridgedMethod.getParameterTypes()) &&
|
||||
bridgeMethod.getReturnType().equals(bridgedMethod.getReturnType());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+23
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2011 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.core;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.NotSerializableException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectStreamClass;
|
||||
import java.lang.reflect.Proxy;
|
||||
@@ -36,16 +37,33 @@ public class ConfigurableObjectInputStream extends ObjectInputStream {
|
||||
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
private final boolean acceptProxyClasses;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new ConfigurableObjectInputStream for the given InputStream and ClassLoader.
|
||||
* @param in the InputStream to read from
|
||||
* @param in the InputStream to read from
|
||||
* @param classLoader the ClassLoader to use for loading local classes
|
||||
* @see java.io.ObjectInputStream#ObjectInputStream(java.io.InputStream)
|
||||
*/
|
||||
public ConfigurableObjectInputStream(InputStream in, ClassLoader classLoader) throws IOException {
|
||||
this(in, classLoader, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ConfigurableObjectInputStream for the given InputStream and ClassLoader.
|
||||
* @param in the InputStream to read from
|
||||
* @param classLoader the ClassLoader to use for loading local classes
|
||||
* @param acceptProxyClasses whether to accept deserialization of proxy classes
|
||||
* (may be deactivated as a security measure)
|
||||
* @see java.io.ObjectInputStream#ObjectInputStream(java.io.InputStream)
|
||||
*/
|
||||
public ConfigurableObjectInputStream(
|
||||
InputStream in, ClassLoader classLoader, boolean acceptProxyClasses) throws IOException {
|
||||
|
||||
super(in);
|
||||
this.classLoader = classLoader;
|
||||
this.acceptProxyClasses = acceptProxyClasses;
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +86,9 @@ public class ConfigurableObjectInputStream extends ObjectInputStream {
|
||||
|
||||
@Override
|
||||
protected Class resolveProxyClass(String[] interfaces) throws IOException, ClassNotFoundException {
|
||||
if (!this.acceptProxyClasses) {
|
||||
throw new NotSerializableException("Not allowed to accept serialized proxy classes");
|
||||
}
|
||||
if (this.classLoader != null) {
|
||||
// Use the specified ClassLoader to resolve local proxy classes.
|
||||
Class[] resolvedInterfaces = new Class[interfaces.length];
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 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.
|
||||
@@ -68,7 +68,7 @@ public class ExceptionDepthComparator implements Comparator<Class<? extends Thro
|
||||
}
|
||||
// If we've gone as far as we can go and haven't found it...
|
||||
if (Throwable.class.equals(exceptionToMatch)) {
|
||||
return -1;
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
return getDepth(declaredException, exceptionToMatch.getSuperclass(), depth + 1);
|
||||
}
|
||||
|
||||
+4
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 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.
|
||||
@@ -41,7 +41,6 @@ import org.springframework.util.Assert;
|
||||
* @author Rob Harrop
|
||||
* @since 2.5.2
|
||||
* @see GenericCollectionTypeResolver
|
||||
* @see JdkVersion
|
||||
*/
|
||||
public abstract class GenericTypeResolver {
|
||||
|
||||
@@ -175,7 +174,7 @@ public abstract class GenericTypeResolver {
|
||||
return doResolveTypeArguments(ownerClass, (Class) rawType, genericIfc);
|
||||
}
|
||||
}
|
||||
else if (genericIfc.isAssignableFrom((Class) ifc)) {
|
||||
else if (ifc != null && genericIfc.isAssignableFrom((Class) ifc)) {
|
||||
return doResolveTypeArguments(ownerClass, (Class) ifc, genericIfc);
|
||||
}
|
||||
return null;
|
||||
@@ -214,7 +213,7 @@ public abstract class GenericTypeResolver {
|
||||
* @param typeVariableMap the TypeVariable Map to resolved against
|
||||
* @return the type if it resolves to a Class, or <code>Object.class</code> otherwise
|
||||
*/
|
||||
static Class resolveType(Type genericType, Map<TypeVariable, Type> typeVariableMap) {
|
||||
public static Class<?> resolveType(Type genericType, Map<TypeVariable, Type> typeVariableMap) {
|
||||
Type rawType = getRawType(genericType, typeVariableMap);
|
||||
return (rawType instanceof Class ? (Class) rawType : Object.class);
|
||||
}
|
||||
@@ -247,7 +246,7 @@ public abstract class GenericTypeResolver {
|
||||
* {@link Class} for the specified {@link Class}. Searches all super types,
|
||||
* enclosing types and interfaces.
|
||||
*/
|
||||
static Map<TypeVariable, Type> getTypeVariableMap(Class clazz) {
|
||||
public static Map<TypeVariable, Type> getTypeVariableMap(Class clazz) {
|
||||
Reference<Map<TypeVariable, Type>> ref = typeVariableCache.get(clazz);
|
||||
Map<TypeVariable, Type> typeVariableMap = (ref != null ? ref.get() : null);
|
||||
|
||||
|
||||
+13
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 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.
|
||||
@@ -80,13 +80,13 @@ public class TypeDescriptor {
|
||||
|
||||
private Object value;
|
||||
|
||||
private TypeDescriptor elementType;
|
||||
private volatile TypeDescriptor elementType;
|
||||
|
||||
private TypeDescriptor mapKeyType;
|
||||
private volatile TypeDescriptor mapKeyType;
|
||||
|
||||
private TypeDescriptor mapValueType;
|
||||
private volatile TypeDescriptor mapValueType;
|
||||
|
||||
private Annotation[] annotations;
|
||||
private volatile Annotation[] annotations;
|
||||
|
||||
|
||||
/**
|
||||
@@ -266,7 +266,7 @@ public class TypeDescriptor {
|
||||
/**
|
||||
* Return the element type as a type descriptor.
|
||||
*/
|
||||
public synchronized TypeDescriptor getElementTypeDescriptor() {
|
||||
public TypeDescriptor getElementTypeDescriptor() {
|
||||
if (this.elementType == null) {
|
||||
this.elementType = forElementType(resolveElementType());
|
||||
}
|
||||
@@ -281,7 +281,7 @@ public class TypeDescriptor {
|
||||
*/
|
||||
public TypeDescriptor getElementTypeDescriptor(Object element) {
|
||||
TypeDescriptor elementType = getElementTypeDescriptor();
|
||||
return (elementType != TypeDescriptor.UNKNOWN ? elementType : forObject(element));
|
||||
return (!TypeDescriptor.UNKNOWN.equals(elementType) ? elementType : forObject(element));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -309,7 +309,7 @@ public class TypeDescriptor {
|
||||
/**
|
||||
* Returns map key type as a type descriptor.
|
||||
*/
|
||||
public synchronized TypeDescriptor getMapKeyTypeDescriptor() {
|
||||
public TypeDescriptor getMapKeyTypeDescriptor() {
|
||||
if (this.mapKeyType == null) {
|
||||
this.mapKeyType = forElementType(resolveMapKeyType());
|
||||
}
|
||||
@@ -317,14 +317,14 @@ public class TypeDescriptor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the map key type as a type descriptor. If the key type is null
|
||||
* Return the map key type as a type descriptor. If the key type is <code>null</code>
|
||||
* (cannot be determined), the type descriptor is derived from the key argument.
|
||||
* @param key the key
|
||||
* @return the map key type descriptor
|
||||
*/
|
||||
public TypeDescriptor getMapKeyTypeDescriptor(Object key) {
|
||||
TypeDescriptor keyType = getMapKeyTypeDescriptor();
|
||||
return (keyType != TypeDescriptor.UNKNOWN ? keyType : TypeDescriptor.forObject(key));
|
||||
return (!TypeDescriptor.UNKNOWN.equals(keyType) ? keyType : TypeDescriptor.forObject(key));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -338,7 +338,7 @@ public class TypeDescriptor {
|
||||
/**
|
||||
* Returns map value type as a type descriptor.
|
||||
*/
|
||||
public synchronized TypeDescriptor getMapValueTypeDescriptor() {
|
||||
public TypeDescriptor getMapValueTypeDescriptor() {
|
||||
if (this.mapValueType == null) {
|
||||
this.mapValueType = forElementType(resolveMapValueType());
|
||||
}
|
||||
@@ -353,13 +353,13 @@ public class TypeDescriptor {
|
||||
*/
|
||||
public TypeDescriptor getMapValueTypeDescriptor(Object value) {
|
||||
TypeDescriptor valueType = getMapValueTypeDescriptor();
|
||||
return (valueType != TypeDescriptor.UNKNOWN ? valueType : TypeDescriptor.forObject(value));
|
||||
return (!TypeDescriptor.UNKNOWN.equals(valueType) ? valueType : TypeDescriptor.forObject(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the annotations associated with the wrapped parameter/field, if any.
|
||||
*/
|
||||
public synchronized Annotation[] getAnnotations() {
|
||||
public Annotation[] getAnnotations() {
|
||||
if (this.annotations == null) {
|
||||
this.annotations = resolveAnnotations();
|
||||
}
|
||||
|
||||
+22
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2011 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,11 +16,11 @@
|
||||
|
||||
package org.springframework.core.convert.converter;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Generic converter interface for converting between two or more types.
|
||||
*
|
||||
@@ -87,6 +87,24 @@ public interface GenericConverter {
|
||||
public Class<?> getTargetType() {
|
||||
return this.targetType;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null || obj.getClass() != ConvertiblePair.class) {
|
||||
return false;
|
||||
}
|
||||
ConvertiblePair other = (ConvertiblePair) obj;
|
||||
return this.sourceType.equals(other.sourceType) && this.targetType.equals(other.targetType);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.sourceType.hashCode() * 31 + this.targetType.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2011 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,7 +22,7 @@ import java.util.Set;
|
||||
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
@@ -32,7 +32,7 @@ import org.springframework.util.ObjectUtils;
|
||||
* @author Keith Donald
|
||||
* @since 3.0
|
||||
*/
|
||||
final class ArrayToArrayConverter implements GenericConverter {
|
||||
final class ArrayToArrayConverter implements ConditionalGenericConverter {
|
||||
|
||||
private final CollectionToArrayConverter helperConverter;
|
||||
|
||||
|
||||
+17
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2011 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,7 +49,8 @@ final class ArrayToCollectionConverter implements ConditionalGenericConverter {
|
||||
}
|
||||
|
||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
return this.conversionService.canConvert(sourceType.getElementTypeDescriptor(), targetType.getElementTypeDescriptor());
|
||||
return ConversionUtils.canConvertElements(
|
||||
sourceType.getElementTypeDescriptor(), targetType.getElementTypeDescriptor(), this.conversionService);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -58,12 +59,21 @@ final class ArrayToCollectionConverter implements ConditionalGenericConverter {
|
||||
return null;
|
||||
}
|
||||
int length = Array.getLength(source);
|
||||
Collection target = CollectionFactory.createCollection(targetType.getType(), length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
Object sourceElement = Array.get(source, i);
|
||||
Object targetElement = this.conversionService.convert(sourceElement, sourceType.getElementTypeDescriptor(), targetType.getElementTypeDescriptor(sourceElement));
|
||||
target.add(targetElement);
|
||||
Collection<Object> target = CollectionFactory.createCollection(targetType.getType(), length);
|
||||
if (targetType.getElementTypeDescriptor() == null) {
|
||||
for (int i = 0; i < length; i++) {
|
||||
Object sourceElement = Array.get(source, i);
|
||||
target.add(sourceElement);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < length; i++) {
|
||||
Object sourceElement = Array.get(source, i);
|
||||
Object targetElement = this.conversionService.convert(sourceElement,
|
||||
sourceType.getElementTypeDescriptor(sourceElement), targetType.getElementTypeDescriptor());
|
||||
target.add(targetElement);
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
|
||||
+17
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2011 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,40 +16,48 @@
|
||||
|
||||
package org.springframework.core.convert.support;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Converts an Array to an Object by returning the first array element after converting it to the desired targetType.
|
||||
* This implementation first adapts the source Array to a List, then delegates to {@link CollectionToObjectConverter} to perform the target Object conversion.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @since 3.0
|
||||
*/
|
||||
final class ArrayToObjectConverter implements ConditionalGenericConverter {
|
||||
|
||||
private final CollectionToObjectConverter helperConverter;
|
||||
private final ConversionService conversionService;
|
||||
|
||||
public ArrayToObjectConverter(ConversionService conversionService) {
|
||||
this.helperConverter = new CollectionToObjectConverter(conversionService);
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
public Set<ConvertiblePair> getConvertibleTypes() {
|
||||
return Collections.singleton(new ConvertiblePair(Object[].class, Object.class));
|
||||
}
|
||||
|
||||
|
||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
return this.helperConverter.matches(sourceType, targetType);
|
||||
return ConversionUtils.canConvertElements(sourceType.getElementTypeDescriptor(), targetType, this.conversionService);
|
||||
}
|
||||
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
return this.helperConverter.convert(Arrays.asList(ObjectUtils.toObjectArray(source)), sourceType, targetType);
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
if (sourceType.isAssignableTo(targetType)) {
|
||||
return source;
|
||||
}
|
||||
if (Array.getLength(source) == 0) {
|
||||
return null;
|
||||
}
|
||||
Object firstElement = Array.get(source, 0);
|
||||
return this.conversionService.convert(firstElement, sourceType.getElementTypeDescriptor(firstElement), targetType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2011 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,7 +49,7 @@ final class CollectionToArrayConverter implements ConditionalGenericConverter {
|
||||
}
|
||||
|
||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
return this.conversionService.canConvert(sourceType.getElementTypeDescriptor(), targetType.getElementTypeDescriptor());
|
||||
return ConversionUtils.canConvertElements(sourceType.getElementTypeDescriptor(), targetType.getElementTypeDescriptor(), this.conversionService);
|
||||
}
|
||||
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
|
||||
+22
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2011 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,26 +49,37 @@ final class CollectionToCollectionConverter implements ConditionalGenericConvert
|
||||
}
|
||||
|
||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
return this.conversionService.canConvert(sourceType.getElementTypeDescriptor(), targetType.getElementTypeDescriptor());
|
||||
return ConversionUtils.canConvertElements(
|
||||
sourceType.getElementTypeDescriptor(), targetType.getElementTypeDescriptor(), this.conversionService);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
boolean copyRequired = !targetType.getType().isInstance(source);
|
||||
Collection<?> sourceCollection = (Collection<?>) source;
|
||||
if (sourceCollection.isEmpty()) {
|
||||
if (!copyRequired && sourceCollection.isEmpty()) {
|
||||
return sourceCollection;
|
||||
}
|
||||
Collection target = CollectionFactory.createCollection(targetType.getType(), sourceCollection.size());
|
||||
for (Object sourceElement : sourceCollection) {
|
||||
Object targetElement = this.conversionService.convert(sourceElement,
|
||||
sourceType.getElementTypeDescriptor(sourceElement),
|
||||
targetType.getElementTypeDescriptor(sourceElement));
|
||||
target.add(targetElement);
|
||||
Collection<Object> target = CollectionFactory.createCollection(targetType.getType(), sourceCollection.size());
|
||||
if (targetType.getElementTypeDescriptor() == null) {
|
||||
for (Object element : sourceCollection) {
|
||||
target.add(element);
|
||||
}
|
||||
}
|
||||
return target;
|
||||
else {
|
||||
for (Object sourceElement : sourceCollection) {
|
||||
Object targetElement = this.conversionService.convert(sourceElement,
|
||||
sourceType.getElementTypeDescriptor(sourceElement), targetType.getElementTypeDescriptor());
|
||||
target.add(targetElement);
|
||||
if (sourceElement != targetElement) {
|
||||
copyRequired = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (copyRequired ? target : source);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user