Compare commits

..

1 Commits

Author SHA1 Message Date
Arjen Poutsma e3b58bf678 Released Spring 3.0 RC2 2009-11-13 15:13:07 +00:00
1599 changed files with 39435 additions and 73397 deletions
-13
View File
@@ -1,13 +0,0 @@
.springBeans
.DS_Store
target
integration-repo
ivy-cache
jmx.log
jxl.log
jmx.log
org.springframework.jdbc/derby.log
org.springframework.spring-parent/.classpath
org.springframework.spring-parent/.project
org.springframework.test/test-output/
spring-build/lib/docbook
+5 -10
View File
@@ -1,9 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="build-spring-framework" default="precommit">
<path id="unit.test.bundles">
<path id="bundles">
<pathelement location="../org.springframework.instrument"/>
<pathelement location="../org.springframework.instrument.tomcat"/>
<pathelement location="../org.springframework.asm"/>
<pathelement location="../org.springframework.core"/>
<pathelement location="../org.springframework.expression"/>
<pathelement location="../org.springframework.beans"/>
@@ -12,23 +13,17 @@
<pathelement location="../org.springframework.transaction"/>
<pathelement location="../org.springframework.oxm"/>
<pathelement location="../org.springframework.jms"/>
<pathelement location="../org.springframework.aspects"/>
<pathelement location="../org.springframework.jdbc"/>
<pathelement location="../org.springframework.web"/>
<pathelement location="../org.springframework.orm"/>
<pathelement location="../org.springframework.context.support"/>
<pathelement location="../org.springframework.aspects"/>
<pathelement location="../org.springframework.web.servlet"/>
<pathelement location="../org.springframework.web.portlet"/>
<pathelement location="../org.springframework.test"/>
<pathelement location="../org.springframework.web.struts"/>
</path>
<path id="bundles">
<pathelement location="../org.springframework.spring-parent"/>
<pathelement location="../org.springframework.asm"/>
<path refid="unit.test.bundles" />
<pathelement location="../org.springframework.integration-tests"/>
<pathelement location="../org.springframework.spring-library"/>
<pathelement location="../org.springframework.integration-tests"/>
</path>
<property file="${basedir}/../build.properties"/>
@@ -37,7 +32,7 @@
<import file="${basedir}/publish-documentation.xml"/>
<import file="${basedir}/../spring-build/multi-bundle/default.xml"/>
<target name="precommit" depends="clean, clean-integration, test"/>
<target name="precommit" depends="clean,clean-integration,test"/>
<presetdef name="javadoc.links">
<javadoc>
+131
View File
@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="generate-poms" xmlns:ivy="antlib:org.apache.ivy.ant">
<property file="${basedir}/../build.properties"/>
<import file="${basedir}/../spring-build/multi-bundle/default.xml"/>
<path id="modules-to-process">
<pathelement location="../org.springframework.instrument"/>
<pathelement location="../org.springframework.instrument.tomcat"/>
<pathelement location="../org.springframework.asm"/>
<pathelement location="../org.springframework.core"/>
<pathelement location="../org.springframework.expression"/>
<pathelement location="../org.springframework.beans"/>
<pathelement location="../org.springframework.aop"/>
<pathelement location="../org.springframework.context"/>
<pathelement location="../org.springframework.transaction"/>
<pathelement location="../org.springframework.oxm"/>
<pathelement location="../org.springframework.jms"/>
<pathelement location="../org.springframework.aspects"/>
<pathelement location="../org.springframework.jdbc"/>
<pathelement location="../org.springframework.web"/>
<pathelement location="../org.springframework.orm"/>
<pathelement location="../org.springframework.context.support"/>
<pathelement location="../org.springframework.web.servlet"/>
<pathelement location="../org.springframework.web.portlet"/>
<pathelement location="../org.springframework.test"/>
<pathelement location="../org.springframework.web.struts"/>
</path>
<condition property="maven.extension" value=".bat" else="">
<os family="windows"/>
</condition>
<property name="mvn.exe" value="mvn${maven.extension}"/>
<target name="test">
<echo message="pom version = ${project.version}"/>
</target>
<target name="generate-pom" depends="ivy.init">
<all-bundles target="do-generate-pom" buildpathRef="modules-to-process"/>
</target>
<target name="generate-pom-test">
<all-bundles target="do-generate-pom-test" buildpathRef="modules-to-process"/>
</target>
<target name="do-generate-pom" depends="ivy.init">
<delete file="pom.xml" quiet="true"/>
<delete file="central-pom.xml" quiet="true"/>
<ivy:makepom ivyfile="ivy.xml" pomfile="pom.xml">
<mapping conf="compile" scope="compile"/>
<mapping conf="test" scope="test"/>
<mapping conf="provided" scope="provided"/>
<mapping conf="runtime" scope="runtime"/>
</ivy:makepom>
<xmlproperty file="../org.springframework.spring-library/pom.xml"/>
<replaceregexp file="pom.xml"
match="&lt;version>.*?&lt;/version>"
replace="&lt;version>@project-version@&lt;/version>" />
<exec executable="${mvn.exe}" failonerror="true">
<arg line="org.springframework.build.repository:org.springframework.build.repository.maven:create-central"/>
</exec>
<move file="pom.xml" tofile="pom-bundle.xml"/>
<move file="central-pom.xml" tofile="pom.xml"/>
<replace file="pom.xml">
<replacetoken><![CDATA[ <version>@project-version@</version>]]></replacetoken>
<replacevalue><![CDATA[ <version>@project-version@</version>
<parent>
<groupId>org.springframework</groupId>
<artifactId>spring-parent</artifactId>
<relativePath>../org.springframework.spring-parent</relativePath>
<version>@project-version@</version>
</parent>
]]></replacevalue>
</replace>
<replace file="pom.xml" token="@project-version@" value="${project.version}"/>
<replace file="pom.xml" token="latest.integration" value="${project.version}"/>
<fixcrlf srcDir="."
eol="lf"
eof="remove"
includes="pom.xml"/>
</target>
<target name="remove-unresolved-references">
<!-- TODO in spring-context these are only found in S2 bundle repo, not maven central -->
<replace file="pom.xml">
<replacetoken><![CDATA[<dependency>
<groupId>com.oracle.oc4j</groupId>
<artifactId>oracle.classloader</artifactId>
<version>10.1.3.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sun.enterprise</groupId>
<artifactId>com.sun.enterprise.loader</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
]]></replacetoken>
<replacevalue><![CDATA[]]></replacevalue>
</replace>
</target>
<target name="do-generate-pom-test">
<exec executable="${mvn.exe}" failonerror="true">
<env key="MAVEN_TERMINATE_CMD" value="on" />
<arg line="-P stage,fast install"/>
</exec>
</target>
</project>
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="package-bundle">
<import file="publish-maven.xml"/>
<target name="package" depends="ivy.init">
<dist-jar/>
<src-jar/>
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="package-library">
<import file="publish-maven.xml"/>
<target name="package" depends="ivy.init">
<dist-jar/>
</target>
+9 -7
View File
@@ -41,6 +41,8 @@
<exclude name="*/target/**"/>
<exclude name="integration-repo/**"/>
<exclude name="ivy-cache/**"/>
<exclude name="org.springframework.samples.petclinic/**"/>
<!--exclude name="ivy-cache/repository/org.apache.velocity/org.apache.velocity.docbookframework.dist/**"/-->
<exclude name="spring-build/lib/docbook/**" />
<exclude name="**/*OLD*/**"/>
</fileset>
@@ -55,19 +57,19 @@
<zip destfile="${package.output.file}">
<zipfileset dir="${package.dir}">
<exclude name="${package.basename}/docs/**"/>
<exclude name="${package.basename}/projects/ivy-cache/**"/>
</zipfileset>
</zip>
<zip destfile="${artifacts.dir}/${package.basename}-with-docs.zip">
<zipfileset dir="${package.dir}"/>
</zip>
<zip destfile="${artifacts.dir}/${package.basename}-dependencies.zip">
<zipfileset dir="${basedir}/../ivy-cache/repository">
<exclude name="org.apache.velocity/org.apache.velocity.docbookframework.dist/**"/>
<zipfileset dir="${package.dir}">
<exclude name="${package.basename}/projects/ivy-cache/**"/>
</zipfileset>
</zip>
<!--zip destfile="${artifacts.dir}/${package.basename}-with-dependencies.zip">
<zipfileset dir="${package.dir}"/>
</zip-->
</target>
</project>
+101
View File
@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!--
This POM cannot be used to build Spring; it is a work in progress and should only be used as
part of a Maven repository upload bundle using artifacts created by the spring build system.
-->
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
<packaging>pom</packaging>
<version>3.0.0.RC2</version>
<name>Spring Framework</name>
<description>Spring is a layered Java/J2EE application platform, based on code published in Expert
One-on-One J2EE Design and Development by Rod Johnson (Wrox, 2002). </description>
<url>http://www.springframework.org</url>
<issueManagement>
<system>JIRA</system>
<url>http://jira.springframework.org/browse/SPR</url>
</issueManagement>
<ciManagement>
<system>Bamboo</system>
<url>https://build.springframework.org/browse/SPR</url>
</ciManagement>
<inceptionYear>2003</inceptionYear>
<organization>
<name>SpringSource</name>
<url>http://www.springsource.com</url>
</organization>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<scm>
<url>https://fisheye.springframework.org/browse/spring-framework</url>
<connection>scm:svn:https://src.springframework.org/svn/spring-framework/trunk</connection>
<developerConnection>scm:svn:https://src.springframework.org/svn/spring-framework/trunk</developerConnection>
</scm>
<mailingLists>
<mailingList>
<name> Spring Forum
</name>
<post>http://forum.springframework.org</post>
<archive>http://forum.springframework.org</archive>
</mailingList>
</mailingLists>
<modules>
<module>../org.springframework.spring-parent</module>
<module>../org.springframework.instrument</module>
<module>../org.springframework.instrument.tomcat</module>
<module>../org.springframework.asm</module>
<module>../org.springframework.core</module>
<module>../org.springframework.expression</module>
<module>../org.springframework.beans</module>
<module>../org.springframework.aop</module>
<module>../org.springframework.context</module>
<module>../org.springframework.transaction</module>
<module>../org.springframework.oxm</module>
<module>../org.springframework.jms</module>
<module>../org.springframework.aspects</module>
<module>../org.springframework.jdbc</module>
<module>../org.springframework.web</module>
<module>../org.springframework.orm</module>
<module>../org.springframework.context.support</module>
<module>../org.springframework.web.servlet</module>
<module>../org.springframework.web.portlet</module>
<module>../org.springframework.test</module>
<module>../org.springframework.web.struts</module>
</modules>
<profiles>
<profile>
<id>staging</id>
<distributionManagement>
<site>
<id>staging</id>
<url>file:///${user.dir}/target/staging</url>
</site>
<repository>
<id>staging</id>
<url>file:///${user.dir}/target/staging</url>
</repository>
<snapshotRepository>
<id>staging</id>
<url>file:///${user.dir}/target/staging</url>
</snapshotRepository>
</distributionManagement>
</profile>
</profiles>
</project>
@@ -3,10 +3,10 @@
<!-- Main targets -->
<target name="publish-documentation" depends="publish-documentation.init">
<sshexec host="static.springsource.org" username="${username}" keyfile="${key.file}" passphrase="${passphrase}"
<sshexec host="spring02.managed.contegix.com" username="${username}" keyfile="${key.file}" passphrase="${passphrase}"
command="mkdir /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}"
<scp remoteToDir="${username}@spring02.managed.contegix.com:/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="static.springsource.org" username="${username}" keyfile="${key.file}" passphrase="${passphrase}"
<sshexec host="spring02.managed.contegix.com" 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>
+95
View File
@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="publish-maven-central-only-pom" xmlns:maven="antlib:org.apache.maven.artifact.ant">
<description>
This build file publishes to a maven repository and two ways.
1. Publish jar, source-jar, and pom artifacts.
2. Publish only the pom artifact.
The additional complexity in the implementation is due to a bug in the maven ant tasks version 2.0.8 that
prevents deploying to a local file repository on windows.
</description>
<condition property="is.windows" value="windows">
<os family="windows"/>
</condition>
<!-- top level targets -->
<target name="publish-maven-central-only-pom-artifacts" depends="publish-central-only-pom-windows,publish-central-only-pom-unix">
</target>
<target name="publish-maven-central-code-artifacts" depends="publish-central-windows,publish-code-unix">
</target>
<target name="publish-maven-milestone-only-pom-artifacts" depends="maven.init">
<maven:deploy>
<remoteRepository url="s3://${publish.bucket}/maven/bundles/${adjusted.release.type}">
<authentication username="${accessKey}" passphrase="${secretKey}"/>
</remoteRepository>
<pom file="${local.pom.output.file}"/>
</maven:deploy>
</target>
<target name="publish-maven-milestone-code-artifacts" depends="maven.init">
<maven:deploy file="${jar.output.file}">
<remoteRepository url="s3://${publish.bucket}/maven/bundles/${adjusted.release.type}">
<authentication username="${accessKey}" passphrase="${secretKey}"/>
</remoteRepository>
<pom file="${pom.output.file}"/>
<attach file="${source-jar.output.file}" classifier="sources"/>
</maven:deploy>
</target>
<target name="install-pom" depends="maven.init">
<maven:install>
<pom file="${local.pom.output.file}"/>
</maven:install>
</target>
<!-- Supporting targets -->
<!-- POM only deployment -->
<target name="publish-central-only-pom-windows" depends="maven.init" if="is.windows">
<maven:deploy>
<!-- Due to http://jira.codehaus.org/browse/MANTTASKS-103 in 2.0.8 on windows, fixed in 2.0.9 -->
<!-- Assuming using local file, value of variable should be of the form L:\temp\maven-repo-test -->
<remoteRepository id="localDisk" url="file:${maven.central.repository}"/>
<pom file="${local.pom.output.file}"/>
</maven:deploy>
</target>
<target name="publish-central-only-pom-unix" depends="maven.init" unless="is.windows">
<maven:deploy>
<remoteRepository url="${maven.central.repository}"/>
<pom file="${local.pom.output.file}"/>
</maven:deploy>
</target>
<!-- jar, source-jar and POM deployment -->
<target name="publish-central-windows" depends="maven.init">
<maven:deploy file="${jar.output.file}">
<!-- Due to http://jira.codehaus.org/browse/MANTTASKS-103 in 2.0.8 on windows, fixed in 2.0.9 -->
<!-- Assuming using local file, value of variable should be of the form L:\temp\maven-repo-test -->
<remoteRepository id="localDisk" url="file:${maven.central.repository}"/>
<pom file="${local.pom.output.file}"/>
<attach file="${source-jar.output.file}" classifier="sources"/>
</maven:deploy>
</target>
<target name="publish-code-unix" depends="maven.init" unless="is.windows">
<maven:deploy file="${jar.output.file}">
<remoteRepository url="${maven.central.repository}"/>
<pom file="${local.pom.output.file}"/>
<attach file="${source-jar.output.file}" classifier="sources"/>
</maven:deploy>
</target>
</project>
+6 -6
View File
@@ -7,7 +7,7 @@
<target name="publish-package" depends="aws.init">
<checksum file="${package.output.file}" algorithm="sha1"/>
<checksum file="${artifacts.dir}/${package.basename}-with-docs.zip" algorithm="sha1"/>
<checksum file="${artifacts.dir}/${package.basename}-dependencies.zip" algorithm="sha1"/>
<!--checksum file="${artifacts.dir}/${package.basename}-with-dependencies.zip" algorithm="sha1"/-->
<aws:s3 accessKey="${accessKey}" secretKey="${secretKey}">
<upload bucketName="dist.${bucket.basename}" file="${package.output.file}"
@@ -30,15 +30,15 @@
<upload bucketName="dist.${bucket.basename}" file="${artifacts.dir}/${package.basename}-with-docs.zip.sha1"
toFile="${adjusted.release.type}/${project.key}/${package.basename}-with-docs.zip.sha1" publicRead="true"/>
<upload bucketName="dist.${bucket.basename}" file="${artifacts.dir}/${package.basename}-dependencies.zip"
toFile="${adjusted.release.type}/${project.key}/${package.basename}-dependencies.zip" publicRead="true">
<!--upload bucketName="dist.${bucket.basename}" file="${artifacts.dir}/${package.basename}-with-dependencies.zip"
toFile="${adjusted.release.type}/${project.key}/${package.basename}-with-dependencies.zip" publicRead="true">
<metadata name="project.name" value="Spring Framework"/>
<metadata name="release.type" value="${release.type}"/>
<metadata name="bundle.version" value="${bundle.version}"/>
<metadata name="package.file.name" value="${package.basename}-dependencies.zip"/>
<metadata name="package.file.name" value="${package.basename}-with-dependencies.zip"/>
</upload>
<upload bucketName="dist.${bucket.basename}" file="${artifacts.dir}/${package.basename}-dependencies.zip.sha1"
toFile="${adjusted.release.type}/${project.key}/${package.basename}-dependencies.zip.sha1" publicRead="true"/>
<upload bucketName="dist.${bucket.basename}" file="${artifacts.dir}/${package.basename}-with-dependencies.zip.sha1"
toFile="${adjusted.release.type}/${project.key}/${package.basename}-with-dependencies.zip.sha1" publicRead="true"/-->
</aws:s3>
</target>
</project>
+58
View File
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="publish-spring-framework" xmlns:maven="antlib:org.apache.maven.artifact.ant">
<property file="${basedir}/../build.properties"/>
<import file="${basedir}/../spring-build/multi-bundle/default.xml"/>
<path id="modules-with-code-artifacts">
<pathelement location="../org.springframework.instrument"/>
<pathelement location="../org.springframework.instrument.tomcat"/>
<pathelement location="../org.springframework.asm"/>
<pathelement location="../org.springframework.core"/>
<pathelement location="../org.springframework.expression"/>
<pathelement location="../org.springframework.beans"/>
<pathelement location="../org.springframework.aop"/>
<pathelement location="../org.springframework.context"/>
<pathelement location="../org.springframework.transaction"/>
<pathelement location="../org.springframework.oxm"/>
<pathelement location="../org.springframework.jms"/>
<pathelement location="../org.springframework.aspects"/>
<pathelement location="../org.springframework.jdbc"/>
<pathelement location="../org.springframework.web"/>
<pathelement location="../org.springframework.orm"/>
<pathelement location="../org.springframework.context.support"/>
<pathelement location="../org.springframework.web.servlet"/>
<pathelement location="../org.springframework.web.portlet"/>
<pathelement location="../org.springframework.test"/>
<pathelement location="../org.springframework.web.struts"/>
</path>
<path id="modules-with-only-pom-artifacts">
<pathelement location="../org.springframework.spring-library"/>
<pathelement location="../org.springframework.spring-parent"/>
</path>
<!-- for milestones -->
<target name="publish-maven-milestone" depends="publish-maven-milestone-only-pom">
<all-bundles target="publish-maven-milestone-code-artifacts" buildpathRef="modules-with-code-artifacts"/>
</target>
<target name="publish-maven-milestone-only-pom">
<all-bundles target="publish-maven-milestone-only-pom-artifacts" buildpathRef="modules-with-only-pom-artifacts"/>
</target>
<!-- for releases -->
<target name="publish-maven-central-release" depends="publish-maven-central-only-pom-release">
<all-bundles target="publish-maven-central-code-artifacts" buildpathRef="modules-with-code-artifacts"/>
</target>
<target name="publish-maven-central-only-pom-release">
<all-bundles target="publish-maven-central-only-pom-artifacts" buildpathRef="modules-with-only-pom-artifacts"/>
</target>
</project>
@@ -3,408 +3,6 @@ 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)
-------------------------------------
* support for Hibernate 3.6 final
* added core serializer abstraction with default implementations using Java Serialization
* consistent use of JDK 1.5's "ThreadLocal.remove()" over "ThreadLocal.set(null)"
* fixed JodaTimeContextHolder to use a non-inheritable ThreadLocal and expose a reset method
* revised "ClassUtils.isAssignable" semantics to cover primitives vs wrappers in both directions
* optimized AnnotationUtils findAnnotation performance for repeated search on same interfaces
* ConversionService protects itself against infinite recursion in ObjectToCollectionConverter
* fixed TypeDescriptor to correctly resolve nested collections and their element types
* BeanWrapper does not attempt to populate Map values on access (just auto-grows Map itself)
* fixed Autowired/CommonAnnotationBeanPostProcessor to prevent race condition in skipping check
* fixed @Value injection to correctly cache temporary null results for non-singleton beans
* ApplicationContext registers context-specific ClassArrayEditor for its bean ClassLoader
* refined ApplicationContext singleton processing to not fail for manually registered null instances
* fixed ApplicationContext event processing for repeated invocations to non-singleton listener beans
* optimized @Bean error messages for static factory methods as well as for argument type mismatches
* modified expression parsing to pass full TypeDescriptor context through to ConversionService calls
* adapted expression parser's Constructor/MethodResolver to accept TypeDescriptors instead of raw types
* SpEL supports projection on any kind of Collection (not just on Lists and arrays)
* SpEL MapAccessor consistently rejects "target.key" style access to Maps if no such key is found
* SpEL method invocations prefer method with fewest parameters (e.g. no-arg over vararg)
* AspectJExpressionPointcut uses bean ClassLoader for initializing the AspectJ pointcut parser
* added AnnotationAsyncExecutionAspect as AspectJ-based variant of @Async processing
* added mode="proxy"/"aspectj" and proxy-target-class options to task:annotation-driven
* JDBC bundle uses local ClassLoader as bean ClassLoader for "sql-error-codes.xml" parsing
* EmbeddedDatabaseFactory shuts down database when failing to populate it in "initDatabase()"
* embedded database support now also works with Derby >= 10.6
* "jdbc:embedded-database" uses id as database name to allow multiple ones in parallel
* ResourceDatabasePopulator throws descriptive ScriptStatementFailedException with resource details
* added configurable Connection/Statement/ResultSet target types to Jdbc4NativeJdbcExtractor
* added OracleJdbc4NativeJdbcExtractor with pre-configured Oracle JDBC API types
* DefaultLobHandler's "wrapAsLob" mode works with PostgreSQL's "getAsciiStream()" requirement
* ResultSetWrappingSqlRowSet (as used by JdbcTemplate's "queryForRowSet") supports column labels now
* LocalSessionFactoryBean's "entityCacheStrategies" works with region names on Hibernate 3.6 as well
* fixed DefaultMessageListenerContainer's no-message-received commit to work without Session caching
* DefaultMessageListenerContainer's skips no-message-received commit on Tibco (avoiding a deadlock)
* JaxWsPortClientInterceptor does not fall back to annotation-specified name as portName anymore
* UriTemplate is serializable now
* fixed AnnotationMethodHandlerAdapter's caching to avoid concurrency issues in RequestMappingInfo
* fixed @MVC processing of parameter-level annotations to work with interface-based proxies again
* revised @RequestParam processing to support CSV-to-array/collection binding with ConversionService
* fixed EvalTag's EvaluationContext caching to properly handle JSP tag caching across requests
* AbstractJasperReportsView only sets locale model attributes if not present already
* DispatcherPortlet throws custom NoHandlerFoundException instead of misleading UnavailableException
* DispatcherPortlet copies all action parameters to render parameters in case of an action exception
* DispatcherPortlet's default resource serving explicitly prevents access to WEB-INF and META-INF
* Portlet @ExceptionHandler methods allow for writing the response directly (like in the Servlet case)
* MockHttpServletRequest/HttpSession/etc returns independent Enumeration from "getAttributeNames()"
Changes in version 3.0.4 (2010-08-19)
-------------------------------------
* support for Hibernate Core 3.6, Hibernate Validator 4.1, EclipseLink 2.1, EHCache 2.2
* OSGi manifest version range accepts EHCache 2.x as well
* added "contentLength()" method to Resource abstraction
* URL-based Resource variants introspect "last-modified" and "content-length" response headers
* refined "exists()" check for UrlResource (HEAD request) and ClassPathResource (URL resolution)
* ConversionService is able to deal with empty collections and nested collections (fixed regression)
* ConversionService properly handles nested Resource arrays in Map values (fixed regression)
* ConversionService does not accidentally use copy constructor for same type
* fixed double ConversionFailedException nesting for ObjectToObjectConverter invocations
* BeanWrapper preserves annotation information for individual array/list/map elements
* Spring's constructor resolution consistently finds non-public multi-arg constructors
* revised constructor argument caching, avoiding a race condition for converted argument values
* SpEL passes full collection type context (generics, annotations) to ConversionService
* SpEL 'select last' operator now works consistently with maps
* BeanWrapper/DataBinder's "autoGrowNestedPaths" works for Maps as well
* fixed concurrency issue in TypedStringValue, showing for nested typed Maps in prototype beans
* fixed WeakReferenceMonitor to never stop its monitoring thread if an entry has been registered
* fixed CronTrigger to correctly parse month parts expressed as numbers (1-12 instead of 0-11)
* TaskExecutorFactoryBean (as used by task:executor) exposes full ThreadPoolTaskExecutor type
* JmsResourceHolder does not ignore IllegalStateException from locally synchronized transaction
* fixed JMS CachingConnectionFactory to correctly cache a producer without fixed destination as well
* DefaultMessageListenerContainer triggers Session commit even if no message has been received
* DefaultMessageListenerContainer supports client id setting even for non-shared Connections
* Spring's MessageEndpointFactory classes are now JCA 1.6 compliant as well
* AbstractJaxWsServiceExporter supports "bindingType" bean property, overriding @BindingType
* AbstractJaxWsServiceExporter supports "webServiceFeatures" bean property on JAX-WS 2.2
* JaxWsPortProxyFactoryBean takes "wsdlDocumentUrl", "namespaceUri" etc defaults from @WebService
* Jaxb2Marshaller's "marshallerProperties" Map accepts any value type
* SpringTemplateLoader for FreeMarker supports last-modified timestamp through Resource abstraction
* HibernateJpaDialect correctly closes borrowed connections even for nested JDBC executions
* DefaultJdoDialect supports JDO 3.0 query timeout facility (as supported by DataNucleus 2.1)
* transaction names based on method id from most specific method (target class instead of interface)
* added "validationMessageSource" to LocalValidatorFactoryBean, for Spring-based validation messages
* Spring field error arguments include actually declared annotation attributes in alphabetical order
* JSR-303 Pattern message resolvable through Spring MessageSource (despite special characters)
* DispatcherServlet applies default view name translation to error views as well
* mvc:annotation-driven reliably detects JSR-303 and JAXB2 in an OSGi environment as well
* revised @MVC handler method resolution with respect to handler methods on generic interfaces
* @MVC handler methods reliably resolve MultipartRequest arguments with HiddenHttpMethodFilter
* WebDataBinder and @MVC request params detect and introspect MultipartFile arrays as well
* fixed @PathVariable regression in combination with ConversionService usage on DataBinder
* @CookieValue returns decoded cookie value in a Servlet environment (analogous to @RequestParam)
* MVC HandlerExceptionResolvers prevent caching for exception views if preventResponseCaching=true
* @ExceptionHandler works for inherited method and CGLIB proxies on Portlet controllers as well
* Portlet @MVC's implicit render model will be updated at the end of the event phase
* Portlet AbstractController consistently uses session mutex if "synchronizeOnSession" is active
* PortletWrappingController supports Portlet 2.0 resource and event requests as well
* fixed JSP EvalTag to render null result as empty String instead of "null" String
* JSP EvalTag resolves "@myBeanName" references in expressions against the WebApplicationContext
* added support for static resource serving: ResourceHttpRequestHandler, mvc:resources
* revised DispatcherServlet's last-modified handling to properly work with scoped controllers
* MockMultipartHttpServletRequest pre-defines method "POST" and content type "multipart/form-data"
Changes in version 3.0.3 (2010-06-15)
-------------------------------------
* Spring autodetects JodaTime 1.3 or higher (as required), ignoring older JodaTime versions
* clarified that Spring's Jackson support requires Jackson 1.3 or higher
* JPA 2.0 support tested and supported with Hibernate 3.5.2 and OpenJPA 2.0.0 GA as well
* revised VFS support for Spring's component scanning to work on JBoss AS 6.0.0 M3 as well
* fixed URIEditor's URI construction to consider fragment as well
* added default InputSourceEditor for SAX InputSource construction with a URL String as system id
* CachedIntrospectionResults only caches GenericTypeAwarePropertyDescriptors if fully safe
* revised BeanWrapper's exception wrapping to consistently handle ConversionExceptions
* DefaultListableBeanFactory checks for alias circle on registerAlias (avoiding endless loop)
* ConversionService is able to apply Converters to interface-based array elements
* ConversionService fully supports conversion from String to MediaType now (through 'valueOf')
* revised exception handling in ObjectToObjectConverter, avoiding InvocationTargetExceptions
* a context ConversionService is able to override an ApplicationContext's resource editors
* refined LifecycleProcessor exception handling, properly wrapping a start exception from a bean
* revised DefaultLifecycleProcessor's handling of circular dependencies to avoid stack overflow
* fixed constructor argument caching for prototypes with multiple constructor matches
* specific detection of CGLIB subclasses in order to properly handle CGLIB interfaces
* registerDependentBean resolves to the canonical bean name in order to handle alias references
* fixed registerResolvableDependency mechanism to correctly handle non-serializable factory objects
* added "expose-proxy" attribute to aop namespace (enforcing AopContext proxy exposure with CGLIB)
* revised AbstractInterceptorDrivenBeanDefinitionDecorator for further alignment with auto-proxying
* BeanDefinitionVisitor/PropertyPlaceholderConfigurer finds and resolves values in arrays as well
* property placeholders can deal with nested expressions which happen to use the same suffix
* SpEL's Elvis operator is able to deal with #{${myProp}?:defaultValue} case if myProp is empty
* introduced EmbeddedValueResolverAware callback interface for convenient placeholder resolution
* @Transactional qualifier value matches against @Qualifier annotations on @Bean methods as well
* setTransactionIsolation on JDBC Connection only called when actually necessary (for PostgreSQL)
* added limit for parsed SQL cache to NamedParameterJdbcTemplate (default is 256; configurable)
* CachingConnectionFactory detects destination equality for WebSphere MQ as well (using toString)
* DefaultPersistenceUnitManager's getPersistenceUnitInfo method has 2.5 compatible signature again
* DefaultMessageListenerContainer reacts to maxConcurrentConsumers reduction for long-lived tasks
* added "idleConsumerLimit" bean property to DefaultMessageListenerContainer (default is 1)
* AsyncAnnotationBeanPostProcessor consistently adds @Async processing as first Advisor in the chain
* ScheduledTaskRegistrar (as used for @Scheduled processing) properly shuts down its default executor
* CronTrigger defensively protects itself against accidental re-fires if a task runs too early
* MailSendException includes all messages as failed messages in case of a connect failure
* added support for JAX-WS 2.1 WebServiceFeatures to JaxWsPortClientInterceptor/PortProxyFactoryBean
* added XmlAwareFormHttpMessageConverter, taking over the 3.0.2-introduced XML multipart support
* ServletContextResourcePatternResolver handles "/WEB-INF/lib/*.jar!/**/context.xml" style patterns
* fixed MVC mapping regression for servlet url-pattern "/" case on servers other than WebSphere
* MVC mappings properly apply even to welcome file entries that forward to a DispatcherServlet
* fixed @ExceptionHandler resolution in case of multiple matches at different inheritance levels
* revised Portlet SessionStatus.setComplete() to avoid re-exposure of attributes in render phase
* shortened Portlet MVC's implicit model render parameter name to "implicitModel"
* added convenient "checkRefresh" bean property to TilesConfigurer
* TilesConfigurer's "definitionsFactoryClass" property applies common Tiles DefinitionsFactory setup
* JSP FormTag calculates proper default form action even when using a rewrite filter on WebSphere
* JSP HiddenInputTag allows for using common HTML attributes (equivalent to LabelTag)
* fixed JSP ErrorsTag to avoid invalid "*.errors" id, using form object name as id prefix instead
* fixed JSP SelectTag's support for rendering enum constants
* JSP Radiobutton/CheckboxesTag utilizes PropertyEditor/ConversionService for label rendering
* MockHttpServletResponse supports multiple includes
Changes in version 3.0.2 (2010-04-02)
-------------------------------------
* fixed cross-module version ranges in OSGi manifests
* fixed contents of org.springframework.web.struts jar
* upgraded to Hibernate Validator 4.0.2 and Jackson 1.4.2
* compatibility with Hibernate 3.5 final (native and also as a JPA 2.0 provider)
* compatibility with OpenJPA 2.0 (support for JPA 2.0 persistence.xml versioning)
* compatibility with Hessian 4.0 (in terms of exception propagation)
* compatibility with JasperReports 3.x (in terms of resource management)
* restored full compatibility with Servlet 2.4 containers on all VMs
* PropertyEditor lookup fallback works on Google App Engine as well
* fixed TypeDescriptor/MethodParameter toString for all cases in debug log messages
* widened AbstractFactoryBean's "getObjectType" signature to return any Class as well
* BeanPostProcessors are allowed to return a null bean value in the middle of the chain
* autowire="byType" ignores parameter name when choosing a primary bean, as defined
* ObjectFactoryCreatingFactoryBean creates a serializable ObjectFactory reference
* added ProviderCreatingFactoryBean, exposing a serializable JSR-330 Provider reference
* "conversionService" bean will be ignored if it is not of type ConversionService
* revised AbstractInterceptorDrivenBeanDefinitionDecorator for alignment with auto-proxying
* SimpleJdbcCall's "returningResultSet" accepts any plain RowMapper now
* added public "validateDatabaseSchema" method to Hibernate LocalSessionFactoryBean
* HibernateJpaDialect borrows JDBC Connection on demand (supporting aggressive release)
* JCA listener containers delegate to wrapped Transaction handle (for Geronimo compatibility)
* @Transactional qualifiers work in unit tests as well (TransactionalTestExecutionListener)
* @Value processing works in test instances (using the test context framework) as well now
* @DirtiesContext is now inherited for class-level usage
* NativeWebRequest detects native MultipartRequest when decorated by HiddenHttpMethodFilter
* WebRequestInterceptor exposes HttpServletResponse through NativeWebRequest (after downcast)
* WebContentInterceptor does not restrict HTTP methods by default anymore
* WebApplicationObjectSupport's initServletContext will be called only once in any scenario
* DispatcherPortlet passes handler instance into HandlerExceptionResolver for action exception
* DispatcherPortlet applies preHandleRender callbacks in case of action exception as well
* UrlPathHelper cuts off trailing servlet-path slashes for root mappings (on WebSphere)
* introduced support for HttpEntity and ResponseEntity wrappers, adding context to body values
* fixed DataBinder's conversion error handling for direct field access with ConversionService
* @InitBinder methods support all applicable Spring 3.0 parameter annotations as well
* fixed @RequestParam(required=false) regression for @InitBinder methods
* @ExceptionHandler methods consistently receive original exception
* fixed indexed property binding regression in form tag library
* fixed @Configurable issue with null bean name
Changes in version 3.0.1 (2010-02-18)
-------------------------------------
* upgraded to AspectJ 1.6.8
* full support for JPA 2.0 persistence schema and PersistenceUnitInfo SPI
* support for JPA PersistenceContext/Unit injection on Google App Engine
* support for Hibernate 3.5 (as native Hibernate API and as JPA 2.0 provider)
* support for Tiles 2.2.1 (preserving compatibility with Tiles 2.1.2 and above)
* consistent treatment of unresolvable placeholders for Resource and Resource array properties
* ConversionFailedException exDLBFposes offending value through public "getValue()" method
* fixed BeanFactory's "getBeansWithAnnotation" to ignore beans with non-determinable type
* widened FactoryBean's "getObjectType" signature to return any Class (Class<?>)
* do not ever consider Object as a candidate type for autowiring by type (autowire="byType")
* BeanDefinitionReader and ClassPath/FileSystemXmlApplicationContext use varargs where possible
* introduced BeanDefinitionRegistryPostProcessor extension to BeanFactoryPostProcessor
* @Configuration classes support definition of BeanFactoryPostProcessor beans
* component-scan's scoped-proxy attribute applies to scope-annotated singleton beans as well
* generic ApplicationListener event type gets detected through AOP proxy as well
* ApplicationListeners will only be executed once per event (even for scripted objects)
* ApplicationListeners will get detected lazily as well (e.g. on @Bean's concrete result)
* inner bean ApplicationListeners will be invoked through their proxy (if any)
* fixed SimpleApplicationEventMulticaster's retriever caching to allow for proper removal
* context-specific "conversionService" bean may refer to annotation-configured converter beans
* refined DefaultLifecycleProcessor's start/stop logging and stop exception handling
* DefaultLifecycleProcessor allows for overriding specific hooks in subclasses
* BeanNameAutoProxyCreator detects alias matches for specified bean names
* proxies with AspectJ pointcuts are fully serializable within a BeanFactory now
* SharedEntityManagerCreator's EntityManager proxies are fully serializable now
* Query call chaining works with shared EntityManager proxy outside of transaction as well
* TransactionInterceptor is able to serialize "transactionManagerBeanName" as well
* non-matching @Transactional qualifier value will lead to IllegalStateException
* fixed WebSphereUowTransactionManager regression: correctly roll back in case of exception
* JndiObjectFactoryBean explicitly only chooses public interfaces as default proxy interfaces
* added vararg variants of query methods to JdbcTemplate (as known from SimpleJdbcTemplate)
* MBeanClientInterceptor/MBeanProxyFactoryBean understands CompositeData/TabularData arrays
* added "workManagerMBeanName" property to JBossWorkManagerTaskExecutor
* task:executor's id value is now used as thread name prefix of ThreadPoolTaskExecutor
* fixed @Scheduled processing to kick in once only even in an ApplicationContext hierarchy
* fixed MediaType's Comparable behavior to do a full comparison, aligned with equals behavior
* added "sortBySpecificity" method to MediaType, for typical use with accept header matching
* MimeMessageHelper encodes from, to, cc, bcc String addresses with given encoding as well
* changed HttpStatus.REQUEST_TOO_LONG constant to REQUEST_ENTITY_TOO_LARGE
* relaxed generic Class declaration in HttpMessageConverter's canRead/canWrite/read signatures
* fixed "mvc:view-controller" to work in a fully isolated fashion on Spring Dynamic Modules
* DefaultRequestToViewNameTranslator strips trailing slashes as well (can also be turned off)
* @RequestParam/RequestHeader/CookieValue's defaultValue allows for declaring empty String
* @SessionAttributes works when used on an annotated controller interface with AOP proxying
* WebRequest is a resolvable dependency in Servlet/Portlet web application contexts
* revised JSP-based views to never fail when trying to set Servlet API forward attributes
* lenient evaluation of boolean 'true' attribute expressions in JSP form tag library
* added new spring:eval tag for evaluating SpEL expressions from JSP pages
* SpringBeanAutowiringSupport works in extra ClassLoaders as well (e.g. WebLogic JAX-WS)
Changes in version 3.0.0.GA (2009-12-16)
----------------------------------------
* component scanning autodetects the new EE 6 "javax.annotation.ManagedBean" stereotype
* updated JPA 2.0 support to the final spec (tested compatibility with EclipseLink 2.0 GA)
* full support for GlassFish V3 GA (includes component scanning and load-time weaving)
* upgraded to JRuby 1.4 (while remaining compatible with JRuby 1.1 and above)
* bean property names are matched leniently ("title" and "Title"; "ISBN" and "iSBN")
* bean properties of type enum array/collection can be populated with comma-separated String
* removed getBeansWithAnnotation(Class,boolean,boolean) method from ListableBeanFactory
* PropertyPlaceholderConfigurer is compatible with Spring 2.5 extensions (again)
* SmartLifecycle beans will get auto-started on demand even if marked as lazy-init
* MBeanExporter detects FactoryBean-exported resources independent from declaration order
* refactored SpelExpressionParser to accept SpelParserConfiguration object with boolean flags
* revised TypeDescriptor's valueOf and forObject factory methods with some level of caching
* revised GenericConverter's "getConvertibleTypes" signature to return Set of ConvertiblePair
* GenericConversionService prefers matches against inherited interfaces over superclasses
* renamed ConverterRegistry's addGenericConverter(GenericConverter) method to addConverter
* no default converters for Object-to-Map and Map-To-Object anymore
* default converter for String-to-Properties parsing only applies for actual Properties objects
* default ObjectToStringConverter only stringifies objects that indicate proper toString behavior
* added "converters" property to FormattingConversionServiceFactoryBean as well
* full support for formatters and formatting annotations on array/collection elements
* no default number formatter (relying on plain java.lang.Number parsing and rendering)
* no default formatters for Date/Calendar (requiring explicit use of @DateTimeFormat)
* BeanValidationPostProcessor runs in before-initialization phase (before init methods) by default
* removed MultipartRequest mixin interface again (avoiding a package dependency cycle)
* revised RestTemplate method signatures to accept Object values instead of just Strings
* revised path variable extraction to properly deal with dots in variable values (again)
* reintroduced createBinder template method in Servlet/Portlet AnnotationMethodHandlerAdapter
Changes in version 3.0.0.RC3 (2009-12-01)
-----------------------------------------
* prepared for Grails and ROO requirements
* restored compatibility with Apache CXF
* fixed bean definition import via "classpath*:" URLs
* added chaining-capable "add" method to MutablePropertyValues
* constructor arguments can be overridden by name in child bean definitions
* BeanDefinitions return isSingleton()=true by default again, with scope name empty
* init/destroy methods get processed in the order of declaration at each hierarchy level
* fixed lookup of LifecycleProcessor bean in a Spring Dynamic Modules environment
* refined lifecycle processing through introduction of startup/shutdown phases
* fixed transaction synchronization setup with TransactionAwareDataSourceProxy involved
* added support for Hibernate 3.3 RegionFactory cache SPI to LocalSessionFactoryBean
* JSR-303 SpringValidatorAdapter uses field name as first argument (analogous to bind errors)
* replaced DefaultConversionService with ConversionServiceFactory(Bean)
* revised FormatterRegistry interface and FormattingConversionServiceFactoryBean setup
* mvc:annotation-driven exposes default Validator and ConversionService as top-level beans
* mvc:annotation-driven registers applicable HttpMessageConverters by default, if available
* added interceptors support to mvc namespace, for path-based interceptor mappings
Changes in version 3.0.0.RC2 (2009-11-13)
-----------------------------------------
+13 -15
View File
@@ -1,27 +1,25 @@
SPRING FRAMEWORK 3.0.7 (December 2011)
--------------------------------------
http://www.springsource.org
SPRING FRAMEWORK 3.0 RC2 (November 2009)
-------------------------------------
http://www.springframework.org
1. INTRODUCTION
Spring Framework 3.0 is the next generation of Spring: fully Java 5 based,
EL enabled, REST enabled, and with support for JSR-330 (Dependency
Injection) and JSR-303 (Bean Validation).
This is the second release candidate of Spring 3.0, which is scheduled for final release in Q4 2009.
It release is feature complete, but may still have some issues.
2. RELEASE NOTES
This release comes with complete reference documentation. For further
details, consult the provided javadoc for specific packages and classes.
This release comes with complete reference documentation already. Consult the provided
javadoc for technical details of specific packages and classes.
3. DISTRIBUTION JAR FILES
The Spring Framework module jar files can be found in the 'dist'
directory. Note that this release does not contain a 'spring.jar' file
anymore, in contrast to previous Spring generations. Furthermore, the jar
file names now follow bundle repository conventions.
The Spring Framework module jar files can be found in the 'dist' directory. Note that
this release does not contain a 'spring.jar' file anymore, in contrast to previous Spring
generations. Furthermore, the jar file names follow bundle repository conventions now.
4. GETTING STARTED
Please consult the blog examples at http://blog.springsource.com as well
as sections of interest in the reference documentation. Sample
applications and related material are provided as separate downloads.
A Getting Started guide is to be provided in time for Spring 3.0 GA. For the time being,
please consult the blog examples at http://blog.springsource.com as well as the sections
of interest in the reference documentation.
+24 -30
View File
@@ -1,30 +1,24 @@
version=3.0.8
# 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.0
build.stamp=RC2
release.type=milestone
natural.name=spring-framework
project.name=Spring Framework
project.key=SPR
ivy.cache.dir=${basedir}/../ivy-cache
integration.repo.dir=${basedir}/../integration-repo
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
+2 -5
View File
@@ -1,5 +1,2 @@
#common dependency versions
aspectj.version=1.6.8.RELEASE
slf4j.version=1.5.3
junit.version=4.7.0
testng.version=5.10.0
org.testng.version=5.10.0
org.junit.version=4.7.0
+21 -22
View File
@@ -1,22 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/main/java"/>
<classpathentry kind="src" path="src/main/resources"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="var" path="IVY_CACHE/org.aopalliance/com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-1.0.0.jar" sourcepath="/IVY_CACHE/org.aopalliance/com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-sources-1.0.0.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-sources-1.1.1.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.easymock/com.springsource.org.easymock/2.5.1/com.springsource.org.easymock-2.5.1.jar" sourcepath="/IVY_CACHE/org.easymock/com.springsource.org.easymock/2.5.1/com.springsource.org.easymock-sources-2.5.1.jar"/>
<classpathentry kind="var" path="IVY_CACHE/com.jamonapi/com.springsource.com.jamonapi/2.4.0/com.springsource.com.jamonapi-2.4.0.jar" sourcepath="/IVY_CACHE/com.jamonapi/com.springsource.com.jamonapi/2.4.0/com.springsource.com.jamonapi-sources-2.4.0.jar"/>
<classpathentry kind="var" path="IVY_CACHE/net.sourceforge.cglib/com.springsource.net.sf.cglib/2.2.0/com.springsource.net.sf.cglib-2.2.0.jar" sourcepath="/IVY_CACHE/net.sourceforge.cglib/com.springsource.net.sf.cglib/2.1.3/com.springsource.net.sf.cglib-sources-2.1.3.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.apache.log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-1.2.15.jar" sourcepath="/IVY_CACHE/org.apache.log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-sources-1.2.15.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-4.7.0.jar" sourcepath="/IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-sources-4.7.0.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.pool/1.3.0/com.springsource.org.apache.commons.pool-1.3.0.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.pool/1.3.0/com.springsource.org.apache.commons.pool-sources-1.3.0.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.aspectj/com.springsource.org.aspectj.weaver/1.6.8.RELEASE/com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar" sourcepath="IVY_CACHE/org.aspectj/com.springsource.org.aspectj.weaver/1.6.8.RELEASE/com.springsource.org.aspectj.weaver-sources-1.6.8.RELEASE.jar"/>
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.beans"/>
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.core"/>
<classpathentry kind="lib" path="/org.springframework.asm/target/artifacts/org.springframework.asm.jar" sourcepath="/org.springframework.asm/target/artifacts/org.springframework.asm-sources.jar"/>
<classpathentry kind="var" path="IVY_CACHE"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/main/java"/>
<classpathentry kind="src" path="src/main/resources"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="var" path="IVY_CACHE/org.aopalliance/com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-1.0.0.jar" sourcepath="/IVY_CACHE/org.aopalliance/com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-sources-1.0.0.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-sources-1.1.1.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.easymock/com.springsource.org.easymock/2.5.1/com.springsource.org.easymock-2.5.1.jar" sourcepath="/IVY_CACHE/org.easymock/com.springsource.org.easymock/2.5.1/com.springsource.org.easymock-sources-2.5.1.jar"/>
<classpathentry kind="var" path="IVY_CACHE/com.jamonapi/com.springsource.com.jamonapi/2.4.0/com.springsource.com.jamonapi-2.4.0.jar" sourcepath="/IVY_CACHE/com.jamonapi/com.springsource.com.jamonapi/2.4.0/com.springsource.com.jamonapi-sources-2.4.0.jar"/>
<classpathentry kind="var" path="IVY_CACHE/net.sourceforge.cglib/com.springsource.net.sf.cglib/2.2.0/com.springsource.net.sf.cglib-2.2.0.jar" sourcepath="/IVY_CACHE/net.sourceforge.cglib/com.springsource.net.sf.cglib/2.1.3/com.springsource.net.sf.cglib-sources-2.1.3.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.apache.log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-1.2.15.jar" sourcepath="/IVY_CACHE/org.apache.log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-sources-1.2.15.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-4.7.0.jar" sourcepath="/IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-sources-4.7.0.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.pool/1.3.0/com.springsource.org.apache.commons.pool-1.3.0.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.pool/1.3.0/com.springsource.org.apache.commons.pool-sources-1.3.0.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.aspectj/com.springsource.org.aspectj.weaver/1.6.5.RELEASE/com.springsource.org.aspectj.weaver-1.6.5.RELEASE.jar" sourcepath="IVY_CACHE/org.aspectj/com.springsource.org.aspectj.weaver/1.6.5.RELEASE/com.springsource.org.aspectj.weaver-sources-1.6.5.RELEASE.jar"/>
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.beans"/>
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.core"/>
<classpathentry kind="lib" path="/org.springframework.asm/target/artifacts/org.springframework.asm.jar" sourcepath="/org.springframework.asm/target/artifacts/org.springframework.asm-sources.jar"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>
-1
View File
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="org.springframework.aop">
<property file="${basedir}/../build.properties"/>
<property file="${basedir}/../build.versions"/>
<import file="${basedir}/../build-spring-framework/package-bundle.xml"/>
<import file="${basedir}/../spring-build/standard/default.xml"/>
</project>
+4 -7
View File
@@ -11,7 +11,6 @@
<configurations>
<include file="${spring.build.dir}/common/default-ivy-configurations.xml"/>
<conf name="commons-logging" extends="runtime" description="JARs needed to run with Commons Logging"/>
<conf name="aspectj" extends="runtime" description="JARs needed to run with AspectJ"/>
<conf name="bytecode-proxy" extends="runtime" description="JARs needed to run with CGLIB bytecode proxies"/>
<conf name="jamon" extends="runtime" description="JARs needed to run with JamonAPI"/>
@@ -21,23 +20,21 @@
<publications>
<artifact name="${ant.project.name}"/>
<artifact name="${ant.project.name}-sources" type="src" ext="jar"/>
<artifact name="license" type="license" ext="txt"/>
<artifact name="notice" type="notice" ext="txt"/>
</publications>
<dependencies>
<dependency org="com.jamonapi" name="com.springsource.com.jamonapi" rev="2.4.0" conf="optional, jamon->compile"/>
<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="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.apache.commons" name="com.springsource.org.apache.commons.logging" rev="1.1.1" conf="compile->compile"/>
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.pool" rev="1.4.0" conf="optional, pooling->compile"/>
<dependency org="org.aspectj" name="com.springsource.org.aspectj.weaver" rev="1.6.5.RELEASE" 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="${junit.version}" conf="test->runtime"/>
<dependency org="org.junit" name="com.springsource.org.junit" rev="4.7.0" conf="test->runtime"/>
<dependency org="org.springframework" name="org.springframework.asm" rev="latest.integration" conf="test->runtime"/>
</dependencies>
+3 -3
View File
@@ -4,12 +4,12 @@
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<packaging>jar</packaging>
<version>3.0.8.BUILD-SNAPSHOT</version>
<version>3.0.0.RC2</version>
<parent>
<groupId>org.springframework</groupId>
<artifactId>spring-parent</artifactId>
<relativePath>../org.springframework.spring-parent</relativePath>
<version>3.0.8.BUILD-SNAPSHOT</version>
<version>3.0.0.RC2</version>
</parent>
<dependencies>
@@ -35,7 +35,7 @@
<dependency>
<groupId>commons-pool</groupId>
<artifactId>commons-pool</artifactId>
<version>1.5.3</version>
<version>1.4</version>
<optional>true</optional>
</dependency>
<dependency>
@@ -34,6 +34,6 @@ public interface TargetClassAware {
* (typically a proxy configuration or an actual proxy).
* @return the target Class, or <code>null</code> if not known
*/
Class<?> getTargetClass();
Class getTargetClass();
}
@@ -1,5 +1,5 @@
/*<
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,7 +39,7 @@ public interface TargetSource extends TargetClassAware {
* target class.
* @return the type of targets returned by this {@link TargetSource}
*/
Class<?> getTargetClass();
Class getTargetClass();
/**
* Will all calls to {@link #getTarget()} return the same object?
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2008 the original author 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.aop.aspectj;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
@@ -140,7 +139,9 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
private boolean argumentsIntrospected = false;
private Type discoveredReturningGenericType;
// The actual type is java.lang.reflect.Type,
// but for JDK 1.4 compatibility we use Object as the static type.
private Object discoveredReturningGenericType;
// Note: Unlike return type, no such generic information is needed for the throwing type,
// since Java doesn't allow exception types to be parameterized.
@@ -294,7 +295,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
return this.discoveredReturningType;
}
protected Type getDiscoveredReturningGenericType() {
protected Object getDiscoveredReturningGenericType() {
return this.discoveredReturningGenericType;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -69,11 +69,21 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice implement
*/
private boolean shouldInvokeOnReturnValueOf(Method method, Object returnValue) {
Class type = getDiscoveredReturningType();
Type genericType = getDiscoveredReturningGenericType();
Object genericType = getDiscoveredReturningGenericType();
// If we aren't dealing with a raw type, check if generic parameters are assignable.
return (ClassUtils.isAssignableValue(type, returnValue) &&
(genericType == null || genericType == type ||
TypeUtils.isAssignable(genericType, method.getGenericReturnType())));
(genericType == null || genericType == type || GenericTypeMatcher.isAssignable(genericType, method)));
}
/**
* Inner class to avoid a static JDK 1.5 dependency for generic type matching.
*/
private static class GenericTypeMatcher {
public static boolean isAssignable(Object genericType, Method method) {
return TypeUtils.isAssignable((Type) genericType, method.getGenericReturnType());
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2009 the original author 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.aop.aspectj;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Map;
@@ -54,7 +52,6 @@ import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
@@ -78,24 +75,28 @@ import org.springframework.util.StringUtils;
public class AspectJExpressionPointcut extends AbstractExpressionPointcut
implements ClassFilter, IntroductionAwareMethodMatcher, BeanFactoryAware {
private static final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES = new HashSet<PointcutPrimitive>();
private static final Set<PointcutPrimitive> DEFAULT_SUPPORTED_PRIMITIVES = new HashSet<PointcutPrimitive>();
static {
SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION);
SUPPORTED_PRIMITIVES.add(PointcutPrimitive.ARGS);
SUPPORTED_PRIMITIVES.add(PointcutPrimitive.REFERENCE);
SUPPORTED_PRIMITIVES.add(PointcutPrimitive.THIS);
SUPPORTED_PRIMITIVES.add(PointcutPrimitive.TARGET);
SUPPORTED_PRIMITIVES.add(PointcutPrimitive.WITHIN);
SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ANNOTATION);
SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_WITHIN);
SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ARGS);
SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_TARGET);
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION);
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.ARGS);
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.REFERENCE);
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.THIS);
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.TARGET);
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.WITHIN);
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ANNOTATION);
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_WITHIN);
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ARGS);
DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_TARGET);
}
private static final Log logger = LogFactory.getLog(AspectJExpressionPointcut.class);
private final Map<Method, ShadowMatch> shadowMatchCache = new ConcurrentHashMap<Method, ShadowMatch>(32);
private PointcutParser pointcutParser;
private Class pointcutDeclarationScope;
private String[] pointcutParameterNames = new String[0];
@@ -104,15 +105,26 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
private BeanFactory beanFactory;
private transient PointcutExpression pointcutExpression;
private transient Map<Method, ShadowMatch> shadowMatchCache = new ConcurrentHashMap<Method, ShadowMatch>(32);
private PointcutExpression pointcutExpression;
/**
* Create a new default AspectJExpressionPointcut.
*/
public AspectJExpressionPointcut() {
this(DEFAULT_SUPPORTED_PRIMITIVES);
}
/**
* Create a new AspectJExpressionPointcut with the given supported primitives.
* @param supportedPrimitives Set of {@link org.aspectj.weaver.tools.PointcutPrimitive}
* instances
*/
public AspectJExpressionPointcut(Set supportedPrimitives) {
this.pointcutParser =
PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution(
supportedPrimitives);
this.pointcutParser.registerPointcutDesignatorHandler(new BeanNamePointcutDesignatorHandler());
}
/**
@@ -122,6 +134,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
* @param paramTypes the parameter types for the pointcut
*/
public AspectJExpressionPointcut(Class declarationScope, String[] paramNames, Class[] paramTypes) {
this(DEFAULT_SUPPORTED_PRIMITIVES);
this.pointcutDeclarationScope = declarationScope;
if (paramNames.length != paramTypes.length) {
throw new IllegalStateException(
@@ -186,30 +199,15 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
* Build the underlying AspectJ pointcut expression.
*/
private PointcutExpression buildPointcutExpression() {
PointcutParser parser = initializePointcutParser();
PointcutParameter[] pointcutParameters = new PointcutParameter[this.pointcutParameterNames.length];
for (int i = 0; i < pointcutParameters.length; i++) {
pointcutParameters[i] = parser.createPointcutParameter(
pointcutParameters[i] = this.pointcutParser.createPointcutParameter(
this.pointcutParameterNames[i], this.pointcutParameterTypes[i]);
}
return parser.parsePointcutExpression(
return this.pointcutParser.parsePointcutExpression(
replaceBooleanOperators(getExpression()), this.pointcutDeclarationScope, pointcutParameters);
}
/**
* Initialize the underlying AspectJ pointcut parser.
*/
private PointcutParser initializePointcutParser() {
ClassLoader cl = (this.beanFactory instanceof ConfigurableBeanFactory ?
((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() :
Thread.currentThread().getContextClassLoader());
PointcutParser parser =
PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution(
SUPPORTED_PRIMITIVES, cl);
parser.registerPointcutDesignatorHandler(new BeanNamePointcutDesignatorHandler());
return parser;
}
/**
* If a pointcut expression has been specified in XML, the user cannot
* write <code>and</code> as "&&" (though &amp;&amp; will work).
@@ -223,7 +221,6 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
return result;
}
/**
* Return the underlying AspectJ pointcut expression.
*/
@@ -232,6 +229,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
return this.pointcutExpression;
}
public boolean matches(Class targetClass) {
checkReadyToMatch();
try {
@@ -460,6 +458,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
/**
* Matcher class for the BeanNamePointcutDesignatorHandler.
*
* <p>Dynamic match tests for this matcher always return true,
* since the matching decision is made at the proxy creation time.
* For static match tests, this matcher abstains to allow the overall
@@ -529,18 +528,4 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
}
}
//---------------------------------------------------------------------
// Serialization support
//---------------------------------------------------------------------
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Rely on default serialization, just initialize state after deserialization.
ois.defaultReadObject();
// Initialize transient fields.
// pointcutExpression will be initialized lazily by checkReadyToMatch()
this.shadowMatchCache = new ConcurrentHashMap<Method, ShadowMatch>(32);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -73,7 +73,7 @@ class RuntimeTestWalker {
catch (IllegalAccessException illegalAccessEx) {
// Famous last words... but I don't see how this can happen given the
// makeAccessible call above
throw new IllegalStateException("Unable to access ShadowMatchImpl.residualTest field");
throw new IllegalStateException("Unable to access ShadowMatchImpl.runtimeTest field.");
}
}
@@ -83,18 +83,15 @@ class RuntimeTestWalker {
* then it tests subtype sensitive vars.
*/
public boolean testsSubtypeSensitiveVars() {
return (this.runtimeTest != null &&
new SubtypeSensitiveVarTypeTestVisitor().testsSubtypeSensitiveVars(this.runtimeTest));
return new SubtypeSensitiveVarTypeTestVisitor().testsSubtypeSensitiveVars(this.runtimeTest);
}
public boolean testThisInstanceOfResidue(Class thisClass) {
return (this.runtimeTest != null &&
new ThisInstanceOfResidueTestVisitor(thisClass).thisInstanceOfMatches(this.runtimeTest));
return new ThisInstanceOfResidueTestVisitor(thisClass).thisInstanceOfMatches(this.runtimeTest);
}
public boolean testTargetInstanceOfResidue(Class targetClass) {
return (this.runtimeTest != null &&
new TargetInstanceOfResidueTestVisitor(targetClass).targetInstanceOfMatches(this.runtimeTest));
return new TargetInstanceOfResidueTestVisitor(targetClass).targetInstanceOfMatches(this.runtimeTest);
}
@@ -142,7 +139,8 @@ class RuntimeTestWalker {
try {
Field varTypeField = ReflectionVar.class.getDeclaredField("varType");
ReflectionUtils.makeAccessible(varTypeField);
return (Integer) varTypeField.get(v);
Integer varTypeValue = (Integer) varTypeField.get(v);
return varTypeValue.intValue();
}
catch (NoSuchFieldException noSuchFieldEx) {
throw new IllegalStateException("the version of aspectjtools.jar / aspectjweaver.jar " +
@@ -152,7 +150,7 @@ class RuntimeTestWalker {
catch (IllegalAccessException illegalAccessEx) {
// Famous last words... but I don't see how this can happen given the
// makeAccessible call above
throw new IllegalStateException("Unable to access ReflectionVar.varType field");
throw new IllegalStateException("Unable to access ReflectionVar.varType field.");
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -215,10 +215,9 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
*/
protected static class AspectJAnnotation<A extends Annotation> {
private static final String[] EXPRESSION_PROPERTIES = new String[] {"value", "pointcut"};
private static Map<Class,AspectJAnnotationType> annotationTypes = new HashMap<Class,AspectJAnnotationType>();
private static Map<Class, AspectJAnnotationType> annotationTypes =
new HashMap<Class, AspectJAnnotationType>();
private static final String[] EXPRESSION_PROPERTIES = new String[]{"value", "pointcut"};
static {
annotationTypes.put(Pointcut.class,AspectJAnnotationType.AtPointcut);
@@ -230,48 +229,46 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
}
private final A annotation;
private AspectJAnnotationType annotationType;
private final String expression;
private final String argNames;
private final AspectJAnnotationType annotationType;
public AspectJAnnotation(A aspectjAnnotation) {
this.annotation = aspectjAnnotation;
for (Class type : annotationTypes.keySet()) {
if (type.isInstance(this.annotation)) {
this.annotationType = annotationTypes.get(type);
break;
}
}
if (this.annotationType == null) {
throw new IllegalStateException("Unknown annotation type: " + this.annotation.toString());
}
private final String pointcutExpression;
private final String argumentNames;
public AspectJAnnotation(A annotation) {
this.annotation = annotation;
this.annotationType = determineAnnotationType(annotation);
// We know these methods exist with the same name on each object,
// but need to invoke them reflectively as there isn't a common interface.
try {
this.pointcutExpression = resolveExpression(annotation);
this.argumentNames = (String) annotation.getClass().getMethod("argNames").invoke(annotation);
this.expression = resolveExpression();
this.argNames = (String)
this.annotation.getClass().getMethod("argNames", (Class[]) null).invoke(this.annotation);
}
catch (Exception ex) {
throw new IllegalArgumentException(annotation + " cannot be an AspectJ annotation", ex);
throw new IllegalArgumentException(aspectjAnnotation + " cannot be an AspectJ annotation", ex);
}
}
private AspectJAnnotationType determineAnnotationType(A annotation) {
for (Class type : annotationTypes.keySet()) {
if (type.isInstance(annotation)) {
return annotationTypes.get(type);
}
}
throw new IllegalStateException("Unknown annotation type: " + annotation.toString());
}
private String resolveExpression(A annotation) throws Exception {
private String resolveExpression() throws Exception {
String expression = null;
for (String methodName : EXPRESSION_PROPERTIES) {
Method method;
try {
method = annotation.getClass().getDeclaredMethod(methodName);
method = this.annotation.getClass().getDeclaredMethod(methodName);
}
catch (NoSuchMethodException ex) {
method = null;
}
if (method != null) {
String candidate = (String) method.invoke(annotation);
String candidate = (String) method.invoke(this.annotation);
if (StringUtils.hasText(candidate)) {
expression = candidate;
}
@@ -289,11 +286,11 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
}
public String getPointcutExpression() {
return this.pointcutExpression;
return this.expression;
}
public String getArgumentNames() {
return this.argumentNames;
public String getArgNames() {
return this.argNames;
}
@Override
@@ -317,7 +314,7 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
if (annotation == null) {
return null;
}
StringTokenizer strTok = new StringTokenizer(annotation.getArgumentNames(), ",");
StringTokenizer strTok = new StringTokenizer(annotation.getArgNames(), ",");
if (strTok.countTokens() > 0) {
String[] names = new String[strTok.countTokens()];
for (int i = 0; i < names.length; i++) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2006 the original author 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,13 +58,18 @@ class InstantiationModelAwarePointcutAdvisorImpl
private String aspectName;
private Boolean isBeforeAdvice;
private Boolean isBeforeAdvice = null;
private Boolean isAfterAdvice;
private Boolean isAfterAdvice = null;
public InstantiationModelAwarePointcutAdvisorImpl(AspectJAdvisorFactory af, AspectJExpressionPointcut ajexp,
MetadataAwareAspectInstanceFactory aif, Method method, int declarationOrderInAspect, String aspectName) {
public InstantiationModelAwarePointcutAdvisorImpl(
AspectJAdvisorFactory af,
AspectJExpressionPointcut ajexp,
MetadataAwareAspectInstanceFactory aif,
Method method,
int declarationOrderInAspect,
String aspectName) {
this.declaredPointcut = ajexp;
this.method = method;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2006 the original author 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,9 +21,9 @@ import java.util.List;
import org.w3c.dom.Node;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.ManagedList;
@@ -34,25 +34,22 @@ import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
* Base implementation for
* {@link org.springframework.beans.factory.xml.BeanDefinitionDecorator BeanDefinitionDecorators}
* wishing to add an {@link org.aopalliance.intercept.MethodInterceptor interceptor}
* to the resulting bean.
* Base implementation for {@link org.springframework.beans.factory.xml.BeanDefinitionDecorator BeanDefinitionDecorators} wishing
* to add an {@link org.aopalliance.intercept.MethodInterceptor interceptor} to the resulting
* bean.
*
* <p>This base class controls the creation of the {@link ProxyFactoryBean} bean definition
* and wraps the original as an inner-bean definition for the <code>target</code> property
* of {@link ProxyFactoryBean}.
* and wraps the original as an inner-bean definition for the <code>target</code> property of
* {@link ProxyFactoryBean}.
*
* <p>Chaining is correctly handled, ensuring that only one {@link ProxyFactoryBean} definition
* is created. If a previous {@link org.springframework.beans.factory.xml.BeanDefinitionDecorator}
* already created the {@link org.springframework.aop.framework.ProxyFactoryBean} then the
* interceptor is simply added to the existing definition.
* is created. If a previous {@link org.springframework.beans.factory.xml.BeanDefinitionDecorator} already created the {@link org.springframework.aop.framework.ProxyFactoryBean}
* then the interceptor is simply added to the existing definition.
*
* <p>Subclasses have only to create the <code>BeanDefinition</code> to the interceptor that
* they wish to add.
* <p>Subclasses have only to create the <code>BeanDefinition</code> to the interceptor they
* wish to add.
*
* @author Rob Harrop
* @author Juergen Hoeller
* @since 2.0
* @see org.aopalliance.intercept.MethodInterceptor
*/
@@ -63,54 +60,51 @@ public abstract class AbstractInterceptorDrivenBeanDefinitionDecorator implement
// get the root bean name - will be the name of the generated proxy factory bean
String existingBeanName = definitionHolder.getBeanName();
BeanDefinition targetDefinition = definitionHolder.getBeanDefinition();
BeanDefinitionHolder targetHolder = new BeanDefinitionHolder(targetDefinition, existingBeanName + ".TARGET");
BeanDefinition existingDefinition = definitionHolder.getBeanDefinition();
// delegate to subclass for interceptor definition
// delegate to subclass for interceptor def
BeanDefinition interceptorDefinition = createInterceptorDefinition(node);
// generate name and register the interceptor
String interceptorName = existingBeanName + "." + getInterceptorNameSuffix(interceptorDefinition);
BeanDefinitionReaderUtils.registerBeanDefinition(
new BeanDefinitionHolder(interceptorDefinition, interceptorName), registry);
BeanDefinitionReaderUtils.registerBeanDefinition(new BeanDefinitionHolder(interceptorDefinition, interceptorName), registry);
BeanDefinitionHolder result = definitionHolder;
if (!isProxyFactoryBeanDefinition(targetDefinition)) {
// create the proxy definition
if (!isProxyFactoryBeanDefinition(existingDefinition)) {
// create the proxy definitionHolder
RootBeanDefinition proxyDefinition = new RootBeanDefinition();
// create proxy factory bean definition
// create proxy factory bean definitionHolder
proxyDefinition.setBeanClass(ProxyFactoryBean.class);
proxyDefinition.setScope(targetDefinition.getScope());
proxyDefinition.setLazyInit(targetDefinition.isLazyInit());
// set up property values
MutablePropertyValues mpvs = new MutablePropertyValues();
proxyDefinition.setPropertyValues(mpvs);
// set the target
proxyDefinition.setDecoratedDefinition(targetHolder);
proxyDefinition.getPropertyValues().add("target", targetHolder);
mpvs.addPropertyValue("target", existingDefinition);
// create the interceptor names list
proxyDefinition.getPropertyValues().add("interceptorNames", new ManagedList<String>());
// copy autowire settings from original bean definition.
proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
proxyDefinition.setPrimary(targetDefinition.isPrimary());
if (targetDefinition instanceof AbstractBeanDefinition) {
proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
}
// wrap it in a BeanDefinitionHolder with bean name
ManagedList interceptorList = new ManagedList();
mpvs.addPropertyValue("interceptorNames", interceptorList);
result = new BeanDefinitionHolder(proxyDefinition, existingBeanName);
}
addInterceptorNameToList(interceptorName, result.getBeanDefinition());
return result;
}
@SuppressWarnings("unchecked")
private void addInterceptorNameToList(String interceptorName, BeanDefinition beanDefinition) {
List<String> list = (List<String>)
beanDefinition.getPropertyValues().getPropertyValue("interceptorNames").getValue();
List list = (List) beanDefinition.getPropertyValues().getPropertyValue("interceptorNames").getValue();
list.add(interceptorName);
}
private boolean isProxyFactoryBeanDefinition(BeanDefinition existingDefinition) {
return ProxyFactoryBean.class.getName().equals(existingDefinition.getBeanClassName());
return existingDefinition.getBeanClassName().equals(ProxyFactoryBean.class.getName());
}
protected String getInterceptorNameSuffix(BeanDefinition interceptorDefinition) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -93,14 +93,7 @@ public abstract class AopConfigUtils {
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
}
}
static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
definition.getPropertyValues().addPropertyValue("proxyTargetClass", Boolean.TRUE);
}
}
@@ -120,7 +113,7 @@ public abstract class AopConfigUtils {
}
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.getPropertyValues().addPropertyValue("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2009 the original author 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,11 +46,6 @@ public abstract class AopNamespaceUtils {
*/
public static final String PROXY_TARGET_CLASS_ATTRIBUTE = "proxy-target-class";
/**
* The <code>expose-proxy</code> attribute as found on AOP-related XML tags.
*/
private static final String EXPOSE_PROXY_ATTRIBUTE = "expose-proxy";
public static void registerAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
@@ -107,10 +102,6 @@ public abstract class AopNamespaceUtils {
if (proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
if (exposeProxy) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
@@ -65,7 +65,7 @@ class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
}
if (!includePatterns.isEmpty()) {
includePatterns.setSource(parserContext.extractSource(element));
beanDef.getPropertyValues().add("includePatterns", includePatterns);
beanDef.getPropertyValues().addPropertyValue("includePatterns", includePatterns);
}
}
@@ -102,17 +102,20 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
configureAutoProxyCreator(parserContext, element);
List<Element> childElts = DomUtils.getChildElements(element);
for (Element elt: childElts) {
String localName = parserContext.getDelegate().getLocalName(elt);
if (POINTCUT.equals(localName)) {
parsePointcut(elt, parserContext);
}
else if (ADVISOR.equals(localName)) {
parseAdvisor(elt, parserContext);
}
else if (ASPECT.equals(localName)) {
parseAspect(elt, parserContext);
NodeList childNodes = element.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node node = childNodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
String localName = parserContext.getDelegate().getLocalName(node);
if (POINTCUT.equals(localName)) {
parsePointcut((Element) node, parserContext);
}
else if (ADVISOR.equals(localName)) {
parseAdvisor((Element) node, parserContext);
}
else if (ASPECT.equals(localName)) {
parseAspect((Element) node, parserContext);
}
}
}
@@ -151,12 +154,12 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
Object pointcut = parsePointcutProperty(advisorElement, parserContext);
if (pointcut instanceof BeanDefinition) {
advisorDef.getPropertyValues().add(POINTCUT, pointcut);
advisorDef.getPropertyValues().addPropertyValue(POINTCUT, pointcut);
parserContext.registerComponent(
new AdvisorComponentDefinition(advisorBeanName, advisorDef, (BeanDefinition) pointcut));
}
else if (pointcut instanceof String) {
advisorDef.getPropertyValues().add(POINTCUT, new RuntimeBeanReference((String) pointcut));
advisorDef.getPropertyValues().addPropertyValue(POINTCUT, new RuntimeBeanReference((String) pointcut));
parserContext.registerComponent(
new AdvisorComponentDefinition(advisorBeanName, advisorDef));
}
@@ -180,12 +183,12 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
"'advice-ref' attribute contains empty value.", advisorElement, this.parseState.snapshot());
}
else {
advisorDefinition.getPropertyValues().add(
advisorDefinition.getPropertyValues().addPropertyValue(
ADVICE_BEAN_NAME, new RuntimeBeanNameReference(adviceRef));
}
if (advisorElement.hasAttribute(ORDER_PROPERTY)) {
advisorDefinition.getPropertyValues().add(
advisorDefinition.getPropertyValues().addPropertyValue(
ORDER_PROPERTY, advisorElement.getAttribute(ORDER_PROPERTY));
}
@@ -318,14 +321,14 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
// create the method factory bean
RootBeanDefinition methodDefinition = new RootBeanDefinition(MethodLocatingFactoryBean.class);
methodDefinition.getPropertyValues().add("targetBeanName", aspectName);
methodDefinition.getPropertyValues().add("methodName", adviceElement.getAttribute("method"));
methodDefinition.getPropertyValues().addPropertyValue("targetBeanName", aspectName);
methodDefinition.getPropertyValues().addPropertyValue("methodName", adviceElement.getAttribute("method"));
methodDefinition.setSynthetic(true);
// create instance factory definition
RootBeanDefinition aspectFactoryDef =
new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class);
aspectFactoryDef.getPropertyValues().add("aspectBeanName", aspectName);
aspectFactoryDef.getPropertyValues().addPropertyValue("aspectBeanName", aspectName);
aspectFactoryDef.setSynthetic(true);
// register the pointcut
@@ -338,7 +341,7 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
advisorDefinition.setSource(parserContext.extractSource(adviceElement));
advisorDefinition.getConstructorArgumentValues().addGenericArgumentValue(adviceDef);
if (aspectElement.hasAttribute(ORDER_PROPERTY)) {
advisorDefinition.getPropertyValues().add(
advisorDefinition.getPropertyValues().addPropertyValue(
ORDER_PROPERTY, aspectElement.getAttribute(ORDER_PROPERTY));
}
@@ -366,19 +369,19 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
RootBeanDefinition adviceDefinition = new RootBeanDefinition(getAdviceClass(adviceElement, parserContext));
adviceDefinition.setSource(parserContext.extractSource(adviceElement));
adviceDefinition.getPropertyValues().add(ASPECT_NAME_PROPERTY, aspectName);
adviceDefinition.getPropertyValues().add(DECLARATION_ORDER_PROPERTY, order);
adviceDefinition.getPropertyValues().addPropertyValue(ASPECT_NAME_PROPERTY, aspectName);
adviceDefinition.getPropertyValues().addPropertyValue(DECLARATION_ORDER_PROPERTY, order);
if (adviceElement.hasAttribute(RETURNING)) {
adviceDefinition.getPropertyValues().add(
adviceDefinition.getPropertyValues().addPropertyValue(
RETURNING_PROPERTY, adviceElement.getAttribute(RETURNING));
}
if (adviceElement.hasAttribute(THROWING)) {
adviceDefinition.getPropertyValues().add(
adviceDefinition.getPropertyValues().addPropertyValue(
THROWING_PROPERTY, adviceElement.getAttribute(THROWING));
}
if (adviceElement.hasAttribute(ARG_NAMES)) {
adviceDefinition.getPropertyValues().add(
adviceDefinition.getPropertyValues().addPropertyValue(
ARG_NAMES_PROPERTY, adviceElement.getAttribute(ARG_NAMES));
}
@@ -504,7 +507,7 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
RootBeanDefinition beanDefinition = new RootBeanDefinition(AspectJExpressionPointcut.class);
beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
beanDefinition.setSynthetic(true);
beanDefinition.getPropertyValues().add(EXPRESSION, expression);
beanDefinition.getPropertyValues().addPropertyValue(EXPRESSION, expression);
return beanDefinition;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -162,7 +162,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
this.targetSource = EmptyTargetSource.forClass(targetClass);
}
public Class<?> getTargetClass() {
public Class getTargetClass() {
return this.targetSource.getTargetClass();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -76,12 +76,7 @@ public abstract class AopContext {
*/
static Object setCurrentProxy(Object proxy) {
Object old = currentProxy.get();
if (proxy != null) {
currentProxy.set(proxy);
}
else {
currentProxy.remove();
}
currentProxy.set(proxy);
return old;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2008 the original author 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,6 @@ package org.springframework.aop.framework;
import java.util.Arrays;
import org.springframework.aop.SpringProxy;
import org.springframework.aop.TargetClassAware;
import org.springframework.aop.TargetSource;
import org.springframework.aop.support.AopUtils;
import org.springframework.aop.target.SingletonTargetSource;
import org.springframework.util.Assert;
/**
@@ -38,37 +34,6 @@ import org.springframework.util.Assert;
*/
public abstract class AopProxyUtils {
/**
* Determine the ultimate target class of the given bean instance, traversing
* not only a top-level proxy but any number of nested proxies as well -
* as long as possible without side effects, that is, just for singleton targets.
* @param candidate the instance to check (might be an AOP proxy)
* @return the target class (or the plain class of the given object as fallback;
* never <code>null</code>)
* @see org.springframework.aop.TargetClassAware#getTargetClass()
* @see org.springframework.aop.framework.Advised#getTargetSource()
*/
public static Class<?> ultimateTargetClass(Object candidate) {
Assert.notNull(candidate, "Candidate object must not be null");
Object current = candidate;
Class<?> result = null;
while (current instanceof TargetClassAware) {
result = ((TargetClassAware) current).getTargetClass();
Object nested = null;
if (current instanceof Advised) {
TargetSource targetSource = ((Advised) current).getTargetSource();
if (targetSource instanceof SingletonTargetSource) {
nested = ((SingletonTargetSource) targetSource).getTarget();
}
}
current = nested;
}
if (result == null) {
result = (AopUtils.isCglibProxy(candidate) ? candidate.getClass().getSuperclass() : candidate.getClass());
}
return result;
}
/**
* Determine the complete set of interfaces to proxy for the given AOP configuration.
* <p>This will always add the {@link Advised} interface unless the AdvisedSupport's
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -268,7 +268,7 @@ final class Cglib2AopProxy implements AopProxy, Serializable {
// Choose a "straight to target" interceptor. (used for calls that are
// unadvised but can return this). May be required to expose the proxy.
Callback targetInterceptor;
Callback targetInterceptor = null;
if (exposeProxy) {
targetInterceptor = isStatic ?
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
@@ -316,8 +316,12 @@ final class Cglib2AopProxy implements AopProxy, Serializable {
// Now copy both the callbacks from mainCallbacks
// and fixedCallbacks into the callbacks array.
callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
for (int x = 0; x < mainCallbacks.length; x++) {
callbacks[x] = mainCallbacks[x];
}
for (int x = 0; x < fixedCallbacks.length; x++) {
callbacks[x + mainCallbacks.length] = fixedCallbacks[x];
}
this.fixedInterceptorOffset = mainCallbacks.length;
}
else {
@@ -606,7 +610,7 @@ final class Cglib2AopProxy implements AopProxy, Serializable {
targetClass = target.getClass();
}
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
Object retVal = null;
// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -146,7 +146,7 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
* unless a hook method throws an exception.
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
MethodInvocation invocation = null;
Object oldProxy = null;
boolean setProxyContext = false;
@@ -169,7 +169,7 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
Object retVal = null;
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
@@ -239,7 +239,7 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
return false;
}
JdkDynamicAopProxy otherProxy;
JdkDynamicAopProxy otherProxy = null;
if (other instanceof JdkDynamicAopProxy) {
otherProxy = (JdkDynamicAopProxy) other;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -113,14 +113,12 @@ public class ProxyConfig implements Serializable {
* ThreadLocal for retrieval via the AopContext class. This is useful
* if an advised object needs to call another advised method on itself.
* (If it uses <code>this</code>, the invocation will not be advised).
* <p>Default is "false", in order to avoid unnecessary extra interception.
* This means that no guarantees are provided that AopContext access will
* work consistently within any method of the advised object.
* <p>Default is "false", for optimal performance.
*/
public void setExposeProxy(boolean exposeProxy) {
this.exposeProxy = exposeProxy;
}
/**
* Return whether the AOP proxy will expose the AOP proxy for
* each invocation.
@@ -102,8 +102,8 @@ public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Clonea
* but would complicate the code. And it would work only for static pointcuts.
*/
protected ReflectiveMethodInvocation(
Object proxy, Object target, Method method, Object[] arguments,
Class targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {
Object proxy, Object target, Method method, Object[] arguments,
Class targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {
this.proxy = proxy;
this.target = target;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -52,7 +52,7 @@ public abstract class AutoProxyUtils {
* @return whether the given bean should be proxied with its target class
*/
public static boolean shouldProxyTargetClass(ConfigurableListableBeanFactory beanFactory, String beanName) {
if (beanName != null && beanFactory.containsBeanDefinition(beanName)) {
if (beanFactory.containsBeanDefinition(beanName)) {
BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
return Boolean.TRUE.equals(bd.getAttribute(PRESERVE_TARGET_CLASS_ATTRIBUTE));
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -84,15 +84,6 @@ public class BeanNameAutoProxyCreator extends AbstractAutoProxyCreator {
if (isMatch(beanName, mappedName)) {
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
}
BeanFactory beanFactory = getBeanFactory();
if (beanFactory != null) {
String[] aliases = beanFactory.getAliases(beanName);
for (String alias : aliases) {
if (isMatch(alias, mappedName)) {
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
}
}
}
}
}
return DO_NOT_PROXY;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2009 the original author 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,12 +46,7 @@ public class ProxyCreationContext {
* @param beanName the name of the bean, or <code>null</code> to reset it
*/
static void setCurrentProxiedBeanName(String beanName) {
if (beanName != null) {
currentProxiedBeanName.set(beanName);
}
else {
currentProxiedBeanName.remove();
}
currentProxiedBeanName.set(beanName);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -45,7 +45,7 @@ public abstract class ExposeBeanNameAdvisors {
* Binding for the bean name of the bean which is currently being invoked
* in the ReflectiveMethodInvocation userAttributes Map.
*/
private static final String BEAN_NAME_ATTRIBUTE = ExposeBeanNameAdvisors.class.getName() + ".BEAN_NAME";
private static final String BEAN_NAME_ATTRIBUTE = ExposeBeanNameAdvisors.class.getName() + ".beanName";
/**
@@ -114,7 +114,7 @@ public abstract class ExposeBeanNameAdvisors {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
pmi.setUserAttribute(BEAN_NAME_ATTRIBUTE, this.beanName);
pmi.setUserAttribute(BEAN_NAME_ATTRIBUTE, beanName);
return mi.proceed();
}
}
@@ -137,7 +137,7 @@ public abstract class ExposeBeanNameAdvisors {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
pmi.setUserAttribute(BEAN_NAME_ATTRIBUTE, this.beanName);
pmi.setUserAttribute(BEAN_NAME_ATTRIBUTE, beanName);
return super.invoke(mi);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2009 the original author 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,9 +70,8 @@ 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 upfront in the interceptor chain. Specifically, note that " +
"advices with order HIGHEST_PRECEDENCE will execute before ExposeInvocationInterceptor!");
"No MethodInvocation found: Check that an AOP invocation is in progress, " +
"and that the ExposeInvocationInterceptor is in the interceptor chain.");
return mi;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2009 the original author 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,29 +53,28 @@ public abstract class ScopedProxyUtils {
// Create a scoped proxy definition for the original bean name,
// "hiding" the target bean in an internal target definition.
RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
proxyDefinition.setOriginatingBeanDefinition(definition.getBeanDefinition());
proxyDefinition.setSource(definition.getSource());
proxyDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
RootBeanDefinition scopedProxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
scopedProxyDefinition.setOriginatingBeanDefinition(definition.getBeanDefinition());
scopedProxyDefinition.setSource(definition.getSource());
scopedProxyDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
String targetBeanName = getTargetBeanName(originalBeanName);
proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);
scopedProxyDefinition.getPropertyValues().addPropertyValue("targetBeanName", targetBeanName);
if (proxyTargetClass) {
targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
// ScopedFactoryBean's "proxyTargetClass" default is TRUE, so we don't need to set it explicitly here.
}
else {
proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
scopedProxyDefinition.getPropertyValues().addPropertyValue("proxyTargetClass", Boolean.FALSE);
}
// Copy autowire settings from original bean definition.
proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
proxyDefinition.setPrimary(targetDefinition.isPrimary());
if (targetDefinition instanceof AbstractBeanDefinition) {
proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
scopedProxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
}
scopedProxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
scopedProxyDefinition.setPrimary(targetDefinition.isPrimary());
// The target bean should be ignored in favor of the scoped proxy.
targetDefinition.setAutowireCandidate(false);
targetDefinition.setPrimary(false);
@@ -85,7 +84,7 @@ public abstract class ScopedProxyUtils {
// Return the scoped proxy definition as primary bean definition
// (potentially an inner bean).
return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());
return new BeanDefinitionHolder(scopedProxyDefinition, originalBeanName, definition.getAliases());
}
/**
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2007 the original author 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,9 +16,6 @@
package org.springframework.aop.support;
import java.io.IOException;
import java.io.ObjectInputStream;
import org.aopalliance.aop.Advice;
import org.springframework.beans.factory.BeanFactory;
@@ -44,9 +41,9 @@ public abstract class AbstractBeanFactoryPointcutAdvisor extends AbstractPointcu
private BeanFactory beanFactory;
private transient Advice advice;
private Advice advice;
private transient volatile Object adviceMonitor = new Object();
private final Object adviceMonitor = new Object();
/**
@@ -77,7 +74,7 @@ public abstract class AbstractBeanFactoryPointcutAdvisor extends AbstractPointcu
synchronized (this.adviceMonitor) {
if (this.advice == null && this.adviceBeanName != null) {
Assert.state(this.beanFactory != null, "BeanFactory must be set to resolve 'adviceBeanName'");
this.advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class);
this.advice = (Advice) this.beanFactory.getBean(this.adviceBeanName, Advice.class);
}
return this.advice;
}
@@ -88,17 +85,4 @@ public abstract class AbstractBeanFactoryPointcutAdvisor extends AbstractPointcu
return getClass().getName() + ": advice bean '" + getAdviceBeanName() + "'";
}
//---------------------------------------------------------------------
// Serialization support
//---------------------------------------------------------------------
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Rely on default serialization, just initialize state after deserialization.
ois.defaultReadObject();
// Initialize transient fields.
this.adviceMonitor = new Object();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -85,7 +85,7 @@ public abstract class AopUtils {
* Check whether the specified class is a CGLIB-generated class.
* @param clazz the class to check
*/
public static boolean isCglibProxyClass(Class<?> clazz) {
public static boolean isCglibProxyClass(Class clazz) {
return (clazz != null && isCglibProxyClassName(clazz.getName()));
}
@@ -98,24 +98,22 @@ public abstract class AopUtils {
}
/**
* Determine the target class of the given bean instance which might be an AOP proxy.
* Determine the target class of the given bean instance,
* which might be an AOP proxy.
* <p>Returns the target class for an AOP proxy and the plain class else.
* @param candidate the instance to check (might be an AOP proxy)
* @return the target class (or the plain class of the given object as fallback;
* never <code>null</code>)
* @return the target class (or the plain class of the given object as fallback)
* @see org.springframework.aop.TargetClassAware#getTargetClass()
* @see org.springframework.aop.framework.AopProxyUtils#ultimateTargetClass(Object)
*/
public static Class<?> getTargetClass(Object candidate) {
public static Class getTargetClass(Object candidate) {
Assert.notNull(candidate, "Candidate object must not be null");
Class<?> result = null;
if (candidate instanceof TargetClassAware) {
result = ((TargetClassAware) candidate).getTargetClass();
return ((TargetClassAware) candidate).getTargetClass();
}
if (result == null) {
result = (isCglibProxy(candidate) ? candidate.getClass().getSuperclass() : candidate.getClass());
if (isCglibProxy(candidate)) {
return candidate.getClass().getSuperclass();
}
return result;
return candidate.getClass();
}
/**
@@ -167,7 +165,7 @@ public abstract class AopUtils {
* <code>targetClass</code> doesn't implement it or is <code>null</code>
* @see org.springframework.util.ClassUtils#getMostSpecificMethod
*/
public static Method getMostSpecificMethod(Method method, Class<?> targetClass) {
public static Method getMostSpecificMethod(Method method, Class targetClass) {
Method resolvedMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
// If we are dealing with method with generic parameters, find the original method.
return BridgeMethodResolver.findBridgedMethod(resolvedMethod);
@@ -182,7 +180,7 @@ public abstract class AopUtils {
* @param targetClass the class to test
* @return whether the pointcut can apply on any method
*/
public static boolean canApply(Pointcut pc, Class<?> targetClass) {
public static boolean canApply(Pointcut pc, Class targetClass) {
return canApply(pc, targetClass, false);
}
@@ -196,7 +194,7 @@ public abstract class AopUtils {
* for this bean includes any introductions
* @return whether the pointcut can apply on any method
*/
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
public static boolean canApply(Pointcut pc, Class targetClass, boolean hasIntroductions) {
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
@@ -209,7 +207,7 @@ public abstract class AopUtils {
Set<Class> classes = new HashSet<Class>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
classes.add(targetClass);
for (Class<?> clazz : classes) {
for (Class clazz : classes) {
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if ((introductionAwareMethodMatcher != null &&
@@ -231,7 +229,7 @@ public abstract class AopUtils {
* @param targetClass class we're testing
* @return whether the pointcut can apply on any method
*/
public static boolean canApply(Advisor advisor, Class<?> targetClass) {
public static boolean canApply(Advisor advisor, Class targetClass) {
return canApply(advisor, targetClass, false);
}
@@ -245,7 +243,7 @@ public abstract class AopUtils {
* any introductions
* @return whether the pointcut can apply on any method
*/
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
public static boolean canApply(Advisor advisor, Class targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
@@ -267,7 +265,7 @@ public abstract class AopUtils {
* @return sublist of Advisors that can apply to an object of the given class
* (may be the incoming List as-is)
*/
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
@@ -301,7 +299,7 @@ public abstract class AopUtils {
* @throws org.springframework.aop.AopInvocationException in case of a reflection error
*/
public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args)
throws Throwable {
throws Throwable {
// Use reflection to invoke the method.
try {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2009 the original author 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,12 +16,15 @@
package org.springframework.aop.target;
import java.io.NotSerializableException;
import java.io.ObjectStreamException;
import java.io.Serializable;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.TargetSource;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.util.ClassUtils;
@@ -62,7 +65,7 @@ public abstract class AbstractBeanFactoryBasedTargetSource
private String targetBeanName;
/** Class of the target */
private Class<?> targetClass;
private Class targetClass;
/**
* BeanFactory that owns this TargetSource. We need to hold onto this
@@ -105,7 +108,7 @@ public abstract class AbstractBeanFactoryBasedTargetSource
* Set the owning BeanFactory. We need to save a reference so that we can
* use the <code>getBean</code> method on every invocation.
*/
public void setBeanFactory(BeanFactory beanFactory) {
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
if (this.targetBeanName == null) {
throw new IllegalStateException("Property'targetBeanName' is required");
}
@@ -120,7 +123,7 @@ public abstract class AbstractBeanFactoryBasedTargetSource
}
public synchronized Class<?> getTargetClass() {
public synchronized Class getTargetClass() {
if (this.targetClass == null && this.beanFactory != null) {
// Determine type of the target bean.
this.targetClass = this.beanFactory.getType(this.targetBeanName);
@@ -128,10 +131,7 @@ public abstract class AbstractBeanFactoryBasedTargetSource
if (logger.isTraceEnabled()) {
logger.trace("Getting bean with name '" + this.targetBeanName + "' in order to determine type");
}
Object beanInstance = this.beanFactory.getBean(this.targetBeanName);
if (beanInstance != null) {
this.targetClass = beanInstance.getClass();
}
this.targetClass = this.beanFactory.getBean(this.targetBeanName).getClass();
}
}
return this.targetClass;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -64,7 +64,7 @@ public abstract class AbstractLazyCreationTargetSource implements TargetSource {
* a meaningful value when the target is still <code>null</code>.
* @see #isInitialized()
*/
public synchronized Class<?> getTargetClass() {
public synchronized Class getTargetClass() {
return (this.lazyTarget != null ? this.lazyTarget.getClass() : null);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2009 the original author 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,9 +16,7 @@
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;
@@ -93,11 +91,6 @@ 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -89,7 +89,7 @@ public class EmptyTargetSource implements TargetSource, Serializable {
/**
* Always returns the specified target Class, or <code>null</code> if none.
*/
public Class<?> getTargetClass() {
public Class getTargetClass() {
return this.targetClass;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -59,7 +59,7 @@ public class HotSwappableTargetSource implements TargetSource, Serializable {
* Return the type of the current target object.
* <p>The returned type should usually be constant across all target objects.
*/
public synchronized Class<?> getTargetClass() {
public synchronized Class getTargetClass() {
return this.target.getClass();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -55,7 +55,7 @@ public class SingletonTargetSource implements TargetSource, Serializable {
}
public Class<?> getTargetClass() {
public Class getTargetClass() {
return this.target.getClass();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -106,7 +106,7 @@ public class ThreadLocalTargetSource extends AbstractPrototypeBasedTargetSource
this.targetSet.clear();
}
// Clear ThreadLocal, just in case.
this.targetInThread.remove();
this.targetInThread.set(null);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -63,7 +63,7 @@ public abstract class AbstractRefreshableTargetSource implements TargetSource, R
}
public synchronized Class<?> getTargetClass() {
public synchronized Class getTargetClass() {
if (this.targetObject == null) {
refresh();
}
@@ -56,15 +56,6 @@
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="expose-proxy" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Indicate that the proxy should be exposed by the AOP framework as a
ThreadLocal for retrieval via the AopContext class. Off by default,
i.e. no guarantees that AopContext access will work.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
@@ -93,15 +84,6 @@
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="expose-proxy" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Indicate that the proxy should be exposed by the AOP framework as a
ThreadLocal for retrieval via the AopContext class. Off by default,
i.e. no guarantees that AopContext access will work.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2008 the original author 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,14 +16,15 @@
package org.springframework.aop.aspectj.annotation;
import static org.junit.Assert.*;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import static org.junit.Assert.*;
import org.junit.Ignore;
import org.junit.Test;
import test.aop.PerThisAspect;
import test.util.SerializationTestUtils;
/**
* @author Rob Harrop
@@ -75,7 +76,6 @@ public final class AspectProxyFactoryTests {
}
@Test
@Ignore // InstantiationModelAwarePointcutAdvisorImpl not serializable yet
public void testWithInstance() throws Exception {
MultiplyReturnValue aspect = new MultiplyReturnValue();
int multiple = 3;
@@ -88,10 +88,8 @@ public final class AspectProxyFactoryTests {
proxyFactory.addAspect(aspect);
ITestBean proxy = proxyFactory.getProxy();
assertEquals(target.getAge() * multiple, proxy.getAge());
ITestBean serializedProxy = (ITestBean) SerializationTestUtils.serializeAndDeserialize(proxy);
assertEquals(target.getAge() * multiple, serializedProxy.getAge());
assertEquals(target.getAge() * multiple, proxy.getAge());
}
@Test(expected=IllegalArgumentException.class)
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -293,33 +293,20 @@ public final class ProxyFactoryTests {
public void testProxyTargetClassWithInterfaceAsTarget() {
ProxyFactory pf = new ProxyFactory();
pf.setTargetClass(ITestBean.class);
Object proxy = pf.getProxy();
assertTrue("Proxy is a JDK proxy", AopUtils.isJdkDynamicProxy(proxy));
assertTrue(proxy instanceof ITestBean);
assertEquals(ITestBean.class, AopProxyUtils.ultimateTargetClass(proxy));
ProxyFactory pf2 = new ProxyFactory(proxy);
Object proxy2 = pf2.getProxy();
assertTrue("Proxy is a JDK proxy", AopUtils.isJdkDynamicProxy(proxy2));
assertTrue(proxy2 instanceof ITestBean);
assertEquals(ITestBean.class, AopProxyUtils.ultimateTargetClass(proxy2));
}
@Test
public void testProxyTargetClassWithConcreteClassAsTarget() {
ProxyFactory pf = new ProxyFactory();
pf.setTargetClass(TestBean.class);
Object proxy = pf.getProxy();
assertTrue("Proxy is a CGLIB proxy", AopUtils.isCglibProxy(proxy));
assertTrue(proxy instanceof TestBean);
assertEquals(TestBean.class, AopProxyUtils.ultimateTargetClass(proxy));
ProxyFactory pf2 = new ProxyFactory(proxy);
pf2.setProxyTargetClass(true);
Object proxy2 = pf2.getProxy();
assertTrue("Proxy is a CGLIB proxy", AopUtils.isCglibProxy(proxy2));
assertTrue(proxy2 instanceof TestBean);
assertEquals(TestBean.class, AopProxyUtils.ultimateTargetClass(proxy2));
}
@Test
@@ -40,7 +40,7 @@ public final class PrototypeBasedTargetSourceTests {
@Test
public void testSerializability() throws Exception {
MutablePropertyValues tsPvs = new MutablePropertyValues();
tsPvs.add("targetBeanName", "person");
tsPvs.addPropertyValue("targetBeanName", "person");
RootBeanDefinition tsBd = new RootBeanDefinition(TestTargetSource.class, tsPvs);
MutablePropertyValues pvs = new MutablePropertyValues();
+5 -5
View File
@@ -4,14 +4,14 @@ Bundle-Vendor: SpringSource
Bundle-ManifestVersion: 2
Import-Template:
com.jamonapi.*;version="[2.4.0, 3.0.0)";resolution:=optional,
net.sf.cglib.*;version="[2.1.3, 3.0.0)";resolution:=optional,
net.sf.cglib.*;version="[2.1.3, 2.2.0)";resolution:=optional,
org.aopalliance.*;version="[1.0.0, 2.0.0)",
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
org.apache.commons.pool.*;version="[1.3.0, 2.0.0)";resolution:=optional,
org.aspectj.*;version=${aj.osgi.range};resolution:=optional,
org.springframework.beans.*;version=${spring.osgi.range};resolution:=optional,
org.springframework.core.*;version=${spring.osgi.range},
org.springframework.util.*;version=${spring.osgi.range},
org.aspectj.*;version="[1.5.4, 2.0.0)";resolution:=optional,
org.springframework.beans.*;version="[3.0.0, 3.0.1)";resolution:=optional,
org.springframework.core.*;version="[3.0.0, 3.0.1)",
org.springframework.util.*;version="[3.0.0, 3.0.1)",
org.w3c.dom.*;version="0";resolution:=optional
Ignored-Existing-Headers:
Bnd-LastModified,
+1 -13
View File
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="org.springframework.asm" xmlns:ivy="antlib:org.apache.ivy.ant"
xmlns:bundlor="antlib:com.springsource.bundlor.ant">
<project name="org.springframework.asm" xmlns:ivy="antlib:org.apache.ivy.ant">
<property file="${basedir}/../build.properties"/>
<import file="${basedir}/../build-spring-framework/package-bundle.xml"/>
<import file="${basedir}/../spring-build/standard/default.xml"/>
@@ -36,7 +35,6 @@
<artifacts pattern="${jar.output.dir}/[artifact].[ext]"/>
<artifacts pattern="${source-jar.output.dir}/[artifact].[ext]"/>
<artifacts pattern="${ivy.output.dir}/[artifact].[ext]"/>
<artifacts pattern="${license.dir}/[artifact].[ext]"/>
</ivy:publish>
</target>
@@ -47,14 +45,4 @@
<taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask" classpathref="jarjar.classpath"/>
</target>
<target name="bundlor" depends="bundlor.init" unless="disable.bundlor">
<bundlor:bundlor inputPath="${jar.output.file}" outputPath="${jar.output.file}"
bundleVersion="${bundle.version}" manifestTemplatePath="${manifest.template.file}"
failOnWarnings="${fail.on.warnings}">
<propertyset refid="bundlor.properties"/>
<propertyset>
<propertyref builtin="all"/>
</propertyset>
</bundlor:bundlor>
</target>
</project>
-2
View File
@@ -17,8 +17,6 @@
<publications>
<artifact name="${ant.project.name}"/>
<artifact name="${ant.project.name}-sources" type="src" ext="jar"/>
<artifact name="license" type="license" ext="txt"/>
<artifact name="notice" type="notice" ext="txt"/>
</publications>
<dependencies>
+56 -56
View File
@@ -1,56 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>spring-asm</artifactId>
<packaging>jar</packaging>
<version>3.0.8.BUILD-SNAPSHOT</version>
<parent>
<groupId>org.springframework</groupId>
<artifactId>spring-parent</artifactId>
<relativePath>../org.springframework.spring-parent</relativePath>
<version>3.0.8.BUILD-SNAPSHOT</version>
</parent>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>jarjar</id>
<phase>process-classes</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask" classpathref="maven.plugin.classpath" />
<jarjar jarfile="${project.build.directory}${file.separator}${project.build.finalName}-jarjar.jar">
<zipfileset src="${project.build.directory}/jarjar-staging/com.springsource.org.objectweb.asm.jar"/>
<zipfileset src="${project.build.directory}/jarjar-staging/com.springsource.org.objectweb.asm.commons.jar"/>
<rule pattern="org.objectweb.asm.**" result="org.springframework.asm.@1"/>
</jarjar>
<unjar src="${project.build.directory}${file.separator}${project.build.finalName}-jarjar.jar"
dest="${project.build.outputDirectory}">
<patternset>
<include name="**/*.class"/>
<exclude name="*"/>
</patternset>
</unjar>
</tasks>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.google.code</groupId>
<artifactId>jarjar</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>spring-asm</artifactId>
<packaging>jar</packaging>
<version>3.0.0.RC2</version>
<parent>
<groupId>org.springframework</groupId>
<artifactId>spring-parent</artifactId>
<relativePath>../org.springframework.spring-parent</relativePath>
<version>3.0.0.RC2</version>
</parent>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>jarjar</id>
<phase>process-classes</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask" classpathref="maven.plugin.classpath" />
<jarjar jarfile="${project.build.directory}${file.separator}${project.build.finalName}-jarjar.jar">
<zipfileset src="${project.build.directory}/jarjar-staging/com.springsource.org.objectweb.asm.jar"/>
<zipfileset src="${project.build.directory}/jarjar-staging/com.springsource.org.objectweb.asm.commons.jar"/>
<rule pattern="org.objectweb.asm.**" result="org.springframework.asm.@1"/>
</jarjar>
<unjar src="${project.build.directory}${file.separator}${project.build.finalName}-jarjar.jar"
dest="${project.build.outputDirectory}">
<patternset>
<include name="**/*.class"/>
<exclude name="*"/>
</patternset>
</unjar>
</tasks>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.google.code</groupId>
<artifactId>jarjar</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
+1 -1
View File
@@ -13,7 +13,7 @@
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.transaction"/>
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.test"/>
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-sources-1.1.1.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.aspectj/com.springsource.org.aspectj.weaver/1.6.8.RELEASE/com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar" sourcepath="/IVY_CACHE/org.aspectj/com.springsource.org.aspectj.weaver/1.6.8.RELEASE/com.springsource.org.aspectj.weaver-sources-1.6.8.RELEASE.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.aspectj/com.springsource.org.aspectj.weaver/1.6.5.RELEASE/com.springsource.org.aspectj.weaver-1.6.5.RELEASE.jar" sourcepath="/IVY_CACHE/org.aspectj/com.springsource.org.aspectj.weaver/1.6.5.RELEASE/com.springsource.org.aspectj.weaver-sources-1.6.5.RELEASE.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-4.7.0.jar" sourcepath="/IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-sources-4.7.0.jar"/>
<classpathentry kind="var" path="IVY_CACHE/javax.persistence/com.springsource.javax.persistence/1.0.0/com.springsource.javax.persistence-1.0.0.jar" sourcepath="/IVY_CACHE/javax.persistence/com.springsource.javax.persistence/1.0.0/com.springsource.javax.persistence-sources-1.0.0.jar"/>
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.orm"/>
-1
View File
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="org.springframework.aspects">
<property file="${basedir}/../build.properties"/>
<property file="${basedir}/../build.versions"/>
<import file="${basedir}/../build-spring-framework/package-bundle.xml"/>
<import file="${basedir}/../spring-build/aspect/default.xml"/>
+38 -41
View File
@@ -1,41 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="http://ivyrep.jayasoft.org/ivy-doc.xsl"?>
<ivy-module
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://incubator.apache.org/ivy/schemas/ivy.xsd"
version="1.3">
<info organisation="org.springframework" module="${ant.project.name}">
<license name="Apache 2.0" url="http://www.apache.org/licenses/LICENSE-2.0"/>
</info>
<configurations>
<include file="${spring.build.dir}/common/default-ivy-configurations.xml"/>
<conf name="commons-logging" extends="runtime" description="JARs needed to run with Commons Logging"/>
<conf name="aspectj" extends="runtime" description="JARs needed to run with AspectJ"/>
<conf name="tx" extends="runtime" description="JARs needed to run transactional aspects"/>
<conf name="orm" extends="runtime" description="JARs needed to compile JPA aspects"/>
</configurations>
<publications>
<artifact name="${ant.project.name}"/>
<artifact name="${ant.project.name}-sources" type="src" ext="jar"/>
<artifact name="license" type="license" ext="txt"/>
<artifact name="notice" type="notice" ext="txt"/>
</publications>
<dependencies>
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.logging" rev="1.1.1" conf="compile, commons-logging->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="test->compile"/>
<dependency org="org.springframework" name="org.springframework.transaction" rev="latest.integration" conf="optional, tx->compile"/>
<dependency org="org.springframework" name="org.springframework.orm" rev="latest.integration" conf="optional, orm->compile"/>
<dependency org="org.springframework" name="org.springframework.test" rev="latest.integration" conf="test->runtime"/>
<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="${junit.version}" conf="test->compile"/>
<dependency org="javax.mail" name="com.springsource.javax.mail" rev="1.4.0" conf="optional, test->compile"/>
</dependencies>
</ivy-module>
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="http://ivyrep.jayasoft.org/ivy-doc.xsl"?>
<ivy-module
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://incubator.apache.org/ivy/schemas/ivy.xsd"
version="1.3">
<info organisation="org.springframework" module="${ant.project.name}">
<license name="Apache 2.0" url="http://www.apache.org/licenses/LICENSE-2.0"/>
</info>
<configurations>
<include file="${spring.build.dir}/common/default-ivy-configurations.xml"/>
<conf name="aspectj" extends="runtime" description="JARs needed to run with AspectJ"/>
<conf name="tx" extends="runtime" description="JARs needed to run transactional aspects"/>
<conf name="orm" extends="runtime" description="JARs needed to compile JPA aspects"/>
</configurations>
<publications>
<artifact name="${ant.project.name}"/>
<artifact name="${ant.project.name}-sources" type="src" ext="jar"/>
</publications>
<dependencies>
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.logging" rev="1.1.1" conf="compile->compile"/>
<dependency org="org.aspectj" name="com.springsource.org.aspectj.weaver" rev="1.6.5.RELEASE" conf="optional, aspectj->compile"/>
<dependency org="org.springframework" name="org.springframework.beans" rev="latest.integration" conf="test->compile"/>
<dependency org="org.springframework" name="org.springframework.transaction" rev="latest.integration" conf="optional, tx->compile"/>
<dependency org="org.springframework" name="org.springframework.orm" rev="latest.integration" conf="optional,orm->compile"/>
<dependency org="org.springframework" name="org.springframework.test" rev="latest.integration" conf="test->runtime"/>
<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="org.junit" name="com.springsource.org.junit" rev="4.7.0" conf="compile->compile"/>
<dependency org="javax.persistence" name="com.springsource.javax.persistence" rev="1.0.0" conf="provided, compile->compile"/>
<dependency org="javax.mail" name="com.springsource.javax.mail" rev="1.4.0" conf="test->compile"/>
</dependencies>
</ivy-module>
+77 -90
View File
@@ -1,90 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<packaging>jar</packaging>
<version>3.0.8.BUILD-SNAPSHOT</version>
<parent>
<groupId>org.springframework</groupId>
<artifactId>spring-parent</artifactId>
<relativePath>../org.springframework.spring-parent</relativePath>
<version>3.0.8.BUILD-SNAPSHOT</version>
</parent>
<dependencies>
<!-- commons logging dependency is in spring-core -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4</version>
<scope>test</scope>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<junitArtifactName>junit:junit</junitArtifactName>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<packaging>jar</packaging>
<version>3.0.0.RC2</version>
<parent>
<groupId>org.springframework</groupId>
<artifactId>spring-parent</artifactId>
<relativePath>../org.springframework.spring-parent</relativePath>
<version>3.0.0.RC2</version>
</parent>
<dependencies>
<!-- common logging dependency is in spring-core -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4</version>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<junitArtifactName>junit:junit</junitArtifactName>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
@@ -1,19 +1,3 @@
/*
* Copyright 2002-2010 the original author 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.mock.staticmock;
import java.util.Arrays;
@@ -28,6 +12,7 @@ import java.util.List;
*
* @author Rod Johnson
* @author Ramnivas Laddad
*
*/
public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMethod()) {
@@ -166,7 +151,7 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth
expectations.verify();
}
Object around() : methodToMock() && cflowbelow(mockStaticsTestMethod()) {
Object around() : methodToMock() {
if (recording) {
expectations.expectCall(thisJoinPointStaticPart.toLongString(), thisJoinPoint.getArgs());
// Return value doesn't matter
@@ -1,33 +1,18 @@
/*
* Copyright 2002-2010 the original author 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.mock.staticmock;
import javax.persistence.Entity;
/**
* Annotation-based aspect to use in test build to enable mocking static methods
* on JPA-annotated <code>@Entity</code> classes, as used by Roo for finders.
*
* <p>Mocking will occur in the call stack of any method in a class (typically a test class)
* on Entity classes, as used by Roo for finders.
* <br>
* Mocking will occur in the call stack of any method in a class (typically a test class)
* that is annotated with the @MockStaticEntityMethods annotation.
*
* <p>Also provides static methods to simplify the programming model for
* <br>
* Also provides static methods to simplify the programming model for
* entering playback mode and setting expected return values.
*
* <p>Usage:
* <ol>
* <br>
* Usage:<ol>
* <li>Annotate a test class with @MockStaticEntityMethods.
* <li>In each test method, AnnotationDrivenStaticEntityMockingControl will begin in recording mode.
* Invoke static methods on Entity classes, with each recording-mode invocation
@@ -38,9 +23,11 @@ package org.springframework.mock.staticmock;
* occur automatically.
* </ol>
*
* @see MockStaticEntityMethods
*
* @author Rod Johnson
* @author Ramnivas Laddad
* @see MockStaticEntityMethods
*
*/
public aspect AnnotationDrivenStaticEntityMockingControl extends AbstractMethodMockingControl {
@@ -63,6 +50,6 @@ public aspect AnnotationDrivenStaticEntityMockingControl extends AbstractMethodM
// @MockStatics classes to invoke each other without resetting the mocking environment
protected pointcut mockStaticsTestMethod() : execution(public * (@MockStaticEntityMethods *).*(..));
protected pointcut methodToMock() : execution(public static * (@javax.persistence.Entity *).*(..));
protected pointcut methodToMock() : execution(public static * (@Entity *).*(..));
}
@@ -1,18 +1,3 @@
/*
* Copyright 2002-2010 the original author 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.mock.staticmock;
import java.lang.annotation.ElementType;
@@ -23,9 +8,11 @@ import java.lang.annotation.Target;
/**
* Annotation to indicate a test class for whose @Test methods
* static methods on Entity classes should be mocked.
*
* @author Rod Johnson
*
* @see AbstractMethodMockingControl
*
* @author Rod Johnson
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@@ -1,75 +0,0 @@
/*
* Copyright 2002-2010 the original author 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.scheduling.aspectj;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.support.TaskExecutorAdapter;
/**
* Abstract aspect that routes selected methods asynchronously.
*
* <p>This aspect needs to be injected with an implementation of
* {@link Executor} to activate it for a specific thread pool.
* Otherwise it will simply delegate all calls synchronously.
*
* @author Ramnivas Laddad
* @author Juergen Hoeller
* @since 3.0.5
*/
public abstract aspect AbstractAsyncExecutionAspect {
private AsyncTaskExecutor asyncExecutor;
public void setExecutor(Executor executor) {
if (executor instanceof AsyncTaskExecutor) {
this.asyncExecutor = (AsyncTaskExecutor) executor;
}
else {
this.asyncExecutor = new TaskExecutorAdapter(executor);
}
}
Object around() : asyncMethod() {
if (this.asyncExecutor == null) {
return proceed();
}
Callable<Object> callable = new Callable<Object>() {
public Object call() throws Exception {
Object result = proceed();
if (result instanceof Future) {
return ((Future<?>) result).get();
}
return null;
}};
Future<?> result = this.asyncExecutor.submit(callable);
if (Future.class.isAssignableFrom(((MethodSignature) thisJoinPointStaticPart.getSignature()).getReturnType())) {
return result;
}
else {
return null;
}
}
public abstract pointcut asyncMethod();
}
@@ -1,54 +0,0 @@
/*
* Copyright 2002-2010 the original author 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.scheduling.aspectj;
import java.util.concurrent.Future;
import org.springframework.scheduling.annotation.Async;
/**
* Aspect to route methods based on the {@link Async} annotation.
*
* <p>This aspect routes methods marked with the {@link Async} annotation
* as well as methods in classes marked with the same. Any method expected
* to be routed asynchronously must return either void, {@link Future},
* or a subtype of {@link Future}. This aspect, therefore, will produce
* a compile-time error for methods that violate this constraint on the return type.
* If, however, a class marked with <code>&#64;Async</code> contains a method that
* violates this constraint, it produces only a warning.
*
* @author Ramnivas Laddad
* @since 3.0.5
*/
public aspect AnnotationAsyncExecutionAspect extends AbstractAsyncExecutionAspect {
private pointcut asyncMarkedMethod()
: execution(@Async (void || Future+) *(..));
private pointcut asyncTypeMarkedMethod()
: execution((void || Future+) (@Async *).*(..));
public pointcut asyncMethod() : asyncMarkedMethod() || asyncTypeMarkedMethod();
declare error:
execution(@Async !(void||Future) *(..)):
"Only methods that return void or Future may have an @Async annotation";
declare warning:
execution(!(void||Future) (@Async *).*(..)):
"Methods in a class marked with @Async that do not return void or Future will be routed synchronously";
}
@@ -1,93 +1,93 @@
/*
* Copyright 2002-2010 the original author 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.transaction.aspectj;
import java.lang.reflect.Method;
import org.aspectj.lang.annotation.SuppressAjWarnings;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.transaction.interceptor.TransactionAttributeSource;
/**
* Abstract superaspect for AspectJ transaction aspects. Concrete
* subaspects will implement the <code>transactionalMethodExecution()</code>
* pointcut using a strategy such as Java 5 annotations.
*
* <p>Suitable for use inside or outside the Spring IoC container.
* Set the "transactionManager" property appropriately, allowing
* use of any transaction implementation supported by Spring.
*
* <p><b>NB:</b> If a method implements an interface that is itself
* transactionally annotated, the relevant Spring transaction attribute
* will <i>not</i> be resolved. This behavior will vary from that of Spring AOP
* if proxying an interface (but not when proxying a class). We recommend that
* transaction annotations should be added to classes, rather than business
* interfaces, as they are an implementation detail rather than a contract
* specification validation.
*
* @author Rod Johnson
* @author Ramnivas Laddad
* @since 2.0
*/
public abstract aspect AbstractTransactionAspect extends TransactionAspectSupport {
/**
* Construct object using the given transaction metadata retrieval strategy.
* @param tas TransactionAttributeSource implementation, retrieving Spring
* transaction metadata for each joinpoint. Write the subclass to pass in null
* if it's intended to be configured by Setter Injection.
*/
protected AbstractTransactionAspect(TransactionAttributeSource tas) {
setTransactionAttributeSource(tas);
}
@SuppressAjWarnings("adviceDidNotMatch")
before(Object txObject) : transactionalMethodExecution(txObject) {
MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature();
Method method = methodSignature.getMethod();
TransactionInfo txInfo = createTransactionIfNecessary(method, txObject.getClass());
}
@SuppressAjWarnings("adviceDidNotMatch")
after(Object txObject) throwing(Throwable t) : transactionalMethodExecution(txObject) {
try {
completeTransactionAfterThrowing(TransactionAspectSupport.currentTransactionInfo(), t);
}
catch (Throwable t2) {
logger.error("Failed to close transaction after throwing in a transactional method", t2);
}
}
@SuppressAjWarnings("adviceDidNotMatch")
after(Object txObject) returning() : transactionalMethodExecution(txObject) {
commitTransactionAfterReturning(TransactionAspectSupport.currentTransactionInfo());
}
@SuppressAjWarnings("adviceDidNotMatch")
after(Object txObject) : transactionalMethodExecution(txObject) {
cleanupTransactionInfo(TransactionAspectSupport.currentTransactionInfo());
}
/**
* Concrete subaspects must implement this pointcut, to identify
* transactional methods. For each selected joinpoint, TransactionMetadata
* will be retrieved using Spring's TransactionAttributeSource interface.
*/
protected abstract pointcut transactionalMethodExecution(Object txObject);
}
/*
* Copyright 2002-2007 the original author 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.transaction.aspectj;
import java.lang.reflect.Method;
import org.aspectj.lang.annotation.SuppressAjWarnings;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.transaction.interceptor.TransactionAttributeSource;
/**
* Abstract superaspect for AspectJ transaction aspects. Concrete
* subaspects will implement the <code>transactionalMethodExecution()</code>
* pointcut using a strategy such as Java 5 annotations.
*
* <p>Suitable for use inside or outside the Spring IoC container.
* Set the "transactionManager" property appropriately, allowing
* use of any transaction implementation supported by Spring.
*
* <p><b>NB:</b> If a method implements an interface that is itself
* transactionally annotated, the relevant Spring transaction attribute
* will <i>not</i> be resolved. This behavior will vary from that of Spring AOP
* if proxying an interface (but not when proxying a class). We recommend that
* transaction annotations should be added to classes, rather than business
* interfaces, as they are an implementation detail rather than a contract
* specification validation.
*
* @author Rod Johnson
* @author Ramnivas Laddad
* @since 2.0
*/
public abstract aspect AbstractTransactionAspect extends TransactionAspectSupport {
/**
* Construct object using the given transaction metadata retrieval strategy.
* @param tas TransactionAttributeSource implementation, retrieving Spring
* transaction metadata for each joinpoint. Write the subclass to pass in null
* if it's intended to be configured by Setter Injection.
*/
protected AbstractTransactionAspect(TransactionAttributeSource tas) {
setTransactionAttributeSource(tas);
}
@SuppressAjWarnings("adviceDidNotMatch")
before(Object txObject) : transactionalMethodExecution(txObject) {
MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature();
Method method = methodSignature.getMethod();
TransactionInfo txInfo = createTransactionIfNecessary(method, txObject.getClass());
}
@SuppressAjWarnings("adviceDidNotMatch")
after(Object txObject) throwing(Throwable t) : transactionalMethodExecution(txObject) {
try {
completeTransactionAfterThrowing(TransactionAspectSupport.currentTransactionInfo(), t);
}
catch (Throwable t2) {
logger.error("Failed to close transaction after throwing in a transactional method", t2);
}
}
@SuppressAjWarnings("adviceDidNotMatch")
after(Object txObject) returning() : transactionalMethodExecution(txObject) {
commitTransactionAfterReturning(TransactionAspectSupport.currentTransactionInfo());
}
@SuppressAjWarnings("adviceDidNotMatch")
after(Object txObject) : transactionalMethodExecution(txObject) {
cleanupTransactionInfo(TransactionAspectSupport.currentTransactionInfo());
}
/**
* Concrete subaspects must implement this pointcut, to identify
* transactional methods. For each selected joinpoint, TransactionMetadata
* will be retrieved using Spring's TransactionAttributeSource interface.
*/
protected abstract pointcut transactionalMethodExecution(Object txObject);
}
@@ -1,75 +1,76 @@
/*
* Copyright 2002-2010 the original author 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.transaction.aspectj;
import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
import org.springframework.transaction.annotation.Transactional;
/**
* Concrete AspectJ transaction aspect using Spring's @Transactional annotation.
*
* <p>When using this aspect, you <i>must</i> annotate the implementation class
* (and/or methods within that class), <i>not</i> the interface (if any) that
* the class implements. AspectJ follows Java's rule that annotations on
* interfaces are <i>not</i> inherited.
*
* <p>A @Transactional annotation on a class specifies the default transaction
* semantics for the execution of any <b>public</b> operation in the class.
*
* <p>A @Transactional annotation on a method within the class overrides the
* default transaction semantics given by the class annotation (if present).
* Any method may be annotated (regardless of visibility).
* Annotating non-public methods directly is the only way
* to get transaction demarcation for the execution of such operations.
*
* @author Rod Johnson
* @author Ramnivas Laddad
* @author Adrian Colyer
* @since 2.0
* @see org.springframework.transaction.annotation.Transactional
*/
public aspect AnnotationTransactionAspect extends AbstractTransactionAspect {
public AnnotationTransactionAspect() {
super(new AnnotationTransactionAttributeSource(false));
}
/**
* Matches the execution of any public method in a type with the
* Transactional annotation, or any subtype of a type with the
* Transactional annotation.
*/
private pointcut executionOfAnyPublicMethodInAtTransactionalType() :
execution(public * ((@Transactional *)+).*(..)) && @this(Transactional);
/**
* Matches the execution of any method with the
* Transactional annotation.
*/
private pointcut executionOfTransactionalMethod() :
execution(* *(..)) && @annotation(Transactional);
/**
* Definition of pointcut from super aspect - matched join points
* will have Spring transaction management applied.
*/
protected pointcut transactionalMethodExecution(Object txObject) :
(executionOfAnyPublicMethodInAtTransactionalType()
|| executionOfTransactionalMethod() )
&& this(txObject);
}
/*
* Copyright 2002-2008 the original author 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.transaction.aspectj;
import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
import org.springframework.transaction.annotation.Transactional;
/**
* Concrete AspectJ transaction aspect using Spring Transactional annotation
* for JDK 1.5+.
*
* <p>When using this aspect, you <i>must</i> annotate the implementation class
* (and/or methods within that class), <i>not</i> the interface (if any) that
* the class implements. AspectJ follows Java's rule that annotations on
* interfaces are <i>not</i> inherited.
*
* <p>A @Transactional annotation on a class specifies the default transaction
* semantics for the execution of any <b>public</b> operation in the class.
*
* <p>A @Transactional annotation on a method within the class overrides the
* default transaction semantics given by the class annotation (if present).
* Any method may be annotated (regardless of visibility).
* Annotating non-public methods directly is the only way
* to get transaction demarcation for the execution of such operations.
*
* @author Rod Johnson
* @author Ramnivas Laddad
* @author Adrian Colyer
* @since 2.0
* @see org.springframework.transaction.annotation.Transactional
*/
public aspect AnnotationTransactionAspect extends AbstractTransactionAspect {
public AnnotationTransactionAspect() {
super(new AnnotationTransactionAttributeSource(false));
}
/**
* Matches the execution of any public method in a type with the
* Transactional annotation, or any subtype of a type with the
* Transactional annotation.
*/
private pointcut executionOfAnyPublicMethodInAtTransactionalType() :
execution(public * ((@Transactional *)+).*(..)) && @this(Transactional);
/**
* Matches the execution of any method with the
* Transactional annotation.
*/
private pointcut executionOfTransactionalMethod() :
execution(* *(..)) && @annotation(Transactional);
/**
* Definition of pointcut from super aspect - matched join points
* will have Spring transaction management applied.
*/
protected pointcut transactionalMethodExecution(Object txObject) :
(executionOfAnyPublicMethodInAtTransactionalType()
|| executionOfTransactionalMethod() )
&& this(txObject);
}
@@ -1,18 +1,17 @@
<?xml version="1.0"?>
<!--
AspectJ load-time weaving config file to install common Spring aspects.
-->
<aspectj>
<!--
<weaver options="-showWeaveInfo"/>
-->
<aspects>
<aspect name="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect"/>
<aspect name="org.springframework.scheduling.aspectj.AnnotationAsyncExecutionAspect"/>
<aspect name="org.springframework.transaction.aspectj.AnnotationTransactionAspect"/>
</aspects>
</aspectj>
<?xml version="1.0"?>
<!--
AspectJ load-time weaving config file to install common Spring aspects.
-->
<aspectj>
<!--
<weaver options="-showWeaveInfo"/>
-->
<aspects>
<aspect name="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect"/>
<aspect name="org.springframework.transaction.aspectj.AnnotationTransactionAspect"/>
</aspects>
</aspectj>
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2007 the original author 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,9 +16,12 @@
package org.springframework.aop.aspectj.autoproxy;
import org.aspectj.lang.annotation.Aspect;
/**
* @author Adrian Colyer
*/
@Aspect
public aspect CodeStyleAspect {
private String foo;
@@ -1,146 +1,146 @@
/*
* Copyright 2002-2010 the original author 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.mock.staticmock;
import javax.persistence.PersistenceException;
import junit.framework.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import static org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl.*;
/**
* Test for static entity mocking framework.
* @author Rod Johnson
* @author Ramnivas Laddad
*
*/
@MockStaticEntityMethods
@RunWith(JUnit4.class)
public class AnnotationDrivenStaticEntityMockingControlTest {
@Test
public void testNoArgIntReturn() {
int expectedCount = 13;
Person.countPeople();
expectReturn(expectedCount);
playback();
Assert.assertEquals(expectedCount, Person.countPeople());
}
@Test(expected=PersistenceException.class)
public void testNoArgThrows() {
Person.countPeople();
expectThrow(new PersistenceException());
playback();
Person.countPeople();
}
@Test
public void testArgMethodMatches() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
expectReturn(found);
playback();
Assert.assertEquals(found, Person.findPerson(id));
}
@Test
public void testLongSeriesOfCalls() {
long id1 = 13;
long id2 = 24;
Person found1 = new Person();
Person.findPerson(id1);
expectReturn(found1);
Person found2 = new Person();
Person.findPerson(id2);
expectReturn(found2);
Person.findPerson(id1);
expectReturn(found1);
Person.countPeople();
expectReturn(0);
playback();
Assert.assertEquals(found1, Person.findPerson(id1));
Assert.assertEquals(found2, Person.findPerson(id2));
Assert.assertEquals(found1, Person.findPerson(id1));
Assert.assertEquals(0, Person.countPeople());
}
// Note delegation is used when tests are invalid and should fail, as otherwise
// the failure will occur on the verify() method in the aspect after
// this method returns, failing the test case
@Test
public void testArgMethodNoMatchExpectReturn() {
try {
new Delegate().testArgMethodNoMatchExpectReturn();
Assert.fail();
} catch (IllegalArgumentException expected) {
}
}
@Test(expected=IllegalArgumentException.class)
public void testArgMethodNoMatchExpectThrow() {
new Delegate().testArgMethodNoMatchExpectThrow();
}
private void called(Person found, long id) {
Assert.assertEquals(found, Person.findPerson(id));
}
@Test
public void testReentrant() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
expectReturn(found);
playback();
called(found, id);
}
@Test(expected=IllegalStateException.class)
public void testRejectUnexpectedCall() {
new Delegate().rejectUnexpectedCall();
}
@Test(expected=IllegalStateException.class)
public void testFailTooFewCalls() {
new Delegate().failTooFewCalls();
}
@Test
public void testEmpty() {
// Test that verification check doesn't blow up if no replay() call happened
}
@Test(expected=IllegalStateException.class)
public void testDoesntEverReplay() {
new Delegate().doesntEverReplay();
}
@Test(expected=IllegalStateException.class)
public void testDoesntEverSetReturn() {
new Delegate().doesntEverSetReturn();
}
}
/*
* Copyright 2009 SpringSource Inc.
*
* 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.mock.staticmock;
import javax.persistence.PersistenceException;
import junit.framework.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import static org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl.*;
/**
* Test for static entity mocking framework.
* @author Rod Johnson
* @author Ramnivas Laddad
*
*/
@MockStaticEntityMethods
@RunWith(JUnit4.class)
public class AnnotationDrivenStaticEntityMockingControlTest {
@Test
public void testNoArgIntReturn() {
int expectedCount = 13;
Person.countPeople();
expectReturn(expectedCount);
playback();
Assert.assertEquals(expectedCount, Person.countPeople());
}
@Test(expected=PersistenceException.class)
public void testNoArgThrows() {
Person.countPeople();
expectThrow(new PersistenceException());
playback();
Person.countPeople();
}
@Test
public void testArgMethodMatches() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
expectReturn(found);
playback();
Assert.assertEquals(found, Person.findPerson(id));
}
@Test
public void testLongSeriesOfCalls() {
long id1 = 13;
long id2 = 24;
Person found1 = new Person();
Person.findPerson(id1);
expectReturn(found1);
Person found2 = new Person();
Person.findPerson(id2);
expectReturn(found2);
Person.findPerson(id1);
expectReturn(found1);
Person.countPeople();
expectReturn(0);
playback();
Assert.assertEquals(found1, Person.findPerson(id1));
Assert.assertEquals(found2, Person.findPerson(id2));
Assert.assertEquals(found1, Person.findPerson(id1));
Assert.assertEquals(0, Person.countPeople());
}
// Note delegation is used when tests are invalid and should fail, as otherwise
// the failure will occur on the verify() method in the aspect after
// this method returns, failing the test case
@Test
public void testArgMethodNoMatchExpectReturn() {
try {
new Delegate().testArgMethodNoMatchExpectReturn();
Assert.fail();
} catch (IllegalArgumentException expected) {
}
}
@Test(expected=IllegalArgumentException.class)
public void testArgMethodNoMatchExpectThrow() {
new Delegate().testArgMethodNoMatchExpectThrow();
}
private void called(Person found, long id) {
Assert.assertEquals(found, Person.findPerson(id));
}
@Test
public void testReentrant() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
expectReturn(found);
playback();
called(found, id);
}
@Test(expected=IllegalStateException.class)
public void testRejectUnexpectedCall() {
new Delegate().rejectUnexpectedCall();
}
@Test(expected=IllegalStateException.class)
public void testFailTooFewCalls() {
new Delegate().failTooFewCalls();
}
@Test
public void testEmpty() {
// Test that verification check doesn't blow up if no replay() call happened
}
@Test(expected=IllegalStateException.class)
public void testDoesntEverReplay() {
new Delegate().doesntEverReplay();
}
@Test(expected=IllegalStateException.class)
public void testDoesntEverSetReturn() {
new Delegate().doesntEverSetReturn();
}
}
@@ -1,92 +1,76 @@
/*
* Copyright 2002-2010 the original author 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.mock.staticmock;
import java.rmi.RemoteException;
import javax.persistence.PersistenceException;
import junit.framework.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl;
import org.springframework.mock.staticmock.MockStaticEntityMethods;
//Used because verification failures occur after method returns,
//so we can't test for them in the test case itself
@MockStaticEntityMethods
@Ignore // This isn't meant for direct testing; rather it is driven from AnnotationDrivenStaticEntityMockingControl
public class Delegate {
@Test
public void testArgMethodNoMatchExpectReturn() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
AnnotationDrivenStaticEntityMockingControl.expectReturn(found);
AnnotationDrivenStaticEntityMockingControl.playback();
Assert.assertEquals(found, Person.findPerson(id + 1));
}
@Test
public void testArgMethodNoMatchExpectThrow() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
AnnotationDrivenStaticEntityMockingControl.expectThrow(new PersistenceException());
AnnotationDrivenStaticEntityMockingControl.playback();
Assert.assertEquals(found, Person.findPerson(id + 1));
}
@Test
public void failTooFewCalls() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
AnnotationDrivenStaticEntityMockingControl.expectReturn(found);
Person.countPeople();
AnnotationDrivenStaticEntityMockingControl.expectReturn(25);
AnnotationDrivenStaticEntityMockingControl.playback();
Assert.assertEquals(found, Person.findPerson(id));
}
@Test
public void doesntEverReplay() {
Person.countPeople();
}
@Test
public void doesntEverSetReturn() {
Person.countPeople();
AnnotationDrivenStaticEntityMockingControl.playback();
}
@Test
public void rejectUnexpectedCall() {
AnnotationDrivenStaticEntityMockingControl.playback();
Person.countPeople();
}
@Test(expected=RemoteException.class)
public void testVerificationFailsEvenWhenTestFailsInExpectedManner() throws RemoteException {
Person.countPeople();
AnnotationDrivenStaticEntityMockingControl.playback();
// No calls to allow verification failure
throw new RemoteException();
}
}
package org.springframework.mock.staticmock;
import java.rmi.RemoteException;
import javax.persistence.PersistenceException;
import junit.framework.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl;
import org.springframework.mock.staticmock.MockStaticEntityMethods;
//Used because verification failures occur after method returns,
//so we can't test for them in the test case itself
@MockStaticEntityMethods
@Ignore // This isn't meant for direct testing; rather it is driven from AnnotationDrivenStaticEntityMockingControl
public class Delegate {
@Test
public void testArgMethodNoMatchExpectReturn() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
AnnotationDrivenStaticEntityMockingControl.expectReturn(found);
AnnotationDrivenStaticEntityMockingControl.playback();
Assert.assertEquals(found, Person.findPerson(id + 1));
}
@Test
public void testArgMethodNoMatchExpectThrow() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
AnnotationDrivenStaticEntityMockingControl.expectThrow(new PersistenceException());
AnnotationDrivenStaticEntityMockingControl.playback();
Assert.assertEquals(found, Person.findPerson(id + 1));
}
@Test
public void failTooFewCalls() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
AnnotationDrivenStaticEntityMockingControl.expectReturn(found);
Person.countPeople();
AnnotationDrivenStaticEntityMockingControl.expectReturn(25);
AnnotationDrivenStaticEntityMockingControl.playback();
Assert.assertEquals(found, Person.findPerson(id));
}
@Test
public void doesntEverReplay() {
Person.countPeople();
}
@Test
public void doesntEverSetReturn() {
Person.countPeople();
AnnotationDrivenStaticEntityMockingControl.playback();
}
@Test
public void rejectUnexpectedCall() {
AnnotationDrivenStaticEntityMockingControl.playback();
Person.countPeople();
}
@Test(expected=RemoteException.class)
public void testVerificationFailsEvenWhenTestFailsInExpectedManner() throws RemoteException {
Person.countPeople();
AnnotationDrivenStaticEntityMockingControl.playback();
// No calls to allow verification failure
throw new RemoteException();
}
}
@@ -1,24 +1,8 @@
/*
* Copyright 2002-2010 the original author 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.mock.staticmock;
import javax.persistence.Entity;
@Entity
public class Person {
}
package org.springframework.mock.staticmock;
import javax.persistence.Entity;
@Entity
public class Person {
}
@@ -1,100 +1,84 @@
/*
* Copyright 2002-2010 the original author 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.mock.staticmock;
privileged aspect Person_Roo_Entity {
@javax.persistence.PersistenceContext
transient javax.persistence.EntityManager Person.entityManager;
@javax.persistence.Id
@javax.persistence.GeneratedValue(strategy = javax.persistence.GenerationType.AUTO)
@javax.persistence.Column(name = "id")
private java.lang.Long Person.id;
@javax.persistence.Version
@javax.persistence.Column(name = "version")
private java.lang.Integer Person.version;
public java.lang.Long Person.getId() {
return this.id;
}
public void Person.setId(java.lang.Long id) {
this.id = id;
}
public java.lang.Integer Person.getVersion() {
return this.version;
}
public void Person.setVersion(java.lang.Integer version) {
this.version = version;
}
@org.springframework.transaction.annotation.Transactional
public void Person.persist() {
if (this.entityManager == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
this.entityManager.persist(this);
}
@org.springframework.transaction.annotation.Transactional
public void Person.remove() {
if (this.entityManager == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
this.entityManager.remove(this);
}
@org.springframework.transaction.annotation.Transactional
public void Person.flush() {
if (this.entityManager == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
this.entityManager.flush();
}
@org.springframework.transaction.annotation.Transactional
public void Person.merge() {
if (this.entityManager == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
Person merged = this.entityManager.merge(this);
this.entityManager.flush();
this.id = merged.getId();
}
public static long Person.countPeople() {
javax.persistence.EntityManager em = new Person().entityManager;
if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
return (Long) em.createQuery("select count(o) from Person o").getSingleResult();
}
public static java.util.List<Person> Person.findAllPeople() {
javax.persistence.EntityManager em = new Person().entityManager;
if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
return em.createQuery("select o from Person o").getResultList();
}
public static Person Person.findPerson(java.lang.Long id) {
if (id == null) throw new IllegalArgumentException("An identifier is required to retrieve an instance of Person");
javax.persistence.EntityManager em = new Person().entityManager;
if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
return em.find(Person.class, id);
}
public static java.util.List<Person> Person.findPersonEntries(int firstResult, int maxResults) {
javax.persistence.EntityManager em = new Person().entityManager;
if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
return em.createQuery("select o from Person o").setFirstResult(firstResult).setMaxResults(maxResults).getResultList();
}
}
package org.springframework.mock.staticmock;
privileged aspect Person_Roo_Entity {
@javax.persistence.PersistenceContext
transient javax.persistence.EntityManager Person.entityManager;
@javax.persistence.Id
@javax.persistence.GeneratedValue(strategy = javax.persistence.GenerationType.AUTO)
@javax.persistence.Column(name = "id")
private java.lang.Long Person.id;
@javax.persistence.Version
@javax.persistence.Column(name = "version")
private java.lang.Integer Person.version;
public java.lang.Long Person.getId() {
return this.id;
}
public void Person.setId(java.lang.Long id) {
this.id = id;
}
public java.lang.Integer Person.getVersion() {
return this.version;
}
public void Person.setVersion(java.lang.Integer version) {
this.version = version;
}
@org.springframework.transaction.annotation.Transactional
public void Person.persist() {
if (this.entityManager == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
this.entityManager.persist(this);
}
@org.springframework.transaction.annotation.Transactional
public void Person.remove() {
if (this.entityManager == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
this.entityManager.remove(this);
}
@org.springframework.transaction.annotation.Transactional
public void Person.flush() {
if (this.entityManager == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
this.entityManager.flush();
}
@org.springframework.transaction.annotation.Transactional
public void Person.merge() {
if (this.entityManager == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
Person merged = this.entityManager.merge(this);
this.entityManager.flush();
this.id = merged.getId();
}
public static long Person.countPeople() {
javax.persistence.EntityManager em = new Person().entityManager;
if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
return (Long) em.createQuery("select count(o) from Person o").getSingleResult();
}
public static java.util.List<Person> Person.findAllPeople() {
javax.persistence.EntityManager em = new Person().entityManager;
if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
return em.createQuery("select o from Person o").getResultList();
}
public static Person Person.findPerson(java.lang.Long id) {
if (id == null) throw new IllegalArgumentException("An identifier is required to retrieve an instance of Person");
javax.persistence.EntityManager em = new Person().entityManager;
if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
return em.find(Person.class, id);
}
public static java.util.List<Person> Person.findPersonEntries(int firstResult, int maxResults) {
javax.persistence.EntityManager em = new Person().entityManager;
if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
return em.createQuery("select o from Person o").setFirstResult(firstResult).setMaxResults(maxResults).getResultList();
}
}
@@ -1,178 +0,0 @@
/*
* Copyright 2002-2010 the original author 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.scheduling.aspectj;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import junit.framework.Assert;
import static junit.framework.Assert.*;
import org.junit.Before;
import org.junit.Test;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
/**
* @author Ramnivas Laddad
*/
public class AnnotationAsyncExecutionAspectTests {
private static final long WAIT_TIME = 1000; //milli seconds
private CountingExecutor executor;
@Before
public void setUp() {
executor = new CountingExecutor();
AnnotationAsyncExecutionAspect.aspectOf().setExecutor(executor);
}
@Test
public void asyncMethodGetsRoutedAsynchronously() {
ClassWithoutAsyncAnnotation obj = new ClassWithoutAsyncAnnotation();
obj.incrementAsync();
executor.waitForCompletion();
assertEquals(1, obj.counter);
assertEquals(1, executor.submitStartCounter);
assertEquals(1, executor.submitCompleteCounter);
}
@Test
public void asyncMethodReturningFutureGetsRoutedAsynchronouslyAndReturnsAFuture() throws InterruptedException, ExecutionException {
ClassWithoutAsyncAnnotation obj = new ClassWithoutAsyncAnnotation();
Future<Integer> future = obj.incrementReturningAFuture();
// No need to executor.waitForCompletion() as future.get() will have the same effect
assertEquals(5, future.get().intValue());
assertEquals(1, obj.counter);
assertEquals(1, executor.submitStartCounter);
assertEquals(1, executor.submitCompleteCounter);
}
@Test
public void syncMethodGetsRoutedSynchronously() {
ClassWithoutAsyncAnnotation obj = new ClassWithoutAsyncAnnotation();
obj.increment();
assertEquals(1, obj.counter);
assertEquals(0, executor.submitStartCounter);
assertEquals(0, executor.submitCompleteCounter);
}
@Test
public void voidMethodInAsyncClassGetsRoutedAsynchronously() {
ClassWithAsyncAnnotation obj = new ClassWithAsyncAnnotation();
obj.increment();
executor.waitForCompletion();
assertEquals(1, obj.counter);
assertEquals(1, executor.submitStartCounter);
assertEquals(1, executor.submitCompleteCounter);
}
@Test
public void methodReturningFutureInAsyncClassGetsRoutedAsynchronouslyAndReturnsAFuture() throws InterruptedException, ExecutionException {
ClassWithAsyncAnnotation obj = new ClassWithAsyncAnnotation();
Future<Integer> future = obj.incrementReturningAFuture();
assertEquals(5, future.get().intValue());
assertEquals(1, obj.counter);
assertEquals(1, executor.submitStartCounter);
assertEquals(1, executor.submitCompleteCounter);
}
@Test
public void methodReturningNonVoidNonFutureInAsyncClassGetsRoutedSynchronously() {
ClassWithAsyncAnnotation obj = new ClassWithAsyncAnnotation();
int returnValue = obj.return5();
assertEquals(5, returnValue);
assertEquals(0, executor.submitStartCounter);
assertEquals(0, executor.submitCompleteCounter);
}
@SuppressWarnings("serial")
private static class CountingExecutor extends SimpleAsyncTaskExecutor {
int submitStartCounter;
int submitCompleteCounter;
@Override
public <T> Future<T> submit(Callable<T> task) {
submitStartCounter++;
Future<T> future = super.submit(task);
submitCompleteCounter++;
synchronized (this) {
notifyAll();
}
return future;
}
public synchronized void waitForCompletion() {
try {
wait(WAIT_TIME);
} catch (InterruptedException e) {
Assert.fail("Didn't finish the async job in " + WAIT_TIME + " milliseconds");
}
}
}
static class ClassWithoutAsyncAnnotation {
int counter;
@Async public void incrementAsync() {
counter++;
}
public void increment() {
counter++;
}
@Async public Future<Integer> incrementReturningAFuture() {
counter++;
return new AsyncResult<Integer>(5);
}
// It should be an error to attach @Async to a method that returns a non-void
// or non-Future.
// We need to keep this commented out, otherwise there will be a compile-time error.
// Please uncomment and re-comment this periodically to check that the compiler
// produces an error message due to the 'declare error' statement
// in AnnotationAsyncExecutionAspect
// @Async public int getInt() {
// return 0;
// }
}
@Async
static class ClassWithAsyncAnnotation {
int counter;
public void increment() {
counter++;
}
// Manually check that there is a warning from the 'declare warning' statement in AnnotationAsynchExecutionAspect
public int return5() {
return 5;
}
public Future<Integer> incrementReturningAFuture() {
counter++;
return new AsyncResult<Integer>(5);
}
}
}
+5 -6
View File
@@ -4,12 +4,11 @@ Bundle-Vendor: SpringSource
Bundle-ManifestVersion: 2
Import-Template:
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
org.aspectj.*;version=${aj.osgi.range};resolution:=optional,
org.springframework.beans.*;version=${spring.osgi.range},
org.springframework.transaction.*;version=${spring.osgi.range};resolution:=optional,
org.springframework.core.task.*;version=${spring.osgi.range};resolution:=optional,
org.springframework.orm.jpa.*;version=${spring.osgi.range};resolution:=optional,
org.springframework.dao.*;version=${spring.osgi.range};resolution:=optional
org.aspectj.*;version="[1.5.4, 2.0.0)";resolution:=optional,
org.springframework.beans.*;version="[3.0.0, 3.0.1)",
org.springframework.transaction.*;version="[3.0.0, 3.0.1)";resolution:=optional,
org.springframework.orm.jpa.*;version="[3.0.0, 3.0.1)";resolution:=optional,
org.springframework.dao.*;version="[3.0.0, 3.0.1)";resolution:=optional
Ignored-Existing-Headers:
Bnd-LastModified,
Import-Package,
-1
View File
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="org.springframework.beans">
<property file="${basedir}/../build.properties"/>
<property file="${basedir}/../build.versions"/>
<import file="${basedir}/../build-spring-framework/package-bundle.xml"/>
<import file="${basedir}/../spring-build/standard/default.xml"/>
</project>
+2 -5
View File
@@ -11,26 +11,23 @@
<configurations>
<include file="${spring.build.dir}/common/default-ivy-configurations.xml"/>
<conf name="commons-logging" extends="runtime" description="JARs needed to run with Commons Logging"/>
<conf name="bytecode-proxy" extends="runtime" description="JARs needed to run with CGLIB bytecode proxies"/>
</configurations>
<publications>
<artifact name="${ant.project.name}"/>
<artifact name="${ant.project.name}-sources" type="src" ext="jar"/>
<artifact name="license" type="license" ext="txt"/>
<artifact name="notice" type="notice" ext="txt"/>
</publications>
<dependencies>
<dependency org="javax.el" name="com.springsource.javax.el" rev="1.0.0" conf="provided->compile"/>
<dependency org="javax.inject" name="com.springsource.javax.inject" rev="1.0.0" conf="provided->compile"/>
<dependency org="net.sourceforge.cglib" name="com.springsource.net.sf.cglib" rev="2.2.0" conf="optional, bytecode-proxy->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.logging" rev="1.1.1" 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.junit" name="com.springsource.org.junit" rev="${junit.version}" conf="test->runtime"/>
<dependency org="org.junit" name="com.springsource.org.junit" rev="4.7.0" 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 -4
View File
@@ -4,12 +4,12 @@
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<packaging>jar</packaging>
<version>3.0.8.BUILD-SNAPSHOT</version>
<version>3.0.0.RC2</version>
<parent>
<groupId>org.springframework</groupId>
<artifactId>spring-parent</artifactId>
<relativePath>../org.springframework.spring-parent</relativePath>
<version>3.0.8.BUILD-SNAPSHOT</version>
<version>3.0.0.RC2</version>
</parent>
<dependencies>
@@ -21,8 +21,8 @@
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
<artifactId>com.springsource.javax.inject</artifactId>
<version>0.9.0.PFD</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -50,7 +50,7 @@ public abstract class AbstractPropertyAccessor extends PropertyEditorRegistrySup
setPropertyValue(pv.getName(), pv.getValue());
}
public void setPropertyValues(Map<?, ?> map) throws BeansException {
public void setPropertyValues(Map map) throws BeansException {
setPropertyValues(new MutablePropertyValues(map));
}
@@ -0,0 +1,90 @@
/*
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans;
import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.core.MethodParameter;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.util.ReflectionUtils;
/**
* {@link TypeDescriptor} extension that exposes additional annotations
* as conversion metadata: namely, annotations on other accessor methods
* (getter/setter) and on the underlying field, if found.
*
* @author Juergen Hoeller
* @since 3.0
*/
class BeanTypeDescriptor extends TypeDescriptor {
private final PropertyDescriptor propertyDescriptor;
private Annotation[] cachedAnnotations;
/**
* Create a new BeanTypeDescriptor for the given bean property.
* @param methodParameter the target method parameter
* @param propertyDescriptor the corresponding JavaBean PropertyDescriptor
*/
public BeanTypeDescriptor(MethodParameter methodParameter, PropertyDescriptor propertyDescriptor) {
super(methodParameter);
this.propertyDescriptor = propertyDescriptor;
}
@Override
public Annotation[] getAnnotations() {
Annotation[] anns = this.cachedAnnotations;
if (anns == null) {
Field underlyingField = ReflectionUtils.findField(
getMethodParameter().getMethod().getDeclaringClass(), this.propertyDescriptor.getName());
Map<Class, Annotation> annMap = new LinkedHashMap<Class, Annotation>();
if (underlyingField != null) {
for (Annotation ann : underlyingField.getAnnotations()) {
annMap.put(ann.annotationType(), ann);
}
}
Method targetMethod = getMethodParameter().getMethod();
Method writeMethod = this.propertyDescriptor.getWriteMethod();
Method readMethod = this.propertyDescriptor.getReadMethod();
if (writeMethod != null && writeMethod != targetMethod) {
for (Annotation ann : writeMethod.getAnnotations()) {
annMap.put(ann.annotationType(), ann);
}
}
if (readMethod != null && readMethod != targetMethod) {
for (Annotation ann : readMethod.getAnnotations()) {
annMap.put(ann.annotationType(), ann);
}
}
for (Annotation ann : targetMethod.getAnnotations()) {
annMap.put(ann.annotationType(), ann);
}
anns = annMap.values().toArray(new Annotation[annMap.size()]);
this.cachedAnnotations = anns;
}
return anns;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -389,17 +389,8 @@ public abstract class BeanUtils {
}
ClassLoader cl = targetType.getClassLoader();
if (cl == null) {
try {
cl = ClassLoader.getSystemClassLoader();
if (cl == null) {
return null;
}
}
catch (Throwable ex) {
// e.g. AccessControlException on Google App Engine
if (logger.isDebugEnabled()) {
logger.debug("Could not access system ClassLoader: " + ex);
}
cl = ClassLoader.getSystemClassLoader();
if (cl == null) {
return null;
}
}
@@ -407,10 +398,8 @@ public abstract class BeanUtils {
try {
Class<?> editorClass = cl.loadClass(editorName);
if (!PropertyEditor.class.isAssignableFrom(editorClass)) {
if (logger.isWarnEnabled()) {
logger.warn("Editor class [" + editorName +
"] does not implement [java.beans.PropertyEditor] interface");
}
logger.warn("Editor class [" + editorName +
"] does not implement [java.beans.PropertyEditor] interface");
unknownEditorTypes.put(targetType, Boolean.TRUE);
return null;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -79,11 +79,11 @@ public interface BeanWrapper extends ConfigurablePropertyAccessor {
PropertyDescriptor getPropertyDescriptor(String propertyName) throws InvalidPropertyException;
/**
* 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
* Set if 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.
* enables auto-growth of collection elements when an index that is out of bounds is accessed.
* <p>Default is false.
*/
void setAutoGrowNestedPaths(boolean autoGrowNestedPaths);
@@ -92,15 +92,4 @@ 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();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,14 +37,11 @@ import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.CollectionFactory;
import org.springframework.core.GenericCollectionTypeResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.convert.ConversionException;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.support.PropertyTypeDescriptor;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
@@ -102,11 +99,6 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
private TypeConverterDelegate typeConverterDelegate;
/**
* The security context used for invoking the property methods
*/
private AccessControlContext acc;
/**
* Cached introspections results for this object, to prevent encountering
* the cost of JavaBeans introspection every time.
@@ -118,9 +110,10 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
*/
private Map<String, BeanWrapperImpl> nestedBeanWrappers;
private boolean autoGrowNestedPaths = false;
/** The security context used for invoking the property methods */
private AccessControlContext acc;
private int autoGrowCollectionLimit = Integer.MAX_VALUE;
private boolean autoGrowNestedPaths = false;
/**
@@ -186,7 +179,6 @@ 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);
}
@@ -222,6 +214,16 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
setIntrospectionClass(object.getClass());
}
/**
* Set the security context used during the invocation of the wrapped instance methods.
* Can be null.
*
* @param acc
*/
public void setSecurityContext(AccessControlContext acc) {
this.acc = acc;
}
public final Object getWrappedInstance() {
return this.object;
}
@@ -254,54 +256,22 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
}
/**
* 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.
* 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.
*/
public void setAutoGrowNestedPaths(boolean autoGrowNestedPaths) {
this.autoGrowNestedPaths = autoGrowNestedPaths;
}
/**
* Return whether "auto-growing" of nested paths has been activated.
* If this BeanWrapper should "auto grow" nested paths.
*/
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.
*/
public void setSecurityContext(AccessControlContext acc) {
this.acc = acc;
}
/**
* Return the security context used during the invocation of the wrapped instance methods.
* Can be null.
*/
public AccessControlContext getSecurityContext() {
return this.acc;
}
/**
* Set the class to introspect.
* Needs to be called when the target object changes.
@@ -383,15 +353,13 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
public TypeDescriptor getPropertyTypeDescriptor(String propertyName) throws BeansException {
try {
String actualPropertyName = PropertyAccessorUtils.getPropertyName(propertyName);
PropertyDescriptor pd = getPropertyDescriptorInternal(actualPropertyName);
PropertyDescriptor pd = getPropertyDescriptorInternal(propertyName);
if (pd != null) {
Class type = getPropertyType(propertyName);
if (pd.getReadMethod() != null) {
return new PropertyTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), type);
return new BeanTypeDescriptor(new MethodParameter(pd.getReadMethod(), -1), pd);
}
else if (pd.getWriteMethod() != null) {
return new PropertyTypeDescriptor(pd, BeanUtils.getWriteMethodParameter(pd), type);
return new BeanTypeDescriptor(BeanUtils.getWriteMethodParameter(pd), pd);
}
}
}
@@ -441,56 +409,17 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
return false;
}
public <T> T convertIfNecessary(Object value, Class<T> requiredType, MethodParameter methodParam)
throws TypeMismatchException {
public <T> T convertIfNecessary(
Object value, Class<T> requiredType, MethodParameter methodParam) throws TypeMismatchException {
try {
return this.typeConverterDelegate.convertIfNecessary(value, requiredType, methodParam);
}
catch (ConverterNotFoundException ex) {
throw new ConversionNotSupportedException(value, requiredType, ex);
}
catch (ConversionException ex) {
catch (IllegalArgumentException ex) {
throw new TypeMismatchException(value, requiredType, ex);
}
catch (IllegalStateException ex) {
throw new ConversionNotSupportedException(value, requiredType, ex);
}
catch (IllegalArgumentException ex) {
throw new TypeMismatchException(value, requiredType, ex);
}
}
private Object convertIfNecessary(String propertyName, Object oldValue, Object newValue, Class<?> requiredType,
TypeDescriptor td) throws TypeMismatchException {
try {
return this.typeConverterDelegate.convertIfNecessary(propertyName, oldValue, newValue, requiredType, td);
}
catch (ConverterNotFoundException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
throw new ConversionNotSupportedException(pce, td.getType(), ex);
}
catch (ConversionException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
throw new TypeMismatchException(pce, requiredType, ex);
}
catch (IllegalStateException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
throw new ConversionNotSupportedException(pce, requiredType, ex);
}
catch (IllegalArgumentException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
throw new TypeMismatchException(pce, requiredType, ex);
}
}
private Object convertIfNecessary(String propertyName, Object oldValue, Object newValue, Class<?> requiredType)
throws TypeMismatchException {
return convertIfNecessary(propertyName, oldValue, newValue, requiredType, TypeDescriptor.valueOf(requiredType));
}
/**
@@ -509,14 +438,19 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"No property '" + propertyName + "' found");
}
return convertForProperty(propertyName, null, value, pd);
}
private Object convertForProperty(String propertyName, Object oldValue, Object newValue, PropertyDescriptor pd)
throws TypeMismatchException {
return convertIfNecessary(propertyName, oldValue, newValue, pd.getPropertyType(),
new PropertyTypeDescriptor(pd, BeanUtils.getWriteMethodParameter(pd)));
try {
return this.typeConverterDelegate.convertIfNecessary(null, value, pd);
}
catch (IllegalArgumentException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, null, value);
throw new TypeMismatchException(pce, pd.getPropertyType(), ex);
}
catch (IllegalStateException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, null, value);
throw new ConversionNotSupportedException(pce, pd.getPropertyType(), ex);
}
}
@@ -605,25 +539,21 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
PropertyTokenHolder tokens = new PropertyTokenHolder();
tokens.actualName = propertyName;
tokens.canonicalName = propertyName;
return setDefaultValue(tokens);
}
private Object setDefaultValue(PropertyTokenHolder tokens) {
PropertyValue pv = createDefaultPropertyValue(tokens);
setPropertyValue(tokens, pv);
setPropertyValue(tokens, createDefaultPropertyValue(tokens));
return getPropertyValue(tokens);
}
private Object setDefaultValue(PropertyTokenHolder tokens) {
setPropertyValue(tokens, createDefaultPropertyValue(tokens));
return getPropertyValue(tokens);
}
private PropertyValue createDefaultPropertyValue(PropertyTokenHolder tokens) {
Class type = getPropertyType(tokens.canonicalName);
if (type == null) {
throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + tokens.canonicalName,
"Could not determine property type for auto-growing a default value");
}
Object defaultValue = newValue(type, tokens.canonicalName);
PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(tokens.actualName);
Object defaultValue = newValue(pd.getPropertyType(), tokens.canonicalName);
return new PropertyValue(tokens.canonicalName, defaultValue);
}
private Object newValue(Class<?> type, String name) {
try {
if (type.isArray()) {
@@ -638,22 +568,20 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
return Array.newInstance(componentType, 0);
}
}
else if (Collection.class.isAssignableFrom(type)) {
return CollectionFactory.createCollection(type, 16);
}
else if (Map.class.isAssignableFrom(type)) {
return CollectionFactory.createMap(type, 16);
}
else {
return type.newInstance();
if (Collection.class.isAssignableFrom(type)) {
return CollectionFactory.createCollection(type, 16);
}
else {
return type.newInstance();
}
}
}
catch (Exception ex) {
throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + name,
"Could not instantiate property type [" + type.getName() + "] to auto-grow nested property path: " + ex);
throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + name, "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.
@@ -742,6 +670,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
}
Object value;
if (System.getSecurityManager() != null) {
try {
value = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@@ -755,7 +684,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
}
}
else {
value = readMethod.invoke(object, (Object[]) null);
value = readMethod.invoke(object, (Object[]) null);
}
if (tokens.keys != null) {
@@ -812,8 +741,9 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
Class<?> mapKeyType = GenericCollectionTypeResolver.getMapKeyReturnType(pd.getReadMethod(), i + 1);
// IMPORTANT: Do not pass full property name in here - property editors
// must not kick in for map keys but rather only for map values.
Object convertedMapKey = convertIfNecessary(null, null, key, mapKeyType,
new PropertyTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), mapKeyType));
Object convertedMapKey = this.typeConverterDelegate.convertIfNecessary(key, mapKeyType);
// Pass full property name and old value in here, since we want full
// conversion ability for map values.
value = map.get(convertedMapKey);
}
else {
@@ -826,6 +756,15 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
}
return value;
}
catch (InvocationTargetException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Getter for property '" + actualName + "' threw exception", ex);
}
catch(IllegalAccessException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Illegal attempt to get property '" + actualName + "' threw exception", ex);
}
catch (IndexOutOfBoundsException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Index of out of bounds in property path '" + propertyName + "'", ex);
@@ -834,17 +773,9 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Invalid index in property path '" + propertyName + "'", ex);
}
catch (TypeMismatchException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Invalid index in property path '" + propertyName + "'", ex);
}
catch (InvocationTargetException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Getter for property '" + actualName + "' threw exception", ex);
}
catch (Exception ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Illegal attempt to get property '" + actualName + "' threw exception", ex);
"Invalid index in property path '" + propertyName + "'", ex);
}
}
@@ -853,31 +784,25 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
return array;
}
int length = Array.getLength(array);
if (index >= length && index < this.autoGrowCollectionLimit) {
if (index >= length) {
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 getPropertyValue(name);
}
else {
return newArray;
} else {
return array;
}
}
@SuppressWarnings("unchecked")
private void growCollectionIfNecessary(
Collection collection, int index, String name, PropertyDescriptor pd, int nestingLevel) {
private void growCollectionIfNecessary(Collection collection, int index, String name, PropertyDescriptor pd, int nestingLevel) {
if (!this.autoGrowNestedPaths) {
return;
}
int size = collection.size();
if (index >= size && index < this.autoGrowCollectionLimit) {
if (index >= collection.size()) {
Class elementType = GenericCollectionTypeResolver.getCollectionReturnType(pd.getReadMethod(), nestingLevel);
if (elementType != null) {
for (int i = collection.size(); i < index + 1; i++) {
@@ -886,7 +811,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
}
}
}
@Override
public void setPropertyValue(String propertyName, Object value) throws BeansException {
BeanWrapperImpl nestedBw;
@@ -953,18 +878,27 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
"Cannot access indexed value in property referenced " +
"in indexed property path '" + propertyName + "': returned null");
}
if (propValue.getClass().isArray()) {
PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);
else if (propValue.getClass().isArray()) {
Class requiredType = propValue.getClass().getComponentType();
int arrayIndex = Integer.parseInt(key);
Object oldValue = null;
try {
if (isExtractOldValueForEditor() && arrayIndex < Array.getLength(propValue)) {
if (isExtractOldValueForEditor()) {
oldValue = Array.get(propValue, arrayIndex);
}
Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(), requiredType,
new PropertyTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), requiredType));
Array.set(propValue, arrayIndex, convertedValue);
Object convertedValue = this.typeConverterDelegate.convertIfNecessary(
propertyName, oldValue, pv.getValue(), requiredType);
Array.set(propValue, Integer.parseInt(key), convertedValue);
}
catch (IllegalArgumentException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
throw new TypeMismatchException(pce, requiredType, ex);
}
catch (IllegalStateException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
throw new ConversionNotSupportedException(pce, requiredType, ex);
}
catch (IndexOutOfBoundsException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
@@ -981,32 +915,32 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
if (isExtractOldValueForEditor() && index < list.size()) {
oldValue = list.get(index);
}
Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(), requiredType,
new PropertyTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), requiredType));
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 " +
size + ", accessed using property path '" + propertyName +
"': List does not support filling up gaps with null elements");
}
}
list.add(convertedValue);
}
else {
try {
try {
Object convertedValue = this.typeConverterDelegate.convertIfNecessary(
propertyName, oldValue, pv.getValue(), requiredType);
if (index < list.size()) {
list.set(index, convertedValue);
}
catch (IndexOutOfBoundsException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Invalid list index in property path '" + propertyName + "'", ex);
else if (index >= list.size()) {
for (int i = list.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 +
"': List does not support filling up gaps with null elements");
}
}
list.add(convertedValue);
}
}
catch (IllegalArgumentException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
throw new TypeMismatchException(pce, requiredType, ex);
}
}
else if (propValue instanceof Map) {
PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);
@@ -1015,19 +949,34 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
Class mapValueType = GenericCollectionTypeResolver.getMapValueReturnType(
pd.getReadMethod(), tokens.keys.length);
Map map = (Map) propValue;
// IMPORTANT: Do not pass full property name in here - property editors
// must not kick in for map keys but rather only for map values.
Object convertedMapKey = convertIfNecessary(null, null, key, mapKeyType,
new PropertyTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), mapKeyType));
Object convertedMapKey;
Object convertedMapValue;
try {
// IMPORTANT: Do not pass full property name in here - property editors
// must not kick in for map keys but rather only for map values.
convertedMapKey = this.typeConverterDelegate.convertIfNecessary(key, mapKeyType);
}
catch (IllegalArgumentException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, null, pv.getValue());
throw new TypeMismatchException(pce, mapKeyType, ex);
}
Object oldValue = null;
if (isExtractOldValueForEditor()) {
oldValue = map.get(convertedMapKey);
}
// Pass full property name and old value in here, since we want full
// conversion ability for map values.
Object convertedMapValue = convertIfNecessary(
propertyName, oldValue, pv.getValue(), mapValueType,
new TypeDescriptor(new MethodParameter(pd.getReadMethod(), -1, tokens.keys.length + 1)));
try {
// Pass full property name and old value in here, since we want full
// conversion ability for map values.
convertedMapValue = this.typeConverterDelegate.convertIfNecessary(
propertyName, oldValue, pv.getValue(), mapValueType, null,
new MethodParameter(pd.getReadMethod(), -1, tokens.keys.length + 1));
}
catch (IllegalArgumentException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
throw new TypeMismatchException(pce, mapValueType, ex);
}
map.put(convertedMapKey, convertedMapValue);
}
else {
@@ -1068,8 +1017,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
else {
if (isExtractOldValueForEditor() && pd.getReadMethod() != null) {
final Method readMethod = pd.getReadMethod();
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers()) &&
!readMethod.isAccessible()) {
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers()) && !readMethod.isAccessible()) {
if (System.getSecurityManager()!= null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
@@ -1088,7 +1036,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
public Object run() throws Exception {
return readMethod.invoke(object);
}
}, acc);
},acc);
}
else {
oldValue = readMethod.invoke(object);
@@ -1104,13 +1052,11 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
}
}
}
valueToApply = convertForProperty(propertyName, oldValue, originalValue, pd);
valueToApply = this.typeConverterDelegate.convertIfNecessary(oldValue, originalValue, pd);
}
pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
}
final Method writeMethod = (pd instanceof GenericTypeAwarePropertyDescriptor ?
((GenericTypeAwarePropertyDescriptor) pd).getWriteMethodForActualAccess() :
pd.getWriteMethod());
final Method writeMethod = pd.getWriteMethod();
if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers()) && !writeMethod.isAccessible()) {
if (System.getSecurityManager()!= null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@@ -1125,6 +1071,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
}
}
final Object value = valueToApply;
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@@ -1133,17 +1080,14 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
return null;
}
}, acc);
}
catch (PrivilegedActionException ex) {
} catch (PrivilegedActionException ex) {
throw ex.getException();
}
}
else {
writeMethod.invoke(this.object, value);
writeMethod.invoke(object, value);
}
}
catch (TypeMismatchException ex) {
throw ex;
}
catch (InvocationTargetException ex) {
PropertyChangeEvent propertyChangeEvent =
@@ -1155,9 +1099,29 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
throw new MethodInvocationException(propertyChangeEvent, ex.getTargetException());
}
}
catch (Exception ex) {
catch (ConversionException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
throw new TypeMismatchException(pce, pd.getPropertyType(), ex);
}
catch (IllegalArgumentException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
throw new TypeMismatchException(pce, pd.getPropertyType(), ex);
}
catch (IllegalStateException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
throw new ConversionNotSupportedException(pce, pd.getPropertyType(), ex);
}
catch (IllegalAccessException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
throw new MethodInvocationException(pce, ex);
}
catch (Exception ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
throw new MethodInvocationException(pce, ex);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,18 +23,18 @@ import java.beans.PropertyDescriptor;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.Collection;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
* Internal class that caches JavaBeans {@link java.beans.PropertyDescriptor}
@@ -130,7 +130,7 @@ public class CachedIntrospectionResults {
* @throws BeansException in case of introspection failure
*/
static CachedIntrospectionResults forClass(Class beanClass) throws BeansException {
CachedIntrospectionResults results;
CachedIntrospectionResults results = null;
Object value = classCache.get(beanClass);
if (value instanceof Reference) {
Reference ref = (Reference) value;
@@ -140,20 +140,19 @@ public class CachedIntrospectionResults {
results = (CachedIntrospectionResults) value;
}
if (results == null) {
// can throw BeansException
results = new CachedIntrospectionResults(beanClass);
// On JDK 1.5 and higher, it is almost always safe to cache the bean class...
// The sole exception is a custom BeanInfo class being provided in a non-safe ClassLoader.
boolean fullyCacheable =
ClassUtils.isCacheSafe(beanClass, CachedIntrospectionResults.class.getClassLoader()) ||
isClassLoaderAccepted(beanClass.getClassLoader());
if (fullyCacheable || !ClassUtils.isPresent(beanClass.getName() + "BeanInfo", beanClass.getClassLoader())) {
results = new CachedIntrospectionResults(beanClass, fullyCacheable);
if (ClassUtils.isCacheSafe(beanClass, CachedIntrospectionResults.class.getClassLoader()) ||
isClassLoaderAccepted(beanClass.getClassLoader()) ||
!ClassUtils.isPresent(beanClass.getName() + "BeanInfo", beanClass.getClassLoader())) {
classCache.put(beanClass, results);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Not strongly caching class [" + beanClass.getName() + "] because it is not cache-safe");
}
results = new CachedIntrospectionResults(beanClass, true);
classCache.put(beanClass, new WeakReference<CachedIntrospectionResults>(results));
}
}
@@ -216,7 +215,7 @@ public class CachedIntrospectionResults {
* @param beanClass the bean class to analyze
* @throws BeansException in case of introspection failure
*/
private CachedIntrospectionResults(Class beanClass, boolean cacheFullMetadata) throws BeansException {
private CachedIntrospectionResults(Class beanClass) throws BeansException {
try {
if (logger.isTraceEnabled()) {
logger.trace("Getting BeanInfo for class [" + beanClass.getName() + "]");
@@ -237,29 +236,24 @@ public class CachedIntrospectionResults {
if (logger.isTraceEnabled()) {
logger.trace("Caching PropertyDescriptors for class [" + beanClass.getName() + "]");
}
this.propertyDescriptorCache = new LinkedHashMap<String, PropertyDescriptor>();
this.propertyDescriptorCache = new HashMap<String, PropertyDescriptor>();
// This call is slow so we do it once.
PropertyDescriptor[] pds = this.beanInfo.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
if (Class.class.equals(beanClass) && "classLoader".equals(pd.getName())) {
// Ignore Class.getClassLoader() method - nobody needs to bind to that
continue;
}
if (logger.isTraceEnabled()) {
logger.trace("Found bean property '" + pd.getName() + "'" +
(pd.getPropertyType() != null ? " of type [" + pd.getPropertyType().getName() + "]" : "") +
(pd.getPropertyEditorClass() != null ?
"; editor [" + pd.getPropertyEditorClass().getName() + "]" : ""));
}
if (cacheFullMetadata) {
pd = buildGenericTypeAwarePropertyDescriptor(beanClass, pd);
}
pd = new GenericTypeAwarePropertyDescriptor(beanClass, pd.getName(), pd.getReadMethod(),
pd.getWriteMethod(), pd.getPropertyEditorClass());
this.propertyDescriptorCache.put(pd.getName(), pd);
}
}
catch (IntrospectionException ex) {
throw new FatalBeanException("Failed to obtain BeanInfo for class [" + beanClass.getName() + "]", ex);
throw new FatalBeanException("Cannot get BeanInfo for object of class [" + beanClass.getName() + "]", ex);
}
}
@@ -271,38 +265,13 @@ public class CachedIntrospectionResults {
return this.beanInfo.getBeanDescriptor().getBeanClass();
}
PropertyDescriptor getPropertyDescriptor(String name) {
PropertyDescriptor pd = this.propertyDescriptorCache.get(name);
if (pd == null && StringUtils.hasLength(name)) {
// Same lenient fallback checking as in PropertyTypeDescriptor...
pd = this.propertyDescriptorCache.get(name.substring(0, 1).toLowerCase() + name.substring(1));
if (pd == null) {
pd = this.propertyDescriptorCache.get(name.substring(0, 1).toUpperCase() + name.substring(1));
}
}
return (pd == null || pd instanceof GenericTypeAwarePropertyDescriptor ? pd :
buildGenericTypeAwarePropertyDescriptor(getBeanClass(), pd));
PropertyDescriptor getPropertyDescriptor(String propertyName) {
return this.propertyDescriptorCache.get(propertyName);
}
PropertyDescriptor[] getPropertyDescriptors() {
PropertyDescriptor[] pds = new PropertyDescriptor[this.propertyDescriptorCache.size()];
int i = 0;
for (PropertyDescriptor pd : this.propertyDescriptorCache.values()) {
pds[i] = (pd instanceof GenericTypeAwarePropertyDescriptor ? pd :
buildGenericTypeAwarePropertyDescriptor(getBeanClass(), pd));
i++;
}
return pds;
}
private PropertyDescriptor buildGenericTypeAwarePropertyDescriptor(Class beanClass, PropertyDescriptor pd) {
try {
return new GenericTypeAwarePropertyDescriptor(beanClass, pd.getName(), pd.getReadMethod(),
pd.getWriteMethod(), pd.getPropertyEditorClass());
}
catch (IntrospectionException ex) {
throw new FatalBeanException("Failed to re-introspect class [" + beanClass.getName() + "]", ex);
}
Collection<PropertyDescriptor> descriptorCollection = this.propertyDescriptorCache.values();
return descriptorCollection.toArray(new PropertyDescriptor[descriptorCollection.size()]);
}
}
@@ -19,32 +19,26 @@ package org.springframework.beans;
import java.beans.PropertyChangeEvent;
/**
* Exception thrown when no suitable editor or converter can be found for a bean property.
* Exception thrown when no suitable editor can be found to set a bean property.
*
* @author Arjen Poutsma
* @author Juergen Hoeller
* @since 3.0
*/
public class ConversionNotSupportedException extends TypeMismatchException {
/**
* Create a new ConversionNotSupportedException.
* @param propertyChangeEvent the PropertyChangeEvent that resulted in the problem
* @param requiredType the required target type (or <code>null</code> if not known)
* @param cause the root cause (may be <code>null</code>)
*/
public ConversionNotSupportedException(PropertyChangeEvent propertyChangeEvent, Class requiredType) {
super(propertyChangeEvent, requiredType);
}
public ConversionNotSupportedException(PropertyChangeEvent propertyChangeEvent, Class requiredType, Throwable cause) {
super(propertyChangeEvent, requiredType, cause);
}
/**
* Create a new ConversionNotSupportedException.
* @param value the offending value that couldn't be converted (may be <code>null</code>)
* @param requiredType the required target type (or <code>null</code> if not known)
* @param cause the root cause (may be <code>null</code>)
*/
public ConversionNotSupportedException(Object value, Class requiredType) {
super(value, requiredType);
}
public ConversionNotSupportedException(Object value, Class requiredType, Throwable cause) {
super(value, requiredType, cause);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2009 the original author 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,8 +22,6 @@ import java.util.HashMap;
import java.util.Map;
import org.springframework.core.MethodParameter;
import org.springframework.core.convert.ConversionException;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
@@ -124,15 +122,14 @@ public class DirectFieldAccessor extends AbstractPropertyAccessor {
try {
ReflectionUtils.makeAccessible(field);
oldValue = field.get(this.target);
Object convertedValue = this.typeConverterDelegate.convertIfNecessary(
field.getName(), oldValue, newValue, field.getType(), new TypeDescriptor(field));
Object convertedValue =
this.typeConverterDelegate.convertIfNecessary(propertyName, oldValue, newValue, field.getType());
field.set(this.target, convertedValue);
}
catch (ConverterNotFoundException ex) {
PropertyChangeEvent pce = new PropertyChangeEvent(this.target, propertyName, oldValue, newValue);
throw new ConversionNotSupportedException(pce, field.getType(), ex);
catch (IllegalAccessException ex) {
throw new InvalidPropertyException(this.target.getClass(), propertyName, "Field is not accessible", ex);
}
catch (ConversionException ex) {
catch (IllegalArgumentException ex) {
PropertyChangeEvent pce = new PropertyChangeEvent(this.target, propertyName, oldValue, newValue);
throw new TypeMismatchException(pce, field.getType(), ex);
}
@@ -140,17 +137,10 @@ public class DirectFieldAccessor extends AbstractPropertyAccessor {
PropertyChangeEvent pce = new PropertyChangeEvent(this.target, propertyName, oldValue, newValue);
throw new ConversionNotSupportedException(pce, field.getType(), ex);
}
catch (IllegalArgumentException ex) {
PropertyChangeEvent pce = new PropertyChangeEvent(this.target, propertyName, oldValue, newValue);
throw new TypeMismatchException(pce, field.getType(), ex);
}
catch (IllegalAccessException ex) {
throw new InvalidPropertyException(this.target.getClass(), propertyName, "Field is not accessible", ex);
}
}
public <T> T convertIfNecessary(
Object value, Class<T> requiredType, MethodParameter methodParam) throws TypeMismatchException {
public Object convertIfNecessary(
Object value, Class requiredType, MethodParameter methodParam) throws TypeMismatchException {
try {
return this.typeConverterDelegate.convertIfNecessary(value, requiredType, methodParam);
}
@@ -100,10 +100,6 @@ class GenericTypeAwarePropertyDescriptor extends PropertyDescriptor {
@Override
public Method getWriteMethod() {
return this.writeMethod;
}
public Method getWriteMethodForActualAccess() {
Set<Method> ambiguousCandidates = this.ambiguousWriteMethods;
if (ambiguousCandidates != null) {
this.ambiguousWriteMethods = null;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,6 +37,7 @@ import org.springframework.util.StringUtils;
*/
public class MutablePropertyValues implements PropertyValues, Serializable {
/** List of PropertyValue objects */
private final List<PropertyValue> propertyValueList;
private Set<String> processedProperties;
@@ -46,11 +47,12 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
/**
* Creates a new empty MutablePropertyValues object.
* <p>Property values can be added with the <code>add</code> method.
* @see #add(String, Object)
* Property values can be added with the <code>addPropertyValue</code> methods.
* @see #addPropertyValue(PropertyValue)
* @see #addPropertyValue(String, Object)
*/
public MutablePropertyValues() {
this.propertyValueList = new ArrayList<PropertyValue>(0);
this.propertyValueList = new ArrayList<PropertyValue>();
}
/**
@@ -117,19 +119,13 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
return this.propertyValueList;
}
/**
* Return the number of PropertyValue entries in the list.
*/
public int size() {
return this.propertyValueList.size();
}
/**
* Copy all given PropertyValues into this object. Guarantees PropertyValue
* references are independent, although it can't deep copy objects currently
* referenced by individual PropertyValue objects.
* @param other the PropertyValues to copy
* @return this in order to allow for adding multiple property values in a chain
* @return this object to allow creating objects, adding multiple PropertyValues
* in a single statement
*/
public MutablePropertyValues addPropertyValues(PropertyValues other) {
if (other != null) {
@@ -145,7 +141,8 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
* Add all property values from the given Map.
* @param other Map with property values keyed by property name,
* which must be a String
* @return this in order to allow for adding multiple property values in a chain
* @return this object to allow creating objects, adding multiple
* PropertyValues in a single statement
*/
public MutablePropertyValues addPropertyValues(Map<?, ?> other) {
if (other != null) {
@@ -157,10 +154,11 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
}
/**
* Add a PropertyValue object, replacing any existing one for the
* corresponding property or getting merged with it (if applicable).
* Add a PropertyValue object, replacing any existing one
* for the corresponding property.
* @param pv PropertyValue object to add
* @return this in order to allow for adding multiple property values in a chain
* @return this object to allow creating objects, adding multiple
* PropertyValues in a single statement
*/
public MutablePropertyValues addPropertyValue(PropertyValue pv) {
for (int i = 0; i < this.propertyValueList.size(); i++) {
@@ -178,8 +176,6 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
/**
* Overloaded version of <code>addPropertyValue</code> that takes
* a property name and a property value.
* <p>Note: As of Spring 3.0, we recommend using the more concise
* and chaining-capable variant {@link #add}.
* @param propertyName name of the property
* @param propertyValue value of the property
* @see #addPropertyValue(PropertyValue)
@@ -188,18 +184,6 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
addPropertyValue(new PropertyValue(propertyName, propertyValue));
}
/**
* Add a PropertyValue object, replacing any existing one for the
* corresponding property or getting merged with it (if applicable).
* @param propertyName name of the property
* @param propertyValue value of the property
* @return this in order to allow for adding multiple property values in a chain
*/
public MutablePropertyValues add(String propertyName, Object propertyValue) {
addPropertyValue(new PropertyValue(propertyName, propertyValue));
return this;
}
/**
* Modify a PropertyValue object held in this object.
* Indexed from 0.
@@ -225,6 +209,15 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
return newPv;
}
/**
* Overloaded version of <code>removePropertyValue</code> that takes a property name.
* @param propertyName name of the property
* @see #removePropertyValue(PropertyValue)
*/
public void removePropertyValue(String propertyName) {
removePropertyValue(getPropertyValue(propertyName));
}
/**
* Remove the given PropertyValue, if contained.
* @param pv the PropertyValue to remove
@@ -234,12 +227,10 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
}
/**
* Overloaded version of <code>removePropertyValue</code> that takes a property name.
* @param propertyName name of the property
* @see #removePropertyValue(PropertyValue)
* Clear this holder, removing all PropertyValues.
*/
public void removePropertyValue(String propertyName) {
this.propertyValueList.remove(getPropertyValue(propertyName));
public void clear() {
this.propertyValueList.clear();
}
@@ -256,6 +247,34 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
return null;
}
/**
* Register the specified property as "processed" in the sense
* of some processor calling the corresponding setter method
* outside of the PropertyValue(s) mechanism.
* <p>This will lead to <code>true</code> being returned from
* a {@link #contains} call for the specified property.
* @param propertyName the name of the property.
*/
public void registerProcessedProperty(String propertyName) {
if (this.processedProperties == null) {
this.processedProperties = new HashSet<String>();
}
this.processedProperties.add(propertyName);
}
public boolean contains(String propertyName) {
return (getPropertyValue(propertyName) != null ||
(this.processedProperties != null && this.processedProperties.contains(propertyName)));
}
public boolean isEmpty() {
return this.propertyValueList.isEmpty();
}
public int size() {
return this.propertyValueList.size();
}
public PropertyValues changesSince(PropertyValues old) {
MutablePropertyValues changes = new MutablePropertyValues();
if (old == this) {
@@ -277,30 +296,6 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
return changes;
}
public boolean contains(String propertyName) {
return (getPropertyValue(propertyName) != null ||
(this.processedProperties != null && this.processedProperties.contains(propertyName)));
}
public boolean isEmpty() {
return this.propertyValueList.isEmpty();
}
/**
* Register the specified property as "processed" in the sense
* of some processor calling the corresponding setter method
* outside of the PropertyValue(s) mechanism.
* <p>This will lead to <code>true</code> being returned from
* a {@link #contains} call for the specified property.
* @param propertyName the name of the property.
*/
public void registerProcessedProperty(String propertyName) {
if (this.processedProperties == null) {
this.processedProperties = new HashSet<String>();
}
this.processedProperties.add(propertyName);
}
/**
* Mark this holder as containing converted values only
@@ -339,10 +334,8 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
@Override
public String toString() {
PropertyValue[] pvs = getPropertyValues();
StringBuilder sb = new StringBuilder("PropertyValues: length=").append(pvs.length);
if (pvs.length > 0) {
sb.append("; ").append(StringUtils.arrayToDelimitedString(pvs, "; "));
}
StringBuilder sb = new StringBuilder("PropertyValues: length=" + pvs.length + "; ");
sb.append(StringUtils.arrayToDelimitedString(pvs, "; "));
return sb.toString();
}
@@ -148,7 +148,7 @@ public interface PropertyAccessor {
* all individual PropertyAccessExceptions. All other properties will have been
* successfully updated.
*/
void setPropertyValues(Map<?, ?> map) throws BeansException;
void setPropertyValues(Map map) throws BeansException;
/**
* The preferred way to perform a batch update.

Some files were not shown because too many files have changed in this diff Show More