mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
194 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cda4ed26f1 | |||
| 386b7507c6 | |||
| 8a1a23af83 | |||
| 580dc8e72a | |||
| 66d2c6698b | |||
| 7f90e3bcf7 | |||
| bc1abe6070 | |||
| 6aa0e62597 | |||
| 52179d8bfb | |||
| ee686188b7 | |||
| 4a98fcb3f7 | |||
| 29ab58c4d8 | |||
| f6d05eaad4 | |||
| 5105793228 | |||
| 689e7b7af2 | |||
| 636e2f0f4c | |||
| 461b488eee | |||
| 6b93f41f3a | |||
| 092241a632 | |||
| 20f4e9023b | |||
| c24bafd644 | |||
| 21b4526063 | |||
| b2ff0b1df0 | |||
| 87d0da2d4c | |||
| ad78b5cdb5 | |||
| de84703c02 | |||
| b67b5ec408 | |||
| 65e88449aa | |||
| 20de98362a | |||
| ea7ff5241d | |||
| ae877e92c7 | |||
| 16305530f2 | |||
| 282de41f06 | |||
| 16eb915c95 | |||
| 0eabef0720 | |||
| 2c9753ad25 | |||
| 81e81ce77c | |||
| 9cecaa769e | |||
| 8c8eca7e05 | |||
| fba8bcc7dc | |||
| fa719ad4c5 | |||
| 63dc53a5ea | |||
| bc7679f9fc | |||
| a6d5d7c8e2 | |||
| 122e4346bb | |||
| c18137d40a | |||
| a827ab88b1 | |||
| 351e72b6e2 | |||
| cbed1c1b4b | |||
| 124837e2c3 | |||
| 753a54096f | |||
| d50881d82b | |||
| f836601e0f | |||
| fbda55f141 | |||
| 10c358718e | |||
| 6f2062fb3a | |||
| f42d4241b4 | |||
| 3576bc4585 | |||
| 47389a0edd | |||
| ab139dffd0 | |||
| a5f3d00977 | |||
| 53b6e1c1b0 | |||
| 65b0a8fcb2 | |||
| 461c200ce6 | |||
| a614430899 | |||
| bc2440ea16 | |||
| 6fb49f1de7 | |||
| 6118d67321 | |||
| cbca6e1acb | |||
| 2c2cf32b8a | |||
| 89755542da | |||
| 051b5f4f4f | |||
| b370969690 | |||
| a1f6eabbce | |||
| 247c46e6ea | |||
| 915ca47cad | |||
| 0d8a020684 | |||
| 1e388a894e | |||
| 4e7752c9ba | |||
| c13e5f9f5b | |||
| 706a09c49e | |||
| c38c09bc35 | |||
| 77bb68b967 | |||
| 212daa1995 | |||
| f7ac7a395c | |||
| 465e84eda4 | |||
| ec577f8e24 | |||
| 26470cc23a | |||
| 296aa96d71 | |||
| a2c3274b8e | |||
| 5e19f2959e | |||
| 5dc59aaa7b | |||
| c9289a4dcf | |||
| 19b4618fb5 | |||
| 4c0744ee54 | |||
| b07d02f1bf | |||
| 69cbadf7e9 | |||
| 0543036ec9 | |||
| 2ff2f0205d | |||
| e22431188b | |||
| b8c0e153e3 | |||
| ff09482653 | |||
| d932c043da | |||
| 0cb7e4dcb3 | |||
| 2e5f1c22f6 | |||
| cf93e7c69e | |||
| 9da980d325 | |||
| 7da13e7ad1 | |||
| a0e40a5610 | |||
| ac5c75690a | |||
| 795a5e02cd | |||
| bb75662a7e | |||
| 23cb161fb3 | |||
| eb1c039a6e | |||
| 4c39f90466 | |||
| d4de1ac346 | |||
| 4880d1d461 | |||
| 5a8aa53232 | |||
| 85b8befbd1 | |||
| 4c4f19ec94 | |||
| 145dcfd0c2 | |||
| 991c982e5b | |||
| 1d6f374970 | |||
| eee72c52da | |||
| b0e3081636 | |||
| 886eb665bf | |||
| 70ee2ee7b1 | |||
| f3f535623f | |||
| 63076d0865 | |||
| fc0a6ce40c | |||
| 88773ae7f1 | |||
| 81b10be1d0 | |||
| 50c5593740 | |||
| af4b22e5b9 | |||
| 6e55c8cd2f | |||
| def90d1016 | |||
| f30b0a86f7 | |||
| 95ad7168bf | |||
| ccb312a974 | |||
| f588ab05fa | |||
| 2dd1134303 | |||
| 0efb9d8023 | |||
| 21fd150894 | |||
| ac9a625ccc | |||
| c31213e5cb | |||
| f82cc6458b | |||
| 8d7df01d73 | |||
| 5303ab68aa | |||
| c91ff130d5 | |||
| 54d0346084 | |||
| 4f926c82bf | |||
| b07b146965 | |||
| cfbc5224e3 | |||
| a0c41a0e03 | |||
| 8fe5151f84 | |||
| 77f8b070cd | |||
| 4f4f3fab7d | |||
| 0444ab236a | |||
| 9ede9fe697 | |||
| 3e98b26b77 | |||
| 0aee6e9f5b | |||
| eddc5b8898 | |||
| 57993d871e | |||
| 3c8a47bd06 | |||
| 7f8c91a52d | |||
| 62f9f477f5 | |||
| 894875ce8d | |||
| 9d1c3fa9ac | |||
| d207c2294d | |||
| e653a9cd03 | |||
| 5675046cb7 | |||
| 20a8039642 | |||
| 4bda92fd8a | |||
| 97adfdd398 | |||
| a5b5df450e | |||
| 80b8fb8b83 | |||
| ef227c5d01 | |||
| 9e5b129ba5 | |||
| 12b30843c5 | |||
| 09f02bc620 | |||
| 3d2611484a | |||
| 6af91773ee | |||
| 9e71af86f8 | |||
| 60ff93e5ac | |||
| f25d2a9416 | |||
| fd4b9cf6a3 | |||
| 1a351db6e0 | |||
| 5b537e9604 | |||
| 6c69f47acf | |||
| 44ef114981 | |||
| 67b342d923 | |||
| 5063c6dd00 | |||
| 8d0bb00188 | |||
| fe59d4a787 |
@@ -0,0 +1,5 @@
|
||||
target
|
||||
integration-repo
|
||||
ivy-cache
|
||||
spring-build
|
||||
jmx.log
|
||||
@@ -3,6 +3,49 @@ SPRING FRAMEWORK CHANGELOG
|
||||
http://www.springsource.org
|
||||
|
||||
|
||||
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)
|
||||
-------------------------------------
|
||||
|
||||
@@ -12,7 +55,7 @@ Changes in version 3.0.1 (2010-02-18)
|
||||
* 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 exposes offending value through public "getValue()" method
|
||||
* 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")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
SPRING FRAMEWORK 3.0.1 (February 2010)
|
||||
------------------------------------
|
||||
SPRING FRAMEWORK 3.0.2 (April 2010)
|
||||
-----------------------------------
|
||||
http://www.springframework.org
|
||||
|
||||
1. INTRODUCTION
|
||||
|
||||
+7
-1
@@ -1,4 +1,10 @@
|
||||
version=3.0.1
|
||||
version=3.0.2
|
||||
# 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=release
|
||||
build.stamp=RELEASE
|
||||
natural.name=spring-framework
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
<?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"/>
|
||||
<?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="output" path="target/classes"/>
|
||||
</classpath>
|
||||
<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>
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.1.RELEASE</version>
|
||||
<version>3.0.2.RELEASE</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.1.RELEASE</version>
|
||||
<version>3.0.2.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
+4
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* 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.
|
||||
@@ -18,6 +18,7 @@ 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;
|
||||
|
||||
@@ -139,9 +140,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
|
||||
private boolean argumentsIntrospected = false;
|
||||
|
||||
// The actual type is java.lang.reflect.Type,
|
||||
// but for JDK 1.4 compatibility we use Object as the static type.
|
||||
private Object discoveredReturningGenericType;
|
||||
private Type 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.
|
||||
|
||||
@@ -295,7 +294,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
return this.discoveredReturningType;
|
||||
}
|
||||
|
||||
protected Object getDiscoveredReturningGenericType() {
|
||||
protected Type getDiscoveredReturningGenericType() {
|
||||
return this.discoveredReturningGenericType;
|
||||
}
|
||||
|
||||
|
||||
+4
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* 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.
|
||||
@@ -69,21 +69,11 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice implement
|
||||
*/
|
||||
private boolean shouldInvokeOnReturnValueOf(Method method, Object returnValue) {
|
||||
Class type = getDiscoveredReturningType();
|
||||
Object genericType = getDiscoveredReturningGenericType();
|
||||
Type 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 || 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());
|
||||
}
|
||||
(genericType == null || genericType == type ||
|
||||
TypeUtils.isAssignable(genericType, method.getGenericReturnType())));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* 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.
|
||||
@@ -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.runtimeTest field.");
|
||||
throw new IllegalStateException("Unable to access ShadowMatchImpl.residualTest field");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,15 +83,18 @@ class RuntimeTestWalker {
|
||||
* then it tests subtype sensitive vars.
|
||||
*/
|
||||
public boolean testsSubtypeSensitiveVars() {
|
||||
return new SubtypeSensitiveVarTypeTestVisitor().testsSubtypeSensitiveVars(this.runtimeTest);
|
||||
return (this.runtimeTest != null &&
|
||||
new SubtypeSensitiveVarTypeTestVisitor().testsSubtypeSensitiveVars(this.runtimeTest));
|
||||
}
|
||||
|
||||
public boolean testThisInstanceOfResidue(Class thisClass) {
|
||||
return new ThisInstanceOfResidueTestVisitor(thisClass).thisInstanceOfMatches(this.runtimeTest);
|
||||
return (this.runtimeTest != null &&
|
||||
new ThisInstanceOfResidueTestVisitor(thisClass).thisInstanceOfMatches(this.runtimeTest));
|
||||
}
|
||||
|
||||
public boolean testTargetInstanceOfResidue(Class targetClass) {
|
||||
return new TargetInstanceOfResidueTestVisitor(targetClass).targetInstanceOfMatches(this.runtimeTest);
|
||||
return (this.runtimeTest != null &&
|
||||
new TargetInstanceOfResidueTestVisitor(targetClass).targetInstanceOfMatches(this.runtimeTest));
|
||||
}
|
||||
|
||||
|
||||
@@ -139,8 +142,7 @@ class RuntimeTestWalker {
|
||||
try {
|
||||
Field varTypeField = ReflectionVar.class.getDeclaredField("varType");
|
||||
ReflectionUtils.makeAccessible(varTypeField);
|
||||
Integer varTypeValue = (Integer) varTypeField.get(v);
|
||||
return varTypeValue.intValue();
|
||||
return (Integer) varTypeField.get(v);
|
||||
}
|
||||
catch (NoSuchFieldException noSuchFieldEx) {
|
||||
throw new IllegalStateException("the version of aspectjtools.jar / aspectjweaver.jar " +
|
||||
@@ -150,7 +152,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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
* 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.
|
||||
@@ -58,18 +58,13 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
||||
|
||||
private String aspectName;
|
||||
|
||||
private Boolean isBeforeAdvice = null;
|
||||
private Boolean isBeforeAdvice;
|
||||
|
||||
private Boolean isAfterAdvice = null;
|
||||
private Boolean isAfterAdvice;
|
||||
|
||||
|
||||
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;
|
||||
|
||||
+20
-14
@@ -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;
|
||||
@@ -63,33 +63,38 @@ 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 existingDefinition = definitionHolder.getBeanDefinition();
|
||||
BeanDefinition targetDefinition = definitionHolder.getBeanDefinition();
|
||||
BeanDefinitionHolder targetHolder = new BeanDefinitionHolder(targetDefinition, existingBeanName + ".TARGET");
|
||||
|
||||
// delegate to subclass for interceptor definition
|
||||
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(existingDefinition)) {
|
||||
if (!isProxyFactoryBeanDefinition(targetDefinition)) {
|
||||
// create the proxy definition
|
||||
RootBeanDefinition proxyDefinition = new RootBeanDefinition();
|
||||
// create proxy factory bean definition
|
||||
proxyDefinition.setBeanClass(ProxyFactoryBean.class);
|
||||
|
||||
// set up property values
|
||||
MutablePropertyValues mpvs = new MutablePropertyValues();
|
||||
proxyDefinition.setPropertyValues(mpvs);
|
||||
|
||||
proxyDefinition.setScope(targetDefinition.getScope());
|
||||
proxyDefinition.setLazyInit(targetDefinition.isLazyInit());
|
||||
// set the target
|
||||
mpvs.add("target", existingDefinition);
|
||||
|
||||
proxyDefinition.setDecoratedDefinition(targetHolder);
|
||||
proxyDefinition.getPropertyValues().add("target", targetHolder);
|
||||
// create the interceptor names list
|
||||
mpvs.add("interceptorNames", new ManagedList<String>());
|
||||
|
||||
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
|
||||
result = new BeanDefinitionHolder(proxyDefinition, existingBeanName);
|
||||
}
|
||||
|
||||
@@ -99,7 +104,8 @@ public abstract class AbstractInterceptorDrivenBeanDefinitionDecorator implement
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void addInterceptorNameToList(String interceptorName, BeanDefinition beanDefinition) {
|
||||
List<String> list = (List<String>) beanDefinition.getPropertyValues().getPropertyValue("interceptorNames").getValue();
|
||||
List<String> list = (List<String>)
|
||||
beanDefinition.getPropertyValues().getPropertyValue("interceptorNames").getValue();
|
||||
list.add(interceptorName);
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* 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.
|
||||
@@ -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 = null;
|
||||
MethodInvocation invocation;
|
||||
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 = null;
|
||||
Object retVal;
|
||||
|
||||
if (this.advised.exposeProxy) {
|
||||
// Make invocation available if necessary.
|
||||
@@ -239,7 +239,7 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
return false;
|
||||
}
|
||||
|
||||
JdkDynamicAopProxy otherProxy = null;
|
||||
JdkDynamicAopProxy otherProxy;
|
||||
if (other instanceof JdkDynamicAopProxy) {
|
||||
otherProxy = (JdkDynamicAopProxy) other;
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* 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.
|
||||
@@ -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 (beanFactory.containsBeanDefinition(beanName)) {
|
||||
if (beanName != null && beanFactory.containsBeanDefinition(beanName)) {
|
||||
BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
|
||||
return Boolean.TRUE.equals(bd.getAttribute(PRESERVE_TARGET_CLASS_ATTRIBUTE));
|
||||
}
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* 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.
|
||||
@@ -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() + ".beanName";
|
||||
private static final String BEAN_NAME_ATTRIBUTE = ExposeBeanNameAdvisors.class.getName() + ".BEAN_NAME";
|
||||
|
||||
|
||||
/**
|
||||
@@ -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, beanName);
|
||||
pmi.setUserAttribute(BEAN_NAME_ATTRIBUTE, this.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, beanName);
|
||||
pmi.setUserAttribute(BEAN_NAME_ATTRIBUTE, this.beanName);
|
||||
return super.invoke(mi);
|
||||
}
|
||||
|
||||
|
||||
+12
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* 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.
|
||||
@@ -53,28 +53,29 @@ public abstract class ScopedProxyUtils {
|
||||
|
||||
// Create a scoped proxy definition for the original bean name,
|
||||
// "hiding" the target bean in an internal target definition.
|
||||
RootBeanDefinition scopedProxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
|
||||
scopedProxyDefinition.setOriginatingBeanDefinition(definition.getBeanDefinition());
|
||||
scopedProxyDefinition.setSource(definition.getSource());
|
||||
scopedProxyDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
|
||||
proxyDefinition.setOriginatingBeanDefinition(definition.getBeanDefinition());
|
||||
proxyDefinition.setSource(definition.getSource());
|
||||
proxyDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
|
||||
String targetBeanName = getTargetBeanName(originalBeanName);
|
||||
scopedProxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);
|
||||
proxyDefinition.getPropertyValues().add("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 {
|
||||
scopedProxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
|
||||
proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
|
||||
}
|
||||
|
||||
// Copy autowire settings from original bean definition.
|
||||
proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
|
||||
proxyDefinition.setPrimary(targetDefinition.isPrimary());
|
||||
if (targetDefinition instanceof AbstractBeanDefinition) {
|
||||
scopedProxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
|
||||
proxyDefinition.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);
|
||||
@@ -84,7 +85,7 @@ public abstract class ScopedProxyUtils {
|
||||
|
||||
// Return the scoped proxy definition as primary bean definition
|
||||
// (potentially an inner bean).
|
||||
return new BeanDefinitionHolder(scopedProxyDefinition, originalBeanName, definition.getAliases());
|
||||
return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+17
-15
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* 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.
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
@@ -102,18 +102,20 @@ public abstract class AopUtils {
|
||||
* 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)
|
||||
* @return the target class (or the plain class of the given object as fallback;
|
||||
* never <code>null</code>)
|
||||
* @see org.springframework.aop.TargetClassAware#getTargetClass()
|
||||
*/
|
||||
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) {
|
||||
return ((TargetClassAware) candidate).getTargetClass();
|
||||
result = ((TargetClassAware) candidate).getTargetClass();
|
||||
}
|
||||
if (isCglibProxy(candidate)) {
|
||||
return candidate.getClass().getSuperclass();
|
||||
if (result == null) {
|
||||
result = (isCglibProxy(candidate) ? candidate.getClass().getSuperclass() : candidate.getClass());
|
||||
}
|
||||
return candidate.getClass();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,7 +167,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);
|
||||
@@ -180,7 +182,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);
|
||||
}
|
||||
|
||||
@@ -194,7 +196,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;
|
||||
}
|
||||
@@ -207,7 +209,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 &&
|
||||
@@ -229,7 +231,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);
|
||||
}
|
||||
|
||||
@@ -243,7 +245,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);
|
||||
}
|
||||
@@ -265,7 +267,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;
|
||||
}
|
||||
|
||||
+8
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* 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.
|
||||
@@ -16,15 +16,14 @@
|
||||
|
||||
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
|
||||
@@ -76,6 +75,7 @@ public final class AspectProxyFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore // InstantiationModelAwarePointcutAdvisorImpl not serializable yet
|
||||
public void testWithInstance() throws Exception {
|
||||
MultiplyReturnValue aspect = new MultiplyReturnValue();
|
||||
int multiple = 3;
|
||||
@@ -88,8 +88,10 @@ 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());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
|
||||
@@ -8,10 +8,10 @@ Import-Template:
|
||||
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="[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.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.w3c.dom.*;version="0";resolution:=optional
|
||||
Ignored-Existing-Headers:
|
||||
Bnd-LastModified,
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-asm</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.1.RELEASE</version>
|
||||
<version>3.0.2.RELEASE</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.1.RELEASE</version>
|
||||
<version>3.0.2.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aspects</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.1.RELEASE</version>
|
||||
<version>3.0.2.RELEASE</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.1.RELEASE</version>
|
||||
<version>3.0.2.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
@@ -32,22 +32,22 @@
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
<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>
|
||||
<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>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
|
||||
+1
-1
@@ -151,7 +151,7 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth
|
||||
expectations.verify();
|
||||
}
|
||||
|
||||
Object around() : methodToMock() {
|
||||
Object around() : methodToMock() && cflowbelow(mockStaticsTestMethod()) {
|
||||
if (recording) {
|
||||
expectations.expectCall(thisJoinPointStaticPart.toLongString(), thisJoinPoint.getArgs());
|
||||
// Return value doesn't matter
|
||||
|
||||
@@ -4,11 +4,11 @@ Bundle-Vendor: SpringSource
|
||||
Bundle-ManifestVersion: 2
|
||||
Import-Template:
|
||||
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
|
||||
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
|
||||
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.orm.jpa.*;version=${spring.osgi.range};resolution:=optional,
|
||||
org.springframework.dao.*;version=${spring.osgi.range};resolution:=optional
|
||||
Ignored-Existing-Headers:
|
||||
Bnd-LastModified,
|
||||
Import-Package,
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.1.RELEASE</version>
|
||||
<version>3.0.2.RELEASE</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.1.RELEASE</version>
|
||||
<version>3.0.2.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* 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.
|
||||
@@ -389,8 +389,17 @@ public abstract class BeanUtils {
|
||||
}
|
||||
ClassLoader cl = targetType.getClassLoader();
|
||||
if (cl == null) {
|
||||
cl = ClassLoader.getSystemClassLoader();
|
||||
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);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -398,8 +407,10 @@ public abstract class BeanUtils {
|
||||
try {
|
||||
Class<?> editorClass = cl.loadClass(editorName);
|
||||
if (!PropertyEditor.class.isAssignableFrom(editorClass)) {
|
||||
logger.warn("Editor class [" + editorName +
|
||||
"] does not implement [java.beans.PropertyEditor] interface");
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Editor class [" + editorName +
|
||||
"] does not implement [java.beans.PropertyEditor] interface");
|
||||
}
|
||||
unknownEditorTypes.put(targetType, Boolean.TRUE);
|
||||
return null;
|
||||
}
|
||||
|
||||
+27
-17
@@ -44,6 +44,7 @@ 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;
|
||||
@@ -101,6 +102,11 @@ 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.
|
||||
@@ -112,9 +118,6 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
*/
|
||||
private Map<String, BeanWrapperImpl> nestedBeanWrappers;
|
||||
|
||||
/** The security context used for invoking the property methods */
|
||||
private AccessControlContext acc;
|
||||
|
||||
private boolean autoGrowNestedPaths = false;
|
||||
|
||||
|
||||
@@ -216,16 +219,6 @@ 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;
|
||||
}
|
||||
@@ -274,6 +267,22 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
return this.autoGrowNestedPaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@@ -360,10 +369,10 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
if (pd != null) {
|
||||
Class type = getPropertyType(propertyName);
|
||||
if (pd.getReadMethod() != null) {
|
||||
return new BeanTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), type);
|
||||
return new PropertyTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), type);
|
||||
}
|
||||
else if (pd.getWriteMethod() != null) {
|
||||
return new BeanTypeDescriptor(pd, BeanUtils.getWriteMethodParameter(pd), type);
|
||||
return new PropertyTypeDescriptor(pd, BeanUtils.getWriteMethodParameter(pd), type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -772,7 +781,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
"Getter for property '" + actualName + "' threw exception", ex);
|
||||
}
|
||||
|
||||
catch(IllegalAccessException ex) {
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
||||
"Illegal attempt to get property '" + actualName + "' threw exception", ex);
|
||||
}
|
||||
@@ -804,7 +813,8 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
}
|
||||
setPropertyValue(name, newArray);
|
||||
return newArray;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
||||
+14
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* 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.
|
||||
@@ -22,6 +22,8 @@ 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;
|
||||
@@ -125,10 +127,11 @@ public class DirectFieldAccessor extends AbstractPropertyAccessor {
|
||||
Object convertedValue = this.typeConverterDelegate.convertIfNecessary(oldValue, newValue, field);
|
||||
field.set(this.target, convertedValue);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new InvalidPropertyException(this.target.getClass(), propertyName, "Field is not accessible", ex);
|
||||
catch (ConverterNotFoundException ex) {
|
||||
PropertyChangeEvent pce = new PropertyChangeEvent(this.target, propertyName, oldValue, newValue);
|
||||
throw new ConversionNotSupportedException(pce, field.getType(), ex);
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
catch (ConversionException ex) {
|
||||
PropertyChangeEvent pce = new PropertyChangeEvent(this.target, propertyName, oldValue, newValue);
|
||||
throw new TypeMismatchException(pce, field.getType(), ex);
|
||||
}
|
||||
@@ -136,6 +139,13 @@ 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(
|
||||
|
||||
+22
-10
@@ -33,6 +33,7 @@ import org.springframework.core.GenericCollectionTypeResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.support.PropertyTypeDescriptor;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -152,7 +153,7 @@ class TypeConverterDelegate {
|
||||
throws IllegalArgumentException {
|
||||
|
||||
return convertIfNecessary(descriptor.getName(), oldValue, newValue, descriptor.getPropertyType(),
|
||||
new BeanTypeDescriptor(descriptor));
|
||||
new PropertyTypeDescriptor(descriptor, BeanUtils.getWriteMethodParameter(descriptor)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -195,8 +196,9 @@ class TypeConverterDelegate {
|
||||
ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
|
||||
if (editor == null && conversionService != null && convertedValue != null) {
|
||||
TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(convertedValue);
|
||||
if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
|
||||
return (T) conversionService.convert(convertedValue, sourceTypeDesc, typeDescriptor);
|
||||
TypeDescriptor targetTypeDesc = typeDescriptor.forElementType(requiredType);
|
||||
if (conversionService.canConvert(sourceTypeDesc, targetTypeDesc)) {
|
||||
return (T) conversionService.convert(convertedValue, sourceTypeDesc, targetTypeDesc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,8 +206,8 @@ class TypeConverterDelegate {
|
||||
if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) {
|
||||
if (requiredType != null && Collection.class.isAssignableFrom(requiredType) &&
|
||||
convertedValue instanceof String && typeDescriptor.getMethodParameter() != null) {
|
||||
Class elementType = GenericCollectionTypeResolver.getCollectionParameterType(typeDescriptor.getMethodParameter());
|
||||
if (elementType != null && Enum.class.isAssignableFrom(elementType)) {
|
||||
Class elemType = GenericCollectionTypeResolver.getCollectionParameterType(typeDescriptor.getMethodParameter());
|
||||
if (elemType != null && Enum.class.isAssignableFrom(elemType)) {
|
||||
convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
|
||||
}
|
||||
}
|
||||
@@ -348,8 +350,8 @@ class TypeConverterDelegate {
|
||||
*/
|
||||
protected PropertyEditor findDefaultEditor(Class requiredType, TypeDescriptor typeDescriptor) {
|
||||
PropertyEditor editor = null;
|
||||
if (typeDescriptor instanceof BeanTypeDescriptor) {
|
||||
PropertyDescriptor pd = ((BeanTypeDescriptor) typeDescriptor).getPropertyDescriptor();
|
||||
if (typeDescriptor instanceof PropertyTypeDescriptor) {
|
||||
PropertyDescriptor pd = ((PropertyTypeDescriptor) typeDescriptor).getPropertyDescriptor();
|
||||
editor = pd.createPropertyEditor(this.targetObject);
|
||||
}
|
||||
if (editor == null && requiredType != null) {
|
||||
@@ -518,6 +520,10 @@ class TypeConverterDelegate {
|
||||
Collection original, String propertyName, Class requiredType, TypeDescriptor typeDescriptor) {
|
||||
|
||||
boolean originalAllowed = requiredType.isInstance(original);
|
||||
if (!originalAllowed && !Collection.class.isAssignableFrom(requiredType)) {
|
||||
return original;
|
||||
}
|
||||
|
||||
MethodParameter methodParam = typeDescriptor.getMethodParameter();
|
||||
Class elementType = null;
|
||||
if (methodParam != null) {
|
||||
@@ -571,8 +577,8 @@ class TypeConverterDelegate {
|
||||
if (methodParam != null) {
|
||||
methodParam.increaseNestingLevel();
|
||||
}
|
||||
Object convertedElement =
|
||||
convertIfNecessary(indexedPropertyName, null, element, elementType, typeDescriptor);
|
||||
Object convertedElement = convertIfNecessary(
|
||||
indexedPropertyName, null, element, elementType, typeDescriptor);
|
||||
if (methodParam != null) {
|
||||
methodParam.decreaseNestingLevel();
|
||||
}
|
||||
@@ -592,8 +598,14 @@ class TypeConverterDelegate {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Map convertToTypedMap(Map original, String propertyName, Class requiredType, TypeDescriptor typeDescriptor) {
|
||||
protected Map convertToTypedMap(
|
||||
Map original, String propertyName, Class requiredType, TypeDescriptor typeDescriptor) {
|
||||
|
||||
boolean originalAllowed = requiredType.isInstance(original);
|
||||
if (!originalAllowed && !Map.class.isAssignableFrom(requiredType)) {
|
||||
return original;
|
||||
}
|
||||
|
||||
Class keyType = null;
|
||||
Class valueType = null;
|
||||
MethodParameter methodParam = typeDescriptor.getMethodParameter();
|
||||
|
||||
+8
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* 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.
|
||||
@@ -153,8 +153,14 @@ public interface BeanFactory {
|
||||
* Return the bean instance that uniquely matches the given object type, if any.
|
||||
* @param requiredType type the bean must match; can be an interface or superclass.
|
||||
* {@literal null} is disallowed.
|
||||
* @return bean matching required type
|
||||
* <p>This method goes into {@link ListableBeanFactory} by-type lookup territory
|
||||
* but may also be translated into a conventional by-name lookup based on the name
|
||||
* of the given type. For more extensive retrieval operations across sets of beans,
|
||||
* use {@link ListableBeanFactory} and/or {@link BeanFactoryUtils}.
|
||||
* @return an instance of the single bean matching the required type
|
||||
* @throws NoSuchBeanDefinitionException if there is not exactly one matching bean found
|
||||
* @since 3.0
|
||||
* @see ListableBeanFactory
|
||||
*/
|
||||
<T> T getBean(Class<T> requiredType) throws BeansException;
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* 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.
|
||||
@@ -193,7 +193,7 @@ public abstract class AbstractFactoryBean<T>
|
||||
* interface, for a consistent offering of abstract template methods.
|
||||
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
|
||||
*/
|
||||
public abstract Class<? extends T> getObjectType();
|
||||
public abstract Class<?> getObjectType();
|
||||
|
||||
/**
|
||||
* Template method that subclasses must override to construct
|
||||
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* 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.
|
||||
@@ -48,7 +48,8 @@ public interface BeanPostProcessor {
|
||||
* The returned bean instance may be a wrapper around the original.
|
||||
* @param bean the new bean instance
|
||||
* @param beanName the name of the bean
|
||||
* @return the bean instance to use, either the original or a wrapped one
|
||||
* @return the bean instance to use, either the original or a wrapped one; if
|
||||
* <code>null</code>, no subsequent BeanPostProcessors will be invoked
|
||||
* @throws org.springframework.beans.BeansException in case of errors
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
|
||||
*/
|
||||
@@ -68,7 +69,8 @@ public interface BeanPostProcessor {
|
||||
* in contrast to all other BeanPostProcessor callbacks.
|
||||
* @param bean the new bean instance
|
||||
* @param beanName the name of the bean
|
||||
* @return the bean instance to use, either the original or a wrapped one
|
||||
* @return the bean instance to use, either the original or a wrapped one; if
|
||||
* <code>null</code>, no subsequent BeanPostProcessors will be invoked
|
||||
* @throws org.springframework.beans.BeansException in case of errors
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
|
||||
* @see org.springframework.beans.factory.FactoryBean
|
||||
|
||||
+30
-24
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* 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.
|
||||
@@ -16,7 +16,10 @@
|
||||
|
||||
package org.springframework.beans.factory.config;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -41,7 +44,7 @@ import org.springframework.util.Assert;
|
||||
* <pre class="code"><beans>
|
||||
*
|
||||
* <!-- Prototype bean since we have state -->
|
||||
* <bean id="myService" class="a.b.c.MyService" singleton="false"/>
|
||||
* <bean id="myService" class="a.b.c.MyService" scope="prototype"/>
|
||||
*
|
||||
* <bean id="myServiceFactory"
|
||||
* class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
|
||||
@@ -63,9 +66,9 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* public class MyClientBean {
|
||||
*
|
||||
* private ObjectFactory myServiceFactory;
|
||||
* private ObjectFactory<MyService> myServiceFactory;
|
||||
*
|
||||
* public void setMyServiceFactory(ObjectFactory myServiceFactory) {
|
||||
* public void setMyServiceFactory(ObjectFactory<MyService> myServiceFactory) {
|
||||
* this.myServiceFactory = myServiceFactory;
|
||||
* }
|
||||
*
|
||||
@@ -91,20 +94,17 @@ import org.springframework.util.Assert;
|
||||
* @see org.springframework.beans.factory.ObjectFactory
|
||||
* @see ServiceLocatorFactoryBean
|
||||
*/
|
||||
public class ObjectFactoryCreatingFactoryBean extends AbstractFactoryBean {
|
||||
public class ObjectFactoryCreatingFactoryBean extends AbstractFactoryBean<ObjectFactory> {
|
||||
|
||||
private String targetBeanName;
|
||||
|
||||
|
||||
/**
|
||||
* Set the name of the target bean.
|
||||
* <p>The target does not <i>have</> to be a prototype bean, but realisticially
|
||||
* always will be (because if the target bean were a singleton, then said
|
||||
* singleton bean could simply be injected straight into the dependent object,
|
||||
* thus obviating the need for the extra level of indirection afforded by
|
||||
* the approach encapsulated by this class). Please note that no exception
|
||||
* will be thrown if the supplied <code>targetBeanName</code> does not
|
||||
* reference a prototype bean.
|
||||
* <p>The target does not <i>have</> to be a non-singleton bean, but realisticially
|
||||
* always will be (because if the target bean were a singleton, then said singleton
|
||||
* bean could simply be injected straight into the dependent object, thus obviating
|
||||
* the need for the extra level of indirection afforded by this factory approach).
|
||||
*/
|
||||
public void setTargetBeanName(String targetBeanName) {
|
||||
this.targetBeanName = targetBeanName;
|
||||
@@ -123,22 +123,28 @@ public class ObjectFactoryCreatingFactoryBean extends AbstractFactoryBean {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object createInstance() {
|
||||
return new ObjectFactory() {
|
||||
public Object getObject() throws BeansException {
|
||||
return getTargetBean(targetBeanName);
|
||||
}
|
||||
};
|
||||
protected ObjectFactory createInstance() {
|
||||
return new TargetBeanObjectFactory(getBeanFactory(), this.targetBeanName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Template method for obtaining a target bean instance.
|
||||
* Called by the exposed ObjectFactory's <code>getObject()</code> method.
|
||||
* @param targetBeanName the name of the target bean
|
||||
* @return the target bean instance
|
||||
* Independent inner class - for serialization purposes.
|
||||
*/
|
||||
protected Object getTargetBean(String targetBeanName) {
|
||||
return getBeanFactory().getBean(targetBeanName);
|
||||
private static class TargetBeanObjectFactory implements ObjectFactory, Serializable {
|
||||
|
||||
private final BeanFactory beanFactory;
|
||||
|
||||
private final String targetBeanName;
|
||||
|
||||
public TargetBeanObjectFactory(BeanFactory beanFactory, String targetBeanName) {
|
||||
this.beanFactory = beanFactory;
|
||||
this.targetBeanName = targetBeanName;
|
||||
}
|
||||
|
||||
public Object getObject() throws BeansException {
|
||||
return this.beanFactory.getBean(this.targetBeanName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* 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.
|
||||
@@ -193,7 +193,8 @@ public class PropertyPathFactoryBean implements FactoryBean<Object>, BeanNameAwa
|
||||
public Object getObject() throws BeansException {
|
||||
BeanWrapper target = this.targetBeanWrapper;
|
||||
if (target != null) {
|
||||
if (logger.isWarnEnabled() && this.beanFactory instanceof ConfigurableBeanFactory &&
|
||||
if (logger.isWarnEnabled() && this.targetBeanName != null &&
|
||||
this.beanFactory instanceof ConfigurableBeanFactory &&
|
||||
((ConfigurableBeanFactory) this.beanFactory).isCurrentlyInCreation(this.targetBeanName)) {
|
||||
logger.warn("Target bean '" + this.targetBeanName + "' is still in creation due to a circular " +
|
||||
"reference - obtained value for property '" + this.propertyPath + "' may be outdated!");
|
||||
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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.beans.factory.config;
|
||||
|
||||
import java.io.Serializable;
|
||||
import javax.inject.Provider;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A {@link org.springframework.beans.factory.FactoryBean} implementation that
|
||||
* returns a value which is a JSR-330 {@link javax.inject.Provider} that in turn
|
||||
* returns a bean sourced from a {@link org.springframework.beans.factory.BeanFactory}.
|
||||
*
|
||||
* <p>This is basically a JSR-330 compliant variant of Spring's good old
|
||||
* {@link ObjectFactoryCreatingFactoryBean}. It can be used for traditional
|
||||
* external dependency injection configuration that targets a property or
|
||||
* constructor argument of type <code>javax.inject.Provider</code>, as an
|
||||
* alternative to JSR-330's <code>@Inject</code> annotation-driven approach.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0.2
|
||||
* @see javax.inject.Provider
|
||||
* @see ObjectFactoryCreatingFactoryBean
|
||||
*/
|
||||
public class ProviderCreatingFactoryBean extends AbstractFactoryBean<Provider> {
|
||||
|
||||
private String targetBeanName;
|
||||
|
||||
|
||||
/**
|
||||
* Set the name of the target bean.
|
||||
* <p>The target does not <i>have</> to be a non-singleton bean, but realisticially
|
||||
* always will be (because if the target bean were a singleton, then said singleton
|
||||
* bean could simply be injected straight into the dependent object, thus obviating
|
||||
* the need for the extra level of indirection afforded by this factory approach).
|
||||
*/
|
||||
public void setTargetBeanName(String targetBeanName) {
|
||||
this.targetBeanName = targetBeanName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.hasText(this.targetBeanName, "Property 'targetBeanName' is required");
|
||||
super.afterPropertiesSet();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class getObjectType() {
|
||||
return Provider.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Provider createInstance() {
|
||||
return new TargetBeanProvider(getBeanFactory(), this.targetBeanName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Independent inner class - for serialization purposes.
|
||||
*/
|
||||
private static class TargetBeanProvider implements Provider, Serializable {
|
||||
|
||||
private final BeanFactory beanFactory;
|
||||
|
||||
private final String targetBeanName;
|
||||
|
||||
public TargetBeanProvider(BeanFactory beanFactory, String targetBeanName) {
|
||||
this.beanFactory = beanFactory;
|
||||
this.targetBeanName = targetBeanName;
|
||||
}
|
||||
|
||||
public Object get() throws BeansException {
|
||||
return this.beanFactory.getBean(this.targetBeanName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+28
-2
@@ -392,6 +392,9 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
Object result = existingBean;
|
||||
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
|
||||
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
|
||||
if (result == null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -402,6 +405,9 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
Object result = existingBean;
|
||||
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
|
||||
result = beanProcessor.postProcessAfterInitialization(result, beanName);
|
||||
if (result == null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -682,11 +688,14 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
*/
|
||||
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
|
||||
Object exposedObject = bean;
|
||||
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
|
||||
if (bean != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
|
||||
for (BeanPostProcessor bp : getBeanPostProcessors()) {
|
||||
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
|
||||
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
|
||||
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
|
||||
if (exposedObject == null) {
|
||||
return exposedObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1130,7 +1139,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
|
||||
// Do not allow eager init for type matching in case of a prioritized post-processor.
|
||||
boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());
|
||||
DependencyDescriptor desc = new DependencyDescriptor(methodParam, false, eager);
|
||||
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
|
||||
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
|
||||
if (autowiredArgument != null) {
|
||||
pvs.add(propertyName, autowiredArgument);
|
||||
@@ -1553,4 +1562,21 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
this.factoryBeanInstanceCache.remove(beanName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Special DependencyDescriptor variant for autowire="byType".
|
||||
* Always optional; never considering the parameter name for choosing a primary candidate.
|
||||
*/
|
||||
private static class AutowireByTypeDependencyDescriptor extends DependencyDescriptor {
|
||||
|
||||
public AutowireByTypeDependencyDescriptor(MethodParameter methodParameter, boolean eager) {
|
||||
super(methodParameter, false, eager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDependencyName() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+17
-2
@@ -57,6 +57,7 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.beans.factory.SmartFactoryBean;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.BeanExpressionContext;
|
||||
import org.springframework.beans.factory.config.BeanExpressionResolver;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
@@ -222,7 +223,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
* @throws BeansException if the bean could not be created
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T doGetBean(
|
||||
protected <T> T doGetBean(
|
||||
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
|
||||
throws BeansException {
|
||||
|
||||
@@ -473,7 +474,20 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
return parentBeanFactory.isTypeMatch(originalBeanName(name), targetType);
|
||||
}
|
||||
|
||||
// Retrieve corresponding bean definition.
|
||||
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
|
||||
|
||||
// Check decorated bean definition, if any: We assume it'll be easier
|
||||
// to determine the decorated bean's type than the proxy's type.
|
||||
BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
|
||||
if (dbd != null && !BeanFactoryUtils.isFactoryDereference(name)) {
|
||||
RootBeanDefinition tbd = getMergedBeanDefinition(dbd.getBeanName(), dbd.getBeanDefinition(), mbd);
|
||||
Class targetClass = predictBeanType(dbd.getBeanName(), tbd, FactoryBean.class, typeToMatch);
|
||||
if (targetClass != null && !FactoryBean.class.isAssignableFrom(targetClass)) {
|
||||
return typeToMatch.isAssignableFrom(targetClass);
|
||||
}
|
||||
}
|
||||
|
||||
Class beanClass = predictBeanType(beanName, mbd, FactoryBean.class, typeToMatch);
|
||||
if (beanClass == null) {
|
||||
return false;
|
||||
@@ -901,6 +915,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
}
|
||||
|
||||
public boolean isCurrentlyInCreation(String beanName) {
|
||||
Assert.notNull(beanName, "Bean name must not be null");
|
||||
return isSingletonCurrentlyInCreation(beanName) || isPrototypeCurrentlyInCreation(beanName);
|
||||
}
|
||||
|
||||
@@ -1241,7 +1256,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
if (this.beanExpressionResolver == null) {
|
||||
return value;
|
||||
}
|
||||
Scope scope = getRegisteredScope(beanDefinition.getScope());
|
||||
Scope scope = (beanDefinition != null ? getRegisteredScope(beanDefinition.getScope()) : null);
|
||||
return this.beanExpressionResolver.evaluate(value, new BeanExpressionContext(this, scope));
|
||||
}
|
||||
|
||||
|
||||
+20
-3
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.beans.factory.support;
|
||||
|
||||
import static org.springframework.util.StringUtils.collectionToCommaDelimitedString;
|
||||
|
||||
import java.beans.ConstructorProperties;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Member;
|
||||
@@ -44,6 +46,7 @@ import org.springframework.beans.factory.UnsatisfiedDependencyException;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
||||
import org.springframework.beans.factory.config.DependencyDescriptor;
|
||||
import org.springframework.beans.factory.config.TypedStringValue;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
@@ -51,6 +54,7 @@ import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.MethodInvoker;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Helper class for resolving constructors and factory methods.
|
||||
@@ -497,12 +501,25 @@ class ConstructorResolver {
|
||||
}
|
||||
|
||||
if (factoryMethodToUse == null) {
|
||||
boolean hasArgs = resolvedValues.getArgumentCount() > 0;
|
||||
String argDesc = "";
|
||||
if (hasArgs) {
|
||||
List<String> argTypes = new ArrayList<String>();
|
||||
for (ValueHolder value : resolvedValues.getIndexedArgumentValues().values()) {
|
||||
String argType = value.getType() != null ?
|
||||
ClassUtils.getShortName(value.getType()) : value.getValue().getClass().getSimpleName();
|
||||
argTypes.add(argType);
|
||||
}
|
||||
argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
|
||||
}
|
||||
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
|
||||
"No matching factory method found: " +
|
||||
(mbd.getFactoryBeanName() != null ?
|
||||
"factory bean '" + mbd.getFactoryBeanName() + "'; " : "") +
|
||||
"factory method '" + mbd.getFactoryMethodName() + "'. " +
|
||||
"Check that a method of the specified name exists and that it is " +
|
||||
"factory bean '" + mbd.getFactoryBeanName() + "'; " : "") +
|
||||
"factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. " +
|
||||
"Check that a method with the specified name " +
|
||||
(hasArgs ? "and arguments " : "") +
|
||||
"exists and that it is " +
|
||||
(isStatic ? "static" : "non-static") + ".");
|
||||
}
|
||||
else if (void.class.equals(factoryMethodToUse.getReturnType())) {
|
||||
|
||||
+4
-2
@@ -262,6 +262,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
|
||||
@Override
|
||||
public boolean containsBeanDefinition(String beanName) {
|
||||
Assert.notNull(beanName, "Bean name must not be null");
|
||||
return this.beanDefinitionMap.containsKey(beanName);
|
||||
}
|
||||
|
||||
@@ -574,7 +575,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
|
||||
throws BeanDefinitionStoreException {
|
||||
|
||||
Assert.hasText(beanName, "'beanName' must not be empty");
|
||||
Assert.hasText(beanName, "Bean name must not be empty");
|
||||
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
|
||||
|
||||
if (beanDefinition instanceof AbstractBeanDefinition) {
|
||||
@@ -693,7 +694,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
if (value != null) {
|
||||
if (value instanceof String) {
|
||||
String strVal = resolveEmbeddedValue((String) value);
|
||||
value = evaluateBeanDefinitionString(strVal, getMergedBeanDefinition(beanName));
|
||||
BeanDefinition bd = (containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
|
||||
value = evaluateBeanDefinitionString(strVal, bd);
|
||||
}
|
||||
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
|
||||
return converter.convertIfNecessary(value, type);
|
||||
|
||||
+3
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* 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.
|
||||
@@ -123,8 +123,6 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
|
||||
final FactoryBean factory, final String beanName, final boolean shouldPostProcess)
|
||||
throws BeanCreationException {
|
||||
|
||||
|
||||
|
||||
Object object;
|
||||
try {
|
||||
if (System.getSecurityManager() != null) {
|
||||
@@ -135,7 +133,8 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
|
||||
return factory.getObject();
|
||||
}
|
||||
}, acc);
|
||||
} catch (PrivilegedActionException pae) {
|
||||
}
|
||||
catch (PrivilegedActionException pae) {
|
||||
throw pae.getException();
|
||||
}
|
||||
}
|
||||
|
||||
+14
-2
@@ -24,6 +24,7 @@ import java.util.Set;
|
||||
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -53,6 +54,8 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
|
||||
private final Set<String> externallyManagedDestroyMethods = Collections.synchronizedSet(new HashSet<String>());
|
||||
|
||||
private BeanDefinitionHolder decoratedDefinition;
|
||||
|
||||
boolean isFactoryMethodUnique;
|
||||
|
||||
/** Package-visible field for caching the resolved constructor or factory method */
|
||||
@@ -75,7 +78,6 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
|
||||
final Object postProcessingLock = new Object();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new RootBeanDefinition, to be configured through its bean
|
||||
* properties and configuration methods.
|
||||
@@ -224,7 +226,9 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
RootBeanDefinition(BeanDefinition original) {
|
||||
super(original);
|
||||
if (original instanceof RootBeanDefinition) {
|
||||
this.isFactoryMethodUnique = ((RootBeanDefinition) original).isFactoryMethodUnique;
|
||||
RootBeanDefinition originalRbd = (RootBeanDefinition) original;
|
||||
this.decoratedDefinition = originalRbd.decoratedDefinition;
|
||||
this.isFactoryMethodUnique = originalRbd.isFactoryMethodUnique;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,6 +293,14 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
return this.externallyManagedDestroyMethods.contains(destroyMethod);
|
||||
}
|
||||
|
||||
public void setDecoratedDefinition(BeanDefinitionHolder decoratedDefinition) {
|
||||
this.decoratedDefinition = decoratedDefinition;
|
||||
}
|
||||
|
||||
public BeanDefinitionHolder getDecoratedDefinition() {
|
||||
return this.decoratedDefinition;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public RootBeanDefinition cloneBeanDefinition() {
|
||||
|
||||
+45
-34
@@ -16,15 +16,6 @@
|
||||
|
||||
package org.springframework.beans.factory;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.MalformedURLException;
|
||||
import java.security.AccessControlContext;
|
||||
@@ -40,12 +31,19 @@ import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.security.auth.Subject;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
import test.beans.DerivedTestBean;
|
||||
import test.beans.DummyFactory;
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.LifecycleBean;
|
||||
import test.beans.NestedTestBean;
|
||||
import test.beans.TestBean;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.NotWritablePropertyException;
|
||||
@@ -72,6 +70,7 @@ import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.ConstructorDependenciesBean;
|
||||
import org.springframework.beans.factory.xml.DependenciesBean;
|
||||
import org.springframework.beans.propertyeditors.CustomNumberEditor;
|
||||
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.support.ConversionServiceFactory;
|
||||
@@ -80,13 +79,6 @@ import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.UrlResource;
|
||||
import org.springframework.util.StopWatch;
|
||||
|
||||
import test.beans.DerivedTestBean;
|
||||
import test.beans.DummyFactory;
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.LifecycleBean;
|
||||
import test.beans.NestedTestBean;
|
||||
import test.beans.TestBean;
|
||||
|
||||
/**
|
||||
* Tests properties population and autowire behavior.
|
||||
*
|
||||
@@ -1103,7 +1095,7 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testAutowireWithNoDependencies() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("rod", bd);
|
||||
assertEquals(1, lbf.getBeanDefinitionCount());
|
||||
Object registered = lbf.autowire(NoDependencies.class, AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT, false);
|
||||
@@ -1180,7 +1172,7 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testAutowireConstructor() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("spouse", bd);
|
||||
ConstructorDependenciesBean bean = (ConstructorDependenciesBean)
|
||||
lbf.autowire(ConstructorDependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, true);
|
||||
@@ -1192,7 +1184,7 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testAutowireBeanByName() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("spouse", bd);
|
||||
DependenciesBean bean = (DependenciesBean)
|
||||
lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true);
|
||||
@@ -1204,7 +1196,7 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testAutowireBeanByNameWithDependencyCheck() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("spous", bd);
|
||||
try {
|
||||
lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true);
|
||||
@@ -1218,7 +1210,7 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testAutowireBeanByNameWithNoDependencyCheck() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("spous", bd);
|
||||
DependenciesBean bean = (DependenciesBean)
|
||||
lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, false);
|
||||
@@ -1228,7 +1220,7 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testAutowireBeanByType() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("test", bd);
|
||||
DependenciesBean bean = (DependenciesBean)
|
||||
lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
|
||||
@@ -1245,7 +1237,7 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testAutowireBeanWithFactoryBeanByType() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(LazyInitFactory.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(LazyInitFactory.class);
|
||||
lbf.registerBeanDefinition("factoryBean", bd);
|
||||
LazyInitFactory factoryBean = (LazyInitFactory) lbf.getBean("&factoryBean");
|
||||
assertNotNull("The FactoryBean should have been registered.", factoryBean);
|
||||
@@ -1264,7 +1256,7 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test(expected=TypeMismatchException.class)
|
||||
public void testAutowireBeanWithFactoryBeanByName() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(LazyInitFactory.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(LazyInitFactory.class);
|
||||
lbf.registerBeanDefinition("factoryBean", bd);
|
||||
LazyInitFactory factoryBean = (LazyInitFactory) lbf.getBean("&factoryBean");
|
||||
assertNotNull("The FactoryBean should have been registered.", factoryBean);
|
||||
@@ -1274,10 +1266,10 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testAutowireBeanByTypeWithTwoMatches() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("test", bd);
|
||||
lbf.registerBeanDefinition("test2", bd2);
|
||||
lbf.registerBeanDefinition("spouse", bd2);
|
||||
try {
|
||||
lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
|
||||
fail("Should have thrown UnsatisfiedDependencyException");
|
||||
@@ -1285,7 +1277,26 @@ public final class DefaultListableBeanFactoryTests {
|
||||
catch (UnsatisfiedDependencyException ex) {
|
||||
// expected
|
||||
assertTrue(ex.getMessage().indexOf("test") != -1);
|
||||
assertTrue(ex.getMessage().indexOf("test2") != -1);
|
||||
assertTrue(ex.getMessage().indexOf("spouse") != -1);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutowireBeanByTypeWithTwoMatchesAndParameterNameDiscovery() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
lbf.setParameterNameDiscoverer(new LocalVariableTableParameterNameDiscoverer());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("test", bd);
|
||||
lbf.registerBeanDefinition("spouse", bd2);
|
||||
try {
|
||||
lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
|
||||
fail("Should have thrown UnsatisfiedDependencyException");
|
||||
}
|
||||
catch (UnsatisfiedDependencyException ex) {
|
||||
// expected
|
||||
assertTrue(ex.getMessage().indexOf("test") != -1);
|
||||
assertTrue(ex.getMessage().indexOf("spouse") != -1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1312,7 +1323,7 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testAutowireExistingBeanByName() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("spouse", bd);
|
||||
DependenciesBean existingBean = new DependenciesBean();
|
||||
lbf.autowireBeanProperties(existingBean, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true);
|
||||
@@ -1324,7 +1335,7 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testAutowireExistingBeanByNameWithDependencyCheck() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("spous", bd);
|
||||
DependenciesBean existingBean = new DependenciesBean();
|
||||
try {
|
||||
@@ -1339,7 +1350,7 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testAutowireExistingBeanByNameWithNoDependencyCheck() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("spous", bd);
|
||||
DependenciesBean existingBean = new DependenciesBean();
|
||||
lbf.autowireBeanProperties(existingBean, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, false);
|
||||
@@ -1349,7 +1360,7 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testAutowireExistingBeanByType() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("test", bd);
|
||||
DependenciesBean existingBean = new DependenciesBean();
|
||||
lbf.autowireBeanProperties(existingBean, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
|
||||
@@ -1431,7 +1442,7 @@ public final class DefaultListableBeanFactoryTests {
|
||||
@Test
|
||||
public void testConfigureBeanWithAutowiring() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
lbf.registerBeanDefinition("spouse", bd);
|
||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||
pvs.add("age", "99");
|
||||
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
package org.springframework.beans.factory;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
|
||||
/**
|
||||
* SPR-5475 exposed the fact that the error message displayed when incorrectly
|
||||
* invoking a factory method is not instructive to the user and rather misleading.
|
||||
*
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class Spr5475Tests {
|
||||
|
||||
@Test
|
||||
public void noArgFactoryMethodInvokedWithOneArg() {
|
||||
assertExceptionMessageForMisconfiguredFactoryMethod(
|
||||
rootBeanDefinition(Foo.class)
|
||||
.setFactoryMethod("noArgFactory")
|
||||
.addConstructorArgValue("bogusArg").getBeanDefinition(),
|
||||
"Error creating bean with name 'foo': No matching factory method found: factory method 'noArgFactory(String)'. " +
|
||||
"Check that a method with the specified name and arguments exists and that it is static.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noArgFactoryMethodInvokedWithTwoArgs() {
|
||||
assertExceptionMessageForMisconfiguredFactoryMethod(
|
||||
rootBeanDefinition(Foo.class)
|
||||
.setFactoryMethod("noArgFactory")
|
||||
.addConstructorArgValue("bogusArg1")
|
||||
.addConstructorArgValue("bogusArg2".getBytes()).getBeanDefinition(),
|
||||
"Error creating bean with name 'foo': No matching factory method found: factory method 'noArgFactory(String,byte[])'. " +
|
||||
"Check that a method with the specified name and arguments exists and that it is static.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noArgFactoryMethodInvokedWithTwoArgsAndTypesSpecified() {
|
||||
RootBeanDefinition def = new RootBeanDefinition(Foo.class);
|
||||
def.setFactoryMethodName("noArgFactory");
|
||||
ConstructorArgumentValues cav = new ConstructorArgumentValues();
|
||||
cav.addIndexedArgumentValue(0, "bogusArg1", CharSequence.class.getName());
|
||||
cav.addIndexedArgumentValue(1, "bogusArg2".getBytes());
|
||||
def.setConstructorArgumentValues(cav);
|
||||
|
||||
assertExceptionMessageForMisconfiguredFactoryMethod(
|
||||
def,
|
||||
"Error creating bean with name 'foo': No matching factory method found: factory method 'noArgFactory(CharSequence,byte[])'. " +
|
||||
"Check that a method with the specified name and arguments exists and that it is static.");
|
||||
}
|
||||
|
||||
private void assertExceptionMessageForMisconfiguredFactoryMethod(BeanDefinition bd, String expectedMessage) {
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
factory.registerBeanDefinition("foo", bd);
|
||||
|
||||
try {
|
||||
factory.preInstantiateSingletons();
|
||||
fail("should have failed with BeanCreationException due to incorrectly invoked factory method");
|
||||
} catch (BeanCreationException ex) {
|
||||
assertThat(ex.getMessage(), equalTo(expectedMessage));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleArgFactoryMethodInvokedWithNoArgs() {
|
||||
// calling a factory method that accepts arguments without any arguments emits an exception unlike cases
|
||||
// where a no-arg factory method is called with arguments. Adding this test just to document the difference
|
||||
assertExceptionMessageForMisconfiguredFactoryMethod(
|
||||
rootBeanDefinition(Foo.class)
|
||||
.setFactoryMethod("singleArgFactory").getBeanDefinition(),
|
||||
"Error creating bean with name 'foo': " +
|
||||
"Unsatisfied dependency expressed through constructor argument with index 0 of type [java.lang.String]: " +
|
||||
"Ambiguous factory method argument types - did you specify the correct bean references as factory method arguments?");
|
||||
}
|
||||
|
||||
|
||||
static class Foo {
|
||||
static Foo noArgFactory() {
|
||||
return new Foo();
|
||||
}
|
||||
|
||||
static Foo singleArgFactory(String arg) {
|
||||
return new Foo();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+13
-8
@@ -1,19 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<!--
|
||||
Test data for ObjectFactoryCreatingFactoryBeanTests
|
||||
-->
|
||||
<beans>
|
||||
|
||||
<bean id="prototypeTarget" class="java.util.Date" scope="prototype"/>
|
||||
|
||||
<bean id="prototype" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
|
||||
<property name="targetBeanName"><idref local="prototypeTarget"/></property>
|
||||
<bean id="prototypeFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
|
||||
<property name="targetBeanName" value="prototypeTarget"/>
|
||||
</bean>
|
||||
|
||||
<bean id="testBean" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBeanTests$TestBean">
|
||||
<property name="objectFactory"><ref local="prototype"/></property>
|
||||
<bean id="factoryTestBean" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBeanTests$FactoryTestBean">
|
||||
<property name="objectFactory" ref="prototypeFactory"/>
|
||||
</bean>
|
||||
|
||||
|
||||
<bean id="prototypeProvider" class="org.springframework.beans.factory.config.ProviderCreatingFactoryBean">
|
||||
<property name="targetBeanName" value="prototypeTarget"/>
|
||||
</bean>
|
||||
|
||||
<bean id="providerTestBean" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBeanTests$ProviderTestBean">
|
||||
<property name="provider" ref="prototypeProvider"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
||||
+68
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* 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.
|
||||
@@ -16,43 +16,49 @@
|
||||
|
||||
package org.springframework.beans.factory.config;
|
||||
|
||||
import static org.easymock.EasyMock.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static test.util.TestResourceUtils.qualifiedResource;
|
||||
|
||||
import java.util.Date;
|
||||
import javax.inject.Provider;
|
||||
|
||||
import static org.easymock.EasyMock.*;
|
||||
import org.junit.After;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.BeansException;
|
||||
import static test.util.TestResourceUtils.*;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.beans.factory.xml.XmlBeanFactory;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.SerializationTestUtils;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ObjectFactoryCreatingFactoryBean}.
|
||||
*
|
||||
* @author Colin Sampaleanu
|
||||
* @author Juergen Hoeller
|
||||
* @author Rick Evans
|
||||
* @author Chris Beams
|
||||
* @since 2004-05-11
|
||||
*/
|
||||
public final class ObjectFactoryCreatingFactoryBeanTests {
|
||||
public class ObjectFactoryCreatingFactoryBeanTests {
|
||||
|
||||
private static final Resource CONTEXT =
|
||||
qualifiedResource(ObjectFactoryCreatingFactoryBeanTests.class, "context.xml");
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
private XmlBeanFactory beanFactory;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.beanFactory = new XmlBeanFactory(CONTEXT);
|
||||
this.beanFactory.setSerializationId("test");
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
this.beanFactory.setSerializationId(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBasicOperation() throws BeansException {
|
||||
TestBean testBean = (TestBean) beanFactory.getBean("testBean");
|
||||
public void testFactoryOperation() throws Exception {
|
||||
FactoryTestBean testBean = beanFactory.getBean("factoryTestBean", FactoryTestBean.class);
|
||||
ObjectFactory<?> objectFactory = testBean.getObjectFactory();
|
||||
|
||||
Date date1 = (Date) objectFactory.getObject();
|
||||
@@ -60,6 +66,40 @@ public final class ObjectFactoryCreatingFactoryBeanTests {
|
||||
assertTrue(date1 != date2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFactorySerialization() throws Exception {
|
||||
FactoryTestBean testBean = beanFactory.getBean("factoryTestBean", FactoryTestBean.class);
|
||||
ObjectFactory<?> objectFactory = testBean.getObjectFactory();
|
||||
|
||||
objectFactory = (ObjectFactory) SerializationTestUtils.serializeAndDeserialize(objectFactory);
|
||||
|
||||
Date date1 = (Date) objectFactory.getObject();
|
||||
Date date2 = (Date) objectFactory.getObject();
|
||||
assertTrue(date1 != date2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProviderOperation() throws Exception {
|
||||
ProviderTestBean testBean = beanFactory.getBean("providerTestBean", ProviderTestBean.class);
|
||||
Provider<?> provider = testBean.getProvider();
|
||||
|
||||
Date date1 = (Date) provider.get();
|
||||
Date date2 = (Date) provider.get();
|
||||
assertTrue(date1 != date2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProviderSerialization() throws Exception {
|
||||
ProviderTestBean testBean = beanFactory.getBean("providerTestBean", ProviderTestBean.class);
|
||||
Provider<?> provider = testBean.getProvider();
|
||||
|
||||
provider = (Provider) SerializationTestUtils.serializeAndDeserialize(provider);
|
||||
|
||||
Date date1 = (Date) provider.get();
|
||||
Date date2 = (Date) provider.get();
|
||||
assertTrue(date1 != date2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoesNotComplainWhenTargetBeanNameRefersToSingleton() throws Exception {
|
||||
final String targetBeanName = "singleton";
|
||||
@@ -78,7 +118,6 @@ public final class ObjectFactoryCreatingFactoryBeanTests {
|
||||
assertSame(expectedSingleton, actualSingleton);
|
||||
|
||||
verify(beanFactory);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -119,10 +158,9 @@ public final class ObjectFactoryCreatingFactoryBeanTests {
|
||||
}
|
||||
|
||||
|
||||
public static class TestBean {
|
||||
|
||||
public ObjectFactory<?> objectFactory;
|
||||
public static class FactoryTestBean {
|
||||
|
||||
private ObjectFactory<?> objectFactory;
|
||||
|
||||
public ObjectFactory<?> getObjectFactory() {
|
||||
return objectFactory;
|
||||
@@ -131,7 +169,20 @@ public final class ObjectFactoryCreatingFactoryBeanTests {
|
||||
public void setObjectFactory(ObjectFactory<?> objectFactory) {
|
||||
this.objectFactory = objectFactory;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class ProviderTestBean {
|
||||
|
||||
private Provider<?> provider;
|
||||
|
||||
public Provider<?> getProvider() {
|
||||
return provider;
|
||||
}
|
||||
|
||||
public void setProvider(Provider<?> provider) {
|
||||
this.provider = provider;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ Import-Template:
|
||||
javax.xml.*;version="0";resolution:=optional,
|
||||
net.sf.cglib.*;version="[2.1.3, 3.0.0)";resolution:=optional,
|
||||
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
|
||||
org.springframework.core.*;version="[3.0.0, 3.0.1)",
|
||||
org.springframework.util.*;version="[3.0.0, 3.0.1)",
|
||||
org.springframework.core.*;version=${spring.osgi.range},
|
||||
org.springframework.util.*;version=${spring.osgi.range},
|
||||
org.xml.sax.*;version="0";resolution:=optional,
|
||||
org.w3c.dom.*;version="0";resolution:=optional
|
||||
Ignored-Existing-Headers:
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.1.RELEASE</version>
|
||||
<version>3.0.2.RELEASE</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.1.RELEASE</version>
|
||||
<version>3.0.2.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
|
||||
|
||||
@@ -10,19 +10,19 @@ Import-Template:
|
||||
javax.naming.*;version="0";resolution:=optional,
|
||||
javax.sql.*;version="0";resolution:=optional,
|
||||
net.sf.ehcache.*;version="[1.3.0, 2.0.0)";resolution:=optional,
|
||||
net.sf.jasperreports.*;version="[2.0.5, 3.0.0)";resolution:=optional,
|
||||
net.sf.jasperreports.*;version="[2.0.5, 4.0.0)";resolution:=optional,
|
||||
org.apache.commons.collections.*;version="[3.2.0, 4.0.0)";resolution:=optional,
|
||||
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)";resolution:=optional,
|
||||
org.apache.velocity.*;version="[1.5.0, 2.0.0)";resolution:=optional,
|
||||
org.quartz.*;version="[1.6.0, 2.0.0)";resolution:=optional,
|
||||
org.springframework.beans.*;version="[3.0.0, 3.0.1)";resolution:=optional,
|
||||
org.springframework.context.*;version="[3.0.0, 3.0.1)",
|
||||
org.springframework.core.*;version="[3.0.0, 3.0.1)",
|
||||
org.springframework.jdbc.*;version="[3.0.0, 3.0.1)";resolution:=optional,
|
||||
org.springframework.jndi.*;version="[3.0.0, 3.0.1)";resolution:=optional,
|
||||
org.springframework.scheduling.*;version="[3.0.0, 3.0.1)";resolution:=optional,
|
||||
org.springframework.transaction.*;version="[3.0.0, 3.0.1)";resolution:=optional,
|
||||
org.springframework.util.*;version="[3.0.0, 3.0.1)"
|
||||
org.springframework.beans.*;version=${spring.osgi.range};resolution:=optional,
|
||||
org.springframework.context.*;version=${spring.osgi.range},
|
||||
org.springframework.core.*;version=${spring.osgi.range},
|
||||
org.springframework.jdbc.*;version=${spring.osgi.range};resolution:=optional,
|
||||
org.springframework.jndi.*;version=${spring.osgi.range};resolution:=optional,
|
||||
org.springframework.scheduling.*;version=${spring.osgi.range};resolution:=optional,
|
||||
org.springframework.transaction.*;version=${spring.osgi.range};resolution:=optional,
|
||||
org.springframework.util.*;version=${spring.osgi.range}
|
||||
Ignored-Existing-Headers:
|
||||
Bnd-LastModified,
|
||||
Import-Package,
|
||||
|
||||
@@ -1,41 +1,38 @@
|
||||
<?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 combineaccessrules="false" kind="src" path="/org.springframework.aop"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.beans"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.core"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.expression"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.instrument"/>
|
||||
<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/edu.emory.mathcs.backport/com.springsource.edu.emory.mathcs.backport/3.0.0/com.springsource.edu.emory.mathcs.backport-3.0.0.jar" sourcepath="/IVY_CACHE/edu.emory.mathcs.backport/com.springsource.edu.emory.mathcs.backport/3.0.0/com.springsource.edu.emory.mathcs.backport-sources-3.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.ejb/com.springsource.javax.ejb/3.0.0/com.springsource.javax.ejb-3.0.0.jar" sourcepath="/IVY_CACHE/javax.ejb/com.springsource.javax.ejb/3.0.0/com.springsource.javax.ejb-sources-3.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.inject/com.springsource.javax.inject/1.0.0/com.springsource.javax.inject-1.0.0.jar" sourcepath="/IVY_CACHE/javax.inject/com.springsource.javax.inject/1.0.0/com.springsource.javax.inject-sources-1.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.jms/com.springsource.javax.jms/1.1.0/com.springsource.javax.jms-1.1.0.jar" sourcepath="/IVY_CACHE/javax.jms/com.springsource.javax.jms/1.1.0/com.springsource.javax.jms-sources-1.1.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 kind="var" path="IVY_CACHE/javax.transaction/com.springsource.javax.transaction/1.1.0/com.springsource.javax.transaction-1.1.0.jar" sourcepath="/IVY_CACHE/javax.transaction/com.springsource.javax.transaction/1.1.0/com.springsource.javax.transaction-sources-1.1.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.validation/com.springsource.javax.validation/1.0.0.GA/com.springsource.javax.validation-1.0.0.GA.jar" sourcepath="/IVY_CACHE/javax.validation/com.springsource.javax.validation/1.0.0/com.springsource.javax.validation-sources-1.0.0.GA.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.xml.rpc/com.springsource.javax.xml.rpc/1.1.0/com.springsource.javax.xml.rpc-1.1.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.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.dbcp/1.2.2.osgi/com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.dbcp/1.2.2.osgi/com.springsource.org.apache.commons.dbcp-sources-1.2.2.osgi.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.apache.commons/com.springsource.org.apache.commons.pool/1.4.0/com.springsource.org.apache.commons.pool-1.4.0.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.pool/1.4.0/com.springsource.org.apache.commons.pool-sources-1.4.0.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.aspectj/com.springsource.org.aspectj.weaver/1.6.8.RELEASE/com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.beanshell/com.springsource.bsh/2.0.0.b4/com.springsource.bsh-2.0.0.b4.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.codehaus.groovy/com.springsource.org.codehaus.groovy/1.6.5/com.springsource.org.codehaus.groovy-1.6.5.jar" sourcepath="/IVY_CACHE/org.codehaus.groovy/com.springsource.org.codehaus.groovy/1.6.5/com.springsource.org.codehaus.groovy-sources-1.6.5.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/org.objectweb.asm/com.springsource.org.objectweb.asm/3.1.0/com.springsource.org.objectweb.asm-3.1.0.jar" sourcepath="IVY_CACHE/org.objectweb.asm/com.springsource.org.objectweb.asm/3.1.0/com.springsource.org.objectweb.asm-sources-3.1.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.objectweb.asm/com.springsource.org.objectweb.asm.commons/3.1.0/com.springsource.org.objectweb.asm.commons-3.1.0.jar" sourcepath="IVY_CACHE/org.objectweb.asm/com.springsource.org.objectweb.asm.commons/3.1.0/com.springsource.org.objectweb.asm.commons-sources-3.1.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.hibernate/com.springsource.org.hibernate.validator/4.0.0.GA/com.springsource.org.hibernate.validator-4.0.0.GA.jar" sourcepath="/IVY_CACHE/org.hibernate/com.springsource.org.hibernate.validator/4.0.0.GA/com.springsource.org.hibernate.validator-sources-4.0.0.GA.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.joda/com.springsource.org.joda.time/1.6.0/com.springsource.org.joda.time-1.6.0.jar" sourcepath="/IVY_CACHE/org.joda/com.springsource.org.joda.time/1.6.0/com.springsource.org.joda.time-sources-1.6.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.jruby/com.springsource.org.jruby/1.4.0/com.springsource.org.jruby-1.4.0.jar" sourcepath="/IVY_CACHE/org.jruby/com.springsource.org.jruby/1.4.0/com.springsource.org.jruby-sources-1.4.0.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.inject/com.springsource.org.atinject.tck/1.0.0/com.springsource.org.atinject.tck-1.0.0.jar" sourcepath="/IVY_CACHE/javax.inject/com.springsource.org.atinject.tck/1.0.0/com.springsource.org.atinject.tck-sources-1.0.0.jar"/>
|
||||
|
||||
<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 combineaccessrules="false" kind="src" path="/org.springframework.aop"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.beans"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.core"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.expression"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.instrument"/>
|
||||
<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/edu.emory.mathcs.backport/com.springsource.edu.emory.mathcs.backport/3.0.0/com.springsource.edu.emory.mathcs.backport-3.0.0.jar" sourcepath="/IVY_CACHE/edu.emory.mathcs.backport/com.springsource.edu.emory.mathcs.backport/3.0.0/com.springsource.edu.emory.mathcs.backport-sources-3.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.ejb/com.springsource.javax.ejb/3.0.0/com.springsource.javax.ejb-3.0.0.jar" sourcepath="/IVY_CACHE/javax.ejb/com.springsource.javax.ejb/3.0.0/com.springsource.javax.ejb-sources-3.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.inject/com.springsource.javax.inject/1.0.0/com.springsource.javax.inject-1.0.0.jar" sourcepath="/IVY_CACHE/javax.inject/com.springsource.javax.inject/1.0.0/com.springsource.javax.inject-sources-1.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.jms/com.springsource.javax.jms/1.1.0/com.springsource.javax.jms-1.1.0.jar" sourcepath="/IVY_CACHE/javax.jms/com.springsource.javax.jms/1.1.0/com.springsource.javax.jms-sources-1.1.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 kind="var" path="IVY_CACHE/javax.transaction/com.springsource.javax.transaction/1.1.0/com.springsource.javax.transaction-1.1.0.jar" sourcepath="/IVY_CACHE/javax.transaction/com.springsource.javax.transaction/1.1.0/com.springsource.javax.transaction-sources-1.1.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.validation/com.springsource.javax.validation/1.0.0.GA/com.springsource.javax.validation-1.0.0.GA.jar" sourcepath="/IVY_CACHE/javax.validation/com.springsource.javax.validation/1.0.0/com.springsource.javax.validation-sources-1.0.0.GA.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.xml.rpc/com.springsource.javax.xml.rpc/1.1.0/com.springsource.javax.xml.rpc-1.1.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.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.dbcp/1.2.2.osgi/com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.dbcp/1.2.2.osgi/com.springsource.org.apache.commons.dbcp-sources-1.2.2.osgi.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.apache.commons/com.springsource.org.apache.commons.pool/1.5.3/com.springsource.org.apache.commons.pool-1.5.3.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.pool/1.5.3/com.springsource.org.apache.commons.pool-sources-1.5.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.aspectj/com.springsource.org.aspectj.weaver/1.6.8.RELEASE/com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.beanshell/com.springsource.bsh/2.0.0.b4/com.springsource.bsh-2.0.0.b4.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.codehaus.groovy/com.springsource.org.codehaus.groovy/1.6.5/com.springsource.org.codehaus.groovy-1.6.5.jar" sourcepath="/IVY_CACHE/org.codehaus.groovy/com.springsource.org.codehaus.groovy/1.6.5/com.springsource.org.codehaus.groovy-sources-1.6.5.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/org.joda/com.springsource.org.joda.time/1.6.0/com.springsource.org.joda.time-1.6.0.jar" sourcepath="/IVY_CACHE/org.joda/com.springsource.org.joda.time/1.6.0/com.springsource.org.joda.time-sources-1.6.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.jruby/com.springsource.org.jruby/1.4.0/com.springsource.org.jruby-1.4.0.jar" sourcepath="/IVY_CACHE/org.jruby/com.springsource.org.jruby/1.4.0/com.springsource.org.jruby-sources-1.4.0.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.inject/com.springsource.org.atinject.tck/1.0.0/com.springsource.org.atinject.tck-1.0.0.jar" sourcepath="/IVY_CACHE/javax.inject/com.springsource.org.atinject.tck/1.0.0/com.springsource.org.atinject.tck-sources-1.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.hibernate/com.springsource.org.hibernate.validator/4.0.2.GA/com.springsource.org.hibernate.validator-4.0.2.GA.jar"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.dbcp" rev="1.2.2.osgi" conf="test->runtime"/>
|
||||
<dependency org="org.apache.log4j" name="com.springsource.org.apache.log4j" rev="1.2.15" conf="test->runtime"/>
|
||||
<dependency org="org.easymock" name="com.springsource.org.easymock" rev="2.5.1" conf="test->compile"/>
|
||||
<dependency org="org.hibernate" name="com.springsource.org.hibernate.validator" rev="4.0.0.GA" conf="test->runtime"/>
|
||||
<dependency org="org.hibernate" name="com.springsource.org.hibernate.validator" rev="4.0.2.GA" conf="test->runtime"/>
|
||||
<dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit.version}" conf="test->runtime"/>
|
||||
<dependency org="org.slf4j" name="com.springsource.slf4j.jcl" rev="${slf4j.version}" conf="test->runtime"/>
|
||||
</dependencies>
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.1.RELEASE</version>
|
||||
<version>3.0.2.RELEASE</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.1.RELEASE</version>
|
||||
<version>3.0.2.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
@@ -191,7 +191,7 @@
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
<version>4.0.0.GA</version>
|
||||
<version>4.0.2.GA</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
+2
-1
@@ -856,7 +856,8 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
*/
|
||||
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
|
||||
// Initialize conversion service for this context.
|
||||
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME)) {
|
||||
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
|
||||
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
|
||||
beanFactory.setConversionService(
|
||||
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
|
||||
}
|
||||
|
||||
+15
-15
@@ -237,7 +237,7 @@ public abstract class JmxUtils {
|
||||
* @return the bean class to expose
|
||||
* @see org.springframework.util.ClassUtils#getUserClass(Object)
|
||||
*/
|
||||
public static Class getClassToExpose(Object managedBean) {
|
||||
public static Class<?> getClassToExpose(Object managedBean) {
|
||||
return ClassUtils.getUserClass(managedBean);
|
||||
}
|
||||
|
||||
@@ -247,12 +247,12 @@ public abstract class JmxUtils {
|
||||
* (for example, checked for annotations).
|
||||
* <p>This implementation returns the superclass for a CGLIB proxy and
|
||||
* the class of the given bean else (for a JDK proxy or a plain bean class).
|
||||
* @param beanClass the bean class (might be an AOP proxy class)
|
||||
* @param clazz the bean class (might be an AOP proxy class)
|
||||
* @return the bean class to expose
|
||||
* @see org.springframework.util.ClassUtils#getUserClass(Class)
|
||||
*/
|
||||
public static Class getClassToExpose(Class beanClass) {
|
||||
return ClassUtils.getUserClass(beanClass);
|
||||
public static Class<?> getClassToExpose(Class<?> clazz) {
|
||||
return ClassUtils.getUserClass(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -260,14 +260,14 @@ public abstract class JmxUtils {
|
||||
* <p>This implementation checks for {@link javax.management.DynamicMBean}
|
||||
* classes as well as classes with corresponding "*MBean" interface
|
||||
* (Standard MBeans) or corresponding "*MXBean" interface (Java 6 MXBeans).
|
||||
* @param beanClass the bean class to analyze
|
||||
* @param clazz the bean class to analyze
|
||||
* @return whether the class qualifies as an MBean
|
||||
* @see org.springframework.jmx.export.MBeanExporter#isMBean(Class)
|
||||
*/
|
||||
public static boolean isMBean(Class beanClass) {
|
||||
return (beanClass != null &&
|
||||
(DynamicMBean.class.isAssignableFrom(beanClass) ||
|
||||
(getMBeanInterface(beanClass) != null || getMXBeanInterface(beanClass) != null)));
|
||||
public static boolean isMBean(Class<?> clazz) {
|
||||
return (clazz != null &&
|
||||
(DynamicMBean.class.isAssignableFrom(clazz) ||
|
||||
(getMBeanInterface(clazz) != null || getMXBeanInterface(clazz) != null)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -277,13 +277,13 @@ public abstract class JmxUtils {
|
||||
* @param clazz the class to check
|
||||
* @return the Standard MBean interface for the given class
|
||||
*/
|
||||
public static Class getMBeanInterface(Class clazz) {
|
||||
if (clazz.getSuperclass() == null) {
|
||||
public static Class<?> getMBeanInterface(Class<?> clazz) {
|
||||
if (clazz == null || clazz.getSuperclass() == null) {
|
||||
return null;
|
||||
}
|
||||
String mbeanInterfaceName = clazz.getName() + MBEAN_SUFFIX;
|
||||
Class[] implementedInterfaces = clazz.getInterfaces();
|
||||
for (Class iface : implementedInterfaces) {
|
||||
for (Class<?> iface : implementedInterfaces) {
|
||||
if (iface.getName().equals(mbeanInterfaceName)) {
|
||||
return iface;
|
||||
}
|
||||
@@ -298,12 +298,12 @@ public abstract class JmxUtils {
|
||||
* @param clazz the class to check
|
||||
* @return whether there is an MXBean interface for the given class
|
||||
*/
|
||||
public static Class getMXBeanInterface(Class clazz) {
|
||||
if (clazz.getSuperclass() == null) {
|
||||
public static Class<?> getMXBeanInterface(Class<?> clazz) {
|
||||
if (clazz == null || clazz.getSuperclass() == null) {
|
||||
return null;
|
||||
}
|
||||
Class[] implementedInterfaces = clazz.getInterfaces();
|
||||
for (Class iface : implementedInterfaces) {
|
||||
for (Class<?> iface : implementedInterfaces) {
|
||||
boolean isMxBean = iface.getName().endsWith(MXBEAN_SUFFIX);
|
||||
if (mxBeanAnnotationAvailable) {
|
||||
Boolean checkResult = MXBeanChecker.evaluateMXBeanAnnotation(iface);
|
||||
|
||||
+4
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* 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.
|
||||
@@ -17,13 +17,13 @@
|
||||
package org.springframework.scheduling.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.framework.AopInfrastructureBean;
|
||||
import org.springframework.aop.framework.ProxyConfig;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
@@ -32,8 +32,6 @@ import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* Bean post-processor that automatically applies asynchronous invocation
|
||||
* behavior to any bean that carries the {@link Async} annotation at class or
|
||||
@@ -105,22 +103,16 @@ public class AsyncAnnotationBeanPostProcessor extends ProxyConfig
|
||||
}
|
||||
|
||||
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) {
|
||||
return bean;
|
||||
}
|
||||
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) {
|
||||
if (bean instanceof AopInfrastructureBean) {
|
||||
// Ignore AOP infrastructure such as scoped proxies.
|
||||
return bean;
|
||||
}
|
||||
|
||||
Class<?> targetClass = AopUtils.getTargetClass(bean);
|
||||
if (targetClass == null) {
|
||||
// Can't do much here.
|
||||
return bean;
|
||||
}
|
||||
|
||||
if (AopUtils.canApply(this.asyncAnnotationAdvisor, targetClass)) {
|
||||
if (bean instanceof Advised) {
|
||||
((Advised) bean).addAdvisor(this.asyncAnnotationAdvisor);
|
||||
|
||||
+1
-4
@@ -26,7 +26,7 @@ import java.lang.annotation.Target;
|
||||
* Annotation that marks a method to be scheduled. Exactly one of the
|
||||
* <code>cron</code>, <code>fixedDelay</code>, or <code>fixedRate</code>
|
||||
* attributes must be provided.
|
||||
*
|
||||
*
|
||||
* <p>The annotated method must expect no arguments and have a
|
||||
* <code>void</code> return type.
|
||||
*
|
||||
@@ -45,7 +45,6 @@ public @interface Scheduled {
|
||||
* triggers on the second as well as minute, hour, day of month, month
|
||||
* and day of week. e.g. <code>"0 * * * * MON-FRI"</code> means once
|
||||
* per minute on weekdays (at the top of the minute - the 0th second).
|
||||
*
|
||||
* @return an expression that can be parsed to a cron schedule
|
||||
*/
|
||||
String cron() default "";
|
||||
@@ -53,14 +52,12 @@ public @interface Scheduled {
|
||||
/**
|
||||
* Execute the annotated method with a fixed period between the end
|
||||
* of the last invocation and the start of the next.
|
||||
*
|
||||
* @return the delay in milliseconds
|
||||
*/
|
||||
long fixedDelay() default -1;
|
||||
|
||||
/**
|
||||
* Execute the annotated method with a fixed period between invocations.
|
||||
*
|
||||
* @return the period in milliseconds
|
||||
*/
|
||||
long fixedRate() default -1;
|
||||
|
||||
+2
-6
@@ -21,7 +21,6 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
@@ -82,15 +81,12 @@ public class ScheduledAnnotationBeanPostProcessor implements BeanPostProcessor,
|
||||
}
|
||||
|
||||
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) {
|
||||
return bean;
|
||||
}
|
||||
|
||||
public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
|
||||
public Object postProcessAfterInitialization(final Object bean, String beanName) {
|
||||
Class<?> targetClass = AopUtils.getTargetClass(bean);
|
||||
if (targetClass == null) {
|
||||
return bean;
|
||||
}
|
||||
ReflectionUtils.doWithMethods(targetClass, new MethodCallback() {
|
||||
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
|
||||
Scheduled annotation = AnnotationUtils.getAnnotation(method, Scheduled.class);
|
||||
|
||||
+8
-1
@@ -20,6 +20,7 @@ import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.BeanWrapperImpl;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.JdkVersion;
|
||||
@@ -33,7 +34,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Mark Fisher
|
||||
* @since 3.0
|
||||
*/
|
||||
public class TaskExecutorFactoryBean implements FactoryBean<TaskExecutor>, BeanNameAware {
|
||||
public class TaskExecutorFactoryBean implements FactoryBean<TaskExecutor>, BeanNameAware, DisposableBean {
|
||||
|
||||
private volatile TaskExecutor target;
|
||||
|
||||
@@ -89,6 +90,12 @@ public class TaskExecutorFactoryBean implements FactoryBean<TaskExecutor>, BeanN
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void destroy() throws Exception {
|
||||
if (this.target instanceof DisposableBean) {
|
||||
((DisposableBean) this.target).destroy();
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeExecutor() throws Exception {
|
||||
synchronized (this.initializationMonitor) {
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ import org.springframework.util.StringUtils;
|
||||
* @since 3.0
|
||||
* @see CronTrigger
|
||||
*/
|
||||
class CronSequenceGenerator {
|
||||
public class CronSequenceGenerator {
|
||||
|
||||
private final BitSet seconds = new BitSet(60);
|
||||
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* 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.
|
||||
@@ -130,9 +130,9 @@ public abstract class AbstractBindingResult extends AbstractErrors implements Bi
|
||||
}
|
||||
|
||||
public String[] resolveMessageCodes(String errorCode, String field) {
|
||||
String fixedField = fixedField(field);
|
||||
Class fieldType = getFieldType(fixedField);
|
||||
return getMessageCodesResolver().resolveMessageCodes(errorCode, getObjectName(), fixedField, fieldType);
|
||||
Class fieldType = getFieldType(field);
|
||||
return getMessageCodesResolver().resolveMessageCodes(
|
||||
errorCode, getObjectName(), fixedField(field), fieldType);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+4
@@ -495,7 +495,11 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
|
||||
* property values, as an alternative to JavaBeans PropertyEditors.
|
||||
*/
|
||||
public void setConversionService(ConversionService conversionService) {
|
||||
Assert.state(this.conversionService == null, "DataBinder is already initialized with ConversionService");
|
||||
this.conversionService = conversionService;
|
||||
if (this.bindingResult != null && conversionService != null) {
|
||||
this.bindingResult.initConversion(conversionService);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+6
-1
@@ -5,7 +5,8 @@
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd
|
||||
http://www.springframework.org/schema/beans/test http://www.springframework.org/schema/beans/factory/xml/support/CustomNamespaceHandlerTests.xsd">
|
||||
http://www.springframework.org/schema/beans/test http://www.springframework.org/schema/beans/factory/xml/support/CustomNamespaceHandlerTests.xsd"
|
||||
default-lazy-init="true">
|
||||
|
||||
<test:testBean id="testBean" name="Rob Harrop" age="23"/>
|
||||
|
||||
@@ -19,6 +20,10 @@
|
||||
<property name="age" value="23"/>
|
||||
</bean>
|
||||
|
||||
<bean id="debuggingTestBeanNoInstance" class="org.springframework.context.ApplicationListener">
|
||||
<test:debug/>
|
||||
</bean>
|
||||
|
||||
<bean id="chainedTestBean" class="org.springframework.beans.TestBean">
|
||||
<test:debug/>
|
||||
<test:nop/>
|
||||
|
||||
+36
-19
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* 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.
|
||||
@@ -16,24 +16,32 @@
|
||||
|
||||
package org.springframework.beans.factory.xml.support;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import static java.lang.String.format;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.InputSource;
|
||||
import test.interceptor.NopInterceptor;
|
||||
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.config.AbstractInterceptorDrivenBeanDefinitionDecorator;
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.interceptor.DebugInterceptor;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.BeanInstantiationException;
|
||||
import org.springframework.beans.ITestBean;
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.TestBean;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
@@ -49,14 +57,10 @@ import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.beans.factory.xml.PluggableSchemaResolver;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
import test.interceptor.NopInterceptor;
|
||||
|
||||
/**
|
||||
* Unit tests for custom XML namespace handler implementations.
|
||||
@@ -65,7 +69,7 @@ import test.interceptor.NopInterceptor;
|
||||
* @author Rick Evans
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class CustomNamespaceHandlerTests {
|
||||
public class CustomNamespaceHandlerTests {
|
||||
|
||||
private static final Class<?> CLASS = CustomNamespaceHandlerTests.class;
|
||||
private static final String CLASSNAME = CLASS.getSimpleName();
|
||||
@@ -75,46 +79,60 @@ public final class CustomNamespaceHandlerTests {
|
||||
private static final String NS_XML = format("%s/%s-context.xml", FQ_PATH, CLASSNAME);
|
||||
private static final String TEST_XSD = format("%s/%s.xsd", FQ_PATH, CLASSNAME);
|
||||
|
||||
private DefaultListableBeanFactory beanFactory;
|
||||
private GenericApplicationContext beanFactory;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
NamespaceHandlerResolver resolver = new DefaultNamespaceHandlerResolver(CLASS.getClassLoader(), NS_PROPS);
|
||||
this.beanFactory = new DefaultListableBeanFactory();
|
||||
this.beanFactory = new GenericApplicationContext();
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this.beanFactory);
|
||||
reader.setNamespaceHandlerResolver(resolver);
|
||||
reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_XSD);
|
||||
reader.setEntityResolver(new DummySchemaResolver());
|
||||
reader.loadBeanDefinitions(getResource());
|
||||
this.beanFactory.refresh();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSimpleParser() throws Exception {
|
||||
TestBean bean = (TestBean) this.beanFactory.getBean("testBean");
|
||||
assetTestBean(bean);
|
||||
assertTestBean(bean);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleDecorator() throws Exception {
|
||||
TestBean bean = (TestBean) this.beanFactory.getBean("customisedTestBean");
|
||||
assetTestBean(bean);
|
||||
assertTestBean(bean);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProxyingDecorator() throws Exception {
|
||||
ITestBean bean = (ITestBean) this.beanFactory.getBean("debuggingTestBean");
|
||||
assetTestBean(bean);
|
||||
assertTestBean(bean);
|
||||
assertTrue(AopUtils.isAopProxy(bean));
|
||||
Advisor[] advisors = ((Advised) bean).getAdvisors();
|
||||
assertEquals("Incorrect number of advisors", 1, advisors.length);
|
||||
assertEquals("Incorrect advice class.", DebugInterceptor.class, advisors[0].getAdvice().getClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProxyingDecoratorNoInstance() throws Exception {
|
||||
String[] beanNames = this.beanFactory.getBeanNamesForType(ApplicationListener.class);
|
||||
assertTrue(Arrays.asList(beanNames).contains("debuggingTestBeanNoInstance"));
|
||||
try {
|
||||
this.beanFactory.getBean("debuggingTestBeanNoInstance");
|
||||
fail("Should have thrown BeanCreationException");
|
||||
}
|
||||
catch (BeanCreationException ex) {
|
||||
assertTrue(ex.getRootCause() instanceof BeanInstantiationException);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChainedDecorators() throws Exception {
|
||||
ITestBean bean = (ITestBean) this.beanFactory.getBean("chainedTestBean");
|
||||
assetTestBean(bean);
|
||||
assertTestBean(bean);
|
||||
assertTrue(AopUtils.isAopProxy(bean));
|
||||
Advisor[] advisors = ((Advised) bean).getAdvisors();
|
||||
assertEquals("Incorrect number of advisors", 2, advisors.length);
|
||||
@@ -159,7 +177,7 @@ public final class CustomNamespaceHandlerTests {
|
||||
}
|
||||
|
||||
|
||||
private void assetTestBean(ITestBean bean) {
|
||||
private void assertTestBean(ITestBean bean) {
|
||||
assertEquals("Invalid name", "Rob Harrop", bean.getName());
|
||||
assertEquals("Invalid age", 23, bean.getAge());
|
||||
}
|
||||
@@ -175,7 +193,6 @@ public final class CustomNamespaceHandlerTests {
|
||||
super(CLASS.getClassLoader());
|
||||
}
|
||||
|
||||
|
||||
public InputSource resolveEntity(String publicId, String systemId) throws IOException {
|
||||
InputSource source = super.resolveEntity(publicId, systemId);
|
||||
if (source == null) {
|
||||
|
||||
+26
@@ -27,6 +27,7 @@ import static org.junit.matchers.JUnitMatchers.*;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.context.annotation6.ComponentForScanning;
|
||||
import org.springframework.context.annotation6.ConfigForScanning;
|
||||
import org.springframework.context.annotation6.Jsr330NamedForScanning;
|
||||
@@ -154,6 +155,31 @@ public class AnnotationConfigApplicationContextTests {
|
||||
assertThat(context.getBean(TestBean.class).name, equalTo("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullReturningBeanPostProcessor() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
context.register(AutowiredConfig.class);
|
||||
context.getBeanFactory().addBeanPostProcessor(new BeanPostProcessor() {
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) {
|
||||
return (bean instanceof TestBean ? null : bean);
|
||||
}
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) {
|
||||
return bean;
|
||||
}
|
||||
});
|
||||
context.getBeanFactory().addBeanPostProcessor(new BeanPostProcessor() {
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) {
|
||||
bean.getClass().getName();
|
||||
return bean;
|
||||
}
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) {
|
||||
bean.getClass().getName();
|
||||
return bean;
|
||||
}
|
||||
});
|
||||
context.refresh();
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
|
||||
+5
-6
@@ -1,12 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<bean id="foo" class="org.springframework.context.annotation.Foo">
|
||||
<constructor-arg ref="barFactory"/>
|
||||
<bean id="foo" class="org.springframework.context.annotation.Spr6602Tests$Foo">
|
||||
<constructor-arg ref="barFactory" />
|
||||
</bean>
|
||||
|
||||
<bean id="barFactory" class="org.springframework.context.annotation.BarFactory"/>
|
||||
|
||||
<bean id="barFactory" class="org.springframework.context.annotation.Spr6602Tests$BarFactory" />
|
||||
|
||||
</beans>
|
||||
|
||||
+41
-32
@@ -36,58 +36,67 @@ public class Spr6602Tests {
|
||||
public void testXmlBehavior() throws Exception {
|
||||
doAssertions(new ClassPathXmlApplicationContext("Spr6602Tests-context.xml", Spr6602Tests.class));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testConfigurationClassBehavior() throws Exception {
|
||||
doAssertions(new AnnotationConfigApplicationContext(FooConfig.class));
|
||||
}
|
||||
|
||||
|
||||
private void doAssertions(ApplicationContext ctx) throws Exception {
|
||||
Foo foo = ctx.getBean(Foo.class);
|
||||
|
||||
|
||||
Bar bar1 = ctx.getBean(Bar.class);
|
||||
Bar bar2 = ctx.getBean(Bar.class);
|
||||
assertThat(bar1, is(bar2));
|
||||
assertThat(bar1, is(foo.bar));
|
||||
|
||||
|
||||
BarFactory barFactory1 = ctx.getBean(BarFactory.class);
|
||||
BarFactory barFactory2 = ctx.getBean(BarFactory.class);
|
||||
assertThat(barFactory1, is(barFactory2));
|
||||
|
||||
|
||||
Bar bar3 = barFactory1.getObject();
|
||||
Bar bar4 = barFactory1.getObject();
|
||||
assertThat(bar3, is(not(bar4)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class FooConfig {
|
||||
@Bean
|
||||
public Foo foo() throws Exception {
|
||||
return new Foo(barFactory().getObject());
|
||||
}
|
||||
|
||||
@Configuration
|
||||
class FooConfig {
|
||||
public @Bean Foo foo() throws Exception {
|
||||
return new Foo(barFactory().getObject());
|
||||
}
|
||||
|
||||
public @Bean BarFactory barFactory() {
|
||||
return new BarFactory();
|
||||
}
|
||||
}
|
||||
|
||||
class Foo { final Bar bar; public Foo(Bar bar) { this.bar = bar; } }
|
||||
class Bar { }
|
||||
|
||||
class BarFactory implements FactoryBean<Bar> {
|
||||
|
||||
public Bar getObject() throws Exception {
|
||||
return new Bar();
|
||||
@Bean
|
||||
public BarFactory barFactory() {
|
||||
return new BarFactory();
|
||||
}
|
||||
}
|
||||
|
||||
public Class<? extends Bar> getObjectType() {
|
||||
return Bar.class;
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
public static class Foo {
|
||||
final Bar bar;
|
||||
|
||||
public Foo(Bar bar) {
|
||||
this.bar = bar;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public static class Bar {
|
||||
}
|
||||
|
||||
public static class BarFactory implements FactoryBean<Bar> {
|
||||
|
||||
public Bar getObject() throws Exception {
|
||||
return new Bar();
|
||||
}
|
||||
|
||||
public Class<? extends Bar> getObjectType() {
|
||||
return Bar.class;
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+16
-3
@@ -249,7 +249,6 @@ public class ApplicationContextExpressionTests {
|
||||
GenericApplicationContext ac = new GenericApplicationContext();
|
||||
AnnotationConfigUtils.registerAnnotationConfigProcessors(ac);
|
||||
|
||||
|
||||
GenericBeanDefinition bd = new GenericBeanDefinition();
|
||||
bd.setBeanClass(TestBean.class);
|
||||
bd.getPropertyValues().add("country", "#{systemProperties.country}");
|
||||
@@ -264,12 +263,10 @@ public class ApplicationContextExpressionTests {
|
||||
public void checkPropertiesAccess() {
|
||||
throw new AccessControlException("Not Allowed");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkPermission(Permission perm) {
|
||||
// allow everything else
|
||||
}
|
||||
|
||||
};
|
||||
System.setSecurityManager(securityManager);
|
||||
ac.refresh();
|
||||
@@ -284,6 +281,22 @@ public class ApplicationContextExpressionTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stringConcatenationWithDebugLogging() {
|
||||
GenericApplicationContext ac = new GenericApplicationContext();
|
||||
AnnotationConfigUtils.registerAnnotationConfigProcessors(ac);
|
||||
|
||||
GenericBeanDefinition bd = new GenericBeanDefinition();
|
||||
bd.setBeanClass(String.class);
|
||||
bd.getConstructorArgumentValues().addGenericArgumentValue("test-#{ T(java.lang.System).currentTimeMillis() }");
|
||||
ac.registerBeanDefinition("str", bd);
|
||||
ac.refresh();
|
||||
|
||||
String str = ac.getBean("str", String.class);
|
||||
assertTrue(str.startsWith("test-"));
|
||||
}
|
||||
|
||||
|
||||
public static class ValueTestBean implements Serializable {
|
||||
|
||||
@Autowired @Value("XXX#{tb0.name}YYY#{mySpecialAttr}ZZZ")
|
||||
|
||||
+78
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* 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.
|
||||
@@ -327,6 +327,83 @@ public class DataBinderTests extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testBindingErrorWithFormatter() {
|
||||
TestBean tb = new TestBean();
|
||||
DataBinder binder = new DataBinder(tb);
|
||||
FormattingConversionService conversionService = new FormattingConversionService();
|
||||
ConversionServiceFactory.addDefaultConverters(conversionService);
|
||||
conversionService.addFormatterForFieldType(Float.class, new NumberFormatter());
|
||||
binder.setConversionService(conversionService);
|
||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||
pvs.add("myFloat", "1x2");
|
||||
|
||||
LocaleContextHolder.setLocale(Locale.GERMAN);
|
||||
try {
|
||||
binder.bind(pvs);
|
||||
assertEquals(new Float(0.0), tb.getMyFloat());
|
||||
assertEquals("1x2", binder.getBindingResult().getFieldValue("myFloat"));
|
||||
assertTrue(binder.getBindingResult().hasFieldErrors("myFloat"));
|
||||
}
|
||||
finally {
|
||||
LocaleContextHolder.resetLocaleContext();
|
||||
}
|
||||
}
|
||||
|
||||
public void testBindingWithFormatterAgainstFields() {
|
||||
TestBean tb = new TestBean();
|
||||
DataBinder binder = new DataBinder(tb);
|
||||
FormattingConversionService conversionService = new FormattingConversionService();
|
||||
ConversionServiceFactory.addDefaultConverters(conversionService);
|
||||
conversionService.addFormatterForFieldType(Float.class, new NumberFormatter());
|
||||
binder.setConversionService(conversionService);
|
||||
binder.initDirectFieldAccess();
|
||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||
pvs.add("myFloat", "1,2");
|
||||
|
||||
LocaleContextHolder.setLocale(Locale.GERMAN);
|
||||
try {
|
||||
binder.bind(pvs);
|
||||
assertEquals(new Float(1.2), tb.getMyFloat());
|
||||
assertEquals("1,2", binder.getBindingResult().getFieldValue("myFloat"));
|
||||
|
||||
PropertyEditor editor = binder.getBindingResult().findEditor("myFloat", Float.class);
|
||||
assertNotNull(editor);
|
||||
editor.setValue(new Float(1.4));
|
||||
assertEquals("1,4", editor.getAsText());
|
||||
|
||||
editor = binder.getBindingResult().findEditor("myFloat", null);
|
||||
assertNotNull(editor);
|
||||
editor.setAsText("1,6");
|
||||
assertEquals(new Float(1.6), editor.getValue());
|
||||
}
|
||||
finally {
|
||||
LocaleContextHolder.resetLocaleContext();
|
||||
}
|
||||
}
|
||||
|
||||
public void testBindingErrorWithFormatterAgainstFields() {
|
||||
TestBean tb = new TestBean();
|
||||
DataBinder binder = new DataBinder(tb);
|
||||
binder.initDirectFieldAccess();
|
||||
FormattingConversionService conversionService = new FormattingConversionService();
|
||||
ConversionServiceFactory.addDefaultConverters(conversionService);
|
||||
conversionService.addFormatterForFieldType(Float.class, new NumberFormatter());
|
||||
binder.setConversionService(conversionService);
|
||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||
pvs.add("myFloat", "1x2");
|
||||
|
||||
LocaleContextHolder.setLocale(Locale.GERMAN);
|
||||
try {
|
||||
binder.bind(pvs);
|
||||
assertEquals(new Float(0.0), tb.getMyFloat());
|
||||
assertEquals("1x2", binder.getBindingResult().getFieldValue("myFloat"));
|
||||
assertTrue(binder.getBindingResult().hasFieldErrors("myFloat"));
|
||||
}
|
||||
finally {
|
||||
LocaleContextHolder.resetLocaleContext();
|
||||
}
|
||||
}
|
||||
|
||||
public void testBindingWithAllowedFields() throws Exception {
|
||||
TestBean rod = new TestBean();
|
||||
DataBinder binder = new DataBinder(rod);
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* 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.
|
||||
@@ -131,7 +131,7 @@ public class ValidatorFactoryTests {
|
||||
|
||||
|
||||
@NameAddressValid
|
||||
private static class ValidPerson {
|
||||
public static class ValidPerson {
|
||||
|
||||
@NotNull
|
||||
private String name;
|
||||
@@ -157,7 +157,7 @@ public class ValidatorFactoryTests {
|
||||
}
|
||||
|
||||
|
||||
private static class ValidAddress {
|
||||
public static class ValidAddress {
|
||||
|
||||
@NotNull
|
||||
private String street;
|
||||
|
||||
@@ -4,7 +4,7 @@ Bundle-Vendor: SpringSource
|
||||
Bundle-ManifestVersion: 2
|
||||
Import-Package:
|
||||
javax.persistence;version="[1.0.0, 3.0.0)";resolution:=optional,
|
||||
org.springframework.orm.jpa.support;version="[3.0.0, 3.0.1)";resolution:=optional,
|
||||
org.springframework.orm.jpa.support;version="${spring.osgi.range.nq}";resolution:=optional,
|
||||
com.ibm.websphere.management;version="0";resolution:=optional
|
||||
Import-Template:
|
||||
bsh.*;version="[2.0.0.b4, 3.0.0)";resolution:=optional,
|
||||
@@ -25,17 +25,17 @@ Import-Template:
|
||||
net.sf.cglib.*;version="[2.1.3, 3.0.0)";resolution:=optional,
|
||||
org.aopalliance.*;version="[1.0.0, 2.0.0)";resolution:=optional,
|
||||
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
|
||||
org.aspectj.weaver.*;version="[1.5.4, 2.0.0)";resolution:=optional,
|
||||
org.aspectj.weaver.*;version=${aj.osgi.range};resolution:=optional,
|
||||
org.codehaus.groovy.*;version="[1.5.0, 2.0.0)";resolution:=optional,
|
||||
org.joda.*;version="[1.6.0, 2.0.0)";resolution:=optional,
|
||||
org.jruby.*;version="[1.1.0, 2.0.0)";resolution:=optional,
|
||||
org.omg.CORBA.*;version="0";resolution:=optional,
|
||||
org.springframework.aop.*;version="[3.0.0, 3.0.1)";resolution:=optional,
|
||||
org.springframework.beans.*;version="[3.0.0, 3.0.1)",
|
||||
org.springframework.core.*;version="[3.0.0, 3.0.1)",
|
||||
org.springframework.expression.*;version="[3.0.0, 3.0.1)";resolution:=optional,
|
||||
org.springframework.aop.*;version=${spring.osgi.range};resolution:=optional,
|
||||
org.springframework.beans.*;version=${spring.osgi.range},
|
||||
org.springframework.core.*;version=${spring.osgi.range},
|
||||
org.springframework.expression.*;version=${spring.osgi.range};resolution:=optional,
|
||||
org.springframework.instrument.*;version="0";resolution:=optional,
|
||||
org.springframework.util.*;version="[3.0.0, 3.0.1)",
|
||||
org.springframework.util.*;version=${spring.osgi.range},
|
||||
org.xml.sax.*;version="0";resolution:=optional,
|
||||
org.w3c.dom.*;version="0";resolution:=optional
|
||||
Ignored-Existing-Headers:
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
<?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.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.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.6.0.jar"/>
|
||||
<?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.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.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.6.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"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.servlet/com.springsource.javax.servlet/2.5.0/com.springsource.javax.servlet-2.5.0.jar" sourcepath="/IVY_CACHE/javax.servlet/com.springsource.javax.servlet/2.5.0/com.springsource.javax.servlet-sources-2.5.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.custommonkey.xmlunit/com.springsource.org.custommonkey.xmlunit/1.2.0/com.springsource.org.custommonkey.xmlunit-1.2.0.jar" sourcepath="/IVY_CACHE/org.custommonkey.xmlunit/com.springsource.org.custommonkey.xmlunit/1.2.0/com.springsource.org.custommonkey.xmlunit-sources-1.2.0.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/org.codehaus.woodstox/com.springsource.com.ctc.wstx/3.2.7/com.springsource.com.ctc.wstx-3.2.7.jar" sourcepath="/IVY_CACHE/org.codehaus.woodstox/com.springsource.com.ctc.wstx/3.2.7/com.springsource.com.ctc.wstx-sources-3.2.7.jar"/>
|
||||
<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/org.jboss.vfs/com.springsource.org.jboss.virtual/2.1.0.GA/com.springsource.org.jboss.virtual-2.1.0.GA.jar"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.servlet/com.springsource.javax.servlet/2.5.0/com.springsource.javax.servlet-2.5.0.jar" sourcepath="/IVY_CACHE/javax.servlet/com.springsource.javax.servlet/2.5.0/com.springsource.javax.servlet-sources-2.5.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.custommonkey.xmlunit/com.springsource.org.custommonkey.xmlunit/1.2.0/com.springsource.org.custommonkey.xmlunit-1.2.0.jar" sourcepath="/IVY_CACHE/org.custommonkey.xmlunit/com.springsource.org.custommonkey.xmlunit/1.2.0/com.springsource.org.custommonkey.xmlunit-sources-1.2.0.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/org.codehaus.woodstox/com.springsource.com.ctc.wstx/3.2.7/com.springsource.com.ctc.wstx-3.2.7.jar" sourcepath="/IVY_CACHE/org.codehaus.woodstox/com.springsource.com.ctc.wstx/3.2.7/com.springsource.com.ctc.wstx-sources-3.2.7.jar"/>
|
||||
<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/org.jboss.vfs/com.springsource.org.jboss.virtual/2.1.0.GA/com.springsource.org.jboss.virtual-2.1.0.GA.jar"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.1.RELEASE</version>
|
||||
<version>3.0.2.RELEASE</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.1.RELEASE</version>
|
||||
<version>3.0.2.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
+26
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* 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.
|
||||
@@ -18,6 +18,7 @@ package org.springframework.core;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
@@ -146,14 +147,7 @@ public abstract class GenericTypeResolver {
|
||||
Class[] result = new Class[typeArgs.length];
|
||||
for (int i = 0; i < typeArgs.length; i++) {
|
||||
Type arg = typeArgs[i];
|
||||
if (arg instanceof TypeVariable) {
|
||||
TypeVariable tv = (TypeVariable) arg;
|
||||
arg = getTypeVariableMap(ownerClass).get(tv);
|
||||
if (arg == null) {
|
||||
arg = extractBoundForTypeVariable(tv);
|
||||
}
|
||||
}
|
||||
result[i] = (arg instanceof Class ? (Class) arg : Object.class);
|
||||
result[i] = extractClass(ownerClass, arg);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -169,6 +163,29 @@ public abstract class GenericTypeResolver {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a class instance from given Type.
|
||||
*/
|
||||
private static Class extractClass(Class ownerClass, Type arg) {
|
||||
if (arg instanceof TypeVariable) {
|
||||
TypeVariable tv = (TypeVariable) arg;
|
||||
arg = getTypeVariableMap(ownerClass).get(tv);
|
||||
if (arg == null) {
|
||||
arg = extractBoundForTypeVariable(tv);
|
||||
}
|
||||
else {
|
||||
arg = extractClass(ownerClass, arg);
|
||||
}
|
||||
}
|
||||
else if (arg instanceof GenericArrayType) {
|
||||
GenericArrayType gat = (GenericArrayType) arg;
|
||||
Type gt = gat.getGenericComponentType();
|
||||
Class<?> componentClass = extractClass(ownerClass, gt);
|
||||
arg = Array.newInstance(componentClass, 0).getClass();
|
||||
}
|
||||
return (arg instanceof Class ? (Class) arg : Object.class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
+7
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* 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.
|
||||
@@ -230,7 +230,12 @@ public class MethodParameter {
|
||||
if (this.parameterAnnotations == null) {
|
||||
Annotation[][] annotationArray = (this.method != null ?
|
||||
this.method.getParameterAnnotations() : this.constructor.getParameterAnnotations());
|
||||
this.parameterAnnotations = annotationArray[this.parameterIndex];
|
||||
if (this.parameterIndex >= 0 && this.parameterIndex < annotationArray.length) {
|
||||
this.parameterAnnotations = annotationArray[this.parameterIndex];
|
||||
}
|
||||
else {
|
||||
this.parameterAnnotations = new Annotation[0];
|
||||
}
|
||||
}
|
||||
return this.parameterAnnotations;
|
||||
}
|
||||
|
||||
+46
-11
@@ -103,8 +103,6 @@ public class TypeDescriptor {
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
// protected constructors for subclasses
|
||||
|
||||
/**
|
||||
* Create a new type descriptor from a method or constructor parameter.
|
||||
* <p>Use this constructor when a target conversion point originates from a method parameter,
|
||||
@@ -112,12 +110,23 @@ public class TypeDescriptor {
|
||||
* @param methodParameter the MethodParameter to wrap
|
||||
* @param type the specific type to expose (may be an array/collection element)
|
||||
*/
|
||||
protected TypeDescriptor(MethodParameter methodParameter, Class<?> type) {
|
||||
public TypeDescriptor(MethodParameter methodParameter, Class<?> type) {
|
||||
Assert.notNull(methodParameter, "MethodParameter must not be null");
|
||||
this.methodParameter = methodParameter;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new type descriptor for a field.
|
||||
* Use this constructor when a target conversion point originates from a field.
|
||||
* @param field the field to wrap
|
||||
*/
|
||||
public TypeDescriptor(Field field, Class<?> type) {
|
||||
Assert.notNull(field, "Field must not be null");
|
||||
this.field = field;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal constructor for a NULL descriptor.
|
||||
*/
|
||||
@@ -227,24 +236,43 @@ public class TypeDescriptor {
|
||||
|
||||
/**
|
||||
* If this type is an array type or {@link Collection} type, returns the underlying element type.
|
||||
* Returns null if the type is neither an array or collection.
|
||||
* Returns <code>null</code> if the type is neither an array or collection.
|
||||
*/
|
||||
public Class<?> getElementType() {
|
||||
return getElementTypeDescriptor().getType();
|
||||
if (isArray()) {
|
||||
return getArrayComponentType();
|
||||
}
|
||||
else if (isCollection()) {
|
||||
return getCollectionElementType();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the element type as a type descriptor.
|
||||
*/
|
||||
public TypeDescriptor getElementTypeDescriptor() {
|
||||
if (isArray()) {
|
||||
return TypeDescriptor.valueOf(getArrayComponentType());
|
||||
return TypeDescriptor.valueOf(getElementType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a copy of this type descriptor, preserving the context information
|
||||
* but exposing the specified element type (e.g. an array/collection element).
|
||||
* @param elementType the desired type to expose
|
||||
* @return the type descriptor
|
||||
*/
|
||||
public TypeDescriptor forElementType(Class<?> elementType) {
|
||||
Assert.notNull(elementType, "Element type must not be null");
|
||||
if (getType().equals(elementType)) {
|
||||
return this;
|
||||
}
|
||||
else if (isCollection()) {
|
||||
return TypeDescriptor.valueOf(getCollectionElementType());
|
||||
else if (this.methodParameter != null) {
|
||||
return new TypeDescriptor(this.methodParameter, elementType);
|
||||
}
|
||||
else {
|
||||
return TypeDescriptor.NULL;
|
||||
return new TypeDescriptor(this.field, elementType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -345,7 +373,14 @@ public class TypeDescriptor {
|
||||
return this.cachedFieldAnnotations;
|
||||
}
|
||||
else if (this.methodParameter != null) {
|
||||
return this.methodParameter.getParameterAnnotations();
|
||||
if (this.methodParameter.getParameterIndex() < 0) {
|
||||
// The best we can do for return type metadata is to expose
|
||||
// method-level annotations when the target is the return type...
|
||||
return this.methodParameter.getMethodAnnotations();
|
||||
}
|
||||
else {
|
||||
return this.methodParameter.getParameterAnnotations();
|
||||
}
|
||||
}
|
||||
else {
|
||||
return new Annotation[0];
|
||||
|
||||
+4
-4
@@ -28,6 +28,7 @@ import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.convert.ConversionFailedException;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
@@ -38,7 +39,6 @@ import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.ConverterFactory;
|
||||
import org.springframework.core.convert.converter.ConverterRegistry;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
import org.springframework.core.style.StylerUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@@ -122,7 +122,7 @@ public class GenericConversionService implements ConversionService, ConverterReg
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
assertNotNull(sourceType, targetType);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Converting value " + StylerUtils.style(source) +" of " + sourceType + " to " + targetType);
|
||||
logger.debug("Converting value of " + sourceType + " to " + targetType);
|
||||
}
|
||||
if (sourceType == TypeDescriptor.NULL) {
|
||||
Assert.isTrue(source == null, "The source must be null if sourceType == TypeDescriptor.NULL");
|
||||
@@ -246,8 +246,8 @@ public class GenericConversionService implements ConversionService, ConverterReg
|
||||
}
|
||||
|
||||
private GenericConverter findConverterForClassPair(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Looking for Converter to convert from " + sourceType + " to " + targetType);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Looking for Converter to convert from " + sourceType + " to " + targetType);
|
||||
}
|
||||
Class<?> sourceObjectType = sourceType.getObjectType();
|
||||
if (sourceObjectType.isInterface()) {
|
||||
|
||||
+13
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* 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.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.beans;
|
||||
package org.springframework.core.convert.support;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.annotation.Annotation;
|
||||
@@ -35,7 +35,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
class BeanTypeDescriptor extends TypeDescriptor {
|
||||
public class PropertyTypeDescriptor extends TypeDescriptor {
|
||||
|
||||
private final PropertyDescriptor propertyDescriptor;
|
||||
|
||||
@@ -45,9 +45,10 @@ class BeanTypeDescriptor extends TypeDescriptor {
|
||||
/**
|
||||
* Create a new BeanTypeDescriptor for the given bean property.
|
||||
* @param propertyDescriptor the corresponding JavaBean PropertyDescriptor
|
||||
* @param methodParameter the target method parameter
|
||||
*/
|
||||
public BeanTypeDescriptor(PropertyDescriptor propertyDescriptor) {
|
||||
super(BeanUtils.getWriteMethodParameter(propertyDescriptor));
|
||||
public PropertyTypeDescriptor(PropertyDescriptor propertyDescriptor, MethodParameter methodParameter) {
|
||||
super(methodParameter);
|
||||
this.propertyDescriptor = propertyDescriptor;
|
||||
}
|
||||
|
||||
@@ -57,7 +58,7 @@ class BeanTypeDescriptor extends TypeDescriptor {
|
||||
* @param methodParameter the target method parameter
|
||||
* @param type the specific type to expose (may be an array/collection element)
|
||||
*/
|
||||
public BeanTypeDescriptor(PropertyDescriptor propertyDescriptor, MethodParameter methodParameter, Class type) {
|
||||
public PropertyTypeDescriptor(PropertyDescriptor propertyDescriptor, MethodParameter methodParameter, Class<?> type) {
|
||||
super(methodParameter, type);
|
||||
this.propertyDescriptor = propertyDescriptor;
|
||||
}
|
||||
@@ -70,7 +71,6 @@ class BeanTypeDescriptor extends TypeDescriptor {
|
||||
return this.propertyDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Annotation[] getAnnotations() {
|
||||
Annotation[] anns = this.cachedAnnotations;
|
||||
if (anns == null) {
|
||||
@@ -82,20 +82,22 @@ class BeanTypeDescriptor extends TypeDescriptor {
|
||||
annMap.put(ann.annotationType(), ann);
|
||||
}
|
||||
}
|
||||
Method targetMethod = getMethodParameter().getMethod();
|
||||
Method writeMethod = this.propertyDescriptor.getWriteMethod();
|
||||
Method readMethod = this.propertyDescriptor.getReadMethod();
|
||||
if (writeMethod != null && writeMethod != targetMethod) {
|
||||
if (writeMethod != null && writeMethod != getMethodParameter().getMethod()) {
|
||||
for (Annotation ann : writeMethod.getAnnotations()) {
|
||||
annMap.put(ann.annotationType(), ann);
|
||||
}
|
||||
}
|
||||
if (readMethod != null && readMethod != targetMethod) {
|
||||
if (readMethod != null && readMethod != getMethodParameter().getMethod()) {
|
||||
for (Annotation ann : readMethod.getAnnotations()) {
|
||||
annMap.put(ann.annotationType(), ann);
|
||||
}
|
||||
}
|
||||
for (Annotation ann : targetMethod.getAnnotations()) {
|
||||
for (Annotation ann : getMethodParameter().getMethodAnnotations()) {
|
||||
annMap.put(ann.annotationType(), ann);
|
||||
}
|
||||
for (Annotation ann : getMethodParameter().getParameterAnnotations()) {
|
||||
annMap.put(ann.annotationType(), ann);
|
||||
}
|
||||
anns = annMap.values().toArray(new Annotation[annMap.size()]);
|
||||
+14
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* 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.
|
||||
@@ -45,7 +45,7 @@ public class ClassPathResource extends AbstractFileResolvingResource {
|
||||
|
||||
private ClassLoader classLoader;
|
||||
|
||||
private Class clazz;
|
||||
private Class<?> clazz;
|
||||
|
||||
|
||||
/**
|
||||
@@ -89,7 +89,7 @@ public class ClassPathResource extends AbstractFileResolvingResource {
|
||||
* @param clazz the class to load resources with
|
||||
* @see java.lang.Class#getResourceAsStream
|
||||
*/
|
||||
public ClassPathResource(String path, Class clazz) {
|
||||
public ClassPathResource(String path, Class<?> clazz) {
|
||||
Assert.notNull(path, "Path must not be null");
|
||||
this.path = StringUtils.cleanPath(path);
|
||||
this.clazz = clazz;
|
||||
@@ -102,7 +102,7 @@ public class ClassPathResource extends AbstractFileResolvingResource {
|
||||
* @param classLoader the class loader to load the resource with, if any
|
||||
* @param clazz the class to load resources with, if any
|
||||
*/
|
||||
protected ClassPathResource(String path, ClassLoader classLoader, Class clazz) {
|
||||
protected ClassPathResource(String path, ClassLoader classLoader, Class<?> clazz) {
|
||||
this.path = StringUtils.cleanPath(path);
|
||||
this.classLoader = classLoader;
|
||||
this.clazz = clazz;
|
||||
@@ -190,7 +190,16 @@ public class ClassPathResource extends AbstractFileResolvingResource {
|
||||
* This implementation returns a description that includes the class path location.
|
||||
*/
|
||||
public String getDescription() {
|
||||
return "class path resource [" + this.path + "]";
|
||||
StringBuilder builder = new StringBuilder("class path resource [");
|
||||
|
||||
if (this.clazz != null) {
|
||||
builder.append(ClassUtils.classPackageAsResourcePath(this.clazz));
|
||||
builder.append('/');
|
||||
}
|
||||
|
||||
builder.append(this.path);
|
||||
builder.append(']');
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
+6
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* 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.
|
||||
@@ -54,7 +54,7 @@ public abstract class ResourcePatternUtils {
|
||||
* ResourcePatternResolver extension, or a PathMatchingResourcePatternResolver
|
||||
* built on the given ResourceLoader.
|
||||
* @param resourceLoader the ResourceLoader to build a pattern resolver for
|
||||
* (not <code>null</code>)
|
||||
* (may be <code>null</code> to indicate a default ResourceLoader)
|
||||
* @return the ResourcePatternResolver
|
||||
* @see PathMatchingResourcePatternResolver
|
||||
*/
|
||||
@@ -63,9 +63,12 @@ public abstract class ResourcePatternUtils {
|
||||
if (resourceLoader instanceof ResourcePatternResolver) {
|
||||
return (ResourcePatternResolver) resourceLoader;
|
||||
}
|
||||
else {
|
||||
else if (resourceLoader != null) {
|
||||
return new PathMatchingResourcePatternResolver(resourceLoader);
|
||||
}
|
||||
else {
|
||||
return new PathMatchingResourcePatternResolver();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+16
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* 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.
|
||||
@@ -19,7 +19,6 @@ package org.springframework.core.type.classreading;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
@@ -37,19 +36,9 @@ public class CachingMetadataReaderFactory extends SimpleMetadataReaderFactory {
|
||||
|
||||
private static final int MAX_ENTRIES = 256;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static final <K, V> Map<K, V> createLRUCache() {
|
||||
return new LinkedHashMap<K, V>(MAX_ENTRIES, 0.75f, true) {
|
||||
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Entry<K, V> eldest) {
|
||||
return size() > MAX_ENTRIES;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private final Map<Resource, MetadataReader> classReaderCache = createLRUCache();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new CachingMetadataReaderFactory for the default class loader.
|
||||
*/
|
||||
@@ -74,6 +63,7 @@ public class CachingMetadataReaderFactory extends SimpleMetadataReaderFactory {
|
||||
super(classLoader);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MetadataReader getMetadataReader(Resource resource) throws IOException {
|
||||
synchronized (this.classReaderCache) {
|
||||
@@ -85,4 +75,16 @@ public class CachingMetadataReaderFactory extends SimpleMetadataReaderFactory {
|
||||
return metadataReader;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static <K, V> Map<K, V> createLRUCache() {
|
||||
return new LinkedHashMap<K, V>(MAX_ENTRIES, 0.75f, true) {
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
|
||||
return size() > MAX_ENTRIES;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* 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.
|
||||
@@ -21,12 +21,15 @@ import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.WildcardType;
|
||||
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Utility to work with Java 5 generic type parameters.
|
||||
* Mainly for internal use within the framework.
|
||||
*
|
||||
* @author Ramnivas Laddad
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
* @since 2.0.7
|
||||
*/
|
||||
public abstract class TypeUtils {
|
||||
@@ -38,56 +41,73 @@ public abstract class TypeUtils {
|
||||
* @param rhsType the value type that should be assigned to the target type
|
||||
* @return true if rhs is assignable to lhs
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static boolean isAssignable(Type lhsType, Type rhsType) {
|
||||
Assert.notNull(lhsType, "Left-hand side type must not be null");
|
||||
Assert.notNull(rhsType, "Right-hand side type must not be null");
|
||||
|
||||
// all types are assignable to themselves and to class Object
|
||||
if (lhsType.equals(rhsType) || lhsType.equals(Object.class)) {
|
||||
return true;
|
||||
}
|
||||
if (lhsType instanceof Class) {
|
||||
Class lhsClass = (Class) lhsType;
|
||||
if (rhsType instanceof Class) {
|
||||
return ClassUtils.isAssignable(lhsClass, (Class) rhsType);
|
||||
|
||||
if (lhsType instanceof Class<?>) {
|
||||
Class<?> lhsClass = (Class<?>) lhsType;
|
||||
|
||||
// just comparing two classes
|
||||
if (rhsType instanceof Class<?>) {
|
||||
return ClassUtils.isAssignable(lhsClass, (Class<?>) rhsType);
|
||||
}
|
||||
else if (rhsType instanceof ParameterizedType){
|
||||
|
||||
if (rhsType instanceof ParameterizedType) {
|
||||
Type rhsRaw = ((ParameterizedType) rhsType).getRawType();
|
||||
if (rhsRaw instanceof Class) {
|
||||
return ClassUtils.isAssignable(lhsClass, (Class) rhsRaw);
|
||||
|
||||
// a parameterized type is always assignable to its raw class type
|
||||
if (rhsRaw instanceof Class<?>) {
|
||||
return ClassUtils.isAssignable(lhsClass, (Class<?>) rhsRaw);
|
||||
}
|
||||
}
|
||||
else if (lhsClass.isArray() && rhsType instanceof GenericArrayType){
|
||||
else if (lhsClass.isArray() && rhsType instanceof GenericArrayType) {
|
||||
Type rhsComponent = ((GenericArrayType) rhsType).getGenericComponentType();
|
||||
|
||||
return isAssignable(lhsClass.getComponentType(), rhsComponent);
|
||||
}
|
||||
}
|
||||
|
||||
// parameterized types are only assignable to other parameterized types and class types
|
||||
if (lhsType instanceof ParameterizedType) {
|
||||
if (rhsType instanceof Class) {
|
||||
if (rhsType instanceof Class<?>) {
|
||||
Type lhsRaw = ((ParameterizedType) lhsType).getRawType();
|
||||
if (lhsRaw instanceof Class) {
|
||||
return ClassUtils.isAssignable((Class) lhsRaw, (Class) rhsType);
|
||||
|
||||
if (lhsRaw instanceof Class<?>) {
|
||||
return ClassUtils.isAssignable((Class<?>) lhsRaw, (Class<?>) rhsType);
|
||||
}
|
||||
}
|
||||
else if (rhsType instanceof ParameterizedType) {
|
||||
return isAssignable((ParameterizedType) lhsType, (ParameterizedType) rhsType);
|
||||
}
|
||||
}
|
||||
|
||||
if (lhsType instanceof GenericArrayType) {
|
||||
Type lhsComponent = ((GenericArrayType) lhsType).getGenericComponentType();
|
||||
if (rhsType instanceof Class) {
|
||||
Class rhsClass = (Class) rhsType;
|
||||
|
||||
if (rhsType instanceof Class<?>) {
|
||||
Class<?> rhsClass = (Class<?>) rhsType;
|
||||
|
||||
if (rhsClass.isArray()) {
|
||||
return isAssignable(lhsComponent, rhsClass.getComponentType());
|
||||
}
|
||||
}
|
||||
else if (rhsType instanceof GenericArrayType) {
|
||||
Type rhsComponent = ((GenericArrayType) rhsType).getGenericComponentType();
|
||||
|
||||
return isAssignable(lhsComponent, rhsComponent);
|
||||
}
|
||||
}
|
||||
|
||||
if (lhsType instanceof WildcardType) {
|
||||
return isAssignable((WildcardType) lhsType, rhsType);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -95,36 +115,113 @@ public abstract class TypeUtils {
|
||||
if (lhsType.equals(rhsType)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Type[] lhsTypeArguments = lhsType.getActualTypeArguments();
|
||||
Type[] rhsTypeArguments = rhsType.getActualTypeArguments();
|
||||
|
||||
if (lhsTypeArguments.length != rhsTypeArguments.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int size = lhsTypeArguments.length, i = 0; i < size; ++i) {
|
||||
Type lhsArg = lhsTypeArguments[i];
|
||||
Type rhsArg = rhsTypeArguments[i];
|
||||
|
||||
if (!lhsArg.equals(rhsArg) &&
|
||||
!(lhsArg instanceof WildcardType && isAssignable((WildcardType) lhsArg, rhsArg))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isAssignable(WildcardType lhsType, Type rhsType) {
|
||||
Type[] upperBounds = lhsType.getUpperBounds();
|
||||
Type[] lowerBounds = lhsType.getLowerBounds();
|
||||
for (int size = upperBounds.length, i = 0; i < size; ++i) {
|
||||
if (!isAssignable(upperBounds[i], rhsType)) {
|
||||
return false;
|
||||
Type[] lUpperBounds = lhsType.getUpperBounds();
|
||||
|
||||
// supply the implicit upper bound if none are specified
|
||||
if (lUpperBounds.length == 0) {
|
||||
lUpperBounds = new Type[] { Object.class };
|
||||
}
|
||||
|
||||
Type[] lLowerBounds = lhsType.getLowerBounds();
|
||||
|
||||
// supply the implicit lower bound if none are specified
|
||||
if (lLowerBounds.length == 0) {
|
||||
lLowerBounds = new Type[] { null };
|
||||
}
|
||||
|
||||
if (rhsType instanceof WildcardType) {
|
||||
// both the upper and lower bounds of the right-hand side must be
|
||||
// completely enclosed in the upper and lower bounds of the left-
|
||||
// hand side.
|
||||
WildcardType rhsWcType = (WildcardType) rhsType;
|
||||
Type[] rUpperBounds = rhsWcType.getUpperBounds();
|
||||
|
||||
if (rUpperBounds.length == 0) {
|
||||
rUpperBounds = new Type[] { Object.class };
|
||||
}
|
||||
|
||||
Type[] rLowerBounds = rhsWcType.getLowerBounds();
|
||||
|
||||
if (rLowerBounds.length == 0) {
|
||||
rLowerBounds = new Type[] { null };
|
||||
}
|
||||
|
||||
for (Type lBound : lUpperBounds) {
|
||||
for (Type rBound : rUpperBounds) {
|
||||
if (!isAssignableBound(lBound, rBound)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (Type rBound : rLowerBounds) {
|
||||
if (!isAssignableBound(lBound, rBound)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Type lBound : lLowerBounds) {
|
||||
for (Type rBound : rUpperBounds) {
|
||||
if (!isAssignableBound(rBound, lBound)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (Type rBound : rLowerBounds) {
|
||||
if (!isAssignableBound(rBound, lBound)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int size = lowerBounds.length, i = 0; i < size; ++i) {
|
||||
if (!isAssignable(rhsType, lowerBounds[i])) {
|
||||
return false;
|
||||
else {
|
||||
for (Type lBound : lUpperBounds) {
|
||||
if (!isAssignableBound(lBound, rhsType)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (Type lBound : lLowerBounds) {
|
||||
if (!isAssignableBound(rhsType, lBound)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isAssignableBound(Type lhsType, Type rhsType) {
|
||||
if (rhsType == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lhsType == null) {
|
||||
return false;
|
||||
}
|
||||
return isAssignable(lhsType, rhsType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.core.io;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.junit.internal.matchers.StringContains.containsString;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests cornering bug SPR-6888.
|
||||
*
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class ClassPathResourceTests {
|
||||
private static final String PACKAGE_PATH = "org/springframework/core/io";
|
||||
private static final String RESOURCE_NAME = "notexist.xml";
|
||||
private static final String FQ_RESOURCE_PATH = PACKAGE_PATH + '/' + RESOURCE_NAME;
|
||||
|
||||
@Test
|
||||
public void stringConstructorRaisesExceptionWithFullyQualifiedPath() {
|
||||
assertExceptionContainsFullyQualifiedPath(new ClassPathResource(FQ_RESOURCE_PATH));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void classLiteralConstructorRaisesExceptionWithFullyQualifiedPath() {
|
||||
assertExceptionContainsFullyQualifiedPath(new ClassPathResource(RESOURCE_NAME, this.getClass()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void classLoaderConstructorRaisesExceptionWithFullyQualifiedPath() {
|
||||
assertExceptionContainsFullyQualifiedPath(new ClassPathResource(FQ_RESOURCE_PATH, this.getClass().getClassLoader()));
|
||||
}
|
||||
|
||||
private void assertExceptionContainsFullyQualifiedPath(ClassPathResource resource) {
|
||||
try {
|
||||
resource.getInputStream();
|
||||
fail("FileNotFoundException expected for resource: " + resource);
|
||||
} catch (IOException ex) {
|
||||
assertThat(ex, instanceOf(FileNotFoundException.class));
|
||||
assertThat(ex.getMessage(), containsString(FQ_RESOURCE_PATH));
|
||||
}
|
||||
}
|
||||
}
|
||||
+38
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* 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.
|
||||
@@ -16,26 +16,41 @@
|
||||
|
||||
package org.springframework.util;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link TypeUtils}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class TypeUtilsTests {
|
||||
|
||||
public static Object object;
|
||||
|
||||
public static String string;
|
||||
|
||||
public static Integer number;
|
||||
|
||||
public static List<Object> objects;
|
||||
|
||||
public static List<String> strings;
|
||||
|
||||
public static List<? extends Object> openObjects;
|
||||
|
||||
public static List<String> strings;
|
||||
public static List<? extends Number> openNumbers;
|
||||
|
||||
public static List<? super Object> storableObjectList;
|
||||
|
||||
public static List<Number>[] array;
|
||||
|
||||
@@ -76,6 +91,25 @@ public class TypeUtilsTests {
|
||||
assertFalse(TypeUtils.isAssignable(objectsType, stringsType));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withWildcardTypes() throws Exception {
|
||||
ParameterizedType openObjectsType = (ParameterizedType) getClass().getField("openObjects").getGenericType();
|
||||
ParameterizedType openNumbersType = (ParameterizedType) getClass().getField("openNumbers").getGenericType();
|
||||
Type storableObjectListType = getClass().getField("storableObjectList").getGenericType();
|
||||
|
||||
Type objectType = getClass().getField("object").getGenericType();
|
||||
Type numberType = getClass().getField("number").getGenericType();
|
||||
Type stringType = getClass().getField("string").getGenericType();
|
||||
|
||||
Type openWildcard = openObjectsType.getActualTypeArguments()[0]; // '?'
|
||||
Type openNumbersWildcard = openNumbersType.getActualTypeArguments()[0]; // '? extends number'
|
||||
|
||||
assertTrue(TypeUtils.isAssignable(openWildcard, objectType));
|
||||
assertTrue(TypeUtils.isAssignable(openNumbersWildcard, numberType));
|
||||
assertFalse(TypeUtils.isAssignable(openNumbersWildcard, stringType));
|
||||
assertFalse(TypeUtils.isAssignable(storableObjectListType, openObjectsType));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withGenericArrayTypes() throws Exception {
|
||||
Type arrayType = getClass().getField("array").getGenericType();
|
||||
|
||||
@@ -7,9 +7,9 @@ Import-Package:
|
||||
Import-Template:
|
||||
javax.xml.*;version="0";resolution:=optional,
|
||||
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
|
||||
org.springframework.asm.*;version="[3.0.0, 3.0.1)";resolution:=optional,
|
||||
org.springframework.asm.*;version=${spring.osgi.range};resolution:=optional,
|
||||
org.apache.log4j.*;version="[1.2.15, 2.0.0)";resolution:=optional,
|
||||
org.aspectj.*;version="[1.5.4, 2.0.0)";resolution:=optional,
|
||||
org.aspectj.*;version=${aj.osgi.range};resolution:=optional,
|
||||
org.jboss.virtual.*;version="[2.1.0.GA, 3.0.0)";resolution:=optional,
|
||||
org.xml.sax.*;version="0";resolution:=optional,
|
||||
org.w3c.dom.*;version="0";resolution:=optional
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.1.RELEASE</version>
|
||||
<version>3.0.2.RELEASE</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.1.RELEASE</version>
|
||||
<version>3.0.2.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* 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.
|
||||
@@ -31,8 +31,9 @@ public class TemplateParserContext implements ParserContext {
|
||||
|
||||
private final String expressionSuffix;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new TemplateParserContext with the default #{ prefix and } suffix.
|
||||
* Create a new TemplateParserContext with the default "#{" prefix and "}" suffix.
|
||||
*/
|
||||
public TemplateParserContext() {
|
||||
this("#{", "}");
|
||||
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 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.expression.spel.ast;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.expression.PropertyAccessor;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
|
||||
/**
|
||||
* Utilities methods for use in the Ast classes.
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @since 3.0.2
|
||||
*/
|
||||
public class AstUtils {
|
||||
|
||||
/**
|
||||
* Determines the set of property resolvers that should be used to try and access a property on the specified target
|
||||
* type. The resolvers are considered to be in an ordered list, however in the returned list any that are exact
|
||||
* matches for the input target type (as opposed to 'general' resolvers that could work for any type) are placed at
|
||||
* the start of the list. In addition, there are specific resolvers that exactly name the class in question and
|
||||
* resolvers that name a specific class but it is a supertype of the class we have. These are put at the end of the
|
||||
* specific resolvers set and will be tried after exactly matching accessors but before generic accessors.
|
||||
*
|
||||
* @param targetType the type upon which property access is being attempted
|
||||
* @return a list of resolvers that should be tried in order to access the property
|
||||
*/
|
||||
public static List<PropertyAccessor> getPropertyAccessorsToTry(Class<?> targetType, ExpressionState state) {
|
||||
List<PropertyAccessor> specificAccessors = new ArrayList<PropertyAccessor>();
|
||||
List<PropertyAccessor> generalAccessors = new ArrayList<PropertyAccessor>();
|
||||
for (PropertyAccessor resolver : state.getPropertyAccessors()) {
|
||||
Class<?>[] targets = resolver.getSpecificTargetClasses();
|
||||
if (targets == null) { // generic resolver that says it can be used for any type
|
||||
generalAccessors.add(resolver);
|
||||
}
|
||||
else {
|
||||
if (targetType != null) {
|
||||
int pos = 0;
|
||||
for (Class<?> clazz : targets) {
|
||||
if (clazz == targetType) { // put exact matches on the front to be tried first?
|
||||
specificAccessors.add(pos++, resolver);
|
||||
}
|
||||
else if (clazz.isAssignableFrom(targetType)) { // put supertype matches at the end of the
|
||||
// specificAccessor list
|
||||
generalAccessors.add(resolver);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
List<PropertyAccessor> resolvers = new ArrayList<PropertyAccessor>();
|
||||
resolvers.addAll(specificAccessors);
|
||||
resolvers.addAll(generalAccessors);
|
||||
return resolvers;
|
||||
}
|
||||
}
|
||||
+150
-48
@@ -21,11 +21,15 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.expression.AccessException;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.PropertyAccessor;
|
||||
import org.springframework.expression.TypedValue;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
import org.springframework.expression.spel.SpelEvaluationException;
|
||||
import org.springframework.expression.spel.SpelMessage;
|
||||
import org.springframework.expression.spel.support.ReflectivePropertyAccessor;
|
||||
|
||||
/**
|
||||
* An Indexer can index into some proceeding structure to access a particular piece of it. Supported structures are:
|
||||
@@ -38,11 +42,25 @@ import org.springframework.expression.spel.SpelMessage;
|
||||
// TODO support correct syntax for multidimensional [][][] and not [,,,]
|
||||
public class Indexer extends SpelNodeImpl {
|
||||
|
||||
// These fields are used when the indexer is being used as a property read accessor. If the name and
|
||||
// target type match these cached values then the cachedReadAccessor is used to read the property.
|
||||
// If they do not match, the correct accessor is discovered and then cached for later use.
|
||||
private String cachedReadName;
|
||||
private Class<?> cachedReadTargetType;
|
||||
private PropertyAccessor cachedReadAccessor;
|
||||
|
||||
// These fields are used when the indexer is being used as a property write accessor. If the name and
|
||||
// target type match these cached values then the cachedWriteAccessor is used to write the property.
|
||||
// If they do not match, the correct accessor is discovered and then cached for later use.
|
||||
private String cachedWriteName;
|
||||
private Class<?> cachedWriteTargetType;
|
||||
private PropertyAccessor cachedWriteAccessor;
|
||||
|
||||
|
||||
public Indexer(int pos, SpelNodeImpl expr) {
|
||||
super(pos, expr);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {
|
||||
TypedValue context = state.getActiveContextObject();
|
||||
@@ -87,61 +105,75 @@ public class Indexer extends SpelNodeImpl {
|
||||
return new TypedValue(o);
|
||||
}
|
||||
}
|
||||
|
||||
int idx = (Integer)state.convertValue(index, TypeDescriptor.valueOf(Integer.class));
|
||||
|
||||
|
||||
if (targetObject == null) {
|
||||
throw new SpelEvaluationException(getStartPosition(),SpelMessage.CANNOT_INDEX_INTO_NULL_VALUE);
|
||||
}
|
||||
|
||||
if (targetObject.getClass().isArray()) {
|
||||
return new TypedValue(accessArrayElement(targetObject, idx),TypeDescriptor.valueOf(targetObjectTypeDescriptor.getElementType()));
|
||||
} else if (targetObject instanceof Collection) {
|
||||
Collection c = (Collection) targetObject;
|
||||
if (idx >= c.size()) {
|
||||
if (state.getConfiguration().isAutoGrowCollections()) {
|
||||
// Grow the collection
|
||||
Object newCollectionElement = null;
|
||||
try {
|
||||
int newElements = idx-c.size();
|
||||
Class elementClass = targetObjectTypeDescriptor.getElementType();
|
||||
if (elementClass == null) {
|
||||
throw new SpelEvaluationException(getStartPosition(), SpelMessage.UNABLE_TO_GROW_COLLECTION_UNKNOWN_ELEMENT_TYPE);
|
||||
}
|
||||
while (newElements>0) {
|
||||
c.add(elementClass.newInstance());
|
||||
newElements--;
|
||||
}
|
||||
newCollectionElement = targetObjectTypeDescriptor.getElementType().newInstance();
|
||||
// if the object is something that looks indexable by an integer, attempt to treat the index value as a number
|
||||
if ((targetObject instanceof Collection ) || targetObject.getClass().isArray() || targetObject instanceof String) {
|
||||
int idx = (Integer)state.convertValue(index, TypeDescriptor.valueOf(Integer.class));
|
||||
if (targetObject.getClass().isArray()) {
|
||||
return new TypedValue(accessArrayElement(targetObject, idx),TypeDescriptor.valueOf(targetObjectTypeDescriptor.getElementType()));
|
||||
} else if (targetObject instanceof Collection) {
|
||||
Collection c = (Collection) targetObject;
|
||||
if (idx >= c.size()) {
|
||||
if (!growCollection(state, targetObjectTypeDescriptor.getElementType(), idx, c)) {
|
||||
throw new SpelEvaluationException(getStartPosition(),SpelMessage.COLLECTION_INDEX_OUT_OF_BOUNDS, c.size(), idx);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new SpelEvaluationException(getStartPosition(), ex, SpelMessage.UNABLE_TO_GROW_COLLECTION);
|
||||
}
|
||||
int pos = 0;
|
||||
for (Object o : c) {
|
||||
if (pos == idx) {
|
||||
return new TypedValue(o,TypeDescriptor.valueOf(targetObjectTypeDescriptor.getElementType()));
|
||||
}
|
||||
c.add(newCollectionElement);
|
||||
return new TypedValue(newCollectionElement,TypeDescriptor.valueOf(targetObjectTypeDescriptor.getElementType()));
|
||||
pos++;
|
||||
}
|
||||
else {
|
||||
throw new SpelEvaluationException(getStartPosition(),SpelMessage.COLLECTION_INDEX_OUT_OF_BOUNDS, c.size(), idx);
|
||||
} else if (targetObject instanceof String) {
|
||||
String ctxString = (String) targetObject;
|
||||
if (idx >= ctxString.length()) {
|
||||
throw new SpelEvaluationException(getStartPosition(),SpelMessage.STRING_INDEX_OUT_OF_BOUNDS, ctxString.length(), idx);
|
||||
}
|
||||
return new TypedValue(String.valueOf(ctxString.charAt(idx)));
|
||||
}
|
||||
int pos = 0;
|
||||
for (Object o : c) {
|
||||
if (pos == idx) {
|
||||
return new TypedValue(o,TypeDescriptor.valueOf(targetObjectTypeDescriptor.getElementType()));
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
} else if (targetObject instanceof String) {
|
||||
String ctxString = (String) targetObject;
|
||||
if (idx >= ctxString.length()) {
|
||||
throw new SpelEvaluationException(getStartPosition(),SpelMessage.STRING_INDEX_OUT_OF_BOUNDS, ctxString.length(), idx);
|
||||
}
|
||||
return new TypedValue(String.valueOf(ctxString.charAt(idx)));
|
||||
}
|
||||
|
||||
// Try and treat the index value as a property of the context object
|
||||
// TODO could call the conversion service to convert the value to a String
|
||||
if (indexValue.getTypeDescriptor().getType()==String.class) {
|
||||
Class<?> targetObjectRuntimeClass = getObjectClass(targetObject);
|
||||
String name = (String)indexValue.getValue();
|
||||
EvaluationContext eContext = state.getEvaluationContext();
|
||||
|
||||
try {
|
||||
if (cachedReadName!=null && cachedReadName.equals(name) && cachedReadTargetType!=null && cachedReadTargetType.equals(targetObjectRuntimeClass)) {
|
||||
// it is OK to use the cached accessor
|
||||
return cachedReadAccessor.read(eContext, targetObject, name);
|
||||
}
|
||||
|
||||
List<PropertyAccessor> accessorsToTry = AstUtils.getPropertyAccessorsToTry(targetObjectRuntimeClass, state);
|
||||
|
||||
if (accessorsToTry != null) {
|
||||
for (PropertyAccessor accessor : accessorsToTry) {
|
||||
if (accessor.canRead(eContext, targetObject, name)) {
|
||||
if (accessor instanceof ReflectivePropertyAccessor) {
|
||||
accessor = ((ReflectivePropertyAccessor)accessor).createOptimalAccessor(eContext, targetObject, name);
|
||||
}
|
||||
this.cachedReadAccessor = accessor;
|
||||
this.cachedReadName = name;
|
||||
this.cachedReadTargetType = targetObjectRuntimeClass;
|
||||
return accessor.read(eContext, targetObject, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (AccessException e) {
|
||||
throw new SpelEvaluationException(getStartPosition(), e, SpelMessage.INDEXING_NOT_SUPPORTED_FOR_TYPE, targetObjectTypeDescriptor.asString());
|
||||
}
|
||||
}
|
||||
|
||||
throw new SpelEvaluationException(getStartPosition(),SpelMessage.INDEXING_NOT_SUPPORTED_FOR_TYPE, targetObjectTypeDescriptor.asString());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isWritable(ExpressionState expressionState) throws SpelEvaluationException {
|
||||
return true;
|
||||
@@ -174,24 +206,94 @@ public class Indexer extends SpelNodeImpl {
|
||||
if (targetObjectTypeDescriptor.isArray()) {
|
||||
int idx = (Integer)state.convertValue(index, TypeDescriptor.valueOf(Integer.class));
|
||||
setArrayElement(state, contextObject.getValue(), idx, newValue, targetObjectTypeDescriptor.getElementType());
|
||||
return;
|
||||
}
|
||||
else if (targetObjectTypeDescriptor.isCollection()) {
|
||||
int idx = (Integer)state.convertValue(index, TypeDescriptor.valueOf(Integer.class));
|
||||
Collection c = (Collection) targetObject;
|
||||
if (idx >= c.size()) {
|
||||
throw new SpelEvaluationException(getStartPosition(),SpelMessage.COLLECTION_INDEX_OUT_OF_BOUNDS, c.size(), idx);
|
||||
if (!growCollection(state, targetObjectTypeDescriptor.getElementType(), idx, c)) {
|
||||
throw new SpelEvaluationException(getStartPosition(),SpelMessage.COLLECTION_INDEX_OUT_OF_BOUNDS, c.size(), idx);
|
||||
}
|
||||
}
|
||||
if (targetObject instanceof List) {
|
||||
List list = (List)targetObject;
|
||||
Object possiblyConvertedValue = state.convertValue(newValue,TypeDescriptor.valueOf(targetObjectTypeDescriptor.getElementType()));
|
||||
list.set(idx,possiblyConvertedValue);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
throw new SpelEvaluationException(getStartPosition(),SpelMessage.INDEXING_NOT_SUPPORTED_FOR_TYPE, contextObject.getClass().getName());
|
||||
throw new SpelEvaluationException(getStartPosition(),SpelMessage.INDEXING_NOT_SUPPORTED_FOR_TYPE, targetObjectTypeDescriptor.asString());
|
||||
}
|
||||
} else {
|
||||
throw new SpelEvaluationException(getStartPosition(),SpelMessage.INDEXING_NOT_SUPPORTED_FOR_TYPE, contextObject.getClass().getName());
|
||||
}
|
||||
|
||||
// Try and treat the index value as a property of the context object
|
||||
// TODO could call the conversion service to convert the value to a String
|
||||
if (index.getTypeDescriptor().getType()==String.class) {
|
||||
Class<?> contextObjectClass = getObjectClass(contextObject.getValue());
|
||||
String name = (String)index.getValue();
|
||||
EvaluationContext eContext = state.getEvaluationContext();
|
||||
try {
|
||||
if (cachedWriteName!=null && cachedWriteName.equals(name) && cachedWriteTargetType!=null && cachedWriteTargetType.equals(contextObjectClass)) {
|
||||
// it is OK to use the cached accessor
|
||||
cachedWriteAccessor.write(eContext, targetObject, name,newValue);
|
||||
return;
|
||||
}
|
||||
|
||||
List<PropertyAccessor> accessorsToTry = AstUtils.getPropertyAccessorsToTry(contextObjectClass, state);
|
||||
if (accessorsToTry != null) {
|
||||
for (PropertyAccessor accessor : accessorsToTry) {
|
||||
if (accessor.canWrite(eContext, contextObject.getValue(), name)) {
|
||||
this.cachedWriteName = name;
|
||||
this.cachedWriteTargetType = contextObjectClass;
|
||||
this.cachedWriteAccessor = accessor;
|
||||
accessor.write(eContext, contextObject.getValue(), name, newValue);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (AccessException ae) {
|
||||
throw new SpelEvaluationException(getStartPosition(), ae, SpelMessage.EXCEPTION_DURING_PROPERTY_WRITE,
|
||||
name, ae.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
throw new SpelEvaluationException(getStartPosition(),SpelMessage.INDEXING_NOT_SUPPORTED_FOR_TYPE, targetObjectTypeDescriptor.asString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to grow the specified collection so that the specified index is valid.
|
||||
*
|
||||
* @param state the expression state
|
||||
* @param elementType the type of the elements in the collection
|
||||
* @param index the index into the collection that needs to be valid
|
||||
* @param collection the collection to grow with elements
|
||||
* @return true if collection growing succeeded, otherwise false
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private boolean growCollection(ExpressionState state, Class<?> elementType, int index,
|
||||
Collection collection) {
|
||||
if (state.getConfiguration().isAutoGrowCollections()) {
|
||||
Object newCollectionElement = null;
|
||||
try {
|
||||
int newElements = index-collection.size();
|
||||
if (elementType == null) {
|
||||
throw new SpelEvaluationException(getStartPosition(), SpelMessage.UNABLE_TO_GROW_COLLECTION_UNKNOWN_ELEMENT_TYPE);
|
||||
}
|
||||
while (newElements>0) {
|
||||
collection.add(elementType.newInstance());
|
||||
newElements--;
|
||||
}
|
||||
newCollectionElement = elementType.newInstance();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new SpelEvaluationException(getStartPosition(), ex, SpelMessage.UNABLE_TO_GROW_COLLECTION);
|
||||
}
|
||||
collection.add(newCollectionElement);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+22
-11
@@ -89,17 +89,7 @@ public class MethodReference extends SpelNodeImpl {
|
||||
// may or may not be a root cause. If there is a root cause it is a user created exception.
|
||||
// If there is no root cause it was a reflective invocation problem.
|
||||
|
||||
Throwable causeOfAccessException = ae.getCause();
|
||||
Throwable rootCause = (causeOfAccessException==null?null:causeOfAccessException.getCause());
|
||||
if (rootCause!=null) {
|
||||
// User exception was the root cause - exit now
|
||||
if (rootCause instanceof RuntimeException) {
|
||||
throw (RuntimeException)rootCause;
|
||||
} else {
|
||||
throw new SpelEvaluationException( getStartPosition(), rootCause, SpelMessage.EXCEPTION_DURING_METHOD_INVOCATION,
|
||||
this.name, state.getActiveContextObject().getValue().getClass().getName(), rootCause.getMessage());
|
||||
}
|
||||
}
|
||||
throwSimpleExceptionIfPossible(state, ae);
|
||||
|
||||
// at this point we know it wasn't a user problem so worth a retry if a better candidate can be found
|
||||
this.cachedExecutor = null;
|
||||
@@ -113,11 +103,32 @@ public class MethodReference extends SpelNodeImpl {
|
||||
return executorToUse.execute(
|
||||
state.getEvaluationContext(), state.getActiveContextObject().getValue(), arguments);
|
||||
} catch (AccessException ae) {
|
||||
// Same unwrapping exception handling as above in above catch block
|
||||
throwSimpleExceptionIfPossible(state, ae);
|
||||
throw new SpelEvaluationException( getStartPosition(), ae, SpelMessage.EXCEPTION_DURING_METHOD_INVOCATION,
|
||||
this.name, state.getActiveContextObject().getValue().getClass().getName(), ae.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decode the AccessException, throwing a lightweight evaluation exception or, if the cause was a RuntimeException,
|
||||
* throw the RuntimeException directly.
|
||||
*/
|
||||
private void throwSimpleExceptionIfPossible(ExpressionState state, AccessException ae) {
|
||||
Throwable causeOfAccessException = ae.getCause();
|
||||
Throwable rootCause = (causeOfAccessException==null?null:causeOfAccessException.getCause());
|
||||
if (rootCause!=null) {
|
||||
// User exception was the root cause - exit now
|
||||
if (rootCause instanceof RuntimeException) {
|
||||
throw (RuntimeException)rootCause;
|
||||
} else {
|
||||
throw new SpelEvaluationException( getStartPosition(), rootCause, SpelMessage.EXCEPTION_DURING_METHOD_INVOCATION,
|
||||
this.name, state.getActiveContextObject().getValue().getClass().getName(), rootCause.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Class<?>[] getTypes(Object... arguments) {
|
||||
Class<?>[] argumentTypes = new Class[arguments.length];
|
||||
for (int i = 0; i < arguments.length; i++) {
|
||||
|
||||
+57
-33
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* 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.
|
||||
@@ -41,20 +41,31 @@ import org.springframework.expression.spel.support.ReflectivePropertyAccessor;
|
||||
*/
|
||||
public class PropertyOrFieldReference extends SpelNodeImpl {
|
||||
|
||||
private final boolean nullSafe;
|
||||
|
||||
private final String name;
|
||||
|
||||
private volatile PropertyAccessor cachedReadAccessor;
|
||||
|
||||
private volatile PropertyAccessor cachedWriteAccessor;
|
||||
|
||||
private final boolean nullSafe;
|
||||
|
||||
public PropertyOrFieldReference(boolean nullSafe, String propertyOrFieldName, int pos) {
|
||||
super(pos);
|
||||
name = propertyOrFieldName;
|
||||
this.nullSafe = nullSafe;
|
||||
this.name = propertyOrFieldName;
|
||||
}
|
||||
|
||||
|
||||
public boolean isNullSafe() {
|
||||
return this.nullSafe;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {
|
||||
TypedValue result = readProperty(state, this.name);
|
||||
@@ -70,28 +81,38 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
|
||||
try {
|
||||
if (isWritable(state)) {
|
||||
List newList = ArrayList.class.newInstance();
|
||||
writeProperty(state, name, newList);
|
||||
writeProperty(state, this.name, newList);
|
||||
result = readProperty(state, this.name);
|
||||
}
|
||||
} catch (InstantiationException e) {
|
||||
throw new SpelEvaluationException(getStartPosition(), e, SpelMessage.UNABLE_TO_CREATE_LIST_FOR_INDEXING);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new SpelEvaluationException(getStartPosition(), e, SpelMessage.UNABLE_TO_CREATE_LIST_FOR_INDEXING);
|
||||
}
|
||||
} else {
|
||||
catch (InstantiationException ex) {
|
||||
throw new SpelEvaluationException(getStartPosition(), ex,
|
||||
SpelMessage.UNABLE_TO_CREATE_LIST_FOR_INDEXING);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new SpelEvaluationException(getStartPosition(), ex,
|
||||
SpelMessage.UNABLE_TO_CREATE_LIST_FOR_INDEXING);
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
if (isWritable(state)) {
|
||||
Map newMap = HashMap.class.newInstance();
|
||||
writeProperty(state, name, newMap);
|
||||
result = readProperty(state, this.name);
|
||||
}
|
||||
} catch (InstantiationException e) {
|
||||
throw new SpelEvaluationException(getStartPosition(), e, SpelMessage.UNABLE_TO_CREATE_MAP_FOR_INDEXING);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new SpelEvaluationException(getStartPosition(), e, SpelMessage.UNABLE_TO_CREATE_MAP_FOR_INDEXING);
|
||||
}
|
||||
catch (InstantiationException ex) {
|
||||
throw new SpelEvaluationException(getStartPosition(), ex,
|
||||
SpelMessage.UNABLE_TO_CREATE_MAP_FOR_INDEXING);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new SpelEvaluationException(getStartPosition(), ex,
|
||||
SpelMessage.UNABLE_TO_CREATE_MAP_FOR_INDEXING);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// 'simple' object
|
||||
try {
|
||||
if (isWritable(state)) {
|
||||
@@ -99,10 +120,14 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
|
||||
writeProperty(state, name, newObject);
|
||||
result = readProperty(state, this.name);
|
||||
}
|
||||
} catch (InstantiationException e) {
|
||||
throw new SpelEvaluationException(getStartPosition(), e, SpelMessage.UNABLE_TO_DYNAMICALLY_CREATE_OBJECT,result.getTypeDescriptor().getType());
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new SpelEvaluationException(getStartPosition(), e, SpelMessage.UNABLE_TO_DYNAMICALLY_CREATE_OBJECT,result.getTypeDescriptor().getType());
|
||||
}
|
||||
catch (InstantiationException ex) {
|
||||
throw new SpelEvaluationException(getStartPosition(), ex,
|
||||
SpelMessage.UNABLE_TO_DYNAMICALLY_CREATE_OBJECT, result.getTypeDescriptor().getType());
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new SpelEvaluationException(getStartPosition(), ex,
|
||||
SpelMessage.UNABLE_TO_DYNAMICALLY_CREATE_OBJECT, result.getTypeDescriptor().getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -176,7 +201,8 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
|
||||
}
|
||||
if (contextObject.getValue() == null) {
|
||||
throw new SpelEvaluationException(SpelMessage.PROPERTY_OR_FIELD_NOT_READABLE_ON_NULL, name);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
throw new SpelEvaluationException(getStartPosition(),SpelMessage.PROPERTY_OR_FIELD_NOT_READABLE, name,
|
||||
FormatHelper.formatClassNameForMessage(contextObjectClass));
|
||||
}
|
||||
@@ -215,33 +241,34 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (AccessException ae) {
|
||||
}
|
||||
catch (AccessException ae) {
|
||||
throw new SpelEvaluationException(getStartPosition(), ae, SpelMessage.EXCEPTION_DURING_PROPERTY_WRITE,
|
||||
name, ae.getMessage());
|
||||
}
|
||||
}
|
||||
if (contextObject.getValue()==null) {
|
||||
throw new SpelEvaluationException(getStartPosition(),SpelMessage.PROPERTY_OR_FIELD_NOT_WRITABLE_ON_NULL, name);
|
||||
} else {
|
||||
throw new SpelEvaluationException(getStartPosition(),SpelMessage.PROPERTY_OR_FIELD_NOT_WRITABLE, name, FormatHelper
|
||||
.formatClassNameForMessage(contextObjectClass));
|
||||
throw new SpelEvaluationException(getStartPosition(), SpelMessage.PROPERTY_OR_FIELD_NOT_WRITABLE_ON_NULL, name);
|
||||
}
|
||||
else {
|
||||
throw new SpelEvaluationException(getStartPosition(), SpelMessage.PROPERTY_OR_FIELD_NOT_WRITABLE, name,
|
||||
FormatHelper.formatClassNameForMessage(contextObjectClass));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isWritableProperty(String name, ExpressionState state) throws SpelEvaluationException {
|
||||
Object contextObject = state.getActiveContextObject().getValue();
|
||||
// TypeDescriptor td = state.getActiveContextObject().getTypeDescriptor();
|
||||
// TypeDescriptor td = state.getActiveContextObject().getTypeDescriptor();
|
||||
EvaluationContext eContext = state.getEvaluationContext();
|
||||
|
||||
List<PropertyAccessor> resolversToTry = getPropertyAccessorsToTry(getObjectClass(contextObject),state);
|
||||
|
||||
List<PropertyAccessor> resolversToTry = getPropertyAccessorsToTry(getObjectClass(contextObject), state);
|
||||
if (resolversToTry != null) {
|
||||
for (PropertyAccessor pfResolver : resolversToTry) {
|
||||
try {
|
||||
if (pfResolver.canWrite(eContext, contextObject, name)) {
|
||||
return true;
|
||||
}
|
||||
} catch (AccessException ae) {
|
||||
}
|
||||
catch (AccessException ae) {
|
||||
// let others try
|
||||
}
|
||||
}
|
||||
@@ -249,6 +276,7 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO when there is more time, remove this and use the version in AstUtils
|
||||
/**
|
||||
* Determines the set of property resolvers that should be used to try and access a property on the specified target
|
||||
* type. The resolvers are considered to be in an ordered list, however in the returned list any that are exact
|
||||
@@ -287,9 +315,5 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
|
||||
resolvers.addAll(generalAccessors);
|
||||
return resolvers;
|
||||
}
|
||||
|
||||
String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-1
@@ -336,7 +336,12 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
|
||||
if (maybeEatMethodOrProperty(nullSafeNavigation) || maybeEatFunctionOrVar() || maybeEatProjection(nullSafeNavigation) || maybeEatSelection(nullSafeNavigation)) {
|
||||
return pop();
|
||||
}
|
||||
raiseInternalException(t.startpos,SpelMessage.UNEXPECTED_DATA_AFTER_DOT,toString(peekToken()));
|
||||
if (peekToken()==null) {
|
||||
// unexpectedly ran out of data
|
||||
raiseInternalException(t.startpos,SpelMessage.OOD);
|
||||
} else {
|
||||
raiseInternalException(t.startpos,SpelMessage.UNEXPECTED_DATA_AFTER_DOT,toString(peekToken()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
-108
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
* 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.expression.spel.support;
|
||||
|
||||
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.
|
||||
*
|
||||
* org.springframework.beans.BeanTypeDescriptor (beans module) is very
|
||||
* similar to this but depending on that would introduce a beans
|
||||
* dependency from the SpEL module.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Andy Clement
|
||||
* @since 3.0
|
||||
*/
|
||||
public class BeanTypeDescriptor extends TypeDescriptor {
|
||||
|
||||
private final PropertyDescriptor propertyDescriptor;
|
||||
|
||||
private Annotation[] cachedAnnotations;
|
||||
|
||||
/**
|
||||
* Create a new BeanTypeDescriptor for the given bean property.
|
||||
*
|
||||
* @param propertyDescriptor
|
||||
* the corresponding JavaBean PropertyDescriptor
|
||||
* @param methodParameter
|
||||
* the target method parameter
|
||||
* @param type
|
||||
* the specific type to expose (may be an array/collection
|
||||
* element)
|
||||
*/
|
||||
public BeanTypeDescriptor(PropertyDescriptor propertyDescriptor,
|
||||
MethodParameter methodParameter, Class type) {
|
||||
super(methodParameter, type);
|
||||
this.propertyDescriptor = propertyDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the underlying PropertyDescriptor.
|
||||
*/
|
||||
public PropertyDescriptor getPropertyDescriptor() {
|
||||
return this.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;
|
||||
}
|
||||
|
||||
}
|
||||
+21
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* 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.
|
||||
@@ -28,6 +28,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.support.PropertyTypeDescriptor;
|
||||
import org.springframework.expression.AccessException;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
@@ -80,17 +81,18 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||
Method method = findGetterForProperty(name, type, target instanceof Class);
|
||||
if (method != null) {
|
||||
// Treat it like a property
|
||||
PropertyDescriptor propertyDescriptor = null;
|
||||
try {
|
||||
// The readerCache will only contain gettable properties (let's not worry about setters for now)
|
||||
propertyDescriptor = new PropertyDescriptor(name,method,null);
|
||||
} catch (IntrospectionException ex) {
|
||||
throw new AccessException("Unable to access property '" + name + "' through getter "+method, ex);
|
||||
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(name, method, null);
|
||||
TypeDescriptor typeDescriptor =
|
||||
new PropertyTypeDescriptor(propertyDescriptor, new MethodParameter(method, -1));
|
||||
this.readerCache.put(cacheKey, new InvokerPair(method, typeDescriptor));
|
||||
this.typeDescriptorCache.put(cacheKey, typeDescriptor);
|
||||
return true;
|
||||
}
|
||||
catch (IntrospectionException ex) {
|
||||
throw new AccessException("Unable to access property '" + name + "' through getter " + method, ex);
|
||||
}
|
||||
TypeDescriptor typeDescriptor = new BeanTypeDescriptor(propertyDescriptor, new MethodParameter(method,-1), method.getReturnType());
|
||||
this.readerCache.put(cacheKey, new InvokerPair(method,typeDescriptor));
|
||||
this.typeDescriptorCache.put(cacheKey, typeDescriptor);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
Field field = findField(name, type, target instanceof Class);
|
||||
@@ -130,16 +132,18 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||
if (method != null) {
|
||||
// TODO remove the duplication here between canRead and read
|
||||
// Treat it like a property
|
||||
PropertyDescriptor propertyDescriptor = null;
|
||||
try {
|
||||
// The readerCache will only contain gettable properties (let's not worry about setters for now)
|
||||
propertyDescriptor = new PropertyDescriptor(name,method,null);
|
||||
} catch (IntrospectionException ex) {
|
||||
throw new AccessException("Unable to access property '" + name + "' through getter "+method, ex);
|
||||
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(name, method, null);
|
||||
TypeDescriptor typeDescriptor =
|
||||
new PropertyTypeDescriptor(propertyDescriptor, new MethodParameter(method, -1));
|
||||
invoker = new InvokerPair(method, typeDescriptor);
|
||||
this.readerCache.put(cacheKey, invoker);
|
||||
}
|
||||
catch (IntrospectionException ex) {
|
||||
throw new AccessException(
|
||||
"Unable to access property '" + name + "' through getter " + method, ex);
|
||||
}
|
||||
TypeDescriptor typeDescriptor = new BeanTypeDescriptor(propertyDescriptor, new MethodParameter(method,-1), method.getReturnType());
|
||||
invoker = new InvokerPair(method,typeDescriptor);
|
||||
this.readerCache.put(cacheKey, invoker);
|
||||
}
|
||||
}
|
||||
if (method != null) {
|
||||
@@ -201,7 +205,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||
throw new AccessException("Unable to access property '" + name + "' through setter "+method, ex);
|
||||
}
|
||||
MethodParameter mp = new MethodParameter(method,0);
|
||||
TypeDescriptor typeDescriptor = new BeanTypeDescriptor(propertyDescriptor,mp,mp.getParameterType());
|
||||
TypeDescriptor typeDescriptor = new PropertyTypeDescriptor(propertyDescriptor, mp);
|
||||
this.writerCache.put(cacheKey, method);
|
||||
this.typeDescriptorCache.put(cacheKey, typeDescriptor);
|
||||
return true;
|
||||
|
||||
+44
-2
@@ -20,8 +20,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.Expression;
|
||||
@@ -31,6 +31,7 @@ import org.springframework.expression.spel.standard.SpelExpression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.expression.spel.support.StandardTypeLocator;
|
||||
import org.springframework.expression.spel.testresources.TestPerson;
|
||||
|
||||
/**
|
||||
* Tests the evaluation of real expressions in a real context.
|
||||
@@ -222,6 +223,20 @@ public class EvaluationTests extends ExpressionTestCase {
|
||||
"org.springframework.expression.spel.testresources.Inventor");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRogueTrailingDotCausesNPE_SPR6866() {
|
||||
try {
|
||||
new SpelExpressionParser().parseExpression("placeOfBirth.foo.");
|
||||
Assert.fail("Should have failed to parse");
|
||||
} catch (ParseException e) {
|
||||
Assert.assertTrue(e instanceof SpelParseException);
|
||||
SpelParseException spe = (SpelParseException)e;
|
||||
Assert.assertEquals(SpelMessage.OOD,spe.getMessageCode());
|
||||
Assert.assertEquals(16,spe.getPosition());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// nested properties
|
||||
@Test
|
||||
public void testPropertiesNested01() {
|
||||
@@ -506,6 +521,33 @@ public class EvaluationTests extends ExpressionTestCase {
|
||||
public void testResolvingString() throws Exception {
|
||||
Class stringClass = parser.parseExpression("T(String)").getValue(Class.class);
|
||||
Assert.assertEquals(String.class,stringClass);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SPR-6984: attempting to index a collection on write using an index that doesn't currently exist in the collection (address.crossStreets[0] below)
|
||||
*/
|
||||
@Test
|
||||
public void initializingCollectionElementsOnWrite() throws Exception {
|
||||
TestPerson person = new TestPerson();
|
||||
EvaluationContext context = new StandardEvaluationContext(person);
|
||||
SpelParserConfiguration config = new SpelParserConfiguration(true, true);
|
||||
ExpressionParser parser = new SpelExpressionParser(config);
|
||||
Expression expression = parser.parseExpression("name");
|
||||
expression.setValue(context, "Oleg");
|
||||
Assert.assertEquals("Oleg",person.getName());
|
||||
|
||||
expression = parser.parseExpression("address.street");
|
||||
expression.setValue(context, "123 High St");
|
||||
Assert.assertEquals("123 High St",person.getAddress().getStreet());
|
||||
|
||||
expression = parser.parseExpression("address.crossStreets[0]");
|
||||
expression.setValue(context, "Blah");
|
||||
Assert.assertEquals("Blah",person.getAddress().getCrossStreets().get(0));
|
||||
|
||||
expression = parser.parseExpression("address.crossStreets[3]");
|
||||
expression.setValue(context, "Wibble");
|
||||
Assert.assertEquals("Blah",person.getAddress().getCrossStreets().get(0));
|
||||
Assert.assertEquals("Wibble",person.getAddress().getCrossStreets().get(3));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+27
@@ -156,6 +156,33 @@ public class MethodInvocationTests extends ExpressionTestCase {
|
||||
Assert.assertEquals(4,parser.parseExpression("counter").getValue(eContext));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check on first usage (when the cachedExecutor in MethodReference is null) that the exception is not wrapped.
|
||||
*/
|
||||
@Test
|
||||
public void testMethodThrowingException_SPR6941() {
|
||||
// Test method on inventor: throwException()
|
||||
// On 1 it will throw an IllegalArgumentException
|
||||
// On 2 it will throw a RuntimeException
|
||||
// On 3 it will exit normally
|
||||
// In each case it increments the Inventor field 'counter' when invoked
|
||||
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
Expression expr = parser.parseExpression("throwException(#bar)");
|
||||
|
||||
eContext.setVariable("bar",2);
|
||||
try {
|
||||
expr.getValue(eContext);
|
||||
Assert.fail();
|
||||
} catch (Exception e) {
|
||||
if (e instanceof SpelEvaluationException) {
|
||||
e.printStackTrace();
|
||||
Assert.fail("Should not be a SpelEvaluationException");
|
||||
}
|
||||
// normal
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMethodFiltering_SPR6764() {
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
|
||||
+119
@@ -291,6 +291,125 @@ public class SpringEL300Tests extends ExpressionTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testNestedProperties_SPR6923() {
|
||||
StandardEvaluationContext eContext = new StandardEvaluationContext(new Foo());
|
||||
String name = null;
|
||||
Expression expr = null;
|
||||
|
||||
expr = new SpelExpressionParser().parseRaw("resource.resource.server");
|
||||
name = expr.getValue(eContext,String.class);
|
||||
Assert.assertEquals("abc",name);
|
||||
}
|
||||
|
||||
static class Foo {
|
||||
public ResourceSummary resource = new ResourceSummary();
|
||||
}
|
||||
|
||||
static class ResourceSummary {
|
||||
ResourceSummary() {
|
||||
this.resource = new Resource();
|
||||
}
|
||||
private final Resource resource;
|
||||
public Resource getResource() {
|
||||
return resource;
|
||||
}
|
||||
}
|
||||
|
||||
static class Resource {
|
||||
public String getServer() {
|
||||
return "abc";
|
||||
}
|
||||
}
|
||||
|
||||
/** Should be accessing Goo.getKey because 'bar' field evaluates to "key" */
|
||||
@Test
|
||||
public void testIndexingAsAPropertyAccess_SPR6968_1() {
|
||||
StandardEvaluationContext eContext = new StandardEvaluationContext(new Goo());
|
||||
String name = null;
|
||||
Expression expr = null;
|
||||
expr = new SpelExpressionParser().parseRaw("instance[bar]");
|
||||
name = expr.getValue(eContext,String.class);
|
||||
Assert.assertEquals("hello",name);
|
||||
name = expr.getValue(eContext,String.class); // will be using the cached accessor this time
|
||||
Assert.assertEquals("hello",name);
|
||||
}
|
||||
|
||||
/** Should be accessing Goo.getKey because 'bar' variable evaluates to "key" */
|
||||
@Test
|
||||
public void testIndexingAsAPropertyAccess_SPR6968_2() {
|
||||
StandardEvaluationContext eContext = new StandardEvaluationContext(new Goo());
|
||||
eContext.setVariable("bar","key");
|
||||
String name = null;
|
||||
Expression expr = null;
|
||||
expr = new SpelExpressionParser().parseRaw("instance[#bar]");
|
||||
name = expr.getValue(eContext,String.class);
|
||||
Assert.assertEquals("hello",name);
|
||||
name = expr.getValue(eContext,String.class); // will be using the cached accessor this time
|
||||
Assert.assertEquals("hello",name);
|
||||
}
|
||||
|
||||
/** Should be accessing Goo.wibble field because 'bar' variable evaluates to "wibble" */
|
||||
@Test
|
||||
public void testIndexingAsAPropertyAccess_SPR6968_3() {
|
||||
StandardEvaluationContext eContext = new StandardEvaluationContext(new Goo());
|
||||
eContext.setVariable("bar","wibble");
|
||||
String name = null;
|
||||
Expression expr = null;
|
||||
expr = new SpelExpressionParser().parseRaw("instance[#bar]");
|
||||
// will access the field 'wibble' and not use a getter
|
||||
name = expr.getValue(eContext,String.class);
|
||||
Assert.assertEquals("wobble",name);
|
||||
name = expr.getValue(eContext,String.class); // will be using the cached accessor this time
|
||||
Assert.assertEquals("wobble",name);
|
||||
}
|
||||
|
||||
/** Should be accessing (setting) Goo.wibble field because 'bar' variable evaluates to "wibble" */
|
||||
@Test
|
||||
public void testIndexingAsAPropertyAccess_SPR6968_4() {
|
||||
Goo g = Goo.instance;
|
||||
StandardEvaluationContext eContext = new StandardEvaluationContext(g);
|
||||
eContext.setVariable("bar","wibble");
|
||||
Expression expr = null;
|
||||
expr = new SpelExpressionParser().parseRaw("instance[#bar]='world'");
|
||||
// will access the field 'wibble' and not use a getter
|
||||
expr.getValue(eContext,String.class);
|
||||
Assert.assertEquals("world",g.wibble);
|
||||
expr.getValue(eContext,String.class); // will be using the cached accessor this time
|
||||
Assert.assertEquals("world",g.wibble);
|
||||
}
|
||||
|
||||
/** Should be accessing Goo.setKey field because 'bar' variable evaluates to "key" */
|
||||
@Test
|
||||
public void testIndexingAsAPropertyAccess_SPR6968_5() {
|
||||
Goo g = Goo.instance;
|
||||
StandardEvaluationContext eContext = new StandardEvaluationContext(g);
|
||||
Expression expr = null;
|
||||
expr = new SpelExpressionParser().parseRaw("instance[bar]='world'");
|
||||
expr.getValue(eContext,String.class);
|
||||
Assert.assertEquals("world",g.value);
|
||||
expr.getValue(eContext,String.class); // will be using the cached accessor this time
|
||||
Assert.assertEquals("world",g.value);
|
||||
}
|
||||
|
||||
static class Goo {
|
||||
|
||||
public static Goo instance = new Goo();
|
||||
public String bar = "key";
|
||||
public String value = null;
|
||||
|
||||
public String wibble = "wobble";
|
||||
|
||||
public String getKey() {
|
||||
return "hello";
|
||||
}
|
||||
|
||||
public void setKey(String s) {
|
||||
value = s;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package org.springframework.expression.spel.testresources;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class TestAddress{
|
||||
private String street;
|
||||
private List<String> crossStreets;
|
||||
|
||||
public String getStreet() {
|
||||
return street;
|
||||
}
|
||||
public void setStreet(String street) {
|
||||
this.street = street;
|
||||
}
|
||||
public List<String> getCrossStreets() {
|
||||
return crossStreets;
|
||||
}
|
||||
public void setCrossStreets(List<String> crossStreets) {
|
||||
this.crossStreets = crossStreets;
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package org.springframework.expression.spel.testresources;
|
||||
|
||||
public class TestPerson {
|
||||
private String name;
|
||||
private TestAddress address;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public TestAddress getAddress() {
|
||||
return address;
|
||||
}
|
||||
public void setAddress(TestAddress address) {
|
||||
this.address = address;
|
||||
}
|
||||
}
|
||||
@@ -4,5 +4,5 @@ Bundle-Vendor: SpringSource
|
||||
Bundle-ManifestVersion: 2
|
||||
Import-Template:
|
||||
org.apache.commons.logging;version="[1.1.1, 2.0.0)",
|
||||
org.springframework.core.*;version="[3.0.0, 3.0.1)",
|
||||
org.springframework.util.*;version="[3.0.0, 3.0.1)"
|
||||
org.springframework.core.*;version=${spring.osgi.range},
|
||||
org.springframework.util.*;version=${spring.osgi.range}
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-instrument-tomcat</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.1.RELEASE</version>
|
||||
<version>3.0.2.RELEASE</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.1.RELEASE</version>
|
||||
<version>3.0.2.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-instrument</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.1.RELEASE</version>
|
||||
<version>3.0.2.RELEASE</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.1.RELEASE</version>
|
||||
<version>3.0.2.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-integration-tests</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.1.RELEASE</version>
|
||||
<version>3.0.2.RELEASE</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.1.RELEASE</version>
|
||||
<version>3.0.2.RELEASE</version>
|
||||
</parent>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>3.0.1.RELEASE</version>
|
||||
<version>3.0.2.RELEASE</version>
|
||||
<parent>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-parent</artifactId>
|
||||
<relativePath>../org.springframework.spring-parent</relativePath>
|
||||
<version>3.0.1.RELEASE</version>
|
||||
<version>3.0.2.RELEASE</version>
|
||||
</parent>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user