Compare commits

...

242 Commits

Author SHA1 Message Date
Spring Buildmaster dfe80ddd9b Release version 4.0.7.RELEASE 2014-09-04 01:16:42 -07:00
Juergen Hoeller d765698ac3 Polishing 2014-09-04 03:06:37 +02:00
Juergen Hoeller d081a4530c Polishing 2014-09-04 02:37:36 +02:00
Juergen Hoeller 97bd0ccfec Polishing 2014-09-04 01:43:15 +02:00
Juergen Hoeller 8543a5548e CachingConnectionFactory proceeds to physicalClose in case of logicalClose exceptions
Issue: SPR-12148
(cherry picked from commit 82f8b43)
2014-09-04 00:58:50 +02:00
Juergen Hoeller d2ef6dcb8d Polishing 2014-09-03 13:49:37 +02:00
Juergen Hoeller bff2bf2cdb AbstractAutowireCapableBeanFactory avoids early FactoryBean instantiation on currently created configuration bean
Issue: SPR-12141
(cherry picked from commit 4432c41)
2014-09-03 13:48:47 +02:00
Juergen Hoeller 72d62a7113 Cache.get(key, type) explicitly defines an IllegalStateException in case of a type mismatch
Issue: SPR-12145
(cherry picked from commit 2f93759)
2014-09-03 13:48:19 +02:00
Stephane Nicoll e1a01d4c3c Improve configuration changes in GuavaCacheManager
Prior to this commit, setting the parameters used to build the caches
was fragile in static mode as the caches were created right when the
setCacheNames setter was called.

This commit provides a better handling of such arguments and also
provide a way to restore the dynamic mode if necessary.

Issue: SPR-12120
(cherry picked from commit d47c543)
2014-09-01 14:08:14 +02:00
Sebastien Deleuze b7726ff48c Improve ResolvableType.hashCode() for better performance
Prior to this commit, when there was a lot of entries in the
ResolvableType.cache HashMap, getting a simple value could
take a lot of time due to a lot of calls to ResolvableType.equals().
ResolvableType.equals() used this.type, getSource(),
this.variableResolver.getSource() and this.componentType, but
ResolvableType.hashCode() used only this.type.

With this commit, ResolvableType.hashCode() now uses the same
fields than ResolvableType.equals().

Performance on the spring-resolvabletype-benchmark project:
 - 8000 us before this commit
 - 120 us with this commit

Issue: SPR-12122
(cherry picked from commit 7ea69fb)
2014-09-01 14:07:43 +02:00
Sam Brannen a52ff46fea Include ALL source artifacts in published sources jars
This commit updates the Gradle build to ensure that *all* source
artifacts are including in published 'sources' jars.

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

Issue: SPR-12085
(cherry picked from commit 07629a3c7c)
2014-08-26 16:51:26 +02:00
Juergen Hoeller eb3509a37c Polishing 2014-08-23 02:02:38 +02:00
Juergen Hoeller 93ad7f8def Polishing 2014-08-23 01:28:10 +02:00
Juergen Hoeller 54ba5c5e7b Polishing 2014-08-22 23:39:37 +02:00
Juergen Hoeller 249c688e9b DispatcherServlet's checkMultipart detects wrapped MultipartRequest as well
Issue: SPR-12114
(cherry picked from commit 786fd92)
2014-08-22 23:18:39 +02:00
Juergen Hoeller e324c2ab4a Polishing 2014-08-22 00:14:10 +02:00
Juergen Hoeller 39a23660fa PropertySource implementations perform conversion to String arrays via StringUtils (getting rid of EMPTY_NAMES_ARRAY)
(cherry picked from commit b73c531)
2014-08-22 00:09:53 +02:00
Juergen Hoeller 25971d9927 Consistent attribute documentation/formatting in spring-context and spring-mvc schemas
(cherry picked from commit b5763fe)
2014-08-22 00:04:12 +02:00
Juergen Hoeller 379e5abd83 ServerEndpointExporter can initialize itself based on a late-provided ServletContext as well (for Boot)
Also allows for direct setting of a ServerContainer and for custom triggering of endpoint registration.

Issue: SPR-12109
(cherry picked from commit 11805b6)
2014-08-22 00:02:14 +02:00
Juergen Hoeller 8fb7b694dd PersistenceAnnotationBeanPostProcessor defensively handles BeanDefinition access for extended EntityManagers
Issue: SPR-8834
(cherry picked from commit 592e344)
2014-08-22 00:01:39 +02:00
Juergen Hoeller 21d0ce5af8 DefaultListableBeanFactory defensively handles BeanDefinition access in getBean(Class)
Issue: SPR-10542
(cherry picked from commit 9d3d6d5)
2014-08-22 00:01:16 +02:00
Juergen Hoeller fb452fad7c Upgrade to Apache HttpComponents HttpClient 4.3.5 and HttpAsyncClient 4.0.2
Issue: SPR-12100
(cherry picked from commit 5cd1e6a)
2014-08-19 21:41:57 +02:00
Juergen Hoeller 2dd2b7175f ShallowEtagHeaderFilter supports Servlet 3.1's setContentLengthLong as well
Issue: SPR-12097
(cherry picked from commit 0c32d66)
2014-08-19 21:39:43 +02:00
Juergen Hoeller f418e6e981 Polishing 2014-08-18 22:24:43 +02:00
Juergen Hoeller 5e2b9b6f07 Latest dependency updates (AspectJ 1.8.2, Jackson 2.3.4) 2014-08-18 22:19:33 +02:00
Stephane Nicoll a95a3ae4ec Exclude infra modules from public distribution
Prior to this commit, spring-build-src and spring-framework-bom
internal artifacts were published as part of the distribution bundle.

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

Issue: SPR-12087
2014-08-18 12:20:24 +02:00
Juergen Hoeller 0c0d23d0f4 Polishing 2014-08-15 00:58:05 +02:00
Juergen Hoeller a31ebb6c1e Polishing 2014-08-15 00:07:25 +02:00
Juergen Hoeller 42c090efa4 Polishing
Issue: SPR-12079
(cherry picked from commit 92bd240)
2014-08-13 15:28:36 +02:00
Juergen Hoeller 035a9b91d2 BeanNameViewResolver ignores non-View beans
Issue: SPR-12079
(cherry picked from commit 626a5fe)
2014-08-13 15:28:09 +02:00
Juergen Hoeller a7492fa55b Polishing 2014-08-12 22:24:50 +02:00
Juergen Hoeller ecf23ff6cd Remove outdated IDE, JIRA and Tomcat references
Issue: SPR-7521
(cherry picked from commit f1f1c4c)
2014-08-12 22:11:49 +02:00
Juergen Hoeller 4129f00a02 Polishing
(cherry picked from commit 4db258b)
2014-08-11 22:35:26 +02:00
Juergen Hoeller e2d71a8ccd Polishing 2014-08-11 15:45:54 +02:00
Juergen Hoeller 1034b0dae2 Tiles 3 TilesViewResolver allows for specifying custom TilesView subclasses as well
Issue: SPR-12075
(cherry picked from commit 7c57424)
2014-08-11 15:45:14 +02:00
Juergen Hoeller c08ded769a Polishing (includes varargs for selected String array setters) 2014-08-09 00:19:56 +02:00
Juergen Hoeller d61353db51 AnnotatedElementUtils adapts post-processed values to AnnotationAttributes as well
Issue: SPR-12065
(cherry picked from commit ef51d4d)
2014-08-09 00:19:28 +02:00
Rossen Stoyanchev 96efafef97 Fix documentation issue for user destinations.
Issue: SPR-11992
2014-07-31 17:15:52 -04:00
Rossen Stoyanchev fbf24a927d Update Javadoc (cherry-picked from 162734)
Issue: SPR-12028
2014-07-29 18:07:36 -04:00
Juergen Hoeller f2eea9d911 Polishing
(cherry picked from commit 8f484d3)
2014-07-29 11:50:50 +02:00
Juergen Hoeller cac0683dab Rearranged statement whitespace in Velocity macros
(cherry picked from commit 7bc9660)
2014-07-29 11:47:12 +02:00
Juergen Hoeller 9ad6618207 Polishing 2014-07-28 22:47:22 +02:00
Juergen Hoeller 84a4433898 AbstractTypeHierarchyTraversingFilter leniently ignores non-loadable super classes and interfaces
Issue: SPR-12042
(cherry picked from commit a3163ce)
2014-07-28 22:27:37 +02:00
Juergen Hoeller 44fac40a2f Latest dependency updates (Hibernate Validator 4.3.2, propdeps plugin 0.0.7) 2014-07-28 22:27:28 +02:00
Juergen Hoeller 6e95b2613e Polishing 2014-07-24 18:35:49 +02:00
Arjen Poutsma fca72f6b65 StaxStreamXMLReader ignores significant whitespace
The StaxStreamXMLReader no longer handles all whitespace as ignorable
whitespace.

Issue: SPR-12000
(cherry picked from commit d6950d8)
2014-07-24 17:57:14 +02:00
Juergen Hoeller 0dca31c39b Typo fixes and cleanup of outdated Java 5 references
Issue: SPR-12020
(cherry picked from commit d4fe732)
2014-07-24 17:56:35 +02:00
Juergen Hoeller d45f743248 TypeDescriptor's getResolvableType() and getSource() are @since 4.0
(cherry picked from commit 0ce90f1)
2014-07-24 17:55:39 +02:00
Juergen Hoeller acbd61b87a ConcurrentMapCacheManager recreates caches in case of setAllowNullValues change
Issue: SPR-12026
(cherry picked from commit 7848412)
2014-07-24 17:54:22 +02:00
Juergen Hoeller dcb83c2daf Autowiring rejects self references to a factory method on the same bean as well
Issue: SPR-12018
(cherry picked from commit 496492b)
2014-07-24 17:53:21 +02:00
Juergen Hoeller 5342d92db7 ResourceHttpMessageConverter does not call contentLength() on InputStreamResource
Issue: SPR-12017
(cherry picked from commit f0bcb77)
2014-07-24 17:50:31 +02:00
Juergen Hoeller 7af1e002bd AbstractMessageListenerContainer calls "Session.recover()" in case of rollback attempt on non-transacted Session
Issue: SPR-12015
(cherry picked from commit c082220)
2014-07-24 17:49:34 +02:00
Juergen Hoeller abd5f18e85 AbstractApplicationContext logs initialization exception before trying to cancel refresh attempt
Issue: SPR-12010
(cherry picked from commit 5e2fbe7)
2014-07-24 17:48:08 +02:00
Juergen Hoeller 940ae0c528 ClassUtils.isCacheSafe defensively catches SecurityException (for Google App Engine compatibility)
Issue: SPR-12002
(cherry picked from commit 48fea0b)
2014-07-24 17:46:42 +02:00
Juergen Hoeller 5f77dce1ee SelectedValueComparator defensively handles null values in exhaustiveCompare
Issue: SPR-12001
(cherry picked from commit 980f971)
2014-07-24 17:46:04 +02:00
Juergen Hoeller 0ef17a2f2c NestedIOException can use IOException constructor with cause argument on JDK 6+
(cherry picked from commit c18b6bf)
2014-07-24 17:44:57 +02:00
Juergen Hoeller 452260316e DefaultListableBeanFactory's registerBeanDefinition only calls resetBeanDefinition in case of pre-existing bean definition or pre-existing singleton instance
Issue: SPR-8318
(cherry picked from commit a4968b9)
2014-07-24 17:43:59 +02:00
Stephane Nicoll c0815407bb Revert ea16ce0
The latest build preview of jdk 1.8.0_20 does not exhibit the problem
anymore.

Issue: SPR-11973
2014-07-23 19:43:09 +02:00
Juergen Hoeller 845528a6cb Polishing 2014-07-10 18:18:44 +02:00
Juergen Hoeller ed88155f55 Reverted test for 1.8 bytecode parsing - 4.0.x tests are still on target 1.7
Issue: SPR-11979
2014-07-10 17:45:08 +02:00
Brian Clozel a3a76d8c15 Fix UriComponentsBuilder.fromUriString parsing error
This commit fixes cases where part of the URI was mistaken for the
userinfo when:
* the URI did not contain any path
* the query string contained the "@"

Issue: SPR-11970
(cherry picked from commit a4484bb)
2014-07-10 16:46:33 +02:00
Juergen Hoeller 10a039000b Test ASM5's bytecode parsing of INVOKESPECIAL/STATIC on interfaces
Issue: SPR-11979
(cherry picked from commit 29f6f3d)
2014-07-10 16:44:59 +02:00
Spring Buildmaster 7de42efaf2 Next development version 2014-07-07 20:49:34 -07:00
Phillip Webb 7dcc01e69b Disable processing javac warnings
Set `-Xlint:-processing` to disable annotation processing warnings.
Required when building on JDK 1.8.0_20-b05 due to JDK-8039469.

Issue: SPR-11973
(cherry picked from commit ea16ce0)
2014-07-07 19:22:07 -07:00
Juergen Hoeller adb73d5f35 Remaining polishing 2014-07-08 00:21:17 +02:00
Juergen Hoeller 7eee7d2e30 Polishing
Issue: SPR-8045
2014-07-08 00:04:19 +02:00
Juergen Hoeller d72ee809b7 Polishing
(cherry picked from commit b559f15)
2014-07-07 21:51:01 +02:00
Juergen Hoeller 31a251e44a Polishing 2014-07-07 20:53:26 +02:00
Brian Clozel ce6adfbe35 Remove Jackson dependency from TransportHandler hierarchy
Prior to this change, AbstractHttpReceivingTransportHandler had a direct
dependency on a Jacckson Exception (checking that exception in a catch
clause). This can cause issues for applications that don't have that
dependency.

This commit removes that direct dependency, still logging the
appropriate log messages using a parent exception (IOException) and
reflection.

Issue: SPR-11963
(cherry picked from commit e549103)
2014-07-07 20:39:29 +02:00
Juergen Hoeller 60d3a7f300 RestTemplate accepts getMessageConverters() List on setMessageConverters again
Issue: SPR-11962
(cherry picked from commit 1222ca3)
2014-07-07 20:37:35 +02:00
Juergen Hoeller 6dbb465585 TypedValue implements equals/hashCode based on value and TypeDescriptor
Issue: SPR-11960
(cherry picked from commit a8848cb)
2014-07-07 20:36:53 +02:00
Juergen Hoeller 47de943926 Upgraded to AspectJ 1.8.1 (also declared as recommended user version) and Tomcat 8.0.9 (first stable version)
Issue: SPR-11957
2014-07-05 11:14:34 +02:00
Juergen Hoeller 0164f8691a CachedSessionInvocationHandler includes durable flag in ConsumerCacheKey
Issue: SPR-11956
(cherry picked from commit 6fd0fc7)
2014-07-05 08:56:10 +02:00
Juergen Hoeller 077c624b73 ConstructorResolver's exception message on null factory-bean hints at potential BeanPostProcessor involvement
Issue: SPR-11951
(cherry picked from commit 6c41cc3)
2014-07-04 22:32:10 +02:00
Juergen Hoeller dae81fd5e6 CachedSessionInvocationHandler properly caches createSharedConsumer results
Issue: SPR-11956
(cherry picked from commit 7a7641b)
2014-07-04 22:31:38 +02:00
Juergen Hoeller 837f27851f Jms2MessageProducerInvocationHandler specifically delegates all CompletionListener-based send methods
Issue: SPR-11950
(cherry picked from commit b6a7957)
2014-07-04 16:13:14 +02:00
Juergen Hoeller c3b992c5c4 Jms2MessageProducerInvocationHandler properly delegates to CachedMessageProducer.this
Issue: SPR-11949
(cherry picked from commit 134e5a2)
2014-07-04 00:27:25 +02:00
Juergen Hoeller f8ab4f6980 Reference documentation backports
Issue: SPR-11944
Issue: SPR-11945
2014-07-03 22:40:02 +02:00
Juergen Hoeller 77406eded8 Refined DefaultJpaDialect's InvalidIsolationLevelException message
Issue: SPR-8325
(cherry picked from commit af13310)
2014-07-03 22:34:14 +02:00
Rossen Stoyanchev 977c5ca439 Synchronize request init in AbstractHttpSockJsSession
Although unlikely in practice (but not impossible), the SockJS
integration tests write a message while the request is initializing.
This change adds synchronization around request intiailization
for the SockJS HTTP sesion.

This is a backport of:
https://github.com/spring-projects/spring-framework/commit/59e02e63c427659e701cc371d210faf1a85c1d42

