Compare commits

...

124 Commits

Author SHA1 Message Date
Spring Buildmaster e5f530d33c Release version 4.0.5 2014-05-20 06:40:52 -07:00
Juergen Hoeller e3e71ba92a Servlet 3 multipart request implements getParameterMap defensively as well
Issue: SPR-11074
(cherry picked from commit c7d1c49)
2014-05-20 11:11:56 +02:00
Juergen Hoeller d4e1b9eb4c Polishing
(cherry picked from commit 6fef8b9)
2014-05-20 11:11:33 +02:00
Rossen Stoyanchev 44ee51a6c9 Disable URL resolution in DTD declarations
Issue: SPR-11768
2014-05-19 22:23:51 -04:00
Juergen Hoeller ba6d187b5c Consistent MvcUriComponentsBuilder assertion handling
(cherry picked from commit 61b47ba)
2014-05-20 01:51:33 +02:00
Juergen Hoeller 54636b3f7c Further UriComponentsBuilder javadoc revision 2014-05-20 01:13:18 +02:00
Juergen Hoeller 545c28fd4e Minor UriComponentsBuilder javadoc revision 2014-05-20 00:47:03 +02:00
Juergen Hoeller 95a7bfd327 Consistent use of IllegalStateException instead of InternalError for UnsupportedEncodingException cause
(cherry picked from commit d9b39ad)
2014-05-20 00:42:48 +02:00
Juergen Hoeller ccebbf74ec Latest patches from ASM trunk
(cherry picked from commit cfc720d)
2014-05-19 22:59:39 +02:00
Juergen Hoeller c350080f99 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 22:46:47 +02:00
Juergen Hoeller 6b9738fd68 Building against latest javax.el 2.2.x version
(cherry picked from commit f73a8ba)
2014-05-19 20:46:42 +02:00
Juergen Hoeller 1120680c65 Consistently log Class.getName() instead of Class.toString(), avoiding double class term in log message
Issue: SPR-11804
(cherry picked from commit 2619955)
2014-05-19 20:46:14 +02:00
Juergen Hoeller a2ef2c9d3e Refined check for NoClassDefFoundError in getTestExecutionListeners()
Issue: SPR-11804
(cherry picked from commit 41ed228)
2014-05-19 17:28:37 +02:00
Juergen Hoeller 1bbc032071 Backported proper updateAccessedAttributes test
Issue: SPR-11738
(cherry picked from commit 6188550)
2014-05-19 16:42:42 +02:00
Juergen Hoeller c70a81a805 Javadoc fixes 2014-05-19 00:08:46 +02:00
Juergen Hoeller 3c709a763d 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:27:44 +02:00
Juergen Hoeller 7d78c65187 Properly evaluate @Conditional in case of multiple imports for same config class (fixing regression in Spring Boot)
Issue: SPR-11788
2014-05-18 02:00:11 +02:00
Rossen Stoyanchev 748167bfa3 Improve StringUtils.cleanPath
Issue: SPR-11793
2014-05-16 11:27:55 -04:00
Juergen Hoeller 3e70013b55 JmsResourceHolder checks for nested DataSource transactions as well (for Oracle AQ compatibility)
Issue: SPR-11791
(cherry picked from commit 5faacd5)
2014-05-16 15:36:16 +02:00
Juergen Hoeller ea9ad4ee9b Properly evaluate @Conditional in case of multiple imports for same config class
Issue: SPR-11788
(cherry picked from commit 52f44b3)
2014-05-16 15:35:56 +02:00
Rossen Stoyanchev 482eff81e1 Await TcpClient shutdown in STOMP relay 2014-05-15 21:46:44 -04:00
Juergen Hoeller c706cbbed4 Latest possible dependency updates for spring-orm
(cherry picked from commit 0d22719)
2014-05-15 17:35:32 +02:00
Juergen Hoeller 7bc38acbf6 Polishing 2014-05-15 15:23:11 +02:00
Juergen Hoeller 297e4eec36 Keep unused MemorySafeUndeclaredThrowableStrategy around in deprecated form for the 4.0.x line
Issue: SPR-11782
2014-05-15 15:05:00 +02:00
Juergen Hoeller 235b65d103 Polishing
(cherry picked from commit b0f0d2f)
2014-05-15 14:43:02 +02:00
Juergen Hoeller 8a28645dd6 ResultSetWrappingSqlRowSet preserves first matching column per name (as defined in ResultSet's javadoc)
Issue: SPR-11786
(cherry picked from commit 0728e32)
2014-05-15 14:40:43 +02:00
Juergen Hoeller f94ded830d Consistent use of ClassUtils.forName instead of class.getClassLoader().loadClass
Issue: SPR-11780
(cherry picked from commit 551950c)
2014-05-15 14:40:15 +02:00
Juergen Hoeller ad8f17b6af Test compatibility with JasperReports 5.5.2 2014-05-12 23:35:17 +02:00
Juergen Hoeller 261520cea0 Undertow-related polishing
(cherry picked from commit 2750ab6)
2014-05-12 23:32:12 +02:00
Juergen Hoeller 00aa40b8da Consistent EhCache version between 4.1 and 4.0.5 2014-05-12 23:27:16 +02:00
Juergen Hoeller ac9b64e528 Consistent declaration of JSP, JSTL and JavaMail API dependencies; updated several dependencies to latest maintenance releases (Tiles 3.0.4, Jetty 9.1.5) 2014-05-12 21:50:13 +02:00
Juergen Hoeller 1e7fade89e JasperReports-related polishing
(cherry picked from commit 782d10c)
2014-05-12 20:50:24 +02:00
Stephane Nicoll 3c58be05a5 Fix typo
Issue: SPR-11571
(cherry picked from commit 6551aa6)
2014-05-08 16:38:08 +02:00
Juergen Hoeller ef290ff95c Additional tests for configuration class importing via ASM
Issue: SPR-11647
(cherry picked from commit 8c9116f)
2014-05-08 16:31:07 +02:00
Juergen Hoeller ae45794451 IdToEntityConverter defensively handles access to getDeclaredMethods
Issue: SPR-11758
(cherry picked from commit 381ccde)
2014-05-08 16:30:45 +02:00
Juergen Hoeller fccec210b4 GenericTypeResolver returns null for entirely unresolvable type arguments only
Issue: SPR-11763
(cherry picked from commit bea34ea)
2014-05-08 16:28:53 +02:00
Sebastien Deleuze 96da77ef75 Avoid ConcurrentModificationException
Removal of cached destination is now moved outside the for loop
that removes subscriptions to avoid ConcurrentModificationException.

Also since updateCache is a LinkedHashMap with accessOrder=true,
a simple access with updateCache.get() modify the map.
By iterating over updateCache.entrySet(), we avoid this update.

Issue: SPR-11755
2014-05-06 20:22:05 -04:00
Juergen Hoeller c9417d0610 Fixed invalid code tag in javadoc
(cherry picked from commit a139670)
2014-05-01 10:55:55 +02:00
Spring Buildmaster 085e52fc31 Next development version 2014-04-30 15:41:11 -07:00
Juergen Hoeller 8f175046c8 spring-orm-hibernate4 requires aopalliance dependency now (after propdeps upgrade) 2014-04-30 23:19:07 +02:00
Juergen Hoeller c1dbd9f150 Upgraded to propdeps plugin 0.0.6
(cherry picked from commit a842b93)
2014-04-30 22:58:56 +02:00
Juergen Hoeller 42a35ef3be AnnotationMetadataReadingVisitor passes metaAnnotationMap into getMergedAnnotationAttributes algorithm, for finding out about applicable overrides
Issue: SPR-11649
(cherry picked from commit 842a8a8)
2014-04-30 22:57:09 +02:00
Rossen Stoyanchev 21fd68150a Log ignored CONNECT messages at error level
Issue: SPR-11673
2014-04-30 11:12:32 -04:00
Rossen Stoyanchev d20259be1d Log STOMP ERROR frames at error level
Issue: SPR-11673
2014-04-30 11:01:18 -04:00
Rossen Stoyanchev 6ca921021c Update log level
Issue: SPR-11673
2014-04-30 10:28:27 -04:00
Rossen Stoyanchev eab9d24c31 Fix Javadoc typo 2014-04-30 10:07:51 -04:00
Juergen Hoeller 15749c2a9d Upgraded to Gradle 1.12 and updated several dependencies to latest maintenance releases
(cherry picked from commit e84f61b)
2014-04-30 14:32:12 +02:00
Juergen Hoeller 93b0f0b126 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 14:32:07 +02:00
Juergen Hoeller 27b2ed1614 Spring Framework build uses Reactor 1.1 GA now, getting rid of last remaining pre-GA dependency 2014-04-30 11:41:57 +02:00
Rossen Stoyanchev 790d62bcb1 Simplify and improve STOMP broker relay int tests 2014-04-29 23:01:40 -04:00
Rossen Stoyanchev 563476f57c Split destination cache into access vs update
Issue: SPR-11657
2014-04-29 22:16:49 -04:00
Rossen Stoyanchev 79de45b805 Add cache limit to DefaultSessionRegistry and polish
Issue: SPR-11657
2014-04-29 18:17:40 -04:00
Sebastien Deleuze 63a868dafb Fix DefaultSubscriptionRegistry when using pattern destinations
DestinationCache is now used for both plain and pattern
destinations. It stores internally the subscriptions map for each
cached destination. Subscriptions are initially created when there
is no cache for the requested destination, and are updated when
subscriptions change.

Issue: SPR-11657
2014-04-29 18:17:30 -04:00
Juergen Hoeller 1afdd9bd75 Polishing
(cherry picked from commit 02aca9c)
2014-04-30 00:10:58 +02:00
Juergen Hoeller d0c839f0eb Polishing 2014-04-29 16:21:06 +02:00
Juergen Hoeller 744727b8aa 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 16:01:44 +02:00
Rossen Stoyanchev 9fbb7394e2 Polish STOMP documentation 2014-04-28 22:35:51 -04:00
Sebastien Deleuze 80cb0c4e5b Include more guidance about DispatcherServlet context
Also update <mvc:annotation-driven /> comment in XSD.

Issue: SPR-11703
2014-04-28 22:10:52 -04:00
Rossen Stoyanchev 5c4804f4a4 Document STOMP-related ApplicationContext events
Issue: SPR-11672
2014-04-28 21:59:09 -04:00
Juergen Hoeller a679f3e7a3 Polishing
(cherry picked from commit be5f2a8)
2014-04-28 23:52:23 +02:00
Juergen Hoeller bd5b3749c5 Revised @PropertySource parsing for consistent PropertySource naming, avoiding accidental overriding by name
Issue: SPR-11637
(cherry picked from commit ab24dda)
2014-04-28 23:47:33 +02:00
Juergen Hoeller 89398b0811 AspectJExpressionPointcut defensively handles fallback expression parsing
Issue: SPR-9335
(cherry picked from commit ce4912b)
2014-04-28 23:47:25 +02:00
Juergen Hoeller a87c9b8c5c Test for base package specified as config location
Issue: SPR-11647
(cherry picked from commit 8e6e6c2)
2014-04-28 23:47:14 +02:00
Juergen Hoeller d0f9853769 Test for overriding singleton @Bean method with scoped proxy in configuration subclass
Issue: SPR-10744
(cherry picked from commit 299776f)
2014-04-28 23:46:51 +02:00
Juergen Hoeller bed739ce92 GenericBeanDefinition's toString() takes parent definition into account
Issue: SPR-9671
(cherry picked from commit 0ef29b2)
2014-04-28 23:46:40 +02:00
Rossen Stoyanchev cb712afa97 Improve handling of disconnects in STOMP broker relay
This is a backport of:
https://github.com/spring-projects/spring-framework/commit/990f5bb720ac172fa659a59339df06065d31c0bf

Issue: SPR-11655
2014-04-28 10:08:00 -04:00
Juergen Hoeller c97c246940 Polishing 2014-04-28 00:29:04 +02:00
Juergen Hoeller 4196e6c96f AbstractMarshaller avoids SAXSource workaround when processExternalEntities=true
Issue: SPR-11737
(cherry picked from commit 93d13cf)
2014-04-28 00:27:04 +02:00
Juergen Hoeller 59cef3ce81 General defensiveness about the bootstrap ClassLoader (i.e. null ClassLoader)
Issue: SPR-11721
2014-04-28 00:26:18 +02:00
Juergen Hoeller c8ea80d7ed Configuration class processing explicitly skips java.* classes since we'll never find @Bean annotations there anyway
Issue: SPR-11718
(cherry picked from commit 470e9c8)
2014-04-28 00:17:19 +02:00
Juergen Hoeller 656fc52ff9 @Bean processing explicitly ignores bridge methods (for method overrides with return type narrowing on JDK 8)
Issue: SPR-11718
(cherry picked from commit dc93406)
2014-04-28 00:16:38 +02:00
Rossen Stoyanchev a4d6f8473e Upgrade to reactor 1.1 RC1 2014-04-25 12:32:36 -04:00
Rossen Stoyanchev 443fb8e4ee Fix issue with subscribe destination
The original fix for SPR-11423:
https://github.com/spring-projects/spring-framework/commit/32e5f57e647022d9ea82c03670936bf31f8467de

was insufficient when using an external broker since the original
destination header has to be in the "native headers" map (i.e. with
STOMP headers) in order to be included in messages broadcast by
the broker.
2014-04-25 12:17:08 -04:00
Juergen Hoeller 95b1cb7173 AspectJ 1.8 final used in build, plus TestNG preparations for optional -target 1.8 usage
Issue: SPR-11212
Issue: SPR-11699
2014-04-24 11:09:39 +02:00
Juergen Hoeller 51fb485181 Polishing
(cherry picked from commit 9353332)
2014-04-24 10:32:38 +02:00
Juergen Hoeller f16e6c4105 General defensiveness about the bootstrap ClassLoader (i.e. null ClassLoader)
Issue: SPR-11721
(cherry picked from commit c05ab3e)
2014-04-24 10:31:48 +02:00
Juergen Hoeller 4dbc0c296c Polishing
(cherry picked from commit ec7d80b)
2014-04-24 10:31:39 +02:00
Juergen Hoeller d71d38bfaf ServletServerHttpResponse specifically checks for Servlet 3.0's HttpServletResponse.getHeader(String) method
Issue: SPR-11712
(cherry picked from commit 21f9ca0)
2014-04-24 10:31:29 +02:00
Juergen Hoeller eb28259371 SpringProperties falls back to ClassLoader.getSystemResource when loaded in bootstrap ClassLoader
Issue: SPR-11721
(cherry picked from commit 9cb5f48)
2014-04-24 10:31:20 +02:00
Juergen Hoeller 7ae6a60f43 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-24 10:30:49 +02:00
Juergen Hoeller d3c9a31e9a DispatcherServlet skips multipart resolution if error page exception attribute indicates MultipartException as root cause
Issue: SPR-11716
(cherry picked from commit 5b47816)
2014-04-24 10:30:12 +02:00
Juergen Hoeller 5aa126600f Final patches from ASM 5.0.2 release
Issue: SPR-11212
(cherry picked from commit fb66567)
2014-04-24 10:29:50 +02:00
Juergen Hoeller 2f15f72fcc ShallowEtagHeaderFilter writes body early on sendError/sendRedirect and interprets setContentLength/setBufferSize as a hint for capacity increase
Issue: SPR-11705
Issue: SPR-11717
(cherry picked from commit 3f392e3)
2014-04-24 10:28:42 +02:00
Juergen Hoeller d5aacdefd9 Polishing
(cherry picked from commit 700c3b2)
2014-04-24 10:27:43 +02:00
Juergen Hoeller e379e77b96 considerInterfaces should work without considerInherited as well
Issue: SPR-11719
(cherry picked from commit 5ab7076)
2014-04-24 10:27:15 +02:00
Juergen Hoeller 9c45755890 AnnotationTypeFilter prevents ASM-based loading of java.* interfaces as well
Issue: SPR-11719
(cherry picked from commit 945335d)
2014-04-24 10:26:42 +02:00
Juergen Hoeller 5962fc2590 EQ/NE do not fail in case of a Comparable mismatch and apply a specific CharSequence equality check
Issue: SPR-11708
(cherry picked from commit 66bae99)
2014-04-24 10:26:08 +02:00
Rossen Stoyanchev 1b59b4eb26 Add Reactor 11 support
This change adds support for Reactor 1.1 in spring-messaging in
addition to Reactor 1.0.1 -- whichever is present on the classpath is
used.

Note also the module name change:
reactor-tcp:1.0.1 -> reactor-net:1.1.0

Issue: SPR-11636
2014-04-23 23:35:49 -04:00
HejiaHo f6b89c2ca9 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:03:23 +01:00
Sam Brannen 82c32db5a1 Don't mutate annotation metadata when merging attrs
Prior to this commit, invoking the getMergedAnnotationAttributes()
method in AnnotationReadingVisitorUtils resulted in mutation of the
internal state of the ASM-based annotation metadata supplied to the
method.

This commit fixes this issue by making a copy of the original
AnnotationAttributes for the target annotation before merging attribute
values from the meta-annotation hierarchy.

This commit also introduces a slight performance improvement by
avoiding duplicate processing of the attributes of the target
annotation.

Issue: SPR-11710
(cherry picked from commit e1720d89fc)
2014-04-21 12:50:27 -04:00
Juergen Hoeller 52f580149f Polishing 2014-04-17 22:42:33 +02:00
Juergen Hoeller 271fe4f554 Polishing
(cherry picked from commit 48c977a)
2014-04-17 22:14:31 +02:00
Juergen Hoeller 02e8198283 MessageConversionException offers constructor without cause argument now, plus related polishing
Issue: SPR-11653
(cherry picked from commit 2888775)
2014-04-17 22:14:01 +02:00
Juergen Hoeller 090ab4bb6d XStreamMarshaller supports custom NameCoder strategy
Issue: SPR-11702
(cherry picked from commit f5cce14)
2014-04-17 21:39:34 +02:00
Juergen Hoeller 18ef1d4f76 WebSocket intro correctly points to annotations section
Issue: SPR-11667
(cherry picked from commit 53162e7)
2014-04-17 21:39:02 +02:00
Juergen Hoeller d9cb44527c Backported tests for package-visible methods with CGLIB proxies
Issue: SPR-11618
(cherry picked from commit 90309ab)
2014-04-17 21:38:01 +02:00
Juergen Hoeller 8e44521ec4 Latest ASM patches (fix for bug 317151 from ASM HEAD; ASM's 1.8 bytecode processing needs to be lenient with CGLIB 3.1)
Issue: SPR-11212
(cherry picked from commit 637ad20)
2014-04-17 21:34:57 +02:00
Juergen Hoeller d28c6d8bdb Consistent documentation for both 'close' and 'shutdown' as inferred destroy methods
Issue: SPR-11680
(cherry picked from commit 14f9dbf)
2014-04-17 21:32:09 +02:00
Juergen Hoeller c9432ce499 JDBC 3.0 related javadoc overhaul
Issue: SPR-11600
(cherry picked from commit 3fef358)
2014-04-17 21:31:45 +02:00
Stephane Nicoll 2d8e0c8f87 Fix expression cache
Prior to this commit, only the java.lang.reflect.Method was used to
identify an annotated method. As a result, if different annotations
were placed on different methods (method overriding, interface
implementation) only the first one (cached) was used.

LazyParamAwareEvaluationContext was affected by the exact
same problem and has been also fixed.

Issue: SPR-11692
(cherry picked from commit df34bab)
2014-04-15 09:29:56 +02:00
Sam Brannen 03ae8eeb95 Make EOF_STATEMENT_SEPARATOR XML friendly
Changed the value of ScriptUtils.EOF_STATEMENT_SEPARATOR from
"<<< END OF SCRIPT >>>" to "^^^ END OF SCRIPT ^^^" so that the angle
brackets do not have to be escaped in XML configuration files.

Issue: SPR-11687
(cherry picked from commit 1753f5d1ca)
2014-04-11 18:27:59 +02:00
Sam Brannen 9230b38aea Support EOF as statement separator in SQL scripts
Prior to Spring Framework 4.0.3, it was possible to supply a bogus
statement separator (i.e., a separator string that does not exist in
the configured SQL scripts) to ResourceDatabasePopulator with the side
effect that the entire contents of a script file would be interpreted
as a single SQL statement.

This undocumented feature was never intentional; however, some
developers came to rely on it. Unfortunately, changes made in
conjunction with SPR-9531 and SPR-11560 caused such scenarios to no
longer work.

This commit introduces first-class support for executing scripts which
contain a single statement that spans multiple lines but is not
followed by an explicit statement separator.

Specifically, ScriptUtils.EOF_STATEMENT_SEPARATOR may now be specified
as a 'virtual' statement separator to denote that a script contains a
single statement and no actual separator.

Issue: SPR-11687
(cherry picked from commit cc0ae3a881)
2014-04-11 18:25:06 +02:00
Sam Brannen d5ce30f360 Deprecate custom/default CtxLdr class name in TCF
Once the new bootstrap strategy for the TestContext framework (TCF) is
introduced in Spring Framework 4.1, a TestContextBootstrapper will
assume full responsibility for determining what ContextLoader to use as
the default. Consequently, the previous support for supplying the class
name for a custom, default ContextLoader will no longer be applicable.

This commit therefore officially deprecates support for custom, default
ContextLoader class names via the following mechanisms:

 - The TestContextManager(Class, String) constructor

 - The getDefaultContextLoaderClassName(Class) method in
   SpringJUnit4ClassRunner

Issue: SPR-11682
2014-04-10 17:54:14 +02:00
Sam Brannen 428aee5b72 Deprecate getDefTELClasses in TestContextMgr
Since a dedicated bootstrap strategy will be introduced for the
TestContext framework in Spring Framework 4.1, this commit officially
deprecates TestContextManager.getDefaultTestExecutionListenerClasses()
as a forewarning to developers or frameworks that may be using this
obscure feature.

Issue: SPR-11679
2014-04-09 22:20:43 +02:00
Juergen Hoeller f7a17added AbstractMarshaller uses general exception message in extracted buildDocument() method
Issue: SPR-11635
2014-04-09 20:54:41 +02:00
Juergen Hoeller 196f629a20 JBoss "vfszip" resources need to be treated as jar URLs
Issue: SPR-11676
(cherry picked from commit be6b54f)
2014-04-09 20:51:23 +02:00
Juergen Hoeller 7135e729e2 Dropped JCache RC repo (now unused); minor dependency upgrades
Issue: SPR-11640
(cherry picked from commit 9e1631d)
2014-04-09 19:00:44 +02:00
Juergen Hoeller 21874627d2 Polishing
Issue: SPR-11637
(cherry picked from commit 0041e24)
2014-04-09 19:00:23 +02:00
Juergen Hoeller 3ab88b857b AbstractMarshaller pre-implements getDefaultEncoding() method
Issue: SPR-11635
(cherry picked from commit d4b0ae9)
2014-04-09 19:00:08 +02:00
Juergen Hoeller 294545d07a XStreamMarshaller lazily creates fallback XppDriver
Issue: SPR-11635
(cherry picked from commit 8f28a93)
2014-04-09 18:59:47 +02:00
Juergen Hoeller 38cd79047a SelectTag correctly detects multiple="true" again
Issue: SPR-11678
(cherry picked from commit 8d8766d)
2014-04-09 18:59:37 +02:00
Stephane Nicoll 8a779c32d5 Update to JCache 1.0.0 final
Issue: SPR-11640
(cherry picked from commit 0bdece7)
2014-04-08 15:20:57 +02:00
Sam Brannen 7ba31dee45 Use unconstrained quotes in reference manual
Prior to this commit, there were numerous places in the reference
manual, where we see output similar to the following:

    BeanDefinition`s with the `ApplicationContext

This commit addresses this issue by using unconstrained quotes
(e.g., ++XYZ++s) instead of backticks (e.g., `XYZ`s) when the formatted
text is immediately followed by an "s".

This commit also corrects a few typos and corrects natural English
pluralization of Java code elements in the reference manual where
appropriate -- for example, "@Controllers" becomes "@Controller classes,
etc.

Issue: SPR-11650
(cherry picked from commit 0eba1f818f)
2014-04-04 22:05:43 +02:00
Brian Clozel 1c45d7573c Fix @SubscribeMapping MESSAGE response destination
Prior to this commit, @SubscribeMapping mapped methods (backed with
@SendTo* annotations, or not) would send MESSAGEs with the wrong
destination. Instead of using the original SUBSCRIBE destination, it
would use the lookup path computed from the configured prefixes in the
application.

This commit fixes this issue - now @SubscribeMapping MESSAGEs use the
original SUBSCRIBE destination.

Issue: SPR-11648
2014-04-04 12:45:19 +02:00
Juergen Hoeller f014bbb5cf Revised ByteArrayOutputStream handling in MarshallingView and co
Issue: SPR-11646
(cherry picked from commit 8006696)
2014-04-02 21:29:37 +02:00
Juergen Hoeller d1030b798d ResourceHttpRequestHandler explicitly closes a Resource's InputStream
Issue: SPR-11644
(cherry picked from commit 3a96f16)
2014-04-02 21:29:05 +02:00
Juergen Hoeller d628025f13 Polishing
Issue: SPR-11262
2014-04-02 21:28:42 +02:00
Rossen Stoyanchev 30ea1a3475 Fix issue with default executor for message channels
This change ensures correct default settings for message channel's
created through the websocket message-broker XML namespace even
when the channels are customized for other reasons -- e.g. to add
a channel interceptor.

Issue: SPR-11623
2014-04-01 14:16:10 -04:00
Rossen Stoyanchev 7b014eaa55 Improve access to WebSocketSession fields
Ensure the Standard- and the JettyWebSocketSession can return the
Principal and accepted WebSocket sub-protocol even after the
session is closed.

Issue: SPR-11621
2014-04-01 14:16:10 -04:00
Rossen Stoyanchev e21c47d4ce Optimize performance in StompEncoder/Decoder escaping
Issue: SPR-11643
2014-04-01 14:16:10 -04:00
Rossen Stoyanchev 632ae6a4df Improve shutdown responsiveness of SubProtocolWSH
Proactively notify all active WebSocket sessions when a shutdown is
progress. Sessions then can ignore further attempts to send messages
and also stop stop trying to flush messages right away.
2014-04-01 14:16:10 -04:00
Sam Brannen 989f6194b6 Support classes AND locations in @ContextConfiguration
Prior to this commit, the Spring TestContext Framework did not support
the declaration of both 'locations' and 'classes' within
@ContextConfiguration at the same time.

This commit addresses this in the following manner:

 - ContextConfigurationAttributes no longer throws an
   IllegalArgumentException if both 'locations' and 'classes' are
   supplied to its constructor.

 - Concrete SmartContextLoader implementations now validate the
   supplied MergedContextConfiguration before attempting to load the
   ApplicationContext. See validateMergedContextConfiguration().

 - Introduced tests for hybrid context loaders like the one used in
   Spring Boot. See HybridContextLoaderTests.

 - Updated the Testing chapter of the reference manual so that it no
   longer states that locations and classes cannot be used
   simultaneously, mentioning Spring Boot as well.

 - The Javadoc for @ContextConfiguration has been updated accordingly.

 - Added hasLocations(), hasClasses(), and hasResources() convenience
   methods to MergedContextConfiguration.

Issue: SPR-11634
(cherry picked from commit 1f017c4acb)
2014-04-01 19:54:04 +02:00
Sam Brannen 17bf5b991f Update Javadoc for supported JBoss VFS version
(cherry picked from commit 34eb4dba3a)
2014-03-30 16:02:27 +02:00
Sam Brannen cd9d7cfe4f 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:46:58 +01:00
256 changed files with 6355 additions and 2692 deletions
+77 -64
View File
@@ -3,7 +3,7 @@ buildscript {
maven { url "http://repo.springsource.org/plugins-release" }
}
dependencies {
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.5")
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.6")
classpath("org.asciidoctor:asciidoctor-gradle-plugin:0.7.0")
classpath("org.springframework.build.gradle:docbook-reference-plugin:0.2.8")
}
@@ -14,23 +14,26 @@ configure(allprojects) { project ->
version = qualifyVersionIfNecessary(version)
ext.aspectjVersion = "1.7.4"
ext.eclipseLinkVersion = "2.4.2"
ext.groovyVersion = "1.8.9"
ext.hibernate3Version = "3.6.10.Final"
ext.hibernate4Version = "4.2.11.Final"
ext.hibValVersion = "4.3.1.Final"
ext.hibernate4Version = "4.2.12.Final"
ext.hibVal4Version = "4.3.1.Final"
ext.hsqldbVersion = "2.3.2"
ext.jackson1Version = "1.9.13"
ext.jackson2Version = "2.3.1"
ext.jackson2Version = "2.3.3"
ext.jasperReportsVersion = "5.5.1"
ext.jettyVersion = "9.1.3.v20140225"
ext.jettyVersion = "9.1.5.v20140505"
ext.jodaVersion = "2.3"
ext.junitVersion = "4.11"
ext.slf4jVersion = "1.7.6"
ext.openJpaVersion = "2.2.2"
ext.slf4jVersion = "1.7.7"
ext.tiles2Version = "2.2.2"
ext.tiles3Version = "3.0.3"
ext.tiles3Version = "3.0.4"
ext.tomcatVersion = "8.0.5"
ext.xstreamVersion = "1.4.7"
ext.gradleScriptDir = "${rootProject.projectDir}/gradle"
ext.gradleScriptDir = "${rootProject.projectDir}/gradle"
apply plugin: "propdeps"
apply plugin: "java"
@@ -71,14 +74,12 @@ configure(allprojects) { project ->
include(["**/*Tests.class", "**/*Test.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.
// run MyTests by itself will fail if MyTests contains any inner classes.
exclude(["**/Abstract*.class", '**/*$*'])
}
repositories {
maven { url "http://repo.spring.io/libs-release" }
maven { url "http://repo.spring.io/milestone" } // for AspectJ 1.8.0.M1
maven { url "https://oss.sonatype.org/content/repositories/releases" } // javax.cache
}
dependencies {
@@ -93,7 +94,7 @@ configure(allprojects) { project ->
ext.javadocLinks = [
"http://docs.oracle.com/javase/7/docs/api/",
"http://docs.oracle.com/javaee/6/api/",
"http://docs.oracle.com/javaee/7/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/",
"http://glassfish.java.net/nonav/docs/v3/api/",
@@ -108,7 +109,7 @@ configure(allprojects) { project ->
"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.7/",
"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/",
@@ -279,7 +280,7 @@ project("spring-beans") {
compile(project(":spring-core"))
compile(files(project(":spring-core").cglibRepackJar))
optional("javax.inject:javax.inject:1")
optional("javax.el:javax.el-api:2.2.4")
optional("javax.el:javax.el-api:2.2.5")
testCompile("log4j:log4j:1.2.17")
}
}
@@ -371,12 +372,12 @@ project("spring-context") {
optional("javax.enterprise.concurrent:javax.enterprise.concurrent-api:1.0")
optional("org.eclipse.persistence:javax.persistence:2.0.0")
optional("javax.validation:validation-api:1.0.0.GA")
optional("org.hibernate:hibernate-validator:${hibValVersion}")
optional("org.hibernate:hibernate-validator:${hibVal4Version}")
optional("joda-time:joda-time:${jodaVersion}")
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
optional("org.beanshell:bsh:2.0b4")
optional("org.jruby:jruby:1.7.10")
optional("org.jruby:jruby:1.7.12")
testCompile("javax.inject:javax.inject-tck:1")
testCompile("commons-dbcp:commons-dbcp:1.4")
testCompile("org.slf4j:slf4j-api:${slf4jVersion}")
@@ -397,7 +398,8 @@ project("spring-messaging") {
compile(project(":spring-beans"))
compile(project(":spring-core"))
compile(project(":spring-context"))
optional("org.projectreactor:reactor-core:1.0.1.RELEASE")
optional("org.projectreactor:reactor-core:1.1.0.RELEASE")
optional("org.projectreactor:reactor-net:1.1.0.RELEASE")
optional("org.projectreactor:reactor-tcp:1.0.1.RELEASE")
optional("org.eclipse.jetty.websocket:websocket-server:${jettyVersion}") {
exclude group: "javax.servlet", module: "javax.servlet-api"
@@ -417,9 +419,9 @@ project("spring-messaging") {
testCompile("org.eclipse.jetty:jetty-webapp:${jettyVersion}") {
exclude group: "javax.servlet", module: "javax.servlet-api"
}
testCompile("org.apache.tomcat.embed:tomcat-embed-core:8.0.3")
testCompile("org.apache.tomcat.embed:tomcat-embed-websocket:8.0.3")
testCompile("org.apache.tomcat.embed:tomcat-embed-logging-juli:8.0.3")
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
testCompile("org.apache.tomcat.embed:tomcat-embed-websocket:${tomcatVersion}")
testCompile("org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}")
testCompile("commons-dbcp:commons-dbcp:1.4")
testCompile("log4j:log4j:1.2.17")
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
@@ -458,8 +460,9 @@ project("spring-oxm") {
dependencies {
compile(project(":spring-beans"))
compile(project(":spring-core"))
optional("org.codehaus.castor:castor-xml:1.3.2") {
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'
@@ -509,11 +512,11 @@ project("spring-jdbc") {
compile(project(":spring-tx"))
optional(project(":spring-context")) // for JndiDataSourceLookup
optional("javax.transaction:javax.transaction-api:1.2")
optional("c3p0:c3p0:0.9.1.2")
optional("com.mchange:c3p0:0.9.2.1")
optional("org.hsqldb:hsqldb:${hsqldbVersion}")
optional("com.h2database:h2:1.0.71")
optional("org.apache.derby:derby:10.10.1.1")
optional("org.apache.derby:derbyclient:10.10.1.1")
optional("com.h2database:h2:1.3.176")
optional("org.apache.derby:derby:10.10.2.0")
optional("org.apache.derby:derbyclient:10.10.2.0")
}
}
@@ -526,10 +529,10 @@ project("spring-context-support") {
compile(project(":spring-context"))
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:1.0.0-RC1")
optional("com.google.guava:guava:16.0.1")
optional("net.sf.ehcache:ehcache-core:2.6.5")
optional("javax.mail:javax.mail-api:1.4.7")
optional("javax.cache:cache-api:1.0.0")
optional("com.google.guava:guava:17.0")
optional("net.sf.ehcache:ehcache-core:2.6.7")
optional("org.quartz-scheduler:quartz:1.8.6") {
exclude group: "org.slf4j", module: "slf4j-log4j12"
}
@@ -537,12 +540,15 @@ project("spring-context-support") {
optional("org.apache.velocity:velocity:1.7")
optional("org.freemarker:freemarker:2.3.20")
optional("com.lowagie:itext:2.1.7")
optional("net.sf.jasperreports:jasperreports:$jasperReportsVersion")
testCompile("org.apache.poi:poi:3.9")
optional("net.sf.jasperreports:jasperreports:$jasperReportsVersion") {
exclude group: "xml-apis", module: "xml-apis"
}
testCompile("org.apache.poi:poi:3.10-FINAL")
testCompile("commons-beanutils:commons-beanutils:1.8.0") // for Velocity/JasperReports
testCompile("commons-digester:commons-digester:1.8.1") // for Velocity/JasperReports
testCompile("org.hsqldb:hsqldb:${hsqldbVersion}")
testCompile("org.slf4j:slf4j-api:${slf4jVersion}")
testRuntime("com.sun.mail:javax.mail:1.4.7")
}
// pick up **/*.types files in src/main
@@ -559,9 +565,9 @@ project("spring-web") {
compile(project(":spring-core"))
provided("javax.servlet:javax.servlet-api:3.0.1")
optional(project(":spring-oxm")) // for MarshallingHttpMessageConverter
optional("javax.servlet.jsp:jsp-api:2.2")
optional("javax.servlet.jsp:javax.servlet.jsp-api:2.2.1")
optional("javax.portlet:portlet-api:2.0")
optional("javax.el:javax.el-api:2.2.4")
optional("javax.el:javax.el-api:2.2.5")
optional("javax.faces:javax.faces-api:2.2")
optional("aopalliance:aopalliance:1.0")
optional("com.caucho:hessian:4.0.7")
@@ -571,7 +577,6 @@ project("spring-web") {
optional("org.codehaus.jackson:jackson-mapper-asl:${jackson1Version}")
optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
optional("rome:rome:1.0")
optional("taglibs:standard:1.1.2")
optional("org.eclipse.jetty:jetty-servlet:${jettyVersion}") {
exclude group: "javax.servlet", module: "javax.servlet-api"
}
@@ -582,6 +587,9 @@ project("spring-web") {
testCompile(project(":spring-context-support")) // for JafMediaTypeFactory
testCompile("xmlunit:xmlunit:1.5")
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
testCompile("org.apache.taglibs:taglibs-standard-jstlel:1.2.1") {
exclude group: "org.apache.taglibs", module: "taglibs-standard-spec"
}
}
// pick up ContextLoader.properties in src/main
@@ -599,7 +607,7 @@ project("spring-websocket") {
optional(project(":spring-webmvc"))
optional("javax.servlet:javax.servlet-api:3.1.0")
optional("javax.websocket:javax.websocket-api:1.0")
optional("org.apache.tomcat:tomcat-websocket:8.0.3") {
optional("org.apache.tomcat:tomcat-websocket:${tomcatVersion}") {
exclude group: "org.apache.tomcat", module: "tomcat-websocket-api"
exclude group: "org.apache.tomcat", module: "tomcat-servlet-api"
}
@@ -612,20 +620,20 @@ project("spring-websocket") {
exclude group: "javax.servlet", module: "javax.servlet"
}
optional("org.eclipse.jetty.websocket:websocket-client:${jettyVersion}")
optional("io.undertow:undertow-core:1.0.0.Final")
optional("io.undertow:undertow-servlet:1.0.0.Final") {
optional("io.undertow:undertow-core:1.0.1.Final")
optional("io.undertow:undertow-servlet:1.0.1.Final") {
exclude group: "org.jboss.spec.javax.servlet", module: "jboss-servlet-api_3.1_spec"
exclude group: "org.jboss.spec.javax.annotation", module: "jboss-annotations-api_1.2_spec"
}
optional("io.undertow:undertow-websockets-jsr:1.0.0.Final") {
optional("io.undertow:undertow-websockets-jsr:1.0.1.Final") {
exclude group: "org.jboss.spec.javax.websocket", module: "jboss-websocket-api_1.0_spec"
}
optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
testCompile("org.apache.tomcat.embed:tomcat-embed-core:8.0.3")
testCompile("org.apache.tomcat.embed:tomcat-embed-websocket:8.0.3")
testCompile("org.apache.tomcat.embed:tomcat-embed-logging-juli:8.0.3")
testCompile("org.projectreactor:reactor-core:1.0.1.RELEASE")
testCompile("org.projectreactor:reactor-tcp:1.0.1.RELEASE")
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
testCompile("org.apache.tomcat.embed:tomcat-embed-websocket:${tomcatVersion}")
testCompile("org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}")
testCompile("org.projectreactor:reactor-core:1.1.0.RELEASE")
testCompile("org.projectreactor:reactor-net:1.1.0.RELEASE")
testCompile("log4j:log4j:1.2.17")
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
}
@@ -643,9 +651,9 @@ project("spring-orm") {
optional(project(":spring-context"))
optional(project(":spring-web"))
optional("aopalliance:aopalliance:1.0")
optional("org.eclipse.persistence:javax.persistence:2.0.0")
optional("org.eclipse.persistence:org.eclipse.persistence.core:2.4.0")
optional("org.eclipse.persistence:org.eclipse.persistence.jpa:2.4.0") {
optional("org.eclipse.persistence:javax.persistence:2.0.5")
optional("org.eclipse.persistence:org.eclipse.persistence.core:${eclipseLinkVersion}")
optional("org.eclipse.persistence:org.eclipse.persistence.jpa:${eclipseLinkVersion}") {
exclude group: 'org.eclipse.persistence', module: 'javax.persistence'
}
optional("org.hibernate:hibernate-core:${hibernate3Version}") {
@@ -655,13 +663,13 @@ project("spring-orm") {
optional("org.hibernate:hibernate-entitymanager:${hibernate3Version}") {
exclude group: 'org.hibernate.javax.persistence', module: 'hibernate-jpa-2.0-api'
}
optional("org.apache.openjpa:openjpa:2.2.1") {
optional("org.apache.openjpa:openjpa:${openJpaVersion}") {
exclude group: 'junit', module: 'junit'
exclude group: 'org.apache.geronimo.specs', module: 'geronimo-jpa_2.0_spec'
exclude group: 'org.apache.geronimo.specs', module: 'geronimo-jta_1.1_spec'
exclude group: 'org.apache.geronimo.specs', module: 'geronimo-jms_1.1_spec'
}
optional("javax.jdo:jdo-api:3.0") {
optional("javax.jdo:jdo-api:3.0.1") {
exclude group: 'javax.transaction', module: 'transaction-api'
}
optional("javax.servlet:javax.servlet-api:3.0.1")
@@ -682,6 +690,7 @@ project("spring-orm-hibernate4") {
optional("org.hibernate:hibernate-core:${hibernate4Version}")
optional("org.hibernate:hibernate-entitymanager:${hibernate4Version}")
optional("javax.servlet:javax.servlet-api:3.0.1")
optional("aopalliance:aopalliance:1.0")
}
}
@@ -698,10 +707,10 @@ project("spring-webmvc") {
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.2")
optional("javax.servlet:jstl:1.2")
optional("javax.servlet.jsp:javax.servlet.jsp-api:2.2.1")
optional("javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:1.2.1")
optional("net.sourceforge.jexcelapi:jxl:2.6.12")
optional("org.apache.poi:poi:3.9")
optional("org.apache.poi:poi:3.10-FINAL")
optional("org.apache.velocity:velocity:1.7")
optional("velocity-tools:velocity-tools-view:1.4")
optional("org.freemarker:freemarker:2.3.20")
@@ -748,7 +757,7 @@ project("spring-webmvc") {
exclude group: "javax.servlet", module: "javax.servlet"
}
testCompile("javax.validation:validation-api:1.0.0.GA")
testCompile("org.hibernate:hibernate-validator:${hibValVersion}")
testCompile("org.hibernate:hibernate-validator:${hibVal4Version}")
testCompile("org.apache.httpcomponents:httpclient:4.3.3")
testCompile("commons-fileupload:commons-fileupload:1.3.1")
testCompile("commons-io:commons-io:1.3")
@@ -768,9 +777,9 @@ project("spring-webmvc-tiles3") {
provided(project(":spring-context"))
provided(project(":spring-web"))
provided("javax.servlet:javax.servlet-api:3.0.1")
optional("javax.servlet.jsp:jsp-api:2.2")
optional("javax.servlet:jstl:1.2")
optional("javax.el:javax.el-api:2.2.4")
optional("javax.servlet.jsp:javax.servlet.jsp-api:2.2.1")
optional("javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:1.2.1")
optional("javax.el:javax.el-api:2.2.5")
optional("org.apache.tiles:tiles-api:${tiles3Version}")
optional("org.apache.tiles:tiles-core:${tiles3Version}") {
exclude group: "org.slf4j", module: "jcl-over-slf4j"
@@ -827,10 +836,13 @@ project("spring-test") {
optional("org.testng:testng:6.8.8")
optional("javax.inject:javax.inject:1")
optional("javax.servlet:javax.servlet-api:3.0.1")
optional("javax.servlet.jsp:jsp-api:2.2")
optional("javax.servlet:jstl:1.2")
optional("javax.servlet.jsp:javax.servlet.jsp-api:2.2.1")
optional("javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:1.2.1")
optional("org.apache.taglibs:taglibs-standard-jstlel:1.2.1") {
exclude group: "org.apache.taglibs", module: "taglibs-standard-spec"
}
optional("javax.portlet:portlet-api:2.0")
optional("javax.el:javax.el-api:2.2.4")
optional("javax.el:javax.el-api:2.2.5")
optional("org.eclipse.persistence:javax.persistence:2.0.0")
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
optional("org.hamcrest:hamcrest-core:1.3")
@@ -839,13 +851,13 @@ project("spring-test") {
testCompile(project(":spring-context-support"))
testCompile(project(":spring-oxm"))
testCompile(project(":spring-webmvc-tiles3"))
testCompile("javax.mail:mail:1.4.7")
testCompile("javax.mail:javax.mail-api:1.4.7")
testCompile("javax.ejb:ejb-api:3.0")
testCompile("org.hibernate:hibernate-core:${hibernate3Version}") {
exclude group: 'org.hibernate.javax.persistence', module: 'hibernate-jpa-2.0-api'
}
testCompile("org.hibernate:hibernate-entitymanager:${hibernate3Version}")
testCompile("org.hibernate:hibernate-validator:${hibValVersion}")
testCompile("org.hibernate:hibernate-validator:${hibVal4Version}")
testCompile("com.thoughtworks.xstream:xstream:${xstreamVersion}")
testCompile("org.codehaus.jackson:jackson-mapper-asl:${jackson1Version}")
testCompile("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
@@ -863,6 +875,7 @@ project("spring-test") {
task testNG(type: Test) {
useTestNG()
scanForTestClasses = false
include(["**/testng/**/*Tests.class", "**/testng/**/*Test.class"])
// Show STD_OUT & STD_ERR of the test JVM(s) on the console:
// testLogging.showStandardStreams = true
@@ -889,8 +902,8 @@ project("spring-aspects") {
dependencies {
aspects(project(":spring-orm"))
ajc("org.aspectj:aspectjtools:1.8.0.RC2") // needed for ajc on JDK 8 only
rt("org.aspectj:aspectjrt:1.8.0.RC2") // needed for ajc on JDK 8 only
ajc("org.aspectj:aspectjtools:1.8.0") // needed for ajc on JDK 8 only
rt("org.aspectj:aspectjrt:1.8.0") // needed for ajc on JDK 8 only
compile("org.aspectj:aspectjweaver:${aspectjVersion}") // exposing regular AspectJ version to users
provided("org.eclipse.persistence:javax.persistence:2.0.0")
optional(project(":spring-aop")) // for @Async support
@@ -901,7 +914,7 @@ project("spring-aspects") {
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")
testCompile("javax.mail:javax.mail-api:1.4.7")
}
eclipse.project {
@@ -1175,7 +1188,7 @@ configure(rootProject) {
task wrapper(type: Wrapper) {
description = "Generates gradlew[.bat] scripts"
gradleVersion = "1.11"
gradleVersion = "1.12"
doLast() {
def gradleOpts = "-XX:MaxMetaspaceSize=1024m -Xmx1024m"
+1 -1
View File
@@ -1 +1 @@
version=4.0.4.BUILD-SNAPSHOT
version=4.0.5.RELEASE
Binary file not shown.
+2 -2
View File
@@ -1,6 +1,6 @@
#Wed Feb 12 23:28:21 CET 2014
#Wed Apr 30 13:06:57 CEST 2014
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=http\://services.gradle.org/distributions/gradle-1.11-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-1.12-bin.zip
@@ -29,7 +29,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;
@@ -108,6 +107,8 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
private BeanFactory beanFactory;
private transient ClassLoader pointcutClassLoader;
private transient PointcutExpression pointcutExpression;
private transient Map<Method, ShadowMatch> shadowMatchCache = new ConcurrentHashMap<Method, ShadowMatch>(32);
@@ -185,20 +186,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() :
ClassUtils.getDefaultClassLoader());
return buildPointcutExpression(cl);
}
/**
* Build the underlying AspectJ pointcut expression.
*/
@@ -252,23 +246,22 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
public boolean matches(Class<?> targetClass) {
checkReadyToMatch();
try {
return this.pointcutExpression.couldMatchJoinPointsInType(targetClass);
}
catch (ReflectionWorldException rwe) {
logger.debug("PointcutExpression matching rejected target class", rwe);
try {
// Actually this is still a "maybe" - treat the pointcut as dynamic if we don't know enough yet
return getFallbackPointcutExpression(targetClass).couldMatchJoinPointsInType(targetClass);
return this.pointcutExpression.couldMatchJoinPointsInType(targetClass);
}
catch (BCException bce) {
logger.debug("Fallback PointcutExpression matching rejected target class", bce);
return false;
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;
}
@Override
@@ -365,12 +358,19 @@ 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 ? buildPointcutExpression(classLoader) : this.pointcutExpression);
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) {
@@ -396,46 +396,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 ex2) {
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 ex3) {
// 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 ex4) {
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);
}
@@ -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.
@@ -91,9 +91,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);
}
@@ -102,32 +104,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;
@@ -261,7 +261,7 @@ 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.");
}
}
}
@@ -604,7 +604,7 @@ 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;
@@ -622,8 +622,8 @@ 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();
@@ -689,13 +689,13 @@ class CglibAopProxy implements AopProxy, Serializable {
private final MethodProxy methodProxy;
private boolean protectedMethod;
private final boolean publicMethod;
public CglibMethodInvocation(Object proxy, Object target, Method method, Object[] arguments,
Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) {
super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);
this.methodProxy = methodProxy;
this.protectedMethod = Modifier.isProtected(method.getModifiers());
this.publicMethod = Modifier.isPublic(method.getModifiers());
}
/**
@@ -704,11 +704,11 @@ class CglibAopProxy implements AopProxy, Serializable {
*/
@Override
protected Object invokeJoinpoint() throws Throwable {
if (this.protectedMethod) {
return super.invokeJoinpoint();
if (this.publicMethod) {
return this.methodProxy.invoke(this.target, this.arguments);
}
else {
return this.methodProxy.invoke(this.target, this.arguments);
return super.invokeJoinpoint();
}
}
}
@@ -829,8 +829,8 @@ 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;
}
@@ -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-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 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;
@@ -81,7 +80,7 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
* Set the {@link BeanFactory} to be used when looking up executors by qualifier.
*/
@Override
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);
}
@@ -119,8 +119,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-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 class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
static {
try {
zoneIdClass = PropertyEditorRegistrySupport.class.getClassLoader().loadClass("java.time.ZoneId");
zoneIdClass = ClassUtils.forName("java.time.ZoneId", PropertyEditorRegistrySupport.class.getClassLoader());
}
catch (ClassNotFoundException ex) {
// Java 8 ZoneId class not available
@@ -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.
@@ -289,15 +289,15 @@ 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);
logger.trace("Enum class [" + enumType + "] cannot be loaded", ex);
}
}
catch (Throwable ex) {
@@ -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) {
@@ -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.
@@ -66,9 +66,9 @@ public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwa
@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.
@@ -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)";
@@ -644,8 +647,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.
* The default is {@code true}; switch this to {@false} for public access only.
* 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.
@@ -105,9 +105,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.
@@ -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.
@@ -69,7 +69,8 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
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;
@@ -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.
@@ -89,7 +89,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-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.
@@ -34,6 +34,7 @@ import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.Constants;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
/**
@@ -261,7 +262,7 @@ public class CronTriggerFactoryBean implements FactoryBean<CronTrigger>, BeanNam
Class<?> cronTriggerClass;
Method jobKeyMethod;
try {
cronTriggerClass = getClass().getClassLoader().loadClass("org.quartz.impl.triggers.CronTriggerImpl");
cronTriggerClass = ClassUtils.forName("org.quartz.impl.triggers.CronTriggerImpl", getClass().getClassLoader());
jobKeyMethod = JobDetail.class.getMethod("getKey");
}
catch (ClassNotFoundException ex) {
@@ -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.
@@ -30,6 +30,7 @@ import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.ClassUtils;
/**
* A Spring {@link FactoryBean} for creating a Quartz {@link org.quartz.JobDetail}
@@ -210,7 +211,7 @@ public class JobDetailFactoryBean
Class<?> jobDetailClass;
try {
jobDetailClass = getClass().getClassLoader().loadClass("org.quartz.impl.JobDetailImpl");
jobDetailClass = ClassUtils.forName("org.quartz.impl.JobDetailImpl", getClass().getClassLoader());
}
catch (ClassNotFoundException ex) {
jobDetailClass = JobDetail.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.
@@ -87,7 +87,7 @@ public class LocalTaskExecutorThreadPool implements ThreadPool {
@Override
public int blockForAvailableThreads() {
// The present implementation always returns 1, making Quartz (1.6)
// The present implementation always returns 1, making Quartz
// always schedule any tasks that it feels like scheduling.
// This could be made smarter for specific TaskExecutors,
// for example calling {@code getMaximumPoolSize() - getActiveCount()}
@@ -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.
@@ -87,14 +87,15 @@ public class MethodInvokingJobDetailFactoryBean extends ArgumentConvertingMethod
static {
try {
jobDetailImplClass = Class.forName("org.quartz.impl.JobDetailImpl");
jobDetailImplClass = ClassUtils.forName("org.quartz.impl.JobDetailImpl",
MethodInvokingJobDetailFactoryBean.class.getClassLoader());
}
catch (ClassNotFoundException ex) {
jobDetailImplClass = null;
}
try {
Class<?> jobExecutionContextClass =
QuartzJobBean.class.getClassLoader().loadClass("org.quartz.JobExecutionContext");
Class<?> jobExecutionContextClass = ClassUtils.forName("org.quartz.JobExecutionContext",
MethodInvokingJobDetailFactoryBean.class.getClassLoader());
setResultMethod = jobExecutionContextClass.getMethod("setResult", Object.class);
}
catch (Exception ex) {
@@ -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.
@@ -28,6 +28,7 @@ import org.quartz.SchedulerException;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
/**
@@ -77,7 +78,7 @@ public abstract class QuartzJobBean implements Job {
static {
try {
Class<?> jobExecutionContextClass =
QuartzJobBean.class.getClassLoader().loadClass("org.quartz.JobExecutionContext");
ClassUtils.forName("org.quartz.JobExecutionContext", QuartzJobBean.class.getClassLoader());
getSchedulerMethod = jobExecutionContextClass.getMethod("getScheduler");
getMergedJobDataMapMethod = jobExecutionContextClass.getMethod("getMergedJobDataMap");
}
@@ -43,6 +43,7 @@ import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
/**
@@ -68,8 +69,8 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware {
static {
// Quartz 2.0 job/trigger key available?
try {
jobKeyClass = Class.forName("org.quartz.JobKey");
triggerKeyClass = Class.forName("org.quartz.TriggerKey");
jobKeyClass = ClassUtils.forName("org.quartz.JobKey", SchedulerAccessor.class.getClassLoader());
triggerKeyClass = ClassUtils.forName("org.quartz.TriggerKey", SchedulerAccessor.class.getClassLoader());
}
catch (ClassNotFoundException ex) {
jobKeyClass = null;
@@ -151,8 +152,6 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware {
* in combination with the Trigger.
* @see #setTriggers
* @see org.quartz.JobDetail
* @see JobDetailBean
* @see JobDetailAwareTrigger
*/
public void setJobDetails(JobDetail... jobDetails) {
// Use modifiable ArrayList here, to allow for further adding of
@@ -180,15 +179,11 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware {
* "jobDetails" property of this FactoryBean.
* @see #setJobDetails
* @see org.quartz.JobDetail
* @see JobDetailAwareTrigger
* @see CronTriggerBean
* @see SimpleTriggerBean
*/
public void setTriggers(Trigger... triggers) {
this.triggers = Arrays.asList(triggers);
}
/**
* Specify Quartz SchedulerListeners to be registered with the Scheduler.
*/
@@ -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.
@@ -33,6 +33,7 @@ import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.Constants;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
/**
@@ -245,14 +246,14 @@ public class SimpleTriggerFactoryBean implements FactoryBean<SimpleTrigger>, Bea
sti.setRepeatCount(this.repeatCount);
sti.setPriority(this.priority);
sti.setMisfireInstruction(this.misfireInstruction);
cti.setDescription(this.description);
sti.setDescription(this.description);
this.simpleTrigger = sti;
*/
Class<?> simpleTriggerClass;
Method jobKeyMethod;
try {
simpleTriggerClass = getClass().getClassLoader().loadClass("org.quartz.impl.triggers.SimpleTriggerImpl");
simpleTriggerClass = ClassUtils.forName("org.quartz.impl.triggers.SimpleTriggerImpl", getClass().getClassLoader());
jobKeyMethod = JobDetail.class.getMethod("getKey");
}
catch (ClassNotFoundException ex) {
@@ -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.
@@ -41,13 +41,13 @@ import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.JRPdfExporterParameter;
import net.sf.jasperreports.engine.export.JRXlsExporterParameter;
import net.sf.jasperreports.engine.util.JRLoader;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.tests.Assume;
@@ -140,7 +140,7 @@ public class JasperReportsUtilsTests {
public void testRenderAsPdfWithExporterParameters() throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
Map<JRExporterParameter, Object> exporterParameters = new HashMap<JRExporterParameter, Object>();
exporterParameters.put(JRPdfExporterParameter.PDF_VERSION, JRPdfExporterParameter.PDF_VERSION_1_6);
exporterParameters.put(JRPdfExporterParameter.PDF_VERSION, JRPdfExporterParameter.PDF_VERSION_1_6.toString());
JasperReportsUtils.renderAsPdf(getReport(), getParameters(), getData(), os, exporterParameters);
byte[] output = os.toByteArray();
assertPdfOutputCorrect(output);
@@ -372,6 +372,8 @@ public abstract class CacheAspectSupport implements InitializingBean {
private final Collection<? extends Cache> caches;
private final MethodCacheKey methodCacheKey;
public CacheOperationContext(CacheOperation operation, Method method,
Object[] args, Object target, Class<?> targetClass) {
this.operation = operation;
@@ -380,6 +382,7 @@ public abstract class CacheAspectSupport implements InitializingBean {
this.target = target;
this.targetClass = targetClass;
this.caches = CacheAspectSupport.this.getCaches(operation);
this.methodCacheKey = new MethodCacheKey(method, targetClass);
}
private Object[] extractArgs(Method method, Object[] args) {
@@ -396,7 +399,7 @@ public abstract class CacheAspectSupport implements InitializingBean {
protected boolean isConditionPassing(Object result) {
if (StringUtils.hasText(this.operation.getCondition())) {
EvaluationContext evaluationContext = createEvaluationContext(result);
return evaluator.condition(this.operation.getCondition(), this.method, evaluationContext);
return evaluator.condition(this.operation.getCondition(), this.methodCacheKey, evaluationContext);
}
return true;
}
@@ -411,7 +414,7 @@ public abstract class CacheAspectSupport implements InitializingBean {
}
if (StringUtils.hasText(unless)) {
EvaluationContext evaluationContext = createEvaluationContext(value);
return !evaluator.unless(unless, this.method, evaluationContext);
return !evaluator.unless(unless, this.methodCacheKey, evaluationContext);
}
return true;
}
@@ -423,7 +426,7 @@ public abstract class CacheAspectSupport implements InitializingBean {
protected Object generateKey(Object result) {
if (StringUtils.hasText(this.operation.getKey())) {
EvaluationContext evaluationContext = createEvaluationContext(result);
return evaluator.key(this.operation.getKey(), this.method, evaluationContext);
return evaluator.key(this.operation.getKey(), this.methodCacheKey, evaluationContext);
}
return keyGenerator.generate(this.target, this.method, this.args);
}
@@ -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,16 +27,19 @@ import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.util.ObjectUtils;
/**
* Utility class handling the SpEL expression parsing.
* Meant to be used as a reusable, thread-safe component.
*
* <p>Performs internal caching for performance reasons.
* <p>Performs internal caching for performance reasons
* using {@link MethodCacheKey}.
*
* @author Costin Leau
* @author Phillip Webb
* @author Sam Brannen
* @author Stephane Nicoll
* @since 3.1
*/
class ExpressionEvaluator {
@@ -49,13 +52,16 @@ class ExpressionEvaluator {
// shared param discoverer since it caches data internally
private final ParameterNameDiscoverer paramNameDiscoverer = new DefaultParameterNameDiscoverer();
private final Map<String, Expression> keyCache = new ConcurrentHashMap<String, Expression>(64);
private final Map<ExpressionKey, Expression> keyCache
= new ConcurrentHashMap<ExpressionKey, Expression>(64);
private final Map<String, Expression> conditionCache = new ConcurrentHashMap<String, Expression>(64);
private final Map<ExpressionKey, Expression> conditionCache
= new ConcurrentHashMap<ExpressionKey, Expression>(64);
private final Map<String, Expression> unlessCache = new ConcurrentHashMap<String, Expression>(64);
private final Map<ExpressionKey, Expression> unlessCache
= new ConcurrentHashMap<ExpressionKey, Expression>(64);
private final Map<String, Method> targetMethodCache = new ConcurrentHashMap<String, Method>(64);
private final Map<MethodCacheKey, Method> targetMethodCache = new ConcurrentHashMap<MethodCacheKey, Method>(64);
/**
@@ -93,22 +99,22 @@ class ExpressionEvaluator {
return evaluationContext;
}
public Object key(String keyExpression, Method method, EvaluationContext evalContext) {
return getExpression(this.keyCache, keyExpression, method).getValue(evalContext);
public Object key(String keyExpression, MethodCacheKey methodKey, EvaluationContext evalContext) {
return getExpression(this.keyCache, keyExpression, methodKey).getValue(evalContext);
}
public boolean condition(String conditionExpression, Method method, EvaluationContext evalContext) {
return getExpression(this.conditionCache, conditionExpression, method).getValue(
public boolean condition(String conditionExpression, MethodCacheKey methodKey, EvaluationContext evalContext) {
return getExpression(this.conditionCache, conditionExpression, methodKey).getValue(
evalContext, boolean.class);
}
public boolean unless(String unlessExpression, Method method, EvaluationContext evalContext) {
return getExpression(this.unlessCache, unlessExpression, method).getValue(
public boolean unless(String unlessExpression, MethodCacheKey methodKey, EvaluationContext evalContext) {
return getExpression(this.unlessCache, unlessExpression, methodKey).getValue(
evalContext, boolean.class);
}
private Expression getExpression(Map<String, Expression> cache, String expression, Method method) {
String key = toString(method, expression);
private Expression getExpression(Map<ExpressionKey, Expression> cache, String expression, MethodCacheKey methodKey) {
ExpressionKey key = createKey(methodKey, expression);
Expression rtn = cache.get(key);
if (rtn == null) {
rtn = this.parser.parseExpression(expression);
@@ -117,13 +123,37 @@ class ExpressionEvaluator {
return rtn;
}
private String toString(Method method, String expression) {
StringBuilder sb = new StringBuilder();
sb.append(method.getDeclaringClass().getName());
sb.append("#");
sb.append(method.toString());
sb.append("#");
sb.append(expression);
return sb.toString();
private ExpressionKey createKey(MethodCacheKey methodCacheKey, String expression) {
return new ExpressionKey(methodCacheKey, expression);
}
private static class ExpressionKey {
private final MethodCacheKey methodCacheKey;
private final String expression;
private ExpressionKey(MethodCacheKey methodCacheKey, String expression) {
this.methodCacheKey = methodCacheKey;
this.expression = expression;
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof ExpressionKey)) {
return false;
}
ExpressionKey otherKey = (ExpressionKey) other;
return (this.methodCacheKey.equals(otherKey.methodCacheKey)
&& ObjectUtils.nullSafeEquals(this.expression, otherKey.expression));
}
@Override
public int hashCode() {
return this.methodCacheKey.hashCode() * 29 + (this.expression != null ? this.expression.hashCode() : 0);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 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.
@@ -33,6 +33,7 @@ import org.springframework.util.ObjectUtils;
* (rather then a dedicated 'closure'-like class for deferred execution).
*
* @author Costin Leau
* @author Stephane Nicoll
* @since 3.1
*/
class LazyParamAwareEvaluationContext extends StandardEvaluationContext {
@@ -45,13 +46,13 @@ class LazyParamAwareEvaluationContext extends StandardEvaluationContext {
private final Class<?> targetClass;
private final Map<String, Method> methodCache;
private final Map<MethodCacheKey, Method> methodCache;
private boolean paramLoaded = false;
LazyParamAwareEvaluationContext(Object rootObject, ParameterNameDiscoverer paramDiscoverer, Method method,
Object[] args, Class<?> targetClass, Map<String, Method> methodCache) {
Object[] args, Class<?> targetClass, Map<MethodCacheKey, Method> methodCache) {
super(rootObject);
this.paramDiscoverer = paramDiscoverer;
@@ -85,7 +86,7 @@ class LazyParamAwareEvaluationContext extends StandardEvaluationContext {
return;
}
String methodKey = toString(this.method);
MethodCacheKey methodKey = new MethodCacheKey(this.method, this.targetClass);
Method targetMethod = this.methodCache.get(methodKey);
if (targetMethod == null) {
targetMethod = AopUtils.getMostSpecificMethod(this.method, this.targetClass);
@@ -110,11 +111,4 @@ class LazyParamAwareEvaluationContext extends StandardEvaluationContext {
}
}
private String toString(Method m) {
StringBuilder sb = new StringBuilder();
sb.append(m.getDeclaringClass().getName());
sb.append("#");
sb.append(m.toString());
return sb.toString();
}
}
@@ -0,0 +1,62 @@
/*
* 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.cache.interceptor;
import java.lang.reflect.Method;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
* Represent a method on a particular {@link Class} and is suitable as a key.
* <p>Mainly for internal use within the framework.
*
* @author Costin Leau
* @author Stephane Nicoll
* @since 4.0.4
*/
public final class MethodCacheKey {
private final Method method;
private final Class<?> targetClass;
public MethodCacheKey(Method method, Class<?> targetClass) {
Assert.notNull(method, "method must be set.");
this.method = method;
this.targetClass = targetClass;
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof MethodCacheKey)) {
return false;
}
MethodCacheKey otherKey = (MethodCacheKey) other;
return (this.method.equals(otherKey.method) && ObjectUtils.nullSafeEquals(this.targetClass,
otherKey.targetClass));
}
@Override
public int hashCode() {
return this.method.hashCode() * 29 + (this.targetClass != null ? this.targetClass.hashCode() : 0);
}
}
@@ -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.
@@ -226,8 +226,8 @@ public class AnnotationConfigUtils {
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
ClassLoader cl = AnnotationConfigUtils.class.getClassLoader();
def.setBeanClass(cl.loadClass(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME));
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
@@ -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.
@@ -197,25 +197,26 @@ public @interface Bean {
/**
* The optional name of a method to call on the bean instance during initialization.
* Not commonly used, given that the method may be called programmatically directly
* within the body of a Bean-annotated method. Default value is {@code ""}, indicating
* that no init method should be called.
* within the body of a Bean-annotated method.
* <p>The default value is {@code ""}, indicating no init method to be called.
*/
String initMethod() default "";
/**
* The optional name of a method to call on the bean instance upon closing the
* application context, for example a {@code close()} method on a JDBC {@code
* DataSource} implementation, or a Hibernate {@code SessionFactory} object.
* application context, for example a {@code close()} method on a JDBC
* {@code DataSource} implementation, or a Hibernate {@code SessionFactory} object.
* The method must have no arguments but may throw any exception.
* <p>As a convenience to the user, the container will attempt to infer a destroy
* method against an object returned from the {@code @Bean} method. For example, given a
* {@code @Bean} method returning an Apache Commons DBCP {@code BasicDataSource}, the
* container will notice the {@code close()} method available on that object and
* method against an object returned from the {@code @Bean} method. For example, given
* an {@code @Bean} method returning an Apache Commons DBCP {@code BasicDataSource},
* the container will notice the {@code close()} method available on that object and
* automatically register it as the {@code destroyMethod}. This 'destroy method
* inference' is currently limited to detecting only public, no-arg methods named
* 'close'. The method may be declared at any level of the inheritance hierarchy and
* will be detected regardless of the return type of the {@code @Bean} method (i.e.,
* detection occurs reflectively against the bean instance itself at creation time).
* 'close' or 'shutdown'. The method may be declared at any level of the inheritance
* hierarchy and will be detected regardless of the return type of the {@code @Bean}
* method (i.e., detection occurs reflectively against the bean instance itself at
* creation time).
* <p>To disable destroy method inference for a particular {@code @Bean}, specify an
* empty string as the value, e.g. {@code @Bean(destroyMethod="")}. Note that the
* {@link org.springframework.beans.factory.DisposableBean} and the
@@ -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.
@@ -238,7 +238,7 @@ public class ClassPathScanningCandidateComponentProvider implements EnvironmentC
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) cl.loadClass("javax.annotation.ManagedBean")), false));
((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
logger.debug("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
@@ -246,7 +246,7 @@ public class ClassPathScanningCandidateComponentProvider implements EnvironmentC
}
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) cl.loadClass("javax.inject.Named")), false));
((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
@@ -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.
@@ -142,10 +142,10 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
private static Class<? extends Annotation> ejbRefClass = null;
static {
ClassLoader cl = CommonAnnotationBeanPostProcessor.class.getClassLoader();
try {
@SuppressWarnings("unchecked")
Class<? extends Annotation> clazz = (Class<? extends Annotation>) cl.loadClass("javax.xml.ws.WebServiceRef");
Class<? extends Annotation> clazz = (Class<? extends Annotation>)
ClassUtils.forName("javax.xml.ws.WebServiceRef", CommonAnnotationBeanPostProcessor.class.getClassLoader());
webServiceRefClass = clazz;
}
catch (ClassNotFoundException ex) {
@@ -153,7 +153,8 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
}
try {
@SuppressWarnings("unchecked")
Class<? extends Annotation> clazz = (Class<? extends Annotation>) cl.loadClass("javax.ejb.EJB");
Class<? extends Annotation> clazz = (Class<? extends Annotation>)
ClassUtils.forName("javax.ejb.EJB", CommonAnnotationBeanPostProcessor.class.getClassLoader());
ejbRefClass = clazz;
}
catch (ClassNotFoundException ex) {
@@ -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.
@@ -258,7 +258,7 @@ public class ComponentScanBeanDefinitionParser implements BeanDefinitionParser {
@SuppressWarnings("unchecked")
private Object instantiateUserDefinedStrategy(String className, Class<?> strategyType, ClassLoader classLoader) {
Object result = null;
Object result;
try {
result = classLoader.loadClass(className).newInstance();
}
@@ -268,7 +268,7 @@ public class ComponentScanBeanDefinitionParser implements BeanDefinitionParser {
}
catch (Exception ex) {
throw new IllegalArgumentException("Unable to instantiate class [" + className + "] for strategy [" +
strategyType.getName() + "]. A zero-argument constructor is required", ex);
strategyType.getName() + "]: a zero-argument constructor is required", ex);
}
if (!strategyType.isAssignableFrom(result.getClass())) {
@@ -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.
@@ -83,13 +83,13 @@ class ConditionEvaluator {
for (String[] conditionClasses : getConditionClasses(metadata)) {
for (String conditionClass : conditionClasses) {
Condition condition = getCondition(conditionClass, context.getClassLoader());
Condition condition = getCondition(conditionClass, this.context.getClassLoader());
ConfigurationPhase requiredPhase = null;
if (condition instanceof ConfigurationCondition) {
requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
}
if (requiredPhase == null || requiredPhase == phase) {
if (!condition.matches(context, metadata)) {
if (!condition.matches(this.context, metadata)) {
return 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.
@@ -16,7 +16,6 @@
package org.springframework.context.annotation;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
@@ -54,7 +53,7 @@ final class ConfigurationClass {
private String beanName;
private final ConfigurationClass importedBy;
private final Set<ConfigurationClass> importedBy = new LinkedHashSet<ConfigurationClass>(1);
private final Set<BeanMethod> beanMethods = new LinkedHashSet<BeanMethod>();
@@ -77,7 +76,6 @@ final class ConfigurationClass {
this.metadata = metadataReader.getAnnotationMetadata();
this.resource = metadataReader.getResource();
this.beanName = beanName;
this.importedBy = null;
}
/**
@@ -91,7 +89,7 @@ final class ConfigurationClass {
public ConfigurationClass(MetadataReader metadataReader, ConfigurationClass importedBy) {
this.metadata = metadataReader.getAnnotationMetadata();
this.resource = metadataReader.getResource();
this.importedBy = importedBy;
this.importedBy.add(importedBy);
}
/**
@@ -106,7 +104,6 @@ final class ConfigurationClass {
this.metadata = new StandardAnnotationMetadata(clazz, true);
this.resource = new DescriptiveResource(clazz.toString());
this.beanName = beanName;
this.importedBy = null;
}
/**
@@ -120,7 +117,7 @@ final class ConfigurationClass {
public ConfigurationClass(Class<?> clazz, ConfigurationClass importedBy) {
this.metadata = new StandardAnnotationMetadata(clazz, true);
this.resource = new DescriptiveResource(clazz.toString());
this.importedBy = importedBy;
this.importedBy.add(importedBy);
}
@@ -151,16 +148,24 @@ final class ConfigurationClass {
* @see #getImportedBy()
*/
public boolean isImported() {
return (this.importedBy != null);
return !this.importedBy.isEmpty();
}
/**
* Return the configuration class that imported this class,
* or {@code null} if this configuration was not imported.
* @since 4.0
* Merge the imported-by declarations from the given configuration class into this one.
* @since 4.0.5
*/
public void mergeImportedBy(ConfigurationClass otherConfigClass) {
this.importedBy.addAll(otherConfigClass.importedBy);
}
/**
* Return the configuration classes that imported this class,
* or an empty Set if this configuration was not imported.
* @since 4.0.5
* @see #isImported()
*/
public ConfigurationClass getImportedBy() {
public Set<ConfigurationClass> getImportedBy() {
return this.importedBy;
}
@@ -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.
@@ -391,14 +391,20 @@ class ConfigurationClassBeanDefinitionReader {
Boolean skip = this.skipped.get(configClass);
if (skip == null) {
if (configClass.isImported()) {
if (shouldSkip(configClass.getImportedBy())) {
// The config that imported this one was skipped, therefore we are skipped
boolean allSkipped = true;
for (ConfigurationClass importedBy : configClass.getImportedBy()) {
if (!shouldSkip(importedBy)) {
allSkipped = false;
break;
}
}
if (allSkipped) {
// The config classes that imported this one were all skipped, therefore we are skipped...
skip = true;
}
}
if (skip == null) {
skip = conditionEvaluator.shouldSkip(configClass.getMetadata(),
ConfigurationPhase.REGISTER_BEAN);
skip = conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN);
}
this.skipped.put(configClass, skip);
}
@@ -24,6 +24,7 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
@@ -112,11 +113,13 @@ class ConfigurationClassParser {
private final ComponentScanAnnotationParser componentScanParser;
private final Set<ConfigurationClass> configurationClasses = new LinkedHashSet<ConfigurationClass>();
private final Map<ConfigurationClass, ConfigurationClass> configurationClasses =
new LinkedHashMap<ConfigurationClass, ConfigurationClass>();
private final Map<String, ConfigurationClass> knownSuperclasses = new HashMap<String, ConfigurationClass>();
private final MultiValueMap<String, PropertySource<?>> propertySources = new LinkedMultiValueMap<String, PropertySource<?>>();
private final MultiValueMap<String, ResourcePropertySource> propertySources =
new LinkedMultiValueMap<String, ResourcePropertySource>();
private final ImportStack importStack = new ImportStack();
@@ -188,13 +191,23 @@ class ConfigurationClassParser {
return;
}
if (this.configurationClasses.contains(configClass) && configClass.getBeanName() != null) {
// Explicit bean definition found, probably replacing an import.
// Let's remove the old one and go with the new one.
this.configurationClasses.remove(configClass);
for (Iterator<ConfigurationClass> it = this.knownSuperclasses.values().iterator(); it.hasNext();) {
if (configClass.equals(it.next())) {
it.remove();
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
if (configClass.isImported()) {
if (existingClass.isImported()) {
existingClass.mergeImportedBy(configClass);
}
// Otherwise ignore new imported config class; existing non-imported class overrides it.
return;
}
else {
// Explicit bean definition found, probably replacing an import.
// Let's remove the old one and go with the new one.
this.configurationClasses.remove(configClass);
for (Iterator<ConfigurationClass> it = this.knownSuperclasses.values().iterator(); it.hasNext(); ) {
if (configClass.equals(it.next())) {
it.remove();
}
}
}
}
@@ -206,7 +219,7 @@ class ConfigurationClassParser {
}
while (sourceClass != null);
this.configurationClasses.add(configClass);
this.configurationClasses.put(configClass, configClass);
}
/**
@@ -267,7 +280,7 @@ class ConfigurationClassParser {
// process superclass, if any
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (!this.knownSuperclasses.containsKey(superclass)) {
if (!superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// superclass found, return its annotation metadata and recurse
try {
@@ -305,23 +318,15 @@ class ConfigurationClassParser {
String name = propertySource.getString("name");
String[] locations = propertySource.getStringArray("value");
boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound");
int locationCount = locations.length;
if (locationCount == 0) {
if (locations.length == 0) {
throw new IllegalArgumentException("At least one @PropertySource(value) location is required");
}
for (String location : locations) {
try {
Resource resource = this.resourceLoader.getResource(
this.environment.resolveRequiredPlaceholders(location));
if (!StringUtils.hasText(name) || this.propertySources.containsKey(name)) {
// We need to ensure unique names when the property source will
// ultimately end up in a composite
ResourcePropertySource ps = new ResourcePropertySource(resource);
this.propertySources.add((StringUtils.hasText(name) ? name : ps.getName()), ps);
}
else {
this.propertySources.add(name, new ResourcePropertySource(name, resource));
}
String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);
Resource resource = this.resourceLoader.getResource(resolvedLocation);
ResourcePropertySource ps = new ResourcePropertySource(resource);
this.propertySources.add((StringUtils.hasText(name) ? name : ps.getName()), ps);
}
catch (IllegalArgumentException ex) {
// from resolveRequiredPlaceholders
@@ -473,26 +478,26 @@ class ConfigurationClassParser {
* @see ConfigurationClass#validate
*/
public void validate() {
for (ConfigurationClass configClass : this.configurationClasses) {
for (ConfigurationClass configClass : this.configurationClasses.keySet()) {
configClass.validate(this.problemReporter);
}
}
public Set<ConfigurationClass> getConfigurationClasses() {
return this.configurationClasses;
return this.configurationClasses.keySet();
}
public List<PropertySource<?>> getPropertySources() {
List<PropertySource<?>> propertySources = new LinkedList<PropertySource<?>>();
for (Map.Entry<String, List<PropertySource<?>>> entry : this.propertySources.entrySet()) {
for (Map.Entry<String, List<ResourcePropertySource>> entry : this.propertySources.entrySet()) {
propertySources.add(0, collatePropertySources(entry.getKey(), entry.getValue()));
}
return propertySources;
}
private PropertySource<?> collatePropertySources(String name, List<PropertySource<?>> propertySources) {
private PropertySource<?> collatePropertySources(String name, List<ResourcePropertySource> propertySources) {
if (propertySources.size() == 1) {
return propertySources.get(0);
return propertySources.get(0).withName(name);
}
CompositePropertySource result = new CompositePropertySource(name);
for (int i = propertySources.size() - 1; i >= 0; i--) {
@@ -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.
@@ -307,7 +307,7 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
"Reason: Environment must implement ConfigurableEnvironment");
}
else {
MutablePropertySources envPropertySources = ((ConfigurableEnvironment)this.environment).getPropertySources();
MutablePropertySources envPropertySources = ((ConfigurableEnvironment) this.environment).getPropertySources();
for (PropertySource<?> propertySource : parsedPropertySources) {
envPropertySources.addLast(propertySource);
}
@@ -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.
@@ -119,7 +119,7 @@ abstract class ConfigurationClassUtils {
/**
* Check the given metadata for a lite configuration class candidate
* (i.e. a class annotated with {@code @Component} or just having
* (e.g. a class annotated with {@code @Component} or just having
* {@code @Import} declarations or {@code @Bean methods}).
* @param metadata the metadata of the annotated class
* @return {@code true} if the given class is to be processed as a lite
@@ -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,40 +19,40 @@ package org.springframework.context.annotation;
/**
* A {@link Condition} that offers more fine-grained control when used with
* {@code @Configuration}. Allows certain {@link Condition}s to adapt when they match
* based on the configuration phase. For example, a condition that checks if a bean has
* already been registered might choose to only be evaluated during the
* based on the configuration phase. For example, a condition that checks if a bean
* has already been registered might choose to only be evaluated during the
* {@link ConfigurationPhase#REGISTER_BEAN REGISTER_BEAN} {@link ConfigurationPhase}.
*
* @author Phillip Webb
* @since 4.0
* @see Configuration
*/
public interface ConfigurationCondition extends Condition {
/**
* Returns the {@link ConfigurationPhase} in which the condition should be evaluated.
* Return the {@link ConfigurationPhase} in which the condition should be evaluated.
*/
ConfigurationPhase getConfigurationPhase();
/**
* The various configuration phases where the condition could be evaluated.
*/
public static enum ConfigurationPhase {
/**
* The {@link Condition} should be evaluated as a {@code @Configuration} class is
* being parsed.
*
* <p>If the condition does not match at this point the {@code @Configuration}
* The {@link Condition} should be evaluated as a {@code @Configuration}
* class is being parsed.
* <p>If the condition does not match at this point, the {@code @Configuration}
* class will not be added.
*/
PARSE_CONFIGURATION,
/**
* The {@link Condition} should be evaluated when adding a regular (non
* {@code @Configuration}) bean. The condition will not prevent
* The {@link Condition} should be evaluated when adding a regular
* (non {@code @Configuration}) bean. The condition will not prevent
* {@code @Configuration} classes from being added.
*
* <p>At the time that the condition is evaluated all {@code @Configuration}s
* <p>At the time that the condition is evaluated, all {@code @Configuration}s
* will have been parsed.
*/
REGISTER_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.
@@ -32,6 +32,7 @@ import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* Advisor that activates asynchronous method execution through the {@link Async}
@@ -73,9 +74,9 @@ public class AsyncAnnotationAdvisor extends AbstractPointcutAdvisor implements B
public AsyncAnnotationAdvisor(Executor executor) {
Set<Class<? extends Annotation>> asyncAnnotationTypes = new LinkedHashSet<Class<? extends Annotation>>(2);
asyncAnnotationTypes.add(Async.class);
ClassLoader cl = AsyncAnnotationAdvisor.class.getClassLoader();
try {
asyncAnnotationTypes.add((Class<? extends Annotation>) cl.loadClass("javax.ejb.Asynchronous"));
asyncAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.ejb.Asynchronous", AsyncAnnotationAdvisor.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
// If EJB 3.1 API not present, simply ignore.
@@ -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.
@@ -25,7 +25,6 @@ import java.util.List;
import org.jruby.Ruby;
import org.jruby.RubyArray;
import org.jruby.RubyException;
import org.jruby.RubyNil;
import org.jruby.ast.ClassNode;
import org.jruby.ast.Colon2Node;
@@ -116,10 +115,12 @@ public abstract class JRubyScriptUtils {
/**
* Find the first {@link ClassNode} under the supplied {@link Node}.
* @return the found {@code ClassNode}, or {@code null}
* if no {@link ClassNode} is found
* @return the corresponding {@code ClassNode}, or {@code null} if none found
*/
private static ClassNode findClassNode(Node node) {
if (node == null) {
return null;
}
if (node instanceof ClassNode) {
return (ClassNode) node;
}
@@ -229,9 +230,6 @@ public abstract class JRubyScriptUtils {
/**
* Exception thrown in response to a JRuby {@link RaiseException}
* being thrown from a JRuby method invocation.
* <p>Introduced because the {@code RaiseException} class does not
* have useful {@link Object#toString()}, {@link Throwable#getMessage()},
* and {@link Throwable#printStackTrace} implementations.
*/
@SuppressWarnings("serial")
public static class JRubyExecutionException extends NestedRuntimeException {
@@ -242,12 +240,7 @@ public abstract class JRubyScriptUtils {
* @param ex the cause (must not be {@code null})
*/
public JRubyExecutionException(RaiseException ex) {
super(buildMessage(ex), ex);
}
private static String buildMessage(RaiseException ex) {
RubyException rubyEx = ex.getException();
return (rubyEx != null && rubyEx.message != null) ? rubyEx.message.toString() : "Unexpected JRuby error";
super(ex.getMessage(), ex);
}
}
@@ -102,6 +102,7 @@ public final class CglibProxyTests extends AbstractAopProxyTests implements Seri
@Test
public void testProtectedMethodInvocation() {
ProtectedMethodTestBean bean = new ProtectedMethodTestBean();
bean.value = "foo";
mockTargetSource.setTarget(bean);
AdvisedSupport as = new AdvisedSupport(new Class<?>[]{});
@@ -109,8 +110,47 @@ public final class CglibProxyTests extends AbstractAopProxyTests implements Seri
as.addAdvice(new NopInterceptor());
AopProxy aop = new CglibAopProxy(as);
Object proxy = aop.getProxy();
ProtectedMethodTestBean proxy = (ProtectedMethodTestBean) aop.getProxy();
assertTrue(AopUtils.isCglibProxy(proxy));
assertEquals(proxy.getClass().getClassLoader(), bean.getClass().getClassLoader());
assertEquals("foo", proxy.getString());
}
@Test
public void testPackageMethodInvocation() {
PackageMethodTestBean bean = new PackageMethodTestBean();
bean.value = "foo";
mockTargetSource.setTarget(bean);
AdvisedSupport as = new AdvisedSupport(new Class<?>[]{});
as.setTargetSource(mockTargetSource);
as.addAdvice(new NopInterceptor());
AopProxy aop = new CglibAopProxy(as);
PackageMethodTestBean proxy = (PackageMethodTestBean) aop.getProxy();
assertTrue(AopUtils.isCglibProxy(proxy));
assertEquals(proxy.getClass().getClassLoader(), bean.getClass().getClassLoader());
assertEquals("foo", proxy.getString());
}
@Test
public void testPackageMethodInvocationWithDifferentClassLoader() {
ClassLoader child = new ClassLoader(getClass().getClassLoader()) {
};
PackageMethodTestBean bean = new PackageMethodTestBean();
bean.value = "foo";
mockTargetSource.setTarget(bean);
AdvisedSupport as = new AdvisedSupport(new Class<?>[]{});
as.setTargetSource(mockTargetSource);
as.addAdvice(new NopInterceptor());
AopProxy aop = new CglibAopProxy(as);
PackageMethodTestBean proxy = (PackageMethodTestBean) aop.getProxy(child);
assertTrue(AopUtils.isCglibProxy(proxy));
assertNotEquals(proxy.getClass().getClassLoader(), bean.getClass().getClassLoader());
assertNull(proxy.getString()); // we're stuck in the proxy instance
}
@Test
@@ -410,9 +450,40 @@ public final class CglibProxyTests extends AbstractAopProxyTests implements Seri
}
public static class HasFinalMethod {
public static class NoArgCtorTestBean {
public final void foo() {
private boolean called = false;
public NoArgCtorTestBean(String x, int y) {
called = true;
}
public boolean wasCalled() {
return called;
}
public void reset() {
called = false;
}
}
public static class ProtectedMethodTestBean {
public String value;
protected String getString() {
return this.value;
}
}
public static class PackageMethodTestBean {
public String value;
String getString() {
return this.value;
}
}
}
@@ -436,32 +507,6 @@ class CglibTestBean {
}
class NoArgCtorTestBean {
private boolean called = false;
public NoArgCtorTestBean(String x, int y) {
called = true;
}
public boolean wasCalled() {
return called;
}
public void reset() {
called = false;
}
}
class ProtectedMethodTestBean {
protected String getString() {
return "foo";
}
}
class UnsupportedInterceptor implements MethodInterceptor {
@Override
@@ -0,0 +1,118 @@
/*
* 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.cache.config;
import org.junit.Test;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
*
* @author Stephane Nicoll
*/
public class ExpressionCachingIntegrationTests {
@SuppressWarnings("unchecked")
@Test // SPR-11692
public void expressionIsCacheBasedOnActualMethod() {
ConfigurableApplicationContext context =
new AnnotationConfigApplicationContext(SharedConfig.class, Spr11692Config.class);
BaseDao<User> userDao = (BaseDao<User>) context.getBean("userDao");
BaseDao<Order> orderDao = (BaseDao<Order>) context.getBean("orderDao");
userDao.persist(new User("1"));
orderDao.persist(new Order("2"));
context.close();
}
@Configuration
static class Spr11692Config {
@Bean
public BaseDao<User> userDao() {
return new UserDaoImpl();
}
@Bean
public BaseDao<Order> orderDao() {
return new OrderDaoImpl();
}
}
private static interface BaseDao<T> {
T persist(T t);
}
private static class UserDaoImpl implements BaseDao<User> {
@Override
@CachePut(value = "users", key = "#user.id")
public User persist(User user) {
return user;
}
}
private static class OrderDaoImpl implements BaseDao<Order> {
@Override
@CachePut(value = "orders", key = "#order.id")
public Order persist(Order order) {
return order;
}
}
private static class User {
private final String id;
private User(String id) {
this.id = id;
}
public String getId() {
return id;
}
}
private static class Order {
private final String id;
private Order(String id) {
this.id = id;
}
public String getId() {
return id;
}
}
@Configuration
@EnableCaching
static class SharedConfig {
@Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager();
}
}
}
@@ -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.
@@ -39,6 +39,7 @@ import static org.junit.Assert.*;
* @author Costin Leau
* @author Phillip Webb
* @author Sam Brannen
* @author Stephane Nicoll
*/
public class ExpressionEvaluatorTests {
@@ -82,8 +83,10 @@ public class ExpressionEvaluatorTests {
Iterator<CacheOperation> it = ops.iterator();
Object keyA = eval.key(it.next().getKey(), method, evalCtx);
Object keyB = eval.key(it.next().getKey(), method, evalCtx);
MethodCacheKey key = new MethodCacheKey(method, AnnotatedClass.class);
Object keyA = eval.key(it.next().getKey(), key, evalCtx);
Object keyB = eval.key(it.next().getKey(), key, evalCtx);
assertEquals(args[0], keyA);
assertEquals(args[1], keyB);
@@ -23,6 +23,7 @@ import org.junit.Test;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.aop.interceptor.SimpleTraceInterceptor;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
@@ -55,6 +56,39 @@ public class BeanMethodPolymorphismTests {
assertTrue(ctx.getDefaultListableBeanFactory().containsSingleton("testBean"));
}
@Test
public void beanMethodOverridingOnASM() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.registerBeanDefinition("config", new RootBeanDefinition(OverridingConfig.class.getName()));
ctx.setAllowBeanDefinitionOverriding(false);
ctx.refresh();
assertFalse(ctx.getDefaultListableBeanFactory().containsSingleton("testBean"));
assertEquals("overridden", ctx.getBean("testBean", TestBean.class).toString());
assertTrue(ctx.getDefaultListableBeanFactory().containsSingleton("testBean"));
}
@Test
public void beanMethodOverridingWithNarrowedReturnType() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(NarrowedOverridingConfig.class);
ctx.setAllowBeanDefinitionOverriding(false);
ctx.refresh();
assertFalse(ctx.getDefaultListableBeanFactory().containsSingleton("testBean"));
assertEquals("overridden", ctx.getBean("testBean", TestBean.class).toString());
assertTrue(ctx.getDefaultListableBeanFactory().containsSingleton("testBean"));
}
@Test
public void beanMethodOverridingWithNarrowedReturnTypeOnASM() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.registerBeanDefinition("config", new RootBeanDefinition(NarrowedOverridingConfig.class.getName()));
ctx.setAllowBeanDefinitionOverriding(false);
ctx.refresh();
assertFalse(ctx.getDefaultListableBeanFactory().containsSingleton("testBean"));
assertEquals("overridden", ctx.getBean("testBean", TestBean.class).toString());
assertTrue(ctx.getDefaultListableBeanFactory().containsSingleton("testBean"));
}
@Test
public void beanMethodOverloadingWithoutInheritance() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
@@ -173,6 +207,26 @@ public class BeanMethodPolymorphismTests {
}
static class ExtendedTestBean extends TestBean {
}
@Configuration
static class NarrowedOverridingConfig extends BaseConfig {
@Bean @Lazy
@Override
public ExtendedTestBean testBean() {
return new ExtendedTestBean() {
@Override
public String toString() {
return "overridden";
}
};
}
}
@Configuration
static class ConfigWithOverloading {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 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,6 +17,8 @@
package org.springframework.context.annotation;
import org.junit.Test;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.componentscan.simple.SimpleComponent;
/**
@@ -36,17 +38,61 @@ public class ComponentScanAndImportAnnotationInteractionTests {
ctx.getBean(SimpleComponent.class); // succeeds -> there is only one bean of type SimpleComponent
}
@Test
public void componentScanOverlapsWithImportUsingAsm() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.registerBeanDefinition("config1", new RootBeanDefinition(Config1.class.getName()));
ctx.registerBeanDefinition("config2", new RootBeanDefinition(Config2.class.getName()));
ctx.refresh(); // no conflicts found trying to register SimpleComponent
ctx.getBean(SimpleComponent.class); // succeeds -> there is only one bean of type SimpleComponent
}
@Test
public void componentScanViaImport() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(Config3.class);
ctx.refresh();
ctx.getBean(SimpleComponent.class);
}
@Test
public void componentScanViaImportUsingAsm() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.registerBeanDefinition("config4", new RootBeanDefinition(Config3.class.getName()));
ctx.refresh();
ctx.getBean(SimpleComponent.class);
}
@Test
public void componentScanViaImportUsingScan() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.scan("org.springframework.context.annotation.componentscan.importing");
ctx.refresh();
ctx.getBean(SimpleComponent.class);
}
@Configuration
@ComponentScan("org.springframework.context.annotation.componentscan.simple")
static class Config1 {
}
@Configuration
@Import(org.springframework.context.annotation.componentscan.simple.SimpleComponent.class)
static class Config2 {
}
@Configuration
@Import(ImportedConfig.class)
static class Config3 {
}
@Configuration
@ComponentScan("org.springframework.context.annotation.componentscan.simple")
public static class ImportedConfig {
}
}
@@ -23,6 +23,7 @@ import java.lang.annotation.Target;
import org.junit.Before;
import org.junit.Test;
import org.springframework.aop.scope.ScopedObject;
import org.springframework.aop.scope.ScopedProxyUtils;
import org.springframework.beans.factory.FactoryBean;
@@ -86,8 +87,7 @@ public class ConfigurationClassPostProcessorTests {
*/
@Test
public void alreadyLoadedConfigurationClasses() {
beanFactory.registerBeanDefinition("unloadedConfig", new RootBeanDefinition(UnloadedConfig.class.getName(),
null, null));
beanFactory.registerBeanDefinition("unloadedConfig", new RootBeanDefinition(UnloadedConfig.class.getName()));
beanFactory.registerBeanDefinition("loadedConfig", new RootBeanDefinition(LoadedConfig.class));
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
pp.postProcessBeanFactory(beanFactory);
@@ -126,56 +126,56 @@ public class ConfigurationClassPostProcessorTests {
@Test
public void postProcessorWorksWithComposedConfigurationWithAttributeOverridesUsingReflection() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(
ComposedConfigurationWithAttributeOverridesClass.class);
ComposedConfigurationWithAttributeOverridesClass.class);
assertSupportForComposedAnnotation(beanDefinition);
}
@Test
public void postProcessorWorksWithComposedConfigurationWithAttributeOverridesUsingAsm() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(
ComposedConfigurationWithAttributeOverridesClass.class.getName());
ComposedConfigurationWithAttributeOverridesClass.class.getName());
assertSupportForComposedAnnotation(beanDefinition);
}
@Test
public void postProcessorWorksWithComposedComposedConfigurationWithAttributeOverridesUsingReflection() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(
ComposedComposedConfigurationWithAttributeOverridesClass.class);
ComposedComposedConfigurationWithAttributeOverridesClass.class);
assertSupportForComposedAnnotation(beanDefinition);
}
@Test
public void postProcessorWorksWithComposedComposedConfigurationWithAttributeOverridesUsingAsm() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(
ComposedComposedConfigurationWithAttributeOverridesClass.class.getName());
ComposedComposedConfigurationWithAttributeOverridesClass.class.getName());
assertSupportForComposedAnnotation(beanDefinition);
}
@Test
public void postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesUsingReflection() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(
MetaComponentScanConfigurationWithAttributeOverridesClass.class);
MetaComponentScanConfigurationWithAttributeOverridesClass.class);
assertSupportForComposedAnnotation(beanDefinition);
}
@Test
public void postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesUsingAsm() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(
MetaComponentScanConfigurationWithAttributeOverridesClass.class.getName());
MetaComponentScanConfigurationWithAttributeOverridesClass.class.getName());
assertSupportForComposedAnnotation(beanDefinition);
}
@Test
public void postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesSubclassUsingReflection() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(
SubMetaComponentScanConfigurationWithAttributeOverridesClass.class);
SubMetaComponentScanConfigurationWithAttributeOverridesClass.class);
assertSupportForComposedAnnotation(beanDefinition);
}
@Test
public void postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesSubclassUsingAsm() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(
SubMetaComponentScanConfigurationWithAttributeOverridesClass.class.getName());
SubMetaComponentScanConfigurationWithAttributeOverridesClass.class.getName());
assertSupportForComposedAnnotation(beanDefinition);
}
@@ -208,8 +208,8 @@ public class ConfigurationClassPostProcessorTests {
public void postProcessorDoesNotOverrideRegularBeanDefinitionsEvenWithScopedProxy() {
RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class);
rbd.setResource(new DescriptiveResource("XML or something"));
BeanDefinitionHolder proxied = ScopedProxyUtils.createScopedProxy(new BeanDefinitionHolder(rbd, "bar"),
beanFactory, true);
BeanDefinitionHolder proxied = ScopedProxyUtils.createScopedProxy(
new BeanDefinitionHolder(rbd, "bar"), beanFactory, true);
beanFactory.registerBeanDefinition("bar", proxied.getBeanDefinition());
beanFactory.registerBeanDefinition("config", new RootBeanDefinition(SingletonBeanConfig.class));
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
@@ -296,8 +296,7 @@ public class ConfigurationClassPostProcessorTests {
RootBeanDefinition bd = new RootBeanDefinition(RepositoryInjectionBean.class);
bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
beanFactory.registerBeanDefinition("annotatedBean", bd);
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(
ScopedProxyRepositoryConfiguration.class));
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(ScopedProxyRepositoryConfiguration.class));
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
pp.postProcessBeanFactory(beanFactory);
beanFactory.freezeConfiguration();
@@ -332,8 +331,7 @@ public class ConfigurationClassPostProcessorTests {
RootBeanDefinition bd = new RootBeanDefinition(RepositoryFactoryBeanInjectionBean.class);
bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
beanFactory.registerBeanDefinition("annotatedBean", bd);
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(
RepositoryFactoryBeanConfiguration.class));
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RepositoryFactoryBeanConfiguration.class));
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
pp.postProcessBeanFactory(beanFactory);
beanFactory.preInstantiateSingletons();
@@ -374,8 +372,7 @@ public class ConfigurationClassPostProcessorTests {
@Test
public void genericsBasedInjectionWithWildcardWithGenericExtendsMatch() {
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(
WildcardWithGenericExtendsConfiguration.class));
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(WildcardWithGenericExtendsConfiguration.class));
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
pp.postProcessBeanFactory(beanFactory);
@@ -574,7 +571,6 @@ public class ConfigurationClassPostProcessorTests {
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public Repository<String> stringRepo() {
return new Repository<String>() {
@Override
public String toString() {
return "Repository<String>";
@@ -586,7 +582,6 @@ public class ConfigurationClassPostProcessorTests {
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public Repository<Integer> integerRepo() {
return new Repository<Integer>() {
@Override
public String toString() {
return "Repository<Integer>";
@@ -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,6 +123,7 @@ public class NestedConfigurationClassTests {
@Configuration
static class L0Config {
@Bean
public TestBean l0Bean() {
return new TestBean("l0");
@@ -135,6 +136,7 @@ public class NestedConfigurationClassTests {
@Configuration
static class L1Config {
@Bean
public TestBean l1Bean() {
return new TestBean("l1");
@@ -147,6 +149,7 @@ public class NestedConfigurationClassTests {
@Configuration
protected static class L2Config {
@Bean
public TestBean l2Bean() {
return new TestBean("l2");
@@ -163,6 +166,7 @@ public class NestedConfigurationClassTests {
@Component
static class L0ConfigLight {
@Bean
public TestBean l0Bean() {
return new TestBean("l0");
@@ -175,6 +179,7 @@ public class NestedConfigurationClassTests {
@Component
static class L1ConfigLight {
@Bean
public TestBean l1Bean() {
return new TestBean("l1");
@@ -187,6 +192,7 @@ public class NestedConfigurationClassTests {
@Component
protected static class L2ConfigLight {
@Bean
public TestBean l2Bean() {
return new TestBean("l2");
@@ -216,6 +222,7 @@ public class NestedConfigurationClassTests {
@Configuration
static class S1Config extends L0Config {
@Override
@Bean
public TestBean overrideBean() {
@@ -124,21 +124,14 @@ public class PropertySourceAnnotationTests {
System.clearProperty("path.to.properties");
}
/**
* Corner bug reported in SPR-9127.
*/
@Test
public void withNameAndMultipleResourceLocations() {
@Test(expected = IllegalArgumentException.class)
public void withEmptyResourceLocations() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(ConfigWithNameAndMultipleResourceLocations.class);
ctx.register(ConfigWithEmptyResourceLocations.class);
ctx.refresh();
assertThat(ctx.getEnvironment().containsProperty("from.p1"), is(true));
assertThat(ctx.getEnvironment().containsProperty("from.p2"), is(true));
}
/**
* SPR-10820
*/
// SPR-10820
@Test
public void orderingWithAndWithoutNameAndMultipleResourceLocations() {
// p2 should 'win' as it was registered last
@@ -148,11 +141,22 @@ public class PropertySourceAnnotationTests {
assertThat(ctxWithName.getEnvironment().getProperty("testbean.name"), equalTo("p2TestBean"));
}
@Test(expected=IllegalArgumentException.class)
public void withEmptyResourceLocations() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(ConfigWithEmptyResourceLocations.class);
ctx.refresh();
@Test
public void withNameAndMultipleResourceLocations() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigWithNameAndMultipleResourceLocations.class);
assertThat(ctx.getEnvironment().containsProperty("from.p1"), is(true));
assertThat(ctx.getEnvironment().containsProperty("from.p2"), is(true));
// p2 should 'win' as it was registered last
assertThat(ctx.getEnvironment().getProperty("testbean.name"), equalTo("p2TestBean"));
}
@Test
public void withMultipleResourceLocations() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigWithMultipleResourceLocations.class);
assertThat(ctx.getEnvironment().containsProperty("from.p1"), is(true));
assertThat(ctx.getEnvironment().containsProperty("from.p2"), is(true));
// p2 should 'win' as it was registered last
assertThat(ctx.getEnvironment().getProperty("testbean.name"), equalTo("p2TestBean"));
}
@Test
@@ -164,6 +168,15 @@ public class PropertySourceAnnotationTests {
assertThat(ctx.getEnvironment().getProperty("testbean.name"), equalTo("p2TestBean"));
}
@Test
public void withNamedPropertySources() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigWithNamedPropertySources.class);
assertThat(ctx.getEnvironment().containsProperty("from.p1"), is(true));
assertThat(ctx.getEnvironment().containsProperty("from.p2"), is(true));
// p2 should 'win' as it was registered last
assertThat(ctx.getEnvironment().getProperty("testbean.name"), equalTo("p2TestBean"));
}
@Test
public void withMissingPropertySource() {
thrown.expect(BeanDefinitionStoreException.class);
@@ -263,8 +276,8 @@ public class PropertySourceAnnotationTests {
@Configuration
@PropertySources({
@PropertySource(name = "psName", value="classpath:org/springframework/context/annotation/p1.properties"),
@PropertySource(name = "psName", value="classpath:org/springframework/context/annotation/p2.properties")
@PropertySource("classpath:org/springframework/context/annotation/p1.properties"),
@PropertySource("classpath:org/springframework/context/annotation/p2.properties"),
})
static class ConfigWithPropertySources {
}
@@ -272,9 +285,18 @@ public class PropertySourceAnnotationTests {
@Configuration
@PropertySources({
@PropertySource(name = "psName", value="classpath:org/springframework/context/annotation/p1.properties"),
@PropertySource(name = "psName", value="classpath:org/springframework/context/annotation/missing.properties"),
@PropertySource(name = "psName", value="classpath:org/springframework/context/annotation/p2.properties")
@PropertySource(name = "psName", value = "classpath:org/springframework/context/annotation/p1.properties"),
@PropertySource(name = "psName", value = "classpath:org/springframework/context/annotation/p2.properties"),
})
static class ConfigWithNamedPropertySources {
}
@Configuration
@PropertySources({
@PropertySource(name = "psName", value = "classpath:org/springframework/context/annotation/p1.properties"),
@PropertySource(name = "psName", value = "classpath:org/springframework/context/annotation/missing.properties"),
@PropertySource(name = "psName", value = "classpath:org/springframework/context/annotation/p2.properties")
})
static class ConfigWithMissingPropertySource {
}
@@ -282,10 +304,10 @@ public class PropertySourceAnnotationTests {
@Configuration
@PropertySources({
@PropertySource(name = "psName", value="classpath:org/springframework/context/annotation/p1.properties"),
@PropertySource(name = "psName", value="classpath:org/springframework/context/annotation/missing.properties", ignoreResourceNotFound=true),
@PropertySource(name = "psName", value="classpath:${myPath}/missing.properties", ignoreResourceNotFound=true),
@PropertySource(name = "psName", value="classpath:org/springframework/context/annotation/p2.properties")
@PropertySource(name = "psName", value = "classpath:org/springframework/context/annotation/p1.properties"),
@PropertySource(name = "psName", value = "classpath:org/springframework/context/annotation/missing.properties", ignoreResourceNotFound=true),
@PropertySource(name = "psName", value = "classpath:${myPath}/missing.properties", ignoreResourceNotFound=true),
@PropertySource(name = "psName", value = "classpath:org/springframework/context/annotation/p2.properties")
})
static class ConfigWithIgnoredPropertySource {
}
@@ -0,0 +1,26 @@
/*
* 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.context.annotation.componentscan.importing;
import org.springframework.context.annotation.ComponentScanAndImportAnnotationInteractionTests;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import(ComponentScanAndImportAnnotationInteractionTests.ImportedConfig.class)
public class ImportingConfig {
}
@@ -0,0 +1,115 @@
/*
* Copyright 2012-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.context.annotation.configuration;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConfigurationCondition;
import org.springframework.context.annotation.Import;
import org.springframework.core.type.AnnotatedTypeMetadata;
import static org.junit.Assert.*;
/**
* @author Andy Wilkinson
*/
public class ImportWithConditionTests {
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
@Test
public void conditionalThenUnconditional() throws Exception {
this.context.register(ConditionalThenUnconditional.class);
this.context.refresh();
assertFalse(this.context.containsBean("beanTwo"));
assertTrue(this.context.containsBean("beanOne"));
}
@Test
public void unconditionalThenConditional() throws Exception {
this.context.register(UnconditionalThenConditional.class);
this.context.refresh();
assertFalse(this.context.containsBean("beanTwo"));
assertTrue(this.context.containsBean("beanOne"));
}
@Configuration
@Import({ConditionalConfiguration.class, UnconditionalConfiguration.class})
protected static class ConditionalThenUnconditional {
@Autowired
private BeanOne beanOne;
}
@Configuration
@Import({UnconditionalConfiguration.class, ConditionalConfiguration.class})
protected static class UnconditionalThenConditional {
@Autowired
private BeanOne beanOne;
}
@Configuration
@Import(BeanProvidingConfiguration.class)
protected static class UnconditionalConfiguration {
}
@Configuration
@Conditional(NeverMatchingCondition.class)
@Import(BeanProvidingConfiguration.class)
protected static class ConditionalConfiguration {
}
@Configuration
protected static class BeanProvidingConfiguration {
@Bean
BeanOne beanOne() {
return new BeanOne();
}
}
private static final class BeanOne {
}
private static final class NeverMatchingCondition implements ConfigurationCondition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return false;
}
@Override
public ConfigurationPhase getConfigurationPhase() {
return ConfigurationPhase.REGISTER_BEAN;
}
}
}
@@ -0,0 +1,130 @@
/*
* 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.context.annotation.configuration;
import org.junit.Test;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
/**
* @author Phillip Webb
*/
public class Spr10744Tests {
private static int createCount = 0;
private static int scopeCount = 0;
@Test
public void testSpr10744() throws Exception {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.getBeanFactory().registerScope("myTestScope", new MyTestScope());
context.register(MyTestConfiguration.class);
context.refresh();
Foo bean1 = context.getBean("foo", Foo.class);
Foo bean2 = context.getBean("foo", Foo.class);
assertThat(bean1, sameInstance(bean2));
// Should not have invoked constructor for the proxy instance
assertThat(createCount, equalTo(0));
assertThat(scopeCount, equalTo(0));
// Proxy mode should create new scoped object on each method call
bean1.getMessage();
assertThat(createCount, equalTo(1));
assertThat(scopeCount, equalTo(1));
bean1.getMessage();
assertThat(createCount, equalTo(2));
assertThat(scopeCount, equalTo(2));
context.close();
}
private static class MyTestScope implements org.springframework.beans.factory.config.Scope {
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
scopeCount++;
return objectFactory.getObject();
}
@Override
public Object remove(String name) {
return null;
}
@Override
public void registerDestructionCallback(String name, Runnable callback) {
}
@Override
public Object resolveContextualObject(String key) {
return null;
}
@Override
public String getConversationId() {
return null;
}
}
static class Foo {
public Foo() {
createCount++;
}
public String getMessage() {
return "Hello";
}
}
@Configuration
static class MyConfiguration {
@Bean
public Foo foo() {
return new Foo();
}
}
@Configuration
static class MyTestConfiguration extends MyConfiguration {
@Bean
@Scope(value = "myTestScope", proxyMode = ScopedProxyMode.TARGET_CLASS)
@Override
public Foo foo() {
return new Foo();
}
}
}
@@ -18,19 +18,22 @@ package org.springframework.scheduling.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.HashMap;
import java.util.concurrent.Future;
import org.junit.Before;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.junit.Test;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.aop.support.DefaultIntroductionAdvisor;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.tests.Assume;
import org.springframework.tests.TestGroup;
import static org.junit.Assert.*;
@@ -46,10 +49,6 @@ public class AsyncExecutionTests {
private static int listenerConstructed = 0;
@Before
public void setUp() {
Assume.group(TestGroup.PERFORMANCE);
}
@Test
public void asyncMethods() throws Exception {
@@ -135,6 +134,46 @@ public class AsyncExecutionTests {
assertEquals("20", future.get());
}
@Test
public void asyncClassWithPostProcessor() throws Exception {
originalThreadName = Thread.currentThread().getName();
GenericApplicationContext context = new GenericApplicationContext();
context.registerBeanDefinition("asyncTest", new RootBeanDefinition(AsyncClassBean.class));
context.registerBeanDefinition("asyncProcessor", new RootBeanDefinition(AsyncAnnotationBeanPostProcessor.class));
context.refresh();
AsyncClassBean asyncTest = context.getBean("asyncTest", AsyncClassBean.class);
asyncTest.doSomething(10);
Future<String> future = asyncTest.returnSomething(20);
assertEquals("20", future.get());
}
@Test
public void asyncClassWithInterface() throws Exception {
originalThreadName = Thread.currentThread().getName();
GenericApplicationContext context = new GenericApplicationContext();
context.registerBeanDefinition("asyncTest", new RootBeanDefinition(AsyncClassBeanWithInterface.class));
context.registerBeanDefinition("autoProxyCreator", new RootBeanDefinition(DefaultAdvisorAutoProxyCreator.class));
context.registerBeanDefinition("asyncAdvisor", new RootBeanDefinition(AsyncAnnotationAdvisor.class));
context.refresh();
RegularInterface asyncTest = context.getBean("asyncTest", RegularInterface.class);
asyncTest.doSomething(10);
Future<String> future = asyncTest.returnSomething(20);
assertEquals("20", future.get());
}
@Test
public void asyncClassWithInterfaceAndPostProcessor() throws Exception {
originalThreadName = Thread.currentThread().getName();
GenericApplicationContext context = new GenericApplicationContext();
context.registerBeanDefinition("asyncTest", new RootBeanDefinition(AsyncClassBeanWithInterface.class));
context.registerBeanDefinition("asyncProcessor", new RootBeanDefinition(AsyncAnnotationBeanPostProcessor.class));
context.refresh();
RegularInterface asyncTest = context.getBean("asyncTest", RegularInterface.class);
asyncTest.doSomething(10);
Future<String> future = asyncTest.returnSomething(20);
assertEquals("20", future.get());
}
@Test
public void asyncInterface() throws Exception {
originalThreadName = Thread.currentThread().getName();
@@ -149,6 +188,46 @@ public class AsyncExecutionTests {
assertEquals("20", future.get());
}
@Test
public void asyncInterfaceWithPostProcessor() throws Exception {
originalThreadName = Thread.currentThread().getName();
GenericApplicationContext context = new GenericApplicationContext();
context.registerBeanDefinition("asyncTest", new RootBeanDefinition(AsyncInterfaceBean.class));
context.registerBeanDefinition("asyncProcessor", new RootBeanDefinition(AsyncAnnotationBeanPostProcessor.class));
context.refresh();
AsyncInterface asyncTest = context.getBean("asyncTest", AsyncInterface.class);
asyncTest.doSomething(10);
Future<String> future = asyncTest.returnSomething(20);
assertEquals("20", future.get());
}
@Test
public void dynamicAsyncInterface() throws Exception {
originalThreadName = Thread.currentThread().getName();
GenericApplicationContext context = new GenericApplicationContext();
context.registerBeanDefinition("asyncTest", new RootBeanDefinition(DynamicAsyncInterfaceBean.class));
context.registerBeanDefinition("autoProxyCreator", new RootBeanDefinition(DefaultAdvisorAutoProxyCreator.class));
context.registerBeanDefinition("asyncAdvisor", new RootBeanDefinition(AsyncAnnotationAdvisor.class));
context.refresh();
AsyncInterface asyncTest = context.getBean("asyncTest", AsyncInterface.class);
asyncTest.doSomething(10);
Future<String> future = asyncTest.returnSomething(20);
assertEquals("20", future.get());
}
@Test
public void dynamicAsyncInterfaceWithPostProcessor() throws Exception {
originalThreadName = Thread.currentThread().getName();
GenericApplicationContext context = new GenericApplicationContext();
context.registerBeanDefinition("asyncTest", new RootBeanDefinition(DynamicAsyncInterfaceBean.class));
context.registerBeanDefinition("asyncProcessor", new RootBeanDefinition(AsyncAnnotationBeanPostProcessor.class));
context.refresh();
AsyncInterface asyncTest = context.getBean("asyncTest", AsyncInterface.class);
asyncTest.doSomething(10);
Future<String> future = asyncTest.returnSomething(20);
assertEquals("20", future.get());
}
@Test
public void asyncMethodsInInterface() throws Exception {
originalThreadName = Thread.currentThread().getName();
@@ -164,6 +243,33 @@ public class AsyncExecutionTests {
assertEquals("20", future.get());
}
@Test
public void asyncMethodsInInterfaceWithPostProcessor() throws Exception {
originalThreadName = Thread.currentThread().getName();
GenericApplicationContext context = new GenericApplicationContext();
context.registerBeanDefinition("asyncTest", new RootBeanDefinition(AsyncMethodsInterfaceBean.class));
context.registerBeanDefinition("asyncProcessor", new RootBeanDefinition(AsyncAnnotationBeanPostProcessor.class));
context.refresh();
AsyncMethodsInterface asyncTest = context.getBean("asyncTest", AsyncMethodsInterface.class);
asyncTest.doNothing(5);
asyncTest.doSomething(10);
Future<String> future = asyncTest.returnSomething(20);
assertEquals("20", future.get());
}
@Test
public void dynamicAsyncMethodsInInterfaceWithPostProcessor() throws Exception {
originalThreadName = Thread.currentThread().getName();
GenericApplicationContext context = new GenericApplicationContext();
context.registerBeanDefinition("asyncTest", new RootBeanDefinition(DynamicAsyncMethodsInterfaceBean.class));
context.registerBeanDefinition("asyncProcessor", new RootBeanDefinition(AsyncAnnotationBeanPostProcessor.class));
context.refresh();
AsyncMethodsInterface asyncTest = context.getBean("asyncTest", AsyncMethodsInterface.class);
asyncTest.doSomething(10);
Future<String> future = asyncTest.returnSomething(20);
assertEquals("20", future.get());
}
@Test
public void asyncMethodListener() throws Exception {
originalThreadName = Thread.currentThread().getName();
@@ -304,6 +410,28 @@ public class AsyncExecutionTests {
}
public interface RegularInterface {
void doSomething(int i);
Future<String> returnSomething(int i);
}
@Async
public static class AsyncClassBeanWithInterface implements RegularInterface {
public void doSomething(int i) {
assertTrue(!Thread.currentThread().getName().equals(originalThreadName));
}
public Future<String> returnSomething(int i) {
assertTrue(!Thread.currentThread().getName().equals(originalThreadName));
return new AsyncResult<String>(Integer.toString(i));
}
}
@Async
public interface AsyncInterface {
@@ -328,6 +456,44 @@ public class AsyncExecutionTests {
}
public static class DynamicAsyncInterfaceBean implements FactoryBean<AsyncInterface> {
private final AsyncInterface proxy;
public DynamicAsyncInterfaceBean() {
ProxyFactory pf = new ProxyFactory(new HashMap<>());
DefaultIntroductionAdvisor advisor = new DefaultIntroductionAdvisor(new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
assertTrue(!Thread.currentThread().getName().equals(originalThreadName));
if (Future.class.equals(invocation.getMethod().getReturnType())) {
return new AsyncResult<String>(invocation.getArguments()[0].toString());
}
return null;
}
});
advisor.addInterface(AsyncInterface.class);
pf.addAdvisor(advisor);
this.proxy = (AsyncInterface) pf.getProxy();
}
@Override
public AsyncInterface getObject() {
return this.proxy;
}
@Override
public Class<?> getObjectType() {
return this.proxy.getClass();
}
@Override
public boolean isSingleton() {
return true;
}
}
public interface AsyncMethodsInterface {
void doNothing(int i);
@@ -360,6 +526,44 @@ public class AsyncExecutionTests {
}
public static class DynamicAsyncMethodsInterfaceBean implements FactoryBean<AsyncMethodsInterface> {
private final AsyncMethodsInterface proxy;
public DynamicAsyncMethodsInterfaceBean() {
ProxyFactory pf = new ProxyFactory(new HashMap<>());
DefaultIntroductionAdvisor advisor = new DefaultIntroductionAdvisor(new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
assertTrue(!Thread.currentThread().getName().equals(originalThreadName));
if (Future.class.equals(invocation.getMethod().getReturnType())) {
return new AsyncResult<String>(invocation.getArguments()[0].toString());
}
return null;
}
});
advisor.addInterface(AsyncMethodsInterface.class);
pf.addAdvisor(advisor);
this.proxy = (AsyncMethodsInterface) pf.getProxy();
}
@Override
public AsyncMethodsInterface getObject() {
return this.proxy;
}
@Override
public Class<?> getObjectType() {
return this.proxy.getClass();
}
@Override
public boolean isSingleton() {
return true;
}
}
public static class AsyncMethodListener implements ApplicationListener<ApplicationEvent> {
@Override
@@ -1,4 +1,3 @@
/*
* Copyright 2002-2012 the original author or authors.
*
@@ -17,19 +16,10 @@
package org.springframework.tests.sample.beans;
import org.springframework.tests.sample.beans.TestBean;
public class Employee extends TestBean {
private String co;
/**
* Constructor for Employee.
*/
public Employee() {
super();
}
public String getCompany() {
return co;
}
@@ -193,9 +193,11 @@ public abstract class ClassVisitor {
*/
public AnnotationVisitor visitTypeAnnotation(int typeRef,
TypePath typePath, String desc, boolean visible) {
/* SPRING PATCH: REMOVED FOR COMPATIBILITY WITH CGLIB 3.1
if (api < Opcodes.ASM5) {
throw new RuntimeException();
}
*/
if (cv != null) {
return cv.visitTypeAnnotation(typeRef, typePath, desc, visible);
}
@@ -756,7 +756,7 @@ public class ClassWriter extends ClassVisitor {
if (innerClasses == null) {
innerClasses = new ByteVector();
}
// §4.7.6 of the JVMS states "Every CONSTANT_Class_info entry in the
// Sec. 4.7.6 of the JVMS states "Every CONSTANT_Class_info entry in the
// constant_pool table which represents a class or interface C that is
// not a package member must have exactly one corresponding entry in the
// classes array". To avoid duplicates we keep track in the intVal field
@@ -116,9 +116,11 @@ public abstract class FieldVisitor {
*/
public AnnotationVisitor visitTypeAnnotation(int typeRef,
TypePath typePath, String desc, boolean visible) {
/* SPRING PATCH: REMOVED FOR COMPATIBILITY WITH CGLIB 3.1
if (api < Opcodes.ASM5) {
throw new RuntimeException();
}
*/
if (fv != null) {
return fv.visitTypeAnnotation(typeRef, typePath, desc, visible);
}
@@ -1426,16 +1426,20 @@ final class Frame {
| cw.getMergedType(t & BASE_VALUE, u & BASE_VALUE);
} else {
// if u and t are array types, but not with the same element
// type, merge(u,t)=java/lang/Object
v = OBJECT | cw.addType("java/lang/Object");
// type, merge(u,t) = dim(u) - 1 | java/lang/Object
int vdim = ELEMENT_OF + (u & DIM);
v = vdim | OBJECT | cw.addType("java/lang/Object");
}
} else if ((t & BASE_KIND) == OBJECT || (t & DIM) != 0) {
// if t is any other reference or array type, the merged type
// is Object, or min(dim(u), dim(t)) | java/lang/Object is u
// and t have different array dimensions
int tdim = t & DIM;
int udim = u & DIM;
v = (udim != tdim ? Math.min(tdim, udim) : 0) | OBJECT
// is min(udim, tdim) | java/lang/Object, where udim is the
// array dimension of u, minus 1 if u is an array type with a
// primitive element type (and similarly for tdim).
int tdim = (((t & DIM) == 0 || (t & BASE_KIND) == OBJECT) ? 0
: ELEMENT_OF) + (t & DIM);
int udim = (((u & DIM) == 0 || (u & BASE_KIND) == OBJECT) ? 0
: ELEMENT_OF) + (u & DIM);
v = Math.min(tdim, udim) | OBJECT
| cw.addType("java/lang/Object");
} else {
// if t is any other type, merge(u,t)=TOP
@@ -208,9 +208,12 @@ final class Item {
this.strVal2 = strVal2;
this.strVal3 = strVal3;
switch (type) {
case ClassWriter.CLASS:
this.intVal = 0; // intVal of a class must be zero, see visitInnerClass
hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
return;
case ClassWriter.UTF8:
case ClassWriter.STR:
case ClassWriter.CLASS:
case ClassWriter.MTYPE:
case ClassWriter.TYPE_NORMAL:
hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
@@ -473,7 +473,7 @@ public class Label {
void addToSubroutine(final long id, final int nbSubroutines) {
if ((status & VISITED) == 0) {
status |= VISITED;
srcAndRefPositions = new int[(nbSubroutines - 1) / 32 + 1];
srcAndRefPositions = new int[nbSubroutines / 32 + 1];
}
srcAndRefPositions[(int) (id >>> 32)] |= (int) id;
}
@@ -110,9 +110,11 @@ public abstract class MethodVisitor {
* allowed (see {@link Opcodes}).
*/
public void visitParameter(String name, int access) {
/* SPRING PATCH: REMOVED FOR COMPATIBILITY WITH CGLIB 3.1
if (api < Opcodes.ASM5) {
throw new RuntimeException();
}
*/
if (mv != null) {
mv.visitParameter(name, access);
}
@@ -179,9 +181,11 @@ public abstract class MethodVisitor {
*/
public AnnotationVisitor visitTypeAnnotation(int typeRef,
TypePath typePath, String desc, boolean visible) {
/* SPRING PATCH: REMOVED FOR COMPATIBILITY WITH CGLIB 3.1
if (api < Opcodes.ASM5) {
throw new RuntimeException();
}
*/
if (mv != null) {
return mv.visitTypeAnnotation(typeRef, typePath, desc, visible);
}
@@ -693,9 +697,11 @@ public abstract class MethodVisitor {
*/
public AnnotationVisitor visitInsnAnnotation(int typeRef,
TypePath typePath, String desc, boolean visible) {
/* SPRING PATCH: REMOVED FOR COMPATIBILITY WITH CGLIB 3.1
if (api < Opcodes.ASM5) {
throw new RuntimeException();
}
*/
if (mv != null) {
return mv.visitInsnAnnotation(typeRef, typePath, desc, visible);
}
@@ -753,9 +759,11 @@ public abstract class MethodVisitor {
*/
public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
TypePath typePath, String desc, boolean visible) {
/* SPRING PATCH: REMOVED FOR COMPATIBILITY WITH CGLIB 3.1
if (api < Opcodes.ASM5) {
throw new RuntimeException();
}
*/
if (mv != null) {
return mv.visitTryCatchAnnotation(typeRef, typePath, desc, visible);
}
@@ -824,9 +832,11 @@ public abstract class MethodVisitor {
public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
TypePath typePath, Label[] start, Label[] end, int[] index,
String desc, boolean visible) {
/* SPRING PATCH: REMOVED FOR COMPATIBILITY WITH CGLIB 3.1
if (api < Opcodes.ASM5) {
throw new RuntimeException();
}
*/
if (mv != null) {
return mv.visitLocalVariableAnnotation(typeRef, typePath, start,
end, index, desc, visible);
@@ -1966,43 +1966,43 @@ class MethodWriter extends MethodVisitor {
stackMap.putByte(v);
}
} else {
StringBuffer buf = new StringBuffer();
StringBuilder sb = new StringBuilder();
d >>= 28;
while (d-- > 0) {
buf.append('[');
sb.append('[');
}
if ((t & Frame.BASE_KIND) == Frame.OBJECT) {
buf.append('L');
buf.append(cw.typeTable[t & Frame.BASE_VALUE].strVal1);
buf.append(';');
sb.append('L');
sb.append(cw.typeTable[t & Frame.BASE_VALUE].strVal1);
sb.append(';');
} else {
switch (t & 0xF) {
case 1:
buf.append('I');
sb.append('I');
break;
case 2:
buf.append('F');
sb.append('F');
break;
case 3:
buf.append('D');
sb.append('D');
break;
case 9:
buf.append('Z');
sb.append('Z');
break;
case 10:
buf.append('B');
sb.append('B');
break;
case 11:
buf.append('C');
sb.append('C');
break;
case 12:
buf.append('S');
sb.append('S');
break;
default:
buf.append('J');
sb.append('J');
}
}
stackMap.putByte(7).putShort(cw.newClass(buf.toString()));
stackMap.putByte(7).putShort(cw.newClass(sb.toString()));
}
}
}
@@ -401,8 +401,8 @@ public class Type {
* @return the size of the arguments of the method (plus one for the
* implicit this argument), argSize, and the size of its return
* value, retSize, packed into a single int i =
* <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal to
* <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>).
* <tt>(argSize &lt;&lt; 2) | retSize</tt> (argSize is therefore equal to
* <tt>i &gt;&gt; 2</tt>, and retSize to <tt>i &amp; 0x03</tt>).
*/
public static int getArgumentsAndReturnSizes(final String desc) {
int n = 1;
@@ -556,11 +556,11 @@ public class Type {
case DOUBLE:
return "double";
case ARRAY:
StringBuffer b = new StringBuffer(getElementType().getClassName());
StringBuilder sb = new StringBuilder(getElementType().getClassName());
for (int i = getDimensions(); i > 0; --i) {
b.append("[]");
sb.append("[]");
}
return b.toString();
return sb.toString();
case OBJECT:
return new String(buf, off, len).replace('/', '.');
default:
@@ -606,9 +606,10 @@ public class Type {
*
* @return the size of the arguments (plus one for the implicit this
* argument), argSize, and the size of the return value, retSize,
* packed into a single int i = <tt>(argSize << 2) | retSize</tt>
* (argSize is therefore equal to <tt>i >> 2</tt>, and retSize to
* <tt>i & 0x03</tt>).
* packed into a single
* int i = <tt>(argSize &lt;&lt; 2) | retSize</tt>
* (argSize is therefore equal to <tt>i &gt;&gt; 2</tt>,
* and retSize to <tt>i &amp; 0x03</tt>).
*/
public int getArgumentsAndReturnSizes() {
return getArgumentsAndReturnSizes(getDescriptor());
@@ -624,9 +625,9 @@ public class Type {
* @return the descriptor corresponding to this Java type.
*/
public String getDescriptor() {
StringBuffer buf = new StringBuffer();
getDescriptor(buf);
return buf.toString();
StringBuilder sb = new StringBuilder();
getDescriptor(sb);
return sb.toString();
}
/**
@@ -642,34 +643,34 @@ public class Type {
*/
public static String getMethodDescriptor(final Type returnType,
final Type... argumentTypes) {
StringBuffer buf = new StringBuffer();
buf.append('(');
StringBuilder sb = new StringBuilder();
sb.append('(');
for (int i = 0; i < argumentTypes.length; ++i) {
argumentTypes[i].getDescriptor(buf);
argumentTypes[i].getDescriptor(sb);
}
buf.append(')');
returnType.getDescriptor(buf);
return buf.toString();
sb.append(')');
returnType.getDescriptor(sb);
return sb.toString();
}
/**
* Appends the descriptor corresponding to this Java type to the given
* string buffer.
* string builder.
*
* @param buf
* the string buffer to which the descriptor must be appended.
* @param sb
* the string builder to which the descriptor must be appended.
*/
private void getDescriptor(final StringBuffer buf) {
private void getDescriptor(final StringBuilder sb) {
if (this.buf == null) {
// descriptor is in byte 3 of 'off' for primitive types (buf ==
// null)
buf.append((char) ((off & 0xFF000000) >>> 24));
sb.append((char) ((off & 0xFF000000) >>> 24));
} else if (sort == OBJECT) {
buf.append('L');
buf.append(this.buf, off, len);
buf.append(';');
sb.append('L');
sb.append(this.buf, off, len);
sb.append(';');
} else { // sort == ARRAY || sort == METHOD
buf.append(this.buf, off, len);
sb.append(this.buf, off, len);
}
}
@@ -699,9 +700,9 @@ public class Type {
* @return the descriptor corresponding to the given class.
*/
public static String getDescriptor(final Class<?> c) {
StringBuffer buf = new StringBuffer();
getDescriptor(buf, c);
return buf.toString();
StringBuilder sb = new StringBuilder();
getDescriptor(sb, c);
return sb.toString();
}
/**
@@ -713,12 +714,12 @@ public class Type {
*/
public static String getConstructorDescriptor(final Constructor<?> c) {
Class<?>[] parameters = c.getParameterTypes();
StringBuffer buf = new StringBuffer();
buf.append('(');
StringBuilder sb = new StringBuilder();
sb.append('(');
for (int i = 0; i < parameters.length; ++i) {
getDescriptor(buf, parameters[i]);
getDescriptor(sb, parameters[i]);
}
return buf.append(")V").toString();
return sb.append(")V").toString();
}
/**
@@ -730,25 +731,25 @@ public class Type {
*/
public static String getMethodDescriptor(final Method m) {
Class<?>[] parameters = m.getParameterTypes();
StringBuffer buf = new StringBuffer();
buf.append('(');
StringBuilder sb = new StringBuilder();
sb.append('(');
for (int i = 0; i < parameters.length; ++i) {
getDescriptor(buf, parameters[i]);
getDescriptor(sb, parameters[i]);
}
buf.append(')');
getDescriptor(buf, m.getReturnType());
return buf.toString();
sb.append(')');
getDescriptor(sb, m.getReturnType());
return sb.toString();
}
/**
* Appends the descriptor of the given class to the given string buffer.
* Appends the descriptor of the given class to the given string builder.
*
* @param buf
* @param sb
* the string buffer to which the descriptor must be appended.
* @param c
* the class whose descriptor must be computed.
*/
private static void getDescriptor(final StringBuffer buf, final Class<?> c) {
private static void getDescriptor(final StringBuilder sb, final Class<?> c) {
Class<?> d = c;
while (true) {
if (d.isPrimitive()) {
@@ -772,20 +773,20 @@ public class Type {
} else /* if (d == Long.TYPE) */{
car = 'J';
}
buf.append(car);
sb.append(car);
return;
} else if (d.isArray()) {
buf.append('[');
sb.append('[');
d = d.getComponentType();
} else {
buf.append('L');
sb.append('L');
String name = d.getName();
int len = name.length();
for (int i = 0; i < len; ++i) {
char car = name.charAt(i);
buf.append(car == '.' ? '/' : car);
sb.append(car == '.' ? '/' : car);
}
buf.append(';');
sb.append(';');
return;
}
}
@@ -0,0 +1,60 @@
/*
* 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.cglib.transform.impl;
import org.springframework.cglib.core.ClassGenerator;
import org.springframework.cglib.core.DefaultGeneratorStrategy;
import org.springframework.cglib.core.TypeUtils;
import org.springframework.cglib.transform.ClassTransformer;
import org.springframework.cglib.transform.MethodFilter;
import org.springframework.cglib.transform.MethodFilterTransformer;
import org.springframework.cglib.transform.TransformingClassGenerator;
/**
* Memory-safe variant of {@link UndeclaredThrowableStrategy} ported from CGLIB 3.1,
* introduced for using it in Spring before it was officially released in CGLIB.
*
* @author Phillip Webb
* @since 3.2.4
* @deprecated as of Spring 4.0.2, in favor of CGLIB 3.1's default strategy.
* Kept around for external code depending on it; to be removed in Spring 4.1.
*/
@Deprecated
public class MemorySafeUndeclaredThrowableStrategy extends DefaultGeneratorStrategy {
private static final MethodFilter TRANSFORM_FILTER = new MethodFilter() {
public boolean accept(int access, String name, String desc, String signature, String[] exceptions) {
return (!TypeUtils.isPrivate(access) && name.indexOf('$') < 0);
}
};
private final Class<?> wrapper;
public MemorySafeUndeclaredThrowableStrategy(Class<?> wrapper) {
this.wrapper = wrapper;
}
protected ClassGenerator transform(ClassGenerator cg) throws Exception {
ClassTransformer ct = new UndeclaredThrowableTransformer(this.wrapper);
ct = new MethodFilterTransformer(TRANSFORM_FILTER, ct);
return new TransformingClassGenerator(cg, ct);
}
}
@@ -243,10 +243,10 @@ public abstract class GenericTypeResolver {
*/
public static Class<?>[] resolveTypeArguments(Class<?> clazz, Class<?> genericIfc) {
ResolvableType type = ResolvableType.forClass(clazz).as(genericIfc);
if (!type.hasGenerics() || type.hasUnresolvableGenerics()) {
if (!type.hasGenerics() || type.isEntirelyUnresolvable()) {
return null;
}
return type.resolveGenerics();
return type.resolveGenerics(Object.class);
}
/**
@@ -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.
@@ -103,8 +103,8 @@ public class LocalVariableTableParameterNameDiscoverer implements ParameterNameD
// We couldn't load the class file, which is not fatal as it
// simply means this method of discovering parameter names won't work.
if (logger.isDebugEnabled()) {
logger.debug("Cannot find '.class' file for class [" + clazz
+ "] - unable to determine constructors/methods parameter names");
logger.debug("Cannot find '.class' file for class [" + clazz +
"] - unable to determine constructor/method parameter names");
}
return NO_DEBUG_INFO_MAP;
}
@@ -117,14 +117,14 @@ public class LocalVariableTableParameterNameDiscoverer implements ParameterNameD
catch (IOException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Exception thrown while reading '.class' file for class [" + clazz +
"] - unable to determine constructors/methods parameter names", ex);
"] - unable to determine constructor/method parameter names", ex);
}
}
catch (IllegalArgumentException ex) {
if (logger.isDebugEnabled()) {
logger.debug("ASM ClassReader failed to parse class file [" + clazz +
"], probably due to a new Java class file version that isn't supported yet " +
"- unable to determine constructors/methods parameter names", ex);
"- unable to determine constructor/method parameter names", ex);
}
}
finally {
@@ -148,6 +148,7 @@ public class LocalVariableTableParameterNameDiscoverer implements ParameterNameD
private static final String STATIC_CLASS_INIT = "<clinit>";
private final Class<?> clazz;
private final Map<Member, String[]> memberMap;
public ParameterNameDiscoveringVisitor(Class<?> clazz, Map<Member, String[]> memberMap) {
@@ -180,12 +181,17 @@ public class LocalVariableTableParameterNameDiscoverer implements ParameterNameD
private static final String CONSTRUCTOR = "<init>";
private final Class<?> clazz;
private final Map<Member, String[]> memberMap;
private final String name;
private final Type[] args;
private final String[] parameterNames;
private final boolean isStatic;
private String[] parameterNames;
private boolean hasLvtInfo = false;
/*
@@ -194,25 +200,22 @@ public class LocalVariableTableParameterNameDiscoverer implements ParameterNameD
*/
private final int[] lvtSlotIndex;
public LocalVariableTableVisitor(Class<?> clazz, Map<Member, String[]> map, String name, String desc,
boolean isStatic) {
public LocalVariableTableVisitor(Class<?> clazz, Map<Member, String[]> map, String name, String desc, boolean isStatic) {
super(SpringAsmInfo.ASM_VERSION);
this.clazz = clazz;
this.memberMap = map;
this.name = name;
// determine args
args = Type.getArgumentTypes(desc);
this.parameterNames = new String[args.length];
this.args = Type.getArgumentTypes(desc);
this.parameterNames = new String[this.args.length];
this.isStatic = isStatic;
this.lvtSlotIndex = computeLvtSlotIndices(isStatic, args);
this.lvtSlotIndex = computeLvtSlotIndices(isStatic, this.args);
}
@Override
public void visitLocalVariable(String name, String description, String signature, Label start, Label end,
int index) {
public void visitLocalVariable(String name, String description, String signature, Label start, Label end, int index) {
this.hasLvtInfo = true;
for (int i = 0; i < lvtSlotIndex.length; i++) {
if (lvtSlotIndex[i] == index) {
for (int i = 0; i < this.lvtSlotIndex.length; i++) {
if (this.lvtSlotIndex[i] == index) {
this.parameterNames[i] = name;
}
}
@@ -225,27 +228,25 @@ public class LocalVariableTableParameterNameDiscoverer implements ParameterNameD
// which doesn't use any local variables.
// This means that hasLvtInfo could be false for that kind of methods
// even if the class has local variable info.
memberMap.put(resolveMember(), parameterNames);
this.memberMap.put(resolveMember(), this.parameterNames);
}
}
private Member resolveMember() {
ClassLoader loader = clazz.getClassLoader();
Class<?>[] classes = new Class<?>[args.length];
// resolve args
for (int i = 0; i < args.length; i++) {
classes[i] = ClassUtils.resolveClassName(args[i].getClassName(), loader);
ClassLoader loader = this.clazz.getClassLoader();
Class<?>[] argTypes = new Class<?>[this.args.length];
for (int i = 0; i < this.args.length; i++) {
argTypes[i] = ClassUtils.resolveClassName(this.args[i].getClassName(), loader);
}
try {
if (CONSTRUCTOR.equals(name)) {
return clazz.getDeclaredConstructor(classes);
if (CONSTRUCTOR.equals(this.name)) {
return this.clazz.getDeclaredConstructor(argTypes);
}
return clazz.getDeclaredMethod(name, classes);
} catch (NoSuchMethodException ex) {
throw new IllegalStateException("Method [" + name
+ "] was discovered in the .class file but cannot be resolved in the class object", ex);
return this.clazz.getDeclaredMethod(this.name, argTypes);
}
catch (NoSuchMethodException ex) {
throw new IllegalStateException("Method [" + this.name +
"] was discovered in the .class file but cannot be resolved in the class object", ex);
}
}
@@ -256,7 +257,8 @@ public class LocalVariableTableParameterNameDiscoverer implements ParameterNameD
lvtIndex[i] = nextIndex;
if (isWideType(paramTypes[i])) {
nextIndex += 2;
} else {
}
else {
nextIndex++;
}
}
@@ -416,7 +416,24 @@ public final class ResolvableType implements Serializable {
}
/**
* Determine whether the underlying type has unresolvable generics:
* Return {@code true} if this type contains unresolvable generics only,
* that is, no substitute for any of its declared type variables.
*/
boolean isEntirelyUnresolvable() {
if (this == NONE) {
return false;
}
ResolvableType[] generics = getGenerics();
for (ResolvableType generic : generics) {
if (!generic.isUnresolvableTypeVariable() && !generic.isWildcardWithoutBounds()) {
return false;
}
}
return true;
}
/**
* Determine whether the underlying type has any unresolvable generics:
* either through an unresolvable type variable on the type itself
* or through implementing a generic interface in a raw fashion,
* i.e. without substituting that interface's type variables.
@@ -634,8 +651,8 @@ public final class ResolvableType implements Serializable {
/**
* Convenience method that will {@link #getGeneric(int...) get} and
* {@link #resolve() resolve} a specific generic parameters.
* @param indexes the indexes that refer to the generic parameter (may be omitted to
* return the first generic)
* @param indexes the indexes that refer to the generic parameter
* (may be omitted to return the first generic)
* @return a resolved {@link Class} or {@code null}
* @see #getGeneric(int...)
* @see #resolve()
@@ -645,11 +662,11 @@ public final class ResolvableType implements Serializable {
}
/**
* Resolve this type to a {@link java.lang.Class}, returning {@code null} if the type
* cannot be resolved. This method will consider bounds of {@link TypeVariable}s and
* {@link WildcardType}s if direct resolution fails; however, bounds of
* {@code Object.class} will be ignored.
* @return the resolved {@link Class} or {@code null}
* Resolve this type to a {@link java.lang.Class}, returning {@code null}
* if the type cannot be resolved. This method will consider bounds of
* {@link TypeVariable}s and {@link WildcardType}s if direct resolution fails;
* however, bounds of {@code Object.class} will be ignored.
* @return the resolved {@link Class}, or {@code null} if not resolvable
* @see #resolve(Class)
* @see #resolveGeneric(int...)
* @see #resolveGenerics()
@@ -55,7 +55,8 @@ public abstract class SpringProperties {
static {
try {
ClassLoader cl = SpringProperties.class.getClassLoader();
URL url = cl.getResource(PROPERTIES_RESOURCE_LOCATION);
URL url = (cl != null ? cl.getResource(PROPERTIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResource(PROPERTIES_RESOURCE_LOCATION));
if (url != null) {
logger.info("Found 'spring.properties' file in local classpath");
InputStream is = url.openStream();
@@ -58,7 +58,6 @@ public class AnnotatedElementUtils {
public static boolean hasMetaAnnotationTypes(AnnotatedElement element, String annotationType) {
return Boolean.TRUE.equals(process(element, annotationType, false, new Processor<Boolean>() {
@Override
public Boolean process(Annotation annotation, int metaDepth) {
if (metaDepth > 0) {
@@ -66,7 +65,6 @@ public class AnnotatedElementUtils {
}
return null;
}
@Override
public void postProcess(Annotation annotation, Boolean result) {
}
@@ -75,12 +73,10 @@ public class AnnotatedElementUtils {
public static boolean isAnnotated(AnnotatedElement element, String annotationType) {
return Boolean.TRUE.equals(process(element, annotationType, false, new Processor<Boolean>() {
@Override
public Boolean process(Annotation annotation, int metaDepth) {
return Boolean.TRUE;
}
@Override
public void postProcess(Annotation annotation, Boolean result) {
}
@@ -95,12 +91,10 @@ public class AnnotatedElementUtils {
final boolean classValuesAsString, final boolean nestedAnnotationsAsMap) {
return process(element, annotationType, false, new Processor<AnnotationAttributes>() {
@Override
public AnnotationAttributes process(Annotation annotation, int metaDepth) {
return AnnotationUtils.getAnnotationAttributes(annotation, classValuesAsString, nestedAnnotationsAsMap);
}
@Override
public void postProcess(Annotation annotation, AnnotationAttributes result) {
for (String key : result.keySet()) {
@@ -125,7 +119,6 @@ public class AnnotatedElementUtils {
final MultiValueMap<String, Object> attributes = new LinkedMultiValueMap<String, Object>();
process(element, annotationType, false, new Processor<Void>() {
@Override
public Void process(Annotation annotation, int metaDepth) {
if (annotation.annotationType().getName().equals(annotationType)) {
@@ -136,7 +129,6 @@ public class AnnotatedElementUtils {
}
return null;
}
@Override
public void postProcess(Annotation annotation, Void result) {
for (String key : attributes.keySet()) {
@@ -199,8 +191,8 @@ public class AnnotatedElementUtils {
Processor<T> processor, Set<AnnotatedElement> visited, int metaDepth) {
if (visited.add(element)) {
Annotation[] annotations = (traverseClassHierarchy ? element.getDeclaredAnnotations()
: element.getAnnotations());
Annotation[] annotations =
(traverseClassHierarchy ? element.getDeclaredAnnotations() : element.getAnnotations());
for (Annotation annotation : annotations) {
if (annotation.annotationType().getName().equals(annotationType) || metaDepth > 0) {
T result = processor.process(annotation, metaDepth);
@@ -228,7 +220,7 @@ public class AnnotatedElementUtils {
if (traverseClassHierarchy && element instanceof Class) {
Class<?> superclass = ((Class<?>) element).getSuperclass();
if (superclass != null && !superclass.equals(Object.class)) {
T result = doProcess(superclass, annotationType, traverseClassHierarchy, processor, visited,
T result = doProcess(superclass, annotationType, true, processor, visited,
metaDepth);
if (result != null) {
return result;
@@ -70,8 +70,8 @@ public abstract class AnnotationUtils {
* Get a single {@link Annotation} of {@code annotationType} from the supplied
* annotation: either the given annotation itself or a meta-annotation thereof.
* @param ann the Annotation to check
* @param annotationType the annotation class to look for, both locally and as a meta-annotation
* @return the matching annotation or {@code null} if not found
* @param annotationType the annotation type to look for, both locally and as a meta-annotation
* @return the matching annotation, or {@code null} if none found
* @since 4.0
*/
@SuppressWarnings("unchecked")
@@ -87,8 +87,8 @@ public abstract class AnnotationUtils {
* Method, Constructor or Field. Meta-annotations will be searched if the annotation
* is not declared locally on the supplied element.
* @param ae the Method, Constructor or Field from which to get the annotation
* @param annotationType the annotation class to look for, both locally and as a meta-annotation
* @return the matching annotation or {@code null} if not found
* @param annotationType the annotation type to look for, both locally and as a meta-annotation
* @return the matching annotation, or {@code null} if none found
* @since 3.1
*/
public static <T extends Annotation> T getAnnotation(AnnotatedElement ae, Class<T> annotationType) {
@@ -119,7 +119,7 @@ public abstract class AnnotationUtils {
* Get a single {@link Annotation} of {@code annotationType} from the supplied {@link Method}.
* <p>Correctly handles bridge {@link Method Methods} generated by the compiler.
* @param method the method to look for annotations on
* @param annotationType the annotation class to look for
* @param annotationType the annotation type to look for
* @return the annotations found
* @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method)
*/
@@ -135,16 +135,16 @@ public abstract class AnnotationUtils {
* <p>Correctly handles bridge {@link Method Methods} generated by the compiler.
* @param method the method to look for annotations on
* @param containerAnnotationType the class of the container that holds the annotations
* @param annotationType the annotation class to look for
* @param annotationType the annotation type to look for
* @return the annotations found
* @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method)
* @since 4.0
* @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method)
*/
public static <A extends Annotation> Set<A> getRepeatableAnnotation(Method method,
Class<? extends Annotation> containerAnnotationType, Class<A> annotationType) {
Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method);
return getRepeatableAnnotation((AnnotatedElement) resolvedMethod,
containerAnnotationType, annotationType);
return getRepeatableAnnotation((AnnotatedElement) resolvedMethod, containerAnnotationType, annotationType);
}
/**
@@ -154,13 +154,14 @@ public abstract class AnnotationUtils {
* <p>Correctly handles bridge {@link Method Methods} generated by the compiler.
* @param annotatedElement the element to look for annotations on
* @param containerAnnotationType the class of the container that holds the annotations
* @param annotationType the annotation class to look for
* @param annotationType the annotation type to look for
* @return the annotations found
* @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method)
* @since 4.0
* @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method)
*/
public static <A extends Annotation> Set<A> getRepeatableAnnotation(AnnotatedElement annotatedElement,
Class<? extends Annotation> containerAnnotationType, Class<A> annotationType) {
if (annotatedElement.getAnnotations().length == 0) {
return Collections.emptySet();
}
@@ -169,13 +170,13 @@ public abstract class AnnotationUtils {
/**
* Find a single {@link Annotation} of {@code annotationType} from the supplied
* {@link Method}, traversing its super methods (i.e., from super classes and
* {@link Method}, traversing its super methods (i.e., from superclasses and
* interfaces) if no annotation can be found on the given method itself.
* <p>Annotations on methods are not inherited by default, so we need to handle
* this explicitly.
* @param method the method to look for annotations on
* @param annotationType the annotation class to look for
* @return the annotation found, or {@code null} if none found
* @param annotationType the annotation type to look for
* @return the annotation found, or {@code null} if none
*/
public static <A extends Annotation> A findAnnotation(Method method, Class<A> annotationType) {
A annotation = getAnnotation(method, annotationType);
@@ -274,10 +275,8 @@ public abstract class AnnotationUtils {
* @param visited the set of annotations that have already been visited
* @return the annotation if found, or {@code null} if not found
*/
private static <A extends Annotation> A findAnnotation(Class<?> clazz, Class<A> annotationType,
Set<Annotation> visited) {
private static <A extends Annotation> A findAnnotation(Class<?> clazz, Class<A> annotationType, Set<Annotation> visited) {
Assert.notNull(clazz, "Class must not be null");
if (isAnnotationDeclaredLocally(annotationType, clazz)) {
return clazz.getAnnotation(annotationType);
}
@@ -289,8 +288,7 @@ public abstract class AnnotationUtils {
}
for (Annotation ann : clazz.getDeclaredAnnotations()) {
if (!isInJavaLangAnnotationPackage(ann) && visited.add(ann)) {
A annotation = findAnnotation(ann.annotationType(), annotationType,
visited);
A annotation = findAnnotation(ann.annotationType(), annotationType, visited);
if (annotation != null) {
return annotation;
}
@@ -313,8 +311,8 @@ public abstract class AnnotationUtils {
* <p>The standard {@link Class} API does not provide a mechanism for determining which class
* in an inheritance hierarchy actually declares an {@link Annotation}, so we need to handle
* this explicitly.
* @param annotationType the annotation class to look for, both locally and as a meta-annotation
* @param clazz the class on which to check for the annotation, or {@code null}
* @param annotationType the annotation type to look for, both locally and as a meta-annotation
* @param clazz the class on which to check for the annotation (may be {@code null})
* @return the first {@link Class} in the inheritance hierarchy of the specified {@code clazz}
* which declares an annotation for the specified {@code annotationType}, or {@code null}
* if not found
@@ -423,10 +421,9 @@ public abstract class AnnotationUtils {
}
/**
* Determine if the supplied {@link Annotation} is defined in the
* Determine if the supplied {@link Annotation} is defined in the core JDK
* {@code java.lang.annotation} package.
*
* @param annotation the annotation to check; never {@code null}
* @param annotation the annotation to check (never {@code null})
* @return {@code true} if the annotation is in the {@code java.lang.annotation} package
*/
public static boolean isInJavaLangAnnotationPackage(Annotation annotation) {
@@ -435,11 +432,10 @@ public abstract class AnnotationUtils {
}
/**
* Retrieve the given annotation's attributes as a Map, preserving all attribute types
* as-is.
* <p>Note: As of Spring 3.1.1, the returned map is actually an
* {@link AnnotationAttributes} instance, however the Map signature of this method has
* been preserved for binary compatibility.
* Retrieve the given annotation's attributes as a {@link Map}, preserving all
* attribute types as-is.
* <p>Note: This method actually returns an {@link AnnotationAttributes} instance.
* However, the {@code Map} signature has been preserved for binary compatibility.
* @param annotation the annotation to retrieve the attributes for
* @return the Map of annotation attributes, with attribute names as keys and
* corresponding attribute values as values
@@ -449,16 +445,15 @@ public abstract class AnnotationUtils {
}
/**
* Retrieve the given annotation's attributes as a Map. Equivalent to calling
* {@link #getAnnotationAttributes(Annotation, boolean, boolean)} with
* Retrieve the given annotation's attributes as a {@link Map}. Equivalent to
* calling {@link #getAnnotationAttributes(Annotation, boolean, boolean)} with
* the {@code nestedAnnotationsAsMap} parameter set to {@code false}.
* <p>Note: As of Spring 3.1.1, the returned map is actually an
* {@link AnnotationAttributes} instance, however the Map signature of this method has
* been preserved for binary compatibility.
* <p>Note: This method actually returns an {@link AnnotationAttributes} instance.
* However, the {@code Map} signature has been preserved for binary compatibility.
* @param annotation the annotation to retrieve the attributes for
* @param classValuesAsString whether to turn Class references into Strings (for
* compatibility with {@link org.springframework.core.type.AnnotationMetadata} or to
* preserve them as Class references
* compatibility with {@link org.springframework.core.type.AnnotationMetadata}
* or to preserve them as Class references
* @return the Map of annotation attributes, with attribute names as keys and
* corresponding attribute values as values
*/
@@ -468,13 +463,13 @@ public abstract class AnnotationUtils {
/**
* Retrieve the given annotation's attributes as an {@link AnnotationAttributes}
* map structure. Implemented in Spring 3.1.1 to provide fully recursive annotation
* reading capabilities on par with that of the reflection-based
* {@link org.springframework.core.type.StandardAnnotationMetadata}.
* map structure.
* <p>This method provides fully recursive annotation reading capabilities on par with
* the reflection-based {@link org.springframework.core.type.StandardAnnotationMetadata}.
* @param annotation the annotation to retrieve the attributes for
* @param classValuesAsString whether to turn Class references into Strings (for
* compatibility with {@link org.springframework.core.type.AnnotationMetadata} or to
* preserve them as Class references
* compatibility with {@link org.springframework.core.type.AnnotationMetadata}
* or to preserve them as Class references
* @param nestedAnnotationsAsMap whether to turn nested Annotation instances into
* {@link AnnotationAttributes} maps (for compatibility with
* {@link org.springframework.core.type.AnnotationMetadata} or to preserve them as
@@ -507,14 +502,13 @@ public abstract class AnnotationUtils {
}
if (nestedAnnotationsAsMap && value instanceof Annotation) {
attrs.put(method.getName(),
getAnnotationAttributes((Annotation) value, classValuesAsString, nestedAnnotationsAsMap));
getAnnotationAttributes((Annotation) value, classValuesAsString, true));
}
else if (nestedAnnotationsAsMap && value instanceof Annotation[]) {
Annotation[] realAnnotations = (Annotation[]) value;
AnnotationAttributes[] mappedAnnotations = new AnnotationAttributes[realAnnotations.length];
for (int i = 0; i < realAnnotations.length; i++) {
mappedAnnotations[i] = getAnnotationAttributes(
realAnnotations[i], classValuesAsString, nestedAnnotationsAsMap);
mappedAnnotations[i] = getAnnotationAttributes(realAnnotations[i], classValuesAsString, true);
}
attrs.put(method.getName(), mappedAnnotations);
}
@@ -542,7 +536,7 @@ public abstract class AnnotationUtils {
}
/**
* Retrieve the <em>value</em> of a named Annotation attribute, given an annotation instance.
* Retrieve the <em>value</em> of a named attribute, given an annotation instance.
* @param annotation the annotation instance from which to retrieve the value
* @param attributeName the name of the attribute value to retrieve
* @return the attribute value, or {@code null} if not found
@@ -550,7 +544,7 @@ public abstract class AnnotationUtils {
*/
public static Object getValue(Annotation annotation, String attributeName) {
try {
Method method = annotation.annotationType().getDeclaredMethod(attributeName, new Class<?>[0]);
Method method = annotation.annotationType().getDeclaredMethod(attributeName);
ReflectionUtils.makeAccessible(method);
return method.invoke(annotation);
}
@@ -571,7 +565,7 @@ public abstract class AnnotationUtils {
}
/**
* Retrieve the <em>default value</em> of a named Annotation attribute, given an annotation instance.
* Retrieve the <em>default value</em> of a named attribute, given an annotation instance.
* @param annotation the annotation instance from which to retrieve the default value
* @param attributeName the name of the attribute value to retrieve
* @return the default value of the named attribute, or {@code null} if not found
@@ -593,7 +587,8 @@ public abstract class AnnotationUtils {
}
/**
* Retrieve the <em>default value</em> of a named Annotation attribute, given the {@link Class annotation type}.
* Retrieve the <em>default value</em> of a named attribute, given the
* {@link Class annotation type}.
* @param annotationType the <em>annotation type</em> for which the default value should be retrieved
* @param attributeName the name of the attribute value to retrieve.
* @return the default value of the named attribute, or {@code null} if not found
@@ -601,8 +596,7 @@ public abstract class AnnotationUtils {
*/
public static Object getDefaultValue(Class<? extends Annotation> annotationType, String attributeName) {
try {
Method method = annotationType.getDeclaredMethod(attributeName, new Class<?>[0]);
return method.getDefaultValue();
return annotationType.getDeclaredMethod(attributeName).getDefaultValue();
}
catch (Exception ex) {
return null;
@@ -620,14 +614,11 @@ public abstract class AnnotationUtils {
private final Set<A> result = new LinkedHashSet<A>();
public AnnotationCollector(Class<? extends Annotation> containerAnnotationType,
Class<A> annotationType) {
public AnnotationCollector(Class<? extends Annotation> containerAnnotationType, Class<A> annotationType) {
this.containerAnnotationType = containerAnnotationType;
this.annotationType = annotationType;
}
public Set<A> getResult(AnnotatedElement element) {
process(element);
return Collections.unmodifiableSet(this.result);
@@ -641,7 +632,7 @@ public abstract class AnnotationUtils {
this.result.add((A) annotation);
}
else if (ObjectUtils.nullSafeEquals(this.containerAnnotationType, annotation.annotationType())) {
result.addAll(Arrays.asList(getValue(annotation)));
this.result.addAll(Arrays.asList(getValue(annotation)));
}
else if (!isInJavaLangAnnotationPackage(annotation)) {
process(annotation.annotationType());
@@ -658,10 +649,10 @@ public abstract class AnnotationUtils {
return (A[]) method.invoke(annotation);
}
catch (Exception ex) {
throw new IllegalStateException("Unable to read value from repeating annotation container "
+ this.containerAnnotationType.getName(), ex);
throw new IllegalStateException("Unable to read value from repeating annotation container " +
this.containerAnnotationType.getName(), ex);
}
}
}
}
@@ -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.
@@ -31,20 +31,23 @@ import org.springframework.util.ReflectionUtils;
* Converts an entity identifier to a entity reference by calling a static finder method
* on the target entity type.
*
* <p>For this converter to match, the finder method must be public, static, have the signature
* <p>For this converter to match, the finder method must be static, have the signature
* {@code find[EntityName]([IdType])}, and return an instance of the desired entity type.
*
* @author Keith Donald
* @author Juergen Hoeller
* @since 3.0
*/
final class IdToEntityConverter implements ConditionalGenericConverter {
private final ConversionService conversionService;
public IdToEntityConverter(ConversionService conversionService) {
this.conversionService = conversionService;
}
@Override
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(Object.class, Object.class));
@@ -53,7 +56,8 @@ final class IdToEntityConverter implements ConditionalGenericConverter {
@Override
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
Method finder = getFinder(targetType.getType());
return finder != null && this.conversionService.canConvert(sourceType, TypeDescriptor.valueOf(finder.getParameterTypes()[0]));
return (finder != null &&
this.conversionService.canConvert(sourceType, TypeDescriptor.valueOf(finder.getParameterTypes()[0])));
}
@Override
@@ -62,18 +66,31 @@ final class IdToEntityConverter implements ConditionalGenericConverter {
return null;
}
Method finder = getFinder(targetType.getType());
Object id = this.conversionService.convert(source, sourceType, TypeDescriptor.valueOf(finder.getParameterTypes()[0]));
Object id = this.conversionService.convert(
source, sourceType, TypeDescriptor.valueOf(finder.getParameterTypes()[0]));
return ReflectionUtils.invokeMethod(finder, source, id);
}
private Method getFinder(Class<?> entityClass) {
String finderMethod = "find" + getEntityName(entityClass);
Method[] methods = entityClass.getDeclaredMethods();
Method[] methods;
boolean localOnlyFiltered;
try {
methods = entityClass.getDeclaredMethods();
localOnlyFiltered = true;
}
catch (SecurityException ex) {
// Not allowed to access non-public methods...
// Fallback: check locally declared public methods only.
methods = entityClass.getMethods();
localOnlyFiltered = false;
}
for (Method method : methods) {
if (Modifier.isStatic(method.getModifiers()) && method.getParameterTypes().length == 1 && method.getReturnType().equals(entityClass)) {
if (method.getName().equals(finderMethod)) {
return method;
}
if (Modifier.isStatic(method.getModifiers()) && method.getName().equals(finderMethod) &&
method.getParameterTypes().length == 1 && method.getReturnType().equals(entityClass) &&
(localOnlyFiltered || method.getDeclaringClass().equals(entityClass))) {
return method;
}
}
return null;
@@ -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,6 +20,7 @@ import org.springframework.core.convert.converter.Converter;
/**
* Simply calls {@link Object#toString()} to convert a source Object to a String.
*
* @author Keith Donald
* @since 3.0
*/
@@ -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.
@@ -29,12 +29,11 @@ import java.util.Set;
*/
public class CompositePropertySource extends PropertySource<Object> {
private Set<PropertySource<?>> propertySources = new LinkedHashSet<PropertySource<?>>();
private final Set<PropertySource<?>> propertySources = new LinkedHashSet<PropertySource<?>>();
/**
* Create a new {@code CompositePropertySource}.
*
* @param name the name of the property source
*/
public CompositePropertySource(String name) {
@@ -60,6 +59,7 @@ public class CompositePropertySource extends PropertySource<Object> {
@Override
public String toString() {
return String.format("%s [name='%s', propertySources=%s]",
this.getClass().getSimpleName(), this.name, this.propertySources);
getClass().getSimpleName(), this.name, this.propertySources);
}
}
@@ -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,6 +18,7 @@ package org.springframework.core.env;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
/**
@@ -53,22 +54,23 @@ public abstract class EnumerablePropertySource<T> extends PropertySource<T> {
super(name, source);
}
/**
* Return the names of all properties contained by the {@linkplain #getSource()
* source} object (never {@code null}).
* Return the names of all properties contained by the
* {@linkplain #getSource() source} object (never {@code null}).
*/
public abstract String[] getPropertyNames();
/**
* Return whether this {@code PropertySource} contains a property with the given name.
* <p>This implementation checks for the presence of the given name within
* the {@link #getPropertyNames()} array.
* @param name the property to find
* <p>This implementation checks for the presence of the given name within the
* {@link #getPropertyNames()} array.
* @param name the name of the property to find
*/
@Override
public boolean containsProperty(String name) {
Assert.notNull(name, "property name must not be null");
for (String candidate : this.getPropertyNames()) {
Assert.notNull(name, "Property name must not be null");
for (String candidate : getPropertyNames()) {
if (candidate.equals(name)) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("PropertySource [%s] contains '%s'", getName(), name));
@@ -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.
@@ -30,13 +30,18 @@ import java.util.Properties;
* {@link Properties#getProperty} and {@link Properties#setProperty}.
*
* @author Chris Beams
* @author Juergen Hoeller
* @since 3.1
*/
public class PropertiesPropertySource extends MapPropertySource {
@SuppressWarnings({ "unchecked", "rawtypes" })
@SuppressWarnings({"unchecked", "rawtypes"})
public PropertiesPropertySource(String name, Properties source) {
super(name, (Map) source);
}
protected PropertiesPropertySource(String name, Map<String, Object> source) {
super(name, source);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 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,9 @@ package org.springframework.core.env;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
* Abstract base class representing a source of name/value property pairs. The underlying
@@ -55,12 +57,13 @@ import org.springframework.util.Assert;
*/
public abstract class PropertySource<T> {
protected final Log logger = LogFactory.getLog(this.getClass());
protected final Log logger = LogFactory.getLog(getClass());
protected final String name;
protected final T source;
/**
* Create a new {@code PropertySource} with the given name and source object.
*/
@@ -74,15 +77,15 @@ public abstract class PropertySource<T> {
/**
* Create a new {@code PropertySource} with the given name and with a new {@code Object}
* instance as the underlying source.
* <p>Often useful in testing scenarios when creating
* anonymous implementations that never query an actual source, but rather return
* hard-coded values.
* <p>Often useful in testing scenarios when creating anonymous implementations that
* never query an actual source but rather return hard-coded values.
*/
@SuppressWarnings("unchecked")
public PropertySource(String name) {
this(name, (T) new Object());
}
/**
* Return the name of this {@code PropertySource}
*/
@@ -94,91 +97,75 @@ public abstract class PropertySource<T> {
* Return the underlying source object for this {@code PropertySource}.
*/
public T getSource() {
return source;
return this.source;
}
/**
* Return whether this {@code PropertySource} contains the given name.
* <p>This implementation simply checks for a null return value
* from {@link #getProperty(String)}. Subclasses may wish to
* implement a more efficient algorithm if possible.
* <p>This implementation simply checks for a {@code null} return value
* from {@link #getProperty(String)}. Subclasses may wish to implement
* a more efficient algorithm if possible.
* @param name the property name to find
*/
public boolean containsProperty(String name) {
return this.getProperty(name) != null;
return (getProperty(name) != null);
}
/**
* Return the value associated with the given name, {@code null} if not found.
* Return the value associated with the given name,
* or {@code null} if not found.
* @param name the property to find
* @see PropertyResolver#getRequiredProperty(String)
*/
public abstract Object getProperty(String name);
/**
* Return a hashcode derived from the {@code name} property of this {@code PropertySource}
* object.
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.name == null) ? 0 : this.name.hashCode());
return result;
}
/**
* This {@code PropertySource} object is equal to the given object if:
* <ul>
* <li>they are the same instance
* <li>the {@code name} properties for both objects are equal
* <li>they are the same instance
* <li>the {@code name} properties for both objects are equal
* </ul>
*
* <P>No properties other than {@code name} are evaluated.
* <p>No properties other than {@code name} are evaluated.
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof PropertySource))
return false;
PropertySource<?> other = (PropertySource<?>) obj;
if (this.name == null) {
if (other.name != null)
return false;
} else if (!this.name.equals(other.name))
return false;
return true;
return (this == obj || (obj instanceof PropertySource &&
ObjectUtils.nullSafeEquals(this.name, ((PropertySource<?>) obj).name)));
}
/**
* Return a hash code derived from the {@code name} property
* of this {@code PropertySource} object.
*/
@Override
public int hashCode() {
return ObjectUtils.nullSafeHashCode(this.name);
}
/**
* Produce concise output (type and name) if the current log level does not include
* debug. If debug is enabled, produce verbose output including hashcode of the
* debug. If debug is enabled, produce verbose output including the hash code of the
* PropertySource instance and every name/value property pair.
*
* This variable verbosity is useful as a property source such as system properties
* <p>This variable verbosity is useful as a property source such as system properties
* or environment variables may contain an arbitrary number of property pairs,
* potentially leading to difficult to read exception and log messages.
*
* @see Log#isDebugEnabled()
*/
@Override
public String toString() {
if (logger.isDebugEnabled()) {
return String.format("%s@%s [name='%s', properties=%s]",
this.getClass().getSimpleName(), System.identityHashCode(this), this.name, this.source);
getClass().getSimpleName(), System.identityHashCode(this), this.name, this.source);
}
else {
return String.format("%s [name='%s']", getClass().getSimpleName(), this.name);
}
return String.format("%s [name='%s']",
this.getClass().getSimpleName(), this.name);
}
/**
* Return a {@code PropertySource} implementation intended for collection comparison purposes only.
*
* <p>Primarily for internal use, but given a collection of {@code PropertySource} objects, may be
* used as follows:
* <pre class="code">
@@ -189,11 +176,9 @@ public abstract class PropertySource<T> {
* assert sources.contains(PropertySource.named("sourceB"));
* assert !sources.contains(PropertySource.named("sourceC"));
* }</pre>
*
* The returned {@code PropertySource} will throw {@code UnsupportedOperationException}
* if any methods other than {@code equals(Object)}, {@code hashCode()}, and {@code toString()}
* are called.
*
* @param name the name of the comparison {@code PropertySource} to be created and returned.
*/
public static PropertySource<?> named(String name) {
@@ -209,7 +194,6 @@ public abstract class PropertySource<T> {
* {@code ApplicationContext}. In such cases, a stub should be used to hold the
* intended default position/order of the property source, then be replaced
* during context refresh.
*
* @see org.springframework.context.support.AbstractApplicationContext#initPropertySources()
* @see org.springframework.web.context.support.StandardServletEnvironment
* @see org.springframework.web.context.support.ServletContextPropertySource
@@ -221,7 +205,7 @@ public abstract class PropertySource<T> {
}
/**
* Always return {@code null}.
* Always returns {@code null}.
*/
@Override
public String getProperty(String name) {
@@ -236,8 +220,7 @@ public abstract class PropertySource<T> {
static class ComparisonPropertySource extends StubPropertySource {
private static final String USAGE_ERROR =
"ComparisonPropertySource instances are for collection comparison " +
"use only";
"ComparisonPropertySource instances are for use with collection comparison only";
public ComparisonPropertySource(String name) {
super(name);
@@ -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,9 +50,9 @@ public class ClassPathResource extends AbstractFileResolvingResource {
/**
* Create a new ClassPathResource for ClassLoader usage.
* A leading slash will be removed, as the ClassLoader
* resource access methods will not accept it.
* Create a new {@code ClassPathResource} for {@code ClassLoader} usage.
* A leading slash will be removed, as the ClassLoader resource access
* methods will not accept it.
* <p>The thread context class loader will be used for
* loading the resource.
* @param path the absolute path within the class path
@@ -64,9 +64,9 @@ public class ClassPathResource extends AbstractFileResolvingResource {
}
/**
* Create a new ClassPathResource for ClassLoader usage.
* A leading slash will be removed, as the ClassLoader
* resource access methods will not accept it.
* Create a new {@code ClassPathResource} for {@code ClassLoader} usage.
* A leading slash will be removed, as the ClassLoader resource access
* methods will not accept it.
* @param path the absolute path within the classpath
* @param classLoader the class loader to load the resource with,
* or {@code null} for the thread context class loader
@@ -83,9 +83,9 @@ public class ClassPathResource extends AbstractFileResolvingResource {
}
/**
* Create a new ClassPathResource for Class usage.
* The path can be relative to the given class,
* or absolute within the classpath via a leading slash.
* Create a new {@code ClassPathResource} for {@code Class} usage.
* The path can be relative to the given class, or absolute within
* the classpath via a leading slash.
* @param path relative or absolute path within the class path
* @param clazz the class to load resources with
* @see java.lang.Class#getResourceAsStream
@@ -97,8 +97,8 @@ public class ClassPathResource extends AbstractFileResolvingResource {
}
/**
* Create a new ClassPathResource with optional ClassLoader and Class.
* Only for internal usage.
* Create a new {@code ClassPathResource} with optional {@code ClassLoader}
* and {@code Class}. Only for internal usage.
* @param path relative or absolute path within the classpath
* @param classLoader the class loader to load the resource with, if any
* @param clazz the class to load resources with, if any
@@ -109,6 +109,7 @@ public class ClassPathResource extends AbstractFileResolvingResource {
this.clazz = clazz;
}
/**
* Return the path for this resource (as resource path within the class path).
*/
@@ -120,9 +121,10 @@ public class ClassPathResource extends AbstractFileResolvingResource {
* Return the ClassLoader that this resource will be obtained from.
*/
public final ClassLoader getClassLoader() {
return (this.classLoader != null ? this.classLoader : this.clazz.getClassLoader());
return (this.clazz != null ? this.clazz.getClassLoader() : this.classLoader);
}
/**
* This implementation checks for the resolution of a resource URL.
* @see java.lang.ClassLoader#getResource(String)
@@ -130,14 +132,23 @@ public class ClassPathResource extends AbstractFileResolvingResource {
*/
@Override
public boolean exists() {
URL url;
return (resolveURL() != null);
}
/**
* Resolves a URL for the underlying class path resource.
* @return the resolved URL, or {@code null} if not resolvable
*/
protected URL resolveURL() {
if (this.clazz != null) {
url = this.clazz.getResource(this.path);
return this.clazz.getResource(this.path);
}
else if (this.classLoader != null) {
return this.classLoader.getResource(this.path);
}
else {
url = this.classLoader.getResource(this.path);
return ClassLoader.getSystemResource(this.path);
}
return (url != null);
}
/**
@@ -151,9 +162,12 @@ public class ClassPathResource extends AbstractFileResolvingResource {
if (this.clazz != null) {
is = this.clazz.getResourceAsStream(this.path);
}
else {
else if (this.classLoader != null) {
is = this.classLoader.getResourceAsStream(this.path);
}
else {
is = ClassLoader.getSystemResourceAsStream(this.path);
}
if (is == null) {
throw new FileNotFoundException(getDescription() + " cannot be opened because it does not exist");
}
@@ -161,19 +175,14 @@ public class ClassPathResource extends AbstractFileResolvingResource {
}
/**
* This implementation returns a URL for the underlying class path resource.
* This implementation returns a URL for the underlying class path resource,
* if available.
* @see java.lang.ClassLoader#getResource(String)
* @see java.lang.Class#getResource(String)
*/
@Override
public URL getURL() throws IOException {
URL url;
if (this.clazz != null) {
url = this.clazz.getResource(this.path);
}
else {
url = this.classLoader.getResource(this.path);
}
URL url = resolveURL();
if (url == null) {
throw new FileNotFoundException(getDescription() + " cannot be resolved to URL because it does not exist");
}
@@ -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.
@@ -45,7 +45,7 @@ public class FileSystemResource extends AbstractResource implements WritableReso
/**
* Create a new FileSystemResource from a File handle.
* Create a new {@code FileSystemResource} from a {@link File} handle.
* <p>Note: When building relative resources via {@link #createRelative},
* the relative path will apply <i>at the same directory level</i>:
* e.g. new File("C:/dir1"), relative path "dir2" -> "C:/dir2"!
@@ -62,7 +62,7 @@ public class FileSystemResource extends AbstractResource implements WritableReso
}
/**
* Create a new FileSystemResource from a file path.
* Create a new {@code FileSystemResource} from a file path.
* <p>Note: When building relative resources via {@link #createRelative},
* it makes a difference whether the specified resource base path here
* ends with a slash or not. In the case of "C:/dir1/", relative paths
@@ -77,6 +77,7 @@ public class FileSystemResource extends AbstractResource implements WritableReso
this.path = StringUtils.cleanPath(path);
}
/**
* Return the file path for this resource.
*/
@@ -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.
@@ -70,7 +70,9 @@ public interface ResourceLoader {
* <p>Clients which need to access the ClassLoader directly can do so
* in a uniform manner with the ResourceLoader, rather than relying
* on the thread context ClassLoader.
* @return the ClassLoader (never {@code null})
* @return the ClassLoader (only {@code null} if even the system
* ClassLoader isn't accessible)
* @see org.springframework.util.ClassUtils#getDefaultClassLoader()
*/
ClassLoader getClassLoader();
@@ -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.
@@ -26,8 +26,11 @@ import org.springframework.core.NestedIOException;
import org.springframework.util.Assert;
/**
* VFS based {@link Resource} implementation.
* Supports the corresponding VFS API versions on JBoss AS 5.x as well as 6.x and 7.x.
* JBoss VFS based {@link Resource} implementation.
*
* <p>As of Spring 4.0, this class supports VFS 3.x on JBoss AS 6+ (package
* {@code org.jboss.vfs}) and is in particular compatible with JBoss AS 7 and
* WildFly 8.
*
* @author Ales Justin
* @author Juergen Hoeller
@@ -40,9 +43,9 @@ public class VfsResource extends AbstractResource {
private final Object resource;
public VfsResource(Object resources) {
Assert.notNull(resources, "VirtualFile must not be null");
this.resource = resources;
public VfsResource(Object resource) {
Assert.notNull(resource, "VirtualFile must not be null");
this.resource = resource;
}
@@ -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.
@@ -29,8 +29,10 @@ import org.springframework.util.ReflectionUtils;
/**
* Utility for detecting and accessing JBoss VFS in the classpath.
* As of Spring 4.0, supports VFS 3.x on JBoss AS 6+ (package {@code org.jboss.vfs})
* and is in particular compatible with JBoss AS 7 and WildFly 8.
*
* <p>As of Spring 4.0, this class supports VFS 3.x on JBoss AS 6+ (package
* {@code org.jboss.vfs}) and is in particular compatible with JBoss AS 7 and
* WildFly 8.
*
* <p>Thanks go to Marius Bogoevici for the initial patch.
* <b>Note:</b> This is an internal class and should not be used outside the framework.
@@ -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.
@@ -42,6 +42,7 @@ import org.springframework.core.io.UrlResource;
import org.springframework.core.io.VfsResource;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.PathMatcher;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.ResourceUtils;
@@ -143,11 +144,15 @@ import org.springframework.util.StringUtils;
*
* <p><b>WARNING:</b> Ant-style patterns with "classpath:" resources are not
* guaranteed to find matching resources if the root package to search is available
* in multiple class path locations. This is because a resource such as<pre class="code">
* in multiple class path locations. This is because a resource such as
* <pre class="code">
* com/mycompany/package1/service-context.xml
* </pre>may be in only one location, but when a path such as<pre class="code">
* </pre>
* may be in only one location, but when a path such as
* <pre class="code">
* classpath:com/mycompany/**&#47;service-context.xml
* </pre>is used to try to resolve it, the resolver will work off the (first) URL
* </pre>
* is used to try to resolve it, the resolver will work off the (first) URL
* returned by {@code getResource("com/mycompany");}. If this base package
* node exists in multiple classloader locations, the actual end resource may
* not be underneath. Therefore, preferably, use "{@code classpath*:}" with the same
@@ -171,10 +176,10 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
private static Method equinoxResolveMethod;
static {
// Detect Equinox OSGi (e.g. on WebSphere 6.1)
try {
Class<?> fileLocatorClass = PathMatchingResourcePatternResolver.class.getClassLoader().loadClass(
"org.eclipse.core.runtime.FileLocator");
// Detect Equinox OSGi (e.g. on WebSphere 6.1)
Class<?> fileLocatorClass = ClassUtils.forName("org.eclipse.core.runtime.FileLocator",
PathMatchingResourcePatternResolver.class.getClassLoader());
equinoxResolveMethod = fileLocatorClass.getMethod("resolve", URL.class);
logger.debug("Found Equinox FileLocator for OSGi bundle URL resolution");
}
@@ -198,17 +203,6 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
this.resourceLoader = new DefaultResourceLoader();
}
/**
* Create a new PathMatchingResourcePatternResolver with a DefaultResourceLoader.
* @param classLoader the ClassLoader to load classpath resources with,
* or {@code null} for using the thread context class loader
* at the time of actual resource access
* @see org.springframework.core.io.DefaultResourceLoader
*/
public PathMatchingResourcePatternResolver(ClassLoader classLoader) {
this.resourceLoader = new DefaultResourceLoader(classLoader);
}
/**
* Create a new PathMatchingResourcePatternResolver.
* <p>ClassLoader access will happen via the thread context class loader.
@@ -220,6 +214,18 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
this.resourceLoader = resourceLoader;
}
/**
* Create a new PathMatchingResourcePatternResolver with a DefaultResourceLoader.
* @param classLoader the ClassLoader to load classpath resources with,
* or {@code null} for using the thread context class loader
* at the time of actual resource access
* @see org.springframework.core.io.DefaultResourceLoader
*/
public PathMatchingResourcePatternResolver(ClassLoader classLoader) {
this.resourceLoader = new DefaultResourceLoader(classLoader);
}
/**
* Return the ResourceLoader that this pattern resolver works with.
*/
@@ -227,10 +233,6 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
return this.resourceLoader;
}
/**
* Return the ClassLoader that this pattern resolver works with
* (never {@code null}).
*/
@Override
public ClassLoader getClassLoader() {
return getResourceLoader().getClassLoader();
@@ -301,7 +303,8 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
if (path.startsWith("/")) {
path = path.substring(1);
}
Enumeration<URL> resourceUrls = getClassLoader().getResources(path);
ClassLoader cl = getClassLoader();
Enumeration<URL> resourceUrls = (cl != null ? cl.getResources(path) : ClassLoader.getSystemResources(path));
Set<Resource> result = new LinkedHashSet<Resource>(16);
while (resourceUrls.hasMoreElements()) {
URL url = resourceUrls.nextElement();
@@ -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,12 +170,13 @@ public abstract class PropertiesLoaderUtils {
*/
public static Properties loadAllProperties(String resourceName, ClassLoader classLoader) throws IOException {
Assert.notNull(resourceName, "Resource name must not be null");
ClassLoader clToUse = classLoader;
if (clToUse == null) {
clToUse = ClassUtils.getDefaultClassLoader();
ClassLoader classLoaderToUse = classLoader;
if (classLoaderToUse == null) {
classLoaderToUse = ClassUtils.getDefaultClassLoader();
}
Enumeration<URL> urls = (classLoaderToUse != null ? classLoaderToUse.getResources(resourceName) :
ClassLoader.getSystemResources(resourceName));
Properties props = new Properties();
Enumeration<URL> urls = clToUse.getResources(resourceName);
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
URLConnection con = url.openConnection();
@@ -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,6 +17,7 @@
package org.springframework.core.io.support;
import java.io.IOException;
import java.util.Map;
import java.util.Properties;
import org.springframework.core.env.PropertiesPropertySource;
@@ -36,6 +37,8 @@ import org.springframework.util.StringUtils;
* @author Chris Beams
* @author Juergen Hoeller
* @since 3.1
* @see org.springframework.core.io.Resource
* @see org.springframework.core.io.support.EncodedResource
*/
public class ResourcePropertySource extends PropertiesPropertySource {
@@ -112,10 +115,27 @@ public class ResourcePropertySource extends PropertiesPropertySource {
this(new DefaultResourceLoader().getResource(location));
}
private ResourcePropertySource(String name, Map<String, Object> source) {
super(name, source);
}
/**
* Return the description string for the resource, and if empty returns
* the class name of the resource plus its identity hash code.
* Return a potentially adapted variant of this {@link ResourcePropertySource},
* overriding the previously given (or derived) name with the specified name.
*/
public ResourcePropertySource withName(String name) {
if (this.name.equals(name)) {
return this;
}
return new ResourcePropertySource(name, this.source);
}
/**
* Return the description String for the given Resource; it the description is
* empty, return the class name of the resource plus its identity hash code.
* @see org.springframework.core.io.Resource#getDescription()
*/
private static String getNameForResource(Resource resource) {
String name = resource.getDescription();
@@ -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.
@@ -67,16 +67,17 @@ public abstract class SpringFactoriesLoader {
*/
public static <T> List<T> loadFactories(Class<T> factoryClass, ClassLoader classLoader) {
Assert.notNull(factoryClass, "'factoryClass' must not be null");
if (classLoader == null) {
classLoader = SpringFactoriesLoader.class.getClassLoader();
ClassLoader classLoaderToUse = classLoader;
if (classLoaderToUse == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
List<String> factoryNames = loadFactoryNames(factoryClass, classLoader);
List<String> factoryNames = loadFactoryNames(factoryClass, classLoaderToUse);
if (logger.isTraceEnabled()) {
logger.trace("Loaded [" + factoryClass.getName() + "] names: " + factoryNames);
}
List<T> result = new ArrayList<T>(factoryNames.size());
for (String factoryName : factoryNames) {
result.add(instantiateFactory(factoryName, factoryClass, classLoader));
result.add(instantiateFactory(factoryName, factoryClass, classLoaderToUse));
}
OrderComparator.sort(result);
return result;
@@ -85,8 +86,9 @@ public abstract class SpringFactoriesLoader {
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
try {
Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
List<String> result = new ArrayList<String>();
Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
@@ -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.
@@ -128,7 +128,7 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements
public boolean hasAnnotatedMethods(String annotationType) {
Method[] methods = getIntrospectedClass().getDeclaredMethods();
for (Method method : methods) {
if (AnnotatedElementUtils.isAnnotated(method, annotationType)) {
if (!method.isBridge() && AnnotatedElementUtils.isAnnotated(method, annotationType)) {
return true;
}
}
@@ -140,7 +140,7 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements
Method[] methods = getIntrospectedClass().getDeclaredMethods();
Set<MethodMetadata> annotatedMethods = new LinkedHashSet<MethodMetadata>();
for (Method method : methods) {
if (AnnotatedElementUtils.isAnnotated(method, annotationType)) {
if (!method.isBridge() && AnnotatedElementUtils.isAnnotated(method, annotationType)) {
annotatedMethods.add(new StandardMethodMetadata(method, this.nestedAnnotationsAsMap));
}
}
@@ -25,6 +25,7 @@ import java.util.Set;
import org.springframework.asm.AnnotationVisitor;
import org.springframework.asm.MethodVisitor;
import org.springframework.asm.Opcodes;
import org.springframework.asm.Type;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;
@@ -55,10 +56,9 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito
/**
* Declared as a {@link LinkedMultiValueMap} instead of a {@link MultiValueMap}
* to ensure that the hierarchical ordering of the entries is preserved.
* @see AnnotationReadingVisitorUtils#getMergedAnnotationAttributes(LinkedMultiValueMap, String)
* @see AnnotationReadingVisitorUtils#getMergedAnnotationAttributes
*/
protected final LinkedMultiValueMap<String, AnnotationAttributes> attributesMap = new LinkedMultiValueMap<String, AnnotationAttributes>(
4);
protected final LinkedMultiValueMap<String, AnnotationAttributes> attributesMap = new LinkedMultiValueMap<String, AnnotationAttributes>(4);
protected final Set<MethodMetadata> methodMetadataSet = new LinkedHashSet<MethodMetadata>(4);
@@ -70,6 +70,11 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
// Skip bridge methods - we're only interested in original annotation-defining user methods.
// On JDK 8, we'd otherwise run into double detection of the same annotated method...
if ((access & Opcodes.ACC_BRIDGE) != 0) {
return super.visitMethod(access, name, desc, signature, exceptions);
}
return new MethodMetadataReadingVisitor(name, access, getClassName(), this.classLoader, this.methodMetadataSet);
}
@@ -119,8 +124,8 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito
@Override
public AnnotationAttributes getAnnotationAttributes(String annotationType, boolean classValuesAsString) {
AnnotationAttributes raw = AnnotationReadingVisitorUtils.getMergedAnnotationAttributes(this.attributesMap,
annotationType);
AnnotationAttributes raw = AnnotationReadingVisitorUtils.getMergedAnnotationAttributes(
this.attributesMap, this.metaAnnotationMap, annotationType);
return AnnotationReadingVisitorUtils.convertClassValues(this.classLoader, raw, classValuesAsString);
}
@@ -25,10 +25,9 @@ import java.util.Set;
import org.springframework.asm.Type;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.LinkedMultiValueMap;
import static org.springframework.core.annotation.AnnotationUtils.VALUE;
/**
* Internal utility class used when reading annotations.
*
@@ -98,20 +97,23 @@ abstract class AnnotationReadingVisitorUtils {
}
/**
* Retrieve the merged attributes of the annotation of the given type, if any,
* from the supplied {@code attributesMap}.
* Retrieve the merged attributes of the annotation of the given type,
* if any, from the supplied {@code attributesMap}.
* <p>Annotation attribute values appearing <em>lower</em> in the annotation
* hierarchy (i.e., closer to the declaring class) will override those
* defined <em>higher</em> in the annotation hierarchy.
* @param attributesMap the map of annotation attribute lists, keyed by
* annotation type name
* @param attributesMap the map of annotation attribute lists,
* keyed by annotation type name
* @param metaAnnotationMap the map of meta annotation relationships,
* keyed by annotation type name
* @param annotationType the name of the annotation type to look for
* @return the merged annotation attributes; or {@code null} if no matching
* annotation is present in the {@code attributesMap}
* @return the merged annotation attributes, or {@code null} if no
* matching annotation is present in the {@code attributesMap}
* @since 4.0.3
*/
public static AnnotationAttributes getMergedAnnotationAttributes(
LinkedMultiValueMap<String, AnnotationAttributes> attributesMap, String annotationType) {
LinkedMultiValueMap<String, AnnotationAttributes> attributesMap,
Map<String, Set<String>> metaAnnotationMap, String annotationType) {
// Get the unmerged list of attributes for the target annotation.
List<AnnotationAttributes> attributesList = attributesMap.get(annotationType);
@@ -119,12 +121,14 @@ abstract class AnnotationReadingVisitorUtils {
return null;
}
// To start with, we populate the results with all attribute values from the
// target annotation.
AnnotationAttributes results = attributesList.get(0);
// To start with, we populate the results with a copy of all attribute
// values from the target annotation. A copy is necessary so that we do
// not inadvertently mutate the state of the metadata passed to this
// method.
AnnotationAttributes results = new AnnotationAttributes(attributesList.get(0));
Set<String> overridableAttributeNames = new HashSet<String>(results.keySet());
overridableAttributeNames.remove(VALUE);
overridableAttributeNames.remove(AnnotationUtils.VALUE);
// Since the map is a LinkedMultiValueMap, we depend on the ordering of
// elements in the map and reverse the order of the keys in order to traverse
@@ -132,17 +136,23 @@ abstract class AnnotationReadingVisitorUtils {
List<String> annotationTypes = new ArrayList<String>(attributesMap.keySet());
Collections.reverse(annotationTypes);
// No need to revisit the target annotation type:
annotationTypes.remove(annotationType);
for (String currentAnnotationType : annotationTypes) {
List<AnnotationAttributes> currentAttributesList = attributesMap.get(currentAnnotationType);
if (currentAttributesList != null && !currentAttributesList.isEmpty()) {
AnnotationAttributes currentAttributes = currentAttributesList.get(0);
for (String overridableAttributeName : overridableAttributeNames) {
Object value = currentAttributes.get(overridableAttributeName);
if (value != null) {
// Store the value, potentially overriding a value from an
// attribute of the same name found higher in the annotation
// hierarchy.
results.put(overridableAttributeName, value);
Set<String> metaAnns = metaAnnotationMap.get(currentAnnotationType);
if (metaAnns != null && metaAnns.contains(annotationType)) {
AnnotationAttributes currentAttributes = currentAttributesList.get(0);
for (String overridableAttributeName : overridableAttributeNames) {
Object value = currentAttributes.get(overridableAttributeName);
if (value != null) {
// Store the value, potentially overriding a value from an
// attribute of the same name found higher in the annotation
// hierarchy.
results.put(overridableAttributeName, value);
}
}
}
}
@@ -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,8 +19,8 @@ package org.springframework.core.type.filter;
import java.io.IOException;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
/**
* Type filter that is aware of traversing over hierarchy.
@@ -61,40 +61,38 @@ public abstract class AbstractTypeHierarchyTraversingFilter implements TypeFilte
return true;
}
if (!this.considerInherited) {
return false;
}
if (metadata.hasSuperClass()) {
// Optimization to avoid creating ClassReader for super class.
Boolean superClassMatch = matchSuperClass(metadata.getSuperClassName());
if (superClassMatch != null) {
if (superClassMatch.booleanValue()) {
return true;
if (this.considerInherited) {
if (metadata.hasSuperClass()) {
// Optimization to avoid creating ClassReader for super class.
Boolean superClassMatch = matchSuperClass(metadata.getSuperClassName());
if (superClassMatch != null) {
if (superClassMatch.booleanValue()) {
return true;
}
}
}
else {
// Need to read super class to determine a match...
if (match(metadata.getSuperClassName(), metadataReaderFactory)) {
return true;
else {
// Need to read super class to determine a match...
if (match(metadata.getSuperClassName(), metadataReaderFactory)) {
return true;
}
}
}
}
if (!this.considerInterfaces) {
return false;
}
for (String ifc : metadata.getInterfaceNames()) {
// Optimization to avoid creating ClassReader for super class
Boolean interfaceMatch = matchInterface(ifc);
if (interfaceMatch != null) {
if (interfaceMatch.booleanValue()) {
return true;
if (this.considerInterfaces) {
for (String ifc : metadata.getInterfaceNames()) {
// Optimization to avoid creating ClassReader for super class
Boolean interfaceMatch = matchInterface(ifc);
if (interfaceMatch != null) {
if (interfaceMatch.booleanValue()) {
return true;
}
}
}
else {
// Need to read interface to determine a match...
if (match(ifc, metadataReaderFactory)) {
return true;
else {
// Need to read interface to determine a match...
if (match(ifc, metadataReaderFactory)) {
return true;
}
}
}
}
@@ -132,7 +130,7 @@ public abstract class AbstractTypeHierarchyTraversingFilter implements TypeFilte
/**
* Override this to match on interface type name.
*/
protected Boolean matchInterface(String interfaceNames) {
protected Boolean matchInterface(String interfaceName) {
return null;
}
@@ -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,8 +19,10 @@ package org.springframework.core.type.filter;
import java.lang.annotation.Annotation;
import java.lang.annotation.Inherited;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.util.ClassUtils;
/**
* A simple filter which matches classes with a given annotation,
@@ -49,7 +51,7 @@ public class AnnotationTypeFilter extends AbstractTypeHierarchyTraversingFilter
* @param annotationType the annotation type to match
*/
public AnnotationTypeFilter(Class<? extends Annotation> annotationType) {
this(annotationType, true);
this(annotationType, true, false);
}
/**
@@ -84,16 +86,26 @@ public class AnnotationTypeFilter extends AbstractTypeHierarchyTraversingFilter
@Override
protected Boolean matchSuperClass(String superClassName) {
if (Object.class.getName().equals(superClassName)) {
return Boolean.FALSE;
return hasAnnotation(superClassName);
}
@Override
protected Boolean matchInterface(String interfaceName) {
return hasAnnotation(interfaceName);
}
protected Boolean hasAnnotation(String typeName) {
if (Object.class.getName().equals(typeName)) {
return false;
}
else if (superClassName.startsWith("java.")) {
else if (typeName.startsWith("java")) {
try {
Class<?> clazz = getClass().getClassLoader().loadClass(superClassName);
return (clazz.getAnnotation(this.annotationType) != null);
Class<?> clazz = ClassUtils.forName(typeName, getClass().getClassLoader());
return ((this.considerMetaAnnotations ? AnnotationUtils.getAnnotation(clazz, this.annotationType) :
clazz.getAnnotation(this.annotationType)) != null);
}
catch (ClassNotFoundException ex) {
// Class not found - can't determine a match that way.
catch (Throwable ex) {
// Class not regularly loadable - can't determine a match that way.
}
}
return null;
@@ -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.
@@ -16,6 +16,8 @@
package org.springframework.core.type.filter;
import org.springframework.util.ClassUtils;
/**
* A simple filter which matches classes that are assignable to a given type.
*
@@ -59,15 +61,15 @@ public class AssignableTypeFilter extends AbstractTypeHierarchyTraversingFilter
return true;
}
else if (Object.class.getName().equals(typeName)) {
return Boolean.FALSE;
return false;
}
else if (typeName.startsWith("java.")) {
else if (typeName.startsWith("java")) {
try {
Class<?> clazz = getClass().getClassLoader().loadClass(typeName);
return Boolean.valueOf(this.targetType.isAssignableFrom(clazz));
Class<?> clazz = ClassUtils.forName(typeName, getClass().getClassLoader());
return this.targetType.isAssignableFrom(clazz);
}
catch (ClassNotFoundException ex) {
// Class not found - can't determine a match that way.
catch (Throwable ex) {
// Class not regularly loadable - can't determine a match that way.
}
}
return null;
@@ -142,12 +142,14 @@ public abstract class ClassUtils {
* ClassLoader, if available; the ClassLoader that loaded the ClassUtils
* class will be used as fallback.
* <p>Call this method if you intend to use the thread context ClassLoader
* in a scenario where you absolutely need a non-null ClassLoader reference:
* in a scenario where you clearly prefer a non-null ClassLoader reference:
* for example, for class path resource loading (but not necessarily for
* {@code Class.forName}, which accepts a {@code null} ClassLoader
* reference as well).
* @return the default ClassLoader (never {@code null})
* @return the default ClassLoader (only {@code null} if even the system
* ClassLoader isn't accessible)
* @see Thread#getContextClassLoader()
* @see ClassLoader#getSystemClassLoader()
*/
public static ClassLoader getDefaultClassLoader() {
ClassLoader cl = null;
@@ -155,11 +157,20 @@ public abstract class ClassUtils {
cl = Thread.currentThread().getContextClassLoader();
}
catch (Throwable ex) {
// Cannot access thread context ClassLoader - falling back to system class loader...
// Cannot access thread context ClassLoader - falling back...
}
if (cl == null) {
// No thread context class loader -> use class loader of this class.
cl = ClassUtils.class.getClassLoader();
if (cl == null) {
// getClassLoader() returning null indicates the bootstrap ClassLoader
try {
cl = ClassLoader.getSystemClassLoader();
}
catch (Throwable ex) {
// Cannot access system ClassLoader - oh well, maybe the caller can live with null...
}
}
}
return cl;
}
@@ -185,7 +196,7 @@ public abstract class ClassUtils {
/**
* Replacement for {@code Class.forName()} that also returns Class instances
* for primitives (e.g."int") and array class names (e.g. "String[]").
* for primitives (e.g. "int") and array class names (e.g. "String[]").
* Furthermore, it is also capable of resolving inner class names in Java source
* style (e.g. "java.lang.Thread.State" instead of "java.lang.Thread$State").
* @param name the name of the Class
@@ -228,19 +239,19 @@ public abstract class ClassUtils {
return Array.newInstance(elementClass, 0).getClass();
}
ClassLoader classLoaderToUse = classLoader;
if (classLoaderToUse == null) {
classLoaderToUse = getDefaultClassLoader();
ClassLoader clToUse = classLoader;
if (clToUse == null) {
clToUse = getDefaultClassLoader();
}
try {
return classLoaderToUse.loadClass(name);
return (clToUse != null ? clToUse.loadClass(name) : Class.forName(name));
}
catch (ClassNotFoundException ex) {
int lastDotIndex = name.lastIndexOf('.');
if (lastDotIndex != -1) {
String innerClassName = name.substring(0, lastDotIndex) + '$' + name.substring(lastDotIndex + 1);
try {
return classLoaderToUse.loadClass(innerClassName);
return (clToUse != null ? clToUse.loadClass(innerClassName) : Class.forName(innerClassName));
}
catch (ClassNotFoundException ex2) {
// swallow - let original exception get through
@@ -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.
@@ -317,7 +317,7 @@ public abstract class CollectionUtils {
* Enumeration elements must be assignable to the type of the given array. The array
* returned will be a different instance than the array given.
*/
public static <A,E extends A> A[] toArray(Enumeration<E> enumeration, A[] array) {
public static <A, E extends A> A[] toArray(Enumeration<E> enumeration, A[] array) {
ArrayList<A> elements = new ArrayList<A>();
while (enumeration.hasMoreElements()) {
elements.add(enumeration.nextElement());
@@ -387,7 +387,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
protected static int calculateShift(int minimumValue, int maximumValue) {
int shift = 0;
int value = 1;
while (value < minimumValue && value < minimumValue) {
while (value < minimumValue && value < maximumValue) {
value <<= 1;
shift++;
}
@@ -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.
@@ -287,7 +287,7 @@ public class MimeType implements Comparable<MimeType>, Serializable {
* method is <b>not</b> symmetric.
* @param other the reference media type with which to compare
* @return {@code true} if this media type includes the given media type;
* {@code false} otherwise
* {@code false} otherwise
*/
public boolean includes(MimeType other) {
if (other == null) {
@@ -424,7 +424,8 @@ public class MimeType implements Comparable<MimeType>, Serializable {
return false;
}
MimeType otherType = (MimeType) other;
return (this.type.equalsIgnoreCase(otherType.type) && this.subtype.equalsIgnoreCase(otherType.subtype) &&
return (this.type.equalsIgnoreCase(otherType.type) &&
this.subtype.equalsIgnoreCase(otherType.subtype) &&
this.parameters.equals(otherType.parameters));
}
@@ -29,7 +29,7 @@ import java.io.ByteArrayOutputStream;
*
* @author Brian Clozel
* @author Juergen Hoeller
* @since 4.0
* @since 4.0.3
*/
public class ResizableByteArrayOutputStream extends ByteArrayOutputStream {
@@ -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.
@@ -66,15 +66,15 @@ public abstract class ResourceUtils {
/** URL protocol for an entry from a zip file: "zip" */
public static final String URL_PROTOCOL_ZIP = "zip";
/** URL protocol for an entry from a WebSphere jar file: "wsjar" */
public static final String URL_PROTOCOL_WSJAR = "wsjar";
/** URL protocol for an entry from a JBoss jar file: "vfszip" */
public static final String URL_PROTOCOL_VFSZIP = "vfszip";
/** URL protocol for a JBoss VFS resource: "vfs" */
public static final String URL_PROTOCOL_VFS = "vfs";
/** URL protocol for an entry from a WebSphere jar file: "wsjar" */
public static final String URL_PROTOCOL_WSJAR = "wsjar";
/** Separator between JAR URL and file path within the JAR */
public static final String JAR_URL_SEPARATOR = "!/";
@@ -116,7 +116,8 @@ public abstract class ResourceUtils {
Assert.notNull(resourceLocation, "Resource location must not be null");
if (resourceLocation.startsWith(CLASSPATH_URL_PREFIX)) {
String path = resourceLocation.substring(CLASSPATH_URL_PREFIX.length());
URL url = ClassUtils.getDefaultClassLoader().getResource(path);
ClassLoader cl = ClassUtils.getDefaultClassLoader();
URL url = (cl != null ? cl.getResource(path) : ClassLoader.getSystemResource(path));
if (url == null) {
String description = "class path resource [" + path + "]";
throw new FileNotFoundException(
@@ -156,7 +157,8 @@ public abstract class ResourceUtils {
if (resourceLocation.startsWith(CLASSPATH_URL_PREFIX)) {
String path = resourceLocation.substring(CLASSPATH_URL_PREFIX.length());
String description = "class path resource [" + path + "]";
URL url = ClassUtils.getDefaultClassLoader().getResource(path);
ClassLoader cl = ClassUtils.getDefaultClassLoader();
URL url = (cl != null ? cl.getResource(path) : ClassLoader.getSystemResource(path));
if (url == null) {
throw new FileNotFoundException(
description + " cannot be resolved to absolute file path " +
@@ -252,7 +254,7 @@ public abstract class ResourceUtils {
*/
public static boolean isFileURL(URL url) {
String protocol = url.getProtocol();
return (URL_PROTOCOL_FILE.equals(protocol) || protocol.startsWith(URL_PROTOCOL_VFS));
return (URL_PROTOCOL_FILE.equals(protocol) || URL_PROTOCOL_VFS.equals(protocol));
}
/**
@@ -264,8 +266,9 @@ public abstract class ResourceUtils {
* @return whether the URL has been identified as a JAR URL
*/
public static boolean isJarURL(URL url) {
String up = url.getProtocol();
return (URL_PROTOCOL_JAR.equals(up) || URL_PROTOCOL_ZIP.equals(up) || URL_PROTOCOL_WSJAR.equals(up));
String protocol = url.getProtocol();
return (URL_PROTOCOL_JAR.equals(protocol) || URL_PROTOCOL_ZIP.equals(protocol) ||
URL_PROTOCOL_WSJAR.equals(protocol) || URL_PROTOCOL_VFSZIP.equals(protocol));
}
/**

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