mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
62 Commits
5.3.x
...
v3.2.3.RELEASE
| Author | SHA1 | Date | |
|---|---|---|---|
| 7482cf9021 | |||
| 404671416a | |||
| 260eafc819 | |||
| ef8b5763e6 | |||
| 6b89af824d | |||
| 86b4b2ef23 | |||
| faa8430fd7 | |||
| 76f870caca | |||
| 615315728b | |||
| 115442242f | |||
| 10c0e8af01 | |||
| b6e20a4cc9 | |||
| a8adec7673 | |||
| 2ae61c503e | |||
| c2b2f30669 | |||
| 239a7cd85f | |||
| 6e4317ebfb | |||
| 325d8834e3 | |||
| 0c76cb7e80 | |||
| 940011e233 | |||
| 92bbd8103b | |||
| 9c194699c7 | |||
| 25701ef984 | |||
| 87ef99df5e | |||
| 13ca2752ae | |||
| ef363b0f7a | |||
| f9db59e730 | |||
| 0dcca2304f | |||
| ad272a0c87 | |||
| be224e1f30 | |||
| 4bb0916202 | |||
| d3eda09c01 | |||
| 399f887128 | |||
| 4d005b6987 | |||
| 532a7a3a02 | |||
| b2d416fd5f | |||
| 7298c3d669 | |||
| 7bbd38b9e0 | |||
| 64d83a550e | |||
| 0df1630ab9 | |||
| 7cbc115da6 | |||
| b962239e11 | |||
| 872cf6b076 | |||
| b2bd319d47 | |||
| e3fa49063e | |||
| c302efdbbf | |||
| 12699696f4 | |||
| c4f2566070 | |||
| 6458643f15 | |||
| 2145545e69 | |||
| f6545cde38 | |||
| 601c64a65c | |||
| 964f1a6213 | |||
| 886cc2cce8 | |||
| 5bdd2d245c | |||
| d0513f7521 | |||
| 265c0c1505 | |||
| 886cf825cb | |||
| 03033f6c06 | |||
| 5ff2dfbe13 | |||
| fa44ab6336 | |||
| eed1a58b81 |
+63
-36
@@ -12,6 +12,11 @@ configure(allprojects) { project ->
|
||||
group = "org.springframework"
|
||||
version = qualifyVersionIfNecessary(version)
|
||||
|
||||
// The following is a work-around for allowing to build on JDK 8 until the
|
||||
// Gradle build uses Ant 1.9.x by default. This is necessary to avoid the
|
||||
// "Class not found: javac1.8" issue with Ant versions prior to 1.9.x
|
||||
ant.properties["build.compiler"] = "javac1.7"
|
||||
|
||||
ext.aspectjVersion = "1.7.2"
|
||||
ext.hsqldbVersion = "1.8.0.10"
|
||||
ext.junitVersion = "4.11"
|
||||
@@ -71,25 +76,26 @@ configure(allprojects) { project ->
|
||||
}
|
||||
|
||||
ext.javadocLinks = [
|
||||
"http://docs.oracle.com/javase/6/docs/api",
|
||||
"http://docs.oracle.com/javaee/6/api",
|
||||
"http://portals.apache.org/pluto/portlet-2.0-apidocs/",
|
||||
"http://commons.apache.org/proper/commons-lang/javadocs/api-release/",
|
||||
"http://commons.apache.org/proper/commons-codec/apidocs/",
|
||||
"http://docs.oracle.com/javase/6/docs/api/",
|
||||
"http://docs.oracle.com/javaee/6/api/",
|
||||
"http://docs.oracle.com/cd/E13222_01/wls/docs90/javadocs/", // CommonJ
|
||||
"http://pic.dhe.ibm.com/infocenter/wasinfo/v7r0/topic/com.ibm.websphere.javadoc.doc/web/apidocs/",
|
||||
"http://glassfish.java.net/nonav/docs/v3/api/",
|
||||
"http://docs.jboss.org/jbossas/javadoc/4.0.5/connector/",
|
||||
"http://docs.jboss.org/jbossas/javadoc/7.1.2.Final/",
|
||||
"http://aopalliance.sourceforge.net/doc/",
|
||||
"http://glassfish.java.net/nonav/docs/v3/api/",
|
||||
"http://docs.oracle.com/cd/E13222_01/wls/docs90/javadocs/", // commonj
|
||||
"http://quartz-scheduler.org/api/2.1.5/",
|
||||
"http://www.eclipse.org/aspectj/doc/released/aspectj5rt-api/",
|
||||
"http://hc.apache.org/httpclient-3.x/apidocs/",
|
||||
"http://fasterxml.github.com/jackson-core/javadoc/2.0.0/",
|
||||
"http://jackson.codehaus.org/1.4.2/javadoc/",
|
||||
"http://pic.dhe.ibm.com/infocenter/wasinfo/v7r0/topic/com.ibm.websphere.javadoc.doc/web/apidocs/",
|
||||
"http://ibatis.apache.org/docs/java/dev/",
|
||||
"http://tiles.apache.org/framework/apidocs/",
|
||||
"http://commons.apache.org/proper/commons-lang/javadocs/api-2.5/",
|
||||
"http://commons.apache.org/proper/commons-codec/apidocs/",
|
||||
"http://commons.apache.org/proper/commons-dbcp/apidocs/",
|
||||
"http://portals.apache.org/pluto/portlet-2.0-apidocs/",
|
||||
"http://tiles.apache.org/framework/apidocs/",
|
||||
"http://ibatis.apache.org/docs/java/dev/",
|
||||
"http://hc.apache.org/httpclient-3.x/apidocs/",
|
||||
"http://aopalliance.sourceforge.net/doc/",
|
||||
"http://www.eclipse.org/aspectj/doc/released/aspectj5rt-api/",
|
||||
"http://ehcache.org/apidocs/",
|
||||
"http://quartz-scheduler.org/api/2.1.5/",
|
||||
"http://jackson.codehaus.org/1.4.2/javadoc/",
|
||||
"http://fasterxml.github.com/jackson-core/javadoc/2.0.1/",
|
||||
] as String[]
|
||||
}
|
||||
|
||||
@@ -118,6 +124,9 @@ configure(subprojects - project(":spring-build-src")) { subproject ->
|
||||
options.author = true
|
||||
options.header = project.name
|
||||
options.links(project.ext.javadocLinks)
|
||||
if(JavaVersion.current().isJava8Compatible()) {
|
||||
options.addStringOption('Xdoclint:none', '-quiet')
|
||||
}
|
||||
|
||||
// suppress warnings due to cross-module @see and @link references;
|
||||
// note that global 'api' task does display all warnings.
|
||||
@@ -245,6 +254,7 @@ project("spring-core") {
|
||||
|
||||
project("spring-beans") {
|
||||
description = "Spring Beans"
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-core"))
|
||||
compile(files(project(":spring-core").cglibRepackJar))
|
||||
@@ -256,6 +266,7 @@ project("spring-beans") {
|
||||
|
||||
project("spring-aop") {
|
||||
description = "Spring AOP"
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-core"))
|
||||
compile(files(project(":spring-core").cglibRepackJar))
|
||||
@@ -269,6 +280,7 @@ project("spring-aop") {
|
||||
|
||||
project("spring-expression") {
|
||||
description = "Spring Expression Language (SpEL)"
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-core"))
|
||||
}
|
||||
@@ -276,9 +288,11 @@ project("spring-expression") {
|
||||
|
||||
project("spring-instrument") {
|
||||
description = "Spring Instrument"
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-core"))
|
||||
}
|
||||
|
||||
jar {
|
||||
manifest.attributes["Premain-Class"] =
|
||||
"org.springframework.instrument.InstrumentationSavingAgent"
|
||||
@@ -287,6 +301,7 @@ project("spring-instrument") {
|
||||
|
||||
project("spring-instrument-tomcat") {
|
||||
description = "Spring Instrument Tomcat"
|
||||
|
||||
dependencies {
|
||||
provided("org.apache.tomcat:catalina:6.0.16")
|
||||
}
|
||||
@@ -294,6 +309,7 @@ project("spring-instrument-tomcat") {
|
||||
|
||||
project("spring-context") {
|
||||
description = "Spring Context"
|
||||
|
||||
dependencies {
|
||||
optional(project(":spring-instrument"))
|
||||
compile(project(":spring-aop"))
|
||||
@@ -306,12 +322,12 @@ project("spring-context") {
|
||||
optional("javax.inject:javax.inject:1")
|
||||
optional("org.apache.geronimo.specs:geronimo-jms_1.1_spec:1.1")
|
||||
optional("javax.persistence:persistence-api:1.0")
|
||||
optional("javax.validation:validation-api:1.0.0.GA")
|
||||
optional("org.beanshell:bsh:2.0b4")
|
||||
optional("org.codehaus.groovy:groovy-all:1.8.8")
|
||||
optional("org.jruby:jruby:1.6.5.1")
|
||||
optional("joda-time:joda-time:2.1")
|
||||
optional("org.slf4j:slf4j-api:${slf4jVersion}")
|
||||
optional("javax.validation:validation-api:1.0.0.GA")
|
||||
optional("org.hibernate:hibernate-validator:4.3.0.Final")
|
||||
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
optional("org.apache.geronimo.specs:geronimo-jta_1.1_spec:1.1")
|
||||
@@ -326,6 +342,7 @@ project("spring-context") {
|
||||
|
||||
project("spring-tx") {
|
||||
description = "Spring Transaction"
|
||||
|
||||
dependencies {
|
||||
optional(project(":spring-context")) // for JCA, @EnableTransactionManagement
|
||||
optional(project(":spring-aop"))
|
||||
@@ -355,10 +372,8 @@ project("spring-oxm") {
|
||||
dependencies {
|
||||
compile(project(":spring-beans"))
|
||||
compile(project(":spring-core"))
|
||||
optional(project(":spring-context")) // for Jaxb2Marshaller
|
||||
compile("commons-lang:commons-lang:2.5")
|
||||
testCompile(project(":spring-context"))
|
||||
optional("com.thoughtworks.xstream:xstream:1.3.1")
|
||||
optional("com.sun.xml.bind:jaxb-impl:2.1.7")
|
||||
optional("org.jibx:jibx-run:1.2.3")
|
||||
optional("org.apache.xmlbeans:xmlbeans:2.4.0")
|
||||
optional("org.codehaus.castor:castor-xml:1.3.2")
|
||||
@@ -373,6 +388,7 @@ project("spring-oxm") {
|
||||
|
||||
project("spring-jms") {
|
||||
description = "Spring JMS"
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-core"))
|
||||
compile(project(":spring-beans"))
|
||||
@@ -391,6 +407,7 @@ project("spring-jms") {
|
||||
|
||||
project("spring-jdbc") {
|
||||
description = "Spring JDBC"
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-core"))
|
||||
compile(project(":spring-beans"))
|
||||
@@ -407,6 +424,7 @@ project("spring-jdbc") {
|
||||
|
||||
project("spring-context-support") {
|
||||
description = "Spring Context Support"
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-core"))
|
||||
compile(project(":spring-beans"))
|
||||
@@ -443,8 +461,6 @@ project("spring-web") {
|
||||
compile(project(":spring-context"))
|
||||
optional(project(":spring-oxm")) // for MarshallingHttpMessageConverter
|
||||
compile("aopalliance:aopalliance:1.0")
|
||||
optional("com.caucho:hessian:3.2.1")
|
||||
optional("rome:rome:1.0")
|
||||
optional("javax.el:el-api:1.0")
|
||||
optional("javax.faces:jsf-api:1.2_08")
|
||||
provided("javax.portlet:portlet-api:2.0")
|
||||
@@ -453,6 +469,8 @@ project("spring-web") {
|
||||
optional("javax.xml:jaxrpc-api:1.1")
|
||||
provided("javax.xml.soap:saaj-api:1.3")
|
||||
provided("javax.activation:activation:1.1")
|
||||
optional("com.caucho:hessian:3.2.1")
|
||||
optional("rome:rome:1.0")
|
||||
optional("commons-fileupload:commons-fileupload:1.2")
|
||||
optional("commons-io:commons-io:1.3")
|
||||
optional("commons-httpclient:commons-httpclient:3.1")
|
||||
@@ -487,16 +505,16 @@ project("spring-orm") {
|
||||
|
||||
dependencies {
|
||||
compile("aopalliance:aopalliance:1.0")
|
||||
optional("javax.persistence:persistence-api:1.0")
|
||||
optional("org.eclipse.persistence:org.eclipse.persistence.core:1.0.1")
|
||||
optional("org.eclipse.persistence:org.eclipse.persistence.jpa:1.0.1")
|
||||
optional("org.hibernate:hibernate-core:3.3.2.GA")
|
||||
optional("org.hibernate:hibernate-annotations:3.4.0.GA")
|
||||
optional("org.hibernate:hibernate-entitymanager:3.4.0.GA")
|
||||
optional("org.apache.openjpa:openjpa:1.1.0")
|
||||
optional("org.eclipse.persistence:org.eclipse.persistence.core:1.0.1")
|
||||
optional("org.eclipse.persistence:org.eclipse.persistence.jpa:1.0.1")
|
||||
optional("toplink.essentials:toplink-essentials:2.0-41b")
|
||||
optional("javax.jdo:jdo-api:3.0")
|
||||
optional("org.apache.ibatis:ibatis-sqlmap:2.3.4.726")
|
||||
optional("javax.persistence:persistence-api:1.0")
|
||||
provided("javax.servlet:servlet-api:2.5")
|
||||
testCompile("javax.servlet:javax.servlet-api:3.0.1")
|
||||
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
|
||||
@@ -517,11 +535,12 @@ project("spring-orm") {
|
||||
project("spring-orm-hibernate4") {
|
||||
description = "Spring Object/Relational Mapping - Hibernate 4 support"
|
||||
merge.into = project(":spring-orm")
|
||||
|
||||
dependencies {
|
||||
provided(project(":spring-tx"))
|
||||
provided(project(":spring-jdbc"))
|
||||
optional("org.hibernate:hibernate-core:4.1.0.Final")
|
||||
optional("org.hibernate:hibernate-entitymanager:4.1.0.Final")
|
||||
optional("org.hibernate:hibernate-core:4.1.9.Final")
|
||||
optional("org.hibernate:hibernate-entitymanager:4.1.9.Final")
|
||||
optional(project(":spring-web"))
|
||||
optional("javax.servlet:servlet-api:2.5")
|
||||
}
|
||||
@@ -529,6 +548,7 @@ project("spring-orm-hibernate4") {
|
||||
|
||||
project("spring-webmvc") {
|
||||
description = "Spring Web MVC"
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-core"))
|
||||
compile(project(":spring-expression"))
|
||||
@@ -541,7 +561,6 @@ project("spring-webmvc") {
|
||||
optional("org.apache.tiles:tiles-core:2.1.2")
|
||||
optional("org.apache.tiles:tiles-jsp:2.1.2")
|
||||
optional("org.apache.tiles:tiles-servlet:2.1.2")
|
||||
optional("velocity-tools:velocity-tools-view:1.4")
|
||||
optional("net.sourceforge.jexcelapi:jxl:2.6.3")
|
||||
optional("org.apache.poi:poi:3.0.2-FINAL")
|
||||
optional("com.lowagie:itext:2.1.7")
|
||||
@@ -550,6 +569,7 @@ project("spring-webmvc") {
|
||||
}
|
||||
optional("rome:rome:1.0")
|
||||
optional("velocity:velocity:1.5")
|
||||
optional("velocity-tools:velocity-tools-view:1.4")
|
||||
optional("org.freemarker:freemarker:2.3.15")
|
||||
optional("org.codehaus.jackson:jackson-mapper-asl:1.4.2")
|
||||
optional("com.fasterxml.jackson.core:jackson-databind:2.0.1")
|
||||
@@ -588,6 +608,7 @@ project("spring-webmvc") {
|
||||
project("spring-webmvc-tiles3") {
|
||||
description = "Spring Framework Tiles3 Integration"
|
||||
merge.into = project(":spring-webmvc")
|
||||
|
||||
dependencies {
|
||||
provided(project(":spring-context"))
|
||||
provided(project(":spring-web"))
|
||||
@@ -618,6 +639,7 @@ project("spring-webmvc-tiles3") {
|
||||
|
||||
project("spring-webmvc-portlet") {
|
||||
description = "Spring Web Portlet"
|
||||
|
||||
dependencies {
|
||||
provided("javax.servlet:servlet-api:2.5")
|
||||
provided("javax.portlet:portlet-api:2.0")
|
||||
@@ -695,11 +717,9 @@ project("spring-test-mvc") {
|
||||
testCompile(project(":spring-context-support"))
|
||||
testCompile(project(":spring-oxm"))
|
||||
testCompile("com.thoughtworks.xstream:xstream:1.3.1")
|
||||
testCompile("cglib:cglib-nodep:2.2")
|
||||
testCompile("rome:rome:1.0")
|
||||
testCompile("javax.activation:activation:1.1")
|
||||
testCompile("javax.mail:mail:1.4")
|
||||
testCompile("javax.xml.bind:jaxb-api:2.2.6")
|
||||
testCompile("org.apache.tiles:tiles-request-api:1.0.1")
|
||||
testCompile("org.apache.tiles:tiles-api:3.0.1")
|
||||
testCompile("org.apache.tiles:tiles-core:3.0.1") {
|
||||
@@ -730,6 +750,7 @@ project("spring-struts") {
|
||||
project("spring-aspects") {
|
||||
description = "Spring Aspects"
|
||||
apply from: "aspects.gradle"
|
||||
|
||||
dependencies {
|
||||
optional(project(":spring-beans")) // for @Configurable support
|
||||
optional(project(":spring-aop")) // for @Async support
|
||||
@@ -747,6 +768,7 @@ project("spring-aspects") {
|
||||
compile(project(":spring-beans")) // for "p" namespace visibility
|
||||
testCompile(project(":spring-test"))
|
||||
}
|
||||
|
||||
eclipse.project {
|
||||
natures += "org.eclipse.ajdt.ui.ajnature"
|
||||
buildCommands = [new org.gradle.plugins.ide.eclipse.model.
|
||||
@@ -759,7 +781,7 @@ configure(rootProject) {
|
||||
|
||||
apply plugin: "docbook-reference"
|
||||
apply plugin: "groovy"
|
||||
apply plugin: "detect-split-packages"
|
||||
// apply plugin: "detect-split-packages"
|
||||
apply from: "${gradleScriptDir}/jdiff.gradle"
|
||||
|
||||
reference {
|
||||
@@ -767,9 +789,11 @@ configure(rootProject) {
|
||||
pdfFilename = "spring-framework-reference.pdf"
|
||||
}
|
||||
|
||||
detectSplitPackages {
|
||||
projectsToScan -= project(":spring-instrument-tomcat")
|
||||
}
|
||||
// TODO: DetectSplitPackagesPlugin fails in line 154 due to method not found on java.io.File.
|
||||
// TODO: Possibly related to user rights or OS differences on OpenJDK 8; works fine on JDK 7.
|
||||
// detectSplitPackages {
|
||||
// projectsToScan -= project(":spring-instrument-tomcat")
|
||||
// }
|
||||
|
||||
// don't publish the default jar for the root project
|
||||
configurations.archives.artifacts.clear()
|
||||
@@ -786,7 +810,7 @@ configure(rootProject) {
|
||||
testCompile(project(":spring-web"))
|
||||
testCompile(project(":spring-webmvc-portlet"))
|
||||
testCompile(project(":spring-orm"))
|
||||
testCompile("org.hibernate:hibernate-core:4.1.0.Final")
|
||||
testCompile("org.hibernate:hibernate-core:4.1.9.Final")
|
||||
testCompile("javax.servlet:servlet-api:2.5")
|
||||
testCompile("javax.portlet:portlet-api:2.0")
|
||||
testCompile("javax.inject:javax.inject:1")
|
||||
@@ -812,6 +836,9 @@ configure(rootProject) {
|
||||
options.stylesheetFile = file("src/api/stylesheet.css")
|
||||
options.splitIndex = true
|
||||
options.links(project.ext.javadocLinks)
|
||||
if(JavaVersion.current().isJava8Compatible()) {
|
||||
options.addStringOption('Xdoclint:none', '-quiet')
|
||||
}
|
||||
|
||||
source subprojects.collect { project ->
|
||||
project.sourceSets.main.allJava
|
||||
@@ -822,7 +849,7 @@ configure(rootProject) {
|
||||
|
||||
doFirst {
|
||||
classpath = files(
|
||||
// ensure servlet 3.x and Hibernate 4.x have precedence on the Javadoc
|
||||
// ensure Servlet 3.x and Hibernate 4.x have precedence on the Javadoc
|
||||
// classpath over their respective 2.5 and 3.x variants
|
||||
project(":spring-webmvc").sourceSets.main.compileClasspath.files.find { it =~ "servlet-api" },
|
||||
rootProject.sourceSets.test.compileClasspath.files.find { it =~ "hibernate-core" },
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
version=3.2.3.BUILD-SNAPSHOT
|
||||
version=3.2.3.RELEASE
|
||||
|
||||
+12
-14
@@ -45,43 +45,41 @@ public class AspectJWeaverMessageHandler implements IMessageHandler {
|
||||
|
||||
private static final String AJ_ID = "[AspectJ] ";
|
||||
|
||||
private static final Log LOGGER = LogFactory.getLog("AspectJ Weaver");
|
||||
private static final Log logger = LogFactory.getLog("AspectJ Weaver");
|
||||
|
||||
|
||||
public boolean handleMessage(IMessage message) throws AbortException {
|
||||
Kind messageKind = message.getKind();
|
||||
|
||||
if (messageKind == IMessage.DEBUG) {
|
||||
if (LOGGER.isDebugEnabled() || LOGGER.isTraceEnabled()) {
|
||||
LOGGER.debug(makeMessageFor(message));
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(makeMessageFor(message));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if ((messageKind == IMessage.INFO) || (messageKind == IMessage.WEAVEINFO)) {
|
||||
if (LOGGER.isInfoEnabled()) {
|
||||
LOGGER.info(makeMessageFor(message));
|
||||
else if (messageKind == IMessage.INFO || messageKind == IMessage.WEAVEINFO) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info(makeMessageFor(message));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (messageKind == IMessage.WARNING) {
|
||||
if (LOGGER.isWarnEnabled()) {
|
||||
LOGGER.warn(makeMessageFor(message));
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn(makeMessageFor(message));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (messageKind == IMessage.ERROR) {
|
||||
if (LOGGER.isErrorEnabled()) {
|
||||
LOGGER.error(makeMessageFor(message));
|
||||
if (logger.isErrorEnabled()) {
|
||||
logger.error(makeMessageFor(message));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (messageKind == IMessage.ABORT) {
|
||||
if (LOGGER.isFatalEnabled()) {
|
||||
LOGGER.fatal(makeMessageFor(message));
|
||||
if (logger.isFatalEnabled()) {
|
||||
logger.fatal(makeMessageFor(message));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.aop.aspectj.annotation;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@@ -105,7 +106,7 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
|
||||
if (Ordered.class.isAssignableFrom(type) && this.beanFactory.isSingleton(this.name)) {
|
||||
return ((Ordered) this.beanFactory.getBean(this.name)).getOrder();
|
||||
}
|
||||
Order order = type.getAnnotation(Order.class);
|
||||
Order order = AnnotationUtils.findAnnotation(type, Order.class);
|
||||
if (order != null) {
|
||||
return order.value();
|
||||
}
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,7 @@ package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import org.springframework.aop.aspectj.SimpleAspectInstanceFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.Order;
|
||||
|
||||
/**
|
||||
@@ -58,7 +59,7 @@ public class SimpleMetadataAwareAspectInstanceFactory extends SimpleAspectInstan
|
||||
*/
|
||||
@Override
|
||||
protected int getOrderForAspectClass(Class<?> aspectClass) {
|
||||
Order order = aspectClass.getAnnotation(Order.class);
|
||||
Order order = AnnotationUtils.findAnnotation(aspectClass, Order.class);
|
||||
if (order != null) {
|
||||
return order.value();
|
||||
}
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,7 @@ package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import org.springframework.aop.aspectj.SingletonAspectInstanceFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.Order;
|
||||
|
||||
/**
|
||||
@@ -59,7 +60,7 @@ public class SingletonMetadataAwareAspectInstanceFactory extends SingletonAspect
|
||||
*/
|
||||
@Override
|
||||
protected int getOrderForAspectClass(Class<?> aspectClass) {
|
||||
Order order = aspectClass.getAnnotation(Order.class);
|
||||
Order order = AnnotationUtils.findAnnotation(aspectClass, Order.class);
|
||||
if (order != null) {
|
||||
return order.value();
|
||||
}
|
||||
|
||||
+9
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -58,15 +58,19 @@ public class AnnotatedGenericBeanDefinition extends GenericBeanDefinition implem
|
||||
* allowing for ASM-based processing and avoidance of early loading of the bean class.
|
||||
* Note that this constructor is functionally equivalent to
|
||||
* {@link org.springframework.context.annotation.ScannedGenericBeanDefinition
|
||||
* ScannedGenericBeanDefinition}, however the semantics of the latter indicate that
|
||||
* a bean was discovered specifically via component-scanning as opposed to other
|
||||
* means.
|
||||
* ScannedGenericBeanDefinition}, however the semantics of the latter indicate that a
|
||||
* bean was discovered specifically via component-scanning as opposed to other means.
|
||||
* @param metadata the annotation metadata for the bean class in question
|
||||
* @since 3.1.1
|
||||
*/
|
||||
public AnnotatedGenericBeanDefinition(AnnotationMetadata metadata) {
|
||||
Assert.notNull(metadata, "AnnotationMetadata must not be null");
|
||||
setBeanClassName(metadata.getClassName());
|
||||
if (metadata instanceof StandardAnnotationMetadata) {
|
||||
setBeanClass(((StandardAnnotationMetadata) metadata).getIntrospectedClass());
|
||||
}
|
||||
else {
|
||||
setBeanClassName(metadata.getClassName());
|
||||
}
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -185,7 +185,7 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
|
||||
* @see #AUTOWIRE_BY_TYPE
|
||||
* @see #AUTOWIRE_CONSTRUCTOR
|
||||
*/
|
||||
Object createBean(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
|
||||
Object createBean(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
|
||||
|
||||
/**
|
||||
* Instantiate a new bean instance of the given class with the specified autowire
|
||||
@@ -213,7 +213,7 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
|
||||
* @see #applyBeanPostProcessorsBeforeInitialization
|
||||
* @see #applyBeanPostProcessorsAfterInitialization
|
||||
*/
|
||||
Object autowire(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
|
||||
Object autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
|
||||
|
||||
/**
|
||||
* Autowire the bean properties of the given bean instance by name or type.
|
||||
|
||||
+25
-31
@@ -171,6 +171,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
setParentBeanFactory(parentBeanFactory);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the instantiation strategy to use for creating bean instances.
|
||||
* Default is CglibSubclassingInstantiationStrategy.
|
||||
@@ -243,7 +244,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
* Ignore the given dependency type for autowiring:
|
||||
* for example, String. Default is none.
|
||||
*/
|
||||
public void ignoreDependencyType(Class type) {
|
||||
public void ignoreDependencyType(Class<?> type) {
|
||||
this.ignoredDependencyTypes.add(type);
|
||||
}
|
||||
|
||||
@@ -257,11 +258,10 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
* @see org.springframework.beans.factory.BeanFactoryAware
|
||||
* @see org.springframework.context.ApplicationContextAware
|
||||
*/
|
||||
public void ignoreDependencyInterface(Class ifc) {
|
||||
public void ignoreDependencyInterface(Class<?> ifc) {
|
||||
this.ignoredDependencyInterfaces.add(ifc);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) {
|
||||
super.copyConfigurationFrom(otherFactory);
|
||||
@@ -305,12 +305,12 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
RootBeanDefinition bd = null;
|
||||
if (mbd instanceof RootBeanDefinition) {
|
||||
RootBeanDefinition rbd = (RootBeanDefinition) mbd;
|
||||
if (rbd.isPrototype()) {
|
||||
bd = rbd;
|
||||
}
|
||||
bd = (rbd.isPrototype() ? rbd : rbd.cloneBeanDefinition());
|
||||
}
|
||||
if (bd == null) {
|
||||
bd = new RootBeanDefinition(mbd);
|
||||
if (!mbd.isPrototype()) {
|
||||
if (bd == null) {
|
||||
bd = new RootBeanDefinition(mbd);
|
||||
}
|
||||
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
|
||||
bd.allowCaching = false;
|
||||
}
|
||||
@@ -329,14 +329,14 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
// Specialized methods for fine-grained control over the bean lifecycle
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
public Object createBean(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException {
|
||||
public Object createBean(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException {
|
||||
// Use non-singleton bean definition, to avoid registering bean as dependent bean.
|
||||
RootBeanDefinition bd = new RootBeanDefinition(beanClass, autowireMode, dependencyCheck);
|
||||
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
|
||||
return createBean(beanClass.getName(), bd, null);
|
||||
}
|
||||
|
||||
public Object autowire(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException {
|
||||
public Object autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException {
|
||||
// Use non-singleton bean definition, to avoid registering bean as dependent bean.
|
||||
final RootBeanDefinition bd = new RootBeanDefinition(beanClass, autowireMode, dependencyCheck);
|
||||
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
|
||||
@@ -346,10 +346,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
else {
|
||||
Object bean;
|
||||
final BeanFactory parent = this;
|
||||
|
||||
if (System.getSecurityManager() != null) {
|
||||
bean = AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||
|
||||
public Object run() {
|
||||
return getInstantiationStrategy().instantiate(bd, null, parent);
|
||||
}
|
||||
@@ -358,7 +356,6 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
else {
|
||||
bean = getInstantiationStrategy().instantiate(bd, null, parent);
|
||||
}
|
||||
|
||||
populateBean(beanClass.getName(), bd, new BeanWrapperImpl(bean));
|
||||
return bean;
|
||||
}
|
||||
@@ -490,7 +487,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
instanceWrapper = createBeanInstance(beanName, mbd, args);
|
||||
}
|
||||
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
|
||||
Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
|
||||
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
|
||||
|
||||
// Allow post-processors to modify the merged bean definition.
|
||||
synchronized (mbd.postProcessingLock) {
|
||||
@@ -587,7 +584,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
for (BeanPostProcessor bp : getBeanPostProcessors()) {
|
||||
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
|
||||
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
|
||||
Class predicted = ibp.predictBeanType(targetType, beanName);
|
||||
Class<?> predicted = ibp.predictBeanType(targetType, beanName);
|
||||
if (predicted != null && (typesToMatch.length != 1 || !FactoryBean.class.equals(typesToMatch[0]) ||
|
||||
FactoryBean.class.isAssignableFrom(predicted))) {
|
||||
return predicted;
|
||||
@@ -688,22 +685,19 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
// Try to obtain the FactoryBean's object type without instantiating it at all.
|
||||
BeanDefinition fbDef = getBeanDefinition(factoryBeanName);
|
||||
if (fbDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) fbDef).hasBeanClass()) {
|
||||
Class<?> fbClass = ((AbstractBeanDefinition) fbDef).getBeanClass();
|
||||
if (ClassUtils.isCglibProxyClass(fbClass)) {
|
||||
// CGLIB subclass methods hide generic parameters. look at the superclass.
|
||||
fbClass = fbClass.getSuperclass();
|
||||
}
|
||||
// CGLIB subclass methods hide generic parameters; look at the original user class.
|
||||
Class<?> fbClass = ClassUtils.getUserClass(((AbstractBeanDefinition) fbDef).getBeanClass());
|
||||
// Find the given factory method, taking into account that in the case of
|
||||
// @Bean methods, there may be parameters present.
|
||||
ReflectionUtils.doWithMethods(fbClass,
|
||||
new ReflectionUtils.MethodCallback() {
|
||||
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
|
||||
if (method.getName().equals(factoryMethodName) &&
|
||||
FactoryBean.class.isAssignableFrom(method.getReturnType())) {
|
||||
objectType.value = GenericTypeResolver.resolveReturnTypeArgument(method, FactoryBean.class);
|
||||
new ReflectionUtils.MethodCallback() {
|
||||
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
|
||||
if (method.getName().equals(factoryMethodName) &&
|
||||
FactoryBean.class.isAssignableFrom(method.getReturnType())) {
|
||||
objectType.value = GenericTypeResolver.resolveReturnTypeArgument(method, FactoryBean.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
if (objectType.value != null) {
|
||||
return objectType.value;
|
||||
}
|
||||
@@ -836,7 +830,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
* @throws BeansException if any post-processing failed
|
||||
* @see MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
|
||||
*/
|
||||
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class beanType, String beanName)
|
||||
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName)
|
||||
throws BeansException {
|
||||
|
||||
try {
|
||||
@@ -887,7 +881,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
* @throws BeansException if any post-processing failed
|
||||
* @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
|
||||
*/
|
||||
protected Object applyBeanPostProcessorsBeforeInstantiation(Class beanClass, String beanName)
|
||||
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName)
|
||||
throws BeansException {
|
||||
|
||||
for (BeanPostProcessor bp : getBeanPostProcessors()) {
|
||||
@@ -916,7 +910,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
*/
|
||||
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
|
||||
// Make sure bean class is actually resolved at this point.
|
||||
Class beanClass = resolveBeanClass(mbd, beanName);
|
||||
Class<?> beanClass = resolveBeanClass(mbd, beanName);
|
||||
|
||||
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
|
||||
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
|
||||
@@ -968,7 +962,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
* @throws org.springframework.beans.BeansException in case of errors
|
||||
* @see org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors
|
||||
*/
|
||||
protected Constructor[] determineConstructorsFromBeanPostProcessors(Class beanClass, String beanName)
|
||||
protected Constructor[] determineConstructorsFromBeanPostProcessors(Class<?> beanClass, String beanName)
|
||||
throws BeansException {
|
||||
|
||||
if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -54,7 +54,7 @@ public abstract class AbstractBeanDefinitionReader implements EnvironmentCapable
|
||||
|
||||
private ClassLoader beanClassLoader;
|
||||
|
||||
private Environment environment = new StandardEnvironment();
|
||||
private Environment environment;
|
||||
|
||||
private BeanNameGenerator beanNameGenerator = new DefaultBeanNameGenerator();
|
||||
|
||||
@@ -90,7 +90,7 @@ public abstract class AbstractBeanDefinitionReader implements EnvironmentCapable
|
||||
|
||||
// Inherit Environment if possible
|
||||
if (this.registry instanceof EnvironmentCapable) {
|
||||
this.environment = ((EnvironmentCapable)this.registry).getEnvironment();
|
||||
this.environment = ((EnvironmentCapable) this.registry).getEnvironment();
|
||||
}
|
||||
else {
|
||||
this.environment = new StandardEnvironment();
|
||||
|
||||
+19
-13
@@ -511,26 +511,32 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
}
|
||||
}
|
||||
|
||||
Class<?> beanClass = predictBeanType(beanName, mbd, typesToMatch);
|
||||
if (beanClass == null) {
|
||||
Class<?> beanType = predictBeanType(beanName, mbd, typesToMatch);
|
||||
if (beanType == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check bean class whether we're dealing with a FactoryBean.
|
||||
if (FactoryBean.class.isAssignableFrom(beanClass)) {
|
||||
if (FactoryBean.class.isAssignableFrom(beanType)) {
|
||||
if (!BeanFactoryUtils.isFactoryDereference(name)) {
|
||||
// If it's a FactoryBean, we want to look at what it creates, not the factory class.
|
||||
Class<?> type = getTypeForFactoryBean(beanName, mbd);
|
||||
return (type != null && typeToMatch.isAssignableFrom(type));
|
||||
}
|
||||
else {
|
||||
return typeToMatch.isAssignableFrom(beanClass);
|
||||
beanType = getTypeForFactoryBean(beanName, mbd);
|
||||
if (beanType == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return !BeanFactoryUtils.isFactoryDereference(name) &&
|
||||
typeToMatch.isAssignableFrom(beanClass);
|
||||
else if (BeanFactoryUtils.isFactoryDereference(name)) {
|
||||
// Special case: A SmartInstantiationAwareBeanPostProcessor returned a non-FactoryBean
|
||||
// type but we nevertheless are being asked to dereference a FactoryBean...
|
||||
// Let's check the original bean class and proceed with it if it is a FactoryBean.
|
||||
beanType = predictBeanType(beanName, mbd, FactoryBean.class);
|
||||
if (beanType == null || !FactoryBean.class.isAssignableFrom(beanType)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return typeToMatch.isAssignableFrom(beanType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1335,8 +1341,8 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
* @param mbd the corresponding bean definition
|
||||
*/
|
||||
protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {
|
||||
Class<?> beanClass = predictBeanType(beanName, mbd, FactoryBean.class);
|
||||
return (beanClass != null && FactoryBean.class.isAssignableFrom(beanClass));
|
||||
Class<?> beanType = predictBeanType(beanName, mbd, FactoryBean.class);
|
||||
return (beanType != null && FactoryBean.class.isAssignableFrom(beanType));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.beans.factory.support;
|
||||
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
@@ -98,7 +97,7 @@ public class ChildBeanDefinition extends AbstractBeanDefinition {
|
||||
* @param pvs the property values to apply
|
||||
*/
|
||||
public ChildBeanDefinition(
|
||||
String parentName, Class beanClass, ConstructorArgumentValues cargs, MutablePropertyValues pvs) {
|
||||
String parentName, Class<?> beanClass, ConstructorArgumentValues cargs, MutablePropertyValues pvs) {
|
||||
|
||||
super(cargs, pvs);
|
||||
this.parentName = parentName;
|
||||
@@ -128,7 +127,7 @@ public class ChildBeanDefinition extends AbstractBeanDefinition {
|
||||
* @param original the original bean definition to copy from
|
||||
*/
|
||||
public ChildBeanDefinition(ChildBeanDefinition original) {
|
||||
super((BeanDefinition) original);
|
||||
super(original);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+8
-11
@@ -107,7 +107,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
* Create a new RootBeanDefinition for a singleton.
|
||||
* @param beanClass the class of the bean to instantiate
|
||||
*/
|
||||
public RootBeanDefinition(Class beanClass) {
|
||||
public RootBeanDefinition(Class<?> beanClass) {
|
||||
super();
|
||||
setBeanClass(beanClass);
|
||||
}
|
||||
@@ -147,7 +147,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
* @param dependencyCheck whether to perform a dependency check for objects
|
||||
* (not applicable to autowiring a constructor, thus ignored there)
|
||||
*/
|
||||
public RootBeanDefinition(Class beanClass, int autowireMode, boolean dependencyCheck) {
|
||||
public RootBeanDefinition(Class<?> beanClass, int autowireMode, boolean dependencyCheck) {
|
||||
super();
|
||||
setBeanClass(beanClass);
|
||||
setAutowireMode(autowireMode);
|
||||
@@ -191,7 +191,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
* @param cargs the constructor argument values to apply
|
||||
* @param pvs the property values to apply
|
||||
*/
|
||||
public RootBeanDefinition(Class beanClass, ConstructorArgumentValues cargs, MutablePropertyValues pvs) {
|
||||
public RootBeanDefinition(Class<?> beanClass, ConstructorArgumentValues cargs, MutablePropertyValues pvs) {
|
||||
super(cargs, pvs);
|
||||
setBeanClass(beanClass);
|
||||
}
|
||||
@@ -225,7 +225,11 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
* @param original the original bean definition to copy from
|
||||
*/
|
||||
public RootBeanDefinition(RootBeanDefinition original) {
|
||||
this((BeanDefinition) original);
|
||||
super(original);
|
||||
this.decoratedDefinition = original.decoratedDefinition;
|
||||
this.allowCaching = original.allowCaching;
|
||||
this.targetType = original.targetType;
|
||||
this.isFactoryMethodUnique = original.isFactoryMethodUnique;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -235,13 +239,6 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
*/
|
||||
RootBeanDefinition(BeanDefinition original) {
|
||||
super(original);
|
||||
if (original instanceof RootBeanDefinition) {
|
||||
RootBeanDefinition originalRbd = (RootBeanDefinition) original;
|
||||
this.decoratedDefinition = originalRbd.decoratedDefinition;
|
||||
this.allowCaching = originalRbd.allowCaching;
|
||||
this.targetType = originalRbd.targetType;
|
||||
this.isFactoryMethodUnique = originalRbd.isFactoryMethodUnique;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+5
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -78,9 +78,12 @@ public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ResourceEditorRegistrar for the given ResourceLoader
|
||||
* Create a new ResourceEditorRegistrar for the given {@link ResourceLoader}
|
||||
* and {@link PropertyResolver}.
|
||||
* @param resourceLoader the ResourceLoader (or ResourcePatternResolver)
|
||||
* to create editors for (usually an ApplicationContext)
|
||||
* @param propertyResolver the PropertyResolver (usually an Environment)
|
||||
* @see org.springframework.core.env.Environment
|
||||
* @see org.springframework.core.io.support.ResourcePatternResolver
|
||||
* @see org.springframework.context.ApplicationContext
|
||||
*/
|
||||
|
||||
+14
@@ -712,6 +712,20 @@ public class DefaultListableBeanFactoryTests {
|
||||
factory.getMergedBeanDefinition("child"), factory.getMergedBeanDefinition("child"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTypeWorksAfterParentChildMerging() {
|
||||
RootBeanDefinition parentDefinition = new RootBeanDefinition(TestBean.class);
|
||||
ChildBeanDefinition childDefinition = new ChildBeanDefinition("parent", DerivedTestBean.class, null, null);
|
||||
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
factory.registerBeanDefinition("parent", parentDefinition);
|
||||
factory.registerBeanDefinition("child", childDefinition);
|
||||
factory.freezeConfiguration();
|
||||
|
||||
assertEquals(TestBean.class, factory.getType("parent"));
|
||||
assertEquals(DerivedTestBean.class, factory.getType("child"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNameAlreadyBound() {
|
||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||
|
||||
+37
-25
@@ -16,59 +16,59 @@
|
||||
|
||||
package org.springframework.beans.factory.support;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
|
||||
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Unit tests for SPR-8954, in which a custom {@link InstantiationAwareBeanPostProcessor}
|
||||
* forces the predicted type of a FactoryBean, effectively preventing retrieval of the
|
||||
* bean from calls to #getBeansOfType(FactoryBean.class). The implementation of
|
||||
* {@link AbstractBeanFactory#isFactoryBean(String, RootBeanDefinition)} now ensures
|
||||
* that not only the predicted bean type is considered, but also the original bean
|
||||
* definition's beanClass.
|
||||
* {@link AbstractBeanFactory#isFactoryBean(String, RootBeanDefinition)} now ensures that
|
||||
* not only the predicted bean type is considered, but also the original bean definition's
|
||||
* beanClass.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class Spr8954Tests {
|
||||
|
||||
@Test
|
||||
public void repro() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
private DefaultListableBeanFactory bf;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
bf = new DefaultListableBeanFactory();
|
||||
bf.registerBeanDefinition("foo", new RootBeanDefinition(FooFactoryBean.class));
|
||||
bf.addBeanPostProcessor(new PredictingBPP());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void repro() {
|
||||
assertThat(bf.getBean("foo"), instanceOf(Foo.class));
|
||||
assertThat(bf.getBean("&foo"), instanceOf(FooFactoryBean.class));
|
||||
|
||||
assertThat(bf.isTypeMatch("&foo", FactoryBean.class), is(true));
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
Map<String, FactoryBean> fbBeans = bf.getBeansOfType(FactoryBean.class);
|
||||
assertThat(1, equalTo(fbBeans.size()));
|
||||
assertThat("&foo", equalTo(fbBeans.keySet().iterator().next()));
|
||||
assertThat(fbBeans.size(), is(1));
|
||||
assertThat(fbBeans.keySet(), hasItem("&foo"));
|
||||
|
||||
Map<String, AnInterface> aiBeans = bf.getBeansOfType(AnInterface.class);
|
||||
assertThat(1, equalTo(aiBeans.size()));
|
||||
assertThat("&foo", equalTo(aiBeans.keySet().iterator().next()));
|
||||
assertThat(aiBeans.size(), is(1));
|
||||
assertThat(aiBeans.keySet(), hasItem("&foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findsBeansByTypeIfNotInstantiated() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.registerBeanDefinition("foo", new RootBeanDefinition(FooFactoryBean.class));
|
||||
bf.addBeanPostProcessor(new PredictingBPP());
|
||||
|
||||
assertThat(bf.isTypeMatch("&foo", FactoryBean.class), is(true));
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@@ -77,8 +77,21 @@ public class Spr8954Tests {
|
||||
assertThat("&foo", equalTo(fbBeans.keySet().iterator().next()));
|
||||
|
||||
Map<String, AnInterface> aiBeans = bf.getBeansOfType(AnInterface.class);
|
||||
assertThat(1, equalTo(aiBeans.size()));
|
||||
assertThat("&foo", equalTo(aiBeans.keySet().iterator().next()));
|
||||
assertThat(aiBeans.size(), is(1));
|
||||
assertThat(aiBeans.keySet(), hasItem("&foo"));
|
||||
}
|
||||
|
||||
/**
|
||||
* SPR-10517
|
||||
*/
|
||||
@Test
|
||||
public void findsFactoryBeanNameByTypeWithoutInstantiation() {
|
||||
String[] names = bf.getBeanNamesForType(AnInterface.class, false, false);
|
||||
assertThat(Arrays.asList(names), hasItem("&foo"));
|
||||
|
||||
Map<String, AnInterface> beans = bf.getBeansOfType(AnInterface.class, false, false);
|
||||
assertThat(beans.size(), is(1));
|
||||
assertThat(beans.keySet(), hasItem("&foo"));
|
||||
}
|
||||
|
||||
|
||||
@@ -116,8 +129,7 @@ public class Spr8954Tests {
|
||||
|
||||
@Override
|
||||
public Class<?> predictBeanType(Class<?> beanClass, String beanName) {
|
||||
return FactoryBean.class.isAssignableFrom(beanClass) ?
|
||||
PredictedType.class : null;
|
||||
return FactoryBean.class.isAssignableFrom(beanClass) ? PredictedType.class : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+16
-15
@@ -29,7 +29,7 @@ import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.InputStreamResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* @author Rick Evans
|
||||
@@ -38,13 +38,13 @@ import org.springframework.tests.sample.beans.TestBean;
|
||||
public class XmlBeanDefinitionReaderTests extends TestCase {
|
||||
|
||||
public void testSetParserClassSunnyDay() {
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
|
||||
new XmlBeanDefinitionReader(registry).setDocumentReaderClass(DefaultBeanDefinitionDocumentReader.class);
|
||||
}
|
||||
|
||||
public void testSetParserClassToNull() {
|
||||
try {
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
|
||||
new XmlBeanDefinitionReader(registry).setDocumentReaderClass(null);
|
||||
fail("Should have thrown IllegalArgumentException (null parserClass)");
|
||||
}
|
||||
@@ -54,7 +54,7 @@ public class XmlBeanDefinitionReaderTests extends TestCase {
|
||||
|
||||
public void testSetParserClassToUnsupportedParserType() throws Exception {
|
||||
try {
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
|
||||
new XmlBeanDefinitionReader(registry).setDocumentReaderClass(String.class);
|
||||
fail("Should have thrown IllegalArgumentException (unsupported parserClass)");
|
||||
}
|
||||
@@ -64,7 +64,7 @@ public class XmlBeanDefinitionReaderTests extends TestCase {
|
||||
|
||||
public void testWithOpenInputStream() {
|
||||
try {
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
|
||||
Resource resource = new InputStreamResource(getClass().getResourceAsStream("test.xml"));
|
||||
new XmlBeanDefinitionReader(registry).loadBeanDefinitions(resource);
|
||||
fail("Should have thrown BeanDefinitionStoreException (can't determine validation mode)");
|
||||
@@ -74,7 +74,7 @@ public class XmlBeanDefinitionReaderTests extends TestCase {
|
||||
}
|
||||
|
||||
public void testWithOpenInputStreamAndExplicitValidationMode() {
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
|
||||
Resource resource = new InputStreamResource(getClass().getResourceAsStream("test.xml"));
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(registry);
|
||||
reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_DTD);
|
||||
@@ -83,14 +83,14 @@ public class XmlBeanDefinitionReaderTests extends TestCase {
|
||||
}
|
||||
|
||||
public void testWithImport() {
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
|
||||
Resource resource = new ClassPathResource("import.xml", getClass());
|
||||
new XmlBeanDefinitionReader(registry).loadBeanDefinitions(resource);
|
||||
testBeanDefinitions(registry);
|
||||
}
|
||||
|
||||
public void testWithWildcardImport() {
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
|
||||
Resource resource = new ClassPathResource("importPattern.xml", getClass());
|
||||
new XmlBeanDefinitionReader(registry).loadBeanDefinitions(resource);
|
||||
testBeanDefinitions(registry);
|
||||
@@ -98,7 +98,7 @@ public class XmlBeanDefinitionReaderTests extends TestCase {
|
||||
|
||||
public void testWithInputSource() {
|
||||
try {
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
|
||||
InputSource resource = new InputSource(getClass().getResourceAsStream("test.xml"));
|
||||
new XmlBeanDefinitionReader(registry).loadBeanDefinitions(resource);
|
||||
fail("Should have thrown BeanDefinitionStoreException (can't determine validation mode)");
|
||||
@@ -108,7 +108,7 @@ public class XmlBeanDefinitionReaderTests extends TestCase {
|
||||
}
|
||||
|
||||
public void testWithInputSourceAndExplicitValidationMode() {
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
|
||||
InputSource resource = new InputSource(getClass().getResourceAsStream("test.xml"));
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(registry);
|
||||
reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_DTD);
|
||||
@@ -117,7 +117,7 @@ public class XmlBeanDefinitionReaderTests extends TestCase {
|
||||
}
|
||||
|
||||
public void testWithFreshInputStream() {
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
|
||||
SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
|
||||
Resource resource = new ClassPathResource("test.xml", getClass());
|
||||
new XmlBeanDefinitionReader(registry).loadBeanDefinitions(resource);
|
||||
testBeanDefinitions(registry);
|
||||
@@ -133,9 +133,10 @@ public class XmlBeanDefinitionReaderTests extends TestCase {
|
||||
assertEquals(TestBean.class.getName(), registry.getBeanDefinition("rod").getBeanClassName());
|
||||
assertEquals(TestBean.class.getName(), registry.getBeanDefinition("aliased").getBeanClassName());
|
||||
assertTrue(registry.isAlias("youralias"));
|
||||
assertEquals(2, registry.getAliases("aliased").length);
|
||||
assertEquals("myalias", registry.getAliases("aliased")[0]);
|
||||
assertEquals("youralias", registry.getAliases("aliased")[1]);
|
||||
String[] aliases = registry.getAliases("aliased");
|
||||
assertEquals(2, aliases.length);
|
||||
assertTrue(ObjectUtils.containsElement(aliases, "myalias"));
|
||||
assertTrue(ObjectUtils.containsElement(aliases, "youralias"));
|
||||
}
|
||||
|
||||
public void testDtdValidationAutodetect() throws Exception {
|
||||
@@ -147,7 +148,7 @@ public class XmlBeanDefinitionReaderTests extends TestCase {
|
||||
}
|
||||
|
||||
private void doTestValidation(String resourceName) throws Exception {
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();;
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
Resource resource = new ClassPathResource(resourceName, getClass());
|
||||
new XmlBeanDefinitionReader(factory).loadBeanDefinitions(resource);
|
||||
TestBean bean = (TestBean) factory.getBean("testBean");
|
||||
|
||||
+11
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -90,7 +90,7 @@ public class ClassPathScanningCandidateComponentProvider implements EnvironmentC
|
||||
|
||||
|
||||
/**
|
||||
* Create a ClassPathScanningCandidateComponentProvider.
|
||||
* Create a ClassPathScanningCandidateComponentProvider with a {@link StandardEnvironment}.
|
||||
* @param useDefaultFilters whether to register the default filters for the
|
||||
* {@link Component @Component}, {@link Repository @Repository},
|
||||
* {@link Service @Service}, and {@link Controller @Controller}
|
||||
@@ -101,6 +101,15 @@ public class ClassPathScanningCandidateComponentProvider implements EnvironmentC
|
||||
this(useDefaultFilters, new StandardEnvironment());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ClassPathScanningCandidateComponentProvider with the given {@link Environment}.
|
||||
* @param useDefaultFilters whether to register the default filters for the
|
||||
* {@link Component @Component}, {@link Repository @Repository},
|
||||
* {@link Service @Service}, and {@link Controller @Controller}
|
||||
* stereotype annotations
|
||||
* @param environment the Environment to use
|
||||
* @see #registerDefaultFilters()
|
||||
*/
|
||||
public ClassPathScanningCandidateComponentProvider(boolean useDefaultFilters, Environment environment) {
|
||||
if (useDefaultFilters) {
|
||||
registerDefaultFilters();
|
||||
|
||||
+39
-42
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,8 +36,8 @@ import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Represents a user-defined {@link Configuration @Configuration} class.
|
||||
* Includes a set of {@link Bean} methods, including all such methods defined in the
|
||||
* ancestry of the class, in a 'flattened-out' manner.
|
||||
* Includes a set of {@link Bean} methods, including all such methods
|
||||
* defined in the ancestry of the class, in a 'flattened-out' manner.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Juergen Hoeller
|
||||
@@ -51,15 +51,15 @@ final class ConfigurationClass {
|
||||
|
||||
private final Resource resource;
|
||||
|
||||
private final Map<String, Class<? extends BeanDefinitionReader>> importedResources =
|
||||
new LinkedHashMap<String, Class<? extends BeanDefinitionReader>>();
|
||||
|
||||
private final Set<BeanMethod> beanMethods = new LinkedHashSet<BeanMethod>();
|
||||
|
||||
private String beanName;
|
||||
|
||||
private final boolean imported;
|
||||
|
||||
private final Set<BeanMethod> beanMethods = new LinkedHashSet<BeanMethod>();
|
||||
|
||||
private final Map<String, Class<? extends BeanDefinitionReader>> importedResources =
|
||||
new LinkedHashMap<String, Class<? extends BeanDefinitionReader>>();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@link ConfigurationClass} with the given name.
|
||||
@@ -81,7 +81,7 @@ final class ConfigurationClass {
|
||||
* using the {@link Import} annotation or automatically processed as a nested
|
||||
* configuration class (if imported is {@code true}).
|
||||
* @param metadataReader reader used to parse the underlying {@link Class}
|
||||
* @param beanName name of the {@code @Configuration} class bean
|
||||
* @param imported whether the given configuration class is being imported
|
||||
* @since 3.1.1
|
||||
*/
|
||||
public ConfigurationClass(MetadataReader metadataReader, boolean imported) {
|
||||
@@ -98,7 +98,7 @@ final class ConfigurationClass {
|
||||
* @see ConfigurationClass#ConfigurationClass(Class, boolean)
|
||||
*/
|
||||
public ConfigurationClass(Class<?> clazz, String beanName) {
|
||||
Assert.hasText(beanName, "bean name must not be null");
|
||||
Assert.hasText(beanName, "Bean name must not be null");
|
||||
this.metadata = new StandardAnnotationMetadata(clazz, true);
|
||||
this.resource = new DescriptiveResource(clazz.toString());
|
||||
this.beanName = beanName;
|
||||
@@ -110,7 +110,7 @@ final class ConfigurationClass {
|
||||
* using the {@link Import} annotation or automatically processed as a nested
|
||||
* configuration class (if imported is {@code true}).
|
||||
* @param clazz the underlying {@link Class} to represent
|
||||
* @param beanName name of the {@code @Configuration} class bean
|
||||
* @param imported whether the given configuration class is being imported
|
||||
* @since 3.1.1
|
||||
*/
|
||||
public ConfigurationClass(Class<?> clazz, boolean imported) {
|
||||
@@ -119,6 +119,7 @@ final class ConfigurationClass {
|
||||
this.imported = imported;
|
||||
}
|
||||
|
||||
|
||||
public AnnotationMetadata getMetadata() {
|
||||
return this.metadata;
|
||||
}
|
||||
@@ -131,6 +132,14 @@ final class ConfigurationClass {
|
||||
return ClassUtils.getShortName(getMetadata().getClassName());
|
||||
}
|
||||
|
||||
public void setBeanName(String beanName) {
|
||||
this.beanName = beanName;
|
||||
}
|
||||
|
||||
public String getBeanName() {
|
||||
return this.beanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this configuration class was registered via @{@link Import} or
|
||||
* automatically registered due to being nested within another configuration class.
|
||||
@@ -140,14 +149,6 @@ final class ConfigurationClass {
|
||||
return this.imported;
|
||||
}
|
||||
|
||||
public void setBeanName(String beanName) {
|
||||
this.beanName = beanName;
|
||||
}
|
||||
|
||||
public String getBeanName() {
|
||||
return this.beanName;
|
||||
}
|
||||
|
||||
public void addBeanMethod(BeanMethod method) {
|
||||
this.beanMethods.add(method);
|
||||
}
|
||||
@@ -156,8 +157,7 @@ final class ConfigurationClass {
|
||||
return this.beanMethods;
|
||||
}
|
||||
|
||||
public void addImportedResource(
|
||||
String importedResource, Class<? extends BeanDefinitionReader> readerClass) {
|
||||
public void addImportedResource(String importedResource, Class<? extends BeanDefinitionReader> readerClass) {
|
||||
this.importedResources.put(importedResource, readerClass);
|
||||
}
|
||||
|
||||
@@ -165,28 +165,8 @@ final class ConfigurationClass {
|
||||
return this.importedResources;
|
||||
}
|
||||
|
||||
|
||||
public void validate(ProblemReporter problemReporter) {
|
||||
// An @Bean method may only be overloaded through inheritance. No single
|
||||
// @Configuration class may declare two @Bean methods with the same name.
|
||||
final char hashDelim = '#';
|
||||
Map<String, Integer> methodNameCounts = new HashMap<String, Integer>();
|
||||
for (BeanMethod beanMethod : beanMethods) {
|
||||
String dClassName = beanMethod.getMetadata().getDeclaringClassName();
|
||||
String methodName = beanMethod.getMetadata().getMethodName();
|
||||
String fqMethodName = dClassName + hashDelim + methodName;
|
||||
Integer currentCount = methodNameCounts.get(fqMethodName);
|
||||
int newCount = currentCount != null ? currentCount + 1 : 1;
|
||||
methodNameCounts.put(fqMethodName, newCount);
|
||||
}
|
||||
|
||||
for (String methodName : methodNameCounts.keySet()) {
|
||||
int count = methodNameCounts.get(methodName);
|
||||
if (count > 1) {
|
||||
String shortMethodName = methodName.substring(methodName.indexOf(hashDelim)+1);
|
||||
problemReporter.error(new BeanMethodOverloadingProblem(shortMethodName, count));
|
||||
}
|
||||
}
|
||||
|
||||
// A configuration class may not be final (CGLIB limitation)
|
||||
if (getMetadata().isAnnotated(Configuration.class.getName())) {
|
||||
if (getMetadata().isFinal()) {
|
||||
@@ -194,6 +174,23 @@ final class ConfigurationClass {
|
||||
}
|
||||
}
|
||||
|
||||
// An @Bean method may only be overloaded through inheritance. No single
|
||||
// @Configuration class may declare two @Bean methods with the same name.
|
||||
Map<String, Integer> methodNameCounts = new HashMap<String, Integer>();
|
||||
for (BeanMethod beanMethod : this.beanMethods) {
|
||||
String fqMethodName = beanMethod.getFullyQualifiedMethodName();
|
||||
Integer currentCount = methodNameCounts.get(fqMethodName);
|
||||
int newCount = currentCount != null ? currentCount + 1 : 1;
|
||||
methodNameCounts.put(fqMethodName, newCount);
|
||||
}
|
||||
for (String fqMethodName : methodNameCounts.keySet()) {
|
||||
int count = methodNameCounts.get(fqMethodName);
|
||||
if (count > 1) {
|
||||
String shortMethodName = ConfigurationMethod.getShortMethodName(fqMethodName);
|
||||
problemReporter.error(new BeanMethodOverloadingProblem(shortMethodName, count));
|
||||
}
|
||||
}
|
||||
|
||||
for (BeanMethod beanMethod : this.beanMethods) {
|
||||
beanMethod.validate(problemReporter);
|
||||
}
|
||||
|
||||
+1
-3
@@ -134,8 +134,6 @@ class ConfigurationClassBeanDefinitionReader {
|
||||
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
|
||||
AnnotationMetadata metadata = configClass.getMetadata();
|
||||
BeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
|
||||
String className = metadata.getClassName();
|
||||
configBeanDef.setBeanClassName(className);
|
||||
if (ConfigurationClassUtils.checkConfigurationClassCandidate(configBeanDef, this.metadataReaderFactory)) {
|
||||
String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
|
||||
this.registry.registerBeanDefinition(configBeanName, configBeanDef);
|
||||
@@ -146,7 +144,7 @@ class ConfigurationClassBeanDefinitionReader {
|
||||
}
|
||||
else {
|
||||
this.problemReporter.error(
|
||||
new InvalidConfigurationImportProblem(className, configClass.getResource(), metadata));
|
||||
new InvalidConfigurationImportProblem(metadata.getClassName(), configClass.getResource(), metadata));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+173
-105
@@ -17,11 +17,12 @@
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
@@ -42,6 +43,7 @@ import org.springframework.beans.factory.support.BeanDefinitionReader;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.BeanNameGenerator;
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.core.NestedIOException;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.env.CompositePropertySource;
|
||||
import org.springframework.core.env.Environment;
|
||||
@@ -54,7 +56,7 @@ import org.springframework.core.type.StandardAnnotationMetadata;
|
||||
import org.springframework.core.type.classreading.MetadataReader;
|
||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||
import org.springframework.core.type.filter.AssignableTypeFilter;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.springframework.context.annotation.MetadataUtils.*;
|
||||
@@ -83,16 +85,6 @@ class ConfigurationClassParser {
|
||||
|
||||
private final ProblemReporter problemReporter;
|
||||
|
||||
private final ImportStack importStack = new ImportStack();
|
||||
|
||||
private final Set<String> knownSuperclasses = new LinkedHashSet<String>();
|
||||
|
||||
private final Set<ConfigurationClass> configurationClasses =
|
||||
new LinkedHashSet<ConfigurationClass>();
|
||||
|
||||
private final Stack<PropertySource<?>> propertySources =
|
||||
new Stack<PropertySource<?>>();
|
||||
|
||||
private final Environment environment;
|
||||
|
||||
private final ResourceLoader resourceLoader;
|
||||
@@ -101,6 +93,14 @@ class ConfigurationClassParser {
|
||||
|
||||
private final ComponentScanAnnotationParser componentScanParser;
|
||||
|
||||
private final Set<ConfigurationClass> configurationClasses = new LinkedHashSet<ConfigurationClass>();
|
||||
|
||||
private final Map<String, ConfigurationClass> knownSuperclasses = new HashMap<String, ConfigurationClass>();
|
||||
|
||||
private final Stack<PropertySource<?>> propertySources = new Stack<PropertySource<?>>();
|
||||
|
||||
private final ImportStack importStack = new ImportStack();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@link ConfigurationClassParser} instance that will be used
|
||||
@@ -149,70 +149,42 @@ class ConfigurationClassParser {
|
||||
}
|
||||
}
|
||||
|
||||
// recursively process the configuration class and its superclass hierarchy
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Recursively process the configuration class and its superclass hierarchy.
|
||||
do {
|
||||
metadata = doProcessConfigurationClass(configClass, metadata);
|
||||
}
|
||||
while (metadata != null);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
this.configurationClasses.add(configClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return annotation metadata of superclass, null if none found or previously processed
|
||||
* @return annotation metadata of superclass, {@code null} if none found or previously processed
|
||||
*/
|
||||
protected AnnotationMetadata doProcessConfigurationClass(
|
||||
ConfigurationClass configClass, AnnotationMetadata metadata) throws IOException {
|
||||
|
||||
// recursively process any member (nested) classes first
|
||||
for (String memberClassName : metadata.getMemberClassNames()) {
|
||||
MetadataReader reader = this.metadataReaderFactory.getMetadataReader(memberClassName);
|
||||
AnnotationMetadata memberClassMetadata = reader.getAnnotationMetadata();
|
||||
if (ConfigurationClassUtils.isConfigurationCandidate(memberClassMetadata)) {
|
||||
processConfigurationClass(new ConfigurationClass(reader, true));
|
||||
}
|
||||
}
|
||||
processMemberClasses(metadata);
|
||||
|
||||
// process any @PropertySource annotations
|
||||
AnnotationAttributes propertySource =
|
||||
attributesFor(metadata, org.springframework.context.annotation.PropertySource.class);
|
||||
AnnotationAttributes propertySource = attributesFor(metadata, org.springframework.context.annotation.PropertySource.class);
|
||||
if (propertySource != null) {
|
||||
String name = propertySource.getString("name");
|
||||
String[] locations = propertySource.getStringArray("value");
|
||||
int nLocations = locations.length;
|
||||
if (nLocations == 0) {
|
||||
throw new IllegalArgumentException("At least one @PropertySource(value) location is required");
|
||||
}
|
||||
for (int i = 0; i < nLocations; i++) {
|
||||
locations[i] = this.environment.resolveRequiredPlaceholders(locations[i]);
|
||||
}
|
||||
ClassLoader classLoader = this.resourceLoader.getClassLoader();
|
||||
if (!StringUtils.hasText(name)) {
|
||||
for (String location : locations) {
|
||||
this.propertySources.push(new ResourcePropertySource(location, classLoader));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (nLocations == 1) {
|
||||
this.propertySources.push(new ResourcePropertySource(name, locations[0], classLoader));
|
||||
}
|
||||
else {
|
||||
CompositePropertySource ps = new CompositePropertySource(name);
|
||||
for (String location : locations) {
|
||||
ps.addPropertySource(new ResourcePropertySource(location, classLoader));
|
||||
}
|
||||
this.propertySources.push(ps);
|
||||
}
|
||||
}
|
||||
processPropertySource(propertySource);
|
||||
}
|
||||
|
||||
// process any @ComponentScan annotions
|
||||
// process any @ComponentScan annotations
|
||||
AnnotationAttributes componentScan = attributesFor(metadata, ComponentScan.class);
|
||||
if (componentScan != null) {
|
||||
// the config class is annotated with @ComponentScan -> perform the scan immediately
|
||||
@@ -228,9 +200,11 @@ class ConfigurationClassParser {
|
||||
}
|
||||
|
||||
// process any @Import annotations
|
||||
Set<String> imports = getImports(metadata.getClassName(), null, new HashSet<String>());
|
||||
if (!CollectionUtils.isEmpty(imports)) {
|
||||
processImport(configClass, imports.toArray(new String[imports.size()]), true);
|
||||
Set<Object> imports = new LinkedHashSet<Object>();
|
||||
Set<Object> visited = new LinkedHashSet<Object>();
|
||||
collectImports(metadata, imports, visited);
|
||||
if (!imports.isEmpty()) {
|
||||
processImport(configClass, imports, true);
|
||||
}
|
||||
|
||||
// process any @ImportResource annotations
|
||||
@@ -252,7 +226,8 @@ class ConfigurationClassParser {
|
||||
// process superclass, if any
|
||||
if (metadata.hasSuperClass()) {
|
||||
String superclass = metadata.getSuperClassName();
|
||||
if (this.knownSuperclasses.add(superclass)) {
|
||||
if (!this.knownSuperclasses.containsKey(superclass)) {
|
||||
this.knownSuperclasses.put(superclass, configClass);
|
||||
// superclass found, return its annotation metadata and recurse
|
||||
if (metadata instanceof StandardAnnotationMetadata) {
|
||||
Class<?> clazz = ((StandardAnnotationMetadata) metadata).getIntrospectedClass();
|
||||
@@ -279,6 +254,65 @@ class ConfigurationClassParser {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register member (nested) classes that happen to be configuration classes themselves.
|
||||
* @param metadata the metadata representation of the containing class
|
||||
* @throws IOException if there is any problem reading metadata from a member class
|
||||
*/
|
||||
private void processMemberClasses(AnnotationMetadata metadata) throws IOException {
|
||||
if (metadata instanceof StandardAnnotationMetadata) {
|
||||
for (Class<?> memberClass : ((StandardAnnotationMetadata) metadata).getIntrospectedClass().getDeclaredClasses()) {
|
||||
if (ConfigurationClassUtils.isConfigurationCandidate(new StandardAnnotationMetadata(memberClass))) {
|
||||
processConfigurationClass(new ConfigurationClass(memberClass, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (String memberClassName : metadata.getMemberClassNames()) {
|
||||
MetadataReader reader = this.metadataReaderFactory.getMetadataReader(memberClassName);
|
||||
AnnotationMetadata memberClassMetadata = reader.getAnnotationMetadata();
|
||||
if (ConfigurationClassUtils.isConfigurationCandidate(memberClassMetadata)) {
|
||||
processConfigurationClass(new ConfigurationClass(reader, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the given <code>@PropertySource</code> annotation metadata.
|
||||
* @param propertySource metadata for the <code>@PropertySource</code> annotation found
|
||||
* @throws IOException if loading a property source failed
|
||||
*/
|
||||
private void processPropertySource(AnnotationAttributes propertySource) throws IOException {
|
||||
String name = propertySource.getString("name");
|
||||
String[] locations = propertySource.getStringArray("value");
|
||||
int nLocations = locations.length;
|
||||
if (nLocations == 0) {
|
||||
throw new IllegalArgumentException("At least one @PropertySource(value) location is required");
|
||||
}
|
||||
for (int i = 0; i < nLocations; i++) {
|
||||
locations[i] = this.environment.resolveRequiredPlaceholders(locations[i]);
|
||||
}
|
||||
ClassLoader classLoader = this.resourceLoader.getClassLoader();
|
||||
if (!StringUtils.hasText(name)) {
|
||||
for (String location : locations) {
|
||||
this.propertySources.push(new ResourcePropertySource(location, classLoader));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (nLocations == 1) {
|
||||
this.propertySources.push(new ResourcePropertySource(name, locations[0], classLoader));
|
||||
}
|
||||
else {
|
||||
CompositePropertySource ps = new CompositePropertySource(name);
|
||||
for (String location : locations) {
|
||||
ps.addPropertySource(new ResourcePropertySource(location, classLoader));
|
||||
}
|
||||
this.propertySources.push(ps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively collect all declared {@code @Import} values. Unlike most
|
||||
* meta-annotations it is valid to have several {@code @Import}s declared with
|
||||
@@ -287,69 +321,103 @@ class ConfigurationClassParser {
|
||||
* <p>For example, it is common for a {@code @Configuration} class to declare direct
|
||||
* {@code @Import}s in addition to meta-imports originating from an {@code @Enable}
|
||||
* annotation.
|
||||
* @param className the class name to search
|
||||
* @param imports the imports collected so far or {@code null}
|
||||
* @param visited used to track visited classes to prevent infinite recursion (must not be null)
|
||||
* @return a set of all {@link Import#value() import values} or {@code null}
|
||||
* @param metadata the metadata representation of the class to search
|
||||
* @param imports the imports collected so far
|
||||
* @param visited used to track visited classes to prevent infinite recursion
|
||||
* @throws IOException if there is any problem reading metadata from the named class
|
||||
*/
|
||||
private Set<String> getImports(String className, Set<String> imports, Set<String> visited) throws IOException {
|
||||
if (visited.add(className) && !className.startsWith("java")) {
|
||||
AnnotationMetadata metadata = metadataReaderFactory.getMetadataReader(className).getAnnotationMetadata();
|
||||
for (String annotationType : metadata.getAnnotationTypes()) {
|
||||
imports = getImports(annotationType, imports, visited);
|
||||
private void collectImports(AnnotationMetadata metadata, Set<Object> imports, Set<Object> visited) throws IOException {
|
||||
String className = metadata.getClassName();
|
||||
if (visited.add(className)) {
|
||||
if (metadata instanceof StandardAnnotationMetadata) {
|
||||
StandardAnnotationMetadata stdMetadata = (StandardAnnotationMetadata) metadata;
|
||||
for (Annotation ann : stdMetadata.getIntrospectedClass().getAnnotations()) {
|
||||
if (!ann.annotationType().getName().startsWith("java") && !(ann instanceof Import)) {
|
||||
collectImports(new StandardAnnotationMetadata(ann.annotationType()), imports, visited);
|
||||
}
|
||||
}
|
||||
Map<String, Object> attributes = stdMetadata.getAnnotationAttributes(Import.class.getName(), false);
|
||||
if (attributes != null) {
|
||||
Class[] value = (Class[]) attributes.get("value");
|
||||
if (!ObjectUtils.isEmpty(value)) {
|
||||
imports.addAll(Arrays.asList(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
Map<String, Object> attributes = metadata.getAnnotationAttributes(Import.class.getName(), true);
|
||||
if (attributes != null) {
|
||||
String[] value = (String[]) attributes.get("value");
|
||||
if (value != null && value.length > 0) {
|
||||
imports = (imports == null ? new LinkedHashSet<String>() : imports);
|
||||
imports.addAll(Arrays.asList(value));
|
||||
else {
|
||||
for (String annotationType : metadata.getAnnotationTypes()) {
|
||||
if (!className.startsWith("java") && !className.equals(Import.class.getName())) {
|
||||
try {
|
||||
collectImports(
|
||||
new StandardAnnotationMetadata(this.resourceLoader.getClassLoader().loadClass(annotationType)),
|
||||
imports, visited);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
Map<String, Object> attributes = metadata.getAnnotationAttributes(Import.class.getName(), true);
|
||||
if (attributes != null) {
|
||||
String[] value = (String[]) attributes.get("value");
|
||||
if (!ObjectUtils.isEmpty(value)) {
|
||||
imports.addAll(Arrays.asList(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return imports;
|
||||
}
|
||||
|
||||
private void processImport(ConfigurationClass configClass, String[] classesToImport, boolean checkForCircularImports) throws IOException {
|
||||
private void processImport(ConfigurationClass configClass, Collection<?> classesToImport, boolean checkForCircularImports) throws IOException {
|
||||
if (checkForCircularImports && this.importStack.contains(configClass)) {
|
||||
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack, configClass.getMetadata()));
|
||||
}
|
||||
else {
|
||||
this.importStack.push(configClass);
|
||||
AnnotationMetadata importingClassMetadata = configClass.getMetadata();
|
||||
for (String candidate : classesToImport) {
|
||||
MetadataReader reader = this.metadataReaderFactory.getMetadataReader(candidate);
|
||||
if (new AssignableTypeFilter(ImportSelector.class).match(reader, this.metadataReaderFactory)) {
|
||||
// the candidate class is an ImportSelector -> delegate to it to determine imports
|
||||
try {
|
||||
ImportSelector selector = BeanUtils.instantiateClass(
|
||||
this.resourceLoader.getClassLoader().loadClass(candidate), ImportSelector.class);
|
||||
processImport(configClass, selector.selectImports(importingClassMetadata), false);
|
||||
try {
|
||||
for (Object candidate : classesToImport) {
|
||||
Object candidateToCheck = (candidate instanceof Class ? (Class) candidate :
|
||||
this.metadataReaderFactory.getMetadataReader((String) candidate));
|
||||
if (checkAssignability(ImportSelector.class, candidateToCheck)) {
|
||||
// the candidate class is an ImportSelector -> delegate to it to determine imports
|
||||
Class<?> candidateClass = (candidate instanceof Class ? (Class) candidate :
|
||||
this.resourceLoader.getClassLoader().loadClass((String) candidate));
|
||||
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
|
||||
processImport(configClass, Arrays.asList(selector.selectImports(importingClassMetadata)), false);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
else if (new AssignableTypeFilter(ImportBeanDefinitionRegistrar.class).match(reader, this.metadataReaderFactory)) {
|
||||
// the candidate class is an ImportBeanDefinitionRegistrar -> delegate to it to register additional bean definitions
|
||||
try {
|
||||
ImportBeanDefinitionRegistrar registrar = BeanUtils.instantiateClass(
|
||||
this.resourceLoader.getClassLoader().loadClass(candidate), ImportBeanDefinitionRegistrar.class);
|
||||
else if (checkAssignability(ImportBeanDefinitionRegistrar.class, candidateToCheck)) {
|
||||
// the candidate class is an ImportBeanDefinitionRegistrar -> delegate to it to register additional bean definitions
|
||||
Class<?> candidateClass = (candidate instanceof Class ? (Class) candidate :
|
||||
this.resourceLoader.getClassLoader().loadClass((String) candidate));
|
||||
ImportBeanDefinitionRegistrar registrar = BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
|
||||
invokeAwareMethods(registrar);
|
||||
registrar.registerBeanDefinitions(importingClassMetadata, registry);
|
||||
registrar.registerBeanDefinitions(importingClassMetadata, this.registry);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
else {
|
||||
// candidate class not an ImportSelector or ImportBeanDefinitionRegistrar -> process it as a @Configuration class
|
||||
this.importStack.registerImport(importingClassMetadata.getClassName(),
|
||||
(candidate instanceof Class ? ((Class) candidate).getName() : (String) candidate));
|
||||
processConfigurationClass(candidateToCheck instanceof Class ? new ConfigurationClass((Class) candidateToCheck, true) :
|
||||
new ConfigurationClass((MetadataReader) candidateToCheck, true));
|
||||
}
|
||||
}
|
||||
else {
|
||||
// the candidate class not an ImportSelector or ImportBeanDefinitionRegistrar -> process it as a @Configuration class
|
||||
this.importStack.registerImport(importingClassMetadata.getClassName(), candidate);
|
||||
processConfigurationClass(new ConfigurationClass(reader, true));
|
||||
}
|
||||
}
|
||||
this.importStack.pop();
|
||||
catch (ClassNotFoundException ex) {
|
||||
throw new NestedIOException("Failed to load import candidate class", ex);
|
||||
}
|
||||
finally {
|
||||
this.importStack.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkAssignability(Class<?> clazz, Object candidate) throws IOException {
|
||||
if (candidate instanceof Class) {
|
||||
return clazz.isAssignableFrom((Class) candidate);
|
||||
}
|
||||
else {
|
||||
return new AssignableTypeFilter(clazz).match((MetadataReader) candidate, this.metadataReaderFactory);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -393,7 +461,7 @@ class ConfigurationClassParser {
|
||||
return this.propertySources;
|
||||
}
|
||||
|
||||
public ImportRegistry getImportRegistry() {
|
||||
ImportRegistry getImportRegistry() {
|
||||
return this.importStack;
|
||||
}
|
||||
|
||||
|
||||
+12
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,6 +36,7 @@ abstract class ConfigurationMethod {
|
||||
this.configurationClass = configurationClass;
|
||||
}
|
||||
|
||||
|
||||
public MethodMetadata getMetadata() {
|
||||
return this.metadata;
|
||||
}
|
||||
@@ -48,13 +49,22 @@ abstract class ConfigurationMethod {
|
||||
return new Location(this.configurationClass.getResource(), this.metadata);
|
||||
}
|
||||
|
||||
String getFullyQualifiedMethodName() {
|
||||
return this.metadata.getDeclaringClassName() + "#" + this.metadata.getMethodName();
|
||||
}
|
||||
|
||||
static String getShortMethodName(String fullyQualifiedMethodName) {
|
||||
return fullyQualifiedMethodName.substring(fullyQualifiedMethodName.indexOf('#') + 1);
|
||||
}
|
||||
|
||||
public void validate(ProblemReporter problemReporter) {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[%s:name=%s,declaringClass=%s]",
|
||||
this.getClass().getSimpleName(), this.getMetadata().getMethodName(), this.getMetadata().getDeclaringClassName());
|
||||
getClass().getSimpleName(), getMetadata().getMethodName(), getMetadata().getDeclaringClassName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -52,9 +52,9 @@ public class GenericApplicationListenerAdapter implements SmartApplicationListen
|
||||
}
|
||||
|
||||
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
|
||||
Class typeArg = GenericTypeResolver.resolveTypeArgument(this.delegate.getClass(), ApplicationListener.class);
|
||||
Class<?> typeArg = GenericTypeResolver.resolveTypeArgument(this.delegate.getClass(), ApplicationListener.class);
|
||||
if (typeArg == null || typeArg.equals(ApplicationEvent.class)) {
|
||||
Class targetClass = AopUtils.getTargetClass(this.delegate);
|
||||
Class<?> targetClass = AopUtils.getTargetClass(this.delegate);
|
||||
if (targetClass != this.delegate.getClass()) {
|
||||
typeArg = GenericTypeResolver.resolveTypeArgument(targetClass, ApplicationListener.class);
|
||||
}
|
||||
|
||||
+30
-22
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,22 +23,26 @@ import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Declares that a field should be formatted as a date time.
|
||||
* Supports formatting by style pattern, ISO date time pattern, or custom format pattern string.
|
||||
* Can be applied to {@code java.util.Date}, {@code java.util.Calendar}, {@code java.long.Long}, or Joda Time fields.
|
||||
* <p>
|
||||
* For style-based formatting, set the {@link #style()} attribute to be the style pattern code.
|
||||
*
|
||||
* <p>Supports formatting by style pattern, ISO date time pattern, or custom format pattern string.
|
||||
* Can be applied to {@code java.util.Date}, {@code java.util.Calendar}, {@code java.long.Long},
|
||||
* Joda-Time value types; and as of Spring 4 and JDK 8, to JSR-310 <code>java.time</code> types too.
|
||||
*
|
||||
* <p>For style-based formatting, set the {@link #style()} attribute to be the style pattern code.
|
||||
* The first character of the code is the date style, and the second character is the time style.
|
||||
* Specify a character of 'S' for short style, 'M' for medium, 'L' for long, and 'F' for full.
|
||||
* A date or time may be omitted by specifying the style character '-'.
|
||||
* <p>
|
||||
* For ISO-based formatting, set the {@link #iso()} attribute to be the desired {@link ISO} format, such as {@link ISO#DATE}.
|
||||
<p>
|
||||
* For custom formatting, set the {@link #pattern()} attribute to be the DateTime pattern, such as {@code yyyy/MM/dd hh:mm:ss a}.
|
||||
* <p>
|
||||
* Each attribute is mutually exclusive, so only set one attribute per annotation instance (the one most convenient one for your formatting needs).
|
||||
*
|
||||
* <p>For ISO-based formatting, set the {@link #iso()} attribute to be the desired {@link ISO} format,
|
||||
* such as {@link ISO#DATE}. For custom formatting, set the {@link #pattern()} attribute to be the
|
||||
* DateTime pattern, such as {@code yyyy/MM/dd hh:mm:ss a}.
|
||||
*
|
||||
* <p>Each attribute is mutually exclusive, so only set one attribute per annotation instance
|
||||
* (the one most convenient one for your formatting needs).
|
||||
* When the pattern attribute is specified, it takes precedence over both the style and ISO attribute.
|
||||
* When the iso attribute is specified, if takes precedence over the style attribute.
|
||||
* When no annotation attributes are specified, the default format applied is style-based with a style code of 'SS' (short date, short time).
|
||||
* When no annotation attributes are specified, the default format applied is style-based
|
||||
* with a style code of 'SS' (short date, short time).
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Juergen Hoeller
|
||||
@@ -51,23 +55,24 @@ public @interface DateTimeFormat {
|
||||
|
||||
/**
|
||||
* The style pattern to use to format the field.
|
||||
* Defaults to 'SS' for short date time.
|
||||
* Set this attribute when you wish to format your field in accordance with a common style other than the default style.
|
||||
* <p>Defaults to 'SS' for short date time. Set this attribute when you wish to format
|
||||
* your field in accordance with a common style other than the default style.
|
||||
*/
|
||||
String style() default "SS";
|
||||
|
||||
/**
|
||||
* The ISO pattern to use to format the field.
|
||||
* The possible ISO patterns are defined in the {@link ISO} enum.
|
||||
* Defaults to ISO.NONE, indicating this attribute should be ignored.
|
||||
* Set this attribute when you wish to format your field in accordance with an ISO date time format.
|
||||
* <p>Defaults to {@link ISO#NONE}, indicating this attribute should be ignored.
|
||||
* Set this attribute when you wish to format your field in accordance with an ISO format.
|
||||
*/
|
||||
ISO iso() default ISO.NONE;
|
||||
|
||||
/**
|
||||
* The custom pattern to use to format the field.
|
||||
* Defaults to empty String, indicating no custom pattern String has been specified.
|
||||
* Set this attribute when you wish to format your field in accordance with a custom date time pattern not represented by a style or ISO format.
|
||||
* <p>Defaults to empty String, indicating no custom pattern String has been specified.
|
||||
* Set this attribute when you wish to format your field in accordance with a custom
|
||||
* date time pattern not represented by a style or ISO format.
|
||||
*/
|
||||
String pattern() default "";
|
||||
|
||||
@@ -78,18 +83,21 @@ public @interface DateTimeFormat {
|
||||
public enum ISO {
|
||||
|
||||
/**
|
||||
* The most common ISO Date Format {@code yyyy-MM-dd} e.g. 2000-10-31.
|
||||
* The most common ISO Date Format {@code yyyy-MM-dd},
|
||||
* e.g. 2000-10-31.
|
||||
*/
|
||||
DATE,
|
||||
|
||||
/**
|
||||
* The most common ISO Time Format {@code HH:mm:ss.SSSZ} e.g. 01:30:00.000-05:00.
|
||||
* The most common ISO Time Format {@code HH:mm:ss.SSSZ},
|
||||
* e.g. 01:30:00.000-05:00.
|
||||
*/
|
||||
TIME,
|
||||
|
||||
/**
|
||||
* The most common ISO DateTime Format {@code yyyy-MM-dd'T'HH:mm:ss.SSSZ} e.g. 2000-10-31 01:30:00.000-05:00.
|
||||
* The default if no annotation value is specified.
|
||||
* The most common ISO DateTime Format {@code yyyy-MM-dd'T'HH:mm:ss.SSSZ},
|
||||
* e.g. 2000-10-31 01:30:00.000-05:00.
|
||||
* <p>This is the default if no annotation value is specified.
|
||||
*/
|
||||
DATE_TIME,
|
||||
|
||||
|
||||
+13
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -46,7 +46,7 @@ public class DateFormatter implements Formatter<Date> {
|
||||
|
||||
private static final Map<ISO, String> ISO_PATTERNS;
|
||||
static {
|
||||
Map<ISO, String> formats = new HashMap<DateTimeFormat.ISO, String>();
|
||||
Map<ISO, String> formats = new HashMap<DateTimeFormat.ISO, String>(4);
|
||||
formats.put(ISO.DATE, "yyyy-MM-dd");
|
||||
formats.put(ISO.TIME, "HH:mm:ss.SSSZ");
|
||||
formats.put(ISO.DATE_TIME, "yyyy-MM-dd'T'HH:mm:ss.SSSZ");
|
||||
@@ -89,6 +89,15 @@ public class DateFormatter implements Formatter<Date> {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ISO format used for this date.
|
||||
* @param iso the {@link ISO} format
|
||||
* @since 3.2
|
||||
*/
|
||||
public void setIso(ISO iso) {
|
||||
this.iso = iso;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the style to use to format date values.
|
||||
* <p>If not specified, DateFormat's default style will be used.
|
||||
@@ -112,7 +121,7 @@ public class DateFormatter implements Formatter<Date> {
|
||||
* <li>'F' = Full</li>
|
||||
* <li>'-' = Omitted</li>
|
||||
* <ul>
|
||||
* This method mimics the styles supported by Joda Time.
|
||||
* This method mimics the styles supported by Joda-Time.
|
||||
* @param stylePattern two characters from the set {"S", "M", "L", "F", "-"}
|
||||
* @since 3.2
|
||||
*/
|
||||
@@ -120,14 +129,6 @@ public class DateFormatter implements Formatter<Date> {
|
||||
this.stylePattern = stylePattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ISO format used for this date.
|
||||
* @param iso the {@link ISO} format
|
||||
* @since 3.2
|
||||
*/
|
||||
public void setIso(ISO iso) {
|
||||
this.iso = iso;
|
||||
}
|
||||
/**
|
||||
* Set the TimeZone to normalize the date values into, if any.
|
||||
*/
|
||||
@@ -204,4 +205,5 @@ public class DateFormatter implements Formatter<Date> {
|
||||
}
|
||||
throw new IllegalStateException("Unsupported style pattern '"+ stylePattern+ "'");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+20
-14
@@ -27,8 +27,8 @@ import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Configures Date formatting for use with Spring.
|
||||
* <p>
|
||||
* Designed for direct instantiation but also exposes the static
|
||||
*
|
||||
* <p>Designed for direct instantiation but also exposes the static
|
||||
* {@link #addDateConverters(ConverterRegistry)} utility method for ad hoc use
|
||||
* against any {@code ConverterRegistry} instance.
|
||||
*
|
||||
@@ -39,10 +39,20 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class DateFormatterRegistrar implements FormatterRegistrar {
|
||||
|
||||
|
||||
private DateFormatter dateFormatter;
|
||||
|
||||
|
||||
/**
|
||||
* Set the date formatter to register. If not specified no formatter is registered.
|
||||
* This method can be used if global formatter configuration is required.
|
||||
* @param dateFormatter the date formatter
|
||||
*/
|
||||
public void setFormatter(DateFormatter dateFormatter) {
|
||||
Assert.notNull(dateFormatter, "DateFormatter must not be null");
|
||||
this.dateFormatter = dateFormatter;
|
||||
}
|
||||
|
||||
|
||||
public void registerFormatters(FormatterRegistry registry) {
|
||||
addDateConverters(registry);
|
||||
registry.addFormatterForFieldAnnotation(new DateTimeFormatAnnotationFormatterFactory());
|
||||
@@ -55,16 +65,6 @@ public class DateFormatterRegistrar implements FormatterRegistrar {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the date formatter to register. If not specified no formatter is registered.
|
||||
* This method can be used if global formatter configuration is required.
|
||||
* @param dateFormatter the date formatter
|
||||
*/
|
||||
public void setFormatter(DateFormatter dateFormatter) {
|
||||
Assert.notNull(dateFormatter, "DateFormatter must not be null");
|
||||
this.dateFormatter = dateFormatter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add date converters to the specified registry.
|
||||
* @param converterRegistry the registry of converters to add to
|
||||
@@ -80,6 +80,7 @@ public class DateFormatterRegistrar implements FormatterRegistrar {
|
||||
|
||||
|
||||
private static class DateToLongConverter implements Converter<Date, Long> {
|
||||
|
||||
public Long convert(Date source) {
|
||||
return source.getTime();
|
||||
}
|
||||
@@ -87,6 +88,7 @@ public class DateFormatterRegistrar implements FormatterRegistrar {
|
||||
|
||||
|
||||
private static class DateToCalendarConverter implements Converter<Date, Calendar> {
|
||||
|
||||
public Calendar convert(Date source) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(source);
|
||||
@@ -96,6 +98,7 @@ public class DateFormatterRegistrar implements FormatterRegistrar {
|
||||
|
||||
|
||||
private static class CalendarToDateConverter implements Converter<Calendar, Date> {
|
||||
|
||||
public Date convert(Calendar source) {
|
||||
return source.getTime();
|
||||
}
|
||||
@@ -103,6 +106,7 @@ public class DateFormatterRegistrar implements FormatterRegistrar {
|
||||
|
||||
|
||||
private static class CalendarToLongConverter implements Converter<Calendar, Long> {
|
||||
|
||||
public Long convert(Calendar source) {
|
||||
return source.getTime().getTime();
|
||||
}
|
||||
@@ -110,6 +114,7 @@ public class DateFormatterRegistrar implements FormatterRegistrar {
|
||||
|
||||
|
||||
private static class LongToDateConverter implements Converter<Long, Date> {
|
||||
|
||||
public Date convert(Long source) {
|
||||
return new Date(source);
|
||||
}
|
||||
@@ -118,10 +123,11 @@ public class DateFormatterRegistrar implements FormatterRegistrar {
|
||||
|
||||
private static class LongToCalendarConverter implements Converter<Long, Calendar> {
|
||||
|
||||
private DateToCalendarConverter dateToCalendarConverter = new DateToCalendarConverter();
|
||||
private final DateToCalendarConverter dateToCalendarConverter = new DateToCalendarConverter();
|
||||
|
||||
public Calendar convert(Long source) {
|
||||
return this.dateToCalendarConverter.convert(new Date(source));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -44,7 +44,7 @@ public class DateTimeFormatAnnotationFormatterFactory implements
|
||||
|
||||
private static final Set<Class<?>> FIELD_TYPES;
|
||||
static {
|
||||
Set<Class<?>> fieldTypes = new HashSet<Class<?>>();
|
||||
Set<Class<?>> fieldTypes = new HashSet<Class<?>>(4);
|
||||
fieldTypes.add(Date.class);
|
||||
fieldTypes.add(Calendar.class);
|
||||
fieldTypes.add(Long.class);
|
||||
@@ -82,4 +82,5 @@ public class DateTimeFormatAnnotationFormatterFactory implements
|
||||
protected String resolveEmbeddedValue(String value) {
|
||||
return (this.embeddedValueResolver != null ? this.embeddedValueResolver.resolveStringValue(value) : value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+66
-64
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,32 +22,34 @@ import org.joda.time.DateTimeZone;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
import org.joda.time.format.ISODateTimeFormat;
|
||||
|
||||
import org.springframework.format.annotation.DateTimeFormat.ISO;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Factory that creates a Joda {@link DateTimeFormatter}. Formatters will be
|
||||
* created using the defined {@link #setPattern(String) pattern}, {@link #setIso ISO},
|
||||
* or {@link #setStyle(String) style} (considered in that order).
|
||||
* Factory that creates a Joda-Time {@link DateTimeFormatter}.
|
||||
*
|
||||
* <p>Formatters will be created using the defined {@link #setPattern pattern},
|
||||
* {@link #setIso ISO}, and {@link #setStyle style} methods (considered in that order).
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Sam Brannen
|
||||
* @since 3.2
|
||||
* @see #createDateTimeFormatter()
|
||||
* @see #createDateTimeFormatter(DateTimeFormatter)
|
||||
* @see #setPattern(String)
|
||||
* @see #setPattern
|
||||
* @see #setStyle
|
||||
* @see #setIso
|
||||
* @see #setStyle(String)
|
||||
* @see DateTimeFormatterFactoryBean
|
||||
*/
|
||||
public class DateTimeFormatterFactory {
|
||||
|
||||
private String pattern;
|
||||
|
||||
private ISO iso;
|
||||
|
||||
private String style;
|
||||
|
||||
private String pattern;
|
||||
|
||||
private TimeZone timeZone;
|
||||
|
||||
|
||||
@@ -67,9 +69,50 @@ public class DateTimeFormatterFactory {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code DateTimeFormatter} using this factory. If no specific
|
||||
* {@link #setStyle(String) style}, {@link #setIso ISO}, or
|
||||
* {@link #setPattern(String) pattern} have been defined the
|
||||
* Set the pattern to use to format date values.
|
||||
* @param pattern the format pattern
|
||||
*/
|
||||
public void setPattern(String pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ISO format used to format date values.
|
||||
* @param iso the ISO format
|
||||
*/
|
||||
public void setIso(ISO iso) {
|
||||
this.iso = iso;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the two characters to use to format date values, in Joda-Time style.
|
||||
* <p>The first character is used for the date style; the second is for
|
||||
* the time style. Supported characters are:
|
||||
* <ul>
|
||||
* <li>'S' = Small</li>
|
||||
* <li>'M' = Medium</li>
|
||||
* <li>'L' = Long</li>
|
||||
* <li>'F' = Full</li>
|
||||
* <li>'-' = Omitted</li>
|
||||
* </ul>
|
||||
* @param style two characters from the set {"S", "M", "L", "F", "-"}
|
||||
*/
|
||||
public void setStyle(String style) {
|
||||
this.style = style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@code TimeZone} to normalize the date values into, if any.
|
||||
* @param timeZone the time zone
|
||||
*/
|
||||
public void setTimeZone(TimeZone timeZone) {
|
||||
this.timeZone = timeZone;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code DateTimeFormatter} using this factory.
|
||||
* <p>If no specific pattern or style has been defined,
|
||||
* {@link DateTimeFormat#mediumDateTime() medium date time format} will be used.
|
||||
* @return a new date time formatter
|
||||
* @see #createDateTimeFormatter(DateTimeFormatter)
|
||||
@@ -79,21 +122,20 @@ public class DateTimeFormatterFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code DateTimeFormatter} using this factory. If no specific
|
||||
* {@link #setStyle(String) style}, {@link #setIso ISO}, or
|
||||
* {@link #setPattern(String) pattern} have been defined the supplied
|
||||
* {@code fallbackFormatter} will be used.
|
||||
* @param fallbackFormatter the fall-back formatter to use when no specific factory
|
||||
* properties have been set (can be {@code null}).
|
||||
* Create a new {@code DateTimeFormatter} using this factory.
|
||||
* <p>If no specific pattern or style has been defined,
|
||||
* the supplied {@code fallbackFormatter} will be used.
|
||||
* @param fallbackFormatter the fall-back formatter to use when no specific
|
||||
* factory properties have been set (can be {@code null}).
|
||||
* @return a new date time formatter
|
||||
*/
|
||||
public DateTimeFormatter createDateTimeFormatter(DateTimeFormatter fallbackFormatter) {
|
||||
DateTimeFormatter dateTimeFormatter = null;
|
||||
if (StringUtils.hasLength(pattern)) {
|
||||
dateTimeFormatter = DateTimeFormat.forPattern(pattern);
|
||||
if (StringUtils.hasLength(this.pattern)) {
|
||||
dateTimeFormatter = DateTimeFormat.forPattern(this.pattern);
|
||||
}
|
||||
else if (iso != null && iso != ISO.NONE) {
|
||||
switch (iso) {
|
||||
else if (this.iso != null && this.iso != ISO.NONE) {
|
||||
switch (this.iso) {
|
||||
case DATE:
|
||||
dateTimeFormatter = ISODateTimeFormat.date();
|
||||
break;
|
||||
@@ -107,11 +149,11 @@ public class DateTimeFormatterFactory {
|
||||
/* no-op */
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unsupported ISO format: " + iso);
|
||||
throw new IllegalStateException("Unsupported ISO format: " + this.iso);
|
||||
}
|
||||
}
|
||||
else if (StringUtils.hasLength(style)) {
|
||||
dateTimeFormatter = DateTimeFormat.forStyle(style);
|
||||
else if (StringUtils.hasLength(this.style)) {
|
||||
dateTimeFormatter = DateTimeFormat.forStyle(this.style);
|
||||
}
|
||||
|
||||
if (dateTimeFormatter != null && this.timeZone != null) {
|
||||
@@ -120,44 +162,4 @@ public class DateTimeFormatterFactory {
|
||||
return (dateTimeFormatter != null ? dateTimeFormatter : fallbackFormatter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@code TimeZone} to normalize the date values into, if any.
|
||||
* @param timeZone the time zone
|
||||
*/
|
||||
public void setTimeZone(TimeZone timeZone) {
|
||||
this.timeZone = timeZone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the two characters to use to format date values. The first character is used for
|
||||
* the date style; the second is for the time style. Supported characters are:
|
||||
* <ul>
|
||||
* <li>'S' = Small</li>
|
||||
* <li>'M' = Medium</li>
|
||||
* <li>'L' = Long</li>
|
||||
* <li>'F' = Full</li>
|
||||
* <li>'-' = Omitted</li>
|
||||
* </ul>
|
||||
* <p>This method mimics the styles supported by Joda Time.
|
||||
* @param style two characters from the set {"S", "M", "L", "F", "-"}
|
||||
*/
|
||||
public void setStyle(String style) {
|
||||
this.style = style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ISO format used to format date values.
|
||||
* @param iso the ISO format
|
||||
*/
|
||||
public void setIso(ISO iso) {
|
||||
this.iso = iso;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the pattern to use to format date values.
|
||||
* @param pattern the format pattern
|
||||
*/
|
||||
public void setPattern(String pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,15 +22,15 @@ import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
/**
|
||||
* {@link FactoryBean} that creates a Joda {@link DateTimeFormatter}. See the
|
||||
* {@linkplain DateTimeFormatterFactory base class} for configuration details.
|
||||
* {@link FactoryBean} that creates a Joda-Time {@link DateTimeFormatter}.
|
||||
* See the {@link DateTimeFormatterFactory base class} for configuration details.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Sam Brannen
|
||||
* @since 3.2
|
||||
* @see #setPattern(String)
|
||||
* @see #setIso(org.springframework.format.annotation.DateTimeFormat.ISO)
|
||||
* @see #setStyle(String)
|
||||
* @see #setPattern
|
||||
* @see #setIso
|
||||
* @see #setStyle
|
||||
* @see DateTimeFormatterFactory
|
||||
*/
|
||||
public class DateTimeFormatterFactoryBean extends DateTimeFormatterFactory
|
||||
|
||||
+12
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -56,7 +56,7 @@ public class JodaDateTimeFormatAnnotationFormatterFactory
|
||||
// (if we did not do this, the default byType rules for LocalDate, LocalTime,
|
||||
// and LocalDateTime would take precedence over the annotation rule, which
|
||||
// is not what we want)
|
||||
Set<Class<?>> fieldTypes = new HashSet<Class<?>>(7);
|
||||
Set<Class<?>> fieldTypes = new HashSet<Class<?>>(8);
|
||||
fieldTypes.add(ReadableInstant.class);
|
||||
fieldTypes.add(LocalDate.class);
|
||||
fieldTypes.add(LocalTime.class);
|
||||
@@ -71,10 +71,6 @@ public class JodaDateTimeFormatAnnotationFormatterFactory
|
||||
private StringValueResolver embeddedValueResolver;
|
||||
|
||||
|
||||
public final Set<Class<?>> getFieldTypes() {
|
||||
return FIELD_TYPES;
|
||||
}
|
||||
|
||||
public void setEmbeddedValueResolver(StringValueResolver resolver) {
|
||||
this.embeddedValueResolver = resolver;
|
||||
}
|
||||
@@ -83,20 +79,24 @@ public class JodaDateTimeFormatAnnotationFormatterFactory
|
||||
return (this.embeddedValueResolver != null ? this.embeddedValueResolver.resolveStringValue(value) : value);
|
||||
}
|
||||
|
||||
|
||||
public final Set<Class<?>> getFieldTypes() {
|
||||
return FIELD_TYPES;
|
||||
}
|
||||
|
||||
public Printer<?> getPrinter(DateTimeFormat annotation, Class<?> fieldType) {
|
||||
DateTimeFormatter formatter = getFormatter(annotation, fieldType);
|
||||
if (ReadableInstant.class.isAssignableFrom(fieldType)) {
|
||||
return new ReadableInstantPrinter(formatter);
|
||||
}
|
||||
if (ReadablePartial.class.isAssignableFrom(fieldType)) {
|
||||
return new ReadablePartialPrinter(formatter);
|
||||
}
|
||||
if (Calendar.class.isAssignableFrom(fieldType)) {
|
||||
else if (ReadableInstant.class.isAssignableFrom(fieldType) || Calendar.class.isAssignableFrom(fieldType)) {
|
||||
// assumes Calendar->ReadableInstant converter is registered
|
||||
return new ReadableInstantPrinter(formatter);
|
||||
}
|
||||
// assumes Date->Long converter is registered
|
||||
return new MillisecondInstantPrinter(formatter);
|
||||
else {
|
||||
// assumes Date->Long converter is registered
|
||||
return new MillisecondInstantPrinter(formatter);
|
||||
}
|
||||
}
|
||||
|
||||
public Parser<DateTime> getParser(DateTimeFormat annotation, Class<?> fieldType) {
|
||||
|
||||
+12
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,8 +21,10 @@ import org.joda.time.DateTimeZone;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
|
||||
/**
|
||||
* A context that holds user-specific Joda Time settings such as the user's Chronology (calendar system) and time zone.
|
||||
* A {@code null} property value indicate the user has not specified a setting.
|
||||
* A context that holds user-specific Joda-Time settings such as the user's
|
||||
* Chronology (calendar system) and time zone.
|
||||
*
|
||||
* <p>A {@code null} property value indicate the user has not specified a setting.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @since 3.0
|
||||
@@ -43,8 +45,7 @@ public class JodaTimeContext {
|
||||
}
|
||||
|
||||
/**
|
||||
* The user's chronology (calendar system).
|
||||
* Null if not specified.
|
||||
* The user's chronology (calendar system), if any.
|
||||
*/
|
||||
public Chronology getChronology() {
|
||||
return this.chronology;
|
||||
@@ -58,8 +59,7 @@ public class JodaTimeContext {
|
||||
}
|
||||
|
||||
/**
|
||||
* The user's timezone.
|
||||
* Null if not specified.
|
||||
* The user's timezone, if any.
|
||||
*/
|
||||
public DateTimeZone getTimeZone() {
|
||||
return timeZone;
|
||||
@@ -67,9 +67,11 @@ public class JodaTimeContext {
|
||||
|
||||
|
||||
/**
|
||||
* Gets the Formatter with the this context's settings applied to the base {@code formatter}.
|
||||
* @param formatter the base formatter that establishes default formatting rules, generally context independent
|
||||
* @return the context DateTimeFormatter
|
||||
* Get the DateTimeFormatter with the this context's settings
|
||||
* applied to the base {@code formatter}.
|
||||
* @param formatter the base formatter that establishes default
|
||||
* formatting rules, generally context-independent
|
||||
* @return the contextual DateTimeFormatter
|
||||
*/
|
||||
public DateTimeFormatter getFormatter(DateTimeFormatter formatter) {
|
||||
if (this.chronology != null) {
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,7 +23,8 @@ import org.joda.time.format.DateTimeFormatter;
|
||||
import org.springframework.core.NamedThreadLocal;
|
||||
|
||||
/**
|
||||
* A holder for a thread-local user {@link JodaTimeContext}.
|
||||
* A holder for a thread-local {@link JodaTimeContext}
|
||||
* with user-specific Joda-Time settings.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Juergen Hoeller
|
||||
|
||||
+42
-54
@@ -27,12 +27,14 @@ import org.joda.time.LocalDateTime;
|
||||
import org.joda.time.LocalTime;
|
||||
import org.joda.time.MutableDateTime;
|
||||
import org.joda.time.ReadableInstant;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.ConverterRegistry;
|
||||
import org.springframework.format.datetime.DateFormatterRegistrar;
|
||||
|
||||
/**
|
||||
* Installs lower-level type converters required to integrate Joda Time support into Spring's field formatting system.
|
||||
* Installs lower-level type converters required to integrate
|
||||
* Joda-Time support into Spring's field formatting system.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Phillip Webb
|
||||
@@ -50,116 +52,87 @@ final class JodaTimeConverters {
|
||||
registry.addConverter(new DateTimeToLocalTimeConverter());
|
||||
registry.addConverter(new DateTimeToLocalDateTimeConverter());
|
||||
registry.addConverter(new DateTimeToDateMidnightConverter());
|
||||
registry.addConverter(new DateTimeToInstantConverter());
|
||||
registry.addConverter(new DateTimeToMutableDateTimeConverter());
|
||||
registry.addConverter(new DateTimeToInstantConverter());
|
||||
registry.addConverter(new DateTimeToDateConverter());
|
||||
registry.addConverter(new DateTimeToCalendarConverter());
|
||||
registry.addConverter(new DateTimeToLongConverter());
|
||||
registry.addConverter(new CalendarToReadableInstantConverter());
|
||||
registry.addConverter(new DateToReadableInstantConverter());
|
||||
registry.addConverter(new CalendarToReadableInstantConverter());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Used when binding a parsed DateTime to a LocalDate field.
|
||||
* @see DateTimeParser
|
||||
**/
|
||||
private static class DateTimeToLocalDateConverter implements Converter<DateTime, LocalDate> {
|
||||
|
||||
public LocalDate convert(DateTime source) {
|
||||
return source.toLocalDate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when binding a parsed DateTime to a LocalTime field.
|
||||
* @see DateTimeParser
|
||||
*/
|
||||
|
||||
private static class DateTimeToLocalTimeConverter implements Converter<DateTime, LocalTime> {
|
||||
|
||||
public LocalTime convert(DateTime source) {
|
||||
return source.toLocalTime();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when binding a parsed DateTime to a LocalDateTime field.
|
||||
* @see DateTimeParser
|
||||
*/
|
||||
|
||||
private static class DateTimeToLocalDateTimeConverter implements Converter<DateTime, LocalDateTime> {
|
||||
|
||||
public LocalDateTime convert(DateTime source) {
|
||||
return source.toLocalDateTime();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when binding a parsed DateTime to a DateMidnight field.
|
||||
* @see DateTimeParser
|
||||
*/
|
||||
|
||||
private static class DateTimeToDateMidnightConverter implements Converter<DateTime, DateMidnight> {
|
||||
|
||||
public DateMidnight convert(DateTime source) {
|
||||
return source.toDateMidnight();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when binding a parsed DateTime to an Instant field.
|
||||
* @see DateTimeParser
|
||||
*/
|
||||
private static class DateTimeToInstantConverter implements Converter<DateTime, Instant> {
|
||||
public Instant convert(DateTime source) {
|
||||
return source.toInstant();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when binding a parsed DateTime to a MutableDateTime field.
|
||||
* @see DateTimeParser
|
||||
*/
|
||||
private static class DateTimeToMutableDateTimeConverter implements Converter<DateTime, MutableDateTime> {
|
||||
|
||||
public MutableDateTime convert(DateTime source) {
|
||||
return source.toMutableDateTime();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when binding a parsed DateTime to a java.util.Date field.
|
||||
* @see DateTimeParser
|
||||
*/
|
||||
|
||||
private static class DateTimeToInstantConverter implements Converter<DateTime, Instant> {
|
||||
|
||||
public Instant convert(DateTime source) {
|
||||
return source.toInstant();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class DateTimeToDateConverter implements Converter<DateTime, Date> {
|
||||
|
||||
public Date convert(DateTime source) {
|
||||
return source.toDate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when binding a parsed DateTime to a java.util.Calendar field.
|
||||
* @see DateTimeParser
|
||||
*/
|
||||
|
||||
private static class DateTimeToCalendarConverter implements Converter<DateTime, Calendar> {
|
||||
|
||||
public Calendar convert(DateTime source) {
|
||||
return source.toGregorianCalendar();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when binding a parsed DateTime to a java.lang.Long field.
|
||||
* @see DateTimeParser
|
||||
*/
|
||||
|
||||
private static class DateTimeToLongConverter implements Converter<DateTime, Long> {
|
||||
|
||||
public Long convert(DateTime source) {
|
||||
return source.getMillis();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when printing a java.util.Calendar field with a ReadableInstantPrinter.
|
||||
* @see MillisecondInstantPrinter
|
||||
* @see JodaDateTimeFormatAnnotationFormatterFactory
|
||||
*/
|
||||
private static class CalendarToReadableInstantConverter implements Converter<Calendar, ReadableInstant> {
|
||||
public ReadableInstant convert(Calendar source) {
|
||||
return new DateTime(source);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when printing a java.util.Date field with a ReadableInstantPrinter.
|
||||
@@ -167,8 +140,23 @@ final class JodaTimeConverters {
|
||||
* @see JodaDateTimeFormatAnnotationFormatterFactory
|
||||
*/
|
||||
private static class DateToReadableInstantConverter implements Converter<Date, ReadableInstant> {
|
||||
|
||||
public ReadableInstant convert(Date source) {
|
||||
return new DateTime(source);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Used when printing a java.util.Calendar field with a ReadableInstantPrinter.
|
||||
* @see MillisecondInstantPrinter
|
||||
* @see JodaDateTimeFormatAnnotationFormatterFactory
|
||||
*/
|
||||
private static class CalendarToReadableInstantConverter implements Converter<Calendar, ReadableInstant> {
|
||||
|
||||
public ReadableInstant convert(Calendar source) {
|
||||
return new DateTime(source);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+35
-30
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.format.datetime.joda;
|
||||
|
||||
import java.util.Calendar;
|
||||
@@ -35,7 +36,7 @@ import org.springframework.format.Printer;
|
||||
import org.springframework.format.annotation.DateTimeFormat.ISO;
|
||||
|
||||
/**
|
||||
* Configures Joda Time's formatting system for use with Spring.
|
||||
* Configures Joda-Time's formatting system for use with Spring.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Juergen Hoeller
|
||||
@@ -51,15 +52,18 @@ import org.springframework.format.annotation.DateTimeFormat.ISO;
|
||||
*/
|
||||
public class JodaTimeFormatterRegistrar implements FormatterRegistrar {
|
||||
|
||||
private static enum Type {DATE, TIME, DATE_TIME}
|
||||
|
||||
|
||||
/**
|
||||
* User defined formatters.
|
||||
*/
|
||||
private Map<Type, DateTimeFormatter> formatters = new HashMap<Type, DateTimeFormatter>();
|
||||
private final Map<Type, DateTimeFormatter> formatters = new HashMap<Type, DateTimeFormatter>();
|
||||
|
||||
/**
|
||||
* Factories used when specific formatters have not been specified.
|
||||
*/
|
||||
private Map<Type, DateTimeFormatterFactory> factories;
|
||||
private final Map<Type, DateTimeFormatterFactory> factories;
|
||||
|
||||
|
||||
public JodaTimeFormatterRegistrar() {
|
||||
@@ -70,12 +74,24 @@ public class JodaTimeFormatterRegistrar implements FormatterRegistrar {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set whether standard ISO formatting should be applied to all date/time types.
|
||||
* Default is "false" (no).
|
||||
* <p>If set to "true", the "dateStyle", "timeStyle" and "dateTimeStyle"
|
||||
* properties are effectively ignored.
|
||||
*/
|
||||
public void setUseIsoFormat(boolean useIsoFormat) {
|
||||
this.factories.get(Type.DATE).setIso(useIsoFormat ? ISO.DATE : null);
|
||||
this.factories.get(Type.TIME).setIso(useIsoFormat ? ISO.TIME : null);
|
||||
this.factories.get(Type.DATE_TIME).setIso(useIsoFormat ? ISO.DATE_TIME : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default format style of Joda {@link LocalDate} objects.
|
||||
* Default is {@link DateTimeFormat#shortDate()}.
|
||||
*/
|
||||
public void setDateStyle(String dateStyle) {
|
||||
this.factories.get(Type.DATE).setStyle(dateStyle+"-");
|
||||
this.factories.get(Type.DATE).setStyle(dateStyle + "-");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,7 +99,7 @@ public class JodaTimeFormatterRegistrar implements FormatterRegistrar {
|
||||
* Default is {@link DateTimeFormat#shortTime()}.
|
||||
*/
|
||||
public void setTimeStyle(String timeStyle) {
|
||||
this.factories.get(Type.TIME).setStyle("-"+timeStyle);
|
||||
this.factories.get(Type.TIME).setStyle("-" + timeStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,25 +111,14 @@ public class JodaTimeFormatterRegistrar implements FormatterRegistrar {
|
||||
this.factories.get(Type.DATE_TIME).setStyle(dateTimeStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether standard ISO formatting should be applied to all Date/Time types.
|
||||
* Default is false (no).
|
||||
* If set to true, the dateStyle, timeStyle, and dateTimeStyle properties are ignored.
|
||||
*/
|
||||
public void setUseIsoFormat(boolean useIsoFormat) {
|
||||
this.factories.get(Type.DATE).setIso(useIsoFormat ? ISO.DATE : null);
|
||||
this.factories.get(Type.TIME).setIso(useIsoFormat ? ISO.TIME : null);
|
||||
this.factories.get(Type.DATE_TIME).setIso(useIsoFormat ? ISO.DATE_TIME : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the formatter that will be used for objects representing date values.
|
||||
* <p>This formatter will be used for the {@link LocalDate} type. When specified
|
||||
* the {@link #setDateStyle(String) dateStyle} and
|
||||
* {@link #setUseIsoFormat(boolean) useIsoFormat} properties will be ignored.
|
||||
* @param formatter the formatter to use
|
||||
* @see #setTimeFormatter(DateTimeFormatter)
|
||||
* @see #setDateTimeFormatter(DateTimeFormatter)
|
||||
* @see #setTimeFormatter
|
||||
* @see #setDateTimeFormatter
|
||||
* @since 3.2
|
||||
*/
|
||||
public void setDateFormatter(DateTimeFormatter formatter) {
|
||||
@@ -126,8 +131,8 @@ public class JodaTimeFormatterRegistrar implements FormatterRegistrar {
|
||||
* the {@link #setTimeStyle(String) timeStyle} and
|
||||
* {@link #setUseIsoFormat(boolean) useIsoFormat} properties will be ignored.
|
||||
* @param formatter the formatter to use
|
||||
* @see #setDateFormatter(DateTimeFormatter)
|
||||
* @see #setDateTimeFormatter(DateTimeFormatter)
|
||||
* @see #setDateFormatter
|
||||
* @see #setDateTimeFormatter
|
||||
* @since 3.2
|
||||
*/
|
||||
public void setTimeFormatter(DateTimeFormatter formatter) {
|
||||
@@ -141,14 +146,15 @@ public class JodaTimeFormatterRegistrar implements FormatterRegistrar {
|
||||
* the {@link #setDateTimeStyle(String) dateTimeStyle} and
|
||||
* {@link #setUseIsoFormat(boolean) useIsoFormat} properties will be ignored.
|
||||
* @param formatter the formatter to use
|
||||
* @see #setDateFormatter(DateTimeFormatter)
|
||||
* @see #setTimeFormatter(DateTimeFormatter)
|
||||
* @see #setDateFormatter
|
||||
* @see #setTimeFormatter
|
||||
* @since 3.2
|
||||
*/
|
||||
public void setDateTimeFormatter(DateTimeFormatter formatter) {
|
||||
this.formatters.put(Type.DATE_TIME, formatter);
|
||||
}
|
||||
|
||||
|
||||
public void registerFormatters(FormatterRegistry registry) {
|
||||
JodaTimeConverters.registerConverters(registry);
|
||||
|
||||
@@ -176,26 +182,25 @@ public class JodaTimeFormatterRegistrar implements FormatterRegistrar {
|
||||
new DateTimeParser(dateTimeFormatter),
|
||||
ReadableInstant.class);
|
||||
|
||||
// In order to retain back compatibility we only register Date/Calendar
|
||||
// In order to retain backwards compatibility we only register Date/Calendar
|
||||
// types when a user defined formatter is specified (see SPR-10105)
|
||||
if(this.formatters.containsKey(Type.DATE_TIME)) {
|
||||
if( this.formatters.containsKey(Type.DATE_TIME)) {
|
||||
addFormatterForFields(registry,
|
||||
new ReadableInstantPrinter(dateTimeFormatter),
|
||||
new DateTimeParser(dateTimeFormatter),
|
||||
Date.class, Calendar.class);
|
||||
}
|
||||
|
||||
registry.addFormatterForFieldAnnotation(
|
||||
new JodaDateTimeFormatAnnotationFormatterFactory());
|
||||
registry.addFormatterForFieldAnnotation(new JodaDateTimeFormatAnnotationFormatterFactory());
|
||||
}
|
||||
|
||||
private DateTimeFormatter getFormatter(Type type) {
|
||||
DateTimeFormatter formatter = this.formatters.get(type);
|
||||
if(formatter != null) {
|
||||
if (formatter != null) {
|
||||
return formatter;
|
||||
}
|
||||
DateTimeFormatter fallbackFormatter = getFallbackFormatter(type);
|
||||
return this.factories.get(type).createDateTimeFormatter(fallbackFormatter );
|
||||
return this.factories.get(type).createDateTimeFormatter(fallbackFormatter);
|
||||
}
|
||||
|
||||
private DateTimeFormatter getFallbackFormatter(Type type) {
|
||||
@@ -208,10 +213,10 @@ public class JodaTimeFormatterRegistrar implements FormatterRegistrar {
|
||||
|
||||
private void addFormatterForFields(FormatterRegistry registry, Printer<?> printer,
|
||||
Parser<?> parser, Class<?>... fieldTypes) {
|
||||
|
||||
for (Class<?> fieldType : fieldTypes) {
|
||||
registry.addFormatterForFieldType(fieldType, printer, parser);
|
||||
}
|
||||
}
|
||||
|
||||
private static enum Type {DATE, TIME, DATE_TIME}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
* Integration with the Joda Time for formatting Joda types as well as standard JDK Date types.
|
||||
* Integration with Joda-Time for formatting Joda date and time types as well as standard JDK Date types.
|
||||
*/
|
||||
package org.springframework.format.datetime.joda;
|
||||
|
||||
+9
-3
@@ -16,12 +16,12 @@
|
||||
|
||||
package org.springframework.scheduling.support;
|
||||
|
||||
import org.springframework.scheduling.Trigger;
|
||||
import org.springframework.scheduling.TriggerContext;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.springframework.scheduling.Trigger;
|
||||
import org.springframework.scheduling.TriggerContext;
|
||||
|
||||
/**
|
||||
* {@link Trigger} implementation for cron expressions.
|
||||
* Wraps a {@link CronSequenceGenerator}.
|
||||
@@ -55,6 +55,12 @@ public class CronTrigger implements Trigger {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine the next execution time according to the given trigger context.
|
||||
* <p>Next execution times are calculated based on the
|
||||
* {@linkplain TriggerContext#lastCompletionTime completion time} of the
|
||||
* previous execution; therefore, overlapping executions won't occur.
|
||||
*/
|
||||
public Date nextExecutionTime(TriggerContext triggerContext) {
|
||||
Date date = triggerContext.lastCompletionTime();
|
||||
if (date != null) {
|
||||
|
||||
+21
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -51,6 +51,12 @@ import org.springframework.util.CollectionUtils;
|
||||
* you will almost always use the default Validator anyway. This can also be injected directly
|
||||
* into any target dependency of type {@link org.springframework.validation.Validator}!
|
||||
*
|
||||
* <p><b>NOTE: This class is based on Bean Validation 1.0 and (optionally) Hibernate Validator 4.x.</b>
|
||||
* Nevertheless, its core functionality does work against Bean Validation 1.1 at runtime.
|
||||
* However, there is no special support for Hibernate Validator 5.0 yet; as a consequence,
|
||||
* {@link #setValidationMessageSource} won't work in that scenario. Please stick with
|
||||
* Hibernate Validator 4.3 for the time being, or upgrade to Spring Framework 4.0.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @see javax.validation.ValidatorFactory
|
||||
@@ -217,10 +223,23 @@ public class LocalValidatorFactoryBean extends SpringValidatorAdapter
|
||||
configuration.addProperty(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
// Allow for custom post-processing before we actually build the ValidatorFactory.
|
||||
postProcessConfiguration(configuration);
|
||||
|
||||
this.validatorFactory = configuration.buildValidatorFactory();
|
||||
setTargetValidator(this.validatorFactory.getValidator());
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-process the given Bean Validation configuration,
|
||||
* adding to or overriding any of its settings.
|
||||
* <p>Invoked right before building the {@link ValidatorFactory}.
|
||||
* @param configuration the Configuration object, pre-populated with
|
||||
* settings driven by LocalValidatorFactoryBean's properties
|
||||
*/
|
||||
protected void postProcessConfiguration(Configuration configuration) {
|
||||
}
|
||||
|
||||
|
||||
public Validator getValidator() {
|
||||
return this.validatorFactory.getValidator();
|
||||
@@ -244,7 +263,7 @@ public class LocalValidatorFactoryBean extends SpringValidatorAdapter
|
||||
|
||||
|
||||
/**
|
||||
* Inner class to avoid a hard-coded Hibernate Validator 4.1 dependency.
|
||||
* Inner class to avoid a hard-coded Hibernate Validator 4.1+ dependency.
|
||||
*/
|
||||
private static class HibernateValidatorDelegate {
|
||||
|
||||
|
||||
+5
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -48,9 +48,10 @@ import org.springframework.validation.annotation.Validated;
|
||||
* inline constraint annotations. Validation groups can be specified through {@code @Validated}
|
||||
* as well. By default, JSR-303 will validate against its default group only.
|
||||
*
|
||||
* <p>As of Spring 3.1, this functionality requires Hibernate Validator 4.2 or higher.
|
||||
* In a future version of Spring, this class will autodetect a Bean Validation 1.1 compliant
|
||||
* provider and automatically use the standard method validation support when available.
|
||||
* <p>As of Spring 3.1, this functionality requires Hibernate Validator 4.2 or 4.3.
|
||||
* In Spring 4.0, this class will autodetect a Bean Validation 1.1 compliant provider
|
||||
* (such as Hibernate Validator 5.0) and automatically use the standard method
|
||||
* validation support when available.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
|
||||
+2
-2
@@ -79,7 +79,7 @@ public class ImportedConfigurationClassEnhancementTests {
|
||||
|
||||
|
||||
@Test(expected=BeanDefinitionParsingException.class)
|
||||
public void importingAnNonConfigurationClassCausesIllegalArgumentException() {
|
||||
public void importingNonConfigurationClassCausesBeanDefinitionParsingException() {
|
||||
new AnnotationConfigApplicationContext(ConfigThatImportsNonConfigClass.class);
|
||||
}
|
||||
}
|
||||
@@ -103,5 +103,5 @@ class ConfigThatDoesImport extends Config { }
|
||||
class ConfigThatDoesNotImport extends Config { }
|
||||
|
||||
@Configuration
|
||||
@Import(Void.class)
|
||||
@Import(TestBean.class)
|
||||
class ConfigThatImportsNonConfigClass { }
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation.spr10546;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@Configuration
|
||||
public class ImportedConfig {
|
||||
@Bean
|
||||
public String myBean() {
|
||||
return "myBean";
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation.spr10546;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@Configuration
|
||||
public class ParentConfig {
|
||||
@Bean
|
||||
public String myBean() {
|
||||
return "myBean";
|
||||
}
|
||||
}
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation.spr10546;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.spr10546.scanpackage.AEnclosingConfig;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@Configuration
|
||||
@ComponentScan(basePackageClasses=AEnclosingConfig.class)
|
||||
public class ParentWithComponentScanConfig {
|
||||
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation.spr10546;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@Configuration
|
||||
@Import(ImportedConfig.class)
|
||||
public class ParentWithImportConfig {
|
||||
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation.spr10546;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportResource;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@Configuration
|
||||
@ImportResource("classpath:org/springframework/context/annotation/spr10546/importedResource.xml")
|
||||
public class ParentWithImportResourceConfig {
|
||||
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation.spr10546;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@Configuration
|
||||
public class ParentWithParentConfig extends ParentConfig {
|
||||
|
||||
}
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation.spr10546;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.spr10546.scanpackage.AEnclosingConfig;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public class Spr10546Tests {
|
||||
private ConfigurableApplicationContext context;
|
||||
|
||||
@After
|
||||
public void closeContext() {
|
||||
if(context != null) {
|
||||
context.close();
|
||||
}
|
||||
}
|
||||
|
||||
// These fail prior to fixing SPR-10546
|
||||
|
||||
@Test
|
||||
public void enclosingConfigFirstParentDefinesBean() {
|
||||
assertLoadsMyBean(AEnclosingConfig.class,AEnclosingConfig.ChildConfig.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prior to fixing SPR-10546 this might have succeeded depending on the ordering the
|
||||
* classes were picked up. If they are picked up in the same order as
|
||||
* {@link #enclosingConfigFirstParentDefinesBean()} then it would fail. This test is
|
||||
* mostly for illustration purposes, but doesn't hurt to continue using it.
|
||||
*
|
||||
* <p>We purposely use the {@link AEnclosingConfig} to make it alphabetically prior to the
|
||||
* {@link AEnclosingConfig.ChildConfig} which encourages this to occur with the
|
||||
* classpath scanning implementation being used by the author of this test.
|
||||
*/
|
||||
@Test
|
||||
public void enclosingConfigFirstParentDefinesBeanWithScanning() {
|
||||
AnnotationConfigApplicationContext ctx= new AnnotationConfigApplicationContext();
|
||||
context = ctx;
|
||||
ctx.scan(AEnclosingConfig.class.getPackage().getName());
|
||||
ctx.refresh();
|
||||
assertThat(context.getBean("myBean",String.class), equalTo("myBean"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enclosingConfigFirstParentDefinesBeanWithImportResource() {
|
||||
assertLoadsMyBean(AEnclosingWithImportResourceConfig.class,AEnclosingWithImportResourceConfig.ChildConfig.class);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class AEnclosingWithImportResourceConfig {
|
||||
@Configuration
|
||||
public static class ChildConfig extends ParentWithImportResourceConfig {}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enclosingConfigFirstParentDefinesBeanWithComponentScan() {
|
||||
assertLoadsMyBean(AEnclosingWithComponentScanConfig.class,AEnclosingWithComponentScanConfig.ChildConfig.class);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class AEnclosingWithComponentScanConfig {
|
||||
@Configuration
|
||||
public static class ChildConfig extends ParentWithComponentScanConfig {}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enclosingConfigFirstParentWithParentDefinesBean() {
|
||||
assertLoadsMyBean(AEnclosingWithGrandparentConfig.class,AEnclosingWithGrandparentConfig.ChildConfig.class);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class AEnclosingWithGrandparentConfig {
|
||||
@Configuration
|
||||
public static class ChildConfig extends ParentWithParentConfig {}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void importChildConfigThenChildConfig() {
|
||||
assertLoadsMyBean(ImportChildConfig.class,ChildConfig.class);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class ChildConfig extends ParentConfig {}
|
||||
|
||||
@Configuration
|
||||
@Import(ChildConfig.class)
|
||||
static class ImportChildConfig {}
|
||||
|
||||
|
||||
// These worked prior, but validating they continue to work
|
||||
|
||||
@Test
|
||||
public void enclosingConfigFirstParentDefinesBeanWithImport() {
|
||||
assertLoadsMyBean(AEnclosingWithImportConfig.class,AEnclosingWithImportConfig.ChildConfig.class);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class AEnclosingWithImportConfig {
|
||||
@Configuration
|
||||
public static class ChildConfig extends ParentWithImportConfig {}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void childConfigFirst() {
|
||||
assertLoadsMyBean(AEnclosingConfig.ChildConfig.class, AEnclosingConfig.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enclosingConfigOnly() {
|
||||
assertLoadsMyBean(AEnclosingConfig.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void childConfigOnly() {
|
||||
assertLoadsMyBean(AEnclosingConfig.ChildConfig.class);
|
||||
}
|
||||
|
||||
private void assertLoadsMyBean(Class<?>... annotatedClasses) {
|
||||
context = new AnnotationConfigApplicationContext(annotatedClasses);
|
||||
assertThat(context.getBean("myBean",String.class), equalTo("myBean"));
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:c="http://www.springframework.org/schema/c"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<bean id="myBean" class="java.lang.String" c:_0="myBean"/>
|
||||
</beans>
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation.spr10546.scanpackage;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.spr10546.ParentConfig;
|
||||
|
||||
|
||||
/**
|
||||
* Note the name of {@link AEnclosingConfig} is chosen to help ensure scanning picks up
|
||||
* the enclosing configuration prior to {@link ChildConfig} to demonstrate this can happen
|
||||
* with classpath scanning.
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@Configuration
|
||||
public class AEnclosingConfig {
|
||||
@Configuration
|
||||
public static class ChildConfig extends ParentConfig {}
|
||||
}
|
||||
+1
-2
@@ -26,8 +26,6 @@ import org.joda.time.format.DateTimeFormatter;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Tests for {@link DateTimeFormatterFactoryBean}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
@@ -60,4 +58,5 @@ public class DateTimeFormatterFactoryBeanTests {
|
||||
factory.setStyle("LL");
|
||||
assertThat(factory.getObject(), is(sameInstance(formatter)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-2
@@ -30,8 +30,6 @@ import org.junit.Test;
|
||||
import org.springframework.format.annotation.DateTimeFormat.ISO;
|
||||
|
||||
/**
|
||||
* Tests for {@link DateTimeFormatterFactory}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
@@ -100,4 +98,5 @@ public class DateTimeFormatterFactoryTests {
|
||||
private DateTimeFormatter applyLocale(DateTimeFormatter dateTimeFormatter) {
|
||||
return dateTimeFormatter.withLocale(Locale.US);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -116,7 +116,7 @@ public class JodaTimeFormattingTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBindLocalDateWithSpecifcFormatter() throws Exception {
|
||||
public void testBindLocalDateWithSpecificFormatter() throws Exception {
|
||||
JodaTimeFormatterRegistrar registrar = new JodaTimeFormatterRegistrar();
|
||||
registrar.setDateFormatter(org.joda.time.format.DateTimeFormat.forPattern("yyyyMMdd"));
|
||||
setUp(registrar);
|
||||
|
||||
+7
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,6 +23,8 @@ import javax.management.modelmbean.RequiredModelMBean;
|
||||
import javax.management.modelmbean.ModelMBeanInfo;
|
||||
import javax.management.modelmbean.ModelMBeanInfoSupport;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.jmx.AbstractMBeanServerTests;
|
||||
import org.springframework.jmx.JmxTestBean;
|
||||
import org.springframework.jmx.export.naming.ObjectNamingStrategy;
|
||||
@@ -36,6 +38,7 @@ import static org.junit.Assert.*;
|
||||
*/
|
||||
public class MBeanExporterOperationsTests extends AbstractMBeanServerTests {
|
||||
|
||||
@Test
|
||||
public void testRegisterManagedResourceWithUserSuppliedObjectName() throws Exception {
|
||||
ObjectName objectName = ObjectNameManager.getInstance("spring:name=Foo");
|
||||
|
||||
@@ -50,6 +53,7 @@ public class MBeanExporterOperationsTests extends AbstractMBeanServerTests {
|
||||
assertEquals("Incorrect name on MBean", name, bean.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterExistingMBeanWithUserSuppliedObjectName() throws Exception {
|
||||
ObjectName objectName = ObjectNameManager.getInstance("spring:name=Foo");
|
||||
ModelMBeanInfo info = new ModelMBeanInfoSupport("myClass", "myDescription", null, null, null, null);
|
||||
@@ -63,6 +67,7 @@ public class MBeanExporterOperationsTests extends AbstractMBeanServerTests {
|
||||
assertEquals(info, infoFromServer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterManagedResourceWithGeneratedObjectName() throws Exception {
|
||||
final ObjectName objectNameTemplate = ObjectNameManager.getInstance("spring:type=Test");
|
||||
|
||||
@@ -88,6 +93,7 @@ public class MBeanExporterOperationsTests extends AbstractMBeanServerTests {
|
||||
assertObjectNameMatchesTemplate(objectNameTemplate, reg2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterManagedResourceWithGeneratedObjectNameWithoutUniqueness() throws Exception {
|
||||
final ObjectName objectNameTemplate = ObjectNameManager.getInstance("spring:type=Test");
|
||||
|
||||
|
||||
@@ -16,26 +16,26 @@
|
||||
|
||||
package org.springframework.ui;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Rick Evans
|
||||
* @author Juergen Hoeller
|
||||
@@ -226,12 +226,12 @@ public final class ModelMapTests {
|
||||
public void testAopCglibProxy() throws Exception {
|
||||
ModelMap map = new ModelMap();
|
||||
ProxyFactory factory = new ProxyFactory();
|
||||
Date date = new Date();
|
||||
factory.setTarget(date);
|
||||
SomeInnerClass val = new SomeInnerClass();
|
||||
factory.setTarget(val);
|
||||
factory.setProxyTargetClass(true);
|
||||
map.addAttribute(factory.getProxy());
|
||||
assertTrue(map.containsKey("date"));
|
||||
assertEquals(date, map.get("date"));
|
||||
assertTrue(map.containsKey("someInnerClass"));
|
||||
assertEquals(val, map.get("someInnerClass"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -288,11 +288,20 @@ public final class ModelMapTests {
|
||||
}
|
||||
|
||||
|
||||
private static class SomeInnerClass {
|
||||
public static class SomeInnerClass {
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
return (obj instanceof SomeInnerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return SomeInnerClass.class.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class UKInnerClass {
|
||||
public static class UKInnerClass {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.format.Formatter;
|
||||
import org.springframework.format.number.NumberFormatter;
|
||||
import org.springframework.format.support.FormattingConversionService;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -614,8 +615,8 @@ public class DataBinderTests extends TestCase {
|
||||
assertNull(rod.getSomeMap().get("key4"));
|
||||
String[] disallowedFields = binder.getBindingResult().getSuppressedFields();
|
||||
assertEquals(2, disallowedFields.length);
|
||||
assertEquals("someMap[key3]", disallowedFields[0]);
|
||||
assertEquals("someMap[key4]", disallowedFields[1]);
|
||||
assertTrue(ObjectUtils.containsElement(disallowedFields, "someMap[key3]"));
|
||||
assertTrue(ObjectUtils.containsElement(disallowedFields, "someMap[key4]"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+9
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.core;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.MalformedParameterizedTypeException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
@@ -446,8 +447,13 @@ public abstract class GenericCollectionTypeResolver {
|
||||
return null;
|
||||
}
|
||||
if (clazz.getSuperclass() != null && isIntrospectionCandidate(clazz.getSuperclass())) {
|
||||
return extractType(clazz.getGenericSuperclass(), source, typeIndex, typeVariableMap, typeIndexesPerLevel,
|
||||
nestingLevel, currentLevel);
|
||||
try {
|
||||
return extractType(clazz.getGenericSuperclass(), source, typeIndex, typeVariableMap,
|
||||
typeIndexesPerLevel, nestingLevel, currentLevel);
|
||||
}
|
||||
catch (MalformedParameterizedTypeException ex) {
|
||||
// from getGenericSuperclass() - ignore and continue with interface introspection
|
||||
}
|
||||
}
|
||||
Type[] ifcs = clazz.getGenericInterfaces();
|
||||
if (ifcs != null) {
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.core;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.MalformedParameterizedTypeException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
@@ -74,12 +75,12 @@ public abstract class GenericTypeResolver {
|
||||
* @param clazz the class to resolve type variables against
|
||||
* @return the corresponding generic parameter or return type
|
||||
*/
|
||||
public static Class<?> resolveParameterType(MethodParameter methodParam, Class clazz) {
|
||||
public static Class<?> resolveParameterType(MethodParameter methodParam, Class<?> clazz) {
|
||||
Type genericType = getTargetType(methodParam);
|
||||
Assert.notNull(clazz, "Class must not be null");
|
||||
Map<TypeVariable, Type> typeVariableMap = getTypeVariableMap(clazz);
|
||||
Type rawType = getRawType(genericType, typeVariableMap);
|
||||
Class result = (rawType instanceof Class ? (Class) rawType : methodParam.getParameterType());
|
||||
Class<?> result = (rawType instanceof Class ? (Class) rawType : methodParam.getParameterType());
|
||||
methodParam.setParameterType(result);
|
||||
methodParam.typeVariableMap = typeVariableMap;
|
||||
return result;
|
||||
@@ -227,7 +228,7 @@ public abstract class GenericTypeResolver {
|
||||
* @param genericIfc the generic interface or superclass to resolve the type argument from
|
||||
* @return the resolved type of the argument, or {@code null} if not resolvable
|
||||
*/
|
||||
public static Class<?> resolveTypeArgument(Class clazz, Class genericIfc) {
|
||||
public static Class<?> resolveTypeArgument(Class<?> clazz, Class<?> genericIfc) {
|
||||
Class[] typeArgs = resolveTypeArguments(clazz, genericIfc);
|
||||
if (typeArgs == null) {
|
||||
return null;
|
||||
@@ -248,11 +249,11 @@ public abstract class GenericTypeResolver {
|
||||
* @return the resolved type of each argument, with the array size matching the
|
||||
* number of actual type arguments, or {@code null} if not resolvable
|
||||
*/
|
||||
public static Class[] resolveTypeArguments(Class clazz, Class genericIfc) {
|
||||
public static Class[] resolveTypeArguments(Class<?> clazz, Class<?> genericIfc) {
|
||||
return doResolveTypeArguments(clazz, clazz, genericIfc);
|
||||
}
|
||||
|
||||
private static Class[] doResolveTypeArguments(Class ownerClass, Class classToIntrospect, Class genericIfc) {
|
||||
private static Class[] doResolveTypeArguments(Class<?> ownerClass, Class<?> classToIntrospect, Class<?> genericIfc) {
|
||||
while (classToIntrospect != null) {
|
||||
if (genericIfc.isInterface()) {
|
||||
Type[] ifcs = classToIntrospect.getGenericInterfaces();
|
||||
@@ -264,10 +265,15 @@ public abstract class GenericTypeResolver {
|
||||
}
|
||||
}
|
||||
else {
|
||||
Class[] result = doResolveTypeArguments(
|
||||
ownerClass, classToIntrospect.getGenericSuperclass(), genericIfc);
|
||||
if (result != null) {
|
||||
return result;
|
||||
try {
|
||||
Class[] result = doResolveTypeArguments(ownerClass, classToIntrospect.getGenericSuperclass(), genericIfc);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
catch (MalformedParameterizedTypeException ex) {
|
||||
// from getGenericSuperclass() - return null to skip further superclass traversal
|
||||
return null;
|
||||
}
|
||||
}
|
||||
classToIntrospect = classToIntrospect.getSuperclass();
|
||||
@@ -275,7 +281,7 @@ public abstract class GenericTypeResolver {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Class[] doResolveTypeArguments(Class ownerClass, Type ifc, Class genericIfc) {
|
||||
private static Class[] doResolveTypeArguments(Class<?> ownerClass, Type ifc, Class<?> genericIfc) {
|
||||
if (ifc instanceof ParameterizedType) {
|
||||
ParameterizedType paramIfc = (ParameterizedType) ifc;
|
||||
Type rawType = paramIfc.getRawType();
|
||||
@@ -301,7 +307,7 @@ public abstract class GenericTypeResolver {
|
||||
/**
|
||||
* Extract a class instance from given Type.
|
||||
*/
|
||||
private static Class extractClass(Class ownerClass, Type arg) {
|
||||
private static Class<?> extractClass(Class<?> ownerClass, Type arg) {
|
||||
if (arg instanceof ParameterizedType) {
|
||||
return extractClass(ownerClass, ((ParameterizedType) arg).getRawType());
|
||||
}
|
||||
@@ -368,7 +374,7 @@ public abstract class GenericTypeResolver {
|
||||
* {@link Class concrete classes} for the specified {@link Class}. Searches
|
||||
* all super types, enclosing types and interfaces.
|
||||
*/
|
||||
public static Map<TypeVariable, Type> getTypeVariableMap(Class clazz) {
|
||||
public static Map<TypeVariable, Type> getTypeVariableMap(Class<?> clazz) {
|
||||
Map<TypeVariable, Type> typeVariableMap = typeVariableCache.get(clazz);
|
||||
|
||||
if (typeVariableMap == null) {
|
||||
@@ -377,28 +383,37 @@ public abstract class GenericTypeResolver {
|
||||
// interfaces
|
||||
extractTypeVariablesFromGenericInterfaces(clazz.getGenericInterfaces(), typeVariableMap);
|
||||
|
||||
// super class
|
||||
Type genericType = clazz.getGenericSuperclass();
|
||||
Class type = clazz.getSuperclass();
|
||||
while (type != null && !Object.class.equals(type)) {
|
||||
if (genericType instanceof ParameterizedType) {
|
||||
ParameterizedType pt = (ParameterizedType) genericType;
|
||||
populateTypeMapFromParameterizedType(pt, typeVariableMap);
|
||||
try {
|
||||
// super class
|
||||
Class<?> type = clazz;
|
||||
while (type.getSuperclass() != null && !Object.class.equals(type.getSuperclass())) {
|
||||
Type genericType = type.getGenericSuperclass();
|
||||
if (genericType instanceof ParameterizedType) {
|
||||
ParameterizedType pt = (ParameterizedType) genericType;
|
||||
populateTypeMapFromParameterizedType(pt, typeVariableMap);
|
||||
}
|
||||
extractTypeVariablesFromGenericInterfaces(type.getSuperclass().getGenericInterfaces(), typeVariableMap);
|
||||
type = type.getSuperclass();
|
||||
}
|
||||
extractTypeVariablesFromGenericInterfaces(type.getGenericInterfaces(), typeVariableMap);
|
||||
genericType = type.getGenericSuperclass();
|
||||
type = type.getSuperclass();
|
||||
}
|
||||
catch (MalformedParameterizedTypeException ex) {
|
||||
// from getGenericSuperclass() - ignore and continue with member class check
|
||||
}
|
||||
|
||||
// enclosing class
|
||||
type = clazz;
|
||||
while (type.isMemberClass()) {
|
||||
genericType = type.getGenericSuperclass();
|
||||
if (genericType instanceof ParameterizedType) {
|
||||
ParameterizedType pt = (ParameterizedType) genericType;
|
||||
populateTypeMapFromParameterizedType(pt, typeVariableMap);
|
||||
try {
|
||||
// enclosing class
|
||||
Class<?> type = clazz;
|
||||
while (type.isMemberClass()) {
|
||||
Type genericType = type.getGenericSuperclass();
|
||||
if (genericType instanceof ParameterizedType) {
|
||||
ParameterizedType pt = (ParameterizedType) genericType;
|
||||
populateTypeMapFromParameterizedType(pt, typeVariableMap);
|
||||
}
|
||||
type = type.getEnclosingClass();
|
||||
}
|
||||
type = type.getEnclosingClass();
|
||||
}
|
||||
catch (MalformedParameterizedTypeException ex) {
|
||||
// from getGenericSuperclass() - ignore and preserve previously accumulated type variables
|
||||
}
|
||||
|
||||
typeVariableCache.put(clazz, typeVariableMap);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -54,6 +54,11 @@ public abstract class JdkVersion {
|
||||
*/
|
||||
public static final int JAVA_17 = 4;
|
||||
|
||||
/**
|
||||
* Constant identifying the 1.8 JVM (Java 8).
|
||||
*/
|
||||
public static final int JAVA_18 = 5;
|
||||
|
||||
|
||||
private static final String javaVersion;
|
||||
|
||||
@@ -62,7 +67,10 @@ public abstract class JdkVersion {
|
||||
static {
|
||||
javaVersion = System.getProperty("java.version");
|
||||
// version String should look like "1.4.2_10"
|
||||
if (javaVersion.contains("1.7.")) {
|
||||
if (javaVersion.contains("1.8.")) {
|
||||
majorJavaVersion = JAVA_18;
|
||||
}
|
||||
else if (javaVersion.contains("1.7.")) {
|
||||
majorJavaVersion = JAVA_17;
|
||||
}
|
||||
else if (javaVersion.contains("1.6.")) {
|
||||
@@ -87,7 +95,7 @@ public abstract class JdkVersion {
|
||||
|
||||
/**
|
||||
* Get the major version code. This means we can do things like
|
||||
* {@code if (getMajorJavaVersion() < JAVA_14)}.
|
||||
* {@code if (getMajorJavaVersion() >= JAVA_17)}.
|
||||
* @return a code comparable to the JAVA_XX codes in this class
|
||||
* @see #JAVA_13
|
||||
* @see #JAVA_14
|
||||
|
||||
+9
-2
@@ -114,8 +114,15 @@ public class LocalVariableTableParameterNameDiscoverer implements ParameterNameD
|
||||
}
|
||||
catch (IOException ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Exception thrown while reading '.class' file for class [" + clazz
|
||||
+ "] - unable to determine constructors/methods parameter names", ex);
|
||||
logger.debug("Exception thrown while reading '.class' file for class [" + clazz +
|
||||
"] - unable to determine constructors/methods parameter names", ex);
|
||||
}
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("ASM ClassReader failed to parse class file [" + clazz +
|
||||
"], probably due to a new Java class file version that isn't supported yet " +
|
||||
"- unable to determine constructors/methods parameter names", ex);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
|
||||
+23
-31
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,7 +24,7 @@ import org.springframework.util.Assert;
|
||||
/**
|
||||
* The purpose of this class is to enable capturing and passing a generic
|
||||
* {@link Type}. In order to capture the generic type and retain it at runtime,
|
||||
* you need to create a sub-class as follows:
|
||||
* you need to create a subclass as follows:
|
||||
*
|
||||
* <pre class="code">
|
||||
* ParameterizedTypeReference<List<String>> typeRef = new ParameterizedTypeReference<List<String>>() {};
|
||||
@@ -37,54 +37,31 @@ import org.springframework.util.Assert;
|
||||
* @author Arjen Poutsma
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.2
|
||||
*
|
||||
* @see <a href="http://gafter.blogspot.nl/2006/12/super-type-tokens.html">Neal Gafter on Super Type Tokens</a>
|
||||
*/
|
||||
public abstract class ParameterizedTypeReference<T> {
|
||||
|
||||
private final Type type;
|
||||
|
||||
|
||||
protected ParameterizedTypeReference() {
|
||||
Class<?> parameterizedTypeReferenceSubClass = findParameterizedTypeReferenceSubClass(getClass());
|
||||
|
||||
Type type = parameterizedTypeReferenceSubClass.getGenericSuperclass();
|
||||
Class<?> parameterizedTypeReferenceSubclass = findParameterizedTypeReferenceSubclass(getClass());
|
||||
Type type = parameterizedTypeReferenceSubclass.getGenericSuperclass();
|
||||
Assert.isInstanceOf(ParameterizedType.class, type);
|
||||
|
||||
ParameterizedType parameterizedType = (ParameterizedType) type;
|
||||
Assert.isTrue(parameterizedType.getActualTypeArguments().length == 1);
|
||||
|
||||
this.type = parameterizedType.getActualTypeArguments()[0];
|
||||
}
|
||||
|
||||
private static Class<?> findParameterizedTypeReferenceSubClass(Class<?> child) {
|
||||
|
||||
Class<?> parent = child.getSuperclass();
|
||||
|
||||
if (Object.class.equals(parent)) {
|
||||
throw new IllegalStateException("Expected ParameterizedTypeReference superclass");
|
||||
}
|
||||
else if (ParameterizedTypeReference.class.equals(parent)) {
|
||||
return child;
|
||||
}
|
||||
else {
|
||||
return findParameterizedTypeReferenceSubClass(parent);
|
||||
}
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o instanceof ParameterizedTypeReference) {
|
||||
ParameterizedTypeReference<?> other = (ParameterizedTypeReference<?>) o;
|
||||
return this.type.equals(other.type);
|
||||
}
|
||||
return false;
|
||||
public boolean equals(Object obj) {
|
||||
return (this == obj || (obj instanceof ParameterizedTypeReference &&
|
||||
this.type.equals(((ParameterizedTypeReference) obj).type)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -96,4 +73,19 @@ public abstract class ParameterizedTypeReference<T> {
|
||||
public String toString() {
|
||||
return "ParameterizedTypeReference<" + this.type + ">";
|
||||
}
|
||||
|
||||
|
||||
private static Class<?> findParameterizedTypeReferenceSubclass(Class<?> child) {
|
||||
Class<?> parent = child.getSuperclass();
|
||||
if (Object.class.equals(parent)) {
|
||||
throw new IllegalStateException("Expected ParameterizedTypeReference superclass");
|
||||
}
|
||||
else if (ParameterizedTypeReference.class.equals(parent)) {
|
||||
return child;
|
||||
}
|
||||
else {
|
||||
return findParameterizedTypeReferenceSubclass(parent);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ public class AnnotationAwareOrderComparator extends OrderComparator {
|
||||
}
|
||||
if (obj != null) {
|
||||
Class<?> clazz = (obj instanceof Class ? (Class) obj : obj.getClass());
|
||||
Order order = clazz.getAnnotation(Order.class);
|
||||
Order order = AnnotationUtils.findAnnotation(clazz, Order.class);
|
||||
if (order != null) {
|
||||
return order.value();
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ package org.springframework.core.annotation;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
@@ -121,24 +120,24 @@ public abstract class AnnotationUtils {
|
||||
*/
|
||||
public static <A extends Annotation> A findAnnotation(Method method, Class<A> annotationType) {
|
||||
A annotation = getAnnotation(method, annotationType);
|
||||
Class<?> cl = method.getDeclaringClass();
|
||||
Class<?> clazz = method.getDeclaringClass();
|
||||
if (annotation == null) {
|
||||
annotation = searchOnInterfaces(method, annotationType, cl.getInterfaces());
|
||||
annotation = searchOnInterfaces(method, annotationType, clazz.getInterfaces());
|
||||
}
|
||||
while (annotation == null) {
|
||||
cl = cl.getSuperclass();
|
||||
if (cl == null || cl == Object.class) {
|
||||
clazz = clazz.getSuperclass();
|
||||
if (clazz == null || clazz.equals(Object.class)) {
|
||||
break;
|
||||
}
|
||||
try {
|
||||
Method equivalentMethod = cl.getDeclaredMethod(method.getName(), method.getParameterTypes());
|
||||
Method equivalentMethod = clazz.getDeclaredMethod(method.getName(), method.getParameterTypes());
|
||||
annotation = getAnnotation(equivalentMethod, annotationType);
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
// No equivalent method found
|
||||
}
|
||||
if (annotation == null) {
|
||||
annotation = searchOnInterfaces(method, annotationType, cl.getInterfaces());
|
||||
annotation = searchOnInterfaces(method, annotationType, clazz.getInterfaces());
|
||||
}
|
||||
}
|
||||
return annotation;
|
||||
@@ -217,7 +216,7 @@ public abstract class AnnotationUtils {
|
||||
}
|
||||
}
|
||||
Class<?> superClass = clazz.getSuperclass();
|
||||
if (superClass == null || superClass == Object.class) {
|
||||
if (superClass == null || superClass.equals(Object.class)) {
|
||||
return null;
|
||||
}
|
||||
return findAnnotation(superClass, annotationType);
|
||||
@@ -273,25 +272,22 @@ public abstract class AnnotationUtils {
|
||||
* @return the first {@link Class} in the inheritance hierarchy of the specified
|
||||
* {@code clazz} which declares an annotation of at least one of the specified
|
||||
* {@code annotationTypes}, or {@code null} if not found
|
||||
* @since 3.2.2
|
||||
* @see Class#isAnnotationPresent(Class)
|
||||
* @see Class#getDeclaredAnnotations()
|
||||
* @see #findAnnotationDeclaringClass(Class, Class)
|
||||
* @see #isAnnotationDeclaredLocally(Class, Class)
|
||||
* @since 3.2.2
|
||||
*/
|
||||
public static Class<?> findAnnotationDeclaringClassForTypes(List<Class<? extends Annotation>> annotationTypes,
|
||||
Class<?> clazz) {
|
||||
public static Class<?> findAnnotationDeclaringClassForTypes(List<Class<? extends Annotation>> annotationTypes, Class<?> clazz) {
|
||||
Assert.notEmpty(annotationTypes, "The list of annotation types must not be empty");
|
||||
if (clazz == null || clazz.equals(Object.class)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (Class<? extends Annotation> annotationType : annotationTypes) {
|
||||
if (isAnnotationDeclaredLocally(annotationType, clazz)) {
|
||||
return clazz;
|
||||
}
|
||||
}
|
||||
|
||||
return findAnnotationDeclaringClassForTypes(annotationTypes, clazz.getSuperclass());
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -437,7 +437,7 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment {
|
||||
|
||||
public <T> T getProperty(String key, Class<T> targetType, T defaultValue) {
|
||||
return this.propertyResolver.getProperty(key, targetType, defaultValue);
|
||||
};
|
||||
}
|
||||
|
||||
public <T> Class<T> getPropertyAsClass(String key, Class<T> targetType) {
|
||||
return this.propertyResolver.getPropertyAsClass(key, targetType);
|
||||
|
||||
Vendored
+68
-64
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.core.env;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
import org.springframework.core.convert.ConversionException;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@@ -35,6 +33,7 @@ public class PropertySourcesPropertyResolver extends AbstractPropertyResolver {
|
||||
|
||||
private final PropertySources propertySources;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new resolver against the given property sources.
|
||||
* @param propertySources the set of {@link PropertySource} objects to use
|
||||
@@ -43,106 +42,110 @@ public class PropertySourcesPropertyResolver extends AbstractPropertyResolver {
|
||||
this.propertySources = propertySources;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean containsProperty(String key) {
|
||||
for (PropertySource<?> propertySource : this.propertySources) {
|
||||
if (propertySource.containsProperty(key)) {
|
||||
return true;
|
||||
if (this.propertySources != null) {
|
||||
for (PropertySource<?> propertySource : this.propertySources) {
|
||||
if (propertySource.containsProperty(key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProperty(String key) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(format("getProperty(\"%s\") (implicit targetType [String])", key));
|
||||
}
|
||||
return this.getProperty(key, String.class);
|
||||
return getProperty(key, String.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getProperty(String key, Class<T> targetValueType) {
|
||||
boolean debugEnabled = logger.isDebugEnabled();
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(format("getProperty(\"%s\", %s)", key, targetValueType.getSimpleName()));
|
||||
logger.trace(String.format("getProperty(\"%s\", %s)", key, targetValueType.getSimpleName()));
|
||||
}
|
||||
|
||||
for (PropertySource<?> propertySource : this.propertySources) {
|
||||
if (debugEnabled) {
|
||||
logger.debug(format("Searching for key '%s' in [%s]", key, propertySource.getName()));
|
||||
}
|
||||
Object value;
|
||||
if ((value = propertySource.getProperty(key)) != null) {
|
||||
Class<?> valueType = value.getClass();
|
||||
if (String.class.equals(valueType)) {
|
||||
value = this.resolveNestedPlaceholders((String) value);
|
||||
}
|
||||
if (this.propertySources != null) {
|
||||
for (PropertySource<?> propertySource : this.propertySources) {
|
||||
if (debugEnabled) {
|
||||
logger.debug(
|
||||
format("Found key '%s' in [%s] with type [%s] and value '%s'",
|
||||
key, propertySource.getName(), valueType.getSimpleName(), value));
|
||||
logger.debug(String.format("Searching for key '%s' in [%s]", key, propertySource.getName()));
|
||||
}
|
||||
if (!this.conversionService.canConvert(valueType, targetValueType)) {
|
||||
throw new IllegalArgumentException(
|
||||
format("Cannot convert value [%s] from source type [%s] to target type [%s]",
|
||||
value, valueType.getSimpleName(), targetValueType.getSimpleName()));
|
||||
Object value;
|
||||
if ((value = propertySource.getProperty(key)) != null) {
|
||||
Class<?> valueType = value.getClass();
|
||||
if (String.class.equals(valueType)) {
|
||||
value = this.resolveNestedPlaceholders((String) value);
|
||||
}
|
||||
if (debugEnabled) {
|
||||
logger.debug(String.format("Found key '%s' in [%s] with type [%s] and value '%s'",
|
||||
key, propertySource.getName(), valueType.getSimpleName(), value));
|
||||
}
|
||||
if (!this.conversionService.canConvert(valueType, targetValueType)) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Cannot convert value [%s] from source type [%s] to target type [%s]",
|
||||
value, valueType.getSimpleName(), targetValueType.getSimpleName()));
|
||||
}
|
||||
return conversionService.convert(value, targetValueType);
|
||||
}
|
||||
return conversionService.convert(value, targetValueType);
|
||||
}
|
||||
}
|
||||
|
||||
if (debugEnabled) {
|
||||
logger.debug(format("Could not find key '%s' in any property source. Returning [null]", key));
|
||||
logger.debug(String.format("Could not find key '%s' in any property source. Returning [null]", key));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Class<T> getPropertyAsClass(String key, Class<T> targetValueType) {
|
||||
boolean debugEnabled = logger.isDebugEnabled();
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(format("getPropertyAsClass(\"%s\", %s)", key, targetValueType.getSimpleName()));
|
||||
logger.trace(String.format("getPropertyAsClass(\"%s\", %s)", key, targetValueType.getSimpleName()));
|
||||
}
|
||||
|
||||
for (PropertySource<?> propertySource : this.propertySources) {
|
||||
if (debugEnabled) {
|
||||
logger.debug(format("Searching for key '%s' in [%s]", key, propertySource.getName()));
|
||||
}
|
||||
Object value;
|
||||
if ((value = propertySource.getProperty(key)) != null) {
|
||||
if (this.propertySources != null) {
|
||||
for (PropertySource<?> propertySource : this.propertySources) {
|
||||
if (debugEnabled) {
|
||||
logger.debug(
|
||||
format("Found key '%s' in [%s] with value '%s'", key, propertySource.getName(), value));
|
||||
logger.debug(String.format("Searching for key '%s' in [%s]", key, propertySource.getName()));
|
||||
}
|
||||
|
||||
Class<?> clazz;
|
||||
if (value instanceof String) {
|
||||
try {
|
||||
clazz = ClassUtils.forName((String)value, null);
|
||||
} catch (Exception ex) {
|
||||
throw new ClassConversionException((String)value, targetValueType, ex);
|
||||
Object value = propertySource.getProperty(key);
|
||||
if (value != null) {
|
||||
if (debugEnabled) {
|
||||
logger.debug(String.format("Found key '%s' in [%s] with value '%s'", key, propertySource.getName(), value));
|
||||
}
|
||||
Class<?> clazz;
|
||||
if (value instanceof String) {
|
||||
try {
|
||||
clazz = ClassUtils.forName((String)value, null);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new ClassConversionException((String)value, targetValueType, ex);
|
||||
}
|
||||
}
|
||||
else if (value instanceof Class) {
|
||||
clazz = (Class<?>)value;
|
||||
}
|
||||
else {
|
||||
clazz = value.getClass();
|
||||
}
|
||||
if (!targetValueType.isAssignableFrom(clazz)) {
|
||||
throw new ClassConversionException(clazz, targetValueType);
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<T> targetClass = (Class<T>) clazz;
|
||||
return targetClass;
|
||||
}
|
||||
else if (value instanceof Class) {
|
||||
clazz = (Class<?>)value;
|
||||
} else {
|
||||
clazz = value.getClass();
|
||||
}
|
||||
|
||||
if (!targetValueType.isAssignableFrom(clazz)) {
|
||||
throw new ClassConversionException(clazz, targetValueType);
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<T> targetClass = (Class<T>)clazz;
|
||||
return targetClass;
|
||||
}
|
||||
}
|
||||
|
||||
if (debugEnabled) {
|
||||
logger.debug(format("Could not find key '%s' in any property source. Returning [null]", key));
|
||||
logger.debug(String.format("Could not find key '%s' in any property source. Returning [null]", key));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
static class ClassConversionException extends ConversionException {
|
||||
private static class ClassConversionException extends ConversionException {
|
||||
|
||||
public ClassConversionException(Class<?> actual, Class<?> expected) {
|
||||
super(String.format("Actual type %s is not assignable to expected type %s", actual.getName(), expected.getName()));
|
||||
}
|
||||
@@ -151,4 +154,5 @@ public class PropertySourcesPropertyResolver extends AbstractPropertyResolver {
|
||||
super(String.format("Could not find/load class %s during attempt to convert to %s", actual, expected.getName()), ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,12 +19,11 @@ package org.springframework.core.io;
|
||||
import java.beans.PropertyEditorSupport;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.core.env.PropertyResolver;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
||||
/**
|
||||
* {@link java.beans.PropertyEditor Editor} for {@link Resource}
|
||||
* descriptors, to automatically convert {@code String} locations
|
||||
@@ -51,7 +50,7 @@ public class ResourceEditor extends PropertyEditorSupport {
|
||||
|
||||
private final ResourceLoader resourceLoader;
|
||||
|
||||
private final PropertyResolver propertyResolver;
|
||||
private PropertyResolver propertyResolver;
|
||||
|
||||
private final boolean ignoreUnresolvablePlaceholders;
|
||||
|
||||
@@ -61,7 +60,7 @@ public class ResourceEditor extends PropertyEditorSupport {
|
||||
* using a {@link DefaultResourceLoader} and {@link StandardEnvironment}.
|
||||
*/
|
||||
public ResourceEditor() {
|
||||
this(new DefaultResourceLoader(), new StandardEnvironment());
|
||||
this(new DefaultResourceLoader(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,7 +72,21 @@ public class ResourceEditor extends PropertyEditorSupport {
|
||||
*/
|
||||
@Deprecated
|
||||
public ResourceEditor(ResourceLoader resourceLoader) {
|
||||
this(resourceLoader, new StandardEnvironment(), true);
|
||||
this(resourceLoader, null, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance of the {@link ResourceEditor} class
|
||||
* using the given {@link ResourceLoader}.
|
||||
* @param resourceLoader the {@code ResourceLoader} to use
|
||||
* @param ignoreUnresolvablePlaceholders whether to ignore unresolvable placeholders
|
||||
* if no corresponding property could be found
|
||||
* @deprecated as of Spring 3.1 in favor of
|
||||
* {@link #ResourceEditor(ResourceLoader, PropertyResolver, boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
public ResourceEditor(ResourceLoader resourceLoader, boolean ignoreUnresolvablePlaceholders) {
|
||||
this(resourceLoader, null, ignoreUnresolvablePlaceholders);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,20 +99,6 @@ public class ResourceEditor extends PropertyEditorSupport {
|
||||
this(resourceLoader, propertyResolver, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance of the {@link ResourceEditor} class
|
||||
* using the given {@link ResourceLoader}.
|
||||
* @param resourceLoader the {@code ResourceLoader} to use
|
||||
* @param ignoreUnresolvablePlaceholders whether to ignore unresolvable placeholders
|
||||
* if no corresponding property could be found
|
||||
* @deprecated as of Spring 3.1 in favor of
|
||||
* {@link #ResourceEditor(ResourceLoader, PropertyResolver, boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
public ResourceEditor(ResourceLoader resourceLoader, boolean ignoreUnresolvablePlaceholders) {
|
||||
this(resourceLoader, new StandardEnvironment(), ignoreUnresolvablePlaceholders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance of the {@link ResourceEditor} class
|
||||
* using the given {@link ResourceLoader}.
|
||||
@@ -110,7 +109,6 @@ public class ResourceEditor extends PropertyEditorSupport {
|
||||
*/
|
||||
public ResourceEditor(ResourceLoader resourceLoader, PropertyResolver propertyResolver, boolean ignoreUnresolvablePlaceholders) {
|
||||
Assert.notNull(resourceLoader, "ResourceLoader must not be null");
|
||||
Assert.notNull(propertyResolver, "PropertyResolver must not be null");
|
||||
this.resourceLoader = resourceLoader;
|
||||
this.propertyResolver = propertyResolver;
|
||||
this.ignoreUnresolvablePlaceholders = ignoreUnresolvablePlaceholders;
|
||||
@@ -137,9 +135,11 @@ public class ResourceEditor extends PropertyEditorSupport {
|
||||
* @see PropertyResolver#resolveRequiredPlaceholders
|
||||
*/
|
||||
protected String resolvePath(String path) {
|
||||
return this.ignoreUnresolvablePlaceholders ?
|
||||
this.propertyResolver.resolvePlaceholders(path) :
|
||||
this.propertyResolver.resolveRequiredPlaceholders(path);
|
||||
if (this.propertyResolver == null) {
|
||||
this.propertyResolver = new StandardEnvironment();
|
||||
}
|
||||
return (this.ignoreUnresolvablePlaceholders ? this.propertyResolver.resolvePlaceholders(path) :
|
||||
this.propertyResolver.resolveRequiredPlaceholders(path));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,6 +22,7 @@ import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
|
||||
@@ -40,6 +41,11 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class UrlResource extends AbstractFileResolvingResource {
|
||||
|
||||
/**
|
||||
* Original URI, if available; used for URI and File access.
|
||||
*/
|
||||
private final URI uri;
|
||||
|
||||
/**
|
||||
* Original URL, used for actual access.
|
||||
*/
|
||||
@@ -50,14 +56,21 @@ public class UrlResource extends AbstractFileResolvingResource {
|
||||
*/
|
||||
private final URL cleanedUrl;
|
||||
|
||||
|
||||
/**
|
||||
* Original URI, if available; used for URI and File access.
|
||||
* Create a new UrlResource based on the given URI object.
|
||||
* @param uri a URI
|
||||
* @throws MalformedURLException if the given URL path is not valid
|
||||
*/
|
||||
private final URI uri;
|
||||
|
||||
public UrlResource(URI uri) throws MalformedURLException {
|
||||
Assert.notNull(uri, "URI must not be null");
|
||||
this.uri = uri;
|
||||
this.url = uri.toURL();
|
||||
this.cleanedUrl = getCleanedUrl(this.url, uri.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new UrlResource.
|
||||
* Create a new UrlResource based on the given URL object.
|
||||
* @param url a URL
|
||||
*/
|
||||
public UrlResource(URL url) {
|
||||
@@ -68,27 +81,56 @@ public class UrlResource extends AbstractFileResolvingResource {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new UrlResource.
|
||||
* @param uri a URI
|
||||
* @throws MalformedURLException if the given URL path is not valid
|
||||
*/
|
||||
public UrlResource(URI uri) throws MalformedURLException {
|
||||
Assert.notNull(uri, "URI must not be null");
|
||||
this.url = uri.toURL();
|
||||
this.cleanedUrl = getCleanedUrl(this.url, uri.toString());
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new UrlResource.
|
||||
* Create a new UrlResource based on a URL path.
|
||||
* <p>Note: The given path needs to be pre-encoded if necessary.
|
||||
* @param path a URL path
|
||||
* @throws MalformedURLException if the given URL path is not valid
|
||||
* @see java.net.URL#URL(String)
|
||||
*/
|
||||
public UrlResource(String path) throws MalformedURLException {
|
||||
Assert.notNull(path, "Path must not be null");
|
||||
this.uri = null;
|
||||
this.url = new URL(path);
|
||||
this.cleanedUrl = getCleanedUrl(this.url, path);
|
||||
this.uri = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new UrlResource based on a URI specification.
|
||||
* <p>The given parts will automatically get encoded if necessary.
|
||||
* @param protocol the URL protocol to use (e.g. "jar" or "file" - without colon);
|
||||
* also known as "scheme"
|
||||
* @param location the location (e.g. the file path within that protocol);
|
||||
* also known as "scheme-specific part"
|
||||
* @throws MalformedURLException if the given URL specification is not valid
|
||||
* @see java.net.URI#URI(String, String, String)
|
||||
*/
|
||||
public UrlResource(String protocol, String location) throws MalformedURLException {
|
||||
this(protocol, location, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new UrlResource based on a URI specification.
|
||||
* <p>The given parts will automatically get encoded if necessary.
|
||||
* @param protocol the URL protocol to use (e.g. "jar" or "file" - without colon);
|
||||
* also known as "scheme"
|
||||
* @param location the location (e.g. the file path within that protocol);
|
||||
* also known as "scheme-specific part"
|
||||
* @param fragment the fragment within that location (e.g. anchor on an HTML page,
|
||||
* as following after a "#" separator)
|
||||
* @throws MalformedURLException if the given URL specification is not valid
|
||||
* @see java.net.URI#URI(String, String, String)
|
||||
*/
|
||||
public UrlResource(String protocol, String location, String fragment) throws MalformedURLException {
|
||||
try {
|
||||
this.uri = new URI(protocol, location, fragment);
|
||||
this.url = this.uri.toURL();
|
||||
this.cleanedUrl = getCleanedUrl(this.url, this.uri.toString());
|
||||
}
|
||||
catch (URISyntaxException ex) {
|
||||
MalformedURLException exToThrow = new MalformedURLException(ex.getMessage());
|
||||
exToThrow.initCause(ex);
|
||||
throw exToThrow;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+28
-22
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,10 +25,12 @@ import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.PropertyResolver;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Editor for {@link org.springframework.core.io.Resource} arrays, to
|
||||
@@ -55,10 +57,10 @@ public class ResourceArrayPropertyEditor extends PropertyEditorSupport {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(ResourceArrayPropertyEditor.class);
|
||||
|
||||
private final PropertyResolver propertyResolver;
|
||||
|
||||
private final ResourcePatternResolver resourcePatternResolver;
|
||||
|
||||
private PropertyResolver propertyResolver;
|
||||
|
||||
private final boolean ignoreUnresolvablePlaceholders;
|
||||
|
||||
|
||||
@@ -69,7 +71,7 @@ public class ResourceArrayPropertyEditor extends PropertyEditorSupport {
|
||||
* @see Environment
|
||||
*/
|
||||
public ResourceArrayPropertyEditor() {
|
||||
this(new PathMatchingResourcePatternResolver(), new StandardEnvironment(), true);
|
||||
this(new PathMatchingResourcePatternResolver(), null, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,7 +82,20 @@ public class ResourceArrayPropertyEditor extends PropertyEditorSupport {
|
||||
*/
|
||||
@Deprecated
|
||||
public ResourceArrayPropertyEditor(ResourcePatternResolver resourcePatternResolver) {
|
||||
this(resourcePatternResolver, new StandardEnvironment(), true);
|
||||
this(resourcePatternResolver, null, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ResourceArrayPropertyEditor with the given {@link ResourcePatternResolver}
|
||||
* and a {@link StandardEnvironment}.
|
||||
* @param resourcePatternResolver the ResourcePatternResolver to use
|
||||
* @param ignoreUnresolvablePlaceholders whether to ignore unresolvable placeholders
|
||||
* if no corresponding system property could be found
|
||||
* @deprecated as of 3.1 in favor of {@link #ResourceArrayPropertyEditor(ResourcePatternResolver, PropertyResolver, boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
public ResourceArrayPropertyEditor(ResourcePatternResolver resourcePatternResolver, boolean ignoreUnresolvablePlaceholders) {
|
||||
this(resourcePatternResolver, null, ignoreUnresolvablePlaceholders);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,19 +108,6 @@ public class ResourceArrayPropertyEditor extends PropertyEditorSupport {
|
||||
this(resourcePatternResolver, propertyResolver, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ResourceArrayPropertyEditor with the given {@link ResourcePatternResolver}
|
||||
* and a {@link StandardEnvironment}.
|
||||
* @param resourcePatternResolver the ResourcePatternResolver to use
|
||||
* @param ignoreUnresolvablePlaceholders whether to ignore unresolvable placeholders
|
||||
* if no corresponding system property could be found
|
||||
* @deprecated as of 3.1 in favor of {@link #ResourceArrayPropertyEditor(ResourcePatternResolver, PropertyResolver, boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
public ResourceArrayPropertyEditor(ResourcePatternResolver resourcePatternResolver, boolean ignoreUnresolvablePlaceholders) {
|
||||
this(resourcePatternResolver, new StandardEnvironment(), ignoreUnresolvablePlaceholders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ResourceArrayPropertyEditor with the given {@link ResourcePatternResolver}
|
||||
* and {@link PropertyResolver} (typically an {@link Environment}).
|
||||
@@ -116,6 +118,8 @@ public class ResourceArrayPropertyEditor extends PropertyEditorSupport {
|
||||
*/
|
||||
public ResourceArrayPropertyEditor(ResourcePatternResolver resourcePatternResolver,
|
||||
PropertyResolver propertyResolver, boolean ignoreUnresolvablePlaceholders) {
|
||||
|
||||
Assert.notNull(resourcePatternResolver, "ResourcePatternResolver must not be null");
|
||||
this.resourcePatternResolver = resourcePatternResolver;
|
||||
this.propertyResolver = propertyResolver;
|
||||
this.ignoreUnresolvablePlaceholders = ignoreUnresolvablePlaceholders;
|
||||
@@ -197,9 +201,11 @@ public class ResourceArrayPropertyEditor extends PropertyEditorSupport {
|
||||
* @see PropertyResolver#resolveRequiredPlaceholders(String)
|
||||
*/
|
||||
protected String resolvePath(String path) {
|
||||
return this.ignoreUnresolvablePlaceholders ?
|
||||
this.propertyResolver.resolvePlaceholders(path) :
|
||||
this.propertyResolver.resolveRequiredPlaceholders(path);
|
||||
if (this.propertyResolver == null) {
|
||||
this.propertyResolver = new StandardEnvironment();
|
||||
}
|
||||
return (this.ignoreUnresolvablePlaceholders ? this.propertyResolver.resolvePlaceholders(path) :
|
||||
this.propertyResolver.resolveRequiredPlaceholders(path));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -145,6 +145,8 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements
|
||||
return AnnotationUtils.getAnnotationAttributes(
|
||||
ann, classValuesAsString, this.nestedAnnotationsAsMap);
|
||||
}
|
||||
}
|
||||
for (Annotation ann : anns) {
|
||||
for (Annotation metaAnn : ann.annotationType().getAnnotations()) {
|
||||
if (metaAnn.annotationType().getName().equals(annotationType)) {
|
||||
return AnnotationUtils.getAnnotationAttributes(
|
||||
|
||||
+9
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,6 +28,7 @@ import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.asm.AnnotationVisitor;
|
||||
import org.springframework.asm.SpringAsmInfo;
|
||||
import org.springframework.asm.Type;
|
||||
@@ -50,14 +51,12 @@ abstract class AbstractRecursiveAnnotationVisitor extends AnnotationVisitor {
|
||||
|
||||
protected final ClassLoader classLoader;
|
||||
|
||||
|
||||
public AbstractRecursiveAnnotationVisitor(ClassLoader classLoader, AnnotationAttributes attributes) {
|
||||
super(SpringAsmInfo.ASM_VERSION);
|
||||
this.classLoader = classLoader;
|
||||
this.attributes = attributes;
|
||||
}
|
||||
|
||||
|
||||
public void visit(String attributeName, Object attributeValue) {
|
||||
this.attributes.put(attributeName, attributeValue);
|
||||
}
|
||||
@@ -74,6 +73,11 @@ abstract class AbstractRecursiveAnnotationVisitor extends AnnotationVisitor {
|
||||
}
|
||||
|
||||
public void visitEnum(String attributeName, String asmTypeDescriptor, String attributeValue) {
|
||||
Object newValue = getEnumValue(asmTypeDescriptor, attributeValue);
|
||||
visit(attributeName, newValue);
|
||||
}
|
||||
|
||||
protected Object getEnumValue(String asmTypeDescriptor, String attributeValue) {
|
||||
Object valueToUse = attributeValue;
|
||||
try {
|
||||
Class<?> enumType = this.classLoader.loadClass(Type.getType(asmTypeDescriptor).getClassName());
|
||||
@@ -88,7 +92,7 @@ abstract class AbstractRecursiveAnnotationVisitor extends AnnotationVisitor {
|
||||
catch (IllegalAccessException ex) {
|
||||
this.logger.warn("Could not access enum value while reading annotation metadata", ex);
|
||||
}
|
||||
this.attributes.put(attributeName, valueToUse);
|
||||
return valueToUse;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +108,6 @@ final class RecursiveAnnotationArrayVisitor extends AbstractRecursiveAnnotationV
|
||||
|
||||
private final List<AnnotationAttributes> allNestedAttributes = new ArrayList<AnnotationAttributes>();
|
||||
|
||||
|
||||
public RecursiveAnnotationArrayVisitor(
|
||||
String attributeName, AnnotationAttributes attributes, ClassLoader classLoader) {
|
||||
super(classLoader, attributes);
|
||||
@@ -152,14 +155,12 @@ class RecursiveAnnotationAttributesVisitor extends AbstractRecursiveAnnotationVi
|
||||
|
||||
private final String annotationType;
|
||||
|
||||
|
||||
public RecursiveAnnotationAttributesVisitor(
|
||||
String annotationType, AnnotationAttributes attributes, ClassLoader classLoader) {
|
||||
super(classLoader, attributes);
|
||||
this.annotationType = annotationType;
|
||||
}
|
||||
|
||||
|
||||
public final void visitEnd() {
|
||||
try {
|
||||
Class<?> annotationClass = this.classLoader.loadClass(this.annotationType);
|
||||
@@ -223,7 +224,6 @@ final class AnnotationAttributesReadingVisitor extends RecursiveAnnotationAttrib
|
||||
|
||||
private final Map<String, Set<String>> metaAnnotationMap;
|
||||
|
||||
|
||||
public AnnotationAttributesReadingVisitor(
|
||||
String annotationType, Map<String, AnnotationAttributes> attributesMap,
|
||||
Map<String, Set<String>> metaAnnotationMap, ClassLoader classLoader) {
|
||||
@@ -258,4 +258,5 @@ final class AnnotationAttributesReadingVisitor extends RecursiveAnnotationAttrib
|
||||
this.metaAnnotationMap.put(annotationClass.getName(), metaAnnotationTypeNames);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -105,19 +105,11 @@ final class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor
|
||||
}
|
||||
|
||||
public AnnotationAttributes getAnnotationAttributes(String annotationType, boolean classValuesAsString) {
|
||||
return getAnnotationAttributes(annotationType, classValuesAsString, false);
|
||||
}
|
||||
|
||||
public AnnotationAttributes getAnnotationAttributes(
|
||||
String annotationType, boolean classValuesAsString, boolean nestedAttributesAsMap) {
|
||||
|
||||
AnnotationAttributes raw = this.attributeMap.get(annotationType);
|
||||
return convertClassValues(raw, classValuesAsString, nestedAttributesAsMap);
|
||||
return convertClassValues(raw, classValuesAsString);
|
||||
}
|
||||
|
||||
private AnnotationAttributes convertClassValues(
|
||||
AnnotationAttributes original, boolean classValuesAsString, boolean nestedAttributesAsMap) {
|
||||
|
||||
private AnnotationAttributes convertClassValues(AnnotationAttributes original, boolean classValuesAsString) {
|
||||
if (original == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -126,12 +118,12 @@ final class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor
|
||||
try {
|
||||
Object value = entry.getValue();
|
||||
if (value instanceof AnnotationAttributes) {
|
||||
value = convertClassValues((AnnotationAttributes)value, classValuesAsString, nestedAttributesAsMap);
|
||||
value = convertClassValues((AnnotationAttributes) value, classValuesAsString);
|
||||
}
|
||||
else if (value instanceof AnnotationAttributes[]) {
|
||||
AnnotationAttributes[] values = (AnnotationAttributes[])value;
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
values[i] = convertClassValues(values[i], classValuesAsString, nestedAttributesAsMap);
|
||||
values[i] = convertClassValues(values[i], classValuesAsString);
|
||||
}
|
||||
}
|
||||
else if (value instanceof Type) {
|
||||
@@ -182,4 +174,5 @@ final class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor
|
||||
annotatedMethods.addAll(list);
|
||||
return annotatedMethods;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+7
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -45,7 +45,7 @@ final class MethodMetadataReadingVisitor extends MethodVisitor implements Method
|
||||
|
||||
private final int access;
|
||||
|
||||
private String declaringClassName;
|
||||
private final String declaringClassName;
|
||||
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
@@ -53,8 +53,10 @@ final class MethodMetadataReadingVisitor extends MethodVisitor implements Method
|
||||
|
||||
private final Map<String, AnnotationAttributes> attributeMap = new LinkedHashMap<String, AnnotationAttributes>(2);
|
||||
|
||||
|
||||
public MethodMetadataReadingVisitor(String name, int access, String declaringClassName, ClassLoader classLoader,
|
||||
MultiValueMap<String, MethodMetadata> methodMetadataMap) {
|
||||
|
||||
super(SpringAsmInfo.ASM_VERSION);
|
||||
this.name = name;
|
||||
this.access = access;
|
||||
@@ -63,10 +65,11 @@ final class MethodMetadataReadingVisitor extends MethodVisitor implements Method
|
||||
this.methodMetadataMap = methodMetadataMap;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(final String desc, boolean visible) {
|
||||
String className = Type.getType(desc).getClassName();
|
||||
methodMetadataMap.add(className, this);
|
||||
this.methodMetadataMap.add(className, this);
|
||||
return new AnnotationAttributesReadingVisitor(className, this.attributeMap, null, this.classLoader);
|
||||
}
|
||||
|
||||
@@ -97,4 +100,5 @@ final class MethodMetadataReadingVisitor extends MethodVisitor implements Method
|
||||
public String getDeclaringClassName() {
|
||||
return this.declaringClassName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ final class SimpleMetadataReader implements MetadataReader {
|
||||
classReader.accept(visitor, ClassReader.SKIP_DEBUG);
|
||||
|
||||
this.annotationMetadata = visitor;
|
||||
// (since AnnotationMetadataReader extends ClassMetadataReadingVisitor)
|
||||
// (since AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor)
|
||||
this.classMetadata = visitor;
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ public abstract class Assert {
|
||||
*/
|
||||
public static void doesNotContain(String textToSearch, String substring, String message) {
|
||||
if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) &&
|
||||
textToSearch.indexOf(substring) != -1) {
|
||||
textToSearch.contains(substring)) {
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
}
|
||||
@@ -236,8 +236,8 @@ public abstract class Assert {
|
||||
*/
|
||||
public static void noNullElements(Object[] array, String message) {
|
||||
if (array != null) {
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
if (array[i] == null) {
|
||||
for (Object element : array) {
|
||||
if (element == null) {
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
}
|
||||
@@ -315,7 +315,7 @@ public abstract class Assert {
|
||||
* @throws IllegalArgumentException if the object is not an instance of clazz
|
||||
* @see Class#isInstance
|
||||
*/
|
||||
public static void isInstanceOf(Class clazz, Object obj) {
|
||||
public static void isInstanceOf(Class<?> clazz, Object obj) {
|
||||
isInstanceOf(clazz, obj, "");
|
||||
}
|
||||
|
||||
@@ -331,7 +331,7 @@ public abstract class Assert {
|
||||
* @throws IllegalArgumentException if the object is not an instance of clazz
|
||||
* @see Class#isInstance
|
||||
*/
|
||||
public static void isInstanceOf(Class type, Object obj, String message) {
|
||||
public static void isInstanceOf(Class<?> type, Object obj, String message) {
|
||||
notNull(type, "Type to check against must not be null");
|
||||
if (!type.isInstance(obj)) {
|
||||
throw new IllegalArgumentException(
|
||||
@@ -348,7 +348,7 @@ public abstract class Assert {
|
||||
* @param subType the sub type to check
|
||||
* @throws IllegalArgumentException if the classes are not assignable
|
||||
*/
|
||||
public static void isAssignable(Class superType, Class subType) {
|
||||
public static void isAssignable(Class<?> superType, Class<?> subType) {
|
||||
isAssignable(superType, subType, "");
|
||||
}
|
||||
|
||||
@@ -363,7 +363,7 @@ public abstract class Assert {
|
||||
* ok when prepended to it.
|
||||
* @throws IllegalArgumentException if the classes are not assignable
|
||||
*/
|
||||
public static void isAssignable(Class superType, Class subType, String message) {
|
||||
public static void isAssignable(Class<?> superType, Class<?> subType, String message) {
|
||||
notNull(superType, "Type to check against must not be null");
|
||||
if (subType == null || !superType.isAssignableFrom(subType)) {
|
||||
throw new IllegalArgumentException(message + subType + " is not assignable to " + superType);
|
||||
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,16 +20,17 @@ import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Test fixture for {@link ParameterizedTypeReference}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class ParameterizedTypeReferenceTest {
|
||||
public class ParameterizedTypeReferenceTests {
|
||||
|
||||
@Test
|
||||
public void map() throws NoSuchMethodException {
|
||||
@@ -58,4 +59,5 @@ public class ParameterizedTypeReferenceTest {
|
||||
public static List<String> listMethod() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
+23
@@ -45,6 +45,16 @@ public class AnnotationAwareOrderComparatorTests {
|
||||
assertTrue(list.get(1) instanceof B);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sortInstancesWithSubclass() {
|
||||
List<Object> list = new ArrayList<>();
|
||||
list.add(new B());
|
||||
list.add(new C());
|
||||
AnnotationAwareOrderComparator.sort(list);
|
||||
assertTrue(list.get(0) instanceof C);
|
||||
assertTrue(list.get(1) instanceof B);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sortClasses() {
|
||||
List<Object> list = new ArrayList<>();
|
||||
@@ -55,6 +65,16 @@ public class AnnotationAwareOrderComparatorTests {
|
||||
assertEquals(B.class, list.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sortClassesWithSubclass() {
|
||||
List<Object> list = new ArrayList<>();
|
||||
list.add(B.class);
|
||||
list.add(C.class);
|
||||
AnnotationAwareOrderComparator.sort(list);
|
||||
assertEquals(C.class, list.get(0));
|
||||
assertEquals(B.class, list.get(1));
|
||||
}
|
||||
|
||||
|
||||
@Order(1)
|
||||
private static class A {
|
||||
@@ -64,4 +84,7 @@ public class AnnotationAwareOrderComparatorTests {
|
||||
private static class B {
|
||||
}
|
||||
|
||||
private static class C extends A {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.tests;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* General build related tests. Part of spring-core to ensure that they run early in the
|
||||
* build process.
|
||||
*/
|
||||
public class BuildTests {
|
||||
|
||||
@Test
|
||||
public void javaVersion() throws Exception {
|
||||
Assume.group(TestGroup.CI);
|
||||
assertThat("Java Version", JavaVersion.runningVersion(), equalTo(JavaVersion.JAVA_17));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -54,7 +54,12 @@ public enum TestGroup {
|
||||
* Tests requiring the presence of jmxremote_optional.jar in jre/lib/ext in order to
|
||||
* avoid "Unsupported protocol: jmxmp" errors.
|
||||
*/
|
||||
JMXMP;
|
||||
JMXMP,
|
||||
|
||||
/**
|
||||
* Tests that should only be run on the continuous integration server.
|
||||
*/
|
||||
CI;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -64,7 +64,7 @@ public class TestGroupTests {
|
||||
thrown.expect(IllegalArgumentException.class);
|
||||
thrown.expectMessage("Unable to find test group 'missing' when parsing " +
|
||||
"testGroups value: 'performance, missing'. Available groups include: " +
|
||||
"[LONG_RUNNING,PERFORMANCE,JMXMP]");
|
||||
"[LONG_RUNNING,PERFORMANCE,JMXMP,CI]");
|
||||
TestGroup.parse("performance, missing");
|
||||
}
|
||||
|
||||
|
||||
+84
-75
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -47,70 +47,14 @@ public class MethodReference extends SpelNodeImpl {
|
||||
|
||||
|
||||
public MethodReference(boolean nullSafe, String methodName, int pos, SpelNodeImpl... arguments) {
|
||||
super(pos,arguments);
|
||||
super(pos, arguments);
|
||||
this.name = methodName;
|
||||
this.nullSafe = nullSafe;
|
||||
}
|
||||
|
||||
class MethodValueRef implements ValueRef {
|
||||
|
||||
private ExpressionState state;
|
||||
private EvaluationContext evaluationContext;
|
||||
private Object target;
|
||||
private Object[] arguments;
|
||||
|
||||
MethodValueRef(ExpressionState state, EvaluationContext evaluationContext, Object object, Object[] arguments) {
|
||||
this.state = state;
|
||||
this.evaluationContext = evaluationContext;
|
||||
this.target = object;
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
public TypedValue getValue() {
|
||||
MethodExecutor executorToUse = cachedExecutor;
|
||||
if (executorToUse != null) {
|
||||
try {
|
||||
return executorToUse.execute(evaluationContext, target, arguments);
|
||||
}
|
||||
catch (AccessException ae) {
|
||||
// Two reasons this can occur:
|
||||
// 1. the method invoked actually threw a real exception
|
||||
// 2. the method invoked was not passed the arguments it expected and has become 'stale'
|
||||
|
||||
// In the first case we should not retry, in the second case we should see if there is a
|
||||
// better suited method.
|
||||
|
||||
// To determine which situation it is, the AccessException will contain a cause.
|
||||
// If the cause is an InvocationTargetException, a user exception was thrown inside the method.
|
||||
// Otherwise the method could not be invoked.
|
||||
throwSimpleExceptionIfPossible(state, ae);
|
||||
|
||||
// at this point we know it wasn't a user problem so worth a retry if a better candidate can be found
|
||||
cachedExecutor = null;
|
||||
}
|
||||
}
|
||||
|
||||
// either there was no accessor or it no longer existed
|
||||
executorToUse = findAccessorForMethod(name, getTypes(arguments), target, evaluationContext);
|
||||
cachedExecutor = executorToUse;
|
||||
try {
|
||||
return executorToUse.execute(evaluationContext, target, arguments);
|
||||
} catch (AccessException ae) {
|
||||
// Same unwrapping exception handling as above in above catch block
|
||||
throwSimpleExceptionIfPossible(state, ae);
|
||||
throw new SpelEvaluationException( getStartPosition(), ae, SpelMessage.EXCEPTION_DURING_METHOD_INVOCATION,
|
||||
name, state.getActiveContextObject().getValue().getClass().getName(), ae.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void setValue(Object newValue) {
|
||||
throw new IllegalAccessError();
|
||||
}
|
||||
|
||||
public boolean isWritable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public final String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -122,22 +66,21 @@ public class MethodReference extends SpelNodeImpl {
|
||||
// expressions
|
||||
try {
|
||||
state.pushActiveContextObject(state.getRootContextObject());
|
||||
arguments[i] = children[i].getValueInternal(state).getValue();
|
||||
arguments[i] = this.children[i].getValueInternal(state).getValue();
|
||||
}
|
||||
finally {
|
||||
state.popActiveContextObject();
|
||||
}
|
||||
}
|
||||
if (currentContext.getValue() == null) {
|
||||
if (nullSafe) {
|
||||
if (this.nullSafe) {
|
||||
return ValueRef.NullValueRef.instance;
|
||||
}
|
||||
else {
|
||||
throw new SpelEvaluationException(getStartPosition(), SpelMessage.METHOD_CALL_ON_NULL_OBJECT_NOT_ALLOWED,
|
||||
FormatHelper.formatMethodForMessage(name, getTypes(arguments)));
|
||||
FormatHelper.formatMethodForMessage(this.name, getTypes(arguments)));
|
||||
}
|
||||
}
|
||||
|
||||
return new MethodValueRef(state,state.getEvaluationContext(),state.getActiveContextObject().getValue(),arguments);
|
||||
}
|
||||
|
||||
@@ -150,7 +93,7 @@ public class MethodReference extends SpelNodeImpl {
|
||||
// expressions
|
||||
try {
|
||||
state.pushActiveContextObject(state.getRootContextObject());
|
||||
arguments[i] = children[i].getValueInternal(state).getValue();
|
||||
arguments[i] = this.children[i].getValueInternal(state).getValue();
|
||||
}
|
||||
finally {
|
||||
state.popActiveContextObject();
|
||||
@@ -162,7 +105,7 @@ public class MethodReference extends SpelNodeImpl {
|
||||
}
|
||||
else {
|
||||
throw new SpelEvaluationException(getStartPosition(), SpelMessage.METHOD_CALL_ON_NULL_OBJECT_NOT_ALLOWED,
|
||||
FormatHelper.formatMethodForMessage(name, getTypes(arguments)));
|
||||
FormatHelper.formatMethodForMessage(this.name, getTypes(arguments)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,7 +139,8 @@ public class MethodReference extends SpelNodeImpl {
|
||||
try {
|
||||
return executorToUse.execute(
|
||||
state.getEvaluationContext(), state.getActiveContextObject().getValue(), arguments);
|
||||
} catch (AccessException ae) {
|
||||
}
|
||||
catch (AccessException ae) {
|
||||
// Same unwrapping exception handling as above in above catch block
|
||||
throwSimpleExceptionIfPossible(state, ae);
|
||||
throw new SpelEvaluationException( getStartPosition(), ae, SpelMessage.EXCEPTION_DURING_METHOD_INVOCATION,
|
||||
@@ -204,7 +148,6 @@ public class MethodReference extends SpelNodeImpl {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decode the AccessException, throwing a lightweight evaluation exception or, if the cause was a RuntimeException,
|
||||
* throw the RuntimeException directly.
|
||||
@@ -235,7 +178,7 @@ public class MethodReference extends SpelNodeImpl {
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(name).append("(");
|
||||
sb.append(this.name).append("(");
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
if (i > 0)
|
||||
sb.append(",");
|
||||
@@ -245,9 +188,9 @@ public class MethodReference extends SpelNodeImpl {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private MethodExecutor findAccessorForMethod(String name,
|
||||
List<TypeDescriptor> argumentTypes, ExpressionState state)
|
||||
private MethodExecutor findAccessorForMethod(String name, List<TypeDescriptor> argumentTypes, ExpressionState state)
|
||||
throws SpelEvaluationException {
|
||||
|
||||
return findAccessorForMethod(name,argumentTypes,state.getActiveContextObject().getValue(),state.getEvaluationContext());
|
||||
}
|
||||
|
||||
@@ -259,19 +202,85 @@ public class MethodReference extends SpelNodeImpl {
|
||||
if (mResolvers != null) {
|
||||
for (MethodResolver methodResolver : mResolvers) {
|
||||
try {
|
||||
MethodExecutor cEx = methodResolver.resolve(
|
||||
eContext, contextObject, name, argumentTypes);
|
||||
MethodExecutor cEx = methodResolver.resolve(eContext, contextObject, name, argumentTypes);
|
||||
if (cEx != null) {
|
||||
return cEx;
|
||||
}
|
||||
}
|
||||
catch (AccessException ex) {
|
||||
throw new SpelEvaluationException(getStartPosition(),ex, SpelMessage.PROBLEM_LOCATING_METHOD, name, contextObject.getClass());
|
||||
throw new SpelEvaluationException(getStartPosition(),ex, SpelMessage.PROBLEM_LOCATING_METHOD,
|
||||
name, contextObject.getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new SpelEvaluationException(getStartPosition(),SpelMessage.METHOD_NOT_FOUND, FormatHelper.formatMethodForMessage(name, argumentTypes),
|
||||
throw new SpelEvaluationException(getStartPosition(),SpelMessage.METHOD_NOT_FOUND,
|
||||
FormatHelper.formatMethodForMessage(name, argumentTypes),
|
||||
FormatHelper.formatClassNameForMessage(contextObject instanceof Class ? ((Class<?>) contextObject) : contextObject.getClass()));
|
||||
}
|
||||
|
||||
|
||||
private class MethodValueRef implements ValueRef {
|
||||
|
||||
private final ExpressionState state;
|
||||
|
||||
private final EvaluationContext evaluationContext;
|
||||
|
||||
private final Object target;
|
||||
|
||||
private final Object[] arguments;
|
||||
|
||||
MethodValueRef(ExpressionState state, EvaluationContext evaluationContext, Object object, Object[] arguments) {
|
||||
this.state = state;
|
||||
this.evaluationContext = evaluationContext;
|
||||
this.target = object;
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
public TypedValue getValue() {
|
||||
MethodExecutor executorToUse = cachedExecutor;
|
||||
if (executorToUse != null) {
|
||||
try {
|
||||
return executorToUse.execute(this.evaluationContext, this.target, this.arguments);
|
||||
}
|
||||
catch (AccessException ae) {
|
||||
// Two reasons this can occur:
|
||||
// 1. the method invoked actually threw a real exception
|
||||
// 2. the method invoked was not passed the arguments it expected and has become 'stale'
|
||||
|
||||
// In the first case we should not retry, in the second case we should see if there is a
|
||||
// better suited method.
|
||||
|
||||
// To determine which situation it is, the AccessException will contain a cause.
|
||||
// If the cause is an InvocationTargetException, a user exception was thrown inside the method.
|
||||
// Otherwise the method could not be invoked.
|
||||
throwSimpleExceptionIfPossible(this.state, ae);
|
||||
|
||||
// at this point we know it wasn't a user problem so worth a retry if a better candidate can be found
|
||||
cachedExecutor = null;
|
||||
}
|
||||
}
|
||||
|
||||
// either there was no accessor or it no longer existed
|
||||
executorToUse = findAccessorForMethod(name, getTypes(this.arguments), this.target, this.evaluationContext);
|
||||
cachedExecutor = executorToUse;
|
||||
try {
|
||||
return executorToUse.execute(this.evaluationContext, this.target, this.arguments);
|
||||
}
|
||||
catch (AccessException ae) {
|
||||
// Same unwrapping exception handling as above in above catch block
|
||||
throwSimpleExceptionIfPossible(this.state, ae);
|
||||
throw new SpelEvaluationException( getStartPosition(), ae, SpelMessage.EXCEPTION_DURING_METHOD_INVOCATION,
|
||||
name, this.state.getActiveContextObject().getValue().getClass().getName(), ae.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void setValue(Object newValue) {
|
||||
throw new IllegalAccessError();
|
||||
}
|
||||
|
||||
public boolean isWritable() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+13
-12
@@ -42,8 +42,8 @@ import org.springframework.expression.spel.SpelEvaluationException;
|
||||
import org.springframework.expression.spel.SpelMessage;
|
||||
|
||||
/**
|
||||
* Reflection-based {@link MethodResolver} used by default in
|
||||
* {@link StandardEvaluationContext} unless explicit method resolvers have been specified.
|
||||
* Reflection-based {@link MethodResolver} used by default in {@link StandardEvaluationContext}
|
||||
* unless explicit method resolvers have been specified.
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @author Juergen Hoeller
|
||||
@@ -63,7 +63,6 @@ public class ReflectiveMethodResolver implements MethodResolver {
|
||||
|
||||
|
||||
public ReflectiveMethodResolver() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,7 +98,8 @@ public class ReflectiveMethodResolver implements MethodResolver {
|
||||
// If a filter is registered for this type, call it
|
||||
MethodFilter filter = (this.filters != null ? this.filters.get(type) : null);
|
||||
if (filter != null) {
|
||||
methods = filter.filter(methods);
|
||||
List<Method> filtered = filter.filter(methods);
|
||||
methods = (filtered instanceof ArrayList ? filtered : new ArrayList<Method>(filtered));
|
||||
}
|
||||
|
||||
// Sort methods into a sensible order
|
||||
@@ -119,7 +119,7 @@ public class ReflectiveMethodResolver implements MethodResolver {
|
||||
}
|
||||
|
||||
// Remove duplicate methods (possible due to resolved bridge methods)
|
||||
methods = new ArrayList<Method>(new LinkedHashSet<Method>(methods));
|
||||
Set<Method> methodsToIterate = new LinkedHashSet<Method>(methods);
|
||||
|
||||
Method closeMatch = null;
|
||||
int closeMatchDistance = Integer.MAX_VALUE;
|
||||
@@ -127,7 +127,7 @@ public class ReflectiveMethodResolver implements MethodResolver {
|
||||
Method matchRequiringConversion = null;
|
||||
boolean multipleOptions = false;
|
||||
|
||||
for (Method method : methods) {
|
||||
for (Method method : methodsToIterate) {
|
||||
if (method.getName().equals(name)) {
|
||||
Class<?>[] paramTypes = method.getParameterTypes();
|
||||
List<TypeDescriptor> paramDescriptors = new ArrayList<TypeDescriptor>(paramTypes.length);
|
||||
@@ -148,9 +148,10 @@ public class ReflectiveMethodResolver implements MethodResolver {
|
||||
return new ReflectiveMethodExecutor(method, null);
|
||||
}
|
||||
else if (matchInfo.kind == ReflectionHelper.ArgsMatchKind.CLOSE) {
|
||||
if (!useDistance) {
|
||||
if (!this.useDistance) {
|
||||
closeMatch = method;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
int matchDistance = ReflectionHelper.getTypeDifferenceWeight(paramDescriptors, argumentTypes);
|
||||
if (matchDistance<closeMatchDistance) {
|
||||
// this is a better match
|
||||
@@ -200,7 +201,7 @@ public class ReflectiveMethodResolver implements MethodResolver {
|
||||
}
|
||||
|
||||
private Method[] getMethods(Class<?> type, Object targetObject) {
|
||||
if(targetObject instanceof Class) {
|
||||
if (targetObject instanceof Class) {
|
||||
Set<Method> methods = new HashSet<Method>();
|
||||
methods.addAll(Arrays.asList(getMethods(type)));
|
||||
methods.addAll(Arrays.asList(getMethods(targetObject.getClass())));
|
||||
@@ -211,9 +212,9 @@ public class ReflectiveMethodResolver implements MethodResolver {
|
||||
|
||||
/**
|
||||
* Return the set of methods for this type. The default implementation returns the
|
||||
* result of Class#getMethods for the given {@code type}, but subclasses may override
|
||||
* in order to alter the results, e.g. specifying static methods declared elsewhere.
|
||||
*
|
||||
* result of {@link Class#getMethods()} for the given {@code type}, but subclasses
|
||||
* may override in order to alter the results, e.g. specifying static methods
|
||||
* declared elsewhere.
|
||||
* @param type the class for which to return the methods
|
||||
* @since 3.1.1
|
||||
*/
|
||||
|
||||
+3
-2
@@ -3,6 +3,7 @@ package org.springframework.expression.spel.testresources;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -30,8 +31,8 @@ public class Inventor {
|
||||
private boolean accessedThroughGetSet;
|
||||
public List<Integer> listOfInteger = new ArrayList<Integer>();
|
||||
public List<Boolean> booleanList = new ArrayList<Boolean>();
|
||||
public Map<String,Boolean> mapOfStringToBoolean = new HashMap<String,Boolean>();
|
||||
public Map<Integer,String> mapOfNumbersUpToTen = new HashMap<Integer,String>();
|
||||
public Map<String,Boolean> mapOfStringToBoolean = new LinkedHashMap<String,Boolean>();
|
||||
public Map<Integer,String> mapOfNumbersUpToTen = new LinkedHashMap<Integer,String>();
|
||||
public List<Integer> listOfNumbersUpToTen = new ArrayList<Integer>();
|
||||
public List<Integer> listOneFive = new ArrayList<Integer>();
|
||||
public String[] stringArrayOfThreeItems = new String[]{"1","2","3"};
|
||||
|
||||
+14
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -37,6 +37,7 @@ import org.springframework.dao.DataRetrievalFailureException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.jdbc.support.JdbcUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link RowMapper} implementation that converts a row into a new instance
|
||||
@@ -163,18 +164,19 @@ public class BeanPropertyRowMapper<T> implements RowMapper<T> {
|
||||
* @return the converted name
|
||||
*/
|
||||
private String underscoreName(String name) {
|
||||
if (!StringUtils.hasLength(name)) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder result = new StringBuilder();
|
||||
if (name != null && name.length() > 0) {
|
||||
result.append(name.substring(0, 1).toLowerCase());
|
||||
for (int i = 1; i < name.length(); i++) {
|
||||
String s = name.substring(i, i + 1);
|
||||
if (s.equals(s.toUpperCase())) {
|
||||
result.append("_");
|
||||
result.append(s.toLowerCase());
|
||||
}
|
||||
else {
|
||||
result.append(s);
|
||||
}
|
||||
result.append(name.substring(0, 1).toLowerCase());
|
||||
for (int i = 1; i < name.length(); i++) {
|
||||
String s = name.substring(i, i + 1);
|
||||
String slc = s.toLowerCase();
|
||||
if (!s.equals(slc)) {
|
||||
result.append("_").append(slc);
|
||||
}
|
||||
else {
|
||||
result.append(s);
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
|
||||
+46
-41
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,21 +32,22 @@ import javax.jms.TextMessage;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Message converter that uses the Jackson 2 library to convert messages to and from JSON.
|
||||
* Maps an object to a {@link javax.jms.BytesMessage}, or to a {@link javax.jms.TextMessage} if the
|
||||
* {@link #setTargetType targetType} is set to {@link org.springframework.jms.support.converter.MessageType#TEXT}.
|
||||
* Converts from a {@link javax.jms.TextMessage} or {@link javax.jms.BytesMessage} to an object.
|
||||
* Maps an object to a {@link BytesMessage}, or to a {@link TextMessage} if the
|
||||
* {@link #setTargetType targetType} is set to {@link MessageType#TEXT}.
|
||||
* Converts from a {@link TextMessage} or {@link BytesMessage} to an object.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @author Dave Syer
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1.4
|
||||
*/
|
||||
public class MappingJackson2MessageConverter implements MessageConverter {
|
||||
public class MappingJackson2MessageConverter implements MessageConverter, BeanClassLoaderAware {
|
||||
|
||||
/**
|
||||
* The default encoding used for writing to text messages: UTF-8.
|
||||
@@ -68,9 +69,11 @@ public class MappingJackson2MessageConverter implements MessageConverter {
|
||||
|
||||
private Map<Class<?>, String> classIdMappings = new HashMap<Class<?>, String>();
|
||||
|
||||
private ClassLoader beanClassLoader;
|
||||
|
||||
|
||||
/**
|
||||
* Specify the {@link org.codehaus.jackson.map.ObjectMapper} to use instead of using the default.
|
||||
* Specify the {@link ObjectMapper} to use instead of using the default.
|
||||
*/
|
||||
public void setObjectMapper(ObjectMapper objectMapper) {
|
||||
Assert.notNull(objectMapper, "ObjectMapper must not be null");
|
||||
@@ -78,13 +81,13 @@ public class MappingJackson2MessageConverter implements MessageConverter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify whether {@link #toMessage(Object, javax.jms.Session)} should marshal to a
|
||||
* {@link javax.jms.BytesMessage} or a {@link javax.jms.TextMessage}.
|
||||
* <p>The default is {@link org.springframework.jms.support.converter.MessageType#BYTES}, i.e. this converter marshals to
|
||||
* a {@link javax.jms.BytesMessage}. Note that the default version of this converter
|
||||
* supports {@link org.springframework.jms.support.converter.MessageType#BYTES} and {@link org.springframework.jms.support.converter.MessageType#TEXT} only.
|
||||
* @see org.springframework.jms.support.converter.MessageType#BYTES
|
||||
* @see org.springframework.jms.support.converter.MessageType#TEXT
|
||||
* Specify whether {@link #toMessage(Object, Session)} should marshal to a
|
||||
* {@link BytesMessage} or a {@link TextMessage}.
|
||||
* <p>The default is {@link MessageType#BYTES}, i.e. this converter marshals to
|
||||
* a {@link BytesMessage}. Note that the default version of this converter
|
||||
* supports {@link MessageType#BYTES} and {@link MessageType#TEXT} only.
|
||||
* @see MessageType#BYTES
|
||||
* @see MessageType#TEXT
|
||||
*/
|
||||
public void setTargetType(MessageType targetType) {
|
||||
Assert.notNull(targetType, "MessageType must not be null");
|
||||
@@ -142,6 +145,10 @@ public class MappingJackson2MessageConverter implements MessageConverter {
|
||||
}
|
||||
}
|
||||
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.beanClassLoader = classLoader;
|
||||
}
|
||||
|
||||
|
||||
public Message toMessage(Object object, Session session) throws JMSException, MessageConversionException {
|
||||
Message message;
|
||||
@@ -176,15 +183,14 @@ public class MappingJackson2MessageConverter implements MessageConverter {
|
||||
|
||||
|
||||
/**
|
||||
* Map the given object to a {@link javax.jms.TextMessage}.
|
||||
* Map the given object to a {@link TextMessage}.
|
||||
* @param object the object to be mapped
|
||||
* @param session current JMS session
|
||||
* @param objectMapper the mapper to use
|
||||
* @return the resulting message
|
||||
* @throws javax.jms.JMSException if thrown by JMS methods
|
||||
* @throws java.io.IOException in case of I/O errors
|
||||
* @see javax.jms.Session#createBytesMessage
|
||||
* @see org.springframework.oxm.Marshaller#marshal(Object, javax.xml.transform.Result)
|
||||
* @throws JMSException if thrown by JMS methods
|
||||
* @throws IOException in case of I/O errors
|
||||
* @see Session#createBytesMessage
|
||||
*/
|
||||
protected TextMessage mapToTextMessage(Object object, Session session, ObjectMapper objectMapper)
|
||||
throws JMSException, IOException {
|
||||
@@ -195,15 +201,14 @@ public class MappingJackson2MessageConverter implements MessageConverter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the given object to a {@link javax.jms.BytesMessage}.
|
||||
* Map the given object to a {@link BytesMessage}.
|
||||
* @param object the object to be mapped
|
||||
* @param session current JMS session
|
||||
* @param objectMapper the mapper to use
|
||||
* @return the resulting message
|
||||
* @throws javax.jms.JMSException if thrown by JMS methods
|
||||
* @throws java.io.IOException in case of I/O errors
|
||||
* @see javax.jms.Session#createBytesMessage
|
||||
* @see org.springframework.oxm.Marshaller#marshal(Object, javax.xml.transform.Result)
|
||||
* @throws JMSException if thrown by JMS methods
|
||||
* @throws IOException in case of I/O errors
|
||||
* @see Session#createBytesMessage
|
||||
*/
|
||||
protected BytesMessage mapToBytesMessage(Object object, Session session, ObjectMapper objectMapper)
|
||||
throws JMSException, IOException {
|
||||
@@ -222,22 +227,22 @@ public class MappingJackson2MessageConverter implements MessageConverter {
|
||||
|
||||
/**
|
||||
* Template method that allows for custom message mapping.
|
||||
* Invoked when {@link #setTargetType} is not {@link org.springframework.jms.support.converter.MessageType#TEXT} or
|
||||
* {@link org.springframework.jms.support.converter.MessageType#BYTES}.
|
||||
* Invoked when {@link #setTargetType} is not {@link MessageType#TEXT} or
|
||||
* {@link MessageType#BYTES}.
|
||||
* <p>The default implementation throws an {@link IllegalArgumentException}.
|
||||
* @param object the object to marshal
|
||||
* @param session the JMS Session
|
||||
* @param objectMapper the mapper to use
|
||||
* @param targetType the target message type (other than TEXT or BYTES)
|
||||
* @return the resulting message
|
||||
* @throws javax.jms.JMSException if thrown by JMS methods
|
||||
* @throws java.io.IOException in case of I/O errors
|
||||
* @throws JMSException if thrown by JMS methods
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
protected Message mapToMessage(Object object, Session session, ObjectMapper objectMapper, MessageType targetType)
|
||||
throws JMSException, IOException {
|
||||
|
||||
throw new IllegalArgumentException("Unsupported message type [" + targetType +
|
||||
"]. MappingJacksonMessageConverter by default only supports TextMessages and BytesMessages.");
|
||||
"]. MappingJackson2MessageConverter by default only supports TextMessages and BytesMessages.");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -247,7 +252,7 @@ public class MappingJackson2MessageConverter implements MessageConverter {
|
||||
* into the configured type id message property.
|
||||
* @param object the payload object to set a type id for
|
||||
* @param message the JMS Message to set the type id on
|
||||
* @throws javax.jms.JMSException if thrown by JMS methods
|
||||
* @throws JMSException if thrown by JMS methods
|
||||
* @see #getJavaTypeForMessage(javax.jms.Message)
|
||||
* @see #setTypeIdPropertyName(String)
|
||||
* @see #setTypeIdMappings(java.util.Map)
|
||||
@@ -283,8 +288,8 @@ public class MappingJackson2MessageConverter implements MessageConverter {
|
||||
* @param message the input message
|
||||
* @param targetJavaType the target type
|
||||
* @return the message converted to an object
|
||||
* @throws javax.jms.JMSException if thrown by JMS
|
||||
* @throws java.io.IOException in case of I/O errors
|
||||
* @throws JMSException if thrown by JMS
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
protected Object convertFromTextMessage(TextMessage message, JavaType targetJavaType)
|
||||
throws JMSException, IOException {
|
||||
@@ -298,8 +303,8 @@ public class MappingJackson2MessageConverter implements MessageConverter {
|
||||
* @param message the input message
|
||||
* @param targetJavaType the target type
|
||||
* @return the message converted to an object
|
||||
* @throws javax.jms.JMSException if thrown by JMS
|
||||
* @throws java.io.IOException in case of I/O errors
|
||||
* @throws JMSException if thrown by JMS
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
protected Object convertFromBytesMessage(BytesMessage message, JavaType targetJavaType)
|
||||
throws JMSException, IOException {
|
||||
@@ -321,14 +326,14 @@ public class MappingJackson2MessageConverter implements MessageConverter {
|
||||
|
||||
/**
|
||||
* Template method that allows for custom message mapping.
|
||||
* Invoked when {@link #setTargetType} is not {@link org.springframework.jms.support.converter.MessageType#TEXT} or
|
||||
* {@link org.springframework.jms.support.converter.MessageType#BYTES}.
|
||||
* Invoked when {@link #setTargetType} is not {@link MessageType#TEXT} or
|
||||
* {@link MessageType#BYTES}.
|
||||
* <p>The default implementation throws an {@link IllegalArgumentException}.
|
||||
* @param message the input message
|
||||
* @param targetJavaType the target type
|
||||
* @return the message converted to an object
|
||||
* @throws javax.jms.JMSException if thrown by JMS
|
||||
* @throws java.io.IOException in case of I/O errors
|
||||
* @throws JMSException if thrown by JMS
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
protected Object convertFromMessage(Message message, JavaType targetJavaType)
|
||||
throws JMSException, IOException {
|
||||
@@ -344,7 +349,7 @@ public class MappingJackson2MessageConverter implements MessageConverter {
|
||||
* and consults the configured type id mapping. This can be overridden with
|
||||
* a different strategy, e.g. doing some heuristics based on message origin.
|
||||
* @param message the JMS Message to set the type id on
|
||||
* @throws javax.jms.JMSException if thrown by JMS methods
|
||||
* @throws JMSException if thrown by JMS methods
|
||||
* @see #setTypeIdOnMessage(Object, javax.jms.Message)
|
||||
* @see #setTypeIdPropertyName(String)
|
||||
* @see #setTypeIdMappings(java.util.Map)
|
||||
@@ -354,13 +359,13 @@ public class MappingJackson2MessageConverter implements MessageConverter {
|
||||
if (typeId == null) {
|
||||
throw new MessageConversionException("Could not find type id property [" + this.typeIdPropertyName + "]");
|
||||
}
|
||||
Class mappedClass = this.idClassMappings.get(typeId);
|
||||
Class<?> mappedClass = this.idClassMappings.get(typeId);
|
||||
if (mappedClass != null) {
|
||||
return this.objectMapper.getTypeFactory().constructType(mappedClass);
|
||||
}
|
||||
try {
|
||||
return this.objectMapper.getTypeFactory().constructType(
|
||||
ClassUtils.forName(typeId, getClass().getClassLoader()));
|
||||
Class<?> typeClass = ClassUtils.forName(typeId, this.beanClassLoader);
|
||||
return this.objectMapper.getTypeFactory().constructType(typeClass);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new MessageConversionException("Failed to resolve type id [" + typeId + "]", ex);
|
||||
|
||||
+12
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,13 +28,12 @@ import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
import javax.xml.transform.Result;
|
||||
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
import org.codehaus.jackson.map.type.TypeFactory;
|
||||
import org.codehaus.jackson.type.JavaType;
|
||||
|
||||
import org.springframework.oxm.Marshaller;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@@ -49,7 +48,7 @@ import org.springframework.util.ClassUtils;
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
*/
|
||||
public class MappingJacksonMessageConverter implements MessageConverter {
|
||||
public class MappingJacksonMessageConverter implements MessageConverter, BeanClassLoaderAware {
|
||||
|
||||
/**
|
||||
* The default encoding used for writing to text messages: UTF-8.
|
||||
@@ -71,6 +70,8 @@ public class MappingJacksonMessageConverter implements MessageConverter {
|
||||
|
||||
private Map<Class<?>, String> classIdMappings = new HashMap<Class<?>, String>();
|
||||
|
||||
private ClassLoader beanClassLoader;
|
||||
|
||||
|
||||
/**
|
||||
* Specify the {@link ObjectMapper} to use instead of using the default.
|
||||
@@ -145,6 +146,10 @@ public class MappingJacksonMessageConverter implements MessageConverter {
|
||||
}
|
||||
}
|
||||
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.beanClassLoader = classLoader;
|
||||
}
|
||||
|
||||
|
||||
public Message toMessage(Object object, Session session) throws JMSException, MessageConversionException {
|
||||
Message message;
|
||||
@@ -187,7 +192,6 @@ public class MappingJacksonMessageConverter implements MessageConverter {
|
||||
* @throws JMSException if thrown by JMS methods
|
||||
* @throws IOException in case of I/O errors
|
||||
* @see Session#createBytesMessage
|
||||
* @see Marshaller#marshal(Object, Result)
|
||||
*/
|
||||
protected TextMessage mapToTextMessage(Object object, Session session, ObjectMapper objectMapper)
|
||||
throws JMSException, IOException {
|
||||
@@ -206,7 +210,6 @@ public class MappingJacksonMessageConverter implements MessageConverter {
|
||||
* @throws JMSException if thrown by JMS methods
|
||||
* @throws IOException in case of I/O errors
|
||||
* @see Session#createBytesMessage
|
||||
* @see Marshaller#marshal(Object, Result)
|
||||
*/
|
||||
protected BytesMessage mapToBytesMessage(Object object, Session session, ObjectMapper objectMapper)
|
||||
throws JMSException, IOException {
|
||||
@@ -357,12 +360,13 @@ public class MappingJacksonMessageConverter implements MessageConverter {
|
||||
if (typeId == null) {
|
||||
throw new MessageConversionException("Could not find type id property [" + this.typeIdPropertyName + "]");
|
||||
}
|
||||
Class mappedClass = this.idClassMappings.get(typeId);
|
||||
Class<?> mappedClass = this.idClassMappings.get(typeId);
|
||||
if (mappedClass != null) {
|
||||
return TypeFactory.type(mappedClass);
|
||||
}
|
||||
try {
|
||||
return TypeFactory.type(ClassUtils.forName(typeId, getClass().getClassLoader()));
|
||||
Class<?> typeClass = ClassUtils.forName(typeId, this.beanClassLoader);
|
||||
return TypeFactory.type(typeClass);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new MessageConversionException("Failed to resolve type id [" + typeId + "]", ex);
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.orm.jdo;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import javax.jdo.Constants;
|
||||
@@ -35,8 +34,6 @@ import org.springframework.jdbc.support.JdbcUtils;
|
||||
import org.springframework.jdbc.support.SQLExceptionTranslator;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionException;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* Default implementation of the {@link JdoDialect} interface.
|
||||
@@ -69,10 +66,6 @@ import org.springframework.util.ReflectionUtils;
|
||||
*/
|
||||
public class DefaultJdoDialect implements JdoDialect, PersistenceExceptionTranslator {
|
||||
|
||||
// JDO 3.0 setTimeoutMillis method available?
|
||||
private static final Method setTimeoutMillisMethod =
|
||||
ClassUtils.getMethodIfAvailable(Query.class, "setTimeoutMillis", Integer.class);
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private SQLExceptionTranslator jdbcExceptionTranslator;
|
||||
@@ -213,19 +206,9 @@ public class DefaultJdoDialect implements JdoDialect, PersistenceExceptionTransl
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation applies a JDO 3.0 query timeout, if available. Otherwise,
|
||||
* it sets the JPA 2.0 query hints "javax.persistence.lock.timeout" and
|
||||
* "javax.persistence.query.timeout", assuming that JDO providers are often
|
||||
* JPA providers as well.
|
||||
* This implementation does nothing.
|
||||
*/
|
||||
public void applyQueryTimeout(Query query, int remainingTimeInSeconds) throws JDOException {
|
||||
if (setTimeoutMillisMethod != null) {
|
||||
ReflectionUtils.invokeMethod(setTimeoutMillisMethod, query, remainingTimeInSeconds);
|
||||
}
|
||||
else {
|
||||
query.addExtension("javax.persistence.lock.timeout", remainingTimeInSeconds);
|
||||
query.addExtension("javax.persistence.query.timeout", remainingTimeInSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+22
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,12 +35,13 @@ import org.springframework.orm.jpa.DefaultJpaDialect;
|
||||
import org.springframework.orm.jpa.EntityManagerFactoryUtils;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionException;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.orm.jpa.JpaDialect} implementation for
|
||||
* Hibernate EntityManager. Developed against Hibernate 3.3;
|
||||
* tested against 3.3, 3.5, 3.6 and 4.0 (with the latter including
|
||||
* Hibernate EntityManager. Developed against Hibernate 3.3; tested
|
||||
* against 3.3, 3.5, 3.6, 4.0, 4.1 and 4.2 (with the latter including
|
||||
* Hibernate EntityManager in the Hibernate core distribution).
|
||||
*
|
||||
* @author Costin Leau
|
||||
@@ -147,7 +148,11 @@ public class HibernateJpaDialect extends DefaultJpaDialect {
|
||||
|
||||
private final Session session;
|
||||
|
||||
private static volatile Method connectionMethod;
|
||||
// This will find a corresponding method on Hibernate 3.x but not on 4.x
|
||||
private static final Method sessionConnectionMethod =
|
||||
ClassUtils.getMethodIfAvailable(Session.class, "connection");
|
||||
|
||||
private static volatile Method connectionMethodToUse = sessionConnectionMethod;
|
||||
|
||||
public HibernateConnectionHandle(Session session) {
|
||||
this.session = session;
|
||||
@@ -155,19 +160,26 @@ public class HibernateJpaDialect extends DefaultJpaDialect {
|
||||
|
||||
public Connection getConnection() {
|
||||
try {
|
||||
if (connectionMethod == null) {
|
||||
// reflective lookup to bridge between Hibernate 3.x and 4.x
|
||||
connectionMethod = this.session.getClass().getMethod("connection");
|
||||
if (connectionMethodToUse == null) {
|
||||
// Reflective lookup trying to find SessionImpl's connection() on Hibernate 4.x
|
||||
connectionMethodToUse = this.session.getClass().getMethod("connection");
|
||||
}
|
||||
return (Connection) ReflectionUtils.invokeMethod(connectionMethod, this.session);
|
||||
return (Connection) ReflectionUtils.invokeMethod(connectionMethodToUse, this.session);
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
throw new IllegalStateException("Cannot find connection() method on Hibernate session", ex);
|
||||
throw new IllegalStateException("Cannot find connection() method on Hibernate Session", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void releaseConnection(Connection con) {
|
||||
JdbcUtils.closeConnection(con);
|
||||
if (sessionConnectionMethod != null) {
|
||||
// Need to explicitly call close() with Hibernate 3.x in order to allow
|
||||
// for eager release of the underlying physical Connection if necessary.
|
||||
// However, do not do this on Hibernate 4.2+ since it would return the
|
||||
// physical Connection to the pool right away, making it unusable for
|
||||
// further operations within the current transaction!
|
||||
JdbcUtils.closeConnection(con);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.orm.jpa.toplink;
|
||||
|
||||
import org.junit.Ignore;
|
||||
|
||||
import org.springframework.orm.jpa.AbstractContainerEntityManagerFactoryIntegrationTests;
|
||||
import org.springframework.orm.jpa.EntityManagerFactoryInfo;
|
||||
|
||||
@@ -26,6 +28,7 @@ import org.springframework.orm.jpa.EntityManagerFactoryInfo;
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
@Ignore
|
||||
public class TopLinkEntityManagerFactoryIntegrationTests extends AbstractContainerEntityManagerFactoryIntegrationTests {
|
||||
|
||||
@Override
|
||||
|
||||
+21
-32
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,10 +25,8 @@ import javax.xml.bind.annotation.XmlSeeAlso;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import org.springframework.core.io.support.ResourcePatternUtils;
|
||||
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
|
||||
import org.springframework.core.type.classreading.MetadataReader;
|
||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||
@@ -42,62 +40,54 @@ import org.springframework.util.ClassUtils;
|
||||
* Helper class for {@link Jaxb2Marshaller} that scans given packages for classes marked with JAXB2 annotations.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Juergen Hoeller
|
||||
* @author David Harrigan
|
||||
* @since 3.1.1
|
||||
* @see #scanPackages()
|
||||
*/
|
||||
class ClassPathJaxb2TypeScanner {
|
||||
|
||||
private static final String RESOURCE_PATTERN = "/**/*.class";
|
||||
|
||||
private final TypeFilter[] jaxb2TypeFilters =
|
||||
new TypeFilter[]{new AnnotationTypeFilter(XmlRootElement.class, false),
|
||||
new AnnotationTypeFilter(XmlType.class, false), new AnnotationTypeFilter(XmlSeeAlso.class, false),
|
||||
new AnnotationTypeFilter(XmlEnum.class, false)};
|
||||
private static final TypeFilter[] JAXB2_TYPE_FILTERS = new TypeFilter[] {
|
||||
new AnnotationTypeFilter(XmlRootElement.class, false), new AnnotationTypeFilter(XmlType.class, false),
|
||||
new AnnotationTypeFilter(XmlSeeAlso.class, false), new AnnotationTypeFilter(XmlEnum.class, false)};
|
||||
|
||||
|
||||
private final ResourcePatternResolver resourcePatternResolver;
|
||||
|
||||
private final String[] packagesToScan;
|
||||
|
||||
private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
|
||||
|
||||
private List<Class<?>> jaxb2Classes = new ArrayList<Class<?>>();
|
||||
|
||||
/** Constructs a new {@code ClassPathJaxb2TypeScanner} for the given packages. */
|
||||
ClassPathJaxb2TypeScanner(String[] packagesToScan) {
|
||||
public ClassPathJaxb2TypeScanner(ClassLoader classLoader, String... packagesToScan) {
|
||||
Assert.notEmpty(packagesToScan, "'packagesToScan' must not be empty");
|
||||
this.resourcePatternResolver = new PathMatchingResourcePatternResolver(classLoader);
|
||||
this.packagesToScan = packagesToScan;
|
||||
}
|
||||
|
||||
void setResourceLoader(ResourceLoader resourceLoader) {
|
||||
if (resourceLoader != null) {
|
||||
this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the JAXB2 classes found in the specified packages. */
|
||||
Class<?>[] getJaxb2Classes() {
|
||||
return jaxb2Classes.toArray(new Class<?>[jaxb2Classes.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans the packages for classes marked with JAXB2 annotations.
|
||||
*
|
||||
* Scan the packages for classes marked with JAXB2 annotations.
|
||||
* @throws UncategorizedMappingException in case of errors
|
||||
*/
|
||||
void scanPackages() throws UncategorizedMappingException {
|
||||
public Class<?>[] scanPackages() throws UncategorizedMappingException {
|
||||
try {
|
||||
for (String packageToScan : packagesToScan) {
|
||||
List<Class<?>> jaxb2Classes = new ArrayList<Class<?>>();
|
||||
for (String packageToScan : this.packagesToScan) {
|
||||
String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
|
||||
ClassUtils.convertClassNameToResourcePath(packageToScan) + RESOURCE_PATTERN;
|
||||
Resource[] resources = resourcePatternResolver.getResources(pattern);
|
||||
MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resourcePatternResolver);
|
||||
Resource[] resources = this.resourcePatternResolver.getResources(pattern);
|
||||
MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver);
|
||||
for (Resource resource : resources) {
|
||||
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource);
|
||||
if (isJaxb2Class(metadataReader, metadataReaderFactory)) {
|
||||
String className = metadataReader.getClassMetadata().getClassName();
|
||||
Class<?> jaxb2AnnotatedClass = resourcePatternResolver.getClassLoader().loadClass(className);
|
||||
Class<?> jaxb2AnnotatedClass = this.resourcePatternResolver.getClassLoader().loadClass(className);
|
||||
jaxb2Classes.add(jaxb2AnnotatedClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
return jaxb2Classes.toArray(new Class<?>[jaxb2Classes.size()]);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new UncategorizedMappingException("Failed to scan classpath for unlisted classes", ex);
|
||||
@@ -107,8 +97,8 @@ class ClassPathJaxb2TypeScanner {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isJaxb2Class(MetadataReader reader, MetadataReaderFactory factory) throws IOException {
|
||||
for (TypeFilter filter : jaxb2TypeFilters) {
|
||||
protected boolean isJaxb2Class(MetadataReader reader, MetadataReaderFactory factory) throws IOException {
|
||||
for (TypeFilter filter : JAXB2_TYPE_FILTERS) {
|
||||
if (filter.match(reader, factory)) {
|
||||
return true;
|
||||
}
|
||||
@@ -116,5 +106,4 @@ class ClassPathJaxb2TypeScanner {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -75,7 +75,6 @@ import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.core.JdkVersion;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.io.Resource;
|
||||
@@ -119,9 +118,8 @@ import org.springframework.util.xml.StaxUtils;
|
||||
* @see #setUnmarshallerListener(javax.xml.bind.Unmarshaller.Listener)
|
||||
* @see #setAdapters(XmlAdapter[])
|
||||
*/
|
||||
public class Jaxb2Marshaller
|
||||
implements MimeMarshaller, MimeUnmarshaller, GenericMarshaller, GenericUnmarshaller, BeanClassLoaderAware,
|
||||
ResourceLoaderAware, InitializingBean {
|
||||
public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, GenericMarshaller, GenericUnmarshaller,
|
||||
BeanClassLoaderAware, InitializingBean {
|
||||
|
||||
private static final String CID = "cid:";
|
||||
|
||||
@@ -177,8 +175,8 @@ public class Jaxb2Marshaller
|
||||
|
||||
|
||||
/**
|
||||
* Set multiple JAXB context paths. The given array of context paths is converted to a
|
||||
* colon-delimited string, as supported by JAXB.
|
||||
* Set multiple JAXB context paths. The given array of context paths gets
|
||||
* converted to a colon-delimited string, as supported by JAXB.
|
||||
*/
|
||||
public void setContextPaths(String... contextPaths) {
|
||||
Assert.notEmpty(contextPaths, "'contextPaths' must not be empty");
|
||||
@@ -187,8 +185,8 @@ public class Jaxb2Marshaller
|
||||
|
||||
/**
|
||||
* Set a JAXB context path.
|
||||
* <p>Setting this property, {@link #setClassesToBeBound "classesToBeBound"}, or
|
||||
* {@link #setPackagesToScan "packagesToScan"} is required.
|
||||
* <p>Setting either this property, {@link #setClassesToBeBound "classesToBeBound"}
|
||||
* or {@link #setPackagesToScan "packagesToScan"} is required.
|
||||
*/
|
||||
public void setContextPath(String contextPath) {
|
||||
Assert.hasText(contextPath, "'contextPath' must not be null");
|
||||
@@ -204,8 +202,8 @@ public class Jaxb2Marshaller
|
||||
|
||||
/**
|
||||
* Set the list of Java classes to be recognized by a newly created JAXBContext.
|
||||
* <p>Setting this property, {@link #setContextPath "contextPath"}, or
|
||||
* {@link #setPackagesToScan "packagesToScan"} is required.
|
||||
* <p>Setting either this property, {@link #setContextPath "contextPath"}
|
||||
* or {@link #setPackagesToScan "packagesToScan"} is required.
|
||||
*/
|
||||
public void setClassesToBeBound(Class<?>... classesToBeBound) {
|
||||
Assert.notEmpty(classesToBeBound, "'classesToBeBound' must not be empty");
|
||||
@@ -220,10 +218,11 @@ public class Jaxb2Marshaller
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the packages to search using Spring-based scanning for classes with JAXB2 annotations in the classpath.
|
||||
* <p>Setting this property, {@link #setContextPath "contextPath"}, or
|
||||
* {@link #setClassesToBeBound "classesToBeBound"} is required. This is analogous to Spring's component-scan feature
|
||||
* ({@link org.springframework.context.annotation.ClassPathBeanDefinitionScanner}).
|
||||
* Set the packages to search for classes with JAXB2 annotations in the classpath.
|
||||
* This is using a Spring-bases search and therefore analogous to Spring's component-scan
|
||||
* feature ({@link org.springframework.context.annotation.ClassPathBeanDefinitionScanner}).
|
||||
* <p>Setting either this property, {@link #setContextPath "contextPath"}
|
||||
* or {@link #setClassesToBeBound "classesToBeBound"} is required.
|
||||
*/
|
||||
public void setPackagesToScan(String[] packagesToScan) {
|
||||
this.packagesToScan = packagesToScan;
|
||||
@@ -390,12 +389,8 @@ public class Jaxb2Marshaller
|
||||
this.beanClassLoader = classLoader;
|
||||
}
|
||||
|
||||
public void setResourceLoader(ResourceLoader resourceLoader) {
|
||||
this.resourceLoader = resourceLoader;
|
||||
}
|
||||
|
||||
|
||||
public final void afterPropertiesSet() throws Exception {
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
boolean hasContextPath = StringUtils.hasLength(this.contextPath);
|
||||
boolean hasClassesToBeBound = !ObjectUtils.isEmpty(this.classesToBeBound);
|
||||
boolean hasPackagesToScan = !ObjectUtils.isEmpty(this.packagesToScan);
|
||||
@@ -487,10 +482,8 @@ public class Jaxb2Marshaller
|
||||
logger.info("Creating JAXBContext by scanning packages [" +
|
||||
StringUtils.arrayToCommaDelimitedString(this.packagesToScan) + "]");
|
||||
}
|
||||
ClassPathJaxb2TypeScanner scanner = new ClassPathJaxb2TypeScanner(this.packagesToScan);
|
||||
scanner.setResourceLoader(this.resourceLoader);
|
||||
scanner.scanPackages();
|
||||
Class<?>[] jaxb2Classes = scanner.getJaxb2Classes();
|
||||
ClassPathJaxb2TypeScanner scanner = new ClassPathJaxb2TypeScanner(this.beanClassLoader, this.packagesToScan);
|
||||
Class<?>[] jaxb2Classes = scanner.scanPackages();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Found JAXB2 classes: [" + StringUtils.arrayToCommaDelimitedString(jaxb2Classes) + "]");
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -79,10 +79,15 @@ public class Person {
|
||||
ObjectUtils.nullSafeEquals(this.someBoolean, otherPerson.someBoolean));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Person.class.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Person [name=" + this.name + ", someDouble=" + this.someDouble
|
||||
+ ", someBoolean=" + this.someBoolean + "]";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,11 +243,10 @@ public class MockServletContext implements ServletContext {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method uses the Java Activation framework, which returns
|
||||
* "application/octet-stream" when the mime type is unknown (i.e. it never returns
|
||||
* {@code null}). In order to maintain the {@link ServletContext#getMimeType(String)
|
||||
* contract, as of version 3.2.2, this method returns null if the mimeType is
|
||||
* "application/octet-stream".
|
||||
* This method uses the Java Activation framework, which returns "application/octet-stream"
|
||||
* when the mime type is unknown (i.e. it never returns {@code null}). In order to maintain
|
||||
* the {@link ServletContext#getMimeType(String)} contract, this method returns {@code null}
|
||||
* if the mimeType is "application/octet-stream", as of Spring 3.2.2.
|
||||
*/
|
||||
public String getMimeType(String filePath) {
|
||||
String mimeType = MimeTypeResolver.getMimeType(filePath);
|
||||
|
||||
@@ -167,7 +167,8 @@ public class TestContext extends AttributeAccessorSupport {
|
||||
* context} associated with this test context is <em>dirty</em> and should be
|
||||
* discarded. Do this if a test has modified the context — for example,
|
||||
* by replacing a bean definition or modifying the state of a singleton bean.
|
||||
* @deprecated As of Spring 3.2.2, use {@link #markApplicationContextDirty(HierarchyMode)} instead.
|
||||
* @deprecated as of Spring 3.2.2; use
|
||||
* {@link #markApplicationContextDirty(DirtiesContext.HierarchyMode)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public void markApplicationContextDirty() {
|
||||
|
||||
+9
-9
@@ -20,6 +20,7 @@ import java.lang.reflect.Method;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.annotation.DirtiesContext.ClassMode;
|
||||
@@ -47,8 +48,8 @@ public class DirtiesContextTestExecutionListener extends AbstractTestExecutionLi
|
||||
* Marks the {@linkplain ApplicationContext application context} of the supplied
|
||||
* {@linkplain TestContext test context} as
|
||||
* {@linkplain TestContext#markApplicationContextDirty() dirty}, and sets the
|
||||
* {@link DependencyInjectionTestExecutionListener#REINJECT_DEPENDENCIES_ATTRIBUTE
|
||||
* REINJECT_DEPENDENCIES_ATTRIBUTE} in the test context to {@code true}.
|
||||
* {@link DependencyInjectionTestExecutionListener#REINJECT_DEPENDENCIES_ATTRIBUTE}
|
||||
* in the test context to {@code true}.
|
||||
* @param testContext the test context whose application context should
|
||||
* marked as dirty
|
||||
* @deprecated as of Spring 3.2.2, use {@link #dirtyContext(TestContext, HierarchyMode)} instead.
|
||||
@@ -61,10 +62,10 @@ public class DirtiesContextTestExecutionListener extends AbstractTestExecutionLi
|
||||
|
||||
/**
|
||||
* Marks the {@linkplain ApplicationContext application context} of the supplied
|
||||
* {@linkplain TestContext test context} as {@linkplain
|
||||
* TestContext#markApplicationContextDirty(HierarchyMode) dirty} and sets the
|
||||
* {@link DependencyInjectionTestExecutionListener#REINJECT_DEPENDENCIES_ATTRIBUTE
|
||||
* REINJECT_DEPENDENCIES_ATTRIBUTE} in the test context to {@code true}.
|
||||
* {@linkplain TestContext test context} as
|
||||
* {@linkplain TestContext#markApplicationContextDirty(DirtiesContext.HierarchyMode) dirty}
|
||||
* and sets {@link DependencyInjectionTestExecutionListener#REINJECT_DEPENDENCIES_ATTRIBUTE}
|
||||
* in the test context to {@code true}.
|
||||
* @param testContext the test context whose application context should
|
||||
* marked as dirty
|
||||
* @param hierarchyMode the context cache clearing mode to be applied if the
|
||||
@@ -85,9 +86,8 @@ public class DirtiesContextTestExecutionListener extends AbstractTestExecutionLi
|
||||
* AFTER_EACH_TEST_METHOD}, the {@linkplain ApplicationContext application
|
||||
* context} of the test context will be
|
||||
* {@linkplain TestContext#markApplicationContextDirty() marked as dirty} and the
|
||||
* {@link DependencyInjectionTestExecutionListener#REINJECT_DEPENDENCIES_ATTRIBUTE
|
||||
* REINJECT_DEPENDENCIES_ATTRIBUTE} in the test context will be set to
|
||||
* {@code true}.
|
||||
* {@link DependencyInjectionTestExecutionListener#REINJECT_DEPENDENCIES_ATTRIBUTE}
|
||||
* in the test context will be set to {@code true}.
|
||||
*/
|
||||
@Override
|
||||
public void afterTestMethod(TestContext testContext) throws Exception {
|
||||
|
||||
+7
-7
@@ -16,13 +16,10 @@
|
||||
|
||||
package org.springframework.transaction.annotation;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.context.annotation.AdviceMode;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
@@ -33,6 +30,9 @@ import org.springframework.tests.transaction.CallCountingTransactionManager;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.annotation.AnnotationTransactionNamespaceHandlerTests.TransactionalTestBean;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Tests demonstrating use of @EnableTransactionManagement @Configuration classes.
|
||||
*
|
||||
@@ -84,9 +84,9 @@ public class EnableTransactionManagementTests {
|
||||
new AnnotationConfigApplicationContext(EnableAspectJTxConfig.class, TxManagerConfig.class);
|
||||
fail("should have thrown CNFE when trying to load AnnotationTransactionAspect. " +
|
||||
"Do you actually have org.springframework.aspects on the classpath?");
|
||||
} catch (Exception ex) {
|
||||
System.out.println(ex);
|
||||
assertThat(ex.getMessage().endsWith("AspectJTransactionManagementConfiguration.class] cannot be opened because it does not exist"), is(true));
|
||||
}
|
||||
catch (Exception ex) {
|
||||
assertThat(ex.getMessage().contains("AspectJTransactionManagementConfiguration"), is(true));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
-1
@@ -85,7 +85,17 @@ public class ResourceHttpMessageConverter extends AbstractHttpMessageConverter<R
|
||||
protected void writeInternal(Resource resource, HttpOutputMessage outputMessage)
|
||||
throws IOException, HttpMessageNotWritableException {
|
||||
|
||||
StreamUtils.copy(resource.getInputStream(), outputMessage.getBody());
|
||||
InputStream in = resource.getInputStream();
|
||||
try {
|
||||
StreamUtils.copy(in, outputMessage.getBody());
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
in.close();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
}
|
||||
}
|
||||
outputMessage.getBody().flush();
|
||||
}
|
||||
|
||||
|
||||
+38
-38
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,11 +22,6 @@ import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.FatalBeanException;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.AnnotationIntrospector;
|
||||
@@ -38,9 +33,14 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
|
||||
import org.springframework.beans.FatalBeanException;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A FactoryBean for creating a Jackson {@link ObjectMapper} with setters to
|
||||
* enable or disable Jackson features from within XML configuration.
|
||||
* A {@link FactoryBean} for creating a Jackson 2 {@link ObjectMapper} with setters
|
||||
* to enable or disable Jackson features from within XML configuration.
|
||||
*
|
||||
* <p>Example usage with
|
||||
* {@link org.springframework.http.converter.json.MappingJackson2HttpMessageConverter}:
|
||||
@@ -56,7 +56,7 @@ import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
* </bean>
|
||||
* </pre>
|
||||
*
|
||||
* <p>Example usage with {@link org.springframework.web.servlet.view.json.MappingJackson2JsonView}:
|
||||
* <p>Example usage with MappingJackson2JsonView:
|
||||
*
|
||||
* <pre>
|
||||
* <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
|
||||
@@ -94,12 +94,8 @@ import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
* </bean>
|
||||
* </pre>
|
||||
*
|
||||
* <p>Note: This BeanFctory is singleton, so if you need more than one you'll need
|
||||
* to configure multiple instances.
|
||||
*
|
||||
* @author <a href="mailto:dmitry.katsubo@gmail.com">Dmitry Katsubo</a>
|
||||
* @author Rossen Stoyanchev
|
||||
*
|
||||
* @since 3.2
|
||||
*/
|
||||
public class Jackson2ObjectMapperFactoryBean implements FactoryBean<ObjectMapper>, InitializingBean {
|
||||
@@ -127,6 +123,8 @@ public class Jackson2ObjectMapperFactoryBean implements FactoryBean<ObjectMapper
|
||||
|
||||
/**
|
||||
* Define the format for date/time with the given {@link DateFormat}.
|
||||
* <p>Note: Setting this property makes the exposed {@link ObjectMapper}
|
||||
* non-thread-safe, according to Jackson's thread safety rules.
|
||||
* @see #setSimpleDateFormat(String)
|
||||
*/
|
||||
public void setDateFormat(DateFormat dateFormat) {
|
||||
@@ -135,6 +133,8 @@ public class Jackson2ObjectMapperFactoryBean implements FactoryBean<ObjectMapper
|
||||
|
||||
/**
|
||||
* Define the date/time format with a {@link SimpleDateFormat}.
|
||||
* <p>Note: Setting this property makes the exposed {@link ObjectMapper}
|
||||
* non-thread-safe, according to Jackson's thread safety rules.
|
||||
* @see #setDateFormat(DateFormat)
|
||||
*/
|
||||
public void setSimpleDateFormat(String format) {
|
||||
@@ -197,8 +197,8 @@ public class Jackson2ObjectMapperFactoryBean implements FactoryBean<ObjectMapper
|
||||
* {@link MapperFeature#AUTO_DETECT_GETTERS} option.
|
||||
*/
|
||||
public void setAutoDetectGettersSetters(boolean autoDetectGettersSetters) {
|
||||
this.features.put(MapperFeature.AUTO_DETECT_SETTERS, autoDetectGettersSetters);
|
||||
this.features.put(MapperFeature.AUTO_DETECT_GETTERS, autoDetectGettersSetters);
|
||||
this.features.put(MapperFeature.AUTO_DETECT_SETTERS, autoDetectGettersSetters);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -217,12 +217,11 @@ public class Jackson2ObjectMapperFactoryBean implements FactoryBean<ObjectMapper
|
||||
|
||||
/**
|
||||
* Specify features to enable.
|
||||
*
|
||||
* @see MapperFeature
|
||||
* @see SerializationFeature
|
||||
* @see DeserializationFeature
|
||||
* @see org.codehaus.jackson.map.JsonParser.Feature
|
||||
* @see org.codehaus.jackson.map.JsonGenerator.Feature
|
||||
* @see com.fasterxml.jackson.core.JsonParser.Feature
|
||||
* @see com.fasterxml.jackson.core.JsonGenerator.Feature
|
||||
* @see com.fasterxml.jackson.databind.SerializationFeature
|
||||
* @see com.fasterxml.jackson.databind.DeserializationFeature
|
||||
* @see com.fasterxml.jackson.databind.MapperFeature
|
||||
*/
|
||||
public void setFeaturesToEnable(Object... featuresToEnable) {
|
||||
if (featuresToEnable != null) {
|
||||
@@ -234,12 +233,11 @@ public class Jackson2ObjectMapperFactoryBean implements FactoryBean<ObjectMapper
|
||||
|
||||
/**
|
||||
* Specify features to disable.
|
||||
*
|
||||
* @see MapperFeature
|
||||
* @see SerializationFeature
|
||||
* @see DeserializationFeature
|
||||
* @see org.codehaus.jackson.map.JsonParser.Feature
|
||||
* @see org.codehaus.jackson.map.JsonGenerator.Feature
|
||||
* @see com.fasterxml.jackson.core.JsonParser.Feature
|
||||
* @see com.fasterxml.jackson.core.JsonGenerator.Feature
|
||||
* @see com.fasterxml.jackson.databind.SerializationFeature
|
||||
* @see com.fasterxml.jackson.databind.DeserializationFeature
|
||||
* @see com.fasterxml.jackson.databind.MapperFeature
|
||||
*/
|
||||
public void setFeaturesToDisable(Object... featuresToDisable) {
|
||||
if (featuresToDisable != null) {
|
||||
@@ -249,7 +247,8 @@ public class Jackson2ObjectMapperFactoryBean implements FactoryBean<ObjectMapper
|
||||
}
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws FatalBeanException {
|
||||
|
||||
public void afterPropertiesSet() {
|
||||
if (this.objectMapper == null) {
|
||||
this.objectMapper = new ObjectMapper();
|
||||
}
|
||||
@@ -258,7 +257,7 @@ public class Jackson2ObjectMapperFactoryBean implements FactoryBean<ObjectMapper
|
||||
this.objectMapper.setDateFormat(this.dateFormat);
|
||||
}
|
||||
|
||||
if (this.serializers != null || this.deserializers != null) {
|
||||
if (!this.serializers.isEmpty() || !this.deserializers.isEmpty()) {
|
||||
SimpleModule module = new SimpleModule();
|
||||
addSerializers(module);
|
||||
addDeserializers(module);
|
||||
@@ -289,26 +288,27 @@ public class Jackson2ObjectMapperFactoryBean implements FactoryBean<ObjectMapper
|
||||
}
|
||||
|
||||
private void configureFeature(Object feature, boolean enabled) {
|
||||
if (feature instanceof MapperFeature) {
|
||||
this.objectMapper.configure((MapperFeature) feature, enabled);
|
||||
}
|
||||
else if (feature instanceof DeserializationFeature) {
|
||||
this.objectMapper.configure((DeserializationFeature) feature, enabled);
|
||||
}
|
||||
else if (feature instanceof SerializationFeature) {
|
||||
this.objectMapper.configure((SerializationFeature) feature, enabled);
|
||||
}
|
||||
else if (feature instanceof JsonParser.Feature) {
|
||||
if (feature instanceof JsonParser.Feature) {
|
||||
this.objectMapper.configure((JsonParser.Feature) feature, enabled);
|
||||
}
|
||||
else if (feature instanceof JsonGenerator.Feature) {
|
||||
this.objectMapper.configure((JsonGenerator.Feature) feature, enabled);
|
||||
}
|
||||
else if (feature instanceof SerializationFeature) {
|
||||
this.objectMapper.configure((SerializationFeature) feature, enabled);
|
||||
}
|
||||
else if (feature instanceof DeserializationFeature) {
|
||||
this.objectMapper.configure((DeserializationFeature) feature, enabled);
|
||||
}
|
||||
else if (feature instanceof MapperFeature) {
|
||||
this.objectMapper.configure((MapperFeature) feature, enabled);
|
||||
}
|
||||
else {
|
||||
throw new FatalBeanException("Unknown feature class " + feature.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the singleton ObjectMapper.
|
||||
*/
|
||||
|
||||
+22
-18
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,8 +32,8 @@ import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
/**
|
||||
* A FactoryBean for creating a Jackson {@link ObjectMapper} with setters to
|
||||
* enable or disable Jackson features from within XML configuration.
|
||||
* A {@link FactoryBean} for creating a Jackson {@link ObjectMapper} with setters
|
||||
* to enable or disable Jackson features from within XML configuration.
|
||||
*
|
||||
* <p>Example usage with MappingJacksonHttpMessageConverter:
|
||||
* <pre>
|
||||
@@ -104,6 +104,8 @@ public class JacksonObjectMapperFactoryBean implements FactoryBean<ObjectMapper>
|
||||
|
||||
/**
|
||||
* Define the format for date/time with the given {@link DateFormat}.
|
||||
* <p>Note: Setting this property makes the exposed {@link ObjectMapper}
|
||||
* non-thread-safe, according to Jackson's thread safety rules.
|
||||
* @see #setSimpleDateFormat(String)
|
||||
*/
|
||||
public void setDateFormat(DateFormat dateFormat) {
|
||||
@@ -112,6 +114,8 @@ public class JacksonObjectMapperFactoryBean implements FactoryBean<ObjectMapper>
|
||||
|
||||
/**
|
||||
* Define the date/time format with a {@link SimpleDateFormat}.
|
||||
* <p>Note: Setting this property makes the exposed {@link ObjectMapper}
|
||||
* non-thread-safe, according to Jackson's thread safety rules.
|
||||
* @see #setDateFormat(DateFormat)
|
||||
*/
|
||||
public void setSimpleDateFormat(String format) {
|
||||
@@ -132,8 +136,8 @@ public class JacksonObjectMapperFactoryBean implements FactoryBean<ObjectMapper>
|
||||
* {@link org.codehaus.jackson.map.DeserializationConfig.Feature#AUTO_DETECT_FIELDS}.
|
||||
*/
|
||||
public void setAutoDetectFields(boolean autoDetectFields) {
|
||||
this.features.put(DeserializationConfig.Feature.AUTO_DETECT_FIELDS, autoDetectFields);
|
||||
this.features.put(SerializationConfig.Feature.AUTO_DETECT_FIELDS, autoDetectFields);
|
||||
this.features.put(DeserializationConfig.Feature.AUTO_DETECT_FIELDS, autoDetectFields);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,11 +165,10 @@ public class JacksonObjectMapperFactoryBean implements FactoryBean<ObjectMapper>
|
||||
|
||||
/**
|
||||
* Specify features to enable.
|
||||
*
|
||||
* @see org.codehaus.jackson.JsonParser.Feature
|
||||
* @see org.codehaus.jackson.JsonGenerator.Feature
|
||||
* @see org.codehaus.jackson.map.SerializationConfig.Feature
|
||||
* @see org.codehaus.jackson.map.DeserializationConfig.Feature
|
||||
* @see org.codehaus.jackson.map.JsonParser.Feature
|
||||
* @see org.codehaus.jackson.map.JsonGenerator.Feature
|
||||
*/
|
||||
public void setFeaturesToEnable(Object[] featuresToEnable) {
|
||||
if (featuresToEnable != null) {
|
||||
@@ -177,11 +180,10 @@ public class JacksonObjectMapperFactoryBean implements FactoryBean<ObjectMapper>
|
||||
|
||||
/**
|
||||
* Specify features to disable.
|
||||
*
|
||||
* @see org.codehaus.jackson.JsonParser.Feature
|
||||
* @see org.codehaus.jackson.JsonGenerator.Feature
|
||||
* @see org.codehaus.jackson.map.SerializationConfig.Feature
|
||||
* @see org.codehaus.jackson.map.DeserializationConfig.Feature
|
||||
* @see org.codehaus.jackson.map.JsonParser.Feature
|
||||
* @see org.codehaus.jackson.map.JsonGenerator.Feature
|
||||
*/
|
||||
public void setFeaturesToDisable(Object[] featuresToDisable) {
|
||||
if (featuresToDisable != null) {
|
||||
@@ -191,6 +193,7 @@ public class JacksonObjectMapperFactoryBean implements FactoryBean<ObjectMapper>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void afterPropertiesSet() {
|
||||
if (this.objectMapper == null) {
|
||||
this.objectMapper = new ObjectMapper();
|
||||
@@ -204,28 +207,29 @@ public class JacksonObjectMapperFactoryBean implements FactoryBean<ObjectMapper>
|
||||
this.objectMapper.getSerializationConfig().setDateFormat(this.dateFormat);
|
||||
}
|
||||
for (Map.Entry<Object, Boolean> entry : this.features.entrySet()) {
|
||||
configureFeature(entry.getKey(), entry.getValue().booleanValue());
|
||||
configureFeature(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private void configureFeature(Object feature, boolean enabled) {
|
||||
if (feature instanceof DeserializationConfig.Feature) {
|
||||
this.objectMapper.configure((DeserializationConfig.Feature) feature, enabled);
|
||||
}
|
||||
else if (feature instanceof SerializationConfig.Feature) {
|
||||
this.objectMapper.configure((SerializationConfig.Feature) feature, enabled);
|
||||
}
|
||||
else if (feature instanceof JsonParser.Feature) {
|
||||
if (feature instanceof JsonParser.Feature) {
|
||||
this.objectMapper.configure((JsonParser.Feature) feature, enabled);
|
||||
}
|
||||
else if (feature instanceof JsonGenerator.Feature) {
|
||||
this.objectMapper.configure((JsonGenerator.Feature) feature, enabled);
|
||||
}
|
||||
else if (feature instanceof SerializationConfig.Feature) {
|
||||
this.objectMapper.configure((SerializationConfig.Feature) feature, enabled);
|
||||
}
|
||||
else if (feature instanceof DeserializationConfig.Feature) {
|
||||
this.objectMapper.configure((DeserializationConfig.Feature) feature, enabled);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Unknown feature class: " + feature.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the singleton ObjectMapper.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
package org.springframework.web;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
@@ -33,6 +33,7 @@ public abstract class HttpMediaTypeException extends ServletException {
|
||||
|
||||
private final List<MediaType> supportedMediaTypes;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new HttpMediaTypeException.
|
||||
* @param message the exception message
|
||||
@@ -48,13 +49,15 @@ public abstract class HttpMediaTypeException extends ServletException {
|
||||
*/
|
||||
protected HttpMediaTypeException(String message, List<MediaType> supportedMediaTypes) {
|
||||
super(message);
|
||||
this.supportedMediaTypes = supportedMediaTypes;
|
||||
this.supportedMediaTypes = Collections.unmodifiableList(supportedMediaTypes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the list of supported media types.
|
||||
*/
|
||||
public List<MediaType> getSupportedMediaTypes() {
|
||||
return supportedMediaTypes;
|
||||
return this.supportedMediaTypes;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,6 +32,7 @@ public class HttpMediaTypeNotSupportedException extends HttpMediaTypeException {
|
||||
|
||||
private final MediaType contentType;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new HttpMediaTypeNotSupportedException.
|
||||
* @param message the exception message
|
||||
@@ -61,11 +62,12 @@ public class HttpMediaTypeNotSupportedException extends HttpMediaTypeException {
|
||||
this.contentType = contentType;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the HTTP request content type method that caused the failure.
|
||||
*/
|
||||
public MediaType getContentType() {
|
||||
return contentType;
|
||||
return this.contentType;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,9 +17,9 @@
|
||||
package org.springframework.web;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
@@ -105,11 +105,11 @@ public class HttpRequestMethodNotSupportedException extends ServletException {
|
||||
* Return the actually supported HTTP methods, if known, as {@link HttpMethod} instances.
|
||||
*/
|
||||
public Set<HttpMethod> getSupportedHttpMethods() {
|
||||
Set<HttpMethod> supportedMethods = new HashSet<HttpMethod>();
|
||||
Set<HttpMethod> supportedMethods = new LinkedHashSet<HttpMethod>();
|
||||
for (String value : this.supportedMethods) {
|
||||
supportedMethods.add(HttpMethod.valueOf(value));
|
||||
}
|
||||
return supportedMethods;
|
||||
return Collections.unmodifiableSet(supportedMethods);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-2
@@ -50,6 +50,8 @@ import org.springframework.web.context.request.NativeWebRequest;
|
||||
*/
|
||||
public class ContentNegotiationManager implements ContentNegotiationStrategy, MediaTypeFileExtensionResolver {
|
||||
|
||||
private static final List<MediaType> MEDIA_TYPE_ALL = Arrays.asList(MediaType.ALL);
|
||||
|
||||
private final List<ContentNegotiationStrategy> contentNegotiationStrategies =
|
||||
new ArrayList<ContentNegotiationStrategy>();
|
||||
|
||||
@@ -119,9 +121,10 @@ public class ContentNegotiationManager implements ContentNegotiationStrategy, Me
|
||||
public List<MediaType> resolveMediaTypes(NativeWebRequest webRequest) throws HttpMediaTypeNotAcceptableException {
|
||||
for (ContentNegotiationStrategy strategy : this.contentNegotiationStrategies) {
|
||||
List<MediaType> mediaTypes = strategy.resolveMediaTypes(webRequest);
|
||||
if (!mediaTypes.isEmpty()) {
|
||||
return mediaTypes;
|
||||
if (mediaTypes.isEmpty() || mediaTypes.equals(MEDIA_TYPE_ALL)) {
|
||||
continue;
|
||||
}
|
||||
return mediaTypes;
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user