Issue: SPR-11916
2014-07-02 18:28:48 -04:00
Juergen Hoeller ede2150544 Polishing 2014-07-02 17:32:43 +02:00
Juergen Hoeller 07edf11e21 Defensively check for pre-resolved FactoryBean.getObject() results in circular reference scenarios
Issue: SPR-11937
(cherry picked from commit d870b38)
2014-07-02 00:23:32 +02:00
Juergen Hoeller f27b9498be CachedIntrospectionResults uses SoftReference instead of WeakReference for non-cache-safe entries
Issue: SPR-11867
2014-07-02 00:22:24 +02:00
Rossen Stoyanchev e9ecaf6f4a Fix issue with StompSubProtocolHandler initialization
This change ensures that StompSubProtocolHandler is injected with an
ApplicationEventPublisher for both the Java and XML config.

Backport for:
https://github.com/spring-projects/spring-framework/commit/0dddb6f3e19377cb397f0396e85734df2c19c2b6
https://github.com/spring-projects/spring-framework/commit/4372dac002be4dd9be9568fafb442cde5b6d1ada

Issue: SPR-11825
2014-07-01 14:59:51 -04:00
Rossen Stoyanchev 5092414842 Improve SubscriptionRegistry subscription removal
This a backport of:
https://github.com/spring-projects/spring-framework/commit/ce20abde51ac52dde2f318e28004af80cca886fe
https://github.com/spring-projects/spring-framework/commit/083d415fc4d54ce19f7939b3d837f1f1eda5732a

