Compare commits

...

363 Commits

Author SHA1 Message Date
Spring Buildmaster 0edb85c78b Release version 3.2.14.RELEASE 2015-06-30 10:36:07 -07:00
Rossen Stoyanchev d875772103 Polish tests 2015-06-30 12:00:12 -04:00
Rossen Stoyanchev 0d394a02f3 Fix test check 2015-06-30 10:00:12 -04:00
Stephane Nicoll d996a0988b Upgrade changelog 2015-06-30 06:19:41 -07:00
Rossen Stoyanchev 5a711c05ec Disable DTD when parsing untrusted XML input
Issue: SPR-13136
2015-06-30 07:59:00 -04:00
Juergen Hoeller 1e42464c22 Polishing 2015-06-17 15:50:19 +02:00
Juergen Hoeller 896f0d91f9 AspectJExpressionPointcut defensively catches exceptions thrown from ShadowMatch.matchesJoinPoint
Issue: SPR-13102
(cherry picked from commit 84ae28b)
2015-06-17 15:50:10 +02:00
Juergen Hoeller 50eef1b979 Upgrade to ASM 5.0.4 (and Hibernate 4.2.19)
Issue: SPR-13039
2015-05-22 17:55:24 +02:00
Juergen Hoeller d5de3867ca Polishing
(cherry picked from commit 3c6f1f8)
2015-05-22 17:50:13 +02:00
Juergen Hoeller a64dcc2a31 Message listener containers only call Session.recover() in client acknowledge mode
Issue: SPR-13052
(cherry picked from commit c111bd7)
2015-05-22 17:38:13 +02:00
Juergen Hoeller e5ccdfb029 Polishing
(cherry picked from commit ce4e795)
2015-05-11 20:12:46 +02:00
Juergen Hoeller adb54b2c69 Backported DispatcherServlet and ServletContextResourcePatternResolver refinements
Issue: SPR-13011
2015-05-11 19:58:36 +02:00
Juergen Hoeller eb6368ca3f CustomBooleanEditor avoids potential NPE in case of allowEmpty=false
Issue: SPR-13010
(cherry picked from commit 0cd7fed)
2015-05-11 19:58:20 +02:00
Juergen Hoeller ed9769a11b Avoid infinite loop in PatternMatchUtils
Issue: SPR-12971
(cherry picked from commit 8e074b6)
2015-05-11 19:58:11 +02:00
Juergen Hoeller b5a56ca3a9 CronSequenceGenerator explicitly rejects invalid incrementer delta
Issue: SPR-12871
(cherry picked from commit 50f4977)
2015-05-11 19:57:25 +02:00
Juergen Hoeller dd73848e15 BeanWrapperImpl.setPropertyValue throws InvalidPropertyException with correct property value for nested collection case
Issue: SPR-12866
(cherry picked from commit d506767)
2015-05-11 19:56:19 +02:00
Juergen Hoeller 64a039402a Clarification: Lifecycle does not imply auto-startup semantics
Issue: SPR-12855
(cherry picked from commit e9e2b73)
2015-05-11 19:55:21 +02:00
Sam Brannen e748cf17d9 Eclipse project deps come after third-party libs
This commit is a backport of SPR-11836.

Prior to this commit, the ordering of classpath entries in the
generated Eclipse .classpath files did not align with the intended
dependency management configured in the Gradle build. Specifically,
project dependencies often came before dependencies on third-party
libraries required for the given project, causing the project not to
compile in Eclipse.

This commit fixes this issue by introducing new functionality in the
ide.gradle script that moves all project dependencies to the end of the
generated classpath.

Issue: SPR-12947, SPR-11836
2015-04-24 21:23:00 +02:00
Juergen Hoeller 3e2491c058 Polishing 2015-03-23 22:43:49 +01:00
Juergen Hoeller e51da28897 Polishing
Issue: SPR-12803
2015-03-11 18:59:32 +01:00
Juergen Hoeller e7cc19537d ReflectiveMethodResolver reliably prefers direct matches over vararg methods
Issue: SPR-12803
2015-03-11 18:58:39 +01:00
Juergen Hoeller 474862a7c9 StandardMultipartFile declares itself as Serializable now
Issue: SPR-12795
(cherry picked from commit 5ba7b89)
2015-03-10 15:30:16 +01:00
Juergen Hoeller 0920266b33 PropertyResourceConfigurerTests accepts "." in operating system name
Issue: SPR-12794
(cherry picked from commit 6fe85c2)
2015-03-10 15:29:44 +01:00
Juergen Hoeller de9c5a8c4d Dependency updates for spring-oxm generation tasks
(cherry picked from commit ebe45cf)
2015-03-06 23:48:20 +01:00
Juergen Hoeller d879bad248 Polishing
(cherry picked from commit 7ed7f98)
2015-03-06 23:47:54 +01:00
Juergen Hoeller ff76be2d16 Converter interface explicitly documents null values
Issue: SPR-12780
(cherry picked from commit 5f30575)
2015-03-06 19:30:05 +01:00
Juergen Hoeller e5207e6231 Polishing 2015-03-02 21:17:16 +01:00
Juergen Hoeller 1c10861a92 Revised documentation on AUTO_ACKNOWLEDGE behavior
Issue: SPR-12705
(cherry picked from commit 91c47a9)
2015-03-02 20:25:10 +01:00
Sam Brannen 1f9bc50c3e Include charset in EncodedResource.equals()
Prior to this commit, the implementation of equals() in EncodedResource
was based solely on the resource and encoding. Thus, if a Charset were
specified instead of an encoding, invocations of equals() would not
work as expected.

This commit addresses this issue by including the charset in the
implementation of equals() and introducing corresponding tests in a new
EncodedResourceTests class. Furthermore, this commit makes
EncodedResource immutable and updates all Javadoc to reflect support
for the encoding and charset properties.

Issue: SPR-12767
(cherry picked from commit 93c70b7440)
2015-02-28 18:01:24 +01:00
Brian Clozel 2d3fe96cd6 Allow file locations for resource handling
Prior to this change, location checks for serving resources would append
`/` to the location path it didn't already have one.

This commit makes sure not to append a `/` if the provided location is
actually a file.

Issue: SPR-12747
2015-02-27 19:12:01 +01:00
Juergen Hoeller 9b26e4f1ad Avoid potential deadlocks between event multicaster and singleton registry through shared lock
Issue: SPR-12739
(cherry picked from commit 772552b)
2015-02-26 21:08:49 +01:00
Juergen Hoeller 9a7871fb70 Consistent validation logic
Issue: SPR-12655
2015-02-20 00:20:07 +01:00
Juergen Hoeller 80128f1992 Polishing 2015-02-19 22:47:26 +01:00
Juergen Hoeller 186fef6808 Revised validation javadoc
Issue: SPR-12655
2015-02-19 22:46:29 +01:00
Juergen Hoeller 3f8d48eb1a Correct reference to executeAndReturnKey method
Issue: SPR-12639
2015-02-18 20:46:04 +01:00
Juergen Hoeller 3ed24bca20 ServletUriComponentsBuilder.java avoids NPE on scheme check
Issue: SPR-12723
(cherry picked from commit 61cc3b5)
2015-02-18 20:44:50 +01:00
Juergen Hoeller f8a8ecd8fe ScheduledAnnotationBeanPostProcessor uses target class as cache key in case of proxy
Issue: SPR-12709
(cherry picked from commit 1273c90)
2015-02-18 20:41:53 +01:00
Spring Buildmaster 16df002de7 Next Development Version 2014-12-30 08:23:52 -08:00
Stephane Nicoll 840ffc5ec4 Update changelog for 3.2.13 2014-12-30 16:49:14 +01:00
Stephane Nicoll 64e79ba692 Use hasLength rather than hasText 2014-12-30 15:39:48 +01:00
Stephane Nicoll 4bcf92f176 Restore JDK 5 compatiblity 2014-12-30 15:34:35 +01:00
Juergen Hoeller 75a9c45865 Polishing
Issue: SPR-12502
(cherry picked from commit 26845f6)
2014-12-30 10:13:03 +01:00
Juergen Hoeller 62a6c3733d Polishing
(cherry picked from commit e9d24d5)
2014-12-29 20:06:57 +01:00
Juergen Hoeller e353af65d2 HandlerExecutionChain prevents re-adding the interceptors array to the list (and declares varargs now)
Issue: SPR-12566
(cherry picked from commit 37713ae)
2014-12-29 20:05:04 +01:00
Juergen Hoeller 568e963466 Annotation post-processors clear old InjectionMetadata registrations on refresh
Issue: SPR-12526
(cherry picked from commit e118086)
2014-12-29 20:02:06 +01:00
Stephane Nicoll c50886ce03 Fix scope inheritance documentation
Issue: SPR-12570
2014-12-29 11:02:55 +01:00
Juergen Hoeller 2b0ada95ce AbstractApplicationEventMulticaster populates ListenerRetriever cache in fully synchronized fashion
Issue: SPR-12545
2014-12-22 15:46:58 +01:00
Juergen Hoeller 4efe6a8a5c AbstractFallbackTransactionAttributeSource's DefaultCacheKey takes targetClass into account (again)
Issue: SPR-12536
2014-12-22 14:01:19 +01:00
Juergen Hoeller ec3967a6c7 Consistent bridge method handling in annotation post-processors
Issue: SPR-12495
Issue: SPR-12187
(cherry picked from commit d97add0)
2014-12-22 13:44:01 +01:00
Juergen Hoeller 4c5e17ec3e Consistent resolution of Class methods and static methods
Issue: SPR-12502
(cherry picked from commit 9ef0bdc)
2014-12-07 23:56:06 +01:00
Juergen Hoeller 9413204838 Polishing
(cherry picked from commit 50c578c)
2014-11-28 22:06:45 +01:00
Juergen Hoeller 925c46e445 Polishing
Issue: SPR-12476
(cherry picked from commit c89d8ec)
2014-11-27 21:26:25 +01:00
Juergen Hoeller a6a837bc3b Revised SqlRowSet javadoc
Issue: SPR-12476
2014-11-27 17:59:49 +01:00
Juergen Hoeller 0e3b26da27 ExtendedBeanInfo ignores invalid bean properties (analogous to the JavaBeans Introspector)
Issue: SPR-12434
(cherry picked from commit b45f1aa)
2014-11-27 01:56:47 +01:00
Juergen Hoeller 98cbae7fdc Polishing
Issue: SPR-12462
(cherry picked from commit 5be50c8)
2014-11-24 19:11:22 +01:00
Brian Clozel 379d2e6da0 Fix location checks for servlet 3 resources
SPR-12354 applied new checks to make sure that served static resources
are under authorized locations.

Prior to this change, serving static resources from Servlet 3 locations
such as "/webjars/" would not work since those locations can be within
one of the JARs on path. In that case, the checkLocation method would
return false and disallow serving that static resource.

This change fixes this issue by making sure to call the
`ServletContextResource.getPath()` method for servlet context resources.

Note that there's a known workaround for this issue, which is using a
classpath scheme as location, such as:
"classpath:/META-INF/resources/webjars/" instead of "/webjars".

Issue: SPR-12432
(cherry picked from commit 1214624)
2014-11-24 19:11:15 +01:00
Brian Clozel c75e370eaf Use https for maven repositories
(cherry picked from commit 493e846)
2014-11-24 19:07:57 +01:00
Juergen Hoeller 4b4bc2dae0 Revised fix for SPR-12334, now finding duplicates at the collectImports level
Issue: SPR-12442
2014-11-22 23:59:12 +01:00
Juergen Hoeller feb6552d2c Avoid early initialization of Derby driver (for "derby.stream.error.method" system property)
Issue: SPR-12437
2014-11-22 23:21:31 +01:00
Juergen Hoeller 7f1e5a49a4 Polishing
(cherry picked from commit 2675ce7)
2014-11-22 23:19:48 +01:00
Juergen Hoeller f6e1856276 Rearranged WebAsyncTask constructor interdependencies and assertions
Issue: SPR-12457
(cherry picked from commit aadb93f)
2014-11-22 23:19:41 +01:00
Juergen Hoeller d02d9cea4e MethodParameter generally uses volatile variables where applicable now (as well as a local copy of the parameterNameDiscoverer field)
Issue: SPR-12453
(cherry picked from commit 7fcadaa)
2014-11-22 23:19:35 +01:00
Spring Buildmaster cf5077861a Next Development Version 2014-11-11 02:26:26 -08:00
Stephane Nicoll e2b42614c4 Update changelog 2014-11-11 10:37:24 +01:00
Rossen Stoyanchev 3f68cd633f Apply extra checks to static resource handling
- remove leading '/' and control chars
- improve url and relative path checks
- account for URL encoding
- add isResourceUnderLocation final verification

Issue: SPR-12354
2014-11-11 06:49:42 +01:00
Juergen Hoeller e1d6826fcd Polishing 2014-11-11 03:26:40 +01:00
Rossen Stoyanchev 6b353e889a Improve exception message
Issue: SPR-12230
(cherry picked from commit 2d0a677)
2014-11-06 16:34:37 +01:00
Juergen Hoeller 983ebaf658 Log context cache statistics in the TCF
Prior to this commit, finding out how many application contexts had
been loaded within a test suite required the use of reflection and a
bit of hacking.

This commit addresses this issue by logging ContextCache statistics
whenever an application context is loaded by the Spring TestContext
Framework (TCF).

The log output can be enabled by setting the
"org.springframework.test.context.cache" logging category to DEBUG.

Issue: SPR-12409
(cherry picked from commit a09bc9b)
2014-11-06 16:34:29 +01:00
Juergen Hoeller d5e4592728 Polishing 2014-11-02 11:19:54 +01:00
Juergen Hoeller 233393e3d5 Test for <util:map> with LinkedCaseInsensitiveMap and specified key/value types, with corresponding 3.2.x fix
Issue: SPR-10994
(cherry picked from commit de8645b)
2014-11-02 11:08:46 +01:00
Juergen Hoeller bb6349f8cc SimpleMetadataReaderFactory is capable of resolving inner class names with dot syntax now (analogous to ClassUtils.forName)
Issue: SPR-12390
(cherry picked from commit 2d874d7)
2014-11-02 00:22:08 +01:00
Juergen Hoeller d53b67f5cb TilesConfigurer defensively expects null from getResources in case of no resources found
Also includes order preservation for resource results with Tiles 2 as well as retrieval failure logging with Tiles 3.

Issue: SPR-12362
(cherry picked from commit c8b8dc5)
2014-11-02 00:21:19 +01:00
Juergen Hoeller f812998826 Set ResponseStatusExceptionResolver.messageSource in the MVC Java config
Issue: SPR-12380
(cherry picked from commit aa82da8)
2014-11-02 00:21:02 +01:00
Juergen Hoeller 7d44c7cb51 QualifierAnnotationAutowireCandidateResolver calls BeanFactory.getType defensively
Issue: SPR-12191
(cherry picked from commit 73ce3b5)
2014-10-22 17:23:41 +02:00
Juergen Hoeller be89612ec0 ConfigurationClassParser avoids ImportBeanDefinitionRegistrar double scan
Issue: SPR-12334
2014-10-22 01:58:57 +02:00
Juergen Hoeller 4ab27d83a1 Consistently accept empty Content-Type header and empty character encoding
Issue: SPR-12173
(cherry picked from commit a1c0905)
2014-10-22 01:58:22 +02:00
Juergen Hoeller de3ea5dad6 Deprecated BeanDefinitionDocumentReader's setEnvironment method in favor of access via XmlReaderContext
Issue: SPR-12248
2014-10-07 18:00:21 +02:00
Juergen Hoeller 1341fd4e73 Consistent use of LinkedHashSet for interfaces (since interface order may matter in subtle cases)
(cherry picked from commit 6f9d7da)
2014-10-07 17:50:20 +02:00
Juergen Hoeller 473d97350e Explicitly detect (and log) private @Scheduled methods on CGLIB proxies
Issue: SPR-12308
(cherry picked from commit 47ed4d6)
2014-10-07 17:38:37 +02:00
Juergen Hoeller 76ab5b9de2 Consistent reset of resource holders on doBegin failure
Issue: SPR-12280
(cherry picked from commit 9758bc7)
2014-10-07 00:39:45 +02:00
Juergen Hoeller 6183e83b6a Provider declaration for @Value method argument works again
Issue: SPR-12297
(cherry picked from commit c672678)
2014-10-07 00:23:24 +02:00
Juergen Hoeller a1538a451a Further locking optimizations for the retrieval of non-singleton beans
Issue: SPR-12250
(cherry picked from commit ac4103d)
2014-10-07 00:12:12 +02:00
Juergen Hoeller b45d08f192 Remove outdated references to ContextLoaderServlet
Issue: SPR-7725
2014-09-30 20:56:57 +02:00
Juergen Hoeller 65d47afc11 WebAsyncManager avoids concurrentResult.toString() and builds correct DeferredResultProcessingInterceptor keys
Issue: SPR-12253
(cherry picked from commit 901346e)
2014-09-30 20:51:45 +02:00
Juergen Hoeller 2c921681fe LiveBeansView escapes double quotes in resource descriptions
Issue: SPR-12252
(cherry picked from commit 1ffefcb)
2014-09-30 20:49:04 +02:00
Juergen Hoeller 834ddad616 Polishing
(cherry picked from commit 50e50d0)
2014-09-20 01:01:30 +02:00
Juergen Hoeller 37da70629f ScheduledAnnotationBeanPostProcessor avoids needless re-scanning of non-annotated classes
Issue: SPR-12189
(cherry picked from commit 58b22ce)
2014-09-17 22:50:05 +02:00
Juergen Hoeller 5cf452463e Log warning for single optional constructor when no default constructor to fall back to
Issue: SPR-12161
(cherry picked from commit 80cec01)
2014-09-17 22:39:13 +02:00
Juergen Hoeller e819999c08 Polishing 2014-09-17 19:10:33 +02:00
Juergen Hoeller 3a1f7b6d14 Client request implementations enforce RFC 6265 (cookies in a single header)
Issue: SPR-12196
(cherry picked from commit 26a93b6)
2014-09-17 18:43:04 +02:00
Juergen Hoeller 44c52a9096 Accept empty Content-Type header
Issue: SPR-12173
(cherry picked from commit 70412a9)
2014-09-17 18:17:09 +02:00
Spring Buildmaster f2675f7571 Next Development Version 2014-09-04 06:29:53 -07:00
Brian Clozel 0262d33f11 Polish 2014-09-04 11:27:55 +02:00
Brian Clozel ab8c3c785f Update changelog for 3.2.11 version 2014-09-04 11:13:32 +02:00
Juergen Hoeller 3264437cec Polishing 2014-09-04 02:42:34 +02:00
Juergen Hoeller 3d4e73b10c Polishing 2014-09-04 01:47:00 +02:00
Juergen Hoeller 42557743e8 CachingConnectionFactory proceeds to physicalClose in case of logicalClose exceptions
Issue: SPR-12148
(cherry picked from commit 82f8b43)
2014-09-04 01:45:47 +02:00
Juergen Hoeller d18bdf6448 Polishing
(cherry picked from commit d2ef6dc)
2014-09-03 14:25:16 +02:00
Juergen Hoeller 5da8a16284 AbstractAutowireCapableBeanFactory avoids early FactoryBean instantiation on currently created configuration bean
Issue: SPR-12141
(cherry picked from commit 4432c41)
2014-09-03 14:23:56 +02:00
Sam Brannen 3b64db18f7 Include ALL source artifacts in published sources jars
This commit updates the Gradle build to ensure that *all* source
artifacts are including in published 'sources' jars.

To achieve this, we are now assembling 'sources' jars from
'sourceSets.main.allSource' and not explicitly including or excluding
anything by default.

Issue: SPR-12085
(cherry picked from commit 07629a3c7c)
2014-08-26 17:06:42 +02:00
Juergen Hoeller 21f0057990 Polishing 2014-08-23 00:11:19 +02:00
Juergen Hoeller 3e17331fd9 PropertySource implementations perform conversion to String arrays via StringUtils (getting rid of EMPTY_NAMES_ARRAY)
(cherry picked from commit b73c531)
2014-08-22 23:51:39 +02:00
Juergen Hoeller a4c8e6176c Consistent attribute documentation/formatting in spring-context and spring-mvc schemas
(cherry picked from commit b5763fe)
2014-08-22 23:50:34 +02:00
Juergen Hoeller 7cf4a4ed2d DispatcherServlet's checkMultipart detects wrapped MultipartRequest as well
Issue: SPR-12114
(cherry picked from commit 786fd92)
2014-08-22 23:49:16 +02:00
Juergen Hoeller 388561df61 PersistenceAnnotationBeanPostProcessor defensively handles BeanDefinition access for extended EntityManagers
Issue: SPR-8834
(cherry picked from commit 592e344)
2014-08-22 23:47:26 +02:00
Juergen Hoeller e89f18bf6d DefaultListableBeanFactory defensively handles BeanDefinition access in getBean(Class)
Issue: SPR-10542
(cherry picked from commit 9d3d6d5)
2014-08-22 23:44:47 +02:00
Stephane Nicoll 76a3e6e6e1 Exclude infra modules from public distribution
Prior to this commit, spring-build-src and spring-framework-bom
internal artifacts were published as part of the distribution bundle.

This commit excludes those projects so that those unnecessary artifacts
are no longer shipped.

Issue: SPR-12087
2014-08-18 13:33:16 +02:00
Juergen Hoeller 0492c9955c Polishing
(cherry picked from commit a31ebb6)
2014-08-15 00:30:14 +02:00
Juergen Hoeller 0c89279d61 Polishing 2014-08-13 15:54:21 +02:00
Juergen Hoeller 3038f03fee Polishing
(cherry picked from commit 4db258b)
2014-08-11 23:34:49 +02:00
Juergen Hoeller 36918d6bb7 Polishing (includes varargs for selected setters) 2014-08-11 22:12:26 +02:00
Juergen Hoeller 6639320e8e Tiles 3 TilesViewResolver allows for specifying custom TilesView subclasses as well
Issue: SPR-12075
(cherry picked from commit 7c57424)
2014-08-11 22:11:07 +02:00
Juergen Hoeller 214f026ea3 Polishing 2014-07-29 12:45:32 +02:00
Juergen Hoeller c0a4631fd1 Polishing 2014-07-29 10:10:48 +02:00
Juergen Hoeller daaeeaa8e2 Latest dependency updates (Hibernate ORM 4.2.15, propdeps plugin 0.0.7) 2014-07-29 00:47:30 +02:00
Juergen Hoeller 780ea59ff3 Polishing 2014-07-29 00:46:20 +02:00
Juergen Hoeller e14aad8840 ResourceHttpMessageConverter does not call contentLength() on InputStreamResource
Issue: SPR-12017
(cherry picked from commit f0bcb77)
2014-07-29 00:18:16 +02:00
Juergen Hoeller 902303b44d AbstractMessageListenerContainer calls "Session.recover()" in case of rollback attempt on non-transacted Session
Issue: SPR-12015
(cherry picked from commit c082220)
2014-07-29 00:17:31 +02:00
Juergen Hoeller b56c8f49b5 AbstractApplicationContext logs initialization exception before trying to cancel refresh attempt
Issue: SPR-12010
(cherry picked from commit 5e2fbe7)
2014-07-29 00:16:41 +02:00
Juergen Hoeller 619e3a995d ClassUtils.isCacheSafe defensively catches SecurityException (for Google App Engine compatibility)
Issue: SPR-12002
(cherry picked from commit 48fea0b)
2014-07-29 00:15:09 +02:00
Juergen Hoeller a3ebf13579 SelectedValueComparator defensively handles null values in exhaustiveCompare
Issue: SPR-12001
(cherry picked from commit 980f971)
2014-07-29 00:13:29 +02:00
Juergen Hoeller ab9d947c08 DefaultListableBeanFactory's registerBeanDefinition only calls resetBeanDefinition in case of pre-existing bean definition or pre-existing singleton instance
Issue: SPR-8318
(cherry picked from commit a4968b9)
2014-07-29 00:13:04 +02:00
Arjen Poutsma b6f13b857c StaxStreamXMLReader ignores significant whitespace
The StaxStreamXMLReader no longer handles all whitespace as ignorable
whitespace.

Issue: SPR-12000
(cherry picked from commit d6950d8)
2014-07-29 00:08:14 +02:00
Brian Clozel 8c43fe1796 Fix UriComponentsBuilder.fromUriString parsing error
This commit fixes cases where part of the URI was mistaken for the
userinfo when:
* the URI did not contain any path
* the query string contained the "@"

Issue: SPR-11970
(cherry picked from commit a4484bb)
2014-07-29 00:06:26 +02:00
Spring Buildmaster a95ed4ad29 Next development version 2014-07-15 16:35:20 -07:00
Phillip Webb 612eba6728 Update changelog 2014-07-15 15:52:39 -07:00
Juergen Hoeller 7a3dd2a42b Allow ASM5's bytecode parsing of INVOKESPECIAL/STATIC on interfaces
Issue: SPR-11979
2014-07-10 17:03:18 +02:00
Juergen Hoeller cec3ffa3ca Polishing
Issue: SPR-8045
(cherry picked from commit 7eee7d2)
2014-07-08 00:16:32 +02:00
Juergen Hoeller a45d49c857 RestTemplate accepts getMessageConverters() List on setMessageConverters again
Issue: SPR-11962
(cherry picked from commit 1222ca3)
2014-07-07 21:05:27 +02:00
Juergen Hoeller 45c93e4791 Polishing 2014-07-04 22:39:29 +02:00
Juergen Hoeller 83a7deb594 ConstructorResolver's exception message on null factory-bean hints at potential BeanPostProcessor involvement
Issue: SPR-11951
(cherry picked from commit 6c41cc3)
2014-07-04 22:35:12 +02:00
Juergen Hoeller d10220edf8 Refined DefaultJpaDialect's InvalidIsolationLevelException message
Issue: SPR-8325
(cherry picked from commit af13310)
2014-07-03 22:54:30 +02:00
Juergen Hoeller fe72fcede5 Polishing
(cherry picked from commit ede2150)
2014-07-02 18:18:21 +02:00
Juergen Hoeller 010d8b8c89 Defensively check for pre-resolved FactoryBean.getObject() results in circular reference scenarios
Issue: SPR-11937
(cherry picked from commit 07edf11)
2014-07-02 00:32:01 +02:00
Juergen Hoeller 8307447235 CachedIntrospectionResults uses SoftReference instead of WeakReference for non-cache-safe entries
Issue: SPR-11867
(cherry picked from commit f27b949)
2014-07-02 00:31:06 +02:00
Juergen Hoeller 983cce22d8 Package javadoc cleanup for web.servlet.mvc, removing outdated references
Issue: SPR-11935
(cherry picked from commit 7396210)
2014-07-01 18:26:31 +02:00
Juergen Hoeller 67ebef6b32 BeanFactoryAnnotationUtils consistently applies bean name fallback when no BeanDefinition present
Issue: SPR-11915
(cherry picked from commit b9935e9)
2014-07-01 18:26:26 +02:00
Juergen Hoeller 386b757e84 Upgrade to ASM 5.0.3 (and Hibernate 4.2.14)
Issue: SPR-11889
2014-07-01 14:45:04 +02:00
Juergen Hoeller c033f889bf Polishing (backported from master)
(cherry picked from commit 48f753f)
2014-07-01 14:28:05 +02:00
Juergen Hoeller 44c61e5d5f Consistent declaration of private static final logger variables
Issue: SPR-11905
(cherry picked from commit c16032b)
2014-07-01 14:22:56 +02:00
Juergen Hoeller f4062bc758 AbstractAutowireCapableBeanFactory's createBean/autowireBean/configureBean use CacheUtils.isCacheSafe to re-enable PropertyDescriptor caching
Issue: SPR-11875
(cherry picked from commit c32d559)
2014-07-01 14:22:03 +02:00
Juergen Hoeller 0298a1f093 Cache Class.getDeclaredMethods() results and avoid pattern matching in isCglibRenamedMethod as far as possible
Issue: SPR-11882
Issue: SPR-11894
(cherry picked from commit 5f695a4)
2014-07-01 14:21:37 +02:00
Juergen Hoeller 247771ce91 UriComponentBuilder allows for multiple independent build() calls on same builder instance
Issue: SPR-11885
(cherry picked from commit c73ac07)
2014-07-01 14:20:11 +02:00
Juergen Hoeller 1be3a6cce2 FrameworkPortlet properly initializes StandardPortletEnvironment's property sources and exposes local PortletRequestAttributes in case of pre-bound ServletRequestAttributes as well
Issue: SPR-11816
Issue: SPR-11295
(cherry picked from commit 7d94b5e)
2014-07-01 14:19:56 +02:00
Juergen Hoeller 1ca0351831 PathMatchingResourcePatternResolver's findPathMatchingResources needs to check for VFS before checking isJarResource
ResourceUtils isFileURL also detects "vfsfile" as a file system protocol (again).

Issue: SPR-11887
(cherry picked from commit 8ddbbc2)
2014-07-01 14:19:20 +02:00
Juergen Hoeller 5b4748d897 MBeanExportConfiguration's SpecificPlatform properly calls afterPropertiesSet
Issue: SPR-11877
(cherry picked from commit 0a34f86)
2014-07-01 14:18:51 +02:00
Juergen Hoeller 13197b6aa5 WebSphereUowTransactionManager exposes SmartTransactionObject
Issue: SPR-11876
(cherry picked from commit a0c86ae)
2014-07-01 14:18:14 +02:00
Juergen Hoeller d96550898f HttpHeaders fails getAllow if set to EmptyCollection
Prior to this commit, calls to getAllow would fail is setAllow was set
to an EmptyCollection right before.

    java.lang.IllegalArgumentException: No enum constant
    org.springframework.http.HttpMethod

This commit fixes this by testing the header value for an empty value
before trying to use it to get a value from the Enum.

Issue: SPR-11917
(cherry picked from commit 9054f4f)
2014-07-01 14:17:55 +02:00
Spring Buildmaster fa2d21c27c Next development version 2014-05-20 04:50:17 -07:00
Phillip Webb 69b9d00179 Add 3.2.9 issues to the changelog 2014-05-20 11:40:13 +01:00
Juergen Hoeller 8aabc43dad Servlet 3 multipart request implements getParameterMap defensively as well
Issue: SPR-11074
(cherry picked from commit c7d1c49)
2014-05-20 11:28:57 +02:00
Juergen Hoeller 4d3aa59028 Polishing
(cherry picked from commit 6fef8b9)
2014-05-20 11:27:55 +02:00
Rossen Stoyanchev c6503ebbf7 Disable URL resolution in DTD declarations
Issue: SPR-11768
2014-05-19 22:43:14 -04:00
Juergen Hoeller f42f2231a4 Minor UriComponentsBuilder javadoc revision
(cherry picked from commit 545c28f)
2014-05-20 01:06:01 +02:00
Juergen Hoeller 0313222bc7 Consistent use of IllegalStateException instead of InternalError for UnsupportedEncodingException cause
(cherry picked from commit d9b39ad)
2014-05-20 01:05:55 +02:00
Juergen Hoeller f524a5abe4 StringUtils.parseLocaleString parses variant correctly when variant contains country code
This commit also includes a JUnit 4 style revision of StringUtilsTests and ObjectUtilsTests.

Issue: SPR-11806
(cherry picked from commit 295a6ae)
2014-05-19 23:05:47 +02:00
Juergen Hoeller f053ce52ea Consistently log Class.getName() instead of Class.toString(), avoiding double class term in log message
Issue: SPR-11804
(cherry picked from commit 1120680)
2014-05-19 21:03:29 +02:00
Juergen Hoeller 5e05a84d81 Refined check for NoClassDefFoundError in getTestExecutionListeners()
Issue: SPR-11804
(cherry picked from commit a2ef2c9)
2014-05-19 17:55:58 +02:00
Juergen Hoeller c7b2ac7bac Backported proper updateAccessedAttributes test
Issue: SPR-11738
(cherry picked from commit 1bbc032)
2014-05-19 17:40:11 +02:00
Juergen Hoeller cbff8b01bb Javadoc fixes 2014-05-18 23:55:57 +02:00
Juergen Hoeller dc50001620 Additional tests for configuration class importing via ASM
Issue: SPR-11647
(cherry picked from commit 8c9116f)
2014-05-18 23:55:12 +02:00
Juergen Hoeller faaf43677d Servlet 3 multipart request implements getParameterNames defensively (for WebLogic 12 compatibility)
This commit also includes lazy resolution support for StandardServletMultipartResolver, along the lines of existing lazy mode in CommonsMultipartResolver.

Issue: SPR-11074
Issue: SPR-11730
(cherry picked from commit 82336c3)
2014-05-18 20:51:39 +02:00
Rossen Stoyanchev f6fddeb6eb Improve StringUtils.cleanPath
Issue: SPR-11793
2014-05-16 11:28:53 -04:00
Juergen Hoeller c3ba0a2c5b JmsResourceHolder checks for nested DataSource transactions as well (for Oracle AQ compatibility)
Issue: SPR-11791
(cherry picked from commit 5faacd5)
2014-05-16 16:55:10 +02:00
Juergen Hoeller 8fed2f0c6c Minor 3.2.x build polishing (including Tiles 3.0.4 upgrade) 2014-05-16 16:54:50 +02:00
Juergen Hoeller b0f7184f3f Polishing 2014-05-15 15:19:17 +02:00
Juergen Hoeller 3ae6c0f401 ResultSetWrappingSqlRowSet preserves first matching column per name (as defined in ResultSet's javadoc)
Issue: SPR-11786
(cherry picked from commit 0728e32)
2014-05-15 15:10:12 +02:00
Juergen Hoeller bc43f2e72a IdToEntityConverter defensively handles access to getDeclaredMethods
Issue: SPR-11758
(cherry picked from commit 381ccde)
2014-05-09 23:17:01 +02:00
Juergen Hoeller 759bb33665 Upgraded to propdeps plugin 0.0.6 and backported several build script refinements 2014-05-01 00:49:29 +02:00
Juergen Hoeller a139670286 Fixed invalid code tag in javadoc 2014-05-01 00:49:22 +02:00
Juergen Hoeller 1fe477a273 Upgraded to Gradle 1.12 and updated selected dependencies
(cherry picked from commit e84f61b)
2014-04-30 20:48:57 +02:00
Juergen Hoeller 0e710769c2 JRubyScriptUtils defensively handles null Nodes in findClassNode (fails against JRuby 1.7.12 otherwise)
Issue: SPR-11747
(cherry picked from commit adb616b)
2014-04-30 20:47:59 +02:00
Juergen Hoeller a5606a6c46 Polishing 2014-04-29 23:39:17 +02:00
Juergen Hoeller 3cb1cb5d2f ConfigurationClassParser considers EnvironmentAware on ImportBeanDefinitionRegistrars
Issue: SPR-11744
2014-04-29 22:02:18 +02:00
Juergen Hoeller 79820e449b ConfigurationClassEnhancer consistently uses registerStaticCallbacks in order to prevent memory leaks
Issue: SPR-9274
2014-04-29 21:59:12 +02:00
Juergen Hoeller 2f5d378d82 AbstractAdvisingBeanPostProcessor uses target class check for existing proxy but checks against actual exposed object otherwise (catching introductions)
Issue: SPR-11725
(cherry picked from commit a0658c5)
2014-04-29 21:49:09 +02:00
Juergen Hoeller 228a586efb AspectJExpressionPointcut defensively handles fallback expression parsing
Issue: SPR-9335
(cherry picked from commit ce4912b)
2014-04-29 21:45:19 +02:00
Juergen Hoeller b13c5b2378 GenericBeanDefinition's toString() takes parent definition into account
Issue: SPR-9671
(cherry picked from commit 0ef29b2)
2014-04-29 21:42:19 +02:00
Juergen Hoeller 779a6b79eb Polishing 2014-04-27 22:52:51 +02:00
Juergen Hoeller 9e2060707a General defensiveness about the bootstrap ClassLoader (i.e. null ClassLoader)
Issue: SPR-11721
2014-04-27 22:29:08 +02:00
Juergen Hoeller 2c1203dc9f AnnotationTypeFilter prevents ASM-based loading of java.* and javax.* interfaces as well
Issue: SPR-11719
2014-04-27 22:28:56 +02:00
Juergen Hoeller 6ee0596c3a SpringProperties falls back to ClassLoader.getSystemResource when loaded in bootstrap ClassLoader
Issue: SPR-11721
(cherry picked from commit 9cb5f48)
2014-04-27 22:28:08 +02:00
Juergen Hoeller 93d13cfcb1 AbstractMarshaller avoids SAXSource workaround when processExternalEntities=true
Issue: SPR-11737
2014-04-27 22:27:46 +02:00
Juergen Hoeller de80cd9b3b ASM 5.0.2 for correct Java 7 stack map frame computations
Issue: SPR-11656
2014-04-25 23:50:02 +02:00
Juergen Hoeller 470e9c8558 Configuration class processing explicitly skips java.* classes since we'll never find @Bean annotations there anyway
Issue: SPR-11718
2014-04-25 23:39:50 +02:00
Juergen Hoeller dc934064a2 @Bean processing explicitly ignores bridge methods (for method overrides with return type narrowing on JDK 8)
Issue: SPR-11718
2014-04-25 23:37:37 +02:00
Juergen Hoeller 5d5f70473a checkNotModified leniently handles IE-10-style If-Modified-Since values and silently proceeds if header value cannot be parsed at all
Issue: SPR-11727
(cherry picked from commit 794e859)
2014-04-25 23:33:10 +02:00
HejiaHo ac85eab372 Fix ConcurrentReferenceHashMap max constraints
Update calculateShift to respect the maximum upper bound as well as the
minimum value.

Issue: SPR-11720

(cherry picked from commit 16410cad)
2014-04-22 15:01:51 +01:00
Juergen Hoeller ffaac0ecf3 Polishing 2014-04-18 13:23:05 +02:00
Juergen Hoeller 5aa93674a3 Consistent documentation for both 'close' and 'shutdown' as inferred destroy methods
Issue: SPR-11680
(cherry picked from commit 14f9dbf)
2014-04-18 12:09:27 +02:00
Phillip Webb 62941b7937 Fixup .mailmap file
Fix a few issues with the `.mailmap` file.

(cherry picked from commit 3a5de00c)
2014-04-18 11:01:38 +01:00
Graham Lea 5fac6614b6 Added a Git .mailmap file
(cherry picked from commit a5e1932c)
2014-04-18 09:50:43 +01:00
Sam Brannen a169c0e727 Ensure Gradle does not execute inner classes as tests 2014-04-10 16:56:56 +02:00
Juergen Hoeller 94caaedf84 Polishing 2014-04-09 20:31:15 +02:00
Juergen Hoeller be6b54fe8b JBoss "vfszip" resources need to be treated as jar URLs
Issue: SPR-11676
2014-04-09 20:30:50 +02:00
Juergen Hoeller 9ac46a965f Java 8 bytecode compatibility for Spring 3.2.x
Issue: SPR-11656
2014-04-09 20:29:17 +02:00
Juergen Hoeller d8a0f7578d Commons Logging resolution failure with JasperReports 2.0.5 -> easiest way out: upgrade to JasperReports 3.7.6 (which in turn requires POI 3.6) 2014-04-02 22:59:42 +02:00
Juergen Hoeller 99a3e9cacb Revised ByteArrayOutputStream handling in MarshallingView and co
Issue: SPR-11646
(cherry picked from commit 8006696)
2014-04-02 22:56:34 +02:00
Juergen Hoeller f93bfa8f84 ResourceHttpRequestHandler explicitly closes a Resource's InputStream
Issue: SPR-11644
(cherry picked from commit 3a96f16)
2014-04-02 22:55:52 +02:00
Juergen Hoeller b80dc9d642 Polishing
Issue: SPR-11262
(cherry picked from commit d628025)
2014-04-02 22:55:33 +02:00
Sam Brannen b31750fafb Reinject Servlet mocks between TestNG test methods
Prior to this commit, if multiple test methods were executed in a
subclass of AbstractTestNGSpringContextTests annotated with
@WebAppConfiguration, then injected Servlet API mocks would only
reference the mocks created for the first test method. Subsequent test
methods could therefore never reference the current mocks, and there
was a discrepancy between the state of the injected mocks and the mock
set in the RequestContextHolder.

This commit addresses this issue by ensuring that dependencies
(including updated mocks) are injected into the test instance before
the next test method if the ServletTestExecutionListener resets the
request attributes in RequestContextHolder.

Issue: SPR-11626
(cherry picked from commit c38600762d)
2014-03-29 21:43:42 +01:00
Juergen Hoeller a4a2e80f23 Consider a null ClassLoader (typically the bootstrap CL) as cache-safe
Issue: SPR-11606
2014-03-26 23:48:29 +01:00
Juergen Hoeller e8c06c6d99 Consistent PropertyAccessor method order as declared in the interface
Issue: SPR-11609
(cherry picked from commit b70148c)
2014-03-26 21:57:40 +01:00
Juergen Hoeller d8180e1e20 Correctly resolve accessors for static properties on Class
Issue: SPR-11609
(cherry picked from commit 3af8a32)
2014-03-26 21:57:35 +01:00
Juergen Hoeller 88485dc1a7 Maintenance version updates (aligned with 4.0.3 release) 2014-03-26 21:12:25 +01:00
Juergen Hoeller a25d67770e Added expression test case for constant on Map
Issue: SPR-11609
2014-03-26 21:11:49 +01:00
Juergen Hoeller 5c9fc09852 Added Spring Data oriented conversion test case
Issue: SPR-11608
2014-03-26 20:50:00 +01:00
Juergen Hoeller e1602f7f83 AbstractApplicationEventMulticaster only caches if event type and source type are cache-safe
Issue: SPR-11606
(cherry picked from commit 3388573)
2014-03-26 20:34:55 +01:00
Juergen Hoeller 20228e78c5 CacheAspectSupport checks Cache.get(key) once per invocation only
Issue: SPR-11592
2014-03-26 00:21:39 +01:00
Juergen Hoeller 623b1fc0d5 Polishing 2014-03-25 00:37:01 +01:00
Juergen Hoeller a2bdc284f9 DispatcherServlet logs request URI in encoded form only
Issue: SPR-11591
(cherry picked from commit 465ca24)
2014-03-25 00:36:36 +01:00
Juergen Hoeller dbd5f67498 Consistently applied appropriate ByteArrayOutputStream initial capacities across the codebase
Issue: SPR-11594
(cherry picked from commit dd7f54c)
2014-03-25 00:35:33 +01:00
Juergen Hoeller ab85aa2096 BufferedImageHttpMessageConverter ignores empty MIME types
Issue: SPR-11581
(cherry picked from commit 90e3dbb)
2014-03-25 00:34:53 +01:00
Juergen Hoeller 5c3f6a1571 Revised naming for prototype inner beans to avoid excessive unique name calculation
Restored original singleton-only adaptInnerBeanName behavior, avoiding endless unique name calculation for every single prototype instance. Non-named inner BeanDefinition objects now suffixed with an identity hex code analogous to non-named XML bean definitions, largely avoiding naming collisions to begin with. After SPR-11246, post-processors can deal with unstable classes per bean name, so occasional collisions aren't a hard problem anymore.

Issue: SPR-11545
(cherry picked from commit 5308b3e)
2014-03-25 00:34:41 +01:00
Juergen Hoeller b73a43972e Upgraded to TestNG 6.8.8 and Hibernate 4.2.10 2014-03-11 21:36:44 +01:00
Juergen Hoeller 9585752693 Polishing 2014-03-11 21:36:10 +01:00
Juergen Hoeller 5c0fdb05bd AbstractFlashMapManager needs to decode parameter names
Also includes general alignment with the 4.0.3 versions of AbstractFlashMapManager and FlashMapManagerTests.

Issue: SPR-11504
2014-03-11 21:35:36 +01:00
Juergen Hoeller eeb82c409a SpEL property-not-found message hints at non-public method/field
Issue: SPR-11535
2014-03-11 10:47:53 +01:00
Juergen Hoeller d317b637e0 CollectionToCollectionConverter avoids collection copy for untyped collection when simply returning source anyway
Also uses addAll instead of iteration over untyped collection now, supporting optimized addAll in target collection type, and avoids repeated getElementTypeDescriptor calls.

Issue: SPR-11479
(cherry picked from commit bea94d5)
2014-03-10 18:48:01 +01:00
Stephane Nicoll b1bcc5d6eb Fix double SPeL evaluation of parameter
When a node of an SPeL expression was a call to a bean referenced
 in a method argument, the expression was resolved twice.

 The resolved arguments are now specified to MethodValueRef instead
 of resolving the arguments again in the constructor

 Issue: SPR-11445
(cherry picked from commit 519799e)
2014-03-07 14:59:41 +01:00
Juergen Hoeller f1ba789494 DefaultListableBeanFactory only puts 'cache-safe' Class keys into its by-type cache
Issue: SPR-11520
(cherry picked from commit 93c8b7a)
2014-03-07 14:58:51 +01:00
Juergen Hoeller d642cd21bb SpringBeanELResolver's setValue should not throw PropertyNotWritableException if provided value is identical to current bean instance
Issue: SPR-11502
(cherry picked from commit 7972b31)
2014-03-07 14:58:16 +01:00
Juergen Hoeller 70155e9ff9 KeyGenerators should not return a plain array parameter as raw key but rather always handle that case in a deepHashCode fashion
Issue: SPR-11505
(cherry picked from commit e50cff4)
2014-03-07 14:57:25 +01:00
Juergen Hoeller 7e2a214f32 instantiateUsingFactoryMethod avoids NPE and reports argument types in case of explicitArgs and resolved generic arguments as well
Issue: SPR-11517
(cherry picked from commit ad31777)
2014-03-07 14:56:45 +01:00
Juergen Hoeller 4c9c7634d0 Log4jWebConfigurer does not try to parse empty "log4jRefreshInterval" context-param
Issue: SPR-11507
(cherry picked from commit 9b77157)
2014-03-07 14:55:44 +01:00
Juergen Hoeller 69c54a053c Fixed content length check in XmlValidationModeDetector
Issue: SPR-11477
(cherry picked from commit 1763bfb)
2014-03-07 14:55:11 +01:00
Rossen Stoyanchev 4b9aad8f65 Refactor async result handling in Spring MVC Test
This change removes the use of a CountDownLatch to wait for the
asynchronously computed controller method return value. Instead we
check in a loop every 200 milliseconds if the result has been set.
If the result is not set within the specified amount of time to wait
an IllegalStateException is raised.

Additional changes:
 - Use AtomicReference to hold the async result
 - Remove @Ignore annotations on AsyncTests methods
 - Remove checks for the presence of Servlet 3

Issue: SPR-11516
2014-03-05 14:54:34 -05:00
Spring Buildmaster 5fe436c9a9 Next development version 2014-02-18 21:51:58 -08:00
Phillip Webb 082a564b9b Update changelog for 3.2.8 2014-02-18 20:58:34 -08:00
Rossen Stoyanchev fb0683c066 Add processExternalEntities support to OXM
Update OXM AbstractMarshaller to support processing of external
XML entities. By default external entities will not be processed.

Issue: SPR-11376
2014-02-18 16:01:20 -08:00
Phillip Webb 09c57203bb Fix memory leak in ConcurrentReferenceHashMap
Update ConcurrentReferenceHashMap to protect against references that
have been garbage collected but for some reason do not appear as a
`pollForPurge` result.

Also added purgeUnreferencedEntries() method to allow for programmatic
cleanup.

Issue: SPR-11440
(cherry picked from commit 2b4c81e6)
2014-02-18 15:18:26 -08:00
Juergen Hoeller 4886bf0708 Polishing 2014-02-14 23:46:22 +01:00
Juergen Hoeller 75e08695a0 Mixed polishing along with recent changes
(cherry picked from commit 14e5a02)
2014-02-14 23:27:09 +01:00
Juergen Hoeller 5da79ebca6 Related polishing
Issue. SPR-11428
(cherry picked from commit 9c6df76)
2014-02-14 23:21:29 +01:00
Juergen Hoeller bb7a1372c0 Avoid unnecessary getMappingForMethod repeat (in particular for RequestMappingInfo)
Issue. SPR-11428
(cherry picked from commit f913940)
2014-02-14 22:54:16 +01:00
Juergen Hoeller 7e3c722146 Objects with multi-threaded access should not lazily populate a hash field
Issue. SPR-11428
(cherry picked from commit 72fe7eb)
2014-02-14 22:53:13 +01:00
Juergen Hoeller d7591c6bd7 Clarified CompositeCacheManager's applicability, added convenience constructor with given delegates, and fixed getCacheNames implementation to never return duplicates
Issue: SPR-11427
(cherry picked from commit d550ffb)
2014-02-14 22:51:12 +01:00
Juergen Hoeller 42dec02203 EhCache/JCacheCacheManager needs to re-obtain runtime-added Cache reference for potential decoration
Issue: SPR-11407
(cherry picked from commit ef1748f)
2014-02-14 22:48:23 +01:00
Sam Brannen 27ad1990e3 Fix imports in SourceHttpMessageConverterTests
Replaced static import of org.junit.Assert.* with implicit imports in
order to avoid ambiguity between JUnit's static Assert methods and those
in org.custommonkey.xmlunit.XMLAssert.
2014-02-13 00:45:40 +01:00
Juergen Hoeller 337b5ff5d6 Actually upgraded to Gradle 1.11 2014-02-13 00:42:41 +01:00
Juergen Hoeller b40403cdc9 Polishing
Issue: SPR-11422
(cherry picked from commit 520ef9e)
2014-02-13 00:42:22 +01:00
Juergen Hoeller 0972582880 resolveFactoryMethodIfPossible considers nonPublicAccessAllowed and SecurityManager
Issue: SPR-11422
(cherry picked from commit 603cdea)
2014-02-13 00:42:16 +01:00
Sam Brannen bc879100c4 Test against CGLIB memory leak for method injection
This commit introduces a test in XmlBeanFactoryTests that verifies that
CGLIB generated subclasses for method injected beans are reused across
bean factories for identical bean definitions. In other words, by
verifying that the same CGLIB generated class is reused for identical
bean definitions, we can be certain that Spring is no longer generating
identical, duplicate classes that consume memory in the VM.

Issue: SPR-10785, SPR-11420
(cherry picked from commit f2a4537)
2014-02-13 00:31:13 +01:00
Sam Brannen 9f77ef4102 Exclude overloaded from equals & hashCode in MethodOverride
Prior to this commit, the inclusion of the 'overloaded' flag in the
implementations of equals() and hashCode() in MethodOverride could lead
to adverse effects in the outcome of equals() in AbstractBeanDefinition.

For example, given two bean definitions A and B that represent the
exact same bean definition metadata for a bean that relies on method
injection, if A has been validated and B has not, then A.equals(B) will
potentially return false, which is not acceptable behavior.

This commit addresses this issue by removing the 'overloaded' flag from
the implementations of equals() and hashCode() for MethodOverride.

Issue: SPR-11420
(cherry picked from commit 9534245)
2014-02-12 17:20:43 +01:00
Juergen Hoeller 7f95a27e6d Upgraded to Commons Logging 1.1.3 and Gradle 1.11 2014-02-12 15:15:41 +01:00
Juergen Hoeller 4ac4630b0b Polishing 2014-02-12 15:15:05 +01:00
Juergen Hoeller 29b40b9d0e Revised InvocableHandlerMethod exception handling
Issue: SPR-11281
(cherry picked from commit 1a1c72c)
2014-02-12 15:13:28 +01:00
Juergen Hoeller 85e336e6da Consistently avoid close() call on Servlet OutputStream
Issue: SPR-11413
(cherry picked from commit 5f1592a)
2014-02-12 15:12:43 +01:00
Juergen Hoeller b223e6efec MarshallingView should not close response OutputStream after copying to it
MarshallingView also explicitly skips BindingResult when searching for a model object now, implementing common custom subclass behavior out-of-the-box.

Issue: SPR-11411
Issue: SPR-11417
2014-02-12 15:12:35 +01:00
Juergen Hoeller d55a173e2e Fix issue w/ use of UrlPathHelper's urlDecode property
Before this change the getPathWithinServletMapping method of
UrlPathHelper could not work properly when a default servlet mapping
(i.e. "/") was used in combination with urlDecode=false. The fact that
the getServletPath() method of HttpServletRequest always returns a
decoded path was getting in the way.

Although there is no way to check Servlet mappings through the Servlet
API, this change aims to detect the given scenario and returns the full
path following the context path thus avoiding URL decoding.

Note that the same can be achieved by setting urlDecode=false and
alwaysUseFullPath=true. However this change ensures that urlDecode
works properly without having to know that.

Issue: SPR-11101
(cherry picked from commit 12598f8)
2014-02-12 15:06:00 +01:00
Juergen Hoeller 4d2d223b0c Revised ExcelViewTests 2014-02-09 01:26:26 +01:00
Juergen Hoeller c3d74b4521 Polishing 2014-02-09 00:45:55 +01:00
Juergen Hoeller 61ab40cd7a Upgraded to Commons FileUpload 1.3.1, TestNG 6.8.7, Hibernate 4.2.8, Joda-Time 2.2, Jackson 1.7.9 2014-02-09 00:45:07 +01:00
Juergen Hoeller 3da9a3193c Polishing
(cherry picked from commit 749b65b)
2014-02-07 18:04:14 +01:00
Juergen Hoeller 7e9cb5195a Fixed broken link to jax-ws-commons website
Issue: SPR-11404
2014-02-07 17:46:51 +01:00
Juergen Hoeller 4233d0a99e Removed outdated hibernate3 references across the codebase
Issue: SPR-9028
(cherry picked from commit 09e2e58)
2014-02-06 23:38:30 +01:00
Juergen Hoeller ad91610796 Polishing
(cherry picked from commit 426f52b)
2014-02-06 23:27:46 +01:00
Juergen Hoeller f558396e91 Introduced SpringNamingPolicy for CGLIB
Issue: SPR-11398
(cherry picked from commit 8c4e372)
2014-02-06 23:25:52 +01:00
Sebastien Deleuze a2ec8f864e Fix EvalTagTests with locales other than English
Issue: SPR-11392
(cherry picked from commit edb0b0e)
2014-02-05 23:27:19 +01:00
Sam Brannen 03e243a4ab Fix off-by-one regression in AbstractMethodMockingControl
Issue: SPR-11385, SPR-10885
(cherry picked from commits 69a89b1 and 3a89bc4)
2014-02-04 23:56:04 +01:00
Juergen Hoeller 60b24cffdb Related polishing
Issue: SPR-11386
(cherry picked from commit 6634c19)
2014-02-04 16:53:50 +01:00
Juergen Hoeller 036bd791f0 Introduced "spring.jdbc.getParameterType.ignore" property
Issue: SPR-11386
(cherry picked from commit 60c1905)
2014-02-04 16:53:44 +01:00
Juergen Hoeller a53df0b2c1 Added explicit tests for generic and raw collection converters
Issue: SPR-11369
2014-02-01 19:36:38 +01:00
Juergen Hoeller 1a011616d9 Polishing
Issue: SPR-11369
2014-02-01 12:12:19 +01:00
Juergen Hoeller 3af9d1f29b Consistent iteration over actualValue in Velocity and FreeMarker macros
This requires consistent exposure of an actualValue in BindStatus, even if no BindingResult available.

Issue: SPR-10837
(cherry picked from commit 4f60b98)
2014-02-01 11:09:28 +01:00
Juergen Hoeller b3fb81bf72 Defensively handle ServletRequestAttributes casting in requestDestroyed callback
Issue: SPR-11378
(cherry picked from commit 5f24294)
2014-02-01 11:07:33 +01:00
Juergen Hoeller dd5af764b5 Avoided unnecessary substring creation for field error access with wildcard
Issue: SPR-11374
(cherry picked from commit 5be8301)
2014-01-31 13:20:59 +01:00
Juergen Hoeller 3ffbb24211 Fixed isMatchingFieldError to properly handle empty field name
Issue: SPR-11374
2014-01-30 23:20:41 +01:00
Juergen Hoeller 4c385f0073 Fixed LiveBeansView to not produce invalid JSON if last bean is not eligible
Also introducing overridable isBeanEligible template method.

Issue: SPR-11366
(cherry picked from commit c1eac20)
2014-01-30 12:32:35 +01:00
Spring Buildmaster 7d527f9771 Next development version 2014-01-28 14:38:50 -08:00
Phillip Webb 3ba7ab15ab Update changelog 2014-01-28 13:53:01 -08:00
Juergen Hoeller 36ab65ace7 Dropped explicit paragraph on web.xml version declaration
Issue: SPR-11364
2014-01-28 17:32:08 +01:00
Juergen Hoeller 35753eb54d Backported test for fallback for non-resolvable property type
(cherry picked from commit 8570f60)
2014-01-28 17:25:12 +01:00
Brian Clozel 1cb9b9cf52 Add RestTemplate constructor with custom converters
Prior to this commit, RestTemplate's constructors were all initializing
default HTTPMessageConverters. Its API provides a way to replace
those converters with custom ones, but default converters are already
defined and initialized at that point, which can be an issue in some
cases (performance, classpath...).

This commits adds a new constructor for RestTemplate with a list
of message converters as argument. With this new constructor,
default message converters are never initialized.

Issue: SPR-11351
(cherry picked from commit 425e5a0)
2014-01-28 12:41:36 +01:00
Juergen Hoeller fe4b57c199 Fixed 'globalJobListeners'/'globalTriggerListeners' to work with Quartz 2.0 & 2.1 as well
Issue: SPR-11362
(cherry picked from commit c719c70)
2014-01-28 12:41:29 +01:00
Juergen Hoeller 2a3b29f98e Upgraded to SLF4J 1.6.6 2014-01-28 01:46:41 +01:00
Juergen Hoeller d26a570192 Polishing 2014-01-28 01:46:19 +01:00
Juergen Hoeller ac3c670f70 Fixed type resolution in case of inconsistencies between read and write method
Issue: SPR-11361
2014-01-28 01:20:27 +01:00
Juergen Hoeller 398f91cb74 Polishing 2014-01-27 22:49:14 +01:00
Juergen Hoeller b4115f3202 Downgraded JOpt build dependency to 3.3
Avoiding accidental use of OptionSet.specs(), as introduced in the JOpt 4.x line.
2014-01-27 22:15:54 +01:00
Juergen Hoeller 7e2167fd17 Specific deprecations and consistent setter varargs in Hibernate support
Issue: SPR-11291
2014-01-27 22:11:58 +01:00
Juergen Hoeller 09ad8347be Downgraded Commons Pool dependency to 1.5.7
Commons Pool 1.6 introduced generics in its APIs, leading to either a 1.6 dependency at runtime or a load of raw type warnings in our CommonsPoolTargetSource.
2014-01-26 00:41:59 +01:00
Juergen Hoeller 2ef39a5666 Consistently declare @SuppressWarnings("serial") instead of dummy serialVersionUID
(cherry picked from commit 56b7d7a)
2014-01-26 00:37:09 +01:00
Juergen Hoeller 1a2033eb41 Compatibility with JOpt 4.6
JOpt 4.6 redeclared its nonOptionArguments() method from List<String> to List<?>, requiring us to select String arguments only as we do for regular option values already.

Issue: SPR-11359
(cherry picked from commit 67e76e9)
2014-01-26 00:37:03 +01:00
Juergen Hoeller 6162917b4e Consistently switched optional dependencies to scope 'optional'; consistently grouped dependency scopes; minor dependency version updates 2014-01-25 22:12:16 +01:00
Juergen Hoeller e07ad5a19b Polishing 2014-01-25 00:15:00 +01:00
Juergen Hoeller 5307a87d1a Polishing
Issue: SPR-11357
2014-01-24 19:19:32 +01:00
Juergen Hoeller 87179b075b Optimized Introspector.flushFromCaches calls to skip Object.class
Issue: SPR-11356
2014-01-24 19:18:39 +01:00
Juergen Hoeller 23249cda98 Added test for SpringProperties setFlag method
Issue: SPR-9014
Issue: SPR-11297
2014-01-24 17:48:40 +01:00
Juergen Hoeller 341d645d09 Polishing
Issue: SPR-11357
2014-01-24 17:46:56 +01:00
Juergen Hoeller 9845d9eb21 Allow consolidating config in root context with Java
Issue: SPR-11357
(backported from 4.0.1)
2014-01-24 17:46:31 +01:00
Juergen Hoeller edb660863b Polishing 2014-01-24 16:59:42 +01:00
Juergen Hoeller 866c7847e3 Introduced SpringProperties class and optional "spring.properties" file
This in particular allows for specifying "spring.getenv.ignore" and "spring.beaninfo.ignore" in a local way within the application, in case that JVM-level system properties are locked.

Issue: SPR-9014
Issue: SPR-11297
(cherry picked from commit 8543b91)
2014-01-24 16:58:16 +01:00
Juergen Hoeller fc361844ec Polishing
Issue: SPR-11297
2014-01-22 23:57:48 +01:00
Juergen Hoeller 52d050d21a Factored out "suppressGetenvAccess()" method
Issue: SPR-11297
2014-01-22 23:57:36 +01:00
Sam Brannen c1569d7ecd Handle NoClassDefFoundError consistently for TELs
Prior to this commit, a NoClassDefFoundError caught in
TestContextManager's retrieveTestExecutionListeners() method would be
handled differently for implicit default listeners (i.e., listeners not
declared via @TestExecutionListeners) and listeners explicitly declared
via @TestExecutionListeners. Specifically, a NoClassDefFoundError would
cause a test to fail for an explicitly declared TestExecutionListener
but not for an implicitly declared one.

This commit addresses this issue by:

 - Always swallowing a NoClassDefFoundError for both implicitly and
   explicitly declared TestExecutionListeners.
 - Changing the log level from DEBUG to INFO to make such situations
   more visible to the average end user.

Issue: SPR-11347

Backport-Commit: fb12e234fc
2014-01-22 23:40:56 +01:00
Juergen Hoeller fdd31c0e66 Preserve visitBeanDefinition stacktrace in BeanDefinitionStoreException
Issue: SPR-11346
2014-01-22 22:40:10 +01:00
Juergen Hoeller cfa78a9b25 Quick paragraph on mvc namespace and matrix variables
Issue: SPR-11331
2014-01-22 22:37:22 +01:00
Juergen Hoeller d434ef9713 Polishing
Issue: SPR-11344
2014-01-22 18:23:59 +01:00
Juergen Hoeller c406c56d57 Avoid class loading during AspectJ expression evaluation
Fixed through downcasting to AspectJ's ReflectionType and ReflectionBasedReferenceTypeDelegate, obtaining the myClass field there. We only fall back to regular class loading if we encounter any other kind of type.

Issue: SPR-11344
2014-01-22 18:23:09 +01:00
Juergen Hoeller d9ab6aaf6c Revised RootBeanDefinition's externallyManaged* Sets to rely on postProcessingLock
This allows us to avoid early initialization of footprint-heavy ConcurrentHashMaps, and reuses the existing postProcessingLock which will typically be active already when registerExternallyManaged* calls come in from the bean factory's post-processing phase.

Issue: SPR-11343
(cherry picked from commit a599b57)
2014-01-22 14:48:26 +01:00
Juergen Hoeller aa1babdfde Fixed setDeliveryPersistent javadoc
Issue: SPR-3983
(cherry picked from commit 9cc86a3)
2014-01-21 17:13:33 +01:00
Juergen Hoeller 09c9137b75 Removed accidental backport of StAX code in 3.2.5 (restoring Java 5 compatibility)
Issue: SPR-11341
2014-01-21 17:12:22 +01:00
Sam Brannen 603d79ac9b Include ServletTEL in abstract base test classes
The ServletTestExecutionListener is now prepended to the set of default
listeners in AbstractJUnit4SpringContextTests and
AbstractTestNGSpringContextTests.

Issue: SPR-11340

Backport-Commit: 3370f8b1b1
2014-01-21 15:18:59 +01:00
Sam Brannen fdac4a7d18 Ensure all tests in spring-test are executed
Prior to this commit TestNG tests would only be executed by the Gradle
build if they were located in the “testng” package. Tests in subpackages
would therefore be omitted from the build.

This commit ensures that all TestNG classes in the “testng” package and
any of its subpackages are executed in the Gradle build.

Furthermore, this commit ensures that the JUnit-based
FailingBeforeAndAfterMethodsTests test class is executed along with the
other JUnit tests even though it resides under the “testng” package.

Issue: SPR-11338

Backport-Commit: 098d7c7465
2014-01-21 15:16:55 +01:00
Juergen Hoeller 11ef4308b8 Polishing 2014-01-21 01:55:09 +01:00
Juergen Hoeller e0f9a85955 Locale/ThemeChangeInterceptor alignment and javadoc polishing
Issue: SPR-11128
(cherry picked from commit 5e5add4)
2014-01-21 01:39:02 +01:00
Juergen Hoeller b229d54172 Consistent evaluation of empty theme names to default theme name
Issue: SPR-11128
(cherry picked from commit cc81aae)
2014-01-21 01:38:03 +01:00
Juergen Hoeller c77832ba6d Added info-level logging for default unit detection
Issue: SPR-11333
(cherry picked from commit 88730bd)
2014-01-21 01:36:50 +01:00
Juergen Hoeller 59893d1f13 Fixed assert in setAspectJAdvisorFactory()
Issue: SPR-11330
(cherry picked from commit f15a5fe)
2014-01-21 01:34:47 +01:00
Juergen Hoeller 9aefa0334f Polishing 2014-01-16 18:28:50 +01:00
Juergen Hoeller f532607d4b Introduced customizeConnection callbacks for URLConnection used by exists() / contentLength() / lastModified()
Issue: SPR-11320
(cherry picked from commit 4f45ad5)
2014-01-16 17:54:44 +01:00
Juergen Hoeller 16bf501b30 Polishing 2014-01-16 17:53:26 +01:00
Juergen Hoeller fd13c994c9 Fixed accidental use of String.isEmpty in SimpleCommandLineArgsParser
Issue: SPR-11321
2014-01-16 17:35:49 +01:00
Juergen Hoeller 1f60738431 checkNotModified needs to consider HEAD as well
Issue: SPR-11317
(cherry picked from commit 17cc63e)
2014-01-15 23:47:16 +01:00
Juergen Hoeller 68b1eb1aba Polishing 2014-01-15 23:46:52 +01:00
Juergen Hoeller 5fb2665d1c Introduced "globalInitializerClasses" next to the existing "contextInitializerClasses", applying to FrameworkServlets as well
Issue: SPR-11314
(cherry picked from commit 91881ff)
2014-01-15 23:46:04 +01:00
Juergen Hoeller 52c11eab41 Polishing
(cherry picked from commit e670f4e)
2014-01-15 17:54:37 +01:00
Juergen Hoeller b6362c5016 Introduced "spring.getenv.ignore" system property for preventing System.getenv calls
Issue: SPR-11297
(cherry picked from commit 961f42b)
2014-01-15 17:52:36 +01:00
Juergen Hoeller 6deb597cdf Removed Commons Lang references and refined Java 5+ implementation details 2014-01-15 15:56:03 +01:00
Juergen Hoeller bfecbaf88e Clarified ArgsMatchKind deprecation 2014-01-15 15:46:46 +01:00
Juergen Hoeller 3429a4186c Polishing 2014-01-15 15:16:01 +01:00
Juergen Hoeller f18debb5a3 Fixed getTypeDifferenceWeight algorithm in ReflectionHelper, and deprecated ArgsMatchKind enum (for removal in 4.0)
Issue: SPR-11306
2014-01-15 15:15:39 +01:00
Juergen Hoeller 62fd12c527 Restored Java 5 compatibility through avoiding Collections.newSetFromMap
Issue: SPR-11313
2014-01-15 14:14:50 +01:00
Juergen Hoeller f8f6c5fd89 Polishing 2014-01-13 23:49:39 +01:00
Juergen Hoeller 354917c53d Polishing (backports from 4.0.1) 2014-01-13 23:36:33 +01:00
Juergen Hoeller 1e0bf493cc Backported generics/varargs signature refinements for scripting package 2014-01-13 23:30:21 +01:00
Juergen Hoeller 0ea4f8ecb7 Fixed resolveProxyTargetClass exception message 2014-01-13 23:21:33 +01:00
Juergen Hoeller 139adba96a Removed TestGroup.LONG_RUNNING marker from Groovy and JRuby tests 2014-01-13 23:21:16 +01:00
Juergen Hoeller 7502ecd35e CronTriggerFactoryBean allows 'calendarName' and 'description' to be specified
Also making 'description' available on SimpleTriggerFactoryBean.

Issue: SPR-9771
2014-01-13 23:18:31 +01:00
Juergen Hoeller 477e60f28a Add minor optimization to AbstractErrors
Issue: SPR-11304
2014-01-13 23:15:50 +01:00
Juergen Hoeller 3db6a7f715 Add method for HTTP PATCH in MockMvcRequestBuilders
Issue: SPR-11299
2014-01-13 23:14:52 +01:00
Juergen Hoeller 0606c98277 Polishing (along with the Tiles 2.2.2 upgrade in the Spring 4.0 line)
Issue: SPR-11285
2014-01-06 00:43:41 +01:00
Juergen Hoeller dbfe68a6dc Further polishing
Issue: SPR-10940
2014-01-05 22:08:02 +01:00
Juergen Hoeller ab6c6b104d Consistent support for setStartTime in CronTrigger(Factory)Bean and SimpleTrigger(Factory)Bean, and consistent declaration of varargs in scheduling.quartz package
Issue: SPR-10940
(cherry picked from commit b228a06)
2014-01-05 18:03:54 +01:00
Juergen Hoeller c2459b4a61 Full Quartz 2.2 support, including LocalDataSourceJobStore
While we've had basic Quartz 2.2 support before, a few details were missing:
* LocalDataSourceJobStore's ConnectionProvider adapters need to provide an empty implementation of Quartz 2.2's new initialize method.
* SchedulerFactoryBean's "schedulerContextMap" needs to be explicitly declared with String keys, otherwise it can't be compiled against Quartz 2.2 (forward compatibility once we're dropping Quartz 1.x support). This doesn't hurt against older Quartz versions either, since the keys need to be Strings anyway.

Issue: SPR-11284
(cherry picked from commit 38a8ace)
2014-01-05 18:03:27 +01:00
Juergen Hoeller 4f24643fd3 Upgraded selected build dependencies to early 2013 releases 2014-01-05 02:47:44 +01:00
Juergen Hoeller 1a0a381559 Made findMethodAnnotationOnBridgeMethod compatible with Java 8 2014-01-05 02:30:04 +01:00
Juergen Hoeller 8c8eead667 Removed AbstractAsyncConfiguration's abstract "asyncAdvisor" method for Java 8 compatibility (to avoid method overloading problem for configuration classes) 2014-01-05 02:28:27 +01:00
Juergen Hoeller b35050caf2 Fixed Jackson2ObjectMapperFactoryBean class name in javadoc examples 2014-01-05 02:24:13 +01:00
Juergen Hoeller 72a5737ab9 Polishing 2014-01-05 00:02:54 +01:00
Juergen Hoeller be2d915cc2 Consistent equals/hashCode/toString implementations in AnnotationMatchingPointcut/ClassFilter/MethodMatcher
Issue: SPR-11275
Issue: SPR-11276
(cherry picked from commit 0de307b)
2014-01-05 00:02:47 +01:00
Juergen Hoeller 6045914057 Polishing 2014-01-03 23:02:51 +01:00
Juergen Hoeller 78646f1f32 Activated through rename to *Tests, and added method call interaction tests
Issue: SPR-7831
(cherry picked from commit 3bed6cf)
2014-01-03 23:02:18 +01:00
Juergen Hoeller f88cbda6ef Introduced "spring.beaninfo.ignore" system property for optimized Introspector usage
Issue: SPR-9014
2014-01-03 14:14:10 +01:00
Juergen Hoeller c48da0d9a4 Avoid hard reference to LocalValidatorFactoryBean in <mvc:annotation-driven> parser
Issue: SPR-11272
2014-01-03 12:18:49 +01:00
Juergen Hoeller e3344898cd Support varargs for DomUtils.getChildElementsByTagName
Issue: SPR-11272
2014-01-03 12:18:19 +01:00
Juergen Hoeller 2e123b01e5 Polishing
Issue: SPR-11259
(cherry picked from commit f0d2151)
2014-01-01 19:24:37 +01:00
Juergen Hoeller 57eedf33d6 Refined logging to include target class for each transactional method name
Also simplified cache key 'hashCode' implementation, relying on 'equals' to differentiate between same method on different target classes.

Issue: SPR-11267
(cherry picked from commit 82ea9ec)
2014-01-01 19:18:39 +01:00
Juergen Hoeller f477a024ad EhCacheFactoryBean does not call set(Sampled)StatisticsEnabled on EhCache 2.7/2.8
Issue: SPR-11265
(cherry picked from commit 73d8f06)
2014-01-01 19:18:12 +01:00
Juergen Hoeller 5dddb492b8 Polishing around @Enable processing and @EnableTransactionManagement
Issue: SPR-11251
2013-12-23 23:09:00 +01:00
Juergen Hoeller ecee20f1fe @Enable registrars called with correct metadata when placed on superclass
Issue: SPR-11251
2013-12-23 23:07:59 +01:00
Juergen Hoeller e08f743301 ResourceDatabasePopulator's setScripts takes varargs
(cherry picked from commit e3017c3)
2013-12-23 23:05:34 +01:00
Juergen Hoeller a05c957d0e Polishing
Issue: SPR-11254
(cherry picked from commit 9a39f39)
2013-12-23 23:05:10 +01:00
Juergen Hoeller a2de329db9 Revised XMLEventStreamWriter to allow for empty elements with attributes
Issue: SPR-11254
(cherry picked from commit ee5b7fd)
2013-12-23 23:04:58 +01:00
Juergen Hoeller 551364f668 Polishing 2013-12-20 00:40:14 +01:00
Juergen Hoeller 08aa22ff1f InjectionMetadata caching per bean name needs to refresh when bean class changes
Issue: SPR-11246
2013-12-20 00:15:09 +01:00
Juergen Hoeller a115a7dad5 Revised BeanInfoFactory javadoc
Issue: SPR-9014
2013-12-20 00:09:49 +01:00
Juergen Hoeller f457319965 Consistent non-declaration of serialVersionUID 2013-12-20 00:06:40 +01:00
Juergen Hoeller 7ad6df8c75 Moved AnnotationBeanNameGenerator's String value check right before cast
Issue: SPR-11221
2013-12-20 00:02:27 +01:00
Juergen Hoeller f5d5882f46 Fixed @Bean meta-annotation detection when using ASM
This turned out to be a bug in the ASM-based AnnotationMetadata implementation where has/getAnnotatedMethods didn't consider meta-annotations., in contrast to its StandardAnnotationMetadata sibling.

Issue: SPR-10488
(cherry picked from commit 105e176)
2013-12-16 23:09:07 +01:00
Juergen Hoeller 0a4d28d5d5 Fixed primitive type assignability in BeanUtils.copyProperties
Issue: SPR-11231
(cherry picked from commit 8a3b4c6)
2013-12-16 22:57:50 +01:00
Spring Buildmaster 9002742873 Next development version 2013-12-12 01:07:15 -08:00
793 changed files with 19600 additions and 13670 deletions
+14
View File
@@ -0,0 +1,14 @@
Juergen Hoeller <jhoeller@vmware.com> jhoeller <jhoeller@vmware.com>
<rstoyanchev@gopivotal.com> <rstoyanchev@vmware.com>
<pwebb@gopivotal.com> <pwebb@vmware.com>
<cbeams@gopivotal.com> <cbeams@vmware.com>
<cbeams@gopivotal.com> <cbeams@gmail.com>
<apoutsma@gopivotal.com> <apoutsma@vmware.com>
<apoutsma@gopivotal.com> <poutsma@mac.com>
<ogierke@gopivotal.com> <ogierke@vmware.com>
<dsyer@gopivotal.com> <david_syer@hotmail.com>
<dsyer@gopivotal.com> <dsyer@vmware.com>
<aclement@gopivotal.com> <andrew.clement@gmail.com>
<aclement@gopivotal.com> <aclement@vmware.com>
<dmitry.katsubo@gmail.com> <dmitry.katsubo@gmai.com>
Nick Williams <nicholas@nicholaswilliams.net> Nicholas Williams <nicholas@nicholaswilliams.net>
+219 -201
View File
@@ -1,10 +1,16 @@
buildscript {
repositories {
maven { url "http://repo.springsource.org/plugins-release" }
maven { url "https://repo.spring.io/plugins-release" }
}
dependencies {
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.4")
classpath("org.springframework.build.gradle:docbook-reference-plugin:0.2.7")
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.7")
classpath("org.springframework.build.gradle:docbook-reference-plugin:0.2.8")
}
}
ext {
moduleProjects = subprojects.findAll {
!it.name.equals('spring-build-src') && !it.name.equals('spring-framework-bom')
}
}
@@ -12,15 +18,10 @@ configure(allprojects) { project ->
group = "org.springframework"
version = qualifyVersionIfNecessary(version)
// The following is a work-around for allowing to build on JDK 8 until the
// Gradle build uses Ant 1.9.x by default. This is necessary to avoid the
// "Class not found: javac1.8" issue with Ant versions prior to 1.9.x
ant.properties["build.compiler"] = "javac1.7"
ext.aspectjVersion = "1.7.2"
ext.aspectjVersion = "1.7.4"
ext.hsqldbVersion = "1.8.0.10"
ext.junitVersion = "4.11"
ext.slf4jVersion = "1.6.1"
ext.slf4jVersion = "1.6.6"
ext.gradleScriptDir = "${rootProject.projectDir}/gradle"
apply plugin: "propdeps"
@@ -64,12 +65,16 @@ configure(allprojects) { project ->
systemProperty("java.awt.headless", "true")
systemProperty("testGroups", project.properties.get("testGroups"))
scanForTestClasses = false
include '**/*Tests.*'
exclude '**/*Abstract*.*'
// Do not include "**/*Test.class" since some *Test classes are broken.
include(["**/*Tests.class"])
// Since we set scanForTestClasses to false, we need to filter out inner
// classes with the "$" pattern; otherwise, using -Dtest.single=MyTests to
// run MyTests by itself will fail if MyTests contains any inner classes.
exclude(["**/Abstract*.class", '**/*$*'])
}
repositories {
maven { url "http://repo.springsource.org/libs-release" }
maven { url "https://repo.spring.io/libs-release" }
}
dependencies {
@@ -79,7 +84,7 @@ configure(allprojects) { project ->
}
ext.javadocLinks = [
"http://docs.oracle.com/javase/6/docs/api/",
"http://docs.oracle.com/javase/7/docs/api/",
"http://docs.oracle.com/javaee/6/api/",
"http://docs.oracle.com/cd/E13222_01/wls/docs90/javadocs/", // CommonJ
"http://pic.dhe.ibm.com/infocenter/wasinfo/v7r0/topic/com.ibm.websphere.javadoc.doc/web/apidocs/",
@@ -90,15 +95,17 @@ configure(allprojects) { project ->
"http://commons.apache.org/proper/commons-codec/apidocs/",
"http://commons.apache.org/proper/commons-dbcp/apidocs/",
"http://portals.apache.org/pluto/portlet-2.0-apidocs/",
"http://tiles.apache.org/tiles-request/apidocs/",
"http://tiles.apache.org/framework/apidocs/",
"http://ibatis.apache.org/docs/java/dev/",
"http://hc.apache.org/httpclient-3.x/apidocs/",
"http://aopalliance.sourceforge.net/doc/",
"http://www.eclipse.org/aspectj/doc/released/aspectj5rt-api/",
"http://ehcache.org/apidocs/",
"http://quartz-scheduler.org/api/2.1.5/",
"http://jackson.codehaus.org/1.4.2/javadoc/",
"http://fasterxml.github.com/jackson-core/javadoc/2.0.1/",
"http://quartz-scheduler.org/api/2.2.0/",
"http://jackson.codehaus.org/1.9.4/javadoc/",
"http://fasterxml.github.com/jackson-core/javadoc/2.3.0/",
"http://fasterxml.github.com/jackson-databind/javadoc/2.3.0/",
"http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs",
"http://ibatis.apache.org/docs/java/dev/"
] as String[]
}
@@ -127,7 +134,7 @@ configure(subprojects - project(":spring-build-src")) { subproject ->
options.author = true
options.header = project.name
options.links(project.ext.javadocLinks)
if(JavaVersion.current().isJava8Compatible()) {
if (JavaVersion.current().isJava8Compatible()) {
options.addStringOption('Xdoclint:none', '-quiet')
}
@@ -137,10 +144,10 @@ configure(subprojects - project(":spring-build-src")) { subproject ->
logging.captureStandardOutput LogLevel.INFO // suppress "## warnings" message
}
task sourcesJar(type: Jar, dependsOn:classes) {
classifier = "sources"
from sourceSets.main.allJava.srcDirs
include "**/*.java", "**/*.aj"
task sourcesJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.allSource
// don't include or exclude anything explicitly by default. See SPR-12085.
}
task javadocJar(type: Jar) {
@@ -169,14 +176,14 @@ project("spring-build-src") {
project("spring-core") {
description = "Spring Core"
// As of Spring 3.2 spring-core repackages both asm 4.0 and cglib 3.0 and inlines both
// into the spring-core jar. cglib 3.0 itself depends on asm 4.0, and is therefore
// As of Spring 3.2.9, spring-core repackages asm 5.0 and cglib 3.1, inlining both
// into the spring-core jar. cglib 3.1 itself depends on asm 4+, and is therefore
// further transformed by the JarJar task to depend on org.springframework.asm; this
// avoids including two different copies of asm unnecessarily. If however future cglib
// versions drift from the version of asm used by Spring internally, this duplication
// will become necessary.
def asmVersion = "4.0"
def cglibVersion = "3.0"
def asmVersion = "5.0.4"
def cglibVersion = "3.1"
configurations {
jarjar
@@ -233,9 +240,9 @@ project("spring-core") {
compile(files(cglibRepackJar))
compile(files(asmRepackJar))
compile("commons-logging:commons-logging:1.1.1")
compile("commons-logging:commons-logging:1.1.3")
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
optional("net.sf.jopt-simple:jopt-simple:3.0")
optional("net.sf.jopt-simple:jopt-simple:3.3")
optional("log4j:log4j:1.2.17")
testCompile("xmlunit:xmlunit:1.3")
testCompile("org.codehaus.woodstox:wstx-asl:3.2.7") {
@@ -262,8 +269,8 @@ project("spring-beans") {
dependencies {
compile(project(":spring-core"))
compile(files(project(":spring-core").cglibRepackJar))
provided("javax.el:el-api:1.0")
provided("javax.inject:javax.inject:1")
optional("javax.el:el-api:1.0")
optional("javax.inject:javax.inject:1")
testCompile("log4j:log4j:1.2.17")
}
}
@@ -272,13 +279,13 @@ project("spring-aop") {
description = "Spring AOP"
dependencies {
compile(project(":spring-beans"))
compile(project(":spring-core"))
compile(files(project(":spring-core").cglibRepackJar))
compile(project(":spring-beans"))
compile("aopalliance:aopalliance:1.0")
optional("com.jamonapi:jamon:2.4")
optional("commons-pool:commons-pool:1.5.3")
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
optional("commons-pool:commons-pool:1.5.7")
optional("com.jamonapi:jamon:2.4")
}
}
@@ -314,28 +321,27 @@ project("spring-context") {
description = "Spring Context"
dependencies {
optional(project(":spring-instrument"))
compile(project(":spring-aop"))
compile(project(":spring-beans"))
compile(project(":spring-expression"))
compile(project(":spring-core"))
compile(files(project(":spring-core").cglibRepackJar))
optional("backport-util-concurrent:backport-util-concurrent:3.0")
optional("javax.ejb:ejb-api:3.0")
optional(project(":spring-instrument"))
optional("javax.inject:javax.inject:1")
optional("javax.ejb:ejb-api:3.0")
optional("org.apache.geronimo.specs:geronimo-jms_1.1_spec:1.1")
optional("backport-util-concurrent:backport-util-concurrent:3.0")
optional("javax.persistence:persistence-api:1.0")
optional("org.beanshell:bsh:2.0b4")
optional("org.codehaus.groovy:groovy-all:1.8.8")
optional("org.jruby:jruby:1.6.5.1")
optional("joda-time:joda-time:2.1")
optional("org.slf4j:slf4j-api:${slf4jVersion}")
optional("javax.validation:validation-api:1.0.0.GA")
optional("org.hibernate:hibernate-validator:4.3.0.Final")
optional("org.hibernate:hibernate-validator:4.3.1.Final")
optional("joda-time:joda-time:2.2")
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
optional("org.apache.geronimo.specs:geronimo-jta_1.1_spec:1.1")
testCompile("commons-dbcp:commons-dbcp:1.2.2")
optional("org.codehaus.groovy:groovy-all:1.8.9")
optional("org.beanshell:bsh:2.0b4")
optional("org.jruby:jruby:1.7.12")
testCompile("javax.inject:javax.inject-tck:1")
testCompile("commons-dbcp:commons-dbcp:1.3")
testCompile("org.slf4j:slf4j-api:${slf4jVersion}")
}
// pick up RmiInvocationWrapperRTD.xml in src/main
@@ -350,17 +356,17 @@ project("spring-tx") {
description = "Spring Transaction"
dependencies {
optional(project(":spring-context")) // for JCA, @EnableTransactionManagement
optional(project(":spring-aop"))
compile(project(":spring-beans"))
compile(project(":spring-core"))
compile("aopalliance:aopalliance:1.0")
provided("com.ibm.websphere:uow:6.0.2.17")
optional("javax.resource:connector-api:1.5")
optional(project(":spring-aop"))
optional(project(":spring-context")) // for JCA, @EnableTransactionManagement
optional("aopalliance:aopalliance:1.0")
optional("org.apache.geronimo.specs:geronimo-jta_1.1_spec:1.1")
optional("javax.resource:connector-api:1.5")
optional("javax.ejb:ejb-api:3.0")
testCompile("javax.persistence:persistence-api:1.0")
optional("com.ibm.websphere:uow:6.0.2.17")
testCompile("org.aspectj:aspectjweaver:${aspectjVersion}")
testCompile("javax.persistence:persistence-api:1.0")
}
}
@@ -378,14 +384,24 @@ project("spring-oxm") {
dependencies {
compile(project(":spring-beans"))
compile(project(":spring-core"))
optional("org.codehaus.castor:castor-xml:1.3.3") {
exclude group: 'stax', module: 'stax-api'
exclude group: "org.springframework", module: "spring-context"
}
optional("org.apache.xmlbeans:xmlbeans:2.6.0") {
exclude group: 'stax', module: 'stax-api'
}
optional("com.thoughtworks.xstream:xstream:1.4.7") {
exclude group: 'xpp3', module: 'xpp3_min'
exclude group: 'xmlpull', module: 'xmlpull'
}
optional("org.jibx:jibx-run:1.2.5")
testCompile(project(":spring-context"))
optional("com.thoughtworks.xstream:xstream:1.3.1")
optional("org.jibx:jibx-run:1.2.3")
optional("org.apache.xmlbeans:xmlbeans:2.4.0")
optional("org.codehaus.castor:castor-xml:1.3.2")
testCompile("org.codehaus.jettison:jettison:1.0.1")
testCompile("xmlunit:xmlunit:1.3")
testCompile("xmlpull:xmlpull:1.1.3.4a")
testCompile("org.codehaus.jettison:jettison:1.0.1") {
exclude group: 'stax', module: 'stax-api'
}
testCompile(files(genCastor.classesDir).builtBy(genCastor))
testCompile(files(genJaxb.classesDir).builtBy(genJaxb))
testCompile(files(genXmlbeans.classesDir).builtBy(genXmlbeans))
@@ -401,13 +417,13 @@ project("spring-jms") {
compile(project(":spring-aop"))
compile(project(":spring-context"))
compile(project(":spring-tx"))
optional(project(":spring-oxm"))
compile("aopalliance:aopalliance:1.0")
provided("org.apache.geronimo.specs:geronimo-jms_1.1_spec:1.1")
optional(project(":spring-oxm"))
optional("aopalliance:aopalliance:1.0")
optional("org.apache.geronimo.specs:geronimo-jta_1.1_spec:1.1")
optional("javax.resource:connector-api:1.5")
optional("org.codehaus.jackson:jackson-mapper-asl:1.4.2")
optional("com.fasterxml.jackson.core:jackson-databind:2.0.1")
optional("org.codehaus.jackson:jackson-mapper-asl:1.7.9")
optional("com.fasterxml.jackson.core:jackson-databind:2.0.6")
}
}
@@ -415,16 +431,16 @@ project("spring-jdbc") {
description = "Spring JDBC"
dependencies {
compile(project(":spring-core"))
compile(project(":spring-beans"))
optional(project(":spring-context")) // for JndiDataSourceLookup
compile(project(":spring-core"))
compile(project(":spring-tx"))
optional(project(":spring-context")) // for JndiDataSourceLookup
optional("org.apache.geronimo.specs:geronimo-jta_1.1_spec:1.1")
optional("c3p0:c3p0:0.9.1.2")
optional("hsqldb:hsqldb:${hsqldbVersion}")
optional("com.h2database:h2:1.0.71")
optional("com.h2database:h2:1.0.79")
optional("org.apache.derby:derby:10.5.3.0_1")
optional("org.apache.derby:derbyclient:10.5.3.0_1")
optional("org.apache.geronimo.specs:geronimo-jta_1.1_spec:1.1")
}
}
@@ -435,23 +451,23 @@ project("spring-context-support") {
compile(project(":spring-core"))
compile(project(":spring-beans"))
compile(project(":spring-context"))
optional(project(":spring-jdbc")) // for Quartz support
optional(project(":spring-tx")) // for Quartz support
optional("javax.mail:mail:1.4")
provided("javax.activation:activation:1.1")
optional(project(":spring-jdbc")) // for Quartz support
optional(project(":spring-tx")) // for Quartz support
optional("javax.mail:mail:1.4.7")
optional("javax.cache:cache-api:0.5")
optional("net.sf.ehcache:ehcache-core:2.0.0")
optional("opensymphony:quartz:1.6.2")
optional("net.sf.ehcache:ehcache-core:2.0.1")
optional("org.quartz-scheduler:quartz:1.7.3")
optional("org.codehaus.fabric3.api:commonj:1.1.0")
optional("velocity:velocity:1.5")
optional("org.freemarker:freemarker:2.3.15")
optional("org.freemarker:freemarker:2.3.20")
optional("com.lowagie:itext:2.1.7")
optional("jasperreports:jasperreports:2.0.5")
optional("org.slf4j:slf4j-api:${slf4jVersion}")
provided("javax.activation:activation:1.1")
testCompile("org.apache.poi:poi:3.0.2-FINAL")
testCompile("commons-beanutils:commons-beanutils:1.8.0") // for Velocity/JasperReports
testCompile("commons-digester:commons-digester:1.8.1") // for Velocity/JasperReports
optional("net.sf.jasperreports:jasperreports:3.7.6")
testCompile("org.apache.poi:poi:3.6")
testCompile("commons-beanutils:commons-beanutils:1.8.0") // for Velocity/JasperReports
testCompile("commons-digester:commons-digester:1.8.1") // for Velocity/JasperReports
testCompile("hsqldb:hsqldb:${hsqldbVersion}")
testCompile("org.slf4j:slf4j-api:${slf4jVersion}")
}
// pick up **/*.types files in src/main
@@ -460,29 +476,30 @@ project("spring-context-support") {
project("spring-web") {
description = "Spring Web"
dependencies {
compile(project(":spring-core"))
compile(project(":spring-beans")) // for MultiPartFilter
compile(project(":spring-aop")) // for JaxWsPortProxyFactoryBean
compile(project(":spring-aop")) // for JaxWsPortProxyFactoryBean
compile(project(":spring-beans")) // for MultipartFilter
compile(project(":spring-context"))
optional(project(":spring-oxm")) // for MarshallingHttpMessageConverter
compile("aopalliance:aopalliance:1.0")
compile(project(":spring-core"))
provided("javax.servlet:javax.servlet-api:3.0.1")
provided("javax.activation:activation:1.1")
optional(project(":spring-oxm")) // for MarshallingHttpMessageConverter
optional("javax.servlet.jsp:jsp-api:2.1")
optional("javax.portlet:portlet-api:2.0")
optional("javax.el:el-api:1.0")
optional("javax.faces:jsf-api:1.2_08")
provided("javax.portlet:portlet-api:2.0")
provided("javax.servlet:javax.servlet-api:3.0.1")
provided("javax.servlet.jsp:jsp-api:2.1")
optional("javax.xml:jaxrpc-api:1.1")
provided("javax.xml.soap:saaj-api:1.3")
provided("javax.activation:activation:1.1")
optional("javax.xml.soap:saaj-api:1.3")
optional("aopalliance:aopalliance:1.0")
optional("com.caucho:hessian:3.2.1")
optional("rome:rome:1.0")
optional("commons-fileupload:commons-fileupload:1.2")
optional("commons-fileupload:commons-fileupload:1.3.1")
optional("commons-io:commons-io:1.3")
optional("commons-httpclient:commons-httpclient:3.1")
optional("org.apache.httpcomponents:httpclient:4.2")
optional("org.codehaus.jackson:jackson-mapper-asl:1.4.2")
optional("com.fasterxml.jackson.core:jackson-databind:2.0.1")
optional("org.apache.httpcomponents:httpclient:4.2.6")
optional("org.codehaus.jackson:jackson-mapper-asl:1.7.9")
optional("com.fasterxml.jackson.core:jackson-databind:2.0.6")
optional("rome:rome:1.0")
optional("taglibs:standard:1.1.2")
optional("org.eclipse.jetty:jetty-servlet:8.1.5.v20120716") {
exclude group: "org.eclipse.jetty.orbit", module: "javax.servlet"
@@ -503,14 +520,20 @@ project("spring-orm") {
description = "Spring Object/Relational Mapping"
compileTestJava {
// necessary to avoid java.lang.VerifyError on toplink compilation
// TODO: remove this block when we remove toplink
// necessary to avoid java.lang.VerifyError on TopLink compilation
sourceCompatibility=1.6
targetCompatibility=1.6
}
dependencies {
compile("aopalliance:aopalliance:1.0")
compile(project(":spring-beans"))
compile(project(":spring-core"))
compile(project(":spring-jdbc"))
compile(project(":spring-tx"))
optional(project(":spring-aop"))
optional(project(":spring-context"))
optional(project(":spring-web"))
optional("aopalliance:aopalliance:1.0")
optional("javax.persistence:persistence-api:1.0")
optional("org.eclipse.persistence:org.eclipse.persistence.core:1.0.1")
optional("org.eclipse.persistence:org.eclipse.persistence.jpa:1.0.1")
@@ -521,20 +544,13 @@ project("spring-orm") {
optional("toplink.essentials:toplink-essentials:2.0-41b")
optional("javax.jdo:jdo-api:3.0")
optional("org.apache.ibatis:ibatis-sqlmap:2.3.4.726")
provided("javax.servlet:servlet-api:2.5")
optional("javax.servlet:servlet-api:2.5")
testCompile("javax.servlet:javax.servlet-api:3.0.1")
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
testCompile("commons-dbcp:commons-dbcp:1.2.2")
testCompile("org.eclipse.persistence:org.eclipse.persistence.asm:1.0.1")
testCompile("org.eclipse.persistence:org.eclipse.persistence.antlr:1.0.1")
testCompile("commons-dbcp:commons-dbcp:1.3")
testCompile("hsqldb:hsqldb:${hsqldbVersion}")
compile(project(":spring-core"))
compile(project(":spring-beans"))
optional(project(":spring-aop"))
optional(project(":spring-context"))
compile(project(":spring-tx"))
compile(project(":spring-jdbc"))
optional(project(":spring-web"))
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
}
}
@@ -543,11 +559,11 @@ project("spring-orm-hibernate4") {
merge.into = project(":spring-orm")
dependencies {
provided(project(":spring-tx"))
provided(project(":spring-jdbc"))
optional("org.hibernate:hibernate-core:4.1.9.Final")
optional("org.hibernate:hibernate-entitymanager:4.1.9.Final")
provided(project(":spring-tx"))
optional(project(":spring-web"))
optional("org.hibernate:hibernate-core:4.2.19.Final")
optional("org.hibernate:hibernate-entitymanager:4.2.19.Final")
optional("javax.servlet:servlet-api:2.5")
}
}
@@ -556,34 +572,33 @@ project("spring-webmvc") {
description = "Spring Web MVC"
dependencies {
compile(project(":spring-beans"))
compile(project(":spring-context"))
compile(project(":spring-core"))
compile(project(":spring-expression"))
compile(project(":spring-beans"))
compile(project(":spring-web"))
compile(project(":spring-context"))
optional(project(":spring-context-support")) // for Velocity support
optional(project(":spring-oxm")) // for MarshallingView
provided("javax.servlet:javax.servlet-api:3.0.1")
optional(project(":spring-context-support")) // for Velocity support
optional(project(":spring-oxm")) // for MarshallingView
optional("javax.servlet.jsp:jsp-api:2.1")
optional("javax.servlet:jstl:1.2")
optional("net.sourceforge.jexcelapi:jxl:2.6.12")
optional("org.apache.poi:poi:3.6")
optional("velocity:velocity:1.5")
optional("velocity-tools:velocity-tools-view:1.4")
optional("org.freemarker:freemarker:2.3.20")
optional("com.lowagie:itext:2.1.7")
optional("net.sf.jasperreports:jasperreports:3.7.6") {
exclude group: "xml-apis", module: "xml-apis"
}
optional("org.codehaus.jackson:jackson-mapper-asl:1.7.9")
optional("com.fasterxml.jackson.core:jackson-databind:2.0.6")
optional("rome:rome:1.0")
optional("org.apache.tiles:tiles-api:2.1.2")
optional("org.apache.tiles:tiles-core:2.1.2")
optional("org.apache.tiles:tiles-jsp:2.1.2")
optional("org.apache.tiles:tiles-servlet:2.1.2")
optional("net.sourceforge.jexcelapi:jxl:2.6.3")
optional("org.apache.poi:poi:3.0.2-FINAL")
optional("com.lowagie:itext:2.1.7")
optional("jasperreports:jasperreports:2.0.5") {
exclude group: "xml-apis", module: "xml-apis"
}
optional("rome:rome:1.0")
optional("velocity:velocity:1.5")
optional("velocity-tools:velocity-tools-view:1.4")
optional("org.freemarker:freemarker:2.3.15")
optional("org.codehaus.jackson:jackson-mapper-asl:1.4.2")
optional("com.fasterxml.jackson.core:jackson-databind:2.0.1")
provided("javax.servlet:jstl:1.2")
provided("javax.servlet:javax.servlet-api:3.0.1")
provided("javax.servlet.jsp:jsp-api:2.1")
testCompile(project(":spring-aop"))
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
testCompile("rhino:js:1.7R1")
testCompile("xmlunit:xmlunit:1.3")
testCompile("dom4j:dom4j:1.6.1") {
@@ -601,10 +616,11 @@ project("spring-webmvc") {
exclude group: "org.eclipse.jetty.orbit", module: "javax.servlet"
}
testCompile("javax.validation:validation-api:1.0.0.GA")
testCompile("commons-fileupload:commons-fileupload:1.2")
testCompile("org.hibernate:hibernate-validator:4.3.1.Final")
testCompile("org.apache.httpcomponents:httpclient:4.2.6")
testCompile("commons-fileupload:commons-fileupload:1.3.1")
testCompile("commons-io:commons-io:1.3")
testCompile("org.hibernate:hibernate-validator:4.3.0.Final")
testCompile("org.apache.httpcomponents:httpclient:4.2")
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
}
// pick up DispatcherServlet.properties in src/main
@@ -618,27 +634,27 @@ project("spring-webmvc-tiles3") {
dependencies {
provided(project(":spring-context"))
provided(project(":spring-web"))
provided("javax.el:el-api:1.0")
provided("javax.servlet:jstl:1.2")
provided("javax.servlet.jsp:jsp-api:2.1")
optional("org.apache.tiles:tiles-request-api:1.0.1")
optional("org.apache.tiles:tiles-api:3.0.1")
optional("org.apache.tiles:tiles-core:3.0.1") {
exclude group: "org.slf4j", module: "jcl-over-slf4j"
}
optional("org.apache.tiles:tiles-servlet:3.0.1") {
exclude group: "org.slf4j", module: "jcl-over-slf4j"
}
optional("org.apache.tiles:tiles-jsp:3.0.1") {
exclude group: "org.slf4j", module: "jcl-over-slf4j"
}
optional("org.apache.tiles:tiles-extras:3.0.1") {
exclude group: "org.slf4j", module: "jcl-over-slf4j"
}
optional("org.apache.tiles:tiles-el:3.0.1") {
exclude group: "org.slf4j", module: "jcl-over-slf4j"
}
provided("javax.servlet:javax.servlet-api:3.0.1")
optional("javax.servlet.jsp:jsp-api:2.1")
optional("javax.servlet:jstl:1.2")
optional("javax.el:el-api:1.0")
optional("org.apache.tiles:tiles-api:3.0.4")
optional("org.apache.tiles:tiles-core:3.0.4") {
exclude group: "org.slf4j", module: "jcl-over-slf4j"
}
optional("org.apache.tiles:tiles-servlet:3.0.4") {
exclude group: "org.slf4j", module: "jcl-over-slf4j"
}
optional("org.apache.tiles:tiles-jsp:3.0.4") {
exclude group: "org.slf4j", module: "jcl-over-slf4j"
}
optional("org.apache.tiles:tiles-el:3.0.4") {
exclude group: "org.slf4j", module: "jcl-over-slf4j"
}
optional("org.apache.tiles:tiles-extras:3.0.4") {
exclude group: "org.slf4j", module: "jcl-over-slf4j"
exclude group: "org.springframework", module: "spring-web"
}
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
}
}
@@ -647,14 +663,14 @@ project("spring-webmvc-portlet") {
description = "Spring Web Portlet"
dependencies {
provided("javax.servlet:servlet-api:2.5")
provided("javax.portlet:portlet-api:2.0")
compile(project(":spring-core"))
compile(project(":spring-beans"))
compile(project(":spring-context"))
compile(project(":spring-core"))
compile(project(":spring-web"))
compile(project(":spring-webmvc"))
optional("commons-fileupload:commons-fileupload:1.2")
provided("javax.servlet:servlet-api:2.5")
provided("javax.portlet:portlet-api:2.0")
optional("commons-fileupload:commons-fileupload:1.3.1")
}
// pick up DispatcherPortlet.properties in src/main
@@ -666,6 +682,7 @@ project("spring-test") {
dependencies {
compile(project(":spring-core"))
provided("javax.activation:activation:1.1")
optional(project(":spring-beans"))
optional(project(":spring-context"))
optional(project(":spring-jdbc"))
@@ -673,72 +690,73 @@ project("spring-test") {
optional(project(":spring-orm"))
optional(project(":spring-web"))
optional(project(":spring-webmvc"))
optional(project(":spring-webmvc-portlet"), )
optional(project(":spring-webmvc-portlet"))
optional("junit:junit:${junitVersion}")
optional("org.testng:testng:6.5.2")
optional("org.testng:testng:6.8.8")
optional("javax.inject:javax.inject:1")
optional("javax.servlet:servlet-api:2.5")
optional("javax.servlet.jsp:jsp-api:2.1")
optional("javax.servlet:jstl:1.2")
optional("javax.portlet:portlet-api:2.0")
optional("javax.persistence:persistence-api:1.0")
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
testCompile("org.hibernate:hibernate-core:3.3.2.GA")
provided("javax.inject:javax.inject:1")
provided("javax.activation:activation:1.1")
provided("javax.servlet:jstl:1.2")
testCompile "org.slf4j:slf4j-jcl:${slf4jVersion}"
testCompile("hsqldb:hsqldb:${hsqldbVersion}")
testCompile "org.slf4j:slf4j-jcl:${slf4jVersion}"
}
task testNG(type: Test) {
useTestNG()
// forkEvery 1
scanForTestClasses = false
include "**/testng/*.*"
include "**/testng/**/*.*"
exclude "**/FailingBeforeAndAfterMethodsTests.class"
// "TestCase" classes are run by other test classes, not the build.
exclude "**/*TestCase.class"
// Generate TestNG reports alongside JUnit reports.
testReport true
getReports().getHtml().setEnabled(true)
// show standard out and standard error of the test JVM(s) on the console
// testLogging.showStandardStreams = true
}
test {
dependsOn testNG
useJUnit()
exclude "**/testng/*.*"
exclude "**/testng/**/*.*"
include "**/testng/FailingBeforeAndAfterMethodsTests"
// "TestCase" classes are run by other test classes, not the build.
exclude(["**/*TestCase.class", "**/*TestSuite.class"])
}
}
project("spring-test-mvc") {
description = "Spring Test MVC Framework"
merge.into = project(":spring-test")
dependencies {
optional(project(":spring-context"))
provided(project(":spring-webmvc"))
provided("javax.servlet:javax.servlet-api:3.0.1")
provided("javax.activation:activation:1.1")
optional(project(":spring-context"))
optional("org.hamcrest:hamcrest-core:1.3")
optional("com.jayway.jsonpath:json-path:0.8.1")
optional("xmlunit:xmlunit:1.3")
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
testCompile("javax.servlet:jstl:1.2")
testCompile("org.hibernate:hibernate-validator:4.3.0.Final")
testCompile("org.codehaus.jackson:jackson-mapper-asl:1.4.2")
testCompile("com.fasterxml.jackson.core:jackson-databind:2.0.1")
testCompile(project(":spring-context-support"))
testCompile(project(":spring-oxm"))
testCompile("com.thoughtworks.xstream:xstream:1.3.1")
testCompile("javax.servlet:jstl:1.2")
testCompile("javax.mail:mail:1.4.7")
testCompile("org.hibernate:hibernate-validator:4.3.1.Final")
testCompile("com.thoughtworks.xstream:xstream:1.4.7")
testCompile("org.codehaus.jackson:jackson-mapper-asl:1.7.9")
testCompile("com.fasterxml.jackson.core:jackson-databind:2.0.6")
testCompile("rome:rome:1.0")
testCompile("javax.activation:activation:1.1")
testCompile("javax.mail:mail:1.4")
testCompile("org.apache.tiles:tiles-request-api:1.0.1")
testCompile("org.apache.tiles:tiles-api:3.0.1")
testCompile("org.apache.tiles:tiles-core:3.0.1") {
testCompile("org.apache.tiles:tiles-api:3.0.4")
testCompile("org.apache.tiles:tiles-core:3.0.4") {
exclude group: "org.slf4j", module: "jcl-over-slf4j"
}
testCompile("org.apache.tiles:tiles-servlet:3.0.1") {
testCompile("org.apache.tiles:tiles-servlet:3.0.4") {
exclude group: "org.slf4j", module: "jcl-over-slf4j"
}
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
}
}
@@ -763,21 +781,20 @@ project("spring-aspects") {
apply from: "aspects.gradle"
dependencies {
optional(project(":spring-beans")) // for @Configurable support
optional(project(":spring-aop")) // for @Async support
optional(project(":spring-context")) // for @Enable* support
compile(project(":spring-context-support")) // for JavaMail support
optional(project(":spring-tx")) // for JPA, @Transactional support
optional(project(":spring-orm")) // for JPA exception translation support
aspects(project(":spring-orm"))
provided("javax.persistence:persistence-api:1.0")
testCompile("javax.mail:mail:1.4")
ajc("org.aspectj:aspectjtools:${aspectjVersion}")
rt("org.aspectj:aspectjrt:${aspectjVersion}")
compile("org.aspectj:aspectjweaver:${aspectjVersion}")
testCompile(project(":spring-core")) // for CodeStyleAspect
compile(project(":spring-beans")) // for "p" namespace visibility
provided("javax.persistence:persistence-api:1.0")
optional(project(":spring-aop")) // for @Async support
optional(project(":spring-beans")) // for @Configurable support
optional(project(":spring-context")) // for @Enable* support
optional(project(":spring-context-support")) // for JavaMail support
optional(project(":spring-orm")) // for JPA exception translation support
optional(project(":spring-tx")) // for JPA, @Transactional support
testCompile(project(":spring-core")) // for CodeStyleAspect
testCompile(project(":spring-test"))
testCompile("javax.mail:mail:1.4.7")
}
eclipse.project {
@@ -827,6 +844,7 @@ configure(rootProject) {
apply plugin: "docbook-reference"
apply plugin: "groovy"
// apply plugin: "detect-split-packages"
apply from: "${gradleScriptDir}/jdiff.gradle"
@@ -845,23 +863,23 @@ configure(rootProject) {
configurations.archives.artifacts.clear()
dependencies { // for integration tests
testCompile(project(":spring-core"))
testCompile(project(":spring-beans"))
testCompile(project(":spring-aop"))
testCompile(project(":spring-expression"))
testCompile(project(":spring-beans"))
testCompile(project(":spring-context"))
testCompile(project(":spring-tx"))
testCompile(project(":spring-core"))
testCompile(project(":spring-expression"))
testCompile(project(":spring-jdbc"))
testCompile(project(":spring-orm"))
testCompile(project(":spring-test"))
testCompile(project(":spring-tx"))
testCompile(project(":spring-web"))
testCompile(project(":spring-webmvc-portlet"))
testCompile(project(":spring-orm"))
testCompile("org.hibernate:hibernate-core:4.1.9.Final")
testCompile("javax.servlet:servlet-api:2.5")
testCompile("javax.portlet:portlet-api:2.0")
testCompile("javax.inject:javax.inject:1")
testCompile("javax.resource:connector-api:1.5")
testCompile("org.aspectj:aspectjweaver:${aspectjVersion}")
testCompile("org.hibernate:hibernate-core:4.2.19.Final")
testCompile("hsqldb:hsqldb:${hsqldbVersion}")
}
@@ -882,7 +900,7 @@ configure(rootProject) {
options.stylesheetFile = file("src/api/stylesheet.css")
options.splitIndex = true
options.links(project.ext.javadocLinks)
if(JavaVersion.current().isJava8Compatible()) {
if (JavaVersion.current().isJava8Compatible()) {
options.addStringOption('Xdoclint:none', '-quiet')
}
@@ -895,7 +913,7 @@ configure(rootProject) {
doFirst {
classpath = files(
// ensure Servlet 3.x and Hibernate 4.x have precedence on the Javadoc
// ensure Servlet 3.x and Hibernate 4.x have precedence on the javadoc
// classpath over their respective 2.5 and 3.x variants
project(":spring-webmvc").sourceSets.main.compileClasspath.files.find { it =~ "servlet-api" },
rootProject.sourceSets.test.compileClasspath.files.find { it =~ "hibernate-core" },
@@ -906,7 +924,7 @@ configure(rootProject) {
}
}
task docsZip(type: Zip) {
task docsZip(type: Zip, dependsOn: 'reference') {
group = "Distribution"
baseName = "spring-framework"
classifier = "docs"
@@ -932,8 +950,8 @@ configure(rootProject) {
classifier = "schema"
description = "Builds -${classifier} archive containing all " +
"XSDs for deployment at http://springframework.org/schema."
subprojects.each { subproject ->
duplicatesStrategy 'exclude'
moduleProjects.each { subproject ->
def Properties schemas = new Properties();
subproject.sourceSets.main.resources.find {
@@ -979,7 +997,7 @@ configure(rootProject) {
into "${baseDir}/schema"
}
subprojects.each { subproject ->
moduleProjects.each { subproject ->
into ("${baseDir}/libs") {
from subproject.jar
if (subproject.tasks.findByPath("sourcesJar")) {
@@ -1032,7 +1050,7 @@ configure(rootProject) {
task wrapper(type: Wrapper) {
description = "Generates gradlew[.bat] scripts"
gradleVersion = "1.6"
gradleVersion = "1.12"
doLast() {
def gradleOpts = "-XX:MaxPermSize=1024m -Xmx1024m"
@@ -21,20 +21,17 @@ import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ProjectDependency;
import org.gradle.api.artifacts.maven.Conf2ScopeMapping
import org.gradle.api.plugins.MavenPlugin
import org.gradle.api.tasks.*
import org.gradle.plugins.ide.eclipse.EclipsePlugin
import org.gradle.plugins.ide.eclipse.model.EclipseClasspath;
import org.gradle.plugins.ide.idea.IdeaPlugin
import org.gradle.api.invocation.*
/**
* Gradle plugin that allows projects to merged together. Primarily developed to
* allow Spring to support multiple multiple incompatible versions of third-party
* allow Spring to support multiple incompatible versions of third-party
* dependencies (for example Hibernate v3 and v4).
* <p>
* The 'merge' extension should be used to define how projects are merged, for example:
* <pre>
* <pre class="code">
* configure(subprojects) {
* apply plugin: MergePlugin
* }
@@ -76,13 +73,13 @@ class MergePlugin implements Plugin<Project> {
// Hook to perform the actual merge logic
project.afterEvaluate{
if(it.merge.into != null) {
if (it.merge.into != null) {
setup(it)
}
}
// Hook to build runtimeMerge dependencies
if(!attachedProjectsEvaluated) {
if (!attachedProjectsEvaluated) {
project.gradle.projectsEvaluated{
postProcessProjects(it)
}
@@ -102,7 +99,7 @@ class MergePlugin implements Plugin<Project> {
// invoking a task will invoke the task with the same name on 'into' project
["sourcesJar", "jar", "javadocJar", "javadoc", "install", "artifactoryPublish"].each {
def task = project.tasks.findByPath(it)
if(task) {
if (task) {
task.enabled = false
task.dependsOn(project.merge.into.tasks.findByPath(it))
}
@@ -120,7 +117,7 @@ class MergePlugin implements Plugin<Project> {
private void setupMaven(Project project) {
project.configurations.each { configuration ->
Conf2ScopeMapping mapping = project.conf2ScopeMappings.getMapping([configuration])
if(mapping.scope) {
if (mapping.scope) {
Configuration intoConfiguration = project.merge.into.configurations.create(
project.name + "-" + configuration.name)
configuration.excludeRules.each {
@@ -131,7 +128,7 @@ class MergePlugin implements Plugin<Project> {
configuration.dependencies.each {
def intoCompile = project.merge.into.configurations.getByName("compile")
// Protect against changing a compile scope dependency (SPR-10218)
if(!intoCompile.dependencies.contains(it)) {
if (!intoCompile.dependencies.contains(it)) {
intoConfiguration.dependencies.add(it)
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,7 +21,6 @@ import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.ProjectDependency;
/**
* Gradle plugin that automatically updates testCompile dependencies to include
* the test source sets of project dependencies.
@@ -41,11 +40,10 @@ class TestSourceSetDependenciesPlugin implements Plugin<Project> {
}
}
private void collectProjectDependencies(Set<ProjectDependency> projectDependencies,
Project project) {
for(def configurationName in ["compile", "optional", "provided", "testCompile"]) {
private void collectProjectDependencies(Set<ProjectDependency> projectDependencies, Project project) {
for (def configurationName in ["compile", "optional", "provided", "testCompile"]) {
Configuration configuration = project.getConfigurations().findByName(configurationName)
if(configuration) {
if (configuration) {
configuration.dependencies.findAll { it instanceof ProjectDependency }.each {
projectDependencies.add(it)
collectProjectDependencies(projectDependencies, it.dependencyProject)
+1 -1
View File
@@ -1 +1 @@
version=3.2.6.BUILD-SNAPSHOT
version=3.2.14.RELEASE
+11
View File
@@ -41,6 +41,17 @@ eclipse.classpath.file.whenMerged { classpath ->
}
}
// Ensure project dependencies come after 3rd-party libs (SPR-11836)
// https://jira.spring.io/browse/SPR-11836
eclipse.classpath.file.whenMerged { classpath ->
classpath.entries.findAll { it instanceof ProjectDependency }.each {
// delete from original position
classpath.entries.remove(it)
// append to end of classpath
classpath.entries.add(it)
}
}
// Allow projects to be used as WPT modules
eclipse.project.natures "org.eclipse.wst.common.project.facet.core.nature"
Binary file not shown.
+5 -5
View File
@@ -1,6 +1,6 @@
#Tue Jul 30 09:29:28 PDT 2013
zipStoreBase=GRADLE_USER_HOME
distributionUrl=http\://services.gradle.org/distributions/gradle-1.6-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
#Wed Apr 30 13:06:57 CEST 2014
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-1.12-bin.zip
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author 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,9 +19,9 @@ package org.springframework.aop;
import java.lang.reflect.Method;
/**
* A specialized type of MethodMatcher that takes into account introductions when
* matching methods. If there are no introductions on the target class, a method
* matcher may be able to optimize matching more effectively for example.
* A specialized type of {@link MethodMatcher} that takes into account introductions
* when matching methods. If there are no introductions on the target class,
* a method matcher may be able to optimize matching more effectively for example.
*
* @author Adrian Colyer
* @since 2.0
@@ -39,6 +39,6 @@ public interface IntroductionAwareMethodMatcher extends MethodMatcher {
* asking is the subject on one or more introductions; {@code false} otherwise
* @return whether or not this method matches statically
*/
boolean matches(Method method, Class targetClass, boolean hasIntroductions);
boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions);
}
@@ -34,6 +34,6 @@ public interface IntroductionInfo {
* Return the additional interfaces introduced by this Advisor or Advice.
* @return the introduced interfaces
*/
Class[] getInterfaces();
Class<?>[] getInterfaces();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -120,9 +120,9 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
/** Non-null if after returning advice binds the return value */
private String returningName = null;
private Class discoveredReturningType = Object.class;
private Class<?> discoveredReturningType = Object.class;
private Class discoveredThrowingType = Object.class;
private Class<?> discoveredThrowingType = Object.class;
/**
* Index for thisJoinPoint argument (currently only
@@ -238,7 +238,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
setArgumentNamesFromStringArray(tokens);
}
public void setArgumentNamesFromStringArray(String[] args) {
public void setArgumentNamesFromStringArray(String... args) {
this.argumentNames = new String[args.length];
for (int i = 0; i < args.length; i++) {
this.argumentNames[i] = StringUtils.trimWhitespace(args[i]);
@@ -251,7 +251,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
if (argumentNames != null) {
if (aspectJAdviceMethod.getParameterTypes().length == argumentNames.length + 1) {
// May need to add implicit join point arg name...
Class firstArgType = aspectJAdviceMethod.getParameterTypes()[0];
Class<?> firstArgType = aspectJAdviceMethod.getParameterTypes()[0];
if (firstArgType == JoinPoint.class ||
firstArgType == ProceedingJoinPoint.class ||
firstArgType == JoinPoint.StaticPart.class) {
@@ -290,7 +290,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
}
protected Class getDiscoveredReturningType() {
protected Class<?> getDiscoveredReturningType() {
return this.discoveredReturningType;
}
@@ -324,7 +324,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
}
protected Class getDiscoveredThrowingType() {
protected Class<?> getDiscoveredThrowingType() {
return this.discoveredThrowingType;
}
@@ -362,7 +362,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
int numUnboundArgs = this.adviceInvocationArgumentCount;
Class[] parameterTypes = this.aspectJAdviceMethod.getParameterTypes();
Class<?>[] parameterTypes = this.aspectJAdviceMethod.getParameterTypes();
if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0])) {
numUnboundArgs--;
}
@@ -378,7 +378,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
this.argumentsIntrospected = true;
}
private boolean maybeBindJoinPoint(Class candidateParameterType) {
private boolean maybeBindJoinPoint(Class<?> candidateParameterType) {
if (candidateParameterType.equals(JoinPoint.class)) {
this.joinPointArgumentIndex = 0;
return true;
@@ -388,7 +388,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
}
private boolean maybeBindProceedingJoinPoint(Class candidateParameterType) {
private boolean maybeBindProceedingJoinPoint(Class<?> candidateParameterType) {
if (candidateParameterType.equals(ProceedingJoinPoint.class)) {
if (!supportsProceedingJoinPoint()) {
throw new IllegalArgumentException("ProceedingJoinPoint is only supported for around advice");
@@ -405,7 +405,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
return false;
}
private boolean maybeBindJoinPointStaticPart(Class candidateParameterType) {
private boolean maybeBindJoinPointStaticPart(Class<?> candidateParameterType) {
if (candidateParameterType.equals(JoinPoint.StaticPart.class)) {
this.joinPointStaticPartArgumentIndex = 0;
return true;
@@ -509,8 +509,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
numParametersToRemove++;
}
String[] pointcutParameterNames = new String[this.argumentNames.length - numParametersToRemove];
Class[] pointcutParameterTypes = new Class[pointcutParameterNames.length];
Class[] methodParameterTypes = this.aspectJAdviceMethod.getParameterTypes();
Class<?>[] pointcutParameterTypes = new Class<?>[pointcutParameterNames.length];
Class<?>[] methodParameterTypes = this.aspectJAdviceMethod.getParameterTypes();
int index = 0;
for (int i = 0; i < this.argumentNames.length; i++) {
@@ -678,7 +678,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
this.adviceMethod = adviceMethod;
}
public boolean matches(Method method, Class targetClass) {
public boolean matches(Method method, Class<?> targetClass) {
return !this.adviceMethod.equals(method);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@ package org.springframework.aop.aspectj;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@@ -29,7 +30,6 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.patterns.NamePattern;
import org.aspectj.weaver.reflect.ReflectionWorld;
import org.aspectj.weaver.reflect.ReflectionWorld.ReflectionWorldException;
import org.aspectj.weaver.reflect.ShadowMatchImpl;
import org.aspectj.weaver.tools.ContextBasedMatcher;
@@ -42,6 +42,7 @@ import org.aspectj.weaver.tools.PointcutParameter;
import org.aspectj.weaver.tools.PointcutParser;
import org.aspectj.weaver.tools.PointcutPrimitive;
import org.aspectj.weaver.tools.ShadowMatch;
import org.springframework.aop.ClassFilter;
import org.springframework.aop.IntroductionAwareMethodMatcher;
import org.springframework.aop.MethodMatcher;
@@ -55,6 +56,7 @@ import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
@@ -98,14 +100,16 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
private static final Log logger = LogFactory.getLog(AspectJExpressionPointcut.class);
private Class pointcutDeclarationScope;
private Class<?> pointcutDeclarationScope;
private String[] pointcutParameterNames = new String[0];
private Class[] pointcutParameterTypes = new Class[0];
private Class<?>[] pointcutParameterTypes = new Class<?>[0];
private BeanFactory beanFactory;
private transient ClassLoader pointcutClassLoader;
private transient PointcutExpression pointcutExpression;
private transient Map<Method, ShadowMatch> shadowMatchCache = new ConcurrentHashMap<Method, ShadowMatch>(32);
@@ -123,7 +127,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
* @param paramNames the parameter names for the pointcut
* @param paramTypes the parameter types for the pointcut
*/
public AspectJExpressionPointcut(Class declarationScope, String[] paramNames, Class[] paramTypes) {
public AspectJExpressionPointcut(Class<?> declarationScope, String[] paramNames, Class<?>[] paramTypes) {
this.pointcutDeclarationScope = declarationScope;
if (paramNames.length != paramTypes.length) {
throw new IllegalStateException(
@@ -137,21 +141,21 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
/**
* Set the declaration scope for the pointcut.
*/
public void setPointcutDeclarationScope(Class pointcutDeclarationScope) {
public void setPointcutDeclarationScope(Class<?> pointcutDeclarationScope) {
this.pointcutDeclarationScope = pointcutDeclarationScope;
}
/**
* Set the parameter names for the pointcut.
*/
public void setParameterNames(String[] names) {
public void setParameterNames(String... names) {
this.pointcutParameterNames = names;
}
/**
* Set the parameter types for the pointcut.
*/
public void setParameterTypes(Class[] types) {
public void setParameterTypes(Class<?>... types) {
this.pointcutParameterTypes = types;
}
@@ -180,20 +184,13 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
throw new IllegalStateException("Must set property 'expression' before attempting to match");
}
if (this.pointcutExpression == null) {
this.pointcutExpression = buildPointcutExpression();
this.pointcutClassLoader = (this.beanFactory instanceof ConfigurableBeanFactory ?
((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() :
ClassUtils.getDefaultClassLoader());
this.pointcutExpression = buildPointcutExpression(this.pointcutClassLoader);
}
}
/**
* Build the underlying AspectJ pointcut expression.
*/
private PointcutExpression buildPointcutExpression() {
ClassLoader cl = (this.beanFactory instanceof ConfigurableBeanFactory ? ((ConfigurableBeanFactory) this.beanFactory)
.getBeanClassLoader() : Thread.currentThread()
.getContextClassLoader());
return buildPointcutExpression(cl);
}
/**
* Build the underlying AspectJ pointcut expression.
*/
@@ -202,11 +199,9 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
PointcutParameter[] pointcutParameters = new PointcutParameter[this.pointcutParameterNames.length];
for (int i = 0; i < pointcutParameters.length; i++) {
pointcutParameters[i] = parser.createPointcutParameter(
this.pointcutParameterNames[i],
this.pointcutParameterTypes[i]);
this.pointcutParameterNames[i], this.pointcutParameterTypes[i]);
}
return parser.parsePointcutExpression(
replaceBooleanOperators(getExpression()),
return parser.parsePointcutExpression(replaceBooleanOperators(getExpression()),
this.pointcutDeclarationScope, pointcutParameters);
}
@@ -244,30 +239,28 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
return this.pointcutExpression;
}
public boolean matches(Class targetClass) {
public boolean matches(Class<?> targetClass) {
checkReadyToMatch();
try {
return this.pointcutExpression.couldMatchJoinPointsInType(targetClass);
} catch (ReflectionWorldException e) {
logger.debug("PointcutExpression matching rejected target class", e);
try {
// Actually this is still a "maybe" - treat the pointcut as dynamic if we
// don't know enough yet
return getFallbackPointcutExpression(targetClass).couldMatchJoinPointsInType(targetClass);
} catch (BCException ex) {
logger.debug(
"Fallback PointcutExpression matching rejected target class",
ex);
return false;
return this.pointcutExpression.couldMatchJoinPointsInType(targetClass);
}
catch (ReflectionWorldException ex) {
logger.debug("PointcutExpression matching rejected target class - trying fallback expression", ex);
// Actually this is still a "maybe" - treat the pointcut as dynamic if we don't know enough yet
PointcutExpression fallbackExpression = getFallbackPointcutExpression(targetClass);
if (fallbackExpression != null) {
return fallbackExpression.couldMatchJoinPointsInType(targetClass);
}
}
}
catch (BCException ex) {
logger.debug("PointcutExpression matching rejected target class", ex);
return false;
}
return false;
}
public boolean matches(Method method, Class targetClass, boolean beanHasIntroductions) {
public boolean matches(Method method, Class<?> targetClass, boolean beanHasIntroductions) {
checkReadyToMatch();
Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
ShadowMatch shadowMatch = getShadowMatch(targetMethod, method);
@@ -283,11 +276,19 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
}
else {
// the maybe case
return (beanHasIntroductions || matchesIgnoringSubtypes(shadowMatch) || matchesTarget(shadowMatch, targetClass));
if (beanHasIntroductions) {
return true;
}
// A match test returned maybe - if there are any subtype sensitive variables
// involved in the test (this, target, at_this, at_target, at_annotation) then
// we say this is not a match as in Spring there will never be a different
// runtime subtype.
RuntimeTestWalker walker = getRuntimeTestWalker(shadowMatch);
return (!walker.testsSubtypeSensitiveVars() || walker.testTargetInstanceOfResidue(targetClass));
}
}
public boolean matches(Method method, Class targetClass) {
public boolean matches(Method method, Class<?> targetClass) {
return matches(method, targetClass, false);
}
@@ -296,7 +297,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
return this.pointcutExpression.mayNeedDynamicTest();
}
public boolean matches(Method method, Class targetClass, Object[] args) {
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
checkReadyToMatch();
ShadowMatch shadowMatch = getShadowMatch(AopUtils.getMostSpecificMethod(method, targetClass), method);
ShadowMatch originalShadowMatch = getShadowMatch(method, method);
@@ -318,31 +319,42 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
catch (IllegalStateException ex) {
// No current invocation...
// TODO: Should we really proceed here?
logger.debug("Couldn't access current invocation - matching with limited context: " + ex);
}
JoinPointMatch joinPointMatch = shadowMatch.matchesJoinPoint(thisObject, targetObject, args);
/*
* Do a final check to see if any this(TYPE) kind of residue match. For
* this purpose, we use the original method's (proxy method's) shadow to
* ensure that 'this' is correctly checked against. Without this check,
* we get incorrect match on this(TYPE) where TYPE matches the target
* type but not 'this' (as would be the case of JDK dynamic proxies).
* <p>See SPR-2979 for the original bug.
*/
if (pmi != null) { // there is a current invocation
RuntimeTestWalker originalMethodResidueTest = getRuntimeTestWalker(originalShadowMatch);
if (!originalMethodResidueTest.testThisInstanceOfResidue(thisObject.getClass())) {
return false;
if (logger.isDebugEnabled()) {
logger.debug("Could not access current invocation - matching with limited context: " + ex);
}
}
if (joinPointMatch.matches() && pmi != null) {
bindParameters(pmi, joinPointMatch);
}
return joinPointMatch.matches();
}
try {
JoinPointMatch joinPointMatch = shadowMatch.matchesJoinPoint(thisObject, targetObject, args);
/*
* Do a final check to see if any this(TYPE) kind of residue match. For
* this purpose, we use the original method's (proxy method's) shadow to
* ensure that 'this' is correctly checked against. Without this check,
* we get incorrect match on this(TYPE) where TYPE matches the target
* type but not 'this' (as would be the case of JDK dynamic proxies).
* <p>See SPR-2979 for the original bug.
*/
if (pmi != null) { // there is a current invocation
RuntimeTestWalker originalMethodResidueTest = getRuntimeTestWalker(originalShadowMatch);
if (!originalMethodResidueTest.testThisInstanceOfResidue(thisObject.getClass())) {
return false;
}
if (joinPointMatch.matches()) {
bindParameters(pmi, joinPointMatch);
}
}
return joinPointMatch.matches();
}
catch (Throwable ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to evaluate join point for arguments " + Arrays.asList(args) +
" - falling back to non-match", ex);
}
return false;
}
}
protected String getCurrentProxiedBeanName() {
return ProxyCreationContext.getCurrentProxiedBeanName();
@@ -350,32 +362,24 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
/**
* Get a new pointcut expression based on a target class's loader, rather
* than the default.
* Get a new pointcut expression based on a target class's loader rather than the default.
*/
private PointcutExpression getFallbackPointcutExpression(
Class<?> targetClass) {
ClassLoader classLoader = targetClass.getClassLoader();
return classLoader == null ? this.pointcutExpression : buildPointcutExpression(classLoader);
}
/**
* A match test returned maybe - if there are any subtype sensitive variables
* involved in the test (this, target, at_this, at_target, at_annotation) then
* we say this is not a match as in Spring there will never be a different
* runtime subtype.
*/
private boolean matchesIgnoringSubtypes(ShadowMatch shadowMatch) {
return !(getRuntimeTestWalker(shadowMatch).testsSubtypeSensitiveVars());
}
private boolean matchesTarget(ShadowMatch shadowMatch, Class targetClass) {
return getRuntimeTestWalker(shadowMatch).testTargetInstanceOfResidue(targetClass);
private PointcutExpression getFallbackPointcutExpression(Class<?> targetClass) {
try {
ClassLoader classLoader = targetClass.getClassLoader();
if (classLoader != null && classLoader != this.pointcutClassLoader) {
return buildPointcutExpression(classLoader);
}
}
catch (Throwable ex) {
logger.debug("Failed to create fallback PointcutExpression", ex);
}
return null;
}
private RuntimeTestWalker getRuntimeTestWalker(ShadowMatch shadowMatch) {
if (shadowMatch instanceof DefensiveShadowMatch) {
return new RuntimeTestWalker(((DefensiveShadowMatch)shadowMatch).primary);
return new RuntimeTestWalker(((DefensiveShadowMatch) shadowMatch).primary);
}
return new RuntimeTestWalker(shadowMatch);
}
@@ -396,44 +400,51 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
if (shadowMatch == null) {
synchronized (this.shadowMatchCache) {
// Not found - now check again with full lock...
PointcutExpression fallbackExpression = null;
Method methodToMatch = targetMethod;
PointcutExpression fallbackPointcutExpression = null;
shadowMatch = this.shadowMatchCache.get(methodToMatch);
shadowMatch = this.shadowMatchCache.get(targetMethod);
if (shadowMatch == null) {
try {
shadowMatch = this.pointcutExpression.matchesMethodExecution(targetMethod);
shadowMatch = this.pointcutExpression.matchesMethodExecution(methodToMatch);
}
catch (ReflectionWorld.ReflectionWorldException ex) {
catch (ReflectionWorldException ex) {
// Failed to introspect target method, probably because it has been loaded
// in a special ClassLoader. Let's try the original method instead...
// in a special ClassLoader. Let's try the declaring ClassLoader instead...
try {
fallbackPointcutExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
shadowMatch = fallbackPointcutExpression.matchesMethodExecution(methodToMatch);
} catch (ReflectionWorld.ReflectionWorldException e) {
if (targetMethod == originalMethod) {
shadowMatch = new ShadowMatchImpl(org.aspectj.util.FuzzyBoolean.NO, null, null, null);
fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
if (fallbackExpression != null) {
shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
}
else {
try {
shadowMatch = this.pointcutExpression.matchesMethodExecution(originalMethod);
}
catch (ReflectionWorld.ReflectionWorldException ex2) {
// Could neither introspect the target class nor the proxy class ->
// let's simply consider this method as non-matching.
methodToMatch = originalMethod;
fallbackPointcutExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
try {
shadowMatch = fallbackPointcutExpression.matchesMethodExecution(methodToMatch);
} catch (ReflectionWorld.ReflectionWorldException e2) {
shadowMatch = new ShadowMatchImpl(org.aspectj.util.FuzzyBoolean.NO, null, null, null);
}
}
catch (ReflectionWorldException ex2) {
fallbackExpression = null;
}
}
if (shadowMatch == null && targetMethod != originalMethod) {
methodToMatch = originalMethod;
try {
shadowMatch = this.pointcutExpression.matchesMethodExecution(methodToMatch);
}
catch (ReflectionWorldException ex3) {
// Could neither introspect the target class nor the proxy class ->
// let's try the original method's declaring class before we give up...
try {
fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
if (fallbackExpression != null) {
shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
}
}
catch (ReflectionWorldException ex4) {
fallbackExpression = null;
}
}
}
if (shadowMatch.maybeMatches() && fallbackPointcutExpression!=null) {
if (shadowMatch == null) {
shadowMatch = new ShadowMatchImpl(org.aspectj.util.FuzzyBoolean.NO, null, null, null);
}
else if (shadowMatch.maybeMatches() && fallbackExpression != null) {
shadowMatch = new DefensiveShadowMatch(shadowMatch,
fallbackPointcutExpression.matchesMethodExecution(methodToMatch));
fallbackExpression.matchesMethodExecution(methodToMatch));
}
this.shadowMatchCache.put(targetMethod, shadowMatch);
}
@@ -551,7 +562,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
return false;
}
private FuzzyBoolean contextMatch(Class targetType) {
private FuzzyBoolean contextMatch(Class<?> targetType) {
String advisedBeanName = getCurrentProxiedBeanName();
if (advisedBeanName == null) { // no proxy creation in progress
// abstain; can't return YES, since that will make pointcut with negation fail
@@ -601,9 +612,11 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
this.shadowMatchCache = new ConcurrentHashMap<Method, ShadowMatch>(32);
}
private static class DefensiveShadowMatch implements ShadowMatch {
private final ShadowMatch primary;
private final ShadowMatch other;
public DefensiveShadowMatch(ShadowMatch primary, ShadowMatch other) {
@@ -612,31 +625,30 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
}
public boolean alwaysMatches() {
return primary.alwaysMatches();
return this.primary.alwaysMatches();
}
public boolean maybeMatches() {
return primary.maybeMatches();
return this.primary.maybeMatches();
}
public boolean neverMatches() {
return primary.neverMatches();
return this.primary.neverMatches();
}
public JoinPointMatch matchesJoinPoint(Object thisObject,
Object targetObject, Object[] args) {
public JoinPointMatch matchesJoinPoint(Object thisObject, Object targetObject, Object[] args) {
try {
return primary.matchesJoinPoint(thisObject, targetObject, args);
} catch (ReflectionWorldException e) {
return other.matchesJoinPoint(thisObject, targetObject, args);
return this.primary.matchesJoinPoint(thisObject, targetObject, args);
}
catch (ReflectionWorldException ex) {
return this.other.matchesJoinPoint(thisObject, targetObject, args);
}
}
public void setMatchingContext(MatchingContext aMatchContext) {
primary.setMatchingContext(aMatchContext);
other.setMatchingContext(aMatchContext);
this.primary.setMatchingContext(aMatchContext);
this.other.setMatchingContext(aMatchContext);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,24 +39,24 @@ public class AspectJExpressionPointcutAdvisor extends AbstractGenericPointcutAdv
this.pointcut.setExpression(expression);
}
public String getExpression() {
return this.pointcut.getExpression();
}
public void setLocation(String location) {
this.pointcut.setLocation(location);
}
public void setParameterTypes(Class[] types) {
this.pointcut.setParameterTypes(types);
}
public void setParameterNames(String[] names) {
this.pointcut.setParameterNames(names);
}
public String getLocation() {
return this.pointcut.getLocation();
}
public String getExpression() {
return this.pointcut.getExpression();
public void setParameterTypes(Class<?>[] types) {
this.pointcut.setParameterTypes(types);
}
public void setParameterNames(String... names) {
this.pointcut.setParameterNames(names);
}
}
@@ -34,7 +34,7 @@ import org.springframework.aop.support.DelegatingIntroductionInterceptor;
*/
public class DeclareParentsAdvisor implements IntroductionAdvisor {
private final Class introducedInterface;
private final Class<?> introducedInterface;
private final ClassFilter typePatternClassFilter;
@@ -47,7 +47,7 @@ public class DeclareParentsAdvisor implements IntroductionAdvisor {
* @param typePattern type pattern the introduction is restricted to
* @param defaultImpl the default implementation class
*/
public DeclareParentsAdvisor(Class interfaceType, String typePattern, Class defaultImpl) {
public DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, Class<?> defaultImpl) {
this(interfaceType, typePattern, defaultImpl,
new DelegatePerTargetObjectIntroductionInterceptor(defaultImpl, interfaceType));
}
@@ -58,7 +58,7 @@ public class DeclareParentsAdvisor implements IntroductionAdvisor {
* @param typePattern type pattern the introduction is restricted to
* @param delegateRef the delegate implementation object
*/
public DeclareParentsAdvisor(Class interfaceType, String typePattern, Object delegateRef) {
public DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, Object delegateRef) {
this(interfaceType, typePattern, delegateRef.getClass(),
new DelegatingIntroductionInterceptor(delegateRef));
}
@@ -71,13 +71,13 @@ public class DeclareParentsAdvisor implements IntroductionAdvisor {
* @param implementationClass implementation class
* @param advice delegation advice
*/
private DeclareParentsAdvisor(Class interfaceType, String typePattern, Class implementationClass, Advice advice) {
private DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, Class<?> implementationClass, Advice advice) {
this.introducedInterface = interfaceType;
ClassFilter typePatternFilter = new TypePatternClassFilter(typePattern);
// Excludes methods implemented.
ClassFilter exclusion = new ClassFilter() {
public boolean matches(Class clazz) {
public boolean matches(Class<?> clazz) {
return !(introducedInterface.isAssignableFrom(clazz));
}
};
@@ -103,8 +103,8 @@ public class DeclareParentsAdvisor implements IntroductionAdvisor {
return this.advice;
}
public Class[] getInterfaces() {
return new Class[] {this.introducedInterface};
public Class<?>[] getInterfaces() {
return new Class<?>[] {this.introducedInterface};
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author 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,8 @@ package org.springframework.aop.aspectj;
import java.lang.reflect.Field;
import org.aspectj.weaver.ReferenceType;
import org.aspectj.weaver.ReferenceTypeDelegate;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.ast.And;
import org.aspectj.weaver.ast.Call;
@@ -30,6 +32,7 @@ import org.aspectj.weaver.ast.Not;
import org.aspectj.weaver.ast.Or;
import org.aspectj.weaver.ast.Test;
import org.aspectj.weaver.internal.tools.MatchingContextBasedTest;
import org.aspectj.weaver.reflect.ReflectionBasedReferenceTypeDelegate;
import org.aspectj.weaver.reflect.ReflectionVar;
import org.aspectj.weaver.reflect.ShadowMatchImpl;
import org.aspectj.weaver.tools.ShadowMatch;
@@ -55,25 +58,36 @@ import org.springframework.util.ReflectionUtils;
*/
class RuntimeTestWalker {
private static final Field residualTestField;
private static final Field varTypeField;
private static final Field myClassField;
static {
try {
residualTestField = ShadowMatchImpl.class.getDeclaredField("residualTest");
varTypeField = ReflectionVar.class.getDeclaredField("varType");
myClassField = ReflectionBasedReferenceTypeDelegate.class.getDeclaredField("myClass");
}
catch (NoSuchFieldException ex) {
throw new IllegalStateException("The version of aspectjtools.jar / aspectjweaver.jar " +
"on the classpath is incompatible with this version of Spring: " + ex);
}
}
private final Test runtimeTest;
public RuntimeTestWalker(ShadowMatch shadowMatch) {
ShadowMatchImpl shadowMatchImplementation = (ShadowMatchImpl) shadowMatch;
try {
Field testField = shadowMatchImplementation.getClass().getDeclaredField("residualTest");
ReflectionUtils.makeAccessible(testField);
this.runtimeTest = (Test) testField.get(shadowMatch);
ReflectionUtils.makeAccessible(residualTestField);
this.runtimeTest = (Test) residualTestField.get(shadowMatch);
}
catch (NoSuchFieldException noSuchFieldEx) {
throw new IllegalStateException("The version of aspectjtools.jar / aspectjweaver.jar " +
"on the classpath is incompatible with this version of Spring: Expected field " +
"'runtimeTest' is not present on ShadowMatchImpl class.");
}
catch (IllegalAccessException illegalAccessEx) {
// Famous last words... but I don't see how this can happen given the
// makeAccessible call above
throw new IllegalStateException("Unable to access ShadowMatchImpl.residualTest field");
catch (IllegalAccessException ex) {
throw new IllegalStateException(ex);
}
}
@@ -87,12 +101,12 @@ class RuntimeTestWalker {
new SubtypeSensitiveVarTypeTestVisitor().testsSubtypeSensitiveVars(this.runtimeTest));
}
public boolean testThisInstanceOfResidue(Class thisClass) {
public boolean testThisInstanceOfResidue(Class<?> thisClass) {
return (this.runtimeTest != null &&
new ThisInstanceOfResidueTestVisitor(thisClass).thisInstanceOfMatches(this.runtimeTest));
}
public boolean testTargetInstanceOfResidue(Class targetClass) {
public boolean testTargetInstanceOfResidue(Class<?> targetClass) {
return (this.runtimeTest != null &&
new TargetInstanceOfResidueTestVisitor(targetClass).targetInstanceOfMatches(this.runtimeTest));
}
@@ -140,19 +154,11 @@ class RuntimeTestWalker {
protected int getVarType(ReflectionVar v) {
try {
Field varTypeField = ReflectionVar.class.getDeclaredField("varType");
ReflectionUtils.makeAccessible(varTypeField);
return (Integer) varTypeField.get(v);
}
catch (NoSuchFieldException noSuchFieldEx) {
throw new IllegalStateException("the version of aspectjtools.jar / aspectjweaver.jar " +
"on the classpath is incompatible with this version of Spring:- expected field " +
"'varType' is not present on ReflectionVar class");
}
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");
catch (IllegalAccessException ex) {
throw new IllegalStateException(ex);
}
}
}
@@ -160,11 +166,13 @@ class RuntimeTestWalker {
private static abstract class InstanceOfResidueTestVisitor extends TestVisitorAdapter {
private Class matchClass;
private boolean matches;
private int matchVarType;
private final Class<?> matchClass;
public InstanceOfResidueTestVisitor(Class matchClass, boolean defaultMatches, int matchVarType) {
private boolean matches;
private final int matchVarType;
public InstanceOfResidueTestVisitor(Class<?> matchClass, boolean defaultMatches, int matchVarType) {
this.matchClass = matchClass;
this.matches = defaultMatches;
this.matchVarType = matchVarType;
@@ -172,19 +180,34 @@ class RuntimeTestWalker {
public boolean instanceOfMatches(Test test) {
test.accept(this);
return matches;
return this.matches;
}
@Override
public void visit(Instanceof i) {
ResolvedType type = (ResolvedType) i.getType();
int varType = getVarType((ReflectionVar) i.getVar());
if (varType != this.matchVarType) {
return;
}
Class<?> typeClass = null;
ResolvedType type = (ResolvedType) i.getType();
if (type instanceof ReferenceType) {
ReferenceTypeDelegate delegate = ((ReferenceType) type).getDelegate();
if (delegate instanceof ReflectionBasedReferenceTypeDelegate) {
try {
ReflectionUtils.makeAccessible(myClassField);
typeClass = (Class<?>) myClassField.get(delegate);
}
catch (IllegalAccessException ex) {
throw new IllegalStateException(ex);
}
}
}
try {
Class typeClass = ClassUtils.forName(type.getName(), this.matchClass.getClassLoader());
// Don't use ReflectionType.isAssignableFrom() as it won't be aware of (Spring) mixins
// Don't use ResolvedType.isAssignableFrom() as it won't be aware of (Spring) mixins
if (typeClass == null) {
typeClass = ClassUtils.forName(type.getName(), this.matchClass.getClassLoader());
}
this.matches = typeClass.isAssignableFrom(this.matchClass);
}
catch (ClassNotFoundException ex) {
@@ -199,7 +222,7 @@ class RuntimeTestWalker {
*/
private static class TargetInstanceOfResidueTestVisitor extends InstanceOfResidueTestVisitor {
public TargetInstanceOfResidueTestVisitor(Class targetClass) {
public TargetInstanceOfResidueTestVisitor(Class<?> targetClass) {
super(targetClass, false, TARGET_VAR);
}
@@ -214,7 +237,7 @@ class RuntimeTestWalker {
*/
private static class ThisInstanceOfResidueTestVisitor extends InstanceOfResidueTestVisitor {
public ThisInstanceOfResidueTestVisitor(Class thisClass) {
public ThisInstanceOfResidueTestVisitor(Class<?> thisClass) {
super(thisClass, true, THIS_VAR);
}
@@ -228,8 +251,11 @@ class RuntimeTestWalker {
private static class SubtypeSensitiveVarTypeTestVisitor extends TestVisitorAdapter {
private final Object thisObj = new Object();
private final Object targetObj = new Object();
private final Object[] argsObjs = new Object[0];
private boolean testsSubtypeSensitiveVars = false;
public boolean testsSubtypeSensitiveVars(Test aTest) {
@@ -240,8 +266,8 @@ class RuntimeTestWalker {
@Override
public void visit(Instanceof i) {
ReflectionVar v = (ReflectionVar) i.getVar();
Object varUnderTest = v.getBindingAtJoinPoint(thisObj,targetObj,argsObjs);
if ((varUnderTest == thisObj) || (varUnderTest == targetObj)) {
Object varUnderTest = v.getBindingAtJoinPoint(this.thisObj, this.targetObj, this.argsObjs);
if (varUnderTest == this.thisObj || varUnderTest == this.targetObj) {
this.testsSubtypeSensitiveVars = true;
}
}
@@ -251,7 +277,7 @@ class RuntimeTestWalker {
// If you thought things were bad before, now we sink to new levels of horror...
ReflectionVar v = (ReflectionVar) hasAnn.getVar();
int varType = getVarType(v);
if ((varType == AT_THIS_VAR) || (varType == AT_TARGET_VAR) || (varType == AT_ANNOTATION_VAR)) {
if (varType == AT_THIS_VAR || varType == AT_TARGET_VAR || varType == AT_ANNOTATION_VAR) {
this.testsSubtypeSensitiveVars = true;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -67,7 +67,7 @@ public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorA
}
public void setAspectJAdvisorFactory(AspectJAdvisorFactory aspectJAdvisorFactory) {
Assert.notNull(this.aspectJAdvisorFactory, "AspectJAdvisorFactory must not be null");
Assert.notNull(aspectJAdvisorFactory, "AspectJAdvisorFactory must not be null");
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
}
@@ -89,7 +89,7 @@ public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorA
}
@Override
protected boolean isInfrastructureClass(Class beanClass) {
protected boolean isInfrastructureClass(Class<?> beanClass) {
// Previously we setProxyTargetClass(true) in the constructor, but that has too
// broad an impact. Instead we now override isInfrastructureClass to avoid proxying
// aspects. I'm not entirely happy with that as there is no good reason not
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -49,7 +49,7 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyConfig
*/
private int order = Ordered.LOWEST_PRECEDENCE;
private final Map<Class, Boolean> eligibleBeans = new ConcurrentHashMap<Class, Boolean>(64);
private final Map<Class<?>, Boolean> eligibleBeans = new ConcurrentHashMap<Class<?>, Boolean>(64);
/**
@@ -87,9 +87,11 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyConfig
// Ignore AOP infrastructure such as scoped proxies.
return bean;
}
if (isEligible(bean, beanName)) {
if (bean instanceof Advised) {
Advised advised = (Advised) bean;
if (bean instanceof Advised) {
Advised advised = (Advised) bean;
if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
// Add our local Advisor to the existing proxy's Advisor chain...
if (this.beforeExistingAdvisors) {
advised.addAdvisor(0, this.advisor);
}
@@ -98,32 +100,47 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyConfig
}
return bean;
}
else {
ProxyFactory proxyFactory = new ProxyFactory(bean);
// Copy our properties (proxyTargetClass etc) inherited from ProxyConfig.
proxyFactory.copyFrom(this);
proxyFactory.addAdvisor(this.advisor);
return proxyFactory.getProxy(this.beanClassLoader);
}
}
else {
// No async proxy needed.
return bean;
if (isEligible(bean, beanName)) {
ProxyFactory proxyFactory = new ProxyFactory(bean);
// Copy our properties (proxyTargetClass etc) inherited from ProxyConfig.
proxyFactory.copyFrom(this);
proxyFactory.addAdvisor(this.advisor);
return proxyFactory.getProxy(this.beanClassLoader);
}
// No async proxy needed.
return bean;
}
/**
* Check whether the given bean is eligible for advising with this
* post-processor's {@link Advisor}.
* <p>Implements caching of {@code canApply} results per bean target class.
* <p>Delegates to {@link #isEligible(Class)} for target class checking.
* Can be overridden e.g. to specifically exclude certain beans by name.
* <p>Note: Only called for regular bean instances but not for existing
* proxy instances which implement {@link Advised} and allow for adding
* the local {@link Advisor} to the existing proxy's {@link Advisor} chain.
* For the latter, {@link #isEligible(Class)} is being called directly,
* with the actual target class behind the existing proxy (as determined
* by {@link AopUtils#getTargetClass(Object)}).
* @param bean the bean instance
* @param beanName the name of the bean
* @see AopUtils#getTargetClass(Object)
* @see AopUtils#canApply(Advisor, Class)
* @see #isEligible(Class)
*/
protected boolean isEligible(Object bean, String beanName) {
Class<?> targetClass = AopUtils.getTargetClass(bean);
return isEligible(bean.getClass());
}
/**
* Check whether the given class is eligible for advising with this
* post-processor's {@link Advisor}.
* <p>Implements caching of {@code canApply} results per bean target class.
* @param targetClass the class to check against
* @see AopUtils#canApply(Advisor, Class)
*/
protected boolean isEligible(Class<?> targetClass) {
Boolean eligible = this.eligibleBeans.get(targetClass);
if (eligible != null) {
return eligible;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,6 +37,7 @@ import org.springframework.aop.RawTargetAccess;
import org.springframework.aop.TargetSource;
import org.springframework.aop.support.AopUtils;
import org.springframework.cglib.core.CodeGenerationException;
import org.springframework.cglib.core.SpringNamingPolicy;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.CallbackFilter;
import org.springframework.cglib.proxy.Dispatcher;
@@ -181,20 +182,20 @@ final class CglibAopProxy implements AopProxy, Serializable {
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setStrategy(new MemorySafeUndeclaredThrowableStrategy(UndeclaredThrowableException.class));
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new MemorySafeUndeclaredThrowableStrategy(UndeclaredThrowableException.class));
enhancer.setInterceptDuringConstruction(false);
Callback[] callbacks = getCallbacks(rootClass);
enhancer.setCallbacks(callbacks);
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
Class<?>[] types = new Class[callbacks.length];
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
enhancer.setCallbacks(callbacks);
// Generate the proxy class and create a proxy instance.
Object proxy;
@@ -259,7 +260,7 @@ final class CglibAopProxy implements AopProxy, Serializable {
if (!Object.class.equals(method.getDeclaringClass()) && !Modifier.isStatic(method.getModifiers()) &&
Modifier.isFinal(method.getModifiers())) {
logger.warn("Unable to proxy method [" + method + "] because it is final: " +
"All calls to this method via a proxy will be routed directly to the proxy.");
"All calls to this method via a proxy will NOT be routed to the target instance.");
}
}
}
@@ -312,8 +313,7 @@ final class CglibAopProxy implements AopProxy, Serializable {
Callback[] fixedCallbacks = new Callback[methods.length];
this.fixedInterceptorMap = new HashMap<String, Integer>(methods.length);
// TODO: small memory optimisation here (can skip creation for
// methods with no advice)
// TODO: small memory optimisation here (can skip creation for methods with no advice)
for (int x = 0; x < methods.length; x++) {
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
@@ -340,16 +340,15 @@ final class CglibAopProxy implements AopProxy, Serializable {
*/
private static Object processReturnType(Object proxy, Object target, Method method, Object retVal) {
// Massage return value if necessary
if (retVal != null && retVal == target &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this".
// Note that we can't help if the target sets a reference
// to itself in another returned object.
if (retVal != null && retVal == target && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this". Note that we can't help
// if the target sets a reference to itself in another returned object.
retVal = proxy;
}
Class<?> returnType = method.getReturnType();
if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
@@ -595,7 +594,7 @@ final class CglibAopProxy implements AopProxy, Serializable {
*/
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
private AdvisedSupport advised;
private final AdvisedSupport advised;
public DynamicAdvisedInterceptor(AdvisedSupport advised) {
this.advised = advised;
@@ -612,8 +611,8 @@ final class CglibAopProxy implements AopProxy, Serializable {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// May be null Get as late as possible to minimize the time we
// "own" the target, in case it comes from a pool.
// May be null. Get as late as possible to minimize the time we
// "own" the target, in case it comes from a pool...
target = getTarget();
if (target != null) {
targetClass = target.getClass();
@@ -818,8 +817,8 @@ final class CglibAopProxy implements AopProxy, Serializable {
// of the target type. If so we know it never needs to have return type
// massage and can use a dispatcher.
// If the proxy is being exposed, then must use the interceptor the
// correct one is already configured. If the target is not static cannot
// use a Dispatcher because the target can not then be released.
// correct one is already configured. If the target is not static, then
// cannot use a dispatcher because the target cannot be released.
if (exposeProxy || !isStatic) {
return INVOKE_TARGET;
}
@@ -851,7 +850,7 @@ final class CglibAopProxy implements AopProxy, Serializable {
@Override
public boolean equals(Object other) {
if (other == this) {
if (this == other) {
return true;
}
if (!(other instanceof ProxyCallbackFilter)) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -75,7 +75,7 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
*/
/** We use a static Log to avoid serialization issues */
private static Log logger = LogFactory.getLog(JdkDynamicAopProxy.class);
private static final Log logger = LogFactory.getLog(JdkDynamicAopProxy.class);
/** Config used to configure this proxy */
private final AdvisedSupport advised;
@@ -114,7 +114,7 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
@@ -124,8 +124,8 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
* on the supplied set of interfaces.
* @param proxiedInterfaces the interfaces to introspect
*/
private void findDefinedEqualsAndHashCodeMethods(Class[] proxiedInterfaces) {
for (Class proxiedInterface : proxiedInterfaces) {
private void findDefinedEqualsAndHashCodeMethods(Class<?>[] proxiedInterfaces) {
for (Class<?> proxiedInterface : proxiedInterfaces) {
Method[] methods = proxiedInterface.getDeclaredMethods();
for (Method method : methods) {
if (AopUtils.isEqualsMethod(method)) {
@@ -153,7 +153,7 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Class targetClass = null;
Class<?> targetClass = null;
Object target = null;
try {
@@ -212,8 +212,10 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
} else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author 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.aop.framework;
import org.aopalliance.intercept.Interceptor;
import org.springframework.aop.TargetSource;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
@@ -47,9 +46,8 @@ public class ProxyFactory extends ProxyCreatorSupport {
* @param target the target object to be proxied
*/
public ProxyFactory(Object target) {
Assert.notNull(target, "Target object must not be null");
setInterfaces(ClassUtils.getAllInterfaces(target));
setTarget(target);
setInterfaces(ClassUtils.getAllInterfaces(target));
}
/**
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -133,7 +133,7 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
* @see #setInterfaces
* @see AbstractSingletonProxyFactoryBean#setProxyInterfaces
*/
public void setProxyInterfaces(Class[] proxyInterfaces) throws ClassNotFoundException {
public void setProxyInterfaces(Class<?>[] proxyInterfaces) throws ClassNotFoundException {
setInterfaces(proxyInterfaces);
}
@@ -154,7 +154,7 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
* @see org.aopalliance.aop.Advice
* @see org.springframework.aop.target.SingletonTargetSource
*/
public void setInterceptorNames(String[] interceptorNames) {
public void setInterceptorNames(String... interceptorNames) {
this.interceptorNames = interceptorNames;
}
@@ -263,7 +263,7 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
return this.singletonInstance.getClass();
}
}
Class[] ifcs = getProxiedInterfaces();
Class<?>[] ifcs = getProxiedInterfaces();
if (ifcs.length == 1) {
return ifcs[0];
}
@@ -292,7 +292,7 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
* @return the merged interface as Class
* @see java.lang.reflect.Proxy#getProxyClass
*/
protected Class createCompositeInterface(Class[] interfaces) {
protected Class<?> createCompositeInterface(Class<?>[] interfaces) {
return ClassUtils.createCompositeInterface(interfaces, this.proxyClassLoader);
}
@@ -306,7 +306,7 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
this.targetSource = freshTargetSource();
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
// Rely on AOP infrastructure to tell us what interfaces to proxy.
Class targetClass = getTargetClass();
Class<?> targetClass = getTargetClass();
if (targetClass == null) {
throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
}
@@ -396,7 +396,7 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
* @return {@code true} if it's an Advisor or Advice
*/
private boolean isNamedBeanAnAdvisorOrAdvice(String beanName) {
Class namedBeanClass = this.beanFactory.getType(beanName);
Class<?> namedBeanClass = this.beanFactory.getType(beanName);
if (namedBeanClass != null) {
return (Advisor.class.isAssignableFrom(namedBeanClass) || Advice.class.isAssignableFrom(namedBeanClass));
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -198,7 +198,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyConfig
* Ordering is significant: The TargetSource returned from the first matching
* TargetSourceCreator (that is, the first that returns non-null) will be used.
*/
public void setCustomTargetSourceCreators(TargetSourceCreator[] targetSourceCreators) {
public void setCustomTargetSourceCreators(TargetSourceCreator... targetSourceCreators) {
this.customTargetSourceCreators = targetSourceCreators;
}
@@ -209,7 +209,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyConfig
* This is perfectly valid, if "specific" interceptors such as matching
* Advisors are all we want.
*/
public void setInterceptorNames(String[] interceptorNames) {
public void setInterceptorNames(String... interceptorNames) {
this.interceptorNames = interceptorNames;
}
@@ -262,7 +262,9 @@ public abstract class AbstractAutoProxyCreator extends ProxyConfig
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, Boolean.TRUE);
if (!this.earlyProxyReferences.containsKey(cacheKey)) {
this.earlyProxyReferences.put(cacheKey, Boolean.TRUE);
}
return wrapIfNecessary(bean, beanName, cacheKey);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -60,7 +60,7 @@ public class BeanNameAutoProxyCreator extends AbstractAutoProxyCreator {
* @see org.springframework.beans.factory.FactoryBean
* @see org.springframework.beans.factory.BeanFactory#FACTORY_BEAN_PREFIX
*/
public void setBeanNames(String[] beanNames) {
public void setBeanNames(String... beanNames) {
Assert.notEmpty(beanNames, "'beanNames' must not be empty");
this.beanNames = new ArrayList<String>(beanNames.length);
for (String mappedName : beanNames) {
@@ -73,7 +73,7 @@ public class BeanNameAutoProxyCreator extends AbstractAutoProxyCreator {
* Identify as bean to proxy if the bean name is in the configured list of names.
*/
@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource targetSource) {
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
if (this.beanNames != null) {
for (String mappedName : this.beanNames) {
if (FactoryBean.class.isAssignableFrom(beanClass)) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2006 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
* TargetSourceCreator that enforces a LazyInitTargetSource for each bean
* that is defined as "lazy-init". This will lead to a proxy created for
* each of those beans, allowing to fetch a reference to such a bean
* without actually initialized the target bean instance.
* without actually initializing the target bean instance.
*
* <p>To be registered as custom TargetSourceCreator for an auto-proxy creator,
* in combination with custom interceptors for specific beans or for the
@@ -60,7 +60,7 @@ public class LazyInitTargetSourceCreator extends AbstractBeanFactoryBasedTargetS
@Override
protected AbstractBeanFactoryBasedTargetSource createBeanFactoryBasedTargetSource(
Class beanClass, String beanName) {
Class<?> beanClass, String beanName) {
if (getBeanFactory() instanceof ConfigurableListableBeanFactory) {
BeanDefinition definition =
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,7 +21,6 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils;
@@ -32,7 +31,7 @@ import org.springframework.util.StringUtils;
/**
* Base class for asynchronous method execution aspects, such as
* {@link org.springframework.scheduling.annotation.AnnotationAsyncExecutionInterceptor}
* {@code org.springframework.scheduling.annotation.AnnotationAsyncExecutionInterceptor}
* or {@code org.springframework.scheduling.aspectj.AnnotationAsyncExecutionAspect}.
*
* <p>Provides support for <i>executor qualification</i> on a method-by-method basis.
@@ -80,7 +79,7 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
/**
* Set the {@link BeanFactory} to be used when looking up executors by qualifier.
*/
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -62,11 +62,11 @@ public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport
/**
* Create a new {@code AsyncExecutionInterceptor}.
* @param executor the {@link Executor} (typically a Spring {@link AsyncTaskExecutor}
* or {@link java.util.concurrent.ExecutorService}) to delegate to.
* @param defaultExecutor the {@link Executor} (typically a Spring {@link AsyncTaskExecutor}
* or {@link java.util.concurrent.ExecutorService}) to delegate to
*/
public AsyncExecutionInterceptor(Executor executor) {
super(executor);
public AsyncExecutionInterceptor(Executor defaultExecutor) {
super(defaultExecutor);
}
@@ -117,8 +117,8 @@ public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport
* Subclasses may override to provide support for extracting qualifier information,
* e.g. via an annotation on the given method.
* @return always {@code null}
* @see #determineAsyncExecutor(Method)
* @since 3.1.2
* @see #determineAsyncExecutor(Method)
*/
@Override
protected String getExecutorQualifier(Method method) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -151,7 +151,7 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor {
/**
* The {@code Set} of allowed placeholders.
*/
private static final Set ALLOWED_PLACEHOLDERS =
private static final Set<Object> ALLOWED_PLACEHOLDERS =
new Constants(CustomizableTraceInterceptor.class).getValues("PLACEHOLDER_");
@@ -258,7 +258,7 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor {
return returnValue;
}
catch (Throwable ex) {
if(stopWatch.isRunning()) {
if (stopWatch.isRunning()) {
stopWatch.stop();
}
exitThroughException = true;
@@ -268,7 +268,7 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor {
}
finally {
if (!exitThroughException) {
if(stopWatch.isRunning()) {
if (stopWatch.isRunning()) {
stopWatch.stop();
}
writeToLog(logger,
@@ -325,18 +325,19 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor {
while (matcher.find()) {
String match = matcher.group();
if (PLACEHOLDER_METHOD_NAME.equals(match)) {
matcher.appendReplacement(output, escape(methodInvocation.getMethod().getName()));
matcher.appendReplacement(output, Matcher.quoteReplacement(methodInvocation.getMethod().getName()));
}
else if (PLACEHOLDER_TARGET_CLASS_NAME.equals(match)) {
String className = getClassForLogging(methodInvocation.getThis()).getName();
matcher.appendReplacement(output, escape(className));
matcher.appendReplacement(output, Matcher.quoteReplacement(className));
}
else if (PLACEHOLDER_TARGET_CLASS_SHORT_NAME.equals(match)) {
String shortName = ClassUtils.getShortName(getClassForLogging(methodInvocation.getThis()));
matcher.appendReplacement(output, escape(shortName));
matcher.appendReplacement(output, Matcher.quoteReplacement(shortName));
}
else if (PLACEHOLDER_ARGUMENTS.equals(match)) {
matcher.appendReplacement(output, escape(StringUtils.arrayToCommaDelimitedString(methodInvocation.getArguments())));
matcher.appendReplacement(output,
Matcher.quoteReplacement(StringUtils.arrayToCommaDelimitedString(methodInvocation.getArguments())));
}
else if (PLACEHOLDER_ARGUMENT_TYPES.equals(match)) {
appendArgumentTypes(methodInvocation, matcher, output);
@@ -345,7 +346,7 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor {
appendReturnValue(methodInvocation, matcher, output, returnValue);
}
else if (throwable != null && PLACEHOLDER_EXCEPTION.equals(match)) {
matcher.appendReplacement(output, escape(throwable.toString()));
matcher.appendReplacement(output, Matcher.quoteReplacement(throwable.toString()));
}
else if (PLACEHOLDER_INVOCATION_TIME.equals(match)) {
matcher.appendReplacement(output, Long.toString(invocationTime));
@@ -379,7 +380,7 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor {
matcher.appendReplacement(output, "null");
}
else {
matcher.appendReplacement(output, escape(returnValue.toString()));
matcher.appendReplacement(output, Matcher.quoteReplacement(returnValue.toString()));
}
}
@@ -394,12 +395,13 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor {
* @param output the {@code StringBuffer} containing the output
*/
private void appendArgumentTypes(MethodInvocation methodInvocation, Matcher matcher, StringBuffer output) {
Class[] argumentTypes = methodInvocation.getMethod().getParameterTypes();
Class<?>[] argumentTypes = methodInvocation.getMethod().getParameterTypes();
String[] argumentTypeShortNames = new String[argumentTypes.length];
for (int i = 0; i < argumentTypeShortNames.length; i++) {
argumentTypeShortNames[i] = ClassUtils.getShortName(argumentTypes[i]);
}
matcher.appendReplacement(output, escape(StringUtils.arrayToCommaDelimitedString(argumentTypeShortNames)));
matcher.appendReplacement(output,
Matcher.quoteReplacement(StringUtils.arrayToCommaDelimitedString(argumentTypeShortNames)));
}
/**
@@ -417,27 +419,4 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor {
}
}
/**
* Replaces {@code $} in inner class names with {@code \$}.
* <p>This code is equivalent to JDK 1.5's {@code quoteReplacement}
* method in the Matcher class itself. We're keeping our own version
* here for JDK 1.4 compliance reasons only.
*/
private String escape(String input) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (c == '\\') {
sb.append("\\\\");
}
else if (c == '$') {
sb.append("\\$");
}
else {
sb.append(c);
}
}
return sb.toString();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -90,7 +90,7 @@ public class ScopedProxyFactoryBean extends ProxyConfig implements FactoryBean<O
pf.copyFrom(this);
pf.setTargetSource(this.scopedTargetSource);
Class beanType = beanFactory.getType(this.targetBeanName);
Class<?> beanType = beanFactory.getType(this.targetBeanName);
if (beanType == null) {
throw new IllegalStateException("Cannot create scoped proxy for bean '" + this.targetBeanName +
"': Target type could not be determined at the time of proxy creation.");
@@ -122,10 +122,7 @@ public class ScopedProxyFactoryBean extends ProxyConfig implements FactoryBean<O
if (this.proxy != null) {
return this.proxy.getClass();
}
if (this.scopedTargetSource != null) {
return this.scopedTargetSource.getTargetClass();
}
return null;
return this.scopedTargetSource.getTargetClass();
}
public boolean isSingleton() {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,17 +29,16 @@ import org.springframework.util.StringUtils;
* <ul>
* <li>pattern: regular expression for the fully-qualified method names to match.
* The exact regexp syntax will depend on the subclass (e.g. Perl5 regular expressions)
* <li>patterns: alternative property taking a String array of patterns. The result will
* be the union of these patterns.
* <li>patterns: alternative property taking a String array of patterns.
* The result will be the union of these patterns.
* </ul>
*
* <p>Note: the regular expressions must be a match. For example,
* {@code .*get.*} will match com.mycom.Foo.getBar().
* {@code get.*} will not.
*
* <p>This base class is serializable. Subclasses should declare all fields transient
* - the initPatternRepresentation method in this class will be invoked again on the
* client side on deserialization.
* <p>This base class is serializable. Subclasses should declare all fields transient;
* the {@link #initPatternRepresentation} method will be invoked again on deserialization.
*
* @author Rod Johnson
* @author Juergen Hoeller
@@ -51,10 +50,14 @@ import org.springframework.util.StringUtils;
public abstract class AbstractRegexpMethodPointcut extends StaticMethodMatcherPointcut
implements Serializable {
/** Regular expressions to match */
/**
* Regular expressions to match.
*/
private String[] patterns = new String[0];
/** Regular expressions <strong>not</strong> to match */
/**
* Regular expressions <strong>not</strong> to match.
*/
private String[] excludedPatterns = new String[0];
@@ -64,15 +67,15 @@ public abstract class AbstractRegexpMethodPointcut extends StaticMethodMatcherPo
* @see #setPatterns
*/
public void setPattern(String pattern) {
setPatterns(new String[] {pattern});
setPatterns(pattern);
}
/**
* Set the regular expressions defining methods to match.
* Matching will be the union of all these; if any match,
* the pointcut matches.
* Matching will be the union of all these; if any match, the pointcut matches.
* @see #setPattern
*/
public void setPatterns(String[] patterns) {
public void setPatterns(String... patterns) {
Assert.notEmpty(patterns, "'patterns' must not be empty");
this.patterns = new String[patterns.length];
for (int i = 0; i < patterns.length; i++) {
@@ -94,15 +97,15 @@ public abstract class AbstractRegexpMethodPointcut extends StaticMethodMatcherPo
* @see #setExcludedPatterns
*/
public void setExcludedPattern(String excludedPattern) {
setExcludedPatterns(new String[] {excludedPattern});
setExcludedPatterns(excludedPattern);
}
/**
* Set the regular expressions defining methods to match for exclusion.
* Matching will be the union of all these; if any match,
* the pointcut matches.
* Matching will be the union of all these; if any match, the pointcut matches.
* @see #setExcludedPattern
*/
public void setExcludedPatterns(String[] excludedPatterns) {
public void setExcludedPatterns(String... excludedPatterns) {
Assert.notEmpty(excludedPatterns, "'excludedPatterns' must not be empty");
this.excludedPatterns = new String[excludedPatterns.length];
for (int i = 0; i < excludedPatterns.length; i++) {
@@ -124,7 +127,7 @@ public abstract class AbstractRegexpMethodPointcut extends StaticMethodMatcherPo
* of the target class as well as against the method's declaring class,
* plus the name of the method.
*/
public boolean matches(Method method, Class targetClass) {
public boolean matches(Method method, Class<?> targetClass) {
return ((targetClass != null && matchesPattern(targetClass.getName() + "." + method.getName())) ||
matchesPattern(method.getDeclaringClass().getName() + "." + method.getName()));
}
@@ -172,18 +175,18 @@ public abstract class AbstractRegexpMethodPointcut extends StaticMethodMatcherPo
protected abstract void initExcludedPatternRepresentation(String[] patterns) throws IllegalArgumentException;
/**
* Does the pattern at the given index match this string?
* @param pattern {@code String} pattern to match
* @param patternIndex index of pattern from 0
* @return {@code true} if there is a match, else {@code false}.
* Does the pattern at the given index match the given String?
* @param pattern the {@code String} pattern to match
* @param patternIndex index of pattern (starting from 0)
* @return {@code true} if there is a match, {@code false} otherwise
*/
protected abstract boolean matches(String pattern, int patternIndex);
/**
* Does the exclusion pattern at the given index match this string?
* @param pattern {@code String} pattern to match.
* @param patternIndex index of pattern starting from 0.
* @return {@code true} if there is a match, else {@code false}.
* Does the exclusion pattern at the given index match the given String?
* @param pattern the {@code String} pattern to match
* @param patternIndex index of pattern (starting from 0)
* @return {@code true} if there is a match, {@code false} otherwise
*/
protected abstract boolean matchesExclusion(String pattern, int patternIndex);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author 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,7 @@ package org.springframework.aop.support;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
@@ -215,7 +215,7 @@ public abstract class AopUtils {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class> classes = new HashSet<Class>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
Set<Class> classes = new LinkedHashSet<Class>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
classes.add(targetClass);
for (Class<?> clazz : classes) {
Method[] methods = clazz.getMethods();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,8 +23,7 @@ import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
* Static utility methods for composing
* {@link org.springframework.aop.ClassFilter ClassFilters}.
* Static utility methods for composing {@link ClassFilter ClassFilters}.
*
* @author Rod Johnson
* @author Rob Harrop
@@ -96,9 +95,9 @@ public abstract class ClassFilters {
this.filters = filters;
}
public boolean matches(Class clazz) {
for (int i = 0; i < this.filters.length; i++) {
if (this.filters[i].matches(clazz)) {
public boolean matches(Class<?> clazz) {
for (ClassFilter filter : this.filters) {
if (filter.matches(clazz)) {
return true;
}
}
@@ -130,9 +129,9 @@ public abstract class ClassFilters {
this.filters = filters;
}
public boolean matches(Class clazz) {
for (int i = 0; i < this.filters.length; i++) {
if (!this.filters[i].matches(clazz)) {
public boolean matches(Class<?> clazz) {
for (ClassFilter filter : this.filters) {
if (!filter.matches(clazz)) {
return false;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -178,7 +178,6 @@ public class ComposablePointcut implements Pointcut, Serializable {
return this.methodMatcher;
}
@Override
public boolean equals(Object other) {
if (this == other) {
@@ -187,7 +186,6 @@ public class ComposablePointcut implements Pointcut, Serializable {
if (!(other instanceof ComposablePointcut)) {
return false;
}
ComposablePointcut that = (ComposablePointcut) other;
return ObjectUtils.nullSafeEquals(that.classFilter, this.classFilter) &&
ObjectUtils.nullSafeEquals(that.methodMatcher, this.methodMatcher);
@@ -207,8 +205,7 @@ public class ComposablePointcut implements Pointcut, Serializable {
@Override
public String toString() {
return "ComposablePointcut: ClassFilter [" + this.classFilter +
"], MethodMatcher [" + this.methodMatcher + "]";
return "ComposablePointcut: " + this.classFilter + ", " +this.methodMatcher;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@
package org.springframework.aop.support;
import java.io.Serializable;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import org.aopalliance.aop.Advice;
@@ -43,7 +43,7 @@ public class DefaultIntroductionAdvisor implements IntroductionAdvisor, ClassFil
private final Advice advice;
private final Set<Class> interfaces = new HashSet<Class>();
private final Set<Class> interfaces = new LinkedHashSet<Class>();
private int order = Integer.MAX_VALUE;
@@ -68,11 +68,11 @@ public class DefaultIntroductionAdvisor implements IntroductionAdvisor, ClassFil
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
if (introductionInfo != null) {
Class[] introducedInterfaces = introductionInfo.getInterfaces();
Class<?>[] introducedInterfaces = introductionInfo.getInterfaces();
if (introducedInterfaces.length == 0) {
throw new IllegalArgumentException("IntroductionAdviceSupport implements no interfaces");
}
for (Class ifc : introducedInterfaces) {
for (Class<?> ifc : introducedInterfaces) {
addInterface(ifc);
}
}
@@ -83,7 +83,7 @@ public class DefaultIntroductionAdvisor implements IntroductionAdvisor, ClassFil
* @param advice the Advice to apply
* @param intf the interface to introduce
*/
public DefaultIntroductionAdvisor(DynamicIntroductionAdvice advice, Class intf) {
public DefaultIntroductionAdvisor(DynamicIntroductionAdvice advice, Class<?> intf) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
addInterface(intf);
@@ -94,7 +94,7 @@ public class DefaultIntroductionAdvisor implements IntroductionAdvisor, ClassFil
* Add the specified interface to the list of interfaces to introduce.
* @param intf the interface to introduce
*/
public void addInterface(Class intf) {
public void addInterface(Class<?> intf) {
Assert.notNull(intf, "Interface must not be null");
if (!intf.isInterface()) {
throw new IllegalArgumentException("Specified class [" + intf.getName() + "] must be an interface");
@@ -102,12 +102,13 @@ public class DefaultIntroductionAdvisor implements IntroductionAdvisor, ClassFil
this.interfaces.add(intf);
}
public Class[] getInterfaces() {
return this.interfaces.toArray(new Class[this.interfaces.size()]);
public Class<?>[] getInterfaces() {
return this.interfaces.toArray(new Class<?>[this.interfaces.size()]);
}
@Override
public void validateInterfaces() throws IllegalArgumentException {
for (Class ifc : this.interfaces) {
for (Class<?> ifc : this.interfaces) {
if (this.advice instanceof DynamicIntroductionAdvice &&
!((DynamicIntroductionAdvice) this.advice).implementsInterface(ifc)) {
throw new IllegalArgumentException("DynamicIntroductionAdvice [" + this.advice + "] " +
@@ -138,7 +139,7 @@ public class DefaultIntroductionAdvisor implements IntroductionAdvisor, ClassFil
return this;
}
public boolean matches(Class clazz) {
public boolean matches(Class<?> clazz) {
return true;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@ import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -43,7 +43,7 @@ import org.springframework.util.ClassUtils;
@SuppressWarnings("serial")
public class IntroductionInfoSupport implements IntroductionInfo, Serializable {
protected final Set<Class> publishedInterfaces = new HashSet<Class>();
protected final Set<Class> publishedInterfaces = new LinkedHashSet<Class>();
private transient Map<Method, Boolean> rememberedMethods = new ConcurrentHashMap<Method, Boolean>(32);
@@ -55,12 +55,12 @@ public class IntroductionInfoSupport implements IntroductionInfo, Serializable {
* <p>Does nothing if the interface is not implemented by the delegate.
* @param intf the interface to suppress
*/
public void suppressInterface(Class intf) {
public void suppressInterface(Class<?> intf) {
this.publishedInterfaces.remove(intf);
}
public Class[] getInterfaces() {
return this.publishedInterfaces.toArray(new Class[this.publishedInterfaces.size()]);
public Class<?>[] getInterfaces() {
return this.publishedInterfaces.toArray(new Class<?>[this.publishedInterfaces.size()]);
}
/**
@@ -68,8 +68,8 @@ public class IntroductionInfoSupport implements IntroductionInfo, Serializable {
* @param ifc the interface to check
* @return whether the interface is part of this introduction
*/
public boolean implementsInterface(Class ifc) {
for (Class pubIfc : this.publishedInterfaces) {
public boolean implementsInterface(Class<?> ifc) {
for (Class<?> pubIfc : this.publishedInterfaces) {
if (ifc.isInterface() && ifc.isAssignableFrom(pubIfc)) {
return true;
}
@@ -25,12 +25,11 @@ import org.springframework.aop.MethodMatcher;
import org.springframework.util.Assert;
/**
* Static utility methods for composing
* {@link org.springframework.aop.MethodMatcher MethodMatchers}.
* Static utility methods for composing {@link MethodMatcher MethodMatchers}.
*
* <p>A MethodMatcher may be evaluated statically (based on method
* and target class) or need further evaluation dynamically
* (based on arguments at the time of method invocation).
* <p>A MethodMatcher may be evaluated statically (based on method and target
* class) or need further evaluation dynamically (based on arguments at the
* time of method invocation).
*
* @author Rod Johnson
* @author Rob Harrop
@@ -88,7 +87,7 @@ public abstract class MethodMatchers {
* asking is the subject on one or more introductions; {@code false} otherwise
* @return whether or not this method matches statically
*/
public static boolean matches(MethodMatcher mm, Method method, Class targetClass, boolean hasIntroductions) {
public static boolean matches(MethodMatcher mm, Method method, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(mm, "MethodMatcher must not be null");
return ((mm instanceof IntroductionAwareMethodMatcher &&
((IntroductionAwareMethodMatcher) mm).matches(method, targetClass, hasIntroductions)) ||
@@ -113,21 +112,21 @@ public abstract class MethodMatchers {
this.mm2 = mm2;
}
public boolean matches(Method method, Class targetClass, boolean hasIntroductions) {
public boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions) {
return (matchesClass1(targetClass) && MethodMatchers.matches(this.mm1, method, targetClass, hasIntroductions)) ||
(matchesClass2(targetClass) && MethodMatchers.matches(this.mm2, method, targetClass, hasIntroductions));
}
public boolean matches(Method method, Class targetClass) {
public boolean matches(Method method, Class<?> targetClass) {
return (matchesClass1(targetClass) && this.mm1.matches(method, targetClass)) ||
(matchesClass2(targetClass) && this.mm2.matches(method, targetClass));
}
protected boolean matchesClass1(Class targetClass) {
protected boolean matchesClass1(Class<?> targetClass) {
return true;
}
protected boolean matchesClass2(Class targetClass) {
protected boolean matchesClass2(Class<?> targetClass) {
return true;
}
@@ -135,7 +134,7 @@ public abstract class MethodMatchers {
return this.mm1.isRuntime() || this.mm2.isRuntime();
}
public boolean matches(Method method, Class targetClass, Object[] args) {
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
return this.mm1.matches(method, targetClass, args) || this.mm2.matches(method, targetClass, args);
}
@@ -179,12 +178,12 @@ public abstract class MethodMatchers {
}
@Override
protected boolean matchesClass1(Class targetClass) {
protected boolean matchesClass1(Class<?> targetClass) {
return this.cf1.matches(targetClass);
}
@Override
protected boolean matchesClass2(Class targetClass) {
protected boolean matchesClass2(Class<?> targetClass) {
return this.cf2.matches(targetClass);
}
@@ -225,12 +224,12 @@ public abstract class MethodMatchers {
this.mm2 = mm2;
}
public boolean matches(Method method, Class targetClass, boolean hasIntroductions) {
public boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions) {
return MethodMatchers.matches(this.mm1, method, targetClass, hasIntroductions) &&
MethodMatchers.matches(this.mm2, method, targetClass, hasIntroductions);
}
public boolean matches(Method method, Class targetClass) {
public boolean matches(Method method, Class<?> targetClass) {
return this.mm1.matches(method, targetClass) && this.mm2.matches(method, targetClass);
}
@@ -238,7 +237,7 @@ public abstract class MethodMatchers {
return this.mm1.isRuntime() || this.mm2.isRuntime();
}
public boolean matches(Method method, Class targetClass, Object[] args) {
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
// Because a dynamic intersection may be composed of a static and dynamic part,
// we must avoid calling the 3-arg matches method on a dynamic matcher, as
// it will probably be an unsupported operation.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,7 +47,7 @@ public class NameMatchMethodPointcut extends StaticMethodMatcherPointcut impleme
* @see #setMappedNames
*/
public void setMappedName(String mappedName) {
setMappedNames(new String[] {mappedName});
setMappedNames(mappedName);
}
/**
@@ -55,7 +55,7 @@ public class NameMatchMethodPointcut extends StaticMethodMatcherPointcut impleme
* Matching will be the union of all these; if any match,
* the pointcut matches.
*/
public void setMappedNames(String[] mappedNames) {
public void setMappedNames(String... mappedNames) {
this.mappedNames = new LinkedList<String>();
if (mappedNames != null) {
this.mappedNames.addAll(Arrays.asList(mappedNames));
@@ -77,7 +77,8 @@ public class NameMatchMethodPointcut extends StaticMethodMatcherPointcut impleme
}
public boolean matches(Method method, Class targetClass) {
@Override
public boolean matches(Method method, Class<?> targetClass) {
for (String mappedName : this.mappedNames) {
if (mappedName.equals(method.getName()) || isMatch(method.getName(), mappedName)) {
return true;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -68,7 +68,7 @@ public class NameMatchMethodPointcutAdvisor extends AbstractGenericPointcutAdvis
* the pointcut matches.
* @see NameMatchMethodPointcut#setMappedNames
*/
public void setMappedNames(String[] mappedNames) {
public void setMappedNames(String... mappedNames) {
this.pointcut.setMappedNames(mappedNames);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -98,7 +98,7 @@ public class RegexpMethodPointcutAdvisor extends AbstractGenericPointcutAdvisor
* @see #setPatterns
*/
public void setPattern(String pattern) {
setPatterns(new String[] {pattern});
setPatterns(pattern);
}
/**
@@ -108,7 +108,7 @@ public class RegexpMethodPointcutAdvisor extends AbstractGenericPointcutAdvisor
* patterns matches, the pointcut matches.
* @see AbstractRegexpMethodPointcut#setPatterns
*/
public void setPatterns(String[] patterns) {
public void setPatterns(String... patterns) {
this.patterns = patterns;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -59,10 +59,32 @@ public class AnnotationClassFilter implements ClassFilter {
}
public boolean matches(Class clazz) {
public boolean matches(Class<?> clazz) {
return (this.checkInherited ?
(AnnotationUtils.findAnnotation(clazz, this.annotationType) != null) :
clazz.isAnnotationPresent(this.annotationType));
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof AnnotationClassFilter)) {
return false;
}
AnnotationClassFilter otherCf = (AnnotationClassFilter) other;
return (this.annotationType.equals(otherCf.annotationType) && this.checkInherited == otherCf.checkInherited);
}
@Override
public int hashCode() {
return this.annotationType.hashCode();
}
@Override
public String toString() {
return getClass().getName() + ": " + this.annotationType;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author 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,7 @@ import org.springframework.aop.ClassFilter;
import org.springframework.aop.MethodMatcher;
import org.springframework.aop.Pointcut;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
* Simple Pointcut that looks for a specific Java 5 annotation
@@ -98,6 +99,36 @@ public class AnnotationMatchingPointcut implements Pointcut {
return this.methodMatcher;
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof AnnotationMatchingPointcut)) {
return false;
}
AnnotationMatchingPointcut that = (AnnotationMatchingPointcut) other;
return ObjectUtils.nullSafeEquals(that.classFilter, this.classFilter) &&
ObjectUtils.nullSafeEquals(that.methodMatcher, this.methodMatcher);
}
@Override
public int hashCode() {
int code = 17;
if (this.classFilter != null) {
code = 37 * code + this.classFilter.hashCode();
}
if (this.methodMatcher != null) {
code = 37 * code + this.methodMatcher.hashCode();
}
return code;
}
@Override
public String toString() {
return "AnnotationMatchingPointcut: " + this.classFilter + ", " +this.methodMatcher;
}
/**
* Factory method for an AnnotationMatchingPointcut that matches
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author 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,4 +73,9 @@ public class AnnotationMethodMatcher extends StaticMethodMatcher {
return this.annotationType.hashCode();
}
@Override
public String toString() {
return getClass().getName() + ": " + this.annotationType;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,7 +24,6 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.aop.TargetSource;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
/**
@@ -48,8 +47,7 @@ import org.springframework.util.ObjectUtils;
* @see ThreadLocalTargetSource
* @see CommonsPoolTargetSource
*/
public abstract class AbstractBeanFactoryBasedTargetSource
implements TargetSource, BeanFactoryAware, Serializable {
public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSource, BeanFactoryAware, Serializable {
/** use serialVersionUID from Spring 1.2.7 for interoperability */
private static final long serialVersionUID = -4721607536018568393L;
@@ -97,7 +95,7 @@ public abstract class AbstractBeanFactoryBasedTargetSource
* <p>Default is to detect the type automatically, through a {@code getType}
* call on the BeanFactory (or even a full {@code getBean} call as fallback).
*/
public void setTargetClass(Class targetClass) {
public void setTargetClass(Class<?> targetClass) {
this.targetClass = targetClass;
}
@@ -107,7 +105,7 @@ public abstract class AbstractBeanFactoryBasedTargetSource
*/
public void setBeanFactory(BeanFactory beanFactory) {
if (this.targetBeanName == null) {
throw new IllegalStateException("Property'targetBeanName' is required");
throw new IllegalStateException("Property 'targetBeanName' is required");
}
this.beanFactory = beanFactory;
}
@@ -181,8 +179,7 @@ public abstract class AbstractBeanFactoryBasedTargetSource
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(ClassUtils.getShortName(getClass()));
StringBuilder sb = new StringBuilder(getClass().getSimpleName());
sb.append(" for target bean '").append(this.targetBeanName).append("'");
if (this.targetClass != null) {
sb.append(" of type [").append(this.targetClass.getName()).append("]");
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -50,6 +50,7 @@ import org.springframework.beans.factory.DisposableBean;
* @see #releaseTarget
* @see #destroy
*/
@SuppressWarnings("serial")
public abstract class AbstractPoolingTargetSource extends AbstractPrototypeBasedTargetSource
implements PoolingConfig, DisposableBean {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,6 +43,7 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory;
* @see ThreadLocalTargetSource
* @see CommonsPoolTargetSource
*/
@SuppressWarnings("serial")
public abstract class AbstractPrototypeBasedTargetSource extends AbstractBeanFactoryBasedTargetSource {
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,8 +24,8 @@ import org.springframework.beans.BeansException;
import org.springframework.core.Constants;
/**
* TargetSource implementation that holds objects in a configurable
* Jakarta Commons Pool.
* {@link org.springframework.aop.TargetSource} implementation that holds
* objects in a configurable Apache Commons Pool.
*
* <p>By default, an instance of {@code GenericObjectPool} is created.
* Subclasses may change the type of {@code ObjectPool} used by
@@ -38,10 +38,12 @@ import org.springframework.core.Constants;
* of configuration properties that are relevant to your chosen implementation.
*
* <p>The {@code testOnBorrow}, {@code testOnReturn} and {@code testWhileIdle}
* properties are explictly not mirrored because the implementation of
* properties are explicitly not mirrored because the implementation of
* {@code PoolableObjectFactory} used by this class does not implement
* meaningful validation. All exposed Commons Pool properties use the corresponding
* Commons Pool defaults: for example,
* meaningful validation. All exposed Commons Pool properties use the
* corresponding Commons Pool defaults.
*
* <p>Compatible with Apache Commons Pool 1.5.x and 1.6.
*
* @author Rod Johnson
* @author Rob Harrop
@@ -55,10 +57,8 @@ import org.springframework.core.Constants;
* @see #setTimeBetweenEvictionRunsMillis
* @see #setMinEvictableIdleTimeMillis
*/
public class CommonsPoolTargetSource extends AbstractPoolingTargetSource
implements PoolableObjectFactory {
private static final long serialVersionUID = 1L;
@SuppressWarnings("serial")
public class CommonsPoolTargetSource extends AbstractPoolingTargetSource implements PoolableObjectFactory {
private static final Constants constants = new Constants(GenericObjectPool.class);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author 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,9 +19,11 @@ package org.springframework.aop.target;
import org.springframework.beans.BeansException;
/**
* TargetSource that creates a new instance of the target bean for each
* request, destroying each instance on release (after each request).
* Obtains bean instances from its containing
* {@link org.springframework.aop.TargetSource} implementation that
* creates a new instance of the target bean for each request,
* destroying each instance on release (after each request).
*
* <p>Obtains bean instances from its containing
* {@link org.springframework.beans.factory.BeanFactory}.
*
* @author Rod Johnson
@@ -29,10 +31,9 @@ import org.springframework.beans.BeansException;
* @see #setBeanFactory
* @see #setTargetBeanName
*/
@SuppressWarnings("serial")
public class PrototypeTargetSource extends AbstractPrototypeBasedTargetSource {
private static final long serialVersionUID = 1L;
/**
* Obtain a new prototype instance for every call.
* @see #newPrototypeInstance()
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,9 +27,10 @@ import org.springframework.beans.factory.DisposableBean;
import org.springframework.core.NamedThreadLocal;
/**
* Alternative to an object pool. This TargetSource uses a threading model in which
* every thread has its own copy of the target. There's no contention for targets.
* Target object creation is kept to a minimum on the running server.
* Alternative to an object pool. This {@link org.springframework.aop.TargetSource}
* uses a threading model in which every thread has its own copy of the target.
* There's no contention for targets. Target object creation is kept to a minimum
* on the running server.
*
* <p>Application code is written as to a normal pool; callers can't assume they
* will be dealing with the same instance in invocations in different threads.
@@ -47,11 +48,10 @@ import org.springframework.core.NamedThreadLocal;
* @see ThreadLocalTargetSourceStats
* @see org.springframework.beans.factory.DisposableBean#destroy()
*/
@SuppressWarnings("serial")
public class ThreadLocalTargetSource extends AbstractPrototypeBasedTargetSource
implements ThreadLocalTargetSourceStats, DisposableBean {
private static final long serialVersionUID = 1L;
/**
* ThreadLocal holding the target associated with the current
* thread. Unlike most ThreadLocals, which are static, this variable
@@ -80,10 +80,8 @@ public class ThreadLocalTargetSource extends AbstractPrototypeBasedTargetSource
Object target = this.targetInThread.get();
if (target == null) {
if (logger.isDebugEnabled()) {
logger.debug("No target for prototype '" + getTargetBeanName() +
"' bound to thread: " +
"creating one and binding it to thread '" +
Thread.currentThread().getName() + "'");
logger.debug("No target for prototype '" + getTargetBeanName() + "' bound to thread: " +
"creating one and binding it to thread '" + Thread.currentThread().getName() + "'");
}
// Associate target with ThreadLocal.
target = newPrototypeInstance();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,26 +27,18 @@ import org.aspectj.lang.annotation.control.CodeGenerationHint;
* @since 2.5.2
*/
public abstract aspect AbstractDependencyInjectionAspect {
/**
* Select construction join points for objects to inject dependencies
*/
public abstract pointcut beanConstruction(Object bean);
private pointcut preConstructionCondition() :
leastSpecificSuperTypeConstruction() && preConstructionConfiguration();
private pointcut postConstructionCondition() :
mostSpecificSubTypeConstruction() && !preConstructionConfiguration();
/**
* Select deserialization join points for objects to inject dependencies
* Select least specific super type that is marked for DI
* (so that injection occurs only once with pre-construction injection).
*/
public abstract pointcut beanDeserialization(Object bean);
/**
* Select join points in a configurable bean
*/
public abstract pointcut inConfigurableBean();
/**
* Select join points in beans to be configured prior to construction?
* By default, use post-construction injection matching the default in the Configurable annotation.
*/
public pointcut preConstructionConfiguration() : if(false);
public abstract pointcut leastSpecificSuperTypeConstruction();
/**
* Select the most-specific initialization join point
@@ -54,31 +46,36 @@ public abstract aspect AbstractDependencyInjectionAspect {
*/
@CodeGenerationHint(ifNameSuffix="6f1")
public pointcut mostSpecificSubTypeConstruction() :
if(thisJoinPoint.getSignature().getDeclaringType() == thisJoinPoint.getThis().getClass());
if (thisJoinPoint.getSignature().getDeclaringType() == thisJoinPoint.getThis().getClass());
/**
* Select least specific super type that is marked for DI (so that injection occurs only once with pre-construction inejection
* Select join points in beans to be configured prior to construction?
* By default, use post-construction injection matching the default in the Configurable annotation.
*/
public abstract pointcut leastSpecificSuperTypeConstruction();
public pointcut preConstructionConfiguration() : if (false);
/**
* Configure the bean
* Select construction join points for objects to inject dependencies.
*/
public abstract void configureBean(Object bean);
public abstract pointcut beanConstruction(Object bean);
/**
* Select deserialization join points for objects to inject dependencies.
*/
public abstract pointcut beanDeserialization(Object bean);
private pointcut preConstructionCondition() :
leastSpecificSuperTypeConstruction() && preConstructionConfiguration();
/**
* Select join points in a configurable bean.
*/
public abstract pointcut inConfigurableBean();
private pointcut postConstructionCondition() :
mostSpecificSubTypeConstruction() && !preConstructionConfiguration();
/**
* Pre-construction configuration.
*/
@SuppressAjWarnings("adviceDidNotMatch")
before(Object bean) :
beanConstruction(bean) && preConstructionCondition() && inConfigurableBean() {
beanConstruction(bean) && preConstructionCondition() && inConfigurableBean() {
configureBean(bean);
}
@@ -87,7 +84,7 @@ public abstract aspect AbstractDependencyInjectionAspect {
*/
@SuppressAjWarnings("adviceDidNotMatch")
after(Object bean) returning :
beanConstruction(bean) && postConstructionCondition() && inConfigurableBean() {
beanConstruction(bean) && postConstructionCondition() && inConfigurableBean() {
configureBean(bean);
}
@@ -96,8 +93,14 @@ public abstract aspect AbstractDependencyInjectionAspect {
*/
@SuppressAjWarnings("adviceDidNotMatch")
after(Object bean) returning :
beanDeserialization(bean) && inConfigurableBean() {
beanDeserialization(bean) && inConfigurableBean() {
configureBean(bean);
}
/**
* Configure the given bean.
*/
public abstract void configureBean(Object bean);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,49 +20,48 @@ import java.io.ObjectStreamException;
import java.io.Serializable;
/**
* An aspect that injects dependency into any object whose type implements the {@link ConfigurableObject} interface.
* <p>
* This aspect supports injecting into domain objects when they are created for the first time as well as
* upon deserialization. Subaspects need to simply provide definition for the configureBean() method. This
* method may be implemented without relying on Spring container if so desired.
* </p>
* <p>
* There are two cases that needs to be handled:
* An aspect that injects dependency into any object whose type implements the
* {@link ConfigurableObject} interface.
*
* <p>This aspect supports injecting into domain objects when they are created
* for the first time as well as upon deserialization. Subaspects need to simply
* provide definition for the configureBean() method. This method may be
* implemented without relying on Spring container if so desired.
*
* <p>There are two cases that needs to be handled:
* <ol>
* <li>Normal object creation via the '{@code new}' operator: this is
* taken care of by advising {@code initialization()} join points.</li>
* <li>Object creation through deserialization: since no constructor is
* invoked during deserialization, the aspect needs to advise a method that a
* deserialization mechanism is going to invoke. Ideally, we should not
* require user classes to implement any specific method. This implies that
* we need to <i>introduce</i> the chosen method. We should also handle the cases
* where the chosen method is already implemented in classes (in which case,
* the user's implementation for that method should take precedence over the
* introduced implementation). There are a few choices for the chosen method:
* <ul>
* <li>readObject(ObjectOutputStream): Java requires that the method must be
* {@code private}</p>. Since aspects cannot introduce a private member,
* while preserving its name, this option is ruled out.</li>
* <li>readResolve(): Java doesn't pose any restriction on an access specifier.
* Problem solved! There is one (minor) limitation of this approach in
* that if a user class already has this method, that method must be
* {@code public}. However, this shouldn't be a big burden, since
* use cases that need classes to implement readResolve() (custom enums,
* for example) are unlikely to be marked as &#64;Configurable, and
* in any case asking to make that method {@code public} should not
* pose any undue burden.</li>
* </ul>
* The minor collaboration needed by user classes (i.e., that the
* implementation of {@code readResolve()}, if any, must be
* {@code public}) can be lifted as well if we were to use an
* experimental feature in AspectJ - the {@code hasmethod()} PCD.</li>
* <li>Normal object creation via the '{@code new}' operator: this is
* taken care of by advising {@code initialization()} join points.</li>
* <li>Object creation through deserialization: since no constructor is
* invoked during deserialization, the aspect needs to advise a method that a
* deserialization mechanism is going to invoke. Ideally, we should not
* require user classes to implement any specific method. This implies that
* we need to <i>introduce</i> the chosen method. We should also handle the cases
* where the chosen method is already implemented in classes (in which case,
* the user's implementation for that method should take precedence over the
* introduced implementation). There are a few choices for the chosen method:
* <ul>
* <li>readObject(ObjectOutputStream): Java requires that the method must be
* {@code private}</p>. Since aspects cannot introduce a private member,
* while preserving its name, this option is ruled out.</li>
* <li>readResolve(): Java doesn't pose any restriction on an access specifier.
* Problem solved! There is one (minor) limitation of this approach in
* that if a user class already has this method, that method must be
* {@code public}. However, this shouldn't be a big burden, since
* use cases that need classes to implement readResolve() (custom enums,
* for example) are unlikely to be marked as &#64;Configurable, and
* in any case asking to make that method {@code public} should not
* pose any undue burden.</li>
* </ul>
* The minor collaboration needed by user classes (i.e., that the implementation of
* {@code readResolve()}, if any, must be {@code public}) can be lifted as well if we
* were to use an experimental feature in AspectJ - the {@code hasmethod()} PCD.</li>
* </ol>
* <p>
* While having type implement the {@link ConfigurableObject} interface is certainly a valid choice, an alternative
* is to use a 'declare parents' statement another aspect (a subaspect of this aspect would be a logical choice)
* that declares the classes that need to be configured by supplying the {@link ConfigurableObject} interface.
* </p>
*
* <p>While having type implement the {@link ConfigurableObject} interface is certainly
* a valid choice, an alternative is to use a 'declare parents' statement another aspect
* (a subaspect of this aspect would be a logical choice) that declares the classes that
* need to be configured by supplying the {@link ConfigurableObject} interface.
*
* @author Ramnivas Laddad
* @since 2.5.2
@@ -72,35 +71,33 @@ public abstract aspect AbstractInterfaceDrivenDependencyInjectionAspect extends
* Select initialization join point as object construction
*/
public pointcut beanConstruction(Object bean) :
initialization(ConfigurableObject+.new(..)) && this(bean);
initialization(ConfigurableObject+.new(..)) && this(bean);
/**
* Select deserialization join point made available through ITDs for ConfigurableDeserializationSupport
*/
public pointcut beanDeserialization(Object bean) :
execution(Object ConfigurableDeserializationSupport+.readResolve()) &&
this(bean);
execution(Object ConfigurableDeserializationSupport+.readResolve()) && this(bean);
public pointcut leastSpecificSuperTypeConstruction() : initialization(ConfigurableObject.new(..));
// Implementation to support re-injecting dependencies once an object is deserialized
/**
* Declare any class implementing Serializable and ConfigurableObject as also implementing
* ConfigurableDeserializationSupport. This allows us to introduce the readResolve()
* ConfigurableDeserializationSupport. This allows us to introduce the {@code readResolve()}
* method and select it with the beanDeserialization() pointcut.
*
* <p>Here is an improved version that uses the hasmethod() pointcut and lifts
* even the minor requirement on user classes:
*
* <pre class="code">declare parents: ConfigurableObject+ Serializable+
* && !hasmethod(Object readResolve() throws ObjectStreamException)
* implements ConfigurableDeserializationSupport;
* <pre class="code">
* declare parents: ConfigurableObject+ Serializable+
* && !hasmethod(Object readResolve() throws ObjectStreamException)
* implements ConfigurableDeserializationSupport;
* </pre>
*/
declare parents:
ConfigurableObject+ && Serializable+ implements ConfigurableDeserializationSupport;
declare parents: ConfigurableObject+ && Serializable+ implements ConfigurableDeserializationSupport;
/**
* A marker interface to which the {@code readResolve()} is introduced.
@@ -111,7 +108,6 @@ public abstract aspect AbstractInterfaceDrivenDependencyInjectionAspect extends
/**
* Introduce the {@code readResolve()} method so that we can advise its
* execution to configure the object.
*
* <p>Note if a method with the same signature already exists in a
* {@code Serializable} class of ConfigurableObject type,
* that implementation will take precedence (a good thing, since we are
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author 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,7 @@ package org.springframework.beans.factory.aspectj;
import java.io.Serializable;
import org.aspectj.lang.annotation.control.CodeGenerationHint;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.DisposableBean;
@@ -44,48 +44,47 @@ import org.springframework.beans.factory.wiring.BeanConfigurerSupport;
* @see org.springframework.beans.factory.annotation.Configurable
* @see org.springframework.beans.factory.annotation.AnnotationBeanWiringInfoResolver
*/
public aspect AnnotationBeanConfigurerAspect
extends AbstractInterfaceDrivenDependencyInjectionAspect
public aspect AnnotationBeanConfigurerAspect extends AbstractInterfaceDrivenDependencyInjectionAspect
implements BeanFactoryAware, InitializingBean, DisposableBean {
private BeanConfigurerSupport beanConfigurerSupport = new BeanConfigurerSupport();
public void setBeanFactory(BeanFactory beanFactory) {
this.beanConfigurerSupport.setBeanFactory(beanFactory);
this.beanConfigurerSupport.setBeanWiringInfoResolver(new AnnotationBeanWiringInfoResolver());
}
public void afterPropertiesSet() throws Exception {
this.beanConfigurerSupport.afterPropertiesSet();
}
public void configureBean(Object bean) {
this.beanConfigurerSupport.configureBean(bean);
}
public void destroy() throws Exception {
this.beanConfigurerSupport.destroy();
}
public pointcut inConfigurableBean() : @this(Configurable);
public pointcut preConstructionConfiguration() : preConstructionConfigurationSupport(*);
declare parents: @Configurable * implements ConfigurableObject;
public void configureBean(Object bean) {
beanConfigurerSupport.configureBean(bean);
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
beanConfigurerSupport.setBeanFactory(beanFactory);
beanConfigurerSupport.setBeanWiringInfoResolver(new AnnotationBeanWiringInfoResolver());
}
public void afterPropertiesSet() throws Exception {
beanConfigurerSupport.afterPropertiesSet();
}
public void destroy() throws Exception {
beanConfigurerSupport.destroy();
}
/*
* An intermediary to match preConstructionConfiguration signature (that doesn't expose the annotation object)
*/
@CodeGenerationHint(ifNameSuffix="bb0")
private pointcut preConstructionConfigurationSupport(Configurable c) : @this(c) && if(c.preConstruction());
private pointcut preConstructionConfigurationSupport(Configurable c) : @this(c) && if (c.preConstruction());
declare parents: @Configurable * implements ConfigurableObject;
/*
* This declaration shouldn't be needed,
* except for an AspectJ bug (https://bugs.eclipse.org/bugs/show_bug.cgi?id=214559)
*/
declare parents: @Configurable Serializable+
implements ConfigurableDeserializationSupport;
declare parents: @Configurable Serializable+ implements ConfigurableDeserializationSupport;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@ import org.springframework.context.annotation.Role;
@Configuration
public class AspectJCachingConfiguration extends AbstractCachingConfiguration {
@Bean(name=AnnotationConfigUtils.CACHE_ASPECT_BEAN_NAME)
@Bean(name = AnnotationConfigUtils.CACHE_ASPECT_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public AnnotationCacheAspect cacheAspect() {
AnnotationCacheAspect cacheAspect = AnnotationCacheAspect.aspectOf();
@@ -47,4 +47,5 @@ public class AspectJCachingConfiguration extends AbstractCachingConfiguration {
}
return cacheAspect;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,9 +28,9 @@ import org.springframework.context.annotation.Role;
* annotated with @{@link org.springframework.beans.factory.annotation.Configurable
* Configurable}.
*
* <p>This configuration class is automatically imported when using the @{@link
* EnableSpringConfigured} annotation. See {@code @EnableSpringConfigured} Javadoc for
* complete usage details.
* <p>This configuration class is automatically imported when using the
* @{@link EnableSpringConfigured} annotation. See {@code @EnableSpringConfigured}'s
* javadoc for complete usage details.
*
* @author Chris Beams
* @since 3.1
@@ -42,9 +42,10 @@ public class SpringConfiguredConfiguration {
public static final String BEAN_CONFIGURER_ASPECT_BEAN_NAME =
"org.springframework.context.config.internalBeanConfigurerAspect";
@Bean(name=BEAN_CONFIGURER_ASPECT_BEAN_NAME)
@Bean(name = BEAN_CONFIGURER_ASPECT_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public AnnotationBeanConfigurerAspect beanConfigurerAspect() {
return AnnotationBeanConfigurerAspect.aspectOf();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author 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,16 +18,22 @@ package org.springframework.mock.staticmock;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import org.springframework.util.ObjectUtils;
/**
* Abstract aspect to enable mocking of methods picked out by a pointcut.
* Sub-aspects must define the mockStaticsTestMethod() pointcut to
* indicate call stacks when mocking should be triggered, and the
* methodToMock() pointcut to pick out a method invocations to mock.
*
* <p>Sub-aspects must define:
* <ul>
* <li>the {@link #mockStaticsTestMethod()} pointcut to indicate call stacks
* when mocking should be triggered
* <li>the {@link #methodToMock()} pointcut to pick out method invocations to mock
* </ul>
*
* @author Rod Johnson
* @author Ramnivas Laddad
* @author Sam Brannen
*/
public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMethod()) {
@@ -35,24 +41,34 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth
protected abstract pointcut methodToMock();
private boolean recording = true;
static enum CallResponse { nothing, return_, throw_ };
// Represents a list of expected calls to static entity methods
static enum CallResponse {
nothing, return_, throw_
};
/**
* Represents a list of expected calls to methods.
*/
// Public to allow inserted code to access: is this normal??
public class Expectations {
// Represents an expected call to a static entity method
/**
* Represents an expected call to a method.
*/
private class Call {
private final String signature;
private final Object[] args;
private Object responseObject; // return value or throwable
private CallResponse responseType = CallResponse.nothing;
public Call(String name, Object[] args) {
this.signature = name;
public Call(String signature, Object[] args) {
this.signature = signature;
this.args = args;
}
@@ -77,7 +93,7 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth
public Object throwException(String lastSig, Object[] args) {
checkSignature(lastSig, args);
throw (RuntimeException)responseObject;
throw (RuntimeException) responseObject;
}
private void checkSignature(String lastSig, Object[] args) {
@@ -88,16 +104,29 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth
throw new IllegalArgumentException("Arguments don't match");
}
}
@Override
public String toString() {
return String.format("Call with signature [%s] and arguments %s", this.signature,
ObjectUtils.nullSafeToString(args));
}
}
private List<Call> calls = new LinkedList<Call>();
// Calls already verified
/**
* The list of recorded calls.
*/
private final LinkedList<Call> calls = new LinkedList<Call>();
/**
* The number of calls already verified.
*/
private int verified;
public void verify() {
if (verified != calls.size()) {
throw new IllegalStateException("Expected " + calls.size() + " calls, received " + verified);
throw new IllegalStateException("Expected " + calls.size() + " calls, but received " + verified);
}
}
@@ -105,31 +134,32 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth
* Validate the call and provide the expected return value.
*/
public Object respond(String lastSig, Object[] args) {
Call call = nextCall();
CallResponse responseType = call.responseType;
if (responseType == CallResponse.return_) {
return call.returnValue(lastSig, args);
Call c = nextCall();
switch (c.responseType) {
case return_: {
return c.returnValue(lastSig, args);
}
case throw_: {
return c.throwException(lastSig, args);
}
default: {
throw new IllegalStateException("Behavior of " + c + " not specified");
}
}
else if (responseType == CallResponse.throw_) {
return call.throwException(lastSig, args);
}
else if (responseType == CallResponse.nothing) {
// do nothing
}
throw new IllegalStateException("Behavior of " + call + " not specified");
}
private Call nextCall() {
verified++;
if (verified > calls.size()) {
throw new IllegalStateException("Expected " + calls.size() + " calls, received " + verified);
throw new IllegalStateException("Expected " + calls.size() + " calls, but received " + verified);
}
return calls.get(verified);
// The 'verified' count is 1-based; whereas, 'calls' is 0-based.
return calls.get(verified - 1);
}
public void expectCall(String lastSig, Object lastArgs[]) {
Call call = new Call(lastSig, lastArgs);
calls.add(call);
public void expectCall(String lastSig, Object[] lastArgs) {
calls.add(new Call(lastSig, lastArgs));
}
public boolean hasCalls() {
@@ -137,29 +167,31 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth
}
public void expectReturn(Object retVal) {
Call call = calls.get(calls.size() - 1);
if (call.hasResponseSpecified()) {
throw new IllegalStateException("No static method invoked before setting return value");
Call c = calls.getLast();
if (c.hasResponseSpecified()) {
throw new IllegalStateException("No method invoked before setting return value");
}
call.setReturnVal(retVal);
c.setReturnVal(retVal);
}
public void expectThrow(Throwable throwable) {
Call call = calls.get(calls.size() - 1);
if (call.hasResponseSpecified()) {
throw new IllegalStateException("No static method invoked before setting throwable");
Call c = calls.getLast();
if (c.hasResponseSpecified()) {
throw new IllegalStateException("No method invoked before setting throwable");
}
call.setThrow(throwable);
c.setThrow(throwable);
}
}
private Expectations expectations = new Expectations();
private final Expectations expectations = new Expectations();
after() returning : mockStaticsTestMethod() {
if (recording && (expectations.hasCalls())) {
throw new IllegalStateException(
"Calls recorded, yet playback state never reached: Create expectations then call "
+ this.getClass().getSimpleName() + ".playback()");
"Calls recorded, yet playback state never reached: Create expectations then call "
+ this.getClass().getSimpleName() + ".playback()");
}
expectations.verify();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author 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,50 +17,69 @@
package org.springframework.mock.staticmock;
/**
* Annotation-based aspect to use in test build to enable mocking static methods
* on JPA-annotated {@code @Entity} classes, as used by Roo for finders.
* Annotation-based aspect to use in test builds to enable mocking of static methods
* on JPA-annotated {@code @Entity} classes, as used by Spring Roo for so-called
* <em>finder methods</em>.
*
* <p>Mocking will occur in the call stack of any method in a class (typically a test class)
* that is annotated with the @MockStaticEntityMethods annotation.
* <p>Mocking will occur within the call stack of any method in a class (typically a
* test class) that is annotated with {@code @MockStaticEntityMethods}.
*
* <p>Also provides static methods to simplify the programming model for
* entering playback mode and setting expected return values.
* <p>This aspect also provides static methods to simplify the programming model for
* setting expectations and entering playback mode.
*
* <p>Usage:
* <ol>
* <li>Annotate a test class with @MockStaticEntityMethods.
* <li>In each test method, AnnotationDrivenStaticEntityMockingControl will begin in recording mode.
* Invoke static methods on Entity classes, with each recording-mode invocation
* being followed by an invocation to the static expectReturn() or expectThrow()
* method on AnnotationDrivenStaticEntityMockingControl.
* <li>Invoke the static AnnotationDrivenStaticEntityMockingControl() method.
* <li>Call the code you wish to test that uses the static methods. Verification will
* occur automatically.
* <li>Annotate a test class with {@code @MockStaticEntityMethods}.
* <li>In each test method, {@code AnnotationDrivenStaticEntityMockingControl}
* will begin in <em>recording</em> mode.
* <li>Invoke static methods on JPA-annotated {@code @Entity} classes, with each
* recording-mode invocation being followed by an invocation of either the static
* {@link #expectReturn(Object)} method or the static {@link #expectThrow(Throwable)}
* method on {@code AnnotationDrivenStaticEntityMockingControl}.
* <li>Invoke the static {@link #playback()} method.
* <li>Call the code you wish to test that uses the static methods.
* <li>Verification will occur automatically.
* </ol>
*
* @author Rod Johnson
* @author Ramnivas Laddad
* @author Sam Brannen
* @see MockStaticEntityMethods
*/
public aspect AnnotationDrivenStaticEntityMockingControl extends AbstractMethodMockingControl {
/**
* Stop recording mock calls and enter playback state
* Expect the supplied {@link Object} to be returned by the previous static
* method invocation.
* @see #playback()
*/
public static void playback() {
AnnotationDrivenStaticEntityMockingControl.aspectOf().playbackInternal();
}
public static void expectReturn(Object retVal) {
AnnotationDrivenStaticEntityMockingControl.aspectOf().expectReturnInternal(retVal);
}
/**
* Expect the supplied {@link Throwable} to be thrown by the previous static
* method invocation.
* @see #playback()
*/
public static void expectThrow(Throwable throwable) {
AnnotationDrivenStaticEntityMockingControl.aspectOf().expectThrowInternal(throwable);
}
// Only matches directly annotated @Test methods, to allow methods in
// @MockStatics classes to invoke each other without resetting the mocking environment
/**
* Stop recording mock expectations and enter <em>playback</em> mode.
* @see #expectReturn(Object)
* @see #expectThrow(Throwable)
*/
public static void playback() {
AnnotationDrivenStaticEntityMockingControl.aspectOf().playbackInternal();
}
// Apparently, the following pointcut was originally defined to only match
// methods directly annotated with @Test (in order to allow methods in
// @MockStaticEntityMethods classes to invoke each other without resetting
// the mocking environment); however, this is no longer the case. The current
// pointcut applies to all public methods in @MockStaticEntityMethods classes.
protected pointcut mockStaticsTestMethod() : execution(public * (@MockStaticEntityMethods *).*(..));
protected pointcut methodToMock() : execution(public static * (@javax.persistence.Entity *).*(..));
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author 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,11 +22,13 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to indicate a test class for whose @Test methods
* static methods on Entity classes should be mocked. See
* {@code AbstractMethodMockingControl}.
* Annotation to indicate a test class for whose {@code @Test} methods
* static methods on JPA-annotated {@code @Entity} classes should be mocked.
*
* <p>See {@link AnnotationDrivenStaticEntityMockingControl} for details.
*
* @author Rod Johnson
* @author Sam Brannen
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,12 +32,12 @@ import org.springframework.scheduling.annotation.EnableAsync;
* @since 3.1
* @see EnableAsync
* @see org.springframework.scheduling.annotation.AsyncConfigurationSelector
* @see org.springframework.scheduling.annotation.ProxyAsyncConfiguration
*/
@Configuration
public class AspectJAsyncConfiguration extends AbstractAsyncConfiguration {
@Override
@Bean(name=AnnotationConfigUtils.ASYNC_EXECUTION_ASPECT_BEAN_NAME)
@Bean(name = AnnotationConfigUtils.ASYNC_EXECUTION_ASPECT_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public AnnotationAsyncExecutionAspect asyncAdvisor() {
AnnotationAsyncExecutionAspect asyncAspect = AnnotationAsyncExecutionAspect.aspectOf();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,7 +37,7 @@ import org.springframework.transaction.config.TransactionManagementConfigUtils;
@Configuration
public class AspectJTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
@Bean(name=TransactionManagementConfigUtils.TRANSACTION_ASPECT_BEAN_NAME)
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ASPECT_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public AnnotationTransactionAspect transactionAspect() {
AnnotationTransactionAspect txAspect = AnnotationTransactionAspect.aspectOf();
@@ -46,4 +46,5 @@ public class AspectJTransactionManagementConfiguration extends AbstractTransacti
}
return txAspect;
}
}
@@ -1,148 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.mock.staticmock;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl.expectReturn;
import static org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl.expectThrow;
import static org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl.playback;
import javax.persistence.PersistenceException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/**
* Test for static entity mocking framework.
* @author Rod Johnson
* @author Ramnivas Laddad
*
*/
@MockStaticEntityMethods
@RunWith(JUnit4.class)
public class AnnotationDrivenStaticEntityMockingControlTest {
@Test
public void testNoArgIntReturn() {
int expectedCount = 13;
Person.countPeople();
expectReturn(expectedCount);
playback();
assertEquals(expectedCount, Person.countPeople());
}
@Test(expected=PersistenceException.class)
public void testNoArgThrows() {
Person.countPeople();
expectThrow(new PersistenceException());
playback();
Person.countPeople();
}
@Test
public void testArgMethodMatches() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
expectReturn(found);
playback();
assertEquals(found, Person.findPerson(id));
}
@Test
public void testLongSeriesOfCalls() {
long id1 = 13;
long id2 = 24;
Person found1 = new Person();
Person.findPerson(id1);
expectReturn(found1);
Person found2 = new Person();
Person.findPerson(id2);
expectReturn(found2);
Person.findPerson(id1);
expectReturn(found1);
Person.countPeople();
expectReturn(0);
playback();
assertEquals(found1, Person.findPerson(id1));
assertEquals(found2, Person.findPerson(id2));
assertEquals(found1, Person.findPerson(id1));
assertEquals(0, Person.countPeople());
}
// Note delegation is used when tests are invalid and should fail, as otherwise
// the failure will occur on the verify() method in the aspect after
// this method returns, failing the test case
@Test
public void testArgMethodNoMatchExpectReturn() {
try {
new Delegate().testArgMethodNoMatchExpectReturn();
fail();
} catch (IllegalArgumentException expected) {
}
}
@Test(expected=IllegalArgumentException.class)
public void testArgMethodNoMatchExpectThrow() {
new Delegate().testArgMethodNoMatchExpectThrow();
}
private void called(Person found, long id) {
assertEquals(found, Person.findPerson(id));
}
@Test
public void testReentrant() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
expectReturn(found);
playback();
called(found, id);
}
@Test(expected=IllegalStateException.class)
public void testRejectUnexpectedCall() {
new Delegate().rejectUnexpectedCall();
}
@Test(expected=IllegalStateException.class)
public void testFailTooFewCalls() {
new Delegate().failTooFewCalls();
}
@Test
public void testEmpty() {
// Test that verification check doesn't blow up if no replay() call happened
}
@Test(expected=IllegalStateException.class)
public void testDoesntEverReplay() {
new Delegate().doesntEverReplay();
}
@Test(expected=IllegalStateException.class)
public void testDoesntEverSetReturn() {
new Delegate().doesntEverSetReturn();
}
}
@@ -0,0 +1,170 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.mock.staticmock;
import java.rmi.RemoteException;
import javax.persistence.PersistenceException;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl.*;
/**
* Tests for Spring's static entity mocking framework (i.e., @{@link MockStaticEntityMethods}
* and {@link AnnotationDrivenStaticEntityMockingControl}).
*
* @author Rod Johnson
* @author Ramnivas Laddad
* @author Sam Brannen
*/
@MockStaticEntityMethods
public class AnnotationDrivenStaticEntityMockingControlTests {
@Test
public void noArgumentMethodInvocationReturnsInt() {
int expectedCount = 13;
Person.countPeople();
expectReturn(expectedCount);
playback();
assertEquals(expectedCount, Person.countPeople());
}
@Test(expected = PersistenceException.class)
public void noArgumentMethodInvocationThrowsException() {
Person.countPeople();
expectThrow(new PersistenceException());
playback();
Person.countPeople();
}
@Test
public void methodArgumentsMatch() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
expectReturn(found);
playback();
assertEquals(found, Person.findPerson(id));
}
@Test
public void longSeriesOfCalls() {
long id1 = 13;
long id2 = 24;
Person found1 = new Person();
Person.findPerson(id1);
expectReturn(found1);
Person found2 = new Person();
Person.findPerson(id2);
expectReturn(found2);
Person.findPerson(id1);
expectReturn(found1);
Person.countPeople();
expectReturn(0);
playback();
assertEquals(found1, Person.findPerson(id1));
assertEquals(found2, Person.findPerson(id2));
assertEquals(found1, Person.findPerson(id1));
assertEquals(0, Person.countPeople());
}
@Test(expected = IllegalArgumentException.class)
public void methodArgumentsDoNotMatchAndReturnsObject() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
AnnotationDrivenStaticEntityMockingControl.expectReturn(found);
AnnotationDrivenStaticEntityMockingControl.playback();
assertEquals(found, Person.findPerson(id + 1));
}
@Test(expected = IllegalArgumentException.class)
public void methodArgumentsDoNotMatchAndThrowsException() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
AnnotationDrivenStaticEntityMockingControl.expectThrow(new PersistenceException());
AnnotationDrivenStaticEntityMockingControl.playback();
assertEquals(found, Person.findPerson(id + 1));
}
@Test
public void reentrant() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
expectReturn(found);
playback();
called(found, id);
}
private void called(Person found, long id) {
assertEquals(found, Person.findPerson(id));
}
@Test(expected = IllegalStateException.class)
public void rejectUnexpectedCall() {
AnnotationDrivenStaticEntityMockingControl.playback();
Person.countPeople();
}
@Test(expected = IllegalStateException.class)
public void tooFewCalls() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
AnnotationDrivenStaticEntityMockingControl.expectReturn(found);
Person.countPeople();
AnnotationDrivenStaticEntityMockingControl.expectReturn(25);
AnnotationDrivenStaticEntityMockingControl.playback();
assertEquals(found, Person.findPerson(id));
}
@Test
public void empty() {
// Test that verification check doesn't blow up if no replay() call happened.
}
@Test(expected = IllegalStateException.class)
public void doesNotEnterPlaybackMode() {
Person.countPeople();
}
@Test(expected = IllegalStateException.class)
public void doesNotSetExpectedReturnValue() {
Person.countPeople();
AnnotationDrivenStaticEntityMockingControl.playback();
}
/**
* Note: this test method currently does NOT actually verify that the mock
* verification fails.
*/
// TODO Determine if it's possible for a mock verification failure to fail a test in
// JUnit 4+ if the test method itself throws an expected exception.
@Test(expected = RemoteException.class)
public void verificationFailsEvenWhenTestFailsInExpectedManner() throws Exception {
Person.countPeople();
AnnotationDrivenStaticEntityMockingControl.playback();
// No calls in order to allow verification failure
throw new RemoteException();
}
}
@@ -1,92 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.mock.staticmock;
import static org.junit.Assert.assertEquals;
import java.rmi.RemoteException;
import javax.persistence.PersistenceException;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl;
import org.springframework.mock.staticmock.MockStaticEntityMethods;
//Used because verification failures occur after method returns,
//so we can't test for them in the test case itself
@MockStaticEntityMethods
@Ignore // This isn't meant for direct testing; rather it is driven from AnnotationDrivenStaticEntityMockingControl
public class Delegate {
@Test
public void testArgMethodNoMatchExpectReturn() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
AnnotationDrivenStaticEntityMockingControl.expectReturn(found);
AnnotationDrivenStaticEntityMockingControl.playback();
assertEquals(found, Person.findPerson(id + 1));
}
@Test
public void testArgMethodNoMatchExpectThrow() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
AnnotationDrivenStaticEntityMockingControl.expectThrow(new PersistenceException());
AnnotationDrivenStaticEntityMockingControl.playback();
assertEquals(found, Person.findPerson(id + 1));
}
@Test
public void failTooFewCalls() {
long id = 13;
Person found = new Person();
Person.findPerson(id);
AnnotationDrivenStaticEntityMockingControl.expectReturn(found);
Person.countPeople();
AnnotationDrivenStaticEntityMockingControl.expectReturn(25);
AnnotationDrivenStaticEntityMockingControl.playback();
assertEquals(found, Person.findPerson(id));
}
@Test
public void doesntEverReplay() {
Person.countPeople();
}
@Test
public void doesntEverSetReturn() {
Person.countPeople();
AnnotationDrivenStaticEntityMockingControl.playback();
}
@Test
public void rejectUnexpectedCall() {
AnnotationDrivenStaticEntityMockingControl.playback();
Person.countPeople();
}
@Test(expected=RemoteException.class)
public void testVerificationFailsEvenWhenTestFailsInExpectedManner() throws RemoteException {
Person.countPeople();
AnnotationDrivenStaticEntityMockingControl.playback();
// No calls to allow verification failure
throw new RemoteException();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,33 +20,36 @@ import java.beans.BeanInfo;
import java.beans.IntrospectionException;
/**
* Strategy for creating {@link BeanInfo} instances.
* Strategy interface for creating {@link BeanInfo} instances for Spring beans.
* Can be used to plug in custom bean property resolution strategies (e.g. for other
* languages on the JVM) or more efficient {@link BeanInfo} retrieval algorithms.
*
* <p>BeanInfoFactories are are instantiated by the {@link CachedIntrospectionResults},
* by using the {@link org.springframework.core.io.support.SpringFactoriesLoader} utility
* class.
* by using the {@link org.springframework.core.io.support.SpringFactoriesLoader}
* utility class.
*
* When a {@link BeanInfo} is to be created, the {@code CachedIntrospectionResults}
* will iterate through the discovered factories, calling {@link
* #getBeanInfo(Class)} on each one. If {@code null} is returned, the next factory will
* be queried. If none of the factories support the class, an standard {@link BeanInfo}
* is created as a default.
* will iterate through the discovered factories, calling {@link #getBeanInfo(Class)}
* on each one. If {@code null} is returned, the next factory will be queried.
* If none of the factories support the class, a standard {@link BeanInfo} will be
* created as a default.
*
* <p>Note that the {@link org.springframework.core.io.support.SpringFactoriesLoader}
* sorts the {@code BeanInfoFactory} instances by
* {@link org.springframework.core.annotation.Order @Order}, so that ones with
* a higher precedence come first.
* {@link org.springframework.core.annotation.Order @Order}, so that ones with a
* higher precedence come first.
*
* @author Arjen Poutsma
* @since 3.2
* @see CachedIntrospectionResults
* @see org.springframework.core.io.support.SpringFactoriesLoader
*/
public interface BeanInfoFactory {
/**
* Returns the bean info for the given class, if supported.
*
* Return the bean info for the given class, if supported.
* @param beanClass the bean class
* @return the bean info, or {@code null} if not the given class is not supported
* @return the BeanInfo, or {@code null} if the given class is not supported
* @throws IntrospectionException in case of exceptions
*/
BeanInfo getBeanInfo(Class<?> beanClass) throws IntrospectionException;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -379,13 +379,28 @@ public abstract class BeanUtils {
* Find a JavaBeans {@code PropertyDescriptor} for the given method,
* with the method either being the read method or the write method for
* that bean property.
* @param method the method to find a corresponding PropertyDescriptor for
* @param method the method to find a corresponding PropertyDescriptor for,
* introspecting its declaring class
* @return the corresponding PropertyDescriptor, or {@code null} if none
* @throws BeansException if PropertyDescriptor lookup fails
*/
public static PropertyDescriptor findPropertyForMethod(Method method) throws BeansException {
return findPropertyForMethod(method, method.getDeclaringClass());
}
/**
* Find a JavaBeans {@code PropertyDescriptor} for the given method,
* with the method either being the read method or the write method for
* that bean property.
* @param method the method to find a corresponding PropertyDescriptor for
* @param clazz the (most specific) class to introspect for descriptors
* @return the corresponding PropertyDescriptor, or {@code null} if none
* @throws BeansException if PropertyDescriptor lookup fails
* @since 3.2.13
*/
public static PropertyDescriptor findPropertyForMethod(Method method, Class<?> clazz) throws BeansException {
Assert.notNull(method, "Method must not be null");
PropertyDescriptor[] pds = getPropertyDescriptors(method.getDeclaringClass());
PropertyDescriptor[] pds = getPropertyDescriptors(clazz);
for (PropertyDescriptor pd : pds) {
if (method.equals(pd.getReadMethod()) || method.equals(pd.getWriteMethod())) {
return pd;
@@ -591,16 +606,16 @@ public abstract class BeanUtils {
actualEditable = editable;
}
PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
List<String> ignoreList = (ignoreProperties != null) ? Arrays.asList(ignoreProperties) : null;
List<String> ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null);
for (PropertyDescriptor targetPd : targetPds) {
Method writeMethod = targetPd.getWriteMethod();
if (writeMethod != null && (ignoreProperties == null || (!ignoreList.contains(targetPd.getName())))) {
if (writeMethod != null && (ignoreList == null || !ignoreList.contains(targetPd.getName()))) {
PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
if (sourcePd != null) {
Method readMethod = sourcePd.getReadMethod();
if (readMethod != null &&
writeMethod.getParameterTypes()[0].isAssignableFrom(readMethod.getReturnType())) {
ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
try {
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
readMethod.setAccessible(true);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -59,7 +59,7 @@ public interface BeanWrapper extends ConfigurablePropertyAccessor {
* @return the type of the wrapped bean instance,
* or {@code null} if no wrapped object has been set
*/
Class getWrappedClass();
Class<?> getWrappedClass();
/**
* Obtain the PropertyDescriptors for the wrapped object
@@ -79,11 +79,13 @@ public interface BeanWrapper extends ConfigurablePropertyAccessor {
PropertyDescriptor getPropertyDescriptor(String propertyName) throws InvalidPropertyException;
/**
* Set whether this BeanWrapper should attempt to "auto-grow" a nested path that contains a null value.
* <p>If "true", a null path location will be populated with a default object value and traversed
* instead of resulting in a {@link NullValueInNestedPathException}. Turning this flag on also
* enables auto-growth of collection elements when accessing an out-of-bounds index.
* <p>Default is "false" on a plain BeanWrapper.
* Set whether this BeanWrapper should attempt to "auto-grow" a
* nested path that contains a {@code null} value.
* <p>If {@code true}, a {@code null} path location will be populated
* with a default object value and traversed instead of resulting in a
* {@link NullValueInNestedPathException}. Turning this flag on also enables
* auto-growth of collection elements when accessing an out-of-bounds index.
* <p>Default is {@code false} on a plain BeanWrapper.
*/
void setAutoGrowNestedPaths(boolean autoGrowNestedPaths);
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -223,7 +223,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
return this.object;
}
public final Class getWrappedClass() {
public final Class<?> getWrappedClass() {
return (this.object != null ? this.object.getClass() : null);
}
@@ -246,7 +246,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
* Return the class of the root object at the top of the path of this BeanWrapper.
* @see #getNestedPath
*/
public final Class getRootClass() {
public final Class<?> getRootClass() {
return (this.rootObject != null ? this.rootObject.getClass() : null);
}
@@ -304,7 +304,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
* Needs to be called when the target object changes.
* @param clazz the class to introspect
*/
protected void setIntrospectionClass(Class clazz) {
protected void setIntrospectionClass(Class<?> clazz) {
if (this.cachedIntrospectionResults != null &&
!clazz.equals(this.cachedIntrospectionResults.getBeanClass())) {
this.cachedIntrospectionResults = null;
@@ -352,7 +352,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
}
@Override
public Class getPropertyType(String propertyName) throws BeansException {
public Class<?> getPropertyType(String propertyName) throws BeansException {
try {
PropertyDescriptor pd = getPropertyDescriptorInternal(propertyName);
if (pd != null) {
@@ -366,7 +366,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
}
// Check to see if there is a custom editor,
// which might give an indication on the desired target type.
Class editorType = guessPropertyTypeFromEditors(propertyName);
Class<?> editorType = guessPropertyTypeFromEditors(propertyName);
if (editorType != null) {
return editorType;
}
@@ -389,7 +389,8 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
if (pd.getReadMethod() != null || pd.getWriteMethod() != null) {
return TypeDescriptor.nested(property(pd), tokens.keys.length);
}
} else {
}
else {
if (pd.getReadMethod() != null || pd.getWriteMethod() != null) {
return new TypeDescriptor(property(pd));
}
@@ -485,13 +486,13 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"No property '" + propertyName + "' found");
}
return convertForProperty(propertyName, null, value, pd);
return convertForProperty(propertyName, null, value, new TypeDescriptor(property(pd)));
}
private Object convertForProperty(String propertyName, Object oldValue, Object newValue, PropertyDescriptor pd)
private Object convertForProperty(String propertyName, Object oldValue, Object newValue, TypeDescriptor td)
throws TypeMismatchException {
return convertIfNecessary(propertyName, oldValue, newValue, pd.getPropertyType(), new TypeDescriptor(property(pd)));
return convertIfNecessary(propertyName, oldValue, newValue, td.getType(), td);
}
private Property property(PropertyDescriptor pd) {
@@ -699,7 +700,8 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
return nestedBw.getPropertyValue(tokens);
}
private Object getPropertyValue(PropertyTokenHolder tokens) throws BeansException {
@SuppressWarnings("unchecked")
private Object getPropertyValue(PropertyTokenHolder tokens) throws BeansException {
String propertyName = tokens.canonicalName;
String actualName = tokens.actualName;
PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);
@@ -766,20 +768,20 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
}
else if (value instanceof List) {
int index = Integer.parseInt(key);
List list = (List) value;
List<Object> list = (List<Object>) value;
growCollectionIfNecessary(list, index, indexedPropertyName, pd, i + 1);
value = list.get(index);
}
else if (value instanceof Set) {
// Apply index to Iterator in case of a Set.
Set set = (Set) value;
Set<Object> set = (Set<Object>) value;
int index = Integer.parseInt(key);
if (index < 0 || index >= set.size()) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Cannot get element with index " + index + " from Set of size " +
set.size() + ", accessed using property path '" + propertyName + "'");
}
Iterator it = set.iterator();
Iterator<Object> it = set.iterator();
for (int j = 0; it.hasNext(); j++) {
Object elem = it.next();
if (j == index) {
@@ -789,11 +791,12 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
}
}
else if (value instanceof Map) {
Map map = (Map) value;
Map<Object, Object> map = (Map<Object, Object>) value;
Class<?> mapKeyType = GenericCollectionTypeResolver.getMapKeyReturnType(pd.getReadMethod(), i + 1);
// IMPORTANT: Do not pass full property name in here - property editors
// must not kick in for map keys but rather only for map values.
TypeDescriptor typeDescriptor = mapKeyType != null ? TypeDescriptor.valueOf(mapKeyType) : TypeDescriptor.valueOf(Object.class);
TypeDescriptor typeDescriptor = (mapKeyType != null ?
TypeDescriptor.valueOf(mapKeyType) : TypeDescriptor.valueOf(Object.class));
Object convertedMapKey = convertIfNecessary(null, null, key, mapKeyType, typeDescriptor);
value = map.get(convertedMapKey);
}
@@ -850,16 +853,15 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
}
}
@SuppressWarnings("unchecked")
private void growCollectionIfNecessary(
Collection collection, int index, String name, PropertyDescriptor pd, int nestingLevel) {
private void growCollectionIfNecessary(Collection<Object> collection, int index, String name,
PropertyDescriptor pd, int nestingLevel) {
if (!this.autoGrowNestedPaths) {
return;
}
int size = collection.size();
if (index >= size && index < this.autoGrowCollectionLimit) {
Class elementType = GenericCollectionTypeResolver.getCollectionReturnType(pd.getReadMethod(), nestingLevel);
Class<?> elementType = GenericCollectionTypeResolver.getCollectionReturnType(pd.getReadMethod(), nestingLevel);
if (elementType != null) {
for (int i = collection.size(); i < index + 1; i++) {
collection.add(newValue(elementType, name));
@@ -945,7 +947,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
}
if (propValue.getClass().isArray()) {
PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);
Class requiredType = propValue.getClass().getComponentType();
Class<?> requiredType = propValue.getClass().getComponentType();
int arrayIndex = Integer.parseInt(key);
Object oldValue = null;
try {
@@ -963,9 +965,9 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
}
else if (propValue instanceof List) {
PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);
Class requiredType = GenericCollectionTypeResolver.getCollectionReturnType(
Class<?> requiredType = GenericCollectionTypeResolver.getCollectionReturnType(
pd.getReadMethod(), tokens.keys.length);
List list = (List) propValue;
List<Object> list = (List<Object>) propValue;
int index = Integer.parseInt(key);
Object oldValue = null;
if (isExtractOldValueForEditor() && index < list.size()) {
@@ -1000,11 +1002,11 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
}
else if (propValue instanceof Map) {
PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);
Class mapKeyType = GenericCollectionTypeResolver.getMapKeyReturnType(
Class<?> mapKeyType = GenericCollectionTypeResolver.getMapKeyReturnType(
pd.getReadMethod(), tokens.keys.length);
Class mapValueType = GenericCollectionTypeResolver.getMapValueReturnType(
Class<?> mapValueType = GenericCollectionTypeResolver.getMapValueReturnType(
pd.getReadMethod(), tokens.keys.length);
Map map = (Map) propValue;
Map<Object, Object> map = (Map<Object, Object>) propValue;
// IMPORTANT: Do not pass full property name in here - property editors
// must not kick in for map keys but rather only for map values.
TypeDescriptor typeDescriptor = (mapKeyType != null ?
@@ -1023,7 +1025,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
else {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Property referenced in indexed property path '" + propertyName +
"' is neither an array nor a List nor a Map; returned value was [" + pv.getValue() + "]");
"' is neither an array nor a List nor a Map; returned value was [" + propValue + "]");
}
}
@@ -1094,7 +1096,8 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
}
}
}
valueToApply = convertForProperty(propertyName, oldValue, originalValue, pd);
valueToApply = convertForProperty(
propertyName, oldValue, originalValue, new TypeDescriptor(property(pd)));
}
pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@ import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.lang.ref.SoftReference;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -33,6 +33,7 @@ import java.util.WeakHashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.SpringProperties;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
@@ -50,6 +51,18 @@ import org.springframework.util.StringUtils;
* implements the factory design pattern, using a private constructor and
* a static {@link #forClass(Class)} factory method to obtain instances.
*
* <p>Note that for caching to work effectively, some preconditions need to be met:
* Prefer an arrangement where the Spring jars live in the same ClassLoader as the
* application classes, which allows for clean caching along with the application's
* lifecycle in any case. For a web application, consider declaring a local
* {@link org.springframework.web.util.IntrospectorCleanupListener} in {@code web.xml}
* in case of a multi-ClassLoader layout, which will allow for effective caching as well.
*
* <p>In case of a non-clean ClassLoader arrangement without a cleanup listener having
* been set up, this class will fall back to a weak-reference-based caching model that
* recreates much-requested entries every time the garbage collector removed them. In
* such a scenario, consider the {@link #IGNORE_BEANINFO_PROPERTY_NAME} system property.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @since 05 May 2001
@@ -59,11 +72,34 @@ import org.springframework.util.StringUtils;
*/
public class CachedIntrospectionResults {
private static final Log logger = LogFactory.getLog(CachedIntrospectionResults.class);
/**
* System property that instructs Spring to use the {@link Introspector#IGNORE_ALL_BEANINFO}
* mode when calling the JavaBeans {@link Introspector}: "spring.beaninfo.ignore", with a
* value of "true" skipping the search for {@code BeanInfo} classes (typically for scenarios
* where no such classes are being defined for beans in the application in the first place).
* <p>The default is "false", considering all {@code BeanInfo} metadata classes, like for
* standard {@link Introspector#getBeanInfo(Class)} calls. Consider switching this flag to
* "true" if you experience repeated ClassLoader access for non-existing {@code BeanInfo}
* classes, in case such access is expensive on startup or on lazy loading.
* <p>Note that such an effect may also indicate a scenario where caching doesn't work
* effectively: Prefer an arrangement where the Spring jars live in the same ClassLoader
* as the application classes, which allows for clean caching along with the application's
* lifecycle in any case. For a web application, consider declaring a local
* {@link org.springframework.web.util.IntrospectorCleanupListener} in {@code web.xml}
* in case of a multi-ClassLoader layout, which will allow for effective caching as well.
* @see Introspector#getBeanInfo(Class, int)
*/
public static final String IGNORE_BEANINFO_PROPERTY_NAME = "spring.beaninfo.ignore";
private static final boolean shouldIntrospectorIgnoreBeaninfoClasses =
SpringProperties.getFlag(IGNORE_BEANINFO_PROPERTY_NAME);
/** Stores the BeanInfoFactory instances */
private static List<BeanInfoFactory> beanInfoFactories =
SpringFactoriesLoader.loadFactories(BeanInfoFactory.class, CachedIntrospectionResults.class.getClassLoader());
private static List<BeanInfoFactory> beanInfoFactories = SpringFactoriesLoader.loadFactories(
BeanInfoFactory.class, CachedIntrospectionResults.class.getClassLoader());
private static final Log logger = LogFactory.getLog(CachedIntrospectionResults.class);
/**
* Set of ClassLoaders that this CachedIntrospectionResults class will always
@@ -158,7 +194,7 @@ public class CachedIntrospectionResults {
}
results = new CachedIntrospectionResults(beanClass);
synchronized (classCache) {
classCache.put(beanClass, new WeakReference<CachedIntrospectionResults>(results));
classCache.put(beanClass, new SoftReference<CachedIntrospectionResults>(results));
}
}
}
@@ -179,8 +215,8 @@ public class CachedIntrospectionResults {
synchronized (acceptedClassLoaders) {
acceptedLoaderArray = acceptedClassLoaders.toArray(new ClassLoader[acceptedClassLoaders.size()]);
}
for (ClassLoader registeredLoader : acceptedLoaderArray) {
if (isUnderneathClassLoader(classLoader, registeredLoader)) {
for (ClassLoader acceptedLoader : acceptedLoaderArray) {
if (isUnderneathClassLoader(classLoader, acceptedLoader)) {
return true;
}
}
@@ -238,20 +274,25 @@ public class CachedIntrospectionResults {
}
if (beanInfo == null) {
// If none of the factories supported the class, fall back to the default
beanInfo = Introspector.getBeanInfo(beanClass);
beanInfo = (shouldIntrospectorIgnoreBeaninfoClasses ?
Introspector.getBeanInfo(beanClass, Introspector.IGNORE_ALL_BEANINFO) :
Introspector.getBeanInfo(beanClass));
}
this.beanInfo = beanInfo;
// Immediately remove class from Introspector cache, to allow for proper
// garbage collection on class loader shutdown - we cache it here anyway,
// in a GC-friendly manner. In contrast to CachedIntrospectionResults,
// Introspector does not use WeakReferences as values of its WeakHashMap!
Class<?> classToFlush = beanClass;
do {
Introspector.flushFromCaches(classToFlush);
classToFlush = classToFlush.getSuperclass();
// Only bother with flushFromCaches if the Introspector actually cached...
if (!shouldIntrospectorIgnoreBeaninfoClasses) {
// Immediately remove class from Introspector cache, to allow for proper
// garbage collection on class loader shutdown - we cache it here anyway,
// in a GC-friendly manner. In contrast to CachedIntrospectionResults,
// Introspector does not use WeakReferences as values of its WeakHashMap!
Class<?> classToFlush = beanClass;
do {
Introspector.flushFromCaches(classToFlush);
classToFlush = classToFlush.getSuperclass();
}
while (classToFlush != null && classToFlush != Object.class);
}
while (classToFlush != null);
if (logger.isTraceEnabled()) {
logger.trace("Caching PropertyDescriptors for class [" + beanClass.getName() + "]");
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,6 +35,9 @@ import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import static org.springframework.beans.PropertyDescriptorUtils.*;
/**
@@ -73,6 +76,8 @@ import static org.springframework.beans.PropertyDescriptorUtils.*;
*/
class ExtendedBeanInfo implements BeanInfo {
private static final Log logger = LogFactory.getLog(ExtendedBeanInfo.class);
private final BeanInfo delegate;
private final Set<PropertyDescriptor> propertyDescriptors =
@@ -94,14 +99,30 @@ class ExtendedBeanInfo implements BeanInfo {
public ExtendedBeanInfo(BeanInfo delegate) throws IntrospectionException {
this.delegate = delegate;
for (PropertyDescriptor pd : delegate.getPropertyDescriptors()) {
this.propertyDescriptors.add(pd instanceof IndexedPropertyDescriptor ?
new SimpleIndexedPropertyDescriptor((IndexedPropertyDescriptor) pd) :
new SimplePropertyDescriptor(pd));
try {
this.propertyDescriptors.add(pd instanceof IndexedPropertyDescriptor ?
new SimpleIndexedPropertyDescriptor((IndexedPropertyDescriptor) pd) :
new SimplePropertyDescriptor(pd));
}
catch (IntrospectionException ex) {
// Probably simply a method that wasn't meant to follow the JavaBeans pattern...
if (logger.isDebugEnabled()) {
logger.debug("Ignoring invalid bean property '" + pd.getName() + "': " + ex.getMessage());
}
}
}
MethodDescriptor[] methodDescriptors = delegate.getMethodDescriptors();
if (methodDescriptors != null) {
for (Method method : findCandidateWriteMethods(methodDescriptors)) {
handleCandidateWriteMethod(method);
try {
handleCandidateWriteMethod(method);
}
catch (IntrospectionException ex) {
// We're only trying to find candidates, can easily ignore extra ones here...
if (logger.isDebugEnabled()) {
logger.debug("Ignoring candidate write method [" + method + "]: " + ex.getMessage());
}
}
}
}
}
@@ -115,7 +136,7 @@ class ExtendedBeanInfo implements BeanInfo {
matches.add(method);
}
}
// sort non-void returning write methods to guard against the ill effects of
// Sort non-void returning write methods to guard against the ill effects of
// non-deterministic sorting of methods returned from Class#getDeclaredMethods
// under JDK 7. See http://bugs.sun.com/view_bug.do?bug_id=7023180
Collections.sort(matches, new Comparator<Method>() {
@@ -130,15 +151,15 @@ class ExtendedBeanInfo implements BeanInfo {
String methodName = method.getName();
Class<?>[] parameterTypes = method.getParameterTypes();
int nParams = parameterTypes.length;
return methodName.length() > 3 && methodName.startsWith("set") && Modifier.isPublic(method.getModifiers()) &&
return (methodName.length() > 3 && methodName.startsWith("set") && Modifier.isPublic(method.getModifiers()) &&
(!void.class.isAssignableFrom(method.getReturnType()) || Modifier.isStatic(method.getModifiers())) &&
(nParams == 1 || (nParams == 2 && parameterTypes[0].equals(int.class)));
(nParams == 1 || (nParams == 2 && parameterTypes[0].equals(int.class))));
}
private void handleCandidateWriteMethod(Method method) throws IntrospectionException {
int nParams = method.getParameterTypes().length;
String propertyName = propertyNameFor(method);
Class<?> propertyType = method.getParameterTypes()[nParams-1];
Class<?> propertyType = method.getParameterTypes()[nParams - 1];
PropertyDescriptor existingPd = findExistingPropertyDescriptor(propertyName, propertyType);
if (nParams == 1) {
if (existingPd == null) {
@@ -428,24 +449,24 @@ class SimpleIndexedPropertyDescriptor extends IndexedPropertyDescriptor {
* See java.beans.IndexedPropertyDescriptor#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (obj != null && obj instanceof IndexedPropertyDescriptor) {
IndexedPropertyDescriptor other = (IndexedPropertyDescriptor) obj;
if (!compareMethods(getIndexedReadMethod(), other.getIndexedReadMethod())) {
return false;
}
if (!compareMethods(getIndexedWriteMethod(), other.getIndexedWriteMethod())) {
return false;
}
if (getIndexedPropertyType() != other.getIndexedPropertyType()) {
return false;
}
return PropertyDescriptorUtils.equals(this, obj);
if (!(other instanceof IndexedPropertyDescriptor)) {
return false;
}
return false;
IndexedPropertyDescriptor otherPd = (IndexedPropertyDescriptor) other;
if (!compareMethods(getIndexedReadMethod(), otherPd.getIndexedReadMethod())) {
return false;
}
if (!compareMethods(getIndexedWriteMethod(), otherPd.getIndexedWriteMethod())) {
return false;
}
if (getIndexedPropertyType() != otherPd.getIndexedPropertyType()) {
return false;
}
return PropertyDescriptorUtils.equals(this, other);
}
@Override
@@ -586,25 +607,23 @@ class PropertyDescriptorUtils {
* editor and flags are equivalent.
* @see PropertyDescriptor#equals(Object)
*/
public static boolean equals(PropertyDescriptor pd1, Object obj) {
if (pd1 == obj) {
public static boolean equals(PropertyDescriptor pd, Object other) {
if (pd == other) {
return true;
}
if (obj != null && obj instanceof PropertyDescriptor) {
PropertyDescriptor pd2 = (PropertyDescriptor) obj;
if (!compareMethods(pd1.getReadMethod(), pd2.getReadMethod())) {
return false;
}
if (!compareMethods(pd1.getWriteMethod(), pd2.getWriteMethod())) {
return false;
}
if (pd1.getPropertyType() == pd2.getPropertyType() &&
pd1.getPropertyEditorClass() == pd2.getPropertyEditorClass() &&
pd1.isBound() == pd2.isBound() && pd1.isConstrained() == pd2.isConstrained()) {
return true;
}
if (!(other instanceof PropertyDescriptor)) {
return false;
}
return false;
PropertyDescriptor otherPd = (PropertyDescriptor) other;
if (!compareMethods(pd.getReadMethod(), otherPd.getReadMethod())) {
return false;
}
if (!compareMethods(pd.getWriteMethod(), otherPd.getWriteMethod())) {
return false;
}
return (pd.getPropertyType() == otherPd.getPropertyType() &&
pd.getPropertyEditorClass() == otherPd.getPropertyEditorClass() &&
pd.isBound() == otherPd.isBound() && pd.isConstrained() == otherPd.isConstrained());
}
/*
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,8 +25,8 @@ import org.springframework.core.Ordered;
/**
* {@link BeanInfoFactory} implementation that evaluates whether bean classes have
* "non-standard" JavaBeans setter methods and are thus candidates for introspection by
* Spring's {@link ExtendedBeanInfo}.
* "non-standard" JavaBeans setter methods and are thus candidates for introspection
* by Spring's (package-visible) {@code ExtendedBeanInfo} implementation.
*
* <p>Ordered at {@link Ordered#LOWEST_PRECEDENCE} to allow other user-defined
* {@link BeanInfoFactory} types to take precedence.
@@ -34,20 +34,20 @@ import org.springframework.core.Ordered;
* @author Chris Beams
* @since 3.2
* @see BeanInfoFactory
* @see CachedIntrospectionResults
*/
public class ExtendedBeanInfoFactory implements Ordered, BeanInfoFactory {
public class ExtendedBeanInfoFactory implements BeanInfoFactory, Ordered {
/**
* Return a new {@link ExtendedBeanInfo} for the given bean class.
* Return an {@link ExtendedBeanInfo} for the given bean class, if applicable.
*/
public BeanInfo getBeanInfo(Class<?> beanClass) throws IntrospectionException {
return supports(beanClass) ?
new ExtendedBeanInfo(Introspector.getBeanInfo(beanClass)) : null;
return (supports(beanClass) ? new ExtendedBeanInfo(Introspector.getBeanInfo(beanClass)) : null);
}
/**
* Return whether the given bean class declares or inherits any non-void returning
* JavaBeans or <em>indexed property</em> setter methods.
* Return whether the given bean class declares or inherits any non-void
* returning bean property or indexed property setter methods.
*/
private boolean supports(Class<?> beanClass) {
for (Method method : beanClass.getMethods()) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,13 +46,13 @@ class GenericTypeAwarePropertyDescriptor extends PropertyDescriptor {
private final Method writeMethod;
private final Class<?> propertyEditorClass;
private volatile Set<Method> ambiguousWriteMethods;
private MethodParameter writeMethodParameter;
private Class<?> propertyType;
private MethodParameter writeMethodParameter;
private final Class<?> propertyEditorClass;
public GenericTypeAwarePropertyDescriptor(Class<?> beanClass, String propertyName,
@@ -60,8 +60,11 @@ class GenericTypeAwarePropertyDescriptor extends PropertyDescriptor {
throws IntrospectionException {
super(propertyName, null, null);
if (beanClass == null) {
throw new IntrospectionException("Bean class must not be null");
}
this.beanClass = beanClass;
this.propertyEditorClass = propertyEditorClass;
Method readMethodToUse = BridgeMethodResolver.findBridgedMethod(readMethod);
Method writeMethodToUse = BridgeMethodResolver.findBridgedMethod(writeMethod);
@@ -93,8 +96,11 @@ class GenericTypeAwarePropertyDescriptor extends PropertyDescriptor {
this.ambiguousWriteMethods = ambiguousCandidates;
}
}
this.propertyEditorClass = propertyEditorClass;
}
public Class<?> getBeanClass() {
return this.beanClass;
}
@@ -120,9 +126,15 @@ class GenericTypeAwarePropertyDescriptor extends PropertyDescriptor {
return this.writeMethod;
}
@Override
public Class<?> getPropertyEditorClass() {
return this.propertyEditorClass;
public synchronized MethodParameter getWriteMethodParameter() {
if (this.writeMethod == null) {
return null;
}
if (this.writeMethodParameter == null) {
this.writeMethodParameter = new MethodParameter(this.writeMethod, 0);
GenericTypeResolver.resolveParameterType(this.writeMethodParameter, this.beanClass);
}
return this.writeMethodParameter;
}
@Override
@@ -144,15 +156,9 @@ class GenericTypeAwarePropertyDescriptor extends PropertyDescriptor {
return this.propertyType;
}
public synchronized MethodParameter getWriteMethodParameter() {
if (this.writeMethod == null) {
return null;
}
if (this.writeMethodParameter == null) {
this.writeMethodParameter = new MethodParameter(this.writeMethod, 0);
GenericTypeResolver.resolveParameterType(this.writeMethodParameter, this.beanClass);
}
return this.writeMethodParameter;
@Override
public Class<?> getPropertyEditorClass() {
return this.propertyEditorClass;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -86,7 +86,7 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
// There is no replacement of existing property values.
if (original != null) {
this.propertyValueList = new ArrayList<PropertyValue>(original.size());
for (Map.Entry entry : original.entrySet()) {
for (Map.Entry<?, ?> entry : original.entrySet()) {
this.propertyValueList.add(new PropertyValue(entry.getKey().toString(), entry.getValue()));
}
}
@@ -303,6 +303,16 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
this.processedProperties.add(propertyName);
}
/**
* Clear the "processed" registration of the given property, if any.
* @since 3.2.13
*/
public void clearProcessedProperty(String propertyName) {
if (this.processedProperties != null) {
this.processedProperties.remove(propertyName);
}
}
/**
* Mark this holder as containing converted values only
* (i.e. no runtime resolution needed anymore).
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -49,7 +49,7 @@ final class PropertyMatches {
* @param propertyName the name of the property to find possible matches for
* @param beanClass the bean class to search for matches
*/
public static PropertyMatches forProperty(String propertyName, Class beanClass) {
public static PropertyMatches forProperty(String propertyName, Class<?> beanClass) {
return forProperty(propertyName, beanClass, DEFAULT_MAX_DISTANCE);
}
@@ -59,7 +59,7 @@ final class PropertyMatches {
* @param beanClass the bean class to search for matches
* @param maxDistance the maximum property distance allowed for matches
*/
public static PropertyMatches forProperty(String propertyName, Class beanClass, int maxDistance) {
public static PropertyMatches forProperty(String propertyName, Class<?> beanClass, int maxDistance) {
return new PropertyMatches(propertyName, beanClass, maxDistance);
}
@@ -76,7 +76,7 @@ final class PropertyMatches {
/**
* Create a new PropertyMatches instance for the given property.
*/
private PropertyMatches(String propertyName, Class beanClass, int maxDistance) {
private PropertyMatches(String propertyName, Class<?> beanClass, int maxDistance) {
this.propertyName = propertyName;
this.possibleMatches = calculateMatches(BeanUtils.getPropertyDescriptors(beanClass), maxDistance);
}
@@ -172,7 +172,8 @@ final class PropertyMatches {
char t_j = s2.charAt(j - 1);
if (s_i == t_j) {
cost = 0;
} else {
}
else {
cost = 1;
}
d[i][j] = Math.min(Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1),
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -200,13 +200,13 @@ class TypeConverterDelegate {
else if (convertedValue instanceof Collection) {
// Convert elements to target type, if determined.
convertedValue = convertToTypedCollection(
(Collection) convertedValue, propertyName, requiredType, typeDescriptor);
(Collection<?>) convertedValue, propertyName, requiredType, typeDescriptor);
standardConversion = true;
}
else if (convertedValue instanceof Map) {
// Convert keys and values to respective target type, if determined.
convertedValue = convertToTypedMap(
(Map) convertedValue, propertyName, requiredType, typeDescriptor);
(Map<?, ?>) convertedValue, propertyName, requiredType, typeDescriptor);
standardConversion = true;
}
if (convertedValue.getClass().isArray() && Array.getLength(convertedValue) == 1) {
@@ -220,8 +220,8 @@ class TypeConverterDelegate {
else if (convertedValue instanceof String && !requiredType.isInstance(convertedValue)) {
if (firstAttemptEx == null && !requiredType.isInterface() && !requiredType.isEnum()) {
try {
Constructor strCtor = requiredType.getConstructor(String.class);
return (T) BeanUtils.instantiateClass(strCtor, convertedValue);
Constructor<T> strCtor = requiredType.getConstructor(String.class);
return BeanUtils.instantiateClass(strCtor, convertedValue);
}
catch (NoSuchMethodException ex) {
// proceed with field lookup
@@ -289,19 +289,19 @@ class TypeConverterDelegate {
if (index > - 1) {
String enumType = trimmedValue.substring(0, index);
String fieldName = trimmedValue.substring(index + 1);
ClassLoader loader = this.targetObject.getClass().getClassLoader();
ClassLoader cl = this.targetObject.getClass().getClassLoader();
try {
Class<?> enumValueType = loader.loadClass(enumType);
Class<?> enumValueType = ClassUtils.forName(enumType, cl);
Field enumField = enumValueType.getField(fieldName);
convertedValue = enumField.get(null);
}
catch (ClassNotFoundException ex) {
if(logger.isTraceEnabled()) {
logger.trace("Enum class [" + enumType + "] cannot be loaded from [" + loader + "]", ex);
if (logger.isTraceEnabled()) {
logger.trace("Enum class [" + enumType + "] cannot be loaded", ex);
}
}
catch (Throwable ex) {
if(logger.isTraceEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Field [" + fieldName + "] isn't an enum value for type [" + enumType + "]", ex);
}
}
@@ -331,7 +331,7 @@ class TypeConverterDelegate {
* @param requiredType the type to find an editor for
* @return the corresponding editor, or {@code null} if none
*/
private PropertyEditor findDefaultEditor(Class requiredType) {
private PropertyEditor findDefaultEditor(Class<?> requiredType) {
PropertyEditor editor = null;
if (requiredType != null) {
// No custom editor -> check BeanWrapperImpl's default editors.
@@ -459,10 +459,10 @@ class TypeConverterDelegate {
private Object convertToTypedArray(Object input, String propertyName, Class<?> componentType) {
if (input instanceof Collection) {
// Convert Collection elements to array elements.
Collection coll = (Collection) input;
Collection<?> coll = (Collection<?>) input;
Object result = Array.newInstance(componentType, coll.size());
int i = 0;
for (Iterator it = coll.iterator(); it.hasNext(); i++) {
for (Iterator<?> it = coll.iterator(); it.hasNext(); i++) {
Object value = convertIfNecessary(
buildIndexedPropertyName(propertyName, i), null, it.next(), componentType);
Array.set(result, i, value);
@@ -495,8 +495,8 @@ class TypeConverterDelegate {
}
@SuppressWarnings("unchecked")
private Collection convertToTypedCollection(
Collection original, String propertyName, Class requiredType, TypeDescriptor typeDescriptor) {
private Collection<?> convertToTypedCollection(
Collection<?> original, String propertyName, Class<?> requiredType, TypeDescriptor typeDescriptor) {
if (!Collection.class.isAssignableFrom(requiredType)) {
return original;
@@ -519,7 +519,7 @@ class TypeConverterDelegate {
return original;
}
Iterator it;
Iterator<?> it;
try {
it = original.iterator();
if (it == null) {
@@ -538,13 +538,13 @@ class TypeConverterDelegate {
return original;
}
Collection convertedCopy;
Collection<Object> convertedCopy;
try {
if (approximable) {
convertedCopy = CollectionFactory.createApproximateCollection(original, original.size());
}
else {
convertedCopy = (Collection) requiredType.newInstance();
convertedCopy = (Collection<Object>) requiredType.newInstance();
}
}
catch (Throwable ex) {
@@ -577,8 +577,8 @@ class TypeConverterDelegate {
}
@SuppressWarnings("unchecked")
private Map convertToTypedMap(
Map original, String propertyName, Class requiredType, TypeDescriptor typeDescriptor) {
private Map<?, ?> convertToTypedMap(
Map<?, ?> original, String propertyName, Class<?> requiredType, TypeDescriptor typeDescriptor) {
if (!Map.class.isAssignableFrom(requiredType)) {
return original;
@@ -602,7 +602,7 @@ class TypeConverterDelegate {
return original;
}
Iterator it;
Iterator<?> it;
try {
it = original.entrySet().iterator();
if (it == null) {
@@ -621,13 +621,13 @@ class TypeConverterDelegate {
return original;
}
Map convertedCopy;
Map<Object, Object> convertedCopy;
try {
if (approximable) {
convertedCopy = CollectionFactory.createApproximateMap(original, original.size());
}
else {
convertedCopy = (Map) requiredType.newInstance();
convertedCopy = (Map<Object, Object>) requiredType.newInstance();
}
}
catch (Throwable ex) {
@@ -639,7 +639,7 @@ class TypeConverterDelegate {
}
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) it.next();
Object key = entry.getKey();
Object value = entry.getValue();
String keyedPropertyName = buildKeyedPropertyName(propertyName, key);
@@ -674,7 +674,7 @@ class TypeConverterDelegate {
null);
}
private boolean canCreateCopy(Class requiredType) {
private boolean canCreateCopy(Class<?> requiredType) {
return (!requiredType.isInterface() && !Modifier.isAbstract(requiredType.getModifiers()) &&
Modifier.isPublic(requiredType.getModifiers()) && ClassUtils.hasConstructor(requiredType));
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -170,8 +170,7 @@ public interface BeanFactory {
* <p>Allows for specifying explicit constructor arguments / factory method arguments,
* overriding the specified default arguments (if any) in the bean definition.
* @param name the name of the bean to retrieve
* @param args arguments to use if creating a prototype using explicit arguments to a
* static factory method. It is invalid to use a non-null args value in any other case.
* @param args arguments to use if creating a prototype using explicit arguments
* @return an instance of the bean
* @throws NoSuchBeanDefinitionException if there is no such bean definition
* @throws BeanDefinitionStoreException if arguments have been given but
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,7 +16,6 @@
package org.springframework.beans.factory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,21 +20,23 @@ import org.springframework.beans.BeansException;
import org.springframework.util.StringUtils;
/**
* Exception thrown when a {@code BeanFactory} is asked for a bean instance
* for which it cannot find a definition.
* Exception thrown when a {@code BeanFactory} is asked for a bean instance for which it
* cannot find a definition. This may point to a non-existing bean, a non-unique bean,
* or a manually registered singleton instance without an associated bean definition.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @see BeanFactory#getBean(String)
* @see BeanFactory#getBean(Class)
* @see NoUniqueBeanDefinitionException
*/
@SuppressWarnings("serial")
public class NoSuchBeanDefinitionException extends BeansException {
/** Name of the missing bean. */
/** Name of the missing bean */
private String beanName;
/** Required type of the missing bean. */
/** Required type of the missing bean */
private Class<?> beanType;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@ package org.springframework.beans.factory.access.el;
import java.beans.FeatureDescriptor;
import java.util.Iterator;
import javax.el.ELContext;
import javax.el.ELException;
import javax.el.ELResolver;
@@ -78,8 +77,14 @@ public abstract class SpringBeanELResolver extends ELResolver {
String beanName = property.toString();
BeanFactory bf = getBeanFactory(elContext);
if (bf.containsBean(beanName)) {
throw new PropertyNotWritableException(
"Variable '" + beanName + "' refers to a Spring bean which by definition is not writable");
if (value == bf.getBean(beanName)) {
// Setting the bean reference to the same value is alright - can simply be ignored...
elContext.setPropertyResolved(true);
}
else {
throw new PropertyNotWritableException(
"Variable '" + beanName + "' refers to a Spring bean which by definition is not writable");
}
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -135,9 +135,9 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
ClassLoader cl = AutowiredAnnotationBeanPostProcessor.class.getClassLoader();
try {
this.autowiredAnnotationTypes.add((Class<? extends Annotation>) cl.loadClass("javax.inject.Inject"));
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.info("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
@@ -215,7 +215,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
if (beanType != null) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType);
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
}
@@ -233,24 +233,25 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
Constructor<?> requiredConstructor = null;
Constructor<?> defaultConstructor = null;
for (Constructor<?> candidate : rawCandidates) {
Annotation annotation = findAutowiredAnnotation(candidate);
if (annotation != null) {
Annotation ann = findAutowiredAnnotation(candidate);
if (ann != null) {
if (requiredConstructor != null) {
throw new BeanCreationException("Invalid autowire-marked constructor: " + candidate +
". Found another constructor with 'required' Autowired annotation: " +
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructor: " + candidate +
". Found constructor with 'required' Autowired annotation already: " +
requiredConstructor);
}
if (candidate.getParameterTypes().length == 0) {
throw new IllegalStateException(
"Autowired annotation requires at least one argument: " + candidate);
}
boolean required = determineRequiredStatus(annotation);
boolean required = determineRequiredStatus(ann);
if (required) {
if (!candidates.isEmpty()) {
throw new BeanCreationException(
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructors: " + candidates +
". Found another constructor with 'required' Autowired annotation: " +
requiredConstructor);
". Found constructor with 'required' Autowired annotation: " +
candidate);
}
requiredConstructor = candidate;
}
@@ -262,13 +263,21 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
}
if (!candidates.isEmpty()) {
// Add default constructor to list of optional constructors, as fallback.
if (requiredConstructor == null && defaultConstructor != null) {
candidates.add(defaultConstructor);
if (requiredConstructor == null) {
if (defaultConstructor != null) {
candidates.add(defaultConstructor);
}
else if (candidates.size() == 1 && logger.isWarnEnabled()) {
logger.warn("Inconsistent constructor declaration on bean with name '" + beanName +
"': single autowire-marked constructor flagged as optional - this constructor " +
"is effectively required since there is no default constructor to fall back to: " +
candidates.get(0));
}
}
candidateConstructors = candidates.toArray(new Constructor[candidates.size()]);
candidateConstructors = candidates.toArray(new Constructor<?>[candidates.size()]);
}
else {
candidateConstructors = new Constructor[0];
candidateConstructors = new Constructor<?>[0];
}
this.candidateConstructorsCache.put(beanClass, candidateConstructors);
}
@@ -281,7 +290,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass());
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
metadata.inject(bean, beanName, pvs);
}
@@ -299,7 +308,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
*/
public void processInjection(Object bean) throws BeansException {
Class<?> clazz = bean.getClass();
InjectionMetadata metadata = findAutowiringMetadata(clazz.getName(), clazz);
InjectionMetadata metadata = findAutowiringMetadata(clazz.getName(), clazz, null);
try {
metadata.inject(bean, null, null);
}
@@ -309,15 +318,18 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
}
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz) {
// Quick check on the concurrent map first, with minimal locking.
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (metadata == null) {
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (metadata == null) {
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
@@ -333,23 +345,25 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
do {
LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<InjectionMetadata.InjectedElement>();
for (Field field : targetClass.getDeclaredFields()) {
Annotation annotation = findAutowiredAnnotation(field);
if (annotation != null) {
Annotation ann = findAutowiredAnnotation(field);
if (ann != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation is not supported on static fields: " + field);
}
continue;
}
boolean required = determineRequiredStatus(annotation);
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
}
for (Method method : targetClass.getDeclaredMethods()) {
Annotation ann = null;
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
Annotation annotation = BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod) ?
findAutowiredAnnotation(bridgedMethod) : findAutowiredAnnotation(method);
if (annotation != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
ann = findAutowiredAnnotation(bridgedMethod);
}
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation is not supported on static methods: " + method);
@@ -361,8 +375,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
logger.warn("Autowired annotation should be used on methods with actual parameters: " + method);
}
}
boolean required = determineRequiredStatus(annotation);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
boolean required = determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new AutowiredMethodElement(method, required, pd));
}
}
@@ -376,9 +390,9 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
private Annotation findAutowiredAnnotation(AccessibleObject ao) {
for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
Annotation annotation = AnnotationUtils.getAnnotation(ao, type);
if (annotation != null) {
return annotation;
Annotation ann = AnnotationUtils.getAnnotation(ao, type);
if (ann != null) {
return ann;
}
}
return null;
@@ -403,21 +417,21 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
* <p>A 'required' dependency means that autowiring should fail when no beans
* are found. Otherwise, the autowiring process will simply bypass the field
* or method when no beans are found.
* @param annotation the Autowired annotation
* @param ann the Autowired annotation
* @return whether the annotation indicates that a dependency is required
*/
protected boolean determineRequiredStatus(Annotation annotation) {
protected boolean determineRequiredStatus(Annotation ann) {
try {
Method method = ReflectionUtils.findMethod(annotation.annotationType(), this.requiredParameterName);
Method method = ReflectionUtils.findMethod(ann.annotationType(), this.requiredParameterName);
if (method == null) {
// annotations like @Inject and @Value don't have a method (attribute) named "required"
// Annotations like @Inject and @Value don't have a method (attribute) named "required"
// -> default to required status
return true;
}
return (this.requiredParameterValue == (Boolean) ReflectionUtils.invokeMethod(method, annotation));
return (this.requiredParameterValue == (Boolean) ReflectionUtils.invokeMethod(method, ann));
}
catch (Exception ex) {
// an exception was thrown during reflective invocation of the required attribute
// An exception was thrown during reflective invocation of the required attribute
// -> default to required status
return true;
}
@@ -483,14 +497,14 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
DependencyDescriptor descriptor = new DependencyDescriptor(field, this.required);
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
TypeConverter typeConverter = beanFactory.getTypeConverter();
value = beanFactory.resolveDependency(descriptor, beanName, autowiredBeanNames, typeConverter);
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
synchronized (this) {
if (!this.cached) {
if (value != null || this.required) {
this.cachedFieldValue = descriptor;
this.cachedFieldValue = desc;
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@ import org.springframework.util.ObjectUtils;
* Spring's {@link Qualifier @Qualifier} annotation.
*
* @author Chris Beams
* @author Juergen Hoeller
* @since 3.1.2
* @see BeanFactoryUtils
*/
@@ -90,9 +91,13 @@ public class BeanFactoryAnnotationUtils {
if (matchingBean != null) {
return matchingBean;
}
else if (bf.containsBean(qualifier)) {
// Fallback: target bean at least found by bean name - probably a manually registered singleton.
return bf.getBean(qualifier, beanType);
}
else {
throw new NoSuchBeanDefinitionException(qualifier, "No matching " + beanType.getSimpleName() +
" bean found for qualifier '" + qualifier + "' - neither qualifier " + "match nor bean name match!");
" bean found for qualifier '" + qualifier + "' - neither qualifier match nor bean name match!");
}
}
@@ -128,7 +133,7 @@ public class BeanFactoryAnnotationUtils {
}
}
catch (NoSuchBeanDefinitionException ex) {
// ignore - can't compare qualifiers for a manually registered singleton object
// Ignore - can't compare qualifiers for a manually registered singleton object
}
}
return false;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,7 +46,7 @@ import org.springframework.util.ReflectionUtils;
*/
public class InjectionMetadata {
private final Log logger = LogFactory.getLog(InjectionMetadata.class);
private static final Log logger = LogFactory.getLog(InjectionMetadata.class);
private final Class<?> targetClass;
@@ -60,6 +60,7 @@ public class InjectionMetadata {
this.injectedElements = elements;
}
public void checkConfigMembers(RootBeanDefinition beanDefinition) {
Set<InjectedElement> checkedElements = new LinkedHashSet<InjectedElement>(this.injectedElements.size());
for (InjectedElement element : this.injectedElements) {
@@ -82,13 +83,31 @@ public class InjectionMetadata {
boolean debug = logger.isDebugEnabled();
for (InjectedElement element : elementsToIterate) {
if (debug) {
logger.debug("Processing injected method of bean '" + beanName + "': " + element);
logger.debug("Processing injected element of bean '" + beanName + "': " + element);
}
element.inject(target, beanName, pvs);
}
}
}
/**
* @since 3.2.13
*/
public void clear(PropertyValues pvs) {
Collection<InjectedElement> elementsToIterate =
(this.checkedElements != null ? this.checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
for (InjectedElement element : elementsToIterate) {
element.clearPropertySkipping(pvs);
}
}
}
public static boolean needsRefresh(InjectionMetadata metadata, Class<?> clazz) {
return (metadata == null || !metadata.targetClass.equals(clazz));
}
public static abstract class InjectedElement {
@@ -165,7 +184,7 @@ public class InjectionMetadata {
}
/**
* Checks whether this injector's property needs to be skipped due to
* Check whether this injector's property needs to be skipped due to
* an explicit property value having been specified. Also marks the
* affected property as processed for other processors to ignore it.
*/
@@ -196,6 +215,20 @@ public class InjectionMetadata {
}
}
/**
* @since 3.2.13
*/
protected void clearPropertySkipping(PropertyValues pvs) {
if (pvs == null) {
return;
}
synchronized (pvs) {
if (Boolean.FALSE.equals(this.skip) && this.pd != null && pvs instanceof MutablePropertyValues) {
((MutablePropertyValues) pvs).clearProcessedProperty(this.pd.getName());
}
}
}
/**
* Either this or {@link #inject} needs to be overridden.
*/
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@ import org.springframework.beans.SimpleTypeConverter;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
@@ -71,9 +72,9 @@ public class QualifierAnnotationAutowireCandidateResolver implements AutowireCan
@SuppressWarnings("unchecked")
public QualifierAnnotationAutowireCandidateResolver() {
this.qualifierTypes.add(Qualifier.class);
ClassLoader cl = QualifierAnnotationAutowireCandidateResolver.class.getClassLoader();
try {
this.qualifierTypes.add((Class<? extends Annotation>) cl.loadClass("javax.inject.Qualifier"));
this.qualifierTypes.add((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Qualifier",
QualifierAnnotationAutowireCandidateResolver.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
@@ -246,9 +247,14 @@ public class QualifierAnnotationAutowireCandidateResolver implements AutowireCan
if (targetAnnotation == null) {
// Look for matching annotation on the target class
if (this.beanFactory != null) {
Class<?> beanType = this.beanFactory.getType(bdHolder.getBeanName());
if (beanType != null) {
targetAnnotation = AnnotationUtils.getAnnotation(ClassUtils.getUserClass(beanType), type);
try {
Class<?> beanType = this.beanFactory.getType(bdHolder.getBeanName());
if (beanType != null) {
targetAnnotation = AnnotationUtils.getAnnotation(ClassUtils.getUserClass(beanType), type);
}
}
catch (NoSuchBeanDefinitionException ex) {
// Not the usual case - simply forget about the type check...
}
}
if (targetAnnotation == null && bd.hasBeanClass()) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -206,7 +206,7 @@ public abstract class PlaceholderConfigurerSupport extends PropertyResourceConfi
visitor.visitBeanDefinition(bd);
}
catch (Exception ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), curName, ex.getMessage());
throw new BeanDefinitionStoreException(bd.getResourceDescription(), curName, ex.getMessage(), ex);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +21,8 @@ import java.util.Set;
import org.springframework.beans.BeansException;
import org.springframework.core.Constants;
import org.springframework.core.SpringProperties;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.util.PropertyPlaceholderHelper;
import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
import org.springframework.util.StringValueResolver;
@@ -82,7 +84,8 @@ public class PropertyPlaceholderConfigurer extends PlaceholderConfigurerSupport
private int systemPropertiesMode = SYSTEM_PROPERTIES_MODE_FALLBACK;
private boolean searchSystemEnvironment = true;
private boolean searchSystemEnvironment =
!SpringProperties.getFlag(AbstractEnvironment.IGNORE_GETENV_PROPERTY_NAME);
/**
@@ -216,8 +219,7 @@ public class PropertyPlaceholderConfigurer extends PlaceholderConfigurerSupport
throws BeansException {
StringValueResolver valueResolver = new PlaceholderResolvingStringValueResolver(props);
this.doProcessProperties(beanFactoryToProcess, valueResolver);
doProcessProperties(beanFactoryToProcess, valueResolver);
}
/**
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -285,7 +285,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
// Use prototype bean definition, to avoid registering bean as dependent bean.
RootBeanDefinition bd = new RootBeanDefinition(beanClass);
bd.setScope(SCOPE_PROTOTYPE);
bd.allowCaching = false;
bd.allowCaching = ClassUtils.isCacheSafe(beanClass, getBeanClassLoader());
return (T) createBean(beanClass.getName(), bd, null);
}
@@ -293,7 +293,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
// Use non-singleton bean definition, to avoid registering bean as dependent bean.
RootBeanDefinition bd = new RootBeanDefinition(ClassUtils.getUserClass(existingBean));
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
bd.allowCaching = false;
bd.allowCaching = ClassUtils.isCacheSafe(bd.getBeanClass(), getBeanClassLoader());
BeanWrapper bw = new BeanWrapperImpl(existingBean);
initBeanWrapper(bw);
populateBean(bd.getBeanClass().getName(), bd, bw);
@@ -312,7 +312,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
bd = new RootBeanDefinition(mbd);
}
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
bd.allowCaching = false;
bd.allowCaching = ClassUtils.isCacheSafe(ClassUtils.getUserClass(existingBean), getBeanClassLoader());
}
BeanWrapper bw = new BeanWrapperImpl(existingBean);
initBeanWrapper(bw);
@@ -711,6 +711,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
final Holder objectType = new Holder();
String factoryBeanName = mbd.getFactoryBeanName();
final String factoryMethodName = mbd.getFactoryMethodName();
if (factoryBeanName != null && factoryMethodName != null) {
// Try to obtain the FactoryBean's object type without instantiating it at all.
BeanDefinition fbDef = getBeanDefinition(factoryBeanName);
@@ -794,7 +795,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
if (bw != null) {
return (FactoryBean<?>) bw.getWrappedInstance();
}
if (isSingletonCurrentlyInCreation(beanName)) {
if (isSingletonCurrentlyInCreation(beanName) ||
(mbd.getFactoryBeanName() != null && isSingletonCurrentlyInCreation(mbd.getFactoryBeanName()))) {
return null;
}
Object instance = null;
@@ -1373,7 +1375,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
MutablePropertyValues mpvs = null;
List<PropertyValue> original;
if (System.getSecurityManager()!= null) {
if (System.getSecurityManager() != null) {
if (bw instanceof BeanWrapperImpl) {
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
}
@@ -1666,7 +1668,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
/**
* Special DependencyDescriptor variant for autowire="byType".
* Special DependencyDescriptor variant for Spring's good old autowire="byType" mode.
* Always optional; never considering the parameter name for choosing a primary candidate.
*/
@SuppressWarnings("serial")
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -38,8 +38,8 @@ import org.springframework.util.StringUtils;
/**
* Base class for concrete, full-fledged
* {@link org.springframework.beans.factory.config.BeanDefinition} classes,
* factoring out common properties of {@link RootBeanDefinition} and
* {@link ChildBeanDefinition}.
* factoring out common properties of {@link GenericBeanDefinition},
* {@link RootBeanDefinition} and {@link ChildBeanDefinition}.
*
* <p>The autowire constants match the ones defined in the
* {@link org.springframework.beans.factory.config.AutowireCapableBeanFactory}
@@ -123,11 +123,14 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
public static final int DEPENDENCY_CHECK_ALL = 3;
/**
* Constant that indicates the container should attempt to infer the {@link
* #setDestroyMethodName destroy method name} for a bean as opposed to explicit
* specification of a method name. The value {@value} is specifically designed to
* include characters otherwise illegal in a method name, ensuring no possibility of
* collisions with legitimately named methods having the same name.
* Constant that indicates the container should attempt to infer the
* {@link #setDestroyMethodName destroy method name} for a bean as opposed to
* explicit specification of a method name. The value {@value} is specifically
* designed to include characters otherwise illegal in a method name, ensuring
* no possibility of collisions with legitimately named methods having the same
* name.
* <p>Currently, the method names detected during destroy method inference
* are "close" and "shutdown", if present on the specific bean class.
*/
public static final String INFER_METHOD = "(inferred)";
@@ -383,7 +386,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
throw new IllegalStateException(
"Bean class name [" + beanClassObject + "] has not been resolved into an actual Class");
}
return (Class) beanClassObject;
return (Class<?>) beanClassObject;
}
public void setBeanClassName(String beanClassName) {
@@ -393,7 +396,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
public String getBeanClassName() {
Object beanClassObject = this.beanClass;
if (beanClassObject instanceof Class) {
return ((Class) beanClassObject).getName();
return ((Class<?>) beanClassObject).getName();
}
else {
return (String) beanClassObject;
@@ -408,12 +411,12 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
* @return the resolved bean class
* @throws ClassNotFoundException if the class name could be resolved
*/
public Class resolveBeanClass(ClassLoader classLoader) throws ClassNotFoundException {
public Class<?> resolveBeanClass(ClassLoader classLoader) throws ClassNotFoundException {
String className = getBeanClassName();
if (className == null) {
return null;
}
Class resolvedClass = ClassUtils.forName(className, classLoader);
Class<?> resolvedClass = ClassUtils.forName(className, classLoader);
this.beanClass = resolvedClass;
return resolvedClass;
}
@@ -551,8 +554,8 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
// Work out whether to apply setter autowiring or constructor autowiring.
// If it has a no-arg constructor it's deemed to be setter autowiring,
// otherwise we'll try constructor autowiring.
Constructor[] constructors = getBeanClass().getConstructors();
for (Constructor constructor : constructors) {
Constructor<?>[] constructors = getBeanClass().getConstructors();
for (Constructor<?> constructor : constructors) {
if (constructor.getParameterTypes().length == 0) {
return AUTOWIRE_BY_TYPE;
}
@@ -677,7 +680,8 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
/**
* Specify whether to allow access to non-public constructors and methods,
* for the case of externalized metadata pointing to those.
* for the case of externalized metadata pointing to those. The default is
* {@code true}; switch this to {@code false} for public access only.
* <p>This applies to constructor resolution, factory method resolution,
* and also init/destroy methods. Bean property accessors have to be public
* in any case and are not affected by this setting.
@@ -699,7 +703,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
/**
* Specify whether to resolve constructors in lenient mode ({@code true},
* which is the default) or to switch to strict resolution (throwing an exception
* in case of ambigious constructors that all match when converting the arguments,
* in case of ambiguous constructors that all match when converting the arguments,
* whereas lenient mode would use the one with the 'closest' type matches).
*/
public void setLenientConstructorResolution(boolean lenientConstructorResolution) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author 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,7 +123,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
/** Resolution strategy for expressions in bean definition values */
private BeanExpressionResolver beanExpressionResolver;
/** Spring 3.0 ConversionService to use instead of PropertyEditors */
/** Spring ConversionService to use instead of PropertyEditors */
private ConversionService conversionService;
/** Custom PropertyEditorRegistrars to apply to the beans of this factory */
@@ -159,10 +159,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
private final Map<String, RootBeanDefinition> mergedBeanDefinitions =
new ConcurrentHashMap<String, RootBeanDefinition>(64);
/**
* Names of beans that have already been created at least once
* (using a ConcurrentHashMap as a Set)
*/
/** Names of beans that have already been created at least once */
private final Map<String, Boolean> alreadyCreated = new ConcurrentHashMap<String, Boolean>(64);
/** Names of beans that are currently in creation */
@@ -503,8 +500,8 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
// Retrieve corresponding bean definition.
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
Class[] typesToMatch = (FactoryBean.class.equals(typeToMatch) ?
new Class[] {typeToMatch} : new Class[] {FactoryBean.class, typeToMatch});
Class<?>[] typesToMatch = (FactoryBean.class.equals(typeToMatch) ?
new Class<?>[] {typeToMatch} : new Class<?>[] {FactoryBean.class, typeToMatch});
// Check decorated bean definition, if any: We assume it'll be easier
// to determine the decorated bean's type than the proxy's type.
@@ -1231,7 +1228,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
// Check validity of the usage of the args parameter. This can
// only be used for prototypes constructed via a factory method.
if (args != null && !mbd.isPrototype()) {
throw new BeanDefinitionStoreException(
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"Can only specify arguments for the getBean method when referring to a prototype bean definition");
}
}
@@ -1391,7 +1388,9 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
* @param beanName the name of the bean
*/
protected void markBeanAsCreated(String beanName) {
this.alreadyCreated.put(beanName, Boolean.TRUE);
if (!this.alreadyCreated.containsKey(beanName)) {
this.alreadyCreated.put(beanName, Boolean.TRUE);
}
}
/**
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -81,6 +81,7 @@ class BeanDefinitionValueResolver {
this.typeConverter = typeConverter;
}
/**
* Given a PropertyValue, return a value, resolving any references to other
* beans in the factory if necessary. The value could be:
@@ -123,7 +124,9 @@ class BeanDefinitionValueResolver {
else if (value instanceof BeanDefinition) {
// Resolve plain BeanDefinition, without contained name: use dummy name.
BeanDefinition bd = (BeanDefinition) value;
return resolveInnerBean(argName, "(inner bean)", bd);
String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR +
ObjectUtils.getIdentityHexString(bd);
return resolveInnerBean(argName, innerBeanName, bd);
}
else if (value instanceof ManagedArray) {
// May need to resolve contained runtime references.
@@ -164,7 +167,7 @@ class BeanDefinitionValueResolver {
else if (value instanceof ManagedProperties) {
Properties original = (Properties) value;
Properties copy = new Properties();
for (Map.Entry propEntry : original.entrySet()) {
for (Map.Entry<Object, Object> propEntry : original.entrySet()) {
Object propKey = propEntry.getKey();
Object propValue = propEntry.getValue();
if (propKey instanceof TypedStringValue) {
@@ -256,20 +259,25 @@ class BeanDefinitionValueResolver {
mbd = this.beanFactory.getMergedBeanDefinition(innerBeanName, innerBd, this.beanDefinition);
// Check given bean name whether it is unique. If not already unique,
// add counter - increasing the counter until the name is unique.
String actualInnerBeanName = adaptInnerBeanName(innerBeanName);
String actualInnerBeanName = innerBeanName;
if (mbd.isSingleton()) {
actualInnerBeanName = adaptInnerBeanName(innerBeanName);
}
this.beanFactory.registerContainedBean(actualInnerBeanName, this.beanName);
// Guarantee initialization of beans that the inner bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
this.beanFactory.getBean(dependsOnBean);
this.beanFactory.registerDependentBean(dependsOnBean, actualInnerBeanName);
this.beanFactory.getBean(dependsOnBean);
}
}
// Actually create the inner bean instance now...
Object innerBean = this.beanFactory.createBean(actualInnerBeanName, mbd, null);
if (innerBean instanceof FactoryBean) {
boolean synthetic = mbd.isSynthetic();
return this.beanFactory.getObjectFromFactoryBean((FactoryBean) innerBean, actualInnerBeanName, !synthetic);
return this.beanFactory.getObjectFromFactoryBean(
(FactoryBean<?>) innerBean, actualInnerBeanName, !synthetic);
}
else {
return innerBean;
@@ -344,7 +352,7 @@ class BeanDefinitionValueResolver {
/**
* For each element in the managed list, resolve reference if necessary.
*/
private List resolveManagedList(Object argName, List<?> ml) {
private List<?> resolveManagedList(Object argName, List<?> ml) {
List<Object> resolved = new ArrayList<Object>(ml.size());
for (int i = 0; i < ml.size(); i++) {
resolved.add(
@@ -356,7 +364,7 @@ class BeanDefinitionValueResolver {
/**
* For each element in the managed set, resolve reference if necessary.
*/
private Set resolveManagedSet(Object argName, Set<?> ms) {
private Set<?> resolveManagedSet(Object argName, Set<?> ms) {
Set<Object> resolved = new LinkedHashSet<Object>(ms.size());
int i = 0;
for (Object m : ms) {
@@ -369,9 +377,9 @@ class BeanDefinitionValueResolver {
/**
* For each element in the managed map, resolve reference if necessary.
*/
private Map resolveManagedMap(Object argName, Map<?, ?> mm) {
private Map<?, ?> resolveManagedMap(Object argName, Map<?, ?> mm) {
Map<Object, Object> resolved = new LinkedHashMap<Object, Object>(mm.size());
for (Map.Entry entry : mm.entrySet()) {
for (Map.Entry<?, ?> entry : mm.entrySet()) {
Object resolvedKey = resolveValueIfNecessary(argName, entry.getKey());
Object resolvedValue = resolveValueIfNecessary(
new KeyedArgName(argName, entry.getKey()), entry.getValue());
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.cglib.core.SpringNamingPolicy;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.CallbackFilter;
import org.springframework.cglib.proxy.Enhancer;
@@ -33,8 +33,9 @@ import org.springframework.cglib.proxy.NoOp;
/**
* Default object instantiation strategy for use in BeanFactories.
* Uses CGLIB to generate subclasses dynamically if methods need to be
* overridden by the container, to implement Method Injection.
*
* <p>Uses CGLIB to generate subclasses dynamically if methods need to be
* overridden by the container to implement <em>Method Injection</em>.
*
* @author Rod Johnson
* @author Juergen Hoeller
@@ -50,13 +51,13 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
/**
* Index in the CGLIB callback array for a method that should
* be overridden to provide method lookup.
* be overridden to provide <em>method lookup</em>.
*/
private static final int LOOKUP_OVERRIDE = 1;
/**
* Index in the CGLIB callback array for a method that should
* be overridden using generic Methodreplacer functionality.
* be overridden using generic <em>method replacer</em> functionality.
*/
private static final int METHOD_REPLACER = 2;
@@ -72,7 +73,7 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
@Override
protected Object instantiateWithMethodInjection(
RootBeanDefinition beanDefinition, String beanName, BeanFactory owner,
Constructor ctor, Object[] args) {
Constructor<?> ctor, Object[] args) {
return new CglibSubclassCreator(beanDefinition, owner).instantiate(ctor, args);
}
@@ -96,17 +97,18 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
}
/**
* Create a new instance of a dynamically generated subclasses implementing the
* Create a new instance of a dynamically generated subclass implementing the
* required lookups.
* @param ctor constructor to use. If this is {@code null}, use the
* no-arg constructor (no parameterization, or Setter Injection)
* @param args arguments to use for the constructor.
* Ignored if the ctor parameter is {@code null}.
* @return new instance of the dynamically generated class
* Ignored if the {@code ctor} parameter is {@code null}.
* @return new instance of the dynamically generated subclass
*/
public Object instantiate(Constructor ctor, Object[] args) {
public Object instantiate(Constructor<?> ctor, Object[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.beanDefinition.getBeanClass());
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setCallbackFilter(new CallbackFilterImpl());
enhancer.setCallbacks(new Callback[] {
NoOp.INSTANCE,
@@ -114,9 +116,7 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
new ReplaceOverrideMethodInterceptor()
});
return (ctor == null) ?
enhancer.create() :
enhancer.create(ctor.getParameterTypes(), args);
return (ctor != null ? enhancer.create(ctor.getParameterTypes(), args) : enhancer.create());
}
@@ -17,6 +17,7 @@
package org.springframework.beans.factory.support;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.util.ObjectUtils;
@@ -127,7 +128,7 @@ public class ChildBeanDefinition extends AbstractBeanDefinition {
* @param original the original bean definition to copy from
*/
public ChildBeanDefinition(ChildBeanDefinition original) {
super(original);
super((BeanDefinition) original);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author 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,12 +54,9 @@ import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
/**
* Helper class for resolving constructors and factory methods.
* Delegate for resolving constructors and factory methods.
* Performs constructor resolution through argument matching.
*
* <p>Operates on an {@link AbstractBeanFactory} and an {@link InstantiationStrategy}.
* Used by {@link AbstractAutowireCapableBeanFactory}.
*
* @author Juergen Hoeller
* @author Rob Harrop
* @author Mark Fisher
@@ -103,12 +100,12 @@ class ConstructorResolver {
* @return a BeanWrapper for the new instance
*/
public BeanWrapper autowireConstructor(
final String beanName, final RootBeanDefinition mbd, Constructor[] chosenCtors, final Object[] explicitArgs) {
final String beanName, final RootBeanDefinition mbd, Constructor<?>[] chosenCtors, final Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
Constructor constructorToUse = null;
Constructor<?> constructorToUse = null;
ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null;
@@ -118,7 +115,7 @@ class ConstructorResolver {
else {
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
constructorToUse = (Constructor) mbd.resolvedConstructorOrFactoryMethod;
constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
// Found a cached constructor...
argsToUse = mbd.resolvedConstructorArguments;
@@ -149,7 +146,7 @@ class ConstructorResolver {
}
// Take specified constructors, if any.
Constructor[] candidates = chosenCtors;
Constructor<?>[] candidates = chosenCtors;
if (candidates == null) {
Class<?> beanClass = mbd.getBeanClass();
try {
@@ -164,7 +161,7 @@ class ConstructorResolver {
}
AutowireUtils.sortConstructors(candidates);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Constructor> ambiguousConstructors = null;
Set<Constructor<?>> ambiguousConstructors = null;
List<Exception> causes = null;
for (int i = 0; i < candidates.length; i++) {
@@ -185,7 +182,7 @@ class ConstructorResolver {
try {
String[] paramNames = null;
if (constructorPropertiesAnnotationAvailable) {
paramNames = ConstructorPropertiesChecker.evaluateAnnotation(candidate, paramTypes.length);
paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
}
if (paramNames == null) {
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
@@ -239,7 +236,7 @@ class ConstructorResolver {
}
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<Constructor>();
ambiguousConstructors = new LinkedHashSet<Constructor<?>>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
@@ -267,7 +264,7 @@ class ConstructorResolver {
Object beanInstance;
if (System.getSecurityManager() != null) {
final Constructor ctorToUse = constructorToUse;
final Constructor<?> ctorToUse = constructorToUse;
final Object[] argumentsToUse = argsToUse;
beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
@@ -295,18 +292,22 @@ class ConstructorResolver {
* @param mbd the bean definition to check
*/
public void resolveFactoryMethodIfPossible(RootBeanDefinition mbd) {
Class factoryClass;
Class<?> factoryClass;
boolean isStatic;
if (mbd.getFactoryBeanName() != null) {
factoryClass = this.beanFactory.getType(mbd.getFactoryBeanName());
isStatic = false;
}
else {
factoryClass = mbd.getBeanClass();
isStatic = true;
}
factoryClass = ClassUtils.getUserClass(factoryClass);
Method[] candidates = ReflectionUtils.getAllDeclaredMethods(factoryClass);
Method[] candidates = getCandidateMethods(factoryClass, mbd);
Method uniqueCandidate = null;
for (Method candidate : candidates) {
if (mbd.isFactoryMethod(candidate)) {
if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
if (uniqueCandidate == null) {
uniqueCandidate = candidate;
}
@@ -321,6 +322,27 @@ class ConstructorResolver {
}
}
/**
* Retrieve all candidate methods for the given class, considering
* the {@link RootBeanDefinition#isNonPublicAccessAllowed()} flag.
* Called as the starting point for factory method determination.
*/
private Method[] getCandidateMethods(final Class<?> factoryClass, final RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
@Override
public Method[] run() {
return (mbd.isNonPublicAccessAllowed() ?
ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods());
}
});
}
else {
return (mbd.isNonPublicAccessAllowed() ?
ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods());
}
}
/**
* Instantiate the bean using a named factory method. The method may be static, if the
* bean definition parameter specifies a class, rather than a "factory-bean", or
@@ -336,7 +358,9 @@ class ConstructorResolver {
* method, or {@code null} if none (-> use constructor argument values from bean definition)
* @return a BeanWrapper for the new instance
*/
public BeanWrapper instantiateUsingFactoryMethod(final String beanName, final RootBeanDefinition mbd, final Object[] explicitArgs) {
public BeanWrapper instantiateUsingFactoryMethod(
final String beanName, final RootBeanDefinition mbd, final Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
@@ -353,7 +377,7 @@ class ConstructorResolver {
factoryBean = this.beanFactory.getBean(factoryBeanName);
if (factoryBean == null) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"factory-bean '" + factoryBeanName + "' returned null");
"factory-bean '" + factoryBeanName + "' (or a BeanPostProcessor involved) returned null");
}
factoryClass = factoryBean.getClass();
isStatic = false;
@@ -397,27 +421,11 @@ class ConstructorResolver {
// Need to determine the factory method...
// Try all methods with this name to see if they match the given arguments.
factoryClass = ClassUtils.getUserClass(factoryClass);
Method[] rawCandidates;
final Class<?> factoryClazz = factoryClass;
if (System.getSecurityManager() != null) {
rawCandidates = AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
public Method[] run() {
return (mbd.isNonPublicAccessAllowed() ?
ReflectionUtils.getAllDeclaredMethods(factoryClazz) : factoryClazz.getMethods());
}
});
}
else {
rawCandidates = (mbd.isNonPublicAccessAllowed() ?
ReflectionUtils.getAllDeclaredMethods(factoryClazz) : factoryClazz.getMethods());
}
Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
List<Method> candidateSet = new ArrayList<Method>();
for (Method candidate : rawCandidates) {
if (Modifier.isStatic(candidate.getModifiers()) == isStatic &&
candidate.getName().equals(mbd.getFactoryMethodName()) &&
mbd.isFactoryMethod(candidate)) {
if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
candidateSet.add(candidate);
}
}
@@ -522,24 +530,30 @@ 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());
List<String> argTypes = new ArrayList<String>(minNrOfArgs);
if (explicitArgs != null) {
for (Object arg : explicitArgs) {
argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
}
}
else {
Set<ValueHolder> valueHolders = new LinkedHashSet<ValueHolder>(resolvedValues.getArgumentCount());
valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
valueHolders.addAll(resolvedValues.getGenericArgumentValues());
for (ValueHolder value : valueHolders) {
String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) :
(value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null"));
argTypes.add(argType);
}
argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
}
String 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() + "(" + argDesc + ")'. " +
"Check that a method with the specified name " +
(hasArgs ? "and arguments " : "") +
(minNrOfArgs > 0 ? "and arguments " : "") +
"exists and that it is " +
(isStatic ? "static" : "non-static") + ".");
}
@@ -759,7 +773,7 @@ class ConstructorResolver {
String beanName, RootBeanDefinition mbd, BeanWrapper bw, Member methodOrCtor, Object[] argsToResolve) {
Class<?>[] paramTypes = (methodOrCtor instanceof Method ?
((Method) methodOrCtor).getParameterTypes() : ((Constructor) methodOrCtor).getParameterTypes());
((Method) methodOrCtor).getParameterTypes() : ((Constructor<?>) methodOrCtor).getParameterTypes());
TypeConverter converter = (this.beanFactory.getCustomTypeConverter() != null ?
this.beanFactory.getCustomTypeConverter() : bw);
BeanDefinitionValueResolver valueResolver =
@@ -881,7 +895,7 @@ class ConstructorResolver {
*/
private static class ConstructorPropertiesChecker {
public static String[] evaluateAnnotation(Constructor<?> candidate, int paramCount) {
public static String[] evaluate(Constructor<?> candidate, int paramCount) {
ConstructorProperties cp = candidate.getAnnotation(ConstructorProperties.class);
if (cp != null) {
String[] names = cp.value();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -59,6 +59,7 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
@@ -102,9 +103,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
private static Class<?> javaxInjectProviderClass = null;
static {
ClassLoader cl = DefaultListableBeanFactory.class.getClassLoader();
try {
javaxInjectProviderClass = cl.loadClass("javax.inject.Provider");
javaxInjectProviderClass =
ClassUtils.forName("javax.inject.Provider", DefaultListableBeanFactory.class.getClassLoader());
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - Provider interface simply not supported then.
@@ -134,14 +135,14 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
/** Map of bean definition objects, keyed by bean name */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
/** Map of singleton and non-singleton bean names keyed by dependency type */
/** Map of singleton and non-singleton bean names, keyed by dependency type */
private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
/** Map of singleton-only bean names keyed by dependency type */
/** Map of singleton-only bean names, keyed by dependency type */
private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
/** List of bean definition names, in registration order */
private final List<String> beanDefinitionNames = new ArrayList<String>();
private final List<String> beanDefinitionNames = new ArrayList<String>(64);
/** Whether bean definition metadata may be cached for all beans */
private boolean configurationFrozen = false;
@@ -260,7 +261,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
if (beanNames.length > 1) {
ArrayList<String> autowireCandidates = new ArrayList<String>();
for (String beanName : beanNames) {
if (getBeanDefinition(beanName).isAutowireCandidate()) {
if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
autowireCandidates.add(beanName);
}
}
@@ -322,7 +323,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
public String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
return doGetBeanNamesForType(type, includeNonSingletons, allowEagerInit);
}
Map<Class<?>, String[]> cache =
@@ -332,7 +333,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
return resolvedBeanNames;
}
resolvedBeanNames = doGetBeanNamesForType(type, includeNonSingletons, allowEagerInit);
cache.put(type, resolvedBeanNames);
if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
cache.put(type, resolvedBeanNames);
}
return resolvedBeanNames;
}
@@ -480,7 +483,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
* found on the given class itself, as well as checking its raw bean class
* if not found on the exposed bean reference (e.g. in case of a proxy).
*/
public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType) {
public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
throws NoSuchBeanDefinitionException{
A ann = null;
Class<?> beanType = getType(beanName);
if (beanType != null) {
@@ -597,12 +602,15 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
if (this.logger.isInfoEnabled()) {
this.logger.info("Pre-instantiating singletons in " + this);
}
List<String> beanNames;
synchronized (this.beanDefinitionMap) {
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
beanNames = new ArrayList<String>(this.beanDefinitionNames);
}
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
@@ -652,8 +660,10 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
}
BeanDefinition oldBeanDefinition;
synchronized (this.beanDefinitionMap) {
Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!this.allowBeanDefinitionOverriding) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
@@ -674,7 +684,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
this.beanDefinitionMap.put(beanName, beanDefinition);
}
resetBeanDefinition(beanName);
if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
@@ -709,9 +721,6 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
// (e.g. the default StaticMessageSource in a StaticApplicationContext).
destroySingleton(beanName);
// Remove any assumptions about by-type mappings.
clearByTypeCache();
// Reset all bean definitions that have the given bean as parent (recursively).
for (String bdName : this.beanDefinitionNames) {
if (!beanName.equals(bdName)) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -317,7 +317,7 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
/**
* Callback before singleton creation.
* <p>Default implementation register the singleton as currently in creation.
* <p>The default implementation register the singleton as currently in creation.
* @param beanName the name of the singleton about to be created
* @see #isSingletonCurrentlyInCreation
*/
@@ -539,13 +539,13 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
}
/**
* Expose the singleton mutex to subclasses.
* Exposes the singleton mutex to subclasses and external collaborators.
* <p>Subclasses should synchronize on the given Object if they perform
* any sort of extended singleton creation phase. In particular, subclasses
* should <i>not</i> have their own mutexes involved in singleton creation,
* to avoid the potential for deadlocks in lazy-init situations.
*/
protected final Object getSingletonMutex() {
public final Object getSingletonMutex() {
return this.singletonObjects;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -65,11 +65,12 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
private static final Log logger = LogFactory.getLog(DisposableBeanAdapter.class);
private static Class closeableInterface;
private static Class<?> closeableInterface;
static {
try {
closeableInterface = DisposableBeanAdapter.class.getClassLoader().loadClass("java.lang.AutoCloseable");
closeableInterface = ClassUtils.forName("java.lang.AutoCloseable",
DisposableBeanAdapter.class.getClassLoader());
}
catch (ClassNotFoundException ex) {
closeableInterface = Closeable.class;
@@ -85,14 +86,14 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
private final boolean nonPublicAccessAllowed;
private final AccessControlContext acc;
private String destroyMethodName;
private transient Method destroyMethod;
private List<DestructionAwareBeanPostProcessor> beanPostProcessors;
private final AccessControlContext acc;
/**
* Create a new DisposableBeanAdapter for the given bean.
@@ -149,9 +150,9 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
this.beanName = beanName;
this.invokeDisposableBean = invokeDisposableBean;
this.nonPublicAccessAllowed = nonPublicAccessAllowed;
this.acc = null;
this.destroyMethodName = destroyMethodName;
this.beanPostProcessors = postProcessors;
this.acc = null;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -89,7 +89,7 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
* Obtain an object to expose from the given FactoryBean.
* @param factory the FactoryBean instance
* @param beanName the name of the bean
* @param shouldPostProcess whether the bean is subject for post-processing
* @param shouldPostProcess whether the bean is subject to post-processing
* @return the object obtained from the FactoryBean
* @throws BeanCreationException if FactoryBean object creation failed
* @see org.springframework.beans.factory.FactoryBean#getObject()
@@ -99,14 +99,40 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
object = doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
object = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (object != null && shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
}
this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
}
}
return (object != NULL_OBJECT ? object : null);
}
}
else {
return doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (object != null && shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
@@ -114,13 +140,11 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
* Obtain an object to expose from the given FactoryBean.
* @param factory the FactoryBean instance
* @param beanName the name of the bean
* @param shouldPostProcess whether the bean is subject for post-processing
* @return the object obtained from the FactoryBean
* @throws BeanCreationException if FactoryBean object creation failed
* @see org.springframework.beans.factory.FactoryBean#getObject()
*/
private Object doGetObjectFromFactoryBean(
final FactoryBean<?> factory, final String beanName, final boolean shouldPostProcess)
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException {
Object object;
@@ -149,23 +173,12 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
// Do not accept a null value for a FactoryBean that's not fully
// initialized yet: Many FactoryBeans just return null then.
if (object == null && isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
if (object != null && shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of the FactoryBean's object failed", ex);
}
}
return object;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -87,7 +87,12 @@ public class GenericBeanDefinition extends AbstractBeanDefinition {
@Override
public String toString() {
return "Generic bean: " + super.toString();
StringBuilder sb = new StringBuilder("Generic bean");
if (this.parentName != null) {
sb.append(" with parent '").append(this.parentName).append("'");
}
sb.append(": ").append(super.toString());
return sb.toString();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,10 +37,9 @@ public class LookupOverride extends MethodOverride {
/**
* Construct a new LookupOverride.
* @param methodName the name of the method to override.
* This method must have no arguments.
* @param beanName name of the bean in the current BeanFactory
* that the overriden method should return
* @param methodName the name of the method to override
* @param beanName the name of the bean in the current BeanFactory
* that the overridden method should return
*/
public LookupOverride(String methodName, String beanName) {
super(methodName);
@@ -48,6 +47,7 @@ public class LookupOverride extends MethodOverride {
this.beanName = beanName;
}
/**
* Return the name of the bean that should be returned by this method.
*/
@@ -55,9 +55,8 @@ public class LookupOverride extends MethodOverride {
return this.beanName;
}
/**
* Match method of the given name, with no parameters.
* Match the method of the given name, with no parameters.
*/
@Override
public boolean matches(Method method) {
@@ -65,11 +64,6 @@ public class LookupOverride extends MethodOverride {
}
@Override
public String toString() {
return "LookupOverride for method '" + getMethodName() + "'; will return bean '" + this.beanName + "'";
}
@Override
public boolean equals(Object other) {
return (other instanceof LookupOverride && super.equals(other) &&
@@ -81,4 +75,9 @@ public class LookupOverride extends MethodOverride {
return (29 * super.hashCode() + ObjectUtils.nullSafeHashCode(this.beanName));
}
@Override
public String toString() {
return "LookupOverride for method '" + getMethodName() + "'; will return bean '" + this.beanName + "'";
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,14 +23,15 @@ import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
* Object representing the override of a method on a managed
* object by the IoC container.
* Object representing the override of a method on a managed object by the IoC
* container.
*
* <p>Note that the override mechanism is <i>not</i> intended as a
* generic means of inserting crosscutting code: use AOP for that.
* <p>Note that the override mechanism is <em>not</em> intended as a generic
* means of inserting crosscutting code: use AOP for that.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @author Sam Brannen
* @since 1.1
*/
public abstract class MethodOverride implements BeanMetadataElement {
@@ -51,6 +52,7 @@ public abstract class MethodOverride implements BeanMetadataElement {
this.methodName = methodName;
}
/**
* Return the name of the method to be overridden.
*/
@@ -59,17 +61,18 @@ public abstract class MethodOverride implements BeanMetadataElement {
}
/**
* Set whether the overridden method has to be considered as overloaded
* (that is, whether arg type matching has to happen).
* <p>Default is "true"; can be switched to "false" to optimize runtime performance.
* Set whether the overridden method is <em>overloaded</em> (i.e., whether argument
* type matching needs to occur to disambiguate methods of the same name).
* <p>Default is {@code true}; can be switched to {@code false} to optimize
* runtime performance.
*/
protected void setOverloaded(boolean overloaded) {
this.overloaded = overloaded;
}
/**
* Return whether the overridden method has to be considered as overloaded
* (that is, whether arg type matching has to happen).
* Return whether the overridden method is <em>overloaded</em> (i.e., whether argument
* type matching needs to occur to disambiguate methods of the same name).
*/
protected boolean isOverloaded() {
return this.overloaded;
@@ -87,11 +90,10 @@ public abstract class MethodOverride implements BeanMetadataElement {
return this.source;
}
/**
* Subclasses must override this to indicate whether they match
* the given method. This allows for argument list checking
* as well as method name checking.
* Subclasses must override this to indicate whether they <em>match</em> the
* given method. This allows for argument list checking as well as method
* name checking.
* @param method the method to check
* @return whether this override matches the given method
*/
@@ -108,7 +110,6 @@ public abstract class MethodOverride implements BeanMetadataElement {
}
MethodOverride that = (MethodOverride) other;
return (ObjectUtils.nullSafeEquals(this.methodName, that.methodName) &&
this.overloaded == that.overloaded &&
ObjectUtils.nullSafeEquals(this.source, that.source));
}
@@ -116,7 +117,6 @@ public abstract class MethodOverride implements BeanMetadataElement {
public int hashCode() {
int hashCode = ObjectUtils.nullSafeHashCode(this.methodName);
hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.source);
hashCode = 29 * hashCode + (this.overloaded ? 1 : 0);
return hashCode;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author 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,6 +52,7 @@ public class ReplaceOverride extends MethodOverride {
this.methodReplacerBeanName = methodReplacerBeanName;
}
/**
* Return the name of the bean implementing MethodReplacer.
*/
@@ -68,28 +69,22 @@ public class ReplaceOverride extends MethodOverride {
this.typeIdentifiers.add(identifier);
}
@Override
public boolean matches(Method method) {
// TODO could cache result for efficiency
if (!method.getName().equals(getMethodName())) {
// It can't match.
return false;
}
if (!isOverloaded()) {
// No overloaded: don't worry about arg type matching.
// Not overloaded: don't worry about arg type matching...
return true;
}
// If we get to here, we need to insist on precise argument matching.
// If we get here, we need to insist on precise argument matching...
if (this.typeIdentifiers.size() != method.getParameterTypes().length) {
return false;
}
for (int i = 0; i < this.typeIdentifiers.size(); i++) {
String identifier = this.typeIdentifiers.get(i);
if (!method.getParameterTypes()[i].getName().contains(identifier)) {
// This parameter cannot match.
return false;
}
}
@@ -97,12 +92,6 @@ public class ReplaceOverride extends MethodOverride {
}
@Override
public String toString() {
return "Replace override for method '" + getMethodName() + "; will call bean '" +
this.methodReplacerBeanName + "'";
}
@Override
public boolean equals(Object other) {
if (!(other instanceof ReplaceOverride) || !super.equals(other)) {
@@ -121,4 +110,10 @@ public class ReplaceOverride extends MethodOverride {
return hashCode;
}
@Override
public String toString() {
return "Replace override for method '" + getMethodName() + "; will call bean '" +
this.methodReplacerBeanName + "'";
}
}
@@ -18,8 +18,8 @@ package org.springframework.beans.factory.support;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.HashSet;
import java.util.Set;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
@@ -48,19 +48,10 @@ import org.springframework.util.Assert;
@SuppressWarnings("serial")
public class RootBeanDefinition extends AbstractBeanDefinition {
// using a ConcurrentHashMap as a Set
private final Map<Member, Boolean> externallyManagedConfigMembers = new ConcurrentHashMap<Member, Boolean>(0);
// using a ConcurrentHashMap as a Set
private final Map<String, Boolean> externallyManagedInitMethods = new ConcurrentHashMap<String, Boolean>(0);
// using a ConcurrentHashMap as a Set
private final Map<String, Boolean> externallyManagedDestroyMethods = new ConcurrentHashMap<String, Boolean>(0);
boolean allowCaching = true;
private BeanDefinitionHolder decoratedDefinition;
boolean allowCaching = true;
private volatile Class<?> targetType;
boolean isFactoryMethodUnique = false;
@@ -87,6 +78,12 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
/** Package-visible field that indicates a before-instantiation post-processor having kicked in */
volatile Boolean beforeInstantiationResolved;
private Set<Member> externallyManagedConfigMembers;
private Set<String> externallyManagedInitMethods;
private Set<String> externallyManagedDestroyMethods;
/**
* Create a new RootBeanDefinition, to be configured through its bean
@@ -225,9 +222,9 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
* @param original the original bean definition to copy from
*/
public RootBeanDefinition(RootBeanDefinition original) {
super(original);
this.decoratedDefinition = original.decoratedDefinition;
super((BeanDefinition) original);
this.allowCaching = original.allowCaching;
this.decoratedDefinition = original.decoratedDefinition;
this.targetType = original.targetType;
this.isFactoryMethodUnique = original.isFactoryMethodUnique;
}
@@ -252,6 +249,20 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
}
}
/**
* Register a target definition that is being decorated by this bean definition.
*/
public void setDecoratedDefinition(BeanDefinitionHolder decoratedDefinition) {
this.decoratedDefinition = decoratedDefinition;
}
/**
* Return the target definition that is being decorated by this bean definition, if any.
*/
public BeanDefinitionHolder getDecoratedDefinition() {
return this.decoratedDefinition;
}
/**
* Specify the target type of this bean definition, if known in advance.
*/
@@ -294,37 +305,52 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
}
}
public void registerExternallyManagedConfigMember(Member configMember) {
this.externallyManagedConfigMembers.put(configMember, Boolean.TRUE);
synchronized (this.postProcessingLock) {
if (this.externallyManagedConfigMembers == null) {
this.externallyManagedConfigMembers = new HashSet<Member>(1);
}
this.externallyManagedConfigMembers.add(configMember);
}
}
public boolean isExternallyManagedConfigMember(Member configMember) {
return this.externallyManagedConfigMembers.containsKey(configMember);
synchronized (this.postProcessingLock) {
return (this.externallyManagedConfigMembers != null &&
this.externallyManagedConfigMembers.contains(configMember));
}
}
public void registerExternallyManagedInitMethod(String initMethod) {
this.externallyManagedInitMethods.put(initMethod, Boolean.TRUE);
synchronized (this.postProcessingLock) {
if (this.externallyManagedInitMethods == null) {
this.externallyManagedInitMethods = new HashSet<String>(1);
}
this.externallyManagedInitMethods.add(initMethod);
}
}
public boolean isExternallyManagedInitMethod(String initMethod) {
return this.externallyManagedInitMethods.containsKey(initMethod);
synchronized (this.postProcessingLock) {
return (this.externallyManagedInitMethods != null &&
this.externallyManagedInitMethods.contains(initMethod));
}
}
public void registerExternallyManagedDestroyMethod(String destroyMethod) {
this.externallyManagedDestroyMethods.put(destroyMethod, Boolean.TRUE);
synchronized (this.postProcessingLock) {
if (this.externallyManagedDestroyMethods == null) {
this.externallyManagedDestroyMethods = new HashSet<String>(1);
}
this.externallyManagedDestroyMethods.add(destroyMethod);
}
}
public boolean isExternallyManagedDestroyMethod(String destroyMethod) {
return this.externallyManagedDestroyMethods.containsKey(destroyMethod);
}
public void setDecoratedDefinition(BeanDefinitionHolder decoratedDefinition) {
this.decoratedDefinition = decoratedDefinition;
}
public BeanDefinitionHolder getDecoratedDefinition() {
return this.decoratedDefinition;
synchronized (this.postProcessingLock) {
return (this.externallyManagedDestroyMethods != null &&
this.externallyManagedDestroyMethods.contains(destroyMethod));
}
}
@@ -62,14 +62,14 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
synchronized (beanDefinition.constructorArgumentLock) {
constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class clazz = beanDefinition.getBeanClass();
final Class<?> clazz = beanDefinition.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor>() {
public Constructor run() throws Exception {
public Constructor<?> run() throws Exception {
return clazz.getDeclaredConstructor((Class[]) null);
}
});
@@ -132,7 +132,7 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
* Instantiation should use the given constructor and parameters.
*/
protected Object instantiateWithMethodInjection(RootBeanDefinition beanDefinition,
String beanName, BeanFactory owner, Constructor ctor, Object[] args) {
String beanName, BeanFactory owner, Constructor<?> ctor, Object[] args) {
throw new UnsupportedOperationException(
"Method Injection not supported in SimpleInstantiationStrategy");
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -129,7 +129,7 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
public Object getBean(String name, Object... args) throws BeansException {
if (args != null) {
throw new UnsupportedOperationException(
"StaticListableBeanFactory does not support explicit bean creation arguments)");
"StaticListableBeanFactory does not support explicit bean creation arguments");
}
return getBean(name);
}
@@ -149,7 +149,7 @@ public abstract class AbstractSimpleBeanDefinitionParser extends AbstractSingleB
*/
protected boolean isEligibleAttribute(Attr attribute, ParserContext parserContext) {
boolean eligible = isEligibleAttribute(attribute);
if(!eligible) {
if (!eligible) {
String fullName = attribute.getName();
eligible = (!fullName.equals("xmlns") && !fullName.startsWith("xmlns:") &&
isEligibleAttribute(parserContext.getDelegate().getLocalName(attribute)));

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