Issue: SPR-11931, SPR-11930
2014-07-01 14:35:22 -04:00
Rossen Stoyanchev 6438209557 Remove JDK 1.7 guards 2014-07-01 14:33:27 -04:00
Juergen Hoeller 7396210d40 Package javadoc cleanup for web.servlet.mvc, removing outdated references
Issue: SPR-11935
(cherry picked from commit ba522e5)
2014-07-01 18:12:42 +02:00
Juergen Hoeller b9935e9fe3 BeanFactoryAnnotationUtils consistently applies bean name fallback when no BeanDefinition present
Issue: SPR-11915
(cherry picked from commit f8b6114)
2014-07-01 18:12:23 +02:00
Juergen Hoeller 86ea3059b6 Polishing 2014-07-01 15:11:36 +02:00
Juergen Hoeller 4384c1ae50 Upgrade to Reactor 1.1.3 2014-07-01 15:10:09 +02:00
Juergen Hoeller 347b7313b8 Dependency updates (as appropriate for the 4.0.x line) 2014-07-01 12:31:47 +02:00
Juergen Hoeller 3fb05017a1 Reference documentation overhaul (backported from master)
Issue: SPR-11853
Issue: SPR-11906
2014-07-01 12:31:16 +02:00
Juergen Hoeller 48f753f368 Polishing (backported from master) 2014-07-01 12:12:42 +02:00
Juergen Hoeller c16032b98a Consistent declaration of private static final logger variables
Issue: SPR-11905
(cherry picked from commit 18131bf)
2014-07-01 12:09:29 +02:00
Juergen Hoeller c32d5592c7 AbstractAutowireCapableBeanFactory's createBean/autowireBean/configureBean use CacheUtils.isCacheSafe to re-enable PropertyDescriptor caching
Issue: SPR-11875
(cherry picked from commit 974bd43)
2014-07-01 12:07:26 +02:00
Juergen Hoeller 5f695a47db Cache Class.getDeclaredMethods() results and avoid pattern matching in isCglibRenamedMethod as far as possible
Issue: SPR-11882
Issue: SPR-11894
2014-07-01 12:06:34 +02:00
Juergen Hoeller 74c878ee0e AnnotationUtils defensively catches and logs unexpected exceptions from retrieval attempts (proceeding like the annotation wasn't there)
Issue: SPR-11874
(cherry picked from commit 2c0c081)
2014-07-01 12:05:38 +02:00
Juergen Hoeller 178d58cc75 ConfigurationClassParser falls back to ASM-based resolution of member classes in case of NoClassDefFoundError
Issue: SPR-11844
(cherry picked from commit 6aa9c40)
2014-07-01 12:02:27 +02:00
Juergen Hoeller 7b38b41bf5 ConfigurationClassPostProcessor skips pre-processed bean definitions now (avoiding side effects in case of multiple CCPPs)
Issue: SPR-11858
(cherry picked from commit b625512)
2014-07-01 12:01:50 +02:00
Juergen Hoeller 6403479902 TypeDescriptor's nested type traversal leniently returns null in case of unresolvable nested type
Issue: SPR-11898
(cherry picked from commit d663580)
2014-07-01 12:00:20 +02:00
Juergen Hoeller 5af1a691bc DefaultAdvisorChainFactory never passes null into ClassFilter, enabling async advisor to work without target class as well
Issue: SPR-11910
(cherry picked from commit a9b650f)
2014-07-01 11:59:43 +02:00
Juergen Hoeller 9f967b1d81 SharedEntityManagerCreator immediately throws TransactionRequiredException on persist, merge, remove etc (as required by JPA spec)
Issue: SPR-11923
(cherry picked from commit 045d735)
2014-07-01 11:59:11 +02:00
Juergen Hoeller e50507206f DefaultSubscriptionRegistry's removeSubscriptionInternal defensively handles non-existing destinations
Issue: SPR-11832
(cherry picked from commit 5a8e470)
2014-07-01 11:58:08 +02:00
Juergen Hoeller c73ac075c4 UriComponentBuilder allows for multiple independent build() calls on same builder instance
Issue: SPR-11885
(cherry picked from commit d239016)
2014-07-01 11:57:45 +02:00
Juergen Hoeller 0bf0901b8f SelectTag consistently checks specified 'multiple' attribute now, never falling back to forceMultiple in case of user-provided value
Issue: SPR-11903
(cherry picked from commit 779ca99)
2014-07-01 11:57:15 +02:00
Juergen Hoeller 7d94b5e853 FrameworkPortlet properly initializes StandardPortletEnvironment's property sources and exposes local PortletRequestAttributes in case of pre-bound ServletRequestAttributes as well
Issue: SPR-11816
Issue: SPR-11295
2014-07-01 11:55:19 +02:00
Juergen Hoeller 8ddbbc2e67 PathMatchingResourcePatternResolver's findPathMatchingResources needs to check for VFS before checking isJarResource
ResourceUtils isFileURL also detects "vfsfile" as a file system protocol (again).

Issue: SPR-11887
2014-07-01 11:54:16 +02:00
Juergen Hoeller 0a34f86333 MBeanExportConfiguration's SpecificPlatform properly calls afterPropertiesSet
Also makes the nested SpecificPlatform enum public for Spring Boot to reuse it.

Issue: SPR-11877
(cherry picked from commit 6f68b03)
2014-07-01 11:52:53 +02:00
Juergen Hoeller a0c86ae455 WebSphereUowTransactionManager exposes SmartTransactionObject
Issue: SPR-11876
(cherry picked from commit 03f3412)
2014-07-01 11:51:33 +02:00
Juergen Hoeller 0761ee99ae Workaround for WFLY-3474 NullPointerException
Prior to this commit, the ServletResponseHttpHeaders.get method
would throw an NPE when used under Wildfly 8.0.0.Final and 8.1.0.Final.
This can be traced to WFLY-3474, which throws an NPE when calling
HttpServletResponse.getHeaders("foo") and that header has not
been defined prior to that.
This would cause NPE being thrown by AbstractSockJsService when
checking for CORS HTTP headers in the server HTTP response.

This commit surrounds that method call in AbstractSockJsService and
guards against this issue.

Issue: SPR-11919
(cherry picked from commit 24cdefb)
2014-07-01 11:51:01 +02:00
Juergen Hoeller 9054f4fb58 HttpHeaders fails getAllow if set to EmptyCollection
Prior to this commit, calls to getAllow would fail is setAllow was set
to an EmptyCollection right before.

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

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

Issue: SPR-11917
(cherry picked from commit 9919a98)
2014-07-01 11:46:53 +02:00
Rossen Stoyanchev 41e78d0f50 Fix failing test 2014-06-29 22:08:25 -04:00
Rossen Stoyanchev 526d5ba253 Fix warnings from sniff task on master 2014-06-29 17:44:43 -04:00
Rossen Stoyanchev 40c203ca71 Minor fix in STOMP broker relay
This is a backport for a change made as part of:
https://github.com/spring-projects/spring-framework/commit/113fd1180a14656a89d6d6639d259c577d70fbc5

Issue: SPR-11884
2014-06-29 16:58:47 -04:00
Rossen Stoyanchev d18fc53148 Avoid multiple invocations of afterConnectionClosed
This change ensures the state of a SockJS session is set to CLOSED
immediately after close is invoked. This avoids duplicate invocations
of afterConnectionClosed in WebSocket transport.

This is a backport of:
https://github.com/spring-projects/spring-framework/commit/3af488a701834f61b89cd84040605a6252962e9c

Issue: SPR-11884
2014-06-29 16:58:13 -04:00
Rossen Stoyanchev 618771d59d Add check for unused WebSocket sessions
Sessions connected to a STOMP endpoint are expected to receive some
client messages. Having received none after successfully connecting
could be an indication of proxy or network issue. This change adds
periodic checks to see if we have not received any messages on a
session which is an indication the session isn't going anywhere
most likely due to a proxy issue (or unreliable network) and close
those sessions.

This is a backport for commit:
https://github.com/spring-projects/spring-framework/commit/a3fa9c979777e554efad0df429041767f05dfdb8

Issue: SPR-11884
2014-06-29 16:58:13 -04:00
Rossen Stoyanchev 87077d3fad Add support for setting removeOnCancelPolicy
This change introduces removeOnCancelPolicy on ThreadPoolTaskScheduler
and ScheduledExecutorFactoryBean and sets it to true for SockJS.
This ensures that cancelled tasks are removed immediately to avoid
the "unbounded retention of cancelled tasks" that is mentioned in
the Javadoc ScheduledThreadPoolExecutor:

"By default, such a cancelled task is not automatically removed from
the work queue until its delay elapses. While this enables further
inspection and monitoring, it may also cause unbounded retention of
cancelled tasks. To avoid this, set setRemoveOnCancelPolicy to true,
which causes tasks to be immediately removed from the work queue at
time of cancellation."

This is a backport for:
https://github.com/spring-projects/spring-framework/commit/7441f2301281049cff7224bf650646490388080e

Issue: SPR-11918
2014-06-29 16:57:58 -04:00
Rossen Stoyanchev c0c3618906 Fix concurrency issues in SockJS session impls
Cherry-picked from:
https://github.com/spring-projects/spring-framework/commit/fcf6ae83285890f2e8e7de77dcc6e633129978e8

Issue: SPR-11916
2014-06-29 15:50:55 -04:00
Spring Buildmaster 0405bb401a Next development version 2014-05-20 06:41:20 -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
567 changed files with 11662 additions and 6671 deletions
+95 -76
View File
@@ -3,34 +3,43 @@ 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.7")
classpath("org.asciidoctor:asciidoctor-gradle-plugin:0.7.0")
classpath("org.springframework.build.gradle:docbook-reference-plugin:0.2.8")
}
}
ext {
moduleProjects = subprojects.findAll {
!it.name.equals('spring-build-src') && !it.name.equals('spring-framework-bom')
}
}
configure(allprojects) { project ->
group = "org.springframework"
version = qualifyVersionIfNecessary(version)
ext.aspectjVersion = "1.7.4"
ext.aspectjVersion = "1.8.2"
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.14.Final"
ext.hibVal4Version = "4.3.2.Final"
ext.hsqldbVersion = "2.3.2"
ext.jackson1Version = "1.9.13"
ext.jackson2Version = "2.3.1"
ext.jackson2Version = "2.3.4"
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.9"
ext.xstreamVersion = "1.4.7"
ext.gradleScriptDir = "${rootProject.projectDir}/gradle"
ext.gradleScriptDir = "${rootProject.projectDir}/gradle"
apply plugin: "propdeps"
apply plugin: "java"
@@ -71,14 +80,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 +100,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 +115,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/",
@@ -149,10 +156,10 @@ configure(subprojects - project(":spring-build-src")) { subproject ->
logging.captureStandardOutput LogLevel.INFO // suppress "## warnings" message
}
task sourcesJar(type: Jar, dependsOn:classes) {
classifier = "sources"
from sourceSets.main.allJava.srcDirs
include "**/*.java", "**/*.aj"
task sourcesJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.allSource
// don't include or exclude anything explicitly by default. See SPR-12085.
}
task javadocJar(type: Jar) {
@@ -279,7 +286,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 +378,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 +404,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.3.RELEASE")
optional("org.projectreactor:reactor-net:1.1.3.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 +425,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 +466,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 +518,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 +535,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 +546,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,19 +571,18 @@ 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")
optional("commons-fileupload:commons-fileupload:1.3.1")
optional("org.apache.httpcomponents:httpclient:4.3.3")
optional("org.apache.httpcomponents:httpasyncclient:4.0.1")
optional("org.apache.httpcomponents:httpclient:4.3.5")
optional("org.apache.httpcomponents:httpasyncclient:4.0.2")
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 +593,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 +613,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 +626,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.3.RELEASE")
testCompile("org.projectreactor:reactor-net:1.1.3.RELEASE")
testCompile("log4j:log4j:1.2.17")
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
}
@@ -643,9 +657,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 +669,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 +696,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 +713,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,8 +763,8 @@ 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.apache.httpcomponents:httpclient:4.3.3")
testCompile("org.hibernate:hibernate-validator:${hibVal4Version}")
testCompile("org.apache.httpcomponents:httpclient:4.3.5")
testCompile("commons-fileupload:commons-fileupload:1.3.1")
testCompile("commons-io:commons-io:1.3")
testCompile("joda-time:joda-time:${jodaVersion}")
@@ -768,9 +783,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 +842,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 +857,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 +881,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,9 +908,9 @@ 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
compile("org.aspectj:aspectjweaver:${aspectjVersion}") // exposing regular AspectJ version to users
ajc("org.aspectj:aspectjtools:${aspectjVersion}")
rt("org.aspectj:aspectjrt:${aspectjVersion}")
compile("org.aspectj:aspectjweaver:${aspectjVersion}")
provided("org.eclipse.persistence:javax.persistence:2.0.0")
optional(project(":spring-aop")) // for @Async support
optional(project(":spring-beans")) // for @Configurable support
@@ -901,7 +920,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 {
@@ -1075,8 +1094,8 @@ configure(rootProject) {
classifier = "schema"
description = "Builds -${classifier} archive containing all " +
"XSDs for deployment at http://springframework.org/schema."
subprojects.each { subproject ->
duplicatesStrategy 'exclude'
moduleProjects.each { subproject ->
def Properties schemas = new Properties();
subproject.sourceSets.main.resources.find {
@@ -1122,7 +1141,7 @@ configure(rootProject) {
into "${baseDir}/schema"
}
subprojects.each { subproject ->
moduleProjects.each { subproject ->
into ("${baseDir}/libs") {
from subproject.jar
if (subproject.tasks.findByPath("sourcesJar")) {
@@ -1175,7 +1194,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"
@@ -21,13 +21,10 @@ import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ProjectDependency;
import org.gradle.api.artifacts.maven.Conf2ScopeMapping
import org.gradle.api.plugins.MavenPlugin
import org.gradle.api.tasks.*
import org.gradle.plugins.ide.eclipse.EclipsePlugin
import org.gradle.plugins.ide.eclipse.model.EclipseClasspath;
import org.gradle.plugins.ide.idea.IdeaPlugin
import org.gradle.api.invocation.*
/**
* Gradle plugin that allows projects to merged together. Primarily developed to
* allow Spring to support multiple incompatible versions of third-party
@@ -76,13 +73,13 @@ class MergePlugin implements Plugin<Project> {
// Hook to perform the actual merge logic
project.afterEvaluate{
if(it.merge.into != null) {
if (it.merge.into != null) {
setup(it)
}
}
// Hook to build runtimeMerge dependencies
if(!attachedProjectsEvaluated) {
if (!attachedProjectsEvaluated) {
project.gradle.projectsEvaluated{
postProcessProjects(it)
}
@@ -102,7 +99,7 @@ class MergePlugin implements Plugin<Project> {
// invoking a task will invoke the task with the same name on 'into' project
["sourcesJar", "jar", "javadocJar", "javadoc", "install", "artifactoryPublish"].each {
def task = project.tasks.findByPath(it)
if(task) {
if (task) {
task.enabled = false
task.dependsOn(project.merge.into.tasks.findByPath(it))
}
@@ -120,7 +117,7 @@ class MergePlugin implements Plugin<Project> {
private void setupMaven(Project project) {
project.configurations.each { configuration ->
Conf2ScopeMapping mapping = project.conf2ScopeMappings.getMapping([configuration])
if(mapping.scope) {
if (mapping.scope) {
Configuration intoConfiguration = project.merge.into.configurations.create(
project.name + "-" + configuration.name)
configuration.excludeRules.each {
@@ -131,7 +128,7 @@ class MergePlugin implements Plugin<Project> {
configuration.dependencies.each {
def intoCompile = project.merge.into.configurations.getByName("compile")
// Protect against changing a compile scope dependency (SPR-10218)
if(!intoCompile.dependencies.contains(it)) {
if (!intoCompile.dependencies.contains(it)) {
intoConfiguration.dependencies.add(it)
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,7 +21,6 @@ import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.ProjectDependency;
/**
* Gradle plugin that automatically updates testCompile dependencies to include
* the test source sets of project dependencies.
@@ -41,11 +40,10 @@ class TestSourceSetDependenciesPlugin implements Plugin<Project> {
}
}
private void collectProjectDependencies(Set<ProjectDependency> projectDependencies,
Project project) {
for(def configurationName in ["compile", "optional", "provided", "testCompile"]) {
private void collectProjectDependencies(Set<ProjectDependency> projectDependencies, Project project) {
for (def configurationName in ["compile", "optional", "provided", "testCompile"]) {
Configuration configuration = project.getConfigurations().findByName(configurationName)
if(configuration) {
if (configuration) {
configuration.dependencies.findAll { it instanceof ProjectDependency }.each {
projectDependencies.add(it)
collectProjectDependencies(projectDependencies, it.dependencyProject)
+1 -1
View File
@@ -1 +1 @@
version=4.0.4.BUILD-SNAPSHOT
version=4.0.7.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
@@ -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.
@@ -240,7 +240,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
setArgumentNamesFromStringArray(tokens);
}
public void setArgumentNamesFromStringArray(String[] args) {
public void setArgumentNamesFromStringArray(String... args) {
this.argumentNames = new String[args.length];
for (int i = 0; i < args.length; i++) {
this.argumentNames[i] = StringUtils.trimWhitespace(args[i]);
@@ -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-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.
@@ -40,24 +40,24 @@ public class AspectJExpressionPointcutAdvisor extends AbstractGenericPointcutAdv
this.pointcut.setExpression(expression);
}
public String getExpression() {
return this.pointcut.getExpression();
}
public void setLocation(String location) {
this.pointcut.setLocation(location);
}
public void setParameterTypes(Class<?>[] types) {
this.pointcut.setParameterTypes(types);
}
public void setParameterNames(String[] names) {
this.pointcut.setParameterNames(names);
}
public String getLocation() {
return this.pointcut.getLocation();
}
public String getExpression() {
return this.pointcut.getExpression();
public void setParameterTypes(Class<?>[] types) {
this.pointcut.setParameterTypes(types);
}
public void setParameterNames(String... names) {
this.pointcut.setParameterNames(names);
}
}
@@ -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;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 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,10 +32,10 @@ public interface AdvisorChainFactory {
* for the given advisor chain configuration.
* @param config the AOP configuration in the form of an Advised object
* @param method the proxied method
* @param targetClass the target class
* @param targetClass the target class (may be {@code null} to indicate a proxy without
* target object, in which case the method's declaring class is the next best option)
* @return List of MethodInterceptors (may also include InterceptorAndDynamicMethodMatchers)
*/
List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, Class<?> targetClass);
List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, Class<?> targetClass);
}
@@ -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-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,19 +50,21 @@ public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializ
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, Class<?> targetClass) {
// This is somewhat tricky... we have to process introductions first,
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
boolean hasIntroductions = hasMatchingIntroductions(config, targetClass);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
for (Advisor advisor : config.getAdvisors()) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) {
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
if (MethodMatchers.matches(mm, method, targetClass, hasIntroductions)) {
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
@@ -78,7 +80,7 @@ public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializ
}
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(targetClass)) {
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
@@ -88,18 +90,19 @@ public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializ
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
/**
* Determine whether the Advisors contain matching introductions.
*/
private static boolean hasMatchingIntroductions(Advised config, Class<?> targetClass) {
private static boolean hasMatchingIntroductions(Advised config, Class<?> actualClass) {
for (int i = 0; i < config.getAdvisors().length; i++) {
Advisor advisor = config.getAdvisors()[i];
if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (ia.getClassFilter().matches(targetClass)) {
if (ia.getClassFilter().matches(actualClass)) {
return true;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -75,7 +75,7 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
*/
/** We use a static Log to avoid serialization issues */
private static Log logger = LogFactory.getLog(JdkDynamicAopProxy.class);
private static final Log logger = LogFactory.getLog(JdkDynamicAopProxy.class);
/** Config used to configure this proxy */
private final AdvisedSupport advised;
@@ -215,8 +215,10 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
} else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,7 +19,6 @@ package org.springframework.aop.framework;
import org.aopalliance.intercept.Interceptor;
import org.springframework.aop.TargetSource;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
@@ -47,9 +46,8 @@ public class ProxyFactory extends ProxyCreatorSupport {
* @param target the target object to be proxied
*/
public ProxyFactory(Object target) {
Assert.notNull(target, "Target object must not be null");
setInterfaces(ClassUtils.getAllInterfaces(target));
setTarget(target);
setInterfaces(ClassUtils.getAllInterfaces(target));
}
/**
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -154,7 +154,7 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
* @see org.aopalliance.aop.Advice
* @see org.springframework.aop.target.SingletonTargetSource
*/
public void setInterceptorNames(String[] interceptorNames) {
public void setInterceptorNames(String... interceptorNames) {
this.interceptorNames = interceptorNames;
}
@@ -205,7 +205,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyConfig
* Ordering is significant: The TargetSource returned from the first matching
* TargetSourceCreator (that is, the first that returns non-null) will be used.
*/
public void setCustomTargetSourceCreators(TargetSourceCreator[] targetSourceCreators) {
public void setCustomTargetSourceCreators(TargetSourceCreator... targetSourceCreators) {
this.customTargetSourceCreators = targetSourceCreators;
}
@@ -216,7 +216,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyConfig
* This is perfectly valid, if "specific" interceptors such as matching
* Advisors are all we want.
*/
public void setInterceptorNames(String[] interceptorNames) {
public void setInterceptorNames(String... interceptorNames) {
this.interceptorNames = interceptorNames;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -60,7 +60,7 @@ public class BeanNameAutoProxyCreator extends AbstractAutoProxyCreator {
* @see org.springframework.beans.factory.FactoryBean
* @see org.springframework.beans.factory.BeanFactory#FACTORY_BEAN_PREFIX
*/
public void setBeanNames(String[] beanNames) {
public void setBeanNames(String... beanNames) {
Assert.notEmpty(beanNames, "'beanNames' must not be empty");
this.beanNames = new ArrayList<String>(beanNames.length);
for (String mappedName : beanNames) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2006 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
* TargetSourceCreator that enforces a LazyInitTargetSource for each bean
* that is defined as "lazy-init". This will lead to a proxy created for
* each of those beans, allowing to fetch a reference to such a bean
* without actually initialized the target bean instance.
* without actually initializing the target bean instance.
*
* <p>To be registered as custom TargetSourceCreator for an auto-proxy creator,
* in combination with custom interceptors for specific beans or for the
@@ -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) {
@@ -258,7 +258,7 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor {
return returnValue;
}
catch (Throwable ex) {
if(stopWatch.isRunning()) {
if (stopWatch.isRunning()) {
stopWatch.stop();
}
exitThroughException = true;
@@ -268,7 +268,7 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor {
}
finally {
if (!exitThroughException) {
if(stopWatch.isRunning()) {
if (stopWatch.isRunning()) {
stopWatch.stop();
}
writeToLog(logger,
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,7 +47,7 @@ public class NameMatchMethodPointcut extends StaticMethodMatcherPointcut impleme
* @see #setMappedNames
*/
public void setMappedName(String mappedName) {
setMappedNames(new String[] {mappedName});
setMappedNames(mappedName);
}
/**
@@ -55,7 +55,7 @@ public class NameMatchMethodPointcut extends StaticMethodMatcherPointcut impleme
* Matching will be the union of all these; if any match,
* the pointcut matches.
*/
public void setMappedNames(String[] mappedNames) {
public void setMappedNames(String... mappedNames) {
this.mappedNames = new LinkedList<String>();
if (mappedNames != null) {
this.mappedNames.addAll(Arrays.asList(mappedNames));
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -68,7 +68,7 @@ public class NameMatchMethodPointcutAdvisor extends AbstractGenericPointcutAdvis
* the pointcut matches.
* @see NameMatchMethodPointcut#setMappedNames
*/
public void setMappedNames(String[] mappedNames) {
public void setMappedNames(String... mappedNames) {
this.pointcut.setMappedNames(mappedNames);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -98,7 +98,7 @@ public class RegexpMethodPointcutAdvisor extends AbstractGenericPointcutAdvisor
* @see #setPatterns
*/
public void setPattern(String pattern) {
setPatterns(new String[] {pattern});
setPatterns(pattern);
}
/**
@@ -108,7 +108,7 @@ public class RegexpMethodPointcutAdvisor extends AbstractGenericPointcutAdvisor
* patterns matches, the pointcut matches.
* @see AbstractRegexpMethodPointcut#setPatterns
*/
public void setPatterns(String[] patterns) {
public void setPatterns(String... patterns) {
this.patterns = patterns;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,7 +24,6 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.aop.TargetSource;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
/**
@@ -48,8 +47,7 @@ import org.springframework.util.ObjectUtils;
* @see ThreadLocalTargetSource
* @see CommonsPoolTargetSource
*/
public abstract class AbstractBeanFactoryBasedTargetSource
implements TargetSource, BeanFactoryAware, Serializable {
public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSource, BeanFactoryAware, Serializable {
/** use serialVersionUID from Spring 1.2.7 for interoperability */
private static final long serialVersionUID = -4721607536018568393L;
@@ -108,7 +106,7 @@ public abstract class AbstractBeanFactoryBasedTargetSource
@Override
public void setBeanFactory(BeanFactory beanFactory) {
if (this.targetBeanName == null) {
throw new IllegalStateException("Property'targetBeanName' is required");
throw new IllegalStateException("Property 'targetBeanName' is required");
}
this.beanFactory = beanFactory;
}
@@ -185,8 +183,7 @@ public abstract class AbstractBeanFactoryBasedTargetSource
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(ClassUtils.getShortName(getClass()));
StringBuilder sb = new StringBuilder(getClass().getSimpleName());
sb.append(" for target bean '").append(this.targetBeanName).append("'");
if (this.targetClass != null) {
sb.append(" of type [").append(this.targetClass.getName()).append("]");
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,26 +27,18 @@ import org.aspectj.lang.annotation.control.CodeGenerationHint;
* @since 2.5.2
*/
public abstract aspect AbstractDependencyInjectionAspect {
/**
* Select construction join points for objects to inject dependencies
*/
public abstract pointcut beanConstruction(Object bean);
private pointcut preConstructionCondition() :
leastSpecificSuperTypeConstruction() && preConstructionConfiguration();
private pointcut postConstructionCondition() :
mostSpecificSubTypeConstruction() && !preConstructionConfiguration();
/**
* Select deserialization join points for objects to inject dependencies
* Select least specific super type that is marked for DI
* (so that injection occurs only once with pre-construction injection).
*/
public abstract pointcut beanDeserialization(Object bean);
/**
* Select join points in a configurable bean
*/
public abstract pointcut inConfigurableBean();
/**
* Select join points in beans to be configured prior to construction?
* By default, use post-construction injection matching the default in the Configurable annotation.
*/
public pointcut preConstructionConfiguration() : if(false);
public abstract pointcut leastSpecificSuperTypeConstruction();
/**
* Select the most-specific initialization join point
@@ -54,24 +46,29 @@ public abstract aspect AbstractDependencyInjectionAspect {
*/
@CodeGenerationHint(ifNameSuffix="6f1")
public pointcut mostSpecificSubTypeConstruction() :
if(thisJoinPoint.getSignature().getDeclaringType() == thisJoinPoint.getThis().getClass());
if (thisJoinPoint.getSignature().getDeclaringType() == thisJoinPoint.getThis().getClass());
/**
* Select least specific super type that is marked for DI (so that injection occurs only once with pre-construction inejection
* Select join points in beans to be configured prior to construction?
* By default, use post-construction injection matching the default in the Configurable annotation.
*/
public abstract pointcut leastSpecificSuperTypeConstruction();
public pointcut preConstructionConfiguration() : if (false);
/**
* Configure the bean
* Select construction join points for objects to inject dependencies.
*/
public abstract void configureBean(Object bean);
public abstract pointcut beanConstruction(Object bean);
/**
* Select deserialization join points for objects to inject dependencies.
*/
public abstract pointcut beanDeserialization(Object bean);
private pointcut preConstructionCondition() :
leastSpecificSuperTypeConstruction() && preConstructionConfiguration();
/**
* Select join points in a configurable bean.
*/
public abstract pointcut inConfigurableBean();
private pointcut postConstructionCondition() :
mostSpecificSubTypeConstruction() && !preConstructionConfiguration();
/**
* Pre-construction configuration.
@@ -100,4 +97,10 @@ public abstract aspect AbstractDependencyInjectionAspect {
configureBean(bean);
}
/**
* Configure the given bean.
*/
public abstract void configureBean(Object bean);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,49 +20,48 @@ import java.io.ObjectStreamException;
import java.io.Serializable;
/**
* An aspect that injects dependency into any object whose type implements the {@link ConfigurableObject} interface.
* <p>
* This aspect supports injecting into domain objects when they are created for the first time as well as
* upon deserialization. Subaspects need to simply provide definition for the configureBean() method. This
* method may be implemented without relying on Spring container if so desired.
* </p>
* <p>
* There are two cases that needs to be handled:
* An aspect that injects dependency into any object whose type implements the
* {@link ConfigurableObject} interface.
*
* <p>This aspect supports injecting into domain objects when they are created
* for the first time as well as upon deserialization. Subaspects need to simply
* provide definition for the configureBean() method. This method may be
* implemented without relying on Spring container if so desired.
*
* <p>There are two cases that needs to be handled:
* <ol>
* <li>Normal object creation via the '{@code new}' operator: this is
* taken care of by advising {@code initialization()} join points.</li>
* <li>Object creation through deserialization: since no constructor is
* invoked during deserialization, the aspect needs to advise a method that a
* deserialization mechanism is going to invoke. Ideally, we should not
* require user classes to implement any specific method. This implies that
* we need to <i>introduce</i> the chosen method. We should also handle the cases
* where the chosen method is already implemented in classes (in which case,
* the user's implementation for that method should take precedence over the
* introduced implementation). There are a few choices for the chosen method:
* <ul>
* <li>readObject(ObjectOutputStream): Java requires that the method must be
* {@code private}</p>. Since aspects cannot introduce a private member,
* while preserving its name, this option is ruled out.</li>
* <li>readResolve(): Java doesn't pose any restriction on an access specifier.
* Problem solved! There is one (minor) limitation of this approach in
* that if a user class already has this method, that method must be
* {@code public}. However, this shouldn't be a big burden, since
* use cases that need classes to implement readResolve() (custom enums,
* for example) are unlikely to be marked as &#64;Configurable, and
* in any case asking to make that method {@code public} should not
* pose any undue burden.</li>
* </ul>
* The minor collaboration needed by user classes (i.e., that the
* implementation of {@code readResolve()}, if any, must be
* {@code public}) can be lifted as well if we were to use an
* experimental feature in AspectJ - the {@code hasmethod()} PCD.</li>
* <li>Normal object creation via the '{@code new}' operator: this is
* taken care of by advising {@code initialization()} join points.</li>
* <li>Object creation through deserialization: since no constructor is
* invoked during deserialization, the aspect needs to advise a method that a
* deserialization mechanism is going to invoke. Ideally, we should not
* require user classes to implement any specific method. This implies that
* we need to <i>introduce</i> the chosen method. We should also handle the cases
* where the chosen method is already implemented in classes (in which case,
* the user's implementation for that method should take precedence over the
* introduced implementation). There are a few choices for the chosen method:
* <ul>
* <li>readObject(ObjectOutputStream): Java requires that the method must be
* {@code private}</p>. Since aspects cannot introduce a private member,
* while preserving its name, this option is ruled out.</li>
* <li>readResolve(): Java doesn't pose any restriction on an access specifier.
* Problem solved! There is one (minor) limitation of this approach in
* that if a user class already has this method, that method must be
* {@code public}. However, this shouldn't be a big burden, since
* use cases that need classes to implement readResolve() (custom enums,
* for example) are unlikely to be marked as &#64;Configurable, and
* in any case asking to make that method {@code public} should not
* pose any undue burden.</li>
* </ul>
* The minor collaboration needed by user classes (i.e., that the implementation of
* {@code readResolve()}, if any, must be {@code public}) can be lifted as well if we
* were to use an experimental feature in AspectJ - the {@code hasmethod()} PCD.</li>
* </ol>
* <p>
* While having type implement the {@link ConfigurableObject} interface is certainly a valid choice, an alternative
* is to use a 'declare parents' statement another aspect (a subaspect of this aspect would be a logical choice)
* that declares the classes that need to be configured by supplying the {@link ConfigurableObject} interface.
* </p>
*
* <p>While having type implement the {@link ConfigurableObject} interface is certainly
* a valid choice, an alternative is to use a 'declare parents' statement another aspect
* (a subaspect of this aspect would be a logical choice) that declares the classes that
* need to be configured by supplying the {@link ConfigurableObject} interface.
*
* @author Ramnivas Laddad
* @since 2.5.2
@@ -72,35 +71,33 @@ public abstract aspect AbstractInterfaceDrivenDependencyInjectionAspect extends
* Select initialization join point as object construction
*/
public pointcut beanConstruction(Object bean) :
initialization(ConfigurableObject+.new(..)) && this(bean);
initialization(ConfigurableObject+.new(..)) && this(bean);
/**
* Select deserialization join point made available through ITDs for ConfigurableDeserializationSupport
*/
public pointcut beanDeserialization(Object bean) :
execution(Object ConfigurableDeserializationSupport+.readResolve()) &&
this(bean);
execution(Object ConfigurableDeserializationSupport+.readResolve()) && this(bean);
public pointcut leastSpecificSuperTypeConstruction() : initialization(ConfigurableObject.new(..));
// Implementation to support re-injecting dependencies once an object is deserialized
/**
* Declare any class implementing Serializable and ConfigurableObject as also implementing
* ConfigurableDeserializationSupport. This allows us to introduce the readResolve()
* ConfigurableDeserializationSupport. This allows us to introduce the {@code readResolve()}
* method and select it with the beanDeserialization() pointcut.
*
* <p>Here is an improved version that uses the hasmethod() pointcut and lifts
* even the minor requirement on user classes:
*
* <pre class="code">declare parents: ConfigurableObject+ Serializable+
* && !hasmethod(Object readResolve() throws ObjectStreamException)
* implements ConfigurableDeserializationSupport;
* <pre class="code">
* declare parents: ConfigurableObject+ Serializable+
* && !hasmethod(Object readResolve() throws ObjectStreamException)
* implements ConfigurableDeserializationSupport;
* </pre>
*/
declare parents:
ConfigurableObject+ && Serializable+ implements ConfigurableDeserializationSupport;
declare parents: ConfigurableObject+ && Serializable+ implements ConfigurableDeserializationSupport;
/**
* A marker interface to which the {@code readResolve()} is introduced.
@@ -111,7 +108,6 @@ public abstract aspect AbstractInterfaceDrivenDependencyInjectionAspect extends
/**
* Introduce the {@code readResolve()} method so that we can advise its
* execution to configure the object.
*
* <p>Note if a method with the same signature already exists in a
* {@code Serializable} class of ConfigurableObject type,
* that implementation will take precedence (a good thing, since we are
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@ package org.springframework.beans.factory.aspectj;
import java.io.Serializable;
import org.aspectj.lang.annotation.control.CodeGenerationHint;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.DisposableBean;
@@ -44,48 +44,47 @@ import org.springframework.beans.factory.wiring.BeanConfigurerSupport;
* @see org.springframework.beans.factory.annotation.Configurable
* @see org.springframework.beans.factory.annotation.AnnotationBeanWiringInfoResolver
*/
public aspect AnnotationBeanConfigurerAspect
extends AbstractInterfaceDrivenDependencyInjectionAspect
public aspect AnnotationBeanConfigurerAspect extends AbstractInterfaceDrivenDependencyInjectionAspect
implements BeanFactoryAware, InitializingBean, DisposableBean {
private BeanConfigurerSupport beanConfigurerSupport = new BeanConfigurerSupport();
public void setBeanFactory(BeanFactory beanFactory) {
this.beanConfigurerSupport.setBeanWiringInfoResolver(new AnnotationBeanWiringInfoResolver());
this.beanConfigurerSupport.setBeanFactory(beanFactory);
}
public void afterPropertiesSet() throws Exception {
this.beanConfigurerSupport.afterPropertiesSet();
}
public void configureBean(Object bean) {
this.beanConfigurerSupport.configureBean(bean);
}
public void destroy() throws Exception {
this.beanConfigurerSupport.destroy();
}
public pointcut inConfigurableBean() : @this(Configurable);
public pointcut preConstructionConfiguration() : preConstructionConfigurationSupport(*);
declare parents: @Configurable * implements ConfigurableObject;
public void configureBean(Object bean) {
beanConfigurerSupport.configureBean(bean);
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
beanConfigurerSupport.setBeanFactory(beanFactory);
beanConfigurerSupport.setBeanWiringInfoResolver(new AnnotationBeanWiringInfoResolver());
}
public void afterPropertiesSet() throws Exception {
beanConfigurerSupport.afterPropertiesSet();
}
public void destroy() throws Exception {
beanConfigurerSupport.destroy();
}
/*
* An intermediary to match preConstructionConfiguration signature (that doesn't expose the annotation object)
*/
@CodeGenerationHint(ifNameSuffix="bb0")
private pointcut preConstructionConfigurationSupport(Configurable c) : @this(c) && if(c.preConstruction());
private pointcut preConstructionConfigurationSupport(Configurable c) : @this(c) && if (c.preConstruction());
declare parents: @Configurable * implements ConfigurableObject;
/*
* This declaration shouldn't be needed,
* except for an AspectJ bug (https://bugs.eclipse.org/bugs/show_bug.cgi?id=214559)
*/
declare parents: @Configurable Serializable+
implements ConfigurableDeserializationSupport;
declare parents: @Configurable Serializable+ implements ConfigurableDeserializationSupport;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@ import org.springframework.context.annotation.Role;
@Configuration
public class AspectJCachingConfiguration extends AbstractCachingConfiguration {
@Bean(name=AnnotationConfigUtils.CACHE_ASPECT_BEAN_NAME)
@Bean(name = AnnotationConfigUtils.CACHE_ASPECT_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public AnnotationCacheAspect cacheAspect() {
AnnotationCacheAspect cacheAspect = AnnotationCacheAspect.aspectOf();
@@ -47,4 +47,5 @@ public class AspectJCachingConfiguration extends AbstractCachingConfiguration {
}
return cacheAspect;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,7 +37,7 @@ import org.springframework.scheduling.annotation.EnableAsync;
@Configuration
public class AspectJAsyncConfiguration extends AbstractAsyncConfiguration {
@Bean(name=AnnotationConfigUtils.ASYNC_EXECUTION_ASPECT_BEAN_NAME)
@Bean(name = AnnotationConfigUtils.ASYNC_EXECUTION_ASPECT_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public AnnotationAsyncExecutionAspect asyncAdvisor() {
AnnotationAsyncExecutionAspect asyncAspect = AnnotationAsyncExecutionAspect.aspectOf();
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,7 +37,7 @@ import org.springframework.transaction.config.TransactionManagementConfigUtils;
@Configuration
public class AspectJTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
@Bean(name=TransactionManagementConfigUtils.TRANSACTION_ASPECT_BEAN_NAME)
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ASPECT_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public AnnotationTransactionAspect transactionAspect() {
AnnotationTransactionAspect txAspect = AnnotationTransactionAspect.aspectOf();
@@ -46,4 +46,5 @@ public class AspectJTransactionManagementConfiguration extends AbstractTransacti
}
return txAspect;
}
}
@@ -398,7 +398,8 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
if (pd.getReadMethod() != null || pd.getWriteMethod() != null) {
return TypeDescriptor.nested(property(pd), tokens.keys.length);
}
} else {
}
else {
if (pd.getReadMethod() != null || pd.getWriteMethod() != null) {
return new TypeDescriptor(property(pd));
}
@@ -21,7 +21,7 @@ import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.lang.ref.SoftReference;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -196,7 +196,7 @@ public class CachedIntrospectionResults {
}
results = new CachedIntrospectionResults(beanClass);
synchronized (classCache) {
classCache.put(beanClass, new WeakReference<CachedIntrospectionResults>(results));
classCache.put(beanClass, new SoftReference<CachedIntrospectionResults>(results));
}
}
}
@@ -115,7 +115,7 @@ class ExtendedBeanInfo implements BeanInfo {
matches.add(method);
}
}
// sort non-void returning write methods to guard against the ill effects of
// Sort non-void returning write methods to guard against the ill effects of
// non-deterministic sorting of methods returned from Class#getDeclaredMethods
// under JDK 7. See http://bugs.sun.com/view_bug.do?bug_id=7023180
Collections.sort(matches, new Comparator<Method>() {
@@ -437,24 +437,24 @@ class SimpleIndexedPropertyDescriptor extends IndexedPropertyDescriptor {
* See java.beans.IndexedPropertyDescriptor#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (obj != null && obj instanceof IndexedPropertyDescriptor) {
IndexedPropertyDescriptor other = (IndexedPropertyDescriptor) obj;
if (!compareMethods(getIndexedReadMethod(), other.getIndexedReadMethod())) {
return false;
}
if (!compareMethods(getIndexedWriteMethod(), other.getIndexedWriteMethod())) {
return false;
}
if (getIndexedPropertyType() != other.getIndexedPropertyType()) {
return false;
}
return PropertyDescriptorUtils.equals(this, obj);
if (!(other instanceof IndexedPropertyDescriptor)) {
return false;
}
return false;
IndexedPropertyDescriptor otherPd = (IndexedPropertyDescriptor) other;
if (!compareMethods(getIndexedReadMethod(), otherPd.getIndexedReadMethod())) {
return false;
}
if (!compareMethods(getIndexedWriteMethod(), otherPd.getIndexedWriteMethod())) {
return false;
}
if (getIndexedPropertyType() != otherPd.getIndexedPropertyType()) {
return false;
}
return PropertyDescriptorUtils.equals(this, other);
}
@Override
@@ -595,25 +595,23 @@ class PropertyDescriptorUtils {
* editor and flags are equivalent.
* @see PropertyDescriptor#equals(Object)
*/
public static boolean equals(PropertyDescriptor pd1, Object obj) {
if (pd1 == obj) {
public static boolean equals(PropertyDescriptor pd, Object other) {
if (pd == other) {
return true;
}
if (obj != null && obj instanceof PropertyDescriptor) {
PropertyDescriptor pd2 = (PropertyDescriptor) obj;
if (!compareMethods(pd1.getReadMethod(), pd2.getReadMethod())) {
return false;
}
if (!compareMethods(pd1.getWriteMethod(), pd2.getWriteMethod())) {
return false;
}
if (pd1.getPropertyType() == pd2.getPropertyType() &&
pd1.getPropertyEditorClass() == pd2.getPropertyEditorClass() &&
pd1.isBound() == pd2.isBound() && pd1.isConstrained() == pd2.isConstrained()) {
return true;
}
if (!(other instanceof PropertyDescriptor)) {
return false;
}
return false;
PropertyDescriptor otherPd = (PropertyDescriptor) other;
if (!compareMethods(pd.getReadMethod(), otherPd.getReadMethod())) {
return false;
}
if (!compareMethods(pd.getWriteMethod(), otherPd.getWriteMethod())) {
return false;
}
return (pd.getPropertyType() == otherPd.getPropertyType() &&
pd.getPropertyEditorClass() == otherPd.getPropertyEditorClass() &&
pd.isBound() == otherPd.isBound() && pd.isConstrained() == otherPd.isConstrained());
}
/*
@@ -1,5 +1,5 @@
/*
* Copyright 2002-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-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.
@@ -172,7 +172,8 @@ final class PropertyMatches {
char t_j = s2.charAt(j - 1);
if (s_i == t_j) {
cost = 0;
} else {
}
else {
cost = 1;
}
d[i][j] = Math.min(Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1),
@@ -1,5 +1,5 @@
/*
* Copyright 2002-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,19 +289,19 @@ class TypeConverterDelegate {
if (index > - 1) {
String enumType = trimmedValue.substring(0, index);
String fieldName = trimmedValue.substring(index + 1);
ClassLoader loader = this.targetObject.getClass().getClassLoader();
ClassLoader cl = this.targetObject.getClass().getClassLoader();
try {
Class<?> enumValueType = loader.loadClass(enumType);
Class<?> enumValueType = ClassUtils.forName(enumType, cl);
Field enumField = enumValueType.getField(fieldName);
convertedValue = enumField.get(null);
}
catch (ClassNotFoundException ex) {
if(logger.isTraceEnabled()) {
logger.trace("Enum class [" + enumType + "] cannot be loaded from [" + loader + "]", ex);
if (logger.isTraceEnabled()) {
logger.trace("Enum class [" + enumType + "] cannot be loaded", ex);
}
}
catch (Throwable ex) {
if(logger.isTraceEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Field [" + fieldName + "] isn't an enum value for type [" + enumType + "]", ex);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -170,8 +170,7 @@ public interface BeanFactory {
* <p>Allows for specifying explicit constructor arguments / factory method arguments,
* overriding the specified default arguments (if any) in the bean definition.
* @param name the name of the bean to retrieve
* @param args arguments to use if creating a prototype using explicit arguments to a
* static factory method. It is invalid to use a non-null args value in any other case.
* @param args arguments to use if creating a prototype using explicit arguments
* @return an instance of the bean
* @throws NoSuchBeanDefinitionException if there is no such bean definition
* @throws BeanDefinitionStoreException if arguments have been given but
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-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) {
@@ -239,7 +239,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
AnnotationAttributes annotation = findAutowiredAnnotation(candidate);
if (annotation != null) {
if (requiredConstructor != null) {
throw new BeanCreationException("Invalid autowire-marked constructor: " + candidate +
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructor: " + candidate +
". Found another constructor with 'required' Autowired annotation: " +
requiredConstructor);
}
@@ -250,10 +251,10 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
boolean required = determineRequiredStatus(annotation);
if (required) {
if (!candidates.isEmpty()) {
throw new BeanCreationException(
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructors: " + candidates +
". Found another constructor with 'required' Autowired annotation: " +
requiredConstructor);
candidate);
}
requiredConstructor = candidate;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@ import org.springframework.util.ObjectUtils;
* Spring's {@link Qualifier @Qualifier} annotation.
*
* @author Chris Beams
* @author Juergen Hoeller
* @since 3.1.2
* @see BeanFactoryUtils
*/
@@ -90,9 +91,13 @@ public class BeanFactoryAnnotationUtils {
if (matchingBean != null) {
return matchingBean;
}
else if (bf.containsBean(qualifier)) {
// Fallback: target bean at least found by bean name - probably a manually registered singleton.
return bf.getBean(qualifier, beanType);
}
else {
throw new NoSuchBeanDefinitionException(qualifier, "No matching " + beanType.getSimpleName() +
" bean found for qualifier '" + qualifier + "' - neither qualifier " + "match nor bean name match!");
" bean found for qualifier '" + qualifier + "' - neither qualifier match nor bean name match!");
}
}
@@ -128,7 +133,7 @@ public class BeanFactoryAnnotationUtils {
}
}
catch (NoSuchBeanDefinitionException ex) {
// ignore - can't compare qualifiers for a manually registered singleton object
// Ignore - can't compare qualifiers for a manually registered singleton object
}
}
return false;
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -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.
@@ -286,7 +286,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
// Use prototype bean definition, to avoid registering bean as dependent bean.
RootBeanDefinition bd = new RootBeanDefinition(beanClass);
bd.setScope(SCOPE_PROTOTYPE);
bd.allowCaching = false;
bd.allowCaching = ClassUtils.isCacheSafe(beanClass, getBeanClassLoader());
return (T) createBean(beanClass.getName(), bd, null);
}
@@ -295,7 +295,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
// Use non-singleton bean definition, to avoid registering bean as dependent bean.
RootBeanDefinition bd = new RootBeanDefinition(ClassUtils.getUserClass(existingBean));
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
bd.allowCaching = false;
bd.allowCaching = ClassUtils.isCacheSafe(bd.getBeanClass(), getBeanClassLoader());
BeanWrapper bw = new BeanWrapperImpl(existingBean);
initBeanWrapper(bw);
populateBean(bd.getBeanClass().getName(), bd, bw);
@@ -315,7 +315,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
bd = new RootBeanDefinition(mbd);
}
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
bd.allowCaching = false;
bd.allowCaching = ClassUtils.isCacheSafe(ClassUtils.getUserClass(existingBean), getBeanClassLoader());
}
BeanWrapper bw = new BeanWrapperImpl(existingBean);
initBeanWrapper(bw);
@@ -832,7 +832,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
if (bw != null) {
return (FactoryBean<?>) bw.getWrappedInstance();
}
if (isSingletonCurrentlyInCreation(beanName)) {
if (isSingletonCurrentlyInCreation(beanName) ||
(mbd.getFactoryBeanName() != null && isSingletonCurrentlyInCreation(mbd.getFactoryBeanName()))) {
return null;
}
Object instance = null;
@@ -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.
@@ -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.
@@ -124,7 +124,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
/** Resolution strategy for expressions in bean definition values */
private BeanExpressionResolver beanExpressionResolver;
/** Spring 3.0 ConversionService to use instead of PropertyEditors */
/** Spring ConversionService to use instead of PropertyEditors */
private ConversionService conversionService;
/** Custom PropertyEditorRegistrars to apply to the beans of this factory */
@@ -160,9 +160,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
private final Map<String, RootBeanDefinition> mergedBeanDefinitions =
new ConcurrentHashMap<String, RootBeanDefinition>(64);
/**
* Names of beans that have already been created at least once
*/
/** Names of beans that have already been created at least once */
private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(64));
/** Names of beans that are currently in creation */
@@ -287,8 +285,8 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
if (isDependent(beanName, dependsOnBean)) {
throw new BeanCreationException("Circular depends-on relationship between '" +
beanName + "' and '" + dependsOnBean + "'");
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
}
registerDependentBean(dependsOnBean, beanName);
getBean(dependsOnBean);
@@ -1276,7 +1274,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
// Check validity of the usage of the args parameter. This can
// only be used for prototypes constructed via a factory method.
if (args != null && !mbd.isPrototype()) {
throw new BeanDefinitionStoreException(
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"Can only specify arguments for the getBean method when referring to a prototype bean definition");
}
}
@@ -1627,8 +1625,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
* instantiation within this class is performed by this method.
* @param beanName the name of the bean
* @param mbd the merged bean definition for the bean
* @param args arguments to use if creating a prototype using explicit arguments to a
* static factory method. This parameter must be {@code null} except in this case.
* @param args arguments to use if creating a prototype using explicit arguments
* @return a new instance of the bean
* @throws BeanCreationException if the bean could not be created
*/
@@ -25,7 +25,6 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanInstantiationException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.cglib.core.SpringNamingPolicy;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.CallbackFilter;
@@ -89,14 +88,13 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
*/
private static class CglibSubclassCreator {
private static final Class<?>[] CALLBACK_TYPES = new Class<?>[] { NoOp.class,
LookupOverrideMethodInterceptor.class, ReplaceOverrideMethodInterceptor.class };
private static final Class<?>[] CALLBACK_TYPES = new Class<?>[]
{NoOp.class, LookupOverrideMethodInterceptor.class, ReplaceOverrideMethodInterceptor.class};
private final RootBeanDefinition beanDefinition;
private final BeanFactory owner;
CglibSubclassCreator(RootBeanDefinition beanDefinition, BeanFactory owner) {
this.beanDefinition = beanDefinition;
this.owner = owner;
@@ -113,7 +111,6 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
*/
Object instantiate(Constructor<?> ctor, Object[] args) {
Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
Object instance;
if (ctor == null) {
instance = BeanUtils.instantiate(subclass);
@@ -123,19 +120,17 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
instance = enhancedSubclassConstructor.newInstance(args);
}
catch (Exception e) {
catch (Exception ex) {
throw new BeanInstantiationException(this.beanDefinition.getBeanClass(), String.format(
"Failed to invoke construcor for CGLIB enhanced subclass [%s]", subclass.getName()), e);
"Failed to invoke constructor for CGLIB enhanced subclass [%s]", subclass.getName()), ex);
}
}
// SPR-10785: set callbacks directly on the instance instead of in the
// enhanced class (via the Enhancer) in order to avoid memory leaks.
Factory factory = (Factory) instance;
factory.setCallbacks(new Callback[] { NoOp.INSTANCE,//
new LookupOverrideMethodInterceptor(beanDefinition, owner),//
new ReplaceOverrideMethodInterceptor(beanDefinition, owner) });
factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
return instance;
}
@@ -153,6 +148,7 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
}
}
/**
* Class providing hashCode and equals methods required by CGLIB to
* ensure that CGLIB doesn't generate a distinct class per bean.
@@ -162,7 +158,6 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
private final RootBeanDefinition beanDefinition;
CglibIdentitySupport(RootBeanDefinition beanDefinition) {
this.beanDefinition = beanDefinition;
}
@@ -173,8 +168,8 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
@Override
public boolean equals(Object other) {
return other.getClass().equals(this.getClass())
&& ((CglibIdentitySupport) other).getBeanDefinition().equals(this.getBeanDefinition());
return (getClass().equals(other.getClass()) &&
this.beanDefinition.equals(((CglibIdentitySupport) other).beanDefinition));
}
@Override
@@ -183,6 +178,7 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
}
}
/**
* CGLIB callback for filtering method interception behavior.
*/
@@ -190,7 +186,6 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
private static final Log logger = LogFactory.getLog(MethodOverrideCallbackFilter.class);
MethodOverrideCallbackFilter(RootBeanDefinition beanDefinition) {
super(beanDefinition);
}
@@ -210,11 +205,12 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
else if (methodOverride instanceof ReplaceOverride) {
return METHOD_REPLACER;
}
throw new UnsupportedOperationException("Unexpected MethodOverride subclass: "
+ methodOverride.getClass().getName());
throw new UnsupportedOperationException("Unexpected MethodOverride subclass: " +
methodOverride.getClass().getName());
}
}
/**
* CGLIB MethodInterceptor to override methods, replacing them with an
* implementation that returns a bean looked up in the container.
@@ -223,7 +219,6 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
private final BeanFactory owner;
LookupOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) {
super(beanDefinition);
this.owner = owner;
@@ -245,7 +240,6 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
private final BeanFactory owner;
ReplaceOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) {
super(beanDefinition);
this.owner = owner;
@@ -255,7 +249,7 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
ReplaceOverride ro = (ReplaceOverride) getBeanDefinition().getMethodOverrides().getOverride(method);
// TODO could cache if a singleton for minor performance optimization
MethodReplacer mr = owner.getBean(ro.getMethodReplacerBeanName(), MethodReplacer.class);
MethodReplacer mr = this.owner.getBean(ro.getMethodReplacerBeanName(), MethodReplacer.class);
return mr.reimplement(obj, method, args);
}
}
@@ -370,7 +370,7 @@ class ConstructorResolver {
factoryBean = this.beanFactory.getBean(factoryBeanName);
if (factoryBean == null) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"factory-bean '" + factoryBeanName + "' returned null");
"factory-bean '" + factoryBeanName + "' (or a BeanPostProcessor involved) returned null");
}
factoryClass = factoryBean.getClass();
isStatic = false;
@@ -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.
@@ -284,7 +284,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
if (beanNames.length > 1) {
ArrayList<String> autowireCandidates = new ArrayList<String>();
for (String beanName : beanNames) {
if (getBeanDefinition(beanName).isAutowireCandidate()) {
if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
autowireCandidates.add(beanName);
}
}
@@ -671,12 +671,15 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
if (this.logger.isDebugEnabled()) {
this.logger.debug("Pre-instantiating singletons in " + this);
}
List<String> beanNames;
synchronized (this.beanDefinitionMap) {
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
beanNames = new ArrayList<String>(this.beanDefinitionNames);
}
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
@@ -728,8 +731,10 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
}
BeanDefinition oldBeanDefinition;
synchronized (this.beanDefinitionMap) {
BeanDefinition oldBeanDefinition = this.beanDefinitionMap.get(beanName);
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!this.allowBeanDefinitionOverriding) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
@@ -758,7 +763,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
this.beanDefinitionMap.put(beanName, beanDefinition);
}
resetBeanDefinition(beanName);
if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
@Override
@@ -794,9 +801,6 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
// (e.g. the default StaticMessageSource in a StaticApplicationContext).
destroySingleton(beanName);
// Remove any assumptions about by-type mappings.
clearByTypeCache();
// Reset all bean definitions that have the given bean as parent (recursively).
for (String bdName : this.beanDefinitionNames) {
if (!beanName.equals(bdName)) {
@@ -1013,7 +1017,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
}
for (String candidateName : candidateNames) {
if (!candidateName.equals(beanName) && isAutowireCandidate(candidateName, descriptor)) {
if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, descriptor)) {
result.put(candidateName, getBean(candidateName));
}
}
@@ -1091,6 +1095,17 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
(candidateName.equals(beanName) || ObjectUtils.containsElement(getAliases(beanName), candidateName)));
}
/**
* Determine whether the given beanName/candidateName pair indicates a self reference,
* i.e. whether the candidate points back to the original bean or to a factory method
* on the original bean.
*/
private boolean isSelfReference(String beanName, String candidateName) {
return (beanName != null && candidateName != null &&
(beanName.equals(candidateName) || (containsBeanDefinition(candidateName) &&
beanName.equals(getMergedLocalBeanDefinition(candidateName).getFactoryBeanName()))));
}
/**
* Raise a NoSuchBeanDefinitionException for an unresolvable dependency.
*/
@@ -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.
@@ -277,7 +277,7 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
@Override
public boolean containsSingleton(String beanName) {
return (this.singletonObjects.containsKey(beanName));
return this.singletonObjects.containsKey(beanName);
}
@Override
@@ -330,8 +330,7 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
* @see #isSingletonCurrentlyInCreation
*/
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) &&
!this.singletonsCurrentlyInCreation.add(beanName)) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
@@ -343,8 +342,7 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
* @see #isSingletonCurrentlyInCreation
*/
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) &&
!this.singletonsCurrentlyInCreation.remove(beanName)) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
@@ -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-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.
@@ -90,7 +90,7 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
* Obtain an object to expose from the given FactoryBean.
* @param factory the FactoryBean instance
* @param beanName the name of the bean
* @param shouldPostProcess whether the bean is subject for post-processing
* @param shouldPostProcess whether the bean is subject to post-processing
* @return the object obtained from the FactoryBean
* @throws BeanCreationException if FactoryBean object creation failed
* @see org.springframework.beans.factory.FactoryBean#getObject()
@@ -100,14 +100,40 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
object = doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
object = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (object != null && shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
}
this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
}
}
return (object != NULL_OBJECT ? object : null);
}
}
else {
return doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (object != null && shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
@@ -115,13 +141,11 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
* Obtain an object to expose from the given FactoryBean.
* @param factory the FactoryBean instance
* @param beanName the name of the bean
* @param shouldPostProcess whether the bean is subject for post-processing
* @return the object obtained from the FactoryBean
* @throws BeanCreationException if FactoryBean object creation failed
* @see org.springframework.beans.factory.FactoryBean#getObject()
*/
private Object doGetObjectFromFactoryBean(
final FactoryBean<?> factory, final String beanName, final boolean shouldPostProcess)
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException {
Object object;
@@ -151,23 +175,12 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
// Do not accept a null value for a FactoryBean that's not fully
// initialized yet: Many FactoryBeans just return null then.
if (object == null && isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
if (object != null && shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of the FactoryBean's object failed", ex);
}
}
return object;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -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();
}
}
@@ -37,8 +37,7 @@ public class LookupOverride extends MethodOverride {
/**
* Construct a new LookupOverride.
* @param methodName the name of the method to override.
* This method must have no arguments.
* @param methodName the name of the method to override
* @param beanName the name of the bean in the current BeanFactory
* that the overridden method should return
*/
@@ -48,6 +47,7 @@ public class LookupOverride extends MethodOverride {
this.beanName = beanName;
}
/**
* Return the name of the bean that should be returned by this method.
*/
@@ -63,10 +63,6 @@ public class LookupOverride extends MethodOverride {
return (method.getName().equals(getMethodName()) && method.getParameterTypes().length == 0);
}
@Override
public String toString() {
return "LookupOverride for method '" + getMethodName() + "'; will return bean '" + this.beanName + "'";
}
@Override
public boolean equals(Object other) {
@@ -79,4 +75,9 @@ public class LookupOverride extends MethodOverride {
return (29 * super.hashCode() + ObjectUtils.nullSafeHashCode(this.beanName));
}
@Override
public String toString() {
return "LookupOverride for method '" + getMethodName() + "'";
}
}
@@ -52,6 +52,7 @@ public abstract class MethodOverride implements BeanMetadataElement {
this.methodName = methodName;
}
/**
* Return the name of the method to be overridden.
*/
@@ -99,6 +100,7 @@ public abstract class MethodOverride implements BeanMetadataElement {
*/
public abstract boolean matches(Method method);
@Override
public boolean equals(Object other) {
if (this == other) {
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -52,6 +52,7 @@ public class ReplaceOverride extends MethodOverride {
this.methodReplacerBeanName = methodReplacerBeanName;
}
/**
* Return the name of the bean implementing MethodReplacer.
*/
@@ -68,28 +69,22 @@ public class ReplaceOverride extends MethodOverride {
this.typeIdentifiers.add(identifier);
}
@Override
public boolean matches(Method method) {
// TODO could cache result for efficiency
if (!method.getName().equals(getMethodName())) {
// It can't match.
return false;
}
if (!isOverloaded()) {
// No overloaded: don't worry about arg type matching.
// Not overloaded: don't worry about arg type matching...
return true;
}
// If we get to here, we need to insist on precise argument matching.
// If we get here, we need to insist on precise argument matching...
if (this.typeIdentifiers.size() != method.getParameterTypes().length) {
return false;
}
for (int i = 0; i < this.typeIdentifiers.size(); i++) {
String identifier = this.typeIdentifiers.get(i);
if (!method.getParameterTypes()[i].getName().contains(identifier)) {
// This parameter cannot match.
return false;
}
}
@@ -97,12 +92,6 @@ public class ReplaceOverride extends MethodOverride {
}
@Override
public String toString() {
return "Replace override for method '" + getMethodName() + "; will call bean '" +
this.methodReplacerBeanName + "'";
}
@Override
public boolean equals(Object other) {
if (!(other instanceof ReplaceOverride) || !super.equals(other)) {
@@ -121,4 +110,9 @@ public class ReplaceOverride extends MethodOverride {
return hashCode;
}
@Override
public String toString() {
return "Replace override for method '" + getMethodName() + "'";
}
}
@@ -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.
@@ -133,7 +133,7 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
public Object getBean(String name, Object... args) throws BeansException {
if (args != null) {
throw new UnsupportedOperationException(
"StaticListableBeanFactory does not support explicit bean creation arguments)");
"StaticListableBeanFactory does not support explicit bean creation arguments");
}
return getBean(name);
}
@@ -149,7 +149,7 @@ public abstract class AbstractSimpleBeanDefinitionParser extends AbstractSingleB
*/
protected boolean isEligibleAttribute(Attr attribute, ParserContext parserContext) {
boolean eligible = isEligibleAttribute(attribute);
if(!eligible) {
if (!eligible) {
String fullName = attribute.getName();
eligible = (!fullName.equals("xmlns") && !fullName.startsWith("xmlns:") &&
isEligibleAttribute(parserContext.getDelegate().getLocalName(attribute)));
@@ -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.
@@ -13,29 +13,30 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.xml;
import java.util.Collection;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
import org.springframework.core.Conventions;
import org.springframework.util.StringUtils;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.core.Conventions;
import org.springframework.util.StringUtils;
/**
* Simple {@code NamespaceHandler} implementation that maps custom
* attributes directly through to bean properties. An important point to note is
* that this {@code NamespaceHandler} does not have a corresponding schema
* since there is no way to know in advance all possible attribute names.
*
* <p>
* An example of the usage of this {@code NamespaceHandler} is shown below:
* <p>An example of the usage of this {@code NamespaceHandler} is shown below:
*
* <pre class="code">
* &lt;bean id=&quot;author&quot; class=&quot;..TestBean&quot; c:name=&quot;Enescu&quot; c:work-ref=&quot;compositions&quot;/&gt;
@@ -51,14 +52,17 @@ import org.w3c.dom.Node;
* support for indexes or types. Further more, the names are used as hints by
* the container which, by default, does type introspection.
*
* @see SimplePropertyNamespaceHandler
* @author Costin Leau
* @since 3.1
* @see SimplePropertyNamespaceHandler
*/
public class SimpleConstructorNamespaceHandler implements NamespaceHandler {
private static final String REF_SUFFIX = "-ref";
private static final String DELIMITER_PREFIX = "_";
@Override
public void init() {
}
@@ -102,7 +106,8 @@ public class SimpleConstructorNamespaceHandler implements NamespaceHandler {
int index = -1;
try {
index = Integer.parseInt(arg);
} catch (NumberFormatException ex) {
}
catch (NumberFormatException ex) {
parserContext.getReaderContext().error(
"Constructor argument '" + argName + "' specifies an invalid integer", attr);
}
@@ -136,11 +141,8 @@ public class SimpleConstructorNamespaceHandler implements NamespaceHandler {
}
private boolean containsArgWithName(String name, ConstructorArgumentValues cvs) {
if (!checkName(name, cvs.getGenericArgumentValues())) {
return checkName(name, cvs.getIndexedArgumentValues().values());
}
return true;
return (checkName(name, cvs.getGenericArgumentValues()) ||
checkName(name, cvs.getIndexedArgumentValues().values()));
}
private boolean checkName(String name, Collection<ValueHolder> values) {
@@ -151,4 +153,5 @@ public class SimpleConstructorNamespaceHandler implements NamespaceHandler {
}
return false;
}
}
@@ -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,13 +16,13 @@
package org.springframework.beans.propertyeditors;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import java.beans.PropertyEditorSupport;
import java.util.Locale;
import java.util.ResourceBundle;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* {@link java.beans.PropertyEditor} implementation for
* {@link java.util.ResourceBundle ResourceBundles}.
@@ -87,7 +87,8 @@ public class ResourceBundleEditor extends PropertyEditorSupport {
int indexOfBaseNameSeparator = rawBaseName.indexOf(BASE_NAME_SEPARATOR);
if (indexOfBaseNameSeparator == -1) {
bundle = ResourceBundle.getBundle(rawBaseName);
} else {
}
else {
// it potentially has locale information
String baseName = rawBaseName.substring(0, indexOfBaseNameSeparator);
if (!StringUtils.hasText(baseName)) {
@@ -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,7 +28,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.beans.propertyeditors.CustomNumberEditor;
@@ -40,6 +39,8 @@ import org.springframework.tests.sample.beans.GenericIntegerBean;
import org.springframework.tests.sample.beans.GenericSetOfIntegerBean;
import org.springframework.tests.sample.beans.TestBean;
import static org.junit.Assert.*;
/**
* @author Juergen Hoeller
* @author Chris Beams
@@ -485,6 +486,29 @@ public class BeanWrapperGenericsTests {
assertEquals(new Long(10), bean.getId());
}
@Test
public void testUntypedPropertyWithMapAtRuntime() {
class Holder<D> {
private final D data;
public Holder(D data) {
this.data = data;
}
public D getData() {
return this.data;
}
}
Map<String, Object> data = new HashMap<String, Object>();
data.put("x", "y");
Holder<Map<String, Object>> context = new Holder<Map<String,Object>>(data);
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(context);
assertEquals("y", bw.getPropertyValue("data['x']"));
bw.setPropertyValue("data['message']", "it works!");
assertEquals(data.get("message"), "it works!");
}
private static abstract class BaseGenericCollectionBean {
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="bean1" class="org.springframework.beans.factory.FactoryBeanTests$PassThroughFactoryBean" primary="true">
<constructor-arg value="org.springframework.beans.factory.FactoryBeanTests$BeanImpl1"/>
<property name="instanceName" value="beanImpl1"/>
</bean>
<bean id="beanImpl1" class="org.springframework.beans.factory.FactoryBeanTests$BeanImpl1">
<property name="impl2" ref="bean2"/>
</bean>
<bean id="bean2" class="org.springframework.beans.factory.FactoryBeanTests$PassThroughFactoryBean" primary="true">
<constructor-arg value="org.springframework.beans.factory.FactoryBeanTests$BeanImpl2"/>
<property name="instanceName" value="beanImpl2"/>
</bean>
<bean id="beanImpl2" class="org.springframework.beans.factory.FactoryBeanTests$BeanImpl2">
<property name="impl1" ref="bean1"/>
</bean>
</beans>
@@ -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,19 +16,24 @@
package org.springframework.beans.factory;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.springframework.tests.TestResourceUtils.qualifiedResource;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Test;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import static org.junit.Assert.*;
import static org.springframework.tests.TestResourceUtils.*;
/**
* @author Rob Harrop
* @author Juergen Hoeller
@@ -40,6 +45,7 @@ public final class FactoryBeanTests {
private static final Resource RETURNS_NULL_CONTEXT = qualifiedResource(CLASS, "returnsNull.xml");
private static final Resource WITH_AUTOWIRING_CONTEXT = qualifiedResource(CLASS, "withAutowiring.xml");
private static final Resource ABSTRACT_CONTEXT = qualifiedResource(CLASS, "abstract.xml");
private static final Resource CIRCULAR_CONTEXT = qualifiedResource(CLASS, "circular.xml");
@Test
public void testFactoryBeanReturnsNull() throws Exception {
@@ -96,6 +102,23 @@ public final class FactoryBeanTests {
factory.getBeansOfType(AbstractFactoryBean.class);
}
@Test
public void testCircularReferenceWithPostProcessor() {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(factory).loadBeanDefinitions(CIRCULAR_CONTEXT);
CountingPostProcessor counter = new CountingPostProcessor();
factory.addBeanPostProcessor(counter);
BeanImpl1 impl1 = factory.getBean(BeanImpl1.class);
assertNotNull(impl1);
assertNotNull(impl1.getImpl2());
assertNotNull(impl1.getImpl2());
assertSame(impl1, impl1.getImpl2().getImpl1());
assertEquals(1, counter.getCount("bean1"));
assertEquals(1, counter.getCount("bean2"));
}
public static class NullReturningFactoryBean implements FactoryBean<Object> {
@@ -193,7 +216,114 @@ public final class FactoryBeanTests {
}
}
public abstract static class AbstractFactoryBean implements FactoryBean<Object> {
}
public static class PassThroughFactoryBean<T> implements FactoryBean<T>, BeanFactoryAware {
private Class<T> type;
private String instanceName;
private BeanFactory beanFactory;
private T instance;
public PassThroughFactoryBean(Class<T> type) {
this.type = type;
}
public void setInstanceName(String instanceName) {
this.instanceName = instanceName;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
@Override
public T getObject() {
if (instance == null) {
instance = beanFactory.getBean(instanceName, type);
}
return instance;
}
@Override
public Class<?> getObjectType() {
return type;
}
@Override
public boolean isSingleton() {
return true;
}
}
public static class CountingPostProcessor implements BeanPostProcessor {
private final Map<String, AtomicInteger> count = new HashMap<String, AtomicInteger>();
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof FactoryBean) {
return bean;
}
AtomicInteger c = count.get(beanName);
if (c == null) {
c = new AtomicInteger(0);
count.put(beanName, c);
}
c.incrementAndGet();
return bean;
}
public int getCount(String beanName) {
AtomicInteger c = count.get(beanName);
if (c != null) {
return c.intValue();
}
else {
return 0;
}
}
}
public static class BeanImpl1 {
private BeanImpl2 impl2;
public BeanImpl2 getImpl2() {
return impl2;
}
public void setImpl2(BeanImpl2 impl2) {
this.impl2 = impl2;
}
}
public static class BeanImpl2 {
private BeanImpl1 impl1;
public BeanImpl1 getImpl1() {
return impl1;
}
public void setImpl1(BeanImpl1 impl1) {
this.impl1 = impl1;
}
}
}
@@ -2593,7 +2593,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
@SuppressWarnings("unchecked")
public <T> T createMock(Class<T> toMock) {
return (T) Proxy.newProxyInstance(AutowiredAnnotationBeanPostProcessorTests.class.getClassLoader(), new Class<?>[]{toMock},
return (T) Proxy.newProxyInstance(AutowiredAnnotationBeanPostProcessorTests.class.getClassLoader(), new Class<?>[] {toMock},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
@@ -2620,11 +2620,11 @@ public class AutowiredAnnotationBeanPostProcessorTests {
return gi2.doSomethingMoreGeneric(o) + "_somethingGeneric_" + o;
}
public static GenericInterface1<String> create(){
public static GenericInterface1<String> create() {
return new StringGenericInterface1Impl();
}
public static GenericInterface1 createPlain(){
public static GenericInterface1 createPlain() {
return new GenericInterface1Impl();
}
}
@@ -2640,7 +2640,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
}
public static class GenericInterface2Impl implements GenericInterface2<String>{
public static class GenericInterface2Impl implements GenericInterface2<String> {
@Override
public String doSomethingMoreGeneric(String o) {
@@ -2658,7 +2658,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
}
public static class PlainGenericInterface2Impl implements GenericInterface2{
public static class PlainGenericInterface2Impl implements GenericInterface2 {
@Override
public String doSomethingMoreGeneric(Object o) {
@@ -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.
@@ -45,7 +45,7 @@ import org.springframework.core.io.Resource;
* also necessary for loading EhCache configuration from a non-default config location.
*
* <p>Note: As of Spring 4.0, Spring's EhCache support requires EhCache 2.1 or higher.
* We recommend the use of EhCache 2.5 or higher.
* We strongly recommend the use of EhCache 2.5 or higher.
*
* @author Juergen Hoeller
* @author Dmitriy Kopylenko
@@ -132,7 +132,7 @@ public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, Ini
@Override
public void afterPropertiesSet() throws IOException, CacheException {
public void afterPropertiesSet() throws CacheException, IOException {
logger.info("Initializing EhCache CacheManager");
InputStream is = (this.configLocation != null ? this.configLocation.getInputStream() : null);
try {
@@ -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,6 +19,7 @@ package org.springframework.cache.guava;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -29,6 +30,7 @@ import com.google.common.cache.CacheLoader;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
* {@link CacheManager} implementation that lazily builds {@link GuavaCache}
@@ -45,6 +47,7 @@ import org.springframework.util.Assert;
* <p>Requires Google Guava 12.0 or higher.
*
* @author Juergen Hoeller
* @author Stephane Nicoll
* @since 4.0
* @see GuavaCache
*/
@@ -81,6 +84,8 @@ public class GuavaCacheManager implements CacheManager {
* Specify the set of cache names for this CacheManager's 'static' mode.
* <p>The number of caches and their names will be fixed after a call to this method,
* with no creation of further cache regions at runtime.
* <p>Calling this with a {@code null} collection argument resets the
* mode to 'dynamic', allowing for further creation of caches again.
*/
public void setCacheNames(Collection<String> cacheNames) {
if (cacheNames != null) {
@@ -89,6 +94,9 @@ public class GuavaCacheManager implements CacheManager {
}
this.dynamic = false;
}
else {
this.dynamic = true;
}
}
/**
@@ -99,7 +107,7 @@ public class GuavaCacheManager implements CacheManager {
*/
public void setCacheBuilder(CacheBuilder<Object, Object> cacheBuilder) {
Assert.notNull(cacheBuilder, "CacheBuilder must not be null");
this.cacheBuilder = cacheBuilder;
doSetCacheBuilder(cacheBuilder);
}
/**
@@ -109,7 +117,7 @@ public class GuavaCacheManager implements CacheManager {
* @see com.google.common.cache.CacheBuilder#from(CacheBuilderSpec)
*/
public void setCacheBuilderSpec(CacheBuilderSpec cacheBuilderSpec) {
this.cacheBuilder = CacheBuilder.from(cacheBuilderSpec);
doSetCacheBuilder(CacheBuilder.from(cacheBuilderSpec));
}
/**
@@ -120,7 +128,7 @@ public class GuavaCacheManager implements CacheManager {
* @see com.google.common.cache.CacheBuilder#from(String)
*/
public void setCacheSpecification(String cacheSpecification) {
this.cacheBuilder = CacheBuilder.from(cacheSpecification);
doSetCacheBuilder(CacheBuilder.from(cacheSpecification));
}
/**
@@ -131,7 +139,10 @@ public class GuavaCacheManager implements CacheManager {
* @see com.google.common.cache.LoadingCache
*/
public void setCacheLoader(CacheLoader<Object, Object> cacheLoader) {
this.cacheLoader = cacheLoader;
if (!ObjectUtils.nullSafeEquals(this.cacheLoader, cacheLoader)) {
this.cacheLoader = cacheLoader;
refreshKnownCaches();
}
}
/**
@@ -141,7 +152,10 @@ public class GuavaCacheManager implements CacheManager {
* An internal holder object will be used to store user-level {@code null}s.
*/
public void setAllowNullValues(boolean allowNullValues) {
this.allowNullValues = allowNullValues;
if (this.allowNullValues != allowNullValues) {
this.allowNullValues = allowNullValues;
refreshKnownCaches();
}
}
/**
@@ -196,4 +210,20 @@ public class GuavaCacheManager implements CacheManager {
}
}
private void doSetCacheBuilder(CacheBuilder<Object, Object> cacheBuilder) {
if (!ObjectUtils.nullSafeEquals(this.cacheBuilder, cacheBuilder)) {
this.cacheBuilder = cacheBuilder;
refreshKnownCaches();
}
}
/**
* Create the known caches again with the current state of this manager.
*/
private void refreshKnownCaches() {
for (Map.Entry<String, Cache> entry : this.cacheMap.entrySet()) {
entry.setValue(createGuavaCache(entry.getKey()));
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,7 +20,6 @@ import java.net.URI;
import java.util.Properties;
import javax.cache.CacheManager;
import javax.cache.Caching;
import javax.cache.spi.CachingProvider;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.DisposableBean;
@@ -75,8 +74,7 @@ public class JCacheManagerFactoryBean
@Override
public void afterPropertiesSet() {
CachingProvider provider = Caching.getCachingProvider();
this.cacheManager = provider.getCacheManager(
this.cacheManager = Caching.getCachingProvider().getCacheManager(
this.cacheManagerUri, this.beanClassLoader, this.cacheManagerProperties);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -68,7 +68,7 @@ public class TransactionAwareCacheManagerProxy implements CacheManager, Initiali
@Override
public void afterPropertiesSet() {
if (this.targetCacheManager == null) {
throw new IllegalStateException("'targetCacheManager' is required");
throw new IllegalArgumentException("Property 'targetCacheManager' is required");
}
}
@@ -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.
@@ -93,7 +93,7 @@ public class ConfigurableMimeFileTypeMap extends FileTypeMap implements Initiali
* Java Activation Framework, for example:<br>
* {@code text/html html htm HTML HTM}
*/
public void setMappings(String[] mappings) {
public void setMappings(String... mappings) {
this.mappings = mappings;
}
@@ -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,12 +152,10 @@ 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
// JobDetail objects during autodetection of JobDetailAwareTriggers.
// JobDetail objects during autodetection of JobDetail-aware Triggers.
this.jobDetails = new ArrayList<JobDetail>(Arrays.asList(jobDetails));
}
@@ -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.
@@ -86,8 +86,8 @@ import org.springframework.util.CollectionUtils;
* @see org.quartz.impl.StdSchedulerFactory
* @see org.springframework.transaction.interceptor.TransactionProxyFactoryBean
*/
public class SchedulerFactoryBean extends SchedulerAccessor implements FactoryBean<Scheduler>, BeanNameAware,
ApplicationContextAware, InitializingBean, DisposableBean, SmartLifecycle {
public class SchedulerFactoryBean extends SchedulerAccessor implements FactoryBean<Scheduler>,
BeanNameAware, ApplicationContextAware, InitializingBean, DisposableBean, SmartLifecycle {
public static final String PROP_THREAD_COUNT = "org.quartz.threadPool.threadCount";
@@ -311,7 +311,7 @@ public class SchedulerFactoryBean extends SchedulerAccessor implements FactoryBe
* reference into the JobDataMap but rather into the SchedulerContext.
* @param schedulerContextAsMap Map with String keys and any objects as
* values (for example Spring-managed beans)
* @see JobDetailBean#setJobDataAsMap
* @see JobDetailFactoryBean#setJobDataAsMap
*/
public void setSchedulerContextAsMap(Map<String, ?> schedulerContextAsMap) {
this.schedulerContextMap = schedulerContextAsMap;
@@ -329,8 +329,8 @@ public class SchedulerFactoryBean extends SchedulerAccessor implements FactoryBe
* correspond to a "setApplicationContext" method in that scenario.
* <p>Note that BeanFactory callback interfaces like ApplicationContextAware
* are not automatically applied to Quartz Job instances, because Quartz
* itself is reponsible for the lifecycle of its Jobs.
* @see JobDetailBean#setApplicationContextJobDataKey
* itself is responsible for the lifecycle of its Jobs.
* @see JobDetailFactoryBean#setApplicationContextJobDataKey
* @see org.springframework.context.ApplicationContext
*/
public void setApplicationContextSchedulerContextKey(String applicationContextSchedulerContextKey) {
@@ -476,7 +476,6 @@ public class SchedulerFactoryBean extends SchedulerAccessor implements FactoryBe
configTimeNonTransactionalDataSourceHolder.set(this.nonTransactionalDataSource);
}
// Get Scheduler instance from SchedulerFactory.
try {
this.scheduler = createScheduler(schedulerFactory, this.schedulerName);
@@ -707,7 +706,7 @@ public class SchedulerFactoryBean extends SchedulerAccessor implements FactoryBe
//---------------------------------------------------------------------
// Implementation of Lifecycle interface
// Implementation of SmartLifecycle interface
//---------------------------------------------------------------------
@Override
@@ -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.
@@ -16,15 +16,19 @@
package org.springframework.cache.guava;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import org.junit.Test;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
/**
* @author Juergen Hoeller
* @author Stephane Nicoll
*/
public class GuavaCacheManagerTests {
@@ -56,7 +60,7 @@ public class GuavaCacheManagerTests {
@Test
public void testStaticMode() {
CacheManager cm = new GuavaCacheManager("c1", "c2");
GuavaCacheManager cm = new GuavaCacheManager("c1", "c2");
Cache cache1 = cm.getCache("c1");
assertTrue(cache1 instanceof GuavaCache);
Cache cache1again = cm.getCache("c1");
@@ -76,6 +80,79 @@ public class GuavaCacheManagerTests {
assertNull(cache1.get("key3").get());
cache1.evict("key3");
assertNull(cache1.get("key3"));
cm.setAllowNullValues(false);
Cache cache1x = cm.getCache("c1");
assertTrue(cache1x instanceof GuavaCache);
assertTrue(cache1x != cache1);
Cache cache2x = cm.getCache("c2");
assertTrue(cache2x instanceof GuavaCache);
assertTrue(cache2x != cache2);
Cache cache3x = cm.getCache("c3");
assertNull(cache3x);
cache1x.put("key1", "value1");
assertEquals("value1", cache1x.get("key1").get());
cache1x.put("key2", 2);
assertEquals(2, cache1x.get("key2").get());
try {
cache1x.put("key3", null);
fail("Should have thrown NullPointerException");
}
catch (NullPointerException ex) {
// expected
}
cm.setAllowNullValues(true);
Cache cache1y = cm.getCache("c1");
cache1y.put("key3", null);
assertNull(cache1y.get("key3").get());
cache1y.evict("key3");
assertNull(cache1y.get("key3"));
}
@Test
public void changeCacheSpecificationRecreateCache() {
GuavaCacheManager cm = new GuavaCacheManager("c1");
Cache cache1 = cm.getCache("c1");
CacheBuilder<Object, Object> cacheBuilder = CacheBuilder.newBuilder().maximumSize(10);
cm.setCacheBuilder(cacheBuilder);
Cache cache1x = cm.getCache("c1");
assertTrue(cache1x != cache1);
cm.setCacheBuilder(cacheBuilder); // Set same instance
Cache cache1xx = cm.getCache("c1");
assertSame(cache1x, cache1xx);
}
@Test
public void changeCacheLoaderRecreateCache() {
GuavaCacheManager cm = new GuavaCacheManager("c1");
Cache cache1 = cm.getCache("c1");
CacheLoader<Object,Object> loader = mockCacheLoader();
cm.setCacheLoader(loader);
Cache cache1x = cm.getCache("c1");
assertTrue(cache1x != cache1);
cm.setCacheLoader(loader); // Set same instance
Cache cache1xx = cm.getCache("c1");
assertSame(cache1x, cache1xx);
}
@Test
public void setCacheNameNullRestoreDynamicMode() {
GuavaCacheManager cm = new GuavaCacheManager("c1");
assertNull(cm.getCache("someCache"));
cm.setCacheNames(null);
assertNotNull(cm.getCache("someCache"));
}
@SuppressWarnings("unchecked")
private CacheLoader<Object, Object> mockCacheLoader() {
return mock(CacheLoader.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.
@@ -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);
@@ -66,6 +66,8 @@ public interface Cache {
* @return the value to which this cache maps the specified key
* (which may be {@code null} itself), or also {@code null} if
* the cache contains no mapping for this key
* @throws IllegalStateException if a cache entry has been found
* but failed to match the specified type
* @see #get(Object)
* @since 4.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.
@@ -37,11 +37,11 @@ import org.springframework.context.annotation.Role;
@Configuration
public class ProxyCachingConfiguration extends AbstractCachingConfiguration {
@Bean(name=AnnotationConfigUtils.CACHE_ADVISOR_BEAN_NAME)
@Bean(name = AnnotationConfigUtils.CACHE_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryCacheOperationSourceAdvisor cacheAdvisor() {
BeanFactoryCacheOperationSourceAdvisor advisor =
new BeanFactoryCacheOperationSourceAdvisor();
new BeanFactoryCacheOperationSourceAdvisor();
advisor.setCacheOperationSource(cacheOperationSource());
advisor.setAdvice(cacheInterceptor());
advisor.setOrder(this.enableCaching.<Integer>getNumber("order"));
@@ -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.
@@ -55,24 +55,25 @@ public class SpringCacheAnnotationParser implements CacheAnnotationParser, Seria
Collection<CacheEvict> evicts = getAnnotations(ae, CacheEvict.class);
if (evicts != null) {
ops = lazyInit(ops);
for (CacheEvict e : evicts) {
ops.add(parseEvictAnnotation(ae, e));
for (CacheEvict evict : evicts) {
ops.add(parseEvictAnnotation(ae, evict));
}
}
Collection<CachePut> updates = getAnnotations(ae, CachePut.class);
if (updates != null) {
Collection<CachePut> puts = getAnnotations(ae, CachePut.class);
if (puts != null) {
ops = lazyInit(ops);
for (CachePut p : updates) {
ops.add(parseUpdateAnnotation(ae, p));
for (CachePut put : puts) {
ops.add(parsePutAnnotation(ae, put));
}
}
Collection<Caching> caching = getAnnotations(ae, Caching.class);
if (caching != null) {
Collection<Caching> cachings = getAnnotations(ae, Caching.class);
if (cachings != null) {
ops = lazyInit(ops);
for (Caching c : caching) {
ops.addAll(parseCachingAnnotation(ae, c));
for (Caching caching : cachings) {
ops.addAll(parseCachingAnnotation(ae, caching));
}
}
return ops;
}
@@ -81,34 +82,34 @@ public class SpringCacheAnnotationParser implements CacheAnnotationParser, Seria
}
CacheableOperation parseCacheableAnnotation(AnnotatedElement ae, Cacheable caching) {
CacheableOperation cuo = new CacheableOperation();
cuo.setCacheNames(caching.value());
cuo.setCondition(caching.condition());
cuo.setUnless(caching.unless());
cuo.setKey(caching.key());
cuo.setName(ae.toString());
return cuo;
CacheableOperation op = new CacheableOperation();
op.setCacheNames(caching.value());
op.setCondition(caching.condition());
op.setUnless(caching.unless());
op.setKey(caching.key());
op.setName(ae.toString());
return op;
}
CacheEvictOperation parseEvictAnnotation(AnnotatedElement ae, CacheEvict caching) {
CacheEvictOperation ceo = new CacheEvictOperation();
ceo.setCacheNames(caching.value());
ceo.setCondition(caching.condition());
ceo.setKey(caching.key());
ceo.setCacheWide(caching.allEntries());
ceo.setBeforeInvocation(caching.beforeInvocation());
ceo.setName(ae.toString());
return ceo;
CacheEvictOperation op = new CacheEvictOperation();
op.setCacheNames(caching.value());
op.setCondition(caching.condition());
op.setKey(caching.key());
op.setCacheWide(caching.allEntries());
op.setBeforeInvocation(caching.beforeInvocation());
op.setName(ae.toString());
return op;
}
CacheOperation parseUpdateAnnotation(AnnotatedElement ae, CachePut caching) {
CachePutOperation cuo = new CachePutOperation();
cuo.setCacheNames(caching.value());
cuo.setCondition(caching.condition());
cuo.setUnless(caching.unless());
cuo.setKey(caching.key());
cuo.setName(ae.toString());
return cuo;
CacheOperation parsePutAnnotation(AnnotatedElement ae, CachePut caching) {
CachePutOperation op = new CachePutOperation();
op.setCacheNames(caching.value());
op.setCondition(caching.condition());
op.setUnless(caching.unless());
op.setKey(caching.key());
op.setName(ae.toString());
return op;
}
Collection<CacheOperation> parseCachingAnnotation(AnnotatedElement ae, Caching caching) {
@@ -132,7 +133,7 @@ public class SpringCacheAnnotationParser implements CacheAnnotationParser, Seria
if (!ObjectUtils.isEmpty(updates)) {
ops = lazyInit(ops);
for (CachePut update : updates) {
ops.add(parseUpdateAnnotation(ae, update));
ops.add(parsePutAnnotation(ae, update));
}
}
@@ -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,6 +19,7 @@ package org.springframework.cache.concurrent;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -70,6 +71,8 @@ public class ConcurrentMapCacheManager implements CacheManager {
* Specify the set of cache names for this CacheManager's 'static' mode.
* <p>The number of caches and their names will be fixed after a call to this method,
* with no creation of further cache regions at runtime.
* <p>Calling this with a {@code null} collection argument resets the
* mode to 'dynamic', allowing for further creation of caches again.
*/
public void setCacheNames(Collection<String> cacheNames) {
if (cacheNames != null) {
@@ -78,6 +81,9 @@ public class ConcurrentMapCacheManager implements CacheManager {
}
this.dynamic = false;
}
else {
this.dynamic = true;
}
}
/**
@@ -85,9 +91,17 @@ public class ConcurrentMapCacheManager implements CacheManager {
* in this cache manager.
* <p>Default is "true", despite ConcurrentHashMap itself not supporting {@code null}
* values. An internal holder object will be used to store user-level {@code null}s.
* <p>Note: A change of the null-value setting will reset all existing caches,
* if any, to reconfigure them with the new null-value requirement.
*/
public void setAllowNullValues(boolean allowNullValues) {
this.allowNullValues = allowNullValues;
if (allowNullValues != this.allowNullValues) {
this.allowNullValues = allowNullValues;
// Need to recreate all Cache instances with the new null-value configuration...
for (Map.Entry<String, Cache> entry : this.cacheMap.entrySet()) {
entry.setValue(createConcurrentMapCache(entry.getKey()));
}
}
}
/**
@@ -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,7 +16,7 @@
package org.springframework.cache.config;
import static org.springframework.context.annotation.AnnotationConfigUtils.*;
import org.w3c.dom.Element;
import org.springframework.aop.config.AopNamespaceUtils;
import org.springframework.beans.factory.config.BeanDefinition;
@@ -26,10 +26,9 @@ import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.cache.annotation.AnnotationCacheOperationSource;
import org.springframework.cache.interceptor.BeanFactoryCacheOperationSourceAdvisor;
import org.springframework.cache.interceptor.CacheInterceptor;
import org.w3c.dom.Element;
import org.springframework.context.annotation.AnnotationConfigUtils;
/**
* {@link org.springframework.beans.factory.xml.BeanDefinitionParser}
@@ -83,13 +82,13 @@ class AnnotationDrivenCacheBeanDefinitionParser implements BeanDefinitionParser
* </pre>
*/
private void registerCacheAspect(Element element, ParserContext parserContext) {
if (!parserContext.getRegistry().containsBeanDefinition(CACHE_ASPECT_BEAN_NAME)) {
if (!parserContext.getRegistry().containsBeanDefinition(AnnotationConfigUtils.CACHE_ASPECT_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
def.setBeanClassName(CACHE_ASPECT_CLASS_NAME);
def.setBeanClassName(AnnotationConfigUtils.CACHE_ASPECT_CLASS_NAME);
def.setFactoryMethodName("aspectOf");
parseCacheManagerProperty(element, def);
CacheNamespaceHandler.parseKeyGenerator(element, def);
parserContext.registerBeanComponent(new BeanComponentDefinition(def, CACHE_ASPECT_BEAN_NAME));
parserContext.registerBeanComponent(new BeanComponentDefinition(def, AnnotationConfigUtils.CACHE_ASPECT_BEAN_NAME));
}
}
@@ -102,11 +101,11 @@ class AnnotationDrivenCacheBeanDefinitionParser implements BeanDefinitionParser
public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
if (!parserContext.getRegistry().containsBeanDefinition(CACHE_ADVISOR_BEAN_NAME)) {
if (!parserContext.getRegistry().containsBeanDefinition(AnnotationConfigUtils.CACHE_ADVISOR_BEAN_NAME)) {
Object eleSource = parserContext.extractSource(element);
// Create the CacheOperationSource definition.
RootBeanDefinition sourceDef = new RootBeanDefinition(AnnotationCacheOperationSource.class);
RootBeanDefinition sourceDef = new RootBeanDefinition("org.springframework.cache.annotation.AnnotationCacheOperationSource");
sourceDef.setSource(eleSource);
sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);
@@ -129,15 +128,16 @@ class AnnotationDrivenCacheBeanDefinitionParser implements BeanDefinitionParser
if (element.hasAttribute("order")) {
advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
}
parserContext.getRegistry().registerBeanDefinition(CACHE_ADVISOR_BEAN_NAME, advisorDef);
parserContext.getRegistry().registerBeanDefinition(AnnotationConfigUtils.CACHE_ADVISOR_BEAN_NAME, advisorDef);
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(),
eleSource);
compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, CACHE_ADVISOR_BEAN_NAME));
compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, AnnotationConfigUtils.CACHE_ADVISOR_BEAN_NAME));
parserContext.registerComponent(compositeDef);
}
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,8 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.w3c.dom.Element;
import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.beans.factory.parsing.ReaderContext;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
@@ -28,7 +30,6 @@ import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.cache.annotation.AnnotationCacheOperationSource;
import org.springframework.cache.interceptor.CacheEvictOperation;
import org.springframework.cache.interceptor.CacheInterceptor;
import org.springframework.cache.interceptor.CacheOperation;
@@ -37,7 +38,6 @@ import org.springframework.cache.interceptor.CacheableOperation;
import org.springframework.cache.interceptor.NameMatchCacheOperationSource;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
/**
* {@link org.springframework.beans.factory.xml.BeanDefinitionParser
@@ -74,10 +74,11 @@ class CacheAdviceParser extends AbstractSingleBeanDefinitionParser {
// Using attributes source.
List<RootBeanDefinition> attributeSourceDefinitions = parseDefinitionsSources(cacheDefs, parserContext);
builder.addPropertyValue("cacheOperationSources", attributeSourceDefinitions);
} else {
}
else {
// Assume annotations source.
builder.addPropertyValue("cacheOperationSources", new RootBeanDefinition(
AnnotationCacheOperationSource.class));
builder.addPropertyValue("cacheOperationSources",
new RootBeanDefinition("org.springframework.cache.annotation.AnnotationCacheOperationSource"));
}
}
@@ -168,7 +169,7 @@ class CacheAdviceParser extends AbstractSingleBeanDefinitionParser {
private static String getAttributeValue(Element element, String attributeName, String defaultValue) {
String attribute = element.getAttribute(attributeName);
if(StringUtils.hasText(attribute)) {
if (StringUtils.hasText(attribute)) {
return attribute.trim();
}
return defaultValue;
@@ -177,8 +178,6 @@ class CacheAdviceParser extends AbstractSingleBeanDefinitionParser {
/**
* Simple, reusable class used for overriding defaults.
*
* @author Costin Leau
*/
private static class Props {
@@ -190,7 +189,6 @@ class CacheAdviceParser extends AbstractSingleBeanDefinitionParser {
private String[] caches = null;
Props(Element root) {
String defaultCache = root.getAttribute("cache");
key = root.getAttribute("key");
@@ -202,7 +200,6 @@ class CacheAdviceParser extends AbstractSingleBeanDefinitionParser {
}
}
<T extends CacheOperation> T merge(Element element, ReaderContext readerCtx, T op) {
String cache = element.getAttribute("cache");
@@ -210,7 +207,8 @@ class CacheAdviceParser extends AbstractSingleBeanDefinitionParser {
String[] localCaches = caches;
if (StringUtils.hasText(cache)) {
localCaches = StringUtils.commaDelimitedListToStringArray(cache.trim());
} else {
}
else {
if (caches == null) {
readerCtx.error("No cache specified specified for " + element.getNodeName(), element);
}
@@ -224,16 +222,16 @@ class CacheAdviceParser extends AbstractSingleBeanDefinitionParser {
}
String merge(Element element, ReaderContext readerCtx) {
String m = element.getAttribute(METHOD_ATTRIBUTE);
if (StringUtils.hasText(m)) {
return m.trim();
}
String method = element.getAttribute(METHOD_ATTRIBUTE);
if (StringUtils.hasText(method)) {
return method;
return method.trim();
}
if (StringUtils.hasText(this.method)) {
return this.method;
}
readerCtx.error("No method specified for " + element.getNodeName(), element);
return null;
}
}
}
@@ -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.
@@ -26,32 +26,32 @@ import org.springframework.util.Assert;
* Base class for cache operations.
*
* @author Costin Leau
* @since 3.1
*/
public abstract class CacheOperation {
private Set<String> cacheNames = Collections.emptySet();
private String name = "";
private String condition = "";
private Set<String> cacheNames = Collections.emptySet();
private String key = "";
private String name = "";
private String keyGenerator = "";
private String cacheManager = "";
private String cacheResolver = "";
private String condition = "";
public Set<String> getCacheNames() {
return cacheNames;
}
public String getCondition() {
return condition;
}
public String getKey() {
return key;
public void setName(String name) {
Assert.hasText(name);
this.name = name;
}
public String getName() {
return name;
return this.name;
}
public void setCacheName(String cacheName) {
@@ -59,17 +59,16 @@ public abstract class CacheOperation {
this.cacheNames = Collections.singleton(cacheName);
}
public void setCacheNames(String[] cacheNames) {
Assert.notEmpty(cacheNames);
public void setCacheNames(String... cacheNames) {
this.cacheNames = new LinkedHashSet<String>(cacheNames.length);
for (String string : cacheNames) {
this.cacheNames.add(string);
for (String cacheName : cacheNames) {
Assert.hasText(cacheName, "Cache name must be non-null if specified");
this.cacheNames.add(cacheName);
}
}
public void setCondition(String condition) {
Assert.notNull(condition);
this.condition = condition;
public Set<String> getCacheNames() {
return this.cacheNames;
}
public void setKey(String key) {
@@ -77,11 +76,47 @@ public abstract class CacheOperation {
this.key = key;
}
public void setName(String name) {
Assert.hasText(name);
this.name = name;
public String getKey() {
return this.key;
}
public void setKeyGenerator(String keyGenerator) {
Assert.notNull(keyGenerator);
this.keyGenerator = keyGenerator;
}
public String getKeyGenerator() {
return this.keyGenerator;
}
public void setCacheManager(String cacheManager) {
Assert.notNull(cacheManager);
this.cacheManager = cacheManager;
}
public String getCacheManager() {
return this.cacheManager;
}
public void setCacheResolver(String cacheResolver) {
Assert.notNull(cacheManager);
this.cacheResolver = cacheResolver;
}
public String getCacheResolver() {
return this.cacheResolver;
}
public void setCondition(String condition) {
Assert.notNull(condition);
this.condition = condition;
}
public String getCondition() {
return this.condition;
}
/**
* This implementation compares the {@code toString()} results.
* @see #toString()
@@ -116,17 +151,15 @@ public abstract class CacheOperation {
* <p>Available to subclasses, for inclusion in their {@code toString()} result.
*/
protected StringBuilder getOperationDescription() {
StringBuilder result = new StringBuilder();
result.append(getClass().getSimpleName());
result.append("[");
result.append(this.name);
result.append("] caches=");
result.append(this.cacheNames);
result.append(" | key='");
result.append(this.key);
result.append("' | condition='");
result.append(this.condition);
result.append("'");
StringBuilder result = new StringBuilder(getClass().getSimpleName());
result.append("[").append(this.name);
result.append("] caches=").append(this.cacheNames);
result.append(" | key='").append(this.key);
result.append("' | keyGenerator='").append(this.keyGenerator);
result.append("' | cacheManager='").append(this.cacheManager);
result.append("' | cacheResolver='").append(this.cacheResolver);
result.append("' | condition='").append(this.condition).append("'");
return result;
}
}
@@ -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.
@@ -46,12 +46,11 @@ public abstract class AbstractCacheManager implements CacheManager, Initializing
public void afterPropertiesSet() {
Collection<? extends Cache> caches = loadCaches();
// preserve the initial order of the cache names
// Preserve the initial order of the cache names
this.cacheMap.clear();
this.cacheNames.clear();
for (Cache cache : caches) {
this.cacheMap.put(cache.getName(), decorateCache(cache));
this.cacheNames.add(cache.getName());
addCache(cache);
}
}
@@ -83,8 +82,9 @@ public abstract class AbstractCacheManager implements CacheManager, Initializing
/**
* Load the caches for this cache manager. Occurs at startup.
* The returned collection must not be null.
* Load the initial caches for this cache manager.
* <p>Called by {@link #afterPropertiesSet()} on startup.
* The returned collection may be empty but must not be {@code null}.
*/
protected abstract Collection<? extends Cache> loadCaches();
@@ -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.
@@ -93,60 +93,6 @@ public class AnnotationConfigUtils {
public static final String COMMON_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalCommonAnnotationProcessor";
/**
* The bean name of the internally managed Scheduled annotation processor.
*/
public static final String SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalScheduledAnnotationProcessor";
/**
* The bean name of the internally managed Async annotation processor.
*/
public static final String ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalAsyncAnnotationProcessor";
/**
* The bean name of the internally managed AspectJ async execution aspect.
*/
public static final String ASYNC_EXECUTION_ASPECT_BEAN_NAME =
"org.springframework.scheduling.config.internalAsyncExecutionAspect";
/**
* The class name of the AspectJ async execution aspect.
*/
public static final String ASYNC_EXECUTION_ASPECT_CLASS_NAME =
"org.springframework.scheduling.aspectj.AnnotationAsyncExecutionAspect";
/**
* The name of the AspectJ async execution aspect @{@code Configuration} class.
*/
public static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME =
"org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";
/**
* The bean name of the internally managed cache advisor.
*/
public static final String CACHE_ADVISOR_BEAN_NAME =
"org.springframework.cache.config.internalCacheAdvisor";
/**
* The bean name of the internally managed cache aspect.
*/
public static final String CACHE_ASPECT_BEAN_NAME =
"org.springframework.cache.config.internalCacheAspect";
/**
* The class name of the AspectJ caching aspect.
*/
public static final String CACHE_ASPECT_CLASS_NAME =
"org.springframework.cache.aspectj.AnnotationCacheAspect";
/**
* The name of the AspectJ caching aspect @{@code Configuration} class.
*/
public static final String CACHE_ASPECT_CONFIGURATION_CLASS_NAME =
"org.springframework.cache.aspectj.AspectJCachingConfiguration";
/**
* The bean name of the internally managed JPA annotation processor.
*/
@@ -158,6 +104,79 @@ public class AnnotationConfigUtils {
"org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor";
/**
* The bean name of the internally managed Scheduled annotation processor.
* <p>ATTENTION:</p> This constant is meant for internal use only. The value is stable
* but don't rely on the presence of this constant declaration; rather copy the value.
*/
public static final String SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalScheduledAnnotationProcessor";
/**
* The bean name of the internally managed Async annotation processor.
* <p>ATTENTION:</p> This constant is meant for internal use only. The value is stable
* but don't rely on the presence of this constant declaration; rather copy the value.
*/
public static final String ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalAsyncAnnotationProcessor";
/**
* The bean name of the internally managed AspectJ async execution aspect.
* <p>ATTENTION:</p> This constant is meant for internal use only. The value is stable
* but don't rely on the presence of this constant declaration; rather copy the value.
*/
public static final String ASYNC_EXECUTION_ASPECT_BEAN_NAME =
"org.springframework.scheduling.config.internalAsyncExecutionAspect";
/**
* The class name of the AspectJ async execution aspect.
* <p>ATTENTION:</p> This constant is meant for internal use only. The value is stable
* but don't rely on the presence of this constant declaration; rather copy the value.
*/
public static final String ASYNC_EXECUTION_ASPECT_CLASS_NAME =
"org.springframework.scheduling.aspectj.AnnotationAsyncExecutionAspect";
/**
* The name of the AspectJ async execution aspect @{@code Configuration} class.
* <p>ATTENTION:</p> This constant is meant for internal use only. The value is stable
* but don't rely on the presence of this constant declaration; rather copy the value.
*/
public static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME =
"org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";
/**
* The bean name of the internally managed cache advisor.
* <p>ATTENTION:</p> This constant is meant for internal use only. The value is stable
* but don't rely on the presence of this constant declaration; rather copy the value.
*/
public static final String CACHE_ADVISOR_BEAN_NAME =
"org.springframework.cache.config.internalCacheAdvisor";
/**
* The bean name of the internally managed cache aspect.
* <p>ATTENTION:</p> This constant is meant for internal use only. The value is stable
* but don't rely on the presence of this constant declaration; rather copy the value.
*/
public static final String CACHE_ASPECT_BEAN_NAME =
"org.springframework.cache.config.internalCacheAspect";
/**
* The class name of the AspectJ caching aspect.
* <p>ATTENTION:</p> This constant is meant for internal use only. The value is stable
* but don't rely on the presence of this constant declaration; rather copy the value.
*/
public static final String CACHE_ASPECT_CLASS_NAME =
"org.springframework.cache.aspectj.AnnotationCacheAspect";
/**
* The name of the AspectJ caching aspect @{@code Configuration} class.
* <p>ATTENTION:</p> This constant is meant for internal use only. The value is stable
* but don't rely on the presence of this constant declaration; rather copy the value.
*/
public static final String CACHE_ASPECT_CONFIGURATION_CLASS_NAME =
"org.springframework.cache.aspectj.AspectJCachingConfiguration";
private static final boolean jsr250Present =
ClassUtils.isPresent("javax.annotation.Resource", AnnotationConfigUtils.class.getClassLoader());
@@ -226,8 +245,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(
@@ -311,14 +330,15 @@ public class AnnotationConfigUtils {
static Set<AnnotationAttributes> attributesForRepeatable(AnnotationMetadata metadata,
Class<?> containerClass, Class<?> annotationClass) {
return attributesForRepeatable(metadata, containerClass.getName(), annotationClass.getName());
}
@SuppressWarnings("unchecked")
static Set<AnnotationAttributes> attributesForRepeatable(AnnotationMetadata metadata,
String containerClassName, String annotationClassName) {
Set<AnnotationAttributes> result = new LinkedHashSet<AnnotationAttributes>();
Set<AnnotationAttributes> result = new LinkedHashSet<AnnotationAttributes>();
addAttributesIfNotNull(result, metadata.getAnnotationAttributes(annotationClassName, false));
Map<String, Object> container = metadata.getAnnotationAttributes(containerClassName, false);
@@ -330,8 +350,7 @@ public class AnnotationConfigUtils {
return Collections.unmodifiableSet(result);
}
private static void addAttributesIfNotNull(Set<AnnotationAttributes> result,
Map<String, Object> attributes) {
private static void addAttributesIfNotNull(Set<AnnotationAttributes> result, Map<String, Object> attributes) {
if (attributes != null) {
result.add(AnnotationAttributes.fromMap(attributes));
}
@@ -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
@@ -167,7 +167,7 @@ public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateCo
* Set the name-matching patterns for determining autowire candidates.
* @param autowireCandidatePatterns the patterns to match against
*/
public void setAutowireCandidatePatterns(String[] autowireCandidatePatterns) {
public void setAutowireCandidatePatterns(String... autowireCandidatePatterns) {
this.autowireCandidatePatterns = autowireCandidatePatterns;
}
@@ -224,7 +224,7 @@ public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateCo
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
return this.registry.getBeanDefinitionCount() - beanCountAtScanStart;
return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}
/**
@@ -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,18 +113,20 @@ class ConfigurationClassParser {
private final ComponentScanAnnotationParser componentScanParser;
private final Set<ConfigurationClass> configurationClasses = new LinkedHashSet<ConfigurationClass>();
private final ConditionEvaluator conditionEvaluator;
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();
private final List<DeferredImportSelectorHolder> deferredImportSelectors = new LinkedList<DeferredImportSelectorHolder>();
private final ConditionEvaluator conditionEvaluator;
/**
* Create a new {@link ConfigurationClassParser} instance that will be used
@@ -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);
}
/**
@@ -215,39 +228,36 @@ class ConfigurationClassParser {
* multiple times as relevant sources are discovered.
* @param configClass the configuration class being build
* @param sourceClass a source class
* @return the superclass, {@code null} if none found or previously processed
* @return the superclass, or {@code null} if none found or previously processed
*/
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
// recursively process any member (nested) classes first
// Recursively process any member (nested) classes first
processMemberClasses(configClass, sourceClass);
// process any @PropertySource annotations
// Process any @PropertySource annotations
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class, org.springframework.context.annotation.PropertySource.class)) {
processPropertySource(propertySource);
}
// process any @ComponentScan annotations
// Process any @ComponentScan annotations
AnnotationAttributes componentScan = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ComponentScan.class);
if (componentScan != null) {
// the config class is annotated with @ComponentScan -> perform the scan immediately
if (!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// check the set of scanned definitions for any further config classes and parse recursively if necessary
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
if (ConfigurationClassUtils.checkConfigurationClassCandidate(holder.getBeanDefinition(), this.metadataReaderFactory)) {
parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
}
if (componentScan != null && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// Check the set of scanned definitions for any further config classes and parse recursively if necessary
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
if (ConfigurationClassUtils.checkConfigurationClassCandidate(holder.getBeanDefinition(), this.metadataReaderFactory)) {
parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
}
}
}
// process any @Import annotations
// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), true);
// process any @ImportResource annotations
// Process any @ImportResource annotations
if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {
AnnotationAttributes importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
String[] resources = importResource.getStringArray("value");
@@ -258,18 +268,18 @@ class ConfigurationClassParser {
}
}
// process individual @Bean methods
// Process individual @Bean methods
Set<MethodMetadata> beanMethods = sourceClass.getMetadata().getAnnotatedMethods(Bean.class.getName());
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// process superclass, if any
// 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
// Superclass found, return its annotation metadata and recurse
try {
return sourceClass.getSuperClass();
}
@@ -279,7 +289,7 @@ class ConfigurationClassParser {
}
}
// no superclass, processing is complete
// No superclass -> processing is complete
return null;
}
@@ -305,23 +315,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 +475,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--) {
@@ -532,6 +534,7 @@ class ConfigurationClassParser {
return new SourceClass(classType);
}
catch (Throwable ex) {
// Enforce ASM via class name resolution
return asSourceClass(classType.getName());
}
}
@@ -669,7 +672,7 @@ class ConfigurationClassParser {
if (this.source instanceof Class<?>) {
return (Class<?>) this.source;
}
String className = ((MetadataReader) source).getClassMetadata().getClassName();
String className = ((MetadataReader) this.source).getClassMetadata().getClassName();
return resourceLoader.getClassLoader().loadClass(className);
}
@@ -688,27 +691,39 @@ class ConfigurationClassParser {
}
public Collection<SourceClass> getMemberClasses() throws IOException {
List<SourceClass> members = new ArrayList<SourceClass>();
if (this.source instanceof Class<?>) {
Class<?> sourceClass = (Class<?>) this.source;
for (Class<?> declaredClass : sourceClass.getDeclaredClasses()) {
try {
members.add(asSourceClass(declaredClass));
}
catch (ClassNotFoundException ex) {
// ignore
Object sourceToProcess = this.source;
if (sourceToProcess instanceof Class<?>) {
Class<?> sourceClass = (Class<?>) sourceToProcess;
try {
Class<?>[] declaredClasses = sourceClass.getDeclaredClasses();
List<SourceClass> members = new ArrayList<SourceClass>(declaredClasses.length);
for (Class<?> declaredClass : declaredClasses) {
try {
members.add(asSourceClass(declaredClass));
}
catch (ClassNotFoundException ex) {
// ignore
}
}
return members;
}
catch (NoClassDefFoundError err) {
// getDeclaredClasses() failed because of non-resolvable dependencies
// -> fall back to ASM below
sourceToProcess = metadataReaderFactory.getMetadataReader(sourceClass.getName());
}
}
else {
MetadataReader sourceReader = (MetadataReader) source;
for (String memberClassName : sourceReader.getClassMetadata().getMemberClassNames()) {
try {
members.add(asSourceClass(memberClassName));
}
catch (ClassNotFoundException ex) {
// ignore
}
// ASM-based resolution - safe for non-resolvable classes as well
MetadataReader sourceReader = (MetadataReader) sourceToProcess;
String[] memberClassNames = sourceReader.getClassMetadata().getMemberClassNames();
List<SourceClass> members = new ArrayList<SourceClass>(memberClassNames.length);
for (String memberClassName : memberClassNames) {
try {
members.add(asSourceClass(memberClassName));
}
catch (ClassNotFoundException ex) {
// ignore
}
}
return members;

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